KVM: s390: Don't enable skeys by default
authorDominik Dingel <dingel@linux.vnet.ibm.com>
Tue, 14 Jan 2014 17:11:14 +0000 (18:11 +0100)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Tue, 22 Apr 2014 07:36:26 +0000 (09:36 +0200)
The first invocation of storage key operations on a given cpu will be intercepted.

On these intercepts we will enable storage keys for the guest and remove the
previously added intercepts.

Signed-off-by: Dominik Dingel <dingel@linux.vnet.ibm.com>
Acked-by: Martin Schwidefsky <schwidefsky@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/asm/kvm_host.h
arch/s390/include/asm/mmu_context.h
arch/s390/kvm/kvm-s390.c
arch/s390/kvm/priv.c
arch/s390/kvm/trace.h

index 154b600..a993b6f 100644 (file)
@@ -89,6 +89,9 @@ struct kvm_s390_sie_block {
        __u16   lctl;                   /* 0x0044 */
        __s16   icpua;                  /* 0x0046 */
 #define ICTL_LPSW 0x00400000
+#define ICTL_ISKE 0x00004000
+#define ICTL_SSKE 0x00002000
+#define ICTL_RRBE 0x00001000
        __u32   ictl;                   /* 0x0048 */
        __u32   eca;                    /* 0x004c */
        __u8    icptcode;               /* 0x0050 */
index 05925ea..d42fb1b 100644 (file)
@@ -23,7 +23,7 @@ static inline int init_new_context(struct task_struct *tsk,
        mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
        mm->context.has_pgste = 0;
-       mm->context.use_skey = 1;
+       mm->context.use_skey = 0;
        mm->context.asce_limit = STACK_TOP_MAX;
        crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
        return 0;
index b3ecb8f..b767ec9 100644 (file)
@@ -465,6 +465,7 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
        vcpu->arch.sie_block->ecb2  = 8;
        vcpu->arch.sie_block->eca   = 0xC1002001U;
        vcpu->arch.sie_block->fac   = (int) (long) vfacilities;
+       vcpu->arch.sie_block->ictl |= ICTL_ISKE | ICTL_SSKE | ICTL_RRBE;
        if (kvm_enabled_cmma()) {
                cbrl = alloc_page(GFP_KERNEL | __GFP_ZERO);
                if (cbrl) {
index 476e9e2..8a63e99 100644 (file)
@@ -147,8 +147,21 @@ static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
        return 0;
 }
 
+static void __skey_check_enable(struct kvm_vcpu *vcpu)
+{
+       if (!(vcpu->arch.sie_block->ictl & (ICTL_ISKE | ICTL_SSKE | ICTL_RRBE)))
+               return;
+
+       s390_enable_skey();
+       trace_kvm_s390_skey_related_inst(vcpu);
+       vcpu->arch.sie_block->ictl &= ~(ICTL_ISKE | ICTL_SSKE | ICTL_RRBE);
+}
+
+
 static int handle_skey(struct kvm_vcpu *vcpu)
 {
+       __skey_check_enable(vcpu);
+
        vcpu->stat.instruction_storage_key++;
 
        if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
@@ -618,6 +631,7 @@ static int handle_pfmf(struct kvm_vcpu *vcpu)
                }
 
                if (vcpu->run->s.regs.gprs[reg1] & PFMF_SK) {
+                       __skey_check_enable(vcpu);
                        if (set_guest_storage_key(current->mm, useraddr,
                                        vcpu->run->s.regs.gprs[reg1] & PFMF_KEY,
                                        vcpu->run->s.regs.gprs[reg1] & PFMF_NQ))
index e8e7213..a4bf7d7 100644 (file)
        TP_printk("%02d[%016lx-%016lx]: " p_str, __entry->id,           \
                  __entry->pswmask, __entry->pswaddr, p_args)
 
+TRACE_EVENT(kvm_s390_skey_related_inst,
+           TP_PROTO(VCPU_PROTO_COMMON),
+           TP_ARGS(VCPU_ARGS_COMMON),
+
+           TP_STRUCT__entry(
+                   VCPU_FIELD_COMMON
+                   ),
+
+           TP_fast_assign(
+                   VCPU_ASSIGN_COMMON
+                   ),
+           VCPU_TP_PRINTK("%s", "first instruction related to skeys on vcpu")
+       );
+
 TRACE_EVENT(kvm_s390_major_guest_pfault,
            TP_PROTO(VCPU_PROTO_COMMON),
            TP_ARGS(VCPU_ARGS_COMMON),