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