Commit 59ac1532 authored by David Hildenbrand's avatar David Hildenbrand Committed by Cornelia Huck
Browse files

s390x/kvm: avoid syscalls by syncing registers with kvm_run



We can avoid loads of syscalls when dropping to user space by storing the values
of more registers directly within kvm_run.

Support is added for:
- ARCH0: CPU timer, clock comparator, TOD programmable register,
         guest breaking-event register, program parameter
- PFAULT: pfault parameters (token, select, compare)

Signed-off-by: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Signed-off-by: default avatarJens Freimann <jfrei@linux.vnet.ibm.com>
Reviewed-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
Acked-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: default avatarCornelia Huck <cornelia.huck@de.ibm.com>
parent fdb78ec0
Loading
Loading
Loading
Loading
+50 −22
Original line number Diff line number Diff line
@@ -252,6 +252,14 @@ int kvm_arch_put_registers(CPUState *cs, int level)
        return 0;
    }

    if (can_sync_regs(cs, KVM_SYNC_ARCH0)) {
        cs->kvm_run->s.regs.cputm = env->cputm;
        cs->kvm_run->s.regs.ckc = env->ckc;
        cs->kvm_run->s.regs.todpr = env->todpr;
        cs->kvm_run->s.regs.gbea = env->gbea;
        cs->kvm_run->s.regs.pp = env->pp;
        cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_ARCH0;
    } else {
        /*
         * These ONE_REGS are not protected by a capability. As they are only
         * necessary for migration we just trace a possible error, but don't
@@ -262,8 +270,15 @@ int kvm_arch_put_registers(CPUState *cs, int level)
        kvm_set_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
        kvm_set_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
        kvm_set_one_reg(cs, KVM_REG_S390_PP, &env->pp);
    }

    if (cap_async_pf) {
    /* pfault parameters */
    if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
        cs->kvm_run->s.regs.pft = env->pfault_token;
        cs->kvm_run->s.regs.pfs = env->pfault_select;
        cs->kvm_run->s.regs.pfc = env->pfault_compare;
        cs->kvm_run->kvm_dirty_regs |= KVM_SYNC_PFAULT;
    } else if (cap_async_pf) {
        r = kvm_set_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
        if (r < 0) {
            return r;
@@ -367,6 +382,13 @@ int kvm_arch_get_registers(CPUState *cs)
        env->psa = cs->kvm_run->s.regs.prefix;
    }

    if (can_sync_regs(cs, KVM_SYNC_ARCH0)) {
        env->cputm = cs->kvm_run->s.regs.cputm;
        env->ckc = cs->kvm_run->s.regs.ckc;
        env->todpr = cs->kvm_run->s.regs.todpr;
        env->gbea = cs->kvm_run->s.regs.gbea;
        env->pp = cs->kvm_run->s.regs.pp;
    } else {
        /*
         * These ONE_REGS are not protected by a capability. As they are only
         * necessary for migration we just trace a possible error, but don't
@@ -377,8 +399,14 @@ int kvm_arch_get_registers(CPUState *cs)
        kvm_get_one_reg(cs, KVM_REG_S390_TODPR, &env->todpr);
        kvm_get_one_reg(cs, KVM_REG_S390_GBEA, &env->gbea);
        kvm_get_one_reg(cs, KVM_REG_S390_PP, &env->pp);
    }

    if (cap_async_pf) {
    /* pfault parameters */
    if (can_sync_regs(cs, KVM_SYNC_PFAULT)) {
        env->pfault_token = cs->kvm_run->s.regs.pft;
        env->pfault_select = cs->kvm_run->s.regs.pfs;
        env->pfault_compare = cs->kvm_run->s.regs.pfc;
    } else if (cap_async_pf) {
        r = kvm_get_one_reg(cs, KVM_REG_S390_PFTOKEN, &env->pfault_token);
        if (r < 0) {
            return r;