KVM: s390: synchronize more registers with kvm_run
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Thu, 17 Jul 2014 08:47:43 +0000 (10:47 +0200)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Mon, 25 Aug 2014 12:35:53 +0000 (14:35 +0200)
In order to reduce the number of syscalls when dropping to user space, this
patch enables the synchronization of the following "registers" with kvm_run:
- ARCH0: CPU timer, clock comparator, TOD programmable register,
         guest breaking-event register, program parameter
- PFAULT: pfault parameters (token, select, compare)

The registers are grouped to reduce the overhead when syncing.

As this grows the number of sync registers quite a bit, let's move the code
synchronizing registers with kvm_run from kvm_arch_vcpu_ioctl_run() into
separate helper routines.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Reviewed-by: Cornelia Huck <cornelia.huck@de.ibm.com>
Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/include/uapi/asm/kvm.h
arch/s390/kvm/kvm-s390.c

index 0fc2643..48eda3a 100644 (file)
@@ -111,12 +111,22 @@ struct kvm_guest_debug_arch {
 #define KVM_SYNC_GPRS   (1UL << 1)
 #define KVM_SYNC_ACRS   (1UL << 2)
 #define KVM_SYNC_CRS    (1UL << 3)
+#define KVM_SYNC_ARCH0  (1UL << 4)
+#define KVM_SYNC_PFAULT (1UL << 5)
 /* definition of registers in kvm_run */
 struct kvm_sync_regs {
        __u64 prefix;   /* prefix register */
        __u64 gprs[16]; /* general purpose registers */
        __u32 acrs[16]; /* access registers */
        __u64 crs[16];  /* control registers */
+       __u64 todpr;    /* tod programmable register [ARCH0] */
+       __u64 cputm;    /* cpu timer [ARCH0] */
+       __u64 ckc;      /* clock comparator [ARCH0] */
+       __u64 pp;       /* program parameter [ARCH0] */
+       __u64 gbea;     /* guest breaking-event address [ARCH0] */
+       __u64 pft;      /* pfault token [PFAULT] */
+       __u64 pfs;      /* pfault select [PFAULT] */
+       __u64 pfc;      /* pfault compare [PFAULT] */
 };
 
 #define KVM_REG_S390_TODPR     (KVM_REG_S390 | KVM_REG_SIZE_U32 | 0x1)
index f00d0b0..ab7cd64 100644 (file)
@@ -546,7 +546,9 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX |
                                    KVM_SYNC_GPRS |
                                    KVM_SYNC_ACRS |
-                                   KVM_SYNC_CRS;
+                                   KVM_SYNC_CRS |
+                                   KVM_SYNC_ARCH0 |
+                                   KVM_SYNC_PFAULT;
        return 0;
 }
 
@@ -1296,6 +1298,47 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
        return rc;
 }
 
+static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
+       vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
+               memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
+               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
+       }
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_ARCH0) {
+               vcpu->arch.sie_block->cputm = kvm_run->s.regs.cputm;
+               vcpu->arch.sie_block->ckc = kvm_run->s.regs.ckc;
+               vcpu->arch.sie_block->todpr = kvm_run->s.regs.todpr;
+               vcpu->arch.sie_block->pp = kvm_run->s.regs.pp;
+               vcpu->arch.sie_block->gbea = kvm_run->s.regs.gbea;
+       }
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_PFAULT) {
+               vcpu->arch.pfault_token = kvm_run->s.regs.pft;
+               vcpu->arch.pfault_select = kvm_run->s.regs.pfs;
+               vcpu->arch.pfault_compare = kvm_run->s.regs.pfc;
+       }
+       kvm_run->kvm_dirty_regs = 0;
+}
+
+static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
+{
+       kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
+       kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
+       kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu);
+       memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
+       kvm_run->s.regs.cputm = vcpu->arch.sie_block->cputm;
+       kvm_run->s.regs.ckc = vcpu->arch.sie_block->ckc;
+       kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
+       kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
+       kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
+       kvm_run->s.regs.pft = vcpu->arch.pfault_token;
+       kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
+       kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
+}
+
 int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        int rc;
@@ -1317,15 +1360,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                return -EINVAL;
        }
 
-       vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
-       vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
-       if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
-               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
-       if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
-               memcpy(&vcpu->arch.sie_block->gcr, &kvm_run->s.regs.crs, 128);
-               kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
-       }
-       kvm_run->kvm_dirty_regs = 0;
+       sync_regs(vcpu, kvm_run);
 
        might_fault();
        rc = __vcpu_run(vcpu);
@@ -1355,10 +1390,7 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
                rc = 0;
        }
 
-       kvm_run->psw_mask     = vcpu->arch.sie_block->gpsw.mask;
-       kvm_run->psw_addr     = vcpu->arch.sie_block->gpsw.addr;
-       kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu);
-       memcpy(&kvm_run->s.regs.crs, &vcpu->arch.sie_block->gcr, 128);
+       store_regs(vcpu, kvm_run);
 
        if (vcpu->sigset_active)
                sigprocmask(SIG_SETMASK, &sigsaved, NULL);