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