18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * hosting IBM Z kernel virtual machines (s390x)
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright IBM Corp. 2008, 2020
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *    Author(s): Carsten Otte <cotte@de.ibm.com>
88c2ecf20Sopenharmony_ci *               Christian Borntraeger <borntraeger@de.ibm.com>
98c2ecf20Sopenharmony_ci *               Heiko Carstens <heiko.carstens@de.ibm.com>
108c2ecf20Sopenharmony_ci *               Christian Ehrhardt <ehrhardt@de.ibm.com>
118c2ecf20Sopenharmony_ci *               Jason J. Herne <jjherne@us.ibm.com>
128c2ecf20Sopenharmony_ci */
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_ci#define KMSG_COMPONENT "kvm-s390"
158c2ecf20Sopenharmony_ci#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci#include <linux/compiler.h>
188c2ecf20Sopenharmony_ci#include <linux/err.h>
198c2ecf20Sopenharmony_ci#include <linux/fs.h>
208c2ecf20Sopenharmony_ci#include <linux/hrtimer.h>
218c2ecf20Sopenharmony_ci#include <linux/init.h>
228c2ecf20Sopenharmony_ci#include <linux/kvm.h>
238c2ecf20Sopenharmony_ci#include <linux/kvm_host.h>
248c2ecf20Sopenharmony_ci#include <linux/mman.h>
258c2ecf20Sopenharmony_ci#include <linux/module.h>
268c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
278c2ecf20Sopenharmony_ci#include <linux/random.h>
288c2ecf20Sopenharmony_ci#include <linux/slab.h>
298c2ecf20Sopenharmony_ci#include <linux/timer.h>
308c2ecf20Sopenharmony_ci#include <linux/vmalloc.h>
318c2ecf20Sopenharmony_ci#include <linux/bitmap.h>
328c2ecf20Sopenharmony_ci#include <linux/sched/signal.h>
338c2ecf20Sopenharmony_ci#include <linux/string.h>
348c2ecf20Sopenharmony_ci#include <linux/pgtable.h>
358c2ecf20Sopenharmony_ci
368c2ecf20Sopenharmony_ci#include <asm/asm-offsets.h>
378c2ecf20Sopenharmony_ci#include <asm/lowcore.h>
388c2ecf20Sopenharmony_ci#include <asm/stp.h>
398c2ecf20Sopenharmony_ci#include <asm/gmap.h>
408c2ecf20Sopenharmony_ci#include <asm/nmi.h>
418c2ecf20Sopenharmony_ci#include <asm/switch_to.h>
428c2ecf20Sopenharmony_ci#include <asm/isc.h>
438c2ecf20Sopenharmony_ci#include <asm/sclp.h>
448c2ecf20Sopenharmony_ci#include <asm/cpacf.h>
458c2ecf20Sopenharmony_ci#include <asm/timex.h>
468c2ecf20Sopenharmony_ci#include <asm/ap.h>
478c2ecf20Sopenharmony_ci#include <asm/uv.h>
488c2ecf20Sopenharmony_ci#include "kvm-s390.h"
498c2ecf20Sopenharmony_ci#include "gaccess.h"
508c2ecf20Sopenharmony_ci
518c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS
528c2ecf20Sopenharmony_ci#include "trace.h"
538c2ecf20Sopenharmony_ci#include "trace-s390.h"
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci#define MEM_OP_MAX_SIZE 65536	/* Maximum transfer size for KVM_S390_MEM_OP */
568c2ecf20Sopenharmony_ci#define LOCAL_IRQS 32
578c2ecf20Sopenharmony_ci#define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
588c2ecf20Sopenharmony_ci			   (KVM_MAX_VCPUS + LOCAL_IRQS))
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_cistruct kvm_stats_debugfs_item debugfs_entries[] = {
618c2ecf20Sopenharmony_ci	VCPU_STAT("userspace_handled", exit_userspace),
628c2ecf20Sopenharmony_ci	VCPU_STAT("exit_null", exit_null),
638c2ecf20Sopenharmony_ci	VCPU_STAT("exit_validity", exit_validity),
648c2ecf20Sopenharmony_ci	VCPU_STAT("exit_stop_request", exit_stop_request),
658c2ecf20Sopenharmony_ci	VCPU_STAT("exit_external_request", exit_external_request),
668c2ecf20Sopenharmony_ci	VCPU_STAT("exit_io_request", exit_io_request),
678c2ecf20Sopenharmony_ci	VCPU_STAT("exit_external_interrupt", exit_external_interrupt),
688c2ecf20Sopenharmony_ci	VCPU_STAT("exit_instruction", exit_instruction),
698c2ecf20Sopenharmony_ci	VCPU_STAT("exit_pei", exit_pei),
708c2ecf20Sopenharmony_ci	VCPU_STAT("exit_program_interruption", exit_program_interruption),
718c2ecf20Sopenharmony_ci	VCPU_STAT("exit_instr_and_program_int", exit_instr_and_program),
728c2ecf20Sopenharmony_ci	VCPU_STAT("exit_operation_exception", exit_operation_exception),
738c2ecf20Sopenharmony_ci	VCPU_STAT("halt_successful_poll", halt_successful_poll),
748c2ecf20Sopenharmony_ci	VCPU_STAT("halt_attempted_poll", halt_attempted_poll),
758c2ecf20Sopenharmony_ci	VCPU_STAT("halt_poll_invalid", halt_poll_invalid),
768c2ecf20Sopenharmony_ci	VCPU_STAT("halt_no_poll_steal", halt_no_poll_steal),
778c2ecf20Sopenharmony_ci	VCPU_STAT("halt_wakeup", halt_wakeup),
788c2ecf20Sopenharmony_ci	VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
798c2ecf20Sopenharmony_ci	VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
808c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_lctlg", instruction_lctlg),
818c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_lctl", instruction_lctl),
828c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stctl", instruction_stctl),
838c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stctg", instruction_stctg),
848c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_ckc", deliver_ckc),
858c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_cputm", deliver_cputm),
868c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_emergency_signal", deliver_emergency_signal),
878c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_external_call", deliver_external_call),
888c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_service_signal", deliver_service_signal),
898c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_virtio", deliver_virtio),
908c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_stop_signal", deliver_stop_signal),
918c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_prefix_signal", deliver_prefix_signal),
928c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_restart_signal", deliver_restart_signal),
938c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_program", deliver_program),
948c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_io", deliver_io),
958c2ecf20Sopenharmony_ci	VCPU_STAT("deliver_machine_check", deliver_machine_check),
968c2ecf20Sopenharmony_ci	VCPU_STAT("exit_wait_state", exit_wait_state),
978c2ecf20Sopenharmony_ci	VCPU_STAT("inject_ckc", inject_ckc),
988c2ecf20Sopenharmony_ci	VCPU_STAT("inject_cputm", inject_cputm),
998c2ecf20Sopenharmony_ci	VCPU_STAT("inject_external_call", inject_external_call),
1008c2ecf20Sopenharmony_ci	VM_STAT("inject_float_mchk", inject_float_mchk),
1018c2ecf20Sopenharmony_ci	VCPU_STAT("inject_emergency_signal", inject_emergency_signal),
1028c2ecf20Sopenharmony_ci	VM_STAT("inject_io", inject_io),
1038c2ecf20Sopenharmony_ci	VCPU_STAT("inject_mchk", inject_mchk),
1048c2ecf20Sopenharmony_ci	VM_STAT("inject_pfault_done", inject_pfault_done),
1058c2ecf20Sopenharmony_ci	VCPU_STAT("inject_program", inject_program),
1068c2ecf20Sopenharmony_ci	VCPU_STAT("inject_restart", inject_restart),
1078c2ecf20Sopenharmony_ci	VM_STAT("inject_service_signal", inject_service_signal),
1088c2ecf20Sopenharmony_ci	VCPU_STAT("inject_set_prefix", inject_set_prefix),
1098c2ecf20Sopenharmony_ci	VCPU_STAT("inject_stop_signal", inject_stop_signal),
1108c2ecf20Sopenharmony_ci	VCPU_STAT("inject_pfault_init", inject_pfault_init),
1118c2ecf20Sopenharmony_ci	VM_STAT("inject_virtio", inject_virtio),
1128c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_epsw", instruction_epsw),
1138c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_gs", instruction_gs),
1148c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_io_other", instruction_io_other),
1158c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_lpsw", instruction_lpsw),
1168c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_lpswe", instruction_lpswe),
1178c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_pfmf", instruction_pfmf),
1188c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_ptff", instruction_ptff),
1198c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stidp", instruction_stidp),
1208c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sck", instruction_sck),
1218c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sckpf", instruction_sckpf),
1228c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_spx", instruction_spx),
1238c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stpx", instruction_stpx),
1248c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stap", instruction_stap),
1258c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_iske", instruction_iske),
1268c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_ri", instruction_ri),
1278c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_rrbe", instruction_rrbe),
1288c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sske", instruction_sske),
1298c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_ipte_interlock", instruction_ipte_interlock),
1308c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_essa", instruction_essa),
1318c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stsi", instruction_stsi),
1328c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_stfl", instruction_stfl),
1338c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_tb", instruction_tb),
1348c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_tpi", instruction_tpi),
1358c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_tprot", instruction_tprot),
1368c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_tsch", instruction_tsch),
1378c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sthyi", instruction_sthyi),
1388c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sie", instruction_sie),
1398c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_sense", instruction_sigp_sense),
1408c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_sense_running", instruction_sigp_sense_running),
1418c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_external_call", instruction_sigp_external_call),
1428c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_emergency", instruction_sigp_emergency),
1438c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_cond_emergency", instruction_sigp_cond_emergency),
1448c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_start", instruction_sigp_start),
1458c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_stop", instruction_sigp_stop),
1468c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_stop_store_status", instruction_sigp_stop_store_status),
1478c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_store_status", instruction_sigp_store_status),
1488c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_store_adtl_status", instruction_sigp_store_adtl_status),
1498c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_set_arch", instruction_sigp_arch),
1508c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_set_prefix", instruction_sigp_prefix),
1518c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_restart", instruction_sigp_restart),
1528c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_cpu_reset", instruction_sigp_cpu_reset),
1538c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_init_cpu_reset", instruction_sigp_init_cpu_reset),
1548c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_sigp_unknown", instruction_sigp_unknown),
1558c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_10", diagnose_10),
1568c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_44", diagnose_44),
1578c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_9c", diagnose_9c),
1588c2ecf20Sopenharmony_ci	VCPU_STAT("diag_9c_ignored", diagnose_9c_ignored),
1598c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_258", diagnose_258),
1608c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_308", diagnose_308),
1618c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_500", diagnose_500),
1628c2ecf20Sopenharmony_ci	VCPU_STAT("instruction_diag_other", diagnose_other),
1638c2ecf20Sopenharmony_ci	{ NULL }
1648c2ecf20Sopenharmony_ci};
1658c2ecf20Sopenharmony_ci
1668c2ecf20Sopenharmony_cistruct kvm_s390_tod_clock_ext {
1678c2ecf20Sopenharmony_ci	__u8 epoch_idx;
1688c2ecf20Sopenharmony_ci	__u64 tod;
1698c2ecf20Sopenharmony_ci	__u8 reserved[7];
1708c2ecf20Sopenharmony_ci} __packed;
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci/* allow nested virtualization in KVM (if enabled by user space) */
1738c2ecf20Sopenharmony_cistatic int nested;
1748c2ecf20Sopenharmony_cimodule_param(nested, int, S_IRUGO);
1758c2ecf20Sopenharmony_ciMODULE_PARM_DESC(nested, "Nested virtualization support");
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci/* allow 1m huge page guest backing, if !nested */
1788c2ecf20Sopenharmony_cistatic int hpage;
1798c2ecf20Sopenharmony_cimodule_param(hpage, int, 0444);
1808c2ecf20Sopenharmony_ciMODULE_PARM_DESC(hpage, "1m huge page backing support");
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_ci/* maximum percentage of steal time for polling.  >100 is treated like 100 */
1838c2ecf20Sopenharmony_cistatic u8 halt_poll_max_steal = 10;
1848c2ecf20Sopenharmony_cimodule_param(halt_poll_max_steal, byte, 0644);
1858c2ecf20Sopenharmony_ciMODULE_PARM_DESC(halt_poll_max_steal, "Maximum percentage of steal time to allow polling");
1868c2ecf20Sopenharmony_ci
1878c2ecf20Sopenharmony_ci/* if set to true, the GISA will be initialized and used if available */
1888c2ecf20Sopenharmony_cistatic bool use_gisa  = true;
1898c2ecf20Sopenharmony_cimodule_param(use_gisa, bool, 0644);
1908c2ecf20Sopenharmony_ciMODULE_PARM_DESC(use_gisa, "Use the GISA if the host supports it.");
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_ci/*
1938c2ecf20Sopenharmony_ci * For now we handle at most 16 double words as this is what the s390 base
1948c2ecf20Sopenharmony_ci * kernel handles and stores in the prefix page. If we ever need to go beyond
1958c2ecf20Sopenharmony_ci * this, this requires changes to code, but the external uapi can stay.
1968c2ecf20Sopenharmony_ci */
1978c2ecf20Sopenharmony_ci#define SIZE_INTERNAL 16
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_ci/*
2008c2ecf20Sopenharmony_ci * Base feature mask that defines default mask for facilities. Consists of the
2018c2ecf20Sopenharmony_ci * defines in FACILITIES_KVM and the non-hypervisor managed bits.
2028c2ecf20Sopenharmony_ci */
2038c2ecf20Sopenharmony_cistatic unsigned long kvm_s390_fac_base[SIZE_INTERNAL] = { FACILITIES_KVM };
2048c2ecf20Sopenharmony_ci/*
2058c2ecf20Sopenharmony_ci * Extended feature mask. Consists of the defines in FACILITIES_KVM_CPUMODEL
2068c2ecf20Sopenharmony_ci * and defines the facilities that can be enabled via a cpu model.
2078c2ecf20Sopenharmony_ci */
2088c2ecf20Sopenharmony_cistatic unsigned long kvm_s390_fac_ext[SIZE_INTERNAL] = { FACILITIES_KVM_CPUMODEL };
2098c2ecf20Sopenharmony_ci
2108c2ecf20Sopenharmony_cistatic unsigned long kvm_s390_fac_size(void)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_MASK_SIZE_U64);
2138c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SIZE_INTERNAL > S390_ARCH_FAC_LIST_SIZE_U64);
2148c2ecf20Sopenharmony_ci	BUILD_BUG_ON(SIZE_INTERNAL * sizeof(unsigned long) >
2158c2ecf20Sopenharmony_ci		sizeof(S390_lowcore.stfle_fac_list));
2168c2ecf20Sopenharmony_ci
2178c2ecf20Sopenharmony_ci	return SIZE_INTERNAL;
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_ci/* available cpu features supported by kvm */
2218c2ecf20Sopenharmony_cistatic DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
2228c2ecf20Sopenharmony_ci/* available subfunctions indicated via query / "test bit" */
2238c2ecf20Sopenharmony_cistatic struct kvm_s390_vm_cpu_subfunc kvm_s390_available_subfunc;
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic struct gmap_notifier gmap_notifier;
2268c2ecf20Sopenharmony_cistatic struct gmap_notifier vsie_gmap_notifier;
2278c2ecf20Sopenharmony_cidebug_info_t *kvm_s390_dbf;
2288c2ecf20Sopenharmony_cidebug_info_t *kvm_s390_dbf_uv;
2298c2ecf20Sopenharmony_ci
2308c2ecf20Sopenharmony_ci/* Section: not file related */
2318c2ecf20Sopenharmony_ciint kvm_arch_hardware_enable(void)
2328c2ecf20Sopenharmony_ci{
2338c2ecf20Sopenharmony_ci	/* every s390 is virtualization enabled ;-) */
2348c2ecf20Sopenharmony_ci	return 0;
2358c2ecf20Sopenharmony_ci}
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ciint kvm_arch_check_processor_compat(void *opaque)
2388c2ecf20Sopenharmony_ci{
2398c2ecf20Sopenharmony_ci	return 0;
2408c2ecf20Sopenharmony_ci}
2418c2ecf20Sopenharmony_ci
2428c2ecf20Sopenharmony_ci/* forward declarations */
2438c2ecf20Sopenharmony_cistatic void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
2448c2ecf20Sopenharmony_ci			      unsigned long end);
2458c2ecf20Sopenharmony_cistatic int sca_switch_to_extended(struct kvm *kvm);
2468c2ecf20Sopenharmony_ci
2478c2ecf20Sopenharmony_cistatic void kvm_clock_sync_scb(struct kvm_s390_sie_block *scb, u64 delta)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	u8 delta_idx = 0;
2508c2ecf20Sopenharmony_ci
2518c2ecf20Sopenharmony_ci	/*
2528c2ecf20Sopenharmony_ci	 * The TOD jumps by delta, we have to compensate this by adding
2538c2ecf20Sopenharmony_ci	 * -delta to the epoch.
2548c2ecf20Sopenharmony_ci	 */
2558c2ecf20Sopenharmony_ci	delta = -delta;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	/* sign-extension - we're adding to signed values below */
2588c2ecf20Sopenharmony_ci	if ((s64)delta < 0)
2598c2ecf20Sopenharmony_ci		delta_idx = -1;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	scb->epoch += delta;
2628c2ecf20Sopenharmony_ci	if (scb->ecd & ECD_MEF) {
2638c2ecf20Sopenharmony_ci		scb->epdx += delta_idx;
2648c2ecf20Sopenharmony_ci		if (scb->epoch < delta)
2658c2ecf20Sopenharmony_ci			scb->epdx += 1;
2668c2ecf20Sopenharmony_ci	}
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/*
2708c2ecf20Sopenharmony_ci * This callback is executed during stop_machine(). All CPUs are therefore
2718c2ecf20Sopenharmony_ci * temporarily stopped. In order not to change guest behavior, we have to
2728c2ecf20Sopenharmony_ci * disable preemption whenever we touch the epoch of kvm and the VCPUs,
2738c2ecf20Sopenharmony_ci * so a CPU won't be stopped while calculating with the epoch.
2748c2ecf20Sopenharmony_ci */
2758c2ecf20Sopenharmony_cistatic int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
2768c2ecf20Sopenharmony_ci			  void *v)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct kvm *kvm;
2798c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
2808c2ecf20Sopenharmony_ci	int i;
2818c2ecf20Sopenharmony_ci	unsigned long long *delta = v;
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_ci	list_for_each_entry(kvm, &vm_list, vm_list) {
2848c2ecf20Sopenharmony_ci		kvm_for_each_vcpu(i, vcpu, kvm) {
2858c2ecf20Sopenharmony_ci			kvm_clock_sync_scb(vcpu->arch.sie_block, *delta);
2868c2ecf20Sopenharmony_ci			if (i == 0) {
2878c2ecf20Sopenharmony_ci				kvm->arch.epoch = vcpu->arch.sie_block->epoch;
2888c2ecf20Sopenharmony_ci				kvm->arch.epdx = vcpu->arch.sie_block->epdx;
2898c2ecf20Sopenharmony_ci			}
2908c2ecf20Sopenharmony_ci			if (vcpu->arch.cputm_enabled)
2918c2ecf20Sopenharmony_ci				vcpu->arch.cputm_start += *delta;
2928c2ecf20Sopenharmony_ci			if (vcpu->arch.vsie_block)
2938c2ecf20Sopenharmony_ci				kvm_clock_sync_scb(vcpu->arch.vsie_block,
2948c2ecf20Sopenharmony_ci						   *delta);
2958c2ecf20Sopenharmony_ci		}
2968c2ecf20Sopenharmony_ci	}
2978c2ecf20Sopenharmony_ci	return NOTIFY_OK;
2988c2ecf20Sopenharmony_ci}
2998c2ecf20Sopenharmony_ci
3008c2ecf20Sopenharmony_cistatic struct notifier_block kvm_clock_notifier = {
3018c2ecf20Sopenharmony_ci	.notifier_call = kvm_clock_sync,
3028c2ecf20Sopenharmony_ci};
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ciint kvm_arch_hardware_setup(void *opaque)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	gmap_notifier.notifier_call = kvm_gmap_notifier;
3078c2ecf20Sopenharmony_ci	gmap_register_pte_notifier(&gmap_notifier);
3088c2ecf20Sopenharmony_ci	vsie_gmap_notifier.notifier_call = kvm_s390_vsie_gmap_notifier;
3098c2ecf20Sopenharmony_ci	gmap_register_pte_notifier(&vsie_gmap_notifier);
3108c2ecf20Sopenharmony_ci	atomic_notifier_chain_register(&s390_epoch_delta_notifier,
3118c2ecf20Sopenharmony_ci				       &kvm_clock_notifier);
3128c2ecf20Sopenharmony_ci	return 0;
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_civoid kvm_arch_hardware_unsetup(void)
3168c2ecf20Sopenharmony_ci{
3178c2ecf20Sopenharmony_ci	gmap_unregister_pte_notifier(&gmap_notifier);
3188c2ecf20Sopenharmony_ci	gmap_unregister_pte_notifier(&vsie_gmap_notifier);
3198c2ecf20Sopenharmony_ci	atomic_notifier_chain_unregister(&s390_epoch_delta_notifier,
3208c2ecf20Sopenharmony_ci					 &kvm_clock_notifier);
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic void allow_cpu_feat(unsigned long nr)
3248c2ecf20Sopenharmony_ci{
3258c2ecf20Sopenharmony_ci	set_bit_inv(nr, kvm_s390_available_cpu_feat);
3268c2ecf20Sopenharmony_ci}
3278c2ecf20Sopenharmony_ci
3288c2ecf20Sopenharmony_cistatic inline int plo_test_bit(unsigned char nr)
3298c2ecf20Sopenharmony_ci{
3308c2ecf20Sopenharmony_ci	unsigned long function = (unsigned long)nr | 0x100;
3318c2ecf20Sopenharmony_ci	int cc;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci	asm volatile(
3348c2ecf20Sopenharmony_ci		"	lgr	0,%[function]\n"
3358c2ecf20Sopenharmony_ci		/* Parameter registers are ignored for "test bit" */
3368c2ecf20Sopenharmony_ci		"	plo	0,0,0,0(0)\n"
3378c2ecf20Sopenharmony_ci		"	ipm	%0\n"
3388c2ecf20Sopenharmony_ci		"	srl	%0,28\n"
3398c2ecf20Sopenharmony_ci		: "=d" (cc)
3408c2ecf20Sopenharmony_ci		: [function] "d" (function)
3418c2ecf20Sopenharmony_ci		: "cc", "0");
3428c2ecf20Sopenharmony_ci	return cc == 0;
3438c2ecf20Sopenharmony_ci}
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic __always_inline void __insn32_query(unsigned int opcode, u8 *query)
3468c2ecf20Sopenharmony_ci{
3478c2ecf20Sopenharmony_ci	asm volatile(
3488c2ecf20Sopenharmony_ci		"	lghi	0,0\n"
3498c2ecf20Sopenharmony_ci		"	lgr	1,%[query]\n"
3508c2ecf20Sopenharmony_ci		/* Parameter registers are ignored */
3518c2ecf20Sopenharmony_ci		"	.insn	rrf,%[opc] << 16,2,4,6,0\n"
3528c2ecf20Sopenharmony_ci		:
3538c2ecf20Sopenharmony_ci		: [query] "d" ((unsigned long)query), [opc] "i" (opcode)
3548c2ecf20Sopenharmony_ci		: "cc", "memory", "0", "1");
3558c2ecf20Sopenharmony_ci}
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci#define INSN_SORTL 0xb938
3588c2ecf20Sopenharmony_ci#define INSN_DFLTCC 0xb939
3598c2ecf20Sopenharmony_ci
3608c2ecf20Sopenharmony_cistatic void kvm_s390_cpu_feat_init(void)
3618c2ecf20Sopenharmony_ci{
3628c2ecf20Sopenharmony_ci	int i;
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	for (i = 0; i < 256; ++i) {
3658c2ecf20Sopenharmony_ci		if (plo_test_bit(i))
3668c2ecf20Sopenharmony_ci			kvm_s390_available_subfunc.plo[i >> 3] |= 0x80 >> (i & 7);
3678c2ecf20Sopenharmony_ci	}
3688c2ecf20Sopenharmony_ci
3698c2ecf20Sopenharmony_ci	if (test_facility(28)) /* TOD-clock steering */
3708c2ecf20Sopenharmony_ci		ptff(kvm_s390_available_subfunc.ptff,
3718c2ecf20Sopenharmony_ci		     sizeof(kvm_s390_available_subfunc.ptff),
3728c2ecf20Sopenharmony_ci		     PTFF_QAF);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	if (test_facility(17)) { /* MSA */
3758c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMAC, (cpacf_mask_t *)
3768c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kmac);
3778c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMC, (cpacf_mask_t *)
3788c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kmc);
3798c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KM, (cpacf_mask_t *)
3808c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.km);
3818c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KIMD, (cpacf_mask_t *)
3828c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kimd);
3838c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KLMD, (cpacf_mask_t *)
3848c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.klmd);
3858c2ecf20Sopenharmony_ci	}
3868c2ecf20Sopenharmony_ci	if (test_facility(76)) /* MSA3 */
3878c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_PCKMO, (cpacf_mask_t *)
3888c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.pckmo);
3898c2ecf20Sopenharmony_ci	if (test_facility(77)) { /* MSA4 */
3908c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMCTR, (cpacf_mask_t *)
3918c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kmctr);
3928c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMF, (cpacf_mask_t *)
3938c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kmf);
3948c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMO, (cpacf_mask_t *)
3958c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kmo);
3968c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_PCC, (cpacf_mask_t *)
3978c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.pcc);
3988c2ecf20Sopenharmony_ci	}
3998c2ecf20Sopenharmony_ci	if (test_facility(57)) /* MSA5 */
4008c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_PRNO, (cpacf_mask_t *)
4018c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.ppno);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci	if (test_facility(146)) /* MSA8 */
4048c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KMA, (cpacf_mask_t *)
4058c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kma);
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	if (test_facility(155)) /* MSA9 */
4088c2ecf20Sopenharmony_ci		__cpacf_query(CPACF_KDSA, (cpacf_mask_t *)
4098c2ecf20Sopenharmony_ci			      kvm_s390_available_subfunc.kdsa);
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_ci	if (test_facility(150)) /* SORTL */
4128c2ecf20Sopenharmony_ci		__insn32_query(INSN_SORTL, kvm_s390_available_subfunc.sortl);
4138c2ecf20Sopenharmony_ci
4148c2ecf20Sopenharmony_ci	if (test_facility(151)) /* DFLTCC */
4158c2ecf20Sopenharmony_ci		__insn32_query(INSN_DFLTCC, kvm_s390_available_subfunc.dfltcc);
4168c2ecf20Sopenharmony_ci
4178c2ecf20Sopenharmony_ci	if (MACHINE_HAS_ESOP)
4188c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP);
4198c2ecf20Sopenharmony_ci	/*
4208c2ecf20Sopenharmony_ci	 * We need SIE support, ESOP (PROT_READ protection for gmap_shadow),
4218c2ecf20Sopenharmony_ci	 * 64bit SCAO (SCA passthrough) and IDTE (for gmap_shadow unshadowing).
4228c2ecf20Sopenharmony_ci	 */
4238c2ecf20Sopenharmony_ci	if (!sclp.has_sief2 || !MACHINE_HAS_ESOP || !sclp.has_64bscao ||
4248c2ecf20Sopenharmony_ci	    !test_facility(3) || !nested)
4258c2ecf20Sopenharmony_ci		return;
4268c2ecf20Sopenharmony_ci	allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIEF2);
4278c2ecf20Sopenharmony_ci	if (sclp.has_64bscao)
4288c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_64BSCAO);
4298c2ecf20Sopenharmony_ci	if (sclp.has_siif)
4308c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIIF);
4318c2ecf20Sopenharmony_ci	if (sclp.has_gpere)
4328c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GPERE);
4338c2ecf20Sopenharmony_ci	if (sclp.has_gsls)
4348c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GSLS);
4358c2ecf20Sopenharmony_ci	if (sclp.has_ib)
4368c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IB);
4378c2ecf20Sopenharmony_ci	if (sclp.has_cei)
4388c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_CEI);
4398c2ecf20Sopenharmony_ci	if (sclp.has_ibs)
4408c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS);
4418c2ecf20Sopenharmony_ci	if (sclp.has_kss)
4428c2ecf20Sopenharmony_ci		allow_cpu_feat(KVM_S390_VM_CPU_FEAT_KSS);
4438c2ecf20Sopenharmony_ci	/*
4448c2ecf20Sopenharmony_ci	 * KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make
4458c2ecf20Sopenharmony_ci	 * all skey handling functions read/set the skey from the PGSTE
4468c2ecf20Sopenharmony_ci	 * instead of the real storage key.
4478c2ecf20Sopenharmony_ci	 *
4488c2ecf20Sopenharmony_ci	 * KVM_S390_VM_CPU_FEAT_CMMA: Wrong shadow of PTE.I bits will make
4498c2ecf20Sopenharmony_ci	 * pages being detected as preserved although they are resident.
4508c2ecf20Sopenharmony_ci	 *
4518c2ecf20Sopenharmony_ci	 * KVM_S390_VM_CPU_FEAT_PFMFI: Wrong shadow of PTE.I bits will
4528c2ecf20Sopenharmony_ci	 * have the same effect as for KVM_S390_VM_CPU_FEAT_SKEY.
4538c2ecf20Sopenharmony_ci	 *
4548c2ecf20Sopenharmony_ci	 * For KVM_S390_VM_CPU_FEAT_SKEY, KVM_S390_VM_CPU_FEAT_CMMA and
4558c2ecf20Sopenharmony_ci	 * KVM_S390_VM_CPU_FEAT_PFMFI, all PTE.I and PGSTE bits have to be
4568c2ecf20Sopenharmony_ci	 * correctly shadowed. We can do that for the PGSTE but not for PTE.I.
4578c2ecf20Sopenharmony_ci	 *
4588c2ecf20Sopenharmony_ci	 * KVM_S390_VM_CPU_FEAT_SIGPIF: Wrong SCB addresses in the SCA. We
4598c2ecf20Sopenharmony_ci	 * cannot easily shadow the SCA because of the ipte lock.
4608c2ecf20Sopenharmony_ci	 */
4618c2ecf20Sopenharmony_ci}
4628c2ecf20Sopenharmony_ci
4638c2ecf20Sopenharmony_ciint kvm_arch_init(void *opaque)
4648c2ecf20Sopenharmony_ci{
4658c2ecf20Sopenharmony_ci	int rc = -ENOMEM;
4668c2ecf20Sopenharmony_ci
4678c2ecf20Sopenharmony_ci	kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long));
4688c2ecf20Sopenharmony_ci	if (!kvm_s390_dbf)
4698c2ecf20Sopenharmony_ci		return -ENOMEM;
4708c2ecf20Sopenharmony_ci
4718c2ecf20Sopenharmony_ci	kvm_s390_dbf_uv = debug_register("kvm-uv", 32, 1, 7 * sizeof(long));
4728c2ecf20Sopenharmony_ci	if (!kvm_s390_dbf_uv)
4738c2ecf20Sopenharmony_ci		goto out;
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view) ||
4768c2ecf20Sopenharmony_ci	    debug_register_view(kvm_s390_dbf_uv, &debug_sprintf_view))
4778c2ecf20Sopenharmony_ci		goto out;
4788c2ecf20Sopenharmony_ci
4798c2ecf20Sopenharmony_ci	kvm_s390_cpu_feat_init();
4808c2ecf20Sopenharmony_ci
4818c2ecf20Sopenharmony_ci	/* Register floating interrupt controller interface. */
4828c2ecf20Sopenharmony_ci	rc = kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC);
4838c2ecf20Sopenharmony_ci	if (rc) {
4848c2ecf20Sopenharmony_ci		pr_err("A FLIC registration call failed with rc=%d\n", rc);
4858c2ecf20Sopenharmony_ci		goto out;
4868c2ecf20Sopenharmony_ci	}
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci	rc = kvm_s390_gib_init(GAL_ISC);
4898c2ecf20Sopenharmony_ci	if (rc)
4908c2ecf20Sopenharmony_ci		goto out;
4918c2ecf20Sopenharmony_ci
4928c2ecf20Sopenharmony_ci	return 0;
4938c2ecf20Sopenharmony_ci
4948c2ecf20Sopenharmony_ciout:
4958c2ecf20Sopenharmony_ci	kvm_arch_exit();
4968c2ecf20Sopenharmony_ci	return rc;
4978c2ecf20Sopenharmony_ci}
4988c2ecf20Sopenharmony_ci
4998c2ecf20Sopenharmony_civoid kvm_arch_exit(void)
5008c2ecf20Sopenharmony_ci{
5018c2ecf20Sopenharmony_ci	kvm_s390_gib_destroy();
5028c2ecf20Sopenharmony_ci	debug_unregister(kvm_s390_dbf);
5038c2ecf20Sopenharmony_ci	debug_unregister(kvm_s390_dbf_uv);
5048c2ecf20Sopenharmony_ci}
5058c2ecf20Sopenharmony_ci
5068c2ecf20Sopenharmony_ci/* Section: device related */
5078c2ecf20Sopenharmony_cilong kvm_arch_dev_ioctl(struct file *filp,
5088c2ecf20Sopenharmony_ci			unsigned int ioctl, unsigned long arg)
5098c2ecf20Sopenharmony_ci{
5108c2ecf20Sopenharmony_ci	if (ioctl == KVM_S390_ENABLE_SIE)
5118c2ecf20Sopenharmony_ci		return s390_enable_sie();
5128c2ecf20Sopenharmony_ci	return -EINVAL;
5138c2ecf20Sopenharmony_ci}
5148c2ecf20Sopenharmony_ci
5158c2ecf20Sopenharmony_ciint kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
5168c2ecf20Sopenharmony_ci{
5178c2ecf20Sopenharmony_ci	int r;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci	switch (ext) {
5208c2ecf20Sopenharmony_ci	case KVM_CAP_S390_PSW:
5218c2ecf20Sopenharmony_ci	case KVM_CAP_S390_GMAP:
5228c2ecf20Sopenharmony_ci	case KVM_CAP_SYNC_MMU:
5238c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL
5248c2ecf20Sopenharmony_ci	case KVM_CAP_S390_UCONTROL:
5258c2ecf20Sopenharmony_ci#endif
5268c2ecf20Sopenharmony_ci	case KVM_CAP_ASYNC_PF:
5278c2ecf20Sopenharmony_ci	case KVM_CAP_SYNC_REGS:
5288c2ecf20Sopenharmony_ci	case KVM_CAP_ONE_REG:
5298c2ecf20Sopenharmony_ci	case KVM_CAP_ENABLE_CAP:
5308c2ecf20Sopenharmony_ci	case KVM_CAP_S390_CSS_SUPPORT:
5318c2ecf20Sopenharmony_ci	case KVM_CAP_IOEVENTFD:
5328c2ecf20Sopenharmony_ci	case KVM_CAP_DEVICE_CTRL:
5338c2ecf20Sopenharmony_ci	case KVM_CAP_S390_IRQCHIP:
5348c2ecf20Sopenharmony_ci	case KVM_CAP_VM_ATTRIBUTES:
5358c2ecf20Sopenharmony_ci	case KVM_CAP_MP_STATE:
5368c2ecf20Sopenharmony_ci	case KVM_CAP_IMMEDIATE_EXIT:
5378c2ecf20Sopenharmony_ci	case KVM_CAP_S390_INJECT_IRQ:
5388c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_SIGP:
5398c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_STSI:
5408c2ecf20Sopenharmony_ci	case KVM_CAP_S390_SKEYS:
5418c2ecf20Sopenharmony_ci	case KVM_CAP_S390_IRQ_STATE:
5428c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_INSTR0:
5438c2ecf20Sopenharmony_ci	case KVM_CAP_S390_CMMA_MIGRATION:
5448c2ecf20Sopenharmony_ci	case KVM_CAP_S390_AIS:
5458c2ecf20Sopenharmony_ci	case KVM_CAP_S390_AIS_MIGRATION:
5468c2ecf20Sopenharmony_ci	case KVM_CAP_S390_VCPU_RESETS:
5478c2ecf20Sopenharmony_ci	case KVM_CAP_SET_GUEST_DEBUG:
5488c2ecf20Sopenharmony_ci	case KVM_CAP_S390_DIAG318:
5498c2ecf20Sopenharmony_ci		r = 1;
5508c2ecf20Sopenharmony_ci		break;
5518c2ecf20Sopenharmony_ci	case KVM_CAP_S390_HPAGE_1M:
5528c2ecf20Sopenharmony_ci		r = 0;
5538c2ecf20Sopenharmony_ci		if (hpage && !kvm_is_ucontrol(kvm))
5548c2ecf20Sopenharmony_ci			r = 1;
5558c2ecf20Sopenharmony_ci		break;
5568c2ecf20Sopenharmony_ci	case KVM_CAP_S390_MEM_OP:
5578c2ecf20Sopenharmony_ci		r = MEM_OP_MAX_SIZE;
5588c2ecf20Sopenharmony_ci		break;
5598c2ecf20Sopenharmony_ci	case KVM_CAP_NR_VCPUS:
5608c2ecf20Sopenharmony_ci	case KVM_CAP_MAX_VCPUS:
5618c2ecf20Sopenharmony_ci	case KVM_CAP_MAX_VCPU_ID:
5628c2ecf20Sopenharmony_ci		r = KVM_S390_BSCA_CPU_SLOTS;
5638c2ecf20Sopenharmony_ci		if (!kvm_s390_use_sca_entries())
5648c2ecf20Sopenharmony_ci			r = KVM_MAX_VCPUS;
5658c2ecf20Sopenharmony_ci		else if (sclp.has_esca && sclp.has_64bscao)
5668c2ecf20Sopenharmony_ci			r = KVM_S390_ESCA_CPU_SLOTS;
5678c2ecf20Sopenharmony_ci		break;
5688c2ecf20Sopenharmony_ci	case KVM_CAP_S390_COW:
5698c2ecf20Sopenharmony_ci		r = MACHINE_HAS_ESOP;
5708c2ecf20Sopenharmony_ci		break;
5718c2ecf20Sopenharmony_ci	case KVM_CAP_S390_VECTOR_REGISTERS:
5728c2ecf20Sopenharmony_ci		r = MACHINE_HAS_VX;
5738c2ecf20Sopenharmony_ci		break;
5748c2ecf20Sopenharmony_ci	case KVM_CAP_S390_RI:
5758c2ecf20Sopenharmony_ci		r = test_facility(64);
5768c2ecf20Sopenharmony_ci		break;
5778c2ecf20Sopenharmony_ci	case KVM_CAP_S390_GS:
5788c2ecf20Sopenharmony_ci		r = test_facility(133);
5798c2ecf20Sopenharmony_ci		break;
5808c2ecf20Sopenharmony_ci	case KVM_CAP_S390_BPB:
5818c2ecf20Sopenharmony_ci		r = test_facility(82);
5828c2ecf20Sopenharmony_ci		break;
5838c2ecf20Sopenharmony_ci	case KVM_CAP_S390_PROTECTED:
5848c2ecf20Sopenharmony_ci		r = is_prot_virt_host();
5858c2ecf20Sopenharmony_ci		break;
5868c2ecf20Sopenharmony_ci	default:
5878c2ecf20Sopenharmony_ci		r = 0;
5888c2ecf20Sopenharmony_ci	}
5898c2ecf20Sopenharmony_ci	return r;
5908c2ecf20Sopenharmony_ci}
5918c2ecf20Sopenharmony_ci
5928c2ecf20Sopenharmony_civoid kvm_arch_sync_dirty_log(struct kvm *kvm, struct kvm_memory_slot *memslot)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	int i;
5958c2ecf20Sopenharmony_ci	gfn_t cur_gfn, last_gfn;
5968c2ecf20Sopenharmony_ci	unsigned long gaddr, vmaddr;
5978c2ecf20Sopenharmony_ci	struct gmap *gmap = kvm->arch.gmap;
5988c2ecf20Sopenharmony_ci	DECLARE_BITMAP(bitmap, _PAGE_ENTRIES);
5998c2ecf20Sopenharmony_ci
6008c2ecf20Sopenharmony_ci	/* Loop over all guest segments */
6018c2ecf20Sopenharmony_ci	cur_gfn = memslot->base_gfn;
6028c2ecf20Sopenharmony_ci	last_gfn = memslot->base_gfn + memslot->npages;
6038c2ecf20Sopenharmony_ci	for (; cur_gfn <= last_gfn; cur_gfn += _PAGE_ENTRIES) {
6048c2ecf20Sopenharmony_ci		gaddr = gfn_to_gpa(cur_gfn);
6058c2ecf20Sopenharmony_ci		vmaddr = gfn_to_hva_memslot(memslot, cur_gfn);
6068c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(vmaddr))
6078c2ecf20Sopenharmony_ci			continue;
6088c2ecf20Sopenharmony_ci
6098c2ecf20Sopenharmony_ci		bitmap_zero(bitmap, _PAGE_ENTRIES);
6108c2ecf20Sopenharmony_ci		gmap_sync_dirty_log_pmd(gmap, bitmap, gaddr, vmaddr);
6118c2ecf20Sopenharmony_ci		for (i = 0; i < _PAGE_ENTRIES; i++) {
6128c2ecf20Sopenharmony_ci			if (test_bit(i, bitmap))
6138c2ecf20Sopenharmony_ci				mark_page_dirty(kvm, cur_gfn + i);
6148c2ecf20Sopenharmony_ci		}
6158c2ecf20Sopenharmony_ci
6168c2ecf20Sopenharmony_ci		if (fatal_signal_pending(current))
6178c2ecf20Sopenharmony_ci			return;
6188c2ecf20Sopenharmony_ci		cond_resched();
6198c2ecf20Sopenharmony_ci	}
6208c2ecf20Sopenharmony_ci}
6218c2ecf20Sopenharmony_ci
6228c2ecf20Sopenharmony_ci/* Section: vm related */
6238c2ecf20Sopenharmony_cistatic void sca_del_vcpu(struct kvm_vcpu *vcpu);
6248c2ecf20Sopenharmony_ci
6258c2ecf20Sopenharmony_ci/*
6268c2ecf20Sopenharmony_ci * Get (and clear) the dirty memory log for a memory slot.
6278c2ecf20Sopenharmony_ci */
6288c2ecf20Sopenharmony_ciint kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
6298c2ecf20Sopenharmony_ci			       struct kvm_dirty_log *log)
6308c2ecf20Sopenharmony_ci{
6318c2ecf20Sopenharmony_ci	int r;
6328c2ecf20Sopenharmony_ci	unsigned long n;
6338c2ecf20Sopenharmony_ci	struct kvm_memory_slot *memslot;
6348c2ecf20Sopenharmony_ci	int is_dirty;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	if (kvm_is_ucontrol(kvm))
6378c2ecf20Sopenharmony_ci		return -EINVAL;
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_ci	mutex_lock(&kvm->slots_lock);
6408c2ecf20Sopenharmony_ci
6418c2ecf20Sopenharmony_ci	r = -EINVAL;
6428c2ecf20Sopenharmony_ci	if (log->slot >= KVM_USER_MEM_SLOTS)
6438c2ecf20Sopenharmony_ci		goto out;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	r = kvm_get_dirty_log(kvm, log, &is_dirty, &memslot);
6468c2ecf20Sopenharmony_ci	if (r)
6478c2ecf20Sopenharmony_ci		goto out;
6488c2ecf20Sopenharmony_ci
6498c2ecf20Sopenharmony_ci	/* Clear the dirty log */
6508c2ecf20Sopenharmony_ci	if (is_dirty) {
6518c2ecf20Sopenharmony_ci		n = kvm_dirty_bitmap_bytes(memslot);
6528c2ecf20Sopenharmony_ci		memset(memslot->dirty_bitmap, 0, n);
6538c2ecf20Sopenharmony_ci	}
6548c2ecf20Sopenharmony_ci	r = 0;
6558c2ecf20Sopenharmony_ciout:
6568c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->slots_lock);
6578c2ecf20Sopenharmony_ci	return r;
6588c2ecf20Sopenharmony_ci}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_cistatic void icpt_operexc_on_all_vcpus(struct kvm *kvm)
6618c2ecf20Sopenharmony_ci{
6628c2ecf20Sopenharmony_ci	unsigned int i;
6638c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
6648c2ecf20Sopenharmony_ci
6658c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
6668c2ecf20Sopenharmony_ci		kvm_s390_sync_request(KVM_REQ_ICPT_OPEREXC, vcpu);
6678c2ecf20Sopenharmony_ci	}
6688c2ecf20Sopenharmony_ci}
6698c2ecf20Sopenharmony_ci
6708c2ecf20Sopenharmony_ciint kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
6718c2ecf20Sopenharmony_ci{
6728c2ecf20Sopenharmony_ci	int r;
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (cap->flags)
6758c2ecf20Sopenharmony_ci		return -EINVAL;
6768c2ecf20Sopenharmony_ci
6778c2ecf20Sopenharmony_ci	switch (cap->cap) {
6788c2ecf20Sopenharmony_ci	case KVM_CAP_S390_IRQCHIP:
6798c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_IRQCHIP");
6808c2ecf20Sopenharmony_ci		kvm->arch.use_irqchip = 1;
6818c2ecf20Sopenharmony_ci		r = 0;
6828c2ecf20Sopenharmony_ci		break;
6838c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_SIGP:
6848c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_SIGP");
6858c2ecf20Sopenharmony_ci		kvm->arch.user_sigp = 1;
6868c2ecf20Sopenharmony_ci		r = 0;
6878c2ecf20Sopenharmony_ci		break;
6888c2ecf20Sopenharmony_ci	case KVM_CAP_S390_VECTOR_REGISTERS:
6898c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
6908c2ecf20Sopenharmony_ci		if (kvm->created_vcpus) {
6918c2ecf20Sopenharmony_ci			r = -EBUSY;
6928c2ecf20Sopenharmony_ci		} else if (MACHINE_HAS_VX) {
6938c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_mask, 129);
6948c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_list, 129);
6958c2ecf20Sopenharmony_ci			if (test_facility(134)) {
6968c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_mask, 134);
6978c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_list, 134);
6988c2ecf20Sopenharmony_ci			}
6998c2ecf20Sopenharmony_ci			if (test_facility(135)) {
7008c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_mask, 135);
7018c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_list, 135);
7028c2ecf20Sopenharmony_ci			}
7038c2ecf20Sopenharmony_ci			if (test_facility(148)) {
7048c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_mask, 148);
7058c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_list, 148);
7068c2ecf20Sopenharmony_ci			}
7078c2ecf20Sopenharmony_ci			if (test_facility(152)) {
7088c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_mask, 152);
7098c2ecf20Sopenharmony_ci				set_kvm_facility(kvm->arch.model.fac_list, 152);
7108c2ecf20Sopenharmony_ci			}
7118c2ecf20Sopenharmony_ci			r = 0;
7128c2ecf20Sopenharmony_ci		} else
7138c2ecf20Sopenharmony_ci			r = -EINVAL;
7148c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
7158c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
7168c2ecf20Sopenharmony_ci			 r ? "(not available)" : "(success)");
7178c2ecf20Sopenharmony_ci		break;
7188c2ecf20Sopenharmony_ci	case KVM_CAP_S390_RI:
7198c2ecf20Sopenharmony_ci		r = -EINVAL;
7208c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
7218c2ecf20Sopenharmony_ci		if (kvm->created_vcpus) {
7228c2ecf20Sopenharmony_ci			r = -EBUSY;
7238c2ecf20Sopenharmony_ci		} else if (test_facility(64)) {
7248c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_mask, 64);
7258c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_list, 64);
7268c2ecf20Sopenharmony_ci			r = 0;
7278c2ecf20Sopenharmony_ci		}
7288c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
7298c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "ENABLE: CAP_S390_RI %s",
7308c2ecf20Sopenharmony_ci			 r ? "(not available)" : "(success)");
7318c2ecf20Sopenharmony_ci		break;
7328c2ecf20Sopenharmony_ci	case KVM_CAP_S390_AIS:
7338c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
7348c2ecf20Sopenharmony_ci		if (kvm->created_vcpus) {
7358c2ecf20Sopenharmony_ci			r = -EBUSY;
7368c2ecf20Sopenharmony_ci		} else {
7378c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_mask, 72);
7388c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_list, 72);
7398c2ecf20Sopenharmony_ci			r = 0;
7408c2ecf20Sopenharmony_ci		}
7418c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
7428c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "ENABLE: AIS %s",
7438c2ecf20Sopenharmony_ci			 r ? "(not available)" : "(success)");
7448c2ecf20Sopenharmony_ci		break;
7458c2ecf20Sopenharmony_ci	case KVM_CAP_S390_GS:
7468c2ecf20Sopenharmony_ci		r = -EINVAL;
7478c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
7488c2ecf20Sopenharmony_ci		if (kvm->created_vcpus) {
7498c2ecf20Sopenharmony_ci			r = -EBUSY;
7508c2ecf20Sopenharmony_ci		} else if (test_facility(133)) {
7518c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_mask, 133);
7528c2ecf20Sopenharmony_ci			set_kvm_facility(kvm->arch.model.fac_list, 133);
7538c2ecf20Sopenharmony_ci			r = 0;
7548c2ecf20Sopenharmony_ci		}
7558c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
7568c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "ENABLE: CAP_S390_GS %s",
7578c2ecf20Sopenharmony_ci			 r ? "(not available)" : "(success)");
7588c2ecf20Sopenharmony_ci		break;
7598c2ecf20Sopenharmony_ci	case KVM_CAP_S390_HPAGE_1M:
7608c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
7618c2ecf20Sopenharmony_ci		if (kvm->created_vcpus)
7628c2ecf20Sopenharmony_ci			r = -EBUSY;
7638c2ecf20Sopenharmony_ci		else if (!hpage || kvm->arch.use_cmma || kvm_is_ucontrol(kvm))
7648c2ecf20Sopenharmony_ci			r = -EINVAL;
7658c2ecf20Sopenharmony_ci		else {
7668c2ecf20Sopenharmony_ci			r = 0;
7678c2ecf20Sopenharmony_ci			mmap_write_lock(kvm->mm);
7688c2ecf20Sopenharmony_ci			kvm->mm->context.allow_gmap_hpage_1m = 1;
7698c2ecf20Sopenharmony_ci			mmap_write_unlock(kvm->mm);
7708c2ecf20Sopenharmony_ci			/*
7718c2ecf20Sopenharmony_ci			 * We might have to create fake 4k page
7728c2ecf20Sopenharmony_ci			 * tables. To avoid that the hardware works on
7738c2ecf20Sopenharmony_ci			 * stale PGSTEs, we emulate these instructions.
7748c2ecf20Sopenharmony_ci			 */
7758c2ecf20Sopenharmony_ci			kvm->arch.use_skf = 0;
7768c2ecf20Sopenharmony_ci			kvm->arch.use_pfmfi = 0;
7778c2ecf20Sopenharmony_ci		}
7788c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
7798c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "ENABLE: CAP_S390_HPAGE %s",
7808c2ecf20Sopenharmony_ci			 r ? "(not available)" : "(success)");
7818c2ecf20Sopenharmony_ci		break;
7828c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_STSI:
7838c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_STSI");
7848c2ecf20Sopenharmony_ci		kvm->arch.user_stsi = 1;
7858c2ecf20Sopenharmony_ci		r = 0;
7868c2ecf20Sopenharmony_ci		break;
7878c2ecf20Sopenharmony_ci	case KVM_CAP_S390_USER_INSTR0:
7888c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_INSTR0");
7898c2ecf20Sopenharmony_ci		kvm->arch.user_instr0 = 1;
7908c2ecf20Sopenharmony_ci		icpt_operexc_on_all_vcpus(kvm);
7918c2ecf20Sopenharmony_ci		r = 0;
7928c2ecf20Sopenharmony_ci		break;
7938c2ecf20Sopenharmony_ci	default:
7948c2ecf20Sopenharmony_ci		r = -EINVAL;
7958c2ecf20Sopenharmony_ci		break;
7968c2ecf20Sopenharmony_ci	}
7978c2ecf20Sopenharmony_ci	return r;
7988c2ecf20Sopenharmony_ci}
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_cistatic int kvm_s390_get_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
8018c2ecf20Sopenharmony_ci{
8028c2ecf20Sopenharmony_ci	int ret;
8038c2ecf20Sopenharmony_ci
8048c2ecf20Sopenharmony_ci	switch (attr->attr) {
8058c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_LIMIT_SIZE:
8068c2ecf20Sopenharmony_ci		ret = 0;
8078c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "QUERY: max guest memory: %lu bytes",
8088c2ecf20Sopenharmony_ci			 kvm->arch.mem_limit);
8098c2ecf20Sopenharmony_ci		if (put_user(kvm->arch.mem_limit, (u64 __user *)attr->addr))
8108c2ecf20Sopenharmony_ci			ret = -EFAULT;
8118c2ecf20Sopenharmony_ci		break;
8128c2ecf20Sopenharmony_ci	default:
8138c2ecf20Sopenharmony_ci		ret = -ENXIO;
8148c2ecf20Sopenharmony_ci		break;
8158c2ecf20Sopenharmony_ci	}
8168c2ecf20Sopenharmony_ci	return ret;
8178c2ecf20Sopenharmony_ci}
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_cistatic int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
8208c2ecf20Sopenharmony_ci{
8218c2ecf20Sopenharmony_ci	int ret;
8228c2ecf20Sopenharmony_ci	unsigned int idx;
8238c2ecf20Sopenharmony_ci	switch (attr->attr) {
8248c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_ENABLE_CMMA:
8258c2ecf20Sopenharmony_ci		ret = -ENXIO;
8268c2ecf20Sopenharmony_ci		if (!sclp.has_cmma)
8278c2ecf20Sopenharmony_ci			break;
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: CMMA support");
8308c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
8318c2ecf20Sopenharmony_ci		if (kvm->created_vcpus)
8328c2ecf20Sopenharmony_ci			ret = -EBUSY;
8338c2ecf20Sopenharmony_ci		else if (kvm->mm->context.allow_gmap_hpage_1m)
8348c2ecf20Sopenharmony_ci			ret = -EINVAL;
8358c2ecf20Sopenharmony_ci		else {
8368c2ecf20Sopenharmony_ci			kvm->arch.use_cmma = 1;
8378c2ecf20Sopenharmony_ci			/* Not compatible with cmma. */
8388c2ecf20Sopenharmony_ci			kvm->arch.use_pfmfi = 0;
8398c2ecf20Sopenharmony_ci			ret = 0;
8408c2ecf20Sopenharmony_ci		}
8418c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
8428c2ecf20Sopenharmony_ci		break;
8438c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_CLR_CMMA:
8448c2ecf20Sopenharmony_ci		ret = -ENXIO;
8458c2ecf20Sopenharmony_ci		if (!sclp.has_cmma)
8468c2ecf20Sopenharmony_ci			break;
8478c2ecf20Sopenharmony_ci		ret = -EINVAL;
8488c2ecf20Sopenharmony_ci		if (!kvm->arch.use_cmma)
8498c2ecf20Sopenharmony_ci			break;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
8528c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
8538c2ecf20Sopenharmony_ci		idx = srcu_read_lock(&kvm->srcu);
8548c2ecf20Sopenharmony_ci		s390_reset_cmma(kvm->arch.gmap->mm);
8558c2ecf20Sopenharmony_ci		srcu_read_unlock(&kvm->srcu, idx);
8568c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
8578c2ecf20Sopenharmony_ci		ret = 0;
8588c2ecf20Sopenharmony_ci		break;
8598c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_LIMIT_SIZE: {
8608c2ecf20Sopenharmony_ci		unsigned long new_limit;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci		if (kvm_is_ucontrol(kvm))
8638c2ecf20Sopenharmony_ci			return -EINVAL;
8648c2ecf20Sopenharmony_ci
8658c2ecf20Sopenharmony_ci		if (get_user(new_limit, (u64 __user *)attr->addr))
8668c2ecf20Sopenharmony_ci			return -EFAULT;
8678c2ecf20Sopenharmony_ci
8688c2ecf20Sopenharmony_ci		if (kvm->arch.mem_limit != KVM_S390_NO_MEM_LIMIT &&
8698c2ecf20Sopenharmony_ci		    new_limit > kvm->arch.mem_limit)
8708c2ecf20Sopenharmony_ci			return -E2BIG;
8718c2ecf20Sopenharmony_ci
8728c2ecf20Sopenharmony_ci		if (!new_limit)
8738c2ecf20Sopenharmony_ci			return -EINVAL;
8748c2ecf20Sopenharmony_ci
8758c2ecf20Sopenharmony_ci		/* gmap_create takes last usable address */
8768c2ecf20Sopenharmony_ci		if (new_limit != KVM_S390_NO_MEM_LIMIT)
8778c2ecf20Sopenharmony_ci			new_limit -= 1;
8788c2ecf20Sopenharmony_ci
8798c2ecf20Sopenharmony_ci		ret = -EBUSY;
8808c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
8818c2ecf20Sopenharmony_ci		if (!kvm->created_vcpus) {
8828c2ecf20Sopenharmony_ci			/* gmap_create will round the limit up */
8838c2ecf20Sopenharmony_ci			struct gmap *new = gmap_create(current->mm, new_limit);
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci			if (!new) {
8868c2ecf20Sopenharmony_ci				ret = -ENOMEM;
8878c2ecf20Sopenharmony_ci			} else {
8888c2ecf20Sopenharmony_ci				gmap_remove(kvm->arch.gmap);
8898c2ecf20Sopenharmony_ci				new->private = kvm;
8908c2ecf20Sopenharmony_ci				kvm->arch.gmap = new;
8918c2ecf20Sopenharmony_ci				ret = 0;
8928c2ecf20Sopenharmony_ci			}
8938c2ecf20Sopenharmony_ci		}
8948c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
8958c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit);
8968c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "New guest asce: 0x%pK",
8978c2ecf20Sopenharmony_ci			 (void *) kvm->arch.gmap->asce);
8988c2ecf20Sopenharmony_ci		break;
8998c2ecf20Sopenharmony_ci	}
9008c2ecf20Sopenharmony_ci	default:
9018c2ecf20Sopenharmony_ci		ret = -ENXIO;
9028c2ecf20Sopenharmony_ci		break;
9038c2ecf20Sopenharmony_ci	}
9048c2ecf20Sopenharmony_ci	return ret;
9058c2ecf20Sopenharmony_ci}
9068c2ecf20Sopenharmony_ci
9078c2ecf20Sopenharmony_cistatic void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu);
9088c2ecf20Sopenharmony_ci
9098c2ecf20Sopenharmony_civoid kvm_s390_vcpu_crypto_reset_all(struct kvm *kvm)
9108c2ecf20Sopenharmony_ci{
9118c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
9128c2ecf20Sopenharmony_ci	int i;
9138c2ecf20Sopenharmony_ci
9148c2ecf20Sopenharmony_ci	kvm_s390_vcpu_block_all(kvm);
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
9178c2ecf20Sopenharmony_ci		kvm_s390_vcpu_crypto_setup(vcpu);
9188c2ecf20Sopenharmony_ci		/* recreate the shadow crycb by leaving the VSIE handler */
9198c2ecf20Sopenharmony_ci		kvm_s390_sync_request(KVM_REQ_VSIE_RESTART, vcpu);
9208c2ecf20Sopenharmony_ci	}
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	kvm_s390_vcpu_unblock_all(kvm);
9238c2ecf20Sopenharmony_ci}
9248c2ecf20Sopenharmony_ci
9258c2ecf20Sopenharmony_cistatic int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
9268c2ecf20Sopenharmony_ci{
9278c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
9288c2ecf20Sopenharmony_ci	switch (attr->attr) {
9298c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
9308c2ecf20Sopenharmony_ci		if (!test_kvm_facility(kvm, 76)) {
9318c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9328c2ecf20Sopenharmony_ci			return -EINVAL;
9338c2ecf20Sopenharmony_ci		}
9348c2ecf20Sopenharmony_ci		get_random_bytes(
9358c2ecf20Sopenharmony_ci			kvm->arch.crypto.crycb->aes_wrapping_key_mask,
9368c2ecf20Sopenharmony_ci			sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
9378c2ecf20Sopenharmony_ci		kvm->arch.crypto.aes_kw = 1;
9388c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support");
9398c2ecf20Sopenharmony_ci		break;
9408c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
9418c2ecf20Sopenharmony_ci		if (!test_kvm_facility(kvm, 76)) {
9428c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9438c2ecf20Sopenharmony_ci			return -EINVAL;
9448c2ecf20Sopenharmony_ci		}
9458c2ecf20Sopenharmony_ci		get_random_bytes(
9468c2ecf20Sopenharmony_ci			kvm->arch.crypto.crycb->dea_wrapping_key_mask,
9478c2ecf20Sopenharmony_ci			sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
9488c2ecf20Sopenharmony_ci		kvm->arch.crypto.dea_kw = 1;
9498c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support");
9508c2ecf20Sopenharmony_ci		break;
9518c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
9528c2ecf20Sopenharmony_ci		if (!test_kvm_facility(kvm, 76)) {
9538c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9548c2ecf20Sopenharmony_ci			return -EINVAL;
9558c2ecf20Sopenharmony_ci		}
9568c2ecf20Sopenharmony_ci		kvm->arch.crypto.aes_kw = 0;
9578c2ecf20Sopenharmony_ci		memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0,
9588c2ecf20Sopenharmony_ci			sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
9598c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support");
9608c2ecf20Sopenharmony_ci		break;
9618c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
9628c2ecf20Sopenharmony_ci		if (!test_kvm_facility(kvm, 76)) {
9638c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9648c2ecf20Sopenharmony_ci			return -EINVAL;
9658c2ecf20Sopenharmony_ci		}
9668c2ecf20Sopenharmony_ci		kvm->arch.crypto.dea_kw = 0;
9678c2ecf20Sopenharmony_ci		memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0,
9688c2ecf20Sopenharmony_ci			sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
9698c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support");
9708c2ecf20Sopenharmony_ci		break;
9718c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_ENABLE_APIE:
9728c2ecf20Sopenharmony_ci		if (!ap_instructions_available()) {
9738c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9748c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
9758c2ecf20Sopenharmony_ci		}
9768c2ecf20Sopenharmony_ci		kvm->arch.crypto.apie = 1;
9778c2ecf20Sopenharmony_ci		break;
9788c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO_DISABLE_APIE:
9798c2ecf20Sopenharmony_ci		if (!ap_instructions_available()) {
9808c2ecf20Sopenharmony_ci			mutex_unlock(&kvm->lock);
9818c2ecf20Sopenharmony_ci			return -EOPNOTSUPP;
9828c2ecf20Sopenharmony_ci		}
9838c2ecf20Sopenharmony_ci		kvm->arch.crypto.apie = 0;
9848c2ecf20Sopenharmony_ci		break;
9858c2ecf20Sopenharmony_ci	default:
9868c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
9878c2ecf20Sopenharmony_ci		return -ENXIO;
9888c2ecf20Sopenharmony_ci	}
9898c2ecf20Sopenharmony_ci
9908c2ecf20Sopenharmony_ci	kvm_s390_vcpu_crypto_reset_all(kvm);
9918c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
9928c2ecf20Sopenharmony_ci	return 0;
9938c2ecf20Sopenharmony_ci}
9948c2ecf20Sopenharmony_ci
9958c2ecf20Sopenharmony_cistatic void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
9968c2ecf20Sopenharmony_ci{
9978c2ecf20Sopenharmony_ci	int cx;
9988c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
9998c2ecf20Sopenharmony_ci
10008c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(cx, vcpu, kvm)
10018c2ecf20Sopenharmony_ci		kvm_s390_sync_request(req, vcpu);
10028c2ecf20Sopenharmony_ci}
10038c2ecf20Sopenharmony_ci
10048c2ecf20Sopenharmony_ci/*
10058c2ecf20Sopenharmony_ci * Must be called with kvm->srcu held to avoid races on memslots, and with
10068c2ecf20Sopenharmony_ci * kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
10078c2ecf20Sopenharmony_ci */
10088c2ecf20Sopenharmony_cistatic int kvm_s390_vm_start_migration(struct kvm *kvm)
10098c2ecf20Sopenharmony_ci{
10108c2ecf20Sopenharmony_ci	struct kvm_memory_slot *ms;
10118c2ecf20Sopenharmony_ci	struct kvm_memslots *slots;
10128c2ecf20Sopenharmony_ci	unsigned long ram_pages = 0;
10138c2ecf20Sopenharmony_ci	int slotnr;
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_ci	/* migration mode already enabled */
10168c2ecf20Sopenharmony_ci	if (kvm->arch.migration_mode)
10178c2ecf20Sopenharmony_ci		return 0;
10188c2ecf20Sopenharmony_ci	slots = kvm_memslots(kvm);
10198c2ecf20Sopenharmony_ci	if (!slots || !slots->used_slots)
10208c2ecf20Sopenharmony_ci		return -EINVAL;
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_ci	if (!kvm->arch.use_cmma) {
10238c2ecf20Sopenharmony_ci		kvm->arch.migration_mode = 1;
10248c2ecf20Sopenharmony_ci		return 0;
10258c2ecf20Sopenharmony_ci	}
10268c2ecf20Sopenharmony_ci	/* mark all the pages in active slots as dirty */
10278c2ecf20Sopenharmony_ci	for (slotnr = 0; slotnr < slots->used_slots; slotnr++) {
10288c2ecf20Sopenharmony_ci		ms = slots->memslots + slotnr;
10298c2ecf20Sopenharmony_ci		if (!ms->dirty_bitmap)
10308c2ecf20Sopenharmony_ci			return -EINVAL;
10318c2ecf20Sopenharmony_ci		/*
10328c2ecf20Sopenharmony_ci		 * The second half of the bitmap is only used on x86,
10338c2ecf20Sopenharmony_ci		 * and would be wasted otherwise, so we put it to good
10348c2ecf20Sopenharmony_ci		 * use here to keep track of the state of the storage
10358c2ecf20Sopenharmony_ci		 * attributes.
10368c2ecf20Sopenharmony_ci		 */
10378c2ecf20Sopenharmony_ci		memset(kvm_second_dirty_bitmap(ms), 0xff, kvm_dirty_bitmap_bytes(ms));
10388c2ecf20Sopenharmony_ci		ram_pages += ms->npages;
10398c2ecf20Sopenharmony_ci	}
10408c2ecf20Sopenharmony_ci	atomic64_set(&kvm->arch.cmma_dirty_pages, ram_pages);
10418c2ecf20Sopenharmony_ci	kvm->arch.migration_mode = 1;
10428c2ecf20Sopenharmony_ci	kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION);
10438c2ecf20Sopenharmony_ci	return 0;
10448c2ecf20Sopenharmony_ci}
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci/*
10478c2ecf20Sopenharmony_ci * Must be called with kvm->slots_lock to avoid races with ourselves and
10488c2ecf20Sopenharmony_ci * kvm_s390_vm_start_migration.
10498c2ecf20Sopenharmony_ci */
10508c2ecf20Sopenharmony_cistatic int kvm_s390_vm_stop_migration(struct kvm *kvm)
10518c2ecf20Sopenharmony_ci{
10528c2ecf20Sopenharmony_ci	/* migration mode already disabled */
10538c2ecf20Sopenharmony_ci	if (!kvm->arch.migration_mode)
10548c2ecf20Sopenharmony_ci		return 0;
10558c2ecf20Sopenharmony_ci	kvm->arch.migration_mode = 0;
10568c2ecf20Sopenharmony_ci	if (kvm->arch.use_cmma)
10578c2ecf20Sopenharmony_ci		kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
10588c2ecf20Sopenharmony_ci	return 0;
10598c2ecf20Sopenharmony_ci}
10608c2ecf20Sopenharmony_ci
10618c2ecf20Sopenharmony_cistatic int kvm_s390_vm_set_migration(struct kvm *kvm,
10628c2ecf20Sopenharmony_ci				     struct kvm_device_attr *attr)
10638c2ecf20Sopenharmony_ci{
10648c2ecf20Sopenharmony_ci	int res = -ENXIO;
10658c2ecf20Sopenharmony_ci
10668c2ecf20Sopenharmony_ci	mutex_lock(&kvm->slots_lock);
10678c2ecf20Sopenharmony_ci	switch (attr->attr) {
10688c2ecf20Sopenharmony_ci	case KVM_S390_VM_MIGRATION_START:
10698c2ecf20Sopenharmony_ci		res = kvm_s390_vm_start_migration(kvm);
10708c2ecf20Sopenharmony_ci		break;
10718c2ecf20Sopenharmony_ci	case KVM_S390_VM_MIGRATION_STOP:
10728c2ecf20Sopenharmony_ci		res = kvm_s390_vm_stop_migration(kvm);
10738c2ecf20Sopenharmony_ci		break;
10748c2ecf20Sopenharmony_ci	default:
10758c2ecf20Sopenharmony_ci		break;
10768c2ecf20Sopenharmony_ci	}
10778c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->slots_lock);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_ci	return res;
10808c2ecf20Sopenharmony_ci}
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_cistatic int kvm_s390_vm_get_migration(struct kvm *kvm,
10838c2ecf20Sopenharmony_ci				     struct kvm_device_attr *attr)
10848c2ecf20Sopenharmony_ci{
10858c2ecf20Sopenharmony_ci	u64 mig = kvm->arch.migration_mode;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	if (attr->attr != KVM_S390_VM_MIGRATION_STATUS)
10888c2ecf20Sopenharmony_ci		return -ENXIO;
10898c2ecf20Sopenharmony_ci
10908c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &mig, sizeof(mig)))
10918c2ecf20Sopenharmony_ci		return -EFAULT;
10928c2ecf20Sopenharmony_ci	return 0;
10938c2ecf20Sopenharmony_ci}
10948c2ecf20Sopenharmony_ci
10958c2ecf20Sopenharmony_cistatic void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod);
10968c2ecf20Sopenharmony_ci
10978c2ecf20Sopenharmony_cistatic int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	struct kvm_s390_vm_tod_clock gtod;
11008c2ecf20Sopenharmony_ci
11018c2ecf20Sopenharmony_ci	if (copy_from_user(&gtod, (void __user *)attr->addr, sizeof(gtod)))
11028c2ecf20Sopenharmony_ci		return -EFAULT;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	if (!test_kvm_facility(kvm, 139) && gtod.epoch_idx)
11058c2ecf20Sopenharmony_ci		return -EINVAL;
11068c2ecf20Sopenharmony_ci	__kvm_s390_set_tod_clock(kvm, &gtod);
11078c2ecf20Sopenharmony_ci
11088c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
11098c2ecf20Sopenharmony_ci		gtod.epoch_idx, gtod.tod);
11108c2ecf20Sopenharmony_ci
11118c2ecf20Sopenharmony_ci	return 0;
11128c2ecf20Sopenharmony_ci}
11138c2ecf20Sopenharmony_ci
11148c2ecf20Sopenharmony_cistatic int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
11158c2ecf20Sopenharmony_ci{
11168c2ecf20Sopenharmony_ci	u8 gtod_high;
11178c2ecf20Sopenharmony_ci
11188c2ecf20Sopenharmony_ci	if (copy_from_user(&gtod_high, (void __user *)attr->addr,
11198c2ecf20Sopenharmony_ci					   sizeof(gtod_high)))
11208c2ecf20Sopenharmony_ci		return -EFAULT;
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci	if (gtod_high != 0)
11238c2ecf20Sopenharmony_ci		return -EINVAL;
11248c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x", gtod_high);
11258c2ecf20Sopenharmony_ci
11268c2ecf20Sopenharmony_ci	return 0;
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_cistatic int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
11308c2ecf20Sopenharmony_ci{
11318c2ecf20Sopenharmony_ci	struct kvm_s390_vm_tod_clock gtod = { 0 };
11328c2ecf20Sopenharmony_ci
11338c2ecf20Sopenharmony_ci	if (copy_from_user(&gtod.tod, (void __user *)attr->addr,
11348c2ecf20Sopenharmony_ci			   sizeof(gtod.tod)))
11358c2ecf20Sopenharmony_ci		return -EFAULT;
11368c2ecf20Sopenharmony_ci
11378c2ecf20Sopenharmony_ci	__kvm_s390_set_tod_clock(kvm, &gtod);
11388c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod.tod);
11398c2ecf20Sopenharmony_ci	return 0;
11408c2ecf20Sopenharmony_ci}
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_cistatic int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
11438c2ecf20Sopenharmony_ci{
11448c2ecf20Sopenharmony_ci	int ret;
11458c2ecf20Sopenharmony_ci
11468c2ecf20Sopenharmony_ci	if (attr->flags)
11478c2ecf20Sopenharmony_ci		return -EINVAL;
11488c2ecf20Sopenharmony_ci
11498c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
11508c2ecf20Sopenharmony_ci	/*
11518c2ecf20Sopenharmony_ci	 * For protected guests, the TOD is managed by the ultravisor, so trying
11528c2ecf20Sopenharmony_ci	 * to change it will never bring the expected results.
11538c2ecf20Sopenharmony_ci	 */
11548c2ecf20Sopenharmony_ci	if (kvm_s390_pv_is_protected(kvm)) {
11558c2ecf20Sopenharmony_ci		ret = -EOPNOTSUPP;
11568c2ecf20Sopenharmony_ci		goto out_unlock;
11578c2ecf20Sopenharmony_ci	}
11588c2ecf20Sopenharmony_ci
11598c2ecf20Sopenharmony_ci	switch (attr->attr) {
11608c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_EXT:
11618c2ecf20Sopenharmony_ci		ret = kvm_s390_set_tod_ext(kvm, attr);
11628c2ecf20Sopenharmony_ci		break;
11638c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_HIGH:
11648c2ecf20Sopenharmony_ci		ret = kvm_s390_set_tod_high(kvm, attr);
11658c2ecf20Sopenharmony_ci		break;
11668c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_LOW:
11678c2ecf20Sopenharmony_ci		ret = kvm_s390_set_tod_low(kvm, attr);
11688c2ecf20Sopenharmony_ci		break;
11698c2ecf20Sopenharmony_ci	default:
11708c2ecf20Sopenharmony_ci		ret = -ENXIO;
11718c2ecf20Sopenharmony_ci		break;
11728c2ecf20Sopenharmony_ci	}
11738c2ecf20Sopenharmony_ci
11748c2ecf20Sopenharmony_ciout_unlock:
11758c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
11768c2ecf20Sopenharmony_ci	return ret;
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_cistatic void kvm_s390_get_tod_clock(struct kvm *kvm,
11808c2ecf20Sopenharmony_ci				   struct kvm_s390_vm_tod_clock *gtod)
11818c2ecf20Sopenharmony_ci{
11828c2ecf20Sopenharmony_ci	struct kvm_s390_tod_clock_ext htod;
11838c2ecf20Sopenharmony_ci
11848c2ecf20Sopenharmony_ci	preempt_disable();
11858c2ecf20Sopenharmony_ci
11868c2ecf20Sopenharmony_ci	get_tod_clock_ext((char *)&htod);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	gtod->tod = htod.tod + kvm->arch.epoch;
11898c2ecf20Sopenharmony_ci	gtod->epoch_idx = 0;
11908c2ecf20Sopenharmony_ci	if (test_kvm_facility(kvm, 139)) {
11918c2ecf20Sopenharmony_ci		gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx;
11928c2ecf20Sopenharmony_ci		if (gtod->tod < htod.tod)
11938c2ecf20Sopenharmony_ci			gtod->epoch_idx += 1;
11948c2ecf20Sopenharmony_ci	}
11958c2ecf20Sopenharmony_ci
11968c2ecf20Sopenharmony_ci	preempt_enable();
11978c2ecf20Sopenharmony_ci}
11988c2ecf20Sopenharmony_ci
11998c2ecf20Sopenharmony_cistatic int kvm_s390_get_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
12008c2ecf20Sopenharmony_ci{
12018c2ecf20Sopenharmony_ci	struct kvm_s390_vm_tod_clock gtod;
12028c2ecf20Sopenharmony_ci
12038c2ecf20Sopenharmony_ci	memset(&gtod, 0, sizeof(gtod));
12048c2ecf20Sopenharmony_ci	kvm_s390_get_tod_clock(kvm, &gtod);
12058c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
12068c2ecf20Sopenharmony_ci		return -EFAULT;
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x, TOD base: 0x%llx",
12098c2ecf20Sopenharmony_ci		gtod.epoch_idx, gtod.tod);
12108c2ecf20Sopenharmony_ci	return 0;
12118c2ecf20Sopenharmony_ci}
12128c2ecf20Sopenharmony_ci
12138c2ecf20Sopenharmony_cistatic int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
12148c2ecf20Sopenharmony_ci{
12158c2ecf20Sopenharmony_ci	u8 gtod_high = 0;
12168c2ecf20Sopenharmony_ci
12178c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &gtod_high,
12188c2ecf20Sopenharmony_ci					 sizeof(gtod_high)))
12198c2ecf20Sopenharmony_ci		return -EFAULT;
12208c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x", gtod_high);
12218c2ecf20Sopenharmony_ci
12228c2ecf20Sopenharmony_ci	return 0;
12238c2ecf20Sopenharmony_ci}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_cistatic int kvm_s390_get_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
12268c2ecf20Sopenharmony_ci{
12278c2ecf20Sopenharmony_ci	u64 gtod;
12288c2ecf20Sopenharmony_ci
12298c2ecf20Sopenharmony_ci	gtod = kvm_s390_get_tod_clock_fast(kvm);
12308c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &gtod, sizeof(gtod)))
12318c2ecf20Sopenharmony_ci		return -EFAULT;
12328c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "QUERY: TOD base: 0x%llx", gtod);
12338c2ecf20Sopenharmony_ci
12348c2ecf20Sopenharmony_ci	return 0;
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr)
12388c2ecf20Sopenharmony_ci{
12398c2ecf20Sopenharmony_ci	int ret;
12408c2ecf20Sopenharmony_ci
12418c2ecf20Sopenharmony_ci	if (attr->flags)
12428c2ecf20Sopenharmony_ci		return -EINVAL;
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	switch (attr->attr) {
12458c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_EXT:
12468c2ecf20Sopenharmony_ci		ret = kvm_s390_get_tod_ext(kvm, attr);
12478c2ecf20Sopenharmony_ci		break;
12488c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_HIGH:
12498c2ecf20Sopenharmony_ci		ret = kvm_s390_get_tod_high(kvm, attr);
12508c2ecf20Sopenharmony_ci		break;
12518c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD_LOW:
12528c2ecf20Sopenharmony_ci		ret = kvm_s390_get_tod_low(kvm, attr);
12538c2ecf20Sopenharmony_ci		break;
12548c2ecf20Sopenharmony_ci	default:
12558c2ecf20Sopenharmony_ci		ret = -ENXIO;
12568c2ecf20Sopenharmony_ci		break;
12578c2ecf20Sopenharmony_ci	}
12588c2ecf20Sopenharmony_ci	return ret;
12598c2ecf20Sopenharmony_ci}
12608c2ecf20Sopenharmony_ci
12618c2ecf20Sopenharmony_cistatic int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
12628c2ecf20Sopenharmony_ci{
12638c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_processor *proc;
12648c2ecf20Sopenharmony_ci	u16 lowest_ibc, unblocked_ibc;
12658c2ecf20Sopenharmony_ci	int ret = 0;
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
12688c2ecf20Sopenharmony_ci	if (kvm->created_vcpus) {
12698c2ecf20Sopenharmony_ci		ret = -EBUSY;
12708c2ecf20Sopenharmony_ci		goto out;
12718c2ecf20Sopenharmony_ci	}
12728c2ecf20Sopenharmony_ci	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
12738c2ecf20Sopenharmony_ci	if (!proc) {
12748c2ecf20Sopenharmony_ci		ret = -ENOMEM;
12758c2ecf20Sopenharmony_ci		goto out;
12768c2ecf20Sopenharmony_ci	}
12778c2ecf20Sopenharmony_ci	if (!copy_from_user(proc, (void __user *)attr->addr,
12788c2ecf20Sopenharmony_ci			    sizeof(*proc))) {
12798c2ecf20Sopenharmony_ci		kvm->arch.model.cpuid = proc->cpuid;
12808c2ecf20Sopenharmony_ci		lowest_ibc = sclp.ibc >> 16 & 0xfff;
12818c2ecf20Sopenharmony_ci		unblocked_ibc = sclp.ibc & 0xfff;
12828c2ecf20Sopenharmony_ci		if (lowest_ibc && proc->ibc) {
12838c2ecf20Sopenharmony_ci			if (proc->ibc > unblocked_ibc)
12848c2ecf20Sopenharmony_ci				kvm->arch.model.ibc = unblocked_ibc;
12858c2ecf20Sopenharmony_ci			else if (proc->ibc < lowest_ibc)
12868c2ecf20Sopenharmony_ci				kvm->arch.model.ibc = lowest_ibc;
12878c2ecf20Sopenharmony_ci			else
12888c2ecf20Sopenharmony_ci				kvm->arch.model.ibc = proc->ibc;
12898c2ecf20Sopenharmony_ci		}
12908c2ecf20Sopenharmony_ci		memcpy(kvm->arch.model.fac_list, proc->fac_list,
12918c2ecf20Sopenharmony_ci		       S390_ARCH_FAC_LIST_SIZE_BYTE);
12928c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx",
12938c2ecf20Sopenharmony_ci			 kvm->arch.model.ibc,
12948c2ecf20Sopenharmony_ci			 kvm->arch.model.cpuid);
12958c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx",
12968c2ecf20Sopenharmony_ci			 kvm->arch.model.fac_list[0],
12978c2ecf20Sopenharmony_ci			 kvm->arch.model.fac_list[1],
12988c2ecf20Sopenharmony_ci			 kvm->arch.model.fac_list[2]);
12998c2ecf20Sopenharmony_ci	} else
13008c2ecf20Sopenharmony_ci		ret = -EFAULT;
13018c2ecf20Sopenharmony_ci	kfree(proc);
13028c2ecf20Sopenharmony_ciout:
13038c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
13048c2ecf20Sopenharmony_ci	return ret;
13058c2ecf20Sopenharmony_ci}
13068c2ecf20Sopenharmony_ci
13078c2ecf20Sopenharmony_cistatic int kvm_s390_set_processor_feat(struct kvm *kvm,
13088c2ecf20Sopenharmony_ci				       struct kvm_device_attr *attr)
13098c2ecf20Sopenharmony_ci{
13108c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_feat data;
13118c2ecf20Sopenharmony_ci
13128c2ecf20Sopenharmony_ci	if (copy_from_user(&data, (void __user *)attr->addr, sizeof(data)))
13138c2ecf20Sopenharmony_ci		return -EFAULT;
13148c2ecf20Sopenharmony_ci	if (!bitmap_subset((unsigned long *) data.feat,
13158c2ecf20Sopenharmony_ci			   kvm_s390_available_cpu_feat,
13168c2ecf20Sopenharmony_ci			   KVM_S390_VM_CPU_FEAT_NR_BITS))
13178c2ecf20Sopenharmony_ci		return -EINVAL;
13188c2ecf20Sopenharmony_ci
13198c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
13208c2ecf20Sopenharmony_ci	if (kvm->created_vcpus) {
13218c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
13228c2ecf20Sopenharmony_ci		return -EBUSY;
13238c2ecf20Sopenharmony_ci	}
13248c2ecf20Sopenharmony_ci	bitmap_copy(kvm->arch.cpu_feat, (unsigned long *) data.feat,
13258c2ecf20Sopenharmony_ci		    KVM_S390_VM_CPU_FEAT_NR_BITS);
13268c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
13278c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest feat: 0x%16.16llx.0x%16.16llx.0x%16.16llx",
13288c2ecf20Sopenharmony_ci			 data.feat[0],
13298c2ecf20Sopenharmony_ci			 data.feat[1],
13308c2ecf20Sopenharmony_ci			 data.feat[2]);
13318c2ecf20Sopenharmony_ci	return 0;
13328c2ecf20Sopenharmony_ci}
13338c2ecf20Sopenharmony_ci
13348c2ecf20Sopenharmony_cistatic int kvm_s390_set_processor_subfunc(struct kvm *kvm,
13358c2ecf20Sopenharmony_ci					  struct kvm_device_attr *attr)
13368c2ecf20Sopenharmony_ci{
13378c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
13388c2ecf20Sopenharmony_ci	if (kvm->created_vcpus) {
13398c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
13408c2ecf20Sopenharmony_ci		return -EBUSY;
13418c2ecf20Sopenharmony_ci	}
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci	if (copy_from_user(&kvm->arch.model.subfuncs, (void __user *)attr->addr,
13448c2ecf20Sopenharmony_ci			   sizeof(struct kvm_s390_vm_cpu_subfunc))) {
13458c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
13468c2ecf20Sopenharmony_ci		return -EFAULT;
13478c2ecf20Sopenharmony_ci	}
13488c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
13498c2ecf20Sopenharmony_ci
13508c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest PLO    subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
13518c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[0],
13528c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[1],
13538c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[2],
13548c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[3]);
13558c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest PTFF   subfunc 0x%16.16lx.%16.16lx",
13568c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ptff)[0],
13578c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ptff)[1]);
13588c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMAC   subfunc 0x%16.16lx.%16.16lx",
13598c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmac)[0],
13608c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmac)[1]);
13618c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMC    subfunc 0x%16.16lx.%16.16lx",
13628c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmc)[0],
13638c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmc)[1]);
13648c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KM     subfunc 0x%16.16lx.%16.16lx",
13658c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.km)[0],
13668c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.km)[1]);
13678c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KIMD   subfunc 0x%16.16lx.%16.16lx",
13688c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kimd)[0],
13698c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kimd)[1]);
13708c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KLMD   subfunc 0x%16.16lx.%16.16lx",
13718c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.klmd)[0],
13728c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.klmd)[1]);
13738c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest PCKMO  subfunc 0x%16.16lx.%16.16lx",
13748c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pckmo)[0],
13758c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pckmo)[1]);
13768c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMCTR  subfunc 0x%16.16lx.%16.16lx",
13778c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmctr)[0],
13788c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmctr)[1]);
13798c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMF    subfunc 0x%16.16lx.%16.16lx",
13808c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmf)[0],
13818c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmf)[1]);
13828c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMO    subfunc 0x%16.16lx.%16.16lx",
13838c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmo)[0],
13848c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmo)[1]);
13858c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest PCC    subfunc 0x%16.16lx.%16.16lx",
13868c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pcc)[0],
13878c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pcc)[1]);
13888c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest PPNO   subfunc 0x%16.16lx.%16.16lx",
13898c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ppno)[0],
13908c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ppno)[1]);
13918c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KMA    subfunc 0x%16.16lx.%16.16lx",
13928c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kma)[0],
13938c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kma)[1]);
13948c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest KDSA   subfunc 0x%16.16lx.%16.16lx",
13958c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kdsa)[0],
13968c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kdsa)[1]);
13978c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest SORTL  subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
13988c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[0],
13998c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[1],
14008c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[2],
14018c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[3]);
14028c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "SET: guest DFLTCC subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
14038c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[0],
14048c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[1],
14058c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[2],
14068c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[3]);
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci	return 0;
14098c2ecf20Sopenharmony_ci}
14108c2ecf20Sopenharmony_ci
14118c2ecf20Sopenharmony_cistatic int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
14128c2ecf20Sopenharmony_ci{
14138c2ecf20Sopenharmony_ci	int ret = -ENXIO;
14148c2ecf20Sopenharmony_ci
14158c2ecf20Sopenharmony_ci	switch (attr->attr) {
14168c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR:
14178c2ecf20Sopenharmony_ci		ret = kvm_s390_set_processor(kvm, attr);
14188c2ecf20Sopenharmony_ci		break;
14198c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR_FEAT:
14208c2ecf20Sopenharmony_ci		ret = kvm_s390_set_processor_feat(kvm, attr);
14218c2ecf20Sopenharmony_ci		break;
14228c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
14238c2ecf20Sopenharmony_ci		ret = kvm_s390_set_processor_subfunc(kvm, attr);
14248c2ecf20Sopenharmony_ci		break;
14258c2ecf20Sopenharmony_ci	}
14268c2ecf20Sopenharmony_ci	return ret;
14278c2ecf20Sopenharmony_ci}
14288c2ecf20Sopenharmony_ci
14298c2ecf20Sopenharmony_cistatic int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr)
14308c2ecf20Sopenharmony_ci{
14318c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_processor *proc;
14328c2ecf20Sopenharmony_ci	int ret = 0;
14338c2ecf20Sopenharmony_ci
14348c2ecf20Sopenharmony_ci	proc = kzalloc(sizeof(*proc), GFP_KERNEL);
14358c2ecf20Sopenharmony_ci	if (!proc) {
14368c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14378c2ecf20Sopenharmony_ci		goto out;
14388c2ecf20Sopenharmony_ci	}
14398c2ecf20Sopenharmony_ci	proc->cpuid = kvm->arch.model.cpuid;
14408c2ecf20Sopenharmony_ci	proc->ibc = kvm->arch.model.ibc;
14418c2ecf20Sopenharmony_ci	memcpy(&proc->fac_list, kvm->arch.model.fac_list,
14428c2ecf20Sopenharmony_ci	       S390_ARCH_FAC_LIST_SIZE_BYTE);
14438c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx",
14448c2ecf20Sopenharmony_ci		 kvm->arch.model.ibc,
14458c2ecf20Sopenharmony_ci		 kvm->arch.model.cpuid);
14468c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx",
14478c2ecf20Sopenharmony_ci		 kvm->arch.model.fac_list[0],
14488c2ecf20Sopenharmony_ci		 kvm->arch.model.fac_list[1],
14498c2ecf20Sopenharmony_ci		 kvm->arch.model.fac_list[2]);
14508c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc)))
14518c2ecf20Sopenharmony_ci		ret = -EFAULT;
14528c2ecf20Sopenharmony_ci	kfree(proc);
14538c2ecf20Sopenharmony_ciout:
14548c2ecf20Sopenharmony_ci	return ret;
14558c2ecf20Sopenharmony_ci}
14568c2ecf20Sopenharmony_ci
14578c2ecf20Sopenharmony_cistatic int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr)
14588c2ecf20Sopenharmony_ci{
14598c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_machine *mach;
14608c2ecf20Sopenharmony_ci	int ret = 0;
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_ci	mach = kzalloc(sizeof(*mach), GFP_KERNEL);
14638c2ecf20Sopenharmony_ci	if (!mach) {
14648c2ecf20Sopenharmony_ci		ret = -ENOMEM;
14658c2ecf20Sopenharmony_ci		goto out;
14668c2ecf20Sopenharmony_ci	}
14678c2ecf20Sopenharmony_ci	get_cpu_id((struct cpuid *) &mach->cpuid);
14688c2ecf20Sopenharmony_ci	mach->ibc = sclp.ibc;
14698c2ecf20Sopenharmony_ci	memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
14708c2ecf20Sopenharmony_ci	       S390_ARCH_FAC_LIST_SIZE_BYTE);
14718c2ecf20Sopenharmony_ci	memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
14728c2ecf20Sopenharmony_ci	       sizeof(S390_lowcore.stfle_fac_list));
14738c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host ibc:  0x%4.4x, host cpuid:  0x%16.16llx",
14748c2ecf20Sopenharmony_ci		 kvm->arch.model.ibc,
14758c2ecf20Sopenharmony_ci		 kvm->arch.model.cpuid);
14768c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host facmask:  0x%16.16llx.%16.16llx.%16.16llx",
14778c2ecf20Sopenharmony_ci		 mach->fac_mask[0],
14788c2ecf20Sopenharmony_ci		 mach->fac_mask[1],
14798c2ecf20Sopenharmony_ci		 mach->fac_mask[2]);
14808c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host faclist:  0x%16.16llx.%16.16llx.%16.16llx",
14818c2ecf20Sopenharmony_ci		 mach->fac_list[0],
14828c2ecf20Sopenharmony_ci		 mach->fac_list[1],
14838c2ecf20Sopenharmony_ci		 mach->fac_list[2]);
14848c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach)))
14858c2ecf20Sopenharmony_ci		ret = -EFAULT;
14868c2ecf20Sopenharmony_ci	kfree(mach);
14878c2ecf20Sopenharmony_ciout:
14888c2ecf20Sopenharmony_ci	return ret;
14898c2ecf20Sopenharmony_ci}
14908c2ecf20Sopenharmony_ci
14918c2ecf20Sopenharmony_cistatic int kvm_s390_get_processor_feat(struct kvm *kvm,
14928c2ecf20Sopenharmony_ci				       struct kvm_device_attr *attr)
14938c2ecf20Sopenharmony_ci{
14948c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_feat data;
14958c2ecf20Sopenharmony_ci
14968c2ecf20Sopenharmony_ci	bitmap_copy((unsigned long *) data.feat, kvm->arch.cpu_feat,
14978c2ecf20Sopenharmony_ci		    KVM_S390_VM_CPU_FEAT_NR_BITS);
14988c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
14998c2ecf20Sopenharmony_ci		return -EFAULT;
15008c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest feat: 0x%16.16llx.0x%16.16llx.0x%16.16llx",
15018c2ecf20Sopenharmony_ci			 data.feat[0],
15028c2ecf20Sopenharmony_ci			 data.feat[1],
15038c2ecf20Sopenharmony_ci			 data.feat[2]);
15048c2ecf20Sopenharmony_ci	return 0;
15058c2ecf20Sopenharmony_ci}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_cistatic int kvm_s390_get_machine_feat(struct kvm *kvm,
15088c2ecf20Sopenharmony_ci				     struct kvm_device_attr *attr)
15098c2ecf20Sopenharmony_ci{
15108c2ecf20Sopenharmony_ci	struct kvm_s390_vm_cpu_feat data;
15118c2ecf20Sopenharmony_ci
15128c2ecf20Sopenharmony_ci	bitmap_copy((unsigned long *) data.feat,
15138c2ecf20Sopenharmony_ci		    kvm_s390_available_cpu_feat,
15148c2ecf20Sopenharmony_ci		    KVM_S390_VM_CPU_FEAT_NR_BITS);
15158c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
15168c2ecf20Sopenharmony_ci		return -EFAULT;
15178c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host feat:  0x%16.16llx.0x%16.16llx.0x%16.16llx",
15188c2ecf20Sopenharmony_ci			 data.feat[0],
15198c2ecf20Sopenharmony_ci			 data.feat[1],
15208c2ecf20Sopenharmony_ci			 data.feat[2]);
15218c2ecf20Sopenharmony_ci	return 0;
15228c2ecf20Sopenharmony_ci}
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_cistatic int kvm_s390_get_processor_subfunc(struct kvm *kvm,
15258c2ecf20Sopenharmony_ci					  struct kvm_device_attr *attr)
15268c2ecf20Sopenharmony_ci{
15278c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &kvm->arch.model.subfuncs,
15288c2ecf20Sopenharmony_ci	    sizeof(struct kvm_s390_vm_cpu_subfunc)))
15298c2ecf20Sopenharmony_ci		return -EFAULT;
15308c2ecf20Sopenharmony_ci
15318c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest PLO    subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
15328c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[0],
15338c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[1],
15348c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[2],
15358c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.plo)[3]);
15368c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest PTFF   subfunc 0x%16.16lx.%16.16lx",
15378c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ptff)[0],
15388c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ptff)[1]);
15398c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMAC   subfunc 0x%16.16lx.%16.16lx",
15408c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmac)[0],
15418c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmac)[1]);
15428c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMC    subfunc 0x%16.16lx.%16.16lx",
15438c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmc)[0],
15448c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmc)[1]);
15458c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KM     subfunc 0x%16.16lx.%16.16lx",
15468c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.km)[0],
15478c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.km)[1]);
15488c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KIMD   subfunc 0x%16.16lx.%16.16lx",
15498c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kimd)[0],
15508c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kimd)[1]);
15518c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KLMD   subfunc 0x%16.16lx.%16.16lx",
15528c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.klmd)[0],
15538c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.klmd)[1]);
15548c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest PCKMO  subfunc 0x%16.16lx.%16.16lx",
15558c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pckmo)[0],
15568c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pckmo)[1]);
15578c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMCTR  subfunc 0x%16.16lx.%16.16lx",
15588c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmctr)[0],
15598c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmctr)[1]);
15608c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMF    subfunc 0x%16.16lx.%16.16lx",
15618c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmf)[0],
15628c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmf)[1]);
15638c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMO    subfunc 0x%16.16lx.%16.16lx",
15648c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmo)[0],
15658c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kmo)[1]);
15668c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest PCC    subfunc 0x%16.16lx.%16.16lx",
15678c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pcc)[0],
15688c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.pcc)[1]);
15698c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest PPNO   subfunc 0x%16.16lx.%16.16lx",
15708c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ppno)[0],
15718c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.ppno)[1]);
15728c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KMA    subfunc 0x%16.16lx.%16.16lx",
15738c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kma)[0],
15748c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kma)[1]);
15758c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest KDSA   subfunc 0x%16.16lx.%16.16lx",
15768c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kdsa)[0],
15778c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.kdsa)[1]);
15788c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest SORTL  subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
15798c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[0],
15808c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[1],
15818c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[2],
15828c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.sortl)[3]);
15838c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: guest DFLTCC subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
15848c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[0],
15858c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[1],
15868c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[2],
15878c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm->arch.model.subfuncs.dfltcc)[3]);
15888c2ecf20Sopenharmony_ci
15898c2ecf20Sopenharmony_ci	return 0;
15908c2ecf20Sopenharmony_ci}
15918c2ecf20Sopenharmony_ci
15928c2ecf20Sopenharmony_cistatic int kvm_s390_get_machine_subfunc(struct kvm *kvm,
15938c2ecf20Sopenharmony_ci					struct kvm_device_attr *attr)
15948c2ecf20Sopenharmony_ci{
15958c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)attr->addr, &kvm_s390_available_subfunc,
15968c2ecf20Sopenharmony_ci	    sizeof(struct kvm_s390_vm_cpu_subfunc)))
15978c2ecf20Sopenharmony_ci		return -EFAULT;
15988c2ecf20Sopenharmony_ci
15998c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  PLO    subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
16008c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.plo)[0],
16018c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.plo)[1],
16028c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.plo)[2],
16038c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.plo)[3]);
16048c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  PTFF   subfunc 0x%16.16lx.%16.16lx",
16058c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.ptff)[0],
16068c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.ptff)[1]);
16078c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMAC   subfunc 0x%16.16lx.%16.16lx",
16088c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmac)[0],
16098c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmac)[1]);
16108c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMC    subfunc 0x%16.16lx.%16.16lx",
16118c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmc)[0],
16128c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmc)[1]);
16138c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KM     subfunc 0x%16.16lx.%16.16lx",
16148c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.km)[0],
16158c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.km)[1]);
16168c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KIMD   subfunc 0x%16.16lx.%16.16lx",
16178c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kimd)[0],
16188c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kimd)[1]);
16198c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KLMD   subfunc 0x%16.16lx.%16.16lx",
16208c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.klmd)[0],
16218c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.klmd)[1]);
16228c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  PCKMO  subfunc 0x%16.16lx.%16.16lx",
16238c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.pckmo)[0],
16248c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.pckmo)[1]);
16258c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMCTR  subfunc 0x%16.16lx.%16.16lx",
16268c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmctr)[0],
16278c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmctr)[1]);
16288c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMF    subfunc 0x%16.16lx.%16.16lx",
16298c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmf)[0],
16308c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmf)[1]);
16318c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMO    subfunc 0x%16.16lx.%16.16lx",
16328c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmo)[0],
16338c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kmo)[1]);
16348c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  PCC    subfunc 0x%16.16lx.%16.16lx",
16358c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.pcc)[0],
16368c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.pcc)[1]);
16378c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  PPNO   subfunc 0x%16.16lx.%16.16lx",
16388c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.ppno)[0],
16398c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.ppno)[1]);
16408c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KMA    subfunc 0x%16.16lx.%16.16lx",
16418c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kma)[0],
16428c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kma)[1]);
16438c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  KDSA   subfunc 0x%16.16lx.%16.16lx",
16448c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kdsa)[0],
16458c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.kdsa)[1]);
16468c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  SORTL  subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
16478c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.sortl)[0],
16488c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.sortl)[1],
16498c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.sortl)[2],
16508c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.sortl)[3]);
16518c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "GET: host  DFLTCC subfunc 0x%16.16lx.%16.16lx.%16.16lx.%16.16lx",
16528c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[0],
16538c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[1],
16548c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[2],
16558c2ecf20Sopenharmony_ci		 ((unsigned long *) &kvm_s390_available_subfunc.dfltcc)[3]);
16568c2ecf20Sopenharmony_ci
16578c2ecf20Sopenharmony_ci	return 0;
16588c2ecf20Sopenharmony_ci}
16598c2ecf20Sopenharmony_ci
16608c2ecf20Sopenharmony_cistatic int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
16618c2ecf20Sopenharmony_ci{
16628c2ecf20Sopenharmony_ci	int ret = -ENXIO;
16638c2ecf20Sopenharmony_ci
16648c2ecf20Sopenharmony_ci	switch (attr->attr) {
16658c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR:
16668c2ecf20Sopenharmony_ci		ret = kvm_s390_get_processor(kvm, attr);
16678c2ecf20Sopenharmony_ci		break;
16688c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MACHINE:
16698c2ecf20Sopenharmony_ci		ret = kvm_s390_get_machine(kvm, attr);
16708c2ecf20Sopenharmony_ci		break;
16718c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR_FEAT:
16728c2ecf20Sopenharmony_ci		ret = kvm_s390_get_processor_feat(kvm, attr);
16738c2ecf20Sopenharmony_ci		break;
16748c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MACHINE_FEAT:
16758c2ecf20Sopenharmony_ci		ret = kvm_s390_get_machine_feat(kvm, attr);
16768c2ecf20Sopenharmony_ci		break;
16778c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
16788c2ecf20Sopenharmony_ci		ret = kvm_s390_get_processor_subfunc(kvm, attr);
16798c2ecf20Sopenharmony_ci		break;
16808c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
16818c2ecf20Sopenharmony_ci		ret = kvm_s390_get_machine_subfunc(kvm, attr);
16828c2ecf20Sopenharmony_ci		break;
16838c2ecf20Sopenharmony_ci	}
16848c2ecf20Sopenharmony_ci	return ret;
16858c2ecf20Sopenharmony_ci}
16868c2ecf20Sopenharmony_ci
16878c2ecf20Sopenharmony_cistatic int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr)
16888c2ecf20Sopenharmony_ci{
16898c2ecf20Sopenharmony_ci	int ret;
16908c2ecf20Sopenharmony_ci
16918c2ecf20Sopenharmony_ci	switch (attr->group) {
16928c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_CTRL:
16938c2ecf20Sopenharmony_ci		ret = kvm_s390_set_mem_control(kvm, attr);
16948c2ecf20Sopenharmony_ci		break;
16958c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD:
16968c2ecf20Sopenharmony_ci		ret = kvm_s390_set_tod(kvm, attr);
16978c2ecf20Sopenharmony_ci		break;
16988c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MODEL:
16998c2ecf20Sopenharmony_ci		ret = kvm_s390_set_cpu_model(kvm, attr);
17008c2ecf20Sopenharmony_ci		break;
17018c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO:
17028c2ecf20Sopenharmony_ci		ret = kvm_s390_vm_set_crypto(kvm, attr);
17038c2ecf20Sopenharmony_ci		break;
17048c2ecf20Sopenharmony_ci	case KVM_S390_VM_MIGRATION:
17058c2ecf20Sopenharmony_ci		ret = kvm_s390_vm_set_migration(kvm, attr);
17068c2ecf20Sopenharmony_ci		break;
17078c2ecf20Sopenharmony_ci	default:
17088c2ecf20Sopenharmony_ci		ret = -ENXIO;
17098c2ecf20Sopenharmony_ci		break;
17108c2ecf20Sopenharmony_ci	}
17118c2ecf20Sopenharmony_ci
17128c2ecf20Sopenharmony_ci	return ret;
17138c2ecf20Sopenharmony_ci}
17148c2ecf20Sopenharmony_ci
17158c2ecf20Sopenharmony_cistatic int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr)
17168c2ecf20Sopenharmony_ci{
17178c2ecf20Sopenharmony_ci	int ret;
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci	switch (attr->group) {
17208c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_CTRL:
17218c2ecf20Sopenharmony_ci		ret = kvm_s390_get_mem_control(kvm, attr);
17228c2ecf20Sopenharmony_ci		break;
17238c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD:
17248c2ecf20Sopenharmony_ci		ret = kvm_s390_get_tod(kvm, attr);
17258c2ecf20Sopenharmony_ci		break;
17268c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MODEL:
17278c2ecf20Sopenharmony_ci		ret = kvm_s390_get_cpu_model(kvm, attr);
17288c2ecf20Sopenharmony_ci		break;
17298c2ecf20Sopenharmony_ci	case KVM_S390_VM_MIGRATION:
17308c2ecf20Sopenharmony_ci		ret = kvm_s390_vm_get_migration(kvm, attr);
17318c2ecf20Sopenharmony_ci		break;
17328c2ecf20Sopenharmony_ci	default:
17338c2ecf20Sopenharmony_ci		ret = -ENXIO;
17348c2ecf20Sopenharmony_ci		break;
17358c2ecf20Sopenharmony_ci	}
17368c2ecf20Sopenharmony_ci
17378c2ecf20Sopenharmony_ci	return ret;
17388c2ecf20Sopenharmony_ci}
17398c2ecf20Sopenharmony_ci
17408c2ecf20Sopenharmony_cistatic int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
17418c2ecf20Sopenharmony_ci{
17428c2ecf20Sopenharmony_ci	int ret;
17438c2ecf20Sopenharmony_ci
17448c2ecf20Sopenharmony_ci	switch (attr->group) {
17458c2ecf20Sopenharmony_ci	case KVM_S390_VM_MEM_CTRL:
17468c2ecf20Sopenharmony_ci		switch (attr->attr) {
17478c2ecf20Sopenharmony_ci		case KVM_S390_VM_MEM_ENABLE_CMMA:
17488c2ecf20Sopenharmony_ci		case KVM_S390_VM_MEM_CLR_CMMA:
17498c2ecf20Sopenharmony_ci			ret = sclp.has_cmma ? 0 : -ENXIO;
17508c2ecf20Sopenharmony_ci			break;
17518c2ecf20Sopenharmony_ci		case KVM_S390_VM_MEM_LIMIT_SIZE:
17528c2ecf20Sopenharmony_ci			ret = 0;
17538c2ecf20Sopenharmony_ci			break;
17548c2ecf20Sopenharmony_ci		default:
17558c2ecf20Sopenharmony_ci			ret = -ENXIO;
17568c2ecf20Sopenharmony_ci			break;
17578c2ecf20Sopenharmony_ci		}
17588c2ecf20Sopenharmony_ci		break;
17598c2ecf20Sopenharmony_ci	case KVM_S390_VM_TOD:
17608c2ecf20Sopenharmony_ci		switch (attr->attr) {
17618c2ecf20Sopenharmony_ci		case KVM_S390_VM_TOD_LOW:
17628c2ecf20Sopenharmony_ci		case KVM_S390_VM_TOD_HIGH:
17638c2ecf20Sopenharmony_ci			ret = 0;
17648c2ecf20Sopenharmony_ci			break;
17658c2ecf20Sopenharmony_ci		default:
17668c2ecf20Sopenharmony_ci			ret = -ENXIO;
17678c2ecf20Sopenharmony_ci			break;
17688c2ecf20Sopenharmony_ci		}
17698c2ecf20Sopenharmony_ci		break;
17708c2ecf20Sopenharmony_ci	case KVM_S390_VM_CPU_MODEL:
17718c2ecf20Sopenharmony_ci		switch (attr->attr) {
17728c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_PROCESSOR:
17738c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_MACHINE:
17748c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_PROCESSOR_FEAT:
17758c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_MACHINE_FEAT:
17768c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
17778c2ecf20Sopenharmony_ci		case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
17788c2ecf20Sopenharmony_ci			ret = 0;
17798c2ecf20Sopenharmony_ci			break;
17808c2ecf20Sopenharmony_ci		default:
17818c2ecf20Sopenharmony_ci			ret = -ENXIO;
17828c2ecf20Sopenharmony_ci			break;
17838c2ecf20Sopenharmony_ci		}
17848c2ecf20Sopenharmony_ci		break;
17858c2ecf20Sopenharmony_ci	case KVM_S390_VM_CRYPTO:
17868c2ecf20Sopenharmony_ci		switch (attr->attr) {
17878c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
17888c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
17898c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
17908c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
17918c2ecf20Sopenharmony_ci			ret = 0;
17928c2ecf20Sopenharmony_ci			break;
17938c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_ENABLE_APIE:
17948c2ecf20Sopenharmony_ci		case KVM_S390_VM_CRYPTO_DISABLE_APIE:
17958c2ecf20Sopenharmony_ci			ret = ap_instructions_available() ? 0 : -ENXIO;
17968c2ecf20Sopenharmony_ci			break;
17978c2ecf20Sopenharmony_ci		default:
17988c2ecf20Sopenharmony_ci			ret = -ENXIO;
17998c2ecf20Sopenharmony_ci			break;
18008c2ecf20Sopenharmony_ci		}
18018c2ecf20Sopenharmony_ci		break;
18028c2ecf20Sopenharmony_ci	case KVM_S390_VM_MIGRATION:
18038c2ecf20Sopenharmony_ci		ret = 0;
18048c2ecf20Sopenharmony_ci		break;
18058c2ecf20Sopenharmony_ci	default:
18068c2ecf20Sopenharmony_ci		ret = -ENXIO;
18078c2ecf20Sopenharmony_ci		break;
18088c2ecf20Sopenharmony_ci	}
18098c2ecf20Sopenharmony_ci
18108c2ecf20Sopenharmony_ci	return ret;
18118c2ecf20Sopenharmony_ci}
18128c2ecf20Sopenharmony_ci
18138c2ecf20Sopenharmony_cistatic long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
18148c2ecf20Sopenharmony_ci{
18158c2ecf20Sopenharmony_ci	uint8_t *keys;
18168c2ecf20Sopenharmony_ci	uint64_t hva;
18178c2ecf20Sopenharmony_ci	int srcu_idx, i, r = 0;
18188c2ecf20Sopenharmony_ci
18198c2ecf20Sopenharmony_ci	if (args->flags != 0)
18208c2ecf20Sopenharmony_ci		return -EINVAL;
18218c2ecf20Sopenharmony_ci
18228c2ecf20Sopenharmony_ci	/* Is this guest using storage keys? */
18238c2ecf20Sopenharmony_ci	if (!mm_uses_skeys(current->mm))
18248c2ecf20Sopenharmony_ci		return KVM_S390_GET_SKEYS_NONE;
18258c2ecf20Sopenharmony_ci
18268c2ecf20Sopenharmony_ci	/* Enforce sane limit on memory allocation */
18278c2ecf20Sopenharmony_ci	if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
18288c2ecf20Sopenharmony_ci		return -EINVAL;
18298c2ecf20Sopenharmony_ci
18308c2ecf20Sopenharmony_ci	keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
18318c2ecf20Sopenharmony_ci	if (!keys)
18328c2ecf20Sopenharmony_ci		return -ENOMEM;
18338c2ecf20Sopenharmony_ci
18348c2ecf20Sopenharmony_ci	mmap_read_lock(current->mm);
18358c2ecf20Sopenharmony_ci	srcu_idx = srcu_read_lock(&kvm->srcu);
18368c2ecf20Sopenharmony_ci	for (i = 0; i < args->count; i++) {
18378c2ecf20Sopenharmony_ci		hva = gfn_to_hva(kvm, args->start_gfn + i);
18388c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(hva)) {
18398c2ecf20Sopenharmony_ci			r = -EFAULT;
18408c2ecf20Sopenharmony_ci			break;
18418c2ecf20Sopenharmony_ci		}
18428c2ecf20Sopenharmony_ci
18438c2ecf20Sopenharmony_ci		r = get_guest_storage_key(current->mm, hva, &keys[i]);
18448c2ecf20Sopenharmony_ci		if (r)
18458c2ecf20Sopenharmony_ci			break;
18468c2ecf20Sopenharmony_ci	}
18478c2ecf20Sopenharmony_ci	srcu_read_unlock(&kvm->srcu, srcu_idx);
18488c2ecf20Sopenharmony_ci	mmap_read_unlock(current->mm);
18498c2ecf20Sopenharmony_ci
18508c2ecf20Sopenharmony_ci	if (!r) {
18518c2ecf20Sopenharmony_ci		r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys,
18528c2ecf20Sopenharmony_ci				 sizeof(uint8_t) * args->count);
18538c2ecf20Sopenharmony_ci		if (r)
18548c2ecf20Sopenharmony_ci			r = -EFAULT;
18558c2ecf20Sopenharmony_ci	}
18568c2ecf20Sopenharmony_ci
18578c2ecf20Sopenharmony_ci	kvfree(keys);
18588c2ecf20Sopenharmony_ci	return r;
18598c2ecf20Sopenharmony_ci}
18608c2ecf20Sopenharmony_ci
18618c2ecf20Sopenharmony_cistatic long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
18628c2ecf20Sopenharmony_ci{
18638c2ecf20Sopenharmony_ci	uint8_t *keys;
18648c2ecf20Sopenharmony_ci	uint64_t hva;
18658c2ecf20Sopenharmony_ci	int srcu_idx, i, r = 0;
18668c2ecf20Sopenharmony_ci	bool unlocked;
18678c2ecf20Sopenharmony_ci
18688c2ecf20Sopenharmony_ci	if (args->flags != 0)
18698c2ecf20Sopenharmony_ci		return -EINVAL;
18708c2ecf20Sopenharmony_ci
18718c2ecf20Sopenharmony_ci	/* Enforce sane limit on memory allocation */
18728c2ecf20Sopenharmony_ci	if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
18738c2ecf20Sopenharmony_ci		return -EINVAL;
18748c2ecf20Sopenharmony_ci
18758c2ecf20Sopenharmony_ci	keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
18768c2ecf20Sopenharmony_ci	if (!keys)
18778c2ecf20Sopenharmony_ci		return -ENOMEM;
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci	r = copy_from_user(keys, (uint8_t __user *)args->skeydata_addr,
18808c2ecf20Sopenharmony_ci			   sizeof(uint8_t) * args->count);
18818c2ecf20Sopenharmony_ci	if (r) {
18828c2ecf20Sopenharmony_ci		r = -EFAULT;
18838c2ecf20Sopenharmony_ci		goto out;
18848c2ecf20Sopenharmony_ci	}
18858c2ecf20Sopenharmony_ci
18868c2ecf20Sopenharmony_ci	/* Enable storage key handling for the guest */
18878c2ecf20Sopenharmony_ci	r = s390_enable_skey();
18888c2ecf20Sopenharmony_ci	if (r)
18898c2ecf20Sopenharmony_ci		goto out;
18908c2ecf20Sopenharmony_ci
18918c2ecf20Sopenharmony_ci	i = 0;
18928c2ecf20Sopenharmony_ci	mmap_read_lock(current->mm);
18938c2ecf20Sopenharmony_ci	srcu_idx = srcu_read_lock(&kvm->srcu);
18948c2ecf20Sopenharmony_ci        while (i < args->count) {
18958c2ecf20Sopenharmony_ci		unlocked = false;
18968c2ecf20Sopenharmony_ci		hva = gfn_to_hva(kvm, args->start_gfn + i);
18978c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(hva)) {
18988c2ecf20Sopenharmony_ci			r = -EFAULT;
18998c2ecf20Sopenharmony_ci			break;
19008c2ecf20Sopenharmony_ci		}
19018c2ecf20Sopenharmony_ci
19028c2ecf20Sopenharmony_ci		/* Lowest order bit is reserved */
19038c2ecf20Sopenharmony_ci		if (keys[i] & 0x01) {
19048c2ecf20Sopenharmony_ci			r = -EINVAL;
19058c2ecf20Sopenharmony_ci			break;
19068c2ecf20Sopenharmony_ci		}
19078c2ecf20Sopenharmony_ci
19088c2ecf20Sopenharmony_ci		r = set_guest_storage_key(current->mm, hva, keys[i], 0);
19098c2ecf20Sopenharmony_ci		if (r) {
19108c2ecf20Sopenharmony_ci			r = fixup_user_fault(current->mm, hva,
19118c2ecf20Sopenharmony_ci					     FAULT_FLAG_WRITE, &unlocked);
19128c2ecf20Sopenharmony_ci			if (r)
19138c2ecf20Sopenharmony_ci				break;
19148c2ecf20Sopenharmony_ci		}
19158c2ecf20Sopenharmony_ci		if (!r)
19168c2ecf20Sopenharmony_ci			i++;
19178c2ecf20Sopenharmony_ci	}
19188c2ecf20Sopenharmony_ci	srcu_read_unlock(&kvm->srcu, srcu_idx);
19198c2ecf20Sopenharmony_ci	mmap_read_unlock(current->mm);
19208c2ecf20Sopenharmony_ciout:
19218c2ecf20Sopenharmony_ci	kvfree(keys);
19228c2ecf20Sopenharmony_ci	return r;
19238c2ecf20Sopenharmony_ci}
19248c2ecf20Sopenharmony_ci
19258c2ecf20Sopenharmony_ci/*
19268c2ecf20Sopenharmony_ci * Base address and length must be sent at the start of each block, therefore
19278c2ecf20Sopenharmony_ci * it's cheaper to send some clean data, as long as it's less than the size of
19288c2ecf20Sopenharmony_ci * two longs.
19298c2ecf20Sopenharmony_ci */
19308c2ecf20Sopenharmony_ci#define KVM_S390_MAX_BIT_DISTANCE (2 * sizeof(void *))
19318c2ecf20Sopenharmony_ci/* for consistency */
19328c2ecf20Sopenharmony_ci#define KVM_S390_CMMA_SIZE_MAX ((u32)KVM_S390_SKEYS_MAX)
19338c2ecf20Sopenharmony_ci
19348c2ecf20Sopenharmony_ci/*
19358c2ecf20Sopenharmony_ci * Similar to gfn_to_memslot, but returns the index of a memslot also when the
19368c2ecf20Sopenharmony_ci * address falls in a hole. In that case the index of one of the memslots
19378c2ecf20Sopenharmony_ci * bordering the hole is returned.
19388c2ecf20Sopenharmony_ci */
19398c2ecf20Sopenharmony_cistatic int gfn_to_memslot_approx(struct kvm_memslots *slots, gfn_t gfn)
19408c2ecf20Sopenharmony_ci{
19418c2ecf20Sopenharmony_ci	int start = 0, end = slots->used_slots;
19428c2ecf20Sopenharmony_ci	int slot = atomic_read(&slots->lru_slot);
19438c2ecf20Sopenharmony_ci	struct kvm_memory_slot *memslots = slots->memslots;
19448c2ecf20Sopenharmony_ci
19458c2ecf20Sopenharmony_ci	if (gfn >= memslots[slot].base_gfn &&
19468c2ecf20Sopenharmony_ci	    gfn < memslots[slot].base_gfn + memslots[slot].npages)
19478c2ecf20Sopenharmony_ci		return slot;
19488c2ecf20Sopenharmony_ci
19498c2ecf20Sopenharmony_ci	while (start < end) {
19508c2ecf20Sopenharmony_ci		slot = start + (end - start) / 2;
19518c2ecf20Sopenharmony_ci
19528c2ecf20Sopenharmony_ci		if (gfn >= memslots[slot].base_gfn)
19538c2ecf20Sopenharmony_ci			end = slot;
19548c2ecf20Sopenharmony_ci		else
19558c2ecf20Sopenharmony_ci			start = slot + 1;
19568c2ecf20Sopenharmony_ci	}
19578c2ecf20Sopenharmony_ci
19588c2ecf20Sopenharmony_ci	if (start >= slots->used_slots)
19598c2ecf20Sopenharmony_ci		return slots->used_slots - 1;
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	if (gfn >= memslots[start].base_gfn &&
19628c2ecf20Sopenharmony_ci	    gfn < memslots[start].base_gfn + memslots[start].npages) {
19638c2ecf20Sopenharmony_ci		atomic_set(&slots->lru_slot, start);
19648c2ecf20Sopenharmony_ci	}
19658c2ecf20Sopenharmony_ci
19668c2ecf20Sopenharmony_ci	return start;
19678c2ecf20Sopenharmony_ci}
19688c2ecf20Sopenharmony_ci
19698c2ecf20Sopenharmony_cistatic int kvm_s390_peek_cmma(struct kvm *kvm, struct kvm_s390_cmma_log *args,
19708c2ecf20Sopenharmony_ci			      u8 *res, unsigned long bufsize)
19718c2ecf20Sopenharmony_ci{
19728c2ecf20Sopenharmony_ci	unsigned long pgstev, hva, cur_gfn = args->start_gfn;
19738c2ecf20Sopenharmony_ci
19748c2ecf20Sopenharmony_ci	args->count = 0;
19758c2ecf20Sopenharmony_ci	while (args->count < bufsize) {
19768c2ecf20Sopenharmony_ci		hva = gfn_to_hva(kvm, cur_gfn);
19778c2ecf20Sopenharmony_ci		/*
19788c2ecf20Sopenharmony_ci		 * We return an error if the first value was invalid, but we
19798c2ecf20Sopenharmony_ci		 * return successfully if at least one value was copied.
19808c2ecf20Sopenharmony_ci		 */
19818c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(hva))
19828c2ecf20Sopenharmony_ci			return args->count ? 0 : -EFAULT;
19838c2ecf20Sopenharmony_ci		if (get_pgste(kvm->mm, hva, &pgstev) < 0)
19848c2ecf20Sopenharmony_ci			pgstev = 0;
19858c2ecf20Sopenharmony_ci		res[args->count++] = (pgstev >> 24) & 0x43;
19868c2ecf20Sopenharmony_ci		cur_gfn++;
19878c2ecf20Sopenharmony_ci	}
19888c2ecf20Sopenharmony_ci
19898c2ecf20Sopenharmony_ci	return 0;
19908c2ecf20Sopenharmony_ci}
19918c2ecf20Sopenharmony_ci
19928c2ecf20Sopenharmony_cistatic unsigned long kvm_s390_next_dirty_cmma(struct kvm_memslots *slots,
19938c2ecf20Sopenharmony_ci					      unsigned long cur_gfn)
19948c2ecf20Sopenharmony_ci{
19958c2ecf20Sopenharmony_ci	int slotidx = gfn_to_memslot_approx(slots, cur_gfn);
19968c2ecf20Sopenharmony_ci	struct kvm_memory_slot *ms = slots->memslots + slotidx;
19978c2ecf20Sopenharmony_ci	unsigned long ofs = cur_gfn - ms->base_gfn;
19988c2ecf20Sopenharmony_ci
19998c2ecf20Sopenharmony_ci	if (ms->base_gfn + ms->npages <= cur_gfn) {
20008c2ecf20Sopenharmony_ci		slotidx--;
20018c2ecf20Sopenharmony_ci		/* If we are above the highest slot, wrap around */
20028c2ecf20Sopenharmony_ci		if (slotidx < 0)
20038c2ecf20Sopenharmony_ci			slotidx = slots->used_slots - 1;
20048c2ecf20Sopenharmony_ci
20058c2ecf20Sopenharmony_ci		ms = slots->memslots + slotidx;
20068c2ecf20Sopenharmony_ci		ofs = 0;
20078c2ecf20Sopenharmony_ci	}
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	if (cur_gfn < ms->base_gfn)
20108c2ecf20Sopenharmony_ci		ofs = 0;
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci	ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, ofs);
20138c2ecf20Sopenharmony_ci	while ((slotidx > 0) && (ofs >= ms->npages)) {
20148c2ecf20Sopenharmony_ci		slotidx--;
20158c2ecf20Sopenharmony_ci		ms = slots->memslots + slotidx;
20168c2ecf20Sopenharmony_ci		ofs = find_next_bit(kvm_second_dirty_bitmap(ms), ms->npages, 0);
20178c2ecf20Sopenharmony_ci	}
20188c2ecf20Sopenharmony_ci	return ms->base_gfn + ofs;
20198c2ecf20Sopenharmony_ci}
20208c2ecf20Sopenharmony_ci
20218c2ecf20Sopenharmony_cistatic int kvm_s390_get_cmma(struct kvm *kvm, struct kvm_s390_cmma_log *args,
20228c2ecf20Sopenharmony_ci			     u8 *res, unsigned long bufsize)
20238c2ecf20Sopenharmony_ci{
20248c2ecf20Sopenharmony_ci	unsigned long mem_end, cur_gfn, next_gfn, hva, pgstev;
20258c2ecf20Sopenharmony_ci	struct kvm_memslots *slots = kvm_memslots(kvm);
20268c2ecf20Sopenharmony_ci	struct kvm_memory_slot *ms;
20278c2ecf20Sopenharmony_ci
20288c2ecf20Sopenharmony_ci	if (unlikely(!slots->used_slots))
20298c2ecf20Sopenharmony_ci		return 0;
20308c2ecf20Sopenharmony_ci
20318c2ecf20Sopenharmony_ci	cur_gfn = kvm_s390_next_dirty_cmma(slots, args->start_gfn);
20328c2ecf20Sopenharmony_ci	ms = gfn_to_memslot(kvm, cur_gfn);
20338c2ecf20Sopenharmony_ci	args->count = 0;
20348c2ecf20Sopenharmony_ci	args->start_gfn = cur_gfn;
20358c2ecf20Sopenharmony_ci	if (!ms)
20368c2ecf20Sopenharmony_ci		return 0;
20378c2ecf20Sopenharmony_ci	next_gfn = kvm_s390_next_dirty_cmma(slots, cur_gfn + 1);
20388c2ecf20Sopenharmony_ci	mem_end = slots->memslots[0].base_gfn + slots->memslots[0].npages;
20398c2ecf20Sopenharmony_ci
20408c2ecf20Sopenharmony_ci	while (args->count < bufsize) {
20418c2ecf20Sopenharmony_ci		hva = gfn_to_hva(kvm, cur_gfn);
20428c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(hva))
20438c2ecf20Sopenharmony_ci			return 0;
20448c2ecf20Sopenharmony_ci		/* Decrement only if we actually flipped the bit to 0 */
20458c2ecf20Sopenharmony_ci		if (test_and_clear_bit(cur_gfn - ms->base_gfn, kvm_second_dirty_bitmap(ms)))
20468c2ecf20Sopenharmony_ci			atomic64_dec(&kvm->arch.cmma_dirty_pages);
20478c2ecf20Sopenharmony_ci		if (get_pgste(kvm->mm, hva, &pgstev) < 0)
20488c2ecf20Sopenharmony_ci			pgstev = 0;
20498c2ecf20Sopenharmony_ci		/* Save the value */
20508c2ecf20Sopenharmony_ci		res[args->count++] = (pgstev >> 24) & 0x43;
20518c2ecf20Sopenharmony_ci		/* If the next bit is too far away, stop. */
20528c2ecf20Sopenharmony_ci		if (next_gfn > cur_gfn + KVM_S390_MAX_BIT_DISTANCE)
20538c2ecf20Sopenharmony_ci			return 0;
20548c2ecf20Sopenharmony_ci		/* If we reached the previous "next", find the next one */
20558c2ecf20Sopenharmony_ci		if (cur_gfn == next_gfn)
20568c2ecf20Sopenharmony_ci			next_gfn = kvm_s390_next_dirty_cmma(slots, cur_gfn + 1);
20578c2ecf20Sopenharmony_ci		/* Reached the end of memory or of the buffer, stop */
20588c2ecf20Sopenharmony_ci		if ((next_gfn >= mem_end) ||
20598c2ecf20Sopenharmony_ci		    (next_gfn - args->start_gfn >= bufsize))
20608c2ecf20Sopenharmony_ci			return 0;
20618c2ecf20Sopenharmony_ci		cur_gfn++;
20628c2ecf20Sopenharmony_ci		/* Reached the end of the current memslot, take the next one. */
20638c2ecf20Sopenharmony_ci		if (cur_gfn - ms->base_gfn >= ms->npages) {
20648c2ecf20Sopenharmony_ci			ms = gfn_to_memslot(kvm, cur_gfn);
20658c2ecf20Sopenharmony_ci			if (!ms)
20668c2ecf20Sopenharmony_ci				return 0;
20678c2ecf20Sopenharmony_ci		}
20688c2ecf20Sopenharmony_ci	}
20698c2ecf20Sopenharmony_ci	return 0;
20708c2ecf20Sopenharmony_ci}
20718c2ecf20Sopenharmony_ci
20728c2ecf20Sopenharmony_ci/*
20738c2ecf20Sopenharmony_ci * This function searches for the next page with dirty CMMA attributes, and
20748c2ecf20Sopenharmony_ci * saves the attributes in the buffer up to either the end of the buffer or
20758c2ecf20Sopenharmony_ci * until a block of at least KVM_S390_MAX_BIT_DISTANCE clean bits is found;
20768c2ecf20Sopenharmony_ci * no trailing clean bytes are saved.
20778c2ecf20Sopenharmony_ci * In case no dirty bits were found, or if CMMA was not enabled or used, the
20788c2ecf20Sopenharmony_ci * output buffer will indicate 0 as length.
20798c2ecf20Sopenharmony_ci */
20808c2ecf20Sopenharmony_cistatic int kvm_s390_get_cmma_bits(struct kvm *kvm,
20818c2ecf20Sopenharmony_ci				  struct kvm_s390_cmma_log *args)
20828c2ecf20Sopenharmony_ci{
20838c2ecf20Sopenharmony_ci	unsigned long bufsize;
20848c2ecf20Sopenharmony_ci	int srcu_idx, peek, ret;
20858c2ecf20Sopenharmony_ci	u8 *values;
20868c2ecf20Sopenharmony_ci
20878c2ecf20Sopenharmony_ci	if (!kvm->arch.use_cmma)
20888c2ecf20Sopenharmony_ci		return -ENXIO;
20898c2ecf20Sopenharmony_ci	/* Invalid/unsupported flags were specified */
20908c2ecf20Sopenharmony_ci	if (args->flags & ~KVM_S390_CMMA_PEEK)
20918c2ecf20Sopenharmony_ci		return -EINVAL;
20928c2ecf20Sopenharmony_ci	/* Migration mode query, and we are not doing a migration */
20938c2ecf20Sopenharmony_ci	peek = !!(args->flags & KVM_S390_CMMA_PEEK);
20948c2ecf20Sopenharmony_ci	if (!peek && !kvm->arch.migration_mode)
20958c2ecf20Sopenharmony_ci		return -EINVAL;
20968c2ecf20Sopenharmony_ci	/* CMMA is disabled or was not used, or the buffer has length zero */
20978c2ecf20Sopenharmony_ci	bufsize = min(args->count, KVM_S390_CMMA_SIZE_MAX);
20988c2ecf20Sopenharmony_ci	if (!bufsize || !kvm->mm->context.uses_cmm) {
20998c2ecf20Sopenharmony_ci		memset(args, 0, sizeof(*args));
21008c2ecf20Sopenharmony_ci		return 0;
21018c2ecf20Sopenharmony_ci	}
21028c2ecf20Sopenharmony_ci	/* We are not peeking, and there are no dirty pages */
21038c2ecf20Sopenharmony_ci	if (!peek && !atomic64_read(&kvm->arch.cmma_dirty_pages)) {
21048c2ecf20Sopenharmony_ci		memset(args, 0, sizeof(*args));
21058c2ecf20Sopenharmony_ci		return 0;
21068c2ecf20Sopenharmony_ci	}
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	values = vmalloc(bufsize);
21098c2ecf20Sopenharmony_ci	if (!values)
21108c2ecf20Sopenharmony_ci		return -ENOMEM;
21118c2ecf20Sopenharmony_ci
21128c2ecf20Sopenharmony_ci	mmap_read_lock(kvm->mm);
21138c2ecf20Sopenharmony_ci	srcu_idx = srcu_read_lock(&kvm->srcu);
21148c2ecf20Sopenharmony_ci	if (peek)
21158c2ecf20Sopenharmony_ci		ret = kvm_s390_peek_cmma(kvm, args, values, bufsize);
21168c2ecf20Sopenharmony_ci	else
21178c2ecf20Sopenharmony_ci		ret = kvm_s390_get_cmma(kvm, args, values, bufsize);
21188c2ecf20Sopenharmony_ci	srcu_read_unlock(&kvm->srcu, srcu_idx);
21198c2ecf20Sopenharmony_ci	mmap_read_unlock(kvm->mm);
21208c2ecf20Sopenharmony_ci
21218c2ecf20Sopenharmony_ci	if (kvm->arch.migration_mode)
21228c2ecf20Sopenharmony_ci		args->remaining = atomic64_read(&kvm->arch.cmma_dirty_pages);
21238c2ecf20Sopenharmony_ci	else
21248c2ecf20Sopenharmony_ci		args->remaining = 0;
21258c2ecf20Sopenharmony_ci
21268c2ecf20Sopenharmony_ci	if (copy_to_user((void __user *)args->values, values, args->count))
21278c2ecf20Sopenharmony_ci		ret = -EFAULT;
21288c2ecf20Sopenharmony_ci
21298c2ecf20Sopenharmony_ci	vfree(values);
21308c2ecf20Sopenharmony_ci	return ret;
21318c2ecf20Sopenharmony_ci}
21328c2ecf20Sopenharmony_ci
21338c2ecf20Sopenharmony_ci/*
21348c2ecf20Sopenharmony_ci * This function sets the CMMA attributes for the given pages. If the input
21358c2ecf20Sopenharmony_ci * buffer has zero length, no action is taken, otherwise the attributes are
21368c2ecf20Sopenharmony_ci * set and the mm->context.uses_cmm flag is set.
21378c2ecf20Sopenharmony_ci */
21388c2ecf20Sopenharmony_cistatic int kvm_s390_set_cmma_bits(struct kvm *kvm,
21398c2ecf20Sopenharmony_ci				  const struct kvm_s390_cmma_log *args)
21408c2ecf20Sopenharmony_ci{
21418c2ecf20Sopenharmony_ci	unsigned long hva, mask, pgstev, i;
21428c2ecf20Sopenharmony_ci	uint8_t *bits;
21438c2ecf20Sopenharmony_ci	int srcu_idx, r = 0;
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci	mask = args->mask;
21468c2ecf20Sopenharmony_ci
21478c2ecf20Sopenharmony_ci	if (!kvm->arch.use_cmma)
21488c2ecf20Sopenharmony_ci		return -ENXIO;
21498c2ecf20Sopenharmony_ci	/* invalid/unsupported flags */
21508c2ecf20Sopenharmony_ci	if (args->flags != 0)
21518c2ecf20Sopenharmony_ci		return -EINVAL;
21528c2ecf20Sopenharmony_ci	/* Enforce sane limit on memory allocation */
21538c2ecf20Sopenharmony_ci	if (args->count > KVM_S390_CMMA_SIZE_MAX)
21548c2ecf20Sopenharmony_ci		return -EINVAL;
21558c2ecf20Sopenharmony_ci	/* Nothing to do */
21568c2ecf20Sopenharmony_ci	if (args->count == 0)
21578c2ecf20Sopenharmony_ci		return 0;
21588c2ecf20Sopenharmony_ci
21598c2ecf20Sopenharmony_ci	bits = vmalloc(array_size(sizeof(*bits), args->count));
21608c2ecf20Sopenharmony_ci	if (!bits)
21618c2ecf20Sopenharmony_ci		return -ENOMEM;
21628c2ecf20Sopenharmony_ci
21638c2ecf20Sopenharmony_ci	r = copy_from_user(bits, (void __user *)args->values, args->count);
21648c2ecf20Sopenharmony_ci	if (r) {
21658c2ecf20Sopenharmony_ci		r = -EFAULT;
21668c2ecf20Sopenharmony_ci		goto out;
21678c2ecf20Sopenharmony_ci	}
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	mmap_read_lock(kvm->mm);
21708c2ecf20Sopenharmony_ci	srcu_idx = srcu_read_lock(&kvm->srcu);
21718c2ecf20Sopenharmony_ci	for (i = 0; i < args->count; i++) {
21728c2ecf20Sopenharmony_ci		hva = gfn_to_hva(kvm, args->start_gfn + i);
21738c2ecf20Sopenharmony_ci		if (kvm_is_error_hva(hva)) {
21748c2ecf20Sopenharmony_ci			r = -EFAULT;
21758c2ecf20Sopenharmony_ci			break;
21768c2ecf20Sopenharmony_ci		}
21778c2ecf20Sopenharmony_ci
21788c2ecf20Sopenharmony_ci		pgstev = bits[i];
21798c2ecf20Sopenharmony_ci		pgstev = pgstev << 24;
21808c2ecf20Sopenharmony_ci		mask &= _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT;
21818c2ecf20Sopenharmony_ci		set_pgste_bits(kvm->mm, hva, mask, pgstev);
21828c2ecf20Sopenharmony_ci	}
21838c2ecf20Sopenharmony_ci	srcu_read_unlock(&kvm->srcu, srcu_idx);
21848c2ecf20Sopenharmony_ci	mmap_read_unlock(kvm->mm);
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci	if (!kvm->mm->context.uses_cmm) {
21878c2ecf20Sopenharmony_ci		mmap_write_lock(kvm->mm);
21888c2ecf20Sopenharmony_ci		kvm->mm->context.uses_cmm = 1;
21898c2ecf20Sopenharmony_ci		mmap_write_unlock(kvm->mm);
21908c2ecf20Sopenharmony_ci	}
21918c2ecf20Sopenharmony_ciout:
21928c2ecf20Sopenharmony_ci	vfree(bits);
21938c2ecf20Sopenharmony_ci	return r;
21948c2ecf20Sopenharmony_ci}
21958c2ecf20Sopenharmony_ci
21968c2ecf20Sopenharmony_cistatic int kvm_s390_cpus_from_pv(struct kvm *kvm, u16 *rcp, u16 *rrcp)
21978c2ecf20Sopenharmony_ci{
21988c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
21998c2ecf20Sopenharmony_ci	u16 rc, rrc;
22008c2ecf20Sopenharmony_ci	int ret = 0;
22018c2ecf20Sopenharmony_ci	int i;
22028c2ecf20Sopenharmony_ci
22038c2ecf20Sopenharmony_ci	/*
22048c2ecf20Sopenharmony_ci	 * We ignore failures and try to destroy as many CPUs as possible.
22058c2ecf20Sopenharmony_ci	 * At the same time we must not free the assigned resources when
22068c2ecf20Sopenharmony_ci	 * this fails, as the ultravisor has still access to that memory.
22078c2ecf20Sopenharmony_ci	 * So kvm_s390_pv_destroy_cpu can leave a "wanted" memory leak
22088c2ecf20Sopenharmony_ci	 * behind.
22098c2ecf20Sopenharmony_ci	 * We want to return the first failure rc and rrc, though.
22108c2ecf20Sopenharmony_ci	 */
22118c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
22128c2ecf20Sopenharmony_ci		mutex_lock(&vcpu->mutex);
22138c2ecf20Sopenharmony_ci		if (kvm_s390_pv_destroy_cpu(vcpu, &rc, &rrc) && !ret) {
22148c2ecf20Sopenharmony_ci			*rcp = rc;
22158c2ecf20Sopenharmony_ci			*rrcp = rrc;
22168c2ecf20Sopenharmony_ci			ret = -EIO;
22178c2ecf20Sopenharmony_ci		}
22188c2ecf20Sopenharmony_ci		mutex_unlock(&vcpu->mutex);
22198c2ecf20Sopenharmony_ci	}
22208c2ecf20Sopenharmony_ci	return ret;
22218c2ecf20Sopenharmony_ci}
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_cistatic int kvm_s390_cpus_to_pv(struct kvm *kvm, u16 *rc, u16 *rrc)
22248c2ecf20Sopenharmony_ci{
22258c2ecf20Sopenharmony_ci	int i, r = 0;
22268c2ecf20Sopenharmony_ci	u16 dummy;
22278c2ecf20Sopenharmony_ci
22288c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
22298c2ecf20Sopenharmony_ci
22308c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
22318c2ecf20Sopenharmony_ci		mutex_lock(&vcpu->mutex);
22328c2ecf20Sopenharmony_ci		r = kvm_s390_pv_create_cpu(vcpu, rc, rrc);
22338c2ecf20Sopenharmony_ci		mutex_unlock(&vcpu->mutex);
22348c2ecf20Sopenharmony_ci		if (r)
22358c2ecf20Sopenharmony_ci			break;
22368c2ecf20Sopenharmony_ci	}
22378c2ecf20Sopenharmony_ci	if (r)
22388c2ecf20Sopenharmony_ci		kvm_s390_cpus_from_pv(kvm, &dummy, &dummy);
22398c2ecf20Sopenharmony_ci	return r;
22408c2ecf20Sopenharmony_ci}
22418c2ecf20Sopenharmony_ci
22428c2ecf20Sopenharmony_cistatic int kvm_s390_handle_pv(struct kvm *kvm, struct kvm_pv_cmd *cmd)
22438c2ecf20Sopenharmony_ci{
22448c2ecf20Sopenharmony_ci	int r = 0;
22458c2ecf20Sopenharmony_ci	u16 dummy;
22468c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)cmd->data;
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci	switch (cmd->cmd) {
22498c2ecf20Sopenharmony_ci	case KVM_PV_ENABLE: {
22508c2ecf20Sopenharmony_ci		r = -EINVAL;
22518c2ecf20Sopenharmony_ci		if (kvm_s390_pv_is_protected(kvm))
22528c2ecf20Sopenharmony_ci			break;
22538c2ecf20Sopenharmony_ci
22548c2ecf20Sopenharmony_ci		/*
22558c2ecf20Sopenharmony_ci		 *  FMT 4 SIE needs esca. As we never switch back to bsca from
22568c2ecf20Sopenharmony_ci		 *  esca, we need no cleanup in the error cases below
22578c2ecf20Sopenharmony_ci		 */
22588c2ecf20Sopenharmony_ci		r = sca_switch_to_extended(kvm);
22598c2ecf20Sopenharmony_ci		if (r)
22608c2ecf20Sopenharmony_ci			break;
22618c2ecf20Sopenharmony_ci
22628c2ecf20Sopenharmony_ci		mmap_write_lock(current->mm);
22638c2ecf20Sopenharmony_ci		r = gmap_mark_unmergeable();
22648c2ecf20Sopenharmony_ci		mmap_write_unlock(current->mm);
22658c2ecf20Sopenharmony_ci		if (r)
22668c2ecf20Sopenharmony_ci			break;
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci		r = kvm_s390_pv_init_vm(kvm, &cmd->rc, &cmd->rrc);
22698c2ecf20Sopenharmony_ci		if (r)
22708c2ecf20Sopenharmony_ci			break;
22718c2ecf20Sopenharmony_ci
22728c2ecf20Sopenharmony_ci		r = kvm_s390_cpus_to_pv(kvm, &cmd->rc, &cmd->rrc);
22738c2ecf20Sopenharmony_ci		if (r)
22748c2ecf20Sopenharmony_ci			kvm_s390_pv_deinit_vm(kvm, &dummy, &dummy);
22758c2ecf20Sopenharmony_ci
22768c2ecf20Sopenharmony_ci		/* we need to block service interrupts from now on */
22778c2ecf20Sopenharmony_ci		set_bit(IRQ_PEND_EXT_SERVICE, &kvm->arch.float_int.masked_irqs);
22788c2ecf20Sopenharmony_ci		break;
22798c2ecf20Sopenharmony_ci	}
22808c2ecf20Sopenharmony_ci	case KVM_PV_DISABLE: {
22818c2ecf20Sopenharmony_ci		r = -EINVAL;
22828c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm))
22838c2ecf20Sopenharmony_ci			break;
22848c2ecf20Sopenharmony_ci
22858c2ecf20Sopenharmony_ci		r = kvm_s390_cpus_from_pv(kvm, &cmd->rc, &cmd->rrc);
22868c2ecf20Sopenharmony_ci		/*
22878c2ecf20Sopenharmony_ci		 * If a CPU could not be destroyed, destroy VM will also fail.
22888c2ecf20Sopenharmony_ci		 * There is no point in trying to destroy it. Instead return
22898c2ecf20Sopenharmony_ci		 * the rc and rrc from the first CPU that failed destroying.
22908c2ecf20Sopenharmony_ci		 */
22918c2ecf20Sopenharmony_ci		if (r)
22928c2ecf20Sopenharmony_ci			break;
22938c2ecf20Sopenharmony_ci		r = kvm_s390_pv_deinit_vm(kvm, &cmd->rc, &cmd->rrc);
22948c2ecf20Sopenharmony_ci
22958c2ecf20Sopenharmony_ci		/* no need to block service interrupts any more */
22968c2ecf20Sopenharmony_ci		clear_bit(IRQ_PEND_EXT_SERVICE, &kvm->arch.float_int.masked_irqs);
22978c2ecf20Sopenharmony_ci		break;
22988c2ecf20Sopenharmony_ci	}
22998c2ecf20Sopenharmony_ci	case KVM_PV_SET_SEC_PARMS: {
23008c2ecf20Sopenharmony_ci		struct kvm_s390_pv_sec_parm parms = {};
23018c2ecf20Sopenharmony_ci		void *hdr;
23028c2ecf20Sopenharmony_ci
23038c2ecf20Sopenharmony_ci		r = -EINVAL;
23048c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm))
23058c2ecf20Sopenharmony_ci			break;
23068c2ecf20Sopenharmony_ci
23078c2ecf20Sopenharmony_ci		r = -EFAULT;
23088c2ecf20Sopenharmony_ci		if (copy_from_user(&parms, argp, sizeof(parms)))
23098c2ecf20Sopenharmony_ci			break;
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci		/* Currently restricted to 8KB */
23128c2ecf20Sopenharmony_ci		r = -EINVAL;
23138c2ecf20Sopenharmony_ci		if (parms.length > PAGE_SIZE * 2)
23148c2ecf20Sopenharmony_ci			break;
23158c2ecf20Sopenharmony_ci
23168c2ecf20Sopenharmony_ci		r = -ENOMEM;
23178c2ecf20Sopenharmony_ci		hdr = vmalloc(parms.length);
23188c2ecf20Sopenharmony_ci		if (!hdr)
23198c2ecf20Sopenharmony_ci			break;
23208c2ecf20Sopenharmony_ci
23218c2ecf20Sopenharmony_ci		r = -EFAULT;
23228c2ecf20Sopenharmony_ci		if (!copy_from_user(hdr, (void __user *)parms.origin,
23238c2ecf20Sopenharmony_ci				    parms.length))
23248c2ecf20Sopenharmony_ci			r = kvm_s390_pv_set_sec_parms(kvm, hdr, parms.length,
23258c2ecf20Sopenharmony_ci						      &cmd->rc, &cmd->rrc);
23268c2ecf20Sopenharmony_ci
23278c2ecf20Sopenharmony_ci		vfree(hdr);
23288c2ecf20Sopenharmony_ci		break;
23298c2ecf20Sopenharmony_ci	}
23308c2ecf20Sopenharmony_ci	case KVM_PV_UNPACK: {
23318c2ecf20Sopenharmony_ci		struct kvm_s390_pv_unp unp = {};
23328c2ecf20Sopenharmony_ci
23338c2ecf20Sopenharmony_ci		r = -EINVAL;
23348c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm) || !mm_is_protected(kvm->mm))
23358c2ecf20Sopenharmony_ci			break;
23368c2ecf20Sopenharmony_ci
23378c2ecf20Sopenharmony_ci		r = -EFAULT;
23388c2ecf20Sopenharmony_ci		if (copy_from_user(&unp, argp, sizeof(unp)))
23398c2ecf20Sopenharmony_ci			break;
23408c2ecf20Sopenharmony_ci
23418c2ecf20Sopenharmony_ci		r = kvm_s390_pv_unpack(kvm, unp.addr, unp.size, unp.tweak,
23428c2ecf20Sopenharmony_ci				       &cmd->rc, &cmd->rrc);
23438c2ecf20Sopenharmony_ci		break;
23448c2ecf20Sopenharmony_ci	}
23458c2ecf20Sopenharmony_ci	case KVM_PV_VERIFY: {
23468c2ecf20Sopenharmony_ci		r = -EINVAL;
23478c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm))
23488c2ecf20Sopenharmony_ci			break;
23498c2ecf20Sopenharmony_ci
23508c2ecf20Sopenharmony_ci		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
23518c2ecf20Sopenharmony_ci				  UVC_CMD_VERIFY_IMG, &cmd->rc, &cmd->rrc);
23528c2ecf20Sopenharmony_ci		KVM_UV_EVENT(kvm, 3, "PROTVIRT VERIFY: rc %x rrc %x", cmd->rc,
23538c2ecf20Sopenharmony_ci			     cmd->rrc);
23548c2ecf20Sopenharmony_ci		break;
23558c2ecf20Sopenharmony_ci	}
23568c2ecf20Sopenharmony_ci	case KVM_PV_PREP_RESET: {
23578c2ecf20Sopenharmony_ci		r = -EINVAL;
23588c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm))
23598c2ecf20Sopenharmony_ci			break;
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
23628c2ecf20Sopenharmony_ci				  UVC_CMD_PREPARE_RESET, &cmd->rc, &cmd->rrc);
23638c2ecf20Sopenharmony_ci		KVM_UV_EVENT(kvm, 3, "PROTVIRT PREP RESET: rc %x rrc %x",
23648c2ecf20Sopenharmony_ci			     cmd->rc, cmd->rrc);
23658c2ecf20Sopenharmony_ci		break;
23668c2ecf20Sopenharmony_ci	}
23678c2ecf20Sopenharmony_ci	case KVM_PV_UNSHARE_ALL: {
23688c2ecf20Sopenharmony_ci		r = -EINVAL;
23698c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_is_protected(kvm))
23708c2ecf20Sopenharmony_ci			break;
23718c2ecf20Sopenharmony_ci
23728c2ecf20Sopenharmony_ci		r = uv_cmd_nodata(kvm_s390_pv_get_handle(kvm),
23738c2ecf20Sopenharmony_ci				  UVC_CMD_SET_UNSHARE_ALL, &cmd->rc, &cmd->rrc);
23748c2ecf20Sopenharmony_ci		KVM_UV_EVENT(kvm, 3, "PROTVIRT UNSHARE: rc %x rrc %x",
23758c2ecf20Sopenharmony_ci			     cmd->rc, cmd->rrc);
23768c2ecf20Sopenharmony_ci		break;
23778c2ecf20Sopenharmony_ci	}
23788c2ecf20Sopenharmony_ci	default:
23798c2ecf20Sopenharmony_ci		r = -ENOTTY;
23808c2ecf20Sopenharmony_ci	}
23818c2ecf20Sopenharmony_ci	return r;
23828c2ecf20Sopenharmony_ci}
23838c2ecf20Sopenharmony_ci
23848c2ecf20Sopenharmony_cilong kvm_arch_vm_ioctl(struct file *filp,
23858c2ecf20Sopenharmony_ci		       unsigned int ioctl, unsigned long arg)
23868c2ecf20Sopenharmony_ci{
23878c2ecf20Sopenharmony_ci	struct kvm *kvm = filp->private_data;
23888c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
23898c2ecf20Sopenharmony_ci	struct kvm_device_attr attr;
23908c2ecf20Sopenharmony_ci	int r;
23918c2ecf20Sopenharmony_ci
23928c2ecf20Sopenharmony_ci	switch (ioctl) {
23938c2ecf20Sopenharmony_ci	case KVM_S390_INTERRUPT: {
23948c2ecf20Sopenharmony_ci		struct kvm_s390_interrupt s390int;
23958c2ecf20Sopenharmony_ci
23968c2ecf20Sopenharmony_ci		r = -EFAULT;
23978c2ecf20Sopenharmony_ci		if (copy_from_user(&s390int, argp, sizeof(s390int)))
23988c2ecf20Sopenharmony_ci			break;
23998c2ecf20Sopenharmony_ci		r = kvm_s390_inject_vm(kvm, &s390int);
24008c2ecf20Sopenharmony_ci		break;
24018c2ecf20Sopenharmony_ci	}
24028c2ecf20Sopenharmony_ci	case KVM_CREATE_IRQCHIP: {
24038c2ecf20Sopenharmony_ci		struct kvm_irq_routing_entry routing;
24048c2ecf20Sopenharmony_ci
24058c2ecf20Sopenharmony_ci		r = -EINVAL;
24068c2ecf20Sopenharmony_ci		if (kvm->arch.use_irqchip) {
24078c2ecf20Sopenharmony_ci			/* Set up dummy routing. */
24088c2ecf20Sopenharmony_ci			memset(&routing, 0, sizeof(routing));
24098c2ecf20Sopenharmony_ci			r = kvm_set_irq_routing(kvm, &routing, 0, 0);
24108c2ecf20Sopenharmony_ci		}
24118c2ecf20Sopenharmony_ci		break;
24128c2ecf20Sopenharmony_ci	}
24138c2ecf20Sopenharmony_ci	case KVM_SET_DEVICE_ATTR: {
24148c2ecf20Sopenharmony_ci		r = -EFAULT;
24158c2ecf20Sopenharmony_ci		if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
24168c2ecf20Sopenharmony_ci			break;
24178c2ecf20Sopenharmony_ci		r = kvm_s390_vm_set_attr(kvm, &attr);
24188c2ecf20Sopenharmony_ci		break;
24198c2ecf20Sopenharmony_ci	}
24208c2ecf20Sopenharmony_ci	case KVM_GET_DEVICE_ATTR: {
24218c2ecf20Sopenharmony_ci		r = -EFAULT;
24228c2ecf20Sopenharmony_ci		if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
24238c2ecf20Sopenharmony_ci			break;
24248c2ecf20Sopenharmony_ci		r = kvm_s390_vm_get_attr(kvm, &attr);
24258c2ecf20Sopenharmony_ci		break;
24268c2ecf20Sopenharmony_ci	}
24278c2ecf20Sopenharmony_ci	case KVM_HAS_DEVICE_ATTR: {
24288c2ecf20Sopenharmony_ci		r = -EFAULT;
24298c2ecf20Sopenharmony_ci		if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
24308c2ecf20Sopenharmony_ci			break;
24318c2ecf20Sopenharmony_ci		r = kvm_s390_vm_has_attr(kvm, &attr);
24328c2ecf20Sopenharmony_ci		break;
24338c2ecf20Sopenharmony_ci	}
24348c2ecf20Sopenharmony_ci	case KVM_S390_GET_SKEYS: {
24358c2ecf20Sopenharmony_ci		struct kvm_s390_skeys args;
24368c2ecf20Sopenharmony_ci
24378c2ecf20Sopenharmony_ci		r = -EFAULT;
24388c2ecf20Sopenharmony_ci		if (copy_from_user(&args, argp,
24398c2ecf20Sopenharmony_ci				   sizeof(struct kvm_s390_skeys)))
24408c2ecf20Sopenharmony_ci			break;
24418c2ecf20Sopenharmony_ci		r = kvm_s390_get_skeys(kvm, &args);
24428c2ecf20Sopenharmony_ci		break;
24438c2ecf20Sopenharmony_ci	}
24448c2ecf20Sopenharmony_ci	case KVM_S390_SET_SKEYS: {
24458c2ecf20Sopenharmony_ci		struct kvm_s390_skeys args;
24468c2ecf20Sopenharmony_ci
24478c2ecf20Sopenharmony_ci		r = -EFAULT;
24488c2ecf20Sopenharmony_ci		if (copy_from_user(&args, argp,
24498c2ecf20Sopenharmony_ci				   sizeof(struct kvm_s390_skeys)))
24508c2ecf20Sopenharmony_ci			break;
24518c2ecf20Sopenharmony_ci		r = kvm_s390_set_skeys(kvm, &args);
24528c2ecf20Sopenharmony_ci		break;
24538c2ecf20Sopenharmony_ci	}
24548c2ecf20Sopenharmony_ci	case KVM_S390_GET_CMMA_BITS: {
24558c2ecf20Sopenharmony_ci		struct kvm_s390_cmma_log args;
24568c2ecf20Sopenharmony_ci
24578c2ecf20Sopenharmony_ci		r = -EFAULT;
24588c2ecf20Sopenharmony_ci		if (copy_from_user(&args, argp, sizeof(args)))
24598c2ecf20Sopenharmony_ci			break;
24608c2ecf20Sopenharmony_ci		mutex_lock(&kvm->slots_lock);
24618c2ecf20Sopenharmony_ci		r = kvm_s390_get_cmma_bits(kvm, &args);
24628c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->slots_lock);
24638c2ecf20Sopenharmony_ci		if (!r) {
24648c2ecf20Sopenharmony_ci			r = copy_to_user(argp, &args, sizeof(args));
24658c2ecf20Sopenharmony_ci			if (r)
24668c2ecf20Sopenharmony_ci				r = -EFAULT;
24678c2ecf20Sopenharmony_ci		}
24688c2ecf20Sopenharmony_ci		break;
24698c2ecf20Sopenharmony_ci	}
24708c2ecf20Sopenharmony_ci	case KVM_S390_SET_CMMA_BITS: {
24718c2ecf20Sopenharmony_ci		struct kvm_s390_cmma_log args;
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci		r = -EFAULT;
24748c2ecf20Sopenharmony_ci		if (copy_from_user(&args, argp, sizeof(args)))
24758c2ecf20Sopenharmony_ci			break;
24768c2ecf20Sopenharmony_ci		mutex_lock(&kvm->slots_lock);
24778c2ecf20Sopenharmony_ci		r = kvm_s390_set_cmma_bits(kvm, &args);
24788c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->slots_lock);
24798c2ecf20Sopenharmony_ci		break;
24808c2ecf20Sopenharmony_ci	}
24818c2ecf20Sopenharmony_ci	case KVM_S390_PV_COMMAND: {
24828c2ecf20Sopenharmony_ci		struct kvm_pv_cmd args;
24838c2ecf20Sopenharmony_ci
24848c2ecf20Sopenharmony_ci		/* protvirt means user sigp */
24858c2ecf20Sopenharmony_ci		kvm->arch.user_cpu_state_ctrl = 1;
24868c2ecf20Sopenharmony_ci		r = 0;
24878c2ecf20Sopenharmony_ci		if (!is_prot_virt_host()) {
24888c2ecf20Sopenharmony_ci			r = -EINVAL;
24898c2ecf20Sopenharmony_ci			break;
24908c2ecf20Sopenharmony_ci		}
24918c2ecf20Sopenharmony_ci		if (copy_from_user(&args, argp, sizeof(args))) {
24928c2ecf20Sopenharmony_ci			r = -EFAULT;
24938c2ecf20Sopenharmony_ci			break;
24948c2ecf20Sopenharmony_ci		}
24958c2ecf20Sopenharmony_ci		if (args.flags) {
24968c2ecf20Sopenharmony_ci			r = -EINVAL;
24978c2ecf20Sopenharmony_ci			break;
24988c2ecf20Sopenharmony_ci		}
24998c2ecf20Sopenharmony_ci		mutex_lock(&kvm->lock);
25008c2ecf20Sopenharmony_ci		r = kvm_s390_handle_pv(kvm, &args);
25018c2ecf20Sopenharmony_ci		mutex_unlock(&kvm->lock);
25028c2ecf20Sopenharmony_ci		if (copy_to_user(argp, &args, sizeof(args))) {
25038c2ecf20Sopenharmony_ci			r = -EFAULT;
25048c2ecf20Sopenharmony_ci			break;
25058c2ecf20Sopenharmony_ci		}
25068c2ecf20Sopenharmony_ci		break;
25078c2ecf20Sopenharmony_ci	}
25088c2ecf20Sopenharmony_ci	default:
25098c2ecf20Sopenharmony_ci		r = -ENOTTY;
25108c2ecf20Sopenharmony_ci	}
25118c2ecf20Sopenharmony_ci
25128c2ecf20Sopenharmony_ci	return r;
25138c2ecf20Sopenharmony_ci}
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_cistatic int kvm_s390_apxa_installed(void)
25168c2ecf20Sopenharmony_ci{
25178c2ecf20Sopenharmony_ci	struct ap_config_info info;
25188c2ecf20Sopenharmony_ci
25198c2ecf20Sopenharmony_ci	if (ap_instructions_available()) {
25208c2ecf20Sopenharmony_ci		if (ap_qci(&info) == 0)
25218c2ecf20Sopenharmony_ci			return info.apxa;
25228c2ecf20Sopenharmony_ci	}
25238c2ecf20Sopenharmony_ci
25248c2ecf20Sopenharmony_ci	return 0;
25258c2ecf20Sopenharmony_ci}
25268c2ecf20Sopenharmony_ci
25278c2ecf20Sopenharmony_ci/*
25288c2ecf20Sopenharmony_ci * The format of the crypto control block (CRYCB) is specified in the 3 low
25298c2ecf20Sopenharmony_ci * order bits of the CRYCB designation (CRYCBD) field as follows:
25308c2ecf20Sopenharmony_ci * Format 0: Neither the message security assist extension 3 (MSAX3) nor the
25318c2ecf20Sopenharmony_ci *	     AP extended addressing (APXA) facility are installed.
25328c2ecf20Sopenharmony_ci * Format 1: The APXA facility is not installed but the MSAX3 facility is.
25338c2ecf20Sopenharmony_ci * Format 2: Both the APXA and MSAX3 facilities are installed
25348c2ecf20Sopenharmony_ci */
25358c2ecf20Sopenharmony_cistatic void kvm_s390_set_crycb_format(struct kvm *kvm)
25368c2ecf20Sopenharmony_ci{
25378c2ecf20Sopenharmony_ci	kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb;
25388c2ecf20Sopenharmony_ci
25398c2ecf20Sopenharmony_ci	/* Clear the CRYCB format bits - i.e., set format 0 by default */
25408c2ecf20Sopenharmony_ci	kvm->arch.crypto.crycbd &= ~(CRYCB_FORMAT_MASK);
25418c2ecf20Sopenharmony_ci
25428c2ecf20Sopenharmony_ci	/* Check whether MSAX3 is installed */
25438c2ecf20Sopenharmony_ci	if (!test_kvm_facility(kvm, 76))
25448c2ecf20Sopenharmony_ci		return;
25458c2ecf20Sopenharmony_ci
25468c2ecf20Sopenharmony_ci	if (kvm_s390_apxa_installed())
25478c2ecf20Sopenharmony_ci		kvm->arch.crypto.crycbd |= CRYCB_FORMAT2;
25488c2ecf20Sopenharmony_ci	else
25498c2ecf20Sopenharmony_ci		kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
25508c2ecf20Sopenharmony_ci}
25518c2ecf20Sopenharmony_ci
25528c2ecf20Sopenharmony_civoid kvm_arch_crypto_set_masks(struct kvm *kvm, unsigned long *apm,
25538c2ecf20Sopenharmony_ci			       unsigned long *aqm, unsigned long *adm)
25548c2ecf20Sopenharmony_ci{
25558c2ecf20Sopenharmony_ci	struct kvm_s390_crypto_cb *crycb = kvm->arch.crypto.crycb;
25568c2ecf20Sopenharmony_ci
25578c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
25588c2ecf20Sopenharmony_ci	kvm_s390_vcpu_block_all(kvm);
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci	switch (kvm->arch.crypto.crycbd & CRYCB_FORMAT_MASK) {
25618c2ecf20Sopenharmony_ci	case CRYCB_FORMAT2: /* APCB1 use 256 bits */
25628c2ecf20Sopenharmony_ci		memcpy(crycb->apcb1.apm, apm, 32);
25638c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET CRYCB: apm %016lx %016lx %016lx %016lx",
25648c2ecf20Sopenharmony_ci			 apm[0], apm[1], apm[2], apm[3]);
25658c2ecf20Sopenharmony_ci		memcpy(crycb->apcb1.aqm, aqm, 32);
25668c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET CRYCB: aqm %016lx %016lx %016lx %016lx",
25678c2ecf20Sopenharmony_ci			 aqm[0], aqm[1], aqm[2], aqm[3]);
25688c2ecf20Sopenharmony_ci		memcpy(crycb->apcb1.adm, adm, 32);
25698c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET CRYCB: adm %016lx %016lx %016lx %016lx",
25708c2ecf20Sopenharmony_ci			 adm[0], adm[1], adm[2], adm[3]);
25718c2ecf20Sopenharmony_ci		break;
25728c2ecf20Sopenharmony_ci	case CRYCB_FORMAT1:
25738c2ecf20Sopenharmony_ci	case CRYCB_FORMAT0: /* Fall through both use APCB0 */
25748c2ecf20Sopenharmony_ci		memcpy(crycb->apcb0.apm, apm, 8);
25758c2ecf20Sopenharmony_ci		memcpy(crycb->apcb0.aqm, aqm, 2);
25768c2ecf20Sopenharmony_ci		memcpy(crycb->apcb0.adm, adm, 2);
25778c2ecf20Sopenharmony_ci		VM_EVENT(kvm, 3, "SET CRYCB: apm %016lx aqm %04x adm %04x",
25788c2ecf20Sopenharmony_ci			 apm[0], *((unsigned short *)aqm),
25798c2ecf20Sopenharmony_ci			 *((unsigned short *)adm));
25808c2ecf20Sopenharmony_ci		break;
25818c2ecf20Sopenharmony_ci	default:	/* Can not happen */
25828c2ecf20Sopenharmony_ci		break;
25838c2ecf20Sopenharmony_ci	}
25848c2ecf20Sopenharmony_ci
25858c2ecf20Sopenharmony_ci	/* recreate the shadow crycb for each vcpu */
25868c2ecf20Sopenharmony_ci	kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART);
25878c2ecf20Sopenharmony_ci	kvm_s390_vcpu_unblock_all(kvm);
25888c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
25898c2ecf20Sopenharmony_ci}
25908c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(kvm_arch_crypto_set_masks);
25918c2ecf20Sopenharmony_ci
25928c2ecf20Sopenharmony_civoid kvm_arch_crypto_clear_masks(struct kvm *kvm)
25938c2ecf20Sopenharmony_ci{
25948c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
25958c2ecf20Sopenharmony_ci	kvm_s390_vcpu_block_all(kvm);
25968c2ecf20Sopenharmony_ci
25978c2ecf20Sopenharmony_ci	memset(&kvm->arch.crypto.crycb->apcb0, 0,
25988c2ecf20Sopenharmony_ci	       sizeof(kvm->arch.crypto.crycb->apcb0));
25998c2ecf20Sopenharmony_ci	memset(&kvm->arch.crypto.crycb->apcb1, 0,
26008c2ecf20Sopenharmony_ci	       sizeof(kvm->arch.crypto.crycb->apcb1));
26018c2ecf20Sopenharmony_ci
26028c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "%s", "CLR CRYCB:");
26038c2ecf20Sopenharmony_ci	/* recreate the shadow crycb for each vcpu */
26048c2ecf20Sopenharmony_ci	kvm_s390_sync_request_broadcast(kvm, KVM_REQ_VSIE_RESTART);
26058c2ecf20Sopenharmony_ci	kvm_s390_vcpu_unblock_all(kvm);
26068c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
26078c2ecf20Sopenharmony_ci}
26088c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(kvm_arch_crypto_clear_masks);
26098c2ecf20Sopenharmony_ci
26108c2ecf20Sopenharmony_cistatic u64 kvm_s390_get_initial_cpuid(void)
26118c2ecf20Sopenharmony_ci{
26128c2ecf20Sopenharmony_ci	struct cpuid cpuid;
26138c2ecf20Sopenharmony_ci
26148c2ecf20Sopenharmony_ci	get_cpu_id(&cpuid);
26158c2ecf20Sopenharmony_ci	cpuid.version = 0xff;
26168c2ecf20Sopenharmony_ci	return *((u64 *) &cpuid);
26178c2ecf20Sopenharmony_ci}
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_cistatic void kvm_s390_crypto_init(struct kvm *kvm)
26208c2ecf20Sopenharmony_ci{
26218c2ecf20Sopenharmony_ci	kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
26228c2ecf20Sopenharmony_ci	kvm_s390_set_crycb_format(kvm);
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci	if (!test_kvm_facility(kvm, 76))
26258c2ecf20Sopenharmony_ci		return;
26268c2ecf20Sopenharmony_ci
26278c2ecf20Sopenharmony_ci	/* Enable AES/DEA protected key functions by default */
26288c2ecf20Sopenharmony_ci	kvm->arch.crypto.aes_kw = 1;
26298c2ecf20Sopenharmony_ci	kvm->arch.crypto.dea_kw = 1;
26308c2ecf20Sopenharmony_ci	get_random_bytes(kvm->arch.crypto.crycb->aes_wrapping_key_mask,
26318c2ecf20Sopenharmony_ci			 sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
26328c2ecf20Sopenharmony_ci	get_random_bytes(kvm->arch.crypto.crycb->dea_wrapping_key_mask,
26338c2ecf20Sopenharmony_ci			 sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
26348c2ecf20Sopenharmony_ci}
26358c2ecf20Sopenharmony_ci
26368c2ecf20Sopenharmony_cistatic void sca_dispose(struct kvm *kvm)
26378c2ecf20Sopenharmony_ci{
26388c2ecf20Sopenharmony_ci	if (kvm->arch.use_esca)
26398c2ecf20Sopenharmony_ci		free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
26408c2ecf20Sopenharmony_ci	else
26418c2ecf20Sopenharmony_ci		free_page((unsigned long)(kvm->arch.sca));
26428c2ecf20Sopenharmony_ci	kvm->arch.sca = NULL;
26438c2ecf20Sopenharmony_ci}
26448c2ecf20Sopenharmony_ci
26458c2ecf20Sopenharmony_ciint kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
26468c2ecf20Sopenharmony_ci{
26478c2ecf20Sopenharmony_ci	gfp_t alloc_flags = GFP_KERNEL;
26488c2ecf20Sopenharmony_ci	int i, rc;
26498c2ecf20Sopenharmony_ci	char debug_name[16];
26508c2ecf20Sopenharmony_ci	static unsigned long sca_offset;
26518c2ecf20Sopenharmony_ci
26528c2ecf20Sopenharmony_ci	rc = -EINVAL;
26538c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL
26548c2ecf20Sopenharmony_ci	if (type & ~KVM_VM_S390_UCONTROL)
26558c2ecf20Sopenharmony_ci		goto out_err;
26568c2ecf20Sopenharmony_ci	if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
26578c2ecf20Sopenharmony_ci		goto out_err;
26588c2ecf20Sopenharmony_ci#else
26598c2ecf20Sopenharmony_ci	if (type)
26608c2ecf20Sopenharmony_ci		goto out_err;
26618c2ecf20Sopenharmony_ci#endif
26628c2ecf20Sopenharmony_ci
26638c2ecf20Sopenharmony_ci	rc = s390_enable_sie();
26648c2ecf20Sopenharmony_ci	if (rc)
26658c2ecf20Sopenharmony_ci		goto out_err;
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci	rc = -ENOMEM;
26688c2ecf20Sopenharmony_ci
26698c2ecf20Sopenharmony_ci	if (!sclp.has_64bscao)
26708c2ecf20Sopenharmony_ci		alloc_flags |= GFP_DMA;
26718c2ecf20Sopenharmony_ci	rwlock_init(&kvm->arch.sca_lock);
26728c2ecf20Sopenharmony_ci	/* start with basic SCA */
26738c2ecf20Sopenharmony_ci	kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
26748c2ecf20Sopenharmony_ci	if (!kvm->arch.sca)
26758c2ecf20Sopenharmony_ci		goto out_err;
26768c2ecf20Sopenharmony_ci	mutex_lock(&kvm_lock);
26778c2ecf20Sopenharmony_ci	sca_offset += 16;
26788c2ecf20Sopenharmony_ci	if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
26798c2ecf20Sopenharmony_ci		sca_offset = 0;
26808c2ecf20Sopenharmony_ci	kvm->arch.sca = (struct bsca_block *)
26818c2ecf20Sopenharmony_ci			((char *) kvm->arch.sca + sca_offset);
26828c2ecf20Sopenharmony_ci	mutex_unlock(&kvm_lock);
26838c2ecf20Sopenharmony_ci
26848c2ecf20Sopenharmony_ci	sprintf(debug_name, "kvm-%u", current->pid);
26858c2ecf20Sopenharmony_ci
26868c2ecf20Sopenharmony_ci	kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long));
26878c2ecf20Sopenharmony_ci	if (!kvm->arch.dbf)
26888c2ecf20Sopenharmony_ci		goto out_err;
26898c2ecf20Sopenharmony_ci
26908c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct sie_page2) != 4096);
26918c2ecf20Sopenharmony_ci	kvm->arch.sie_page2 =
26928c2ecf20Sopenharmony_ci	     (struct sie_page2 *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
26938c2ecf20Sopenharmony_ci	if (!kvm->arch.sie_page2)
26948c2ecf20Sopenharmony_ci		goto out_err;
26958c2ecf20Sopenharmony_ci
26968c2ecf20Sopenharmony_ci	kvm->arch.sie_page2->kvm = kvm;
26978c2ecf20Sopenharmony_ci	kvm->arch.model.fac_list = kvm->arch.sie_page2->fac_list;
26988c2ecf20Sopenharmony_ci
26998c2ecf20Sopenharmony_ci	for (i = 0; i < kvm_s390_fac_size(); i++) {
27008c2ecf20Sopenharmony_ci		kvm->arch.model.fac_mask[i] = S390_lowcore.stfle_fac_list[i] &
27018c2ecf20Sopenharmony_ci					      (kvm_s390_fac_base[i] |
27028c2ecf20Sopenharmony_ci					       kvm_s390_fac_ext[i]);
27038c2ecf20Sopenharmony_ci		kvm->arch.model.fac_list[i] = S390_lowcore.stfle_fac_list[i] &
27048c2ecf20Sopenharmony_ci					      kvm_s390_fac_base[i];
27058c2ecf20Sopenharmony_ci	}
27068c2ecf20Sopenharmony_ci	kvm->arch.model.subfuncs = kvm_s390_available_subfunc;
27078c2ecf20Sopenharmony_ci
27088c2ecf20Sopenharmony_ci	/* we are always in czam mode - even on pre z14 machines */
27098c2ecf20Sopenharmony_ci	set_kvm_facility(kvm->arch.model.fac_mask, 138);
27108c2ecf20Sopenharmony_ci	set_kvm_facility(kvm->arch.model.fac_list, 138);
27118c2ecf20Sopenharmony_ci	/* we emulate STHYI in kvm */
27128c2ecf20Sopenharmony_ci	set_kvm_facility(kvm->arch.model.fac_mask, 74);
27138c2ecf20Sopenharmony_ci	set_kvm_facility(kvm->arch.model.fac_list, 74);
27148c2ecf20Sopenharmony_ci	if (MACHINE_HAS_TLB_GUEST) {
27158c2ecf20Sopenharmony_ci		set_kvm_facility(kvm->arch.model.fac_mask, 147);
27168c2ecf20Sopenharmony_ci		set_kvm_facility(kvm->arch.model.fac_list, 147);
27178c2ecf20Sopenharmony_ci	}
27188c2ecf20Sopenharmony_ci
27198c2ecf20Sopenharmony_ci	if (css_general_characteristics.aiv && test_facility(65))
27208c2ecf20Sopenharmony_ci		set_kvm_facility(kvm->arch.model.fac_mask, 65);
27218c2ecf20Sopenharmony_ci
27228c2ecf20Sopenharmony_ci	kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid();
27238c2ecf20Sopenharmony_ci	kvm->arch.model.ibc = sclp.ibc & 0x0fff;
27248c2ecf20Sopenharmony_ci
27258c2ecf20Sopenharmony_ci	kvm_s390_crypto_init(kvm);
27268c2ecf20Sopenharmony_ci
27278c2ecf20Sopenharmony_ci	mutex_init(&kvm->arch.float_int.ais_lock);
27288c2ecf20Sopenharmony_ci	spin_lock_init(&kvm->arch.float_int.lock);
27298c2ecf20Sopenharmony_ci	for (i = 0; i < FIRQ_LIST_COUNT; i++)
27308c2ecf20Sopenharmony_ci		INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
27318c2ecf20Sopenharmony_ci	init_waitqueue_head(&kvm->arch.ipte_wq);
27328c2ecf20Sopenharmony_ci	mutex_init(&kvm->arch.ipte_mutex);
27338c2ecf20Sopenharmony_ci
27348c2ecf20Sopenharmony_ci	debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
27358c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 3, "vm created with type %lu", type);
27368c2ecf20Sopenharmony_ci
27378c2ecf20Sopenharmony_ci	if (type & KVM_VM_S390_UCONTROL) {
27388c2ecf20Sopenharmony_ci		kvm->arch.gmap = NULL;
27398c2ecf20Sopenharmony_ci		kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT;
27408c2ecf20Sopenharmony_ci	} else {
27418c2ecf20Sopenharmony_ci		if (sclp.hamax == U64_MAX)
27428c2ecf20Sopenharmony_ci			kvm->arch.mem_limit = TASK_SIZE_MAX;
27438c2ecf20Sopenharmony_ci		else
27448c2ecf20Sopenharmony_ci			kvm->arch.mem_limit = min_t(unsigned long, TASK_SIZE_MAX,
27458c2ecf20Sopenharmony_ci						    sclp.hamax + 1);
27468c2ecf20Sopenharmony_ci		kvm->arch.gmap = gmap_create(current->mm, kvm->arch.mem_limit - 1);
27478c2ecf20Sopenharmony_ci		if (!kvm->arch.gmap)
27488c2ecf20Sopenharmony_ci			goto out_err;
27498c2ecf20Sopenharmony_ci		kvm->arch.gmap->private = kvm;
27508c2ecf20Sopenharmony_ci		kvm->arch.gmap->pfault_enabled = 0;
27518c2ecf20Sopenharmony_ci	}
27528c2ecf20Sopenharmony_ci
27538c2ecf20Sopenharmony_ci	kvm->arch.use_pfmfi = sclp.has_pfmfi;
27548c2ecf20Sopenharmony_ci	kvm->arch.use_skf = sclp.has_skey;
27558c2ecf20Sopenharmony_ci	spin_lock_init(&kvm->arch.start_stop_lock);
27568c2ecf20Sopenharmony_ci	kvm_s390_vsie_init(kvm);
27578c2ecf20Sopenharmony_ci	if (use_gisa)
27588c2ecf20Sopenharmony_ci		kvm_s390_gisa_init(kvm);
27598c2ecf20Sopenharmony_ci	KVM_EVENT(3, "vm 0x%pK created by pid %u", kvm, current->pid);
27608c2ecf20Sopenharmony_ci
27618c2ecf20Sopenharmony_ci	return 0;
27628c2ecf20Sopenharmony_ciout_err:
27638c2ecf20Sopenharmony_ci	free_page((unsigned long)kvm->arch.sie_page2);
27648c2ecf20Sopenharmony_ci	debug_unregister(kvm->arch.dbf);
27658c2ecf20Sopenharmony_ci	sca_dispose(kvm);
27668c2ecf20Sopenharmony_ci	KVM_EVENT(3, "creation of vm failed: %d", rc);
27678c2ecf20Sopenharmony_ci	return rc;
27688c2ecf20Sopenharmony_ci}
27698c2ecf20Sopenharmony_ci
27708c2ecf20Sopenharmony_civoid kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
27718c2ecf20Sopenharmony_ci{
27728c2ecf20Sopenharmony_ci	u16 rc, rrc;
27738c2ecf20Sopenharmony_ci
27748c2ecf20Sopenharmony_ci	VCPU_EVENT(vcpu, 3, "%s", "free cpu");
27758c2ecf20Sopenharmony_ci	trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
27768c2ecf20Sopenharmony_ci	kvm_s390_clear_local_irqs(vcpu);
27778c2ecf20Sopenharmony_ci	kvm_clear_async_pf_completion_queue(vcpu);
27788c2ecf20Sopenharmony_ci	if (!kvm_is_ucontrol(vcpu->kvm))
27798c2ecf20Sopenharmony_ci		sca_del_vcpu(vcpu);
27808c2ecf20Sopenharmony_ci
27818c2ecf20Sopenharmony_ci	if (kvm_is_ucontrol(vcpu->kvm))
27828c2ecf20Sopenharmony_ci		gmap_remove(vcpu->arch.gmap);
27838c2ecf20Sopenharmony_ci
27848c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.use_cmma)
27858c2ecf20Sopenharmony_ci		kvm_s390_vcpu_unsetup_cmma(vcpu);
27868c2ecf20Sopenharmony_ci	/* We can not hold the vcpu mutex here, we are already dying */
27878c2ecf20Sopenharmony_ci	if (kvm_s390_pv_cpu_get_handle(vcpu))
27888c2ecf20Sopenharmony_ci		kvm_s390_pv_destroy_cpu(vcpu, &rc, &rrc);
27898c2ecf20Sopenharmony_ci	free_page((unsigned long)(vcpu->arch.sie_block));
27908c2ecf20Sopenharmony_ci}
27918c2ecf20Sopenharmony_ci
27928c2ecf20Sopenharmony_cistatic void kvm_free_vcpus(struct kvm *kvm)
27938c2ecf20Sopenharmony_ci{
27948c2ecf20Sopenharmony_ci	unsigned int i;
27958c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
27968c2ecf20Sopenharmony_ci
27978c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm)
27988c2ecf20Sopenharmony_ci		kvm_vcpu_destroy(vcpu);
27998c2ecf20Sopenharmony_ci
28008c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
28018c2ecf20Sopenharmony_ci	for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
28028c2ecf20Sopenharmony_ci		kvm->vcpus[i] = NULL;
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	atomic_set(&kvm->online_vcpus, 0);
28058c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
28068c2ecf20Sopenharmony_ci}
28078c2ecf20Sopenharmony_ci
28088c2ecf20Sopenharmony_civoid kvm_arch_destroy_vm(struct kvm *kvm)
28098c2ecf20Sopenharmony_ci{
28108c2ecf20Sopenharmony_ci	u16 rc, rrc;
28118c2ecf20Sopenharmony_ci
28128c2ecf20Sopenharmony_ci	kvm_free_vcpus(kvm);
28138c2ecf20Sopenharmony_ci	sca_dispose(kvm);
28148c2ecf20Sopenharmony_ci	kvm_s390_gisa_destroy(kvm);
28158c2ecf20Sopenharmony_ci	/*
28168c2ecf20Sopenharmony_ci	 * We are already at the end of life and kvm->lock is not taken.
28178c2ecf20Sopenharmony_ci	 * This is ok as the file descriptor is closed by now and nobody
28188c2ecf20Sopenharmony_ci	 * can mess with the pv state. To avoid lockdep_assert_held from
28198c2ecf20Sopenharmony_ci	 * complaining we do not use kvm_s390_pv_is_protected.
28208c2ecf20Sopenharmony_ci	 */
28218c2ecf20Sopenharmony_ci	if (kvm_s390_pv_get_handle(kvm))
28228c2ecf20Sopenharmony_ci		kvm_s390_pv_deinit_vm(kvm, &rc, &rrc);
28238c2ecf20Sopenharmony_ci	debug_unregister(kvm->arch.dbf);
28248c2ecf20Sopenharmony_ci	free_page((unsigned long)kvm->arch.sie_page2);
28258c2ecf20Sopenharmony_ci	if (!kvm_is_ucontrol(kvm))
28268c2ecf20Sopenharmony_ci		gmap_remove(kvm->arch.gmap);
28278c2ecf20Sopenharmony_ci	kvm_s390_destroy_adapters(kvm);
28288c2ecf20Sopenharmony_ci	kvm_s390_clear_float_irqs(kvm);
28298c2ecf20Sopenharmony_ci	kvm_s390_vsie_destroy(kvm);
28308c2ecf20Sopenharmony_ci	KVM_EVENT(3, "vm 0x%pK destroyed", kvm);
28318c2ecf20Sopenharmony_ci}
28328c2ecf20Sopenharmony_ci
28338c2ecf20Sopenharmony_ci/* Section: vcpu related */
28348c2ecf20Sopenharmony_cistatic int __kvm_ucontrol_vcpu_init(struct kvm_vcpu *vcpu)
28358c2ecf20Sopenharmony_ci{
28368c2ecf20Sopenharmony_ci	vcpu->arch.gmap = gmap_create(current->mm, -1UL);
28378c2ecf20Sopenharmony_ci	if (!vcpu->arch.gmap)
28388c2ecf20Sopenharmony_ci		return -ENOMEM;
28398c2ecf20Sopenharmony_ci	vcpu->arch.gmap->private = vcpu->kvm;
28408c2ecf20Sopenharmony_ci
28418c2ecf20Sopenharmony_ci	return 0;
28428c2ecf20Sopenharmony_ci}
28438c2ecf20Sopenharmony_ci
28448c2ecf20Sopenharmony_cistatic void sca_del_vcpu(struct kvm_vcpu *vcpu)
28458c2ecf20Sopenharmony_ci{
28468c2ecf20Sopenharmony_ci	if (!kvm_s390_use_sca_entries())
28478c2ecf20Sopenharmony_ci		return;
28488c2ecf20Sopenharmony_ci	read_lock(&vcpu->kvm->arch.sca_lock);
28498c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.use_esca) {
28508c2ecf20Sopenharmony_ci		struct esca_block *sca = vcpu->kvm->arch.sca;
28518c2ecf20Sopenharmony_ci
28528c2ecf20Sopenharmony_ci		clear_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
28538c2ecf20Sopenharmony_ci		sca->cpu[vcpu->vcpu_id].sda = 0;
28548c2ecf20Sopenharmony_ci	} else {
28558c2ecf20Sopenharmony_ci		struct bsca_block *sca = vcpu->kvm->arch.sca;
28568c2ecf20Sopenharmony_ci
28578c2ecf20Sopenharmony_ci		clear_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
28588c2ecf20Sopenharmony_ci		sca->cpu[vcpu->vcpu_id].sda = 0;
28598c2ecf20Sopenharmony_ci	}
28608c2ecf20Sopenharmony_ci	read_unlock(&vcpu->kvm->arch.sca_lock);
28618c2ecf20Sopenharmony_ci}
28628c2ecf20Sopenharmony_ci
28638c2ecf20Sopenharmony_cistatic void sca_add_vcpu(struct kvm_vcpu *vcpu)
28648c2ecf20Sopenharmony_ci{
28658c2ecf20Sopenharmony_ci	if (!kvm_s390_use_sca_entries()) {
28668c2ecf20Sopenharmony_ci		struct bsca_block *sca = vcpu->kvm->arch.sca;
28678c2ecf20Sopenharmony_ci
28688c2ecf20Sopenharmony_ci		/* we still need the basic sca for the ipte control */
28698c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
28708c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaol = (__u32)(__u64)sca;
28718c2ecf20Sopenharmony_ci		return;
28728c2ecf20Sopenharmony_ci	}
28738c2ecf20Sopenharmony_ci	read_lock(&vcpu->kvm->arch.sca_lock);
28748c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.use_esca) {
28758c2ecf20Sopenharmony_ci		struct esca_block *sca = vcpu->kvm->arch.sca;
28768c2ecf20Sopenharmony_ci
28778c2ecf20Sopenharmony_ci		sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block;
28788c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
28798c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaol = (__u32)(__u64)sca & ~0x3fU;
28808c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
28818c2ecf20Sopenharmony_ci		set_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
28828c2ecf20Sopenharmony_ci	} else {
28838c2ecf20Sopenharmony_ci		struct bsca_block *sca = vcpu->kvm->arch.sca;
28848c2ecf20Sopenharmony_ci
28858c2ecf20Sopenharmony_ci		sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block;
28868c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
28878c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaol = (__u32)(__u64)sca;
28888c2ecf20Sopenharmony_ci		set_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
28898c2ecf20Sopenharmony_ci	}
28908c2ecf20Sopenharmony_ci	read_unlock(&vcpu->kvm->arch.sca_lock);
28918c2ecf20Sopenharmony_ci}
28928c2ecf20Sopenharmony_ci
28938c2ecf20Sopenharmony_ci/* Basic SCA to Extended SCA data copy routines */
28948c2ecf20Sopenharmony_cistatic inline void sca_copy_entry(struct esca_entry *d, struct bsca_entry *s)
28958c2ecf20Sopenharmony_ci{
28968c2ecf20Sopenharmony_ci	d->sda = s->sda;
28978c2ecf20Sopenharmony_ci	d->sigp_ctrl.c = s->sigp_ctrl.c;
28988c2ecf20Sopenharmony_ci	d->sigp_ctrl.scn = s->sigp_ctrl.scn;
28998c2ecf20Sopenharmony_ci}
29008c2ecf20Sopenharmony_ci
29018c2ecf20Sopenharmony_cistatic void sca_copy_b_to_e(struct esca_block *d, struct bsca_block *s)
29028c2ecf20Sopenharmony_ci{
29038c2ecf20Sopenharmony_ci	int i;
29048c2ecf20Sopenharmony_ci
29058c2ecf20Sopenharmony_ci	d->ipte_control = s->ipte_control;
29068c2ecf20Sopenharmony_ci	d->mcn[0] = s->mcn;
29078c2ecf20Sopenharmony_ci	for (i = 0; i < KVM_S390_BSCA_CPU_SLOTS; i++)
29088c2ecf20Sopenharmony_ci		sca_copy_entry(&d->cpu[i], &s->cpu[i]);
29098c2ecf20Sopenharmony_ci}
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_cistatic int sca_switch_to_extended(struct kvm *kvm)
29128c2ecf20Sopenharmony_ci{
29138c2ecf20Sopenharmony_ci	struct bsca_block *old_sca = kvm->arch.sca;
29148c2ecf20Sopenharmony_ci	struct esca_block *new_sca;
29158c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
29168c2ecf20Sopenharmony_ci	unsigned int vcpu_idx;
29178c2ecf20Sopenharmony_ci	u32 scaol, scaoh;
29188c2ecf20Sopenharmony_ci
29198c2ecf20Sopenharmony_ci	if (kvm->arch.use_esca)
29208c2ecf20Sopenharmony_ci		return 0;
29218c2ecf20Sopenharmony_ci
29228c2ecf20Sopenharmony_ci	new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL|__GFP_ZERO);
29238c2ecf20Sopenharmony_ci	if (!new_sca)
29248c2ecf20Sopenharmony_ci		return -ENOMEM;
29258c2ecf20Sopenharmony_ci
29268c2ecf20Sopenharmony_ci	scaoh = (u32)((u64)(new_sca) >> 32);
29278c2ecf20Sopenharmony_ci	scaol = (u32)(u64)(new_sca) & ~0x3fU;
29288c2ecf20Sopenharmony_ci
29298c2ecf20Sopenharmony_ci	kvm_s390_vcpu_block_all(kvm);
29308c2ecf20Sopenharmony_ci	write_lock(&kvm->arch.sca_lock);
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci	sca_copy_b_to_e(new_sca, old_sca);
29338c2ecf20Sopenharmony_ci
29348c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) {
29358c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaoh = scaoh;
29368c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->scaol = scaol;
29378c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
29388c2ecf20Sopenharmony_ci	}
29398c2ecf20Sopenharmony_ci	kvm->arch.sca = new_sca;
29408c2ecf20Sopenharmony_ci	kvm->arch.use_esca = 1;
29418c2ecf20Sopenharmony_ci
29428c2ecf20Sopenharmony_ci	write_unlock(&kvm->arch.sca_lock);
29438c2ecf20Sopenharmony_ci	kvm_s390_vcpu_unblock_all(kvm);
29448c2ecf20Sopenharmony_ci
29458c2ecf20Sopenharmony_ci	free_page((unsigned long)old_sca);
29468c2ecf20Sopenharmony_ci
29478c2ecf20Sopenharmony_ci	VM_EVENT(kvm, 2, "Switched to ESCA (0x%pK -> 0x%pK)",
29488c2ecf20Sopenharmony_ci		 old_sca, kvm->arch.sca);
29498c2ecf20Sopenharmony_ci	return 0;
29508c2ecf20Sopenharmony_ci}
29518c2ecf20Sopenharmony_ci
29528c2ecf20Sopenharmony_cistatic int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
29538c2ecf20Sopenharmony_ci{
29548c2ecf20Sopenharmony_ci	int rc;
29558c2ecf20Sopenharmony_ci
29568c2ecf20Sopenharmony_ci	if (!kvm_s390_use_sca_entries()) {
29578c2ecf20Sopenharmony_ci		if (id < KVM_MAX_VCPUS)
29588c2ecf20Sopenharmony_ci			return true;
29598c2ecf20Sopenharmony_ci		return false;
29608c2ecf20Sopenharmony_ci	}
29618c2ecf20Sopenharmony_ci	if (id < KVM_S390_BSCA_CPU_SLOTS)
29628c2ecf20Sopenharmony_ci		return true;
29638c2ecf20Sopenharmony_ci	if (!sclp.has_esca || !sclp.has_64bscao)
29648c2ecf20Sopenharmony_ci		return false;
29658c2ecf20Sopenharmony_ci
29668c2ecf20Sopenharmony_ci	mutex_lock(&kvm->lock);
29678c2ecf20Sopenharmony_ci	rc = kvm->arch.use_esca ? 0 : sca_switch_to_extended(kvm);
29688c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
29698c2ecf20Sopenharmony_ci
29708c2ecf20Sopenharmony_ci	return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS;
29718c2ecf20Sopenharmony_ci}
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
29748c2ecf20Sopenharmony_cistatic void __start_cpu_timer_accounting(struct kvm_vcpu *vcpu)
29758c2ecf20Sopenharmony_ci{
29768c2ecf20Sopenharmony_ci	WARN_ON_ONCE(vcpu->arch.cputm_start != 0);
29778c2ecf20Sopenharmony_ci	raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
29788c2ecf20Sopenharmony_ci	vcpu->arch.cputm_start = get_tod_clock_fast();
29798c2ecf20Sopenharmony_ci	raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
29808c2ecf20Sopenharmony_ci}
29818c2ecf20Sopenharmony_ci
29828c2ecf20Sopenharmony_ci/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
29838c2ecf20Sopenharmony_cistatic void __stop_cpu_timer_accounting(struct kvm_vcpu *vcpu)
29848c2ecf20Sopenharmony_ci{
29858c2ecf20Sopenharmony_ci	WARN_ON_ONCE(vcpu->arch.cputm_start == 0);
29868c2ecf20Sopenharmony_ci	raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
29878c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->cputm -= get_tod_clock_fast() - vcpu->arch.cputm_start;
29888c2ecf20Sopenharmony_ci	vcpu->arch.cputm_start = 0;
29898c2ecf20Sopenharmony_ci	raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
29908c2ecf20Sopenharmony_ci}
29918c2ecf20Sopenharmony_ci
29928c2ecf20Sopenharmony_ci/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
29938c2ecf20Sopenharmony_cistatic void __enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
29948c2ecf20Sopenharmony_ci{
29958c2ecf20Sopenharmony_ci	WARN_ON_ONCE(vcpu->arch.cputm_enabled);
29968c2ecf20Sopenharmony_ci	vcpu->arch.cputm_enabled = true;
29978c2ecf20Sopenharmony_ci	__start_cpu_timer_accounting(vcpu);
29988c2ecf20Sopenharmony_ci}
29998c2ecf20Sopenharmony_ci
30008c2ecf20Sopenharmony_ci/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
30018c2ecf20Sopenharmony_cistatic void __disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
30028c2ecf20Sopenharmony_ci{
30038c2ecf20Sopenharmony_ci	WARN_ON_ONCE(!vcpu->arch.cputm_enabled);
30048c2ecf20Sopenharmony_ci	__stop_cpu_timer_accounting(vcpu);
30058c2ecf20Sopenharmony_ci	vcpu->arch.cputm_enabled = false;
30068c2ecf20Sopenharmony_ci}
30078c2ecf20Sopenharmony_ci
30088c2ecf20Sopenharmony_cistatic void enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
30098c2ecf20Sopenharmony_ci{
30108c2ecf20Sopenharmony_ci	preempt_disable(); /* protect from TOD sync and vcpu_load/put */
30118c2ecf20Sopenharmony_ci	__enable_cpu_timer_accounting(vcpu);
30128c2ecf20Sopenharmony_ci	preempt_enable();
30138c2ecf20Sopenharmony_ci}
30148c2ecf20Sopenharmony_ci
30158c2ecf20Sopenharmony_cistatic void disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
30168c2ecf20Sopenharmony_ci{
30178c2ecf20Sopenharmony_ci	preempt_disable(); /* protect from TOD sync and vcpu_load/put */
30188c2ecf20Sopenharmony_ci	__disable_cpu_timer_accounting(vcpu);
30198c2ecf20Sopenharmony_ci	preempt_enable();
30208c2ecf20Sopenharmony_ci}
30218c2ecf20Sopenharmony_ci
30228c2ecf20Sopenharmony_ci/* set the cpu timer - may only be called from the VCPU thread itself */
30238c2ecf20Sopenharmony_civoid kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm)
30248c2ecf20Sopenharmony_ci{
30258c2ecf20Sopenharmony_ci	preempt_disable(); /* protect from TOD sync and vcpu_load/put */
30268c2ecf20Sopenharmony_ci	raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
30278c2ecf20Sopenharmony_ci	if (vcpu->arch.cputm_enabled)
30288c2ecf20Sopenharmony_ci		vcpu->arch.cputm_start = get_tod_clock_fast();
30298c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->cputm = cputm;
30308c2ecf20Sopenharmony_ci	raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
30318c2ecf20Sopenharmony_ci	preempt_enable();
30328c2ecf20Sopenharmony_ci}
30338c2ecf20Sopenharmony_ci
30348c2ecf20Sopenharmony_ci/* update and get the cpu timer - can also be called from other VCPU threads */
30358c2ecf20Sopenharmony_ci__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)
30368c2ecf20Sopenharmony_ci{
30378c2ecf20Sopenharmony_ci	unsigned int seq;
30388c2ecf20Sopenharmony_ci	__u64 value;
30398c2ecf20Sopenharmony_ci
30408c2ecf20Sopenharmony_ci	if (unlikely(!vcpu->arch.cputm_enabled))
30418c2ecf20Sopenharmony_ci		return vcpu->arch.sie_block->cputm;
30428c2ecf20Sopenharmony_ci
30438c2ecf20Sopenharmony_ci	preempt_disable(); /* protect from TOD sync and vcpu_load/put */
30448c2ecf20Sopenharmony_ci	do {
30458c2ecf20Sopenharmony_ci		seq = raw_read_seqcount(&vcpu->arch.cputm_seqcount);
30468c2ecf20Sopenharmony_ci		/*
30478c2ecf20Sopenharmony_ci		 * If the writer would ever execute a read in the critical
30488c2ecf20Sopenharmony_ci		 * section, e.g. in irq context, we have a deadlock.
30498c2ecf20Sopenharmony_ci		 */
30508c2ecf20Sopenharmony_ci		WARN_ON_ONCE((seq & 1) && smp_processor_id() == vcpu->cpu);
30518c2ecf20Sopenharmony_ci		value = vcpu->arch.sie_block->cputm;
30528c2ecf20Sopenharmony_ci		/* if cputm_start is 0, accounting is being started/stopped */
30538c2ecf20Sopenharmony_ci		if (likely(vcpu->arch.cputm_start))
30548c2ecf20Sopenharmony_ci			value -= get_tod_clock_fast() - vcpu->arch.cputm_start;
30558c2ecf20Sopenharmony_ci	} while (read_seqcount_retry(&vcpu->arch.cputm_seqcount, seq & ~1));
30568c2ecf20Sopenharmony_ci	preempt_enable();
30578c2ecf20Sopenharmony_ci	return value;
30588c2ecf20Sopenharmony_ci}
30598c2ecf20Sopenharmony_ci
30608c2ecf20Sopenharmony_civoid kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
30618c2ecf20Sopenharmony_ci{
30628c2ecf20Sopenharmony_ci
30638c2ecf20Sopenharmony_ci	gmap_enable(vcpu->arch.enabled_gmap);
30648c2ecf20Sopenharmony_ci	kvm_s390_set_cpuflags(vcpu, CPUSTAT_RUNNING);
30658c2ecf20Sopenharmony_ci	if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
30668c2ecf20Sopenharmony_ci		__start_cpu_timer_accounting(vcpu);
30678c2ecf20Sopenharmony_ci	vcpu->cpu = cpu;
30688c2ecf20Sopenharmony_ci}
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_civoid kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
30718c2ecf20Sopenharmony_ci{
30728c2ecf20Sopenharmony_ci	vcpu->cpu = -1;
30738c2ecf20Sopenharmony_ci	if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
30748c2ecf20Sopenharmony_ci		__stop_cpu_timer_accounting(vcpu);
30758c2ecf20Sopenharmony_ci	kvm_s390_clear_cpuflags(vcpu, CPUSTAT_RUNNING);
30768c2ecf20Sopenharmony_ci	vcpu->arch.enabled_gmap = gmap_get_enabled();
30778c2ecf20Sopenharmony_ci	gmap_disable(vcpu->arch.enabled_gmap);
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci}
30808c2ecf20Sopenharmony_ci
30818c2ecf20Sopenharmony_civoid kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
30828c2ecf20Sopenharmony_ci{
30838c2ecf20Sopenharmony_ci	mutex_lock(&vcpu->kvm->lock);
30848c2ecf20Sopenharmony_ci	preempt_disable();
30858c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
30868c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->epdx = vcpu->kvm->arch.epdx;
30878c2ecf20Sopenharmony_ci	preempt_enable();
30888c2ecf20Sopenharmony_ci	mutex_unlock(&vcpu->kvm->lock);
30898c2ecf20Sopenharmony_ci	if (!kvm_is_ucontrol(vcpu->kvm)) {
30908c2ecf20Sopenharmony_ci		vcpu->arch.gmap = vcpu->kvm->arch.gmap;
30918c2ecf20Sopenharmony_ci		sca_add_vcpu(vcpu);
30928c2ecf20Sopenharmony_ci	}
30938c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
30948c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
30958c2ecf20Sopenharmony_ci	/* make vcpu_load load the right gmap on the first trigger */
30968c2ecf20Sopenharmony_ci	vcpu->arch.enabled_gmap = vcpu->arch.gmap;
30978c2ecf20Sopenharmony_ci}
30988c2ecf20Sopenharmony_ci
30998c2ecf20Sopenharmony_cistatic bool kvm_has_pckmo_subfunc(struct kvm *kvm, unsigned long nr)
31008c2ecf20Sopenharmony_ci{
31018c2ecf20Sopenharmony_ci	if (test_bit_inv(nr, (unsigned long *)&kvm->arch.model.subfuncs.pckmo) &&
31028c2ecf20Sopenharmony_ci	    test_bit_inv(nr, (unsigned long *)&kvm_s390_available_subfunc.pckmo))
31038c2ecf20Sopenharmony_ci		return true;
31048c2ecf20Sopenharmony_ci	return false;
31058c2ecf20Sopenharmony_ci}
31068c2ecf20Sopenharmony_ci
31078c2ecf20Sopenharmony_cistatic bool kvm_has_pckmo_ecc(struct kvm *kvm)
31088c2ecf20Sopenharmony_ci{
31098c2ecf20Sopenharmony_ci	/* At least one ECC subfunction must be present */
31108c2ecf20Sopenharmony_ci	return kvm_has_pckmo_subfunc(kvm, 32) ||
31118c2ecf20Sopenharmony_ci	       kvm_has_pckmo_subfunc(kvm, 33) ||
31128c2ecf20Sopenharmony_ci	       kvm_has_pckmo_subfunc(kvm, 34) ||
31138c2ecf20Sopenharmony_ci	       kvm_has_pckmo_subfunc(kvm, 40) ||
31148c2ecf20Sopenharmony_ci	       kvm_has_pckmo_subfunc(kvm, 41);
31158c2ecf20Sopenharmony_ci
31168c2ecf20Sopenharmony_ci}
31178c2ecf20Sopenharmony_ci
31188c2ecf20Sopenharmony_cistatic void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
31198c2ecf20Sopenharmony_ci{
31208c2ecf20Sopenharmony_ci	/*
31218c2ecf20Sopenharmony_ci	 * If the AP instructions are not being interpreted and the MSAX3
31228c2ecf20Sopenharmony_ci	 * facility is not configured for the guest, there is nothing to set up.
31238c2ecf20Sopenharmony_ci	 */
31248c2ecf20Sopenharmony_ci	if (!vcpu->kvm->arch.crypto.apie && !test_kvm_facility(vcpu->kvm, 76))
31258c2ecf20Sopenharmony_ci		return;
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd;
31288c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA);
31298c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->eca &= ~ECA_APIE;
31308c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->ecd &= ~ECD_ECC;
31318c2ecf20Sopenharmony_ci
31328c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.crypto.apie)
31338c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_APIE;
31348c2ecf20Sopenharmony_ci
31358c2ecf20Sopenharmony_ci	/* Set up protected key support */
31368c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.crypto.aes_kw) {
31378c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb3 |= ECB3_AES;
31388c2ecf20Sopenharmony_ci		/* ecc is also wrapped with AES key */
31398c2ecf20Sopenharmony_ci		if (kvm_has_pckmo_ecc(vcpu->kvm))
31408c2ecf20Sopenharmony_ci			vcpu->arch.sie_block->ecd |= ECD_ECC;
31418c2ecf20Sopenharmony_ci	}
31428c2ecf20Sopenharmony_ci
31438c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.crypto.dea_kw)
31448c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb3 |= ECB3_DEA;
31458c2ecf20Sopenharmony_ci}
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_civoid kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
31488c2ecf20Sopenharmony_ci{
31498c2ecf20Sopenharmony_ci	free_page(vcpu->arch.sie_block->cbrlo);
31508c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->cbrlo = 0;
31518c2ecf20Sopenharmony_ci}
31528c2ecf20Sopenharmony_ci
31538c2ecf20Sopenharmony_ciint kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu)
31548c2ecf20Sopenharmony_ci{
31558c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->cbrlo = get_zeroed_page(GFP_KERNEL);
31568c2ecf20Sopenharmony_ci	if (!vcpu->arch.sie_block->cbrlo)
31578c2ecf20Sopenharmony_ci		return -ENOMEM;
31588c2ecf20Sopenharmony_ci	return 0;
31598c2ecf20Sopenharmony_ci}
31608c2ecf20Sopenharmony_ci
31618c2ecf20Sopenharmony_cistatic void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
31628c2ecf20Sopenharmony_ci{
31638c2ecf20Sopenharmony_ci	struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model;
31648c2ecf20Sopenharmony_ci
31658c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->ibc = model->ibc;
31668c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 7))
31678c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
31688c2ecf20Sopenharmony_ci}
31698c2ecf20Sopenharmony_ci
31708c2ecf20Sopenharmony_cistatic int kvm_s390_vcpu_setup(struct kvm_vcpu *vcpu)
31718c2ecf20Sopenharmony_ci{
31728c2ecf20Sopenharmony_ci	int rc = 0;
31738c2ecf20Sopenharmony_ci	u16 uvrc, uvrrc;
31748c2ecf20Sopenharmony_ci
31758c2ecf20Sopenharmony_ci	atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
31768c2ecf20Sopenharmony_ci						    CPUSTAT_SM |
31778c2ecf20Sopenharmony_ci						    CPUSTAT_STOPPED);
31788c2ecf20Sopenharmony_ci
31798c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 78))
31808c2ecf20Sopenharmony_ci		kvm_s390_set_cpuflags(vcpu, CPUSTAT_GED2);
31818c2ecf20Sopenharmony_ci	else if (test_kvm_facility(vcpu->kvm, 8))
31828c2ecf20Sopenharmony_ci		kvm_s390_set_cpuflags(vcpu, CPUSTAT_GED);
31838c2ecf20Sopenharmony_ci
31848c2ecf20Sopenharmony_ci	kvm_s390_vcpu_setup_model(vcpu);
31858c2ecf20Sopenharmony_ci
31868c2ecf20Sopenharmony_ci	/* pgste_set_pte has special handling for !MACHINE_HAS_ESOP */
31878c2ecf20Sopenharmony_ci	if (MACHINE_HAS_ESOP)
31888c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb |= ECB_HOSTPROTINT;
31898c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 9))
31908c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb |= ECB_SRSI;
31918c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 73))
31928c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb |= ECB_TE;
31938c2ecf20Sopenharmony_ci
31948c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 8) && vcpu->kvm->arch.use_pfmfi)
31958c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb2 |= ECB2_PFMFI;
31968c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 130))
31978c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb2 |= ECB2_IEP;
31988c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->eca = ECA_MVPGI | ECA_PROTEXCI;
31998c2ecf20Sopenharmony_ci	if (sclp.has_cei)
32008c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_CEI;
32018c2ecf20Sopenharmony_ci	if (sclp.has_ib)
32028c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_IB;
32038c2ecf20Sopenharmony_ci	if (sclp.has_siif)
32048c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_SII;
32058c2ecf20Sopenharmony_ci	if (sclp.has_sigpif)
32068c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_SIGPI;
32078c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 129)) {
32088c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_VX;
32098c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
32108c2ecf20Sopenharmony_ci	}
32118c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 139))
32128c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecd |= ECD_MEF;
32138c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 156))
32148c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecd |= ECD_ETOKENF;
32158c2ecf20Sopenharmony_ci	if (vcpu->arch.sie_block->gd) {
32168c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->eca |= ECA_AIV;
32178c2ecf20Sopenharmony_ci		VCPU_EVENT(vcpu, 3, "AIV gisa format-%u enabled for cpu %03u",
32188c2ecf20Sopenharmony_ci			   vcpu->arch.sie_block->gd & 0x3, vcpu->vcpu_id);
32198c2ecf20Sopenharmony_ci	}
32208c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx)
32218c2ecf20Sopenharmony_ci					| SDNXC;
32228c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb;
32238c2ecf20Sopenharmony_ci
32248c2ecf20Sopenharmony_ci	if (sclp.has_kss)
32258c2ecf20Sopenharmony_ci		kvm_s390_set_cpuflags(vcpu, CPUSTAT_KSS);
32268c2ecf20Sopenharmony_ci	else
32278c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
32288c2ecf20Sopenharmony_ci
32298c2ecf20Sopenharmony_ci	if (vcpu->kvm->arch.use_cmma) {
32308c2ecf20Sopenharmony_ci		rc = kvm_s390_vcpu_setup_cmma(vcpu);
32318c2ecf20Sopenharmony_ci		if (rc)
32328c2ecf20Sopenharmony_ci			return rc;
32338c2ecf20Sopenharmony_ci	}
32348c2ecf20Sopenharmony_ci	hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
32358c2ecf20Sopenharmony_ci	vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
32368c2ecf20Sopenharmony_ci
32378c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->hpid = HPID_KVM;
32388c2ecf20Sopenharmony_ci
32398c2ecf20Sopenharmony_ci	kvm_s390_vcpu_crypto_setup(vcpu);
32408c2ecf20Sopenharmony_ci
32418c2ecf20Sopenharmony_ci	mutex_lock(&vcpu->kvm->lock);
32428c2ecf20Sopenharmony_ci	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
32438c2ecf20Sopenharmony_ci		rc = kvm_s390_pv_create_cpu(vcpu, &uvrc, &uvrrc);
32448c2ecf20Sopenharmony_ci		if (rc)
32458c2ecf20Sopenharmony_ci			kvm_s390_vcpu_unsetup_cmma(vcpu);
32468c2ecf20Sopenharmony_ci	}
32478c2ecf20Sopenharmony_ci	mutex_unlock(&vcpu->kvm->lock);
32488c2ecf20Sopenharmony_ci
32498c2ecf20Sopenharmony_ci	return rc;
32508c2ecf20Sopenharmony_ci}
32518c2ecf20Sopenharmony_ci
32528c2ecf20Sopenharmony_ciint kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
32538c2ecf20Sopenharmony_ci{
32548c2ecf20Sopenharmony_ci	if (!kvm_is_ucontrol(kvm) && !sca_can_add_vcpu(kvm, id))
32558c2ecf20Sopenharmony_ci		return -EINVAL;
32568c2ecf20Sopenharmony_ci	return 0;
32578c2ecf20Sopenharmony_ci}
32588c2ecf20Sopenharmony_ci
32598c2ecf20Sopenharmony_ciint kvm_arch_vcpu_create(struct kvm_vcpu *vcpu)
32608c2ecf20Sopenharmony_ci{
32618c2ecf20Sopenharmony_ci	struct sie_page *sie_page;
32628c2ecf20Sopenharmony_ci	int rc;
32638c2ecf20Sopenharmony_ci
32648c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
32658c2ecf20Sopenharmony_ci	sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL);
32668c2ecf20Sopenharmony_ci	if (!sie_page)
32678c2ecf20Sopenharmony_ci		return -ENOMEM;
32688c2ecf20Sopenharmony_ci
32698c2ecf20Sopenharmony_ci	vcpu->arch.sie_block = &sie_page->sie_block;
32708c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci	/* the real guest size will always be smaller than msl */
32738c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->mso = 0;
32748c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->msl = sclp.hamax;
32758c2ecf20Sopenharmony_ci
32768c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->icpua = vcpu->vcpu_id;
32778c2ecf20Sopenharmony_ci	spin_lock_init(&vcpu->arch.local_int.lock);
32788c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gd = (u32)(u64)vcpu->kvm->arch.gisa_int.origin;
32798c2ecf20Sopenharmony_ci	if (vcpu->arch.sie_block->gd && sclp.has_gisaf)
32808c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gd |= GISA_FORMAT1;
32818c2ecf20Sopenharmony_ci	seqcount_init(&vcpu->arch.cputm_seqcount);
32828c2ecf20Sopenharmony_ci
32838c2ecf20Sopenharmony_ci	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
32848c2ecf20Sopenharmony_ci	kvm_clear_async_pf_completion_queue(vcpu);
32858c2ecf20Sopenharmony_ci	vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
32868c2ecf20Sopenharmony_ci				    KVM_SYNC_GPRS |
32878c2ecf20Sopenharmony_ci				    KVM_SYNC_ACRS |
32888c2ecf20Sopenharmony_ci				    KVM_SYNC_CRS |
32898c2ecf20Sopenharmony_ci				    KVM_SYNC_ARCH0 |
32908c2ecf20Sopenharmony_ci				    KVM_SYNC_PFAULT |
32918c2ecf20Sopenharmony_ci				    KVM_SYNC_DIAG318;
32928c2ecf20Sopenharmony_ci	kvm_s390_set_prefix(vcpu, 0);
32938c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 64))
32948c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
32958c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 82))
32968c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
32978c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 133))
32988c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
32998c2ecf20Sopenharmony_ci	if (test_kvm_facility(vcpu->kvm, 156))
33008c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_ETOKEN;
33018c2ecf20Sopenharmony_ci	/* fprs can be synchronized via vrs, even if the guest has no vx. With
33028c2ecf20Sopenharmony_ci	 * MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format.
33038c2ecf20Sopenharmony_ci	 */
33048c2ecf20Sopenharmony_ci	if (MACHINE_HAS_VX)
33058c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
33068c2ecf20Sopenharmony_ci	else
33078c2ecf20Sopenharmony_ci		vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
33088c2ecf20Sopenharmony_ci
33098c2ecf20Sopenharmony_ci	if (kvm_is_ucontrol(vcpu->kvm)) {
33108c2ecf20Sopenharmony_ci		rc = __kvm_ucontrol_vcpu_init(vcpu);
33118c2ecf20Sopenharmony_ci		if (rc)
33128c2ecf20Sopenharmony_ci			goto out_free_sie_block;
33138c2ecf20Sopenharmony_ci	}
33148c2ecf20Sopenharmony_ci
33158c2ecf20Sopenharmony_ci	VM_EVENT(vcpu->kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK",
33168c2ecf20Sopenharmony_ci		 vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
33178c2ecf20Sopenharmony_ci	trace_kvm_s390_create_vcpu(vcpu->vcpu_id, vcpu, vcpu->arch.sie_block);
33188c2ecf20Sopenharmony_ci
33198c2ecf20Sopenharmony_ci	rc = kvm_s390_vcpu_setup(vcpu);
33208c2ecf20Sopenharmony_ci	if (rc)
33218c2ecf20Sopenharmony_ci		goto out_ucontrol_uninit;
33228c2ecf20Sopenharmony_ci	return 0;
33238c2ecf20Sopenharmony_ci
33248c2ecf20Sopenharmony_ciout_ucontrol_uninit:
33258c2ecf20Sopenharmony_ci	if (kvm_is_ucontrol(vcpu->kvm))
33268c2ecf20Sopenharmony_ci		gmap_remove(vcpu->arch.gmap);
33278c2ecf20Sopenharmony_ciout_free_sie_block:
33288c2ecf20Sopenharmony_ci	free_page((unsigned long)(vcpu->arch.sie_block));
33298c2ecf20Sopenharmony_ci	return rc;
33308c2ecf20Sopenharmony_ci}
33318c2ecf20Sopenharmony_ci
33328c2ecf20Sopenharmony_ciint kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
33338c2ecf20Sopenharmony_ci{
33348c2ecf20Sopenharmony_ci	clear_bit(vcpu->vcpu_idx, vcpu->kvm->arch.gisa_int.kicked_mask);
33358c2ecf20Sopenharmony_ci	return kvm_s390_vcpu_has_irq(vcpu, 0);
33368c2ecf20Sopenharmony_ci}
33378c2ecf20Sopenharmony_ci
33388c2ecf20Sopenharmony_cibool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
33398c2ecf20Sopenharmony_ci{
33408c2ecf20Sopenharmony_ci	return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE);
33418c2ecf20Sopenharmony_ci}
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_civoid kvm_s390_vcpu_block(struct kvm_vcpu *vcpu)
33448c2ecf20Sopenharmony_ci{
33458c2ecf20Sopenharmony_ci	atomic_or(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
33468c2ecf20Sopenharmony_ci	exit_sie(vcpu);
33478c2ecf20Sopenharmony_ci}
33488c2ecf20Sopenharmony_ci
33498c2ecf20Sopenharmony_civoid kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu)
33508c2ecf20Sopenharmony_ci{
33518c2ecf20Sopenharmony_ci	atomic_andnot(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
33528c2ecf20Sopenharmony_ci}
33538c2ecf20Sopenharmony_ci
33548c2ecf20Sopenharmony_cistatic void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu)
33558c2ecf20Sopenharmony_ci{
33568c2ecf20Sopenharmony_ci	atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
33578c2ecf20Sopenharmony_ci	exit_sie(vcpu);
33588c2ecf20Sopenharmony_ci}
33598c2ecf20Sopenharmony_ci
33608c2ecf20Sopenharmony_cibool kvm_s390_vcpu_sie_inhibited(struct kvm_vcpu *vcpu)
33618c2ecf20Sopenharmony_ci{
33628c2ecf20Sopenharmony_ci	return atomic_read(&vcpu->arch.sie_block->prog20) &
33638c2ecf20Sopenharmony_ci	       (PROG_BLOCK_SIE | PROG_REQUEST);
33648c2ecf20Sopenharmony_ci}
33658c2ecf20Sopenharmony_ci
33668c2ecf20Sopenharmony_cistatic void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu)
33678c2ecf20Sopenharmony_ci{
33688c2ecf20Sopenharmony_ci	atomic_andnot(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
33698c2ecf20Sopenharmony_ci}
33708c2ecf20Sopenharmony_ci
33718c2ecf20Sopenharmony_ci/*
33728c2ecf20Sopenharmony_ci * Kick a guest cpu out of (v)SIE and wait until (v)SIE is not running.
33738c2ecf20Sopenharmony_ci * If the CPU is not running (e.g. waiting as idle) the function will
33748c2ecf20Sopenharmony_ci * return immediately. */
33758c2ecf20Sopenharmony_civoid exit_sie(struct kvm_vcpu *vcpu)
33768c2ecf20Sopenharmony_ci{
33778c2ecf20Sopenharmony_ci	kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOP_INT);
33788c2ecf20Sopenharmony_ci	kvm_s390_vsie_kick(vcpu);
33798c2ecf20Sopenharmony_ci	while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE)
33808c2ecf20Sopenharmony_ci		cpu_relax();
33818c2ecf20Sopenharmony_ci}
33828c2ecf20Sopenharmony_ci
33838c2ecf20Sopenharmony_ci/* Kick a guest cpu out of SIE to process a request synchronously */
33848c2ecf20Sopenharmony_civoid kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu)
33858c2ecf20Sopenharmony_ci{
33868c2ecf20Sopenharmony_ci	kvm_make_request(req, vcpu);
33878c2ecf20Sopenharmony_ci	kvm_s390_vcpu_request(vcpu);
33888c2ecf20Sopenharmony_ci}
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_cistatic void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
33918c2ecf20Sopenharmony_ci			      unsigned long end)
33928c2ecf20Sopenharmony_ci{
33938c2ecf20Sopenharmony_ci	struct kvm *kvm = gmap->private;
33948c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
33958c2ecf20Sopenharmony_ci	unsigned long prefix;
33968c2ecf20Sopenharmony_ci	int i;
33978c2ecf20Sopenharmony_ci
33988c2ecf20Sopenharmony_ci	if (gmap_is_shadow(gmap))
33998c2ecf20Sopenharmony_ci		return;
34008c2ecf20Sopenharmony_ci	if (start >= 1UL << 31)
34018c2ecf20Sopenharmony_ci		/* We are only interested in prefix pages */
34028c2ecf20Sopenharmony_ci		return;
34038c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
34048c2ecf20Sopenharmony_ci		/* match against both prefix pages */
34058c2ecf20Sopenharmony_ci		prefix = kvm_s390_get_prefix(vcpu);
34068c2ecf20Sopenharmony_ci		if (prefix <= end && start <= prefix + 2*PAGE_SIZE - 1) {
34078c2ecf20Sopenharmony_ci			VCPU_EVENT(vcpu, 2, "gmap notifier for %lx-%lx",
34088c2ecf20Sopenharmony_ci				   start, end);
34098c2ecf20Sopenharmony_ci			kvm_s390_sync_request(KVM_REQ_MMU_RELOAD, vcpu);
34108c2ecf20Sopenharmony_ci		}
34118c2ecf20Sopenharmony_ci	}
34128c2ecf20Sopenharmony_ci}
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_cibool kvm_arch_no_poll(struct kvm_vcpu *vcpu)
34158c2ecf20Sopenharmony_ci{
34168c2ecf20Sopenharmony_ci	/* do not poll with more than halt_poll_max_steal percent of steal time */
34178c2ecf20Sopenharmony_ci	if (S390_lowcore.avg_steal_timer * 100 / (TICK_USEC << 12) >=
34188c2ecf20Sopenharmony_ci	    halt_poll_max_steal) {
34198c2ecf20Sopenharmony_ci		vcpu->stat.halt_no_poll_steal++;
34208c2ecf20Sopenharmony_ci		return true;
34218c2ecf20Sopenharmony_ci	}
34228c2ecf20Sopenharmony_ci	return false;
34238c2ecf20Sopenharmony_ci}
34248c2ecf20Sopenharmony_ci
34258c2ecf20Sopenharmony_ciint kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
34268c2ecf20Sopenharmony_ci{
34278c2ecf20Sopenharmony_ci	/* kvm common code refers to this, but never calls it */
34288c2ecf20Sopenharmony_ci	BUG();
34298c2ecf20Sopenharmony_ci	return 0;
34308c2ecf20Sopenharmony_ci}
34318c2ecf20Sopenharmony_ci
34328c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
34338c2ecf20Sopenharmony_ci					   struct kvm_one_reg *reg)
34348c2ecf20Sopenharmony_ci{
34358c2ecf20Sopenharmony_ci	int r = -EINVAL;
34368c2ecf20Sopenharmony_ci
34378c2ecf20Sopenharmony_ci	switch (reg->id) {
34388c2ecf20Sopenharmony_ci	case KVM_REG_S390_TODPR:
34398c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.sie_block->todpr,
34408c2ecf20Sopenharmony_ci			     (u32 __user *)reg->addr);
34418c2ecf20Sopenharmony_ci		break;
34428c2ecf20Sopenharmony_ci	case KVM_REG_S390_EPOCHDIFF:
34438c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.sie_block->epoch,
34448c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34458c2ecf20Sopenharmony_ci		break;
34468c2ecf20Sopenharmony_ci	case KVM_REG_S390_CPU_TIMER:
34478c2ecf20Sopenharmony_ci		r = put_user(kvm_s390_get_cpu_timer(vcpu),
34488c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34498c2ecf20Sopenharmony_ci		break;
34508c2ecf20Sopenharmony_ci	case KVM_REG_S390_CLOCK_COMP:
34518c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.sie_block->ckc,
34528c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34538c2ecf20Sopenharmony_ci		break;
34548c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFTOKEN:
34558c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.pfault_token,
34568c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34578c2ecf20Sopenharmony_ci		break;
34588c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFCOMPARE:
34598c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.pfault_compare,
34608c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34618c2ecf20Sopenharmony_ci		break;
34628c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFSELECT:
34638c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.pfault_select,
34648c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34658c2ecf20Sopenharmony_ci		break;
34668c2ecf20Sopenharmony_ci	case KVM_REG_S390_PP:
34678c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.sie_block->pp,
34688c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34698c2ecf20Sopenharmony_ci		break;
34708c2ecf20Sopenharmony_ci	case KVM_REG_S390_GBEA:
34718c2ecf20Sopenharmony_ci		r = put_user(vcpu->arch.sie_block->gbea,
34728c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34738c2ecf20Sopenharmony_ci		break;
34748c2ecf20Sopenharmony_ci	default:
34758c2ecf20Sopenharmony_ci		break;
34768c2ecf20Sopenharmony_ci	}
34778c2ecf20Sopenharmony_ci
34788c2ecf20Sopenharmony_ci	return r;
34798c2ecf20Sopenharmony_ci}
34808c2ecf20Sopenharmony_ci
34818c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
34828c2ecf20Sopenharmony_ci					   struct kvm_one_reg *reg)
34838c2ecf20Sopenharmony_ci{
34848c2ecf20Sopenharmony_ci	int r = -EINVAL;
34858c2ecf20Sopenharmony_ci	__u64 val;
34868c2ecf20Sopenharmony_ci
34878c2ecf20Sopenharmony_ci	switch (reg->id) {
34888c2ecf20Sopenharmony_ci	case KVM_REG_S390_TODPR:
34898c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.sie_block->todpr,
34908c2ecf20Sopenharmony_ci			     (u32 __user *)reg->addr);
34918c2ecf20Sopenharmony_ci		break;
34928c2ecf20Sopenharmony_ci	case KVM_REG_S390_EPOCHDIFF:
34938c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.sie_block->epoch,
34948c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
34958c2ecf20Sopenharmony_ci		break;
34968c2ecf20Sopenharmony_ci	case KVM_REG_S390_CPU_TIMER:
34978c2ecf20Sopenharmony_ci		r = get_user(val, (u64 __user *)reg->addr);
34988c2ecf20Sopenharmony_ci		if (!r)
34998c2ecf20Sopenharmony_ci			kvm_s390_set_cpu_timer(vcpu, val);
35008c2ecf20Sopenharmony_ci		break;
35018c2ecf20Sopenharmony_ci	case KVM_REG_S390_CLOCK_COMP:
35028c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.sie_block->ckc,
35038c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35048c2ecf20Sopenharmony_ci		break;
35058c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFTOKEN:
35068c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.pfault_token,
35078c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35088c2ecf20Sopenharmony_ci		if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
35098c2ecf20Sopenharmony_ci			kvm_clear_async_pf_completion_queue(vcpu);
35108c2ecf20Sopenharmony_ci		break;
35118c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFCOMPARE:
35128c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.pfault_compare,
35138c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35148c2ecf20Sopenharmony_ci		break;
35158c2ecf20Sopenharmony_ci	case KVM_REG_S390_PFSELECT:
35168c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.pfault_select,
35178c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35188c2ecf20Sopenharmony_ci		break;
35198c2ecf20Sopenharmony_ci	case KVM_REG_S390_PP:
35208c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.sie_block->pp,
35218c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35228c2ecf20Sopenharmony_ci		break;
35238c2ecf20Sopenharmony_ci	case KVM_REG_S390_GBEA:
35248c2ecf20Sopenharmony_ci		r = get_user(vcpu->arch.sie_block->gbea,
35258c2ecf20Sopenharmony_ci			     (u64 __user *)reg->addr);
35268c2ecf20Sopenharmony_ci		break;
35278c2ecf20Sopenharmony_ci	default:
35288c2ecf20Sopenharmony_ci		break;
35298c2ecf20Sopenharmony_ci	}
35308c2ecf20Sopenharmony_ci
35318c2ecf20Sopenharmony_ci	return r;
35328c2ecf20Sopenharmony_ci}
35338c2ecf20Sopenharmony_ci
35348c2ecf20Sopenharmony_cistatic void kvm_arch_vcpu_ioctl_normal_reset(struct kvm_vcpu *vcpu)
35358c2ecf20Sopenharmony_ci{
35368c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_RI;
35378c2ecf20Sopenharmony_ci	vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
35388c2ecf20Sopenharmony_ci	memset(vcpu->run->s.regs.riccb, 0, sizeof(vcpu->run->s.regs.riccb));
35398c2ecf20Sopenharmony_ci
35408c2ecf20Sopenharmony_ci	kvm_clear_async_pf_completion_queue(vcpu);
35418c2ecf20Sopenharmony_ci	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
35428c2ecf20Sopenharmony_ci		kvm_s390_vcpu_stop(vcpu);
35438c2ecf20Sopenharmony_ci	kvm_s390_clear_local_irqs(vcpu);
35448c2ecf20Sopenharmony_ci}
35458c2ecf20Sopenharmony_ci
35468c2ecf20Sopenharmony_cistatic void kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
35478c2ecf20Sopenharmony_ci{
35488c2ecf20Sopenharmony_ci	/* Initial reset is a superset of the normal reset */
35498c2ecf20Sopenharmony_ci	kvm_arch_vcpu_ioctl_normal_reset(vcpu);
35508c2ecf20Sopenharmony_ci
35518c2ecf20Sopenharmony_ci	/*
35528c2ecf20Sopenharmony_ci	 * This equals initial cpu reset in pop, but we don't switch to ESA.
35538c2ecf20Sopenharmony_ci	 * We do not only reset the internal data, but also ...
35548c2ecf20Sopenharmony_ci	 */
35558c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.mask = 0;
35568c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.addr = 0;
35578c2ecf20Sopenharmony_ci	kvm_s390_set_prefix(vcpu, 0);
35588c2ecf20Sopenharmony_ci	kvm_s390_set_cpu_timer(vcpu, 0);
35598c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->ckc = 0;
35608c2ecf20Sopenharmony_ci	memset(vcpu->arch.sie_block->gcr, 0, sizeof(vcpu->arch.sie_block->gcr));
35618c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gcr[0] = CR0_INITIAL_MASK;
35628c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gcr[14] = CR14_INITIAL_MASK;
35638c2ecf20Sopenharmony_ci
35648c2ecf20Sopenharmony_ci	/* ... the data in sync regs */
35658c2ecf20Sopenharmony_ci	memset(vcpu->run->s.regs.crs, 0, sizeof(vcpu->run->s.regs.crs));
35668c2ecf20Sopenharmony_ci	vcpu->run->s.regs.ckc = 0;
35678c2ecf20Sopenharmony_ci	vcpu->run->s.regs.crs[0] = CR0_INITIAL_MASK;
35688c2ecf20Sopenharmony_ci	vcpu->run->s.regs.crs[14] = CR14_INITIAL_MASK;
35698c2ecf20Sopenharmony_ci	vcpu->run->psw_addr = 0;
35708c2ecf20Sopenharmony_ci	vcpu->run->psw_mask = 0;
35718c2ecf20Sopenharmony_ci	vcpu->run->s.regs.todpr = 0;
35728c2ecf20Sopenharmony_ci	vcpu->run->s.regs.cputm = 0;
35738c2ecf20Sopenharmony_ci	vcpu->run->s.regs.ckc = 0;
35748c2ecf20Sopenharmony_ci	vcpu->run->s.regs.pp = 0;
35758c2ecf20Sopenharmony_ci	vcpu->run->s.regs.gbea = 1;
35768c2ecf20Sopenharmony_ci	vcpu->run->s.regs.fpc = 0;
35778c2ecf20Sopenharmony_ci	/*
35788c2ecf20Sopenharmony_ci	 * Do not reset these registers in the protected case, as some of
35798c2ecf20Sopenharmony_ci	 * them are overlayed and they are not accessible in this case
35808c2ecf20Sopenharmony_ci	 * anyway.
35818c2ecf20Sopenharmony_ci	 */
35828c2ecf20Sopenharmony_ci	if (!kvm_s390_pv_cpu_is_protected(vcpu)) {
35838c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gbea = 1;
35848c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->pp = 0;
35858c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
35868c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->todpr = 0;
35878c2ecf20Sopenharmony_ci	}
35888c2ecf20Sopenharmony_ci}
35898c2ecf20Sopenharmony_ci
35908c2ecf20Sopenharmony_cistatic void kvm_arch_vcpu_ioctl_clear_reset(struct kvm_vcpu *vcpu)
35918c2ecf20Sopenharmony_ci{
35928c2ecf20Sopenharmony_ci	struct kvm_sync_regs *regs = &vcpu->run->s.regs;
35938c2ecf20Sopenharmony_ci
35948c2ecf20Sopenharmony_ci	/* Clear reset is a superset of the initial reset */
35958c2ecf20Sopenharmony_ci	kvm_arch_vcpu_ioctl_initial_reset(vcpu);
35968c2ecf20Sopenharmony_ci
35978c2ecf20Sopenharmony_ci	memset(&regs->gprs, 0, sizeof(regs->gprs));
35988c2ecf20Sopenharmony_ci	memset(&regs->vrs, 0, sizeof(regs->vrs));
35998c2ecf20Sopenharmony_ci	memset(&regs->acrs, 0, sizeof(regs->acrs));
36008c2ecf20Sopenharmony_ci	memset(&regs->gscb, 0, sizeof(regs->gscb));
36018c2ecf20Sopenharmony_ci
36028c2ecf20Sopenharmony_ci	regs->etoken = 0;
36038c2ecf20Sopenharmony_ci	regs->etoken_extension = 0;
36048c2ecf20Sopenharmony_ci}
36058c2ecf20Sopenharmony_ci
36068c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
36078c2ecf20Sopenharmony_ci{
36088c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36098c2ecf20Sopenharmony_ci	memcpy(&vcpu->run->s.regs.gprs, &regs->gprs, sizeof(regs->gprs));
36108c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36118c2ecf20Sopenharmony_ci	return 0;
36128c2ecf20Sopenharmony_ci}
36138c2ecf20Sopenharmony_ci
36148c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
36158c2ecf20Sopenharmony_ci{
36168c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36178c2ecf20Sopenharmony_ci	memcpy(&regs->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
36188c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36198c2ecf20Sopenharmony_ci	return 0;
36208c2ecf20Sopenharmony_ci}
36218c2ecf20Sopenharmony_ci
36228c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
36238c2ecf20Sopenharmony_ci				  struct kvm_sregs *sregs)
36248c2ecf20Sopenharmony_ci{
36258c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci	memcpy(&vcpu->run->s.regs.acrs, &sregs->acrs, sizeof(sregs->acrs));
36288c2ecf20Sopenharmony_ci	memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
36298c2ecf20Sopenharmony_ci
36308c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36318c2ecf20Sopenharmony_ci	return 0;
36328c2ecf20Sopenharmony_ci}
36338c2ecf20Sopenharmony_ci
36348c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
36358c2ecf20Sopenharmony_ci				  struct kvm_sregs *sregs)
36368c2ecf20Sopenharmony_ci{
36378c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36388c2ecf20Sopenharmony_ci
36398c2ecf20Sopenharmony_ci	memcpy(&sregs->acrs, &vcpu->run->s.regs.acrs, sizeof(sregs->acrs));
36408c2ecf20Sopenharmony_ci	memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
36418c2ecf20Sopenharmony_ci
36428c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36438c2ecf20Sopenharmony_ci	return 0;
36448c2ecf20Sopenharmony_ci}
36458c2ecf20Sopenharmony_ci
36468c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
36478c2ecf20Sopenharmony_ci{
36488c2ecf20Sopenharmony_ci	int ret = 0;
36498c2ecf20Sopenharmony_ci
36508c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36518c2ecf20Sopenharmony_ci
36528c2ecf20Sopenharmony_ci	vcpu->run->s.regs.fpc = fpu->fpc;
36538c2ecf20Sopenharmony_ci	if (MACHINE_HAS_VX)
36548c2ecf20Sopenharmony_ci		convert_fp_to_vx((__vector128 *) vcpu->run->s.regs.vrs,
36558c2ecf20Sopenharmony_ci				 (freg_t *) fpu->fprs);
36568c2ecf20Sopenharmony_ci	else
36578c2ecf20Sopenharmony_ci		memcpy(vcpu->run->s.regs.fprs, &fpu->fprs, sizeof(fpu->fprs));
36588c2ecf20Sopenharmony_ci
36598c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36608c2ecf20Sopenharmony_ci	return ret;
36618c2ecf20Sopenharmony_ci}
36628c2ecf20Sopenharmony_ci
36638c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
36648c2ecf20Sopenharmony_ci{
36658c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci	/* make sure we have the latest values */
36688c2ecf20Sopenharmony_ci	save_fpu_regs();
36698c2ecf20Sopenharmony_ci	if (MACHINE_HAS_VX)
36708c2ecf20Sopenharmony_ci		convert_vx_to_fp((freg_t *) fpu->fprs,
36718c2ecf20Sopenharmony_ci				 (__vector128 *) vcpu->run->s.regs.vrs);
36728c2ecf20Sopenharmony_ci	else
36738c2ecf20Sopenharmony_ci		memcpy(fpu->fprs, vcpu->run->s.regs.fprs, sizeof(fpu->fprs));
36748c2ecf20Sopenharmony_ci	fpu->fpc = vcpu->run->s.regs.fpc;
36758c2ecf20Sopenharmony_ci
36768c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
36778c2ecf20Sopenharmony_ci	return 0;
36788c2ecf20Sopenharmony_ci}
36798c2ecf20Sopenharmony_ci
36808c2ecf20Sopenharmony_cistatic int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
36818c2ecf20Sopenharmony_ci{
36828c2ecf20Sopenharmony_ci	int rc = 0;
36838c2ecf20Sopenharmony_ci
36848c2ecf20Sopenharmony_ci	if (!is_vcpu_stopped(vcpu))
36858c2ecf20Sopenharmony_ci		rc = -EBUSY;
36868c2ecf20Sopenharmony_ci	else {
36878c2ecf20Sopenharmony_ci		vcpu->run->psw_mask = psw.mask;
36888c2ecf20Sopenharmony_ci		vcpu->run->psw_addr = psw.addr;
36898c2ecf20Sopenharmony_ci	}
36908c2ecf20Sopenharmony_ci	return rc;
36918c2ecf20Sopenharmony_ci}
36928c2ecf20Sopenharmony_ci
36938c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
36948c2ecf20Sopenharmony_ci				  struct kvm_translation *tr)
36958c2ecf20Sopenharmony_ci{
36968c2ecf20Sopenharmony_ci	return -EINVAL; /* not implemented yet */
36978c2ecf20Sopenharmony_ci}
36988c2ecf20Sopenharmony_ci
36998c2ecf20Sopenharmony_ci#define VALID_GUESTDBG_FLAGS (KVM_GUESTDBG_SINGLESTEP | \
37008c2ecf20Sopenharmony_ci			      KVM_GUESTDBG_USE_HW_BP | \
37018c2ecf20Sopenharmony_ci			      KVM_GUESTDBG_ENABLE)
37028c2ecf20Sopenharmony_ci
37038c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
37048c2ecf20Sopenharmony_ci					struct kvm_guest_debug *dbg)
37058c2ecf20Sopenharmony_ci{
37068c2ecf20Sopenharmony_ci	int rc = 0;
37078c2ecf20Sopenharmony_ci
37088c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
37098c2ecf20Sopenharmony_ci
37108c2ecf20Sopenharmony_ci	vcpu->guest_debug = 0;
37118c2ecf20Sopenharmony_ci	kvm_s390_clear_bp_data(vcpu);
37128c2ecf20Sopenharmony_ci
37138c2ecf20Sopenharmony_ci	if (dbg->control & ~VALID_GUESTDBG_FLAGS) {
37148c2ecf20Sopenharmony_ci		rc = -EINVAL;
37158c2ecf20Sopenharmony_ci		goto out;
37168c2ecf20Sopenharmony_ci	}
37178c2ecf20Sopenharmony_ci	if (!sclp.has_gpere) {
37188c2ecf20Sopenharmony_ci		rc = -EINVAL;
37198c2ecf20Sopenharmony_ci		goto out;
37208c2ecf20Sopenharmony_ci	}
37218c2ecf20Sopenharmony_ci
37228c2ecf20Sopenharmony_ci	if (dbg->control & KVM_GUESTDBG_ENABLE) {
37238c2ecf20Sopenharmony_ci		vcpu->guest_debug = dbg->control;
37248c2ecf20Sopenharmony_ci		/* enforce guest PER */
37258c2ecf20Sopenharmony_ci		kvm_s390_set_cpuflags(vcpu, CPUSTAT_P);
37268c2ecf20Sopenharmony_ci
37278c2ecf20Sopenharmony_ci		if (dbg->control & KVM_GUESTDBG_USE_HW_BP)
37288c2ecf20Sopenharmony_ci			rc = kvm_s390_import_bp_data(vcpu, dbg);
37298c2ecf20Sopenharmony_ci	} else {
37308c2ecf20Sopenharmony_ci		kvm_s390_clear_cpuflags(vcpu, CPUSTAT_P);
37318c2ecf20Sopenharmony_ci		vcpu->arch.guestdbg.last_bp = 0;
37328c2ecf20Sopenharmony_ci	}
37338c2ecf20Sopenharmony_ci
37348c2ecf20Sopenharmony_ci	if (rc) {
37358c2ecf20Sopenharmony_ci		vcpu->guest_debug = 0;
37368c2ecf20Sopenharmony_ci		kvm_s390_clear_bp_data(vcpu);
37378c2ecf20Sopenharmony_ci		kvm_s390_clear_cpuflags(vcpu, CPUSTAT_P);
37388c2ecf20Sopenharmony_ci	}
37398c2ecf20Sopenharmony_ci
37408c2ecf20Sopenharmony_ciout:
37418c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
37428c2ecf20Sopenharmony_ci	return rc;
37438c2ecf20Sopenharmony_ci}
37448c2ecf20Sopenharmony_ci
37458c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
37468c2ecf20Sopenharmony_ci				    struct kvm_mp_state *mp_state)
37478c2ecf20Sopenharmony_ci{
37488c2ecf20Sopenharmony_ci	int ret;
37498c2ecf20Sopenharmony_ci
37508c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
37518c2ecf20Sopenharmony_ci
37528c2ecf20Sopenharmony_ci	/* CHECK_STOP and LOAD are not supported yet */
37538c2ecf20Sopenharmony_ci	ret = is_vcpu_stopped(vcpu) ? KVM_MP_STATE_STOPPED :
37548c2ecf20Sopenharmony_ci				      KVM_MP_STATE_OPERATING;
37558c2ecf20Sopenharmony_ci
37568c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
37578c2ecf20Sopenharmony_ci	return ret;
37588c2ecf20Sopenharmony_ci}
37598c2ecf20Sopenharmony_ci
37608c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
37618c2ecf20Sopenharmony_ci				    struct kvm_mp_state *mp_state)
37628c2ecf20Sopenharmony_ci{
37638c2ecf20Sopenharmony_ci	int rc = 0;
37648c2ecf20Sopenharmony_ci
37658c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
37668c2ecf20Sopenharmony_ci
37678c2ecf20Sopenharmony_ci	/* user space knows about this interface - let it control the state */
37688c2ecf20Sopenharmony_ci	vcpu->kvm->arch.user_cpu_state_ctrl = 1;
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci	switch (mp_state->mp_state) {
37718c2ecf20Sopenharmony_ci	case KVM_MP_STATE_STOPPED:
37728c2ecf20Sopenharmony_ci		rc = kvm_s390_vcpu_stop(vcpu);
37738c2ecf20Sopenharmony_ci		break;
37748c2ecf20Sopenharmony_ci	case KVM_MP_STATE_OPERATING:
37758c2ecf20Sopenharmony_ci		rc = kvm_s390_vcpu_start(vcpu);
37768c2ecf20Sopenharmony_ci		break;
37778c2ecf20Sopenharmony_ci	case KVM_MP_STATE_LOAD:
37788c2ecf20Sopenharmony_ci		if (!kvm_s390_pv_cpu_is_protected(vcpu)) {
37798c2ecf20Sopenharmony_ci			rc = -ENXIO;
37808c2ecf20Sopenharmony_ci			break;
37818c2ecf20Sopenharmony_ci		}
37828c2ecf20Sopenharmony_ci		rc = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_OPR_LOAD);
37838c2ecf20Sopenharmony_ci		break;
37848c2ecf20Sopenharmony_ci	case KVM_MP_STATE_CHECK_STOP:
37858c2ecf20Sopenharmony_ci		fallthrough;	/* CHECK_STOP and LOAD are not supported yet */
37868c2ecf20Sopenharmony_ci	default:
37878c2ecf20Sopenharmony_ci		rc = -ENXIO;
37888c2ecf20Sopenharmony_ci	}
37898c2ecf20Sopenharmony_ci
37908c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
37918c2ecf20Sopenharmony_ci	return rc;
37928c2ecf20Sopenharmony_ci}
37938c2ecf20Sopenharmony_ci
37948c2ecf20Sopenharmony_cistatic bool ibs_enabled(struct kvm_vcpu *vcpu)
37958c2ecf20Sopenharmony_ci{
37968c2ecf20Sopenharmony_ci	return kvm_s390_test_cpuflags(vcpu, CPUSTAT_IBS);
37978c2ecf20Sopenharmony_ci}
37988c2ecf20Sopenharmony_ci
37998c2ecf20Sopenharmony_cistatic int kvm_s390_handle_requests(struct kvm_vcpu *vcpu)
38008c2ecf20Sopenharmony_ci{
38018c2ecf20Sopenharmony_ciretry:
38028c2ecf20Sopenharmony_ci	kvm_s390_vcpu_request_handled(vcpu);
38038c2ecf20Sopenharmony_ci	if (!kvm_request_pending(vcpu))
38048c2ecf20Sopenharmony_ci		return 0;
38058c2ecf20Sopenharmony_ci	/*
38068c2ecf20Sopenharmony_ci	 * We use MMU_RELOAD just to re-arm the ipte notifier for the
38078c2ecf20Sopenharmony_ci	 * guest prefix page. gmap_mprotect_notify will wait on the ptl lock.
38088c2ecf20Sopenharmony_ci	 * This ensures that the ipte instruction for this request has
38098c2ecf20Sopenharmony_ci	 * already finished. We might race against a second unmapper that
38108c2ecf20Sopenharmony_ci	 * wants to set the blocking bit. Lets just retry the request loop.
38118c2ecf20Sopenharmony_ci	 */
38128c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_MMU_RELOAD, vcpu)) {
38138c2ecf20Sopenharmony_ci		int rc;
38148c2ecf20Sopenharmony_ci		rc = gmap_mprotect_notify(vcpu->arch.gmap,
38158c2ecf20Sopenharmony_ci					  kvm_s390_get_prefix(vcpu),
38168c2ecf20Sopenharmony_ci					  PAGE_SIZE * 2, PROT_WRITE);
38178c2ecf20Sopenharmony_ci		if (rc) {
38188c2ecf20Sopenharmony_ci			kvm_make_request(KVM_REQ_MMU_RELOAD, vcpu);
38198c2ecf20Sopenharmony_ci			return rc;
38208c2ecf20Sopenharmony_ci		}
38218c2ecf20Sopenharmony_ci		goto retry;
38228c2ecf20Sopenharmony_ci	}
38238c2ecf20Sopenharmony_ci
38248c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_TLB_FLUSH, vcpu)) {
38258c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ihcpu = 0xffff;
38268c2ecf20Sopenharmony_ci		goto retry;
38278c2ecf20Sopenharmony_ci	}
38288c2ecf20Sopenharmony_ci
38298c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu)) {
38308c2ecf20Sopenharmony_ci		if (!ibs_enabled(vcpu)) {
38318c2ecf20Sopenharmony_ci			trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 1);
38328c2ecf20Sopenharmony_ci			kvm_s390_set_cpuflags(vcpu, CPUSTAT_IBS);
38338c2ecf20Sopenharmony_ci		}
38348c2ecf20Sopenharmony_ci		goto retry;
38358c2ecf20Sopenharmony_ci	}
38368c2ecf20Sopenharmony_ci
38378c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu)) {
38388c2ecf20Sopenharmony_ci		if (ibs_enabled(vcpu)) {
38398c2ecf20Sopenharmony_ci			trace_kvm_s390_enable_disable_ibs(vcpu->vcpu_id, 0);
38408c2ecf20Sopenharmony_ci			kvm_s390_clear_cpuflags(vcpu, CPUSTAT_IBS);
38418c2ecf20Sopenharmony_ci		}
38428c2ecf20Sopenharmony_ci		goto retry;
38438c2ecf20Sopenharmony_ci	}
38448c2ecf20Sopenharmony_ci
38458c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_ICPT_OPEREXC, vcpu)) {
38468c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
38478c2ecf20Sopenharmony_ci		goto retry;
38488c2ecf20Sopenharmony_ci	}
38498c2ecf20Sopenharmony_ci
38508c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_START_MIGRATION, vcpu)) {
38518c2ecf20Sopenharmony_ci		/*
38528c2ecf20Sopenharmony_ci		 * Disable CMM virtualization; we will emulate the ESSA
38538c2ecf20Sopenharmony_ci		 * instruction manually, in order to provide additional
38548c2ecf20Sopenharmony_ci		 * functionalities needed for live migration.
38558c2ecf20Sopenharmony_ci		 */
38568c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb2 &= ~ECB2_CMMA;
38578c2ecf20Sopenharmony_ci		goto retry;
38588c2ecf20Sopenharmony_ci	}
38598c2ecf20Sopenharmony_ci
38608c2ecf20Sopenharmony_ci	if (kvm_check_request(KVM_REQ_STOP_MIGRATION, vcpu)) {
38618c2ecf20Sopenharmony_ci		/*
38628c2ecf20Sopenharmony_ci		 * Re-enable CMM virtualization if CMMA is available and
38638c2ecf20Sopenharmony_ci		 * CMM has been used.
38648c2ecf20Sopenharmony_ci		 */
38658c2ecf20Sopenharmony_ci		if ((vcpu->kvm->arch.use_cmma) &&
38668c2ecf20Sopenharmony_ci		    (vcpu->kvm->mm->context.uses_cmm))
38678c2ecf20Sopenharmony_ci			vcpu->arch.sie_block->ecb2 |= ECB2_CMMA;
38688c2ecf20Sopenharmony_ci		goto retry;
38698c2ecf20Sopenharmony_ci	}
38708c2ecf20Sopenharmony_ci
38718c2ecf20Sopenharmony_ci	/* nothing to do, just clear the request */
38728c2ecf20Sopenharmony_ci	kvm_clear_request(KVM_REQ_UNHALT, vcpu);
38738c2ecf20Sopenharmony_ci	/* we left the vsie handler, nothing to do, just clear the request */
38748c2ecf20Sopenharmony_ci	kvm_clear_request(KVM_REQ_VSIE_RESTART, vcpu);
38758c2ecf20Sopenharmony_ci
38768c2ecf20Sopenharmony_ci	return 0;
38778c2ecf20Sopenharmony_ci}
38788c2ecf20Sopenharmony_ci
38798c2ecf20Sopenharmony_cistatic void __kvm_s390_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
38808c2ecf20Sopenharmony_ci{
38818c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
38828c2ecf20Sopenharmony_ci	struct kvm_s390_tod_clock_ext htod;
38838c2ecf20Sopenharmony_ci	int i;
38848c2ecf20Sopenharmony_ci
38858c2ecf20Sopenharmony_ci	preempt_disable();
38868c2ecf20Sopenharmony_ci
38878c2ecf20Sopenharmony_ci	get_tod_clock_ext((char *)&htod);
38888c2ecf20Sopenharmony_ci
38898c2ecf20Sopenharmony_ci	kvm->arch.epoch = gtod->tod - htod.tod;
38908c2ecf20Sopenharmony_ci	kvm->arch.epdx = 0;
38918c2ecf20Sopenharmony_ci	if (test_kvm_facility(kvm, 139)) {
38928c2ecf20Sopenharmony_ci		kvm->arch.epdx = gtod->epoch_idx - htod.epoch_idx;
38938c2ecf20Sopenharmony_ci		if (kvm->arch.epoch > gtod->tod)
38948c2ecf20Sopenharmony_ci			kvm->arch.epdx -= 1;
38958c2ecf20Sopenharmony_ci	}
38968c2ecf20Sopenharmony_ci
38978c2ecf20Sopenharmony_ci	kvm_s390_vcpu_block_all(kvm);
38988c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
38998c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->epoch = kvm->arch.epoch;
39008c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->epdx  = kvm->arch.epdx;
39018c2ecf20Sopenharmony_ci	}
39028c2ecf20Sopenharmony_ci
39038c2ecf20Sopenharmony_ci	kvm_s390_vcpu_unblock_all(kvm);
39048c2ecf20Sopenharmony_ci	preempt_enable();
39058c2ecf20Sopenharmony_ci}
39068c2ecf20Sopenharmony_ci
39078c2ecf20Sopenharmony_ciint kvm_s390_try_set_tod_clock(struct kvm *kvm, const struct kvm_s390_vm_tod_clock *gtod)
39088c2ecf20Sopenharmony_ci{
39098c2ecf20Sopenharmony_ci	if (!mutex_trylock(&kvm->lock))
39108c2ecf20Sopenharmony_ci		return 0;
39118c2ecf20Sopenharmony_ci	__kvm_s390_set_tod_clock(kvm, gtod);
39128c2ecf20Sopenharmony_ci	mutex_unlock(&kvm->lock);
39138c2ecf20Sopenharmony_ci	return 1;
39148c2ecf20Sopenharmony_ci}
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci/**
39178c2ecf20Sopenharmony_ci * kvm_arch_fault_in_page - fault-in guest page if necessary
39188c2ecf20Sopenharmony_ci * @vcpu: The corresponding virtual cpu
39198c2ecf20Sopenharmony_ci * @gpa: Guest physical address
39208c2ecf20Sopenharmony_ci * @writable: Whether the page should be writable or not
39218c2ecf20Sopenharmony_ci *
39228c2ecf20Sopenharmony_ci * Make sure that a guest page has been faulted-in on the host.
39238c2ecf20Sopenharmony_ci *
39248c2ecf20Sopenharmony_ci * Return: Zero on success, negative error code otherwise.
39258c2ecf20Sopenharmony_ci */
39268c2ecf20Sopenharmony_cilong kvm_arch_fault_in_page(struct kvm_vcpu *vcpu, gpa_t gpa, int writable)
39278c2ecf20Sopenharmony_ci{
39288c2ecf20Sopenharmony_ci	return gmap_fault(vcpu->arch.gmap, gpa,
39298c2ecf20Sopenharmony_ci			  writable ? FAULT_FLAG_WRITE : 0);
39308c2ecf20Sopenharmony_ci}
39318c2ecf20Sopenharmony_ci
39328c2ecf20Sopenharmony_cistatic void __kvm_inject_pfault_token(struct kvm_vcpu *vcpu, bool start_token,
39338c2ecf20Sopenharmony_ci				      unsigned long token)
39348c2ecf20Sopenharmony_ci{
39358c2ecf20Sopenharmony_ci	struct kvm_s390_interrupt inti;
39368c2ecf20Sopenharmony_ci	struct kvm_s390_irq irq;
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci	if (start_token) {
39398c2ecf20Sopenharmony_ci		irq.u.ext.ext_params2 = token;
39408c2ecf20Sopenharmony_ci		irq.type = KVM_S390_INT_PFAULT_INIT;
39418c2ecf20Sopenharmony_ci		WARN_ON_ONCE(kvm_s390_inject_vcpu(vcpu, &irq));
39428c2ecf20Sopenharmony_ci	} else {
39438c2ecf20Sopenharmony_ci		inti.type = KVM_S390_INT_PFAULT_DONE;
39448c2ecf20Sopenharmony_ci		inti.parm64 = token;
39458c2ecf20Sopenharmony_ci		WARN_ON_ONCE(kvm_s390_inject_vm(vcpu->kvm, &inti));
39468c2ecf20Sopenharmony_ci	}
39478c2ecf20Sopenharmony_ci}
39488c2ecf20Sopenharmony_ci
39498c2ecf20Sopenharmony_cibool kvm_arch_async_page_not_present(struct kvm_vcpu *vcpu,
39508c2ecf20Sopenharmony_ci				     struct kvm_async_pf *work)
39518c2ecf20Sopenharmony_ci{
39528c2ecf20Sopenharmony_ci	trace_kvm_s390_pfault_init(vcpu, work->arch.pfault_token);
39538c2ecf20Sopenharmony_ci	__kvm_inject_pfault_token(vcpu, true, work->arch.pfault_token);
39548c2ecf20Sopenharmony_ci
39558c2ecf20Sopenharmony_ci	return true;
39568c2ecf20Sopenharmony_ci}
39578c2ecf20Sopenharmony_ci
39588c2ecf20Sopenharmony_civoid kvm_arch_async_page_present(struct kvm_vcpu *vcpu,
39598c2ecf20Sopenharmony_ci				 struct kvm_async_pf *work)
39608c2ecf20Sopenharmony_ci{
39618c2ecf20Sopenharmony_ci	trace_kvm_s390_pfault_done(vcpu, work->arch.pfault_token);
39628c2ecf20Sopenharmony_ci	__kvm_inject_pfault_token(vcpu, false, work->arch.pfault_token);
39638c2ecf20Sopenharmony_ci}
39648c2ecf20Sopenharmony_ci
39658c2ecf20Sopenharmony_civoid kvm_arch_async_page_ready(struct kvm_vcpu *vcpu,
39668c2ecf20Sopenharmony_ci			       struct kvm_async_pf *work)
39678c2ecf20Sopenharmony_ci{
39688c2ecf20Sopenharmony_ci	/* s390 will always inject the page directly */
39698c2ecf20Sopenharmony_ci}
39708c2ecf20Sopenharmony_ci
39718c2ecf20Sopenharmony_cibool kvm_arch_can_dequeue_async_page_present(struct kvm_vcpu *vcpu)
39728c2ecf20Sopenharmony_ci{
39738c2ecf20Sopenharmony_ci	/*
39748c2ecf20Sopenharmony_ci	 * s390 will always inject the page directly,
39758c2ecf20Sopenharmony_ci	 * but we still want check_async_completion to cleanup
39768c2ecf20Sopenharmony_ci	 */
39778c2ecf20Sopenharmony_ci	return true;
39788c2ecf20Sopenharmony_ci}
39798c2ecf20Sopenharmony_ci
39808c2ecf20Sopenharmony_cistatic bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
39818c2ecf20Sopenharmony_ci{
39828c2ecf20Sopenharmony_ci	hva_t hva;
39838c2ecf20Sopenharmony_ci	struct kvm_arch_async_pf arch;
39848c2ecf20Sopenharmony_ci
39858c2ecf20Sopenharmony_ci	if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
39868c2ecf20Sopenharmony_ci		return false;
39878c2ecf20Sopenharmony_ci	if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) !=
39888c2ecf20Sopenharmony_ci	    vcpu->arch.pfault_compare)
39898c2ecf20Sopenharmony_ci		return false;
39908c2ecf20Sopenharmony_ci	if (psw_extint_disabled(vcpu))
39918c2ecf20Sopenharmony_ci		return false;
39928c2ecf20Sopenharmony_ci	if (kvm_s390_vcpu_has_irq(vcpu, 0))
39938c2ecf20Sopenharmony_ci		return false;
39948c2ecf20Sopenharmony_ci	if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK))
39958c2ecf20Sopenharmony_ci		return false;
39968c2ecf20Sopenharmony_ci	if (!vcpu->arch.gmap->pfault_enabled)
39978c2ecf20Sopenharmony_ci		return false;
39988c2ecf20Sopenharmony_ci
39998c2ecf20Sopenharmony_ci	hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr));
40008c2ecf20Sopenharmony_ci	hva += current->thread.gmap_addr & ~PAGE_MASK;
40018c2ecf20Sopenharmony_ci	if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8))
40028c2ecf20Sopenharmony_ci		return false;
40038c2ecf20Sopenharmony_ci
40048c2ecf20Sopenharmony_ci	return kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch);
40058c2ecf20Sopenharmony_ci}
40068c2ecf20Sopenharmony_ci
40078c2ecf20Sopenharmony_cistatic int vcpu_pre_run(struct kvm_vcpu *vcpu)
40088c2ecf20Sopenharmony_ci{
40098c2ecf20Sopenharmony_ci	int rc, cpuflags;
40108c2ecf20Sopenharmony_ci
40118c2ecf20Sopenharmony_ci	/*
40128c2ecf20Sopenharmony_ci	 * On s390 notifications for arriving pages will be delivered directly
40138c2ecf20Sopenharmony_ci	 * to the guest but the house keeping for completed pfaults is
40148c2ecf20Sopenharmony_ci	 * handled outside the worker.
40158c2ecf20Sopenharmony_ci	 */
40168c2ecf20Sopenharmony_ci	kvm_check_async_pf_completion(vcpu);
40178c2ecf20Sopenharmony_ci
40188c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gg14 = vcpu->run->s.regs.gprs[14];
40198c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gg15 = vcpu->run->s.regs.gprs[15];
40208c2ecf20Sopenharmony_ci
40218c2ecf20Sopenharmony_ci	if (need_resched())
40228c2ecf20Sopenharmony_ci		schedule();
40238c2ecf20Sopenharmony_ci
40248c2ecf20Sopenharmony_ci	if (!kvm_is_ucontrol(vcpu->kvm)) {
40258c2ecf20Sopenharmony_ci		rc = kvm_s390_deliver_pending_interrupts(vcpu);
40268c2ecf20Sopenharmony_ci		if (rc)
40278c2ecf20Sopenharmony_ci			return rc;
40288c2ecf20Sopenharmony_ci	}
40298c2ecf20Sopenharmony_ci
40308c2ecf20Sopenharmony_ci	rc = kvm_s390_handle_requests(vcpu);
40318c2ecf20Sopenharmony_ci	if (rc)
40328c2ecf20Sopenharmony_ci		return rc;
40338c2ecf20Sopenharmony_ci
40348c2ecf20Sopenharmony_ci	if (guestdbg_enabled(vcpu)) {
40358c2ecf20Sopenharmony_ci		kvm_s390_backup_guest_per_regs(vcpu);
40368c2ecf20Sopenharmony_ci		kvm_s390_patch_guest_per_regs(vcpu);
40378c2ecf20Sopenharmony_ci	}
40388c2ecf20Sopenharmony_ci
40398c2ecf20Sopenharmony_ci	clear_bit(kvm_vcpu_get_idx(vcpu), vcpu->kvm->arch.gisa_int.kicked_mask);
40408c2ecf20Sopenharmony_ci
40418c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->icptcode = 0;
40428c2ecf20Sopenharmony_ci	cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
40438c2ecf20Sopenharmony_ci	VCPU_EVENT(vcpu, 6, "entering sie flags %x", cpuflags);
40448c2ecf20Sopenharmony_ci	trace_kvm_s390_sie_enter(vcpu, cpuflags);
40458c2ecf20Sopenharmony_ci
40468c2ecf20Sopenharmony_ci	return 0;
40478c2ecf20Sopenharmony_ci}
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_cistatic int vcpu_post_run_fault_in_sie(struct kvm_vcpu *vcpu)
40508c2ecf20Sopenharmony_ci{
40518c2ecf20Sopenharmony_ci	struct kvm_s390_pgm_info pgm_info = {
40528c2ecf20Sopenharmony_ci		.code = PGM_ADDRESSING,
40538c2ecf20Sopenharmony_ci	};
40548c2ecf20Sopenharmony_ci	u8 opcode, ilen;
40558c2ecf20Sopenharmony_ci	int rc;
40568c2ecf20Sopenharmony_ci
40578c2ecf20Sopenharmony_ci	VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
40588c2ecf20Sopenharmony_ci	trace_kvm_s390_sie_fault(vcpu);
40598c2ecf20Sopenharmony_ci
40608c2ecf20Sopenharmony_ci	/*
40618c2ecf20Sopenharmony_ci	 * We want to inject an addressing exception, which is defined as a
40628c2ecf20Sopenharmony_ci	 * suppressing or terminating exception. However, since we came here
40638c2ecf20Sopenharmony_ci	 * by a DAT access exception, the PSW still points to the faulting
40648c2ecf20Sopenharmony_ci	 * instruction since DAT exceptions are nullifying. So we've got
40658c2ecf20Sopenharmony_ci	 * to look up the current opcode to get the length of the instruction
40668c2ecf20Sopenharmony_ci	 * to be able to forward the PSW.
40678c2ecf20Sopenharmony_ci	 */
40688c2ecf20Sopenharmony_ci	rc = read_guest_instr(vcpu, vcpu->arch.sie_block->gpsw.addr, &opcode, 1);
40698c2ecf20Sopenharmony_ci	ilen = insn_length(opcode);
40708c2ecf20Sopenharmony_ci	if (rc < 0) {
40718c2ecf20Sopenharmony_ci		return rc;
40728c2ecf20Sopenharmony_ci	} else if (rc) {
40738c2ecf20Sopenharmony_ci		/* Instruction-Fetching Exceptions - we can't detect the ilen.
40748c2ecf20Sopenharmony_ci		 * Forward by arbitrary ilc, injection will take care of
40758c2ecf20Sopenharmony_ci		 * nullification if necessary.
40768c2ecf20Sopenharmony_ci		 */
40778c2ecf20Sopenharmony_ci		pgm_info = vcpu->arch.pgm;
40788c2ecf20Sopenharmony_ci		ilen = 4;
40798c2ecf20Sopenharmony_ci	}
40808c2ecf20Sopenharmony_ci	pgm_info.flags = ilen | KVM_S390_PGM_FLAGS_ILC_VALID;
40818c2ecf20Sopenharmony_ci	kvm_s390_forward_psw(vcpu, ilen);
40828c2ecf20Sopenharmony_ci	return kvm_s390_inject_prog_irq(vcpu, &pgm_info);
40838c2ecf20Sopenharmony_ci}
40848c2ecf20Sopenharmony_ci
40858c2ecf20Sopenharmony_cistatic int vcpu_post_run(struct kvm_vcpu *vcpu, int exit_reason)
40868c2ecf20Sopenharmony_ci{
40878c2ecf20Sopenharmony_ci	struct mcck_volatile_info *mcck_info;
40888c2ecf20Sopenharmony_ci	struct sie_page *sie_page;
40898c2ecf20Sopenharmony_ci
40908c2ecf20Sopenharmony_ci	VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
40918c2ecf20Sopenharmony_ci		   vcpu->arch.sie_block->icptcode);
40928c2ecf20Sopenharmony_ci	trace_kvm_s390_sie_exit(vcpu, vcpu->arch.sie_block->icptcode);
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	if (guestdbg_enabled(vcpu))
40958c2ecf20Sopenharmony_ci		kvm_s390_restore_guest_per_regs(vcpu);
40968c2ecf20Sopenharmony_ci
40978c2ecf20Sopenharmony_ci	vcpu->run->s.regs.gprs[14] = vcpu->arch.sie_block->gg14;
40988c2ecf20Sopenharmony_ci	vcpu->run->s.regs.gprs[15] = vcpu->arch.sie_block->gg15;
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci	if (exit_reason == -EINTR) {
41018c2ecf20Sopenharmony_ci		VCPU_EVENT(vcpu, 3, "%s", "machine check");
41028c2ecf20Sopenharmony_ci		sie_page = container_of(vcpu->arch.sie_block,
41038c2ecf20Sopenharmony_ci					struct sie_page, sie_block);
41048c2ecf20Sopenharmony_ci		mcck_info = &sie_page->mcck_info;
41058c2ecf20Sopenharmony_ci		kvm_s390_reinject_machine_check(vcpu, mcck_info);
41068c2ecf20Sopenharmony_ci		return 0;
41078c2ecf20Sopenharmony_ci	}
41088c2ecf20Sopenharmony_ci
41098c2ecf20Sopenharmony_ci	if (vcpu->arch.sie_block->icptcode > 0) {
41108c2ecf20Sopenharmony_ci		int rc = kvm_handle_sie_intercept(vcpu);
41118c2ecf20Sopenharmony_ci
41128c2ecf20Sopenharmony_ci		if (rc != -EOPNOTSUPP)
41138c2ecf20Sopenharmony_ci			return rc;
41148c2ecf20Sopenharmony_ci		vcpu->run->exit_reason = KVM_EXIT_S390_SIEIC;
41158c2ecf20Sopenharmony_ci		vcpu->run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
41168c2ecf20Sopenharmony_ci		vcpu->run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
41178c2ecf20Sopenharmony_ci		vcpu->run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
41188c2ecf20Sopenharmony_ci		return -EREMOTE;
41198c2ecf20Sopenharmony_ci	} else if (exit_reason != -EFAULT) {
41208c2ecf20Sopenharmony_ci		vcpu->stat.exit_null++;
41218c2ecf20Sopenharmony_ci		return 0;
41228c2ecf20Sopenharmony_ci	} else if (kvm_is_ucontrol(vcpu->kvm)) {
41238c2ecf20Sopenharmony_ci		vcpu->run->exit_reason = KVM_EXIT_S390_UCONTROL;
41248c2ecf20Sopenharmony_ci		vcpu->run->s390_ucontrol.trans_exc_code =
41258c2ecf20Sopenharmony_ci						current->thread.gmap_addr;
41268c2ecf20Sopenharmony_ci		vcpu->run->s390_ucontrol.pgm_code = 0x10;
41278c2ecf20Sopenharmony_ci		return -EREMOTE;
41288c2ecf20Sopenharmony_ci	} else if (current->thread.gmap_pfault) {
41298c2ecf20Sopenharmony_ci		trace_kvm_s390_major_guest_pfault(vcpu);
41308c2ecf20Sopenharmony_ci		current->thread.gmap_pfault = 0;
41318c2ecf20Sopenharmony_ci		if (kvm_arch_setup_async_pf(vcpu))
41328c2ecf20Sopenharmony_ci			return 0;
41338c2ecf20Sopenharmony_ci		return kvm_arch_fault_in_page(vcpu, current->thread.gmap_addr, 1);
41348c2ecf20Sopenharmony_ci	}
41358c2ecf20Sopenharmony_ci	return vcpu_post_run_fault_in_sie(vcpu);
41368c2ecf20Sopenharmony_ci}
41378c2ecf20Sopenharmony_ci
41388c2ecf20Sopenharmony_ci#define PSW_INT_MASK (PSW_MASK_EXT | PSW_MASK_IO | PSW_MASK_MCHECK)
41398c2ecf20Sopenharmony_cistatic int __vcpu_run(struct kvm_vcpu *vcpu)
41408c2ecf20Sopenharmony_ci{
41418c2ecf20Sopenharmony_ci	int rc, exit_reason;
41428c2ecf20Sopenharmony_ci	struct sie_page *sie_page = (struct sie_page *)vcpu->arch.sie_block;
41438c2ecf20Sopenharmony_ci
41448c2ecf20Sopenharmony_ci	/*
41458c2ecf20Sopenharmony_ci	 * We try to hold kvm->srcu during most of vcpu_run (except when run-
41468c2ecf20Sopenharmony_ci	 * ning the guest), so that memslots (and other stuff) are protected
41478c2ecf20Sopenharmony_ci	 */
41488c2ecf20Sopenharmony_ci	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
41498c2ecf20Sopenharmony_ci
41508c2ecf20Sopenharmony_ci	do {
41518c2ecf20Sopenharmony_ci		rc = vcpu_pre_run(vcpu);
41528c2ecf20Sopenharmony_ci		if (rc)
41538c2ecf20Sopenharmony_ci			break;
41548c2ecf20Sopenharmony_ci
41558c2ecf20Sopenharmony_ci		srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
41568c2ecf20Sopenharmony_ci		/*
41578c2ecf20Sopenharmony_ci		 * As PF_VCPU will be used in fault handler, between
41588c2ecf20Sopenharmony_ci		 * guest_enter and guest_exit should be no uaccess.
41598c2ecf20Sopenharmony_ci		 */
41608c2ecf20Sopenharmony_ci		local_irq_disable();
41618c2ecf20Sopenharmony_ci		guest_enter_irqoff();
41628c2ecf20Sopenharmony_ci		__disable_cpu_timer_accounting(vcpu);
41638c2ecf20Sopenharmony_ci		local_irq_enable();
41648c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
41658c2ecf20Sopenharmony_ci			memcpy(sie_page->pv_grregs,
41668c2ecf20Sopenharmony_ci			       vcpu->run->s.regs.gprs,
41678c2ecf20Sopenharmony_ci			       sizeof(sie_page->pv_grregs));
41688c2ecf20Sopenharmony_ci		}
41698c2ecf20Sopenharmony_ci		exit_reason = sie64a(vcpu->arch.sie_block,
41708c2ecf20Sopenharmony_ci				     vcpu->run->s.regs.gprs);
41718c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
41728c2ecf20Sopenharmony_ci			memcpy(vcpu->run->s.regs.gprs,
41738c2ecf20Sopenharmony_ci			       sie_page->pv_grregs,
41748c2ecf20Sopenharmony_ci			       sizeof(sie_page->pv_grregs));
41758c2ecf20Sopenharmony_ci			/*
41768c2ecf20Sopenharmony_ci			 * We're not allowed to inject interrupts on intercepts
41778c2ecf20Sopenharmony_ci			 * that leave the guest state in an "in-between" state
41788c2ecf20Sopenharmony_ci			 * where the next SIE entry will do a continuation.
41798c2ecf20Sopenharmony_ci			 * Fence interrupts in our "internal" PSW.
41808c2ecf20Sopenharmony_ci			 */
41818c2ecf20Sopenharmony_ci			if (vcpu->arch.sie_block->icptcode == ICPT_PV_INSTR ||
41828c2ecf20Sopenharmony_ci			    vcpu->arch.sie_block->icptcode == ICPT_PV_PREF) {
41838c2ecf20Sopenharmony_ci				vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK;
41848c2ecf20Sopenharmony_ci			}
41858c2ecf20Sopenharmony_ci		}
41868c2ecf20Sopenharmony_ci		local_irq_disable();
41878c2ecf20Sopenharmony_ci		__enable_cpu_timer_accounting(vcpu);
41888c2ecf20Sopenharmony_ci		guest_exit_irqoff();
41898c2ecf20Sopenharmony_ci		local_irq_enable();
41908c2ecf20Sopenharmony_ci		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
41918c2ecf20Sopenharmony_ci
41928c2ecf20Sopenharmony_ci		rc = vcpu_post_run(vcpu, exit_reason);
41938c2ecf20Sopenharmony_ci	} while (!signal_pending(current) && !guestdbg_exit_pending(vcpu) && !rc);
41948c2ecf20Sopenharmony_ci
41958c2ecf20Sopenharmony_ci	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
41968c2ecf20Sopenharmony_ci	return rc;
41978c2ecf20Sopenharmony_ci}
41988c2ecf20Sopenharmony_ci
41998c2ecf20Sopenharmony_cistatic void sync_regs_fmt2(struct kvm_vcpu *vcpu)
42008c2ecf20Sopenharmony_ci{
42018c2ecf20Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
42028c2ecf20Sopenharmony_ci	struct runtime_instr_cb *riccb;
42038c2ecf20Sopenharmony_ci	struct gs_cb *gscb;
42048c2ecf20Sopenharmony_ci
42058c2ecf20Sopenharmony_ci	riccb = (struct runtime_instr_cb *) &kvm_run->s.regs.riccb;
42068c2ecf20Sopenharmony_ci	gscb = (struct gs_cb *) &kvm_run->s.regs.gscb;
42078c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
42088c2ecf20Sopenharmony_ci	vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
42098c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
42108c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->todpr = kvm_run->s.regs.todpr;
42118c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->pp = kvm_run->s.regs.pp;
42128c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gbea = kvm_run->s.regs.gbea;
42138c2ecf20Sopenharmony_ci	}
42148c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_PFAULT) {
42158c2ecf20Sopenharmony_ci		vcpu->arch.pfault_token = kvm_run->s.regs.pft;
42168c2ecf20Sopenharmony_ci		vcpu->arch.pfault_select = kvm_run->s.regs.pfs;
42178c2ecf20Sopenharmony_ci		vcpu->arch.pfault_compare = kvm_run->s.regs.pfc;
42188c2ecf20Sopenharmony_ci		if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
42198c2ecf20Sopenharmony_ci			kvm_clear_async_pf_completion_queue(vcpu);
42208c2ecf20Sopenharmony_ci	}
42218c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) {
42228c2ecf20Sopenharmony_ci		vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318;
42238c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc;
42248c2ecf20Sopenharmony_ci	}
42258c2ecf20Sopenharmony_ci	/*
42268c2ecf20Sopenharmony_ci	 * If userspace sets the riccb (e.g. after migration) to a valid state,
42278c2ecf20Sopenharmony_ci	 * we should enable RI here instead of doing the lazy enablement.
42288c2ecf20Sopenharmony_ci	 */
42298c2ecf20Sopenharmony_ci	if ((kvm_run->kvm_dirty_regs & KVM_SYNC_RICCB) &&
42308c2ecf20Sopenharmony_ci	    test_kvm_facility(vcpu->kvm, 64) &&
42318c2ecf20Sopenharmony_ci	    riccb->v &&
42328c2ecf20Sopenharmony_ci	    !(vcpu->arch.sie_block->ecb3 & ECB3_RI)) {
42338c2ecf20Sopenharmony_ci		VCPU_EVENT(vcpu, 3, "%s", "ENABLE: RI (sync_regs)");
42348c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb3 |= ECB3_RI;
42358c2ecf20Sopenharmony_ci	}
42368c2ecf20Sopenharmony_ci	/*
42378c2ecf20Sopenharmony_ci	 * If userspace sets the gscb (e.g. after migration) to non-zero,
42388c2ecf20Sopenharmony_ci	 * we should enable GS here instead of doing the lazy enablement.
42398c2ecf20Sopenharmony_ci	 */
42408c2ecf20Sopenharmony_ci	if ((kvm_run->kvm_dirty_regs & KVM_SYNC_GSCB) &&
42418c2ecf20Sopenharmony_ci	    test_kvm_facility(vcpu->kvm, 133) &&
42428c2ecf20Sopenharmony_ci	    gscb->gssm &&
42438c2ecf20Sopenharmony_ci	    !vcpu->arch.gs_enabled) {
42448c2ecf20Sopenharmony_ci		VCPU_EVENT(vcpu, 3, "%s", "ENABLE: GS (sync_regs)");
42458c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecb |= ECB_GS;
42468c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
42478c2ecf20Sopenharmony_ci		vcpu->arch.gs_enabled = 1;
42488c2ecf20Sopenharmony_ci	}
42498c2ecf20Sopenharmony_ci	if ((kvm_run->kvm_dirty_regs & KVM_SYNC_BPBC) &&
42508c2ecf20Sopenharmony_ci	    test_kvm_facility(vcpu->kvm, 82)) {
42518c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
42528c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0;
42538c2ecf20Sopenharmony_ci	}
42548c2ecf20Sopenharmony_ci	if (MACHINE_HAS_GS) {
42558c2ecf20Sopenharmony_ci		preempt_disable();
42568c2ecf20Sopenharmony_ci		__ctl_set_bit(2, 4);
42578c2ecf20Sopenharmony_ci		if (current->thread.gs_cb) {
42588c2ecf20Sopenharmony_ci			vcpu->arch.host_gscb = current->thread.gs_cb;
42598c2ecf20Sopenharmony_ci			save_gs_cb(vcpu->arch.host_gscb);
42608c2ecf20Sopenharmony_ci		}
42618c2ecf20Sopenharmony_ci		if (vcpu->arch.gs_enabled) {
42628c2ecf20Sopenharmony_ci			current->thread.gs_cb = (struct gs_cb *)
42638c2ecf20Sopenharmony_ci						&vcpu->run->s.regs.gscb;
42648c2ecf20Sopenharmony_ci			restore_gs_cb(current->thread.gs_cb);
42658c2ecf20Sopenharmony_ci		}
42668c2ecf20Sopenharmony_ci		preempt_enable();
42678c2ecf20Sopenharmony_ci	}
42688c2ecf20Sopenharmony_ci	/* SIE will load etoken directly from SDNX and therefore kvm_run */
42698c2ecf20Sopenharmony_ci}
42708c2ecf20Sopenharmony_ci
42718c2ecf20Sopenharmony_cistatic void sync_regs(struct kvm_vcpu *vcpu)
42728c2ecf20Sopenharmony_ci{
42738c2ecf20Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
42748c2ecf20Sopenharmony_ci
42758c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
42768c2ecf20Sopenharmony_ci		kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
42778c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
42788c2ecf20Sopenharmony_ci		memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
42798c2ecf20Sopenharmony_ci		/* some control register changes require a tlb flush */
42808c2ecf20Sopenharmony_ci		kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
42818c2ecf20Sopenharmony_ci	}
42828c2ecf20Sopenharmony_ci	if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
42838c2ecf20Sopenharmony_ci		kvm_s390_set_cpu_timer(vcpu, kvm_run->s.regs.cputm);
42848c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc;
42858c2ecf20Sopenharmony_ci	}
42868c2ecf20Sopenharmony_ci	save_access_regs(vcpu->arch.host_acrs);
42878c2ecf20Sopenharmony_ci	restore_access_regs(vcpu->run->s.regs.acrs);
42888c2ecf20Sopenharmony_ci	/* save host (userspace) fprs/vrs */
42898c2ecf20Sopenharmony_ci	save_fpu_regs();
42908c2ecf20Sopenharmony_ci	vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc;
42918c2ecf20Sopenharmony_ci	vcpu->arch.host_fpregs.regs = current->thread.fpu.regs;
42928c2ecf20Sopenharmony_ci	if (MACHINE_HAS_VX)
42938c2ecf20Sopenharmony_ci		current->thread.fpu.regs = vcpu->run->s.regs.vrs;
42948c2ecf20Sopenharmony_ci	else
42958c2ecf20Sopenharmony_ci		current->thread.fpu.regs = vcpu->run->s.regs.fprs;
42968c2ecf20Sopenharmony_ci	current->thread.fpu.fpc = vcpu->run->s.regs.fpc;
42978c2ecf20Sopenharmony_ci	if (test_fp_ctl(current->thread.fpu.fpc))
42988c2ecf20Sopenharmony_ci		/* User space provided an invalid FPC, let's clear it */
42998c2ecf20Sopenharmony_ci		current->thread.fpu.fpc = 0;
43008c2ecf20Sopenharmony_ci
43018c2ecf20Sopenharmony_ci	/* Sync fmt2 only data */
43028c2ecf20Sopenharmony_ci	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) {
43038c2ecf20Sopenharmony_ci		sync_regs_fmt2(vcpu);
43048c2ecf20Sopenharmony_ci	} else {
43058c2ecf20Sopenharmony_ci		/*
43068c2ecf20Sopenharmony_ci		 * In several places we have to modify our internal view to
43078c2ecf20Sopenharmony_ci		 * not do things that are disallowed by the ultravisor. For
43088c2ecf20Sopenharmony_ci		 * example we must not inject interrupts after specific exits
43098c2ecf20Sopenharmony_ci		 * (e.g. 112 prefix page not secure). We do this by turning
43108c2ecf20Sopenharmony_ci		 * off the machine check, external and I/O interrupt bits
43118c2ecf20Sopenharmony_ci		 * of our PSW copy. To avoid getting validity intercepts, we
43128c2ecf20Sopenharmony_ci		 * do only accept the condition code from userspace.
43138c2ecf20Sopenharmony_ci		 */
43148c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gpsw.mask &= ~PSW_MASK_CC;
43158c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gpsw.mask |= kvm_run->psw_mask &
43168c2ecf20Sopenharmony_ci						   PSW_MASK_CC;
43178c2ecf20Sopenharmony_ci	}
43188c2ecf20Sopenharmony_ci
43198c2ecf20Sopenharmony_ci	kvm_run->kvm_dirty_regs = 0;
43208c2ecf20Sopenharmony_ci}
43218c2ecf20Sopenharmony_ci
43228c2ecf20Sopenharmony_cistatic void store_regs_fmt2(struct kvm_vcpu *vcpu)
43238c2ecf20Sopenharmony_ci{
43248c2ecf20Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
43258c2ecf20Sopenharmony_ci
43268c2ecf20Sopenharmony_ci	kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
43278c2ecf20Sopenharmony_ci	kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
43288c2ecf20Sopenharmony_ci	kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
43298c2ecf20Sopenharmony_ci	kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
43308c2ecf20Sopenharmony_ci	kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val;
43318c2ecf20Sopenharmony_ci	if (MACHINE_HAS_GS) {
43328c2ecf20Sopenharmony_ci		preempt_disable();
43338c2ecf20Sopenharmony_ci		__ctl_set_bit(2, 4);
43348c2ecf20Sopenharmony_ci		if (vcpu->arch.gs_enabled)
43358c2ecf20Sopenharmony_ci			save_gs_cb(current->thread.gs_cb);
43368c2ecf20Sopenharmony_ci		current->thread.gs_cb = vcpu->arch.host_gscb;
43378c2ecf20Sopenharmony_ci		restore_gs_cb(vcpu->arch.host_gscb);
43388c2ecf20Sopenharmony_ci		if (!vcpu->arch.host_gscb)
43398c2ecf20Sopenharmony_ci			__ctl_clear_bit(2, 4);
43408c2ecf20Sopenharmony_ci		vcpu->arch.host_gscb = NULL;
43418c2ecf20Sopenharmony_ci		preempt_enable();
43428c2ecf20Sopenharmony_ci	}
43438c2ecf20Sopenharmony_ci	/* SIE will save etoken directly into SDNX and therefore kvm_run */
43448c2ecf20Sopenharmony_ci}
43458c2ecf20Sopenharmony_ci
43468c2ecf20Sopenharmony_cistatic void store_regs(struct kvm_vcpu *vcpu)
43478c2ecf20Sopenharmony_ci{
43488c2ecf20Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
43498c2ecf20Sopenharmony_ci
43508c2ecf20Sopenharmony_ci	kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
43518c2ecf20Sopenharmony_ci	kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
43528c2ecf20Sopenharmony_ci	kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu);
43538c2ecf20Sopenharmony_ci	memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
43548c2ecf20Sopenharmony_ci	kvm_run->s.regs.cputm = kvm_s390_get_cpu_timer(vcpu);
43558c2ecf20Sopenharmony_ci	kvm_run->s.regs.ckc = vcpu->arch.sie_block->ckc;
43568c2ecf20Sopenharmony_ci	kvm_run->s.regs.pft = vcpu->arch.pfault_token;
43578c2ecf20Sopenharmony_ci	kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
43588c2ecf20Sopenharmony_ci	kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
43598c2ecf20Sopenharmony_ci	save_access_regs(vcpu->run->s.regs.acrs);
43608c2ecf20Sopenharmony_ci	restore_access_regs(vcpu->arch.host_acrs);
43618c2ecf20Sopenharmony_ci	/* Save guest register state */
43628c2ecf20Sopenharmony_ci	save_fpu_regs();
43638c2ecf20Sopenharmony_ci	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
43648c2ecf20Sopenharmony_ci	/* Restore will be done lazily at return */
43658c2ecf20Sopenharmony_ci	current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
43668c2ecf20Sopenharmony_ci	current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
43678c2ecf20Sopenharmony_ci	if (likely(!kvm_s390_pv_cpu_is_protected(vcpu)))
43688c2ecf20Sopenharmony_ci		store_regs_fmt2(vcpu);
43698c2ecf20Sopenharmony_ci}
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_ciint kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
43728c2ecf20Sopenharmony_ci{
43738c2ecf20Sopenharmony_ci	struct kvm_run *kvm_run = vcpu->run;
43748c2ecf20Sopenharmony_ci	int rc;
43758c2ecf20Sopenharmony_ci
43768c2ecf20Sopenharmony_ci	if (kvm_run->immediate_exit)
43778c2ecf20Sopenharmony_ci		return -EINTR;
43788c2ecf20Sopenharmony_ci
43798c2ecf20Sopenharmony_ci	if (kvm_run->kvm_valid_regs & ~KVM_SYNC_S390_VALID_FIELDS ||
43808c2ecf20Sopenharmony_ci	    kvm_run->kvm_dirty_regs & ~KVM_SYNC_S390_VALID_FIELDS)
43818c2ecf20Sopenharmony_ci		return -EINVAL;
43828c2ecf20Sopenharmony_ci
43838c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
43848c2ecf20Sopenharmony_ci
43858c2ecf20Sopenharmony_ci	if (guestdbg_exit_pending(vcpu)) {
43868c2ecf20Sopenharmony_ci		kvm_s390_prepare_debug_exit(vcpu);
43878c2ecf20Sopenharmony_ci		rc = 0;
43888c2ecf20Sopenharmony_ci		goto out;
43898c2ecf20Sopenharmony_ci	}
43908c2ecf20Sopenharmony_ci
43918c2ecf20Sopenharmony_ci	kvm_sigset_activate(vcpu);
43928c2ecf20Sopenharmony_ci
43938c2ecf20Sopenharmony_ci	/*
43948c2ecf20Sopenharmony_ci	 * no need to check the return value of vcpu_start as it can only have
43958c2ecf20Sopenharmony_ci	 * an error for protvirt, but protvirt means user cpu state
43968c2ecf20Sopenharmony_ci	 */
43978c2ecf20Sopenharmony_ci	if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) {
43988c2ecf20Sopenharmony_ci		kvm_s390_vcpu_start(vcpu);
43998c2ecf20Sopenharmony_ci	} else if (is_vcpu_stopped(vcpu)) {
44008c2ecf20Sopenharmony_ci		pr_err_ratelimited("can't run stopped vcpu %d\n",
44018c2ecf20Sopenharmony_ci				   vcpu->vcpu_id);
44028c2ecf20Sopenharmony_ci		rc = -EINVAL;
44038c2ecf20Sopenharmony_ci		goto out;
44048c2ecf20Sopenharmony_ci	}
44058c2ecf20Sopenharmony_ci
44068c2ecf20Sopenharmony_ci	sync_regs(vcpu);
44078c2ecf20Sopenharmony_ci	enable_cpu_timer_accounting(vcpu);
44088c2ecf20Sopenharmony_ci
44098c2ecf20Sopenharmony_ci	might_fault();
44108c2ecf20Sopenharmony_ci	rc = __vcpu_run(vcpu);
44118c2ecf20Sopenharmony_ci
44128c2ecf20Sopenharmony_ci	if (signal_pending(current) && !rc) {
44138c2ecf20Sopenharmony_ci		kvm_run->exit_reason = KVM_EXIT_INTR;
44148c2ecf20Sopenharmony_ci		rc = -EINTR;
44158c2ecf20Sopenharmony_ci	}
44168c2ecf20Sopenharmony_ci
44178c2ecf20Sopenharmony_ci	if (guestdbg_exit_pending(vcpu) && !rc)  {
44188c2ecf20Sopenharmony_ci		kvm_s390_prepare_debug_exit(vcpu);
44198c2ecf20Sopenharmony_ci		rc = 0;
44208c2ecf20Sopenharmony_ci	}
44218c2ecf20Sopenharmony_ci
44228c2ecf20Sopenharmony_ci	if (rc == -EREMOTE) {
44238c2ecf20Sopenharmony_ci		/* userspace support is needed, kvm_run has been prepared */
44248c2ecf20Sopenharmony_ci		rc = 0;
44258c2ecf20Sopenharmony_ci	}
44268c2ecf20Sopenharmony_ci
44278c2ecf20Sopenharmony_ci	disable_cpu_timer_accounting(vcpu);
44288c2ecf20Sopenharmony_ci	store_regs(vcpu);
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	kvm_sigset_deactivate(vcpu);
44318c2ecf20Sopenharmony_ci
44328c2ecf20Sopenharmony_ci	vcpu->stat.exit_userspace++;
44338c2ecf20Sopenharmony_ciout:
44348c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
44358c2ecf20Sopenharmony_ci	return rc;
44368c2ecf20Sopenharmony_ci}
44378c2ecf20Sopenharmony_ci
44388c2ecf20Sopenharmony_ci/*
44398c2ecf20Sopenharmony_ci * store status at address
44408c2ecf20Sopenharmony_ci * we use have two special cases:
44418c2ecf20Sopenharmony_ci * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
44428c2ecf20Sopenharmony_ci * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
44438c2ecf20Sopenharmony_ci */
44448c2ecf20Sopenharmony_ciint kvm_s390_store_status_unloaded(struct kvm_vcpu *vcpu, unsigned long gpa)
44458c2ecf20Sopenharmony_ci{
44468c2ecf20Sopenharmony_ci	unsigned char archmode = 1;
44478c2ecf20Sopenharmony_ci	freg_t fprs[NUM_FPRS];
44488c2ecf20Sopenharmony_ci	unsigned int px;
44498c2ecf20Sopenharmony_ci	u64 clkcomp, cputm;
44508c2ecf20Sopenharmony_ci	int rc;
44518c2ecf20Sopenharmony_ci
44528c2ecf20Sopenharmony_ci	px = kvm_s390_get_prefix(vcpu);
44538c2ecf20Sopenharmony_ci	if (gpa == KVM_S390_STORE_STATUS_NOADDR) {
44548c2ecf20Sopenharmony_ci		if (write_guest_abs(vcpu, 163, &archmode, 1))
44558c2ecf20Sopenharmony_ci			return -EFAULT;
44568c2ecf20Sopenharmony_ci		gpa = 0;
44578c2ecf20Sopenharmony_ci	} else if (gpa == KVM_S390_STORE_STATUS_PREFIXED) {
44588c2ecf20Sopenharmony_ci		if (write_guest_real(vcpu, 163, &archmode, 1))
44598c2ecf20Sopenharmony_ci			return -EFAULT;
44608c2ecf20Sopenharmony_ci		gpa = px;
44618c2ecf20Sopenharmony_ci	} else
44628c2ecf20Sopenharmony_ci		gpa -= __LC_FPREGS_SAVE_AREA;
44638c2ecf20Sopenharmony_ci
44648c2ecf20Sopenharmony_ci	/* manually convert vector registers if necessary */
44658c2ecf20Sopenharmony_ci	if (MACHINE_HAS_VX) {
44668c2ecf20Sopenharmony_ci		convert_vx_to_fp(fprs, (__vector128 *) vcpu->run->s.regs.vrs);
44678c2ecf20Sopenharmony_ci		rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
44688c2ecf20Sopenharmony_ci				     fprs, 128);
44698c2ecf20Sopenharmony_ci	} else {
44708c2ecf20Sopenharmony_ci		rc = write_guest_abs(vcpu, gpa + __LC_FPREGS_SAVE_AREA,
44718c2ecf20Sopenharmony_ci				     vcpu->run->s.regs.fprs, 128);
44728c2ecf20Sopenharmony_ci	}
44738c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_GPREGS_SAVE_AREA,
44748c2ecf20Sopenharmony_ci			      vcpu->run->s.regs.gprs, 128);
44758c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_PSW_SAVE_AREA,
44768c2ecf20Sopenharmony_ci			      &vcpu->arch.sie_block->gpsw, 16);
44778c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_PREFIX_SAVE_AREA,
44788c2ecf20Sopenharmony_ci			      &px, 4);
44798c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_FP_CREG_SAVE_AREA,
44808c2ecf20Sopenharmony_ci			      &vcpu->run->s.regs.fpc, 4);
44818c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_TOD_PROGREG_SAVE_AREA,
44828c2ecf20Sopenharmony_ci			      &vcpu->arch.sie_block->todpr, 4);
44838c2ecf20Sopenharmony_ci	cputm = kvm_s390_get_cpu_timer(vcpu);
44848c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_CPU_TIMER_SAVE_AREA,
44858c2ecf20Sopenharmony_ci			      &cputm, 8);
44868c2ecf20Sopenharmony_ci	clkcomp = vcpu->arch.sie_block->ckc >> 8;
44878c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_CLOCK_COMP_SAVE_AREA,
44888c2ecf20Sopenharmony_ci			      &clkcomp, 8);
44898c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_AREGS_SAVE_AREA,
44908c2ecf20Sopenharmony_ci			      &vcpu->run->s.regs.acrs, 64);
44918c2ecf20Sopenharmony_ci	rc |= write_guest_abs(vcpu, gpa + __LC_CREGS_SAVE_AREA,
44928c2ecf20Sopenharmony_ci			      &vcpu->arch.sie_block->gcr, 128);
44938c2ecf20Sopenharmony_ci	return rc ? -EFAULT : 0;
44948c2ecf20Sopenharmony_ci}
44958c2ecf20Sopenharmony_ci
44968c2ecf20Sopenharmony_ciint kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
44978c2ecf20Sopenharmony_ci{
44988c2ecf20Sopenharmony_ci	/*
44998c2ecf20Sopenharmony_ci	 * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy
45008c2ecf20Sopenharmony_ci	 * switch in the run ioctl. Let's update our copies before we save
45018c2ecf20Sopenharmony_ci	 * it into the save area
45028c2ecf20Sopenharmony_ci	 */
45038c2ecf20Sopenharmony_ci	save_fpu_regs();
45048c2ecf20Sopenharmony_ci	vcpu->run->s.regs.fpc = current->thread.fpu.fpc;
45058c2ecf20Sopenharmony_ci	save_access_regs(vcpu->run->s.regs.acrs);
45068c2ecf20Sopenharmony_ci
45078c2ecf20Sopenharmony_ci	return kvm_s390_store_status_unloaded(vcpu, addr);
45088c2ecf20Sopenharmony_ci}
45098c2ecf20Sopenharmony_ci
45108c2ecf20Sopenharmony_cistatic void __disable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
45118c2ecf20Sopenharmony_ci{
45128c2ecf20Sopenharmony_ci	kvm_check_request(KVM_REQ_ENABLE_IBS, vcpu);
45138c2ecf20Sopenharmony_ci	kvm_s390_sync_request(KVM_REQ_DISABLE_IBS, vcpu);
45148c2ecf20Sopenharmony_ci}
45158c2ecf20Sopenharmony_ci
45168c2ecf20Sopenharmony_cistatic void __disable_ibs_on_all_vcpus(struct kvm *kvm)
45178c2ecf20Sopenharmony_ci{
45188c2ecf20Sopenharmony_ci	unsigned int i;
45198c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu;
45208c2ecf20Sopenharmony_ci
45218c2ecf20Sopenharmony_ci	kvm_for_each_vcpu(i, vcpu, kvm) {
45228c2ecf20Sopenharmony_ci		__disable_ibs_on_vcpu(vcpu);
45238c2ecf20Sopenharmony_ci	}
45248c2ecf20Sopenharmony_ci}
45258c2ecf20Sopenharmony_ci
45268c2ecf20Sopenharmony_cistatic void __enable_ibs_on_vcpu(struct kvm_vcpu *vcpu)
45278c2ecf20Sopenharmony_ci{
45288c2ecf20Sopenharmony_ci	if (!sclp.has_ibs)
45298c2ecf20Sopenharmony_ci		return;
45308c2ecf20Sopenharmony_ci	kvm_check_request(KVM_REQ_DISABLE_IBS, vcpu);
45318c2ecf20Sopenharmony_ci	kvm_s390_sync_request(KVM_REQ_ENABLE_IBS, vcpu);
45328c2ecf20Sopenharmony_ci}
45338c2ecf20Sopenharmony_ci
45348c2ecf20Sopenharmony_ciint kvm_s390_vcpu_start(struct kvm_vcpu *vcpu)
45358c2ecf20Sopenharmony_ci{
45368c2ecf20Sopenharmony_ci	int i, online_vcpus, r = 0, started_vcpus = 0;
45378c2ecf20Sopenharmony_ci
45388c2ecf20Sopenharmony_ci	if (!is_vcpu_stopped(vcpu))
45398c2ecf20Sopenharmony_ci		return 0;
45408c2ecf20Sopenharmony_ci
45418c2ecf20Sopenharmony_ci	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 1);
45428c2ecf20Sopenharmony_ci	/* Only one cpu at a time may enter/leave the STOPPED state. */
45438c2ecf20Sopenharmony_ci	spin_lock(&vcpu->kvm->arch.start_stop_lock);
45448c2ecf20Sopenharmony_ci	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
45458c2ecf20Sopenharmony_ci
45468c2ecf20Sopenharmony_ci	/* Let's tell the UV that we want to change into the operating state */
45478c2ecf20Sopenharmony_ci	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
45488c2ecf20Sopenharmony_ci		r = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_OPR);
45498c2ecf20Sopenharmony_ci		if (r) {
45508c2ecf20Sopenharmony_ci			spin_unlock(&vcpu->kvm->arch.start_stop_lock);
45518c2ecf20Sopenharmony_ci			return r;
45528c2ecf20Sopenharmony_ci		}
45538c2ecf20Sopenharmony_ci	}
45548c2ecf20Sopenharmony_ci
45558c2ecf20Sopenharmony_ci	for (i = 0; i < online_vcpus; i++) {
45568c2ecf20Sopenharmony_ci		if (!is_vcpu_stopped(vcpu->kvm->vcpus[i]))
45578c2ecf20Sopenharmony_ci			started_vcpus++;
45588c2ecf20Sopenharmony_ci	}
45598c2ecf20Sopenharmony_ci
45608c2ecf20Sopenharmony_ci	if (started_vcpus == 0) {
45618c2ecf20Sopenharmony_ci		/* we're the only active VCPU -> speed it up */
45628c2ecf20Sopenharmony_ci		__enable_ibs_on_vcpu(vcpu);
45638c2ecf20Sopenharmony_ci	} else if (started_vcpus == 1) {
45648c2ecf20Sopenharmony_ci		/*
45658c2ecf20Sopenharmony_ci		 * As we are starting a second VCPU, we have to disable
45668c2ecf20Sopenharmony_ci		 * the IBS facility on all VCPUs to remove potentially
45678c2ecf20Sopenharmony_ci		 * oustanding ENABLE requests.
45688c2ecf20Sopenharmony_ci		 */
45698c2ecf20Sopenharmony_ci		__disable_ibs_on_all_vcpus(vcpu->kvm);
45708c2ecf20Sopenharmony_ci	}
45718c2ecf20Sopenharmony_ci
45728c2ecf20Sopenharmony_ci	kvm_s390_clear_cpuflags(vcpu, CPUSTAT_STOPPED);
45738c2ecf20Sopenharmony_ci	/*
45748c2ecf20Sopenharmony_ci	 * The real PSW might have changed due to a RESTART interpreted by the
45758c2ecf20Sopenharmony_ci	 * ultravisor. We block all interrupts and let the next sie exit
45768c2ecf20Sopenharmony_ci	 * refresh our view.
45778c2ecf20Sopenharmony_ci	 */
45788c2ecf20Sopenharmony_ci	if (kvm_s390_pv_cpu_is_protected(vcpu))
45798c2ecf20Sopenharmony_ci		vcpu->arch.sie_block->gpsw.mask &= ~PSW_INT_MASK;
45808c2ecf20Sopenharmony_ci	/*
45818c2ecf20Sopenharmony_ci	 * Another VCPU might have used IBS while we were offline.
45828c2ecf20Sopenharmony_ci	 * Let's play safe and flush the VCPU at startup.
45838c2ecf20Sopenharmony_ci	 */
45848c2ecf20Sopenharmony_ci	kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
45858c2ecf20Sopenharmony_ci	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
45868c2ecf20Sopenharmony_ci	return 0;
45878c2ecf20Sopenharmony_ci}
45888c2ecf20Sopenharmony_ci
45898c2ecf20Sopenharmony_ciint kvm_s390_vcpu_stop(struct kvm_vcpu *vcpu)
45908c2ecf20Sopenharmony_ci{
45918c2ecf20Sopenharmony_ci	int i, online_vcpus, r = 0, started_vcpus = 0;
45928c2ecf20Sopenharmony_ci	struct kvm_vcpu *started_vcpu = NULL;
45938c2ecf20Sopenharmony_ci
45948c2ecf20Sopenharmony_ci	if (is_vcpu_stopped(vcpu))
45958c2ecf20Sopenharmony_ci		return 0;
45968c2ecf20Sopenharmony_ci
45978c2ecf20Sopenharmony_ci	trace_kvm_s390_vcpu_start_stop(vcpu->vcpu_id, 0);
45988c2ecf20Sopenharmony_ci	/* Only one cpu at a time may enter/leave the STOPPED state. */
45998c2ecf20Sopenharmony_ci	spin_lock(&vcpu->kvm->arch.start_stop_lock);
46008c2ecf20Sopenharmony_ci	online_vcpus = atomic_read(&vcpu->kvm->online_vcpus);
46018c2ecf20Sopenharmony_ci
46028c2ecf20Sopenharmony_ci	/* Let's tell the UV that we want to change into the stopped state */
46038c2ecf20Sopenharmony_ci	if (kvm_s390_pv_cpu_is_protected(vcpu)) {
46048c2ecf20Sopenharmony_ci		r = kvm_s390_pv_set_cpu_state(vcpu, PV_CPU_STATE_STP);
46058c2ecf20Sopenharmony_ci		if (r) {
46068c2ecf20Sopenharmony_ci			spin_unlock(&vcpu->kvm->arch.start_stop_lock);
46078c2ecf20Sopenharmony_ci			return r;
46088c2ecf20Sopenharmony_ci		}
46098c2ecf20Sopenharmony_ci	}
46108c2ecf20Sopenharmony_ci
46118c2ecf20Sopenharmony_ci	/*
46128c2ecf20Sopenharmony_ci	 * Set the VCPU to STOPPED and THEN clear the interrupt flag,
46138c2ecf20Sopenharmony_ci	 * now that the SIGP STOP and SIGP STOP AND STORE STATUS orders
46148c2ecf20Sopenharmony_ci	 * have been fully processed. This will ensure that the VCPU
46158c2ecf20Sopenharmony_ci	 * is kept BUSY if another VCPU is inquiring with SIGP SENSE.
46168c2ecf20Sopenharmony_ci	 */
46178c2ecf20Sopenharmony_ci	kvm_s390_set_cpuflags(vcpu, CPUSTAT_STOPPED);
46188c2ecf20Sopenharmony_ci	kvm_s390_clear_stop_irq(vcpu);
46198c2ecf20Sopenharmony_ci
46208c2ecf20Sopenharmony_ci	__disable_ibs_on_vcpu(vcpu);
46218c2ecf20Sopenharmony_ci
46228c2ecf20Sopenharmony_ci	for (i = 0; i < online_vcpus; i++) {
46238c2ecf20Sopenharmony_ci		if (!is_vcpu_stopped(vcpu->kvm->vcpus[i])) {
46248c2ecf20Sopenharmony_ci			started_vcpus++;
46258c2ecf20Sopenharmony_ci			started_vcpu = vcpu->kvm->vcpus[i];
46268c2ecf20Sopenharmony_ci		}
46278c2ecf20Sopenharmony_ci	}
46288c2ecf20Sopenharmony_ci
46298c2ecf20Sopenharmony_ci	if (started_vcpus == 1) {
46308c2ecf20Sopenharmony_ci		/*
46318c2ecf20Sopenharmony_ci		 * As we only have one VCPU left, we want to enable the
46328c2ecf20Sopenharmony_ci		 * IBS facility for that VCPU to speed it up.
46338c2ecf20Sopenharmony_ci		 */
46348c2ecf20Sopenharmony_ci		__enable_ibs_on_vcpu(started_vcpu);
46358c2ecf20Sopenharmony_ci	}
46368c2ecf20Sopenharmony_ci
46378c2ecf20Sopenharmony_ci	spin_unlock(&vcpu->kvm->arch.start_stop_lock);
46388c2ecf20Sopenharmony_ci	return 0;
46398c2ecf20Sopenharmony_ci}
46408c2ecf20Sopenharmony_ci
46418c2ecf20Sopenharmony_cistatic int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
46428c2ecf20Sopenharmony_ci				     struct kvm_enable_cap *cap)
46438c2ecf20Sopenharmony_ci{
46448c2ecf20Sopenharmony_ci	int r;
46458c2ecf20Sopenharmony_ci
46468c2ecf20Sopenharmony_ci	if (cap->flags)
46478c2ecf20Sopenharmony_ci		return -EINVAL;
46488c2ecf20Sopenharmony_ci
46498c2ecf20Sopenharmony_ci	switch (cap->cap) {
46508c2ecf20Sopenharmony_ci	case KVM_CAP_S390_CSS_SUPPORT:
46518c2ecf20Sopenharmony_ci		if (!vcpu->kvm->arch.css_support) {
46528c2ecf20Sopenharmony_ci			vcpu->kvm->arch.css_support = 1;
46538c2ecf20Sopenharmony_ci			VM_EVENT(vcpu->kvm, 3, "%s", "ENABLE: CSS support");
46548c2ecf20Sopenharmony_ci			trace_kvm_s390_enable_css(vcpu->kvm);
46558c2ecf20Sopenharmony_ci		}
46568c2ecf20Sopenharmony_ci		r = 0;
46578c2ecf20Sopenharmony_ci		break;
46588c2ecf20Sopenharmony_ci	default:
46598c2ecf20Sopenharmony_ci		r = -EINVAL;
46608c2ecf20Sopenharmony_ci		break;
46618c2ecf20Sopenharmony_ci	}
46628c2ecf20Sopenharmony_ci	return r;
46638c2ecf20Sopenharmony_ci}
46648c2ecf20Sopenharmony_ci
46658c2ecf20Sopenharmony_cistatic long kvm_s390_guest_sida_op(struct kvm_vcpu *vcpu,
46668c2ecf20Sopenharmony_ci				   struct kvm_s390_mem_op *mop)
46678c2ecf20Sopenharmony_ci{
46688c2ecf20Sopenharmony_ci	void __user *uaddr = (void __user *)mop->buf;
46698c2ecf20Sopenharmony_ci	int r = 0;
46708c2ecf20Sopenharmony_ci
46718c2ecf20Sopenharmony_ci	if (mop->flags || !mop->size)
46728c2ecf20Sopenharmony_ci		return -EINVAL;
46738c2ecf20Sopenharmony_ci	if (mop->size + mop->sida_offset < mop->size)
46748c2ecf20Sopenharmony_ci		return -EINVAL;
46758c2ecf20Sopenharmony_ci	if (mop->size + mop->sida_offset > sida_size(vcpu->arch.sie_block))
46768c2ecf20Sopenharmony_ci		return -E2BIG;
46778c2ecf20Sopenharmony_ci	if (!kvm_s390_pv_cpu_is_protected(vcpu))
46788c2ecf20Sopenharmony_ci		return -EINVAL;
46798c2ecf20Sopenharmony_ci
46808c2ecf20Sopenharmony_ci	switch (mop->op) {
46818c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_SIDA_READ:
46828c2ecf20Sopenharmony_ci		if (copy_to_user(uaddr, (void *)(sida_origin(vcpu->arch.sie_block) +
46838c2ecf20Sopenharmony_ci				 mop->sida_offset), mop->size))
46848c2ecf20Sopenharmony_ci			r = -EFAULT;
46858c2ecf20Sopenharmony_ci
46868c2ecf20Sopenharmony_ci		break;
46878c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_SIDA_WRITE:
46888c2ecf20Sopenharmony_ci		if (copy_from_user((void *)(sida_origin(vcpu->arch.sie_block) +
46898c2ecf20Sopenharmony_ci				   mop->sida_offset), uaddr, mop->size))
46908c2ecf20Sopenharmony_ci			r = -EFAULT;
46918c2ecf20Sopenharmony_ci		break;
46928c2ecf20Sopenharmony_ci	}
46938c2ecf20Sopenharmony_ci	return r;
46948c2ecf20Sopenharmony_ci}
46958c2ecf20Sopenharmony_cistatic long kvm_s390_guest_mem_op(struct kvm_vcpu *vcpu,
46968c2ecf20Sopenharmony_ci				  struct kvm_s390_mem_op *mop)
46978c2ecf20Sopenharmony_ci{
46988c2ecf20Sopenharmony_ci	void __user *uaddr = (void __user *)mop->buf;
46998c2ecf20Sopenharmony_ci	void *tmpbuf = NULL;
47008c2ecf20Sopenharmony_ci	int r = 0;
47018c2ecf20Sopenharmony_ci	const u64 supported_flags = KVM_S390_MEMOP_F_INJECT_EXCEPTION
47028c2ecf20Sopenharmony_ci				    | KVM_S390_MEMOP_F_CHECK_ONLY;
47038c2ecf20Sopenharmony_ci
47048c2ecf20Sopenharmony_ci	if (mop->flags & ~supported_flags || mop->ar >= NUM_ACRS || !mop->size)
47058c2ecf20Sopenharmony_ci		return -EINVAL;
47068c2ecf20Sopenharmony_ci
47078c2ecf20Sopenharmony_ci	if (mop->size > MEM_OP_MAX_SIZE)
47088c2ecf20Sopenharmony_ci		return -E2BIG;
47098c2ecf20Sopenharmony_ci
47108c2ecf20Sopenharmony_ci	if (kvm_s390_pv_cpu_is_protected(vcpu))
47118c2ecf20Sopenharmony_ci		return -EINVAL;
47128c2ecf20Sopenharmony_ci
47138c2ecf20Sopenharmony_ci	if (!(mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY)) {
47148c2ecf20Sopenharmony_ci		tmpbuf = vmalloc(mop->size);
47158c2ecf20Sopenharmony_ci		if (!tmpbuf)
47168c2ecf20Sopenharmony_ci			return -ENOMEM;
47178c2ecf20Sopenharmony_ci	}
47188c2ecf20Sopenharmony_ci
47198c2ecf20Sopenharmony_ci	switch (mop->op) {
47208c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_LOGICAL_READ:
47218c2ecf20Sopenharmony_ci		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
47228c2ecf20Sopenharmony_ci			r = check_gva_range(vcpu, mop->gaddr, mop->ar,
47238c2ecf20Sopenharmony_ci					    mop->size, GACC_FETCH);
47248c2ecf20Sopenharmony_ci			break;
47258c2ecf20Sopenharmony_ci		}
47268c2ecf20Sopenharmony_ci		r = read_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
47278c2ecf20Sopenharmony_ci		if (r == 0) {
47288c2ecf20Sopenharmony_ci			if (copy_to_user(uaddr, tmpbuf, mop->size))
47298c2ecf20Sopenharmony_ci				r = -EFAULT;
47308c2ecf20Sopenharmony_ci		}
47318c2ecf20Sopenharmony_ci		break;
47328c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_LOGICAL_WRITE:
47338c2ecf20Sopenharmony_ci		if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) {
47348c2ecf20Sopenharmony_ci			r = check_gva_range(vcpu, mop->gaddr, mop->ar,
47358c2ecf20Sopenharmony_ci					    mop->size, GACC_STORE);
47368c2ecf20Sopenharmony_ci			break;
47378c2ecf20Sopenharmony_ci		}
47388c2ecf20Sopenharmony_ci		if (copy_from_user(tmpbuf, uaddr, mop->size)) {
47398c2ecf20Sopenharmony_ci			r = -EFAULT;
47408c2ecf20Sopenharmony_ci			break;
47418c2ecf20Sopenharmony_ci		}
47428c2ecf20Sopenharmony_ci		r = write_guest(vcpu, mop->gaddr, mop->ar, tmpbuf, mop->size);
47438c2ecf20Sopenharmony_ci		break;
47448c2ecf20Sopenharmony_ci	}
47458c2ecf20Sopenharmony_ci
47468c2ecf20Sopenharmony_ci	if (r > 0 && (mop->flags & KVM_S390_MEMOP_F_INJECT_EXCEPTION) != 0)
47478c2ecf20Sopenharmony_ci		kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm);
47488c2ecf20Sopenharmony_ci
47498c2ecf20Sopenharmony_ci	vfree(tmpbuf);
47508c2ecf20Sopenharmony_ci	return r;
47518c2ecf20Sopenharmony_ci}
47528c2ecf20Sopenharmony_ci
47538c2ecf20Sopenharmony_cistatic long kvm_s390_guest_memsida_op(struct kvm_vcpu *vcpu,
47548c2ecf20Sopenharmony_ci				      struct kvm_s390_mem_op *mop)
47558c2ecf20Sopenharmony_ci{
47568c2ecf20Sopenharmony_ci	int r, srcu_idx;
47578c2ecf20Sopenharmony_ci
47588c2ecf20Sopenharmony_ci	srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
47598c2ecf20Sopenharmony_ci
47608c2ecf20Sopenharmony_ci	switch (mop->op) {
47618c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_LOGICAL_READ:
47628c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_LOGICAL_WRITE:
47638c2ecf20Sopenharmony_ci		r = kvm_s390_guest_mem_op(vcpu, mop);
47648c2ecf20Sopenharmony_ci		break;
47658c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_SIDA_READ:
47668c2ecf20Sopenharmony_ci	case KVM_S390_MEMOP_SIDA_WRITE:
47678c2ecf20Sopenharmony_ci		/* we are locked against sida going away by the vcpu->mutex */
47688c2ecf20Sopenharmony_ci		r = kvm_s390_guest_sida_op(vcpu, mop);
47698c2ecf20Sopenharmony_ci		break;
47708c2ecf20Sopenharmony_ci	default:
47718c2ecf20Sopenharmony_ci		r = -EINVAL;
47728c2ecf20Sopenharmony_ci	}
47738c2ecf20Sopenharmony_ci
47748c2ecf20Sopenharmony_ci	srcu_read_unlock(&vcpu->kvm->srcu, srcu_idx);
47758c2ecf20Sopenharmony_ci	return r;
47768c2ecf20Sopenharmony_ci}
47778c2ecf20Sopenharmony_ci
47788c2ecf20Sopenharmony_cilong kvm_arch_vcpu_async_ioctl(struct file *filp,
47798c2ecf20Sopenharmony_ci			       unsigned int ioctl, unsigned long arg)
47808c2ecf20Sopenharmony_ci{
47818c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu = filp->private_data;
47828c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
47838c2ecf20Sopenharmony_ci
47848c2ecf20Sopenharmony_ci	switch (ioctl) {
47858c2ecf20Sopenharmony_ci	case KVM_S390_IRQ: {
47868c2ecf20Sopenharmony_ci		struct kvm_s390_irq s390irq;
47878c2ecf20Sopenharmony_ci
47888c2ecf20Sopenharmony_ci		if (copy_from_user(&s390irq, argp, sizeof(s390irq)))
47898c2ecf20Sopenharmony_ci			return -EFAULT;
47908c2ecf20Sopenharmony_ci		return kvm_s390_inject_vcpu(vcpu, &s390irq);
47918c2ecf20Sopenharmony_ci	}
47928c2ecf20Sopenharmony_ci	case KVM_S390_INTERRUPT: {
47938c2ecf20Sopenharmony_ci		struct kvm_s390_interrupt s390int;
47948c2ecf20Sopenharmony_ci		struct kvm_s390_irq s390irq = {};
47958c2ecf20Sopenharmony_ci
47968c2ecf20Sopenharmony_ci		if (copy_from_user(&s390int, argp, sizeof(s390int)))
47978c2ecf20Sopenharmony_ci			return -EFAULT;
47988c2ecf20Sopenharmony_ci		if (s390int_to_s390irq(&s390int, &s390irq))
47998c2ecf20Sopenharmony_ci			return -EINVAL;
48008c2ecf20Sopenharmony_ci		return kvm_s390_inject_vcpu(vcpu, &s390irq);
48018c2ecf20Sopenharmony_ci	}
48028c2ecf20Sopenharmony_ci	}
48038c2ecf20Sopenharmony_ci	return -ENOIOCTLCMD;
48048c2ecf20Sopenharmony_ci}
48058c2ecf20Sopenharmony_ci
48068c2ecf20Sopenharmony_cilong kvm_arch_vcpu_ioctl(struct file *filp,
48078c2ecf20Sopenharmony_ci			 unsigned int ioctl, unsigned long arg)
48088c2ecf20Sopenharmony_ci{
48098c2ecf20Sopenharmony_ci	struct kvm_vcpu *vcpu = filp->private_data;
48108c2ecf20Sopenharmony_ci	void __user *argp = (void __user *)arg;
48118c2ecf20Sopenharmony_ci	int idx;
48128c2ecf20Sopenharmony_ci	long r;
48138c2ecf20Sopenharmony_ci	u16 rc, rrc;
48148c2ecf20Sopenharmony_ci
48158c2ecf20Sopenharmony_ci	vcpu_load(vcpu);
48168c2ecf20Sopenharmony_ci
48178c2ecf20Sopenharmony_ci	switch (ioctl) {
48188c2ecf20Sopenharmony_ci	case KVM_S390_STORE_STATUS:
48198c2ecf20Sopenharmony_ci		idx = srcu_read_lock(&vcpu->kvm->srcu);
48208c2ecf20Sopenharmony_ci		r = kvm_s390_store_status_unloaded(vcpu, arg);
48218c2ecf20Sopenharmony_ci		srcu_read_unlock(&vcpu->kvm->srcu, idx);
48228c2ecf20Sopenharmony_ci		break;
48238c2ecf20Sopenharmony_ci	case KVM_S390_SET_INITIAL_PSW: {
48248c2ecf20Sopenharmony_ci		psw_t psw;
48258c2ecf20Sopenharmony_ci
48268c2ecf20Sopenharmony_ci		r = -EFAULT;
48278c2ecf20Sopenharmony_ci		if (copy_from_user(&psw, argp, sizeof(psw)))
48288c2ecf20Sopenharmony_ci			break;
48298c2ecf20Sopenharmony_ci		r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
48308c2ecf20Sopenharmony_ci		break;
48318c2ecf20Sopenharmony_ci	}
48328c2ecf20Sopenharmony_ci	case KVM_S390_CLEAR_RESET:
48338c2ecf20Sopenharmony_ci		r = 0;
48348c2ecf20Sopenharmony_ci		kvm_arch_vcpu_ioctl_clear_reset(vcpu);
48358c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
48368c2ecf20Sopenharmony_ci			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
48378c2ecf20Sopenharmony_ci					  UVC_CMD_CPU_RESET_CLEAR, &rc, &rrc);
48388c2ecf20Sopenharmony_ci			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET CLEAR VCPU: rc %x rrc %x",
48398c2ecf20Sopenharmony_ci				   rc, rrc);
48408c2ecf20Sopenharmony_ci		}
48418c2ecf20Sopenharmony_ci		break;
48428c2ecf20Sopenharmony_ci	case KVM_S390_INITIAL_RESET:
48438c2ecf20Sopenharmony_ci		r = 0;
48448c2ecf20Sopenharmony_ci		kvm_arch_vcpu_ioctl_initial_reset(vcpu);
48458c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
48468c2ecf20Sopenharmony_ci			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
48478c2ecf20Sopenharmony_ci					  UVC_CMD_CPU_RESET_INITIAL,
48488c2ecf20Sopenharmony_ci					  &rc, &rrc);
48498c2ecf20Sopenharmony_ci			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET INITIAL VCPU: rc %x rrc %x",
48508c2ecf20Sopenharmony_ci				   rc, rrc);
48518c2ecf20Sopenharmony_ci		}
48528c2ecf20Sopenharmony_ci		break;
48538c2ecf20Sopenharmony_ci	case KVM_S390_NORMAL_RESET:
48548c2ecf20Sopenharmony_ci		r = 0;
48558c2ecf20Sopenharmony_ci		kvm_arch_vcpu_ioctl_normal_reset(vcpu);
48568c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu)) {
48578c2ecf20Sopenharmony_ci			r = uv_cmd_nodata(kvm_s390_pv_cpu_get_handle(vcpu),
48588c2ecf20Sopenharmony_ci					  UVC_CMD_CPU_RESET, &rc, &rrc);
48598c2ecf20Sopenharmony_ci			VCPU_EVENT(vcpu, 3, "PROTVIRT RESET NORMAL VCPU: rc %x rrc %x",
48608c2ecf20Sopenharmony_ci				   rc, rrc);
48618c2ecf20Sopenharmony_ci		}
48628c2ecf20Sopenharmony_ci		break;
48638c2ecf20Sopenharmony_ci	case KVM_SET_ONE_REG:
48648c2ecf20Sopenharmony_ci	case KVM_GET_ONE_REG: {
48658c2ecf20Sopenharmony_ci		struct kvm_one_reg reg;
48668c2ecf20Sopenharmony_ci		r = -EINVAL;
48678c2ecf20Sopenharmony_ci		if (kvm_s390_pv_cpu_is_protected(vcpu))
48688c2ecf20Sopenharmony_ci			break;
48698c2ecf20Sopenharmony_ci		r = -EFAULT;
48708c2ecf20Sopenharmony_ci		if (copy_from_user(&reg, argp, sizeof(reg)))
48718c2ecf20Sopenharmony_ci			break;
48728c2ecf20Sopenharmony_ci		if (ioctl == KVM_SET_ONE_REG)
48738c2ecf20Sopenharmony_ci			r = kvm_arch_vcpu_ioctl_set_one_reg(vcpu, &reg);
48748c2ecf20Sopenharmony_ci		else
48758c2ecf20Sopenharmony_ci			r = kvm_arch_vcpu_ioctl_get_one_reg(vcpu, &reg);
48768c2ecf20Sopenharmony_ci		break;
48778c2ecf20Sopenharmony_ci	}
48788c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL
48798c2ecf20Sopenharmony_ci	case KVM_S390_UCAS_MAP: {
48808c2ecf20Sopenharmony_ci		struct kvm_s390_ucas_mapping ucasmap;
48818c2ecf20Sopenharmony_ci
48828c2ecf20Sopenharmony_ci		if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
48838c2ecf20Sopenharmony_ci			r = -EFAULT;
48848c2ecf20Sopenharmony_ci			break;
48858c2ecf20Sopenharmony_ci		}
48868c2ecf20Sopenharmony_ci
48878c2ecf20Sopenharmony_ci		if (!kvm_is_ucontrol(vcpu->kvm)) {
48888c2ecf20Sopenharmony_ci			r = -EINVAL;
48898c2ecf20Sopenharmony_ci			break;
48908c2ecf20Sopenharmony_ci		}
48918c2ecf20Sopenharmony_ci
48928c2ecf20Sopenharmony_ci		r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
48938c2ecf20Sopenharmony_ci				     ucasmap.vcpu_addr, ucasmap.length);
48948c2ecf20Sopenharmony_ci		break;
48958c2ecf20Sopenharmony_ci	}
48968c2ecf20Sopenharmony_ci	case KVM_S390_UCAS_UNMAP: {
48978c2ecf20Sopenharmony_ci		struct kvm_s390_ucas_mapping ucasmap;
48988c2ecf20Sopenharmony_ci
48998c2ecf20Sopenharmony_ci		if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
49008c2ecf20Sopenharmony_ci			r = -EFAULT;
49018c2ecf20Sopenharmony_ci			break;
49028c2ecf20Sopenharmony_ci		}
49038c2ecf20Sopenharmony_ci
49048c2ecf20Sopenharmony_ci		if (!kvm_is_ucontrol(vcpu->kvm)) {
49058c2ecf20Sopenharmony_ci			r = -EINVAL;
49068c2ecf20Sopenharmony_ci			break;
49078c2ecf20Sopenharmony_ci		}
49088c2ecf20Sopenharmony_ci
49098c2ecf20Sopenharmony_ci		r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
49108c2ecf20Sopenharmony_ci			ucasmap.length);
49118c2ecf20Sopenharmony_ci		break;
49128c2ecf20Sopenharmony_ci	}
49138c2ecf20Sopenharmony_ci#endif
49148c2ecf20Sopenharmony_ci	case KVM_S390_VCPU_FAULT: {
49158c2ecf20Sopenharmony_ci		r = gmap_fault(vcpu->arch.gmap, arg, 0);
49168c2ecf20Sopenharmony_ci		break;
49178c2ecf20Sopenharmony_ci	}
49188c2ecf20Sopenharmony_ci	case KVM_ENABLE_CAP:
49198c2ecf20Sopenharmony_ci	{
49208c2ecf20Sopenharmony_ci		struct kvm_enable_cap cap;
49218c2ecf20Sopenharmony_ci		r = -EFAULT;
49228c2ecf20Sopenharmony_ci		if (copy_from_user(&cap, argp, sizeof(cap)))
49238c2ecf20Sopenharmony_ci			break;
49248c2ecf20Sopenharmony_ci		r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap);
49258c2ecf20Sopenharmony_ci		break;
49268c2ecf20Sopenharmony_ci	}
49278c2ecf20Sopenharmony_ci	case KVM_S390_MEM_OP: {
49288c2ecf20Sopenharmony_ci		struct kvm_s390_mem_op mem_op;
49298c2ecf20Sopenharmony_ci
49308c2ecf20Sopenharmony_ci		if (copy_from_user(&mem_op, argp, sizeof(mem_op)) == 0)
49318c2ecf20Sopenharmony_ci			r = kvm_s390_guest_memsida_op(vcpu, &mem_op);
49328c2ecf20Sopenharmony_ci		else
49338c2ecf20Sopenharmony_ci			r = -EFAULT;
49348c2ecf20Sopenharmony_ci		break;
49358c2ecf20Sopenharmony_ci	}
49368c2ecf20Sopenharmony_ci	case KVM_S390_SET_IRQ_STATE: {
49378c2ecf20Sopenharmony_ci		struct kvm_s390_irq_state irq_state;
49388c2ecf20Sopenharmony_ci
49398c2ecf20Sopenharmony_ci		r = -EFAULT;
49408c2ecf20Sopenharmony_ci		if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
49418c2ecf20Sopenharmony_ci			break;
49428c2ecf20Sopenharmony_ci		if (irq_state.len > VCPU_IRQS_MAX_BUF ||
49438c2ecf20Sopenharmony_ci		    irq_state.len == 0 ||
49448c2ecf20Sopenharmony_ci		    irq_state.len % sizeof(struct kvm_s390_irq) > 0) {
49458c2ecf20Sopenharmony_ci			r = -EINVAL;
49468c2ecf20Sopenharmony_ci			break;
49478c2ecf20Sopenharmony_ci		}
49488c2ecf20Sopenharmony_ci		/* do not use irq_state.flags, it will break old QEMUs */
49498c2ecf20Sopenharmony_ci		r = kvm_s390_set_irq_state(vcpu,
49508c2ecf20Sopenharmony_ci					   (void __user *) irq_state.buf,
49518c2ecf20Sopenharmony_ci					   irq_state.len);
49528c2ecf20Sopenharmony_ci		break;
49538c2ecf20Sopenharmony_ci	}
49548c2ecf20Sopenharmony_ci	case KVM_S390_GET_IRQ_STATE: {
49558c2ecf20Sopenharmony_ci		struct kvm_s390_irq_state irq_state;
49568c2ecf20Sopenharmony_ci
49578c2ecf20Sopenharmony_ci		r = -EFAULT;
49588c2ecf20Sopenharmony_ci		if (copy_from_user(&irq_state, argp, sizeof(irq_state)))
49598c2ecf20Sopenharmony_ci			break;
49608c2ecf20Sopenharmony_ci		if (irq_state.len == 0) {
49618c2ecf20Sopenharmony_ci			r = -EINVAL;
49628c2ecf20Sopenharmony_ci			break;
49638c2ecf20Sopenharmony_ci		}
49648c2ecf20Sopenharmony_ci		/* do not use irq_state.flags, it will break old QEMUs */
49658c2ecf20Sopenharmony_ci		r = kvm_s390_get_irq_state(vcpu,
49668c2ecf20Sopenharmony_ci					   (__u8 __user *)  irq_state.buf,
49678c2ecf20Sopenharmony_ci					   irq_state.len);
49688c2ecf20Sopenharmony_ci		break;
49698c2ecf20Sopenharmony_ci	}
49708c2ecf20Sopenharmony_ci	default:
49718c2ecf20Sopenharmony_ci		r = -ENOTTY;
49728c2ecf20Sopenharmony_ci	}
49738c2ecf20Sopenharmony_ci
49748c2ecf20Sopenharmony_ci	vcpu_put(vcpu);
49758c2ecf20Sopenharmony_ci	return r;
49768c2ecf20Sopenharmony_ci}
49778c2ecf20Sopenharmony_ci
49788c2ecf20Sopenharmony_civm_fault_t kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
49798c2ecf20Sopenharmony_ci{
49808c2ecf20Sopenharmony_ci#ifdef CONFIG_KVM_S390_UCONTROL
49818c2ecf20Sopenharmony_ci	if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
49828c2ecf20Sopenharmony_ci		 && (kvm_is_ucontrol(vcpu->kvm))) {
49838c2ecf20Sopenharmony_ci		vmf->page = virt_to_page(vcpu->arch.sie_block);
49848c2ecf20Sopenharmony_ci		get_page(vmf->page);
49858c2ecf20Sopenharmony_ci		return 0;
49868c2ecf20Sopenharmony_ci	}
49878c2ecf20Sopenharmony_ci#endif
49888c2ecf20Sopenharmony_ci	return VM_FAULT_SIGBUS;
49898c2ecf20Sopenharmony_ci}
49908c2ecf20Sopenharmony_ci
49918c2ecf20Sopenharmony_ci/* Section: memory related */
49928c2ecf20Sopenharmony_ciint kvm_arch_prepare_memory_region(struct kvm *kvm,
49938c2ecf20Sopenharmony_ci				   struct kvm_memory_slot *memslot,
49948c2ecf20Sopenharmony_ci				   const struct kvm_userspace_memory_region *mem,
49958c2ecf20Sopenharmony_ci				   enum kvm_mr_change change)
49968c2ecf20Sopenharmony_ci{
49978c2ecf20Sopenharmony_ci	/* A few sanity checks. We can have memory slots which have to be
49988c2ecf20Sopenharmony_ci	   located/ended at a segment boundary (1MB). The memory in userland is
49998c2ecf20Sopenharmony_ci	   ok to be fragmented into various different vmas. It is okay to mmap()
50008c2ecf20Sopenharmony_ci	   and munmap() stuff in this slot after doing this call at any time */
50018c2ecf20Sopenharmony_ci
50028c2ecf20Sopenharmony_ci	if (mem->userspace_addr & 0xffffful)
50038c2ecf20Sopenharmony_ci		return -EINVAL;
50048c2ecf20Sopenharmony_ci
50058c2ecf20Sopenharmony_ci	if (mem->memory_size & 0xffffful)
50068c2ecf20Sopenharmony_ci		return -EINVAL;
50078c2ecf20Sopenharmony_ci
50088c2ecf20Sopenharmony_ci	if (mem->guest_phys_addr + mem->memory_size > kvm->arch.mem_limit)
50098c2ecf20Sopenharmony_ci		return -EINVAL;
50108c2ecf20Sopenharmony_ci
50118c2ecf20Sopenharmony_ci	/* When we are protected, we should not change the memory slots */
50128c2ecf20Sopenharmony_ci	if (kvm_s390_pv_get_handle(kvm))
50138c2ecf20Sopenharmony_ci		return -EINVAL;
50148c2ecf20Sopenharmony_ci
50158c2ecf20Sopenharmony_ci	if (!kvm->arch.migration_mode)
50168c2ecf20Sopenharmony_ci		return 0;
50178c2ecf20Sopenharmony_ci
50188c2ecf20Sopenharmony_ci	/*
50198c2ecf20Sopenharmony_ci	 * Turn off migration mode when:
50208c2ecf20Sopenharmony_ci	 * - userspace creates a new memslot with dirty logging off,
50218c2ecf20Sopenharmony_ci	 * - userspace modifies an existing memslot (MOVE or FLAGS_ONLY) and
50228c2ecf20Sopenharmony_ci	 *   dirty logging is turned off.
50238c2ecf20Sopenharmony_ci	 * Migration mode expects dirty page logging being enabled to store
50248c2ecf20Sopenharmony_ci	 * its dirty bitmap.
50258c2ecf20Sopenharmony_ci	 */
50268c2ecf20Sopenharmony_ci	if (change != KVM_MR_DELETE &&
50278c2ecf20Sopenharmony_ci	    !(mem->flags & KVM_MEM_LOG_DIRTY_PAGES))
50288c2ecf20Sopenharmony_ci		WARN(kvm_s390_vm_stop_migration(kvm),
50298c2ecf20Sopenharmony_ci		     "Failed to stop migration mode");
50308c2ecf20Sopenharmony_ci
50318c2ecf20Sopenharmony_ci	return 0;
50328c2ecf20Sopenharmony_ci}
50338c2ecf20Sopenharmony_ci
50348c2ecf20Sopenharmony_civoid kvm_arch_commit_memory_region(struct kvm *kvm,
50358c2ecf20Sopenharmony_ci				const struct kvm_userspace_memory_region *mem,
50368c2ecf20Sopenharmony_ci				struct kvm_memory_slot *old,
50378c2ecf20Sopenharmony_ci				const struct kvm_memory_slot *new,
50388c2ecf20Sopenharmony_ci				enum kvm_mr_change change)
50398c2ecf20Sopenharmony_ci{
50408c2ecf20Sopenharmony_ci	int rc = 0;
50418c2ecf20Sopenharmony_ci
50428c2ecf20Sopenharmony_ci	switch (change) {
50438c2ecf20Sopenharmony_ci	case KVM_MR_DELETE:
50448c2ecf20Sopenharmony_ci		rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
50458c2ecf20Sopenharmony_ci					old->npages * PAGE_SIZE);
50468c2ecf20Sopenharmony_ci		break;
50478c2ecf20Sopenharmony_ci	case KVM_MR_MOVE:
50488c2ecf20Sopenharmony_ci		rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
50498c2ecf20Sopenharmony_ci					old->npages * PAGE_SIZE);
50508c2ecf20Sopenharmony_ci		if (rc)
50518c2ecf20Sopenharmony_ci			break;
50528c2ecf20Sopenharmony_ci		fallthrough;
50538c2ecf20Sopenharmony_ci	case KVM_MR_CREATE:
50548c2ecf20Sopenharmony_ci		rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
50558c2ecf20Sopenharmony_ci				      mem->guest_phys_addr, mem->memory_size);
50568c2ecf20Sopenharmony_ci		break;
50578c2ecf20Sopenharmony_ci	case KVM_MR_FLAGS_ONLY:
50588c2ecf20Sopenharmony_ci		break;
50598c2ecf20Sopenharmony_ci	default:
50608c2ecf20Sopenharmony_ci		WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
50618c2ecf20Sopenharmony_ci	}
50628c2ecf20Sopenharmony_ci	if (rc)
50638c2ecf20Sopenharmony_ci		pr_warn("failed to commit memory region\n");
50648c2ecf20Sopenharmony_ci	return;
50658c2ecf20Sopenharmony_ci}
50668c2ecf20Sopenharmony_ci
50678c2ecf20Sopenharmony_cistatic inline unsigned long nonhyp_mask(int i)
50688c2ecf20Sopenharmony_ci{
50698c2ecf20Sopenharmony_ci	unsigned int nonhyp_fai = (sclp.hmfai << i * 2) >> 30;
50708c2ecf20Sopenharmony_ci
50718c2ecf20Sopenharmony_ci	return 0x0000ffffffffffffUL >> (nonhyp_fai << 4);
50728c2ecf20Sopenharmony_ci}
50738c2ecf20Sopenharmony_ci
50748c2ecf20Sopenharmony_civoid kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu)
50758c2ecf20Sopenharmony_ci{
50768c2ecf20Sopenharmony_ci	vcpu->valid_wakeup = false;
50778c2ecf20Sopenharmony_ci}
50788c2ecf20Sopenharmony_ci
50798c2ecf20Sopenharmony_cistatic int __init kvm_s390_init(void)
50808c2ecf20Sopenharmony_ci{
50818c2ecf20Sopenharmony_ci	int i;
50828c2ecf20Sopenharmony_ci
50838c2ecf20Sopenharmony_ci	if (!sclp.has_sief2) {
50848c2ecf20Sopenharmony_ci		pr_info("SIE is not available\n");
50858c2ecf20Sopenharmony_ci		return -ENODEV;
50868c2ecf20Sopenharmony_ci	}
50878c2ecf20Sopenharmony_ci
50888c2ecf20Sopenharmony_ci	if (nested && hpage) {
50898c2ecf20Sopenharmony_ci		pr_info("A KVM host that supports nesting cannot back its KVM guests with huge pages\n");
50908c2ecf20Sopenharmony_ci		return -EINVAL;
50918c2ecf20Sopenharmony_ci	}
50928c2ecf20Sopenharmony_ci
50938c2ecf20Sopenharmony_ci	for (i = 0; i < 16; i++)
50948c2ecf20Sopenharmony_ci		kvm_s390_fac_base[i] |=
50958c2ecf20Sopenharmony_ci			S390_lowcore.stfle_fac_list[i] & nonhyp_mask(i);
50968c2ecf20Sopenharmony_ci
50978c2ecf20Sopenharmony_ci	return kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
50988c2ecf20Sopenharmony_ci}
50998c2ecf20Sopenharmony_ci
51008c2ecf20Sopenharmony_cistatic void __exit kvm_s390_exit(void)
51018c2ecf20Sopenharmony_ci{
51028c2ecf20Sopenharmony_ci	kvm_exit();
51038c2ecf20Sopenharmony_ci}
51048c2ecf20Sopenharmony_ci
51058c2ecf20Sopenharmony_cimodule_init(kvm_s390_init);
51068c2ecf20Sopenharmony_cimodule_exit(kvm_s390_exit);
51078c2ecf20Sopenharmony_ci
51088c2ecf20Sopenharmony_ci/*
51098c2ecf20Sopenharmony_ci * Enable autoloading of the kvm module.
51108c2ecf20Sopenharmony_ci * Note that we add the module alias here instead of virt/kvm/kvm_main.c
51118c2ecf20Sopenharmony_ci * since x86 takes a different approach.
51128c2ecf20Sopenharmony_ci */
51138c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
51148c2ecf20Sopenharmony_ciMODULE_ALIAS_MISCDEV(KVM_MINOR);
51158c2ecf20Sopenharmony_ciMODULE_ALIAS("devname:kvm");
5116