18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-only */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright SUSE Linux Products GmbH 2009 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Authors: Alexander Graf <agraf@suse.de> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef __ASM_KVM_BOOK3S_H__ 108c2ecf20Sopenharmony_ci#define __ASM_KVM_BOOK3S_H__ 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/types.h> 138c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 148c2ecf20Sopenharmony_ci#include <asm/kvm_book3s_asm.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_cistruct kvmppc_bat { 178c2ecf20Sopenharmony_ci u64 raw; 188c2ecf20Sopenharmony_ci u32 bepi; 198c2ecf20Sopenharmony_ci u32 bepi_mask; 208c2ecf20Sopenharmony_ci u32 brpn; 218c2ecf20Sopenharmony_ci u8 wimg; 228c2ecf20Sopenharmony_ci u8 pp; 238c2ecf20Sopenharmony_ci bool vs : 1; 248c2ecf20Sopenharmony_ci bool vp : 1; 258c2ecf20Sopenharmony_ci}; 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_cistruct kvmppc_sid_map { 288c2ecf20Sopenharmony_ci u64 guest_vsid; 298c2ecf20Sopenharmony_ci u64 guest_esid; 308c2ecf20Sopenharmony_ci u64 host_vsid; 318c2ecf20Sopenharmony_ci bool valid : 1; 328c2ecf20Sopenharmony_ci}; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci#define SID_MAP_BITS 9 358c2ecf20Sopenharmony_ci#define SID_MAP_NUM (1 << SID_MAP_BITS) 368c2ecf20Sopenharmony_ci#define SID_MAP_MASK (SID_MAP_NUM - 1) 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 398c2ecf20Sopenharmony_ci#define SID_CONTEXTS 1 408c2ecf20Sopenharmony_ci#else 418c2ecf20Sopenharmony_ci#define SID_CONTEXTS 128 428c2ecf20Sopenharmony_ci#define VSID_POOL_SIZE (SID_CONTEXTS * 16) 438c2ecf20Sopenharmony_ci#endif 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct hpte_cache { 468c2ecf20Sopenharmony_ci struct hlist_node list_pte; 478c2ecf20Sopenharmony_ci struct hlist_node list_pte_long; 488c2ecf20Sopenharmony_ci struct hlist_node list_vpte; 498c2ecf20Sopenharmony_ci struct hlist_node list_vpte_long; 508c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 518c2ecf20Sopenharmony_ci struct hlist_node list_vpte_64k; 528c2ecf20Sopenharmony_ci#endif 538c2ecf20Sopenharmony_ci struct rcu_head rcu_head; 548c2ecf20Sopenharmony_ci u64 host_vpn; 558c2ecf20Sopenharmony_ci u64 pfn; 568c2ecf20Sopenharmony_ci ulong slot; 578c2ecf20Sopenharmony_ci struct kvmppc_pte pte; 588c2ecf20Sopenharmony_ci int pagesize; 598c2ecf20Sopenharmony_ci}; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* 628c2ecf20Sopenharmony_ci * Struct for a virtual core. 638c2ecf20Sopenharmony_ci * Note: entry_exit_map combines a bitmap of threads that have entered 648c2ecf20Sopenharmony_ci * in the bottom 8 bits and a bitmap of threads that have exited in the 658c2ecf20Sopenharmony_ci * next 8 bits. This is so that we can atomically set the entry bit 668c2ecf20Sopenharmony_ci * iff the exit map is 0 without taking a lock. 678c2ecf20Sopenharmony_ci */ 688c2ecf20Sopenharmony_cistruct kvmppc_vcore { 698c2ecf20Sopenharmony_ci int n_runnable; 708c2ecf20Sopenharmony_ci int num_threads; 718c2ecf20Sopenharmony_ci int entry_exit_map; 728c2ecf20Sopenharmony_ci int napping_threads; 738c2ecf20Sopenharmony_ci int first_vcpuid; 748c2ecf20Sopenharmony_ci u16 pcpu; 758c2ecf20Sopenharmony_ci u16 last_cpu; 768c2ecf20Sopenharmony_ci u8 vcore_state; 778c2ecf20Sopenharmony_ci u8 in_guest; 788c2ecf20Sopenharmony_ci struct kvm_vcpu *runnable_threads[MAX_SMT_THREADS]; 798c2ecf20Sopenharmony_ci struct list_head preempt_list; 808c2ecf20Sopenharmony_ci spinlock_t lock; 818c2ecf20Sopenharmony_ci struct rcuwait wait; 828c2ecf20Sopenharmony_ci spinlock_t stoltb_lock; /* protects stolen_tb and preempt_tb */ 838c2ecf20Sopenharmony_ci u64 stolen_tb; 848c2ecf20Sopenharmony_ci u64 preempt_tb; 858c2ecf20Sopenharmony_ci struct kvm_vcpu *runner; 868c2ecf20Sopenharmony_ci struct kvm *kvm; 878c2ecf20Sopenharmony_ci u64 tb_offset; /* guest timebase - host timebase */ 888c2ecf20Sopenharmony_ci u64 tb_offset_applied; /* timebase offset currently in force */ 898c2ecf20Sopenharmony_ci ulong lpcr; 908c2ecf20Sopenharmony_ci u32 arch_compat; 918c2ecf20Sopenharmony_ci ulong pcr; 928c2ecf20Sopenharmony_ci ulong dpdes; /* doorbell state (POWER8) */ 938c2ecf20Sopenharmony_ci ulong vtb; /* virtual timebase */ 948c2ecf20Sopenharmony_ci ulong conferring_threads; 958c2ecf20Sopenharmony_ci unsigned int halt_poll_ns; 968c2ecf20Sopenharmony_ci atomic_t online_count; 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_cistruct kvmppc_vcpu_book3s { 1008c2ecf20Sopenharmony_ci struct kvmppc_sid_map sid_map[SID_MAP_NUM]; 1018c2ecf20Sopenharmony_ci struct { 1028c2ecf20Sopenharmony_ci u64 esid; 1038c2ecf20Sopenharmony_ci u64 vsid; 1048c2ecf20Sopenharmony_ci } slb_shadow[64]; 1058c2ecf20Sopenharmony_ci u8 slb_shadow_max; 1068c2ecf20Sopenharmony_ci struct kvmppc_bat ibat[8]; 1078c2ecf20Sopenharmony_ci struct kvmppc_bat dbat[8]; 1088c2ecf20Sopenharmony_ci u64 hid[6]; 1098c2ecf20Sopenharmony_ci u64 gqr[8]; 1108c2ecf20Sopenharmony_ci u64 sdr1; 1118c2ecf20Sopenharmony_ci u64 hior; 1128c2ecf20Sopenharmony_ci u64 msr_mask; 1138c2ecf20Sopenharmony_ci u64 vtb; 1148c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_32 1158c2ecf20Sopenharmony_ci u32 vsid_pool[VSID_POOL_SIZE]; 1168c2ecf20Sopenharmony_ci u32 vsid_next; 1178c2ecf20Sopenharmony_ci#else 1188c2ecf20Sopenharmony_ci u64 proto_vsid_first; 1198c2ecf20Sopenharmony_ci u64 proto_vsid_max; 1208c2ecf20Sopenharmony_ci u64 proto_vsid_next; 1218c2ecf20Sopenharmony_ci#endif 1228c2ecf20Sopenharmony_ci int context_id[SID_CONTEXTS]; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci bool hior_explicit; /* HIOR is set by ioctl, not PVR */ 1258c2ecf20Sopenharmony_ci 1268c2ecf20Sopenharmony_ci struct hlist_head hpte_hash_pte[HPTEG_HASH_NUM_PTE]; 1278c2ecf20Sopenharmony_ci struct hlist_head hpte_hash_pte_long[HPTEG_HASH_NUM_PTE_LONG]; 1288c2ecf20Sopenharmony_ci struct hlist_head hpte_hash_vpte[HPTEG_HASH_NUM_VPTE]; 1298c2ecf20Sopenharmony_ci struct hlist_head hpte_hash_vpte_long[HPTEG_HASH_NUM_VPTE_LONG]; 1308c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_BOOK3S_64 1318c2ecf20Sopenharmony_ci struct hlist_head hpte_hash_vpte_64k[HPTEG_HASH_NUM_VPTE_64K]; 1328c2ecf20Sopenharmony_ci#endif 1338c2ecf20Sopenharmony_ci int hpte_cache_count; 1348c2ecf20Sopenharmony_ci spinlock_t mmu_lock; 1358c2ecf20Sopenharmony_ci}; 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci#define VSID_REAL 0x07ffffffffc00000ULL 1388c2ecf20Sopenharmony_ci#define VSID_BAT 0x07ffffffffb00000ULL 1398c2ecf20Sopenharmony_ci#define VSID_64K 0x0800000000000000ULL 1408c2ecf20Sopenharmony_ci#define VSID_1T 0x1000000000000000ULL 1418c2ecf20Sopenharmony_ci#define VSID_REAL_DR 0x2000000000000000ULL 1428c2ecf20Sopenharmony_ci#define VSID_REAL_IR 0x4000000000000000ULL 1438c2ecf20Sopenharmony_ci#define VSID_PR 0x8000000000000000ULL 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ciextern void kvmppc_mmu_pte_flush(struct kvm_vcpu *vcpu, ulong ea, ulong ea_mask); 1468c2ecf20Sopenharmony_ciextern void kvmppc_mmu_pte_vflush(struct kvm_vcpu *vcpu, u64 vp, u64 vp_mask); 1478c2ecf20Sopenharmony_ciextern void kvmppc_mmu_pte_pflush(struct kvm_vcpu *vcpu, ulong pa_start, ulong pa_end); 1488c2ecf20Sopenharmony_ciextern void kvmppc_set_msr(struct kvm_vcpu *vcpu, u64 new_msr); 1498c2ecf20Sopenharmony_ciextern void kvmppc_mmu_book3s_64_init(struct kvm_vcpu *vcpu); 1508c2ecf20Sopenharmony_ciextern void kvmppc_mmu_book3s_32_init(struct kvm_vcpu *vcpu); 1518c2ecf20Sopenharmony_ciextern void kvmppc_mmu_book3s_hv_init(struct kvm_vcpu *vcpu); 1528c2ecf20Sopenharmony_ciextern int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte, 1538c2ecf20Sopenharmony_ci bool iswrite); 1548c2ecf20Sopenharmony_ciextern void kvmppc_mmu_unmap_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte); 1558c2ecf20Sopenharmony_ciextern int kvmppc_mmu_map_segment(struct kvm_vcpu *vcpu, ulong eaddr); 1568c2ecf20Sopenharmony_ciextern void kvmppc_mmu_flush_segment(struct kvm_vcpu *vcpu, ulong eaddr, ulong seg_size); 1578c2ecf20Sopenharmony_ciextern void kvmppc_mmu_flush_segments(struct kvm_vcpu *vcpu); 1588c2ecf20Sopenharmony_ciextern int kvmppc_book3s_hv_page_fault(struct kvm_vcpu *vcpu, 1598c2ecf20Sopenharmony_ci unsigned long addr, unsigned long status); 1608c2ecf20Sopenharmony_ciextern long kvmppc_hv_find_lock_hpte(struct kvm *kvm, gva_t eaddr, 1618c2ecf20Sopenharmony_ci unsigned long slb_v, unsigned long valid); 1628c2ecf20Sopenharmony_ciextern int kvmppc_hv_emulate_mmio(struct kvm_vcpu *vcpu, 1638c2ecf20Sopenharmony_ci unsigned long gpa, gva_t ea, int is_store); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ciextern void kvmppc_mmu_hpte_cache_map(struct kvm_vcpu *vcpu, struct hpte_cache *pte); 1668c2ecf20Sopenharmony_ciextern struct hpte_cache *kvmppc_mmu_hpte_cache_next(struct kvm_vcpu *vcpu); 1678c2ecf20Sopenharmony_ciextern void kvmppc_mmu_hpte_cache_free(struct hpte_cache *pte); 1688c2ecf20Sopenharmony_ciextern void kvmppc_mmu_hpte_destroy(struct kvm_vcpu *vcpu); 1698c2ecf20Sopenharmony_ciextern int kvmppc_mmu_hpte_init(struct kvm_vcpu *vcpu); 1708c2ecf20Sopenharmony_ciextern void kvmppc_mmu_invalidate_pte(struct kvm_vcpu *vcpu, struct hpte_cache *pte); 1718c2ecf20Sopenharmony_ciextern int kvmppc_mmu_hpte_sysinit(void); 1728c2ecf20Sopenharmony_ciextern void kvmppc_mmu_hpte_sysexit(void); 1738c2ecf20Sopenharmony_ciextern int kvmppc_mmu_hv_init(void); 1748c2ecf20Sopenharmony_ciextern int kvmppc_book3s_hcall_implemented(struct kvm *kvm, unsigned long hc); 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ciextern int kvmppc_book3s_radix_page_fault(struct kvm_vcpu *vcpu, 1778c2ecf20Sopenharmony_ci unsigned long ea, unsigned long dsisr); 1788c2ecf20Sopenharmony_ciextern unsigned long __kvmhv_copy_tofrom_guest_radix(int lpid, int pid, 1798c2ecf20Sopenharmony_ci gva_t eaddr, void *to, void *from, 1808c2ecf20Sopenharmony_ci unsigned long n); 1818c2ecf20Sopenharmony_ciextern long kvmhv_copy_from_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, 1828c2ecf20Sopenharmony_ci void *to, unsigned long n); 1838c2ecf20Sopenharmony_ciextern long kvmhv_copy_to_guest_radix(struct kvm_vcpu *vcpu, gva_t eaddr, 1848c2ecf20Sopenharmony_ci void *from, unsigned long n); 1858c2ecf20Sopenharmony_ciextern int kvmppc_mmu_walk_radix_tree(struct kvm_vcpu *vcpu, gva_t eaddr, 1868c2ecf20Sopenharmony_ci struct kvmppc_pte *gpte, u64 root, 1878c2ecf20Sopenharmony_ci u64 *pte_ret_p); 1888c2ecf20Sopenharmony_ciextern int kvmppc_mmu_radix_translate_table(struct kvm_vcpu *vcpu, gva_t eaddr, 1898c2ecf20Sopenharmony_ci struct kvmppc_pte *gpte, u64 table, 1908c2ecf20Sopenharmony_ci int table_index, u64 *pte_ret_p); 1918c2ecf20Sopenharmony_ciextern int kvmppc_mmu_radix_xlate(struct kvm_vcpu *vcpu, gva_t eaddr, 1928c2ecf20Sopenharmony_ci struct kvmppc_pte *gpte, bool data, bool iswrite); 1938c2ecf20Sopenharmony_ciextern void kvmppc_radix_tlbie_page(struct kvm *kvm, unsigned long addr, 1948c2ecf20Sopenharmony_ci unsigned int pshift, unsigned int lpid); 1958c2ecf20Sopenharmony_ciextern void kvmppc_unmap_pte(struct kvm *kvm, pte_t *pte, unsigned long gpa, 1968c2ecf20Sopenharmony_ci unsigned int shift, 1978c2ecf20Sopenharmony_ci const struct kvm_memory_slot *memslot, 1988c2ecf20Sopenharmony_ci unsigned int lpid); 1998c2ecf20Sopenharmony_ciextern bool kvmppc_hv_handle_set_rc(struct kvm *kvm, bool nested, 2008c2ecf20Sopenharmony_ci bool writing, unsigned long gpa, 2018c2ecf20Sopenharmony_ci unsigned int lpid); 2028c2ecf20Sopenharmony_ciextern int kvmppc_book3s_instantiate_page(struct kvm_vcpu *vcpu, 2038c2ecf20Sopenharmony_ci unsigned long gpa, 2048c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot, 2058c2ecf20Sopenharmony_ci bool writing, bool kvm_ro, 2068c2ecf20Sopenharmony_ci pte_t *inserted_pte, unsigned int *levelp); 2078c2ecf20Sopenharmony_ciextern int kvmppc_init_vm_radix(struct kvm *kvm); 2088c2ecf20Sopenharmony_ciextern void kvmppc_free_radix(struct kvm *kvm); 2098c2ecf20Sopenharmony_ciextern void kvmppc_free_pgtable_radix(struct kvm *kvm, pgd_t *pgd, 2108c2ecf20Sopenharmony_ci unsigned int lpid); 2118c2ecf20Sopenharmony_ciextern int kvmppc_radix_init(void); 2128c2ecf20Sopenharmony_ciextern void kvmppc_radix_exit(void); 2138c2ecf20Sopenharmony_ciextern int kvm_unmap_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 2148c2ecf20Sopenharmony_ci unsigned long gfn); 2158c2ecf20Sopenharmony_ciextern int kvm_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 2168c2ecf20Sopenharmony_ci unsigned long gfn); 2178c2ecf20Sopenharmony_ciextern int kvm_test_age_radix(struct kvm *kvm, struct kvm_memory_slot *memslot, 2188c2ecf20Sopenharmony_ci unsigned long gfn); 2198c2ecf20Sopenharmony_ciextern long kvmppc_hv_get_dirty_log_radix(struct kvm *kvm, 2208c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot, unsigned long *map); 2218c2ecf20Sopenharmony_ciextern void kvmppc_radix_flush_memslot(struct kvm *kvm, 2228c2ecf20Sopenharmony_ci const struct kvm_memory_slot *memslot); 2238c2ecf20Sopenharmony_ciextern int kvmhv_get_rmmu_info(struct kvm *kvm, struct kvm_ppc_rmmu_info *info); 2248c2ecf20Sopenharmony_ci 2258c2ecf20Sopenharmony_ci/* XXX remove this export when load_last_inst() is generic */ 2268c2ecf20Sopenharmony_ciextern int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, bool data); 2278c2ecf20Sopenharmony_ciextern void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec); 2288c2ecf20Sopenharmony_ciextern void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu, 2298c2ecf20Sopenharmony_ci unsigned int vec); 2308c2ecf20Sopenharmony_ciextern void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags); 2318c2ecf20Sopenharmony_ciextern void kvmppc_trigger_fac_interrupt(struct kvm_vcpu *vcpu, ulong fac); 2328c2ecf20Sopenharmony_ciextern void kvmppc_set_bat(struct kvm_vcpu *vcpu, struct kvmppc_bat *bat, 2338c2ecf20Sopenharmony_ci bool upper, u32 val); 2348c2ecf20Sopenharmony_ciextern void kvmppc_giveup_ext(struct kvm_vcpu *vcpu, ulong msr); 2358c2ecf20Sopenharmony_ciextern int kvmppc_emulate_paired_single(struct kvm_vcpu *vcpu); 2368c2ecf20Sopenharmony_ciextern kvm_pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, 2378c2ecf20Sopenharmony_ci bool writing, bool *writable); 2388c2ecf20Sopenharmony_ciextern void kvmppc_add_revmap_chain(struct kvm *kvm, struct revmap_entry *rev, 2398c2ecf20Sopenharmony_ci unsigned long *rmap, long pte_index, int realmode); 2408c2ecf20Sopenharmony_ciextern void kvmppc_update_dirty_map(const struct kvm_memory_slot *memslot, 2418c2ecf20Sopenharmony_ci unsigned long gfn, unsigned long psize); 2428c2ecf20Sopenharmony_ciextern void kvmppc_invalidate_hpte(struct kvm *kvm, __be64 *hptep, 2438c2ecf20Sopenharmony_ci unsigned long pte_index); 2448c2ecf20Sopenharmony_civoid kvmppc_clear_ref_hpte(struct kvm *kvm, __be64 *hptep, 2458c2ecf20Sopenharmony_ci unsigned long pte_index); 2468c2ecf20Sopenharmony_ciextern void *kvmppc_pin_guest_page(struct kvm *kvm, unsigned long addr, 2478c2ecf20Sopenharmony_ci unsigned long *nb_ret); 2488c2ecf20Sopenharmony_ciextern void kvmppc_unpin_guest_page(struct kvm *kvm, void *addr, 2498c2ecf20Sopenharmony_ci unsigned long gpa, bool dirty); 2508c2ecf20Sopenharmony_ciextern long kvmppc_do_h_enter(struct kvm *kvm, unsigned long flags, 2518c2ecf20Sopenharmony_ci long pte_index, unsigned long pteh, unsigned long ptel, 2528c2ecf20Sopenharmony_ci pgd_t *pgdir, bool realmode, unsigned long *idx_ret); 2538c2ecf20Sopenharmony_ciextern long kvmppc_do_h_remove(struct kvm *kvm, unsigned long flags, 2548c2ecf20Sopenharmony_ci unsigned long pte_index, unsigned long avpn, 2558c2ecf20Sopenharmony_ci unsigned long *hpret); 2568c2ecf20Sopenharmony_ciextern long kvmppc_hv_get_dirty_log_hpt(struct kvm *kvm, 2578c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot, unsigned long *map); 2588c2ecf20Sopenharmony_ciextern void kvmppc_harvest_vpa_dirty(struct kvmppc_vpa *vpa, 2598c2ecf20Sopenharmony_ci struct kvm_memory_slot *memslot, 2608c2ecf20Sopenharmony_ci unsigned long *map); 2618c2ecf20Sopenharmony_ciextern void kvmppc_update_lpcr(struct kvm *kvm, unsigned long lpcr, 2628c2ecf20Sopenharmony_ci unsigned long mask); 2638c2ecf20Sopenharmony_ciextern void kvmppc_set_fscr(struct kvm_vcpu *vcpu, u64 fscr); 2648c2ecf20Sopenharmony_ci 2658c2ecf20Sopenharmony_ciextern int kvmhv_p9_tm_emulation_early(struct kvm_vcpu *vcpu); 2668c2ecf20Sopenharmony_ciextern int kvmhv_p9_tm_emulation(struct kvm_vcpu *vcpu); 2678c2ecf20Sopenharmony_ciextern void kvmhv_emulate_tm_rollback(struct kvm_vcpu *vcpu); 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ciextern void kvmppc_entry_trampoline(void); 2708c2ecf20Sopenharmony_ciextern void kvmppc_hv_entry_trampoline(void); 2718c2ecf20Sopenharmony_ciextern u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst); 2728c2ecf20Sopenharmony_ciextern ulong kvmppc_alignment_dar(struct kvm_vcpu *vcpu, unsigned int inst); 2738c2ecf20Sopenharmony_ciextern int kvmppc_h_pr(struct kvm_vcpu *vcpu, unsigned long cmd); 2748c2ecf20Sopenharmony_ciextern void kvmppc_pr_init_default_hcalls(struct kvm *kvm); 2758c2ecf20Sopenharmony_ciextern int kvmppc_hcall_impl_pr(unsigned long cmd); 2768c2ecf20Sopenharmony_ciextern int kvmppc_hcall_impl_hv_realmode(unsigned long cmd); 2778c2ecf20Sopenharmony_ciextern void kvmppc_copy_to_svcpu(struct kvm_vcpu *vcpu); 2788c2ecf20Sopenharmony_ciextern void kvmppc_copy_from_svcpu(struct kvm_vcpu *vcpu); 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#ifdef CONFIG_PPC_TRANSACTIONAL_MEM 2818c2ecf20Sopenharmony_civoid kvmppc_save_tm_pr(struct kvm_vcpu *vcpu); 2828c2ecf20Sopenharmony_civoid kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu); 2838c2ecf20Sopenharmony_civoid kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu); 2848c2ecf20Sopenharmony_civoid kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu); 2858c2ecf20Sopenharmony_ci#else 2868c2ecf20Sopenharmony_cistatic inline void kvmppc_save_tm_pr(struct kvm_vcpu *vcpu) {} 2878c2ecf20Sopenharmony_cistatic inline void kvmppc_restore_tm_pr(struct kvm_vcpu *vcpu) {} 2888c2ecf20Sopenharmony_cistatic inline void kvmppc_save_tm_sprs(struct kvm_vcpu *vcpu) {} 2898c2ecf20Sopenharmony_cistatic inline void kvmppc_restore_tm_sprs(struct kvm_vcpu *vcpu) {} 2908c2ecf20Sopenharmony_ci#endif 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cilong kvmhv_nested_init(void); 2938c2ecf20Sopenharmony_civoid kvmhv_nested_exit(void); 2948c2ecf20Sopenharmony_civoid kvmhv_vm_nested_init(struct kvm *kvm); 2958c2ecf20Sopenharmony_cilong kvmhv_set_partition_table(struct kvm_vcpu *vcpu); 2968c2ecf20Sopenharmony_cilong kvmhv_copy_tofrom_guest_nested(struct kvm_vcpu *vcpu); 2978c2ecf20Sopenharmony_civoid kvmhv_set_ptbl_entry(unsigned int lpid, u64 dw0, u64 dw1); 2988c2ecf20Sopenharmony_civoid kvmhv_release_all_nested(struct kvm *kvm); 2998c2ecf20Sopenharmony_cilong kvmhv_enter_nested_guest(struct kvm_vcpu *vcpu); 3008c2ecf20Sopenharmony_cilong kvmhv_do_nested_tlbie(struct kvm_vcpu *vcpu); 3018c2ecf20Sopenharmony_ciint kvmhv_run_single_vcpu(struct kvm_vcpu *vcpu, 3028c2ecf20Sopenharmony_ci u64 time_limit, unsigned long lpcr); 3038c2ecf20Sopenharmony_civoid kvmhv_save_hv_regs(struct kvm_vcpu *vcpu, struct hv_guest_state *hr); 3048c2ecf20Sopenharmony_civoid kvmhv_restore_hv_return_state(struct kvm_vcpu *vcpu, 3058c2ecf20Sopenharmony_ci struct hv_guest_state *hr); 3068c2ecf20Sopenharmony_cilong int kvmhv_nested_page_fault(struct kvm_vcpu *vcpu); 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_civoid kvmppc_giveup_fac(struct kvm_vcpu *vcpu, ulong fac); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciextern int kvm_irq_bypass; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic inline struct kvmppc_vcpu_book3s *to_book3s(struct kvm_vcpu *vcpu) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci return vcpu->arch.book3s; 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci/* Also add subarch specific defines */ 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_32_HANDLER 3208c2ecf20Sopenharmony_ci#include <asm/kvm_book3s_32.h> 3218c2ecf20Sopenharmony_ci#endif 3228c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_BOOK3S_64_HANDLER 3238c2ecf20Sopenharmony_ci#include <asm/kvm_book3s_64.h> 3248c2ecf20Sopenharmony_ci#endif 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic inline void kvmppc_set_gpr(struct kvm_vcpu *vcpu, int num, ulong val) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci vcpu->arch.regs.gpr[num] = val; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_gpr(struct kvm_vcpu *vcpu, int num) 3328c2ecf20Sopenharmony_ci{ 3338c2ecf20Sopenharmony_ci return vcpu->arch.regs.gpr[num]; 3348c2ecf20Sopenharmony_ci} 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_cistatic inline void kvmppc_set_cr(struct kvm_vcpu *vcpu, u32 val) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci vcpu->arch.regs.ccr = val; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic inline u32 kvmppc_get_cr(struct kvm_vcpu *vcpu) 3428c2ecf20Sopenharmony_ci{ 3438c2ecf20Sopenharmony_ci return vcpu->arch.regs.ccr; 3448c2ecf20Sopenharmony_ci} 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic inline void kvmppc_set_xer(struct kvm_vcpu *vcpu, ulong val) 3478c2ecf20Sopenharmony_ci{ 3488c2ecf20Sopenharmony_ci vcpu->arch.regs.xer = val; 3498c2ecf20Sopenharmony_ci} 3508c2ecf20Sopenharmony_ci 3518c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_xer(struct kvm_vcpu *vcpu) 3528c2ecf20Sopenharmony_ci{ 3538c2ecf20Sopenharmony_ci return vcpu->arch.regs.xer; 3548c2ecf20Sopenharmony_ci} 3558c2ecf20Sopenharmony_ci 3568c2ecf20Sopenharmony_cistatic inline void kvmppc_set_ctr(struct kvm_vcpu *vcpu, ulong val) 3578c2ecf20Sopenharmony_ci{ 3588c2ecf20Sopenharmony_ci vcpu->arch.regs.ctr = val; 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_ctr(struct kvm_vcpu *vcpu) 3628c2ecf20Sopenharmony_ci{ 3638c2ecf20Sopenharmony_ci return vcpu->arch.regs.ctr; 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ci 3668c2ecf20Sopenharmony_cistatic inline void kvmppc_set_lr(struct kvm_vcpu *vcpu, ulong val) 3678c2ecf20Sopenharmony_ci{ 3688c2ecf20Sopenharmony_ci vcpu->arch.regs.link = val; 3698c2ecf20Sopenharmony_ci} 3708c2ecf20Sopenharmony_ci 3718c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_lr(struct kvm_vcpu *vcpu) 3728c2ecf20Sopenharmony_ci{ 3738c2ecf20Sopenharmony_ci return vcpu->arch.regs.link; 3748c2ecf20Sopenharmony_ci} 3758c2ecf20Sopenharmony_ci 3768c2ecf20Sopenharmony_cistatic inline void kvmppc_set_pc(struct kvm_vcpu *vcpu, ulong val) 3778c2ecf20Sopenharmony_ci{ 3788c2ecf20Sopenharmony_ci vcpu->arch.regs.nip = val; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_pc(struct kvm_vcpu *vcpu) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci return vcpu->arch.regs.nip; 3848c2ecf20Sopenharmony_ci} 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_cistatic inline u64 kvmppc_get_msr(struct kvm_vcpu *vcpu); 3878c2ecf20Sopenharmony_cistatic inline bool kvmppc_need_byteswap(struct kvm_vcpu *vcpu) 3888c2ecf20Sopenharmony_ci{ 3898c2ecf20Sopenharmony_ci return (kvmppc_get_msr(vcpu) & MSR_LE) != (MSR_KERNEL & MSR_LE); 3908c2ecf20Sopenharmony_ci} 3918c2ecf20Sopenharmony_ci 3928c2ecf20Sopenharmony_cistatic inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci return vcpu->arch.fault_dar; 3958c2ecf20Sopenharmony_ci} 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_cistatic inline bool is_kvmppc_resume_guest(int r) 3988c2ecf20Sopenharmony_ci{ 3998c2ecf20Sopenharmony_ci return (r == RESUME_GUEST || r == RESUME_GUEST_NV); 4008c2ecf20Sopenharmony_ci} 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_cistatic inline bool is_kvmppc_hv_enabled(struct kvm *kvm); 4038c2ecf20Sopenharmony_cistatic inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu) 4048c2ecf20Sopenharmony_ci{ 4058c2ecf20Sopenharmony_ci /* Only PR KVM supports the magic page */ 4068c2ecf20Sopenharmony_ci return !is_kvmppc_hv_enabled(vcpu->kvm); 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_ciextern int kvmppc_h_logical_ci_load(struct kvm_vcpu *vcpu); 4108c2ecf20Sopenharmony_ciextern int kvmppc_h_logical_ci_store(struct kvm_vcpu *vcpu); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_ci/* Magic register values loaded into r3 and r4 before the 'sc' assembly 4138c2ecf20Sopenharmony_ci * instruction for the OSI hypercalls */ 4148c2ecf20Sopenharmony_ci#define OSI_SC_MAGIC_R3 0x113724FA 4158c2ecf20Sopenharmony_ci#define OSI_SC_MAGIC_R4 0x77810F9B 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci#define INS_DCBZ 0x7c0007ec 4188c2ecf20Sopenharmony_ci/* TO = 31 for unconditional trap */ 4198c2ecf20Sopenharmony_ci#define INS_TW 0x7fe00008 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ci#define SPLIT_HACK_MASK 0xff000000 4228c2ecf20Sopenharmony_ci#define SPLIT_HACK_OFFS 0xfb000000 4238c2ecf20Sopenharmony_ci 4248c2ecf20Sopenharmony_ci/* 4258c2ecf20Sopenharmony_ci * This packs a VCPU ID from the [0..KVM_MAX_VCPU_ID) space down to the 4268c2ecf20Sopenharmony_ci * [0..KVM_MAX_VCPUS) space, using knowledge of the guest's core stride 4278c2ecf20Sopenharmony_ci * (but not its actual threading mode, which is not available) to avoid 4288c2ecf20Sopenharmony_ci * collisions. 4298c2ecf20Sopenharmony_ci * 4308c2ecf20Sopenharmony_ci * The implementation leaves VCPU IDs from the range [0..KVM_MAX_VCPUS) (block 4318c2ecf20Sopenharmony_ci * 0) unchanged: if the guest is filling each VCORE completely then it will be 4328c2ecf20Sopenharmony_ci * using consecutive IDs and it will fill the space without any packing. 4338c2ecf20Sopenharmony_ci * 4348c2ecf20Sopenharmony_ci * For higher VCPU IDs, the packed ID is based on the VCPU ID modulo 4358c2ecf20Sopenharmony_ci * KVM_MAX_VCPUS (effectively masking off the top bits) and then an offset is 4368c2ecf20Sopenharmony_ci * added to avoid collisions. 4378c2ecf20Sopenharmony_ci * 4388c2ecf20Sopenharmony_ci * VCPU IDs in the range [KVM_MAX_VCPUS..(KVM_MAX_VCPUS*2)) (block 1) are only 4398c2ecf20Sopenharmony_ci * possible if the guest is leaving at least 1/2 of each VCORE empty, so IDs 4408c2ecf20Sopenharmony_ci * can be safely packed into the second half of each VCORE by adding an offset 4418c2ecf20Sopenharmony_ci * of (stride / 2). 4428c2ecf20Sopenharmony_ci * 4438c2ecf20Sopenharmony_ci * Similarly, if VCPU IDs in the range [(KVM_MAX_VCPUS*2)..(KVM_MAX_VCPUS*4)) 4448c2ecf20Sopenharmony_ci * (blocks 2 and 3) are seen, the guest must be leaving at least 3/4 of each 4458c2ecf20Sopenharmony_ci * VCORE empty so packed IDs can be offset by (stride / 4) and (stride * 3 / 4). 4468c2ecf20Sopenharmony_ci * 4478c2ecf20Sopenharmony_ci * Finally, VCPU IDs from blocks 5..7 will only be seen if the guest is using a 4488c2ecf20Sopenharmony_ci * stride of 8 and 1 thread per core so the remaining offsets of 1, 5, 3 and 7 4498c2ecf20Sopenharmony_ci * must be free to use. 4508c2ecf20Sopenharmony_ci * 4518c2ecf20Sopenharmony_ci * (The offsets for each block are stored in block_offsets[], indexed by the 4528c2ecf20Sopenharmony_ci * block number if the stride is 8. For cases where the guest's stride is less 4538c2ecf20Sopenharmony_ci * than 8, we can re-use the block_offsets array by multiplying the block 4548c2ecf20Sopenharmony_ci * number by (MAX_SMT_THREADS / stride) to reach the correct entry.) 4558c2ecf20Sopenharmony_ci */ 4568c2ecf20Sopenharmony_cistatic inline u32 kvmppc_pack_vcpu_id(struct kvm *kvm, u32 id) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci const int block_offsets[MAX_SMT_THREADS] = {0, 4, 2, 6, 1, 5, 3, 7}; 4598c2ecf20Sopenharmony_ci int stride = kvm->arch.emul_smt_mode; 4608c2ecf20Sopenharmony_ci int block = (id / KVM_MAX_VCPUS) * (MAX_SMT_THREADS / stride); 4618c2ecf20Sopenharmony_ci u32 packed_id; 4628c2ecf20Sopenharmony_ci 4638c2ecf20Sopenharmony_ci if (WARN_ONCE(block >= MAX_SMT_THREADS, "VCPU ID too large to pack")) 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci packed_id = (id % KVM_MAX_VCPUS) + block_offsets[block]; 4668c2ecf20Sopenharmony_ci if (WARN_ONCE(packed_id >= KVM_MAX_VCPUS, "VCPU ID packing failed")) 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci return packed_id; 4698c2ecf20Sopenharmony_ci} 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci#endif /* __ASM_KVM_BOOK3S_H__ */ 472