qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH] s390: use sync regs for register transfer


From: Jens Freimann
Subject: [Qemu-devel] [PATCH] s390: use sync regs for register transfer
Date: Wed, 22 Aug 2012 13:54:43 +0200

From: Christian Borntraeger <address@hidden>

Newer kernels provide the guest registers in kvm_run. Lets use
those if available. This avoids ioctls on cpu_synchronize_state
making intercepts faster.

In addition, we have now the prefix register, the access registers
the control registers up to date. This helps in certain cases,
e.g. for resolving kernel module addresses with gdb on a guest.

On return, we only update the gprs, since qemu does not change
prefix, crs and acrs. Blindly updating those might cause some
expensive flushing in the kernel.

Signed-off-by: Christian Borntraeger <address@hidden>
Signed-off-by: Jens Freimann <address@hidden>
---
 target-s390x/kvm.c | 75 +++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 51 insertions(+), 24 deletions(-)

diff --git a/target-s390x/kvm.c b/target-s390x/kvm.c
index 07edf93..4598923 100644
--- a/target-s390x/kvm.c
+++ b/target-s390x/kvm.c
@@ -88,50 +88,77 @@ void kvm_arch_reset_vcpu(CPUS390XState *env)
     /* FIXME: add code to reset vcpu. */
 }
 
+/* we want to have the prefix, the GPRS, the ACRS and the CRS up to date */
+#define QEMU_NEEDED_REGS  (KVM_SYNC_PREFIX | KVM_SYNC_GPRS | \
+                         KVM_SYNC_ACRS   | KVM_SYNC_CRS)
+
+/* But qemu only changes the GPRS */
+#define QEMU_DIRTY_REGS  (KVM_SYNC_GPRS)
+
 int kvm_arch_put_registers(CPUS390XState *env, int level)
 {
     struct kvm_regs regs;
     int ret;
     int i;
 
-    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
-    if (ret < 0) {
-        return ret;
-    }
-
-    for (i = 0; i < 16; i++) {
-        regs.gprs[i] = env->regs[i];
-    }
-
-    ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
-    if (ret < 0) {
-        return ret;
-    }
-
     env->kvm_run->psw_addr = env->psw.addr;
     env->kvm_run->psw_mask = env->psw.mask;
 
-    return ret;
+    if ((env->kvm_run->kvm_valid_regs & QEMU_NEEDED_REGS) == QEMU_NEEDED_REGS) 
{
+        env->kvm_run->s.regs.prefix = env->psa;
+        for (i = 0; i < 16; i++) {
+            env->kvm_run->s.regs.gprs[i] = env->regs[i];
+            env->kvm_run->kvm_dirty_regs |= QEMU_DIRTY_REGS;
+        }
+    } else {
+        for (i = 0; i < 16; i++) {
+            regs.gprs[i] = env->regs[i];
+        }
+        ret = kvm_vcpu_ioctl(env, KVM_SET_REGS, &regs);
+        if (ret < 0) {
+            return ret;
+        }
+        /* no prefix available */
+    }
+    /* sregs unchanged */
+
+    return 0;
 }
 
 int kvm_arch_get_registers(CPUS390XState *env)
 {
     int ret;
     struct kvm_regs regs;
+    struct kvm_sregs sregs;
     int i;
 
-    ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
-    if (ret < 0) {
-        return ret;
-    }
-
-    for (i = 0; i < 16; i++) {
-        env->regs[i] = regs.gprs[i];
-    }
-
     env->psw.addr = env->kvm_run->psw_addr;
     env->psw.mask = env->kvm_run->psw_mask;
 
+    if ((env->kvm_run->kvm_valid_regs & QEMU_NEEDED_REGS) == QEMU_NEEDED_REGS) 
{
+        env->psa = env->kvm_run->s.regs.prefix;
+        for (i = 0; i < 16; i++) {
+            env->regs[i] = env->kvm_run->s.regs.gprs[i];
+            env->cregs[i] = env->kvm_run->s.regs.crs[i];
+            env->aregs[i] = env->kvm_run->s.regs.acrs[i];
+        }
+    } else {
+        ret = kvm_vcpu_ioctl(env, KVM_GET_REGS, &regs);
+        if (ret < 0) {
+            return ret;
+        }
+        ret = kvm_vcpu_ioctl(env, KVM_GET_SREGS, &sregs);
+        if (ret < 0) {
+            return ret;
+        }
+        for (i = 0; i < 16; i++) {
+            env->regs[i] = regs.gprs[i];
+            env->cregs[i] = sregs.crs[i];
+            env->aregs[i] = sregs.acrs[i];
+        }
+        /* no prefix available */
+    }
+
     return 0;
 }
 
-- 
1.7.11.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]