1d809aa23SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2b0c632dbSHeiko Carstens /* 3bb64da9aSChristian Borntraeger * hosting IBM Z kernel virtual machines (s390x) 4b0c632dbSHeiko Carstens * 5a37cb07aSChristian Borntraeger * Copyright IBM Corp. 2008, 2018 6b0c632dbSHeiko Carstens * 7b0c632dbSHeiko Carstens * Author(s): Carsten Otte <cotte@de.ibm.com> 8b0c632dbSHeiko Carstens * Christian Borntraeger <borntraeger@de.ibm.com> 9b0c632dbSHeiko Carstens * Heiko Carstens <heiko.carstens@de.ibm.com> 10628eb9b8SChristian Ehrhardt * Christian Ehrhardt <ehrhardt@de.ibm.com> 1115f36ebdSJason J. Herne * Jason J. Herne <jjherne@us.ibm.com> 12b0c632dbSHeiko Carstens */ 13b0c632dbSHeiko Carstens 14b0c632dbSHeiko Carstens #include <linux/compiler.h> 15b0c632dbSHeiko Carstens #include <linux/err.h> 16b0c632dbSHeiko Carstens #include <linux/fs.h> 17ca872302SChristian Borntraeger #include <linux/hrtimer.h> 18b0c632dbSHeiko Carstens #include <linux/init.h> 19b0c632dbSHeiko Carstens #include <linux/kvm.h> 20b0c632dbSHeiko Carstens #include <linux/kvm_host.h> 21b2d73b2aSMartin Schwidefsky #include <linux/mman.h> 22b0c632dbSHeiko Carstens #include <linux/module.h> 23d3217967SPaul Gortmaker #include <linux/moduleparam.h> 24a374e892STony Krowiak #include <linux/random.h> 25b0c632dbSHeiko Carstens #include <linux/slab.h> 26ba5c1e9bSCarsten Otte #include <linux/timer.h> 2741408c28SThomas Huth #include <linux/vmalloc.h> 2815c9705fSDavid Hildenbrand #include <linux/bitmap.h> 29174cd4b1SIngo Molnar #include <linux/sched/signal.h> 30190df4a2SClaudio Imbrenda #include <linux/string.h> 31174cd4b1SIngo Molnar 32cbb870c8SHeiko Carstens #include <asm/asm-offsets.h> 33b0c632dbSHeiko Carstens #include <asm/lowcore.h> 34fd5ada04SMartin Schwidefsky #include <asm/stp.h> 35b0c632dbSHeiko Carstens #include <asm/pgtable.h> 361e133ab2SMartin Schwidefsky #include <asm/gmap.h> 37f5daba1dSHeiko Carstens #include <asm/nmi.h> 38a0616cdeSDavid Howells #include <asm/switch_to.h> 396d3da241SJens Freimann #include <asm/isc.h> 401526bf9cSChristian Borntraeger #include <asm/sclp.h> 410a763c78SDavid Hildenbrand #include <asm/cpacf.h> 42221bb8a4SLinus Torvalds #include <asm/timex.h> 438f2abe6aSChristian Borntraeger #include "kvm-s390.h" 44b0c632dbSHeiko Carstens #include "gaccess.h" 45b0c632dbSHeiko Carstens 46ea2cdd27SDavid Hildenbrand #define KMSG_COMPONENT "kvm-s390" 47ea2cdd27SDavid Hildenbrand #undef pr_fmt 48ea2cdd27SDavid Hildenbrand #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt 49ea2cdd27SDavid Hildenbrand 505786fffaSCornelia Huck #define CREATE_TRACE_POINTS 515786fffaSCornelia Huck #include "trace.h" 52ade38c31SCornelia Huck #include "trace-s390.h" 535786fffaSCornelia Huck 5441408c28SThomas Huth #define MEM_OP_MAX_SIZE 65536 /* Maximum transfer size for KVM_S390_MEM_OP */ 55816c7667SJens Freimann #define LOCAL_IRQS 32 56816c7667SJens Freimann #define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \ 57816c7667SJens Freimann (KVM_MAX_VCPUS + LOCAL_IRQS)) 5841408c28SThomas Huth 59b0c632dbSHeiko Carstens #define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU 60b0c632dbSHeiko Carstens 61b0c632dbSHeiko Carstens struct kvm_stats_debugfs_item debugfs_entries[] = { 62b0c632dbSHeiko Carstens { "userspace_handled", VCPU_STAT(exit_userspace) }, 630eaeafa1SChristian Borntraeger { "exit_null", VCPU_STAT(exit_null) }, 648f2abe6aSChristian Borntraeger { "exit_validity", VCPU_STAT(exit_validity) }, 658f2abe6aSChristian Borntraeger { "exit_stop_request", VCPU_STAT(exit_stop_request) }, 668f2abe6aSChristian Borntraeger { "exit_external_request", VCPU_STAT(exit_external_request) }, 67a5e0aceaSChristian Borntraeger { "exit_io_request", VCPU_STAT(exit_io_request) }, 688f2abe6aSChristian Borntraeger { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) }, 69ba5c1e9bSCarsten Otte { "exit_instruction", VCPU_STAT(exit_instruction) }, 709ec6de19SAlexander Yarygin { "exit_pei", VCPU_STAT(exit_pei) }, 71ba5c1e9bSCarsten Otte { "exit_program_interruption", VCPU_STAT(exit_program_interruption) }, 72ba5c1e9bSCarsten Otte { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, 73a011eeb2SJanosch Frank { "exit_operation_exception", VCPU_STAT(exit_operation_exception) }, 74f7819512SPaolo Bonzini { "halt_successful_poll", VCPU_STAT(halt_successful_poll) }, 7562bea5bfSPaolo Bonzini { "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) }, 763491caf2SChristian Borntraeger { "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) }, 77ce2e4f0bSDavid Hildenbrand { "halt_wakeup", VCPU_STAT(halt_wakeup) }, 78f5e10b09SChristian Borntraeger { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, 79ba5c1e9bSCarsten Otte { "instruction_lctl", VCPU_STAT(instruction_lctl) }, 80aba07508SDavid Hildenbrand { "instruction_stctl", VCPU_STAT(instruction_stctl) }, 81aba07508SDavid Hildenbrand { "instruction_stctg", VCPU_STAT(instruction_stctg) }, 82ba5c1e9bSCarsten Otte { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) }, 837697e71fSChristian Ehrhardt { "deliver_external_call", VCPU_STAT(deliver_external_call) }, 84ba5c1e9bSCarsten Otte { "deliver_service_signal", VCPU_STAT(deliver_service_signal) }, 85ba5c1e9bSCarsten Otte { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) }, 86ba5c1e9bSCarsten Otte { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) }, 87ba5c1e9bSCarsten Otte { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) }, 88ba5c1e9bSCarsten Otte { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) }, 89ba5c1e9bSCarsten Otte { "deliver_program_interruption", VCPU_STAT(deliver_program_int) }, 9009a0fb67SChristian Borntraeger { "deliver_io_interrupt", VCPU_STAT(deliver_io_int) }, 91*32de0749SQingFeng Hao { "deliver_machine_check", VCPU_STAT(deliver_machine_check) }, 92ba5c1e9bSCarsten Otte { "exit_wait_state", VCPU_STAT(exit_wait_state) }, 93a37cb07aSChristian Borntraeger { "instruction_epsw", VCPU_STAT(instruction_epsw) }, 94a37cb07aSChristian Borntraeger { "instruction_gs", VCPU_STAT(instruction_gs) }, 95a37cb07aSChristian Borntraeger { "instruction_io_other", VCPU_STAT(instruction_io_other) }, 96a37cb07aSChristian Borntraeger { "instruction_lpsw", VCPU_STAT(instruction_lpsw) }, 97a37cb07aSChristian Borntraeger { "instruction_lpswe", VCPU_STAT(instruction_lpswe) }, 9869d0d3a3SChristian Borntraeger { "instruction_pfmf", VCPU_STAT(instruction_pfmf) }, 99a37cb07aSChristian Borntraeger { "instruction_ptff", VCPU_STAT(instruction_ptff) }, 100453423dcSChristian Borntraeger { "instruction_stidp", VCPU_STAT(instruction_stidp) }, 101a37cb07aSChristian Borntraeger { "instruction_sck", VCPU_STAT(instruction_sck) }, 102a37cb07aSChristian Borntraeger { "instruction_sckpf", VCPU_STAT(instruction_sckpf) }, 103453423dcSChristian Borntraeger { "instruction_spx", VCPU_STAT(instruction_spx) }, 104453423dcSChristian Borntraeger { "instruction_stpx", VCPU_STAT(instruction_stpx) }, 105453423dcSChristian Borntraeger { "instruction_stap", VCPU_STAT(instruction_stap) }, 106a37cb07aSChristian Borntraeger { "instruction_iske", VCPU_STAT(instruction_iske) }, 107a37cb07aSChristian Borntraeger { "instruction_ri", VCPU_STAT(instruction_ri) }, 108a37cb07aSChristian Borntraeger { "instruction_rrbe", VCPU_STAT(instruction_rrbe) }, 109a37cb07aSChristian Borntraeger { "instruction_sske", VCPU_STAT(instruction_sske) }, 1108a242234SHeiko Carstens { "instruction_ipte_interlock", VCPU_STAT(instruction_ipte_interlock) }, 111b31288faSKonstantin Weitz { "instruction_essa", VCPU_STAT(instruction_essa) }, 112453423dcSChristian Borntraeger { "instruction_stsi", VCPU_STAT(instruction_stsi) }, 113453423dcSChristian Borntraeger { "instruction_stfl", VCPU_STAT(instruction_stfl) }, 114a37cb07aSChristian Borntraeger { "instruction_tb", VCPU_STAT(instruction_tb) }, 115a37cb07aSChristian Borntraeger { "instruction_tpi", VCPU_STAT(instruction_tpi) }, 116bb25b9baSChristian Borntraeger { "instruction_tprot", VCPU_STAT(instruction_tprot) }, 117a37cb07aSChristian Borntraeger { "instruction_tsch", VCPU_STAT(instruction_tsch) }, 11895ca2cb5SJanosch Frank { "instruction_sthyi", VCPU_STAT(instruction_sthyi) }, 119a3508fbeSDavid Hildenbrand { "instruction_sie", VCPU_STAT(instruction_sie) }, 1205288fbf0SChristian Borntraeger { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) }, 121bd59d3a4SCornelia Huck { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) }, 1227697e71fSChristian Ehrhardt { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) }, 1235288fbf0SChristian Borntraeger { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) }, 12442cb0c9fSDavid Hildenbrand { "instruction_sigp_cond_emergency", VCPU_STAT(instruction_sigp_cond_emergency) }, 12542cb0c9fSDavid Hildenbrand { "instruction_sigp_start", VCPU_STAT(instruction_sigp_start) }, 1265288fbf0SChristian Borntraeger { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) }, 12742cb0c9fSDavid Hildenbrand { "instruction_sigp_stop_store_status", VCPU_STAT(instruction_sigp_stop_store_status) }, 12842cb0c9fSDavid Hildenbrand { "instruction_sigp_store_status", VCPU_STAT(instruction_sigp_store_status) }, 129cd7b4b61SEric Farman { "instruction_sigp_store_adtl_status", VCPU_STAT(instruction_sigp_store_adtl_status) }, 1305288fbf0SChristian Borntraeger { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) }, 1315288fbf0SChristian Borntraeger { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) }, 1325288fbf0SChristian Borntraeger { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) }, 13342cb0c9fSDavid Hildenbrand { "instruction_sigp_cpu_reset", VCPU_STAT(instruction_sigp_cpu_reset) }, 13442cb0c9fSDavid Hildenbrand { "instruction_sigp_init_cpu_reset", VCPU_STAT(instruction_sigp_init_cpu_reset) }, 13542cb0c9fSDavid Hildenbrand { "instruction_sigp_unknown", VCPU_STAT(instruction_sigp_unknown) }, 136866c138cSChristian Borntraeger { "instruction_diag_10", VCPU_STAT(diagnose_10) }, 137866c138cSChristian Borntraeger { "instruction_diag_44", VCPU_STAT(diagnose_44) }, 138866c138cSChristian Borntraeger { "instruction_diag_9c", VCPU_STAT(diagnose_9c) }, 139866c138cSChristian Borntraeger { "instruction_diag_258", VCPU_STAT(diagnose_258) }, 140866c138cSChristian Borntraeger { "instruction_diag_308", VCPU_STAT(diagnose_308) }, 141866c138cSChristian Borntraeger { "instruction_diag_500", VCPU_STAT(diagnose_500) }, 142a37cb07aSChristian Borntraeger { "instruction_diag_other", VCPU_STAT(diagnose_other) }, 143b0c632dbSHeiko Carstens { NULL } 144b0c632dbSHeiko Carstens }; 145b0c632dbSHeiko Carstens 1468fa1696eSCollin L. Walling struct kvm_s390_tod_clock_ext { 1478fa1696eSCollin L. Walling __u8 epoch_idx; 1488fa1696eSCollin L. Walling __u64 tod; 1498fa1696eSCollin L. Walling __u8 reserved[7]; 1508fa1696eSCollin L. Walling } __packed; 1518fa1696eSCollin L. Walling 152a411edf1SDavid Hildenbrand /* allow nested virtualization in KVM (if enabled by user space) */ 153a411edf1SDavid Hildenbrand static int nested; 154a411edf1SDavid Hildenbrand module_param(nested, int, S_IRUGO); 155a411edf1SDavid Hildenbrand MODULE_PARM_DESC(nested, "Nested virtualization support"); 156a411edf1SDavid Hildenbrand 157b0c632dbSHeiko Carstens 158c3b9e3e1SChristian Borntraeger /* 159c3b9e3e1SChristian Borntraeger * For now we handle at most 16 double words as this is what the s390 base 160c3b9e3e1SChristian Borntraeger * kernel handles and stores in the prefix page. If we ever need to go beyond 161c3b9e3e1SChristian Borntraeger * this, this requires changes to code, but the external uapi can stay. 162c3b9e3e1SChristian Borntraeger */ 163c3b9e3e1SChristian Borntraeger #define SIZE_INTERNAL 16 164c3b9e3e1SChristian Borntraeger 165c3b9e3e1SChristian Borntraeger /* 166c3b9e3e1SChristian Borntraeger * Base feature mask that defines default mask for facilities. Consists of the 167c3b9e3e1SChristian Borntraeger * defines in FACILITIES_KVM and the non-hypervisor managed bits. 168c3b9e3e1SChristian Borntraeger */ 169c3b9e3e1SChristian Borntraeger static unsigned long kvm_s390_fac_base[SIZE_INTERNAL] = { FACILITIES_KVM }; 170c3b9e3e1SChristian Borntraeger /* 171c3b9e3e1SChristian Borntraeger * Extended feature mask. Consists of the defines in FACILITIES_KVM_CPUMODEL 172c3b9e3e1SChristian Borntraeger * and defines the facilities that can be enabled via a cpu model. 173c3b9e3e1SChristian Borntraeger */ 174c3b9e3e1SChristian Borntraeger static unsigned long kvm_s390_fac_ext[SIZE_INTERNAL] = { FACILITIES_KVM_CPUMODEL }; 175c3b9e3e1SChristian Borntraeger 176c3b9e3e1SChristian Borntraeger static unsigned long kvm_s390_fac_size(void) 17778c4b59fSMichael Mueller { 178c3b9e3e1SChristian Borntraeger BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_MASK_SIZE_U64); 179c3b9e3e1SChristian Borntraeger BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_LIST_SIZE_U64); 180c3b9e3e1SChristian Borntraeger BUILD_BUG_ON(SIZE_INTERNAL * sizeof(unsigned long) > 181c3b9e3e1SChristian Borntraeger sizeof(S390_lowcore.stfle_fac_list)); 182c3b9e3e1SChristian Borntraeger 183c3b9e3e1SChristian Borntraeger return SIZE_INTERNAL; 18478c4b59fSMichael Mueller } 18578c4b59fSMichael Mueller 18615c9705fSDavid Hildenbrand /* available cpu features supported by kvm */ 18715c9705fSDavid Hildenbrand static DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS); 1880a763c78SDavid Hildenbrand /* available subfunctions indicated via query / "test bit" */ 1890a763c78SDavid Hildenbrand static struct kvm_s390_vm_cpu_subfunc kvm_s390_available_subfunc; 19015c9705fSDavid Hildenbrand 1919d8d5786SMichael Mueller static struct gmap_notifier gmap_notifier; 192a3508fbeSDavid Hildenbrand static struct gmap_notifier vsie_gmap_notifier; 19378f26131SChristian Borntraeger debug_info_t *kvm_s390_dbf; 1949d8d5786SMichael Mueller 195b0c632dbSHeiko Carstens /* Section: not file related */ 19613a34e06SRadim Krčmář int kvm_arch_hardware_enable(void) 197b0c632dbSHeiko Carstens { 198b0c632dbSHeiko Carstens /* every s390 is virtualization enabled ;-) */ 19910474ae8SAlexander Graf return 0; 200b0c632dbSHeiko Carstens } 201b0c632dbSHeiko Carstens 202414d3b07SMartin Schwidefsky static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start, 203414d3b07SMartin Schwidefsky unsigned long end); 2042c70fe44SChristian Borntraeger 2051575767eSDavid Hildenbrand static void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta) 2061575767eSDavid Hildenbrand { 2071575767eSDavid Hildenbrand u8 delta_idx = 0; 2081575767eSDavid Hildenbrand 2091575767eSDavid Hildenbrand /* 2101575767eSDavid Hildenbrand * The TOD jumps by delta, we have to compensate this by adding 2111575767eSDavid Hildenbrand * -delta to the epoch. 2121575767eSDavid Hildenbrand */ 2131575767eSDavid Hildenbrand delta = -delta; 2141575767eSDavid Hildenbrand 2151575767eSDavid Hildenbrand /* sign-extension - we're adding to signed values below */ 2161575767eSDavid Hildenbrand if ((s64)delta < 0) 2171575767eSDavid Hildenbrand delta_idx = -1; 2181575767eSDavid Hildenbrand 2191575767eSDavid Hildenbrand scb->epoch += delta; 2201575767eSDavid Hildenbrand if (scb->ecd & ECD_MEF) { 2211575767eSDavid Hildenbrand scb->epdx += delta_idx; 2221575767eSDavid Hildenbrand if (scb->epoch < delta) 2231575767eSDavid Hildenbrand scb->epdx += 1; 2241575767eSDavid Hildenbrand } 2251575767eSDavid Hildenbrand } 2261575767eSDavid Hildenbrand 227fdf03650SFan Zhang /* 228fdf03650SFan Zhang * This callback is executed during stop_machine(). All CPUs are therefore 229fdf03650SFan Zhang * temporarily stopped. In order not to change guest behavior, we have to 230fdf03650SFan Zhang * disable preemption whenever we touch the epoch of kvm and the VCPUs, 231fdf03650SFan Zhang * so a CPU won't be stopped while calculating with the epoch. 232fdf03650SFan Zhang */ 233fdf03650SFan Zhang static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val, 234fdf03650SFan Zhang void *v) 235fdf03650SFan Zhang { 236fdf03650SFan Zhang struct kvm *kvm; 237fdf03650SFan Zhang struct kvm_vcpu *vcpu; 238fdf03650SFan Zhang int i; 239fdf03650SFan Zhang unsigned long long *delta = v; 240fdf03650SFan Zhang 241fdf03650SFan Zhang list_for_each_entry(kvm, &vm_list, vm_list) { 242fdf03650SFan Zhang kvm_for_each_vcpu(i, vcpu, kvm) { 2431575767eSDavid Hildenbrand kvm_clock_sync_scb(vcpu->arch.sie_block, *delta); 2441575767eSDavid Hildenbrand if (i == 0) { 2451575767eSDavid Hildenbrand kvm->arch.epoch = vcpu->arch.sie_block->epoch; 2461575767eSDavid Hildenbrand kvm->arch.epdx = vcpu->arch.sie_block->epdx; 2471575767eSDavid Hildenbrand } 248db0758b2SDavid Hildenbrand if (vcpu->arch.cputm_enabled) 249db0758b2SDavid Hildenbrand vcpu->arch.cputm_start += *delta; 25091473b48SDavid Hildenbrand if (vcpu->arch.vsie_block) 2511575767eSDavid Hildenbrand kvm_clock_sync_scb(vcpu->arch.vsie_block, 2521575767eSDavid Hildenbrand *delta); 253fdf03650SFan Zhang } 254fdf03650SFan Zhang } 255fdf03650SFan Zhang return NOTIFY_OK; 256fdf03650SFan Zhang } 257fdf03650SFan Zhang 258fdf03650SFan Zhang static struct notifier_block kvm_clock_notifier = { 259fdf03650SFan Zhang .notifier_call = kvm_clock_sync, 260fdf03650SFan Zhang }; 261fdf03650SFan Zhang 262b0c632dbSHeiko Carstens int kvm_arch_hardware_setup(void) 263b0c632dbSHeiko Carstens { 2642c70fe44SChristian Borntraeger gmap_notifier.notifier_call = kvm_gmap_notifier; 265b2d73b2aSMartin Schwidefsky gmap_register_pte_notifier(&gmap_notifier); 266a3508fbeSDavid Hildenbrand vsie_gmap_notifier.notifier_call = kvm_s390_vsie_gmap_notifier; 267a3508fbeSDavid Hildenbrand gmap_register_pte_notifier(&vsie_gmap_notifier); 268fdf03650SFan Zhang atomic_notifier_chain_register(&s390_epoch_delta_notifier, 269fdf03650SFan Zhang &kvm_clock_notifier); 270b0c632dbSHeiko Carstens return 0; 271b0c632dbSHeiko Carstens } 272b0c632dbSHeiko Carstens 273b0c632dbSHeiko Carstens void kvm_arch_hardware_unsetup(void) 274b0c632dbSHeiko Carstens { 275b2d73b2aSMartin Schwidefsky gmap_unregister_pte_notifier(&gmap_notifier); 276a3508fbeSDavid Hildenbrand gmap_unregister_pte_notifier(&vsie_gmap_notifier); 277fdf03650SFan Zhang atomic_notifier_chain_unregister(&s390_epoch_delta_notifier, 278fdf03650SFan Zhang &kvm_clock_notifier); 279b0c632dbSHeiko Carstens } 280b0c632dbSHeiko Carstens 28122be5a13SDavid Hildenbrand static void allow_cpu_feat(unsigned long nr) 28222be5a13SDavid Hildenbrand { 28322be5a13SDavid Hildenbrand set_bit_inv(nr, kvm_s390_available_cpu_feat); 28422be5a13SDavid Hildenbrand } 28522be5a13SDavid Hildenbrand 2860a763c78SDavid Hildenbrand static inline int plo_test_bit(unsigned char nr) 2870a763c78SDavid Hildenbrand { 2880a763c78SDavid Hildenbrand register unsigned long r0 asm("0") = (unsigned long) nr | 0x100; 289d051ae53SHeiko Carstens int cc; 2900a763c78SDavid Hildenbrand 2910a763c78SDavid Hildenbrand asm volatile( 2920a763c78SDavid Hildenbrand /* Parameter registers are ignored for "test bit" */ 2930a763c78SDavid Hildenbrand " plo 0,0,0,0(0)\n" 2940a763c78SDavid Hildenbrand " ipm %0\n" 2950a763c78SDavid Hildenbrand " srl %0,28\n" 2960a763c78SDavid Hildenbrand : "=d" (cc) 2970a763c78SDavid Hildenbrand : "d" (r0) 2980a763c78SDavid Hildenbrand : "cc"); 2990a763c78SDavid Hildenbrand return cc == 0; 3000a763c78SDavid Hildenbrand } 3010a763c78SDavid Hildenbrand 30222be5a13SDavid Hildenbrand static void kvm_s390_cpu_feat_init(void) 30322be5a13SDavid Hildenbrand { 3040a763c78SDavid Hildenbrand int i; 3050a763c78SDavid Hildenbrand 3060a763c78SDavid Hildenbrand for (i = 0; i < 256; ++i) { 3070a763c78SDavid Hildenbrand if (plo_test_bit(i)) 3080a763c78SDavid Hildenbrand kvm_s390_available_subfunc.plo[i >> 3] |= 0x80 >> (i & 7); 3090a763c78SDavid Hildenbrand } 3100a763c78SDavid Hildenbrand 3110a763c78SDavid Hildenbrand if (test_facility(28)) /* TOD-clock steering */ 312221bb8a4SLinus Torvalds ptff(kvm_s390_available_subfunc.ptff, 313221bb8a4SLinus Torvalds sizeof(kvm_s390_available_subfunc.ptff), 314221bb8a4SLinus Torvalds PTFF_QAF); 3150a763c78SDavid Hildenbrand 3160a763c78SDavid Hildenbrand if (test_facility(17)) { /* MSA */ 31769c0e360SMartin Schwidefsky __cpacf_query(CPACF_KMAC, (cpacf_mask_t *) 31869c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kmac); 31969c0e360SMartin Schwidefsky __cpacf_query(CPACF_KMC, (cpacf_mask_t *) 32069c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kmc); 32169c0e360SMartin Schwidefsky __cpacf_query(CPACF_KM, (cpacf_mask_t *) 32269c0e360SMartin Schwidefsky kvm_s390_available_subfunc.km); 32369c0e360SMartin Schwidefsky __cpacf_query(CPACF_KIMD, (cpacf_mask_t *) 32469c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kimd); 32569c0e360SMartin Schwidefsky __cpacf_query(CPACF_KLMD, (cpacf_mask_t *) 32669c0e360SMartin Schwidefsky kvm_s390_available_subfunc.klmd); 3270a763c78SDavid Hildenbrand } 3280a763c78SDavid Hildenbrand if (test_facility(76)) /* MSA3 */ 32969c0e360SMartin Schwidefsky __cpacf_query(CPACF_PCKMO, (cpacf_mask_t *) 33069c0e360SMartin Schwidefsky kvm_s390_available_subfunc.pckmo); 3310a763c78SDavid Hildenbrand if (test_facility(77)) { /* MSA4 */ 33269c0e360SMartin Schwidefsky __cpacf_query(CPACF_KMCTR, (cpacf_mask_t *) 33369c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kmctr); 33469c0e360SMartin Schwidefsky __cpacf_query(CPACF_KMF, (cpacf_mask_t *) 33569c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kmf); 33669c0e360SMartin Schwidefsky __cpacf_query(CPACF_KMO, (cpacf_mask_t *) 33769c0e360SMartin Schwidefsky kvm_s390_available_subfunc.kmo); 33869c0e360SMartin Schwidefsky __cpacf_query(CPACF_PCC, (cpacf_mask_t *) 33969c0e360SMartin Schwidefsky kvm_s390_available_subfunc.pcc); 3400a763c78SDavid Hildenbrand } 3410a763c78SDavid Hildenbrand if (test_facility(57)) /* MSA5 */ 342985a9d20SHarald Freudenberger __cpacf_query(CPACF_PRNO, (cpacf_mask_t *) 34369c0e360SMartin Schwidefsky kvm_s390_available_subfunc.ppno); 3440a763c78SDavid Hildenbrand 345e000b8e0SJason J. Herne if (test_facility(146)) /* MSA8 */ 346e000b8e0SJason J. Herne __cpacf_query(CPACF_KMA, (cpacf_mask_t *) 347e000b8e0SJason J. Herne kvm_s390_available_subfunc.kma); 348e000b8e0SJason J. Herne 34922be5a13SDavid Hildenbrand if (MACHINE_HAS_ESOP) 35022be5a13SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP); 351a3508fbeSDavid Hildenbrand /* 352a3508fbeSDavid Hildenbrand * We need SIE support, ESOP (PROT_READ protection for gmap_shadow), 353a3508fbeSDavid Hildenbrand * 64bit SCAO (SCA passthrough) and IDTE (for gmap_shadow unshadowing). 354a3508fbeSDavid Hildenbrand */ 355a3508fbeSDavid Hildenbrand if (!sclp.has_sief2 || !MACHINE_HAS_ESOP || !sclp.has_64bscao || 356a411edf1SDavid Hildenbrand !test_facility(3) || !nested) 357a3508fbeSDavid Hildenbrand return; 358a3508fbeSDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIEF2); 35919c439b5SDavid Hildenbrand if (sclp.has_64bscao) 36019c439b5SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_64BSCAO); 3610615a326SDavid Hildenbrand if (sclp.has_siif) 3620615a326SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIIF); 36377d18f6dSDavid Hildenbrand if (sclp.has_gpere) 36477d18f6dSDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GPERE); 365a1b7b9b2SDavid Hildenbrand if (sclp.has_gsls) 366a1b7b9b2SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GSLS); 3675630a8e8SDavid Hildenbrand if (sclp.has_ib) 3685630a8e8SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IB); 36913ee3f67SDavid Hildenbrand if (sclp.has_cei) 37013ee3f67SDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_CEI); 3717fd7f39dSDavid Hildenbrand if (sclp.has_ibs) 3727fd7f39dSDavid Hildenbrand allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS); 373730cd632SFarhan Ali if (sclp.has_kss) 374730cd632SFarhan Ali allow_cpu_feat(KVM_S390_VM_CPU_FEAT_KSS); 3755d3876a8SDavid Hildenbrand /* 3765d3876a8SDavid Hildenbrand * KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make 3775d3876a8SDavid Hildenbrand * all skey handling functions read/set the skey from the PGSTE 3785d3876a8SDavid Hildenbrand * instead of the real storage key. 3795d3876a8SDavid Hildenbrand * 3805d3876a8SDavid Hildenbrand * KVM_S390_VM_CPU_FEAT_CMMA: Wrong shadow of PTE.I bits will make 3815d3876a8SDavid Hildenbrand * pages being detected as preserved although they are resident. 3825d3876a8SDavid Hildenbrand * 3835d3876a8SDavid Hildenbrand * KVM_S390_VM_CPU_FEAT_PFMFI: Wrong shadow of PTE.I bits will 3845d3876a8SDavid Hildenbrand * have the same effect as for KVM_S390_VM_CPU_FEAT_SKEY. 3855d3876a8SDavid Hildenbrand * 3865d3876a8SDavid Hildenbrand * For KVM_S390_VM_CPU_FEAT_SKEY, KVM_S390_VM_CPU_FEAT_CMMA and 3875d3876a8SDavid Hildenbrand * KVM_S390_VM_CPU_FEAT_PFMFI, all PTE.I and PGSTE bits have to be 3885d3876a8SDavid Hildenbrand * correctly shadowed. We can do that for the PGSTE but not for PTE.I. 3895d3876a8SDavid Hildenbrand * 3905d3876a8SDavid Hildenbrand * KVM_S390_VM_CPU_FEAT_SIGPIF: Wrong SCB addresses in the SCA. We 3915d3876a8SDavid Hildenbrand * cannot easily shadow the SCA because of the ipte lock. 3925d3876a8SDavid Hildenbrand */ 39322be5a13SDavid Hildenbrand } 39422be5a13SDavid Hildenbrand 395b0c632dbSHeiko Carstens int kvm_arch_init(void *opaque) 396b0c632dbSHeiko Carstens { 39778f26131SChristian Borntraeger kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long)); 39878f26131SChristian Borntraeger if (!kvm_s390_dbf) 39978f26131SChristian Borntraeger return -ENOMEM; 40078f26131SChristian Borntraeger 40178f26131SChristian Borntraeger if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view)) { 40278f26131SChristian Borntraeger debug_unregister(kvm_s390_dbf); 40378f26131SChristian Borntraeger return -ENOMEM; 40478f26131SChristian Borntraeger } 40578f26131SChristian Borntraeger 40622be5a13SDavid Hildenbrand kvm_s390_cpu_feat_init(); 40722be5a13SDavid Hildenbrand 40884877d93SCornelia Huck /* Register floating interrupt controller interface. */ 40984877d93SCornelia Huck return kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC); 410b0c632dbSHeiko Carstens } 411b0c632dbSHeiko Carstens 41278f26131SChristian Borntraeger void kvm_arch_exit(void) 41378f26131SChristian Borntraeger { 41478f26131SChristian Borntraeger debug_unregister(kvm_s390_dbf); 41578f26131SChristian Borntraeger } 41678f26131SChristian Borntraeger 417b0c632dbSHeiko Carstens /* Section: device related */ 418b0c632dbSHeiko Carstens long kvm_arch_dev_ioctl(struct file *filp, 419b0c632dbSHeiko Carstens unsigned int ioctl, unsigned long arg) 420b0c632dbSHeiko Carstens { 421b0c632dbSHeiko Carstens if (ioctl == KVM_S390_ENABLE_SIE) 422b0c632dbSHeiko Carstens return s390_enable_sie(); 423b0c632dbSHeiko Carstens return -EINVAL; 424b0c632dbSHeiko Carstens } 425b0c632dbSHeiko Carstens 426784aa3d7SAlexander Graf int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext) 427b0c632dbSHeiko Carstens { 428d7b0b5ebSCarsten Otte int r; 429d7b0b5ebSCarsten Otte 4302bd0ac4eSCarsten Otte switch (ext) { 431d7b0b5ebSCarsten Otte case KVM_CAP_S390_PSW: 432b6cf8788SChristian Borntraeger case KVM_CAP_S390_GMAP: 43352e16b18SChristian Borntraeger case KVM_CAP_SYNC_MMU: 4341efd0f59SCarsten Otte #ifdef CONFIG_KVM_S390_UCONTROL 4351efd0f59SCarsten Otte case KVM_CAP_S390_UCONTROL: 4361efd0f59SCarsten Otte #endif 4373c038e6bSDominik Dingel case KVM_CAP_ASYNC_PF: 43860b413c9SChristian Borntraeger case KVM_CAP_SYNC_REGS: 43914eebd91SCarsten Otte case KVM_CAP_ONE_REG: 440d6712df9SCornelia Huck case KVM_CAP_ENABLE_CAP: 441fa6b7fe9SCornelia Huck case KVM_CAP_S390_CSS_SUPPORT: 44210ccaa1eSCornelia Huck case KVM_CAP_IOEVENTFD: 443c05c4186SJens Freimann case KVM_CAP_DEVICE_CTRL: 444d938dc55SCornelia Huck case KVM_CAP_ENABLE_CAP_VM: 44578599d90SCornelia Huck case KVM_CAP_S390_IRQCHIP: 446f2061656SDominik Dingel case KVM_CAP_VM_ATTRIBUTES: 4476352e4d2SDavid Hildenbrand case KVM_CAP_MP_STATE: 448460df4c1SPaolo Bonzini case KVM_CAP_IMMEDIATE_EXIT: 44947b43c52SJens Freimann case KVM_CAP_S390_INJECT_IRQ: 4502444b352SDavid Hildenbrand case KVM_CAP_S390_USER_SIGP: 451e44fc8c9SEkaterina Tumanova case KVM_CAP_S390_USER_STSI: 45230ee2a98SJason J. Herne case KVM_CAP_S390_SKEYS: 453816c7667SJens Freimann case KVM_CAP_S390_IRQ_STATE: 4546502a34cSDavid Hildenbrand case KVM_CAP_S390_USER_INSTR0: 4554036e387SClaudio Imbrenda case KVM_CAP_S390_CMMA_MIGRATION: 45647a4693eSYi Min Zhao case KVM_CAP_S390_AIS: 457da9a1446SChristian Borntraeger case KVM_CAP_S390_AIS_MIGRATION: 458d7b0b5ebSCarsten Otte r = 1; 459d7b0b5ebSCarsten Otte break; 46041408c28SThomas Huth case KVM_CAP_S390_MEM_OP: 46141408c28SThomas Huth r = MEM_OP_MAX_SIZE; 46241408c28SThomas Huth break; 463e726b1bdSChristian Borntraeger case KVM_CAP_NR_VCPUS: 464e726b1bdSChristian Borntraeger case KVM_CAP_MAX_VCPUS: 46576a6dd72SDavid Hildenbrand r = KVM_S390_BSCA_CPU_SLOTS; 466a6940674SDavid Hildenbrand if (!kvm_s390_use_sca_entries()) 467a6940674SDavid Hildenbrand r = KVM_MAX_VCPUS; 468a6940674SDavid Hildenbrand else if (sclp.has_esca && sclp.has_64bscao) 46976a6dd72SDavid Hildenbrand r = KVM_S390_ESCA_CPU_SLOTS; 470e726b1bdSChristian Borntraeger break; 471e1e2e605SNick Wang case KVM_CAP_NR_MEMSLOTS: 472e1e2e605SNick Wang r = KVM_USER_MEM_SLOTS; 473e1e2e605SNick Wang break; 4741526bf9cSChristian Borntraeger case KVM_CAP_S390_COW: 475abf09bedSMartin Schwidefsky r = MACHINE_HAS_ESOP; 4761526bf9cSChristian Borntraeger break; 47768c55750SEric Farman case KVM_CAP_S390_VECTOR_REGISTERS: 47868c55750SEric Farman r = MACHINE_HAS_VX; 47968c55750SEric Farman break; 480c6e5f166SFan Zhang case KVM_CAP_S390_RI: 481c6e5f166SFan Zhang r = test_facility(64); 482c6e5f166SFan Zhang break; 4834e0b1ab7SFan Zhang case KVM_CAP_S390_GS: 4844e0b1ab7SFan Zhang r = test_facility(133); 4854e0b1ab7SFan Zhang break; 48635b3fde6SChristian Borntraeger case KVM_CAP_S390_BPB: 48735b3fde6SChristian Borntraeger r = test_facility(82); 48835b3fde6SChristian Borntraeger break; 4892bd0ac4eSCarsten Otte default: 490d7b0b5ebSCarsten Otte r = 0; 491b0c632dbSHeiko Carstens } 492d7b0b5ebSCarsten Otte return r; 4932bd0ac4eSCarsten Otte } 494b0c632dbSHeiko Carstens 49515f36ebdSJason J. Herne static void kvm_s390_sync_dirty_log(struct kvm *kvm, 49615f36ebdSJason J. Herne struct kvm_memory_slot *memslot) 49715f36ebdSJason J. Herne { 49815f36ebdSJason J. Herne gfn_t cur_gfn, last_gfn; 49915f36ebdSJason J. Herne unsigned long address; 50015f36ebdSJason J. Herne struct gmap *gmap = kvm->arch.gmap; 50115f36ebdSJason J. Herne 50215f36ebdSJason J. Herne /* Loop over all guest pages */ 50315f36ebdSJason J. Herne last_gfn = memslot->base_gfn + memslot->npages; 50415f36ebdSJason J. Herne for (cur_gfn = memslot->base_gfn; cur_gfn <= last_gfn; cur_gfn++) { 50515f36ebdSJason J. Herne address = gfn_to_hva_memslot(memslot, cur_gfn); 50615f36ebdSJason J. Herne 5071e133ab2SMartin Schwidefsky if (test_and_clear_guest_dirty(gmap->mm, address)) 50815f36ebdSJason J. Herne mark_page_dirty(kvm, cur_gfn); 5091763f8d0SChristian Borntraeger if (fatal_signal_pending(current)) 5101763f8d0SChristian Borntraeger return; 51170c88a00SChristian Borntraeger cond_resched(); 51215f36ebdSJason J. Herne } 51315f36ebdSJason J. Herne } 51415f36ebdSJason J. Herne 515b0c632dbSHeiko Carstens /* Section: vm related */ 516a6e2f683SEugene (jno) Dvurechenski static void sca_del_vcpu(struct kvm_vcpu *vcpu); 517a6e2f683SEugene (jno) Dvurechenski 518b0c632dbSHeiko Carstens /* 519b0c632dbSHeiko Carstens * Get (and clear) the dirty memory log for a memory slot. 520b0c632dbSHeiko Carstens */ 521b0c632dbSHeiko Carstens int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, 522b0c632dbSHeiko Carstens struct kvm_dirty_log *log) 523b0c632dbSHeiko Carstens { 52415f36ebdSJason J. Herne int r; 52515f36ebdSJason J. Herne unsigned long n; 5269f6b8029SPaolo Bonzini struct kvm_memslots *slots; 52715f36ebdSJason J. Herne struct kvm_memory_slot *memslot; 52815f36ebdSJason J. Herne int is_dirty = 0; 52915f36ebdSJason J. Herne 530e1e8a962SJanosch Frank if (kvm_is_ucontrol(kvm)) 531e1e8a962SJanosch Frank return -EINVAL; 532e1e8a962SJanosch Frank 53315f36ebdSJason J. Herne mutex_lock(&kvm->slots_lock); 53415f36ebdSJason J. Herne 53515f36ebdSJason J. Herne r = -EINVAL; 53615f36ebdSJason J. Herne if (log->slot >= KVM_USER_MEM_SLOTS) 53715f36ebdSJason J. Herne goto out; 53815f36ebdSJason J. Herne 5399f6b8029SPaolo Bonzini slots = kvm_memslots(kvm); 5409f6b8029SPaolo Bonzini memslot = id_to_memslot(slots, log->slot); 54115f36ebdSJason J. Herne r = -ENOENT; 54215f36ebdSJason J. Herne if (!memslot->dirty_bitmap) 54315f36ebdSJason J. Herne goto out; 54415f36ebdSJason J. Herne 54515f36ebdSJason J. Herne kvm_s390_sync_dirty_log(kvm, memslot); 54615f36ebdSJason J. Herne r = kvm_get_dirty_log(kvm, log, &is_dirty); 54715f36ebdSJason J. Herne if (r) 54815f36ebdSJason J. Herne goto out; 54915f36ebdSJason J. Herne 55015f36ebdSJason J. Herne /* Clear the dirty log */ 55115f36ebdSJason J. Herne if (is_dirty) { 55215f36ebdSJason J. Herne n = kvm_dirty_bitmap_bytes(memslot); 55315f36ebdSJason J. Herne memset(memslot->dirty_bitmap, 0, n); 55415f36ebdSJason J. Herne } 55515f36ebdSJason J. Herne r = 0; 55615f36ebdSJason J. Herne out: 55715f36ebdSJason J. Herne mutex_unlock(&kvm->slots_lock); 55815f36ebdSJason J. Herne return r; 559b0c632dbSHeiko Carstens } 560b0c632dbSHeiko Carstens 5616502a34cSDavid Hildenbrand static void icpt_operexc_on_all_vcpus(struct kvm *kvm) 5626502a34cSDavid Hildenbrand { 5636502a34cSDavid Hildenbrand unsigned int i; 5646502a34cSDavid Hildenbrand struct kvm_vcpu *vcpu; 5656502a34cSDavid Hildenbrand 5666502a34cSDavid Hildenbrand kvm_for_each_vcpu(i, vcpu, kvm) { 5676502a34cSDavid Hildenbrand kvm_s390_sync_request(KVM_REQ_ICPT_OPEREXC, vcpu); 5686502a34cSDavid Hildenbrand } 5696502a34cSDavid Hildenbrand } 5706502a34cSDavid Hildenbrand 571d938dc55SCornelia Huck static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap) 572d938dc55SCornelia Huck { 573d938dc55SCornelia Huck int r; 574d938dc55SCornelia Huck 575d938dc55SCornelia Huck if (cap->flags) 576d938dc55SCornelia Huck return -EINVAL; 577d938dc55SCornelia Huck 578d938dc55SCornelia Huck switch (cap->cap) { 57984223598SCornelia Huck case KVM_CAP_S390_IRQCHIP: 580c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_IRQCHIP"); 58184223598SCornelia Huck kvm->arch.use_irqchip = 1; 58284223598SCornelia Huck r = 0; 58384223598SCornelia Huck break; 5842444b352SDavid Hildenbrand case KVM_CAP_S390_USER_SIGP: 585c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_SIGP"); 5862444b352SDavid Hildenbrand kvm->arch.user_sigp = 1; 5872444b352SDavid Hildenbrand r = 0; 5882444b352SDavid Hildenbrand break; 58968c55750SEric Farman case KVM_CAP_S390_VECTOR_REGISTERS: 5905967c17bSDavid Hildenbrand mutex_lock(&kvm->lock); 591a03825bbSPaolo Bonzini if (kvm->created_vcpus) { 5925967c17bSDavid Hildenbrand r = -EBUSY; 5935967c17bSDavid Hildenbrand } else if (MACHINE_HAS_VX) { 594c54f0d6aSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_mask, 129); 595c54f0d6aSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_list, 129); 5962f87d942SGuenther Hutzl if (test_facility(134)) { 5972f87d942SGuenther Hutzl set_kvm_facility(kvm->arch.model.fac_mask, 134); 5982f87d942SGuenther Hutzl set_kvm_facility(kvm->arch.model.fac_list, 134); 5992f87d942SGuenther Hutzl } 60053743aa7SMaxim Samoylov if (test_facility(135)) { 60153743aa7SMaxim Samoylov set_kvm_facility(kvm->arch.model.fac_mask, 135); 60253743aa7SMaxim Samoylov set_kvm_facility(kvm->arch.model.fac_list, 135); 60353743aa7SMaxim Samoylov } 60418280d8bSMichael Mueller r = 0; 60518280d8bSMichael Mueller } else 60618280d8bSMichael Mueller r = -EINVAL; 6075967c17bSDavid Hildenbrand mutex_unlock(&kvm->lock); 608c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s", 609c92ea7b9SChristian Borntraeger r ? "(not available)" : "(success)"); 61068c55750SEric Farman break; 611c6e5f166SFan Zhang case KVM_CAP_S390_RI: 612c6e5f166SFan Zhang r = -EINVAL; 613c6e5f166SFan Zhang mutex_lock(&kvm->lock); 614a03825bbSPaolo Bonzini if (kvm->created_vcpus) { 615c6e5f166SFan Zhang r = -EBUSY; 616c6e5f166SFan Zhang } else if (test_facility(64)) { 617c54f0d6aSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_mask, 64); 618c54f0d6aSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_list, 64); 619c6e5f166SFan Zhang r = 0; 620c6e5f166SFan Zhang } 621c6e5f166SFan Zhang mutex_unlock(&kvm->lock); 622c6e5f166SFan Zhang VM_EVENT(kvm, 3, "ENABLE: CAP_S390_RI %s", 623c6e5f166SFan Zhang r ? "(not available)" : "(success)"); 624c6e5f166SFan Zhang break; 62547a4693eSYi Min Zhao case KVM_CAP_S390_AIS: 62647a4693eSYi Min Zhao mutex_lock(&kvm->lock); 62747a4693eSYi Min Zhao if (kvm->created_vcpus) { 62847a4693eSYi Min Zhao r = -EBUSY; 62947a4693eSYi Min Zhao } else { 63047a4693eSYi Min Zhao set_kvm_facility(kvm->arch.model.fac_mask, 72); 63147a4693eSYi Min Zhao set_kvm_facility(kvm->arch.model.fac_list, 72); 63247a4693eSYi Min Zhao r = 0; 63347a4693eSYi Min Zhao } 63447a4693eSYi Min Zhao mutex_unlock(&kvm->lock); 63547a4693eSYi Min Zhao VM_EVENT(kvm, 3, "ENABLE: AIS %s", 63647a4693eSYi Min Zhao r ? "(not available)" : "(success)"); 63747a4693eSYi Min Zhao break; 6384e0b1ab7SFan Zhang case KVM_CAP_S390_GS: 6394e0b1ab7SFan Zhang r = -EINVAL; 6404e0b1ab7SFan Zhang mutex_lock(&kvm->lock); 641241e3ec0SChristian Borntraeger if (kvm->created_vcpus) { 6424e0b1ab7SFan Zhang r = -EBUSY; 6434e0b1ab7SFan Zhang } else if (test_facility(133)) { 6444e0b1ab7SFan Zhang set_kvm_facility(kvm->arch.model.fac_mask, 133); 6454e0b1ab7SFan Zhang set_kvm_facility(kvm->arch.model.fac_list, 133); 6464e0b1ab7SFan Zhang r = 0; 6474e0b1ab7SFan Zhang } 6484e0b1ab7SFan Zhang mutex_unlock(&kvm->lock); 6494e0b1ab7SFan Zhang VM_EVENT(kvm, 3, "ENABLE: CAP_S390_GS %s", 6504e0b1ab7SFan Zhang r ? "(not available)" : "(success)"); 6514e0b1ab7SFan Zhang break; 652e44fc8c9SEkaterina Tumanova case KVM_CAP_S390_USER_STSI: 653c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_STSI"); 654e44fc8c9SEkaterina Tumanova kvm->arch.user_stsi = 1; 655e44fc8c9SEkaterina Tumanova r = 0; 656e44fc8c9SEkaterina Tumanova break; 6576502a34cSDavid Hildenbrand case KVM_CAP_S390_USER_INSTR0: 6586502a34cSDavid Hildenbrand VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_INSTR0"); 6596502a34cSDavid Hildenbrand kvm->arch.user_instr0 = 1; 6606502a34cSDavid Hildenbrand icpt_operexc_on_all_vcpus(kvm); 6616502a34cSDavid Hildenbrand r = 0; 6626502a34cSDavid Hildenbrand break; 663d938dc55SCornelia Huck default: 664d938dc55SCornelia Huck r = -EINVAL; 665d938dc55SCornelia Huck break; 666d938dc55SCornelia Huck } 667d938dc55SCornelia Huck return r; 668d938dc55SCornelia Huck } 669d938dc55SCornelia Huck 6708c0a7ce6SDominik Dingel static int kvm_s390_get_mem_control(struct kvm *kvm, struct kvm_device_attr *attr) 6718c0a7ce6SDominik Dingel { 6728c0a7ce6SDominik Dingel int ret; 6738c0a7ce6SDominik Dingel 6748c0a7ce6SDominik Dingel switch (attr->attr) { 6758c0a7ce6SDominik Dingel case KVM_S390_VM_MEM_LIMIT_SIZE: 6768c0a7ce6SDominik Dingel ret = 0; 677c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "QUERY: max guest memory: %lu bytes", 678a3a92c31SDominik Dingel kvm->arch.mem_limit); 679a3a92c31SDominik Dingel if (put_user(kvm->arch.mem_limit, (u64 __user *)attr->addr)) 6808c0a7ce6SDominik Dingel ret = -EFAULT; 6818c0a7ce6SDominik Dingel break; 6828c0a7ce6SDominik Dingel default: 6838c0a7ce6SDominik Dingel ret = -ENXIO; 6848c0a7ce6SDominik Dingel break; 6858c0a7ce6SDominik Dingel } 6868c0a7ce6SDominik Dingel return ret; 6878c0a7ce6SDominik Dingel } 6888c0a7ce6SDominik Dingel 6898c0a7ce6SDominik Dingel static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *attr) 6904f718eabSDominik Dingel { 6914f718eabSDominik Dingel int ret; 6924f718eabSDominik Dingel unsigned int idx; 6934f718eabSDominik Dingel switch (attr->attr) { 6944f718eabSDominik Dingel case KVM_S390_VM_MEM_ENABLE_CMMA: 695f9cbd9b0SDavid Hildenbrand ret = -ENXIO; 696c24cc9c8SDavid Hildenbrand if (!sclp.has_cmma) 697e6db1d61SDominik Dingel break; 698e6db1d61SDominik Dingel 6994f718eabSDominik Dingel ret = -EBUSY; 700c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: CMMA support"); 7014f718eabSDominik Dingel mutex_lock(&kvm->lock); 702a03825bbSPaolo Bonzini if (!kvm->created_vcpus) { 7034f718eabSDominik Dingel kvm->arch.use_cmma = 1; 704c9f0a2b8SJanosch Frank /* Not compatible with cmma. */ 705c9f0a2b8SJanosch Frank kvm->arch.use_pfmfi = 0; 7064f718eabSDominik Dingel ret = 0; 7074f718eabSDominik Dingel } 7084f718eabSDominik Dingel mutex_unlock(&kvm->lock); 7094f718eabSDominik Dingel break; 7104f718eabSDominik Dingel case KVM_S390_VM_MEM_CLR_CMMA: 711f9cbd9b0SDavid Hildenbrand ret = -ENXIO; 712f9cbd9b0SDavid Hildenbrand if (!sclp.has_cmma) 713f9cbd9b0SDavid Hildenbrand break; 714c3489155SDominik Dingel ret = -EINVAL; 715c3489155SDominik Dingel if (!kvm->arch.use_cmma) 716c3489155SDominik Dingel break; 717c3489155SDominik Dingel 718c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "RESET: CMMA states"); 7194f718eabSDominik Dingel mutex_lock(&kvm->lock); 7204f718eabSDominik Dingel idx = srcu_read_lock(&kvm->srcu); 721a13cff31SDominik Dingel s390_reset_cmma(kvm->arch.gmap->mm); 7224f718eabSDominik Dingel srcu_read_unlock(&kvm->srcu, idx); 7234f718eabSDominik Dingel mutex_unlock(&kvm->lock); 7244f718eabSDominik Dingel ret = 0; 7254f718eabSDominik Dingel break; 7268c0a7ce6SDominik Dingel case KVM_S390_VM_MEM_LIMIT_SIZE: { 7278c0a7ce6SDominik Dingel unsigned long new_limit; 7288c0a7ce6SDominik Dingel 7298c0a7ce6SDominik Dingel if (kvm_is_ucontrol(kvm)) 7308c0a7ce6SDominik Dingel return -EINVAL; 7318c0a7ce6SDominik Dingel 7328c0a7ce6SDominik Dingel if (get_user(new_limit, (u64 __user *)attr->addr)) 7338c0a7ce6SDominik Dingel return -EFAULT; 7348c0a7ce6SDominik Dingel 735a3a92c31SDominik Dingel if (kvm->arch.mem_limit != KVM_S390_NO_MEM_LIMIT && 736a3a92c31SDominik Dingel new_limit > kvm->arch.mem_limit) 7378c0a7ce6SDominik Dingel return -E2BIG; 7388c0a7ce6SDominik Dingel 739a3a92c31SDominik Dingel if (!new_limit) 740a3a92c31SDominik Dingel return -EINVAL; 741a3a92c31SDominik Dingel 7426ea427bbSMartin Schwidefsky /* gmap_create takes last usable address */ 743a3a92c31SDominik Dingel if (new_limit != KVM_S390_NO_MEM_LIMIT) 744a3a92c31SDominik Dingel new_limit -= 1; 745a3a92c31SDominik Dingel 7468c0a7ce6SDominik Dingel ret = -EBUSY; 7478c0a7ce6SDominik Dingel mutex_lock(&kvm->lock); 748a03825bbSPaolo Bonzini if (!kvm->created_vcpus) { 7496ea427bbSMartin Schwidefsky /* gmap_create will round the limit up */ 7506ea427bbSMartin Schwidefsky struct gmap *new = gmap_create(current->mm, new_limit); 7518c0a7ce6SDominik Dingel 7528c0a7ce6SDominik Dingel if (!new) { 7538c0a7ce6SDominik Dingel ret = -ENOMEM; 7548c0a7ce6SDominik Dingel } else { 7556ea427bbSMartin Schwidefsky gmap_remove(kvm->arch.gmap); 7568c0a7ce6SDominik Dingel new->private = kvm; 7578c0a7ce6SDominik Dingel kvm->arch.gmap = new; 7588c0a7ce6SDominik Dingel ret = 0; 7598c0a7ce6SDominik Dingel } 7608c0a7ce6SDominik Dingel } 7618c0a7ce6SDominik Dingel mutex_unlock(&kvm->lock); 762a3a92c31SDominik Dingel VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit); 763a3a92c31SDominik Dingel VM_EVENT(kvm, 3, "New guest asce: 0x%pK", 764a3a92c31SDominik Dingel (void *) kvm->arch.gmap->asce); 7658c0a7ce6SDominik Dingel break; 7668c0a7ce6SDominik Dingel } 7674f718eabSDominik Dingel default: 7684f718eabSDominik Dingel ret = -ENXIO; 7694f718eabSDominik Dingel break; 7704f718eabSDominik Dingel } 7714f718eabSDominik Dingel return ret; 7724f718eabSDominik Dingel } 7734f718eabSDominik Dingel 774a374e892STony Krowiak static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu); 775a374e892STony Krowiak 776a374e892STony Krowiak static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr) 777a374e892STony Krowiak { 778a374e892STony Krowiak struct kvm_vcpu *vcpu; 779a374e892STony Krowiak int i; 780a374e892STony Krowiak 7819d8d5786SMichael Mueller if (!test_kvm_facility(kvm, 76)) 782a374e892STony Krowiak return -EINVAL; 783a374e892STony Krowiak 784a374e892STony Krowiak mutex_lock(&kvm->lock); 785a374e892STony Krowiak switch (attr->attr) { 786a374e892STony Krowiak case KVM_S390_VM_CRYPTO_ENABLE_AES_KW: 787a374e892STony Krowiak get_random_bytes( 788a374e892STony Krowiak kvm->arch.crypto.crycb->aes_wrapping_key_mask, 789a374e892STony Krowiak sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask)); 790a374e892STony Krowiak kvm->arch.crypto.aes_kw = 1; 791c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support"); 792a374e892STony Krowiak break; 793a374e892STony Krowiak case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW: 794a374e892STony Krowiak get_random_bytes( 795a374e892STony Krowiak kvm->arch.crypto.crycb->dea_wrapping_key_mask, 796a374e892STony Krowiak sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask)); 797a374e892STony Krowiak kvm->arch.crypto.dea_kw = 1; 798c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support"); 799a374e892STony Krowiak break; 800a374e892STony Krowiak case KVM_S390_VM_CRYPTO_DISABLE_AES_KW: 801a374e892STony Krowiak kvm->arch.crypto.aes_kw = 0; 802a374e892STony Krowiak memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0, 803a374e892STony Krowiak sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask)); 804c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support"); 805a374e892STony Krowiak break; 806a374e892STony Krowiak case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW: 807a374e892STony Krowiak kvm->arch.crypto.dea_kw = 0; 808a374e892STony Krowiak memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0, 809a374e892STony Krowiak sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask)); 810c92ea7b9SChristian Borntraeger VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support"); 811a374e892STony Krowiak break; 812a374e892STony Krowiak default: 813a374e892STony Krowiak mutex_unlock(&kvm->lock); 814a374e892STony Krowiak return -ENXIO; 815a374e892STony Krowiak } 816a374e892STony Krowiak 817a374e892STony Krowiak kvm_for_each_vcpu(i, vcpu, kvm) { 818a374e892STony Krowiak kvm_s390_vcpu_crypto_setup(vcpu); 819a374e892STony Krowiak exit_sie(vcpu); 820a374e892STony Krowiak } 821a374e892STony Krowiak mutex_unlock(&kvm->lock); 822a374e892STony Krowiak return 0; 823a374e892STony Krowiak } 824a374e892STony Krowiak 825190df4a2SClaudio Imbrenda static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req) 826190df4a2SClaudio Imbrenda { 827190df4a2SClaudio Imbrenda int cx; 828190df4a2SClaudio Imbrenda struct kvm_vcpu *vcpu; 829190df4a2SClaudio Imbrenda 830190df4a2SClaudio Imbrenda kvm_for_each_vcpu(cx, vcpu, kvm) 831190df4a2SClaudio Imbrenda kvm_s390_sync_request(req, vcpu); 832190df4a2SClaudio Imbrenda } 833190df4a2SClaudio Imbrenda 834190df4a2SClaudio Imbrenda /* 835190df4a2SClaudio Imbrenda * Must be called with kvm->srcu held to avoid races on memslots, and with 8361de1ea7eSChristian Borntraeger * kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration. 837190df4a2SClaudio Imbrenda */ 838190df4a2SClaudio Imbrenda static int kvm_s390_vm_start_migration(struct kvm *kvm) 839190df4a2SClaudio Imbrenda { 840190df4a2SClaudio Imbrenda struct kvm_s390_migration_state *mgs; 841190df4a2SClaudio Imbrenda struct kvm_memory_slot *ms; 842190df4a2SClaudio Imbrenda /* should be the only one */ 843190df4a2SClaudio Imbrenda struct kvm_memslots *slots; 844190df4a2SClaudio Imbrenda unsigned long ram_pages; 845190df4a2SClaudio Imbrenda int slotnr; 846190df4a2SClaudio Imbrenda 847190df4a2SClaudio Imbrenda /* migration mode already enabled */ 848190df4a2SClaudio Imbrenda if (kvm->arch.migration_state) 849190df4a2SClaudio Imbrenda return 0; 850190df4a2SClaudio Imbrenda 851190df4a2SClaudio Imbrenda slots = kvm_memslots(kvm); 852190df4a2SClaudio Imbrenda if (!slots || !slots->used_slots) 853190df4a2SClaudio Imbrenda return -EINVAL; 854190df4a2SClaudio Imbrenda 855190df4a2SClaudio Imbrenda mgs = kzalloc(sizeof(*mgs), GFP_KERNEL); 856190df4a2SClaudio Imbrenda if (!mgs) 857190df4a2SClaudio Imbrenda return -ENOMEM; 858190df4a2SClaudio Imbrenda kvm->arch.migration_state = mgs; 859190df4a2SClaudio Imbrenda 860190df4a2SClaudio Imbrenda if (kvm->arch.use_cmma) { 861190df4a2SClaudio Imbrenda /* 86232aa144fSChristian Borntraeger * Get the first slot. They are reverse sorted by base_gfn, so 86332aa144fSChristian Borntraeger * the first slot is also the one at the end of the address 86432aa144fSChristian Borntraeger * space. We have verified above that at least one slot is 86532aa144fSChristian Borntraeger * present. 866190df4a2SClaudio Imbrenda */ 86732aa144fSChristian Borntraeger ms = slots->memslots; 868190df4a2SClaudio Imbrenda /* round up so we only use full longs */ 869190df4a2SClaudio Imbrenda ram_pages = roundup(ms->base_gfn + ms->npages, BITS_PER_LONG); 870190df4a2SClaudio Imbrenda /* allocate enough bytes to store all the bits */ 871190df4a2SClaudio Imbrenda mgs->pgste_bitmap = vmalloc(ram_pages / 8); 872190df4a2SClaudio Imbrenda if (!mgs->pgste_bitmap) { 873190df4a2SClaudio Imbrenda kfree(mgs); 874190df4a2SClaudio Imbrenda kvm->arch.migration_state = NULL; 875190df4a2SClaudio Imbrenda return -ENOMEM; 876190df4a2SClaudio Imbrenda } 877190df4a2SClaudio Imbrenda 878190df4a2SClaudio Imbrenda mgs->bitmap_size = ram_pages; 879190df4a2SClaudio Imbrenda atomic64_set(&mgs->dirty_pages, ram_pages); 880190df4a2SClaudio Imbrenda /* mark all the pages in active slots as dirty */ 881190df4a2SClaudio Imbrenda for (slotnr = 0; slotnr < slots->used_slots; slotnr++) { 882190df4a2SClaudio Imbrenda ms = slots->memslots + slotnr; 883190df4a2SClaudio Imbrenda bitmap_set(mgs->pgste_bitmap, ms->base_gfn, ms->npages); 884190df4a2SClaudio Imbrenda } 885190df4a2SClaudio Imbrenda 886190df4a2SClaudio Imbrenda kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION); 887190df4a2SClaudio Imbrenda } 888190df4a2SClaudio Imbrenda return 0; 889190df4a2SClaudio Imbrenda } 890190df4a2SClaudio Imbrenda 891190df4a2SClaudio Imbrenda /* 8921de1ea7eSChristian Borntraeger * Must be called with kvm->slots_lock to avoid races with ourselves and 893190df4a2SClaudio Imbrenda * kvm_s390_vm_start_migration. 894190df4a2SClaudio Imbrenda */ 895190df4a2SClaudio Imbrenda static int kvm_s390_vm_stop_migration(struct kvm *kvm) 896190df4a2SClaudio Imbrenda { 897190df4a2SClaudio Imbrenda struct kvm_s390_migration_state *mgs; 898190df4a2SClaudio Imbrenda 899190df4a2SClaudio Imbrenda /* migration mode already disabled */ 900190df4a2SClaudio Imbrenda if (!kvm->arch.migration_state) 901190df4a2SClaudio Imbrenda return 0; 902190df4a2SClaudio Imbrenda mgs = kvm->arch.migration_state; 903190df4a2SClaudio Imbrenda kvm->arch.migration_state = NULL; 904190df4a2SClaudio Imbrenda 905190df4a2SClaudio Imbrenda if (kvm->arch.use_cmma) { 906190df4a2SClaudio Imbrenda kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION); 9071de1ea7eSChristian Borntraeger /* We have to wait for the essa emulation to finish */ 9081de1ea7eSChristian Borntraeger synchronize_srcu(&kvm->srcu); 909190df4a2SClaudio Imbrenda vfree(mgs->pgste_bitmap); 910190df4a2SClaudio Imbrenda } 911190df4a2SClaudio Imbrenda kfree(mgs); 912190df4a2SClaudio Imbrenda return 0; 913190df4a2SClaudio Imbrenda } 914190df4a2SClaudio Imbrenda 915190df4a2SClaudio Imbrenda static int kvm_s390_vm_set_migration(struct kvm *kvm, 916190df4a2SClaudio Imbrenda struct kvm_device_attr *attr) 917190df4a2SClaudio Imbrenda { 9181de1ea7eSChristian Borntraeger int res = -ENXIO; 919190df4a2SClaudio Imbrenda 9201de1ea7eSChristian Borntraeger mutex_lock(&kvm->slots_lock); 921190df4a2SClaudio Imbrenda switch (attr->attr) { 922190df4a2SClaudio Imbrenda case KVM_S390_VM_MIGRATION_START: 923190df4a2SClaudio Imbrenda res = kvm_s390_vm_start_migration(kvm); 924190df4a2SClaudio Imbrenda break; 925190df4a2SClaudio Imbrenda case KVM_S390_VM_MIGRATION_STOP: 926190df4a2SClaudio Imbrenda res = kvm_s390_vm_stop_migration(kvm); 927190df4a2SClaudio Imbrenda break; 928190df4a2SClaudio Imbrenda default: 929190df4a2SClaudio Imbrenda break; 930190df4a2SClaudio Imbrenda } 9311de1ea7eSChristian Borntraeger mutex_unlock(&kvm->slots_lock); 932190df4a2SClaudio Imbrenda 933190df4a2SClaudio Imbrenda return res; 934190df4a2SClaudio Imbrenda } 935190df4a2SClaudio Imbrenda 936190df4a2SClaudio Imbrenda static int kvm_s390_vm_get_migration(struct kvm *kvm, 937190df4a2SClaudio Imbrenda struct kvm_device_attr *attr) 938190df4a2SClaudio Imbrenda { 939190df4a2SClaudio Imbrenda u64 mig = (kvm->arch.migration_state != NULL); 940190df4a2SClaudio Imbrenda 941190df4a2SClaudio Imbrenda if (attr->attr != KVM_S390_VM_MIGRATION_STATUS) 942190df4a2SClaudio Imbrenda return -ENXIO; 943190df4a2SClaudio Imbrenda 944190df4a2SClaudio Imbrenda if (copy_to_user((void __user *)attr->addr, &mig, sizeof(mig))) 945190df4a2SClaudio Imbrenda return -EFAULT; 946190df4a2SClaudio Imbrenda return 0; 947190df4a2SClaudio Imbrenda } 948190df4a2SClaudio Imbrenda 9498fa1696eSCollin L. Walling static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr) 9508fa1696eSCollin L. Walling { 9518fa1696eSCollin L. Walling struct kvm_s390_vm_tod_clock gtod; 9528fa1696eSCollin L. Walling 9538fa1696eSCollin L. Walling if (copy_from_user(>od, (void __user *)attr->addr, sizeof(gtod))) 9548fa1696eSCollin L. Walling return -EFAULT; 9558fa1696eSCollin L. Walling 9560e7def5fSDavid Hildenbrand if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx) 9578fa1696eSCollin L. Walling return -EINVAL; 9580e7def5fSDavid Hildenbrand kvm_s390_set_tod_clock(kvm, >od); 9598fa1696eSCollin L. Walling 9608fa1696eSCollin L. Walling VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx", 9618fa1696eSCollin L. Walling gtod.epoch_idx, gtod.tod); 9628fa1696eSCollin L. Walling 9638fa1696eSCollin L. Walling return 0; 9648fa1696eSCollin L. Walling } 9658fa1696eSCollin L. Walling 96672f25020SJason J. Herne static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr) 96772f25020SJason J. Herne { 96872f25020SJason J. Herne u8 gtod_high; 96972f25020SJason J. Herne 97072f25020SJason J. Herne if (copy_from_user(>od_high, (void __user *)attr->addr, 97172f25020SJason J. Herne sizeof(gtod_high))) 97272f25020SJason J. Herne return -EFAULT; 97372f25020SJason J. Herne 97472f25020SJason J. Herne if (gtod_high != 0) 97572f25020SJason J. Herne return -EINVAL; 97658c383c6SChristian Borntraeger VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x", gtod_high); 97772f25020SJason J. Herne 97872f25020SJason J. Herne return 0; 97972f25020SJason J. Herne } 98072f25020SJason J. Herne 98172f25020SJason J. Herne static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr) 98272f25020SJason J. Herne { 9830e7def5fSDavid Hildenbrand struct kvm_s390_vm_tod_clock gtod = { 0 }; 98472f25020SJason J. Herne 9850e7def5fSDavid Hildenbrand if (copy_from_user(>od.tod, (void __user *)attr->addr, 9860e7def5fSDavid Hildenbrand sizeof(gtod.tod))) 98772f25020SJason J. Herne return -EFAULT; 98872f25020SJason J. Herne 9890e7def5fSDavid Hildenbrand kvm_s390_set_tod_clock(kvm, >od); 9900e7def5fSDavid Hildenbrand VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod); 99172f25020SJason J. Herne return 0; 99272f25020SJason J. Herne } 99372f25020SJason J. Herne 99472f25020SJason J. Herne static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr) 99572f25020SJason J. Herne { 99672f25020SJason J. Herne int ret; 99772f25020SJason J. Herne 99872f25020SJason J. Herne if (attr->flags) 99972f25020SJason J. Herne return -EINVAL; 100072f25020SJason J. Herne 100172f25020SJason J. Herne switch (attr->attr) { 10028fa1696eSCollin L. Walling case KVM_S390_VM_TOD_EXT: 10038fa1696eSCollin L. Walling ret = kvm_s390_set_tod_ext(kvm, attr); 10048fa1696eSCollin L. Walling break; 100572f25020SJason J. Herne case KVM_S390_VM_TOD_HIGH: 100672f25020SJason J. Herne ret = kvm_s390_set_tod_high(kvm, attr); 100772f25020SJason J. Herne break; 100872f25020SJason J. Herne case KVM_S390_VM_TOD_LOW: 100972f25020SJason J. Herne ret = kvm_s390_set_tod_low(kvm, attr); 101072f25020SJason J. Herne break; 101172f25020SJason J. Herne default: 101272f25020SJason J. Herne ret = -ENXIO; 101372f25020SJason J. Herne break; 101472f25020SJason J. Herne } 101572f25020SJason J. Herne return ret; 101672f25020SJason J. Herne } 101772f25020SJason J. Herne 10188fa1696eSCollin L. Walling static void kvm_s390_get_tod_clock_ext(struct kvm *kvm, 10198fa1696eSCollin L. Walling struct kvm_s390_vm_tod_clock *gtod) 10208fa1696eSCollin L. Walling { 10218fa1696eSCollin L. Walling struct kvm_s390_tod_clock_ext htod; 10228fa1696eSCollin L. Walling 10238fa1696eSCollin L. Walling preempt_disable(); 10248fa1696eSCollin L. Walling 10258fa1696eSCollin L. Walling get_tod_clock_ext((char *)&htod); 10268fa1696eSCollin L. Walling 10278fa1696eSCollin L. Walling gtod->tod = htod.tod + kvm->arch.epoch; 10288fa1696eSCollin L. Walling gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx; 10298fa1696eSCollin L. Walling 10308fa1696eSCollin L. Walling if (gtod->tod < htod.tod) 10318fa1696eSCollin L. Walling gtod->epoch_idx += 1; 10328fa1696eSCollin L. Walling 10338fa1696eSCollin L. Walling preempt_enable(); 10348fa1696eSCollin L. Walling } 10358fa1696eSCollin L. Walling 10368fa1696eSCollin L. Walling static int kvm_s390_get_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr) 10378fa1696eSCollin L. Walling { 10388fa1696eSCollin L. Walling struct kvm_s390_vm_tod_clock gtod; 10398fa1696eSCollin L. Walling 10408fa1696eSCollin L. Walling memset(>od, 0, sizeof(gtod)); 10418fa1696eSCollin L. Walling 10428fa1696eSCollin L. Walling if (test_kvm_facility(kvm, 139)) 10438fa1696eSCollin L. Walling kvm_s390_get_tod_clock_ext(kvm, >od); 10448fa1696eSCollin L. Walling else 10458fa1696eSCollin L. Walling gtod.tod = kvm_s390_get_tod_clock_fast(kvm); 10468fa1696eSCollin L. Walling 10478fa1696eSCollin L. Walling if (copy_to_user((void __user *)attr->addr, >od, sizeof(gtod))) 10488fa1696eSCollin L. Walling return -EFAULT; 10498fa1696eSCollin L. Walling 10508fa1696eSCollin L. Walling VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x, TOD base: 0x%llx", 10518fa1696eSCollin L. Walling gtod.epoch_idx, gtod.tod); 10528fa1696eSCollin L. Walling return 0; 10538fa1696eSCollin L. Walling } 10548fa1696eSCollin L. Walling 105572f25020SJason J. Herne static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr) 105672f25020SJason J. Herne { 105772f25020SJason J. Herne u8 gtod_high = 0; 105872f25020SJason J. Herne 105972f25020SJason J. Herne if (copy_to_user((void __user *)attr->addr, >od_high, 106072f25020SJason J. Herne sizeof(gtod_high))) 106172f25020SJason J. Herne return -EFAULT; 106258c383c6SChristian Borntraeger VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x", gtod_high); 106372f25020SJason J. Herne 106472f25020SJason J. Herne return 0; 106572f25020SJason J. Herne } 106672f25020SJason J. Herne 106772f25020SJason J. Herne static int kvm_s390_get_tod_low(struct kvm *kvm, struct kvm_device_attr *attr) 106872f25020SJason J. Herne { 10695a3d883aSDavid Hildenbrand u64 gtod; 107072f25020SJason J. Herne 107160417fccSDavid Hildenbrand gtod = kvm_s390_get_tod_clock_fast(kvm); 107272f25020SJason J. Herne if (copy_to_user((void __user *)attr->addr, >od, sizeof(gtod))) 107372f25020SJason J. Herne return -EFAULT; 107458c383c6SChristian Borntraeger VM_EVENT(kvm, 3, "QUERY: TOD base: 0x%llx", gtod); 107572f25020SJason J. Herne 107672f25020SJason J. Herne return 0; 107772f25020SJason J. Herne } 107872f25020SJason J. Herne 107972f25020SJason J. Herne static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr) 108072f25020SJason J. Herne { 108172f25020SJason J. Herne int ret; 108272f25020SJason J. Herne 108372f25020SJason J. Herne if (attr->flags) 108472f25020SJason J. Herne return -EINVAL; 108572f25020SJason J. Herne 108672f25020SJason J. Herne switch (attr->attr) { 10878fa1696eSCollin L. Walling case KVM_S390_VM_TOD_EXT: 10888fa1696eSCollin L. Walling ret = kvm_s390_get_tod_ext(kvm, attr); 10898fa1696eSCollin L. Walling break; 109072f25020SJason J. Herne case KVM_S390_VM_TOD_HIGH: 109172f25020SJason J. Herne ret = kvm_s390_get_tod_high(kvm, attr); 109272f25020SJason J. Herne break; 109372f25020SJason J. Herne case KVM_S390_VM_TOD_LOW: 109472f25020SJason J. Herne ret = kvm_s390_get_tod_low(kvm, attr); 109572f25020SJason J. Herne break; 109672f25020SJason J. Herne default: 109772f25020SJason J. Herne ret = -ENXIO; 109872f25020SJason J. Herne break; 109972f25020SJason J. Herne } 110072f25020SJason J. Herne return ret; 110172f25020SJason J. Herne } 110272f25020SJason J. Herne 1103658b6edaSMichael Mueller static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr) 1104658b6edaSMichael Mueller { 1105658b6edaSMichael Mueller struct kvm_s390_vm_cpu_processor *proc; 1106053dd230SDavid Hildenbrand u16 lowest_ibc, unblocked_ibc; 1107658b6edaSMichael Mueller int ret = 0; 1108658b6edaSMichael Mueller 1109658b6edaSMichael Mueller mutex_lock(&kvm->lock); 1110a03825bbSPaolo Bonzini if (kvm->created_vcpus) { 1111658b6edaSMichael Mueller ret = -EBUSY; 1112658b6edaSMichael Mueller goto out; 1113658b6edaSMichael Mueller } 1114658b6edaSMichael Mueller proc = kzalloc(sizeof(*proc), GFP_KERNEL); 1115658b6edaSMichael Mueller if (!proc) { 1116658b6edaSMichael Mueller ret = -ENOMEM; 1117658b6edaSMichael Mueller goto out; 1118658b6edaSMichael Mueller } 1119658b6edaSMichael Mueller if (!copy_from_user(proc, (void __user *)attr->addr, 1120658b6edaSMichael Mueller sizeof(*proc))) { 11219bb0ec09SDavid Hildenbrand kvm->arch.model.cpuid = proc->cpuid; 1122053dd230SDavid Hildenbrand lowest_ibc = sclp.ibc >> 16 & 0xfff; 1123053dd230SDavid Hildenbrand unblocked_ibc = sclp.ibc & 0xfff; 11240487c44dSDavid Hildenbrand if (lowest_ibc && proc->ibc) { 1125053dd230SDavid Hildenbrand if (proc->ibc > unblocked_ibc) 1126053dd230SDavid Hildenbrand kvm->arch.model.ibc = unblocked_ibc; 1127053dd230SDavid Hildenbrand else if (proc->ibc < lowest_ibc) 1128053dd230SDavid Hildenbrand kvm->arch.model.ibc = lowest_ibc; 1129053dd230SDavid Hildenbrand else 1130658b6edaSMichael Mueller kvm->arch.model.ibc = proc->ibc; 1131053dd230SDavid Hildenbrand } 1132c54f0d6aSDavid Hildenbrand memcpy(kvm->arch.model.fac_list, proc->fac_list, 1133658b6edaSMichael Mueller S390_ARCH_FAC_LIST_SIZE_BYTE); 1134a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "SET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx", 1135a8c39dd7SChristian Borntraeger kvm->arch.model.ibc, 1136a8c39dd7SChristian Borntraeger kvm->arch.model.cpuid); 1137a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "SET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx", 1138a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[0], 1139a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[1], 1140a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[2]); 1141658b6edaSMichael Mueller } else 1142658b6edaSMichael Mueller ret = -EFAULT; 1143658b6edaSMichael Mueller kfree(proc); 1144658b6edaSMichael Mueller out: 1145658b6edaSMichael Mueller mutex_unlock(&kvm->lock); 1146658b6edaSMichael Mueller return ret; 1147658b6edaSMichael Mueller } 1148658b6edaSMichael Mueller 114915c9705fSDavid Hildenbrand static int kvm_s390_set_processor_feat(struct kvm *kvm, 115015c9705fSDavid Hildenbrand struct kvm_device_attr *attr) 115115c9705fSDavid Hildenbrand { 115215c9705fSDavid Hildenbrand struct kvm_s390_vm_cpu_feat data; 115315c9705fSDavid Hildenbrand 115415c9705fSDavid Hildenbrand if (copy_from_user(&data, (void __user *)attr->addr, sizeof(data))) 115515c9705fSDavid Hildenbrand return -EFAULT; 115615c9705fSDavid Hildenbrand if (!bitmap_subset((unsigned long *) data.feat, 115715c9705fSDavid Hildenbrand kvm_s390_available_cpu_feat, 115815c9705fSDavid Hildenbrand KVM_S390_VM_CPU_FEAT_NR_BITS)) 115915c9705fSDavid Hildenbrand return -EINVAL; 116015c9705fSDavid Hildenbrand 116115c9705fSDavid Hildenbrand mutex_lock(&kvm->lock); 11622f8311c9SChristian Borntraeger if (kvm->created_vcpus) { 11632f8311c9SChristian Borntraeger mutex_unlock(&kvm->lock); 11642f8311c9SChristian Borntraeger return -EBUSY; 11652f8311c9SChristian Borntraeger } 116615c9705fSDavid Hildenbrand bitmap_copy(kvm->arch.cpu_feat, (unsigned long *) data.feat, 116715c9705fSDavid Hildenbrand KVM_S390_VM_CPU_FEAT_NR_BITS); 116815c9705fSDavid Hildenbrand mutex_unlock(&kvm->lock); 11692f8311c9SChristian Borntraeger VM_EVENT(kvm, 3, "SET: guest feat: 0x%16.16llx.0x%16.16llx.0x%16.16llx", 11702f8311c9SChristian Borntraeger data.feat[0], 11712f8311c9SChristian Borntraeger data.feat[1], 11722f8311c9SChristian Borntraeger data.feat[2]); 11732f8311c9SChristian Borntraeger return 0; 117415c9705fSDavid Hildenbrand } 117515c9705fSDavid Hildenbrand 11760a763c78SDavid Hildenbrand static int kvm_s390_set_processor_subfunc(struct kvm *kvm, 11770a763c78SDavid Hildenbrand struct kvm_device_attr *attr) 11780a763c78SDavid Hildenbrand { 11790a763c78SDavid Hildenbrand /* 11800a763c78SDavid Hildenbrand * Once supported by kernel + hw, we have to store the subfunctions 11810a763c78SDavid Hildenbrand * in kvm->arch and remember that user space configured them. 11820a763c78SDavid Hildenbrand */ 11830a763c78SDavid Hildenbrand return -ENXIO; 11840a763c78SDavid Hildenbrand } 11850a763c78SDavid Hildenbrand 1186658b6edaSMichael Mueller static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) 1187658b6edaSMichael Mueller { 1188658b6edaSMichael Mueller int ret = -ENXIO; 1189658b6edaSMichael Mueller 1190658b6edaSMichael Mueller switch (attr->attr) { 1191658b6edaSMichael Mueller case KVM_S390_VM_CPU_PROCESSOR: 1192658b6edaSMichael Mueller ret = kvm_s390_set_processor(kvm, attr); 1193658b6edaSMichael Mueller break; 119415c9705fSDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_FEAT: 119515c9705fSDavid Hildenbrand ret = kvm_s390_set_processor_feat(kvm, attr); 119615c9705fSDavid Hildenbrand break; 11970a763c78SDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC: 11980a763c78SDavid Hildenbrand ret = kvm_s390_set_processor_subfunc(kvm, attr); 11990a763c78SDavid Hildenbrand break; 1200658b6edaSMichael Mueller } 1201658b6edaSMichael Mueller return ret; 1202658b6edaSMichael Mueller } 1203658b6edaSMichael Mueller 1204658b6edaSMichael Mueller static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr) 1205658b6edaSMichael Mueller { 1206658b6edaSMichael Mueller struct kvm_s390_vm_cpu_processor *proc; 1207658b6edaSMichael Mueller int ret = 0; 1208658b6edaSMichael Mueller 1209658b6edaSMichael Mueller proc = kzalloc(sizeof(*proc), GFP_KERNEL); 1210658b6edaSMichael Mueller if (!proc) { 1211658b6edaSMichael Mueller ret = -ENOMEM; 1212658b6edaSMichael Mueller goto out; 1213658b6edaSMichael Mueller } 12149bb0ec09SDavid Hildenbrand proc->cpuid = kvm->arch.model.cpuid; 1215658b6edaSMichael Mueller proc->ibc = kvm->arch.model.ibc; 1216c54f0d6aSDavid Hildenbrand memcpy(&proc->fac_list, kvm->arch.model.fac_list, 1217c54f0d6aSDavid Hildenbrand S390_ARCH_FAC_LIST_SIZE_BYTE); 1218a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "GET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx", 1219a8c39dd7SChristian Borntraeger kvm->arch.model.ibc, 1220a8c39dd7SChristian Borntraeger kvm->arch.model.cpuid); 1221a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "GET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx", 1222a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[0], 1223a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[1], 1224a8c39dd7SChristian Borntraeger kvm->arch.model.fac_list[2]); 1225658b6edaSMichael Mueller if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc))) 1226658b6edaSMichael Mueller ret = -EFAULT; 1227658b6edaSMichael Mueller kfree(proc); 1228658b6edaSMichael Mueller out: 1229658b6edaSMichael Mueller return ret; 1230658b6edaSMichael Mueller } 1231658b6edaSMichael Mueller 1232658b6edaSMichael Mueller static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr) 1233658b6edaSMichael Mueller { 1234658b6edaSMichael Mueller struct kvm_s390_vm_cpu_machine *mach; 1235658b6edaSMichael Mueller int ret = 0; 1236658b6edaSMichael Mueller 1237658b6edaSMichael Mueller mach = kzalloc(sizeof(*mach), GFP_KERNEL); 1238658b6edaSMichael Mueller if (!mach) { 1239658b6edaSMichael Mueller ret = -ENOMEM; 1240658b6edaSMichael Mueller goto out; 1241658b6edaSMichael Mueller } 1242658b6edaSMichael Mueller get_cpu_id((struct cpuid *) &mach->cpuid); 124337c5f6c8SDavid Hildenbrand mach->ibc = sclp.ibc; 1244c54f0d6aSDavid Hildenbrand memcpy(&mach->fac_mask, kvm->arch.model.fac_mask, 1245981467c9SMichael Mueller S390_ARCH_FAC_LIST_SIZE_BYTE); 1246658b6edaSMichael Mueller memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list, 124704478197SChristian Borntraeger sizeof(S390_lowcore.stfle_fac_list)); 1248a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "GET: host ibc: 0x%4.4x, host cpuid: 0x%16.16llx", 1249a8c39dd7SChristian Borntraeger kvm->arch.model.ibc, 1250a8c39dd7SChristian Borntraeger kvm->arch.model.cpuid); 1251a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "GET: host facmask: 0x%16.16llx.%16.16llx.%16.16llx", 1252a8c39dd7SChristian Borntraeger mach->fac_mask[0], 1253a8c39dd7SChristian Borntraeger mach->fac_mask[1], 1254a8c39dd7SChristian Borntraeger mach->fac_mask[2]); 1255a8c39dd7SChristian Borntraeger VM_EVENT(kvm, 3, "GET: host faclist: 0x%16.16llx.%16.16llx.%16.16llx", 1256a8c39dd7SChristian Borntraeger mach->fac_list[0], 1257a8c39dd7SChristian Borntraeger mach->fac_list[1], 1258a8c39dd7SChristian Borntraeger mach->fac_list[2]); 1259658b6edaSMichael Mueller if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach))) 1260658b6edaSMichael Mueller ret = -EFAULT; 1261658b6edaSMichael Mueller kfree(mach); 1262658b6edaSMichael Mueller out: 1263658b6edaSMichael Mueller return ret; 1264658b6edaSMichael Mueller } 1265658b6edaSMichael Mueller 126615c9705fSDavid Hildenbrand static int kvm_s390_get_processor_feat(struct kvm *kvm, 126715c9705fSDavid Hildenbrand struct kvm_device_attr *attr) 126815c9705fSDavid Hildenbrand { 126915c9705fSDavid Hildenbrand struct kvm_s390_vm_cpu_feat data; 127015c9705fSDavid Hildenbrand 127115c9705fSDavid Hildenbrand bitmap_copy((unsigned long *) data.feat, kvm->arch.cpu_feat, 127215c9705fSDavid Hildenbrand KVM_S390_VM_CPU_FEAT_NR_BITS); 127315c9705fSDavid Hildenbrand if (copy_to_user((void __user *)attr->addr, &data, sizeof(data))) 127415c9705fSDavid Hildenbrand return -EFAULT; 12752f8311c9SChristian Borntraeger VM_EVENT(kvm, 3, "GET: guest feat: 0x%16.16llx.0x%16.16llx.0x%16.16llx", 12762f8311c9SChristian Borntraeger data.feat[0], 12772f8311c9SChristian Borntraeger data.feat[1], 12782f8311c9SChristian Borntraeger data.feat[2]); 127915c9705fSDavid Hildenbrand return 0; 128015c9705fSDavid Hildenbrand } 128115c9705fSDavid Hildenbrand 128215c9705fSDavid Hildenbrand static int kvm_s390_get_machine_feat(struct kvm *kvm, 128315c9705fSDavid Hildenbrand struct kvm_device_attr *attr) 128415c9705fSDavid Hildenbrand { 128515c9705fSDavid Hildenbrand struct kvm_s390_vm_cpu_feat data; 128615c9705fSDavid Hildenbrand 128715c9705fSDavid Hildenbrand bitmap_copy((unsigned long *) data.feat, 128815c9705fSDavid Hildenbrand kvm_s390_available_cpu_feat, 128915c9705fSDavid Hildenbrand KVM_S390_VM_CPU_FEAT_NR_BITS); 129015c9705fSDavid Hildenbrand if (copy_to_user((void __user *)attr->addr, &data, sizeof(data))) 129115c9705fSDavid Hildenbrand return -EFAULT; 12922f8311c9SChristian Borntraeger VM_EVENT(kvm, 3, "GET: host feat: 0x%16.16llx.0x%16.16llx.0x%16.16llx", 12932f8311c9SChristian Borntraeger data.feat[0], 12942f8311c9SChristian Borntraeger data.feat[1], 12952f8311c9SChristian Borntraeger data.feat[2]); 129615c9705fSDavid Hildenbrand return 0; 129715c9705fSDavid Hildenbrand } 129815c9705fSDavid Hildenbrand 12990a763c78SDavid Hildenbrand static int kvm_s390_get_processor_subfunc(struct kvm *kvm, 13000a763c78SDavid Hildenbrand struct kvm_device_attr *attr) 13010a763c78SDavid Hildenbrand { 13020a763c78SDavid Hildenbrand /* 13030a763c78SDavid Hildenbrand * Once we can actually configure subfunctions (kernel + hw support), 13040a763c78SDavid Hildenbrand * we have to check if they were already set by user space, if so copy 13050a763c78SDavid Hildenbrand * them from kvm->arch. 13060a763c78SDavid Hildenbrand */ 13070a763c78SDavid Hildenbrand return -ENXIO; 13080a763c78SDavid Hildenbrand } 13090a763c78SDavid Hildenbrand 13100a763c78SDavid Hildenbrand static int kvm_s390_get_machine_subfunc(struct kvm *kvm, 13110a763c78SDavid Hildenbrand struct kvm_device_attr *attr) 13120a763c78SDavid Hildenbrand { 13130a763c78SDavid Hildenbrand if (copy_to_user((void __user *)attr->addr, &kvm_s390_available_subfunc, 13140a763c78SDavid Hildenbrand sizeof(struct kvm_s390_vm_cpu_subfunc))) 13150a763c78SDavid Hildenbrand return -EFAULT; 13160a763c78SDavid Hildenbrand return 0; 13170a763c78SDavid Hildenbrand } 1318658b6edaSMichael Mueller static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr) 1319658b6edaSMichael Mueller { 1320658b6edaSMichael Mueller int ret = -ENXIO; 1321658b6edaSMichael Mueller 1322658b6edaSMichael Mueller switch (attr->attr) { 1323658b6edaSMichael Mueller case KVM_S390_VM_CPU_PROCESSOR: 1324658b6edaSMichael Mueller ret = kvm_s390_get_processor(kvm, attr); 1325658b6edaSMichael Mueller break; 1326658b6edaSMichael Mueller case KVM_S390_VM_CPU_MACHINE: 1327658b6edaSMichael Mueller ret = kvm_s390_get_machine(kvm, attr); 1328658b6edaSMichael Mueller break; 132915c9705fSDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_FEAT: 133015c9705fSDavid Hildenbrand ret = kvm_s390_get_processor_feat(kvm, attr); 133115c9705fSDavid Hildenbrand break; 133215c9705fSDavid Hildenbrand case KVM_S390_VM_CPU_MACHINE_FEAT: 133315c9705fSDavid Hildenbrand ret = kvm_s390_get_machine_feat(kvm, attr); 133415c9705fSDavid Hildenbrand break; 13350a763c78SDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC: 13360a763c78SDavid Hildenbrand ret = kvm_s390_get_processor_subfunc(kvm, attr); 13370a763c78SDavid Hildenbrand break; 13380a763c78SDavid Hildenbrand case KVM_S390_VM_CPU_MACHINE_SUBFUNC: 13390a763c78SDavid Hildenbrand ret = kvm_s390_get_machine_subfunc(kvm, attr); 13400a763c78SDavid Hildenbrand break; 1341658b6edaSMichael Mueller } 1342658b6edaSMichael Mueller return ret; 1343658b6edaSMichael Mueller } 1344658b6edaSMichael Mueller 1345f2061656SDominik Dingel static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr) 1346f2061656SDominik Dingel { 1347f2061656SDominik Dingel int ret; 1348f2061656SDominik Dingel 1349f2061656SDominik Dingel switch (attr->group) { 13504f718eabSDominik Dingel case KVM_S390_VM_MEM_CTRL: 13518c0a7ce6SDominik Dingel ret = kvm_s390_set_mem_control(kvm, attr); 13524f718eabSDominik Dingel break; 135372f25020SJason J. Herne case KVM_S390_VM_TOD: 135472f25020SJason J. Herne ret = kvm_s390_set_tod(kvm, attr); 135572f25020SJason J. Herne break; 1356658b6edaSMichael Mueller case KVM_S390_VM_CPU_MODEL: 1357658b6edaSMichael Mueller ret = kvm_s390_set_cpu_model(kvm, attr); 1358658b6edaSMichael Mueller break; 1359a374e892STony Krowiak case KVM_S390_VM_CRYPTO: 1360a374e892STony Krowiak ret = kvm_s390_vm_set_crypto(kvm, attr); 1361a374e892STony Krowiak break; 1362190df4a2SClaudio Imbrenda case KVM_S390_VM_MIGRATION: 1363190df4a2SClaudio Imbrenda ret = kvm_s390_vm_set_migration(kvm, attr); 1364190df4a2SClaudio Imbrenda break; 1365f2061656SDominik Dingel default: 1366f2061656SDominik Dingel ret = -ENXIO; 1367f2061656SDominik Dingel break; 1368f2061656SDominik Dingel } 1369f2061656SDominik Dingel 1370f2061656SDominik Dingel return ret; 1371f2061656SDominik Dingel } 1372f2061656SDominik Dingel 1373f2061656SDominik Dingel static int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr) 1374f2061656SDominik Dingel { 13758c0a7ce6SDominik Dingel int ret; 13768c0a7ce6SDominik Dingel 13778c0a7ce6SDominik Dingel switch (attr->group) { 13788c0a7ce6SDominik Dingel case KVM_S390_VM_MEM_CTRL: 13798c0a7ce6SDominik Dingel ret = kvm_s390_get_mem_control(kvm, attr); 13808c0a7ce6SDominik Dingel break; 138172f25020SJason J. Herne case KVM_S390_VM_TOD: 138272f25020SJason J. Herne ret = kvm_s390_get_tod(kvm, attr); 138372f25020SJason J. Herne break; 1384658b6edaSMichael Mueller case KVM_S390_VM_CPU_MODEL: 1385658b6edaSMichael Mueller ret = kvm_s390_get_cpu_model(kvm, attr); 1386658b6edaSMichael Mueller break; 1387190df4a2SClaudio Imbrenda case KVM_S390_VM_MIGRATION: 1388190df4a2SClaudio Imbrenda ret = kvm_s390_vm_get_migration(kvm, attr); 1389190df4a2SClaudio Imbrenda break; 13908c0a7ce6SDominik Dingel default: 13918c0a7ce6SDominik Dingel ret = -ENXIO; 13928c0a7ce6SDominik Dingel break; 13938c0a7ce6SDominik Dingel } 13948c0a7ce6SDominik Dingel 13958c0a7ce6SDominik Dingel return ret; 1396f2061656SDominik Dingel } 1397f2061656SDominik Dingel 1398f2061656SDominik Dingel static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr) 1399f2061656SDominik Dingel { 1400f2061656SDominik Dingel int ret; 1401f2061656SDominik Dingel 1402f2061656SDominik Dingel switch (attr->group) { 14034f718eabSDominik Dingel case KVM_S390_VM_MEM_CTRL: 14044f718eabSDominik Dingel switch (attr->attr) { 14054f718eabSDominik Dingel case KVM_S390_VM_MEM_ENABLE_CMMA: 14064f718eabSDominik Dingel case KVM_S390_VM_MEM_CLR_CMMA: 1407f9cbd9b0SDavid Hildenbrand ret = sclp.has_cmma ? 0 : -ENXIO; 1408f9cbd9b0SDavid Hildenbrand break; 14098c0a7ce6SDominik Dingel case KVM_S390_VM_MEM_LIMIT_SIZE: 14104f718eabSDominik Dingel ret = 0; 14114f718eabSDominik Dingel break; 14124f718eabSDominik Dingel default: 14134f718eabSDominik Dingel ret = -ENXIO; 14144f718eabSDominik Dingel break; 14154f718eabSDominik Dingel } 14164f718eabSDominik Dingel break; 141772f25020SJason J. Herne case KVM_S390_VM_TOD: 141872f25020SJason J. Herne switch (attr->attr) { 141972f25020SJason J. Herne case KVM_S390_VM_TOD_LOW: 142072f25020SJason J. Herne case KVM_S390_VM_TOD_HIGH: 142172f25020SJason J. Herne ret = 0; 142272f25020SJason J. Herne break; 142372f25020SJason J. Herne default: 142472f25020SJason J. Herne ret = -ENXIO; 142572f25020SJason J. Herne break; 142672f25020SJason J. Herne } 142772f25020SJason J. Herne break; 1428658b6edaSMichael Mueller case KVM_S390_VM_CPU_MODEL: 1429658b6edaSMichael Mueller switch (attr->attr) { 1430658b6edaSMichael Mueller case KVM_S390_VM_CPU_PROCESSOR: 1431658b6edaSMichael Mueller case KVM_S390_VM_CPU_MACHINE: 143215c9705fSDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_FEAT: 143315c9705fSDavid Hildenbrand case KVM_S390_VM_CPU_MACHINE_FEAT: 14340a763c78SDavid Hildenbrand case KVM_S390_VM_CPU_MACHINE_SUBFUNC: 1435658b6edaSMichael Mueller ret = 0; 1436658b6edaSMichael Mueller break; 14370a763c78SDavid Hildenbrand /* configuring subfunctions is not supported yet */ 14380a763c78SDavid Hildenbrand case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC: 1439658b6edaSMichael Mueller default: 1440658b6edaSMichael Mueller ret = -ENXIO; 1441658b6edaSMichael Mueller break; 1442658b6edaSMichael Mueller } 1443658b6edaSMichael Mueller break; 1444a374e892STony Krowiak case KVM_S390_VM_CRYPTO: 1445a374e892STony Krowiak switch (attr->attr) { 1446a374e892STony Krowiak case KVM_S390_VM_CRYPTO_ENABLE_AES_KW: 1447a374e892STony Krowiak case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW: 1448a374e892STony Krowiak case KVM_S390_VM_CRYPTO_DISABLE_AES_KW: 1449a374e892STony Krowiak case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW: 1450a374e892STony Krowiak ret = 0; 1451a374e892STony Krowiak break; 1452a374e892STony Krowiak default: 1453a374e892STony Krowiak ret = -ENXIO; 1454a374e892STony Krowiak break; 1455a374e892STony Krowiak } 1456a374e892STony Krowiak break; 1457190df4a2SClaudio Imbrenda case KVM_S390_VM_MIGRATION: 1458190df4a2SClaudio Imbrenda ret = 0; 1459190df4a2SClaudio Imbrenda break; 1460f2061656SDominik Dingel default: 1461f2061656SDominik Dingel ret = -ENXIO; 1462f2061656SDominik Dingel break; 1463f2061656SDominik Dingel } 1464f2061656SDominik Dingel 1465f2061656SDominik Dingel return ret; 1466f2061656SDominik Dingel } 1467f2061656SDominik Dingel 146830ee2a98SJason J. Herne static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args) 146930ee2a98SJason J. Herne { 147030ee2a98SJason J. Herne uint8_t *keys; 147130ee2a98SJason J. Herne uint64_t hva; 14724f899147SChristian Borntraeger int srcu_idx, i, r = 0; 147330ee2a98SJason J. Herne 147430ee2a98SJason J. Herne if (args->flags != 0) 147530ee2a98SJason J. Herne return -EINVAL; 147630ee2a98SJason J. Herne 147730ee2a98SJason J. Herne /* Is this guest using storage keys? */ 147830ee2a98SJason J. Herne if (!mm_use_skey(current->mm)) 147930ee2a98SJason J. Herne return KVM_S390_GET_SKEYS_NONE; 148030ee2a98SJason J. Herne 148130ee2a98SJason J. Herne /* Enforce sane limit on memory allocation */ 148230ee2a98SJason J. Herne if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX) 148330ee2a98SJason J. Herne return -EINVAL; 148430ee2a98SJason J. Herne 1485752ade68SMichal Hocko keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL); 148630ee2a98SJason J. Herne if (!keys) 148730ee2a98SJason J. Herne return -ENOMEM; 148830ee2a98SJason J. Herne 1489d3ed1ceeSMartin Schwidefsky down_read(¤t->mm->mmap_sem); 14904f899147SChristian Borntraeger srcu_idx = srcu_read_lock(&kvm->srcu); 149130ee2a98SJason J. Herne for (i = 0; i < args->count; i++) { 149230ee2a98SJason J. Herne hva = gfn_to_hva(kvm, args->start_gfn + i); 149330ee2a98SJason J. Herne if (kvm_is_error_hva(hva)) { 149430ee2a98SJason J. Herne r = -EFAULT; 1495d3ed1ceeSMartin Schwidefsky break; 149630ee2a98SJason J. Herne } 149730ee2a98SJason J. Herne 1498154c8c19SDavid Hildenbrand r = get_guest_storage_key(current->mm, hva, &keys[i]); 1499154c8c19SDavid Hildenbrand if (r) 1500d3ed1ceeSMartin Schwidefsky break; 150130ee2a98SJason J. Herne } 15024f899147SChristian Borntraeger srcu_read_unlock(&kvm->srcu, srcu_idx); 1503d3ed1ceeSMartin Schwidefsky up_read(¤t->mm->mmap_sem); 150430ee2a98SJason J. Herne 1505d3ed1ceeSMartin Schwidefsky if (!r) { 150630ee2a98SJason J. Herne r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys, 150730ee2a98SJason J. Herne sizeof(uint8_t) * args->count); 150830ee2a98SJason J. Herne if (r) 150930ee2a98SJason J. Herne r = -EFAULT; 1510d3ed1ceeSMartin Schwidefsky } 1511d3ed1ceeSMartin Schwidefsky 151230ee2a98SJason J. Herne kvfree(keys); 151330ee2a98SJason J. Herne return r; 151430ee2a98SJason J. Herne } 151530ee2a98SJason J. Herne 151630ee2a98SJason J. Herne static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args) 151730ee2a98SJason J. Herne { 151830ee2a98SJason J. Herne uint8_t *keys; 151930ee2a98SJason J. Herne uint64_t hva; 15204f899147SChristian Borntraeger int srcu_idx, i, r = 0; 152130ee2a98SJason J. Herne 152230ee2a98SJason J. Herne if (args->flags != 0) 152330ee2a98SJason J. Herne return -EINVAL; 152430ee2a98SJason J. Herne 152530ee2a98SJason J. Herne /* Enforce sane limit on memory allocation */ 152630ee2a98SJason J. Herne if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX) 152730ee2a98SJason J. Herne return -EINVAL; 152830ee2a98SJason J. Herne 1529752ade68SMichal Hocko keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL); 153030ee2a98SJason J. Herne if (!keys) 153130ee2a98SJason J. Herne return -ENOMEM; 153230ee2a98SJason J. Herne 153330ee2a98SJason J. Herne r = copy_from_user(keys, (uint8_t __user *)args->skeydata_addr, 153430ee2a98SJason J. Herne sizeof(uint8_t) * args->count); 153530ee2a98SJason J. Herne if (r) { 153630ee2a98SJason J. Herne r = -EFAULT; 153730ee2a98SJason J. Herne goto out; 153830ee2a98SJason J. Herne } 153930ee2a98SJason J. Herne 154030ee2a98SJason J. Herne /* Enable storage key handling for the guest */ 154114d4a425SDominik Dingel r = s390_enable_skey(); 154214d4a425SDominik Dingel if (r) 154314d4a425SDominik Dingel goto out; 154430ee2a98SJason J. Herne 1545d3ed1ceeSMartin Schwidefsky down_read(¤t->mm->mmap_sem); 15464f899147SChristian Borntraeger srcu_idx = srcu_read_lock(&kvm->srcu); 154730ee2a98SJason J. Herne for (i = 0; i < args->count; i++) { 154830ee2a98SJason J. Herne hva = gfn_to_hva(kvm, args->start_gfn + i); 154930ee2a98SJason J. Herne if (kvm_is_error_hva(hva)) { 155030ee2a98SJason J. Herne r = -EFAULT; 1551d3ed1ceeSMartin Schwidefsky break; 155230ee2a98SJason J. Herne } 155330ee2a98SJason J. Herne 155430ee2a98SJason J. Herne /* Lowest order bit is reserved */ 155530ee2a98SJason J. Herne if (keys[i] & 0x01) { 155630ee2a98SJason J. Herne r = -EINVAL; 1557d3ed1ceeSMartin Schwidefsky break; 155830ee2a98SJason J. Herne } 155930ee2a98SJason J. Herne 1560fe69eabfSDavid Hildenbrand r = set_guest_storage_key(current->mm, hva, keys[i], 0); 156130ee2a98SJason J. Herne if (r) 1562d3ed1ceeSMartin Schwidefsky break; 156330ee2a98SJason J. Herne } 15644f899147SChristian Borntraeger srcu_read_unlock(&kvm->srcu, srcu_idx); 1565d3ed1ceeSMartin Schwidefsky up_read(¤t->mm->mmap_sem); 156630ee2a98SJason J. Herne out: 156730ee2a98SJason J. Herne kvfree(keys); 156830ee2a98SJason J. Herne return r; 156930ee2a98SJason J. Herne } 157030ee2a98SJason J. Herne 15714036e387SClaudio Imbrenda /* 15724036e387SClaudio Imbrenda * Base address and length must be sent at the start of each block, therefore 15734036e387SClaudio Imbrenda * it's cheaper to send some clean data, as long as it's less than the size of 15744036e387SClaudio Imbrenda * two longs. 15754036e387SClaudio Imbrenda */ 15764036e387SClaudio Imbrenda #define KVM_S390_MAX_BIT_DISTANCE (2 * sizeof(void *)) 15774036e387SClaudio Imbrenda /* for consistency */ 15784036e387SClaudio Imbrenda #define KVM_S390_CMMA_SIZE_MAX ((u32)KVM_S390_SKEYS_MAX) 15794036e387SClaudio Imbrenda 15804036e387SClaudio Imbrenda /* 15814036e387SClaudio Imbrenda * This function searches for the next page with dirty CMMA attributes, and 15824036e387SClaudio Imbrenda * saves the attributes in the buffer up to either the end of the buffer or 15834036e387SClaudio Imbrenda * until a block of at least KVM_S390_MAX_BIT_DISTANCE clean bits is found; 15844036e387SClaudio Imbrenda * no trailing clean bytes are saved. 15854036e387SClaudio Imbrenda * In case no dirty bits were found, or if CMMA was not enabled or used, the 15864036e387SClaudio Imbrenda * output buffer will indicate 0 as length. 15874036e387SClaudio Imbrenda */ 15884036e387SClaudio Imbrenda static int kvm_s390_get_cmma_bits(struct kvm *kvm, 15894036e387SClaudio Imbrenda struct kvm_s390_cmma_log *args) 15904036e387SClaudio Imbrenda { 15914036e387SClaudio Imbrenda struct kvm_s390_migration_state *s = kvm->arch.migration_state; 15924036e387SClaudio Imbrenda unsigned long bufsize, hva, pgstev, i, next, cur; 15934036e387SClaudio Imbrenda int srcu_idx, peek, r = 0, rr; 15944036e387SClaudio Imbrenda u8 *res; 15954036e387SClaudio Imbrenda 15964036e387SClaudio Imbrenda cur = args->start_gfn; 15974036e387SClaudio Imbrenda i = next = pgstev = 0; 15984036e387SClaudio Imbrenda 15994036e387SClaudio Imbrenda if (unlikely(!kvm->arch.use_cmma)) 16004036e387SClaudio Imbrenda return -ENXIO; 16014036e387SClaudio Imbrenda /* Invalid/unsupported flags were specified */ 16024036e387SClaudio Imbrenda if (args->flags & ~KVM_S390_CMMA_PEEK) 16034036e387SClaudio Imbrenda return -EINVAL; 16044036e387SClaudio Imbrenda /* Migration mode query, and we are not doing a migration */ 16054036e387SClaudio Imbrenda peek = !!(args->flags & KVM_S390_CMMA_PEEK); 16064036e387SClaudio Imbrenda if (!peek && !s) 16074036e387SClaudio Imbrenda return -EINVAL; 16084036e387SClaudio Imbrenda /* CMMA is disabled or was not used, or the buffer has length zero */ 16094036e387SClaudio Imbrenda bufsize = min(args->count, KVM_S390_CMMA_SIZE_MAX); 1610c9f0a2b8SJanosch Frank if (!bufsize || !kvm->mm->context.uses_cmm) { 16114036e387SClaudio Imbrenda memset(args, 0, sizeof(*args)); 16124036e387SClaudio Imbrenda return 0; 16134036e387SClaudio Imbrenda } 16144036e387SClaudio Imbrenda 16154036e387SClaudio Imbrenda if (!peek) { 16164036e387SClaudio Imbrenda /* We are not peeking, and there are no dirty pages */ 16174036e387SClaudio Imbrenda if (!atomic64_read(&s->dirty_pages)) { 16184036e387SClaudio Imbrenda memset(args, 0, sizeof(*args)); 16194036e387SClaudio Imbrenda return 0; 16204036e387SClaudio Imbrenda } 16214036e387SClaudio Imbrenda cur = find_next_bit(s->pgste_bitmap, s->bitmap_size, 16224036e387SClaudio Imbrenda args->start_gfn); 16234036e387SClaudio Imbrenda if (cur >= s->bitmap_size) /* nothing found, loop back */ 16244036e387SClaudio Imbrenda cur = find_next_bit(s->pgste_bitmap, s->bitmap_size, 0); 16254036e387SClaudio Imbrenda if (cur >= s->bitmap_size) { /* again! (very unlikely) */ 16264036e387SClaudio Imbrenda memset(args, 0, sizeof(*args)); 16274036e387SClaudio Imbrenda return 0; 16284036e387SClaudio Imbrenda } 16294036e387SClaudio Imbrenda next = find_next_bit(s->pgste_bitmap, s->bitmap_size, cur + 1); 16304036e387SClaudio Imbrenda } 16314036e387SClaudio Imbrenda 16324036e387SClaudio Imbrenda res = vmalloc(bufsize); 16334036e387SClaudio Imbrenda if (!res) 16344036e387SClaudio Imbrenda return -ENOMEM; 16354036e387SClaudio Imbrenda 16364036e387SClaudio Imbrenda args->start_gfn = cur; 16374036e387SClaudio Imbrenda 16384036e387SClaudio Imbrenda down_read(&kvm->mm->mmap_sem); 16394036e387SClaudio Imbrenda srcu_idx = srcu_read_lock(&kvm->srcu); 16404036e387SClaudio Imbrenda while (i < bufsize) { 16414036e387SClaudio Imbrenda hva = gfn_to_hva(kvm, cur); 16424036e387SClaudio Imbrenda if (kvm_is_error_hva(hva)) { 16434036e387SClaudio Imbrenda r = -EFAULT; 16444036e387SClaudio Imbrenda break; 16454036e387SClaudio Imbrenda } 16464036e387SClaudio Imbrenda /* decrement only if we actually flipped the bit to 0 */ 16474036e387SClaudio Imbrenda if (!peek && test_and_clear_bit(cur, s->pgste_bitmap)) 16484036e387SClaudio Imbrenda atomic64_dec(&s->dirty_pages); 16494036e387SClaudio Imbrenda r = get_pgste(kvm->mm, hva, &pgstev); 16504036e387SClaudio Imbrenda if (r < 0) 16514036e387SClaudio Imbrenda pgstev = 0; 16524036e387SClaudio Imbrenda /* save the value */ 16531bab1c02SClaudio Imbrenda res[i++] = (pgstev >> 24) & 0x43; 16544036e387SClaudio Imbrenda /* 16554036e387SClaudio Imbrenda * if the next bit is too far away, stop. 16564036e387SClaudio Imbrenda * if we reached the previous "next", find the next one 16574036e387SClaudio Imbrenda */ 16584036e387SClaudio Imbrenda if (!peek) { 16594036e387SClaudio Imbrenda if (next > cur + KVM_S390_MAX_BIT_DISTANCE) 16604036e387SClaudio Imbrenda break; 16614036e387SClaudio Imbrenda if (cur == next) 16624036e387SClaudio Imbrenda next = find_next_bit(s->pgste_bitmap, 16634036e387SClaudio Imbrenda s->bitmap_size, cur + 1); 16644036e387SClaudio Imbrenda /* reached the end of the bitmap or of the buffer, stop */ 16654036e387SClaudio Imbrenda if ((next >= s->bitmap_size) || 16664036e387SClaudio Imbrenda (next >= args->start_gfn + bufsize)) 16674036e387SClaudio Imbrenda break; 16684036e387SClaudio Imbrenda } 16694036e387SClaudio Imbrenda cur++; 16704036e387SClaudio Imbrenda } 16714036e387SClaudio Imbrenda srcu_read_unlock(&kvm->srcu, srcu_idx); 16724036e387SClaudio Imbrenda up_read(&kvm->mm->mmap_sem); 16734036e387SClaudio Imbrenda args->count = i; 16744036e387SClaudio Imbrenda args->remaining = s ? atomic64_read(&s->dirty_pages) : 0; 16754036e387SClaudio Imbrenda 16764036e387SClaudio Imbrenda rr = copy_to_user((void __user *)args->values, res, args->count); 16774036e387SClaudio Imbrenda if (rr) 16784036e387SClaudio Imbrenda r = -EFAULT; 16794036e387SClaudio Imbrenda 16804036e387SClaudio Imbrenda vfree(res); 16814036e387SClaudio Imbrenda return r; 16824036e387SClaudio Imbrenda } 16834036e387SClaudio Imbrenda 16844036e387SClaudio Imbrenda /* 16854036e387SClaudio Imbrenda * This function sets the CMMA attributes for the given pages. If the input 16864036e387SClaudio Imbrenda * buffer has zero length, no action is taken, otherwise the attributes are 1687c9f0a2b8SJanosch Frank * set and the mm->context.uses_cmm flag is set. 16884036e387SClaudio Imbrenda */ 16894036e387SClaudio Imbrenda static int kvm_s390_set_cmma_bits(struct kvm *kvm, 16904036e387SClaudio Imbrenda const struct kvm_s390_cmma_log *args) 16914036e387SClaudio Imbrenda { 16924036e387SClaudio Imbrenda unsigned long hva, mask, pgstev, i; 16934036e387SClaudio Imbrenda uint8_t *bits; 16944036e387SClaudio Imbrenda int srcu_idx, r = 0; 16954036e387SClaudio Imbrenda 16964036e387SClaudio Imbrenda mask = args->mask; 16974036e387SClaudio Imbrenda 16984036e387SClaudio Imbrenda if (!kvm->arch.use_cmma) 16994036e387SClaudio Imbrenda return -ENXIO; 17004036e387SClaudio Imbrenda /* invalid/unsupported flags */ 17014036e387SClaudio Imbrenda if (args->flags != 0) 17024036e387SClaudio Imbrenda return -EINVAL; 17034036e387SClaudio Imbrenda /* Enforce sane limit on memory allocation */ 17044036e387SClaudio Imbrenda if (args->count > KVM_S390_CMMA_SIZE_MAX) 17054036e387SClaudio Imbrenda return -EINVAL; 17064036e387SClaudio Imbrenda /* Nothing to do */ 17074036e387SClaudio Imbrenda if (args->count == 0) 17084036e387SClaudio Imbrenda return 0; 17094036e387SClaudio Imbrenda 17104036e387SClaudio Imbrenda bits = vmalloc(sizeof(*bits) * args->count); 17114036e387SClaudio Imbrenda if (!bits) 17124036e387SClaudio Imbrenda return -ENOMEM; 17134036e387SClaudio Imbrenda 17144036e387SClaudio Imbrenda r = copy_from_user(bits, (void __user *)args->values, args->count); 17154036e387SClaudio Imbrenda if (r) { 17164036e387SClaudio Imbrenda r = -EFAULT; 17174036e387SClaudio Imbrenda goto out; 17184036e387SClaudio Imbrenda } 17194036e387SClaudio Imbrenda 17204036e387SClaudio Imbrenda down_read(&kvm->mm->mmap_sem); 17214036e387SClaudio Imbrenda srcu_idx = srcu_read_lock(&kvm->srcu); 17224036e387SClaudio Imbrenda for (i = 0; i < args->count; i++) { 17234036e387SClaudio Imbrenda hva = gfn_to_hva(kvm, args->start_gfn + i); 17244036e387SClaudio Imbrenda if (kvm_is_error_hva(hva)) { 17254036e387SClaudio Imbrenda r = -EFAULT; 17264036e387SClaudio Imbrenda break; 17274036e387SClaudio Imbrenda } 17284036e387SClaudio Imbrenda 17294036e387SClaudio Imbrenda pgstev = bits[i]; 17304036e387SClaudio Imbrenda pgstev = pgstev << 24; 17311bab1c02SClaudio Imbrenda mask &= _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT; 17324036e387SClaudio Imbrenda set_pgste_bits(kvm->mm, hva, mask, pgstev); 17334036e387SClaudio Imbrenda } 17344036e387SClaudio Imbrenda srcu_read_unlock(&kvm->srcu, srcu_idx); 17354036e387SClaudio Imbrenda up_read(&kvm->mm->mmap_sem); 17364036e387SClaudio Imbrenda 1737c9f0a2b8SJanosch Frank if (!kvm->mm->context.uses_cmm) { 17384036e387SClaudio Imbrenda down_write(&kvm->mm->mmap_sem); 1739c9f0a2b8SJanosch Frank kvm->mm->context.uses_cmm = 1; 17404036e387SClaudio Imbrenda up_write(&kvm->mm->mmap_sem); 17414036e387SClaudio Imbrenda } 17424036e387SClaudio Imbrenda out: 17434036e387SClaudio Imbrenda vfree(bits); 17444036e387SClaudio Imbrenda return r; 17454036e387SClaudio Imbrenda } 17464036e387SClaudio Imbrenda 1747b0c632dbSHeiko Carstens long kvm_arch_vm_ioctl(struct file *filp, 1748b0c632dbSHeiko Carstens unsigned int ioctl, unsigned long arg) 1749b0c632dbSHeiko Carstens { 1750b0c632dbSHeiko Carstens struct kvm *kvm = filp->private_data; 1751b0c632dbSHeiko Carstens void __user *argp = (void __user *)arg; 1752f2061656SDominik Dingel struct kvm_device_attr attr; 1753b0c632dbSHeiko Carstens int r; 1754b0c632dbSHeiko Carstens 1755b0c632dbSHeiko Carstens switch (ioctl) { 1756ba5c1e9bSCarsten Otte case KVM_S390_INTERRUPT: { 1757ba5c1e9bSCarsten Otte struct kvm_s390_interrupt s390int; 1758ba5c1e9bSCarsten Otte 1759ba5c1e9bSCarsten Otte r = -EFAULT; 1760ba5c1e9bSCarsten Otte if (copy_from_user(&s390int, argp, sizeof(s390int))) 1761ba5c1e9bSCarsten Otte break; 1762ba5c1e9bSCarsten Otte r = kvm_s390_inject_vm(kvm, &s390int); 1763ba5c1e9bSCarsten Otte break; 1764ba5c1e9bSCarsten Otte } 1765d938dc55SCornelia Huck case KVM_ENABLE_CAP: { 1766d938dc55SCornelia Huck struct kvm_enable_cap cap; 1767d938dc55SCornelia Huck r = -EFAULT; 1768d938dc55SCornelia Huck if (copy_from_user(&cap, argp, sizeof(cap))) 1769d938dc55SCornelia Huck break; 1770d938dc55SCornelia Huck r = kvm_vm_ioctl_enable_cap(kvm, &cap); 1771d938dc55SCornelia Huck break; 1772d938dc55SCornelia Huck } 177384223598SCornelia Huck case KVM_CREATE_IRQCHIP: { 177484223598SCornelia Huck struct kvm_irq_routing_entry routing; 177584223598SCornelia Huck 177684223598SCornelia Huck r = -EINVAL; 177784223598SCornelia Huck if (kvm->arch.use_irqchip) { 177884223598SCornelia Huck /* Set up dummy routing. */ 177984223598SCornelia Huck memset(&routing, 0, sizeof(routing)); 1780152b2839SNicholas Krause r = kvm_set_irq_routing(kvm, &routing, 0, 0); 178184223598SCornelia Huck } 178284223598SCornelia Huck break; 178384223598SCornelia Huck } 1784f2061656SDominik Dingel case KVM_SET_DEVICE_ATTR: { 1785f2061656SDominik Dingel r = -EFAULT; 1786f2061656SDominik Dingel if (copy_from_user(&attr, (void __user *)arg, sizeof(attr))) 1787f2061656SDominik Dingel break; 1788f2061656SDominik Dingel r = kvm_s390_vm_set_attr(kvm, &attr); 1789f2061656SDominik Dingel break; 1790f2061656SDominik Dingel } 1791f2061656SDominik Dingel case KVM_GET_DEVICE_ATTR: { 1792f2061656SDominik Dingel r = -EFAULT; 1793f2061656SDominik Dingel if (copy_from_user(&attr, (void __user *)arg, sizeof(attr))) 1794f2061656SDominik Dingel break; 1795f2061656SDominik Dingel r = kvm_s390_vm_get_attr(kvm, &attr); 1796f2061656SDominik Dingel break; 1797f2061656SDominik Dingel } 1798f2061656SDominik Dingel case KVM_HAS_DEVICE_ATTR: { 1799f2061656SDominik Dingel r = -EFAULT; 1800f2061656SDominik Dingel if (copy_from_user(&attr, (void __user *)arg, sizeof(attr))) 1801f2061656SDominik Dingel break; 1802f2061656SDominik Dingel r = kvm_s390_vm_has_attr(kvm, &attr); 1803f2061656SDominik Dingel break; 1804f2061656SDominik Dingel } 180530ee2a98SJason J. Herne case KVM_S390_GET_SKEYS: { 180630ee2a98SJason J. Herne struct kvm_s390_skeys args; 180730ee2a98SJason J. Herne 180830ee2a98SJason J. Herne r = -EFAULT; 180930ee2a98SJason J. Herne if (copy_from_user(&args, argp, 181030ee2a98SJason J. Herne sizeof(struct kvm_s390_skeys))) 181130ee2a98SJason J. Herne break; 181230ee2a98SJason J. Herne r = kvm_s390_get_skeys(kvm, &args); 181330ee2a98SJason J. Herne break; 181430ee2a98SJason J. Herne } 181530ee2a98SJason J. Herne case KVM_S390_SET_SKEYS: { 181630ee2a98SJason J. Herne struct kvm_s390_skeys args; 181730ee2a98SJason J. Herne 181830ee2a98SJason J. Herne r = -EFAULT; 181930ee2a98SJason J. Herne if (copy_from_user(&args, argp, 182030ee2a98SJason J. Herne sizeof(struct kvm_s390_skeys))) 182130ee2a98SJason J. Herne break; 182230ee2a98SJason J. Herne r = kvm_s390_set_skeys(kvm, &args); 182330ee2a98SJason J. Herne break; 182430ee2a98SJason J. Herne } 18254036e387SClaudio Imbrenda case KVM_S390_GET_CMMA_BITS: { 18264036e387SClaudio Imbrenda struct kvm_s390_cmma_log args; 18274036e387SClaudio Imbrenda 18284036e387SClaudio Imbrenda r = -EFAULT; 18294036e387SClaudio Imbrenda if (copy_from_user(&args, argp, sizeof(args))) 18304036e387SClaudio Imbrenda break; 18311de1ea7eSChristian Borntraeger mutex_lock(&kvm->slots_lock); 18324036e387SClaudio Imbrenda r = kvm_s390_get_cmma_bits(kvm, &args); 18331de1ea7eSChristian Borntraeger mutex_unlock(&kvm->slots_lock); 18344036e387SClaudio Imbrenda if (!r) { 18354036e387SClaudio Imbrenda r = copy_to_user(argp, &args, sizeof(args)); 18364036e387SClaudio Imbrenda if (r) 18374036e387SClaudio Imbrenda r = -EFAULT; 18384036e387SClaudio Imbrenda } 18394036e387SClaudio Imbrenda break; 18404036e387SClaudio Imbrenda } 18414036e387SClaudio Imbrenda case KVM_S390_SET_CMMA_BITS: { 18424036e387SClaudio Imbrenda struct kvm_s390_cmma_log args; 18434036e387SClaudio Imbrenda 18444036e387SClaudio Imbrenda r = -EFAULT; 18454036e387SClaudio Imbrenda if (copy_from_user(&args, argp, sizeof(args))) 18464036e387SClaudio Imbrenda break; 18471de1ea7eSChristian Borntraeger mutex_lock(&kvm->slots_lock); 18484036e387SClaudio Imbrenda r = kvm_s390_set_cmma_bits(kvm, &args); 18491de1ea7eSChristian Borntraeger mutex_unlock(&kvm->slots_lock); 18504036e387SClaudio Imbrenda break; 18514036e387SClaudio Imbrenda } 1852b0c632dbSHeiko Carstens default: 1853367e1319SAvi Kivity r = -ENOTTY; 1854b0c632dbSHeiko Carstens } 1855b0c632dbSHeiko Carstens 1856b0c632dbSHeiko Carstens return r; 1857b0c632dbSHeiko Carstens } 1858b0c632dbSHeiko Carstens 185945c9b47cSTony Krowiak static int kvm_s390_query_ap_config(u8 *config) 186045c9b47cSTony Krowiak { 186145c9b47cSTony Krowiak u32 fcn_code = 0x04000000UL; 186286044c8cSChristian Borntraeger u32 cc = 0; 186345c9b47cSTony Krowiak 186486044c8cSChristian Borntraeger memset(config, 0, 128); 186545c9b47cSTony Krowiak asm volatile( 186645c9b47cSTony Krowiak "lgr 0,%1\n" 186745c9b47cSTony Krowiak "lgr 2,%2\n" 186845c9b47cSTony Krowiak ".long 0xb2af0000\n" /* PQAP(QCI) */ 186986044c8cSChristian Borntraeger "0: ipm %0\n" 187045c9b47cSTony Krowiak "srl %0,28\n" 187186044c8cSChristian Borntraeger "1:\n" 187286044c8cSChristian Borntraeger EX_TABLE(0b, 1b) 187386044c8cSChristian Borntraeger : "+r" (cc) 187445c9b47cSTony Krowiak : "r" (fcn_code), "r" (config) 187545c9b47cSTony Krowiak : "cc", "0", "2", "memory" 187645c9b47cSTony Krowiak ); 187745c9b47cSTony Krowiak 187845c9b47cSTony Krowiak return cc; 187945c9b47cSTony Krowiak } 188045c9b47cSTony Krowiak 188145c9b47cSTony Krowiak static int kvm_s390_apxa_installed(void) 188245c9b47cSTony Krowiak { 188345c9b47cSTony Krowiak u8 config[128]; 188445c9b47cSTony Krowiak int cc; 188545c9b47cSTony Krowiak 1886a6aacc3fSHeiko Carstens if (test_facility(12)) { 188745c9b47cSTony Krowiak cc = kvm_s390_query_ap_config(config); 188845c9b47cSTony Krowiak 188945c9b47cSTony Krowiak if (cc) 189045c9b47cSTony Krowiak pr_err("PQAP(QCI) failed with cc=%d", cc); 189145c9b47cSTony Krowiak else 189245c9b47cSTony Krowiak return config[0] & 0x40; 189345c9b47cSTony Krowiak } 189445c9b47cSTony Krowiak 189545c9b47cSTony Krowiak return 0; 189645c9b47cSTony Krowiak } 189745c9b47cSTony Krowiak 189845c9b47cSTony Krowiak static void kvm_s390_set_crycb_format(struct kvm *kvm) 189945c9b47cSTony Krowiak { 190045c9b47cSTony Krowiak kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb; 190145c9b47cSTony Krowiak 190245c9b47cSTony Krowiak if (kvm_s390_apxa_installed()) 190345c9b47cSTony Krowiak kvm->arch.crypto.crycbd |= CRYCB_FORMAT2; 190445c9b47cSTony Krowiak else 190545c9b47cSTony Krowiak kvm->arch.crypto.crycbd |= CRYCB_FORMAT1; 190645c9b47cSTony Krowiak } 190745c9b47cSTony Krowiak 19089bb0ec09SDavid Hildenbrand static u64 kvm_s390_get_initial_cpuid(void) 19099d8d5786SMichael Mueller { 19109bb0ec09SDavid Hildenbrand struct cpuid cpuid; 19119bb0ec09SDavid Hildenbrand 19129bb0ec09SDavid Hildenbrand get_cpu_id(&cpuid); 19139bb0ec09SDavid Hildenbrand cpuid.version = 0xff; 19149bb0ec09SDavid Hildenbrand return *((u64 *) &cpuid); 19159d8d5786SMichael Mueller } 19169d8d5786SMichael Mueller 1917c54f0d6aSDavid Hildenbrand static void kvm_s390_crypto_init(struct kvm *kvm) 19185102ee87STony Krowiak { 19199d8d5786SMichael Mueller if (!test_kvm_facility(kvm, 76)) 1920c54f0d6aSDavid Hildenbrand return; 19215102ee87STony Krowiak 1922c54f0d6aSDavid Hildenbrand kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb; 192345c9b47cSTony Krowiak kvm_s390_set_crycb_format(kvm); 19245102ee87STony Krowiak 1925ed6f76b4STony Krowiak /* Enable AES/DEA protected key functions by default */ 1926ed6f76b4STony Krowiak kvm->arch.crypto.aes_kw = 1; 1927ed6f76b4STony Krowiak kvm->arch.crypto.dea_kw = 1; 1928ed6f76b4STony Krowiak get_random_bytes(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 1929ed6f76b4STony Krowiak sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask)); 1930ed6f76b4STony Krowiak get_random_bytes(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 1931ed6f76b4STony Krowiak sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask)); 19325102ee87STony Krowiak } 19335102ee87STony Krowiak 19347d43bafcSEugene (jno) Dvurechenski static void sca_dispose(struct kvm *kvm) 19357d43bafcSEugene (jno) Dvurechenski { 19367d43bafcSEugene (jno) Dvurechenski if (kvm->arch.use_esca) 19375e044315SEugene (jno) Dvurechenski free_pages_exact(kvm->arch.sca, sizeof(struct esca_block)); 19387d43bafcSEugene (jno) Dvurechenski else 19397d43bafcSEugene (jno) Dvurechenski free_page((unsigned long)(kvm->arch.sca)); 19407d43bafcSEugene (jno) Dvurechenski kvm->arch.sca = NULL; 19417d43bafcSEugene (jno) Dvurechenski } 19427d43bafcSEugene (jno) Dvurechenski 1943e08b9637SCarsten Otte int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) 1944b0c632dbSHeiko Carstens { 194576a6dd72SDavid Hildenbrand gfp_t alloc_flags = GFP_KERNEL; 19469d8d5786SMichael Mueller int i, rc; 1947b0c632dbSHeiko Carstens char debug_name[16]; 1948f6c137ffSChristian Borntraeger static unsigned long sca_offset; 1949b0c632dbSHeiko Carstens 1950e08b9637SCarsten Otte rc = -EINVAL; 1951e08b9637SCarsten Otte #ifdef CONFIG_KVM_S390_UCONTROL 1952e08b9637SCarsten Otte if (type & ~KVM_VM_S390_UCONTROL) 1953e08b9637SCarsten Otte goto out_err; 1954e08b9637SCarsten Otte if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN))) 1955e08b9637SCarsten Otte goto out_err; 1956e08b9637SCarsten Otte #else 1957e08b9637SCarsten Otte if (type) 1958e08b9637SCarsten Otte goto out_err; 1959e08b9637SCarsten Otte #endif 1960e08b9637SCarsten Otte 1961b0c632dbSHeiko Carstens rc = s390_enable_sie(); 1962b0c632dbSHeiko Carstens if (rc) 1963d89f5effSJan Kiszka goto out_err; 1964b0c632dbSHeiko Carstens 1965b290411aSCarsten Otte rc = -ENOMEM; 1966b290411aSCarsten Otte 19677d43bafcSEugene (jno) Dvurechenski kvm->arch.use_esca = 0; /* start with basic SCA */ 196876a6dd72SDavid Hildenbrand if (!sclp.has_64bscao) 196976a6dd72SDavid Hildenbrand alloc_flags |= GFP_DMA; 19705e044315SEugene (jno) Dvurechenski rwlock_init(&kvm->arch.sca_lock); 197176a6dd72SDavid Hildenbrand kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags); 1972b0c632dbSHeiko Carstens if (!kvm->arch.sca) 1973d89f5effSJan Kiszka goto out_err; 1974f6c137ffSChristian Borntraeger spin_lock(&kvm_lock); 1975c5c2c393SDavid Hildenbrand sca_offset += 16; 1976bc784cceSEugene (jno) Dvurechenski if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE) 1977c5c2c393SDavid Hildenbrand sca_offset = 0; 1978bc784cceSEugene (jno) Dvurechenski kvm->arch.sca = (struct bsca_block *) 1979bc784cceSEugene (jno) Dvurechenski ((char *) kvm->arch.sca + sca_offset); 1980f6c137ffSChristian Borntraeger spin_unlock(&kvm_lock); 1981b0c632dbSHeiko Carstens 1982b0c632dbSHeiko Carstens sprintf(debug_name, "kvm-%u", current->pid); 1983b0c632dbSHeiko Carstens 19841cb9cf72SChristian Borntraeger kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long)); 1985b0c632dbSHeiko Carstens if (!kvm->arch.dbf) 198640f5b735SDominik Dingel goto out_err; 1987b0c632dbSHeiko Carstens 198819114bebSMichael Mueller BUILD_BUG_ON(sizeof(struct sie_page2) != 4096); 1989c54f0d6aSDavid Hildenbrand kvm->arch.sie_page2 = 1990c54f0d6aSDavid Hildenbrand (struct sie_page2 *) get_zeroed_page(GFP_KERNEL | GFP_DMA); 1991c54f0d6aSDavid Hildenbrand if (!kvm->arch.sie_page2) 199240f5b735SDominik Dingel goto out_err; 19939d8d5786SMichael Mueller 1994c54f0d6aSDavid Hildenbrand kvm->arch.model.fac_list = kvm->arch.sie_page2->fac_list; 1995c3b9e3e1SChristian Borntraeger 1996c3b9e3e1SChristian Borntraeger for (i = 0; i < kvm_s390_fac_size(); i++) { 1997c3b9e3e1SChristian Borntraeger kvm->arch.model.fac_mask[i] = S390_lowcore.stfle_fac_list[i] & 1998c3b9e3e1SChristian Borntraeger (kvm_s390_fac_base[i] | 1999c3b9e3e1SChristian Borntraeger kvm_s390_fac_ext[i]); 2000c3b9e3e1SChristian Borntraeger kvm->arch.model.fac_list[i] = S390_lowcore.stfle_fac_list[i] & 2001c3b9e3e1SChristian Borntraeger kvm_s390_fac_base[i]; 2002c3b9e3e1SChristian Borntraeger } 2003981467c9SMichael Mueller 20041935222dSDavid Hildenbrand /* we are always in czam mode - even on pre z14 machines */ 20051935222dSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_mask, 138); 20061935222dSDavid Hildenbrand set_kvm_facility(kvm->arch.model.fac_list, 138); 20071935222dSDavid Hildenbrand /* we emulate STHYI in kvm */ 200895ca2cb5SJanosch Frank set_kvm_facility(kvm->arch.model.fac_mask, 74); 200995ca2cb5SJanosch Frank set_kvm_facility(kvm->arch.model.fac_list, 74); 20101bab1c02SClaudio Imbrenda if (MACHINE_HAS_TLB_GUEST) { 20111bab1c02SClaudio Imbrenda set_kvm_facility(kvm->arch.model.fac_mask, 147); 20121bab1c02SClaudio Imbrenda set_kvm_facility(kvm->arch.model.fac_list, 147); 20131bab1c02SClaudio Imbrenda } 201495ca2cb5SJanosch Frank 20159bb0ec09SDavid Hildenbrand kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid(); 201637c5f6c8SDavid Hildenbrand kvm->arch.model.ibc = sclp.ibc & 0x0fff; 20179d8d5786SMichael Mueller 2018c54f0d6aSDavid Hildenbrand kvm_s390_crypto_init(kvm); 20195102ee87STony Krowiak 202051978393SFei Li mutex_init(&kvm->arch.float_int.ais_lock); 202151978393SFei Li kvm->arch.float_int.simm = 0; 202251978393SFei Li kvm->arch.float_int.nimm = 0; 2023ba5c1e9bSCarsten Otte spin_lock_init(&kvm->arch.float_int.lock); 20246d3da241SJens Freimann for (i = 0; i < FIRQ_LIST_COUNT; i++) 20256d3da241SJens Freimann INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]); 20268a242234SHeiko Carstens init_waitqueue_head(&kvm->arch.ipte_wq); 2027a6b7e459SThomas Huth mutex_init(&kvm->arch.ipte_mutex); 2028ba5c1e9bSCarsten Otte 2029b0c632dbSHeiko Carstens debug_register_view(kvm->arch.dbf, &debug_sprintf_view); 203078f26131SChristian Borntraeger VM_EVENT(kvm, 3, "vm created with type %lu", type); 2031b0c632dbSHeiko Carstens 2032e08b9637SCarsten Otte if (type & KVM_VM_S390_UCONTROL) { 2033e08b9637SCarsten Otte kvm->arch.gmap = NULL; 2034a3a92c31SDominik Dingel kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT; 2035e08b9637SCarsten Otte } else { 203632e6b236SGuenther Hutzl if (sclp.hamax == U64_MAX) 2037ee71d16dSMartin Schwidefsky kvm->arch.mem_limit = TASK_SIZE_MAX; 203832e6b236SGuenther Hutzl else 2039ee71d16dSMartin Schwidefsky kvm->arch.mem_limit = min_t(unsigned long, TASK_SIZE_MAX, 204032e6b236SGuenther Hutzl sclp.hamax + 1); 20416ea427bbSMartin Schwidefsky kvm->arch.gmap = gmap_create(current->mm, kvm->arch.mem_limit - 1); 2042598841caSCarsten Otte if (!kvm->arch.gmap) 204340f5b735SDominik Dingel goto out_err; 20442c70fe44SChristian Borntraeger kvm->arch.gmap->private = kvm; 204524eb3a82SDominik Dingel kvm->arch.gmap->pfault_enabled = 0; 2046e08b9637SCarsten Otte } 2047fa6b7fe9SCornelia Huck 2048fa6b7fe9SCornelia Huck kvm->arch.css_support = 0; 204984223598SCornelia Huck kvm->arch.use_irqchip = 0; 2050c9f0a2b8SJanosch Frank kvm->arch.use_pfmfi = sclp.has_pfmfi; 205172f25020SJason J. Herne kvm->arch.epoch = 0; 2052fa6b7fe9SCornelia Huck 20538ad35755SDavid Hildenbrand spin_lock_init(&kvm->arch.start_stop_lock); 2054a3508fbeSDavid Hildenbrand kvm_s390_vsie_init(kvm); 2055d7c5cb01SMichael Mueller kvm_s390_gisa_init(kvm); 20568335713aSChristian Borntraeger KVM_EVENT(3, "vm 0x%pK created by pid %u", kvm, current->pid); 20578ad35755SDavid Hildenbrand 2058d89f5effSJan Kiszka return 0; 2059d89f5effSJan Kiszka out_err: 2060c54f0d6aSDavid Hildenbrand free_page((unsigned long)kvm->arch.sie_page2); 206140f5b735SDominik Dingel debug_unregister(kvm->arch.dbf); 20627d43bafcSEugene (jno) Dvurechenski sca_dispose(kvm); 206378f26131SChristian Borntraeger KVM_EVENT(3, "creation of vm failed: %d", rc); 2064d89f5effSJan Kiszka return rc; 2065b0c632dbSHeiko Carstens } 2066b0c632dbSHeiko Carstens 2067235539b4SLuiz Capitulino bool kvm_arch_has_vcpu_debugfs(void) 2068235539b4SLuiz Capitulino { 2069235539b4SLuiz Capitulino return false; 2070235539b4SLuiz Capitulino } 2071235539b4SLuiz Capitulino 2072235539b4SLuiz Capitulino int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu) 2073235539b4SLuiz Capitulino { 2074235539b4SLuiz Capitulino return 0; 2075235539b4SLuiz Capitulino } 2076235539b4SLuiz Capitulino 2077d329c035SChristian Borntraeger void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) 2078d329c035SChristian Borntraeger { 2079d329c035SChristian Borntraeger VCPU_EVENT(vcpu, 3, "%s", "free cpu"); 2080ade38c31SCornelia Huck trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id); 208167335e63SChristian Borntraeger kvm_s390_clear_local_irqs(vcpu); 20823c038e6bSDominik Dingel kvm_clear_async_pf_completion_queue(vcpu); 2083bc784cceSEugene (jno) Dvurechenski if (!kvm_is_ucontrol(vcpu->kvm)) 2084a6e2f683SEugene (jno) Dvurechenski sca_del_vcpu(vcpu); 208527e0393fSCarsten Otte 208627e0393fSCarsten Otte if (kvm_is_ucontrol(vcpu->kvm)) 20876ea427bbSMartin Schwidefsky gmap_remove(vcpu->arch.gmap); 208827e0393fSCarsten Otte 2089e6db1d61SDominik Dingel if (vcpu->kvm->arch.use_cmma) 2090b31605c1SDominik Dingel kvm_s390_vcpu_unsetup_cmma(vcpu); 2091d329c035SChristian Borntraeger free_page((unsigned long)(vcpu->arch.sie_block)); 2092b31288faSKonstantin Weitz 20936692cef3SChristian Borntraeger kvm_vcpu_uninit(vcpu); 2094b110feafSMichael Mueller kmem_cache_free(kvm_vcpu_cache, vcpu); 2095d329c035SChristian Borntraeger } 2096d329c035SChristian Borntraeger 2097d329c035SChristian Borntraeger static void kvm_free_vcpus(struct kvm *kvm) 2098d329c035SChristian Borntraeger { 2099d329c035SChristian Borntraeger unsigned int i; 2100988a2caeSGleb Natapov struct kvm_vcpu *vcpu; 2101d329c035SChristian Borntraeger 2102988a2caeSGleb Natapov kvm_for_each_vcpu(i, vcpu, kvm) 2103988a2caeSGleb Natapov kvm_arch_vcpu_destroy(vcpu); 2104988a2caeSGleb Natapov 2105988a2caeSGleb Natapov mutex_lock(&kvm->lock); 2106988a2caeSGleb Natapov for (i = 0; i < atomic_read(&kvm->online_vcpus); i++) 2107d329c035SChristian Borntraeger kvm->vcpus[i] = NULL; 2108988a2caeSGleb Natapov 2109988a2caeSGleb Natapov atomic_set(&kvm->online_vcpus, 0); 2110988a2caeSGleb Natapov mutex_unlock(&kvm->lock); 2111d329c035SChristian Borntraeger } 2112d329c035SChristian Borntraeger 2113b0c632dbSHeiko Carstens void kvm_arch_destroy_vm(struct kvm *kvm) 2114b0c632dbSHeiko Carstens { 2115d329c035SChristian Borntraeger kvm_free_vcpus(kvm); 21167d43bafcSEugene (jno) Dvurechenski sca_dispose(kvm); 2117d329c035SChristian Borntraeger debug_unregister(kvm->arch.dbf); 2118d7c5cb01SMichael Mueller kvm_s390_gisa_destroy(kvm); 2119c54f0d6aSDavid Hildenbrand free_page((unsigned long)kvm->arch.sie_page2); 212027e0393fSCarsten Otte if (!kvm_is_ucontrol(kvm)) 21216ea427bbSMartin Schwidefsky gmap_remove(kvm->arch.gmap); 2122841b91c5SCornelia Huck kvm_s390_destroy_adapters(kvm); 212367335e63SChristian Borntraeger kvm_s390_clear_float_irqs(kvm); 2124a3508fbeSDavid Hildenbrand kvm_s390_vsie_destroy(kvm); 2125190df4a2SClaudio Imbrenda if (kvm->arch.migration_state) { 2126190df4a2SClaudio Imbrenda vfree(kvm->arch.migration_state->pgste_bitmap); 2127190df4a2SClaudio Imbrenda kfree(kvm->arch.migration_state); 2128190df4a2SClaudio Imbrenda } 21298335713aSChristian Borntraeger KVM_EVENT(3, "vm 0x%pK destroyed", kvm); 2130b0c632dbSHeiko Carstens } 2131b0c632dbSHeiko Carstens 2132b0c632dbSHeiko Carstens /* Section: vcpu related */ 2133dafd032aSDominik Dingel static int __kvm_ucontrol_vcpu_init(struct kvm_vcpu *vcpu) 2134b0c632dbSHeiko Carstens { 21356ea427bbSMartin Schwidefsky vcpu->arch.gmap = gmap_create(current->mm, -1UL); 213627e0393fSCarsten Otte if (!vcpu->arch.gmap) 213727e0393fSCarsten Otte return -ENOMEM; 21382c70fe44SChristian Borntraeger vcpu->arch.gmap->private = vcpu->kvm; 2139dafd032aSDominik Dingel 214027e0393fSCarsten Otte return 0; 214127e0393fSCarsten Otte } 214227e0393fSCarsten Otte 2143a6e2f683SEugene (jno) Dvurechenski static void sca_del_vcpu(struct kvm_vcpu *vcpu) 2144a6e2f683SEugene (jno) Dvurechenski { 2145a6940674SDavid Hildenbrand if (!kvm_s390_use_sca_entries()) 2146a6940674SDavid Hildenbrand return; 21475e044315SEugene (jno) Dvurechenski read_lock(&vcpu->kvm->arch.sca_lock); 21487d43bafcSEugene (jno) Dvurechenski if (vcpu->kvm->arch.use_esca) { 21497d43bafcSEugene (jno) Dvurechenski struct esca_block *sca = vcpu->kvm->arch.sca; 21507d43bafcSEugene (jno) Dvurechenski 21517d43bafcSEugene (jno) Dvurechenski clear_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn); 21527d43bafcSEugene (jno) Dvurechenski sca->cpu[vcpu->vcpu_id].sda = 0; 21537d43bafcSEugene (jno) Dvurechenski } else { 2154bc784cceSEugene (jno) Dvurechenski struct bsca_block *sca = vcpu->kvm->arch.sca; 2155a6e2f683SEugene (jno) Dvurechenski 2156a6e2f683SEugene (jno) Dvurechenski clear_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn); 2157a6e2f683SEugene (jno) Dvurechenski sca->cpu[vcpu->vcpu_id].sda = 0; 2158a6e2f683SEugene (jno) Dvurechenski } 21595e044315SEugene (jno) Dvurechenski read_unlock(&vcpu->kvm->arch.sca_lock); 21607d43bafcSEugene (jno) Dvurechenski } 2161a6e2f683SEugene (jno) Dvurechenski 2162eaa78f34SDavid Hildenbrand static void sca_add_vcpu(struct kvm_vcpu *vcpu) 2163a6e2f683SEugene (jno) Dvurechenski { 2164a6940674SDavid Hildenbrand if (!kvm_s390_use_sca_entries()) { 2165a6940674SDavid Hildenbrand struct bsca_block *sca = vcpu->kvm->arch.sca; 2166a6940674SDavid Hildenbrand 2167a6940674SDavid Hildenbrand /* we still need the basic sca for the ipte control */ 2168a6940674SDavid Hildenbrand vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32); 2169a6940674SDavid Hildenbrand vcpu->arch.sie_block->scaol = (__u32)(__u64)sca; 2170f07afa04SDavid Hildenbrand return; 2171a6940674SDavid Hildenbrand } 2172eaa78f34SDavid Hildenbrand read_lock(&vcpu->kvm->arch.sca_lock); 2173eaa78f34SDavid Hildenbrand if (vcpu->kvm->arch.use_esca) { 2174eaa78f34SDavid Hildenbrand struct esca_block *sca = vcpu->kvm->arch.sca; 21757d43bafcSEugene (jno) Dvurechenski 2176eaa78f34SDavid Hildenbrand sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block; 21777d43bafcSEugene (jno) Dvurechenski vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32); 21787d43bafcSEugene (jno) Dvurechenski vcpu->arch.sie_block->scaol = (__u32)(__u64)sca & ~0x3fU; 21790c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb2 |= ECB2_ESCA; 2180eaa78f34SDavid Hildenbrand set_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn); 21817d43bafcSEugene (jno) Dvurechenski } else { 2182eaa78f34SDavid Hildenbrand struct bsca_block *sca = vcpu->kvm->arch.sca; 2183a6e2f683SEugene (jno) Dvurechenski 2184eaa78f34SDavid Hildenbrand sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block; 2185a6e2f683SEugene (jno) Dvurechenski vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32); 2186a6e2f683SEugene (jno) Dvurechenski vcpu->arch.sie_block->scaol = (__u32)(__u64)sca; 2187eaa78f34SDavid Hildenbrand set_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn); 2188a6e2f683SEugene (jno) Dvurechenski } 2189eaa78f34SDavid Hildenbrand read_unlock(&vcpu->kvm->arch.sca_lock); 21905e044315SEugene (jno) Dvurechenski } 21915e044315SEugene (jno) Dvurechenski 21925e044315SEugene (jno) Dvurechenski /* Basic SCA to Extended SCA data copy routines */ 21935e044315SEugene (jno) Dvurechenski static inline void sca_copy_entry(struct esca_entry *d, struct bsca_entry *s) 21945e044315SEugene (jno) Dvurechenski { 21955e044315SEugene (jno) Dvurechenski d->sda = s->sda; 21965e044315SEugene (jno) Dvurechenski d->sigp_ctrl.c = s->sigp_ctrl.c; 21975e044315SEugene (jno) Dvurechenski d->sigp_ctrl.scn = s->sigp_ctrl.scn; 21985e044315SEugene (jno) Dvurechenski } 21995e044315SEugene (jno) Dvurechenski 22005e044315SEugene (jno) Dvurechenski static void sca_copy_b_to_e(struct esca_block *d, struct bsca_block *s) 22015e044315SEugene (jno) Dvurechenski { 22025e044315SEugene (jno) Dvurechenski int i; 22035e044315SEugene (jno) Dvurechenski 22045e044315SEugene (jno) Dvurechenski d->ipte_control = s->ipte_control; 22055e044315SEugene (jno) Dvurechenski d->mcn[0] = s->mcn; 22065e044315SEugene (jno) Dvurechenski for (i = 0; i < KVM_S390_BSCA_CPU_SLOTS; i++) 22075e044315SEugene (jno) Dvurechenski sca_copy_entry(&d->cpu[i], &s->cpu[i]); 22085e044315SEugene (jno) Dvurechenski } 22095e044315SEugene (jno) Dvurechenski 22105e044315SEugene (jno) Dvurechenski static int sca_switch_to_extended(struct kvm *kvm) 22115e044315SEugene (jno) Dvurechenski { 22125e044315SEugene (jno) Dvurechenski struct bsca_block *old_sca = kvm->arch.sca; 22135e044315SEugene (jno) Dvurechenski struct esca_block *new_sca; 22145e044315SEugene (jno) Dvurechenski struct kvm_vcpu *vcpu; 22155e044315SEugene (jno) Dvurechenski unsigned int vcpu_idx; 22165e044315SEugene (jno) Dvurechenski u32 scaol, scaoh; 22175e044315SEugene (jno) Dvurechenski 22185e044315SEugene (jno) Dvurechenski new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL|__GFP_ZERO); 22195e044315SEugene (jno) Dvurechenski if (!new_sca) 22205e044315SEugene (jno) Dvurechenski return -ENOMEM; 22215e044315SEugene (jno) Dvurechenski 22225e044315SEugene (jno) Dvurechenski scaoh = (u32)((u64)(new_sca) >> 32); 22235e044315SEugene (jno) Dvurechenski scaol = (u32)(u64)(new_sca) & ~0x3fU; 22245e044315SEugene (jno) Dvurechenski 22255e044315SEugene (jno) Dvurechenski kvm_s390_vcpu_block_all(kvm); 22265e044315SEugene (jno) Dvurechenski write_lock(&kvm->arch.sca_lock); 22275e044315SEugene (jno) Dvurechenski 22285e044315SEugene (jno) Dvurechenski sca_copy_b_to_e(new_sca, old_sca); 22295e044315SEugene (jno) Dvurechenski 22305e044315SEugene (jno) Dvurechenski kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) { 22315e044315SEugene (jno) Dvurechenski vcpu->arch.sie_block->scaoh = scaoh; 22325e044315SEugene (jno) Dvurechenski vcpu->arch.sie_block->scaol = scaol; 22330c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb2 |= ECB2_ESCA; 22345e044315SEugene (jno) Dvurechenski } 22355e044315SEugene (jno) Dvurechenski kvm->arch.sca = new_sca; 22365e044315SEugene (jno) Dvurechenski kvm->arch.use_esca = 1; 22375e044315SEugene (jno) Dvurechenski 22385e044315SEugene (jno) Dvurechenski write_unlock(&kvm->arch.sca_lock); 22395e044315SEugene (jno) Dvurechenski kvm_s390_vcpu_unblock_all(kvm); 22405e044315SEugene (jno) Dvurechenski 22415e044315SEugene (jno) Dvurechenski free_page((unsigned long)old_sca); 22425e044315SEugene (jno) Dvurechenski 22438335713aSChristian Borntraeger VM_EVENT(kvm, 2, "Switched to ESCA (0x%pK -> 0x%pK)", 22448335713aSChristian Borntraeger old_sca, kvm->arch.sca); 22455e044315SEugene (jno) Dvurechenski return 0; 22467d43bafcSEugene (jno) Dvurechenski } 2247a6e2f683SEugene (jno) Dvurechenski 2248a6e2f683SEugene (jno) Dvurechenski static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id) 2249a6e2f683SEugene (jno) Dvurechenski { 22505e044315SEugene (jno) Dvurechenski int rc; 22515e044315SEugene (jno) Dvurechenski 2252a6940674SDavid Hildenbrand if (!kvm_s390_use_sca_entries()) { 2253a6940674SDavid Hildenbrand if (id < KVM_MAX_VCPUS) 2254a6940674SDavid Hildenbrand return true; 2255a6940674SDavid Hildenbrand return false; 2256a6940674SDavid Hildenbrand } 22575e044315SEugene (jno) Dvurechenski if (id < KVM_S390_BSCA_CPU_SLOTS) 22585e044315SEugene (jno) Dvurechenski return true; 225976a6dd72SDavid Hildenbrand if (!sclp.has_esca || !sclp.has_64bscao) 22605e044315SEugene (jno) Dvurechenski return false; 22615e044315SEugene (jno) Dvurechenski 22625e044315SEugene (jno) Dvurechenski mutex_lock(&kvm->lock); 22635e044315SEugene (jno) Dvurechenski rc = kvm->arch.use_esca ? 0 : sca_switch_to_extended(kvm); 22645e044315SEugene (jno) Dvurechenski mutex_unlock(&kvm->lock); 22655e044315SEugene (jno) Dvurechenski 22665e044315SEugene (jno) Dvurechenski return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS; 2267a6e2f683SEugene (jno) Dvurechenski } 2268a6e2f683SEugene (jno) Dvurechenski 2269dafd032aSDominik Dingel int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) 2270dafd032aSDominik Dingel { 2271dafd032aSDominik Dingel vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; 2272dafd032aSDominik Dingel kvm_clear_async_pf_completion_queue(vcpu); 227359674c1aSChristian Borntraeger vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX | 227459674c1aSChristian Borntraeger KVM_SYNC_GPRS | 22759eed0735SChristian Borntraeger KVM_SYNC_ACRS | 2276b028ee3eSDavid Hildenbrand KVM_SYNC_CRS | 2277b028ee3eSDavid Hildenbrand KVM_SYNC_ARCH0 | 2278b028ee3eSDavid Hildenbrand KVM_SYNC_PFAULT; 227975a4615cSJulius Niedworok kvm_s390_set_prefix(vcpu, 0); 2280c6e5f166SFan Zhang if (test_kvm_facility(vcpu->kvm, 64)) 2281c6e5f166SFan Zhang vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB; 228235b3fde6SChristian Borntraeger if (test_kvm_facility(vcpu->kvm, 82)) 228335b3fde6SChristian Borntraeger vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC; 22844e0b1ab7SFan Zhang if (test_kvm_facility(vcpu->kvm, 133)) 22854e0b1ab7SFan Zhang vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB; 2286f6aa6dc4SDavid Hildenbrand /* fprs can be synchronized via vrs, even if the guest has no vx. With 2287f6aa6dc4SDavid Hildenbrand * MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format. 2288f6aa6dc4SDavid Hildenbrand */ 2289f6aa6dc4SDavid Hildenbrand if (MACHINE_HAS_VX) 229068c55750SEric Farman vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS; 22916fd8e67dSDavid Hildenbrand else 22926fd8e67dSDavid Hildenbrand vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS; 2293dafd032aSDominik Dingel 2294dafd032aSDominik Dingel if (kvm_is_ucontrol(vcpu->kvm)) 2295dafd032aSDominik Dingel return __kvm_ucontrol_vcpu_init(vcpu); 2296dafd032aSDominik Dingel 2297b0c632dbSHeiko Carstens return 0; 2298b0c632dbSHeiko Carstens } 2299b0c632dbSHeiko Carstens 2300db0758b2SDavid Hildenbrand /* needs disabled preemption to protect from TOD sync and vcpu_load/put */ 2301db0758b2SDavid Hildenbrand static void __start_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2302db0758b2SDavid Hildenbrand { 2303db0758b2SDavid Hildenbrand WARN_ON_ONCE(vcpu->arch.cputm_start != 0); 23049c23a131SDavid Hildenbrand raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount); 2305db0758b2SDavid Hildenbrand vcpu->arch.cputm_start = get_tod_clock_fast(); 23069c23a131SDavid Hildenbrand raw_write_seqcount_end(&vcpu->arch.cputm_seqcount); 2307db0758b2SDavid Hildenbrand } 2308db0758b2SDavid Hildenbrand 2309db0758b2SDavid Hildenbrand /* needs disabled preemption to protect from TOD sync and vcpu_load/put */ 2310db0758b2SDavid Hildenbrand static void __stop_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2311db0758b2SDavid Hildenbrand { 2312db0758b2SDavid Hildenbrand WARN_ON_ONCE(vcpu->arch.cputm_start == 0); 23139c23a131SDavid Hildenbrand raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount); 2314db0758b2SDavid Hildenbrand vcpu->arch.sie_block->cputm -= get_tod_clock_fast() - vcpu->arch.cputm_start; 2315db0758b2SDavid Hildenbrand vcpu->arch.cputm_start = 0; 23169c23a131SDavid Hildenbrand raw_write_seqcount_end(&vcpu->arch.cputm_seqcount); 2317db0758b2SDavid Hildenbrand } 2318db0758b2SDavid Hildenbrand 2319db0758b2SDavid Hildenbrand /* needs disabled preemption to protect from TOD sync and vcpu_load/put */ 2320db0758b2SDavid Hildenbrand static void __enable_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2321db0758b2SDavid Hildenbrand { 2322db0758b2SDavid Hildenbrand WARN_ON_ONCE(vcpu->arch.cputm_enabled); 2323db0758b2SDavid Hildenbrand vcpu->arch.cputm_enabled = true; 2324db0758b2SDavid Hildenbrand __start_cpu_timer_accounting(vcpu); 2325db0758b2SDavid Hildenbrand } 2326db0758b2SDavid Hildenbrand 2327db0758b2SDavid Hildenbrand /* needs disabled preemption to protect from TOD sync and vcpu_load/put */ 2328db0758b2SDavid Hildenbrand static void __disable_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2329db0758b2SDavid Hildenbrand { 2330db0758b2SDavid Hildenbrand WARN_ON_ONCE(!vcpu->arch.cputm_enabled); 2331db0758b2SDavid Hildenbrand __stop_cpu_timer_accounting(vcpu); 2332db0758b2SDavid Hildenbrand vcpu->arch.cputm_enabled = false; 2333db0758b2SDavid Hildenbrand } 2334db0758b2SDavid Hildenbrand 2335db0758b2SDavid Hildenbrand static void enable_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2336db0758b2SDavid Hildenbrand { 2337db0758b2SDavid Hildenbrand preempt_disable(); /* protect from TOD sync and vcpu_load/put */ 2338db0758b2SDavid Hildenbrand __enable_cpu_timer_accounting(vcpu); 2339db0758b2SDavid Hildenbrand preempt_enable(); 2340db0758b2SDavid Hildenbrand } 2341db0758b2SDavid Hildenbrand 2342db0758b2SDavid Hildenbrand static void disable_cpu_timer_accounting(struct kvm_vcpu *vcpu) 2343db0758b2SDavid Hildenbrand { 2344db0758b2SDavid Hildenbrand preempt_disable(); /* protect from TOD sync and vcpu_load/put */ 2345db0758b2SDavid Hildenbrand __disable_cpu_timer_accounting(vcpu); 2346db0758b2SDavid Hildenbrand preempt_enable(); 2347db0758b2SDavid Hildenbrand } 2348db0758b2SDavid Hildenbrand 23494287f247SDavid Hildenbrand /* set the cpu timer - may only be called from the VCPU thread itself */ 23504287f247SDavid Hildenbrand void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm) 23514287f247SDavid Hildenbrand { 2352db0758b2SDavid Hildenbrand preempt_disable(); /* protect from TOD sync and vcpu_load/put */ 23539c23a131SDavid Hildenbrand raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount); 2354db0758b2SDavid Hildenbrand if (vcpu->arch.cputm_enabled) 2355db0758b2SDavid Hildenbrand vcpu->arch.cputm_start = get_tod_clock_fast(); 23564287f247SDavid Hildenbrand vcpu->arch.sie_block->cputm = cputm; 23579c23a131SDavid Hildenbrand raw_write_seqcount_end(&vcpu->arch.cputm_seqcount); 2358db0758b2SDavid Hildenbrand preempt_enable(); 23594287f247SDavid Hildenbrand } 23604287f247SDavid Hildenbrand 2361db0758b2SDavid Hildenbrand /* update and get the cpu timer - can also be called from other VCPU threads */ 23624287f247SDavid Hildenbrand __u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu) 23634287f247SDavid Hildenbrand { 23649c23a131SDavid Hildenbrand unsigned int seq; 2365db0758b2SDavid Hildenbrand __u64 value; 2366db0758b2SDavid Hildenbrand 2367db0758b2SDavid Hildenbrand if (unlikely(!vcpu->arch.cputm_enabled)) 23684287f247SDavid Hildenbrand return vcpu->arch.sie_block->cputm; 2369db0758b2SDavid Hildenbrand 23709c23a131SDavid Hildenbrand preempt_disable(); /* protect from TOD sync and vcpu_load/put */ 23719c23a131SDavid Hildenbrand do { 23729c23a131SDavid Hildenbrand seq = raw_read_seqcount(&vcpu->arch.cputm_seqcount); 23739c23a131SDavid Hildenbrand /* 23749c23a131SDavid Hildenbrand * If the writer would ever execute a read in the critical 23759c23a131SDavid Hildenbrand * section, e.g. in irq context, we have a deadlock. 23769c23a131SDavid Hildenbrand */ 23779c23a131SDavid Hildenbrand WARN_ON_ONCE((seq & 1) && smp_processor_id() == vcpu->cpu); 2378db0758b2SDavid Hildenbrand value = vcpu->arch.sie_block->cputm; 23799c23a131SDavid Hildenbrand /* if cputm_start is 0, accounting is being started/stopped */ 23809c23a131SDavid Hildenbrand if (likely(vcpu->arch.cputm_start)) 2381db0758b2SDavid Hildenbrand value -= get_tod_clock_fast() - vcpu->arch.cputm_start; 23829c23a131SDavid Hildenbrand } while (read_seqcount_retry(&vcpu->arch.cputm_seqcount, seq & ~1)); 23839c23a131SDavid Hildenbrand preempt_enable(); 2384db0758b2SDavid Hildenbrand return value; 23854287f247SDavid Hildenbrand } 23864287f247SDavid Hildenbrand 2387b0c632dbSHeiko Carstens void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) 2388b0c632dbSHeiko Carstens { 23899977e886SHendrik Brueckner 239037d9df98SDavid Hildenbrand gmap_enable(vcpu->arch.enabled_gmap); 2391ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_RUNNING); 23925ebda316SDavid Hildenbrand if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu)) 2393db0758b2SDavid Hildenbrand __start_cpu_timer_accounting(vcpu); 239401a745acSDavid Hildenbrand vcpu->cpu = cpu; 2395b0c632dbSHeiko Carstens } 2396b0c632dbSHeiko Carstens 2397b0c632dbSHeiko Carstens void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) 2398b0c632dbSHeiko Carstens { 239901a745acSDavid Hildenbrand vcpu->cpu = -1; 24005ebda316SDavid Hildenbrand if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu)) 2401db0758b2SDavid Hildenbrand __stop_cpu_timer_accounting(vcpu); 24029daecfc6SDavid Hildenbrand kvm_s390_clear_cpuflags(vcpu, CPUSTAT_RUNNING); 240337d9df98SDavid Hildenbrand vcpu->arch.enabled_gmap = gmap_get_enabled(); 240437d9df98SDavid Hildenbrand gmap_disable(vcpu->arch.enabled_gmap); 24059977e886SHendrik Brueckner 2406b0c632dbSHeiko Carstens } 2407b0c632dbSHeiko Carstens 2408b0c632dbSHeiko Carstens static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu) 2409b0c632dbSHeiko Carstens { 2410b0c632dbSHeiko Carstens /* this equals initial cpu reset in pop, but we don't switch to ESA */ 2411b0c632dbSHeiko Carstens vcpu->arch.sie_block->gpsw.mask = 0UL; 2412b0c632dbSHeiko Carstens vcpu->arch.sie_block->gpsw.addr = 0UL; 24138d26cf7bSChristian Borntraeger kvm_s390_set_prefix(vcpu, 0); 24144287f247SDavid Hildenbrand kvm_s390_set_cpu_timer(vcpu, 0); 2415b0c632dbSHeiko Carstens vcpu->arch.sie_block->ckc = 0UL; 2416b0c632dbSHeiko Carstens vcpu->arch.sie_block->todpr = 0; 2417b0c632dbSHeiko Carstens memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64)); 2418b0c632dbSHeiko Carstens vcpu->arch.sie_block->gcr[0] = 0xE0UL; 2419b0c632dbSHeiko Carstens vcpu->arch.sie_block->gcr[14] = 0xC2000000UL; 24209abc2a08SDavid Hildenbrand /* make sure the new fpc will be lazily loaded */ 24219abc2a08SDavid Hildenbrand save_fpu_regs(); 24229abc2a08SDavid Hildenbrand current->thread.fpu.fpc = 0; 2423b0c632dbSHeiko Carstens vcpu->arch.sie_block->gbea = 1; 2424672550fbSChristian Borntraeger vcpu->arch.sie_block->pp = 0; 242535b3fde6SChristian Borntraeger vcpu->arch.sie_block->fpf &= ~FPF_BPBC; 24263c038e6bSDominik Dingel vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID; 24273c038e6bSDominik Dingel kvm_clear_async_pf_completion_queue(vcpu); 24286352e4d2SDavid Hildenbrand if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) 24296852d7b6SDavid Hildenbrand kvm_s390_vcpu_stop(vcpu); 24302ed10cc1SJens Freimann kvm_s390_clear_local_irqs(vcpu); 2431b0c632dbSHeiko Carstens } 2432b0c632dbSHeiko Carstens 243331928aa5SDominik Dingel void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu) 243442897d86SMarcelo Tosatti { 243572f25020SJason J. Herne mutex_lock(&vcpu->kvm->lock); 2436fdf03650SFan Zhang preempt_disable(); 243772f25020SJason J. Herne vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch; 2438d16b52cbSDavid Hildenbrand vcpu->arch.sie_block->epdx = vcpu->kvm->arch.epdx; 2439fdf03650SFan Zhang preempt_enable(); 244072f25020SJason J. Herne mutex_unlock(&vcpu->kvm->lock); 244125508824SDavid Hildenbrand if (!kvm_is_ucontrol(vcpu->kvm)) { 2442dafd032aSDominik Dingel vcpu->arch.gmap = vcpu->kvm->arch.gmap; 2443eaa78f34SDavid Hildenbrand sca_add_vcpu(vcpu); 244425508824SDavid Hildenbrand } 24456502a34cSDavid Hildenbrand if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0) 24466502a34cSDavid Hildenbrand vcpu->arch.sie_block->ictl |= ICTL_OPEREXC; 244737d9df98SDavid Hildenbrand /* make vcpu_load load the right gmap on the first trigger */ 244837d9df98SDavid Hildenbrand vcpu->arch.enabled_gmap = vcpu->arch.gmap; 244942897d86SMarcelo Tosatti } 245042897d86SMarcelo Tosatti 24515102ee87STony Krowiak static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu) 24525102ee87STony Krowiak { 24539d8d5786SMichael Mueller if (!test_kvm_facility(vcpu->kvm, 76)) 24545102ee87STony Krowiak return; 24555102ee87STony Krowiak 2456a374e892STony Krowiak vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA); 2457a374e892STony Krowiak 2458a374e892STony Krowiak if (vcpu->kvm->arch.crypto.aes_kw) 2459a374e892STony Krowiak vcpu->arch.sie_block->ecb3 |= ECB3_AES; 2460a374e892STony Krowiak if (vcpu->kvm->arch.crypto.dea_kw) 2461a374e892STony Krowiak vcpu->arch.sie_block->ecb3 |= ECB3_DEA; 2462a374e892STony Krowiak 24635102ee87STony Krowiak vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd; 24645102ee87STony Krowiak } 24655102ee87STony Krowiak 2466b31605c1SDominik Dingel void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu) 2467b31605c1SDominik Dingel { 2468b31605c1SDominik Dingel free_page(vcpu->arch.sie_block->cbrlo); 2469b31605c1SDominik Dingel vcpu->arch.sie_block->cbrlo = 0; 2470b31605c1SDominik Dingel } 2471b31605c1SDominik Dingel 2472b31605c1SDominik Dingel int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu) 2473b31605c1SDominik Dingel { 2474b31605c1SDominik Dingel vcpu->arch.sie_block->cbrlo = get_zeroed_page(GFP_KERNEL); 2475b31605c1SDominik Dingel if (!vcpu->arch.sie_block->cbrlo) 2476b31605c1SDominik Dingel return -ENOMEM; 2477b31605c1SDominik Dingel return 0; 2478b31605c1SDominik Dingel } 2479b31605c1SDominik Dingel 248091520f1aSMichael Mueller static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu) 248191520f1aSMichael Mueller { 248291520f1aSMichael Mueller struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model; 248391520f1aSMichael Mueller 248491520f1aSMichael Mueller vcpu->arch.sie_block->ibc = model->ibc; 248580bc79dcSDavid Hildenbrand if (test_kvm_facility(vcpu->kvm, 7)) 2486c54f0d6aSDavid Hildenbrand vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list; 248791520f1aSMichael Mueller } 248891520f1aSMichael Mueller 2489b0c632dbSHeiko Carstens int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) 2490b0c632dbSHeiko Carstens { 2491b31605c1SDominik Dingel int rc = 0; 2492b31288faSKonstantin Weitz 24939e6dabefSCornelia Huck atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | 24949e6dabefSCornelia Huck CPUSTAT_SM | 2495a4a4f191SGuenther Hutzl CPUSTAT_STOPPED); 2496a4a4f191SGuenther Hutzl 249753df84f8SGuenther Hutzl if (test_kvm_facility(vcpu->kvm, 78)) 2498ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_GED2); 249953df84f8SGuenther Hutzl else if (test_kvm_facility(vcpu->kvm, 8)) 2500ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_GED); 2501a4a4f191SGuenther Hutzl 250291520f1aSMichael Mueller kvm_s390_vcpu_setup_model(vcpu); 250391520f1aSMichael Mueller 2504bdab09f3SDavid Hildenbrand /* pgste_set_pte has special handling for !MACHINE_HAS_ESOP */ 2505bdab09f3SDavid Hildenbrand if (MACHINE_HAS_ESOP) 25060c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb |= ECB_HOSTPROTINT; 2507bd50e8ecSDavid Hildenbrand if (test_kvm_facility(vcpu->kvm, 9)) 25080c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb |= ECB_SRSI; 2509f597d24eSDavid Hildenbrand if (test_kvm_facility(vcpu->kvm, 73)) 25100c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb |= ECB_TE; 25117feb6bb8SMichael Mueller 2512c9f0a2b8SJanosch Frank if (test_kvm_facility(vcpu->kvm, 8) && vcpu->kvm->arch.use_pfmfi) 25130c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb2 |= ECB2_PFMFI; 2514cd1836f5SJanosch Frank if (test_kvm_facility(vcpu->kvm, 130)) 25150c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb2 |= ECB2_IEP; 25160c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca = ECA_MVPGI | ECA_PROTEXCI; 251748ee7d3aSDavid Hildenbrand if (sclp.has_cei) 25180c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca |= ECA_CEI; 251911ad65b7SDavid Hildenbrand if (sclp.has_ib) 25200c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca |= ECA_IB; 252137c5f6c8SDavid Hildenbrand if (sclp.has_siif) 25220c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca |= ECA_SII; 252337c5f6c8SDavid Hildenbrand if (sclp.has_sigpif) 25240c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca |= ECA_SIGPI; 252518280d8bSMichael Mueller if (test_kvm_facility(vcpu->kvm, 129)) { 25260c9d8683SDavid Hildenbrand vcpu->arch.sie_block->eca |= ECA_VX; 25270c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT; 252813211ea7SEric Farman } 25298fa1696eSCollin L. Walling if (test_kvm_facility(vcpu->kvm, 139)) 25308fa1696eSCollin L. Walling vcpu->arch.sie_block->ecd |= ECD_MEF; 25318fa1696eSCollin L. Walling 2532d7c5cb01SMichael Mueller if (vcpu->arch.sie_block->gd) { 2533d7c5cb01SMichael Mueller vcpu->arch.sie_block->eca |= ECA_AIV; 2534d7c5cb01SMichael Mueller VCPU_EVENT(vcpu, 3, "AIV gisa format-%u enabled for cpu %03u", 2535d7c5cb01SMichael Mueller vcpu->arch.sie_block->gd & 0x3, vcpu->vcpu_id); 2536d7c5cb01SMichael Mueller } 25374e0b1ab7SFan Zhang vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx) 25384e0b1ab7SFan Zhang | SDNXC; 2539c6e5f166SFan Zhang vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb; 2540730cd632SFarhan Ali 2541730cd632SFarhan Ali if (sclp.has_kss) 2542ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_KSS); 2543730cd632SFarhan Ali else 2544492d8642SThomas Huth vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE; 25455a5e6536SMatthew Rosato 2546e6db1d61SDominik Dingel if (vcpu->kvm->arch.use_cmma) { 2547b31605c1SDominik Dingel rc = kvm_s390_vcpu_setup_cmma(vcpu); 2548b31605c1SDominik Dingel if (rc) 2549b31605c1SDominik Dingel return rc; 2550b31288faSKonstantin Weitz } 25510ac96cafSDavid Hildenbrand hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 2552ca872302SChristian Borntraeger vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup; 25539d8d5786SMichael Mueller 25545102ee87STony Krowiak kvm_s390_vcpu_crypto_setup(vcpu); 25555102ee87STony Krowiak 2556b31605c1SDominik Dingel return rc; 2557b0c632dbSHeiko Carstens } 2558b0c632dbSHeiko Carstens 2559b0c632dbSHeiko Carstens struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, 2560b0c632dbSHeiko Carstens unsigned int id) 2561b0c632dbSHeiko Carstens { 25624d47555aSCarsten Otte struct kvm_vcpu *vcpu; 25637feb6bb8SMichael Mueller struct sie_page *sie_page; 25644d47555aSCarsten Otte int rc = -EINVAL; 2565b0c632dbSHeiko Carstens 25664215825eSDavid Hildenbrand if (!kvm_is_ucontrol(kvm) && !sca_can_add_vcpu(kvm, id)) 25674d47555aSCarsten Otte goto out; 25684d47555aSCarsten Otte 25694d47555aSCarsten Otte rc = -ENOMEM; 25704d47555aSCarsten Otte 2571b110feafSMichael Mueller vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); 2572b0c632dbSHeiko Carstens if (!vcpu) 25734d47555aSCarsten Otte goto out; 2574b0c632dbSHeiko Carstens 2575da72ca4dSQingFeng Hao BUILD_BUG_ON(sizeof(struct sie_page) != 4096); 25767feb6bb8SMichael Mueller sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL); 25777feb6bb8SMichael Mueller if (!sie_page) 2578b0c632dbSHeiko Carstens goto out_free_cpu; 2579b0c632dbSHeiko Carstens 25807feb6bb8SMichael Mueller vcpu->arch.sie_block = &sie_page->sie_block; 25817feb6bb8SMichael Mueller vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb; 25827feb6bb8SMichael Mueller 2583efed1104SDavid Hildenbrand /* the real guest size will always be smaller than msl */ 2584efed1104SDavid Hildenbrand vcpu->arch.sie_block->mso = 0; 2585efed1104SDavid Hildenbrand vcpu->arch.sie_block->msl = sclp.hamax; 2586efed1104SDavid Hildenbrand 2587b0c632dbSHeiko Carstens vcpu->arch.sie_block->icpua = id; 2588ba5c1e9bSCarsten Otte spin_lock_init(&vcpu->arch.local_int.lock); 2589d7c5cb01SMichael Mueller vcpu->arch.sie_block->gd = (u32)(u64)kvm->arch.gisa; 25904b9f9525SMichael Mueller if (vcpu->arch.sie_block->gd && sclp.has_gisaf) 25914b9f9525SMichael Mueller vcpu->arch.sie_block->gd |= GISA_FORMAT1; 25929c23a131SDavid Hildenbrand seqcount_init(&vcpu->arch.cputm_seqcount); 2593ba5c1e9bSCarsten Otte 2594b0c632dbSHeiko Carstens rc = kvm_vcpu_init(vcpu, kvm, id); 2595b0c632dbSHeiko Carstens if (rc) 25969abc2a08SDavid Hildenbrand goto out_free_sie_block; 25978335713aSChristian Borntraeger VM_EVENT(kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK", id, vcpu, 2598b0c632dbSHeiko Carstens vcpu->arch.sie_block); 2599ade38c31SCornelia Huck trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block); 2600b0c632dbSHeiko Carstens 2601b0c632dbSHeiko Carstens return vcpu; 26027b06bf2fSWei Yongjun out_free_sie_block: 26037b06bf2fSWei Yongjun free_page((unsigned long)(vcpu->arch.sie_block)); 2604b0c632dbSHeiko Carstens out_free_cpu: 2605b110feafSMichael Mueller kmem_cache_free(kvm_vcpu_cache, vcpu); 26064d47555aSCarsten Otte out: 2607b0c632dbSHeiko Carstens return ERR_PTR(rc); 2608b0c632dbSHeiko Carstens } 2609b0c632dbSHeiko Carstens 2610b0c632dbSHeiko Carstens int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu) 2611b0c632dbSHeiko Carstens { 26129a022067SDavid Hildenbrand return kvm_s390_vcpu_has_irq(vcpu, 0); 2613b0c632dbSHeiko Carstens } 2614b0c632dbSHeiko Carstens 2615199b5763SLongpeng(Mike) bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu) 2616199b5763SLongpeng(Mike) { 26170546c63dSLongpeng(Mike) return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE); 2618199b5763SLongpeng(Mike) } 2619199b5763SLongpeng(Mike) 262027406cd5SChristian Borntraeger void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu) 262149b99e1eSChristian Borntraeger { 2622805de8f4SPeter Zijlstra atomic_or(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20); 262361a6df54SDavid Hildenbrand exit_sie(vcpu); 262449b99e1eSChristian Borntraeger } 262549b99e1eSChristian Borntraeger 262627406cd5SChristian Borntraeger void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu) 262749b99e1eSChristian Borntraeger { 2628805de8f4SPeter Zijlstra atomic_andnot(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20); 262949b99e1eSChristian Borntraeger } 263049b99e1eSChristian Borntraeger 26318e236546SChristian Borntraeger static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu) 26328e236546SChristian Borntraeger { 2633805de8f4SPeter Zijlstra atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20); 263461a6df54SDavid Hildenbrand exit_sie(vcpu); 26358e236546SChristian Borntraeger } 26368e236546SChristian Borntraeger 26378e236546SChristian Borntraeger static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu) 26388e236546SChristian Borntraeger { 26399bf9fde2SJason J. Herne atomic_andnot(PROG_REQUEST, &vcpu->arch.sie_block->prog20); 26408e236546SChristian Borntraeger } 26418e236546SChristian Borntraeger 264249b99e1eSChristian Borntraeger /* 264349b99e1eSChristian Borntraeger * Kick a guest cpu out of SIE and wait until SIE is not running. 264449b99e1eSChristian Borntraeger * If the CPU is not running (e.g. waiting as idle) the function will 264549b99e1eSChristian Borntraeger * return immediately. */ 264649b99e1eSChristian Borntraeger void exit_sie(struct kvm_vcpu *vcpu) 264749b99e1eSChristian Borntraeger { 2648ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT); 264949b99e1eSChristian Borntraeger while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE) 265049b99e1eSChristian Borntraeger cpu_relax(); 265149b99e1eSChristian Borntraeger } 265249b99e1eSChristian Borntraeger 26538e236546SChristian Borntraeger /* Kick a guest cpu out of SIE to process a request synchronously */ 26548e236546SChristian Borntraeger void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu) 265549b99e1eSChristian Borntraeger { 26568e236546SChristian Borntraeger kvm_make_request(req, vcpu); 26578e236546SChristian Borntraeger kvm_s390_vcpu_request(vcpu); 265849b99e1eSChristian Borntraeger } 265949b99e1eSChristian Borntraeger 2660414d3b07SMartin Schwidefsky static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start, 2661414d3b07SMartin Schwidefsky unsigned long end) 26622c70fe44SChristian Borntraeger { 26632c70fe44SChristian Borntraeger struct kvm *kvm = gmap->private; 26642c70fe44SChristian Borntraeger struct kvm_vcpu *vcpu; 2665414d3b07SMartin Schwidefsky unsigned long prefix; 2666414d3b07SMartin Schwidefsky int i; 26672c70fe44SChristian Borntraeger 266865d0b0d4SDavid Hildenbrand if (gmap_is_shadow(gmap)) 266965d0b0d4SDavid Hildenbrand return; 2670414d3b07SMartin Schwidefsky if (start >= 1UL << 31) 2671414d3b07SMartin Schwidefsky /* We are only interested in prefix pages */ 2672414d3b07SMartin Schwidefsky return; 26732c70fe44SChristian Borntraeger kvm_for_each_vcpu(i, vcpu, kvm) { 26742c70fe44SChristian Borntraeger /* match against both prefix pages */ 2675414d3b07SMartin Schwidefsky prefix = kvm_s390_get_prefix(vcpu); 2676414d3b07SMartin Schwidefsky if (prefix <= end && start <= prefix + 2*PAGE_SIZE - 1) { 2677414d3b07SMartin Schwidefsky VCPU_EVENT(vcpu, 2, "gmap notifier for %lx-%lx", 2678414d3b07SMartin Schwidefsky start, end); 26798e236546SChristian Borntraeger kvm_s390_sync_request(KVM_REQ_MMU_RELOAD, vcpu); 26802c70fe44SChristian Borntraeger } 26812c70fe44SChristian Borntraeger } 26822c70fe44SChristian Borntraeger } 26832c70fe44SChristian Borntraeger 2684b6d33834SChristoffer Dall int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu) 2685b6d33834SChristoffer Dall { 2686b6d33834SChristoffer Dall /* kvm common code refers to this, but never calls it */ 2687b6d33834SChristoffer Dall BUG(); 2688b6d33834SChristoffer Dall return 0; 2689b6d33834SChristoffer Dall } 2690b6d33834SChristoffer Dall 269114eebd91SCarsten Otte static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu, 269214eebd91SCarsten Otte struct kvm_one_reg *reg) 269314eebd91SCarsten Otte { 269414eebd91SCarsten Otte int r = -EINVAL; 269514eebd91SCarsten Otte 269614eebd91SCarsten Otte switch (reg->id) { 269729b7c71bSCarsten Otte case KVM_REG_S390_TODPR: 269829b7c71bSCarsten Otte r = put_user(vcpu->arch.sie_block->todpr, 269929b7c71bSCarsten Otte (u32 __user *)reg->addr); 270029b7c71bSCarsten Otte break; 270129b7c71bSCarsten Otte case KVM_REG_S390_EPOCHDIFF: 270229b7c71bSCarsten Otte r = put_user(vcpu->arch.sie_block->epoch, 270329b7c71bSCarsten Otte (u64 __user *)reg->addr); 270429b7c71bSCarsten Otte break; 270546a6dd1cSJason J. herne case KVM_REG_S390_CPU_TIMER: 27064287f247SDavid Hildenbrand r = put_user(kvm_s390_get_cpu_timer(vcpu), 270746a6dd1cSJason J. herne (u64 __user *)reg->addr); 270846a6dd1cSJason J. herne break; 270946a6dd1cSJason J. herne case KVM_REG_S390_CLOCK_COMP: 271046a6dd1cSJason J. herne r = put_user(vcpu->arch.sie_block->ckc, 271146a6dd1cSJason J. herne (u64 __user *)reg->addr); 271246a6dd1cSJason J. herne break; 2713536336c2SDominik Dingel case KVM_REG_S390_PFTOKEN: 2714536336c2SDominik Dingel r = put_user(vcpu->arch.pfault_token, 2715536336c2SDominik Dingel (u64 __user *)reg->addr); 2716536336c2SDominik Dingel break; 2717536336c2SDominik Dingel case KVM_REG_S390_PFCOMPARE: 2718536336c2SDominik Dingel r = put_user(vcpu->arch.pfault_compare, 2719536336c2SDominik Dingel (u64 __user *)reg->addr); 2720536336c2SDominik Dingel break; 2721536336c2SDominik Dingel case KVM_REG_S390_PFSELECT: 2722536336c2SDominik Dingel r = put_user(vcpu->arch.pfault_select, 2723536336c2SDominik Dingel (u64 __user *)reg->addr); 2724536336c2SDominik Dingel break; 2725672550fbSChristian Borntraeger case KVM_REG_S390_PP: 2726672550fbSChristian Borntraeger r = put_user(vcpu->arch.sie_block->pp, 2727672550fbSChristian Borntraeger (u64 __user *)reg->addr); 2728672550fbSChristian Borntraeger break; 2729afa45ff5SChristian Borntraeger case KVM_REG_S390_GBEA: 2730afa45ff5SChristian Borntraeger r = put_user(vcpu->arch.sie_block->gbea, 2731afa45ff5SChristian Borntraeger (u64 __user *)reg->addr); 2732afa45ff5SChristian Borntraeger break; 273314eebd91SCarsten Otte default: 273414eebd91SCarsten Otte break; 273514eebd91SCarsten Otte } 273614eebd91SCarsten Otte 273714eebd91SCarsten Otte return r; 273814eebd91SCarsten Otte } 273914eebd91SCarsten Otte 274014eebd91SCarsten Otte static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu, 274114eebd91SCarsten Otte struct kvm_one_reg *reg) 274214eebd91SCarsten Otte { 274314eebd91SCarsten Otte int r = -EINVAL; 27444287f247SDavid Hildenbrand __u64 val; 274514eebd91SCarsten Otte 274614eebd91SCarsten Otte switch (reg->id) { 274729b7c71bSCarsten Otte case KVM_REG_S390_TODPR: 274829b7c71bSCarsten Otte r = get_user(vcpu->arch.sie_block->todpr, 274929b7c71bSCarsten Otte (u32 __user *)reg->addr); 275029b7c71bSCarsten Otte break; 275129b7c71bSCarsten Otte case KVM_REG_S390_EPOCHDIFF: 275229b7c71bSCarsten Otte r = get_user(vcpu->arch.sie_block->epoch, 275329b7c71bSCarsten Otte (u64 __user *)reg->addr); 275429b7c71bSCarsten Otte break; 275546a6dd1cSJason J. herne case KVM_REG_S390_CPU_TIMER: 27564287f247SDavid Hildenbrand r = get_user(val, (u64 __user *)reg->addr); 27574287f247SDavid Hildenbrand if (!r) 27584287f247SDavid Hildenbrand kvm_s390_set_cpu_timer(vcpu, val); 275946a6dd1cSJason J. herne break; 276046a6dd1cSJason J. herne case KVM_REG_S390_CLOCK_COMP: 276146a6dd1cSJason J. herne r = get_user(vcpu->arch.sie_block->ckc, 276246a6dd1cSJason J. herne (u64 __user *)reg->addr); 276346a6dd1cSJason J. herne break; 2764536336c2SDominik Dingel case KVM_REG_S390_PFTOKEN: 2765536336c2SDominik Dingel r = get_user(vcpu->arch.pfault_token, 2766536336c2SDominik Dingel (u64 __user *)reg->addr); 27679fbd8082SDavid Hildenbrand if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) 27689fbd8082SDavid Hildenbrand kvm_clear_async_pf_completion_queue(vcpu); 2769536336c2SDominik Dingel break; 2770536336c2SDominik Dingel case KVM_REG_S390_PFCOMPARE: 2771536336c2SDominik Dingel r = get_user(vcpu->arch.pfault_compare, 2772536336c2SDominik Dingel (u64 __user *)reg->addr); 2773536336c2SDominik Dingel break; 2774536336c2SDominik Dingel case KVM_REG_S390_PFSELECT: 2775536336c2SDominik Dingel r = get_user(vcpu->arch.pfault_select, 2776536336c2SDominik Dingel (u64 __user *)reg->addr); 2777536336c2SDominik Dingel break; 2778672550fbSChristian Borntraeger case KVM_REG_S390_PP: 2779672550fbSChristian Borntraeger r = get_user(vcpu->arch.sie_block->pp, 2780672550fbSChristian Borntraeger (u64 __user *)reg->addr); 2781672550fbSChristian Borntraeger break; 2782afa45ff5SChristian Borntraeger case KVM_REG_S390_GBEA: 2783afa45ff5SChristian Borntraeger r = get_user(vcpu->arch.sie_block->gbea, 2784afa45ff5SChristian Borntraeger (u64 __user *)reg->addr); 2785afa45ff5SChristian Borntraeger break; 278614eebd91SCarsten Otte default: 278714eebd91SCarsten Otte break; 278814eebd91SCarsten Otte } 278914eebd91SCarsten Otte 279014eebd91SCarsten Otte return r; 279114eebd91SCarsten Otte } 2792b6d33834SChristoffer Dall 2793b0c632dbSHeiko Carstens static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu) 2794b0c632dbSHeiko Carstens { 2795b0c632dbSHeiko Carstens kvm_s390_vcpu_initial_reset(vcpu); 2796b0c632dbSHeiko Carstens return 0; 2797b0c632dbSHeiko Carstens } 2798b0c632dbSHeiko Carstens 2799b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 2800b0c632dbSHeiko Carstens { 2801875656feSChristoffer Dall vcpu_load(vcpu); 28025a32c1afSChristian Borntraeger memcpy(&vcpu->run->s.regs.gprs, ®s->gprs, sizeof(regs->gprs)); 2803875656feSChristoffer Dall vcpu_put(vcpu); 2804b0c632dbSHeiko Carstens return 0; 2805b0c632dbSHeiko Carstens } 2806b0c632dbSHeiko Carstens 2807b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) 2808b0c632dbSHeiko Carstens { 28091fc9b76bSChristoffer Dall vcpu_load(vcpu); 28105a32c1afSChristian Borntraeger memcpy(®s->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs)); 28111fc9b76bSChristoffer Dall vcpu_put(vcpu); 2812b0c632dbSHeiko Carstens return 0; 2813b0c632dbSHeiko Carstens } 2814b0c632dbSHeiko Carstens 2815b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, 2816b0c632dbSHeiko Carstens struct kvm_sregs *sregs) 2817b0c632dbSHeiko Carstens { 2818b4ef9d4eSChristoffer Dall vcpu_load(vcpu); 2819b4ef9d4eSChristoffer Dall 282059674c1aSChristian Borntraeger memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs)); 2821b0c632dbSHeiko Carstens memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs)); 2822b4ef9d4eSChristoffer Dall 2823b4ef9d4eSChristoffer Dall vcpu_put(vcpu); 2824b0c632dbSHeiko Carstens return 0; 2825b0c632dbSHeiko Carstens } 2826b0c632dbSHeiko Carstens 2827b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, 2828b0c632dbSHeiko Carstens struct kvm_sregs *sregs) 2829b0c632dbSHeiko Carstens { 2830bcdec41cSChristoffer Dall vcpu_load(vcpu); 2831bcdec41cSChristoffer Dall 283259674c1aSChristian Borntraeger memcpy(&sregs->acrs, &vcpu->run->s.regs.acrs, sizeof(sregs->acrs)); 2833b0c632dbSHeiko Carstens memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs)); 2834bcdec41cSChristoffer Dall 2835bcdec41cSChristoffer Dall vcpu_put(vcpu); 2836b0c632dbSHeiko Carstens return 0; 2837b0c632dbSHeiko Carstens } 2838b0c632dbSHeiko Carstens 2839b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 2840b0c632dbSHeiko Carstens { 28416a96bc7fSChristoffer Dall int ret = 0; 28426a96bc7fSChristoffer Dall 28436a96bc7fSChristoffer Dall vcpu_load(vcpu); 28446a96bc7fSChristoffer Dall 28456a96bc7fSChristoffer Dall if (test_fp_ctl(fpu->fpc)) { 28466a96bc7fSChristoffer Dall ret = -EINVAL; 28476a96bc7fSChristoffer Dall goto out; 28486a96bc7fSChristoffer Dall } 2849e1788bb9SChristian Borntraeger vcpu->run->s.regs.fpc = fpu->fpc; 28509abc2a08SDavid Hildenbrand if (MACHINE_HAS_VX) 2851a7d4b8f2SDavid Hildenbrand convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs, 2852a7d4b8f2SDavid Hildenbrand (freg_t *) fpu->fprs); 28539abc2a08SDavid Hildenbrand else 2854a7d4b8f2SDavid Hildenbrand memcpy(vcpu->run->s.regs.fprs, &fpu->fprs, sizeof(fpu->fprs)); 28556a96bc7fSChristoffer Dall 28566a96bc7fSChristoffer Dall out: 28576a96bc7fSChristoffer Dall vcpu_put(vcpu); 28586a96bc7fSChristoffer Dall return ret; 2859b0c632dbSHeiko Carstens } 2860b0c632dbSHeiko Carstens 2861b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) 2862b0c632dbSHeiko Carstens { 28631393123eSChristoffer Dall vcpu_load(vcpu); 28641393123eSChristoffer Dall 28659abc2a08SDavid Hildenbrand /* make sure we have the latest values */ 28669abc2a08SDavid Hildenbrand save_fpu_regs(); 28679abc2a08SDavid Hildenbrand if (MACHINE_HAS_VX) 2868a7d4b8f2SDavid Hildenbrand convert_vx_to_fp((freg_t *) fpu->fprs, 2869a7d4b8f2SDavid Hildenbrand (__vector128 *) vcpu->run->s.regs.vrs); 28709abc2a08SDavid Hildenbrand else 2871a7d4b8f2SDavid Hildenbrand memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs)); 2872e1788bb9SChristian Borntraeger fpu->fpc = vcpu->run->s.regs.fpc; 28731393123eSChristoffer Dall 28741393123eSChristoffer Dall vcpu_put(vcpu); 2875b0c632dbSHeiko Carstens return 0; 2876b0c632dbSHeiko Carstens } 2877b0c632dbSHeiko Carstens 2878b0c632dbSHeiko Carstens static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw) 2879b0c632dbSHeiko Carstens { 2880b0c632dbSHeiko Carstens int rc = 0; 2881b0c632dbSHeiko Carstens 28827a42fdc2SDavid Hildenbrand if (!is_vcpu_stopped(vcpu)) 2883b0c632dbSHeiko Carstens rc = -EBUSY; 2884d7b0b5ebSCarsten Otte else { 2885d7b0b5ebSCarsten Otte vcpu->run->psw_mask = psw.mask; 2886d7b0b5ebSCarsten Otte vcpu->run->psw_addr = psw.addr; 2887d7b0b5ebSCarsten Otte } 2888b0c632dbSHeiko Carstens return rc; 2889b0c632dbSHeiko Carstens } 2890b0c632dbSHeiko Carstens 2891b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, 2892b0c632dbSHeiko Carstens struct kvm_translation *tr) 2893b0c632dbSHeiko Carstens { 2894b0c632dbSHeiko Carstens return -EINVAL; /* not implemented yet */ 2895b0c632dbSHeiko Carstens } 2896b0c632dbSHeiko Carstens 289727291e21SDavid Hildenbrand #define VALID_GUESTDBG_FLAGS (KVM_GUESTDBG_SINGLESTEP | \ 289827291e21SDavid Hildenbrand KVM_GUESTDBG_USE_HW_BP | \ 289927291e21SDavid Hildenbrand KVM_GUESTDBG_ENABLE) 290027291e21SDavid Hildenbrand 2901d0bfb940SJan Kiszka int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu, 2902d0bfb940SJan Kiszka struct kvm_guest_debug *dbg) 2903b0c632dbSHeiko Carstens { 290427291e21SDavid Hildenbrand int rc = 0; 290527291e21SDavid Hildenbrand 290666b56562SChristoffer Dall vcpu_load(vcpu); 290766b56562SChristoffer Dall 290827291e21SDavid Hildenbrand vcpu->guest_debug = 0; 290927291e21SDavid Hildenbrand kvm_s390_clear_bp_data(vcpu); 291027291e21SDavid Hildenbrand 291166b56562SChristoffer Dall if (dbg->control & ~VALID_GUESTDBG_FLAGS) { 291266b56562SChristoffer Dall rc = -EINVAL; 291366b56562SChristoffer Dall goto out; 291466b56562SChristoffer Dall } 291566b56562SChristoffer Dall if (!sclp.has_gpere) { 291666b56562SChristoffer Dall rc = -EINVAL; 291766b56562SChristoffer Dall goto out; 291866b56562SChristoffer Dall } 291927291e21SDavid Hildenbrand 292027291e21SDavid Hildenbrand if (dbg->control & KVM_GUESTDBG_ENABLE) { 292127291e21SDavid Hildenbrand vcpu->guest_debug = dbg->control; 292227291e21SDavid Hildenbrand /* enforce guest PER */ 2923ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_P); 292427291e21SDavid Hildenbrand 292527291e21SDavid Hildenbrand if (dbg->control & KVM_GUESTDBG_USE_HW_BP) 292627291e21SDavid Hildenbrand rc = kvm_s390_import_bp_data(vcpu, dbg); 292727291e21SDavid Hildenbrand } else { 29289daecfc6SDavid Hildenbrand kvm_s390_clear_cpuflags(vcpu, CPUSTAT_P); 292927291e21SDavid Hildenbrand vcpu->arch.guestdbg.last_bp = 0; 293027291e21SDavid Hildenbrand } 293127291e21SDavid Hildenbrand 293227291e21SDavid Hildenbrand if (rc) { 293327291e21SDavid Hildenbrand vcpu->guest_debug = 0; 293427291e21SDavid Hildenbrand kvm_s390_clear_bp_data(vcpu); 29359daecfc6SDavid Hildenbrand kvm_s390_clear_cpuflags(vcpu, CPUSTAT_P); 293627291e21SDavid Hildenbrand } 293727291e21SDavid Hildenbrand 293866b56562SChristoffer Dall out: 293966b56562SChristoffer Dall vcpu_put(vcpu); 294027291e21SDavid Hildenbrand return rc; 2941b0c632dbSHeiko Carstens } 2942b0c632dbSHeiko Carstens 294362d9f0dbSMarcelo Tosatti int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, 294462d9f0dbSMarcelo Tosatti struct kvm_mp_state *mp_state) 294562d9f0dbSMarcelo Tosatti { 2946fd232561SChristoffer Dall int ret; 2947fd232561SChristoffer Dall 2948fd232561SChristoffer Dall vcpu_load(vcpu); 2949fd232561SChristoffer Dall 29506352e4d2SDavid Hildenbrand /* CHECK_STOP and LOAD are not supported yet */ 2951fd232561SChristoffer Dall ret = is_vcpu_stopped(vcpu) ? KVM_MP_STATE_STOPPED : 29526352e4d2SDavid Hildenbrand KVM_MP_STATE_OPERATING; 2953fd232561SChristoffer Dall 2954fd232561SChristoffer Dall vcpu_put(vcpu); 2955fd232561SChristoffer Dall return ret; 295662d9f0dbSMarcelo Tosatti } 295762d9f0dbSMarcelo Tosatti 295862d9f0dbSMarcelo Tosatti int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, 295962d9f0dbSMarcelo Tosatti struct kvm_mp_state *mp_state) 296062d9f0dbSMarcelo Tosatti { 29616352e4d2SDavid Hildenbrand int rc = 0; 29626352e4d2SDavid Hildenbrand 2963e83dff5eSChristoffer Dall vcpu_load(vcpu); 2964e83dff5eSChristoffer Dall 29656352e4d2SDavid Hildenbrand /* user space knows about this interface - let it control the state */ 29666352e4d2SDavid Hildenbrand vcpu->kvm->arch.user_cpu_state_ctrl = 1; 29676352e4d2SDavid Hildenbrand 29686352e4d2SDavid Hildenbrand switch (mp_state->mp_state) { 29696352e4d2SDavid Hildenbrand case KVM_MP_STATE_STOPPED: 29706352e4d2SDavid Hildenbrand kvm_s390_vcpu_stop(vcpu); 29716352e4d2SDavid Hildenbrand break; 29726352e4d2SDavid Hildenbrand case KVM_MP_STATE_OPERATING: 29736352e4d2SDavid Hildenbrand kvm_s390_vcpu_start(vcpu); 29746352e4d2SDavid Hildenbrand break; 29756352e4d2SDavid Hildenbrand case KVM_MP_STATE_LOAD: 29766352e4d2SDavid Hildenbrand case KVM_MP_STATE_CHECK_STOP: 29776352e4d2SDavid Hildenbrand /* fall through - CHECK_STOP and LOAD are not supported yet */ 29786352e4d2SDavid Hildenbrand default: 29796352e4d2SDavid Hildenbrand rc = -ENXIO; 29806352e4d2SDavid Hildenbrand } 29816352e4d2SDavid Hildenbrand 2982e83dff5eSChristoffer Dall vcpu_put(vcpu); 29836352e4d2SDavid Hildenbrand return rc; 298462d9f0dbSMarcelo Tosatti } 298562d9f0dbSMarcelo Tosatti 29868ad35755SDavid Hildenbrand static bool ibs_enabled(struct kvm_vcpu *vcpu) 29878ad35755SDavid Hildenbrand { 29888d5fb0dcSDavid Hildenbrand return kvm_s390_test_cpuflags(vcpu, CPUSTAT_IBS); 29898ad35755SDavid Hildenbrand } 29908ad35755SDavid Hildenbrand 29912c70fe44SChristian Borntraeger static int kvm_s390_handle_requests(struct kvm_vcpu *vcpu) 29922c70fe44SChristian Borntraeger { 29938ad35755SDavid Hildenbrand retry: 29948e236546SChristian Borntraeger kvm_s390_vcpu_request_handled(vcpu); 29952fa6e1e1SRadim Krčmář if (!kvm_request_pending(vcpu)) 2996586b7ccdSChristian Borntraeger return 0; 29972c70fe44SChristian Borntraeger /* 29982c70fe44SChristian Borntraeger * We use MMU_RELOAD just to re-arm the ipte notifier for the 2999b2d73b2aSMartin Schwidefsky * guest prefix page. gmap_mprotect_notify will wait on the ptl lock. 30002c70fe44SChristian Borntraeger * This ensures that the ipte instruction for this request has 30012c70fe44SChristian Borntraeger * already finished. We might race against a second unmapper that 30022c70fe44SChristian Borntraeger * wants to set the blocking bit. Lets just retry the request loop. 30032c70fe44SChristian Borntraeger */ 30048ad35755SDavid Hildenbrand if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) { 30052c70fe44SChristian Borntraeger int rc; 3006b2d73b2aSMartin Schwidefsky rc = gmap_mprotect_notify(vcpu->arch.gmap, 3007fda902cbSMichael Mueller kvm_s390_get_prefix(vcpu), 3008b2d73b2aSMartin Schwidefsky PAGE_SIZE * 2, PROT_WRITE); 3009aca411a4SJulius Niedworok if (rc) { 3010aca411a4SJulius Niedworok kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu); 30112c70fe44SChristian Borntraeger return rc; 3012aca411a4SJulius Niedworok } 30138ad35755SDavid Hildenbrand goto retry; 30142c70fe44SChristian Borntraeger } 30158ad35755SDavid Hildenbrand 3016d3d692c8SDavid Hildenbrand if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu)) { 3017d3d692c8SDavid Hildenbrand vcpu->arch.sie_block->ihcpu = 0xffff; 3018d3d692c8SDavid Hildenbrand goto retry; 3019d3d692c8SDavid Hildenbrand } 3020d3d692c8SDavid Hildenbrand 30218ad35755SDavid Hildenbrand if (kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu)) { 30228ad35755SDavid Hildenbrand if (!ibs_enabled(vcpu)) { 30238ad35755SDavid Hildenbrand trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 1); 3024ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_IBS); 30258ad35755SDavid Hildenbrand } 30268ad35755SDavid Hildenbrand goto retry; 30278ad35755SDavid Hildenbrand } 30288ad35755SDavid Hildenbrand 30298ad35755SDavid Hildenbrand if (kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu)) { 30308ad35755SDavid Hildenbrand if (ibs_enabled(vcpu)) { 30318ad35755SDavid Hildenbrand trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 0); 30329daecfc6SDavid Hildenbrand kvm_s390_clear_cpuflags(vcpu, CPUSTAT_IBS); 30338ad35755SDavid Hildenbrand } 30348ad35755SDavid Hildenbrand goto retry; 30358ad35755SDavid Hildenbrand } 30368ad35755SDavid Hildenbrand 30376502a34cSDavid Hildenbrand if (kvm_check_request(KVM_REQ_ICPT_OPEREXC, vcpu)) { 30386502a34cSDavid Hildenbrand vcpu->arch.sie_block->ictl |= ICTL_OPEREXC; 30396502a34cSDavid Hildenbrand goto retry; 30406502a34cSDavid Hildenbrand } 30416502a34cSDavid Hildenbrand 3042190df4a2SClaudio Imbrenda if (kvm_check_request(KVM_REQ_START_MIGRATION, vcpu)) { 3043190df4a2SClaudio Imbrenda /* 3044c9f0a2b8SJanosch Frank * Disable CMM virtualization; we will emulate the ESSA 3045190df4a2SClaudio Imbrenda * instruction manually, in order to provide additional 3046190df4a2SClaudio Imbrenda * functionalities needed for live migration. 3047190df4a2SClaudio Imbrenda */ 3048190df4a2SClaudio Imbrenda vcpu->arch.sie_block->ecb2 &= ~ECB2_CMMA; 3049190df4a2SClaudio Imbrenda goto retry; 3050190df4a2SClaudio Imbrenda } 3051190df4a2SClaudio Imbrenda 3052190df4a2SClaudio Imbrenda if (kvm_check_request(KVM_REQ_STOP_MIGRATION, vcpu)) { 3053190df4a2SClaudio Imbrenda /* 3054c9f0a2b8SJanosch Frank * Re-enable CMM virtualization if CMMA is available and 3055c9f0a2b8SJanosch Frank * CMM has been used. 3056190df4a2SClaudio Imbrenda */ 3057190df4a2SClaudio Imbrenda if ((vcpu->kvm->arch.use_cmma) && 3058c9f0a2b8SJanosch Frank (vcpu->kvm->mm->context.uses_cmm)) 3059190df4a2SClaudio Imbrenda vcpu->arch.sie_block->ecb2 |= ECB2_CMMA; 3060190df4a2SClaudio Imbrenda goto retry; 3061190df4a2SClaudio Imbrenda } 3062190df4a2SClaudio Imbrenda 30630759d068SDavid Hildenbrand /* nothing to do, just clear the request */ 306472875d8aSRadim Krčmář kvm_clear_request(KVM_REQ_UNHALT, vcpu); 30650759d068SDavid Hildenbrand 30662c70fe44SChristian Borntraeger return 0; 30672c70fe44SChristian Borntraeger } 30682c70fe44SChristian Borntraeger 30690e7def5fSDavid Hildenbrand void kvm_s390_set_tod_clock(struct kvm *kvm, 30708fa1696eSCollin L. Walling const struct kvm_s390_vm_tod_clock *gtod) 30718fa1696eSCollin L. Walling { 30728fa1696eSCollin L. Walling struct kvm_vcpu *vcpu; 30738fa1696eSCollin L. Walling struct kvm_s390_tod_clock_ext htod; 30748fa1696eSCollin L. Walling int i; 30758fa1696eSCollin L. Walling 30768fa1696eSCollin L. Walling mutex_lock(&kvm->lock); 30778fa1696eSCollin L. Walling preempt_disable(); 30788fa1696eSCollin L. Walling 30798fa1696eSCollin L. Walling get_tod_clock_ext((char *)&htod); 30808fa1696eSCollin L. Walling 30818fa1696eSCollin L. Walling kvm->arch.epoch = gtod->tod - htod.tod; 30820e7def5fSDavid Hildenbrand kvm->arch.epdx = 0; 30830e7def5fSDavid Hildenbrand if (test_kvm_facility(kvm, 139)) { 30848fa1696eSCollin L. Walling kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx; 30858fa1696eSCollin L. Walling if (kvm->arch.epoch > gtod->tod) 30868fa1696eSCollin L. Walling kvm->arch.epdx -= 1; 30870e7def5fSDavid Hildenbrand } 30888fa1696eSCollin L. Walling 30898fa1696eSCollin L. Walling kvm_s390_vcpu_block_all(kvm); 30908fa1696eSCollin L. Walling kvm_for_each_vcpu(i, vcpu, kvm) { 30918fa1696eSCollin L. Walling vcpu->arch.sie_block->epoch = kvm->arch.epoch; 30928fa1696eSCollin L. Walling vcpu->arch.sie_block->epdx = kvm->arch.epdx; 30938fa1696eSCollin L. Walling } 30948fa1696eSCollin L. Walling 30958fa1696eSCollin L. Walling kvm_s390_vcpu_unblock_all(kvm); 30968fa1696eSCollin L. Walling preempt_enable(); 30978fa1696eSCollin L. Walling mutex_unlock(&kvm->lock); 30988fa1696eSCollin L. Walling } 30998fa1696eSCollin L. Walling 3100fa576c58SThomas Huth /** 3101fa576c58SThomas Huth * kvm_arch_fault_in_page - fault-in guest page if necessary 3102fa576c58SThomas Huth * @vcpu: The corresponding virtual cpu 3103fa576c58SThomas Huth * @gpa: Guest physical address 3104fa576c58SThomas Huth * @writable: Whether the page should be writable or not 3105fa576c58SThomas Huth * 3106fa576c58SThomas Huth * Make sure that a guest page has been faulted-in on the host. 3107fa576c58SThomas Huth * 3108fa576c58SThomas Huth * Return: Zero on success, negative error code otherwise. 3109fa576c58SThomas Huth */ 3110fa576c58SThomas Huth long kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable) 311124eb3a82SDominik Dingel { 3112527e30b4SMartin Schwidefsky return gmap_fault(vcpu->arch.gmap, gpa, 3113527e30b4SMartin Schwidefsky writable ? FAULT_FLAG_WRITE : 0); 311424eb3a82SDominik Dingel } 311524eb3a82SDominik Dingel 31163c038e6bSDominik Dingel static void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token, 31173c038e6bSDominik Dingel unsigned long token) 31183c038e6bSDominik Dingel { 31193c038e6bSDominik Dingel struct kvm_s390_interrupt inti; 3120383d0b05SJens Freimann struct kvm_s390_irq irq; 31213c038e6bSDominik Dingel 31223c038e6bSDominik Dingel if (start_token) { 3123383d0b05SJens Freimann irq.u.ext.ext_params2 = token; 3124383d0b05SJens Freimann irq.type = KVM_S390_INT_PFAULT_INIT; 3125383d0b05SJens Freimann WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &irq)); 31263c038e6bSDominik Dingel } else { 31273c038e6bSDominik Dingel inti.type = KVM_S390_INT_PFAULT_DONE; 3128383d0b05SJens Freimann inti.parm64 = token; 31293c038e6bSDominik Dingel WARN_ON_ONCE(kvm_s390_inject_vm(vcpu->kvm, &inti)); 31303c038e6bSDominik Dingel } 31313c038e6bSDominik Dingel } 31323c038e6bSDominik Dingel 31333c038e6bSDominik Dingel void kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu, 31343c038e6bSDominik Dingel struct kvm_async_pf *work) 31353c038e6bSDominik Dingel { 31363c038e6bSDominik Dingel trace_kvm_s390_pfault_init(vcpu, work->arch.pfault_token); 31373c038e6bSDominik Dingel __kvm_inject_pfault_token(vcpu, true, work->arch.pfault_token); 31383c038e6bSDominik Dingel } 31393c038e6bSDominik Dingel 31403c038e6bSDominik Dingel void kvm_arch_async_page_present(struct kvm_vcpu *vcpu, 31413c038e6bSDominik Dingel struct kvm_async_pf *work) 31423c038e6bSDominik Dingel { 31433c038e6bSDominik Dingel trace_kvm_s390_pfault_done(vcpu, work->arch.pfault_token); 31443c038e6bSDominik Dingel __kvm_inject_pfault_token(vcpu, false, work->arch.pfault_token); 31453c038e6bSDominik Dingel } 31463c038e6bSDominik Dingel 31473c038e6bSDominik Dingel void kvm_arch_async_page_ready(struct kvm_vcpu *vcpu, 31483c038e6bSDominik Dingel struct kvm_async_pf *work) 31493c038e6bSDominik Dingel { 31503c038e6bSDominik Dingel /* s390 will always inject the page directly */ 31513c038e6bSDominik Dingel } 31523c038e6bSDominik Dingel 31533c038e6bSDominik Dingel bool kvm_arch_can_inject_async_page_present(struct kvm_vcpu *vcpu) 31543c038e6bSDominik Dingel { 31553c038e6bSDominik Dingel /* 31563c038e6bSDominik Dingel * s390 will always inject the page directly, 31573c038e6bSDominik Dingel * but we still want check_async_completion to cleanup 31583c038e6bSDominik Dingel */ 31593c038e6bSDominik Dingel return true; 31603c038e6bSDominik Dingel } 31613c038e6bSDominik Dingel 31623c038e6bSDominik Dingel static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu) 31633c038e6bSDominik Dingel { 31643c038e6bSDominik Dingel hva_t hva; 31653c038e6bSDominik Dingel struct kvm_arch_async_pf arch; 31663c038e6bSDominik Dingel int rc; 31673c038e6bSDominik Dingel 31683c038e6bSDominik Dingel if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) 31693c038e6bSDominik Dingel return 0; 31703c038e6bSDominik Dingel if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) != 31713c038e6bSDominik Dingel vcpu->arch.pfault_compare) 31723c038e6bSDominik Dingel return 0; 31733c038e6bSDominik Dingel if (psw_extint_disabled(vcpu)) 31743c038e6bSDominik Dingel return 0; 31759a022067SDavid Hildenbrand if (kvm_s390_vcpu_has_irq(vcpu, 0)) 31763c038e6bSDominik Dingel return 0; 31773c038e6bSDominik Dingel if (!(vcpu->arch.sie_block->gcr[0] & 0x200ul)) 31783c038e6bSDominik Dingel return 0; 31793c038e6bSDominik Dingel if (!vcpu->arch.gmap->pfault_enabled) 31803c038e6bSDominik Dingel return 0; 31813c038e6bSDominik Dingel 318281480cc1SHeiko Carstens hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr)); 318381480cc1SHeiko Carstens hva += current->thread.gmap_addr & ~PAGE_MASK; 318481480cc1SHeiko Carstens if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8)) 31853c038e6bSDominik Dingel return 0; 31863c038e6bSDominik Dingel 31873c038e6bSDominik Dingel rc = kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch); 31883c038e6bSDominik Dingel return rc; 31893c038e6bSDominik Dingel } 31903c038e6bSDominik Dingel 31913fb4c40fSThomas Huth static int vcpu_pre_run(struct kvm_vcpu *vcpu) 3192b0c632dbSHeiko Carstens { 31933fb4c40fSThomas Huth int rc, cpuflags; 3194e168bf8dSCarsten Otte 31953c038e6bSDominik Dingel /* 31963c038e6bSDominik Dingel * On s390 notifications for arriving pages will be delivered directly 31973c038e6bSDominik Dingel * to the guest but the house keeping for completed pfaults is 31983c038e6bSDominik Dingel * handled outside the worker. 31993c038e6bSDominik Dingel */ 32003c038e6bSDominik Dingel kvm_check_async_pf_completion(vcpu); 32013c038e6bSDominik Dingel 32027ec7c8c7SChristian Borntraeger vcpu->arch.sie_block->gg14 = vcpu->run->s.regs.gprs[14]; 32037ec7c8c7SChristian Borntraeger vcpu->arch.sie_block->gg15 = vcpu->run->s.regs.gprs[15]; 3204b0c632dbSHeiko Carstens 3205b0c632dbSHeiko Carstens if (need_resched()) 3206b0c632dbSHeiko Carstens schedule(); 3207b0c632dbSHeiko Carstens 3208d3a73acbSMartin Schwidefsky if (test_cpu_flag(CIF_MCCK_PENDING)) 320971cde587SChristian Borntraeger s390_handle_mcck(); 321071cde587SChristian Borntraeger 321179395031SJens Freimann if (!kvm_is_ucontrol(vcpu->kvm)) { 321279395031SJens Freimann rc = kvm_s390_deliver_pending_interrupts(vcpu); 321379395031SJens Freimann if (rc) 321479395031SJens Freimann return rc; 321579395031SJens Freimann } 32160ff31867SCarsten Otte 32172c70fe44SChristian Borntraeger rc = kvm_s390_handle_requests(vcpu); 32182c70fe44SChristian Borntraeger if (rc) 32192c70fe44SChristian Borntraeger return rc; 32202c70fe44SChristian Borntraeger 322127291e21SDavid Hildenbrand if (guestdbg_enabled(vcpu)) { 322227291e21SDavid Hildenbrand kvm_s390_backup_guest_per_regs(vcpu); 322327291e21SDavid Hildenbrand kvm_s390_patch_guest_per_regs(vcpu); 322427291e21SDavid Hildenbrand } 322527291e21SDavid Hildenbrand 3226b0c632dbSHeiko Carstens vcpu->arch.sie_block->icptcode = 0; 32273fb4c40fSThomas Huth cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags); 32283fb4c40fSThomas Huth VCPU_EVENT(vcpu, 6, "entering sie flags %x", cpuflags); 32293fb4c40fSThomas Huth trace_kvm_s390_sie_enter(vcpu, cpuflags); 32302b29a9fdSDominik Dingel 32313fb4c40fSThomas Huth return 0; 32323fb4c40fSThomas Huth } 32333fb4c40fSThomas Huth 3234492d8642SThomas Huth static int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu) 3235492d8642SThomas Huth { 323656317920SDavid Hildenbrand struct kvm_s390_pgm_info pgm_info = { 323756317920SDavid Hildenbrand .code = PGM_ADDRESSING, 323856317920SDavid Hildenbrand }; 323956317920SDavid Hildenbrand u8 opcode, ilen; 3240492d8642SThomas Huth int rc; 3241492d8642SThomas Huth 3242492d8642SThomas Huth VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction"); 3243492d8642SThomas Huth trace_kvm_s390_sie_fault(vcpu); 3244492d8642SThomas Huth 3245492d8642SThomas Huth /* 3246492d8642SThomas Huth * We want to inject an addressing exception, which is defined as a 3247492d8642SThomas Huth * suppressing or terminating exception. However, since we came here 3248492d8642SThomas Huth * by a DAT access exception, the PSW still points to the faulting 3249492d8642SThomas Huth * instruction since DAT exceptions are nullifying. So we've got 3250492d8642SThomas Huth * to look up the current opcode to get the length of the instruction 3251492d8642SThomas Huth * to be able to forward the PSW. 3252492d8642SThomas Huth */ 32533fa8cad7SDavid Hildenbrand rc = read_guest_instr(vcpu, vcpu->arch.sie_block->gpsw.addr, &opcode, 1); 325456317920SDavid Hildenbrand ilen = insn_length(opcode); 32559b0d721aSDavid Hildenbrand if (rc < 0) { 32569b0d721aSDavid Hildenbrand return rc; 32579b0d721aSDavid Hildenbrand } else if (rc) { 32589b0d721aSDavid Hildenbrand /* Instruction-Fetching Exceptions - we can't detect the ilen. 32599b0d721aSDavid Hildenbrand * Forward by arbitrary ilc, injection will take care of 32609b0d721aSDavid Hildenbrand * nullification if necessary. 32619b0d721aSDavid Hildenbrand */ 32629b0d721aSDavid Hildenbrand pgm_info = vcpu->arch.pgm; 32639b0d721aSDavid Hildenbrand ilen = 4; 32649b0d721aSDavid Hildenbrand } 326556317920SDavid Hildenbrand pgm_info.flags = ilen | KVM_S390_PGM_FLAGS_ILC_VALID; 326656317920SDavid Hildenbrand kvm_s390_forward_psw(vcpu, ilen); 326756317920SDavid Hildenbrand return kvm_s390_inject_prog_irq(vcpu, &pgm_info); 3268492d8642SThomas Huth } 3269492d8642SThomas Huth 32703fb4c40fSThomas Huth static int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason) 32713fb4c40fSThomas Huth { 32724d62fcc0SQingFeng Hao struct mcck_volatile_info *mcck_info; 32734d62fcc0SQingFeng Hao struct sie_page *sie_page; 32744d62fcc0SQingFeng Hao 32752b29a9fdSDominik Dingel VCPU_EVENT(vcpu, 6, "exit sie icptcode %d", 32762b29a9fdSDominik Dingel vcpu->arch.sie_block->icptcode); 32772b29a9fdSDominik Dingel trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode); 32782b29a9fdSDominik Dingel 327927291e21SDavid Hildenbrand if (guestdbg_enabled(vcpu)) 328027291e21SDavid Hildenbrand kvm_s390_restore_guest_per_regs(vcpu); 328127291e21SDavid Hildenbrand 32827ec7c8c7SChristian Borntraeger vcpu->run->s.regs.gprs[14] = vcpu->arch.sie_block->gg14; 32837ec7c8c7SChristian Borntraeger vcpu->run->s.regs.gprs[15] = vcpu->arch.sie_block->gg15; 328471f116bfSDavid Hildenbrand 32854d62fcc0SQingFeng Hao if (exit_reason == -EINTR) { 32864d62fcc0SQingFeng Hao VCPU_EVENT(vcpu, 3, "%s", "machine check"); 32874d62fcc0SQingFeng Hao sie_page = container_of(vcpu->arch.sie_block, 32884d62fcc0SQingFeng Hao struct sie_page, sie_block); 32894d62fcc0SQingFeng Hao mcck_info = &sie_page->mcck_info; 32904d62fcc0SQingFeng Hao kvm_s390_reinject_machine_check(vcpu, mcck_info); 32914d62fcc0SQingFeng Hao return 0; 32924d62fcc0SQingFeng Hao } 32934d62fcc0SQingFeng Hao 329471f116bfSDavid Hildenbrand if (vcpu->arch.sie_block->icptcode > 0) { 329571f116bfSDavid Hildenbrand int rc = kvm_handle_sie_intercept(vcpu); 329671f116bfSDavid Hildenbrand 329771f116bfSDavid Hildenbrand if (rc != -EOPNOTSUPP) 329871f116bfSDavid Hildenbrand return rc; 329971f116bfSDavid Hildenbrand vcpu->run->exit_reason = KVM_EXIT_S390_SIEIC; 330071f116bfSDavid Hildenbrand vcpu->run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode; 330171f116bfSDavid Hildenbrand vcpu->run->s390_sieic.ipa = vcpu->arch.sie_block->ipa; 330271f116bfSDavid Hildenbrand vcpu->run->s390_sieic.ipb = vcpu->arch.sie_block->ipb; 330371f116bfSDavid Hildenbrand return -EREMOTE; 330471f116bfSDavid Hildenbrand } else if (exit_reason != -EFAULT) { 330571f116bfSDavid Hildenbrand vcpu->stat.exit_null++; 330671f116bfSDavid Hildenbrand return 0; 3307210b1607SThomas Huth } else if (kvm_is_ucontrol(vcpu->kvm)) { 3308210b1607SThomas Huth vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL; 3309210b1607SThomas Huth vcpu->run->s390_ucontrol.trans_exc_code = 3310210b1607SThomas Huth current->thread.gmap_addr; 3311210b1607SThomas Huth vcpu->run->s390_ucontrol.pgm_code = 0x10; 331271f116bfSDavid Hildenbrand return -EREMOTE; 331324eb3a82SDominik Dingel } else if (current->thread.gmap_pfault) { 33143c038e6bSDominik Dingel trace_kvm_s390_major_guest_pfault(vcpu); 331524eb3a82SDominik Dingel current->thread.gmap_pfault = 0; 331671f116bfSDavid Hildenbrand if (kvm_arch_setup_async_pf(vcpu)) 331771f116bfSDavid Hildenbrand return 0; 331871f116bfSDavid Hildenbrand return kvm_arch_fault_in_page(vcpu, current->thread.gmap_addr, 1); 3319fa576c58SThomas Huth } 332071f116bfSDavid Hildenbrand return vcpu_post_run_fault_in_sie(vcpu); 33213fb4c40fSThomas Huth } 33223fb4c40fSThomas Huth 33233fb4c40fSThomas Huth static int __vcpu_run(struct kvm_vcpu *vcpu) 33243fb4c40fSThomas Huth { 33253fb4c40fSThomas Huth int rc, exit_reason; 33263fb4c40fSThomas Huth 3327800c1065SThomas Huth /* 3328800c1065SThomas Huth * We try to hold kvm->srcu during most of vcpu_run (except when run- 3329800c1065SThomas Huth * ning the guest), so that memslots (and other stuff) are protected 3330800c1065SThomas Huth */ 3331800c1065SThomas Huth vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 3332800c1065SThomas Huth 3333a76ccff6SThomas Huth do { 33343fb4c40fSThomas Huth rc = vcpu_pre_run(vcpu); 33353fb4c40fSThomas Huth if (rc) 3336a76ccff6SThomas Huth break; 33373fb4c40fSThomas Huth 3338800c1065SThomas Huth srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); 33393fb4c40fSThomas Huth /* 3340a76ccff6SThomas Huth * As PF_VCPU will be used in fault handler, between 3341a76ccff6SThomas Huth * guest_enter and guest_exit should be no uaccess. 33423fb4c40fSThomas Huth */ 33430097d12eSChristian Borntraeger local_irq_disable(); 33446edaa530SPaolo Bonzini guest_enter_irqoff(); 3345db0758b2SDavid Hildenbrand __disable_cpu_timer_accounting(vcpu); 33460097d12eSChristian Borntraeger local_irq_enable(); 3347a76ccff6SThomas Huth exit_reason = sie64a(vcpu->arch.sie_block, 3348a76ccff6SThomas Huth vcpu->run->s.regs.gprs); 33490097d12eSChristian Borntraeger local_irq_disable(); 3350db0758b2SDavid Hildenbrand __enable_cpu_timer_accounting(vcpu); 33516edaa530SPaolo Bonzini guest_exit_irqoff(); 33520097d12eSChristian Borntraeger local_irq_enable(); 3353800c1065SThomas Huth vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 33543fb4c40fSThomas Huth 33553fb4c40fSThomas Huth rc = vcpu_post_run(vcpu, exit_reason); 335627291e21SDavid Hildenbrand } while (!signal_pending(current) && !guestdbg_exit_pending(vcpu) && !rc); 33573fb4c40fSThomas Huth 3358800c1065SThomas Huth srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); 3359e168bf8dSCarsten Otte return rc; 3360b0c632dbSHeiko Carstens } 3361b0c632dbSHeiko Carstens 3362b028ee3eSDavid Hildenbrand static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3363b028ee3eSDavid Hildenbrand { 33644d5f2c04SChristian Borntraeger struct runtime_instr_cb *riccb; 33654e0b1ab7SFan Zhang struct gs_cb *gscb; 33664d5f2c04SChristian Borntraeger 33674d5f2c04SChristian Borntraeger riccb = (struct runtime_instr_cb *) &kvm_run->s.regs.riccb; 33684e0b1ab7SFan Zhang gscb = (struct gs_cb *) &kvm_run->s.regs.gscb; 3369b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask; 3370b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr; 3371b028ee3eSDavid Hildenbrand if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) 3372b028ee3eSDavid Hildenbrand kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix); 3373b028ee3eSDavid Hildenbrand if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) { 3374b028ee3eSDavid Hildenbrand memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128); 3375d3d692c8SDavid Hildenbrand /* some control register changes require a tlb flush */ 3376d3d692c8SDavid Hildenbrand kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); 3377b028ee3eSDavid Hildenbrand } 3378b028ee3eSDavid Hildenbrand if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) { 33794287f247SDavid Hildenbrand kvm_s390_set_cpu_timer(vcpu, kvm_run->s.regs.cputm); 3380b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc; 3381b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->todpr = kvm_run->s.regs.todpr; 3382b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->pp = kvm_run->s.regs.pp; 3383b028ee3eSDavid Hildenbrand vcpu->arch.sie_block->gbea = kvm_run->s.regs.gbea; 3384b028ee3eSDavid Hildenbrand } 3385b028ee3eSDavid Hildenbrand if (kvm_run->kvm_dirty_regs & KVM_SYNC_PFAULT) { 3386b028ee3eSDavid Hildenbrand vcpu->arch.pfault_token = kvm_run->s.regs.pft; 3387b028ee3eSDavid Hildenbrand vcpu->arch.pfault_select = kvm_run->s.regs.pfs; 3388b028ee3eSDavid Hildenbrand vcpu->arch.pfault_compare = kvm_run->s.regs.pfc; 33899fbd8082SDavid Hildenbrand if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID) 33909fbd8082SDavid Hildenbrand kvm_clear_async_pf_completion_queue(vcpu); 3391b028ee3eSDavid Hildenbrand } 339280cd8763SFan Zhang /* 339380cd8763SFan Zhang * If userspace sets the riccb (e.g. after migration) to a valid state, 339480cd8763SFan Zhang * we should enable RI here instead of doing the lazy enablement. 339580cd8763SFan Zhang */ 339680cd8763SFan Zhang if ((kvm_run->kvm_dirty_regs & KVM_SYNC_RICCB) && 33974d5f2c04SChristian Borntraeger test_kvm_facility(vcpu->kvm, 64) && 3398bb59c2daSAlice Frosi riccb->v && 33990c9d8683SDavid Hildenbrand !(vcpu->arch.sie_block->ecb3 & ECB3_RI)) { 34004d5f2c04SChristian Borntraeger VCPU_EVENT(vcpu, 3, "%s", "ENABLE: RI (sync_regs)"); 34010c9d8683SDavid Hildenbrand vcpu->arch.sie_block->ecb3 |= ECB3_RI; 340280cd8763SFan Zhang } 34034e0b1ab7SFan Zhang /* 34044e0b1ab7SFan Zhang * If userspace sets the gscb (e.g. after migration) to non-zero, 34054e0b1ab7SFan Zhang * we should enable GS here instead of doing the lazy enablement. 34064e0b1ab7SFan Zhang */ 34074e0b1ab7SFan Zhang if ((kvm_run->kvm_dirty_regs & KVM_SYNC_GSCB) && 34084e0b1ab7SFan Zhang test_kvm_facility(vcpu->kvm, 133) && 34094e0b1ab7SFan Zhang gscb->gssm && 34104e0b1ab7SFan Zhang !vcpu->arch.gs_enabled) { 34114e0b1ab7SFan Zhang VCPU_EVENT(vcpu, 3, "%s", "ENABLE: GS (sync_regs)"); 34124e0b1ab7SFan Zhang vcpu->arch.sie_block->ecb |= ECB_GS; 34134e0b1ab7SFan Zhang vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT; 34144e0b1ab7SFan Zhang vcpu->arch.gs_enabled = 1; 341580cd8763SFan Zhang } 341635b3fde6SChristian Borntraeger if ((kvm_run->kvm_dirty_regs & KVM_SYNC_BPBC) && 341735b3fde6SChristian Borntraeger test_kvm_facility(vcpu->kvm, 82)) { 341835b3fde6SChristian Borntraeger vcpu->arch.sie_block->fpf &= ~FPF_BPBC; 341935b3fde6SChristian Borntraeger vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0; 342035b3fde6SChristian Borntraeger } 342131d8b8d4SChristian Borntraeger save_access_regs(vcpu->arch.host_acrs); 342231d8b8d4SChristian Borntraeger restore_access_regs(vcpu->run->s.regs.acrs); 3423e1788bb9SChristian Borntraeger /* save host (userspace) fprs/vrs */ 3424e1788bb9SChristian Borntraeger save_fpu_regs(); 3425e1788bb9SChristian Borntraeger vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc; 3426e1788bb9SChristian Borntraeger vcpu->arch.host_fpregs.regs = current->thread.fpu.regs; 3427e1788bb9SChristian Borntraeger if (MACHINE_HAS_VX) 3428e1788bb9SChristian Borntraeger current->thread.fpu.regs = vcpu->run->s.regs.vrs; 3429e1788bb9SChristian Borntraeger else 3430e1788bb9SChristian Borntraeger current->thread.fpu.regs = vcpu->run->s.regs.fprs; 3431e1788bb9SChristian Borntraeger current->thread.fpu.fpc = vcpu->run->s.regs.fpc; 3432e1788bb9SChristian Borntraeger if (test_fp_ctl(current->thread.fpu.fpc)) 3433e1788bb9SChristian Borntraeger /* User space provided an invalid FPC, let's clear it */ 3434e1788bb9SChristian Borntraeger current->thread.fpu.fpc = 0; 34354e0b1ab7SFan Zhang if (MACHINE_HAS_GS) { 34364e0b1ab7SFan Zhang preempt_disable(); 34374e0b1ab7SFan Zhang __ctl_set_bit(2, 4); 34384e0b1ab7SFan Zhang if (current->thread.gs_cb) { 34394e0b1ab7SFan Zhang vcpu->arch.host_gscb = current->thread.gs_cb; 34404e0b1ab7SFan Zhang save_gs_cb(vcpu->arch.host_gscb); 34414e0b1ab7SFan Zhang } 34424e0b1ab7SFan Zhang if (vcpu->arch.gs_enabled) { 34434e0b1ab7SFan Zhang current->thread.gs_cb = (struct gs_cb *) 34444e0b1ab7SFan Zhang &vcpu->run->s.regs.gscb; 34454e0b1ab7SFan Zhang restore_gs_cb(current->thread.gs_cb); 34464e0b1ab7SFan Zhang } 34474e0b1ab7SFan Zhang preempt_enable(); 34484e0b1ab7SFan Zhang } 344980cd8763SFan Zhang 3450b028ee3eSDavid Hildenbrand kvm_run->kvm_dirty_regs = 0; 3451b028ee3eSDavid Hildenbrand } 3452b028ee3eSDavid Hildenbrand 3453b028ee3eSDavid Hildenbrand static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3454b028ee3eSDavid Hildenbrand { 3455b028ee3eSDavid Hildenbrand kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask; 3456b028ee3eSDavid Hildenbrand kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr; 3457b028ee3eSDavid Hildenbrand kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu); 3458b028ee3eSDavid Hildenbrand memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128); 34594287f247SDavid Hildenbrand kvm_run->s.regs.cputm = kvm_s390_get_cpu_timer(vcpu); 3460b028ee3eSDavid Hildenbrand kvm_run->s.regs.ckc = vcpu->arch.sie_block->ckc; 3461b028ee3eSDavid Hildenbrand kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr; 3462b028ee3eSDavid Hildenbrand kvm_run->s.regs.pp = vcpu->arch.sie_block->pp; 3463b028ee3eSDavid Hildenbrand kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea; 3464b028ee3eSDavid Hildenbrand kvm_run->s.regs.pft = vcpu->arch.pfault_token; 3465b028ee3eSDavid Hildenbrand kvm_run->s.regs.pfs = vcpu->arch.pfault_select; 3466b028ee3eSDavid Hildenbrand kvm_run->s.regs.pfc = vcpu->arch.pfault_compare; 346735b3fde6SChristian Borntraeger kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC; 346831d8b8d4SChristian Borntraeger save_access_regs(vcpu->run->s.regs.acrs); 346931d8b8d4SChristian Borntraeger restore_access_regs(vcpu->arch.host_acrs); 3470e1788bb9SChristian Borntraeger /* Save guest register state */ 3471e1788bb9SChristian Borntraeger save_fpu_regs(); 3472e1788bb9SChristian Borntraeger vcpu->run->s.regs.fpc = current->thread.fpu.fpc; 3473e1788bb9SChristian Borntraeger /* Restore will be done lazily at return */ 3474e1788bb9SChristian Borntraeger current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc; 3475e1788bb9SChristian Borntraeger current->thread.fpu.regs = vcpu->arch.host_fpregs.regs; 34764e0b1ab7SFan Zhang if (MACHINE_HAS_GS) { 34774e0b1ab7SFan Zhang __ctl_set_bit(2, 4); 34784e0b1ab7SFan Zhang if (vcpu->arch.gs_enabled) 34794e0b1ab7SFan Zhang save_gs_cb(current->thread.gs_cb); 34804e0b1ab7SFan Zhang preempt_disable(); 34814e0b1ab7SFan Zhang current->thread.gs_cb = vcpu->arch.host_gscb; 34824e0b1ab7SFan Zhang restore_gs_cb(vcpu->arch.host_gscb); 34834e0b1ab7SFan Zhang preempt_enable(); 34844e0b1ab7SFan Zhang if (!vcpu->arch.host_gscb) 34854e0b1ab7SFan Zhang __ctl_clear_bit(2, 4); 34864e0b1ab7SFan Zhang vcpu->arch.host_gscb = NULL; 34874e0b1ab7SFan Zhang } 3488e1788bb9SChristian Borntraeger 3489b028ee3eSDavid Hildenbrand } 3490b028ee3eSDavid Hildenbrand 3491b0c632dbSHeiko Carstens int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 3492b0c632dbSHeiko Carstens { 34938f2abe6aSChristian Borntraeger int rc; 3494b0c632dbSHeiko Carstens 3495460df4c1SPaolo Bonzini if (kvm_run->immediate_exit) 3496460df4c1SPaolo Bonzini return -EINTR; 3497460df4c1SPaolo Bonzini 3498accb757dSChristoffer Dall vcpu_load(vcpu); 3499accb757dSChristoffer Dall 350027291e21SDavid Hildenbrand if (guestdbg_exit_pending(vcpu)) { 350127291e21SDavid Hildenbrand kvm_s390_prepare_debug_exit(vcpu); 3502accb757dSChristoffer Dall rc = 0; 3503accb757dSChristoffer Dall goto out; 350427291e21SDavid Hildenbrand } 350527291e21SDavid Hildenbrand 350620b7035cSJan H. Schönherr kvm_sigset_activate(vcpu); 3507b0c632dbSHeiko Carstens 35086352e4d2SDavid Hildenbrand if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) { 35096852d7b6SDavid Hildenbrand kvm_s390_vcpu_start(vcpu); 35106352e4d2SDavid Hildenbrand } else if (is_vcpu_stopped(vcpu)) { 3511ea2cdd27SDavid Hildenbrand pr_err_ratelimited("can't run stopped vcpu %d\n", 35126352e4d2SDavid Hildenbrand vcpu->vcpu_id); 3513accb757dSChristoffer Dall rc = -EINVAL; 3514accb757dSChristoffer Dall goto out; 35156352e4d2SDavid Hildenbrand } 3516b0c632dbSHeiko Carstens 3517b028ee3eSDavid Hildenbrand sync_regs(vcpu, kvm_run); 3518db0758b2SDavid Hildenbrand enable_cpu_timer_accounting(vcpu); 3519d7b0b5ebSCarsten Otte 3520dab4079dSHeiko Carstens might_fault(); 3521e168bf8dSCarsten Otte rc = __vcpu_run(vcpu); 35229ace903dSChristian Ehrhardt 3523b1d16c49SChristian Ehrhardt if (signal_pending(current) && !rc) { 3524b1d16c49SChristian Ehrhardt kvm_run->exit_reason = KVM_EXIT_INTR; 35258f2abe6aSChristian Borntraeger rc = -EINTR; 3526b1d16c49SChristian Ehrhardt } 35278f2abe6aSChristian Borntraeger 352827291e21SDavid Hildenbrand if (guestdbg_exit_pending(vcpu) && !rc) { 352927291e21SDavid Hildenbrand kvm_s390_prepare_debug_exit(vcpu); 353027291e21SDavid Hildenbrand rc = 0; 353127291e21SDavid Hildenbrand } 353227291e21SDavid Hildenbrand 35338f2abe6aSChristian Borntraeger if (rc == -EREMOTE) { 353471f116bfSDavid Hildenbrand /* userspace support is needed, kvm_run has been prepared */ 35358f2abe6aSChristian Borntraeger rc = 0; 35368f2abe6aSChristian Borntraeger } 35378f2abe6aSChristian Borntraeger 3538db0758b2SDavid Hildenbrand disable_cpu_timer_accounting(vcpu); 3539b028ee3eSDavid Hildenbrand store_regs(vcpu, kvm_run); 3540d7b0b5ebSCarsten Otte 354120b7035cSJan H. Schönherr kvm_sigset_deactivate(vcpu); 3542b0c632dbSHeiko Carstens 3543b0c632dbSHeiko Carstens vcpu->stat.exit_userspace++; 3544accb757dSChristoffer Dall out: 3545accb757dSChristoffer Dall vcpu_put(vcpu); 35467e8e6ab4SHeiko Carstens return rc; 3547b0c632dbSHeiko Carstens } 3548b0c632dbSHeiko Carstens 3549b0c632dbSHeiko Carstens /* 3550b0c632dbSHeiko Carstens * store status at address 3551b0c632dbSHeiko Carstens * we use have two special cases: 3552b0c632dbSHeiko Carstens * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit 3553b0c632dbSHeiko Carstens * KVM_S390_STORE_STATUS_PREFIXED: -> prefix 3554b0c632dbSHeiko Carstens */ 3555d0bce605SHeiko Carstens int kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa) 3556b0c632dbSHeiko Carstens { 3557092670cdSCarsten Otte unsigned char archmode = 1; 35589abc2a08SDavid Hildenbrand freg_t fprs[NUM_FPRS]; 3559fda902cbSMichael Mueller unsigned int px; 35604287f247SDavid Hildenbrand u64 clkcomp, cputm; 3561d0bce605SHeiko Carstens int rc; 3562b0c632dbSHeiko Carstens 3563d9a3a09aSMartin Schwidefsky px = kvm_s390_get_prefix(vcpu); 3564d0bce605SHeiko Carstens if (gpa == KVM_S390_STORE_STATUS_NOADDR) { 3565d0bce605SHeiko Carstens if (write_guest_abs(vcpu, 163, &archmode, 1)) 3566b0c632dbSHeiko Carstens return -EFAULT; 3567d9a3a09aSMartin Schwidefsky gpa = 0; 3568d0bce605SHeiko Carstens } else if (gpa == KVM_S390_STORE_STATUS_PREFIXED) { 3569d0bce605SHeiko Carstens if (write_guest_real(vcpu, 163, &archmode, 1)) 3570b0c632dbSHeiko Carstens return -EFAULT; 3571d9a3a09aSMartin Schwidefsky gpa = px; 3572d9a3a09aSMartin Schwidefsky } else 3573d9a3a09aSMartin Schwidefsky gpa -= __LC_FPREGS_SAVE_AREA; 35749abc2a08SDavid Hildenbrand 35759abc2a08SDavid Hildenbrand /* manually convert vector registers if necessary */ 35769abc2a08SDavid Hildenbrand if (MACHINE_HAS_VX) { 35779522b37fSDavid Hildenbrand convert_vx_to_fp(fprs, (__vector128 *) vcpu->run->s.regs.vrs); 3578d9a3a09aSMartin Schwidefsky rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, 35799abc2a08SDavid Hildenbrand fprs, 128); 35809abc2a08SDavid Hildenbrand } else { 35819abc2a08SDavid Hildenbrand rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA, 35826fd8e67dSDavid Hildenbrand vcpu->run->s.regs.fprs, 128); 35839abc2a08SDavid Hildenbrand } 3584d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA, 3585d0bce605SHeiko Carstens vcpu->run->s.regs.gprs, 128); 3586d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA, 3587d0bce605SHeiko Carstens &vcpu->arch.sie_block->gpsw, 16); 3588d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA, 3589fda902cbSMichael Mueller &px, 4); 3590d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA, 35919abc2a08SDavid Hildenbrand &vcpu->run->s.regs.fpc, 4); 3592d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA, 3593d0bce605SHeiko Carstens &vcpu->arch.sie_block->todpr, 4); 35944287f247SDavid Hildenbrand cputm = kvm_s390_get_cpu_timer(vcpu); 3595d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA, 35964287f247SDavid Hildenbrand &cputm, 8); 3597178bd789SThomas Huth clkcomp = vcpu->arch.sie_block->ckc >> 8; 3598d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA, 3599d0bce605SHeiko Carstens &clkcomp, 8); 3600d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_AREGS_SAVE_AREA, 3601d0bce605SHeiko Carstens &vcpu->run->s.regs.acrs, 64); 3602d9a3a09aSMartin Schwidefsky rc |= write_guest_abs(vcpu, gpa + __LC_CREGS_SAVE_AREA, 3603d0bce605SHeiko Carstens &vcpu->arch.sie_block->gcr, 128); 3604d0bce605SHeiko Carstens return rc ? -EFAULT : 0; 3605b0c632dbSHeiko Carstens } 3606b0c632dbSHeiko Carstens 3607e879892cSThomas Huth int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) 3608e879892cSThomas Huth { 3609e879892cSThomas Huth /* 3610e879892cSThomas Huth * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy 361131d8b8d4SChristian Borntraeger * switch in the run ioctl. Let's update our copies before we save 3612e879892cSThomas Huth * it into the save area 3613e879892cSThomas Huth */ 3614d0164ee2SHendrik Brueckner save_fpu_regs(); 36159abc2a08SDavid Hildenbrand vcpu->run->s.regs.fpc = current->thread.fpu.fpc; 3616e879892cSThomas Huth save_access_regs(vcpu->run->s.regs.acrs); 3617e879892cSThomas Huth 3618e879892cSThomas Huth return kvm_s390_store_status_unloaded(vcpu, addr); 3619e879892cSThomas Huth } 3620e879892cSThomas Huth 36218ad35755SDavid Hildenbrand static void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu) 36228ad35755SDavid Hildenbrand { 36238ad35755SDavid Hildenbrand kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu); 36248e236546SChristian Borntraeger kvm_s390_sync_request(KVM_REQ_DISABLE_IBS, vcpu); 36258ad35755SDavid Hildenbrand } 36268ad35755SDavid Hildenbrand 36278ad35755SDavid Hildenbrand static void __disable_ibs_on_all_vcpus(struct kvm *kvm) 36288ad35755SDavid Hildenbrand { 36298ad35755SDavid Hildenbrand unsigned int i; 36308ad35755SDavid Hildenbrand struct kvm_vcpu *vcpu; 36318ad35755SDavid Hildenbrand 36328ad35755SDavid Hildenbrand kvm_for_each_vcpu(i, vcpu, kvm) { 36338ad35755SDavid Hildenbrand __disable_ibs_on_vcpu(vcpu); 36348ad35755SDavid Hildenbrand } 36358ad35755SDavid Hildenbrand } 36368ad35755SDavid Hildenbrand 36378ad35755SDavid Hildenbrand static void __enable_ibs_on_vcpu(struct kvm_vcpu *vcpu) 36388ad35755SDavid Hildenbrand { 363909a400e7SDavid Hildenbrand if (!sclp.has_ibs) 364009a400e7SDavid Hildenbrand return; 36418ad35755SDavid Hildenbrand kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu); 36428e236546SChristian Borntraeger kvm_s390_sync_request(KVM_REQ_ENABLE_IBS, vcpu); 36438ad35755SDavid Hildenbrand } 36448ad35755SDavid Hildenbrand 36456852d7b6SDavid Hildenbrand void kvm_s390_vcpu_start(struct kvm_vcpu *vcpu) 36466852d7b6SDavid Hildenbrand { 36478ad35755SDavid Hildenbrand int i, online_vcpus, started_vcpus = 0; 36488ad35755SDavid Hildenbrand 36498ad35755SDavid Hildenbrand if (!is_vcpu_stopped(vcpu)) 36508ad35755SDavid Hildenbrand return; 36518ad35755SDavid Hildenbrand 36526852d7b6SDavid Hildenbrand trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1); 36538ad35755SDavid Hildenbrand /* Only one cpu at a time may enter/leave the STOPPED state. */ 3654433b9ee4SDavid Hildenbrand spin_lock(&vcpu->kvm->arch.start_stop_lock); 36558ad35755SDavid Hildenbrand online_vcpus = atomic_read(&vcpu->kvm->online_vcpus); 36568ad35755SDavid Hildenbrand 36578ad35755SDavid Hildenbrand for (i = 0; i < online_vcpus; i++) { 36588ad35755SDavid Hildenbrand if (!is_vcpu_stopped(vcpu->kvm->vcpus[i])) 36598ad35755SDavid Hildenbrand started_vcpus++; 36608ad35755SDavid Hildenbrand } 36618ad35755SDavid Hildenbrand 36628ad35755SDavid Hildenbrand if (started_vcpus == 0) { 36638ad35755SDavid Hildenbrand /* we're the only active VCPU -> speed it up */ 36648ad35755SDavid Hildenbrand __enable_ibs_on_vcpu(vcpu); 36658ad35755SDavid Hildenbrand } else if (started_vcpus == 1) { 36668ad35755SDavid Hildenbrand /* 36678ad35755SDavid Hildenbrand * As we are starting a second VCPU, we have to disable 36688ad35755SDavid Hildenbrand * the IBS facility on all VCPUs to remove potentially 36698ad35755SDavid Hildenbrand * oustanding ENABLE requests. 36708ad35755SDavid Hildenbrand */ 36718ad35755SDavid Hildenbrand __disable_ibs_on_all_vcpus(vcpu->kvm); 36728ad35755SDavid Hildenbrand } 36738ad35755SDavid Hildenbrand 36749daecfc6SDavid Hildenbrand kvm_s390_clear_cpuflags(vcpu, CPUSTAT_STOPPED); 36758ad35755SDavid Hildenbrand /* 36768ad35755SDavid Hildenbrand * Another VCPU might have used IBS while we were offline. 36778ad35755SDavid Hildenbrand * Let's play safe and flush the VCPU at startup. 36788ad35755SDavid Hildenbrand */ 3679d3d692c8SDavid Hildenbrand kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu); 3680433b9ee4SDavid Hildenbrand spin_unlock(&vcpu->kvm->arch.start_stop_lock); 36818ad35755SDavid Hildenbrand return; 36826852d7b6SDavid Hildenbrand } 36836852d7b6SDavid Hildenbrand 36846852d7b6SDavid Hildenbrand void kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu) 36856852d7b6SDavid Hildenbrand { 36868ad35755SDavid Hildenbrand int i, online_vcpus, started_vcpus = 0; 36878ad35755SDavid Hildenbrand struct kvm_vcpu *started_vcpu = NULL; 36888ad35755SDavid Hildenbrand 36898ad35755SDavid Hildenbrand if (is_vcpu_stopped(vcpu)) 36908ad35755SDavid Hildenbrand return; 36918ad35755SDavid Hildenbrand 36926852d7b6SDavid Hildenbrand trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0); 36938ad35755SDavid Hildenbrand /* Only one cpu at a time may enter/leave the STOPPED state. */ 3694433b9ee4SDavid Hildenbrand spin_lock(&vcpu->kvm->arch.start_stop_lock); 36958ad35755SDavid Hildenbrand online_vcpus = atomic_read(&vcpu->kvm->online_vcpus); 36968ad35755SDavid Hildenbrand 369732f5ff63SDavid Hildenbrand /* SIGP STOP and SIGP STOP AND STORE STATUS has been fully processed */ 36986cddd432SDavid Hildenbrand kvm_s390_clear_stop_irq(vcpu); 369932f5ff63SDavid Hildenbrand 3700ef8f4f49SDavid Hildenbrand kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED); 37018ad35755SDavid Hildenbrand __disable_ibs_on_vcpu(vcpu); 37028ad35755SDavid Hildenbrand 37038ad35755SDavid Hildenbrand for (i = 0; i < online_vcpus; i++) { 37048ad35755SDavid Hildenbrand if (!is_vcpu_stopped(vcpu->kvm->vcpus[i])) { 37058ad35755SDavid Hildenbrand started_vcpus++; 37068ad35755SDavid Hildenbrand started_vcpu = vcpu->kvm->vcpus[i]; 37078ad35755SDavid Hildenbrand } 37088ad35755SDavid Hildenbrand } 37098ad35755SDavid Hildenbrand 37108ad35755SDavid Hildenbrand if (started_vcpus == 1) { 37118ad35755SDavid Hildenbrand /* 37128ad35755SDavid Hildenbrand * As we only have one VCPU left, we want to enable the 37138ad35755SDavid Hildenbrand * IBS facility for that VCPU to speed it up. 37148ad35755SDavid Hildenbrand */ 37158ad35755SDavid Hildenbrand __enable_ibs_on_vcpu(started_vcpu); 37168ad35755SDavid Hildenbrand } 37178ad35755SDavid Hildenbrand 3718433b9ee4SDavid Hildenbrand spin_unlock(&vcpu->kvm->arch.start_stop_lock); 37198ad35755SDavid Hildenbrand return; 37206852d7b6SDavid Hildenbrand } 37216852d7b6SDavid Hildenbrand 3722d6712df9SCornelia Huck static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, 3723d6712df9SCornelia Huck struct kvm_enable_cap *cap) 3724d6712df9SCornelia Huck { 3725d6712df9SCornelia Huck int r; 3726d6712df9SCornelia Huck 3727d6712df9SCornelia Huck if (cap->flags) 3728d6712df9SCornelia Huck return -EINVAL; 3729d6712df9SCornelia Huck 3730d6712df9SCornelia Huck switch (cap->cap) { 3731fa6b7fe9SCornelia Huck case KVM_CAP_S390_CSS_SUPPORT: 3732fa6b7fe9SCornelia Huck if (!vcpu->kvm->arch.css_support) { 3733fa6b7fe9SCornelia Huck vcpu->kvm->arch.css_support = 1; 3734c92ea7b9SChristian Borntraeger VM_EVENT(vcpu->kvm, 3, "%s", "ENABLE: CSS support"); 3735fa6b7fe9SCornelia Huck trace_kvm_s390_enable_css(vcpu->kvm); 3736fa6b7fe9SCornelia Huck } 3737fa6b7fe9SCornelia Huck r = 0; 3738fa6b7fe9SCornelia Huck break; 3739d6712df9SCornelia Huck default: 3740d6712df9SCornelia Huck r = -EINVAL; 3741d6712df9SCornelia Huck break; 3742d6712df9SCornelia Huck } 3743d6712df9SCornelia Huck return r; 3744d6712df9SCornelia Huck } 3745d6712df9SCornelia Huck 374641408c28SThomas Huth static long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu, 374741408c28SThomas Huth struct kvm_s390_mem_op *mop) 374841408c28SThomas Huth { 374941408c28SThomas Huth void __user *uaddr = (void __user *)mop->buf; 375041408c28SThomas Huth void *tmpbuf = NULL; 375141408c28SThomas Huth int r, srcu_idx; 375241408c28SThomas Huth const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION 375341408c28SThomas Huth | KVM_S390_MEMOP_F_CHECK_ONLY; 375441408c28SThomas Huth 375541408c28SThomas Huth if (mop->flags & ~supported_flags) 375641408c28SThomas Huth return -EINVAL; 375741408c28SThomas Huth 375841408c28SThomas Huth if (mop->size > MEM_OP_MAX_SIZE) 375941408c28SThomas Huth return -E2BIG; 376041408c28SThomas Huth 376141408c28SThomas Huth if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) { 376241408c28SThomas Huth tmpbuf = vmalloc(mop->size); 376341408c28SThomas Huth if (!tmpbuf) 376441408c28SThomas Huth return -ENOMEM; 376541408c28SThomas Huth } 376641408c28SThomas Huth 376741408c28SThomas Huth srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 376841408c28SThomas Huth 376941408c28SThomas Huth switch (mop->op) { 377041408c28SThomas Huth case KVM_S390_MEMOP_LOGICAL_READ: 377141408c28SThomas Huth if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { 377292c96321SDavid Hildenbrand r = check_gva_range(vcpu, mop->gaddr, mop->ar, 377392c96321SDavid Hildenbrand mop->size, GACC_FETCH); 377441408c28SThomas Huth break; 377541408c28SThomas Huth } 377641408c28SThomas Huth r = read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size); 377741408c28SThomas Huth if (r == 0) { 377841408c28SThomas Huth if (copy_to_user(uaddr, tmpbuf, mop->size)) 377941408c28SThomas Huth r = -EFAULT; 378041408c28SThomas Huth } 378141408c28SThomas Huth break; 378241408c28SThomas Huth case KVM_S390_MEMOP_LOGICAL_WRITE: 378341408c28SThomas Huth if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { 378492c96321SDavid Hildenbrand r = check_gva_range(vcpu, mop->gaddr, mop->ar, 378592c96321SDavid Hildenbrand mop->size, GACC_STORE); 378641408c28SThomas Huth break; 378741408c28SThomas Huth } 378841408c28SThomas Huth if (copy_from_user(tmpbuf, uaddr, mop->size)) { 378941408c28SThomas Huth r = -EFAULT; 379041408c28SThomas Huth break; 379141408c28SThomas Huth } 379241408c28SThomas Huth r = write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size); 379341408c28SThomas Huth break; 379441408c28SThomas Huth default: 379541408c28SThomas Huth r = -EINVAL; 379641408c28SThomas Huth } 379741408c28SThomas Huth 379841408c28SThomas Huth srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx); 379941408c28SThomas Huth 380041408c28SThomas Huth if (r > 0 && (mop->flags & KVM_S390_MEMOP_F_INJECT_EXCEPTION) != 0) 380141408c28SThomas Huth kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm); 380241408c28SThomas Huth 380341408c28SThomas Huth vfree(tmpbuf); 380441408c28SThomas Huth return r; 380541408c28SThomas Huth } 380641408c28SThomas Huth 38075cb0944cSPaolo Bonzini long kvm_arch_vcpu_async_ioctl(struct file *filp, 3808b0c632dbSHeiko Carstens unsigned int ioctl, unsigned long arg) 3809b0c632dbSHeiko Carstens { 3810b0c632dbSHeiko Carstens struct kvm_vcpu *vcpu = filp->private_data; 3811b0c632dbSHeiko Carstens void __user *argp = (void __user *)arg; 3812b0c632dbSHeiko Carstens 381393736624SAvi Kivity switch (ioctl) { 381447b43c52SJens Freimann case KVM_S390_IRQ: { 381547b43c52SJens Freimann struct kvm_s390_irq s390irq; 381647b43c52SJens Freimann 381747b43c52SJens Freimann if (copy_from_user(&s390irq, argp, sizeof(s390irq))) 38189b062471SChristoffer Dall return -EFAULT; 38199b062471SChristoffer Dall return kvm_s390_inject_vcpu(vcpu, &s390irq); 382047b43c52SJens Freimann } 382193736624SAvi Kivity case KVM_S390_INTERRUPT: { 3822ba5c1e9bSCarsten Otte struct kvm_s390_interrupt s390int; 3823383d0b05SJens Freimann struct kvm_s390_irq s390irq; 3824ba5c1e9bSCarsten Otte 3825ba5c1e9bSCarsten Otte if (copy_from_user(&s390int, argp, sizeof(s390int))) 38269b062471SChristoffer Dall return -EFAULT; 3827383d0b05SJens Freimann if (s390int_to_s390irq(&s390int, &s390irq)) 3828383d0b05SJens Freimann return -EINVAL; 38299b062471SChristoffer Dall return kvm_s390_inject_vcpu(vcpu, &s390irq); 3830ba5c1e9bSCarsten Otte } 38319b062471SChristoffer Dall } 38325cb0944cSPaolo Bonzini return -ENOIOCTLCMD; 38335cb0944cSPaolo Bonzini } 38345cb0944cSPaolo Bonzini 38355cb0944cSPaolo Bonzini long kvm_arch_vcpu_ioctl(struct file *filp, 38365cb0944cSPaolo Bonzini unsigned int ioctl, unsigned long arg) 38375cb0944cSPaolo Bonzini { 38385cb0944cSPaolo Bonzini struct kvm_vcpu *vcpu = filp->private_data; 38395cb0944cSPaolo Bonzini void __user *argp = (void __user *)arg; 38405cb0944cSPaolo Bonzini int idx; 38415cb0944cSPaolo Bonzini long r; 38429b062471SChristoffer Dall 38439b062471SChristoffer Dall vcpu_load(vcpu); 38449b062471SChristoffer Dall 38459b062471SChristoffer Dall switch (ioctl) { 3846b0c632dbSHeiko Carstens case KVM_S390_STORE_STATUS: 3847800c1065SThomas Huth idx = srcu_read_lock(&vcpu->kvm->srcu); 3848bc923cc9SAvi Kivity r = kvm_s390_vcpu_store_status(vcpu, arg); 3849800c1065SThomas Huth srcu_read_unlock(&vcpu->kvm->srcu, idx); 3850bc923cc9SAvi Kivity break; 3851b0c632dbSHeiko Carstens case KVM_S390_SET_INITIAL_PSW: { 3852b0c632dbSHeiko Carstens psw_t psw; 3853b0c632dbSHeiko Carstens 3854bc923cc9SAvi Kivity r = -EFAULT; 3855b0c632dbSHeiko Carstens if (copy_from_user(&psw, argp, sizeof(psw))) 3856bc923cc9SAvi Kivity break; 3857bc923cc9SAvi Kivity r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw); 3858bc923cc9SAvi Kivity break; 3859b0c632dbSHeiko Carstens } 3860b0c632dbSHeiko Carstens case KVM_S390_INITIAL_RESET: 3861bc923cc9SAvi Kivity r = kvm_arch_vcpu_ioctl_initial_reset(vcpu); 3862bc923cc9SAvi Kivity break; 386314eebd91SCarsten Otte case KVM_SET_ONE_REG: 386414eebd91SCarsten Otte case KVM_GET_ONE_REG: { 386514eebd91SCarsten Otte struct kvm_one_reg reg; 386614eebd91SCarsten Otte r = -EFAULT; 386714eebd91SCarsten Otte if (copy_from_user(®, argp, sizeof(reg))) 386814eebd91SCarsten Otte break; 386914eebd91SCarsten Otte if (ioctl == KVM_SET_ONE_REG) 387014eebd91SCarsten Otte r = kvm_arch_vcpu_ioctl_set_one_reg(vcpu, ®); 387114eebd91SCarsten Otte else 387214eebd91SCarsten Otte r = kvm_arch_vcpu_ioctl_get_one_reg(vcpu, ®); 387314eebd91SCarsten Otte break; 387414eebd91SCarsten Otte } 387527e0393fSCarsten Otte #ifdef CONFIG_KVM_S390_UCONTROL 387627e0393fSCarsten Otte case KVM_S390_UCAS_MAP: { 387727e0393fSCarsten Otte struct kvm_s390_ucas_mapping ucasmap; 387827e0393fSCarsten Otte 387927e0393fSCarsten Otte if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) { 388027e0393fSCarsten Otte r = -EFAULT; 388127e0393fSCarsten Otte break; 388227e0393fSCarsten Otte } 388327e0393fSCarsten Otte 388427e0393fSCarsten Otte if (!kvm_is_ucontrol(vcpu->kvm)) { 388527e0393fSCarsten Otte r = -EINVAL; 388627e0393fSCarsten Otte break; 388727e0393fSCarsten Otte } 388827e0393fSCarsten Otte 388927e0393fSCarsten Otte r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr, 389027e0393fSCarsten Otte ucasmap.vcpu_addr, ucasmap.length); 389127e0393fSCarsten Otte break; 389227e0393fSCarsten Otte } 389327e0393fSCarsten Otte case KVM_S390_UCAS_UNMAP: { 389427e0393fSCarsten Otte struct kvm_s390_ucas_mapping ucasmap; 389527e0393fSCarsten Otte 389627e0393fSCarsten Otte if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) { 389727e0393fSCarsten Otte r = -EFAULT; 389827e0393fSCarsten Otte break; 389927e0393fSCarsten Otte } 390027e0393fSCarsten Otte 390127e0393fSCarsten Otte if (!kvm_is_ucontrol(vcpu->kvm)) { 390227e0393fSCarsten Otte r = -EINVAL; 390327e0393fSCarsten Otte break; 390427e0393fSCarsten Otte } 390527e0393fSCarsten Otte 390627e0393fSCarsten Otte r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr, 390727e0393fSCarsten Otte ucasmap.length); 390827e0393fSCarsten Otte break; 390927e0393fSCarsten Otte } 391027e0393fSCarsten Otte #endif 3911ccc7910fSCarsten Otte case KVM_S390_VCPU_FAULT: { 3912527e30b4SMartin Schwidefsky r = gmap_fault(vcpu->arch.gmap, arg, 0); 3913ccc7910fSCarsten Otte break; 3914ccc7910fSCarsten Otte } 3915d6712df9SCornelia Huck case KVM_ENABLE_CAP: 3916d6712df9SCornelia Huck { 3917d6712df9SCornelia Huck struct kvm_enable_cap cap; 3918d6712df9SCornelia Huck r = -EFAULT; 3919d6712df9SCornelia Huck if (copy_from_user(&cap, argp, sizeof(cap))) 3920d6712df9SCornelia Huck break; 3921d6712df9SCornelia Huck r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap); 3922d6712df9SCornelia Huck break; 3923d6712df9SCornelia Huck } 392441408c28SThomas Huth case KVM_S390_MEM_OP: { 392541408c28SThomas Huth struct kvm_s390_mem_op mem_op; 392641408c28SThomas Huth 392741408c28SThomas Huth if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0) 392841408c28SThomas Huth r = kvm_s390_guest_mem_op(vcpu, &mem_op); 392941408c28SThomas Huth else 393041408c28SThomas Huth r = -EFAULT; 393141408c28SThomas Huth break; 393241408c28SThomas Huth } 3933816c7667SJens Freimann case KVM_S390_SET_IRQ_STATE: { 3934816c7667SJens Freimann struct kvm_s390_irq_state irq_state; 3935816c7667SJens Freimann 3936816c7667SJens Freimann r = -EFAULT; 3937816c7667SJens Freimann if (copy_from_user(&irq_state, argp, sizeof(irq_state))) 3938816c7667SJens Freimann break; 3939816c7667SJens Freimann if (irq_state.len > VCPU_IRQS_MAX_BUF || 3940816c7667SJens Freimann irq_state.len == 0 || 3941816c7667SJens Freimann irq_state.len % sizeof(struct kvm_s390_irq) > 0) { 3942816c7667SJens Freimann r = -EINVAL; 3943816c7667SJens Freimann break; 3944816c7667SJens Freimann } 3945bb64da9aSChristian Borntraeger /* do not use irq_state.flags, it will break old QEMUs */ 3946816c7667SJens Freimann r = kvm_s390_set_irq_state(vcpu, 3947816c7667SJens Freimann (void __user *) irq_state.buf, 3948816c7667SJens Freimann irq_state.len); 3949816c7667SJens Freimann break; 3950816c7667SJens Freimann } 3951816c7667SJens Freimann case KVM_S390_GET_IRQ_STATE: { 3952816c7667SJens Freimann struct kvm_s390_irq_state irq_state; 3953816c7667SJens Freimann 3954816c7667SJens Freimann r = -EFAULT; 3955816c7667SJens Freimann if (copy_from_user(&irq_state, argp, sizeof(irq_state))) 3956816c7667SJens Freimann break; 3957816c7667SJens Freimann if (irq_state.len == 0) { 3958816c7667SJens Freimann r = -EINVAL; 3959816c7667SJens Freimann break; 3960816c7667SJens Freimann } 3961bb64da9aSChristian Borntraeger /* do not use irq_state.flags, it will break old QEMUs */ 3962816c7667SJens Freimann r = kvm_s390_get_irq_state(vcpu, 3963816c7667SJens Freimann (__u8 __user *) irq_state.buf, 3964816c7667SJens Freimann irq_state.len); 3965816c7667SJens Freimann break; 3966816c7667SJens Freimann } 3967b0c632dbSHeiko Carstens default: 39683e6afcf1SCarsten Otte r = -ENOTTY; 3969b0c632dbSHeiko Carstens } 39709b062471SChristoffer Dall 39719b062471SChristoffer Dall vcpu_put(vcpu); 3972bc923cc9SAvi Kivity return r; 3973b0c632dbSHeiko Carstens } 3974b0c632dbSHeiko Carstens 39755b1c1493SCarsten Otte int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf) 39765b1c1493SCarsten Otte { 39775b1c1493SCarsten Otte #ifdef CONFIG_KVM_S390_UCONTROL 39785b1c1493SCarsten Otte if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET) 39795b1c1493SCarsten Otte && (kvm_is_ucontrol(vcpu->kvm))) { 39805b1c1493SCarsten Otte vmf->page = virt_to_page(vcpu->arch.sie_block); 39815b1c1493SCarsten Otte get_page(vmf->page); 39825b1c1493SCarsten Otte return 0; 39835b1c1493SCarsten Otte } 39845b1c1493SCarsten Otte #endif 39855b1c1493SCarsten Otte return VM_FAULT_SIGBUS; 39865b1c1493SCarsten Otte } 39875b1c1493SCarsten Otte 39885587027cSAneesh Kumar K.V int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot, 39895587027cSAneesh Kumar K.V unsigned long npages) 3990db3fe4ebSTakuya Yoshikawa { 3991db3fe4ebSTakuya Yoshikawa return 0; 3992db3fe4ebSTakuya Yoshikawa } 3993db3fe4ebSTakuya Yoshikawa 3994b0c632dbSHeiko Carstens /* Section: memory related */ 3995f7784b8eSMarcelo Tosatti int kvm_arch_prepare_memory_region(struct kvm *kvm, 3996f7784b8eSMarcelo Tosatti struct kvm_memory_slot *memslot, 399709170a49SPaolo Bonzini const struct kvm_userspace_memory_region *mem, 39987b6195a9STakuya Yoshikawa enum kvm_mr_change change) 3999b0c632dbSHeiko Carstens { 4000dd2887e7SNick Wang /* A few sanity checks. We can have memory slots which have to be 4001dd2887e7SNick Wang located/ended at a segment boundary (1MB). The memory in userland is 4002dd2887e7SNick Wang ok to be fragmented into various different vmas. It is okay to mmap() 4003dd2887e7SNick Wang and munmap() stuff in this slot after doing this call at any time */ 4004b0c632dbSHeiko Carstens 4005598841caSCarsten Otte if (mem->userspace_addr & 0xffffful) 4006b0c632dbSHeiko Carstens return -EINVAL; 4007b0c632dbSHeiko Carstens 4008598841caSCarsten Otte if (mem->memory_size & 0xffffful) 4009b0c632dbSHeiko Carstens return -EINVAL; 4010b0c632dbSHeiko Carstens 4011a3a92c31SDominik Dingel if (mem->guest_phys_addr + mem->memory_size > kvm->arch.mem_limit) 4012a3a92c31SDominik Dingel return -EINVAL; 4013a3a92c31SDominik Dingel 4014f7784b8eSMarcelo Tosatti return 0; 4015f7784b8eSMarcelo Tosatti } 4016f7784b8eSMarcelo Tosatti 4017f7784b8eSMarcelo Tosatti void kvm_arch_commit_memory_region(struct kvm *kvm, 401809170a49SPaolo Bonzini const struct kvm_userspace_memory_region *mem, 40198482644aSTakuya Yoshikawa const struct kvm_memory_slot *old, 4020f36f3f28SPaolo Bonzini const struct kvm_memory_slot *new, 40218482644aSTakuya Yoshikawa enum kvm_mr_change change) 4022f7784b8eSMarcelo Tosatti { 4023f7850c92SCarsten Otte int rc; 4024f7784b8eSMarcelo Tosatti 40252cef4debSChristian Borntraeger /* If the basics of the memslot do not change, we do not want 40262cef4debSChristian Borntraeger * to update the gmap. Every update causes several unnecessary 40272cef4debSChristian Borntraeger * segment translation exceptions. This is usually handled just 40282cef4debSChristian Borntraeger * fine by the normal fault handler + gmap, but it will also 40292cef4debSChristian Borntraeger * cause faults on the prefix page of running guest CPUs. 40302cef4debSChristian Borntraeger */ 40312cef4debSChristian Borntraeger if (old->userspace_addr == mem->userspace_addr && 40322cef4debSChristian Borntraeger old->base_gfn * PAGE_SIZE == mem->guest_phys_addr && 40332cef4debSChristian Borntraeger old->npages * PAGE_SIZE == mem->memory_size) 40342cef4debSChristian Borntraeger return; 4035598841caSCarsten Otte 4036598841caSCarsten Otte rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr, 4037598841caSCarsten Otte mem->guest_phys_addr, mem->memory_size); 4038598841caSCarsten Otte if (rc) 4039ea2cdd27SDavid Hildenbrand pr_warn("failed to commit memory region\n"); 4040598841caSCarsten Otte return; 4041b0c632dbSHeiko Carstens } 4042b0c632dbSHeiko Carstens 404360a37709SAlexander Yarygin static inline unsigned long nonhyp_mask(int i) 404460a37709SAlexander Yarygin { 404560a37709SAlexander Yarygin unsigned int nonhyp_fai = (sclp.hmfai << i * 2) >> 30; 404660a37709SAlexander Yarygin 404760a37709SAlexander Yarygin return 0x0000ffffffffffffUL >> (nonhyp_fai << 4); 404860a37709SAlexander Yarygin } 404960a37709SAlexander Yarygin 40503491caf2SChristian Borntraeger void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) 40513491caf2SChristian Borntraeger { 40523491caf2SChristian Borntraeger vcpu->valid_wakeup = false; 40533491caf2SChristian Borntraeger } 40543491caf2SChristian Borntraeger 4055b0c632dbSHeiko Carstens static int __init kvm_s390_init(void) 4056b0c632dbSHeiko Carstens { 405760a37709SAlexander Yarygin int i; 405860a37709SAlexander Yarygin 405907197fd0SDavid Hildenbrand if (!sclp.has_sief2) { 406007197fd0SDavid Hildenbrand pr_info("SIE not available\n"); 406107197fd0SDavid Hildenbrand return -ENODEV; 406207197fd0SDavid Hildenbrand } 406307197fd0SDavid Hildenbrand 406460a37709SAlexander Yarygin for (i = 0; i < 16; i++) 4065c3b9e3e1SChristian Borntraeger kvm_s390_fac_base[i] |= 406660a37709SAlexander Yarygin S390_lowcore.stfle_fac_list[i] & nonhyp_mask(i); 406760a37709SAlexander Yarygin 40689d8d5786SMichael Mueller return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE); 4069b0c632dbSHeiko Carstens } 4070b0c632dbSHeiko Carstens 4071b0c632dbSHeiko Carstens static void __exit kvm_s390_exit(void) 4072b0c632dbSHeiko Carstens { 4073b0c632dbSHeiko Carstens kvm_exit(); 4074b0c632dbSHeiko Carstens } 4075b0c632dbSHeiko Carstens 4076b0c632dbSHeiko Carstens module_init(kvm_s390_init); 4077b0c632dbSHeiko Carstens module_exit(kvm_s390_exit); 4078566af940SCornelia Huck 4079566af940SCornelia Huck /* 4080566af940SCornelia Huck * Enable autoloading of the kvm module. 4081566af940SCornelia Huck * Note that we add the module alias here instead of virt/kvm/kvm_main.c 4082566af940SCornelia Huck * since x86 takes a different approach. 4083566af940SCornelia Huck */ 4084566af940SCornelia Huck #include <linux/miscdevice.h> 4085566af940SCornelia Huck MODULE_ALIAS_MISCDEV(KVM_MINOR); 4086566af940SCornelia Huck MODULE_ALIAS("devname:kvm"); 4087