162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */ 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * definition for kvm on s390 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright IBM Corp. 2008, 2020 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Author(s): Carsten Otte <cotte@de.ibm.com> 862306a36Sopenharmony_ci * Christian Borntraeger <borntraeger@de.ibm.com> 962306a36Sopenharmony_ci * Christian Ehrhardt <ehrhardt@de.ibm.com> 1062306a36Sopenharmony_ci */ 1162306a36Sopenharmony_ci 1262306a36Sopenharmony_ci#ifndef ARCH_S390_KVM_S390_H 1362306a36Sopenharmony_ci#define ARCH_S390_KVM_S390_H 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include <linux/hrtimer.h> 1662306a36Sopenharmony_ci#include <linux/kvm.h> 1762306a36Sopenharmony_ci#include <linux/kvm_host.h> 1862306a36Sopenharmony_ci#include <linux/lockdep.h> 1962306a36Sopenharmony_ci#include <asm/facility.h> 2062306a36Sopenharmony_ci#include <asm/processor.h> 2162306a36Sopenharmony_ci#include <asm/sclp.h> 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* Transactional Memory Execution related macros */ 2462306a36Sopenharmony_ci#define IS_TE_ENABLED(vcpu) ((vcpu->arch.sie_block->ecb & ECB_TE)) 2562306a36Sopenharmony_ci#define TDB_FORMAT1 1 2662306a36Sopenharmony_ci#define IS_ITDB_VALID(vcpu) \ 2762306a36Sopenharmony_ci ((*(char *)phys_to_virt((vcpu)->arch.sie_block->itdba) == TDB_FORMAT1)) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ciextern debug_info_t *kvm_s390_dbf; 3062306a36Sopenharmony_ciextern debug_info_t *kvm_s390_dbf_uv; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci#define KVM_UV_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ 3362306a36Sopenharmony_cido { \ 3462306a36Sopenharmony_ci debug_sprintf_event((d_kvm)->arch.dbf, d_loglevel, d_string "\n", \ 3562306a36Sopenharmony_ci d_args); \ 3662306a36Sopenharmony_ci debug_sprintf_event(kvm_s390_dbf_uv, d_loglevel, \ 3762306a36Sopenharmony_ci "%d: " d_string "\n", (d_kvm)->userspace_pid, \ 3862306a36Sopenharmony_ci d_args); \ 3962306a36Sopenharmony_ci} while (0) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci#define KVM_EVENT(d_loglevel, d_string, d_args...)\ 4262306a36Sopenharmony_cido { \ 4362306a36Sopenharmony_ci debug_sprintf_event(kvm_s390_dbf, d_loglevel, d_string "\n", \ 4462306a36Sopenharmony_ci d_args); \ 4562306a36Sopenharmony_ci} while (0) 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci#define VM_EVENT(d_kvm, d_loglevel, d_string, d_args...)\ 4862306a36Sopenharmony_cido { \ 4962306a36Sopenharmony_ci debug_sprintf_event(d_kvm->arch.dbf, d_loglevel, d_string "\n", \ 5062306a36Sopenharmony_ci d_args); \ 5162306a36Sopenharmony_ci} while (0) 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#define VCPU_EVENT(d_vcpu, d_loglevel, d_string, d_args...)\ 5462306a36Sopenharmony_cido { \ 5562306a36Sopenharmony_ci debug_sprintf_event(d_vcpu->kvm->arch.dbf, d_loglevel, \ 5662306a36Sopenharmony_ci "%02d[%016lx-%016lx]: " d_string "\n", d_vcpu->vcpu_id, \ 5762306a36Sopenharmony_ci d_vcpu->arch.sie_block->gpsw.mask, d_vcpu->arch.sie_block->gpsw.addr,\ 5862306a36Sopenharmony_ci d_args); \ 5962306a36Sopenharmony_ci} while (0) 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_cistatic inline void kvm_s390_set_cpuflags(struct kvm_vcpu *vcpu, u32 flags) 6262306a36Sopenharmony_ci{ 6362306a36Sopenharmony_ci atomic_or(flags, &vcpu->arch.sie_block->cpuflags); 6462306a36Sopenharmony_ci} 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic inline void kvm_s390_clear_cpuflags(struct kvm_vcpu *vcpu, u32 flags) 6762306a36Sopenharmony_ci{ 6862306a36Sopenharmony_ci atomic_andnot(flags, &vcpu->arch.sie_block->cpuflags); 6962306a36Sopenharmony_ci} 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistatic inline bool kvm_s390_test_cpuflags(struct kvm_vcpu *vcpu, u32 flags) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci return (atomic_read(&vcpu->arch.sie_block->cpuflags) & flags) == flags; 7462306a36Sopenharmony_ci} 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic inline int is_vcpu_stopped(struct kvm_vcpu *vcpu) 7762306a36Sopenharmony_ci{ 7862306a36Sopenharmony_ci return kvm_s390_test_cpuflags(vcpu, CPUSTAT_STOPPED); 7962306a36Sopenharmony_ci} 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic inline int is_vcpu_idle(struct kvm_vcpu *vcpu) 8262306a36Sopenharmony_ci{ 8362306a36Sopenharmony_ci return test_bit(vcpu->vcpu_idx, vcpu->kvm->arch.idle_mask); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistatic inline int kvm_is_ucontrol(struct kvm *kvm) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL 8962306a36Sopenharmony_ci if (kvm->arch.gmap) 9062306a36Sopenharmony_ci return 0; 9162306a36Sopenharmony_ci return 1; 9262306a36Sopenharmony_ci#else 9362306a36Sopenharmony_ci return 0; 9462306a36Sopenharmony_ci#endif 9562306a36Sopenharmony_ci} 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci#define GUEST_PREFIX_SHIFT 13 9862306a36Sopenharmony_cistatic inline u32 kvm_s390_get_prefix(struct kvm_vcpu *vcpu) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci return vcpu->arch.sie_block->prefix << GUEST_PREFIX_SHIFT; 10162306a36Sopenharmony_ci} 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_cistatic inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix) 10462306a36Sopenharmony_ci{ 10562306a36Sopenharmony_ci VCPU_EVENT(vcpu, 3, "set prefix of cpu %03u to 0x%x", vcpu->vcpu_id, 10662306a36Sopenharmony_ci prefix); 10762306a36Sopenharmony_ci vcpu->arch.sie_block->prefix = prefix >> GUEST_PREFIX_SHIFT; 10862306a36Sopenharmony_ci kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); 10962306a36Sopenharmony_ci kvm_make_request(KVM_REQ_REFRESH_GUEST_PREFIX, vcpu); 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu, u8 *ar) 11362306a36Sopenharmony_ci{ 11462306a36Sopenharmony_ci u32 base2 = vcpu->arch.sie_block->ipb >> 28; 11562306a36Sopenharmony_ci u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci if (ar) 11862306a36Sopenharmony_ci *ar = base2; 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; 12162306a36Sopenharmony_ci} 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistatic inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu, 12462306a36Sopenharmony_ci u64 *address1, u64 *address2, 12562306a36Sopenharmony_ci u8 *ar_b1, u8 *ar_b2) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci u32 base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28; 12862306a36Sopenharmony_ci u32 disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16; 12962306a36Sopenharmony_ci u32 base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12; 13062306a36Sopenharmony_ci u32 disp2 = vcpu->arch.sie_block->ipb & 0x0fff; 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci *address1 = (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1; 13362306a36Sopenharmony_ci *address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (ar_b1) 13662306a36Sopenharmony_ci *ar_b1 = base1; 13762306a36Sopenharmony_ci if (ar_b2) 13862306a36Sopenharmony_ci *ar_b2 = base2; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic inline void kvm_s390_get_regs_rre(struct kvm_vcpu *vcpu, int *r1, int *r2) 14262306a36Sopenharmony_ci{ 14362306a36Sopenharmony_ci if (r1) 14462306a36Sopenharmony_ci *r1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 20; 14562306a36Sopenharmony_ci if (r2) 14662306a36Sopenharmony_ci *r2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16; 14762306a36Sopenharmony_ci} 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu, u8 *ar) 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci u32 base2 = vcpu->arch.sie_block->ipb >> 28; 15262306a36Sopenharmony_ci u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) + 15362306a36Sopenharmony_ci ((vcpu->arch.sie_block->ipb & 0xff00) << 4); 15462306a36Sopenharmony_ci /* The displacement is a 20bit _SIGNED_ value */ 15562306a36Sopenharmony_ci if (disp2 & 0x80000) 15662306a36Sopenharmony_ci disp2+=0xfff00000; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci if (ar) 15962306a36Sopenharmony_ci *ar = base2; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + (long)(int)disp2; 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu, u8 *ar) 16562306a36Sopenharmony_ci{ 16662306a36Sopenharmony_ci u32 base2 = vcpu->arch.sie_block->ipb >> 28; 16762306a36Sopenharmony_ci u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci if (ar) 17062306a36Sopenharmony_ci *ar = base2; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; 17362306a36Sopenharmony_ci} 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_ci/* Set the condition code in the guest program status word */ 17662306a36Sopenharmony_cistatic inline void kvm_s390_set_psw_cc(struct kvm_vcpu *vcpu, unsigned long cc) 17762306a36Sopenharmony_ci{ 17862306a36Sopenharmony_ci vcpu->arch.sie_block->gpsw.mask &= ~(3UL << 44); 17962306a36Sopenharmony_ci vcpu->arch.sie_block->gpsw.mask |= cc << 44; 18062306a36Sopenharmony_ci} 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci/* test availability of facility in a kvm instance */ 18362306a36Sopenharmony_cistatic inline int test_kvm_facility(struct kvm *kvm, unsigned long nr) 18462306a36Sopenharmony_ci{ 18562306a36Sopenharmony_ci return __test_facility(nr, kvm->arch.model.fac_mask) && 18662306a36Sopenharmony_ci __test_facility(nr, kvm->arch.model.fac_list); 18762306a36Sopenharmony_ci} 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic inline int set_kvm_facility(u64 *fac_list, unsigned long nr) 19062306a36Sopenharmony_ci{ 19162306a36Sopenharmony_ci unsigned char *ptr; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci if (nr >= MAX_FACILITY_BIT) 19462306a36Sopenharmony_ci return -EINVAL; 19562306a36Sopenharmony_ci ptr = (unsigned char *) fac_list + (nr >> 3); 19662306a36Sopenharmony_ci *ptr |= (0x80UL >> (nr & 7)); 19762306a36Sopenharmony_ci return 0; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic inline int test_kvm_cpu_feat(struct kvm *kvm, unsigned long nr) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci WARN_ON_ONCE(nr >= KVM_S390_VM_CPU_FEAT_NR_BITS); 20362306a36Sopenharmony_ci return test_bit_inv(nr, kvm->arch.cpu_feat); 20462306a36Sopenharmony_ci} 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci/* are cpu states controlled by user space */ 20762306a36Sopenharmony_cistatic inline int kvm_s390_user_cpu_state_ctrl(struct kvm *kvm) 20862306a36Sopenharmony_ci{ 20962306a36Sopenharmony_ci return kvm->arch.user_cpu_state_ctrl != 0; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic inline void kvm_s390_set_user_cpu_state_ctrl(struct kvm *kvm) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci if (kvm->arch.user_cpu_state_ctrl) 21562306a36Sopenharmony_ci return; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci VM_EVENT(kvm, 3, "%s", "ENABLE: Userspace CPU state control"); 21862306a36Sopenharmony_ci kvm->arch.user_cpu_state_ctrl = 1; 21962306a36Sopenharmony_ci} 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci/* get the end gfn of the last (highest gfn) memslot */ 22262306a36Sopenharmony_cistatic inline unsigned long kvm_s390_get_gfn_end(struct kvm_memslots *slots) 22362306a36Sopenharmony_ci{ 22462306a36Sopenharmony_ci struct rb_node *node; 22562306a36Sopenharmony_ci struct kvm_memory_slot *ms; 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (WARN_ON(kvm_memslots_empty(slots))) 22862306a36Sopenharmony_ci return 0; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci node = rb_last(&slots->gfn_tree); 23162306a36Sopenharmony_ci ms = container_of(node, struct kvm_memory_slot, gfn_node[slots->node_idx]); 23262306a36Sopenharmony_ci return ms->base_gfn + ms->npages; 23362306a36Sopenharmony_ci} 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_cistatic inline u32 kvm_s390_get_gisa_desc(struct kvm *kvm) 23662306a36Sopenharmony_ci{ 23762306a36Sopenharmony_ci u32 gd = virt_to_phys(kvm->arch.gisa_int.origin); 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci if (gd && sclp.has_gisaf) 24062306a36Sopenharmony_ci gd |= GISA_FORMAT1; 24162306a36Sopenharmony_ci return gd; 24262306a36Sopenharmony_ci} 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci/* implemented in pv.c */ 24562306a36Sopenharmony_ciint kvm_s390_pv_destroy_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); 24662306a36Sopenharmony_ciint kvm_s390_pv_create_cpu(struct kvm_vcpu *vcpu, u16 *rc, u16 *rrc); 24762306a36Sopenharmony_ciint kvm_s390_pv_set_aside(struct kvm *kvm, u16 *rc, u16 *rrc); 24862306a36Sopenharmony_ciint kvm_s390_pv_deinit_aside_vm(struct kvm *kvm, u16 *rc, u16 *rrc); 24962306a36Sopenharmony_ciint kvm_s390_pv_deinit_cleanup_all(struct kvm *kvm, u16 *rc, u16 *rrc); 25062306a36Sopenharmony_ciint kvm_s390_pv_deinit_vm(struct kvm *kvm, u16 *rc, u16 *rrc); 25162306a36Sopenharmony_ciint kvm_s390_pv_init_vm(struct kvm *kvm, u16 *rc, u16 *rrc); 25262306a36Sopenharmony_ciint kvm_s390_pv_set_sec_parms(struct kvm *kvm, void *hdr, u64 length, u16 *rc, 25362306a36Sopenharmony_ci u16 *rrc); 25462306a36Sopenharmony_ciint kvm_s390_pv_unpack(struct kvm *kvm, unsigned long addr, unsigned long size, 25562306a36Sopenharmony_ci unsigned long tweak, u16 *rc, u16 *rrc); 25662306a36Sopenharmony_ciint kvm_s390_pv_set_cpu_state(struct kvm_vcpu *vcpu, u8 state); 25762306a36Sopenharmony_ciint kvm_s390_pv_dump_cpu(struct kvm_vcpu *vcpu, void *buff, u16 *rc, u16 *rrc); 25862306a36Sopenharmony_ciint kvm_s390_pv_dump_stor_state(struct kvm *kvm, void __user *buff_user, 25962306a36Sopenharmony_ci u64 *gaddr, u64 buff_user_len, u16 *rc, u16 *rrc); 26062306a36Sopenharmony_ciint kvm_s390_pv_dump_complete(struct kvm *kvm, void __user *buff_user, 26162306a36Sopenharmony_ci u16 *rc, u16 *rrc); 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic inline u64 kvm_s390_pv_get_handle(struct kvm *kvm) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci return kvm->arch.pv.handle; 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic inline u64 kvm_s390_pv_cpu_get_handle(struct kvm_vcpu *vcpu) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci return vcpu->arch.pv.handle; 27162306a36Sopenharmony_ci} 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci/* implemented in interrupt.c */ 27462306a36Sopenharmony_ciint kvm_s390_handle_wait(struct kvm_vcpu *vcpu); 27562306a36Sopenharmony_civoid kvm_s390_vcpu_wakeup(struct kvm_vcpu *vcpu); 27662306a36Sopenharmony_cienum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); 27762306a36Sopenharmony_ciint __must_check kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); 27862306a36Sopenharmony_civoid kvm_s390_clear_local_irqs(struct kvm_vcpu *vcpu); 27962306a36Sopenharmony_civoid kvm_s390_clear_float_irqs(struct kvm *kvm); 28062306a36Sopenharmony_ciint __must_check kvm_s390_inject_vm(struct kvm *kvm, 28162306a36Sopenharmony_ci struct kvm_s390_interrupt *s390int); 28262306a36Sopenharmony_ciint __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, 28362306a36Sopenharmony_ci struct kvm_s390_irq *irq); 28462306a36Sopenharmony_cistatic inline int kvm_s390_inject_prog_irq(struct kvm_vcpu *vcpu, 28562306a36Sopenharmony_ci struct kvm_s390_pgm_info *pgm_info) 28662306a36Sopenharmony_ci{ 28762306a36Sopenharmony_ci struct kvm_s390_irq irq = { 28862306a36Sopenharmony_ci .type = KVM_S390_PROGRAM_INT, 28962306a36Sopenharmony_ci .u.pgm = *pgm_info, 29062306a36Sopenharmony_ci }; 29162306a36Sopenharmony_ci 29262306a36Sopenharmony_ci return kvm_s390_inject_vcpu(vcpu, &irq); 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_cistatic inline int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci struct kvm_s390_irq irq = { 29762306a36Sopenharmony_ci .type = KVM_S390_PROGRAM_INT, 29862306a36Sopenharmony_ci .u.pgm.code = code, 29962306a36Sopenharmony_ci }; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci return kvm_s390_inject_vcpu(vcpu, &irq); 30262306a36Sopenharmony_ci} 30362306a36Sopenharmony_cistruct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, 30462306a36Sopenharmony_ci u64 isc_mask, u32 schid); 30562306a36Sopenharmony_ciint kvm_s390_reinject_io_int(struct kvm *kvm, 30662306a36Sopenharmony_ci struct kvm_s390_interrupt_info *inti); 30762306a36Sopenharmony_ciint kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked); 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci/* implemented in intercept.c */ 31062306a36Sopenharmony_ciu8 kvm_s390_get_ilen(struct kvm_vcpu *vcpu); 31162306a36Sopenharmony_ciint kvm_handle_sie_intercept(struct kvm_vcpu *vcpu); 31262306a36Sopenharmony_cistatic inline void kvm_s390_rewind_psw(struct kvm_vcpu *vcpu, int ilen) 31362306a36Sopenharmony_ci{ 31462306a36Sopenharmony_ci struct kvm_s390_sie_block *sie_block = vcpu->arch.sie_block; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci sie_block->gpsw.addr = __rewind_psw(sie_block->gpsw, ilen); 31762306a36Sopenharmony_ci} 31862306a36Sopenharmony_cistatic inline void kvm_s390_forward_psw(struct kvm_vcpu *vcpu, int ilen) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci kvm_s390_rewind_psw(vcpu, -ilen); 32162306a36Sopenharmony_ci} 32262306a36Sopenharmony_cistatic inline void kvm_s390_retry_instr(struct kvm_vcpu *vcpu) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci /* don't inject PER events if we re-execute the instruction */ 32562306a36Sopenharmony_ci vcpu->arch.sie_block->icptstatus &= ~0x02; 32662306a36Sopenharmony_ci kvm_s390_rewind_psw(vcpu, kvm_s390_get_ilen(vcpu)); 32762306a36Sopenharmony_ci} 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ciint handle_sthyi(struct kvm_vcpu *vcpu); 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci/* implemented in priv.c */ 33262306a36Sopenharmony_ciint is_valid_psw(psw_t *psw); 33362306a36Sopenharmony_ciint kvm_s390_handle_aa(struct kvm_vcpu *vcpu); 33462306a36Sopenharmony_ciint kvm_s390_handle_b2(struct kvm_vcpu *vcpu); 33562306a36Sopenharmony_ciint kvm_s390_handle_e3(struct kvm_vcpu *vcpu); 33662306a36Sopenharmony_ciint kvm_s390_handle_e5(struct kvm_vcpu *vcpu); 33762306a36Sopenharmony_ciint kvm_s390_handle_01(struct kvm_vcpu *vcpu); 33862306a36Sopenharmony_ciint kvm_s390_handle_b9(struct kvm_vcpu *vcpu); 33962306a36Sopenharmony_ciint kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); 34062306a36Sopenharmony_ciint kvm_s390_handle_stctl(struct kvm_vcpu *vcpu); 34162306a36Sopenharmony_ciint kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); 34262306a36Sopenharmony_ciint kvm_s390_handle_eb(struct kvm_vcpu *vcpu); 34362306a36Sopenharmony_ciint kvm_s390_skey_check_enable(struct kvm_vcpu *vcpu); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci/* implemented in vsie.c */ 34662306a36Sopenharmony_ciint kvm_s390_handle_vsie(struct kvm_vcpu *vcpu); 34762306a36Sopenharmony_civoid kvm_s390_vsie_kick(struct kvm_vcpu *vcpu); 34862306a36Sopenharmony_civoid kvm_s390_vsie_gmap_notifier(struct gmap *gmap, unsigned long start, 34962306a36Sopenharmony_ci unsigned long end); 35062306a36Sopenharmony_civoid kvm_s390_vsie_init(struct kvm *kvm); 35162306a36Sopenharmony_civoid kvm_s390_vsie_destroy(struct kvm *kvm); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci/* implemented in sigp.c */ 35462306a36Sopenharmony_ciint kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 35562306a36Sopenharmony_ciint kvm_s390_handle_sigp_pei(struct kvm_vcpu *vcpu); 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci/* implemented in kvm-s390.c */ 35862306a36Sopenharmony_ciint kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod); 35962306a36Sopenharmony_cilong kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable); 36062306a36Sopenharmony_ciint kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long addr); 36162306a36Sopenharmony_ciint kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr); 36262306a36Sopenharmony_ciint kvm_s390_vcpu_start(struct kvm_vcpu *vcpu); 36362306a36Sopenharmony_ciint kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu); 36462306a36Sopenharmony_civoid kvm_s390_vcpu_block(struct kvm_vcpu *vcpu); 36562306a36Sopenharmony_civoid kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu); 36662306a36Sopenharmony_cibool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu); 36762306a36Sopenharmony_civoid exit_sie(struct kvm_vcpu *vcpu); 36862306a36Sopenharmony_civoid kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu); 36962306a36Sopenharmony_ciint kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu); 37062306a36Sopenharmony_civoid kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu); 37162306a36Sopenharmony_civoid kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm); 37262306a36Sopenharmony_ci__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu); 37362306a36Sopenharmony_ciint kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rc, u16 *rrc); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci/* implemented in diag.c */ 37662306a36Sopenharmony_ciint kvm_s390_handle_diag(struct kvm_vcpu *vcpu); 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_cistatic inline void kvm_s390_vcpu_block_all(struct kvm *kvm) 37962306a36Sopenharmony_ci{ 38062306a36Sopenharmony_ci unsigned long i; 38162306a36Sopenharmony_ci struct kvm_vcpu *vcpu; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci WARN_ON(!mutex_is_locked(&kvm->lock)); 38462306a36Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) 38562306a36Sopenharmony_ci kvm_s390_vcpu_block(vcpu); 38662306a36Sopenharmony_ci} 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_cistatic inline void kvm_s390_vcpu_unblock_all(struct kvm *kvm) 38962306a36Sopenharmony_ci{ 39062306a36Sopenharmony_ci unsigned long i; 39162306a36Sopenharmony_ci struct kvm_vcpu *vcpu; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci kvm_for_each_vcpu(i, vcpu, kvm) 39462306a36Sopenharmony_ci kvm_s390_vcpu_unblock(vcpu); 39562306a36Sopenharmony_ci} 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_cistatic inline u64 kvm_s390_get_tod_clock_fast(struct kvm *kvm) 39862306a36Sopenharmony_ci{ 39962306a36Sopenharmony_ci u64 rc; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci preempt_disable(); 40262306a36Sopenharmony_ci rc = get_tod_clock_fast() + kvm->arch.epoch; 40362306a36Sopenharmony_ci preempt_enable(); 40462306a36Sopenharmony_ci return rc; 40562306a36Sopenharmony_ci} 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci/** 40862306a36Sopenharmony_ci * kvm_s390_inject_prog_cond - conditionally inject a program check 40962306a36Sopenharmony_ci * @vcpu: virtual cpu 41062306a36Sopenharmony_ci * @rc: original return/error code 41162306a36Sopenharmony_ci * 41262306a36Sopenharmony_ci * This function is supposed to be used after regular guest access functions 41362306a36Sopenharmony_ci * failed, to conditionally inject a program check to a vcpu. The typical 41462306a36Sopenharmony_ci * pattern would look like 41562306a36Sopenharmony_ci * 41662306a36Sopenharmony_ci * rc = write_guest(vcpu, addr, data, len); 41762306a36Sopenharmony_ci * if (rc) 41862306a36Sopenharmony_ci * return kvm_s390_inject_prog_cond(vcpu, rc); 41962306a36Sopenharmony_ci * 42062306a36Sopenharmony_ci * A negative return code from guest access functions implies an internal error 42162306a36Sopenharmony_ci * like e.g. out of memory. In these cases no program check should be injected 42262306a36Sopenharmony_ci * to the guest. 42362306a36Sopenharmony_ci * A positive value implies that an exception happened while accessing a guest's 42462306a36Sopenharmony_ci * memory. In this case all data belonging to the corresponding program check 42562306a36Sopenharmony_ci * has been stored in vcpu->arch.pgm and can be injected with 42662306a36Sopenharmony_ci * kvm_s390_inject_prog_irq(). 42762306a36Sopenharmony_ci * 42862306a36Sopenharmony_ci * Returns: - the original @rc value if @rc was negative (internal error) 42962306a36Sopenharmony_ci * - zero if @rc was already zero 43062306a36Sopenharmony_ci * - zero or error code from injecting if @rc was positive 43162306a36Sopenharmony_ci * (program check injected to @vcpu) 43262306a36Sopenharmony_ci */ 43362306a36Sopenharmony_cistatic inline int kvm_s390_inject_prog_cond(struct kvm_vcpu *vcpu, int rc) 43462306a36Sopenharmony_ci{ 43562306a36Sopenharmony_ci if (rc <= 0) 43662306a36Sopenharmony_ci return rc; 43762306a36Sopenharmony_ci return kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm); 43862306a36Sopenharmony_ci} 43962306a36Sopenharmony_ci 44062306a36Sopenharmony_ciint s390int_to_s390irq(struct kvm_s390_interrupt *s390int, 44162306a36Sopenharmony_ci struct kvm_s390_irq *s390irq); 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci/* implemented in interrupt.c */ 44462306a36Sopenharmony_ciint kvm_s390_vcpu_has_irq(struct kvm_vcpu *vcpu, int exclude_stop); 44562306a36Sopenharmony_ciint psw_extint_disabled(struct kvm_vcpu *vcpu); 44662306a36Sopenharmony_civoid kvm_s390_destroy_adapters(struct kvm *kvm); 44762306a36Sopenharmony_ciint kvm_s390_ext_call_pending(struct kvm_vcpu *vcpu); 44862306a36Sopenharmony_ciextern struct kvm_device_ops kvm_flic_ops; 44962306a36Sopenharmony_ciint kvm_s390_is_stop_irq_pending(struct kvm_vcpu *vcpu); 45062306a36Sopenharmony_ciint kvm_s390_is_restart_irq_pending(struct kvm_vcpu *vcpu); 45162306a36Sopenharmony_civoid kvm_s390_clear_stop_irq(struct kvm_vcpu *vcpu); 45262306a36Sopenharmony_ciint kvm_s390_set_irq_state(struct kvm_vcpu *vcpu, 45362306a36Sopenharmony_ci void __user *buf, int len); 45462306a36Sopenharmony_ciint kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, 45562306a36Sopenharmony_ci __u8 __user *buf, int len); 45662306a36Sopenharmony_civoid kvm_s390_gisa_init(struct kvm *kvm); 45762306a36Sopenharmony_civoid kvm_s390_gisa_clear(struct kvm *kvm); 45862306a36Sopenharmony_civoid kvm_s390_gisa_destroy(struct kvm *kvm); 45962306a36Sopenharmony_civoid kvm_s390_gisa_disable(struct kvm *kvm); 46062306a36Sopenharmony_civoid kvm_s390_gisa_enable(struct kvm *kvm); 46162306a36Sopenharmony_ciint __init kvm_s390_gib_init(u8 nisc); 46262306a36Sopenharmony_civoid kvm_s390_gib_destroy(void); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci/* implemented in guestdbg.c */ 46562306a36Sopenharmony_civoid kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu); 46662306a36Sopenharmony_civoid kvm_s390_restore_guest_per_regs(struct kvm_vcpu *vcpu); 46762306a36Sopenharmony_civoid kvm_s390_patch_guest_per_regs(struct kvm_vcpu *vcpu); 46862306a36Sopenharmony_ciint kvm_s390_import_bp_data(struct kvm_vcpu *vcpu, 46962306a36Sopenharmony_ci struct kvm_guest_debug *dbg); 47062306a36Sopenharmony_civoid kvm_s390_clear_bp_data(struct kvm_vcpu *vcpu); 47162306a36Sopenharmony_civoid kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu); 47262306a36Sopenharmony_ciint kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu); 47362306a36Sopenharmony_ciint kvm_s390_handle_per_event(struct kvm_vcpu *vcpu); 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci/* support for Basic/Extended SCA handling */ 47662306a36Sopenharmony_cistatic inline union ipte_control *kvm_s390_get_ipte_control(struct kvm *kvm) 47762306a36Sopenharmony_ci{ 47862306a36Sopenharmony_ci struct bsca_block *sca = kvm->arch.sca; /* SCA version doesn't matter */ 47962306a36Sopenharmony_ci 48062306a36Sopenharmony_ci return &sca->ipte_control; 48162306a36Sopenharmony_ci} 48262306a36Sopenharmony_cistatic inline int kvm_s390_use_sca_entries(void) 48362306a36Sopenharmony_ci{ 48462306a36Sopenharmony_ci /* 48562306a36Sopenharmony_ci * Without SIGP interpretation, only SRS interpretation (if available) 48662306a36Sopenharmony_ci * might use the entries. By not setting the entries and keeping them 48762306a36Sopenharmony_ci * invalid, hardware will not access them but intercept. 48862306a36Sopenharmony_ci */ 48962306a36Sopenharmony_ci return sclp.has_sigpif; 49062306a36Sopenharmony_ci} 49162306a36Sopenharmony_civoid kvm_s390_reinject_machine_check(struct kvm_vcpu *vcpu, 49262306a36Sopenharmony_ci struct mcck_volatile_info *mcck_info); 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci/** 49562306a36Sopenharmony_ci * kvm_s390_vcpu_crypto_reset_all 49662306a36Sopenharmony_ci * 49762306a36Sopenharmony_ci * Reset the crypto attributes for each vcpu. This can be done while the vcpus 49862306a36Sopenharmony_ci * are running as each vcpu will be removed from SIE before resetting the crypt 49962306a36Sopenharmony_ci * attributes and restored to SIE afterward. 50062306a36Sopenharmony_ci * 50162306a36Sopenharmony_ci * Note: The kvm->lock must be held while calling this function 50262306a36Sopenharmony_ci * 50362306a36Sopenharmony_ci * @kvm: the KVM guest 50462306a36Sopenharmony_ci */ 50562306a36Sopenharmony_civoid kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm); 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci/** 50862306a36Sopenharmony_ci * kvm_s390_vcpu_pci_enable_interp 50962306a36Sopenharmony_ci * 51062306a36Sopenharmony_ci * Set the associated PCI attributes for each vcpu to allow for zPCI Load/Store 51162306a36Sopenharmony_ci * interpretation as well as adapter interruption forwarding. 51262306a36Sopenharmony_ci * 51362306a36Sopenharmony_ci * @kvm: the KVM guest 51462306a36Sopenharmony_ci */ 51562306a36Sopenharmony_civoid kvm_s390_vcpu_pci_enable_interp(struct kvm *kvm); 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci/** 51862306a36Sopenharmony_ci * diag9c_forwarding_hz 51962306a36Sopenharmony_ci * 52062306a36Sopenharmony_ci * Set the maximum number of diag9c forwarding per second 52162306a36Sopenharmony_ci */ 52262306a36Sopenharmony_ciextern unsigned int diag9c_forwarding_hz; 52362306a36Sopenharmony_ci 52462306a36Sopenharmony_ci#endif 525