Release 4.15 arch/s390/kvm/kvm-s390.c
// SPDX-License-Identifier: GPL-2.0
/*
* hosting IBM Z kernel virtual machines (s390x)
*
* Copyright IBM Corp. 2008, 2017
*
* Author(s): Carsten Otte <cotte@de.ibm.com>
* Christian Borntraeger <borntraeger@de.ibm.com>
* Heiko Carstens <heiko.carstens@de.ibm.com>
* Christian Ehrhardt <ehrhardt@de.ibm.com>
* Jason J. Herne <jjherne@us.ibm.com>
*/
#include <linux/compiler.h>
#include <linux/err.h>
#include <linux/fs.h>
#include <linux/hrtimer.h>
#include <linux/init.h>
#include <linux/kvm.h>
#include <linux/kvm_host.h>
#include <linux/mman.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/timer.h>
#include <linux/vmalloc.h>
#include <linux/bitmap.h>
#include <linux/sched/signal.h>
#include <linux/string.h>
#include <asm/asm-offsets.h>
#include <asm/lowcore.h>
#include <asm/stp.h>
#include <asm/pgtable.h>
#include <asm/gmap.h>
#include <asm/nmi.h>
#include <asm/switch_to.h>
#include <asm/isc.h>
#include <asm/sclp.h>
#include <asm/cpacf.h>
#include <asm/timex.h>
#include "kvm-s390.h"
#include "gaccess.h"
#define KMSG_COMPONENT "kvm-s390"
#undef pr_fmt
#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
#define CREATE_TRACE_POINTS
#include "trace.h"
#include "trace-s390.h"
#define MEM_OP_MAX_SIZE 65536
/* Maximum transfer size for KVM_S390_MEM_OP */
#define LOCAL_IRQS 32
#define VCPU_IRQS_MAX_BUF (sizeof(struct kvm_s390_irq) * \
(KVM_MAX_VCPUS + LOCAL_IRQS))
#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
struct kvm_stats_debugfs_item debugfs_entries[] = {
{ "userspace_handled", VCPU_STAT(exit_userspace) },
{ "exit_null", VCPU_STAT(exit_null) },
{ "exit_validity", VCPU_STAT(exit_validity) },
{ "exit_stop_request", VCPU_STAT(exit_stop_request) },
{ "exit_external_request", VCPU_STAT(exit_external_request) },
{ "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
{ "exit_instruction", VCPU_STAT(exit_instruction) },
{ "exit_pei", VCPU_STAT(exit_pei) },
{ "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
{ "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
{ "exit_operation_exception", VCPU_STAT(exit_operation_exception) },
{ "halt_successful_poll", VCPU_STAT(halt_successful_poll) },
{ "halt_attempted_poll", VCPU_STAT(halt_attempted_poll) },
{ "halt_poll_invalid", VCPU_STAT(halt_poll_invalid) },
{ "halt_wakeup", VCPU_STAT(halt_wakeup) },
{ "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
{ "instruction_lctl", VCPU_STAT(instruction_lctl) },
{ "instruction_stctl", VCPU_STAT(instruction_stctl) },
{ "instruction_stctg", VCPU_STAT(instruction_stctg) },
{ "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
{ "deliver_external_call", VCPU_STAT(deliver_external_call) },
{ "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
{ "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
{ "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
{ "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
{ "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
{ "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
{ "exit_wait_state", VCPU_STAT(exit_wait_state) },
{ "instruction_pfmf", VCPU_STAT(instruction_pfmf) },
{ "instruction_stidp", VCPU_STAT(instruction_stidp) },
{ "instruction_spx", VCPU_STAT(instruction_spx) },
{ "instruction_stpx", VCPU_STAT(instruction_stpx) },
{ "instruction_stap", VCPU_STAT(instruction_stap) },
{ "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
{ "instruction_ipte_interlock", VCPU_STAT(instruction_ipte_interlock) },
{ "instruction_stsch", VCPU_STAT(instruction_stsch) },
{ "instruction_chsc", VCPU_STAT(instruction_chsc) },
{ "instruction_essa", VCPU_STAT(instruction_essa) },
{ "instruction_stsi", VCPU_STAT(instruction_stsi) },
{ "instruction_stfl", VCPU_STAT(instruction_stfl) },
{ "instruction_tprot", VCPU_STAT(instruction_tprot) },
{ "instruction_sthyi", VCPU_STAT(instruction_sthyi) },
{ "instruction_sie", VCPU_STAT(instruction_sie) },
{ "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
{ "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
{ "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
{ "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
{ "instruction_sigp_cond_emergency", VCPU_STAT(instruction_sigp_cond_emergency) },
{ "instruction_sigp_start", VCPU_STAT(instruction_sigp_start) },
{ "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
{ "instruction_sigp_stop_store_status", VCPU_STAT(instruction_sigp_stop_store_status) },
{ "instruction_sigp_store_status", VCPU_STAT(instruction_sigp_store_status) },
{ "instruction_sigp_store_adtl_status", VCPU_STAT(instruction_sigp_store_adtl_status) },
{ "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
{ "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
{ "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
{ "instruction_sigp_cpu_reset", VCPU_STAT(instruction_sigp_cpu_reset) },
{ "instruction_sigp_init_cpu_reset", VCPU_STAT(instruction_sigp_init_cpu_reset) },
{ "instruction_sigp_unknown", VCPU_STAT(instruction_sigp_unknown) },
{ "diagnose_10", VCPU_STAT(diagnose_10) },
{ "diagnose_44", VCPU_STAT(diagnose_44) },
{ "diagnose_9c", VCPU_STAT(diagnose_9c) },
{ "diagnose_258", VCPU_STAT(diagnose_258) },
{ "diagnose_308", VCPU_STAT(diagnose_308) },
{ "diagnose_500", VCPU_STAT(diagnose_500) },
{ NULL }
};
struct kvm_s390_tod_clock_ext {
__u8 epoch_idx;
__u64 tod;
__u8 reserved[7];
} __packed;
/* allow nested virtualization in KVM (if enabled by user space) */
static int nested;
module_param(nested, int, S_IRUGO);
MODULE_PARM_DESC(nested, "Nested virtualization support");
/* upper facilities limit for kvm */
unsigned long kvm_s390_fac_list_mask[16] = { FACILITIES_KVM };
unsigned long kvm_s390_fac_list_mask_size(void)
{
BUILD_BUG_ON(ARRAY_SIZE(kvm_s390_fac_list_mask) > S390_ARCH_FAC_MASK_SIZE_U64);
return ARRAY_SIZE(kvm_s390_fac_list_mask);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 24 | 100.00% | 2 | 100.00% |
| Total | 24 | 100.00% | 2 | 100.00% |
/* available cpu features supported by kvm */
static DECLARE_BITMAP(kvm_s390_available_cpu_feat, KVM_S390_VM_CPU_FEAT_NR_BITS);
/* available subfunctions indicated via query / "test bit" */
static struct kvm_s390_vm_cpu_subfunc kvm_s390_available_subfunc;
static struct gmap_notifier gmap_notifier;
static struct gmap_notifier vsie_gmap_notifier;
debug_info_t *kvm_s390_dbf;
/* Section: not file related */
int kvm_arch_hardware_enable(void)
{
/* every s390 is virtualization enabled ;-) */
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 7 | 63.64% | 1 | 50.00% |
| Alexander Graf | 4 | 36.36% | 1 | 50.00% |
| Total | 11 | 100.00% | 2 | 100.00% |
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
unsigned long end);
/*
* This callback is executed during stop_machine(). All CPUs are therefore
* temporarily stopped. In order not to change guest behavior, we have to
* disable preemption whenever we touch the epoch of kvm and the VCPUs,
* so a CPU won't be stopped while calculating with the epoch.
*/
static int kvm_clock_sync(struct notifier_block *notifier, unsigned long val,
void *v)
{
struct kvm *kvm;
struct kvm_vcpu *vcpu;
int i;
unsigned long long *delta = v;
list_for_each_entry(kvm, &vm_list, vm_list) {
kvm->arch.epoch -= *delta;
kvm_for_each_vcpu(i, vcpu, kvm) {
vcpu->arch.sie_block->epoch -= *delta;
if (vcpu->arch.cputm_enabled)
vcpu->arch.cputm_start += *delta;
if (vcpu->arch.vsie_block)
vcpu->arch.vsie_block->epoch -= *delta;
}
}
return NOTIFY_OK;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Fan Zhang | 83 | 69.75% | 1 | 33.33% |
| David Hildenbrand | 36 | 30.25% | 2 | 66.67% |
| Total | 119 | 100.00% | 3 | 100.00% |
static struct notifier_block kvm_clock_notifier = {
.notifier_call = kvm_clock_sync,
};
int kvm_arch_hardware_setup(void)
{
gmap_notifier.notifier_call = kvm_gmap_notifier;
gmap_register_pte_notifier(&gmap_notifier);
vsie_gmap_notifier.notifier_call = kvm_s390_vsie_gmap_notifier;
gmap_register_pte_notifier(&vsie_gmap_notifier);
atomic_notifier_chain_register(&s390_epoch_delta_notifier,
&kvm_clock_notifier);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 12 | 27.91% | 1 | 20.00% |
| Christian Bornträger | 11 | 25.58% | 1 | 20.00% |
| Heiko Carstens | 10 | 23.26% | 1 | 20.00% |
| Fan Zhang | 9 | 20.93% | 1 | 20.00% |
| Martin Schwidefsky | 1 | 2.33% | 1 | 20.00% |
| Total | 43 | 100.00% | 5 | 100.00% |
void kvm_arch_hardware_unsetup(void)
{
gmap_unregister_pte_notifier(&gmap_notifier);
gmap_unregister_pte_notifier(&vsie_gmap_notifier);
atomic_notifier_chain_unregister(&s390_epoch_delta_notifier,
&kvm_clock_notifier);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Fan Zhang | 9 | 32.14% | 1 | 20.00% |
| Christian Bornträger | 7 | 25.00% | 1 | 20.00% |
| David Hildenbrand | 6 | 21.43% | 1 | 20.00% |
| Heiko Carstens | 5 | 17.86% | 1 | 20.00% |
| Martin Schwidefsky | 1 | 3.57% | 1 | 20.00% |
| Total | 28 | 100.00% | 5 | 100.00% |
static void allow_cpu_feat(unsigned long nr)
{
set_bit_inv(nr, kvm_s390_available_cpu_feat);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 9 | 52.94% | 1 | 33.33% |
| Christian Bornträger | 4 | 23.53% | 1 | 33.33% |
| Heiko Carstens | 4 | 23.53% | 1 | 33.33% |
| Total | 17 | 100.00% | 3 | 100.00% |
static inline int plo_test_bit(unsigned char nr)
{
register unsigned long r0 asm("0") = (unsigned long) nr | 0x100;
int cc;
asm volatile(
/* Parameter registers are ignored for "test bit" */
" plo 0,0,0,0(0)\n"
" ipm %0\n"
" srl %0,28\n"
: "=d" (cc)
: "d" (r0)
: "cc");
return cc == 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 31 | 75.61% | 1 | 33.33% |
| Christian Bornträger | 5 | 12.20% | 1 | 33.33% |
| Heiko Carstens | 5 | 12.20% | 1 | 33.33% |
| Total | 41 | 100.00% | 3 | 100.00% |
static void kvm_s390_cpu_feat_init(void)
{
int i;
for (i = 0; i < 256; ++i) {
if (plo_test_bit(i))
kvm_s390_available_subfunc.plo[i >> 3] |= 0x80 >> (i & 7);
}
if (test_facility(28)) /* TOD-clock steering */
ptff(kvm_s390_available_subfunc.ptff,
sizeof(kvm_s390_available_subfunc.ptff),
PTFF_QAF);
if (test_facility(17)) { /* MSA */
__cpacf_query(CPACF_KMAC, (cpacf_mask_t *)
kvm_s390_available_subfunc.kmac);
__cpacf_query(CPACF_KMC, (cpacf_mask_t *)
kvm_s390_available_subfunc.kmc);
__cpacf_query(CPACF_KM, (cpacf_mask_t *)
kvm_s390_available_subfunc.km);
__cpacf_query(CPACF_KIMD, (cpacf_mask_t *)
kvm_s390_available_subfunc.kimd);
__cpacf_query(CPACF_KLMD, (cpacf_mask_t *)
kvm_s390_available_subfunc.klmd);
}
if (test_facility(76)) /* MSA3 */
__cpacf_query(CPACF_PCKMO, (cpacf_mask_t *)
kvm_s390_available_subfunc.pckmo);
if (test_facility(77)) { /* MSA4 */
__cpacf_query(CPACF_KMCTR, (cpacf_mask_t *)
kvm_s390_available_subfunc.kmctr);
__cpacf_query(CPACF_KMF, (cpacf_mask_t *)
kvm_s390_available_subfunc.kmf);
__cpacf_query(CPACF_KMO, (cpacf_mask_t *)
kvm_s390_available_subfunc.kmo);
__cpacf_query(CPACF_PCC, (cpacf_mask_t *)
kvm_s390_available_subfunc.pcc);
}
if (test_facility(57)) /* MSA5 */
__cpacf_query(CPACF_PRNO, (cpacf_mask_t *)
kvm_s390_available_subfunc.ppno);
if (test_facility(146)) /* MSA8 */
__cpacf_query(CPACF_KMA, (cpacf_mask_t *)
kvm_s390_available_subfunc.kma);
if (MACHINE_HAS_ESOP)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_ESOP);
/*
* We need SIE support, ESOP (PROT_READ protection for gmap_shadow),
* 64bit SCAO (SCA passthrough) and IDTE (for gmap_shadow unshadowing).
*/
if (!sclp.has_sief2 || !MACHINE_HAS_ESOP || !sclp.has_64bscao ||
!test_facility(3) || !nested)
return;
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIEF2);
if (sclp.has_64bscao)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_64BSCAO);
if (sclp.has_siif)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_SIIF);
if (sclp.has_gpere)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GPERE);
if (sclp.has_gsls)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_GSLS);
if (sclp.has_ib)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IB);
if (sclp.has_cei)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_CEI);
if (sclp.has_ibs)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_IBS);
if (sclp.has_kss)
allow_cpu_feat(KVM_S390_VM_CPU_FEAT_KSS);
/*
* KVM_S390_VM_CPU_FEAT_SKEY: Wrong shadow of PTE.I bits will make
* all skey handling functions read/set the skey from the PGSTE
* instead of the real storage key.
*
* KVM_S390_VM_CPU_FEAT_CMMA: Wrong shadow of PTE.I bits will make
* pages being detected as preserved although they are resident.
*
* KVM_S390_VM_CPU_FEAT_PFMFI: Wrong shadow of PTE.I bits will
* have the same effect as for KVM_S390_VM_CPU_FEAT_SKEY.
*
* For KVM_S390_VM_CPU_FEAT_SKEY, KVM_S390_VM_CPU_FEAT_CMMA and
* KVM_S390_VM_CPU_FEAT_PFMFI, all PTE.I and PGSTE bits have to be
* correctly shadowed. We can do that for the PGSTE but not for PTE.I.
*
* KVM_S390_VM_CPU_FEAT_SIGPIF: Wrong SCB addresses in the SCA. We
* cannot easily shadow the SCA because of the ipte lock.
*/
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 316 | 78.41% | 12 | 66.67% |
| Martin Schwidefsky | 44 | 10.92% | 1 | 5.56% |
| Jason J. Herne | 21 | 5.21% | 1 | 5.56% |
| Farhan Ali | 11 | 2.73% | 1 | 5.56% |
| Linus Torvalds | 9 | 2.23% | 1 | 5.56% |
| Harald Freudenberger | 1 | 0.25% | 1 | 5.56% |
| Heiko Carstens | 1 | 0.25% | 1 | 5.56% |
| Total | 403 | 100.00% | 18 | 100.00% |
int kvm_arch_init(void *opaque)
{
kvm_s390_dbf = debug_register("kvm-trace", 32, 1, 7 * sizeof(long));
if (!kvm_s390_dbf)
return -ENOMEM;
if (debug_register_view(kvm_s390_dbf, &debug_sprintf_view)) {
debug_unregister(kvm_s390_dbf);
return -ENOMEM;
}
kvm_s390_cpu_feat_init();
/* Register floating interrupt controller interface. */
return kvm_register_device_ops(&kvm_flic_ops, KVM_DEV_TYPE_FLIC);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 48 | 68.57% | 1 | 25.00% |
| Heiko Carstens | 11 | 15.71% | 1 | 25.00% |
| Cornelia Huck | 8 | 11.43% | 1 | 25.00% |
| David Hildenbrand | 3 | 4.29% | 1 | 25.00% |
| Total | 70 | 100.00% | 4 | 100.00% |
void kvm_arch_exit(void)
{
debug_unregister(kvm_s390_dbf);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 12 | 100.00% | 1 | 100.00% |
| Total | 12 | 100.00% | 1 | 100.00% |
/* Section: device related */
long kvm_arch_dev_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
if (ioctl == KVM_S390_ENABLE_SIE)
return s390_enable_sie();
return -EINVAL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 32 | 100.00% | 1 | 100.00% |
| Total | 32 | 100.00% | 1 | 100.00% |
int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
{
int r;
switch (ext) {
case KVM_CAP_S390_PSW:
case KVM_CAP_S390_GMAP:
case KVM_CAP_SYNC_MMU:
#ifdef CONFIG_KVM_S390_UCONTROL
case KVM_CAP_S390_UCONTROL:
#endif
case KVM_CAP_ASYNC_PF:
case KVM_CAP_SYNC_REGS:
case KVM_CAP_ONE_REG:
case KVM_CAP_ENABLE_CAP:
case KVM_CAP_S390_CSS_SUPPORT:
case KVM_CAP_IOEVENTFD:
case KVM_CAP_DEVICE_CTRL:
case KVM_CAP_ENABLE_CAP_VM:
case KVM_CAP_S390_IRQCHIP:
case KVM_CAP_VM_ATTRIBUTES:
case KVM_CAP_MP_STATE:
case KVM_CAP_IMMEDIATE_EXIT:
case KVM_CAP_S390_INJECT_IRQ:
case KVM_CAP_S390_USER_SIGP:
case KVM_CAP_S390_USER_STSI:
case KVM_CAP_S390_SKEYS:
case KVM_CAP_S390_IRQ_STATE:
case KVM_CAP_S390_USER_INSTR0:
case KVM_CAP_S390_CMMA_MIGRATION:
case KVM_CAP_S390_AIS:
case KVM_CAP_S390_AIS_MIGRATION:
r = 1;
break;
case KVM_CAP_S390_MEM_OP:
r = MEM_OP_MAX_SIZE;
break;
case KVM_CAP_NR_VCPUS:
case KVM_CAP_MAX_VCPUS:
r = KVM_S390_BSCA_CPU_SLOTS;
if (!kvm_s390_use_sca_entries())
r = KVM_MAX_VCPUS;
else if (sclp.has_esca && sclp.has_64bscao)
r = KVM_S390_ESCA_CPU_SLOTS;
break;
case KVM_CAP_NR_MEMSLOTS:
r = KVM_USER_MEM_SLOTS;
break;
case KVM_CAP_S390_COW:
r = MACHINE_HAS_ESOP;
break;
case KVM_CAP_S390_VECTOR_REGISTERS:
r = MACHINE_HAS_VX;
break;
case KVM_CAP_S390_RI:
r = test_facility(64);
break;
case KVM_CAP_S390_GS:
r = test_facility(133);
break;
case KVM_CAP_S390_BPB:
r = test_facility(82);
break;
default:
r = 0;
}
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 40 | 18.52% | 7 | 17.50% |
| Carsten Otte | 35 | 16.20% | 4 | 10.00% |
| David Hildenbrand | 31 | 14.35% | 5 | 12.50% |
| Fan Zhang | 22 | 10.19% | 2 | 5.00% |
| Cornelia Huck | 15 | 6.94% | 5 | 12.50% |
| Jens Freimann | 9 | 4.17% | 3 | 7.50% |
| Heiko Carstens | 8 | 3.70% | 1 | 2.50% |
| Nick Wang | 8 | 3.70% | 1 | 2.50% |
| Thomas Huth | 8 | 3.70% | 1 | 2.50% |
| Eric Farman | 8 | 3.70% | 1 | 2.50% |
| Alexander Graf | 6 | 2.78% | 1 | 2.50% |
| Dominik Dingel | 6 | 2.78% | 2 | 5.00% |
| Eugene (jno) Dvurechenski | 4 | 1.85% | 1 | 2.50% |
| Jason J. Herne | 3 | 1.39% | 1 | 2.50% |
| Paolo Bonzini | 3 | 1.39% | 1 | 2.50% |
| Yi Min Zhao | 3 | 1.39% | 1 | 2.50% |
| Claudio Imbrenda | 3 | 1.39% | 1 | 2.50% |
| Ekaterina Tumanova | 3 | 1.39% | 1 | 2.50% |
| Martin Schwidefsky | 1 | 0.46% | 1 | 2.50% |
| Total | 216 | 100.00% | 40 | 100.00% |
static void kvm_s390_sync_dirty_log(struct kvm *kvm,
struct kvm_memory_slot *memslot)
{
gfn_t cur_gfn, last_gfn;
unsigned long address;
struct gmap *gmap = kvm->arch.gmap;
/* Loop over all guest pages */
last_gfn = memslot->base_gfn + memslot->npages;
for (cur_gfn = memslot->base_gfn; cur_gfn <= last_gfn; cur_gfn++) {
address = gfn_to_hva_memslot(memslot, cur_gfn);
if (test_and_clear_guest_dirty(gmap->mm, address))
mark_page_dirty(kvm, cur_gfn);
if (fatal_signal_pending(current))
return;
cond_resched();
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 89 | 87.25% | 1 | 20.00% |
| Christian Bornträger | 8 | 7.84% | 2 | 40.00% |
| Martin Schwidefsky | 5 | 4.90% | 2 | 40.00% |
| Total | 102 | 100.00% | 5 | 100.00% |
/* Section: vm related */
static void sca_del_vcpu(struct kvm_vcpu *vcpu);
/*
* Get (and clear) the dirty memory log for a memory slot.
*/
int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
struct kvm_dirty_log *log)
{
int r;
unsigned long n;
struct kvm_memslots *slots;
struct kvm_memory_slot *memslot;
int is_dirty = 0;
if (kvm_is_ucontrol(kvm))
return -EINVAL;
mutex_lock(&kvm->slots_lock);
r = -EINVAL;
if (log->slot >= KVM_USER_MEM_SLOTS)
goto out;
slots = kvm_memslots(kvm);
memslot = id_to_memslot(slots, log->slot);
r = -ENOENT;
if (!memslot->dirty_bitmap)
goto out;
kvm_s390_sync_dirty_log(kvm, memslot);
r = kvm_get_dirty_log(kvm, log, &is_dirty);
if (r)
goto out;
/* Clear the dirty log */
if (is_dirty) {
n = kvm_dirty_bitmap_bytes(memslot);
memset(memslot->dirty_bitmap, 0, n);
}
r = 0;
out:
mutex_unlock(&kvm->slots_lock);
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 131 | 75.72% | 1 | 25.00% |
| Heiko Carstens | 18 | 10.40% | 1 | 25.00% |
| Paolo Bonzini | 13 | 7.51% | 1 | 25.00% |
| Janosch Frank | 11 | 6.36% | 1 | 25.00% |
| Total | 173 | 100.00% | 4 | 100.00% |
static void icpt_operexc_on_all_vcpus(struct kvm *kvm)
{
unsigned int i;
struct kvm_vcpu *vcpu;
kvm_for_each_vcpu(i, vcpu, kvm) {
kvm_s390_sync_request(KVM_REQ_ICPT_OPEREXC, vcpu);
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 37 | 100.00% | 1 | 100.00% |
| Total | 37 | 100.00% | 1 | 100.00% |
static int kvm_vm_ioctl_enable_cap(struct kvm *kvm, struct kvm_enable_cap *cap)
{
int r;
if (cap->flags)
return -EINVAL;
switch (cap->cap) {
case KVM_CAP_S390_IRQCHIP:
VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_IRQCHIP");
kvm->arch.use_irqchip = 1;
r = 0;
break;
case KVM_CAP_S390_USER_SIGP:
VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_SIGP");
kvm->arch.user_sigp = 1;
r = 0;
break;
case KVM_CAP_S390_VECTOR_REGISTERS:
mutex_lock(&kvm->lock);
if (kvm->created_vcpus) {
r = -EBUSY;
} else if (MACHINE_HAS_VX) {
set_kvm_facility(kvm->arch.model.fac_mask, 129);
set_kvm_facility(kvm->arch.model.fac_list, 129);
if (test_facility(134)) {
set_kvm_facility(kvm->arch.model.fac_mask, 134);
set_kvm_facility(kvm->arch.model.fac_list, 134);
}
if (test_facility(135)) {
set_kvm_facility(kvm->arch.model.fac_mask, 135);
set_kvm_facility(kvm->arch.model.fac_list, 135);
}
r = 0;
} else
r = -EINVAL;
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "ENABLE: CAP_S390_VECTOR_REGISTERS %s",
r ? "(not available)" : "(success)");
break;
case KVM_CAP_S390_RI:
r = -EINVAL;
mutex_lock(&kvm->lock);
if (kvm->created_vcpus) {
r = -EBUSY;
} else if (test_facility(64)) {
set_kvm_facility(kvm->arch.model.fac_mask, 64);
set_kvm_facility(kvm->arch.model.fac_list, 64);
r = 0;
}
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "ENABLE: CAP_S390_RI %s",
r ? "(not available)" : "(success)");
break;
case KVM_CAP_S390_AIS:
mutex_lock(&kvm->lock);
if (kvm->created_vcpus) {
r = -EBUSY;
} else {
set_kvm_facility(kvm->arch.model.fac_mask, 72);
set_kvm_facility(kvm->arch.model.fac_list, 72);
r = 0;
}
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "ENABLE: AIS %s",
r ? "(not available)" : "(success)");
break;
case KVM_CAP_S390_GS:
r = -EINVAL;
mutex_lock(&kvm->lock);
if (atomic_read(&kvm->online_vcpus)) {
r = -EBUSY;
} else if (test_facility(133)) {
set_kvm_facility(kvm->arch.model.fac_mask, 133);
set_kvm_facility(kvm->arch.model.fac_list, 133);
r = 0;
}
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "ENABLE: CAP_S390_GS %s",
r ? "(not available)" : "(success)");
break;
case KVM_CAP_S390_USER_STSI:
VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_STSI");
kvm->arch.user_stsi = 1;
r = 0;
break;
case KVM_CAP_S390_USER_INSTR0:
VM_EVENT(kvm, 3, "%s", "ENABLE: CAP_S390_USER_INSTR0");
kvm->arch.user_instr0 = 1;
icpt_operexc_on_all_vcpus(kvm);
r = 0;
break;
default:
r = -EINVAL;
break;
}
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Fan Zhang | 187 | 31.59% | 2 | 12.50% |
| Yi Min Zhao | 81 | 13.68% | 1 | 6.25% |
| David Hildenbrand | 81 | 13.68% | 4 | 25.00% |
| Cornelia Huck | 63 | 10.64% | 2 | 12.50% |
| Christian Bornträger | 48 | 8.11% | 1 | 6.25% |
| Maxim Samoylov | 35 | 5.91% | 1 | 6.25% |
| Guenther Hutzl | 35 | 5.91% | 1 | 6.25% |
| Michael Müller | 29 | 4.90% | 1 | 6.25% |
| Ekaterina Tumanova | 16 | 2.70% | 1 | 6.25% |
| Eric Farman | 15 | 2.53% | 1 | 6.25% |
| Paolo Bonzini | 2 | 0.34% | 1 | 6.25% |
| Total | 592 | 100.00% | 16 | 100.00% |
static int kvm_s390_get_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
switch (attr->attr) {
case KVM_S390_VM_MEM_LIMIT_SIZE:
ret = 0;
VM_EVENT(kvm, 3, "QUERY: max guest memory: %lu bytes",
kvm->arch.mem_limit);
if (put_user(kvm->arch.mem_limit, (u64 __user *)attr->addr))
ret = -EFAULT;
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 71 | 83.53% | 3 | 75.00% |
| Christian Bornträger | 14 | 16.47% | 1 | 25.00% |
| Total | 85 | 100.00% | 4 | 100.00% |
static int kvm_s390_set_mem_control(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
unsigned int idx;
switch (attr->attr) {
case KVM_S390_VM_MEM_ENABLE_CMMA:
ret = -ENXIO;
if (!sclp.has_cmma)
break;
ret = -EBUSY;
VM_EVENT(kvm, 3, "%s", "ENABLE: CMMA support");
mutex_lock(&kvm->lock);
if (!kvm->created_vcpus) {
kvm->arch.use_cmma = 1;
ret = 0;
}
mutex_unlock(&kvm->lock);
break;
case KVM_S390_VM_MEM_CLR_CMMA:
ret = -ENXIO;
if (!sclp.has_cmma)
break;
ret = -EINVAL;
if (!kvm->arch.use_cmma)
break;
VM_EVENT(kvm, 3, "%s", "RESET: CMMA states");
mutex_lock(&kvm->lock);
idx = srcu_read_lock(&kvm->srcu);
s390_reset_cmma(kvm->arch.gmap->mm);
srcu_read_unlock(&kvm->srcu, idx);
mutex_unlock(&kvm->lock);
ret = 0;
break;
case KVM_S390_VM_MEM_LIMIT_SIZE: {
unsigned long new_limit;
if (kvm_is_ucontrol(kvm))
return -EINVAL;
if (get_user(new_limit, (u64 __user *)attr->addr))
return -EFAULT;
if (kvm->arch.mem_limit != KVM_S390_NO_MEM_LIMIT &&
new_limit > kvm->arch.mem_limit)
return -E2BIG;
if (!new_limit)
return -EINVAL;
/* gmap_create takes last usable address */
if (new_limit != KVM_S390_NO_MEM_LIMIT)
new_limit -= 1;
ret = -EBUSY;
mutex_lock(&kvm->lock);
if (!kvm->created_vcpus) {
/* gmap_create will round the limit up */
struct gmap *new = gmap_create(current->mm, new_limit);
if (!new) {
ret = -ENOMEM;
} else {
gmap_remove(kvm->arch.gmap);
new->private = kvm;
kvm->arch.gmap = new;
ret = 0;
}
}
mutex_unlock(&kvm->lock);
VM_EVENT(kvm, 3, "SET: max guest address: %lu", new_limit);
VM_EVENT(kvm, 3, "New guest asce: 0x%pK",
(void *) kvm->arch.gmap->asce);
break;
}
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 289 | 71.01% | 6 | 40.00% |
| Christian Bornträger | 32 | 7.86% | 1 | 6.67% |
| Cornelia Huck | 26 | 6.39% | 2 | 13.33% |
| Heiko Carstens | 21 | 5.16% | 1 | 6.67% |
| David Hildenbrand | 17 | 4.18% | 2 | 13.33% |
| Carsten Otte | 14 | 3.44% | 1 | 6.67% |
| Paolo Bonzini | 4 | 0.98% | 1 | 6.67% |
| Martin Schwidefsky | 4 | 0.98% | 1 | 6.67% |
| Total | 407 | 100.00% | 15 | 100.00% |
static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu);
static int kvm_s390_vm_set_crypto(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_vcpu *vcpu;
int i;
if (!test_kvm_facility(kvm, 76))
return -EINVAL;
mutex_lock(&kvm->lock);
switch (attr->attr) {
case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
get_random_bytes(
kvm->arch.crypto.crycb->aes_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
kvm->arch.crypto.aes_kw = 1;
VM_EVENT(kvm, 3, "%s", "ENABLE: AES keywrapping support");
break;
case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
get_random_bytes(
kvm->arch.crypto.crycb->dea_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
kvm->arch.crypto.dea_kw = 1;
VM_EVENT(kvm, 3, "%s", "ENABLE: DEA keywrapping support");
break;
case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
kvm->arch.crypto.aes_kw = 0;
memset(kvm->arch.crypto.crycb->aes_wrapping_key_mask, 0,
sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
VM_EVENT(kvm, 3, "%s", "DISABLE: AES keywrapping support");
break;
case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
kvm->arch.crypto.dea_kw = 0;
memset(kvm->arch.crypto.crycb->dea_wrapping_key_mask, 0,
sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
VM_EVENT(kvm, 3, "%s", "DISABLE: DEA keywrapping support");
break;
default:
mutex_unlock(&kvm->lock);
return -ENXIO;
}
kvm_for_each_vcpu(i, vcpu, kvm) {
kvm_s390_vcpu_crypto_setup(vcpu);
exit_sie(vcpu);
}
mutex_unlock(&kvm->lock);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 259 | 84.64% | 1 | 33.33% |
| Christian Bornträger | 44 | 14.38% | 1 | 33.33% |
| Michael Müller | 3 | 0.98% | 1 | 33.33% |
| Total | 306 | 100.00% | 3 | 100.00% |
static void kvm_s390_sync_request_broadcast(struct kvm *kvm, int req)
{
int cx;
struct kvm_vcpu *vcpu;
kvm_for_each_vcpu(cx, vcpu, kvm)
kvm_s390_sync_request(req, vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 18 | 48.65% | 1 | 33.33% |
| Jason J. Herne | 15 | 40.54% | 1 | 33.33% |
| Christian Bornträger | 4 | 10.81% | 1 | 33.33% |
| Total | 37 | 100.00% | 3 | 100.00% |
/*
* Must be called with kvm->srcu held to avoid races on memslots, and with
* kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
*/
static int kvm_s390_vm_start_migration(struct kvm *kvm)
{
struct kvm_s390_migration_state *mgs;
struct kvm_memory_slot *ms;
/* should be the only one */
struct kvm_memslots *slots;
unsigned long ram_pages;
int slotnr;
/* migration mode already enabled */
if (kvm->arch.migration_state)
return 0;
slots = kvm_memslots(kvm);
if (!slots || !slots->used_slots)
return -EINVAL;
mgs = kzalloc(sizeof(*mgs), GFP_KERNEL);
if (!mgs)
return -ENOMEM;
kvm->arch.migration_state = mgs;
if (kvm->arch.use_cmma) {
/*
* Get the first slot. They are reverse sorted by base_gfn, so
* the first slot is also the one at the end of the address
* space. We have verified above that at least one slot is
* present.
*/
ms = slots->memslots;
/* round up so we only use full longs */
ram_pages = roundup(ms->base_gfn + ms->npages, BITS_PER_LONG);
/* allocate enough bytes to store all the bits */
mgs->pgste_bitmap = vmalloc(ram_pages / 8);
if (!mgs->pgste_bitmap) {
kfree(mgs);
kvm->arch.migration_state = NULL;
return -ENOMEM;
}
mgs->bitmap_size = ram_pages;
atomic64_set(&mgs->dirty_pages, ram_pages);
/* mark all the pages in active slots as dirty */
for (slotnr = 0; slotnr < slots->used_slots; slotnr++) {
ms = slots->memslots + slotnr;
bitmap_set(mgs->pgste_bitmap, ms->base_gfn, ms->npages);
}
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_START_MIGRATION);
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 171 | 72.77% | 1 | 20.00% |
| Jason J. Herne | 52 | 22.13% | 1 | 20.00% |
| Christian Bornträger | 12 | 5.11% | 3 | 60.00% |
| Total | 235 | 100.00% | 5 | 100.00% |
/*
* Must be called with kvm->slots_lock to avoid races with ourselves and
* kvm_s390_vm_start_migration.
*/
static int kvm_s390_vm_stop_migration(struct kvm *kvm)
{
struct kvm_s390_migration_state *mgs;
/* migration mode already disabled */
if (!kvm->arch.migration_state)
return 0;
mgs = kvm->arch.migration_state;
kvm->arch.migration_state = NULL;
if (kvm->arch.use_cmma) {
kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
/* We have to wait for the essa emulation to finish */
synchronize_srcu(&kvm->srcu);
vfree(mgs->pgste_bitmap);
}
kfree(mgs);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 51 | 59.30% | 1 | 20.00% |
| Jason J. Herne | 20 | 23.26% | 1 | 20.00% |
| Christian Bornträger | 14 | 16.28% | 2 | 40.00% |
| Fan Zhang | 1 | 1.16% | 1 | 20.00% |
| Total | 86 | 100.00% | 5 | 100.00% |
static int kvm_s390_vm_set_migration(struct kvm *kvm,
struct kvm_device_attr *attr)
{
int res = -ENXIO;
mutex_lock(&kvm->slots_lock);
switch (attr->attr) {
case KVM_S390_VM_MIGRATION_START:
res = kvm_s390_vm_start_migration(kvm);
break;
case KVM_S390_VM_MIGRATION_STOP:
res = kvm_s390_vm_stop_migration(kvm);
break;
default:
break;
}
mutex_unlock(&kvm->slots_lock);
return res;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 41 | 56.16% | 1 | 25.00% |
| Claudio Imbrenda | 21 | 28.77% | 1 | 25.00% |
| Tony Krowiak | 9 | 12.33% | 1 | 25.00% |
| Christian Bornträger | 2 | 2.74% | 1 | 25.00% |
| Total | 73 | 100.00% | 4 | 100.00% |
static int kvm_s390_vm_get_migration(struct kvm *kvm,
struct kvm_device_attr *attr)
{
u64 mig = (kvm->arch.migration_state != NULL);
if (attr->attr != KVM_S390_VM_MIGRATION_STATUS)
return -ENXIO;
if (copy_to_user((void __user *)attr->addr, &mig, sizeof(mig)))
return -EFAULT;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 33 | 47.14% | 1 | 33.33% |
| Michael Müller | 30 | 42.86% | 1 | 33.33% |
| Tony Krowiak | 7 | 10.00% | 1 | 33.33% |
| Total | 70 | 100.00% | 3 | 100.00% |
static int kvm_s390_set_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_s390_vm_tod_clock gtod;
if (copy_from_user(>od, (void __user *)attr->addr, sizeof(gtod)))
return -EFAULT;
if (test_kvm_facility(kvm, 139))
kvm_s390_set_tod_clock_ext(kvm, >od);
else if (gtod.epoch_idx == 0)
kvm_s390_set_tod_clock(kvm, gtod.tod);
else
return -EINVAL;
VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x, TOD base: 0x%llx",
gtod.epoch_idx, gtod.tod);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Collin L. Walling | 106 | 100.00% | 1 | 100.00% |
| Total | 106 | 100.00% | 1 | 100.00% |
static int kvm_s390_set_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
{
u8 gtod_high;
if (copy_from_user(>od_high, (void __user *)attr->addr,
sizeof(gtod_high)))
return -EFAULT;
if (gtod_high != 0)
return -EINVAL;
VM_EVENT(kvm, 3, "SET: TOD extension: 0x%x", gtod_high);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 36 | 52.17% | 1 | 16.67% |
| Michael Müller | 19 | 27.54% | 1 | 16.67% |
| Christian Bornträger | 11 | 15.94% | 3 | 50.00% |
| David Hildenbrand | 3 | 4.35% | 1 | 16.67% |
| Total | 69 | 100.00% | 6 | 100.00% |
static int kvm_s390_set_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
{
u64 gtod;
if (copy_from_user(>od, (void __user *)attr->addr, sizeof(gtod)))
return -EFAULT;
kvm_s390_set_tod_clock(kvm, gtod);
VM_EVENT(kvm, 3, "SET: TOD base: 0x%llx", gtod);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 41 | 62.12% | 4 | 44.44% |
| Jason J. Herne | 12 | 18.18% | 1 | 11.11% |
| Michael Müller | 7 | 10.61% | 1 | 11.11% |
| Christian Bornträger | 6 | 9.09% | 3 | 33.33% |
| Total | 66 | 100.00% | 9 | 100.00% |
static int kvm_s390_set_tod(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
if (attr->flags)
return -EINVAL;
switch (attr->attr) {
case KVM_S390_VM_TOD_EXT:
ret = kvm_s390_set_tod_ext(kvm, attr);
break;
case KVM_S390_VM_TOD_HIGH:
ret = kvm_s390_set_tod_high(kvm, attr);
break;
case KVM_S390_VM_TOD_LOW:
ret = kvm_s390_set_tod_low(kvm, attr);
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 40 | 46.51% | 1 | 20.00% |
| Jason J. Herne | 18 | 20.93% | 1 | 20.00% |
| David Hildenbrand | 15 | 17.44% | 2 | 40.00% |
| Collin L. Walling | 13 | 15.12% | 1 | 20.00% |
| Total | 86 | 100.00% | 5 | 100.00% |
static void kvm_s390_get_tod_clock_ext(struct kvm *kvm,
struct kvm_s390_vm_tod_clock *gtod)
{
struct kvm_s390_tod_clock_ext htod;
preempt_disable();
get_tod_clock_ext((char *)&htod);
gtod->tod = htod.tod + kvm->arch.epoch;
gtod->epoch_idx = htod.epoch_idx + kvm->arch.epdx;
if (gtod->tod < htod.tod)
gtod->epoch_idx += 1;
preempt_enable();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Collin L. Walling | 80 | 100.00% | 1 | 100.00% |
| Total | 80 | 100.00% | 1 | 100.00% |
static int kvm_s390_get_tod_ext(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_s390_vm_tod_clock gtod;
memset(>od, 0, sizeof(gtod));
if (test_kvm_facility(kvm, 139))
kvm_s390_get_tod_clock_ext(kvm, >od);
else
gtod.tod = kvm_s390_get_tod_clock_fast(kvm);
if (copy_to_user((void __user *)attr->addr, >od, sizeof(gtod)))
return -EFAULT;
VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x, TOD base: 0x%llx",
gtod.epoch_idx, gtod.tod);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Collin L. Walling | 101 | 95.28% | 1 | 33.33% |
| Michael Müller | 3 | 2.83% | 1 | 33.33% |
| David Hildenbrand | 2 | 1.89% | 1 | 33.33% |
| Total | 106 | 100.00% | 3 | 100.00% |
static int kvm_s390_get_tod_high(struct kvm *kvm, struct kvm_device_attr *attr)
{
u8 gtod_high = 0;
if (copy_to_user((void __user *)attr->addr, >od_high,
sizeof(gtod_high)))
return -EFAULT;
VM_EVENT(kvm, 3, "QUERY: TOD extension: 0x%x", gtod_high);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 25 | 40.98% | 1 | 20.00% |
| Michael Müller | 24 | 39.34% | 1 | 20.00% |
| Christian Bornträger | 12 | 19.67% | 3 | 60.00% |
| Total | 61 | 100.00% | 5 | 100.00% |
static int kvm_s390_get_tod_low(struct kvm *kvm, struct kvm_device_attr *attr)
{
u64 gtod;
gtod = kvm_s390_get_tod_clock_fast(kvm);
if (copy_to_user((void __user *)attr->addr, >od, sizeof(gtod)))
return -EFAULT;
VM_EVENT(kvm, 3, "QUERY: TOD base: 0x%llx", gtod);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 27 | 40.91% | 1 | 16.67% |
| Jason J. Herne | 25 | 37.88% | 1 | 16.67% |
| Christian Bornträger | 12 | 18.18% | 3 | 50.00% |
| David Hildenbrand | 2 | 3.03% | 1 | 16.67% |
| Total | 66 | 100.00% | 6 | 100.00% |
static int kvm_s390_get_tod(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
if (attr->flags)
return -EINVAL;
switch (attr->attr) {
case KVM_S390_VM_TOD_EXT:
ret = kvm_s390_get_tod_ext(kvm, attr);
break;
case KVM_S390_VM_TOD_HIGH:
ret = kvm_s390_get_tod_high(kvm, attr);
break;
case KVM_S390_VM_TOD_LOW:
ret = kvm_s390_get_tod_low(kvm, attr);
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 41 | 47.67% | 1 | 25.00% |
| Michael Müller | 32 | 37.21% | 2 | 50.00% |
| Collin L. Walling | 13 | 15.12% | 1 | 25.00% |
| Total | 86 | 100.00% | 4 | 100.00% |
static int kvm_s390_set_processor(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_processor *proc;
u16 lowest_ibc, unblocked_ibc;
int ret = 0;
mutex_lock(&kvm->lock);
if (kvm->created_vcpus) {
ret = -EBUSY;
goto out;
}
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (!proc) {
ret = -ENOMEM;
goto out;
}
if (!copy_from_user(proc, (void __user *)attr->addr,
sizeof(*proc))) {
kvm->arch.model.cpuid = proc->cpuid;
lowest_ibc = sclp.ibc >> 16 & 0xfff;
unblocked_ibc = sclp.ibc & 0xfff;
if (lowest_ibc && proc->ibc) {
if (proc->ibc > unblocked_ibc)
kvm->arch.model.ibc = unblocked_ibc;
else if (proc->ibc < lowest_ibc)
kvm->arch.model.ibc = lowest_ibc;
else
kvm->arch.model.ibc = proc->ibc;
}
memcpy(kvm->arch.model.fac_list, proc->fac_list,
S390_ARCH_FAC_LIST_SIZE_BYTE);
VM_EVENT(kvm, 3, "SET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx",
kvm->arch.model.ibc,
kvm->arch.model.cpuid);
VM_EVENT(kvm, 3, "SET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx",
kvm->arch.model.fac_list[0],
kvm->arch.model.fac_list[1],
kvm->arch.model.fac_list[2]);
} else
ret = -EFAULT;
kfree(proc);
out:
mutex_unlock(&kvm->lock);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 161 | 52.61% | 1 | 12.50% |
| David Hildenbrand | 74 | 24.18% | 4 | 50.00% |
| Christian Bornträger | 70 | 22.88% | 2 | 25.00% |
| Paolo Bonzini | 1 | 0.33% | 1 | 12.50% |
| Total | 306 | 100.00% | 8 | 100.00% |
static int kvm_s390_set_processor_feat(struct kvm *kvm,
struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_feat data;
int ret = -EBUSY;
if (copy_from_user(&data, (void __user *)attr->addr, sizeof(data)))
return -EFAULT;
if (!bitmap_subset((unsigned long *) data.feat,
kvm_s390_available_cpu_feat,
KVM_S390_VM_CPU_FEAT_NR_BITS))
return -EINVAL;
mutex_lock(&kvm->lock);
if (!atomic_read(&kvm->online_vcpus)) {
bitmap_copy(kvm->arch.cpu_feat, (unsigned long *) data.feat,
KVM_S390_VM_CPU_FEAT_NR_BITS);
ret = 0;
}
mutex_unlock(&kvm->lock);
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 99 | 75.57% | 2 | 66.67% |
| Michael Müller | 32 | 24.43% | 1 | 33.33% |
| Total | 131 | 100.00% | 3 | 100.00% |
static int kvm_s390_set_processor_subfunc(struct kvm *kvm,
struct kvm_device_attr *attr)
{
/*
* Once supported by kernel + hw, we have to store the subfunctions
* in kvm->arch and remember that user space configured them.
*/
return -ENXIO;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 21 | 100.00% | 1 | 100.00% |
| Total | 21 | 100.00% | 1 | 100.00% |
static int kvm_s390_set_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret = -ENXIO;
switch (attr->attr) {
case KVM_S390_VM_CPU_PROCESSOR:
ret = kvm_s390_set_processor(kvm, attr);
break;
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
ret = kvm_s390_set_processor_feat(kvm, attr);
break;
case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
ret = kvm_s390_set_processor_subfunc(kvm, attr);
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 44 | 61.11% | 2 | 66.67% |
| Michael Müller | 28 | 38.89% | 1 | 33.33% |
| Total | 72 | 100.00% | 3 | 100.00% |
static int kvm_s390_get_processor(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_processor *proc;
int ret = 0;
proc = kzalloc(sizeof(*proc), GFP_KERNEL);
if (!proc) {
ret = -ENOMEM;
goto out;
}
proc->cpuid = kvm->arch.model.cpuid;
proc->ibc = kvm->arch.model.ibc;
memcpy(&proc->fac_list, kvm->arch.model.fac_list,
S390_ARCH_FAC_LIST_SIZE_BYTE);
VM_EVENT(kvm, 3, "GET: guest ibc: 0x%4.4x, guest cpuid: 0x%16.16llx",
kvm->arch.model.ibc,
kvm->arch.model.cpuid);
VM_EVENT(kvm, 3, "GET: guest faclist: 0x%16.16llx.%16.16llx.%16.16llx",
kvm->arch.model.fac_list[0],
kvm->arch.model.fac_list[1],
kvm->arch.model.fac_list[2]);
if (copy_to_user((void __user *)attr->addr, proc, sizeof(*proc)))
ret = -EFAULT;
kfree(proc);
out:
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 92 | 46.00% | 1 | 8.33% |
| Christian Bornträger | 63 | 31.50% | 2 | 16.67% |
| Dominik Dingel | 20 | 10.00% | 2 | 16.67% |
| Jason J. Herne | 8 | 4.00% | 1 | 8.33% |
| Heiko Carstens | 6 | 3.00% | 1 | 8.33% |
| Carsten Otte | 4 | 2.00% | 2 | 16.67% |
| Tony Krowiak | 3 | 1.50% | 1 | 8.33% |
| Jan Kiszka | 3 | 1.50% | 1 | 8.33% |
| David Hildenbrand | 1 | 0.50% | 1 | 8.33% |
| Total | 200 | 100.00% | 12 | 100.00% |
static int kvm_s390_get_machine(struct kvm *kvm, struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_machine *mach;
int ret = 0;
mach = kzalloc(sizeof(*mach), GFP_KERNEL);
if (!mach) {
ret = -ENOMEM;
goto out;
}
get_cpu_id((struct cpuid *) &mach->cpuid);
mach->ibc = sclp.ibc;
memcpy(&mach->fac_mask, kvm->arch.model.fac_mask,
S390_ARCH_FAC_LIST_SIZE_BYTE);
memcpy((unsigned long *)&mach->fac_list, S390_lowcore.stfle_fac_list,
sizeof(S390_lowcore.stfle_fac_list));
VM_EVENT(kvm, 3, "GET: host ibc: 0x%4.4x, host cpuid: 0x%16.16llx",
kvm->arch.model.ibc,
kvm->arch.model.cpuid);
VM_EVENT(kvm, 3, "GET: host facmask: 0x%16.16llx.%16.16llx.%16.16llx",
mach->fac_mask[0],
mach->fac_mask[1],
mach->fac_mask[2]);
VM_EVENT(kvm, 3, "GET: host faclist: 0x%16.16llx.%16.16llx.%16.16llx",
mach->fac_list[0],
mach->fac_list[1],
mach->fac_list[2]);
if (copy_to_user((void __user *)attr->addr, mach, sizeof(*mach)))
ret = -EFAULT;
kfree(mach);
out:
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 117 | 48.95% | 2 | 22.22% |
| Christian Bornträger | 91 | 38.08% | 2 | 22.22% |
| Dominik Dingel | 19 | 7.95% | 2 | 22.22% |
| Jason J. Herne | 8 | 3.35% | 1 | 11.11% |
| David Hildenbrand | 4 | 1.67% | 2 | 22.22% |
| Total | 239 | 100.00% | 9 | 100.00% |
static int kvm_s390_get_processor_feat(struct kvm *kvm,
struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_feat data;
bitmap_copy((unsigned long *) data.feat, kvm->arch.cpu_feat,
KVM_S390_VM_CPU_FEAT_NR_BITS);
if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
return -EFAULT;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 69 | 100.00% | 1 | 100.00% |
| Total | 69 | 100.00% | 1 | 100.00% |
static int kvm_s390_get_machine_feat(struct kvm *kvm,
struct kvm_device_attr *attr)
{
struct kvm_s390_vm_cpu_feat data;
bitmap_copy((unsigned long *) data.feat,
kvm_s390_available_cpu_feat,
KVM_S390_VM_CPU_FEAT_NR_BITS);
if (copy_to_user((void __user *)attr->addr, &data, sizeof(data)))
return -EFAULT;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 40 | 61.54% | 1 | 50.00% |
| Michael Müller | 25 | 38.46% | 1 | 50.00% |
| Total | 65 | 100.00% | 2 | 100.00% |
static int kvm_s390_get_processor_subfunc(struct kvm *kvm,
struct kvm_device_attr *attr)
{
/*
* Once we can actually configure subfunctions (kernel + hw support),
* we have to check if they were already set by user space, if so copy
* them from kvm->arch.
*/
return -ENXIO;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 21 | 100.00% | 1 | 100.00% |
| Total | 21 | 100.00% | 1 | 100.00% |
static int kvm_s390_get_machine_subfunc(struct kvm *kvm,
struct kvm_device_attr *attr)
{
if (copy_to_user((void __user *)attr->addr, &kvm_s390_available_subfunc,
sizeof(struct kvm_s390_vm_cpu_subfunc)))
return -EFAULT;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 41 | 89.13% | 1 | 50.00% |
| Michael Müller | 5 | 10.87% | 1 | 50.00% |
| Total | 46 | 100.00% | 2 | 100.00% |
static int kvm_s390_get_cpu_model(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret = -ENXIO;
switch (attr->attr) {
case KVM_S390_VM_CPU_PROCESSOR:
ret = kvm_s390_get_processor(kvm, attr);
break;
case KVM_S390_VM_CPU_MACHINE:
ret = kvm_s390_get_machine(kvm, attr);
break;
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
ret = kvm_s390_get_processor_feat(kvm, attr);
break;
case KVM_S390_VM_CPU_MACHINE_FEAT:
ret = kvm_s390_get_machine_feat(kvm, attr);
break;
case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
ret = kvm_s390_get_processor_subfunc(kvm, attr);
break;
case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
ret = kvm_s390_get_machine_subfunc(kvm, attr);
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 49 | 44.14% | 1 | 25.00% |
| David Hildenbrand | 48 | 43.24% | 2 | 50.00% |
| Tony Krowiak | 14 | 12.61% | 1 | 25.00% |
| Total | 111 | 100.00% | 4 | 100.00% |
static int kvm_s390_vm_set_attr(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
switch (attr->group) {
case KVM_S390_VM_MEM_CTRL:
ret = kvm_s390_set_mem_control(kvm, attr);
break;
case KVM_S390_VM_TOD:
ret = kvm_s390_set_tod(kvm, attr);
break;
case KVM_S390_VM_CPU_MODEL:
ret = kvm_s390_set_cpu_model(kvm, attr);
break;
case KVM_S390_VM_CRYPTO:
ret = kvm_s390_vm_set_crypto(kvm, attr);
break;
case KVM_S390_VM_MIGRATION:
ret = kvm_s390_vm_set_migration(kvm, attr);
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 31 | 30.39% | 3 | 25.00% |
| Jason J. Herne | 13 | 12.75% | 1 | 8.33% |
| Michael Müller | 13 | 12.75% | 1 | 8.33% |
| Tony Krowiak | 13 | 12.75% | 1 | 8.33% |
| Claudio Imbrenda | 13 | 12.75% | 1 | 8.33% |
| Carsten Otte | 8 | 7.84% | 2 | 16.67% |
| Heiko Carstens | 7 | 6.86% | 1 | 8.33% |
| Jan Kiszka | 3 | 2.94% | 1 | 8.33% |
| Christian Bornträger | 1 | 0.98% | 1 | 8.33% |
| Total | 102 | 100.00% | 12 | 100.00% |
static int kvm_s390_vm_get_attr(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
switch (attr->group) {
case KVM_S390_VM_MEM_CTRL:
ret = kvm_s390_get_mem_control(kvm, attr);
break;
case KVM_S390_VM_TOD:
ret = kvm_s390_get_tod(kvm, attr);
break;
case KVM_S390_VM_CPU_MODEL:
ret = kvm_s390_get_cpu_model(kvm, attr);
break;
case KVM_S390_VM_MIGRATION:
ret = kvm_s390_vm_get_migration(kvm, attr);
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 50 | 56.18% | 2 | 40.00% |
| Claudio Imbrenda | 13 | 14.61% | 1 | 20.00% |
| Jason J. Herne | 13 | 14.61% | 1 | 20.00% |
| Michael Müller | 13 | 14.61% | 1 | 20.00% |
| Total | 89 | 100.00% | 5 | 100.00% |
static int kvm_s390_vm_has_attr(struct kvm *kvm, struct kvm_device_attr *attr)
{
int ret;
switch (attr->group) {
case KVM_S390_VM_MEM_CTRL:
switch (attr->attr) {
case KVM_S390_VM_MEM_ENABLE_CMMA:
case KVM_S390_VM_MEM_CLR_CMMA:
ret = sclp.has_cmma ? 0 : -ENXIO;
break;
case KVM_S390_VM_MEM_LIMIT_SIZE:
ret = 0;
break;
default:
ret = -ENXIO;
break;
}
break;
case KVM_S390_VM_TOD:
switch (attr->attr) {
case KVM_S390_VM_TOD_LOW:
case KVM_S390_VM_TOD_HIGH:
ret = 0;
break;
default:
ret = -ENXIO;
break;
}
break;
case KVM_S390_VM_CPU_MODEL:
switch (attr->attr) {
case KVM_S390_VM_CPU_PROCESSOR:
case KVM_S390_VM_CPU_MACHINE:
case KVM_S390_VM_CPU_PROCESSOR_FEAT:
case KVM_S390_VM_CPU_MACHINE_FEAT:
case KVM_S390_VM_CPU_MACHINE_SUBFUNC:
ret = 0;
break;
/* configuring subfunctions is not supported yet */
case KVM_S390_VM_CPU_PROCESSOR_SUBFUNC:
default:
ret = -ENXIO;
break;
}
break;
case KVM_S390_VM_CRYPTO:
switch (attr->attr) {
case KVM_S390_VM_CRYPTO_ENABLE_AES_KW:
case KVM_S390_VM_CRYPTO_ENABLE_DEA_KW:
case KVM_S390_VM_CRYPTO_DISABLE_AES_KW:
case KVM_S390_VM_CRYPTO_DISABLE_DEA_KW:
ret = 0;
break;
default:
ret = -ENXIO;
break;
}
break;
case KVM_S390_VM_MIGRATION:
ret = 0;
break;
default:
ret = -ENXIO;
break;
}
return ret;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 70 | 35.18% | 3 | 30.00% |
| Tony Krowiak | 36 | 18.09% | 1 | 10.00% |
| Jason J. Herne | 30 | 15.08% | 1 | 10.00% |
| Michael Müller | 30 | 15.08% | 1 | 10.00% |
| David Hildenbrand | 25 | 12.56% | 3 | 30.00% |
| Claudio Imbrenda | 8 | 4.02% | 1 | 10.00% |
| Total | 199 | 100.00% | 10 | 100.00% |
static long kvm_s390_get_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
{
uint8_t *keys;
uint64_t hva;
int srcu_idx, i, r = 0;
if (args->flags != 0)
return -EINVAL;
/* Is this guest using storage keys? */
if (!mm_use_skey(current->mm))
return KVM_S390_GET_SKEYS_NONE;
/* Enforce sane limit on memory allocation */
if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
return -EINVAL;
keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
if (!keys)
return -ENOMEM;
down_read(¤t->mm->mmap_sem);
srcu_idx = srcu_read_lock(&kvm->srcu);
for (i = 0; i < args->count; i++) {
hva = gfn_to_hva(kvm, args->start_gfn + i);
if (kvm_is_error_hva(hva)) {
r = -EFAULT;
break;
}
r = get_guest_storage_key(current->mm, hva, &keys[i]);
if (r)
break;
}
srcu_read_unlock(&kvm->srcu, srcu_idx);
up_read(¤t->mm->mmap_sem);
if (!r) {
r = copy_to_user((uint8_t __user *)args->skeydata_addr, keys,
sizeof(uint8_t) * args->count);
if (r)
r = -EFAULT;
}
kvfree(keys);
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 176 | 68.22% | 1 | 12.50% |
| Martin Schwidefsky | 25 | 9.69% | 1 | 12.50% |
| Christian Bornträger | 22 | 8.53% | 1 | 12.50% |
| Heiko Carstens | 15 | 5.81% | 1 | 12.50% |
| Carsten Otte | 9 | 3.49% | 1 | 12.50% |
| David Hildenbrand | 8 | 3.10% | 1 | 12.50% |
| Cornelia Huck | 2 | 0.78% | 1 | 12.50% |
| Michal Hocko | 1 | 0.39% | 1 | 12.50% |
| Total | 258 | 100.00% | 8 | 100.00% |
static long kvm_s390_set_skeys(struct kvm *kvm, struct kvm_s390_skeys *args)
{
uint8_t *keys;
uint64_t hva;
int srcu_idx, i, r = 0;
if (args->flags != 0)
return -EINVAL;
/* Enforce sane limit on memory allocation */
if (args->count < 1 || args->count > KVM_S390_SKEYS_MAX)
return -EINVAL;
keys = kvmalloc_array(args->count, sizeof(uint8_t), GFP_KERNEL);
if (!keys)
return -ENOMEM;
r = copy_from_user(keys, (uint8_t __user *)args->skeydata_addr,
sizeof(uint8_t) * args->count);
if (r) {
r = -EFAULT;
goto out;
}
/* Enable storage key handling for the guest */
r = s390_enable_skey();
if (r)
goto out;
down_read(¤t->mm->mmap_sem);
srcu_idx = srcu_read_lock(&kvm->srcu);
for (i = 0; i < args->count; i++) {
hva = gfn_to_hva(kvm, args->start_gfn + i);
if (kvm_is_error_hva(hva)) {
r = -EFAULT;
break;
}
/* Lowest order bit is reserved */
if (keys[i] & 0x01) {
r = -EINVAL;
break;
}
r = set_guest_storage_key(current->mm, hva, keys[i], 0);
if (r)
break;
}
srcu_read_unlock(&kvm->srcu, srcu_idx);
up_read(¤t->mm->mmap_sem);
out:
kvfree(keys);
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 210 | 76.09% | 1 | 14.29% |
| Christian Bornträger | 22 | 7.97% | 1 | 14.29% |
| Martin Schwidefsky | 20 | 7.25% | 1 | 14.29% |
| Dominik Dingel | 16 | 5.80% | 2 | 28.57% |
| Tony Krowiak | 7 | 2.54% | 1 | 14.29% |
| Michal Hocko | 1 | 0.36% | 1 | 14.29% |
| Total | 276 | 100.00% | 7 | 100.00% |
/*
* Base address and length must be sent at the start of each block, therefore
* it's cheaper to send some clean data, as long as it's less than the size of
* two longs.
*/
#define KVM_S390_MAX_BIT_DISTANCE (2 * sizeof(void *))
/* for consistency */
#define KVM_S390_CMMA_SIZE_MAX ((u32)KVM_S390_SKEYS_MAX)
/*
* This function searches for the next page with dirty CMMA attributes, and
* saves the attributes in the buffer up to either the end of the buffer or
* until a block of at least KVM_S390_MAX_BIT_DISTANCE clean bits is found;
* no trailing clean bytes are saved.
* In case no dirty bits were found, or if CMMA was not enabled or used, the
* output buffer will indicate 0 as length.
*/
static int kvm_s390_get_cmma_bits(struct kvm *kvm,
struct kvm_s390_cmma_log *args)
{
struct kvm_s390_migration_state *s = kvm->arch.migration_state;
unsigned long bufsize, hva, pgstev, i, next, cur;
int srcu_idx, peek, r = 0, rr;
u8 *res;
cur = args->start_gfn;
i = next = pgstev = 0;
if (unlikely(!kvm->arch.use_cmma))
return -ENXIO;
/* Invalid/unsupported flags were specified */
if (args->flags & ~KVM_S390_CMMA_PEEK)
return -EINVAL;
/* Migration mode query, and we are not doing a migration */
peek = !!(args->flags & KVM_S390_CMMA_PEEK);
if (!peek && !s)
return -EINVAL;
/* CMMA is disabled or was not used, or the buffer has length zero */
bufsize = min(args->count, KVM_S390_CMMA_SIZE_MAX);
if (!bufsize || !kvm->mm->context.use_cmma) {
memset(args, 0, sizeof(*args));
return 0;
}
if (!peek) {
/* We are not peeking, and there are no dirty pages */
if (!atomic64_read(&s->dirty_pages)) {
memset(args, 0, sizeof(*args));
return 0;
}
cur = find_next_bit(s->pgste_bitmap, s->bitmap_size,
args->start_gfn);
if (cur >= s->bitmap_size) /* nothing found, loop back */
cur = find_next_bit(s->pgste_bitmap, s->bitmap_size, 0);
if (cur >= s->bitmap_size) { /* again! (very unlikely) */
memset(args, 0, sizeof(*args));
return 0;
}
next = find_next_bit(s->pgste_bitmap, s->bitmap_size, cur + 1);
}
res = vmalloc(bufsize);
if (!res)
return -ENOMEM;
args->start_gfn = cur;
down_read(&kvm->mm->mmap_sem);
srcu_idx = srcu_read_lock(&kvm->srcu);
while (i < bufsize) {
hva = gfn_to_hva(kvm, cur);
if (kvm_is_error_hva(hva)) {
r = -EFAULT;
break;
}
/* decrement only if we actually flipped the bit to 0 */
if (!peek && test_and_clear_bit(cur, s->pgste_bitmap))
atomic64_dec(&s->dirty_pages);
r = get_pgste(kvm->mm, hva, &pgstev);
if (r < 0)
pgstev = 0;
/* save the value */
res[i++] = (pgstev >> 24) & 0x43;
/*
* if the next bit is too far away, stop.
* if we reached the previous "next", find the next one
*/
if (!peek) {
if (next > cur + KVM_S390_MAX_BIT_DISTANCE)
break;
if (cur == next)
next = find_next_bit(s->pgste_bitmap,
s->bitmap_size, cur + 1);
/* reached the end of the bitmap or of the buffer, stop */
if ((next >= s->bitmap_size) ||
(next >= args->start_gfn + bufsize))
break;
}
cur++;
}
srcu_read_unlock(&kvm->srcu, srcu_idx);
up_read(&kvm->mm->mmap_sem);
args->count = i;
args->remaining = s ? atomic64_read(&s->dirty_pages) : 0;
rr = copy_to_user((void __user *)args->values, res, args->count);
if (rr)
r = -EFAULT;
vfree(res);
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 375 | 65.67% | 2 | 20.00% |
| Jason J. Herne | 105 | 18.39% | 1 | 10.00% |
| Cornelia Huck | 29 | 5.08% | 2 | 20.00% |
| Martin Schwidefsky | 18 | 3.15% | 1 | 10.00% |
| Heiko Carstens | 17 | 2.98% | 1 | 10.00% |
| Carsten Otte | 15 | 2.63% | 1 | 10.00% |
| David Hildenbrand | 7 | 1.23% | 1 | 10.00% |
| Dominik Dingel | 5 | 0.88% | 1 | 10.00% |
| Total | 571 | 100.00% | 10 | 100.00% |
/*
* This function sets the CMMA attributes for the given pages. If the input
* buffer has zero length, no action is taken, otherwise the attributes are
* set and the mm->context.use_cmma flag is set.
*/
static int kvm_s390_set_cmma_bits(struct kvm *kvm,
const struct kvm_s390_cmma_log *args)
{
unsigned long hva, mask, pgstev, i;
uint8_t *bits;
int srcu_idx, r = 0;
mask = args->mask;
if (!kvm->arch.use_cmma)
return -ENXIO;
/* invalid/unsupported flags */
if (args->flags != 0)
return -EINVAL;
/* Enforce sane limit on memory allocation */
if (args->count > KVM_S390_CMMA_SIZE_MAX)
return -EINVAL;
/* Nothing to do */
if (args->count == 0)
return 0;
bits = vmalloc(sizeof(*bits) * args->count);
if (!bits)
return -ENOMEM;
r = copy_from_user(bits, (void __user *)args->values, args->count);
if (r) {
r = -EFAULT;
goto out;
}
down_read(&kvm->mm->mmap_sem);
srcu_idx = srcu_read_lock(&kvm->srcu);
for (i = 0; i < args->count; i++) {
hva = gfn_to_hva(kvm, args->start_gfn + i);
if (kvm_is_error_hva(hva)) {
r = -EFAULT;
break;
}
pgstev = bits[i];
pgstev = pgstev << 24;
mask &= _PGSTE_GPS_USAGE_MASK | _PGSTE_GPS_NODAT;
set_pgste_bits(kvm->mm, hva, mask, pgstev);
}
srcu_read_unlock(&kvm->srcu, srcu_idx);
up_read(&kvm->mm->mmap_sem);
if (!kvm->mm->context.use_cmma) {
down_write(&kvm->mm->mmap_sem);
kvm->mm->context.use_cmma = 1;
up_write(&kvm->mm->mmap_sem);
}
out:
vfree(bits);
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Jason J. Herne | 161 | 49.85% | 1 | 25.00% |
| Claudio Imbrenda | 144 | 44.58% | 2 | 50.00% |
| Martin Schwidefsky | 18 | 5.57% | 1 | 25.00% |
| Total | 323 | 100.00% | 4 | 100.00% |
long kvm_arch_vm_ioctl(struct file *filp,
unsigned int ioctl, unsigned long arg)
{
struct kvm *kvm = filp->private_data;
void __user *argp = (void __user *)arg;
struct kvm_device_attr attr;
int r;
switch (ioctl) {
case KVM_S390_INTERRUPT: {
struct kvm_s390_interrupt s390int;
r = -EFAULT;
if (copy_from_user(&s390int, argp, sizeof(s390int)))
break;
r = kvm_s390_inject_vm(kvm, &s390int);
break;
}
case KVM_ENABLE_CAP: {
struct kvm_enable_cap cap;
r = -EFAULT;
if (copy_from_user(&cap, argp, sizeof(cap)))
break;
r = kvm_vm_ioctl_enable_cap(kvm, &cap);
break;
}
case KVM_CREATE_IRQCHIP: {
struct kvm_irq_routing_entry routing;
r = -EINVAL;
if (kvm->arch.use_irqchip) {
/* Set up dummy routing. */
memset(&routing, 0, sizeof(routing));
r = kvm_set_irq_routing(kvm, &routing, 0, 0);
}
break;
}
case KVM_SET_DEVICE_ATTR: {
r = -EFAULT;
if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
break;
r = kvm_s390_vm_set_attr(kvm, &attr);
break;
}
case KVM_GET_DEVICE_ATTR: {
r = -EFAULT;
if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
break;
r = kvm_s390_vm_get_attr(kvm, &attr);
break;
}
case KVM_HAS_DEVICE_ATTR: {
r = -EFAULT;
if (copy_from_user(&attr, (void __user *)arg, sizeof(attr)))
break;
r = kvm_s390_vm_has_attr(kvm, &attr);
break;
}
case KVM_S390_GET_SKEYS: {
struct kvm_s390_skeys args;
r = -EFAULT;
if (copy_from_user(&args, argp,
sizeof(struct kvm_s390_skeys)))
break;
r = kvm_s390_get_skeys(kvm, &args);
break;
}
case KVM_S390_SET_SKEYS: {
struct kvm_s390_skeys args;
r = -EFAULT;
if (copy_from_user(&args, argp,
sizeof(struct kvm_s390_skeys)))
break;
r = kvm_s390_set_skeys(kvm, &args);
break;
}
case KVM_S390_GET_CMMA_BITS: {
struct kvm_s390_cmma_log args;
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
mutex_lock(&kvm->slots_lock);
r = kvm_s390_get_cmma_bits(kvm, &args);
mutex_unlock(&kvm->slots_lock);
if (!r) {
r = copy_to_user(argp, &args, sizeof(args));
if (r)
r = -EFAULT;
}
break;
}
case KVM_S390_SET_CMMA_BITS: {
struct kvm_s390_cmma_log args;
r = -EFAULT;
if (copy_from_user(&args, argp, sizeof(args)))
break;
mutex_lock(&kvm->slots_lock);
r = kvm_s390_set_cmma_bits(kvm, &args);
mutex_unlock(&kvm->slots_lock);
break;
}
default:
r = -ENOTTY;
}
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Dominik Dingel | 175 | 31.76% | 1 | 10.00% |
| Jason J. Herne | 96 | 17.42% | 1 | 10.00% |
| Cornelia Huck | 91 | 16.52% | 2 | 20.00% |
| Claudio Imbrenda | 57 | 10.34% | 1 | 10.00% |
| Heiko Carstens | 56 | 10.16% | 1 | 10.00% |
| Carsten Otte | 41 | 7.44% | 1 | 10.00% |
| Christian Bornträger | 32 | 5.81% | 1 | 10.00% |
| Nicholas Krause | 2 | 0.36% | 1 | 10.00% |
| Avi Kivity | 1 | 0.18% | 1 | 10.00% |
| Total | 551 | 100.00% | 10 | 100.00% |
static int kvm_s390_query_ap_config(u8 *config)
{
u32 fcn_code = 0x04000000UL;
u32 cc = 0;
memset(config, 0, 128);
asm volatile(
"lgr 0,%1\n"
"lgr 2,%2\n"
".long 0xb2af0000\n" /* PQAP(QCI) */
"0: ipm %0\n"
"srl %0,28\n"
"1:\n"
EX_TABLE(0b, 1b)
: "+r" (cc)
: "r" (fcn_code), "r" (config)
: "cc", "0", "2", "memory"
);
return cc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 25 | 67.57% | 1 | 50.00% |
| Christian Bornträger | 12 | 32.43% | 1 | 50.00% |
| Total | 37 | 100.00% | 2 | 100.00% |
static int kvm_s390_apxa_installed(void)
{
u8 config[128];
int cc;
if (test_facility(12)) {
cc = kvm_s390_query_ap_config(config);
if (cc)
pr_err("PQAP(QCI) failed with cc=%d", cc);
else
return config[0] & 0x40;
}
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 56 | 100.00% | 1 | 100.00% |
| Total | 56 | 100.00% | 1 | 100.00% |
static void kvm_s390_set_crycb_format(struct kvm *kvm)
{
kvm->arch.crypto.crycbd = (__u32)(unsigned long) kvm->arch.crypto.crycb;
if (kvm_s390_apxa_installed())
kvm->arch.crypto.crycbd |= CRYCB_FORMAT2;
else
kvm->arch.crypto.crycbd |= CRYCB_FORMAT1;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 60 | 100.00% | 1 | 100.00% |
| Total | 60 | 100.00% | 1 | 100.00% |
static u64 kvm_s390_get_initial_cpuid(void)
{
struct cpuid cpuid;
get_cpu_id(&cpuid);
cpuid.version = 0xff;
return *((u64 *) &cpuid);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 22 | 62.86% | 1 | 50.00% |
| Michael Müller | 13 | 37.14% | 1 | 50.00% |
| Total | 35 | 100.00% | 2 | 100.00% |
static void kvm_s390_crypto_init(struct kvm *kvm)
{
if (!test_kvm_facility(kvm, 76))
return;
kvm->arch.crypto.crycb = &kvm->arch.sie_page2->crycb;
kvm_s390_set_crycb_format(kvm);
/* Enable AES/DEA protected key functions by default */
kvm->arch.crypto.aes_kw = 1;
kvm->arch.crypto.dea_kw = 1;
get_random_bytes(kvm->arch.crypto.crycb->aes_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->aes_wrapping_key_mask));
get_random_bytes(kvm->arch.crypto.crycb->dea_wrapping_key_mask,
sizeof(kvm->arch.crypto.crycb->dea_wrapping_key_mask));
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 109 | 93.16% | 4 | 66.67% |
| David Hildenbrand | 5 | 4.27% | 1 | 16.67% |
| Michael Müller | 3 | 2.56% | 1 | 16.67% |
| Total | 117 | 100.00% | 6 | 100.00% |
static void sca_dispose(struct kvm *kvm)
{
if (kvm->arch.use_esca)
free_pages_exact(kvm->arch.sca, sizeof(struct esca_block));
else
free_page((unsigned long)(kvm->arch.sca));
kvm->arch.sca = NULL;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 58 | 100.00% | 2 | 100.00% |
| Total | 58 | 100.00% | 2 | 100.00% |
int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
{
gfp_t alloc_flags = GFP_KERNEL;
int i, rc;
char debug_name[16];
static unsigned long sca_offset;
rc = -EINVAL;
#ifdef CONFIG_KVM_S390_UCONTROL
if (type & ~KVM_VM_S390_UCONTROL)
goto out_err;
if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
goto out_err;
#else
if (type)
goto out_err;
#endif
rc = s390_enable_sie();
if (rc)
goto out_err;
rc = -ENOMEM;
kvm->arch.use_esca = 0; /* start with basic SCA */
if (!sclp.has_64bscao)
alloc_flags |= GFP_DMA;
rwlock_init(&kvm->arch.sca_lock);
kvm->arch.sca = (struct bsca_block *) get_zeroed_page(alloc_flags);
if (!kvm->arch.sca)
goto out_err;
spin_lock(&kvm_lock);
sca_offset += 16;
if (sca_offset + sizeof(struct bsca_block) > PAGE_SIZE)
sca_offset = 0;
kvm->arch.sca = (struct bsca_block *)
((char *) kvm->arch.sca + sca_offset);
spin_unlock(&kvm_lock);
sprintf(debug_name, "kvm-%u", current->pid);
kvm->arch.dbf = debug_register(debug_name, 32, 1, 7 * sizeof(long));
if (!kvm->arch.dbf)
goto out_err;
kvm->arch.sie_page2 =
(struct sie_page2 *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
if (!kvm->arch.sie_page2)
goto out_err;
/* Populate the facility mask initially. */
memcpy(kvm->arch.model.fac_mask, S390_lowcore.stfle_fac_list,
sizeof(S390_lowcore.stfle_fac_list));
for (i = 0; i < S390_ARCH_FAC_LIST_SIZE_U64; i++) {
if (i < kvm_s390_fac_list_mask_size())
kvm->arch.model.fac_mask[i] &= kvm_s390_fac_list_mask[i];
else
kvm->arch.model.fac_mask[i] = 0UL;
}
/* Populate the facility list initially. */
kvm->arch.model.fac_list = kvm->arch.sie_page2->fac_list;
memcpy(kvm->arch.model.fac_list, kvm->arch.model.fac_mask,
S390_ARCH_FAC_LIST_SIZE_BYTE);
/* we are always in czam mode - even on pre z14 machines */
set_kvm_facility(kvm->arch.model.fac_mask, 138);
set_kvm_facility(kvm->arch.model.fac_list, 138);
/* we emulate STHYI in kvm */
set_kvm_facility(kvm->arch.model.fac_mask, 74);
set_kvm_facility(kvm->arch.model.fac_list, 74);
if (MACHINE_HAS_TLB_GUEST) {
set_kvm_facility(kvm->arch.model.fac_mask, 147);
set_kvm_facility(kvm->arch.model.fac_list, 147);
}
kvm->arch.model.cpuid = kvm_s390_get_initial_cpuid();
kvm->arch.model.ibc = sclp.ibc & 0x0fff;
kvm_s390_crypto_init(kvm);
mutex_init(&kvm->arch.float_int.ais_lock);
kvm->arch.float_int.simm = 0;
kvm->arch.float_int.nimm = 0;
spin_lock_init(&kvm->arch.float_int.lock);
for (i = 0; i < FIRQ_LIST_COUNT; i++)
INIT_LIST_HEAD(&kvm->arch.float_int.lists[i]);
init_waitqueue_head(&kvm->arch.ipte_wq);
mutex_init(&kvm->arch.ipte_mutex);
debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
VM_EVENT(kvm, 3, "vm created with type %lu", type);
if (type & KVM_VM_S390_UCONTROL) {
kvm->arch.gmap = NULL;
kvm->arch.mem_limit = KVM_S390_NO_MEM_LIMIT;
} else {
if (sclp.hamax == U64_MAX)
kvm->arch.mem_limit = TASK_SIZE_MAX;
else
kvm->arch.mem_limit = min_t(unsigned long, TASK_SIZE_MAX,
sclp.hamax + 1);
kvm->arch.gmap = gmap_create(current->mm, kvm->arch.mem_limit - 1);
if (!kvm->arch.gmap)
goto out_err;
kvm->arch.gmap->private = kvm;
kvm->arch.gmap->pfault_enabled = 0;
}
kvm->arch.css_support = 0;
kvm->arch.use_irqchip = 0;
kvm->arch.epoch = 0;
spin_lock_init(&kvm->arch.start_stop_lock);
kvm_s390_vsie_init(kvm);
KVM_EVENT(3, "vm 0x%pK created by pid %u", kvm, current->pid);
return 0;
out_err:
free_page((unsigned long)kvm->arch.sie_page2);
debug_unregister(kvm->arch.dbf);
sca_dispose(kvm);
KVM_EVENT(3, "creation of vm failed: %d", rc);
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 144 | 17.08% | 4 | 8.89% |
| Carsten Otte | 132 | 15.66% | 4 | 8.89% |
| Heiko Carstens | 132 | 15.66% | 2 | 4.44% |
| David Hildenbrand | 108 | 12.81% | 8 | 17.78% |
| Christian Bornträger | 90 | 10.68% | 7 | 15.56% |
| Dominik Dingel | 34 | 4.03% | 3 | 6.67% |
| Fei Li | 32 | 3.80% | 1 | 2.22% |
| Claudio Imbrenda | 32 | 3.80% | 1 | 2.22% |
| Janosch Frank | 26 | 3.08% | 1 | 2.22% |
| Guenther Hutzl | 24 | 2.85% | 1 | 2.22% |
| Eugene (jno) Dvurechenski | 23 | 2.73% | 3 | 6.67% |
| Jens Freimann | 17 | 2.02% | 1 | 2.22% |
| Cornelia Huck | 16 | 1.90% | 2 | 4.44% |
| Thomas Huth | 10 | 1.19% | 1 | 2.22% |
| Jason J. Herne | 8 | 0.95% | 1 | 2.22% |
| Jan Kiszka | 7 | 0.83% | 1 | 2.22% |
| Tony Krowiak | 4 | 0.47% | 1 | 2.22% |
| Martin Schwidefsky | 4 | 0.47% | 3 | 6.67% |
| Total | 843 | 100.00% | 45 | 100.00% |
bool kvm_arch_has_vcpu_debugfs(void)
{
return false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Luiz Fernando N. Capitulino | 10 | 100.00% | 1 | 100.00% |
| Total | 10 | 100.00% | 1 | 100.00% |
int kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu)
{
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Luiz Fernando N. Capitulino | 13 | 100.00% | 1 | 100.00% |
| Total | 13 | 100.00% | 1 | 100.00% |
void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
{
VCPU_EVENT(vcpu, 3, "%s", "free cpu");
trace_kvm_s390_destroy_vcpu(vcpu->vcpu_id);
kvm_s390_clear_local_irqs(vcpu);
kvm_clear_async_pf_completion_queue(vcpu);
if (!kvm_is_ucontrol(vcpu->kvm))
sca_del_vcpu(vcpu);
if (kvm_is_ucontrol(vcpu->kvm))
gmap_remove(vcpu->arch.gmap);
if (vcpu->kvm->arch.use_cmma)
kvm_s390_vcpu_unsetup_cmma(vcpu);
free_page((unsigned long)(vcpu->arch.sie_block));
kvm_vcpu_uninit(vcpu);
kmem_cache_free(kvm_vcpu_cache, vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 54 | 47.79% | 4 | 28.57% |
| Carsten Otte | 27 | 23.89% | 2 | 14.29% |
| Dominik Dingel | 11 | 9.73% | 3 | 21.43% |
| Konstantin Weitz | 9 | 7.96% | 1 | 7.14% |
| Cornelia Huck | 7 | 6.19% | 1 | 7.14% |
| Michael Müller | 3 | 2.65% | 1 | 7.14% |
| Martin Schwidefsky | 1 | 0.88% | 1 | 7.14% |
| Eugene (jno) Dvurechenski | 1 | 0.88% | 1 | 7.14% |
| Total | 113 | 100.00% | 14 | 100.00% |
static void kvm_free_vcpus(struct kvm *kvm)
{
unsigned int i;
struct kvm_vcpu *vcpu;
kvm_for_each_vcpu(i, vcpu, kvm)
kvm_arch_vcpu_destroy(vcpu);
mutex_lock(&kvm->lock);
for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
kvm->vcpus[i] = NULL;
atomic_set(&kvm->online_vcpus, 0);
mutex_unlock(&kvm->lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 47 | 54.02% | 2 | 50.00% |
| Gleb Natapov | 33 | 37.93% | 1 | 25.00% |
| Heiko Carstens | 7 | 8.05% | 1 | 25.00% |
| Total | 87 | 100.00% | 4 | 100.00% |
void kvm_arch_destroy_vm(struct kvm *kvm)
{
kvm_free_vcpus(kvm);
sca_dispose(kvm);
debug_unregister(kvm->arch.dbf);
free_page((unsigned long)kvm->arch.sie_page2);
if (!kvm_is_ucontrol(kvm))
gmap_remove(kvm->arch.gmap);
kvm_s390_destroy_adapters(kvm);
kvm_s390_clear_float_irqs(kvm);
kvm_s390_vsie_destroy(kvm);
if (kvm->arch.migration_state) {
vfree(kvm->arch.migration_state->pgste_bitmap);
kfree(kvm->arch.migration_state);
}
KVM_EVENT(3, "vm 0x%pK destroyed", kvm);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Claudio Imbrenda | 30 | 26.55% | 1 | 6.67% |
| Heiko Carstens | 26 | 23.01% | 1 | 6.67% |
| Carsten Otte | 23 | 20.35% | 3 | 20.00% |
| Christian Bornträger | 13 | 11.50% | 4 | 26.67% |
| David Hildenbrand | 11 | 9.73% | 2 | 13.33% |
| Tony Krowiak | 7 | 6.19% | 1 | 6.67% |
| Cornelia Huck | 1 | 0.88% | 1 | 6.67% |
| Martin Schwidefsky | 1 | 0.88% | 1 | 6.67% |
| Eugene (jno) Dvurechenski | 1 | 0.88% | 1 | 6.67% |
| Total | 113 | 100.00% | 15 | 100.00% |
/* Section: vcpu related */
static int __kvm_ucontrol_vcpu_init(struct kvm_vcpu *vcpu)
{
vcpu->arch.gmap = gmap_create(current->mm, -1UL);
if (!vcpu->arch.gmap)
return -ENOMEM;
vcpu->arch.gmap->private = vcpu->kvm;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Carsten Otte | 28 | 50.91% | 3 | 30.00% |
| Christian Bornträger | 12 | 21.82% | 1 | 10.00% |
| Heiko Carstens | 7 | 12.73% | 1 | 10.00% |
| Dominik Dingel | 4 | 7.27% | 3 | 30.00% |
| Martin Schwidefsky | 4 | 7.27% | 2 | 20.00% |
| Total | 55 | 100.00% | 10 | 100.00% |
static void sca_del_vcpu(struct kvm_vcpu *vcpu)
{
if (!kvm_s390_use_sca_entries())
return;
read_lock(&vcpu->kvm->arch.sca_lock);
if (vcpu->kvm->arch.use_esca) {
struct esca_block *sca = vcpu->kvm->arch.sca;
clear_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
sca->cpu[vcpu->vcpu_id].sda = 0;
} else {
struct bsca_block *sca = vcpu->kvm->arch.sca;
clear_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
sca->cpu[vcpu->vcpu_id].sda = 0;
}
read_unlock(&vcpu->kvm->arch.sca_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 135 | 95.07% | 4 | 80.00% |
| David Hildenbrand | 7 | 4.93% | 1 | 20.00% |
| Total | 142 | 100.00% | 5 | 100.00% |
static void sca_add_vcpu(struct kvm_vcpu *vcpu)
{
if (!kvm_s390_use_sca_entries()) {
struct bsca_block *sca = vcpu->kvm->arch.sca;
/* we still need the basic sca for the ipte control */
vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
vcpu->arch.sie_block->scaol = (__u32)(__u64)sca;
}
read_lock(&vcpu->kvm->arch.sca_lock);
if (vcpu->kvm->arch.use_esca) {
struct esca_block *sca = vcpu->kvm->arch.sca;
sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block;
vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
vcpu->arch.sie_block->scaol = (__u32)(__u64)sca & ~0x3fU;
vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
set_bit_inv(vcpu->vcpu_id, (unsigned long *) sca->mcn);
} else {
struct bsca_block *sca = vcpu->kvm->arch.sca;
sca->cpu[vcpu->vcpu_id].sda = (__u64) vcpu->arch.sie_block;
vcpu->arch.sie_block->scaoh = (__u32)(((__u64)sca) >> 32);
vcpu->arch.sie_block->scaol = (__u32)(__u64)sca;
set_bit_inv(vcpu->vcpu_id, (unsigned long *) &sca->mcn);
}
read_unlock(&vcpu->kvm->arch.sca_lock);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 206 | 69.13% | 4 | 50.00% |
| David Hildenbrand | 92 | 30.87% | 4 | 50.00% |
| Total | 298 | 100.00% | 8 | 100.00% |
/* Basic SCA to Extended SCA data copy routines */
static inline void sca_copy_entry(struct esca_entry *d, struct bsca_entry *s)
{
d->sda = s->sda;
d->sigp_ctrl.c = s->sigp_ctrl.c;
d->sigp_ctrl.scn = s->sigp_ctrl.scn;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 49 | 100.00% | 1 | 100.00% |
| Total | 49 | 100.00% | 1 | 100.00% |
static void sca_copy_b_to_e(struct esca_block *d, struct bsca_block *s)
{
int i;
d->ipte_control = s->ipte_control;
d->mcn[0] = s->mcn;
for (i = 0; i < KVM_S390_BSCA_CPU_SLOTS; i++)
sca_copy_entry(&d->cpu[i], &s->cpu[i]);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 70 | 100.00% | 1 | 100.00% |
| Total | 70 | 100.00% | 1 | 100.00% |
static int sca_switch_to_extended(struct kvm *kvm)
{
struct bsca_block *old_sca = kvm->arch.sca;
struct esca_block *new_sca;
struct kvm_vcpu *vcpu;
unsigned int vcpu_idx;
u32 scaol, scaoh;
new_sca = alloc_pages_exact(sizeof(*new_sca), GFP_KERNEL|__GFP_ZERO);
if (!new_sca)
return -ENOMEM;
scaoh = (u32)((u64)(new_sca) >> 32);
scaol = (u32)(u64)(new_sca) & ~0x3fU;
kvm_s390_vcpu_block_all(kvm);
write_lock(&kvm->arch.sca_lock);
sca_copy_b_to_e(new_sca, old_sca);
kvm_for_each_vcpu(vcpu_idx, vcpu, kvm) {
vcpu->arch.sie_block->scaoh = scaoh;
vcpu->arch.sie_block->scaol = scaol;
vcpu->arch.sie_block->ecb2 |= ECB2_ESCA;
}
kvm->arch.sca = new_sca;
kvm->arch.use_esca = 1;
write_unlock(&kvm->arch.sca_lock);
kvm_s390_vcpu_unblock_all(kvm);
free_page((unsigned long)old_sca);
VM_EVENT(kvm, 2, "Switched to ESCA (0x%pK -> 0x%pK)",
old_sca, kvm->arch.sca);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 216 | 99.08% | 2 | 50.00% |
| Christian Bornträger | 1 | 0.46% | 1 | 25.00% |
| David Hildenbrand | 1 | 0.46% | 1 | 25.00% |
| Total | 218 | 100.00% | 4 | 100.00% |
static int sca_can_add_vcpu(struct kvm *kvm, unsigned int id)
{
int rc;
if (!kvm_s390_use_sca_entries()) {
if (id < KVM_MAX_VCPUS)
return true;
return false;
}
if (id < KVM_S390_BSCA_CPU_SLOTS)
return true;
if (!sclp.has_esca || !sclp.has_64bscao)
return false;
mutex_lock(&kvm->lock);
rc = kvm->arch.use_esca ? 0 : sca_switch_to_extended(kvm);
mutex_unlock(&kvm->lock);
return rc == 0 && id < KVM_S390_ESCA_CPU_SLOTS;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Eugene (jno) Dvurechenski | 77 | 75.49% | 2 | 50.00% |
| David Hildenbrand | 25 | 24.51% | 2 | 50.00% |
| Total | 102 | 100.00% | 4 | 100.00% |
int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
{
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
kvm_clear_async_pf_completion_queue(vcpu);
vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
KVM_SYNC_GPRS |
KVM_SYNC_ACRS |
KVM_SYNC_CRS |
KVM_SYNC_ARCH0 |
KVM_SYNC_PFAULT;
kvm_s390_set_prefix(vcpu, 0);
if (test_kvm_facility(vcpu->kvm, 64))
vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
if (test_kvm_facility(vcpu->kvm, 82))
vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
if (test_kvm_facility(vcpu->kvm, 133))
vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
/* fprs can be synchronized via vrs, even if the guest has no vx. With
* MACHINE_HAS_VX, (load|store)_fpu_regs() will work with vrs format.
*/
if (MACHINE_HAS_VX)
vcpu->run->kvm_valid_regs |= KVM_SYNC_VRS;
else
vcpu->run->kvm_valid_regs |= KVM_SYNC_FPRS;
if (kvm_is_ucontrol(vcpu->kvm))
return __kvm_ucontrol_vcpu_init(vcpu);
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Fan Zhang | 32 | 22.07% | 2 | 12.50% |
| Christian Bornträger | 31 | 21.38% | 5 | 31.25% |
| Dominik Dingel | 30 | 20.69% | 1 | 6.25% |
| Eric Farman | 17 | 11.72% | 1 | 6.25% |
| David Hildenbrand | 15 | 10.34% | 3 | 18.75% |
| Julius Niedworok | 7 | 4.83% | 1 | 6.25% |
| Heiko Carstens | 6 | 4.14% | 1 | 6.25% |
| Cornelia Huck | 4 | 2.76% | 1 | 6.25% |
| Carsten Otte | 3 | 2.07% | 1 | 6.25% |
| Total | 145 | 100.00% | 16 | 100.00% |
/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
static void __start_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
WARN_ON_ONCE(vcpu->arch.cputm_start != 0);
raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
vcpu->arch.cputm_start = get_tod_clock_fast();
raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 51 | 100.00% | 2 | 100.00% |
| Total | 51 | 100.00% | 2 | 100.00% |
/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
static void __stop_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
WARN_ON_ONCE(vcpu->arch.cputm_start == 0);
raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
vcpu->arch.sie_block->cputm -= get_tod_clock_fast() - vcpu->arch.cputm_start;
vcpu->arch.cputm_start = 0;
raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 67 | 100.00% | 2 | 100.00% |
| Total | 67 | 100.00% | 2 | 100.00% |
/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
static void __enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
WARN_ON_ONCE(vcpu->arch.cputm_enabled);
vcpu->arch.cputm_enabled = true;
__start_cpu_timer_accounting(vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 33 | 100.00% | 1 | 100.00% |
| Total | 33 | 100.00% | 1 | 100.00% |
/* needs disabled preemption to protect from TOD sync and vcpu_load/put */
static void __disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
WARN_ON_ONCE(!vcpu->arch.cputm_enabled);
__stop_cpu_timer_accounting(vcpu);
vcpu->arch.cputm_enabled = false;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 34 | 100.00% | 1 | 100.00% |
| Total | 34 | 100.00% | 1 | 100.00% |
static void enable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
preempt_disable(); /* protect from TOD sync and vcpu_load/put */
__enable_cpu_timer_accounting(vcpu);
preempt_enable();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
static void disable_cpu_timer_accounting(struct kvm_vcpu *vcpu)
{
preempt_disable(); /* protect from TOD sync and vcpu_load/put */
__disable_cpu_timer_accounting(vcpu);
preempt_enable();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 23 | 100.00% | 1 | 100.00% |
| Total | 23 | 100.00% | 1 | 100.00% |
/* set the cpu timer - may only be called from the VCPU thread itself */
void kvm_s390_set_cpu_timer(struct kvm_vcpu *vcpu, __u64 cputm)
{
preempt_disable(); /* protect from TOD sync and vcpu_load/put */
raw_write_seqcount_begin(&vcpu->arch.cputm_seqcount);
if (vcpu->arch.cputm_enabled)
vcpu->arch.cputm_start = get_tod_clock_fast();
vcpu->arch.sie_block->cputm = cputm;
raw_write_seqcount_end(&vcpu->arch.cputm_seqcount);
preempt_enable();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 67 | 100.00% | 3 | 100.00% |
| Total | 67 | 100.00% | 3 | 100.00% |
/* update and get the cpu timer - can also be called from other VCPU threads */
__u64 kvm_s390_get_cpu_timer(struct kvm_vcpu *vcpu)
{
unsigned int seq;
__u64 value;
if (unlikely(!vcpu->arch.cputm_enabled))
return vcpu->arch.sie_block->cputm;
preempt_disable(); /* protect from TOD sync and vcpu_load/put */
do {
seq = raw_read_seqcount(&vcpu->arch.cputm_seqcount);
/*
* If the writer would ever execute a read in the critical
* section, e.g. in irq context, we have a deadlock.
*/
WARN_ON_ONCE((seq & 1) && smp_processor_id() == vcpu->cpu);
value = vcpu->arch.sie_block->cputm;
/* if cputm_start is 0, accounting is being started/stopped */
if (likely(vcpu->arch.cputm_start))
value -= get_tod_clock_fast() - vcpu->arch.cputm_start;
} while (read_seqcount_retry(&vcpu->arch.cputm_seqcount, seq & ~1));
preempt_enable();
return value;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 129 | 98.47% | 3 | 75.00% |
| Heiko Carstens | 2 | 1.53% | 1 | 25.00% |
| Total | 131 | 100.00% | 4 | 100.00% |
void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
gmap_enable(vcpu->arch.enabled_gmap);
atomic_or(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
__start_cpu_timer_accounting(vcpu);
vcpu->cpu = cpu;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 32 | 52.46% | 5 | 45.45% |
| Carsten Otte | 11 | 18.03% | 2 | 18.18% |
| Cornelia Huck | 7 | 11.48% | 1 | 9.09% |
| Heiko Carstens | 6 | 9.84% | 1 | 9.09% |
| Christian Bornträger | 4 | 6.56% | 1 | 9.09% |
| Peter Zijlstra | 1 | 1.64% | 1 | 9.09% |
| Total | 61 | 100.00% | 11 | 100.00% |
void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
{
vcpu->cpu = -1;
if (vcpu->arch.cputm_enabled && !is_vcpu_idle(vcpu))
__stop_cpu_timer_accounting(vcpu);
atomic_andnot(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
vcpu->arch.enabled_gmap = gmap_get_enabled();
gmap_disable(vcpu->arch.enabled_gmap);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 36 | 52.94% | 4 | 40.00% |
| Carsten Otte | 11 | 16.18% | 1 | 10.00% |
| Heiko Carstens | 9 | 13.24% | 1 | 10.00% |
| Cornelia Huck | 9 | 13.24% | 1 | 10.00% |
| Christian Bornträger | 2 | 2.94% | 2 | 20.00% |
| Peter Zijlstra | 1 | 1.47% | 1 | 10.00% |
| Total | 68 | 100.00% | 10 | 100.00% |
static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
{
/* this equals initial cpu reset in pop, but we don't switch to ESA */
vcpu->arch.sie_block->gpsw.mask = 0UL;
vcpu->arch.sie_block->gpsw.addr = 0UL;
kvm_s390_set_prefix(vcpu, 0);
kvm_s390_set_cpu_timer(vcpu, 0);
vcpu->arch.sie_block->ckc = 0UL;
vcpu->arch.sie_block->todpr = 0;
memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
vcpu->arch.sie_block->gcr[0] = 0xE0UL;
vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
/* make sure the new fpc will be lazily loaded */
save_fpu_regs();
current->thread.fpu.fpc = 0;
vcpu->arch.sie_block->gbea = 1;
vcpu->arch.sie_block->pp = 0;
vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
kvm_clear_async_pf_completion_queue(vcpu);
if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
kvm_s390_vcpu_stop(vcpu);
kvm_s390_clear_local_irqs(vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 99 | 51.03% | 1 | 7.69% |
| Christian Bornträger | 41 | 21.13% | 5 | 38.46% |
| David Hildenbrand | 23 | 11.86% | 4 | 30.77% |
| Gleb Natapov | 16 | 8.25% | 1 | 7.69% |
| Dominik Dingel | 13 | 6.70% | 1 | 7.69% |
| Jens Freimann | 2 | 1.03% | 1 | 7.69% |
| Total | 194 | 100.00% | 13 | 100.00% |
void kvm_arch_vcpu_postcreate(struct kvm_vcpu *vcpu)
{
mutex_lock(&vcpu->kvm->lock);
preempt_disable();
vcpu->arch.sie_block->epoch = vcpu->kvm->arch.epoch;
preempt_enable();
mutex_unlock(&vcpu->kvm->lock);
if (!kvm_is_ucontrol(vcpu->kvm)) {
vcpu->arch.gmap = vcpu->kvm->arch.gmap;
sca_add_vcpu(vcpu);
}
if (test_kvm_facility(vcpu->kvm, 74) || vcpu->kvm->arch.user_instr0)
vcpu->arch.sie_block->ictl |= ICTL_OPEREXC;
/* make vcpu_load load the right gmap on the first trigger */
vcpu->arch.enabled_gmap = vcpu->arch.gmap;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 49 | 39.20% | 3 | 33.33% |
| Jason J. Herne | 36 | 28.80% | 1 | 11.11% |
| Dominik Dingel | 27 | 21.60% | 2 | 22.22% |
| Fan Zhang | 6 | 4.80% | 1 | 11.11% |
| Sheng Yang | 4 | 3.20% | 1 | 11.11% |
| Marcelo Tosatti | 3 | 2.40% | 1 | 11.11% |
| Total | 125 | 100.00% | 9 | 100.00% |
static void kvm_s390_vcpu_crypto_setup(struct kvm_vcpu *vcpu)
{
if (!test_kvm_facility(vcpu->kvm, 76))
return;
vcpu->arch.sie_block->ecb3 &= ~(ECB3_AES | ECB3_DEA);
if (vcpu->kvm->arch.crypto.aes_kw)
vcpu->arch.sie_block->ecb3 |= ECB3_AES;
if (vcpu->kvm->arch.crypto.dea_kw)
vcpu->arch.sie_block->ecb3 |= ECB3_DEA;
vcpu->arch.sie_block->crycbd = vcpu->kvm->arch.crypto.crycbd;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Tony Krowiak | 96 | 95.05% | 2 | 66.67% |
| Michael Müller | 5 | 4.95% | 1 | 33.33% |
| Total | 101 | 100.00% | 3 | 100.00% |
void kvm_s390_vcpu_unsetup_cmma(struct kvm_vcpu *vcpu)
{
free_page(vcpu->arch.sie_block->cbrlo);
vcpu->arch.sie_block->cbrlo = 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 14 | 45.16% | 1 | 20.00% |
| Dominik Dingel | 12 | 38.71% | 1 | 20.00% |
| Carsten Otte | 3 | 9.68% | 1 | 20.00% |
| Cornelia Huck | 1 | 3.23% | 1 | 20.00% |
| Christian Bornträger | 1 | 3.23% | 1 | 20.00% |
| Total | 31 | 100.00% | 5 | 100.00% |
int kvm_s390_vcpu_setup_cmma(struct kvm_vcpu *vcpu)
{
vcpu->arch.sie_block->cbrlo = get_zeroed_page(GFP_KERNEL);
if (!vcpu->arch.sie_block->cbrlo)
return -ENOMEM;
vcpu->arch.sie_block->ecb2 &= ~ECB2_PFMFI;
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Carsten Otte | 17 | 32.69% | 1 | 14.29% |
| Dominik Dingel | 16 | 30.77% | 2 | 28.57% |
| Heiko Carstens | 12 | 23.08% | 1 | 14.29% |
| Christian Bornträger | 6 | 11.54% | 2 | 28.57% |
| David Hildenbrand | 1 | 1.92% | 1 | 14.29% |
| Total | 52 | 100.00% | 7 | 100.00% |
static void kvm_s390_vcpu_setup_model(struct kvm_vcpu *vcpu)
{
struct kvm_s390_cpu_model *model = &vcpu->kvm->arch.model;
vcpu->arch.sie_block->ibc = model->ibc;
if (test_kvm_facility(vcpu->kvm, 7))
vcpu->arch.sie_block->fac = (u32)(u64) model->fac_list;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Michael Müller | 52 | 78.79% | 1 | 33.33% |
| David Hildenbrand | 14 | 21.21% | 2 | 66.67% |
| Total | 66 | 100.00% | 3 | 100.00% |
int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
{
int rc = 0;
atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
CPUSTAT_SM |
CPUSTAT_STOPPED);
if (test_kvm_facility(vcpu->kvm, 78))
atomic_or(CPUSTAT_GED2, &vcpu->arch.sie_block->cpuflags);
else if (test_kvm_facility(vcpu->kvm, 8))
atomic_or(CPUSTAT_GED, &vcpu->arch.sie_block->cpuflags);
kvm_s390_vcpu_setup_model(vcpu);
/* pgste_set_pte has special handling for !MACHINE_HAS_ESOP */
if (MACHINE_HAS_ESOP)
vcpu->arch.sie_block->ecb |= ECB_HOSTPROTINT;
if (test_kvm_facility(vcpu->kvm, 9))
vcpu->arch.sie_block->ecb |= ECB_SRSI;
if (test_kvm_facility(vcpu->kvm, 73))
vcpu->arch.sie_block->ecb |= ECB_TE;
if (test_kvm_facility(vcpu->kvm, 8) && sclp.has_pfmfi)
vcpu->arch.sie_block->ecb2 |= ECB2_PFMFI;
if (test_kvm_facility(vcpu->kvm, 130))
vcpu->arch.sie_block->ecb2 |= ECB2_IEP;
vcpu->arch.sie_block->eca = ECA_MVPGI | ECA_PROTEXCI;
if (sclp.has_cei)
vcpu->arch.sie_block->eca |= ECA_CEI;
if (sclp.has_ib)
vcpu->arch.sie_block->eca |= ECA_IB;
if (sclp.has_siif)
vcpu->arch.sie_block->eca |= ECA_SII;
if (sclp.has_sigpif)
vcpu->arch.sie_block->eca |= ECA_SIGPI;
if (test_kvm_facility(vcpu->kvm, 129)) {
vcpu->arch.sie_block->eca |= ECA_VX;
vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
}
if (test_kvm_facility(vcpu->kvm, 139))
vcpu->arch.sie_block->ecd |= ECD_MEF;
vcpu->arch.sie_block->sdnxo = ((unsigned long) &vcpu->run->s.regs.sdnx)
| SDNXC;
vcpu->arch.sie_block->riccbd = (unsigned long) &vcpu->run->s.regs.riccb;
if (sclp.has_kss)
atomic_or(CPUSTAT_KSS, &vcpu->arch.sie_block->cpuflags);
else
vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
if (vcpu->kvm->arch.use_cmma) {
rc = kvm_s390_vcpu_setup_cmma(vcpu);
if (rc)
return rc;
}
hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
kvm_s390_vcpu_crypto_setup(vcpu);
return rc;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| David Hildenbrand | 106 | 22.80% | 10 | 26.32% |
| Heiko Carstens | 64 | 13.76% | 2 | 5.26% |
| Fan Zhang | 50 | 10.75% | 2 | 5.26% |
| Guenther Hutzl | 48 | 10.32% | 2 | 5.26% |
| Michael Müller | 30 | 6.45% | 4 | 10.53% |
| Dominik Dingel | 28 | 6.02% | 3 | 7.89% |
| Eric Farman | 26 | 5.59% | 1 | 2.63% |
| Farhan Ali | 21 | 4.52% | 1 | 2.63% |
| Collin L. Walling | 21 | 4.52% | 1 | 2.63% |
| Janosch Frank | 20 | 4.30% | 1 | 2.63% |
| Christian Bornträger | 19 | 4.09% | 4 | 10.53% |
| Konstantin Weitz | 11 | 2.37% | 1 | 2.63% |
| Martin Schwidefsky | 8 | 1.72% | 1 | 2.63% |
| Tony Krowiak | 5 | 1.08% | 1 | 2.63% |
| Carsten Otte | 4 | 0.86% | 2 | 5.26% |
| Peter Zijlstra | 2 | 0.43% | 1 | 2.63% |
| Cornelia Huck | 2 | 0.43% | 1 | 2.63% |
| Total | 465 | 100.00% | 38 | 100.00% |
struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
unsigned int id)
{
struct kvm_vcpu *vcpu;
struct sie_page *sie_page;
int rc = -EINVAL;
if (!kvm_is_ucontrol(kvm) && !sca_can_add_vcpu(kvm, id))
goto out;
rc = -ENOMEM;
vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
if (!vcpu)
goto out;
BUILD_BUG_ON(sizeof(struct sie_page) != 4096);
sie_page = (struct sie_page *) get_zeroed_page(GFP_KERNEL);
if (!sie_page)
goto out_free_cpu;
vcpu->arch.sie_block = &sie_page->sie_block;
vcpu->arch.sie_block->itdba = (unsigned long) &sie_page->itdb;
/* the real guest size will always be smaller than msl */
vcpu->arch.sie_block->mso = 0;
vcpu->arch.sie_block->msl = sclp.hamax;
vcpu->arch.sie_block->icpua = id;
spin_lock_init(&vcpu->arch.local_int.lock);
vcpu->arch.local_int.float_int = &kvm->arch.float_int;
vcpu->arch.local_int.wq = &vcpu->wq;
vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
seqcount_init(&vcpu->arch.cputm_seqcount);
rc = kvm_vcpu_init(vcpu, kvm, id);
if (rc)
goto out_free_sie_block;
VM_EVENT(kvm, 3, "create cpu %d at 0x%pK, sie block at 0x%pK", id, vcpu,
vcpu->arch.sie_block);
trace_kvm_s390_create_vcpu(id, vcpu, vcpu->arch.sie_block);
return vcpu;
out_free_sie_block:
free_page((unsigned long)(vcpu->arch.sie_block));
out_free_cpu:
kmem_cache_free(kvm_vcpu_cache, vcpu);
out:
return ERR_PTR(rc);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 116 | 36.36% | 1 | 4.17% |
| Carsten Otte | 47 | 14.73% | 2 | 8.33% |
| David Hildenbrand | 40 | 12.54% | 4 | 16.67% |
| Michael Müller | 31 | 9.72% | 2 | 8.33% |
| Christian Bornträger | 28 | 8.78% | 7 | 29.17% |
| Cornelia Huck | 11 | 3.45% | 2 | 8.33% |
| QingFeng Hao | 11 | 3.45% | 1 | 4.17% |
| Martin Schwidefsky | 10 | 3.13% | 1 | 4.17% |
| Wei Yongjun | 9 | 2.82% | 1 | 4.17% |
| Dominik Dingel | 6 | 1.88% | 1 | 4.17% |
| Eugene (jno) Dvurechenski | 6 | 1.88% | 1 | 4.17% |
| Jens Freimann | 4 | 1.25% | 1 | 4.17% |
| Total | 319 | 100.00% | 24 | 100.00% |
int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
{
return kvm_s390_vcpu_has_irq(vcpu, 0);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Marcelo Tosatti | 11 | 61.11% | 1 | 25.00% |
| Michael Müller | 3 | 16.67% | 1 | 25.00% |
| David Hildenbrand | 3 | 16.67% | 1 | 25.00% |
| Heiko Carstens | 1 | 5.56% | 1 | 25.00% |
| Total | 18 | 100.00% | 4 | 100.00% |
bool kvm_arch_vcpu_in_kernel(struct kvm_vcpu *vcpu)
{
return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Longpeng( Mike) | 26 | 100.00% | 2 | 100.00% |
| Total | 26 | 100.00% | 2 | 100.00% |
void kvm_s390_vcpu_block(struct kvm_vcpu *vcpu)
{
atomic_or(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
exit_sie(vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Heiko Carstens | 17 | 58.62% | 1 | 20.00% |
| Christian Bornträger | 6 | 20.69% | 2 | 40.00% |
| David Hildenbrand | 5 | 17.24% | 1 | 20.00% |
| Peter Zijlstra | 1 | 3.45% | 1 | 20.00% |
| Total | 29 | 100.00% | 5 | 100.00% |
void kvm_s390_vcpu_unblock(struct kvm_vcpu *vcpu)
{
atomic_andnot(PROG_BLOCK_SIE, &vcpu->arch.sie_block->prog20);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 14 | 58.33% | 2 | 40.00% |
| Michael Müller | 8 | 33.33% | 1 | 20.00% |
| Heiko Carstens | 1 | 4.17% | 1 | 20.00% |
| Peter Zijlstra | 1 | 4.17% | 1 | 20.00% |
| Total | 24 | 100.00% | 5 | 100.00% |
static void kvm_s390_vcpu_request(struct kvm_vcpu *vcpu)
{
atomic_or(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
exit_sie(vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 24 | 80.00% | 1 | 33.33% |
| David Hildenbrand | 5 | 16.67% | 1 | 33.33% |
| Peter Zijlstra | 1 | 3.33% | 1 | 33.33% |
| Total | 30 | 100.00% | 3 | 100.00% |
static void kvm_s390_vcpu_request_handled(struct kvm_vcpu *vcpu)
{
atomic_andnot(PROG_REQUEST, &vcpu->arch.sie_block->prog20);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 24 | 96.00% | 1 | 50.00% |
| Jason J. Herne | 1 | 4.00% | 1 | 50.00% |
| Total | 25 | 100.00% | 2 | 100.00% |
/*
* Kick a guest cpu out of SIE and wait until SIE is not running.
* If the CPU is not running (e.g. waiting as idle) the function will
* return immediately. */
void exit_sie(struct kvm_vcpu *vcpu)
{
atomic_or(CPUSTAT_STOP_INT, &vcpu->arch.sie_block->cpuflags);
while (vcpu->arch.sie_block->prog0c & PROG_IN_SIE)
cpu_relax();
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 34 | 87.18% | 3 | 50.00% |
| Konstantin Weitz | 2 | 5.13% | 1 | 16.67% |
| Heiko Carstens | 2 | 5.13% | 1 | 16.67% |
| Peter Zijlstra | 1 | 2.56% | 1 | 16.67% |
| Total | 39 | 100.00% | 6 | 100.00% |
/* Kick a guest cpu out of SIE to process a request synchronously */
void kvm_s390_sync_request(int req, struct kvm_vcpu *vcpu)
{
kvm_make_request(req, vcpu);
kvm_s390_vcpu_request(vcpu);
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 20 | 80.00% | 2 | 66.67% |
| Konstantin Weitz | 5 | 20.00% | 1 | 33.33% |
| Total | 25 | 100.00% | 3 | 100.00% |
static void kvm_gmap_notifier(struct gmap *gmap, unsigned long start,
unsigned long end)
{
struct kvm *kvm = gmap->private;
struct kvm_vcpu *vcpu;
unsigned long prefix;
int i;
if (gmap_is_shadow(gmap))
return;
if (start >= 1UL << 31)
/* We are only interested in prefix pages */
return;
kvm_for_each_vcpu(i, vcpu, kvm) {
/* match against both prefix pages */
prefix = kvm_s390_get_prefix(vcpu);
if (prefix <= end && start <= prefix + 2*PAGE_SIZE - 1) {
VCPU_EVENT(vcpu, 2, "gmap notifier for %lx-%lx",
start, end);
kvm_s390_sync_request(KVM_REQ_MMU_RELOAD, vcpu);
}
}
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christian Bornträger | 50 | 43.86% | 3 | 37.50% |
| Martin Schwidefsky | 44 | 38.60% | 1 | 12.50% |
| David Hildenbrand | 8 | 7.02% | 1 | 12.50% |
| Carsten Otte | 7 | 6.14% | 1 | 12.50% |
| Konstantin Weitz | 3 | 2.63% | 1 | 12.50% |
| Michael Müller | 2 | 1.75% | 1 | 12.50% |
| Total | 114 | 100.00% | 8 | 100.00% |
int kvm_arch_vcpu_should_kick(struct kvm_vcpu *vcpu)
{
/* kvm common code refers to this, but never calls it */
BUG();
return 0;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Christoffer Dall | 9 | 52.94% | 1 | 33.33% |
| Heiko Carstens | 6 | 35.29% | 1 | 33.33% |
| Christian Bornträger | 2 | 11.76% | 1 | 33.33% |
| Total | 17 | 100.00% | 3 | 100.00% |
static int kvm_arch_vcpu_ioctl_get_one_reg(struct kvm_vcpu *vcpu,
struct kvm_one_reg *reg)
{
int r = -EINVAL;
switch (reg->id) {
case KVM_REG_S390_TODPR:
r = put_user(vcpu->arch.sie_block->todpr,
(u32 __user *)reg->addr);
break;
case KVM_REG_S390_EPOCHDIFF:
r = put_user(vcpu->arch.sie_block->epoch,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_CPU_TIMER:
r = put_user(kvm_s390_get_cpu_timer(vcpu),
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_CLOCK_COMP:
r = put_user(vcpu->arch.sie_block->ckc,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_PFTOKEN:
r = put_user(vcpu->arch.pfault_token,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_PFCOMPARE:
r = put_user(vcpu->arch.pfault_compare,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_PFSELECT:
r = put_user(vcpu->arch.pfault_select,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_PP:
r = put_user(vcpu->arch.sie_block->pp,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_GBEA:
r = put_user(vcpu->arch.sie_block->gbea,
(u64 __user *)reg->addr);
break;
default:
break;
}
return r;
}
Contributors
| Person | Tokens | Prop | Commits | CommitProp |
| Carsten Otte | 65 | 25.00% | 4 | 33.33% |
| Heiko Carstens | 59 | 22.69% | 1 | 8.33% |
| Dominik Dingel | 55 | 21.15% | 1 | 8.33% |
| Christian Bornträger | 35 | 13.46% | 3 | 25.00% |
| Jason J. Herne | 34 | 13.08% | 1 | 8.33% |
| Michael Müller | 9 | 3.46% | 1 | 8.33% |
| David Hildenbrand | 3 | 1.15% | 1 | 8.33% |
| Total | 260 | 100.00% | 12 | 100.00% |
static int kvm_arch_vcpu_ioctl_set_one_reg(struct kvm_vcpu *vcpu,
struct kvm_one_reg *reg)
{
int r = -EINVAL;
__u64 val;
switch (reg->id) {
case KVM_REG_S390_TODPR:
r = get_user(vcpu->arch.sie_block->todpr,
(u32 __user *)reg->addr);
break;
case KVM_REG_S390_EPOCHDIFF:
r = get_user(vcpu->arch.sie_block->epoch,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_CPU_TIMER:
r = get_user(val, (u64 __user *)reg->addr);
if (!r)
kvm_s390_set_cpu_timer(vcpu, val);
break;
case KVM_REG_S390_CLOCK_COMP:
r = get_user(vcpu->arch.sie_block->ckc,
(u64 __user *)reg->addr);
break;
case KVM_REG_S390_PFTOKEN:
r = get_user(vcpu->arch.pfault_token,
(u64 __user *)reg->addr);