162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright IBM Corp. 2008
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Authors: Hollis Blanchard <hollisb@us.ibm.com>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifndef __POWERPC_KVM_PPC_H__
1062306a36Sopenharmony_ci#define __POWERPC_KVM_PPC_H__
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/* This file exists just so we can dereference kvm_vcpu, avoiding nested header
1362306a36Sopenharmony_ci * dependencies. */
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci#include <linux/mutex.h>
1662306a36Sopenharmony_ci#include <linux/timer.h>
1762306a36Sopenharmony_ci#include <linux/types.h>
1862306a36Sopenharmony_ci#include <linux/kvm_types.h>
1962306a36Sopenharmony_ci#include <linux/kvm_host.h>
2062306a36Sopenharmony_ci#include <linux/bug.h>
2162306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S
2262306a36Sopenharmony_ci#include <asm/kvm_book3s.h>
2362306a36Sopenharmony_ci#else
2462306a36Sopenharmony_ci#include <asm/kvm_booke.h>
2562306a36Sopenharmony_ci#endif
2662306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_64_HANDLER
2762306a36Sopenharmony_ci#include <asm/paca.h>
2862306a36Sopenharmony_ci#include <asm/xive.h>
2962306a36Sopenharmony_ci#include <asm/cpu_has_feature.h>
3062306a36Sopenharmony_ci#endif
3162306a36Sopenharmony_ci#include <asm/inst.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci/*
3462306a36Sopenharmony_ci * KVMPPC_INST_SW_BREAKPOINT is debug Instruction
3562306a36Sopenharmony_ci * for supporting software breakpoint.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ci#define KVMPPC_INST_SW_BREAKPOINT	0x00dddd00
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cienum emulation_result {
4062306a36Sopenharmony_ci	EMULATE_DONE,         /* no further processing */
4162306a36Sopenharmony_ci	EMULATE_DO_MMIO,      /* kvm_run filled with MMIO request */
4262306a36Sopenharmony_ci	EMULATE_FAIL,         /* can't emulate this instruction */
4362306a36Sopenharmony_ci	EMULATE_AGAIN,        /* something went wrong. go again */
4462306a36Sopenharmony_ci	EMULATE_EXIT_USER,    /* emulation requires exit to user-space */
4562306a36Sopenharmony_ci};
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_cienum instruction_fetch_type {
4862306a36Sopenharmony_ci	INST_GENERIC,
4962306a36Sopenharmony_ci	INST_SC,		/* system call */
5062306a36Sopenharmony_ci};
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_cienum xlate_instdata {
5362306a36Sopenharmony_ci	XLATE_INST,		/* translate instruction address */
5462306a36Sopenharmony_ci	XLATE_DATA		/* translate data address */
5562306a36Sopenharmony_ci};
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_cienum xlate_readwrite {
5862306a36Sopenharmony_ci	XLATE_READ,		/* check for read permissions */
5962306a36Sopenharmony_ci	XLATE_WRITE		/* check for write permissions */
6062306a36Sopenharmony_ci};
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ciextern int kvmppc_vcpu_run(struct kvm_vcpu *vcpu);
6362306a36Sopenharmony_ciextern int __kvmppc_vcpu_run(struct kvm_vcpu *vcpu);
6462306a36Sopenharmony_ciextern void kvmppc_handler_highmem(void);
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ciextern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu);
6762306a36Sopenharmony_ciextern int kvmppc_handle_load(struct kvm_vcpu *vcpu,
6862306a36Sopenharmony_ci                              unsigned int rt, unsigned int bytes,
6962306a36Sopenharmony_ci			      int is_default_endian);
7062306a36Sopenharmony_ciextern int kvmppc_handle_loads(struct kvm_vcpu *vcpu,
7162306a36Sopenharmony_ci                               unsigned int rt, unsigned int bytes,
7262306a36Sopenharmony_ci			       int is_default_endian);
7362306a36Sopenharmony_ciextern int kvmppc_handle_vsx_load(struct kvm_vcpu *vcpu,
7462306a36Sopenharmony_ci				unsigned int rt, unsigned int bytes,
7562306a36Sopenharmony_ci			int is_default_endian, int mmio_sign_extend);
7662306a36Sopenharmony_ciextern int kvmppc_handle_vmx_load(struct kvm_vcpu *vcpu,
7762306a36Sopenharmony_ci		unsigned int rt, unsigned int bytes, int is_default_endian);
7862306a36Sopenharmony_ciextern int kvmppc_handle_vmx_store(struct kvm_vcpu *vcpu,
7962306a36Sopenharmony_ci		unsigned int rs, unsigned int bytes, int is_default_endian);
8062306a36Sopenharmony_ciextern int kvmppc_handle_store(struct kvm_vcpu *vcpu,
8162306a36Sopenharmony_ci			       u64 val, unsigned int bytes,
8262306a36Sopenharmony_ci			       int is_default_endian);
8362306a36Sopenharmony_ciextern int kvmppc_handle_vsx_store(struct kvm_vcpu *vcpu,
8462306a36Sopenharmony_ci				int rs, unsigned int bytes,
8562306a36Sopenharmony_ci				int is_default_endian);
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ciextern int kvmppc_load_last_inst(struct kvm_vcpu *vcpu,
8862306a36Sopenharmony_ci				 enum instruction_fetch_type type,
8962306a36Sopenharmony_ci				 unsigned long *inst);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ciextern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
9262306a36Sopenharmony_ci		     bool data);
9362306a36Sopenharmony_ciextern int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
9462306a36Sopenharmony_ci		     bool data);
9562306a36Sopenharmony_ciextern int kvmppc_emulate_instruction(struct kvm_vcpu *vcpu);
9662306a36Sopenharmony_ciextern int kvmppc_emulate_loadstore(struct kvm_vcpu *vcpu);
9762306a36Sopenharmony_ciextern int kvmppc_emulate_mmio(struct kvm_vcpu *vcpu);
9862306a36Sopenharmony_ciextern void kvmppc_emulate_dec(struct kvm_vcpu *vcpu);
9962306a36Sopenharmony_ciextern u32 kvmppc_get_dec(struct kvm_vcpu *vcpu, u64 tb);
10062306a36Sopenharmony_ciextern void kvmppc_decrementer_func(struct kvm_vcpu *vcpu);
10162306a36Sopenharmony_ciextern int kvmppc_sanity_check(struct kvm_vcpu *vcpu);
10262306a36Sopenharmony_ciextern int kvmppc_subarch_vcpu_init(struct kvm_vcpu *vcpu);
10362306a36Sopenharmony_ciextern void kvmppc_subarch_vcpu_uninit(struct kvm_vcpu *vcpu);
10462306a36Sopenharmony_ci
10562306a36Sopenharmony_ci/* Core-specific hooks */
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ciextern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gpa_t gpaddr,
10862306a36Sopenharmony_ci                           unsigned int gtlb_idx);
10962306a36Sopenharmony_ciextern void kvmppc_mmu_switch_pid(struct kvm_vcpu *vcpu, u32 pid);
11062306a36Sopenharmony_ciextern int kvmppc_mmu_dtlb_index(struct kvm_vcpu *vcpu, gva_t eaddr);
11162306a36Sopenharmony_ciextern int kvmppc_mmu_itlb_index(struct kvm_vcpu *vcpu, gva_t eaddr);
11262306a36Sopenharmony_ciextern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
11362306a36Sopenharmony_ci                              gva_t eaddr);
11462306a36Sopenharmony_ciextern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu);
11562306a36Sopenharmony_ciextern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu);
11662306a36Sopenharmony_ciextern int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr,
11762306a36Sopenharmony_ci			enum xlate_instdata xlid, enum xlate_readwrite xlrw,
11862306a36Sopenharmony_ci			struct kvmppc_pte *pte);
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ciextern int kvmppc_core_vcpu_create(struct kvm_vcpu *vcpu);
12162306a36Sopenharmony_ciextern void kvmppc_core_vcpu_free(struct kvm_vcpu *vcpu);
12262306a36Sopenharmony_ciextern int kvmppc_core_vcpu_setup(struct kvm_vcpu *vcpu);
12362306a36Sopenharmony_ciextern int kvmppc_core_vcpu_translate(struct kvm_vcpu *vcpu,
12462306a36Sopenharmony_ci                                      struct kvm_translation *tr);
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_ciextern void kvmppc_core_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
12762306a36Sopenharmony_ciextern void kvmppc_core_vcpu_put(struct kvm_vcpu *vcpu);
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ciextern int kvmppc_core_prepare_to_enter(struct kvm_vcpu *vcpu);
13062306a36Sopenharmony_ciextern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_ciextern void kvmppc_core_queue_machine_check(struct kvm_vcpu *vcpu,
13362306a36Sopenharmony_ci					    ulong srr1_flags);
13462306a36Sopenharmony_ciextern void kvmppc_core_queue_syscall(struct kvm_vcpu *vcpu);
13562306a36Sopenharmony_ciextern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu,
13662306a36Sopenharmony_ci				      ulong srr1_flags);
13762306a36Sopenharmony_ciextern void kvmppc_core_queue_fpunavail(struct kvm_vcpu *vcpu,
13862306a36Sopenharmony_ci					ulong srr1_flags);
13962306a36Sopenharmony_ciextern void kvmppc_core_queue_vec_unavail(struct kvm_vcpu *vcpu,
14062306a36Sopenharmony_ci					  ulong srr1_flags);
14162306a36Sopenharmony_ciextern void kvmppc_core_queue_vsx_unavail(struct kvm_vcpu *vcpu,
14262306a36Sopenharmony_ci					  ulong srr1_flags);
14362306a36Sopenharmony_ciextern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
14462306a36Sopenharmony_ciextern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
14562306a36Sopenharmony_ciextern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
14662306a36Sopenharmony_ci                                       struct kvm_interrupt *irq);
14762306a36Sopenharmony_ciextern void kvmppc_core_dequeue_external(struct kvm_vcpu *vcpu);
14862306a36Sopenharmony_ciextern void kvmppc_core_queue_dtlb_miss(struct kvm_vcpu *vcpu,
14962306a36Sopenharmony_ci					ulong dear_flags,
15062306a36Sopenharmony_ci					ulong esr_flags);
15162306a36Sopenharmony_ciextern void kvmppc_core_queue_data_storage(struct kvm_vcpu *vcpu,
15262306a36Sopenharmony_ci					   ulong srr1_flags,
15362306a36Sopenharmony_ci					   ulong dar,
15462306a36Sopenharmony_ci					   ulong dsisr);
15562306a36Sopenharmony_ciextern void kvmppc_core_queue_itlb_miss(struct kvm_vcpu *vcpu);
15662306a36Sopenharmony_ciextern void kvmppc_core_queue_inst_storage(struct kvm_vcpu *vcpu,
15762306a36Sopenharmony_ci					   ulong srr1_flags);
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ciextern void kvmppc_core_flush_tlb(struct kvm_vcpu *vcpu);
16062306a36Sopenharmony_ciextern int kvmppc_core_check_requests(struct kvm_vcpu *vcpu);
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ciextern int kvmppc_booke_init(void);
16362306a36Sopenharmony_ciextern void kvmppc_booke_exit(void);
16462306a36Sopenharmony_ci
16562306a36Sopenharmony_ciextern int kvmppc_kvm_pv(struct kvm_vcpu *vcpu);
16662306a36Sopenharmony_ciextern void kvmppc_map_magic(struct kvm_vcpu *vcpu);
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ciextern int kvmppc_allocate_hpt(struct kvm_hpt_info *info, u32 order);
16962306a36Sopenharmony_ciextern void kvmppc_set_hpt(struct kvm *kvm, struct kvm_hpt_info *info);
17062306a36Sopenharmony_ciextern int kvmppc_alloc_reset_hpt(struct kvm *kvm, int order);
17162306a36Sopenharmony_ciextern void kvmppc_free_hpt(struct kvm_hpt_info *info);
17262306a36Sopenharmony_ciextern void kvmppc_rmap_reset(struct kvm *kvm);
17362306a36Sopenharmony_ciextern void kvmppc_map_vrma(struct kvm_vcpu *vcpu,
17462306a36Sopenharmony_ci			struct kvm_memory_slot *memslot, unsigned long porder);
17562306a36Sopenharmony_ciextern int kvmppc_pseries_do_hcall(struct kvm_vcpu *vcpu);
17662306a36Sopenharmony_ciextern long kvm_spapr_tce_attach_iommu_group(struct kvm *kvm, int tablefd,
17762306a36Sopenharmony_ci		struct iommu_group *grp);
17862306a36Sopenharmony_ciextern void kvm_spapr_tce_release_iommu_group(struct kvm *kvm,
17962306a36Sopenharmony_ci		struct iommu_group *grp);
18062306a36Sopenharmony_ciextern int kvmppc_switch_mmu_to_hpt(struct kvm *kvm);
18162306a36Sopenharmony_ciextern int kvmppc_switch_mmu_to_radix(struct kvm *kvm);
18262306a36Sopenharmony_ciextern void kvmppc_setup_partition_table(struct kvm *kvm);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_ciextern int kvm_vm_ioctl_create_spapr_tce(struct kvm *kvm,
18562306a36Sopenharmony_ci				struct kvm_create_spapr_tce_64 *args);
18662306a36Sopenharmony_ci#define kvmppc_ioba_validate(stt, ioba, npages)                         \
18762306a36Sopenharmony_ci		(iommu_tce_check_ioba((stt)->page_shift, (stt)->offset, \
18862306a36Sopenharmony_ci				(stt)->size, (ioba), (npages)) ?        \
18962306a36Sopenharmony_ci				H_PARAMETER : H_SUCCESS)
19062306a36Sopenharmony_ciextern long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
19162306a36Sopenharmony_ci			     unsigned long ioba, unsigned long tce);
19262306a36Sopenharmony_ciextern long kvmppc_h_put_tce_indirect(struct kvm_vcpu *vcpu,
19362306a36Sopenharmony_ci		unsigned long liobn, unsigned long ioba,
19462306a36Sopenharmony_ci		unsigned long tce_list, unsigned long npages);
19562306a36Sopenharmony_ciextern long kvmppc_h_stuff_tce(struct kvm_vcpu *vcpu,
19662306a36Sopenharmony_ci		unsigned long liobn, unsigned long ioba,
19762306a36Sopenharmony_ci		unsigned long tce_value, unsigned long npages);
19862306a36Sopenharmony_ciextern long kvmppc_h_get_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
19962306a36Sopenharmony_ci			     unsigned long ioba);
20062306a36Sopenharmony_ciextern struct page *kvm_alloc_hpt_cma(unsigned long nr_pages);
20162306a36Sopenharmony_ciextern void kvm_free_hpt_cma(struct page *page, unsigned long nr_pages);
20262306a36Sopenharmony_ciextern int kvmppc_core_init_vm(struct kvm *kvm);
20362306a36Sopenharmony_ciextern void kvmppc_core_destroy_vm(struct kvm *kvm);
20462306a36Sopenharmony_ciextern void kvmppc_core_free_memslot(struct kvm *kvm,
20562306a36Sopenharmony_ci				     struct kvm_memory_slot *slot);
20662306a36Sopenharmony_ciextern int kvmppc_core_prepare_memory_region(struct kvm *kvm,
20762306a36Sopenharmony_ci				const struct kvm_memory_slot *old,
20862306a36Sopenharmony_ci				struct kvm_memory_slot *new,
20962306a36Sopenharmony_ci				enum kvm_mr_change change);
21062306a36Sopenharmony_ciextern void kvmppc_core_commit_memory_region(struct kvm *kvm,
21162306a36Sopenharmony_ci				struct kvm_memory_slot *old,
21262306a36Sopenharmony_ci				const struct kvm_memory_slot *new,
21362306a36Sopenharmony_ci				enum kvm_mr_change change);
21462306a36Sopenharmony_ciextern int kvm_vm_ioctl_get_smmu_info(struct kvm *kvm,
21562306a36Sopenharmony_ci				      struct kvm_ppc_smmu_info *info);
21662306a36Sopenharmony_ciextern void kvmppc_core_flush_memslot(struct kvm *kvm,
21762306a36Sopenharmony_ci				      struct kvm_memory_slot *memslot);
21862306a36Sopenharmony_ci
21962306a36Sopenharmony_ciextern int kvmppc_bookehv_init(void);
22062306a36Sopenharmony_ciextern void kvmppc_bookehv_exit(void);
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_ciextern int kvmppc_prepare_to_enter(struct kvm_vcpu *vcpu);
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ciextern int kvm_vm_ioctl_get_htab_fd(struct kvm *kvm, struct kvm_get_htab_fd *);
22562306a36Sopenharmony_ciextern int kvm_vm_ioctl_resize_hpt_prepare(struct kvm *kvm,
22662306a36Sopenharmony_ci					   struct kvm_ppc_resize_hpt *rhpt);
22762306a36Sopenharmony_ciextern int kvm_vm_ioctl_resize_hpt_commit(struct kvm *kvm,
22862306a36Sopenharmony_ci					  struct kvm_ppc_resize_hpt *rhpt);
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_ciint kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq);
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ciextern int kvm_vm_ioctl_rtas_define_token(struct kvm *kvm, void __user *argp);
23362306a36Sopenharmony_ciextern int kvmppc_rtas_hcall(struct kvm_vcpu *vcpu);
23462306a36Sopenharmony_ciextern void kvmppc_rtas_tokens_free(struct kvm *kvm);
23562306a36Sopenharmony_ci
23662306a36Sopenharmony_ciextern int kvmppc_xics_set_xive(struct kvm *kvm, u32 irq, u32 server,
23762306a36Sopenharmony_ci				u32 priority);
23862306a36Sopenharmony_ciextern int kvmppc_xics_get_xive(struct kvm *kvm, u32 irq, u32 *server,
23962306a36Sopenharmony_ci				u32 *priority);
24062306a36Sopenharmony_ciextern int kvmppc_xics_int_on(struct kvm *kvm, u32 irq);
24162306a36Sopenharmony_ciextern int kvmppc_xics_int_off(struct kvm *kvm, u32 irq);
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_civoid kvmppc_core_dequeue_debug(struct kvm_vcpu *vcpu);
24462306a36Sopenharmony_civoid kvmppc_core_queue_debug(struct kvm_vcpu *vcpu);
24562306a36Sopenharmony_ci
24662306a36Sopenharmony_ciunion kvmppc_one_reg {
24762306a36Sopenharmony_ci	u32	wval;
24862306a36Sopenharmony_ci	u64	dval;
24962306a36Sopenharmony_ci	vector128 vval;
25062306a36Sopenharmony_ci	u64	vsxval[2];
25162306a36Sopenharmony_ci	u32	vsx32val[4];
25262306a36Sopenharmony_ci	u16	vsx16val[8];
25362306a36Sopenharmony_ci	u8	vsx8val[16];
25462306a36Sopenharmony_ci	struct {
25562306a36Sopenharmony_ci		u64	addr;
25662306a36Sopenharmony_ci		u64	length;
25762306a36Sopenharmony_ci	}	vpaval;
25862306a36Sopenharmony_ci	u64	xive_timaval[2];
25962306a36Sopenharmony_ci};
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_cistruct kvmppc_ops {
26262306a36Sopenharmony_ci	struct module *owner;
26362306a36Sopenharmony_ci	int (*get_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
26462306a36Sopenharmony_ci	int (*set_sregs)(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
26562306a36Sopenharmony_ci	int (*get_one_reg)(struct kvm_vcpu *vcpu, u64 id,
26662306a36Sopenharmony_ci			   union kvmppc_one_reg *val);
26762306a36Sopenharmony_ci	int (*set_one_reg)(struct kvm_vcpu *vcpu, u64 id,
26862306a36Sopenharmony_ci			   union kvmppc_one_reg *val);
26962306a36Sopenharmony_ci	void (*vcpu_load)(struct kvm_vcpu *vcpu, int cpu);
27062306a36Sopenharmony_ci	void (*vcpu_put)(struct kvm_vcpu *vcpu);
27162306a36Sopenharmony_ci	void (*inject_interrupt)(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags);
27262306a36Sopenharmony_ci	void (*set_msr)(struct kvm_vcpu *vcpu, u64 msr);
27362306a36Sopenharmony_ci	int (*vcpu_run)(struct kvm_vcpu *vcpu);
27462306a36Sopenharmony_ci	int (*vcpu_create)(struct kvm_vcpu *vcpu);
27562306a36Sopenharmony_ci	void (*vcpu_free)(struct kvm_vcpu *vcpu);
27662306a36Sopenharmony_ci	int (*check_requests)(struct kvm_vcpu *vcpu);
27762306a36Sopenharmony_ci	int (*get_dirty_log)(struct kvm *kvm, struct kvm_dirty_log *log);
27862306a36Sopenharmony_ci	void (*flush_memslot)(struct kvm *kvm, struct kvm_memory_slot *memslot);
27962306a36Sopenharmony_ci	int (*prepare_memory_region)(struct kvm *kvm,
28062306a36Sopenharmony_ci				     const struct kvm_memory_slot *old,
28162306a36Sopenharmony_ci				     struct kvm_memory_slot *new,
28262306a36Sopenharmony_ci				     enum kvm_mr_change change);
28362306a36Sopenharmony_ci	void (*commit_memory_region)(struct kvm *kvm,
28462306a36Sopenharmony_ci				     struct kvm_memory_slot *old,
28562306a36Sopenharmony_ci				     const struct kvm_memory_slot *new,
28662306a36Sopenharmony_ci				     enum kvm_mr_change change);
28762306a36Sopenharmony_ci	bool (*unmap_gfn_range)(struct kvm *kvm, struct kvm_gfn_range *range);
28862306a36Sopenharmony_ci	bool (*age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
28962306a36Sopenharmony_ci	bool (*test_age_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
29062306a36Sopenharmony_ci	bool (*set_spte_gfn)(struct kvm *kvm, struct kvm_gfn_range *range);
29162306a36Sopenharmony_ci	void (*free_memslot)(struct kvm_memory_slot *slot);
29262306a36Sopenharmony_ci	int (*init_vm)(struct kvm *kvm);
29362306a36Sopenharmony_ci	void (*destroy_vm)(struct kvm *kvm);
29462306a36Sopenharmony_ci	int (*get_smmu_info)(struct kvm *kvm, struct kvm_ppc_smmu_info *info);
29562306a36Sopenharmony_ci	int (*emulate_op)(struct kvm_vcpu *vcpu,
29662306a36Sopenharmony_ci			  unsigned int inst, int *advance);
29762306a36Sopenharmony_ci	int (*emulate_mtspr)(struct kvm_vcpu *vcpu, int sprn, ulong spr_val);
29862306a36Sopenharmony_ci	int (*emulate_mfspr)(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val);
29962306a36Sopenharmony_ci	void (*fast_vcpu_kick)(struct kvm_vcpu *vcpu);
30062306a36Sopenharmony_ci	int (*arch_vm_ioctl)(struct file *filp, unsigned int ioctl,
30162306a36Sopenharmony_ci			     unsigned long arg);
30262306a36Sopenharmony_ci	int (*hcall_implemented)(unsigned long hcall);
30362306a36Sopenharmony_ci	int (*irq_bypass_add_producer)(struct irq_bypass_consumer *,
30462306a36Sopenharmony_ci				       struct irq_bypass_producer *);
30562306a36Sopenharmony_ci	void (*irq_bypass_del_producer)(struct irq_bypass_consumer *,
30662306a36Sopenharmony_ci					struct irq_bypass_producer *);
30762306a36Sopenharmony_ci	int (*configure_mmu)(struct kvm *kvm, struct kvm_ppc_mmuv3_cfg *cfg);
30862306a36Sopenharmony_ci	int (*get_rmmu_info)(struct kvm *kvm, struct kvm_ppc_rmmu_info *info);
30962306a36Sopenharmony_ci	int (*set_smt_mode)(struct kvm *kvm, unsigned long mode,
31062306a36Sopenharmony_ci			    unsigned long flags);
31162306a36Sopenharmony_ci	void (*giveup_ext)(struct kvm_vcpu *vcpu, ulong msr);
31262306a36Sopenharmony_ci	int (*enable_nested)(struct kvm *kvm);
31362306a36Sopenharmony_ci	int (*load_from_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
31462306a36Sopenharmony_ci			       int size);
31562306a36Sopenharmony_ci	int (*store_to_eaddr)(struct kvm_vcpu *vcpu, ulong *eaddr, void *ptr,
31662306a36Sopenharmony_ci			      int size);
31762306a36Sopenharmony_ci	int (*enable_svm)(struct kvm *kvm);
31862306a36Sopenharmony_ci	int (*svm_off)(struct kvm *kvm);
31962306a36Sopenharmony_ci	int (*enable_dawr1)(struct kvm *kvm);
32062306a36Sopenharmony_ci	bool (*hash_v3_possible)(void);
32162306a36Sopenharmony_ci	int (*create_vm_debugfs)(struct kvm *kvm);
32262306a36Sopenharmony_ci	int (*create_vcpu_debugfs)(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry);
32362306a36Sopenharmony_ci};
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ciextern struct kvmppc_ops *kvmppc_hv_ops;
32662306a36Sopenharmony_ciextern struct kvmppc_ops *kvmppc_pr_ops;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_cistatic inline int kvmppc_get_last_inst(struct kvm_vcpu *vcpu,
32962306a36Sopenharmony_ci				enum instruction_fetch_type type, ppc_inst_t *inst)
33062306a36Sopenharmony_ci{
33162306a36Sopenharmony_ci	int ret = EMULATE_DONE;
33262306a36Sopenharmony_ci	u32 fetched_inst;
33362306a36Sopenharmony_ci
33462306a36Sopenharmony_ci	/* Load the instruction manually if it failed to do so in the
33562306a36Sopenharmony_ci	 * exit path */
33662306a36Sopenharmony_ci	if (vcpu->arch.last_inst == KVM_INST_FETCH_FAILED)
33762306a36Sopenharmony_ci		ret = kvmppc_load_last_inst(vcpu, type, &vcpu->arch.last_inst);
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	/*  Write fetch_failed unswapped if the fetch failed */
34062306a36Sopenharmony_ci	if (ret != EMULATE_DONE) {
34162306a36Sopenharmony_ci		*inst = ppc_inst(KVM_INST_FETCH_FAILED);
34262306a36Sopenharmony_ci		return ret;
34362306a36Sopenharmony_ci	}
34462306a36Sopenharmony_ci
34562306a36Sopenharmony_ci#ifdef CONFIG_PPC64
34662306a36Sopenharmony_ci	/* Is this a prefixed instruction? */
34762306a36Sopenharmony_ci	if ((vcpu->arch.last_inst >> 32) != 0) {
34862306a36Sopenharmony_ci		u32 prefix = vcpu->arch.last_inst >> 32;
34962306a36Sopenharmony_ci		u32 suffix = vcpu->arch.last_inst;
35062306a36Sopenharmony_ci		if (kvmppc_need_byteswap(vcpu)) {
35162306a36Sopenharmony_ci			prefix = swab32(prefix);
35262306a36Sopenharmony_ci			suffix = swab32(suffix);
35362306a36Sopenharmony_ci		}
35462306a36Sopenharmony_ci		*inst = ppc_inst_prefix(prefix, suffix);
35562306a36Sopenharmony_ci		return EMULATE_DONE;
35662306a36Sopenharmony_ci	}
35762306a36Sopenharmony_ci#endif
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci	fetched_inst = kvmppc_need_byteswap(vcpu) ?
36062306a36Sopenharmony_ci		swab32(vcpu->arch.last_inst) :
36162306a36Sopenharmony_ci		vcpu->arch.last_inst;
36262306a36Sopenharmony_ci	*inst = ppc_inst(fetched_inst);
36362306a36Sopenharmony_ci	return EMULATE_DONE;
36462306a36Sopenharmony_ci}
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_cistatic inline bool is_kvmppc_hv_enabled(struct kvm *kvm)
36762306a36Sopenharmony_ci{
36862306a36Sopenharmony_ci	return kvm->arch.kvm_ops == kvmppc_hv_ops;
36962306a36Sopenharmony_ci}
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ciextern int kvmppc_hwrng_present(void);
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci/*
37462306a36Sopenharmony_ci * Cuts out inst bits with ordering according to spec.
37562306a36Sopenharmony_ci * That means the leftmost bit is zero. All given bits are included.
37662306a36Sopenharmony_ci */
37762306a36Sopenharmony_cistatic inline u32 kvmppc_get_field(u64 inst, int msb, int lsb)
37862306a36Sopenharmony_ci{
37962306a36Sopenharmony_ci	u32 r;
38062306a36Sopenharmony_ci	u32 mask;
38162306a36Sopenharmony_ci
38262306a36Sopenharmony_ci	BUG_ON(msb > lsb);
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_ci	mask = (1 << (lsb - msb + 1)) - 1;
38562306a36Sopenharmony_ci	r = (inst >> (63 - lsb)) & mask;
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci	return r;
38862306a36Sopenharmony_ci}
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci/*
39162306a36Sopenharmony_ci * Replaces inst bits with ordering according to spec.
39262306a36Sopenharmony_ci */
39362306a36Sopenharmony_cistatic inline u32 kvmppc_set_field(u64 inst, int msb, int lsb, int value)
39462306a36Sopenharmony_ci{
39562306a36Sopenharmony_ci	u32 r;
39662306a36Sopenharmony_ci	u32 mask;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	BUG_ON(msb > lsb);
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	mask = ((1 << (lsb - msb + 1)) - 1) << (63 - lsb);
40162306a36Sopenharmony_ci	r = (inst & ~mask) | ((value << (63 - lsb)) & mask);
40262306a36Sopenharmony_ci
40362306a36Sopenharmony_ci	return r;
40462306a36Sopenharmony_ci}
40562306a36Sopenharmony_ci
40662306a36Sopenharmony_ci#define one_reg_size(id)	\
40762306a36Sopenharmony_ci	(1ul << (((id) & KVM_REG_SIZE_MASK) >> KVM_REG_SIZE_SHIFT))
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci#define get_reg_val(id, reg)	({		\
41062306a36Sopenharmony_ci	union kvmppc_one_reg __u;		\
41162306a36Sopenharmony_ci	switch (one_reg_size(id)) {		\
41262306a36Sopenharmony_ci	case 4: __u.wval = (reg); break;	\
41362306a36Sopenharmony_ci	case 8: __u.dval = (reg); break;	\
41462306a36Sopenharmony_ci	default: BUG();				\
41562306a36Sopenharmony_ci	}					\
41662306a36Sopenharmony_ci	__u;					\
41762306a36Sopenharmony_ci})
41862306a36Sopenharmony_ci
41962306a36Sopenharmony_ci
42062306a36Sopenharmony_ci#define set_reg_val(id, val)	({		\
42162306a36Sopenharmony_ci	u64 __v;				\
42262306a36Sopenharmony_ci	switch (one_reg_size(id)) {		\
42362306a36Sopenharmony_ci	case 4: __v = (val).wval; break;	\
42462306a36Sopenharmony_ci	case 8: __v = (val).dval; break;	\
42562306a36Sopenharmony_ci	default: BUG();				\
42662306a36Sopenharmony_ci	}					\
42762306a36Sopenharmony_ci	__v;					\
42862306a36Sopenharmony_ci})
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ciint kvmppc_core_get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
43162306a36Sopenharmony_ciint kvmppc_core_set_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ciint kvmppc_get_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
43462306a36Sopenharmony_ciint kvmppc_set_sregs_ivor(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs);
43562306a36Sopenharmony_ci
43662306a36Sopenharmony_ciint kvm_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
43762306a36Sopenharmony_ciint kvm_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, struct kvm_one_reg *reg);
43862306a36Sopenharmony_ciint kvmppc_get_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
43962306a36Sopenharmony_ciint kvmppc_set_one_reg(struct kvm_vcpu *vcpu, u64 id, union kvmppc_one_reg *);
44062306a36Sopenharmony_ci
44162306a36Sopenharmony_civoid kvmppc_set_pid(struct kvm_vcpu *vcpu, u32 pid);
44262306a36Sopenharmony_ci
44362306a36Sopenharmony_cistruct openpic;
44462306a36Sopenharmony_ci
44562306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_HV_POSSIBLE
44662306a36Sopenharmony_ciextern void kvm_cma_reserve(void) __init;
44762306a36Sopenharmony_cistatic inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
44862306a36Sopenharmony_ci{
44962306a36Sopenharmony_ci	paca_ptrs[cpu]->kvm_hstate.xics_phys = (void __iomem *)addr;
45062306a36Sopenharmony_ci}
45162306a36Sopenharmony_ci
45262306a36Sopenharmony_cistatic inline void kvmppc_set_xive_tima(int cpu,
45362306a36Sopenharmony_ci					unsigned long phys_addr,
45462306a36Sopenharmony_ci					void __iomem *virt_addr)
45562306a36Sopenharmony_ci{
45662306a36Sopenharmony_ci	paca_ptrs[cpu]->kvm_hstate.xive_tima_phys = (void __iomem *)phys_addr;
45762306a36Sopenharmony_ci	paca_ptrs[cpu]->kvm_hstate.xive_tima_virt = virt_addr;
45862306a36Sopenharmony_ci}
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_cistatic inline u32 kvmppc_get_xics_latch(void)
46162306a36Sopenharmony_ci{
46262306a36Sopenharmony_ci	u32 xirr;
46362306a36Sopenharmony_ci
46462306a36Sopenharmony_ci	xirr = get_paca()->kvm_hstate.saved_xirr;
46562306a36Sopenharmony_ci	get_paca()->kvm_hstate.saved_xirr = 0;
46662306a36Sopenharmony_ci	return xirr;
46762306a36Sopenharmony_ci}
46862306a36Sopenharmony_ci
46962306a36Sopenharmony_ci/*
47062306a36Sopenharmony_ci * To avoid the need to unnecessarily exit fully to the host kernel, an IPI to
47162306a36Sopenharmony_ci * a CPU thread that's running/napping inside of a guest is by default regarded
47262306a36Sopenharmony_ci * as a request to wake the CPU (if needed) and continue execution within the
47362306a36Sopenharmony_ci * guest, potentially to process new state like externally-generated
47462306a36Sopenharmony_ci * interrupts or IPIs sent from within the guest itself (e.g. H_PROD/H_IPI).
47562306a36Sopenharmony_ci *
47662306a36Sopenharmony_ci * To force an exit to the host kernel, kvmppc_set_host_ipi() must be called
47762306a36Sopenharmony_ci * prior to issuing the IPI to set the corresponding 'host_ipi' flag in the
47862306a36Sopenharmony_ci * target CPU's PACA. To avoid unnecessary exits to the host, this flag should
47962306a36Sopenharmony_ci * be immediately cleared via kvmppc_clear_host_ipi() by the IPI handler on
48062306a36Sopenharmony_ci * the receiving side prior to processing the IPI work.
48162306a36Sopenharmony_ci *
48262306a36Sopenharmony_ci * NOTE:
48362306a36Sopenharmony_ci *
48462306a36Sopenharmony_ci * We currently issue an smp_mb() at the beginning of kvmppc_set_host_ipi().
48562306a36Sopenharmony_ci * This is to guard against sequences such as the following:
48662306a36Sopenharmony_ci *
48762306a36Sopenharmony_ci *      CPU
48862306a36Sopenharmony_ci *        X: smp_muxed_ipi_set_message():
48962306a36Sopenharmony_ci *        X:   smp_mb()
49062306a36Sopenharmony_ci *        X:   message[RESCHEDULE] = 1
49162306a36Sopenharmony_ci *        X: doorbell_global_ipi(42):
49262306a36Sopenharmony_ci *        X:   kvmppc_set_host_ipi(42)
49362306a36Sopenharmony_ci *        X:   ppc_msgsnd_sync()/smp_mb()
49462306a36Sopenharmony_ci *        X:   ppc_msgsnd() -> 42
49562306a36Sopenharmony_ci *       42: doorbell_exception(): // from CPU X
49662306a36Sopenharmony_ci *       42:   ppc_msgsync()
49762306a36Sopenharmony_ci *      105: smp_muxed_ipi_set_message():
49862306a36Sopenharmony_ci *      105:   smb_mb()
49962306a36Sopenharmony_ci *           // STORE DEFERRED DUE TO RE-ORDERING
50062306a36Sopenharmony_ci *    --105:   message[CALL_FUNCTION] = 1
50162306a36Sopenharmony_ci *    | 105: doorbell_global_ipi(42):
50262306a36Sopenharmony_ci *    | 105:   kvmppc_set_host_ipi(42)
50362306a36Sopenharmony_ci *    |  42:   kvmppc_clear_host_ipi(42)
50462306a36Sopenharmony_ci *    |  42: smp_ipi_demux_relaxed()
50562306a36Sopenharmony_ci *    |  42: // returns to executing guest
50662306a36Sopenharmony_ci *    |      // RE-ORDERED STORE COMPLETES
50762306a36Sopenharmony_ci *    ->105:   message[CALL_FUNCTION] = 1
50862306a36Sopenharmony_ci *      105:   ppc_msgsnd_sync()/smp_mb()
50962306a36Sopenharmony_ci *      105:   ppc_msgsnd() -> 42
51062306a36Sopenharmony_ci *       42: local_paca->kvm_hstate.host_ipi == 0 // IPI ignored
51162306a36Sopenharmony_ci *      105: // hangs waiting on 42 to process messages/call_single_queue
51262306a36Sopenharmony_ci *
51362306a36Sopenharmony_ci * We also issue an smp_mb() at the end of kvmppc_clear_host_ipi(). This is
51462306a36Sopenharmony_ci * to guard against sequences such as the following (as well as to create
51562306a36Sopenharmony_ci * a read-side pairing with the barrier in kvmppc_set_host_ipi()):
51662306a36Sopenharmony_ci *
51762306a36Sopenharmony_ci *      CPU
51862306a36Sopenharmony_ci *        X: smp_muxed_ipi_set_message():
51962306a36Sopenharmony_ci *        X:   smp_mb()
52062306a36Sopenharmony_ci *        X:   message[RESCHEDULE] = 1
52162306a36Sopenharmony_ci *        X: doorbell_global_ipi(42):
52262306a36Sopenharmony_ci *        X:   kvmppc_set_host_ipi(42)
52362306a36Sopenharmony_ci *        X:   ppc_msgsnd_sync()/smp_mb()
52462306a36Sopenharmony_ci *        X:   ppc_msgsnd() -> 42
52562306a36Sopenharmony_ci *       42: doorbell_exception(): // from CPU X
52662306a36Sopenharmony_ci *       42:   ppc_msgsync()
52762306a36Sopenharmony_ci *           // STORE DEFERRED DUE TO RE-ORDERING
52862306a36Sopenharmony_ci *    -- 42:   kvmppc_clear_host_ipi(42)
52962306a36Sopenharmony_ci *    |  42: smp_ipi_demux_relaxed()
53062306a36Sopenharmony_ci *    | 105: smp_muxed_ipi_set_message():
53162306a36Sopenharmony_ci *    | 105:   smb_mb()
53262306a36Sopenharmony_ci *    | 105:   message[CALL_FUNCTION] = 1
53362306a36Sopenharmony_ci *    | 105: doorbell_global_ipi(42):
53462306a36Sopenharmony_ci *    | 105:   kvmppc_set_host_ipi(42)
53562306a36Sopenharmony_ci *    |      // RE-ORDERED STORE COMPLETES
53662306a36Sopenharmony_ci *    -> 42:   kvmppc_clear_host_ipi(42)
53762306a36Sopenharmony_ci *       42: // returns to executing guest
53862306a36Sopenharmony_ci *      105:   ppc_msgsnd_sync()/smp_mb()
53962306a36Sopenharmony_ci *      105:   ppc_msgsnd() -> 42
54062306a36Sopenharmony_ci *       42: local_paca->kvm_hstate.host_ipi == 0 // IPI ignored
54162306a36Sopenharmony_ci *      105: // hangs waiting on 42 to process messages/call_single_queue
54262306a36Sopenharmony_ci */
54362306a36Sopenharmony_cistatic inline void kvmppc_set_host_ipi(int cpu)
54462306a36Sopenharmony_ci{
54562306a36Sopenharmony_ci	/*
54662306a36Sopenharmony_ci	 * order stores of IPI messages vs. setting of host_ipi flag
54762306a36Sopenharmony_ci	 *
54862306a36Sopenharmony_ci	 * pairs with the barrier in kvmppc_clear_host_ipi()
54962306a36Sopenharmony_ci	 */
55062306a36Sopenharmony_ci	smp_mb();
55162306a36Sopenharmony_ci	WRITE_ONCE(paca_ptrs[cpu]->kvm_hstate.host_ipi, 1);
55262306a36Sopenharmony_ci}
55362306a36Sopenharmony_ci
55462306a36Sopenharmony_cistatic inline void kvmppc_clear_host_ipi(int cpu)
55562306a36Sopenharmony_ci{
55662306a36Sopenharmony_ci	WRITE_ONCE(paca_ptrs[cpu]->kvm_hstate.host_ipi, 0);
55762306a36Sopenharmony_ci	/*
55862306a36Sopenharmony_ci	 * order clearing of host_ipi flag vs. processing of IPI messages
55962306a36Sopenharmony_ci	 *
56062306a36Sopenharmony_ci	 * pairs with the barrier in kvmppc_set_host_ipi()
56162306a36Sopenharmony_ci	 */
56262306a36Sopenharmony_ci	smp_mb();
56362306a36Sopenharmony_ci}
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_cistatic inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
56662306a36Sopenharmony_ci{
56762306a36Sopenharmony_ci	vcpu->kvm->arch.kvm_ops->fast_vcpu_kick(vcpu);
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ciextern void kvm_hv_vm_activated(void);
57162306a36Sopenharmony_ciextern void kvm_hv_vm_deactivated(void);
57262306a36Sopenharmony_ciextern bool kvm_hv_mode_active(void);
57362306a36Sopenharmony_ci
57462306a36Sopenharmony_ciextern void kvmppc_check_need_tlb_flush(struct kvm *kvm, int pcpu);
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci#else
57762306a36Sopenharmony_cistatic inline void __init kvm_cma_reserve(void)
57862306a36Sopenharmony_ci{}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_cistatic inline void kvmppc_set_xics_phys(int cpu, unsigned long addr)
58162306a36Sopenharmony_ci{}
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_cistatic inline void kvmppc_set_xive_tima(int cpu,
58462306a36Sopenharmony_ci					unsigned long phys_addr,
58562306a36Sopenharmony_ci					void __iomem *virt_addr)
58662306a36Sopenharmony_ci{}
58762306a36Sopenharmony_ci
58862306a36Sopenharmony_cistatic inline u32 kvmppc_get_xics_latch(void)
58962306a36Sopenharmony_ci{
59062306a36Sopenharmony_ci	return 0;
59162306a36Sopenharmony_ci}
59262306a36Sopenharmony_ci
59362306a36Sopenharmony_cistatic inline void kvmppc_set_host_ipi(int cpu)
59462306a36Sopenharmony_ci{}
59562306a36Sopenharmony_ci
59662306a36Sopenharmony_cistatic inline void kvmppc_clear_host_ipi(int cpu)
59762306a36Sopenharmony_ci{}
59862306a36Sopenharmony_ci
59962306a36Sopenharmony_cistatic inline void kvmppc_fast_vcpu_kick(struct kvm_vcpu *vcpu)
60062306a36Sopenharmony_ci{
60162306a36Sopenharmony_ci	kvm_vcpu_kick(vcpu);
60262306a36Sopenharmony_ci}
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_cistatic inline bool kvm_hv_mode_active(void)		{ return false; }
60562306a36Sopenharmony_ci
60662306a36Sopenharmony_ci#endif
60762306a36Sopenharmony_ci
60862306a36Sopenharmony_ci#ifdef CONFIG_PPC_PSERIES
60962306a36Sopenharmony_cistatic inline bool kvmhv_on_pseries(void)
61062306a36Sopenharmony_ci{
61162306a36Sopenharmony_ci	return !cpu_has_feature(CPU_FTR_HVMODE);
61262306a36Sopenharmony_ci}
61362306a36Sopenharmony_ci#else
61462306a36Sopenharmony_cistatic inline bool kvmhv_on_pseries(void)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	return false;
61762306a36Sopenharmony_ci}
61862306a36Sopenharmony_ci#endif
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci#ifdef CONFIG_KVM_XICS
62162306a36Sopenharmony_cistatic inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
62262306a36Sopenharmony_ci{
62362306a36Sopenharmony_ci	return vcpu->arch.irq_type == KVMPPC_IRQ_XICS;
62462306a36Sopenharmony_ci}
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_cistatic inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap(
62762306a36Sopenharmony_ci				struct kvm *kvm)
62862306a36Sopenharmony_ci{
62962306a36Sopenharmony_ci	if (kvm && kvm_irq_bypass)
63062306a36Sopenharmony_ci		return kvm->arch.pimap;
63162306a36Sopenharmony_ci	return NULL;
63262306a36Sopenharmony_ci}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ciextern void kvmppc_alloc_host_rm_ops(void);
63562306a36Sopenharmony_ciextern void kvmppc_free_host_rm_ops(void);
63662306a36Sopenharmony_ciextern void kvmppc_free_pimap(struct kvm *kvm);
63762306a36Sopenharmony_ciextern int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall);
63862306a36Sopenharmony_ciextern void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu);
63962306a36Sopenharmony_ciextern int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd);
64062306a36Sopenharmony_ciextern int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req);
64162306a36Sopenharmony_ciextern u64 kvmppc_xics_get_icp(struct kvm_vcpu *vcpu);
64262306a36Sopenharmony_ciextern int kvmppc_xics_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
64362306a36Sopenharmony_ciextern int kvmppc_xics_connect_vcpu(struct kvm_device *dev,
64462306a36Sopenharmony_ci			struct kvm_vcpu *vcpu, u32 cpu);
64562306a36Sopenharmony_ciextern void kvmppc_xics_ipi_action(void);
64662306a36Sopenharmony_ciextern void kvmppc_xics_set_mapped(struct kvm *kvm, unsigned long guest_irq,
64762306a36Sopenharmony_ci				   unsigned long host_irq);
64862306a36Sopenharmony_ciextern void kvmppc_xics_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
64962306a36Sopenharmony_ci				   unsigned long host_irq);
65062306a36Sopenharmony_ciextern long kvmppc_deliver_irq_passthru(struct kvm_vcpu *vcpu, __be32 xirr,
65162306a36Sopenharmony_ci					struct kvmppc_irq_map *irq_map,
65262306a36Sopenharmony_ci					struct kvmppc_passthru_irqmap *pimap,
65362306a36Sopenharmony_ci					bool *again);
65462306a36Sopenharmony_ci
65562306a36Sopenharmony_ciextern int kvmppc_xics_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
65662306a36Sopenharmony_ci			       int level, bool line_status);
65762306a36Sopenharmony_ci
65862306a36Sopenharmony_ciextern int h_ipi_redirect;
65962306a36Sopenharmony_ci#else
66062306a36Sopenharmony_cistatic inline struct kvmppc_passthru_irqmap *kvmppc_get_passthru_irqmap(
66162306a36Sopenharmony_ci				struct kvm *kvm)
66262306a36Sopenharmony_ci	{ return NULL; }
66362306a36Sopenharmony_cistatic inline void kvmppc_alloc_host_rm_ops(void) {}
66462306a36Sopenharmony_cistatic inline void kvmppc_free_host_rm_ops(void) {}
66562306a36Sopenharmony_cistatic inline void kvmppc_free_pimap(struct kvm *kvm) {}
66662306a36Sopenharmony_cistatic inline int kvmppc_xics_rm_complete(struct kvm_vcpu *vcpu, u32 hcall)
66762306a36Sopenharmony_ci	{ return 0; }
66862306a36Sopenharmony_cistatic inline int kvmppc_xics_enabled(struct kvm_vcpu *vcpu)
66962306a36Sopenharmony_ci	{ return 0; }
67062306a36Sopenharmony_cistatic inline void kvmppc_xics_free_icp(struct kvm_vcpu *vcpu) { }
67162306a36Sopenharmony_cistatic inline int kvmppc_xics_hcall(struct kvm_vcpu *vcpu, u32 cmd)
67262306a36Sopenharmony_ci	{ return 0; }
67362306a36Sopenharmony_cistatic inline int kvmppc_xive_xics_hcall(struct kvm_vcpu *vcpu, u32 req)
67462306a36Sopenharmony_ci	{ return 0; }
67562306a36Sopenharmony_ci#endif
67662306a36Sopenharmony_ci
67762306a36Sopenharmony_ci#ifdef CONFIG_KVM_XIVE
67862306a36Sopenharmony_ci/*
67962306a36Sopenharmony_ci * Below the first "xive" is the "eXternal Interrupt Virtualization Engine"
68062306a36Sopenharmony_ci * ie. P9 new interrupt controller, while the second "xive" is the legacy
68162306a36Sopenharmony_ci * "eXternal Interrupt Vector Entry" which is the configuration of an
68262306a36Sopenharmony_ci * interrupt on the "xics" interrupt controller on P8 and earlier. Those
68362306a36Sopenharmony_ci * two function consume or produce a legacy "XIVE" state from the
68462306a36Sopenharmony_ci * new "XIVE" interrupt controller.
68562306a36Sopenharmony_ci */
68662306a36Sopenharmony_ciextern int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
68762306a36Sopenharmony_ci				u32 priority);
68862306a36Sopenharmony_ciextern int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
68962306a36Sopenharmony_ci				u32 *priority);
69062306a36Sopenharmony_ciextern int kvmppc_xive_int_on(struct kvm *kvm, u32 irq);
69162306a36Sopenharmony_ciextern int kvmppc_xive_int_off(struct kvm *kvm, u32 irq);
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ciextern int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
69462306a36Sopenharmony_ci				    struct kvm_vcpu *vcpu, u32 cpu);
69562306a36Sopenharmony_ciextern void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu);
69662306a36Sopenharmony_ciextern int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
69762306a36Sopenharmony_ci				  unsigned long host_irq);
69862306a36Sopenharmony_ciextern int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
69962306a36Sopenharmony_ci				  unsigned long host_irq);
70062306a36Sopenharmony_ciextern u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu);
70162306a36Sopenharmony_ciextern int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval);
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_ciextern int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
70462306a36Sopenharmony_ci			       int level, bool line_status);
70562306a36Sopenharmony_ciextern void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu);
70662306a36Sopenharmony_ciextern void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu);
70762306a36Sopenharmony_ciextern bool kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu);
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_cistatic inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
71062306a36Sopenharmony_ci{
71162306a36Sopenharmony_ci	return vcpu->arch.irq_type == KVMPPC_IRQ_XIVE;
71262306a36Sopenharmony_ci}
71362306a36Sopenharmony_ci
71462306a36Sopenharmony_ciextern int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
71562306a36Sopenharmony_ci					   struct kvm_vcpu *vcpu, u32 cpu);
71662306a36Sopenharmony_ciextern void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu);
71762306a36Sopenharmony_ciextern int kvmppc_xive_native_get_vp(struct kvm_vcpu *vcpu,
71862306a36Sopenharmony_ci				     union kvmppc_one_reg *val);
71962306a36Sopenharmony_ciextern int kvmppc_xive_native_set_vp(struct kvm_vcpu *vcpu,
72062306a36Sopenharmony_ci				     union kvmppc_one_reg *val);
72162306a36Sopenharmony_ciextern bool kvmppc_xive_native_supported(void);
72262306a36Sopenharmony_ci
72362306a36Sopenharmony_ci#else
72462306a36Sopenharmony_cistatic inline int kvmppc_xive_set_xive(struct kvm *kvm, u32 irq, u32 server,
72562306a36Sopenharmony_ci				       u32 priority) { return -1; }
72662306a36Sopenharmony_cistatic inline int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
72762306a36Sopenharmony_ci				       u32 *priority) { return -1; }
72862306a36Sopenharmony_cistatic inline int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) { return -1; }
72962306a36Sopenharmony_cistatic inline int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) { return -1; }
73062306a36Sopenharmony_ci
73162306a36Sopenharmony_cistatic inline int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
73262306a36Sopenharmony_ci					   struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
73362306a36Sopenharmony_cistatic inline void kvmppc_xive_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
73462306a36Sopenharmony_cistatic inline int kvmppc_xive_set_mapped(struct kvm *kvm, unsigned long guest_irq,
73562306a36Sopenharmony_ci					 struct irq_desc *host_desc) { return -ENODEV; }
73662306a36Sopenharmony_cistatic inline int kvmppc_xive_clr_mapped(struct kvm *kvm, unsigned long guest_irq,
73762306a36Sopenharmony_ci					 struct irq_desc *host_desc) { return -ENODEV; }
73862306a36Sopenharmony_cistatic inline u64 kvmppc_xive_get_icp(struct kvm_vcpu *vcpu) { return 0; }
73962306a36Sopenharmony_cistatic inline int kvmppc_xive_set_icp(struct kvm_vcpu *vcpu, u64 icpval) { return -ENOENT; }
74062306a36Sopenharmony_ci
74162306a36Sopenharmony_cistatic inline int kvmppc_xive_set_irq(struct kvm *kvm, int irq_source_id, u32 irq,
74262306a36Sopenharmony_ci				      int level, bool line_status) { return -ENODEV; }
74362306a36Sopenharmony_cistatic inline void kvmppc_xive_push_vcpu(struct kvm_vcpu *vcpu) { }
74462306a36Sopenharmony_cistatic inline void kvmppc_xive_pull_vcpu(struct kvm_vcpu *vcpu) { }
74562306a36Sopenharmony_cistatic inline bool kvmppc_xive_rearm_escalation(struct kvm_vcpu *vcpu) { return true; }
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_cistatic inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
74862306a36Sopenharmony_ci	{ return 0; }
74962306a36Sopenharmony_cistatic inline int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
75062306a36Sopenharmony_ci			  struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
75162306a36Sopenharmony_cistatic inline void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
75262306a36Sopenharmony_cistatic inline int kvmppc_xive_native_get_vp(struct kvm_vcpu *vcpu,
75362306a36Sopenharmony_ci					    union kvmppc_one_reg *val)
75462306a36Sopenharmony_ci{ return 0; }
75562306a36Sopenharmony_cistatic inline int kvmppc_xive_native_set_vp(struct kvm_vcpu *vcpu,
75662306a36Sopenharmony_ci					    union kvmppc_one_reg *val)
75762306a36Sopenharmony_ci{ return -ENOENT; }
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci#endif /* CONFIG_KVM_XIVE */
76062306a36Sopenharmony_ci
76162306a36Sopenharmony_ci#if defined(CONFIG_PPC_POWERNV) && defined(CONFIG_KVM_BOOK3S_64_HANDLER)
76262306a36Sopenharmony_cistatic inline bool xics_on_xive(void)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	return xive_enabled() && cpu_has_feature(CPU_FTR_HVMODE);
76562306a36Sopenharmony_ci}
76662306a36Sopenharmony_ci#else
76762306a36Sopenharmony_cistatic inline bool xics_on_xive(void)
76862306a36Sopenharmony_ci{
76962306a36Sopenharmony_ci	return false;
77062306a36Sopenharmony_ci}
77162306a36Sopenharmony_ci#endif
77262306a36Sopenharmony_ci
77362306a36Sopenharmony_ci/*
77462306a36Sopenharmony_ci * Prototypes for functions called only from assembler code.
77562306a36Sopenharmony_ci * Having prototypes reduces sparse errors.
77662306a36Sopenharmony_ci */
77762306a36Sopenharmony_cilong kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
77862306a36Sopenharmony_ci			 unsigned long ioba, unsigned long tce);
77962306a36Sopenharmony_cilong kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
78062306a36Sopenharmony_ci				  unsigned long liobn, unsigned long ioba,
78162306a36Sopenharmony_ci				  unsigned long tce_list, unsigned long npages);
78262306a36Sopenharmony_cilong kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
78362306a36Sopenharmony_ci			   unsigned long liobn, unsigned long ioba,
78462306a36Sopenharmony_ci			   unsigned long tce_value, unsigned long npages);
78562306a36Sopenharmony_cilong int kvmppc_rm_h_confer(struct kvm_vcpu *vcpu, int target,
78662306a36Sopenharmony_ci                            unsigned int yield_count);
78762306a36Sopenharmony_cilong kvmppc_rm_h_random(struct kvm_vcpu *vcpu);
78862306a36Sopenharmony_civoid kvmhv_commence_exit(int trap);
78962306a36Sopenharmony_civoid kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu);
79062306a36Sopenharmony_civoid kvmppc_subcore_enter_guest(void);
79162306a36Sopenharmony_civoid kvmppc_subcore_exit_guest(void);
79262306a36Sopenharmony_cilong kvmppc_realmode_hmi_handler(void);
79362306a36Sopenharmony_cilong kvmppc_p9_realmode_hmi_handler(struct kvm_vcpu *vcpu);
79462306a36Sopenharmony_cilong kvmppc_h_enter(struct kvm_vcpu *vcpu, unsigned long flags,
79562306a36Sopenharmony_ci                    long pte_index, unsigned long pteh, unsigned long ptel);
79662306a36Sopenharmony_cilong kvmppc_h_remove(struct kvm_vcpu *vcpu, unsigned long flags,
79762306a36Sopenharmony_ci                     unsigned long pte_index, unsigned long avpn);
79862306a36Sopenharmony_cilong kvmppc_h_bulk_remove(struct kvm_vcpu *vcpu);
79962306a36Sopenharmony_cilong kvmppc_h_protect(struct kvm_vcpu *vcpu, unsigned long flags,
80062306a36Sopenharmony_ci                      unsigned long pte_index, unsigned long avpn);
80162306a36Sopenharmony_cilong kvmppc_h_read(struct kvm_vcpu *vcpu, unsigned long flags,
80262306a36Sopenharmony_ci                   unsigned long pte_index);
80362306a36Sopenharmony_cilong kvmppc_h_clear_ref(struct kvm_vcpu *vcpu, unsigned long flags,
80462306a36Sopenharmony_ci                        unsigned long pte_index);
80562306a36Sopenharmony_cilong kvmppc_h_clear_mod(struct kvm_vcpu *vcpu, unsigned long flags,
80662306a36Sopenharmony_ci                        unsigned long pte_index);
80762306a36Sopenharmony_cilong kvmppc_rm_h_page_init(struct kvm_vcpu *vcpu, unsigned long flags,
80862306a36Sopenharmony_ci			   unsigned long dest, unsigned long src);
80962306a36Sopenharmony_cilong kvmppc_hpte_hv_fault(struct kvm_vcpu *vcpu, unsigned long addr,
81062306a36Sopenharmony_ci                          unsigned long slb_v, unsigned int status, bool data);
81162306a36Sopenharmony_civoid kvmppc_guest_entry_inject_int(struct kvm_vcpu *vcpu);
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci/*
81462306a36Sopenharmony_ci * Host-side operations we want to set up while running in real
81562306a36Sopenharmony_ci * mode in the guest operating on the xics.
81662306a36Sopenharmony_ci * Currently only VCPU wakeup is supported.
81762306a36Sopenharmony_ci */
81862306a36Sopenharmony_ci
81962306a36Sopenharmony_ciunion kvmppc_rm_state {
82062306a36Sopenharmony_ci	unsigned long raw;
82162306a36Sopenharmony_ci	struct {
82262306a36Sopenharmony_ci		u32 in_host;
82362306a36Sopenharmony_ci		u32 rm_action;
82462306a36Sopenharmony_ci	};
82562306a36Sopenharmony_ci};
82662306a36Sopenharmony_ci
82762306a36Sopenharmony_cistruct kvmppc_host_rm_core {
82862306a36Sopenharmony_ci	union kvmppc_rm_state rm_state;
82962306a36Sopenharmony_ci	void *rm_data;
83062306a36Sopenharmony_ci	char pad[112];
83162306a36Sopenharmony_ci};
83262306a36Sopenharmony_ci
83362306a36Sopenharmony_cistruct kvmppc_host_rm_ops {
83462306a36Sopenharmony_ci	struct kvmppc_host_rm_core	*rm_core;
83562306a36Sopenharmony_ci	void		(*vcpu_kick)(struct kvm_vcpu *vcpu);
83662306a36Sopenharmony_ci};
83762306a36Sopenharmony_ci
83862306a36Sopenharmony_ciextern struct kvmppc_host_rm_ops *kvmppc_host_rm_ops_hv;
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_cistatic inline unsigned long kvmppc_get_epr(struct kvm_vcpu *vcpu)
84162306a36Sopenharmony_ci{
84262306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOKE_HV
84362306a36Sopenharmony_ci	return mfspr(SPRN_GEPR);
84462306a36Sopenharmony_ci#elif defined(CONFIG_BOOKE)
84562306a36Sopenharmony_ci	return vcpu->arch.epr;
84662306a36Sopenharmony_ci#else
84762306a36Sopenharmony_ci	return 0;
84862306a36Sopenharmony_ci#endif
84962306a36Sopenharmony_ci}
85062306a36Sopenharmony_ci
85162306a36Sopenharmony_cistatic inline void kvmppc_set_epr(struct kvm_vcpu *vcpu, u32 epr)
85262306a36Sopenharmony_ci{
85362306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOKE_HV
85462306a36Sopenharmony_ci	mtspr(SPRN_GEPR, epr);
85562306a36Sopenharmony_ci#elif defined(CONFIG_BOOKE)
85662306a36Sopenharmony_ci	vcpu->arch.epr = epr;
85762306a36Sopenharmony_ci#endif
85862306a36Sopenharmony_ci}
85962306a36Sopenharmony_ci
86062306a36Sopenharmony_ci#ifdef CONFIG_KVM_MPIC
86162306a36Sopenharmony_ci
86262306a36Sopenharmony_civoid kvmppc_mpic_set_epr(struct kvm_vcpu *vcpu);
86362306a36Sopenharmony_ciint kvmppc_mpic_connect_vcpu(struct kvm_device *dev, struct kvm_vcpu *vcpu,
86462306a36Sopenharmony_ci			     u32 cpu);
86562306a36Sopenharmony_civoid kvmppc_mpic_disconnect_vcpu(struct openpic *opp, struct kvm_vcpu *vcpu);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci#else
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_cistatic inline void kvmppc_mpic_set_epr(struct kvm_vcpu *vcpu)
87062306a36Sopenharmony_ci{
87162306a36Sopenharmony_ci}
87262306a36Sopenharmony_ci
87362306a36Sopenharmony_cistatic inline int kvmppc_mpic_connect_vcpu(struct kvm_device *dev,
87462306a36Sopenharmony_ci		struct kvm_vcpu *vcpu, u32 cpu)
87562306a36Sopenharmony_ci{
87662306a36Sopenharmony_ci	return -EINVAL;
87762306a36Sopenharmony_ci}
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_cistatic inline void kvmppc_mpic_disconnect_vcpu(struct openpic *opp,
88062306a36Sopenharmony_ci		struct kvm_vcpu *vcpu)
88162306a36Sopenharmony_ci{
88262306a36Sopenharmony_ci}
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ci#endif /* CONFIG_KVM_MPIC */
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ciint kvm_vcpu_ioctl_config_tlb(struct kvm_vcpu *vcpu,
88762306a36Sopenharmony_ci			      struct kvm_config_tlb *cfg);
88862306a36Sopenharmony_ciint kvm_vcpu_ioctl_dirty_tlb(struct kvm_vcpu *vcpu,
88962306a36Sopenharmony_ci			     struct kvm_dirty_tlb *cfg);
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_cilong kvmppc_alloc_lpid(void);
89262306a36Sopenharmony_civoid kvmppc_free_lpid(long lpid);
89362306a36Sopenharmony_civoid kvmppc_init_lpid(unsigned long nr_lpids);
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_cistatic inline void kvmppc_mmu_flush_icache(kvm_pfn_t pfn)
89662306a36Sopenharmony_ci{
89762306a36Sopenharmony_ci	struct folio *folio;
89862306a36Sopenharmony_ci	/*
89962306a36Sopenharmony_ci	 * We can only access pages that the kernel maps
90062306a36Sopenharmony_ci	 * as memory. Bail out for unmapped ones.
90162306a36Sopenharmony_ci	 */
90262306a36Sopenharmony_ci	if (!pfn_valid(pfn))
90362306a36Sopenharmony_ci		return;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	/* Clear i-cache for new pages */
90662306a36Sopenharmony_ci	folio = page_folio(pfn_to_page(pfn));
90762306a36Sopenharmony_ci	if (!test_bit(PG_dcache_clean, &folio->flags)) {
90862306a36Sopenharmony_ci		flush_dcache_icache_folio(folio);
90962306a36Sopenharmony_ci		set_bit(PG_dcache_clean, &folio->flags);
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci}
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci/*
91462306a36Sopenharmony_ci * Shared struct helpers. The shared struct can be little or big endian,
91562306a36Sopenharmony_ci * depending on the guest endianness. So expose helpers to all of them.
91662306a36Sopenharmony_ci */
91762306a36Sopenharmony_cistatic inline bool kvmppc_shared_big_endian(struct kvm_vcpu *vcpu)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci#if defined(CONFIG_PPC_BOOK3S_64) && defined(CONFIG_KVM_BOOK3S_PR_POSSIBLE)
92062306a36Sopenharmony_ci	/* Only Book3S_64 PR supports bi-endian for now */
92162306a36Sopenharmony_ci	return vcpu->arch.shared_big_endian;
92262306a36Sopenharmony_ci#elif defined(CONFIG_PPC_BOOK3S_64) && defined(__LITTLE_ENDIAN__)
92362306a36Sopenharmony_ci	/* Book3s_64 HV on little endian is always little endian */
92462306a36Sopenharmony_ci	return false;
92562306a36Sopenharmony_ci#else
92662306a36Sopenharmony_ci	return true;
92762306a36Sopenharmony_ci#endif
92862306a36Sopenharmony_ci}
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci#define SPRNG_WRAPPER_GET(reg, bookehv_spr)				\
93162306a36Sopenharmony_cistatic inline ulong kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
93262306a36Sopenharmony_ci{									\
93362306a36Sopenharmony_ci	return mfspr(bookehv_spr);					\
93462306a36Sopenharmony_ci}									\
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci#define SPRNG_WRAPPER_SET(reg, bookehv_spr)				\
93762306a36Sopenharmony_cistatic inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, ulong val)	\
93862306a36Sopenharmony_ci{									\
93962306a36Sopenharmony_ci	mtspr(bookehv_spr, val);						\
94062306a36Sopenharmony_ci}									\
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci#define SHARED_WRAPPER_GET(reg, size)					\
94362306a36Sopenharmony_cistatic inline u##size kvmppc_get_##reg(struct kvm_vcpu *vcpu)		\
94462306a36Sopenharmony_ci{									\
94562306a36Sopenharmony_ci	if (kvmppc_shared_big_endian(vcpu))				\
94662306a36Sopenharmony_ci	       return be##size##_to_cpu(vcpu->arch.shared->reg);	\
94762306a36Sopenharmony_ci	else								\
94862306a36Sopenharmony_ci	       return le##size##_to_cpu(vcpu->arch.shared->reg);	\
94962306a36Sopenharmony_ci}									\
95062306a36Sopenharmony_ci
95162306a36Sopenharmony_ci#define SHARED_WRAPPER_SET(reg, size)					\
95262306a36Sopenharmony_cistatic inline void kvmppc_set_##reg(struct kvm_vcpu *vcpu, u##size val)	\
95362306a36Sopenharmony_ci{									\
95462306a36Sopenharmony_ci	if (kvmppc_shared_big_endian(vcpu))				\
95562306a36Sopenharmony_ci	       vcpu->arch.shared->reg = cpu_to_be##size(val);		\
95662306a36Sopenharmony_ci	else								\
95762306a36Sopenharmony_ci	       vcpu->arch.shared->reg = cpu_to_le##size(val);		\
95862306a36Sopenharmony_ci}									\
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci#define SHARED_WRAPPER(reg, size)					\
96162306a36Sopenharmony_ci	SHARED_WRAPPER_GET(reg, size)					\
96262306a36Sopenharmony_ci	SHARED_WRAPPER_SET(reg, size)					\
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci#define SPRNG_WRAPPER(reg, bookehv_spr)					\
96562306a36Sopenharmony_ci	SPRNG_WRAPPER_GET(reg, bookehv_spr)				\
96662306a36Sopenharmony_ci	SPRNG_WRAPPER_SET(reg, bookehv_spr)				\
96762306a36Sopenharmony_ci
96862306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOKE_HV
96962306a36Sopenharmony_ci
97062306a36Sopenharmony_ci#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr)			\
97162306a36Sopenharmony_ci	SPRNG_WRAPPER(reg, bookehv_spr)					\
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci#else
97462306a36Sopenharmony_ci
97562306a36Sopenharmony_ci#define SHARED_SPRNG_WRAPPER(reg, size, bookehv_spr)			\
97662306a36Sopenharmony_ci	SHARED_WRAPPER(reg, size)					\
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_ci#endif
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ciSHARED_WRAPPER(critical, 64)
98162306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(sprg0, 64, SPRN_GSPRG0)
98262306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(sprg1, 64, SPRN_GSPRG1)
98362306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(sprg2, 64, SPRN_GSPRG2)
98462306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(sprg3, 64, SPRN_GSPRG3)
98562306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(srr0, 64, SPRN_GSRR0)
98662306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(srr1, 64, SPRN_GSRR1)
98762306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(dar, 64, SPRN_GDEAR)
98862306a36Sopenharmony_ciSHARED_SPRNG_WRAPPER(esr, 64, SPRN_GESR)
98962306a36Sopenharmony_ciSHARED_WRAPPER_GET(msr, 64)
99062306a36Sopenharmony_cistatic inline void kvmppc_set_msr_fast(struct kvm_vcpu *vcpu, u64 val)
99162306a36Sopenharmony_ci{
99262306a36Sopenharmony_ci	if (kvmppc_shared_big_endian(vcpu))
99362306a36Sopenharmony_ci	       vcpu->arch.shared->msr = cpu_to_be64(val);
99462306a36Sopenharmony_ci	else
99562306a36Sopenharmony_ci	       vcpu->arch.shared->msr = cpu_to_le64(val);
99662306a36Sopenharmony_ci}
99762306a36Sopenharmony_ciSHARED_WRAPPER(dsisr, 32)
99862306a36Sopenharmony_ciSHARED_WRAPPER(int_pending, 32)
99962306a36Sopenharmony_ciSHARED_WRAPPER(sprg4, 64)
100062306a36Sopenharmony_ciSHARED_WRAPPER(sprg5, 64)
100162306a36Sopenharmony_ciSHARED_WRAPPER(sprg6, 64)
100262306a36Sopenharmony_ciSHARED_WRAPPER(sprg7, 64)
100362306a36Sopenharmony_ci
100462306a36Sopenharmony_cistatic inline u32 kvmppc_get_sr(struct kvm_vcpu *vcpu, int nr)
100562306a36Sopenharmony_ci{
100662306a36Sopenharmony_ci	if (kvmppc_shared_big_endian(vcpu))
100762306a36Sopenharmony_ci	       return be32_to_cpu(vcpu->arch.shared->sr[nr]);
100862306a36Sopenharmony_ci	else
100962306a36Sopenharmony_ci	       return le32_to_cpu(vcpu->arch.shared->sr[nr]);
101062306a36Sopenharmony_ci}
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_cistatic inline void kvmppc_set_sr(struct kvm_vcpu *vcpu, int nr, u32 val)
101362306a36Sopenharmony_ci{
101462306a36Sopenharmony_ci	if (kvmppc_shared_big_endian(vcpu))
101562306a36Sopenharmony_ci	       vcpu->arch.shared->sr[nr] = cpu_to_be32(val);
101662306a36Sopenharmony_ci	else
101762306a36Sopenharmony_ci	       vcpu->arch.shared->sr[nr] = cpu_to_le32(val);
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_ci/*
102162306a36Sopenharmony_ci * Please call after prepare_to_enter. This function puts the lazy ee and irq
102262306a36Sopenharmony_ci * disabled tracking state back to normal mode, without actually enabling
102362306a36Sopenharmony_ci * interrupts.
102462306a36Sopenharmony_ci */
102562306a36Sopenharmony_cistatic inline void kvmppc_fix_ee_before_entry(void)
102662306a36Sopenharmony_ci{
102762306a36Sopenharmony_ci	trace_hardirqs_on();
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_ci#ifdef CONFIG_PPC64
103062306a36Sopenharmony_ci	/*
103162306a36Sopenharmony_ci	 * To avoid races, the caller must have gone directly from having
103262306a36Sopenharmony_ci	 * interrupts fully-enabled to hard-disabled.
103362306a36Sopenharmony_ci	 */
103462306a36Sopenharmony_ci	WARN_ON(local_paca->irq_happened != PACA_IRQ_HARD_DIS);
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	/* Only need to enable IRQs by hard enabling them after this */
103762306a36Sopenharmony_ci	local_paca->irq_happened = 0;
103862306a36Sopenharmony_ci	irq_soft_mask_set(IRQS_ENABLED);
103962306a36Sopenharmony_ci#endif
104062306a36Sopenharmony_ci}
104162306a36Sopenharmony_ci
104262306a36Sopenharmony_cistatic inline void kvmppc_fix_ee_after_exit(void)
104362306a36Sopenharmony_ci{
104462306a36Sopenharmony_ci#ifdef CONFIG_PPC64
104562306a36Sopenharmony_ci	/* Only need to enable IRQs by hard enabling them after this */
104662306a36Sopenharmony_ci	local_paca->irq_happened = PACA_IRQ_HARD_DIS;
104762306a36Sopenharmony_ci	irq_soft_mask_set(IRQS_ALL_DISABLED);
104862306a36Sopenharmony_ci#endif
104962306a36Sopenharmony_ci
105062306a36Sopenharmony_ci	trace_hardirqs_off();
105162306a36Sopenharmony_ci}
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci
105462306a36Sopenharmony_cistatic inline ulong kvmppc_get_ea_indexed(struct kvm_vcpu *vcpu, int ra, int rb)
105562306a36Sopenharmony_ci{
105662306a36Sopenharmony_ci	ulong ea;
105762306a36Sopenharmony_ci	ulong msr_64bit = 0;
105862306a36Sopenharmony_ci
105962306a36Sopenharmony_ci	ea = kvmppc_get_gpr(vcpu, rb);
106062306a36Sopenharmony_ci	if (ra)
106162306a36Sopenharmony_ci		ea += kvmppc_get_gpr(vcpu, ra);
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci#if defined(CONFIG_PPC_BOOK3E_64)
106462306a36Sopenharmony_ci	msr_64bit = MSR_CM;
106562306a36Sopenharmony_ci#elif defined(CONFIG_PPC_BOOK3S_64)
106662306a36Sopenharmony_ci	msr_64bit = MSR_SF;
106762306a36Sopenharmony_ci#endif
106862306a36Sopenharmony_ci
106962306a36Sopenharmony_ci	if (!(kvmppc_get_msr(vcpu) & msr_64bit))
107062306a36Sopenharmony_ci		ea = (uint32_t)ea;
107162306a36Sopenharmony_ci
107262306a36Sopenharmony_ci	return ea;
107362306a36Sopenharmony_ci}
107462306a36Sopenharmony_ci
107562306a36Sopenharmony_ciextern void xics_wake_cpu(int cpu);
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci#endif /* __POWERPC_KVM_PPC_H__ */
1078