xref: /kernel/linux/linux-5.10/arch/s390/kvm/kvm-s390.h (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * definition for kvm on s390
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2008, 2020
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *    Author(s): Carsten Otte <cotte@de.ibm.com>
88c2ecf20Sopenharmony_ci *               Christian Borntraeger <borntraeger@de.ibm.com>
98c2ecf20Sopenharmony_ci *               Christian Ehrhardt <ehrhardt@de.ibm.com>
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#ifndef ARCH_S390_KVM_S390_H
138c2ecf20Sopenharmony_ci#define ARCH_S390_KVM_S390_H
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci#include <linux/hrtimer.h>
168c2ecf20Sopenharmony_ci#include <linux/kvm.h>
178c2ecf20Sopenharmony_ci#include <linux/kvm_host.h>
188c2ecf20Sopenharmony_ci#include <linux/lockdep.h>
198c2ecf20Sopenharmony_ci#include <asm/facility.h>
208c2ecf20Sopenharmony_ci#include <asm/processor.h>
218c2ecf20Sopenharmony_ci#include <asm/sclp.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* Transactional Memory Execution related macros */
248c2ecf20Sopenharmony_ci#define IS_TE_ENABLED(vcpu)	((vcpu->arch.sie_block->ecb & ECB_TE))
258c2ecf20Sopenharmony_ci#define TDB_FORMAT1		1
268c2ecf20Sopenharmony_ci#define IS_ITDB_VALID(vcpu)	((*(char *)vcpu->arch.sie_block->itdba == TDB_FORMAT1))
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ciextern debug_info_t *kvm_s390_dbf;
298c2ecf20Sopenharmony_ciextern debug_info_t *kvm_s390_dbf_uv;
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_ci#define KVM_UV_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
328c2ecf20Sopenharmony_cido { \
338c2ecf20Sopenharmony_ci	debug_sprintf_event((d_kvm)->arch.dbf, d_loglevel, d_string "\n", \
348c2ecf20Sopenharmony_ci	  d_args); \
358c2ecf20Sopenharmony_ci	debug_sprintf_event(kvm_s390_dbf_uv, d_loglevel, \
368c2ecf20Sopenharmony_ci			    "%d: " d_string "\n", (d_kvm)->userspace_pid, \
378c2ecf20Sopenharmony_ci			    d_args); \
388c2ecf20Sopenharmony_ci} while (0)
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci#define KVM_EVENT(d_loglevel, d_string, d_args...)\
418c2ecf20Sopenharmony_cido { \
428c2ecf20Sopenharmony_ci	debug_sprintf_event(kvm_s390_dbf, d_loglevel, d_string "\n", \
438c2ecf20Sopenharmony_ci	  d_args); \
448c2ecf20Sopenharmony_ci} while (0)
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\
478c2ecf20Sopenharmony_cido { \
488c2ecf20Sopenharmony_ci	debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \
498c2ecf20Sopenharmony_ci	  d_args); \
508c2ecf20Sopenharmony_ci} while (0)
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#define VCPU_EVENT(d_vcpu, d_loglevel, d_string, d_args...)\
538c2ecf20Sopenharmony_cido { \
548c2ecf20Sopenharmony_ci	debug_sprintf_event(d_vcpu->kvm->arch.dbf, d_loglevel, \
558c2ecf20Sopenharmony_ci	  "%02d[%016lx-%016lx]: " d_string "\n", d_vcpu->vcpu_id, \
568c2ecf20Sopenharmony_ci	  d_vcpu->arch.sie_block->gpsw.mask, d_vcpu->arch.sie_block->gpsw.addr,\
578c2ecf20Sopenharmony_ci	  d_args); \
588c2ecf20Sopenharmony_ci} while (0)
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistatic inline void kvm_s390_set_cpuflags(struct kvm_vcpu *vcpu, u32 flags)
618c2ecf20Sopenharmony_ci{
628c2ecf20Sopenharmony_ci	atomic_or(flags, &vcpu->arch.sie_block->cpuflags);
638c2ecf20Sopenharmony_ci}
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_cistatic inline void kvm_s390_clear_cpuflags(struct kvm_vcpu *vcpu, u32 flags)
668c2ecf20Sopenharmony_ci{
678c2ecf20Sopenharmony_ci	atomic_andnot(flags, &vcpu->arch.sie_block->cpuflags);
688c2ecf20Sopenharmony_ci}
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_cistatic inline bool kvm_s390_test_cpuflags(struct kvm_vcpu *vcpu, u32 flags)
718c2ecf20Sopenharmony_ci{
728c2ecf20Sopenharmony_ci	return (atomic_read(&vcpu->arch.sie_block->cpuflags) & flags) == flags;
738c2ecf20Sopenharmony_ci}
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_cistatic inline int is_vcpu_stopped(struct kvm_vcpu *vcpu)
768c2ecf20Sopenharmony_ci{
778c2ecf20Sopenharmony_ci	return kvm_s390_test_cpuflags(vcpu, CPUSTAT_STOPPED);
788c2ecf20Sopenharmony_ci}
798c2ecf20Sopenharmony_ci
808c2ecf20Sopenharmony_cistatic inline int is_vcpu_idle(struct kvm_vcpu *vcpu)
818c2ecf20Sopenharmony_ci{
828c2ecf20Sopenharmony_ci	return test_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.idle_mask);
838c2ecf20Sopenharmony_ci}
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistatic inline int kvm_is_ucontrol(struct kvm *kvm)
868c2ecf20Sopenharmony_ci{
878c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL
888c2ecf20Sopenharmony_ci	if (kvm->arch.gmap)
898c2ecf20Sopenharmony_ci		return 0;
908c2ecf20Sopenharmony_ci	return 1;
918c2ecf20Sopenharmony_ci#else
928c2ecf20Sopenharmony_ci	return 0;
938c2ecf20Sopenharmony_ci#endif
948c2ecf20Sopenharmony_ci}
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci#define GUEST_PREFIX_SHIFT 13
978c2ecf20Sopenharmony_cistatic inline u32 kvm_s390_get_prefix(struct kvm_vcpu *vcpu)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	return vcpu->arch.sie_block->prefix << GUEST_PREFIX_SHIFT;
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix)
1038c2ecf20Sopenharmony_ci{
1048c2ecf20Sopenharmony_ci	VCPU_EVENT(vcpu, 3, "set prefix of cpu %03u to 0x%x", vcpu->vcpu_id,
1058c2ecf20Sopenharmony_ci		   prefix);
1068c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->prefix = prefix >> GUEST_PREFIX_SHIFT;
1078c2ecf20Sopenharmony_ci	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
1088c2ecf20Sopenharmony_ci	kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
1098c2ecf20Sopenharmony_ci}
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, u8 *ar)
1128c2ecf20Sopenharmony_ci{
1138c2ecf20Sopenharmony_ci	u32 base2 = vcpu->arch.sie_block->ipb >> 28;
1148c2ecf20Sopenharmony_ci	u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
1158c2ecf20Sopenharmony_ci
1168c2ecf20Sopenharmony_ci	if (ar)
1178c2ecf20Sopenharmony_ci		*ar = base2;
1188c2ecf20Sopenharmony_ci
1198c2ecf20Sopenharmony_ci	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
1208c2ecf20Sopenharmony_ci}
1218c2ecf20Sopenharmony_ci
1228c2ecf20Sopenharmony_cistatic inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
1238c2ecf20Sopenharmony_ci					      u64 *address1, u64 *address2,
1248c2ecf20Sopenharmony_ci					      u8 *ar_b1, u8 *ar_b2)
1258c2ecf20Sopenharmony_ci{
1268c2ecf20Sopenharmony_ci	u32 base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
1278c2ecf20Sopenharmony_ci	u32 disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
1288c2ecf20Sopenharmony_ci	u32 base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
1298c2ecf20Sopenharmony_ci	u32 disp2 = vcpu->arch.sie_block->ipb & 0x0fff;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	*address1 = (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1;
1328c2ecf20Sopenharmony_ci	*address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_ci	if (ar_b1)
1358c2ecf20Sopenharmony_ci		*ar_b1 = base1;
1368c2ecf20Sopenharmony_ci	if (ar_b2)
1378c2ecf20Sopenharmony_ci		*ar_b2 = base2;
1388c2ecf20Sopenharmony_ci}
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_cistatic inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2)
1418c2ecf20Sopenharmony_ci{
1428c2ecf20Sopenharmony_ci	if (r1)
1438c2ecf20Sopenharmony_ci		*r1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 20;
1448c2ecf20Sopenharmony_ci	if (r2)
1458c2ecf20Sopenharmony_ci		*r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu, u8 *ar)
1498c2ecf20Sopenharmony_ci{
1508c2ecf20Sopenharmony_ci	u32 base2 = vcpu->arch.sie_block->ipb >> 28;
1518c2ecf20Sopenharmony_ci	u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
1528c2ecf20Sopenharmony_ci			((vcpu->arch.sie_block->ipb & 0xff00) << 4);
1538c2ecf20Sopenharmony_ci	/* The displacement is a 20bit _SIGNED_ value */
1548c2ecf20Sopenharmony_ci	if (disp2 & 0x80000)
1558c2ecf20Sopenharmony_ci		disp2+=0xfff00000;
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	if (ar)
1588c2ecf20Sopenharmony_ci		*ar = base2;
1598c2ecf20Sopenharmony_ci
1608c2ecf20Sopenharmony_ci	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + (long)(int)disp2;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu, u8 *ar)
1648c2ecf20Sopenharmony_ci{
1658c2ecf20Sopenharmony_ci	u32 base2 = vcpu->arch.sie_block->ipb >> 28;
1668c2ecf20Sopenharmony_ci	u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
1678c2ecf20Sopenharmony_ci
1688c2ecf20Sopenharmony_ci	if (ar)
1698c2ecf20Sopenharmony_ci		*ar = base2;
1708c2ecf20Sopenharmony_ci
1718c2ecf20Sopenharmony_ci	return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
1728c2ecf20Sopenharmony_ci}
1738c2ecf20Sopenharmony_ci
1748c2ecf20Sopenharmony_ci/* Set the condition code in the guest program status word */
1758c2ecf20Sopenharmony_cistatic inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc)
1768c2ecf20Sopenharmony_ci{
1778c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.mask &= ~(3UL << 44);
1788c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.mask |= cc << 44;
1798c2ecf20Sopenharmony_ci}
1808c2ecf20Sopenharmony_ci
1818c2ecf20Sopenharmony_ci/* test availability of facility in a kvm instance */
1828c2ecf20Sopenharmony_cistatic inline int test_kvm_facility(struct kvm *kvm, unsigned long nr)
1838c2ecf20Sopenharmony_ci{
1848c2ecf20Sopenharmony_ci	return __test_facility(nr, kvm->arch.model.fac_mask) &&
1858c2ecf20Sopenharmony_ci		__test_facility(nr, kvm->arch.model.fac_list);
1868c2ecf20Sopenharmony_ci}
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_cistatic inline int set_kvm_facility(u64 *fac_list, unsigned long nr)
1898c2ecf20Sopenharmony_ci{
1908c2ecf20Sopenharmony_ci	unsigned char *ptr;
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci	if (nr >= MAX_FACILITY_BIT)
1938c2ecf20Sopenharmony_ci		return -EINVAL;
1948c2ecf20Sopenharmony_ci	ptr = (unsigned char *) fac_list + (nr >> 3);
1958c2ecf20Sopenharmony_ci	*ptr |= (0x80UL >> (nr & 7));
1968c2ecf20Sopenharmony_ci	return 0;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic inline int test_kvm_cpu_feat(struct kvm *kvm, unsigned long nr)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	WARN_ON_ONCE(nr >= KVM_S390_VM_CPU_FEAT_NR_BITS);
2028c2ecf20Sopenharmony_ci	return test_bit_inv(nr, kvm->arch.cpu_feat);
2038c2ecf20Sopenharmony_ci}
2048c2ecf20Sopenharmony_ci
2058c2ecf20Sopenharmony_ci/* are cpu states controlled by user space */
2068c2ecf20Sopenharmony_cistatic inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	return kvm->arch.user_cpu_state_ctrl != 0;
2098c2ecf20Sopenharmony_ci}
2108c2ecf20Sopenharmony_ci
2118c2ecf20Sopenharmony_ci/* implemented in pv.c */
2128c2ecf20Sopenharmony_ciint kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);
2138c2ecf20Sopenharmony_ciint kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc);
2148c2ecf20Sopenharmony_ciint kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc);
2158c2ecf20Sopenharmony_ciint kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc);
2168c2ecf20Sopenharmony_ciint kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc,
2178c2ecf20Sopenharmony_ci			      u16 *rrc);
2188c2ecf20Sopenharmony_ciint kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size,
2198c2ecf20Sopenharmony_ci		       unsigned long tweak, u16 *rc, u16 *rrc);
2208c2ecf20Sopenharmony_ciint kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_pv_get_handle(struct kvm *kvm)
2238c2ecf20Sopenharmony_ci{
2248c2ecf20Sopenharmony_ci	return kvm->arch.pv.handle;
2258c2ecf20Sopenharmony_ci}
2268c2ecf20Sopenharmony_ci
2278c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_pv_cpu_get_handle(struct kvm_vcpu *vcpu)
2288c2ecf20Sopenharmony_ci{
2298c2ecf20Sopenharmony_ci	return vcpu->arch.pv.handle;
2308c2ecf20Sopenharmony_ci}
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_cistatic inline bool kvm_s390_pv_is_protected(struct kvm *kvm)
2338c2ecf20Sopenharmony_ci{
2348c2ecf20Sopenharmony_ci	lockdep_assert_held(&kvm->lock);
2358c2ecf20Sopenharmony_ci	return !!kvm_s390_pv_get_handle(kvm);
2368c2ecf20Sopenharmony_ci}
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic inline bool kvm_s390_pv_cpu_is_protected(struct kvm_vcpu *vcpu)
2398c2ecf20Sopenharmony_ci{
2408c2ecf20Sopenharmony_ci	lockdep_assert_held(&vcpu->mutex);
2418c2ecf20Sopenharmony_ci	return !!kvm_s390_pv_cpu_get_handle(vcpu);
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/* implemented in interrupt.c */
2458c2ecf20Sopenharmony_ciint kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
2468c2ecf20Sopenharmony_civoid kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu);
2478c2ecf20Sopenharmony_cienum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
2488c2ecf20Sopenharmony_ciint __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu);
2498c2ecf20Sopenharmony_civoid kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu);
2508c2ecf20Sopenharmony_civoid kvm_s390_clear_float_irqs(struct kvm *kvm);
2518c2ecf20Sopenharmony_ciint __must_check kvm_s390_inject_vm(struct kvm *kvm,
2528c2ecf20Sopenharmony_ci				    struct kvm_s390_interrupt *s390int);
2538c2ecf20Sopenharmony_ciint __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
2548c2ecf20Sopenharmony_ci				      struct kvm_s390_irq *irq);
2558c2ecf20Sopenharmony_cistatic inline int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu,
2568c2ecf20Sopenharmony_ci					   struct kvm_s390_pgm_info *pgm_info)
2578c2ecf20Sopenharmony_ci{
2588c2ecf20Sopenharmony_ci	struct kvm_s390_irq irq = {
2598c2ecf20Sopenharmony_ci		.type = KVM_S390_PROGRAM_INT,
2608c2ecf20Sopenharmony_ci		.u.pgm = *pgm_info,
2618c2ecf20Sopenharmony_ci	};
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci	return kvm_s390_inject_vcpu(vcpu, &irq);
2648c2ecf20Sopenharmony_ci}
2658c2ecf20Sopenharmony_cistatic inline int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code)
2668c2ecf20Sopenharmony_ci{
2678c2ecf20Sopenharmony_ci	struct kvm_s390_irq irq = {
2688c2ecf20Sopenharmony_ci		.type = KVM_S390_PROGRAM_INT,
2698c2ecf20Sopenharmony_ci		.u.pgm.code = code,
2708c2ecf20Sopenharmony_ci	};
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	return kvm_s390_inject_vcpu(vcpu, &irq);
2738c2ecf20Sopenharmony_ci}
2748c2ecf20Sopenharmony_cistruct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
2758c2ecf20Sopenharmony_ci						    u64 isc_mask, u32 schid);
2768c2ecf20Sopenharmony_ciint kvm_s390_reinject_io_int(struct kvm *kvm,
2778c2ecf20Sopenharmony_ci			     struct kvm_s390_interrupt_info *inti);
2788c2ecf20Sopenharmony_ciint kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci/* implemented in intercept.c */
2818c2ecf20Sopenharmony_ciu8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu);
2828c2ecf20Sopenharmony_ciint kvm_handle_sie_intercept(struct kvm_vcpu *vcpu);
2838c2ecf20Sopenharmony_cistatic inline void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilen)
2848c2ecf20Sopenharmony_ci{
2858c2ecf20Sopenharmony_ci	struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block;
2868c2ecf20Sopenharmony_ci
2878c2ecf20Sopenharmony_ci	sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilen);
2888c2ecf20Sopenharmony_ci}
2898c2ecf20Sopenharmony_cistatic inline void kvm_s390_forward_psw(struct kvm_vcpu *vcpu, int ilen)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	kvm_s390_rewind_psw(vcpu, -ilen);
2928c2ecf20Sopenharmony_ci}
2938c2ecf20Sopenharmony_cistatic inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu)
2948c2ecf20Sopenharmony_ci{
2958c2ecf20Sopenharmony_ci	/* don't inject PER events if we re-execute the instruction */
2968c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->icptstatus &= ~0x02;
2978c2ecf20Sopenharmony_ci	kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu));
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_ciint handle_sthyi(struct kvm_vcpu *vcpu);
3018c2ecf20Sopenharmony_ci
3028c2ecf20Sopenharmony_ci/* implemented in priv.c */
3038c2ecf20Sopenharmony_ciint is_valid_psw(psw_t *psw);
3048c2ecf20Sopenharmony_ciint kvm_s390_handle_aa(struct kvm_vcpu *vcpu);
3058c2ecf20Sopenharmony_ciint kvm_s390_handle_b2(struct kvm_vcpu *vcpu);
3068c2ecf20Sopenharmony_ciint kvm_s390_handle_e3(struct kvm_vcpu *vcpu);
3078c2ecf20Sopenharmony_ciint kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
3088c2ecf20Sopenharmony_ciint kvm_s390_handle_01(struct kvm_vcpu *vcpu);
3098c2ecf20Sopenharmony_ciint kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
3108c2ecf20Sopenharmony_ciint kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
3118c2ecf20Sopenharmony_ciint kvm_s390_handle_stctl(struct kvm_vcpu *vcpu);
3128c2ecf20Sopenharmony_ciint kvm_s390_handle_lctl(struct kvm_vcpu *vcpu);
3138c2ecf20Sopenharmony_ciint kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
3148c2ecf20Sopenharmony_ciint kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu);
3158c2ecf20Sopenharmony_ci
3168c2ecf20Sopenharmony_ci/* implemented in vsie.c */
3178c2ecf20Sopenharmony_ciint kvm_s390_handle_vsie(struct kvm_vcpu *vcpu);
3188c2ecf20Sopenharmony_civoid kvm_s390_vsie_kick(struct kvm_vcpu *vcpu);
3198c2ecf20Sopenharmony_civoid kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start,
3208c2ecf20Sopenharmony_ci				 unsigned long end);
3218c2ecf20Sopenharmony_civoid kvm_s390_vsie_init(struct kvm *kvm);
3228c2ecf20Sopenharmony_civoid kvm_s390_vsie_destroy(struct kvm *kvm);
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci/* implemented in sigp.c */
3258c2ecf20Sopenharmony_ciint kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
3268c2ecf20Sopenharmony_ciint kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu);
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_ci/* implemented in kvm-s390.c */
3298c2ecf20Sopenharmony_ciint kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
3308c2ecf20Sopenharmony_cilong kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable);
3318c2ecf20Sopenharmony_ciint kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr);
3328c2ecf20Sopenharmony_ciint kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr);
3338c2ecf20Sopenharmony_ciint kvm_s390_vcpu_start(struct kvm_vcpu *vcpu);
3348c2ecf20Sopenharmony_ciint kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu);
3358c2ecf20Sopenharmony_civoid kvm_s390_vcpu_block(struct kvm_vcpu *vcpu);
3368c2ecf20Sopenharmony_civoid kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu);
3378c2ecf20Sopenharmony_cibool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu);
3388c2ecf20Sopenharmony_civoid exit_sie(struct kvm_vcpu *vcpu);
3398c2ecf20Sopenharmony_civoid kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu);
3408c2ecf20Sopenharmony_ciint kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu);
3418c2ecf20Sopenharmony_civoid kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu);
3428c2ecf20Sopenharmony_civoid kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm);
3438c2ecf20Sopenharmony_ci__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu);
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_ci/* implemented in diag.c */
3468c2ecf20Sopenharmony_ciint kvm_s390_handle_diag(struct kvm_vcpu *vcpu);
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_cistatic inline void kvm_s390_vcpu_block_all(struct kvm *kvm)
3498c2ecf20Sopenharmony_ci{
3508c2ecf20Sopenharmony_ci	int i;
3518c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	WARN_ON(!mutex_is_locked(&kvm->lock));
3548c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm)
3558c2ecf20Sopenharmony_ci		kvm_s390_vcpu_block(vcpu);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_cistatic inline void kvm_s390_vcpu_unblock_all(struct kvm *kvm)
3598c2ecf20Sopenharmony_ci{
3608c2ecf20Sopenharmony_ci	int i;
3618c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm)
3648c2ecf20Sopenharmony_ci		kvm_s390_vcpu_unblock(vcpu);
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic inline u64 kvm_s390_get_tod_clock_fast(struct kvm *kvm)
3688c2ecf20Sopenharmony_ci{
3698c2ecf20Sopenharmony_ci	u64 rc;
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	preempt_disable();
3728c2ecf20Sopenharmony_ci	rc = get_tod_clock_fast() + kvm->arch.epoch;
3738c2ecf20Sopenharmony_ci	preempt_enable();
3748c2ecf20Sopenharmony_ci	return rc;
3758c2ecf20Sopenharmony_ci}
3768c2ecf20Sopenharmony_ci
3778c2ecf20Sopenharmony_ci/**
3788c2ecf20Sopenharmony_ci * kvm_s390_inject_prog_cond - conditionally inject a program check
3798c2ecf20Sopenharmony_ci * @vcpu: virtual cpu
3808c2ecf20Sopenharmony_ci * @rc: original return/error code
3818c2ecf20Sopenharmony_ci *
3828c2ecf20Sopenharmony_ci * This function is supposed to be used after regular guest access functions
3838c2ecf20Sopenharmony_ci * failed, to conditionally inject a program check to a vcpu. The typical
3848c2ecf20Sopenharmony_ci * pattern would look like
3858c2ecf20Sopenharmony_ci *
3868c2ecf20Sopenharmony_ci * rc = write_guest(vcpu, addr, data, len);
3878c2ecf20Sopenharmony_ci * if (rc)
3888c2ecf20Sopenharmony_ci *	return kvm_s390_inject_prog_cond(vcpu, rc);
3898c2ecf20Sopenharmony_ci *
3908c2ecf20Sopenharmony_ci * A negative return code from guest access functions implies an internal error
3918c2ecf20Sopenharmony_ci * like e.g. out of memory. In these cases no program check should be injected
3928c2ecf20Sopenharmony_ci * to the guest.
3938c2ecf20Sopenharmony_ci * A positive value implies that an exception happened while accessing a guest's
3948c2ecf20Sopenharmony_ci * memory. In this case all data belonging to the corresponding program check
3958c2ecf20Sopenharmony_ci * has been stored in vcpu->arch.pgm and can be injected with
3968c2ecf20Sopenharmony_ci * kvm_s390_inject_prog_irq().
3978c2ecf20Sopenharmony_ci *
3988c2ecf20Sopenharmony_ci * Returns: - the original @rc value if @rc was negative (internal error)
3998c2ecf20Sopenharmony_ci *	    - zero if @rc was already zero
4008c2ecf20Sopenharmony_ci *	    - zero or error code from injecting if @rc was positive
4018c2ecf20Sopenharmony_ci *	      (program check injected to @vcpu)
4028c2ecf20Sopenharmony_ci */
4038c2ecf20Sopenharmony_cistatic inline int kvm_s390_inject_prog_cond(struct kvm_vcpu *vcpu, int rc)
4048c2ecf20Sopenharmony_ci{
4058c2ecf20Sopenharmony_ci	if (rc <= 0)
4068c2ecf20Sopenharmony_ci		return rc;
4078c2ecf20Sopenharmony_ci	return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
4088c2ecf20Sopenharmony_ci}
4098c2ecf20Sopenharmony_ci
4108c2ecf20Sopenharmony_ciint s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
4118c2ecf20Sopenharmony_ci			struct kvm_s390_irq *s390irq);
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci/* implemented in interrupt.c */
4148c2ecf20Sopenharmony_ciint kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop);
4158c2ecf20Sopenharmony_ciint psw_extint_disabled(struct kvm_vcpu *vcpu);
4168c2ecf20Sopenharmony_civoid kvm_s390_destroy_adapters(struct kvm *kvm);
4178c2ecf20Sopenharmony_ciint kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu);
4188c2ecf20Sopenharmony_ciextern struct kvm_device_ops kvm_flic_ops;
4198c2ecf20Sopenharmony_ciint kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu);
4208c2ecf20Sopenharmony_ciint kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu);
4218c2ecf20Sopenharmony_civoid kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu);
4228c2ecf20Sopenharmony_ciint kvm_s390_set_irq_state(struct kvm_vcpu *vcpu,
4238c2ecf20Sopenharmony_ci			   void __user *buf, int len);
4248c2ecf20Sopenharmony_ciint kvm_s390_get_irq_state(struct kvm_vcpu *vcpu,
4258c2ecf20Sopenharmony_ci			   __u8 __user *buf, int len);
4268c2ecf20Sopenharmony_civoid kvm_s390_gisa_init(struct kvm *kvm);
4278c2ecf20Sopenharmony_civoid kvm_s390_gisa_clear(struct kvm *kvm);
4288c2ecf20Sopenharmony_civoid kvm_s390_gisa_destroy(struct kvm *kvm);
4298c2ecf20Sopenharmony_ciint kvm_s390_gib_init(u8 nisc);
4308c2ecf20Sopenharmony_civoid kvm_s390_gib_destroy(void);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci/* implemented in guestdbg.c */
4338c2ecf20Sopenharmony_civoid kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);
4348c2ecf20Sopenharmony_civoid kvm_s390_restore_guest_per_regs(struct kvm_vcpu *vcpu);
4358c2ecf20Sopenharmony_civoid kvm_s390_patch_guest_per_regs(struct kvm_vcpu *vcpu);
4368c2ecf20Sopenharmony_ciint kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
4378c2ecf20Sopenharmony_ci			    struct kvm_guest_debug *dbg);
4388c2ecf20Sopenharmony_civoid kvm_s390_clear_bp_data(struct kvm_vcpu *vcpu);
4398c2ecf20Sopenharmony_civoid kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu);
4408c2ecf20Sopenharmony_ciint kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu);
4418c2ecf20Sopenharmony_ciint kvm_s390_handle_per_event(struct kvm_vcpu *vcpu);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_ci/* support for Basic/Extended SCA handling */
4448c2ecf20Sopenharmony_cistatic inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm)
4458c2ecf20Sopenharmony_ci{
4468c2ecf20Sopenharmony_ci	struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */
4478c2ecf20Sopenharmony_ci
4488c2ecf20Sopenharmony_ci	return &sca->ipte_control;
4498c2ecf20Sopenharmony_ci}
4508c2ecf20Sopenharmony_cistatic inline int kvm_s390_use_sca_entries(void)
4518c2ecf20Sopenharmony_ci{
4528c2ecf20Sopenharmony_ci	/*
4538c2ecf20Sopenharmony_ci	 * Without SIGP interpretation, only SRS interpretation (if available)
4548c2ecf20Sopenharmony_ci	 * might use the entries. By not setting the entries and keeping them
4558c2ecf20Sopenharmony_ci	 * invalid, hardware will not access them but intercept.
4568c2ecf20Sopenharmony_ci	 */
4578c2ecf20Sopenharmony_ci	return sclp.has_sigpif;
4588c2ecf20Sopenharmony_ci}
4598c2ecf20Sopenharmony_civoid kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu,
4608c2ecf20Sopenharmony_ci				     struct mcck_volatile_info *mcck_info);
4618c2ecf20Sopenharmony_ci
4628c2ecf20Sopenharmony_ci/**
4638c2ecf20Sopenharmony_ci * kvm_s390_vcpu_crypto_reset_all
4648c2ecf20Sopenharmony_ci *
4658c2ecf20Sopenharmony_ci * Reset the crypto attributes for each vcpu. This can be done while the vcpus
4668c2ecf20Sopenharmony_ci * are running as each vcpu will be removed from SIE before resetting the crypt
4678c2ecf20Sopenharmony_ci * attributes and restored to SIE afterward.
4688c2ecf20Sopenharmony_ci *
4698c2ecf20Sopenharmony_ci * Note: The kvm->lock must be held while calling this function
4708c2ecf20Sopenharmony_ci *
4718c2ecf20Sopenharmony_ci * @kvm: the KVM guest
4728c2ecf20Sopenharmony_ci */
4738c2ecf20Sopenharmony_civoid kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm);
4748c2ecf20Sopenharmony_ci#endif
475