162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright SUSE Linux Products GmbH 2009 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Authors: Alexander Graf <agraf@suse.de> 762306a36Sopenharmony_ci */ 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci#ifndef __ASM_KVM_BOOK3S_H__ 1062306a36Sopenharmony_ci#define __ASM_KVM_BOOK3S_H__ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#include <linux/types.h> 1362306a36Sopenharmony_ci#include <linux/kvm_host.h> 1462306a36Sopenharmony_ci#include <asm/kvm_book3s_asm.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_cistruct kvmppc_bat { 1762306a36Sopenharmony_ci u64 raw; 1862306a36Sopenharmony_ci u32 bepi; 1962306a36Sopenharmony_ci u32 bepi_mask; 2062306a36Sopenharmony_ci u32 brpn; 2162306a36Sopenharmony_ci u8 wimg; 2262306a36Sopenharmony_ci u8 pp; 2362306a36Sopenharmony_ci bool vs : 1; 2462306a36Sopenharmony_ci bool vp : 1; 2562306a36Sopenharmony_ci}; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_cistruct kvmppc_sid_map { 2862306a36Sopenharmony_ci u64 guest_vsid; 2962306a36Sopenharmony_ci u64 guest_esid; 3062306a36Sopenharmony_ci u64 host_vsid; 3162306a36Sopenharmony_ci bool valid : 1; 3262306a36Sopenharmony_ci}; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define SID_MAP_BITS 9 3562306a36Sopenharmony_ci#define SID_MAP_NUM (1 << SID_MAP_BITS) 3662306a36Sopenharmony_ci#define SID_MAP_MASK (SID_MAP_NUM - 1) 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 3962306a36Sopenharmony_ci#define SID_CONTEXTS 1 4062306a36Sopenharmony_ci#else 4162306a36Sopenharmony_ci#define SID_CONTEXTS 128 4262306a36Sopenharmony_ci#define VSID_POOL_SIZE (SID_CONTEXTS * 16) 4362306a36Sopenharmony_ci#endif 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct hpte_cache { 4662306a36Sopenharmony_ci struct hlist_node list_pte; 4762306a36Sopenharmony_ci struct hlist_node list_pte_long; 4862306a36Sopenharmony_ci struct hlist_node list_vpte; 4962306a36Sopenharmony_ci struct hlist_node list_vpte_long; 5062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 5162306a36Sopenharmony_ci struct hlist_node list_vpte_64k; 5262306a36Sopenharmony_ci#endif 5362306a36Sopenharmony_ci struct rcu_head rcu_head; 5462306a36Sopenharmony_ci u64 host_vpn; 5562306a36Sopenharmony_ci u64 pfn; 5662306a36Sopenharmony_ci ulong slot; 5762306a36Sopenharmony_ci struct kvmppc_pte pte; 5862306a36Sopenharmony_ci int pagesize; 5962306a36Sopenharmony_ci}; 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* 6262306a36Sopenharmony_ci * Struct for a virtual core. 6362306a36Sopenharmony_ci * Note: entry_exit_map combines a bitmap of threads that have entered 6462306a36Sopenharmony_ci * in the bottom 8 bits and a bitmap of threads that have exited in the 6562306a36Sopenharmony_ci * next 8 bits. This is so that we can atomically set the entry bit 6662306a36Sopenharmony_ci * iff the exit map is 0 without taking a lock. 6762306a36Sopenharmony_ci */ 6862306a36Sopenharmony_cistruct kvmppc_vcore { 6962306a36Sopenharmony_ci int n_runnable; 7062306a36Sopenharmony_ci int num_threads; 7162306a36Sopenharmony_ci int entry_exit_map; 7262306a36Sopenharmony_ci int napping_threads; 7362306a36Sopenharmony_ci int first_vcpuid; 7462306a36Sopenharmony_ci u16 pcpu; 7562306a36Sopenharmony_ci u16 last_cpu; 7662306a36Sopenharmony_ci u8 vcore_state; 7762306a36Sopenharmony_ci u8 in_guest; 7862306a36Sopenharmony_ci struct kvm_vcpu *runnable_threads[MAX_SMT_THREADS]; 7962306a36Sopenharmony_ci struct list_head preempt_list; 8062306a36Sopenharmony_ci spinlock_t lock; 8162306a36Sopenharmony_ci struct rcuwait wait; 8262306a36Sopenharmony_ci spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */ 8362306a36Sopenharmony_ci u64 stolen_tb; 8462306a36Sopenharmony_ci u64 preempt_tb; 8562306a36Sopenharmony_ci struct kvm_vcpu *runner; 8662306a36Sopenharmony_ci struct kvm *kvm; 8762306a36Sopenharmony_ci u64 tb_offset; /* guest timebase - host timebase */ 8862306a36Sopenharmony_ci u64 tb_offset_applied; /* timebase offset currently in force */ 8962306a36Sopenharmony_ci ulong lpcr; 9062306a36Sopenharmony_ci u32 arch_compat; 9162306a36Sopenharmony_ci ulong pcr; 9262306a36Sopenharmony_ci ulong dpdes; /* doorbell state (POWER8) */ 9362306a36Sopenharmony_ci ulong vtb; /* virtual timebase */ 9462306a36Sopenharmony_ci ulong conferring_threads; 9562306a36Sopenharmony_ci unsigned int halt_poll_ns; 9662306a36Sopenharmony_ci atomic_t online_count; 9762306a36Sopenharmony_ci}; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_cistruct kvmppc_vcpu_book3s { 10062306a36Sopenharmony_ci struct kvmppc_sid_map sid_map[SID_MAP_NUM]; 10162306a36Sopenharmony_ci struct { 10262306a36Sopenharmony_ci u64 esid; 10362306a36Sopenharmony_ci u64 vsid; 10462306a36Sopenharmony_ci } slb_shadow[64]; 10562306a36Sopenharmony_ci u8 slb_shadow_max; 10662306a36Sopenharmony_ci struct kvmppc_bat ibat[8]; 10762306a36Sopenharmony_ci struct kvmppc_bat dbat[8]; 10862306a36Sopenharmony_ci u64 hid[6]; 10962306a36Sopenharmony_ci u64 gqr[8]; 11062306a36Sopenharmony_ci u64 sdr1; 11162306a36Sopenharmony_ci u64 hior; 11262306a36Sopenharmony_ci u64 msr_mask; 11362306a36Sopenharmony_ci u64 vtb; 11462306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_32 11562306a36Sopenharmony_ci u32 vsid_pool[VSID_POOL_SIZE]; 11662306a36Sopenharmony_ci u32 vsid_next; 11762306a36Sopenharmony_ci#else 11862306a36Sopenharmony_ci u64 proto_vsid_first; 11962306a36Sopenharmony_ci u64 proto_vsid_max; 12062306a36Sopenharmony_ci u64 proto_vsid_next; 12162306a36Sopenharmony_ci#endif 12262306a36Sopenharmony_ci int context_id[SID_CONTEXTS]; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci bool hior_explicit; /* HIOR is set by ioctl, not PVR */ 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE]; 12762306a36Sopenharmony_ci struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; 12862306a36Sopenharmony_ci struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; 12962306a36Sopenharmony_ci struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; 13062306a36Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 13162306a36Sopenharmony_ci struct hlist_head hpte_hash_vpte_64k[HPTEG_HASH_NUM_VPTE_64K]; 13262306a36Sopenharmony_ci#endif 13362306a36Sopenharmony_ci int hpte_cache_count; 13462306a36Sopenharmony_ci spinlock_t mmu_lock; 13562306a36Sopenharmony_ci}; 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci#define VSID_REAL 0x07ffffffffc00000ULL 13862306a36Sopenharmony_ci#define VSID_BAT 0x07ffffffffb00000ULL 13962306a36Sopenharmony_ci#define VSID_64K 0x0800000000000000ULL 14062306a36Sopenharmony_ci#define VSID_1T 0x1000000000000000ULL 14162306a36Sopenharmony_ci#define VSID_REAL_DR 0x2000000000000000ULL 14262306a36Sopenharmony_ci#define VSID_REAL_IR 0x4000000000000000ULL 14362306a36Sopenharmony_ci#define VSID_PR 0x8000000000000000ULL 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ciextern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask); 14662306a36Sopenharmony_ciextern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); 14762306a36Sopenharmony_ciextern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end); 14862306a36Sopenharmony_ciextern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); 14962306a36Sopenharmony_ciextern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); 15062306a36Sopenharmony_ciextern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); 15162306a36Sopenharmony_ciextern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); 15262306a36Sopenharmony_ciextern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, 15362306a36Sopenharmony_ci bool iswrite); 15462306a36Sopenharmony_ciextern void kvmppc_mmu_unmap_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); 15562306a36Sopenharmony_ciextern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); 15662306a36Sopenharmony_ciextern void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong eaddr, ulong seg_size); 15762306a36Sopenharmony_ciextern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); 15862306a36Sopenharmony_ciextern int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu, 15962306a36Sopenharmony_ci unsigned long addr, unsigned long status); 16062306a36Sopenharmony_ciextern long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, 16162306a36Sopenharmony_ci unsigned long slb_v, unsigned long valid); 16262306a36Sopenharmony_ciextern int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu, 16362306a36Sopenharmony_ci unsigned long gpa, gva_t ea, int is_store); 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ciextern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte); 16662306a36Sopenharmony_ciextern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu); 16762306a36Sopenharmony_ciextern void kvmppc_mmu_hpte_cache_free(struct hpte_cache *pte); 16862306a36Sopenharmony_ciextern void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu); 16962306a36Sopenharmony_ciextern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu); 17062306a36Sopenharmony_ciextern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte); 17162306a36Sopenharmony_ciextern int kvmppc_mmu_hpte_sysinit(void); 17262306a36Sopenharmony_ciextern void kvmppc_mmu_hpte_sysexit(void); 17362306a36Sopenharmony_ciextern int kvmppc_mmu_hv_init(void); 17462306a36Sopenharmony_ciextern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_ciextern int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu, 17762306a36Sopenharmony_ci unsigned long ea, unsigned long dsisr); 17862306a36Sopenharmony_ciextern unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid, 17962306a36Sopenharmony_ci gva_t eaddr, void *to, void *from, 18062306a36Sopenharmony_ci unsigned long n); 18162306a36Sopenharmony_ciextern long kvmhv_copy_from_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, 18262306a36Sopenharmony_ci void *to, unsigned long n); 18362306a36Sopenharmony_ciextern long kvmhv_copy_to_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, 18462306a36Sopenharmony_ci void *from, unsigned long n); 18562306a36Sopenharmony_ciextern int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr, 18662306a36Sopenharmony_ci struct kvmppc_pte *gpte, u64 root, 18762306a36Sopenharmony_ci u64 *pte_ret_p); 18862306a36Sopenharmony_ciextern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr, 18962306a36Sopenharmony_ci struct kvmppc_pte *gpte, u64 table, 19062306a36Sopenharmony_ci int table_index, u64 *pte_ret_p); 19162306a36Sopenharmony_ciextern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, 19262306a36Sopenharmony_ci struct kvmppc_pte *gpte, bool data, bool iswrite); 19362306a36Sopenharmony_ciextern void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, 19462306a36Sopenharmony_ci unsigned int pshift, unsigned int lpid); 19562306a36Sopenharmony_ciextern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, 19662306a36Sopenharmony_ci unsigned int shift, 19762306a36Sopenharmony_ci const struct kvm_memory_slot *memslot, 19862306a36Sopenharmony_ci unsigned int lpid); 19962306a36Sopenharmony_ciextern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, 20062306a36Sopenharmony_ci bool writing, unsigned long gpa, 20162306a36Sopenharmony_ci unsigned int lpid); 20262306a36Sopenharmony_ciextern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, 20362306a36Sopenharmony_ci unsigned long gpa, 20462306a36Sopenharmony_ci struct kvm_memory_slot *memslot, 20562306a36Sopenharmony_ci bool writing, bool kvm_ro, 20662306a36Sopenharmony_ci pte_t *inserted_pte, unsigned int *levelp); 20762306a36Sopenharmony_ciextern int kvmppc_init_vm_radix(struct kvm *kvm); 20862306a36Sopenharmony_ciextern void kvmppc_free_radix(struct kvm *kvm); 20962306a36Sopenharmony_ciextern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, 21062306a36Sopenharmony_ci unsigned int lpid); 21162306a36Sopenharmony_ciextern int kvmppc_radix_init(void); 21262306a36Sopenharmony_ciextern void kvmppc_radix_exit(void); 21362306a36Sopenharmony_ciextern void kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 21462306a36Sopenharmony_ci unsigned long gfn); 21562306a36Sopenharmony_ciextern bool kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 21662306a36Sopenharmony_ci unsigned long gfn); 21762306a36Sopenharmony_ciextern bool kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 21862306a36Sopenharmony_ci unsigned long gfn); 21962306a36Sopenharmony_ciextern long kvmppc_hv_get_dirty_log_radix(struct kvm *kvm, 22062306a36Sopenharmony_ci struct kvm_memory_slot *memslot, unsigned long *map); 22162306a36Sopenharmony_ciextern void kvmppc_radix_flush_memslot(struct kvm *kvm, 22262306a36Sopenharmony_ci const struct kvm_memory_slot *memslot); 22362306a36Sopenharmony_ciextern int kvmhv_get_rmmu_info(struct kvm *kvm, struct kvm_ppc_rmmu_info *info); 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/* XXX remove this export when load_last_inst() is generic */ 22662306a36Sopenharmony_ciextern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); 22762306a36Sopenharmony_ciextern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); 22862306a36Sopenharmony_ciextern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, 22962306a36Sopenharmony_ci unsigned int vec); 23062306a36Sopenharmony_ciextern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags); 23162306a36Sopenharmony_ciextern void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac); 23262306a36Sopenharmony_ciextern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, 23362306a36Sopenharmony_ci bool upper, u32 val); 23462306a36Sopenharmony_ciextern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); 23562306a36Sopenharmony_ciextern int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu); 23662306a36Sopenharmony_ciextern kvm_pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, 23762306a36Sopenharmony_ci bool writing, bool *writable); 23862306a36Sopenharmony_ciextern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, 23962306a36Sopenharmony_ci unsigned long *rmap, long pte_index, int realmode); 24062306a36Sopenharmony_ciextern void kvmppc_update_dirty_map(const struct kvm_memory_slot *memslot, 24162306a36Sopenharmony_ci unsigned long gfn, unsigned long psize); 24262306a36Sopenharmony_ciextern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, 24362306a36Sopenharmony_ci unsigned long pte_index); 24462306a36Sopenharmony_civoid kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, 24562306a36Sopenharmony_ci unsigned long pte_index); 24662306a36Sopenharmony_ciextern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, 24762306a36Sopenharmony_ci unsigned long *nb_ret); 24862306a36Sopenharmony_ciextern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr, 24962306a36Sopenharmony_ci unsigned long gpa, bool dirty); 25062306a36Sopenharmony_ciextern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, 25162306a36Sopenharmony_ci long pte_index, unsigned long pteh, unsigned long ptel, 25262306a36Sopenharmony_ci pgd_t *pgdir, bool realmode, unsigned long *idx_ret); 25362306a36Sopenharmony_ciextern long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags, 25462306a36Sopenharmony_ci unsigned long pte_index, unsigned long avpn, 25562306a36Sopenharmony_ci unsigned long *hpret); 25662306a36Sopenharmony_ciextern long kvmppc_hv_get_dirty_log_hpt(struct kvm *kvm, 25762306a36Sopenharmony_ci struct kvm_memory_slot *memslot, unsigned long *map); 25862306a36Sopenharmony_ciextern void kvmppc_harvest_vpa_dirty(struct kvmppc_vpa *vpa, 25962306a36Sopenharmony_ci struct kvm_memory_slot *memslot, 26062306a36Sopenharmony_ci unsigned long *map); 26162306a36Sopenharmony_ciextern unsigned long kvmppc_filter_lpcr_hv(struct kvm *kvm, 26262306a36Sopenharmony_ci unsigned long lpcr); 26362306a36Sopenharmony_ciextern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, 26462306a36Sopenharmony_ci unsigned long mask); 26562306a36Sopenharmony_ciextern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ciextern int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu); 26862306a36Sopenharmony_ciextern int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu); 26962306a36Sopenharmony_ciextern void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ciextern void kvmppc_entry_trampoline(void); 27262306a36Sopenharmony_ciextern void kvmppc_hv_entry_trampoline(void); 27362306a36Sopenharmony_ciextern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); 27462306a36Sopenharmony_ciextern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); 27562306a36Sopenharmony_ciextern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); 27662306a36Sopenharmony_ciextern void kvmppc_pr_init_default_hcalls(struct kvm *kvm); 27762306a36Sopenharmony_ciextern int kvmppc_hcall_impl_pr(unsigned long cmd); 27862306a36Sopenharmony_ciextern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd); 27962306a36Sopenharmony_ciextern void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu); 28062306a36Sopenharmony_ciextern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_cilong kvmppc_read_intr(void); 28362306a36Sopenharmony_civoid kvmppc_set_msr_hv(struct kvm_vcpu *vcpu, u64 msr); 28462306a36Sopenharmony_civoid kvmppc_inject_interrupt_hv(struct kvm_vcpu *vcpu, int vec, u64 srr1_flags); 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 28762306a36Sopenharmony_civoid kvmppc_save_tm_pr(struct kvm_vcpu *vcpu); 28862306a36Sopenharmony_civoid kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu); 28962306a36Sopenharmony_civoid kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu); 29062306a36Sopenharmony_civoid kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu); 29162306a36Sopenharmony_ci#else 29262306a36Sopenharmony_cistatic inline void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu) {} 29362306a36Sopenharmony_cistatic inline void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu) {} 29462306a36Sopenharmony_cistatic inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {} 29562306a36Sopenharmony_cistatic inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {} 29662306a36Sopenharmony_ci#endif 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_cilong kvmhv_nested_init(void); 29962306a36Sopenharmony_civoid kvmhv_nested_exit(void); 30062306a36Sopenharmony_civoid kvmhv_vm_nested_init(struct kvm *kvm); 30162306a36Sopenharmony_cilong kvmhv_set_partition_table(struct kvm_vcpu *vcpu); 30262306a36Sopenharmony_cilong kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu); 30362306a36Sopenharmony_civoid kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1); 30462306a36Sopenharmony_civoid kvmhv_release_all_nested(struct kvm *kvm); 30562306a36Sopenharmony_cilong kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu); 30662306a36Sopenharmony_cilong kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu); 30762306a36Sopenharmony_cilong do_h_rpt_invalidate_pat(struct kvm_vcpu *vcpu, unsigned long lpid, 30862306a36Sopenharmony_ci unsigned long type, unsigned long pg_sizes, 30962306a36Sopenharmony_ci unsigned long start, unsigned long end); 31062306a36Sopenharmony_ciint kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, 31162306a36Sopenharmony_ci u64 time_limit, unsigned long lpcr); 31262306a36Sopenharmony_civoid kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr); 31362306a36Sopenharmony_civoid kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu, 31462306a36Sopenharmony_ci struct hv_guest_state *hr); 31562306a36Sopenharmony_cilong int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu); 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_civoid kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac); 31862306a36Sopenharmony_ci 31962306a36Sopenharmony_ciextern int kvm_irq_bypass; 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_cistatic inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) 32262306a36Sopenharmony_ci{ 32362306a36Sopenharmony_ci return vcpu->arch.book3s; 32462306a36Sopenharmony_ci} 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci/* Also add subarch specific defines */ 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_32_HANDLER 32962306a36Sopenharmony_ci#include <asm/kvm_book3s_32.h> 33062306a36Sopenharmony_ci#endif 33162306a36Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_64_HANDLER 33262306a36Sopenharmony_ci#include <asm/kvm_book3s_64.h> 33362306a36Sopenharmony_ci#endif 33462306a36Sopenharmony_ci 33562306a36Sopenharmony_cistatic inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci vcpu->arch.regs.gpr[num] = val; 33862306a36Sopenharmony_ci} 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_cistatic inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) 34162306a36Sopenharmony_ci{ 34262306a36Sopenharmony_ci return vcpu->arch.regs.gpr[num]; 34362306a36Sopenharmony_ci} 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) 34662306a36Sopenharmony_ci{ 34762306a36Sopenharmony_ci vcpu->arch.regs.ccr = val; 34862306a36Sopenharmony_ci} 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_cistatic inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci return vcpu->arch.regs.ccr; 35362306a36Sopenharmony_ci} 35462306a36Sopenharmony_ci 35562306a36Sopenharmony_cistatic inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) 35662306a36Sopenharmony_ci{ 35762306a36Sopenharmony_ci vcpu->arch.regs.xer = val; 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu) 36162306a36Sopenharmony_ci{ 36262306a36Sopenharmony_ci return vcpu->arch.regs.xer; 36362306a36Sopenharmony_ci} 36462306a36Sopenharmony_ci 36562306a36Sopenharmony_cistatic inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) 36662306a36Sopenharmony_ci{ 36762306a36Sopenharmony_ci vcpu->arch.regs.ctr = val; 36862306a36Sopenharmony_ci} 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci return vcpu->arch.regs.ctr; 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_cistatic inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci vcpu->arch.regs.link = val; 37862306a36Sopenharmony_ci} 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_cistatic inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci return vcpu->arch.regs.link; 38362306a36Sopenharmony_ci} 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_cistatic inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci vcpu->arch.regs.nip = val; 38862306a36Sopenharmony_ci} 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_cistatic inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) 39162306a36Sopenharmony_ci{ 39262306a36Sopenharmony_ci return vcpu->arch.regs.nip; 39362306a36Sopenharmony_ci} 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu); 39662306a36Sopenharmony_cistatic inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu) 39762306a36Sopenharmony_ci{ 39862306a36Sopenharmony_ci return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE); 39962306a36Sopenharmony_ci} 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_cistatic inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) 40262306a36Sopenharmony_ci{ 40362306a36Sopenharmony_ci return vcpu->arch.fault_dar; 40462306a36Sopenharmony_ci} 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci/* Expiry time of vcpu DEC relative to host TB */ 40762306a36Sopenharmony_cistatic inline u64 kvmppc_dec_expires_host_tb(struct kvm_vcpu *vcpu) 40862306a36Sopenharmony_ci{ 40962306a36Sopenharmony_ci return vcpu->arch.dec_expires - vcpu->arch.vcore->tb_offset; 41062306a36Sopenharmony_ci} 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic inline bool is_kvmppc_resume_guest(int r) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci return (r == RESUME_GUEST || r == RESUME_GUEST_NV); 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_ci 41762306a36Sopenharmony_cistatic inline bool is_kvmppc_hv_enabled(struct kvm *kvm); 41862306a36Sopenharmony_cistatic inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu) 41962306a36Sopenharmony_ci{ 42062306a36Sopenharmony_ci /* Only PR KVM supports the magic page */ 42162306a36Sopenharmony_ci return !is_kvmppc_hv_enabled(vcpu->kvm); 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ciextern int kvmppc_h_logical_ci_load(struct kvm_vcpu *vcpu); 42562306a36Sopenharmony_ciextern int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu); 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci/* Magic register values loaded into r3 and r4 before the 'sc' assembly 42862306a36Sopenharmony_ci * instruction for the OSI hypercalls */ 42962306a36Sopenharmony_ci#define OSI_SC_MAGIC_R3 0x113724FA 43062306a36Sopenharmony_ci#define OSI_SC_MAGIC_R4 0x77810F9B 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci#define INS_DCBZ 0x7c0007ec 43362306a36Sopenharmony_ci/* TO = 31 for unconditional trap */ 43462306a36Sopenharmony_ci#define INS_TW 0x7fe00008 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci#define SPLIT_HACK_MASK 0xff000000 43762306a36Sopenharmony_ci#define SPLIT_HACK_OFFS 0xfb000000 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci/* 44062306a36Sopenharmony_ci * This packs a VCPU ID from the [0..KVM_MAX_VCPU_IDS) space down to the 44162306a36Sopenharmony_ci * [0..KVM_MAX_VCPUS) space, using knowledge of the guest's core stride 44262306a36Sopenharmony_ci * (but not its actual threading mode, which is not available) to avoid 44362306a36Sopenharmony_ci * collisions. 44462306a36Sopenharmony_ci * 44562306a36Sopenharmony_ci * The implementation leaves VCPU IDs from the range [0..KVM_MAX_VCPUS) (block 44662306a36Sopenharmony_ci * 0) unchanged: if the guest is filling each VCORE completely then it will be 44762306a36Sopenharmony_ci * using consecutive IDs and it will fill the space without any packing. 44862306a36Sopenharmony_ci * 44962306a36Sopenharmony_ci * For higher VCPU IDs, the packed ID is based on the VCPU ID modulo 45062306a36Sopenharmony_ci * KVM_MAX_VCPUS (effectively masking off the top bits) and then an offset is 45162306a36Sopenharmony_ci * added to avoid collisions. 45262306a36Sopenharmony_ci * 45362306a36Sopenharmony_ci * VCPU IDs in the range [KVM_MAX_VCPUS..(KVM_MAX_VCPUS*2)) (block 1) are only 45462306a36Sopenharmony_ci * possible if the guest is leaving at least 1/2 of each VCORE empty, so IDs 45562306a36Sopenharmony_ci * can be safely packed into the second half of each VCORE by adding an offset 45662306a36Sopenharmony_ci * of (stride / 2). 45762306a36Sopenharmony_ci * 45862306a36Sopenharmony_ci * Similarly, if VCPU IDs in the range [(KVM_MAX_VCPUS*2)..(KVM_MAX_VCPUS*4)) 45962306a36Sopenharmony_ci * (blocks 2 and 3) are seen, the guest must be leaving at least 3/4 of each 46062306a36Sopenharmony_ci * VCORE empty so packed IDs can be offset by (stride / 4) and (stride * 3 / 4). 46162306a36Sopenharmony_ci * 46262306a36Sopenharmony_ci * Finally, VCPU IDs from blocks 5..7 will only be seen if the guest is using a 46362306a36Sopenharmony_ci * stride of 8 and 1 thread per core so the remaining offsets of 1, 5, 3 and 7 46462306a36Sopenharmony_ci * must be free to use. 46562306a36Sopenharmony_ci * 46662306a36Sopenharmony_ci * (The offsets for each block are stored in block_offsets[], indexed by the 46762306a36Sopenharmony_ci * block number if the stride is 8. For cases where the guest's stride is less 46862306a36Sopenharmony_ci * than 8, we can re-use the block_offsets array by multiplying the block 46962306a36Sopenharmony_ci * number by (MAX_SMT_THREADS / stride) to reach the correct entry.) 47062306a36Sopenharmony_ci */ 47162306a36Sopenharmony_cistatic inline u32 kvmppc_pack_vcpu_id(struct kvm *kvm, u32 id) 47262306a36Sopenharmony_ci{ 47362306a36Sopenharmony_ci const int block_offsets[MAX_SMT_THREADS] = {0, 4, 2, 6, 1, 5, 3, 7}; 47462306a36Sopenharmony_ci int stride = kvm->arch.emul_smt_mode; 47562306a36Sopenharmony_ci int block = (id / KVM_MAX_VCPUS) * (MAX_SMT_THREADS / stride); 47662306a36Sopenharmony_ci u32 packed_id; 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_ci if (WARN_ONCE(block >= MAX_SMT_THREADS, "VCPU ID too large to pack")) 47962306a36Sopenharmony_ci return 0; 48062306a36Sopenharmony_ci packed_id = (id % KVM_MAX_VCPUS) + block_offsets[block]; 48162306a36Sopenharmony_ci if (WARN_ONCE(packed_id >= KVM_MAX_VCPUS, "VCPU ID packing failed")) 48262306a36Sopenharmony_ci return 0; 48362306a36Sopenharmony_ci return packed_id; 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci#endif /* __ASM_KVM_BOOK3S_H__ */ 487