From: Jean-Philippe Brucker <[email protected]> The target code calls kvm_arm_vcpu_init() to mark the vCPU as part of a Realm. For a Realm vCPU, only x0-x7 can be set at runtime. Before boot, the PC can also be set, and is ignored at runtime. KVM also accepts a few system register changes during initial configuration, as returned by KVM_GET_REG_LIST.
Signed-off-by: Jean-Philippe Brucker <[email protected]> Signed-off-by: Mathieu Poirier <[email protected]> --- target/arm/cpu.h | 3 +++ target/arm/kvm-rme.c | 9 ++++++++ target/arm/kvm-stub.c | 5 ++++ target/arm/kvm.c | 54 +++++++++++++++++++++++++++++++++++++++++-- target/arm/kvm_arm.h | 10 ++++++++ 5 files changed, 79 insertions(+), 2 deletions(-) diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 03a30afcbed1..c7927036360c 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -1055,6 +1055,9 @@ struct ArchCPU { /* KVM steal time */ OnOffAuto kvm_steal_time; + /* Realm Management Extension */ + bool kvm_rme; + /* Uniprocessor system with MP extensions */ bool mp_is_up; diff --git a/target/arm/kvm-rme.c b/target/arm/kvm-rme.c index b86b9d6a25cb..90c1d30ba24c 100644 --- a/target/arm/kvm-rme.c +++ b/target/arm/kvm-rme.c @@ -90,3 +90,12 @@ int kvm_arm_rme_init(MachineState *ms, KVMState *s) cgs->ready = true; return 0; } + +void kvm_arm_rme_vcpu_init(ARMCPU *cpu) +{ + if (!rme_guest) { + return; + } + + cpu->kvm_rme = true; +} diff --git a/target/arm/kvm-stub.c b/target/arm/kvm-stub.c index eec1ca3dd2e5..4ab6f08637d1 100644 --- a/target/arm/kvm-stub.c +++ b/target/arm/kvm-stub.c @@ -124,3 +124,8 @@ int kvm_arm_rme_init(MachineState *ms, KVMState *s) { g_assert_not_reached(); } + +void kvm_arm_rme_vcpu_init(ARMCPU *cpu) +{ + g_assert_not_reached(); +} diff --git a/target/arm/kvm.c b/target/arm/kvm.c index b609f29c11c6..4c212ed0c337 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -2009,6 +2009,8 @@ int kvm_arch_init_vcpu(CPUState *cs) cpu->kvm_init_features[0] |= 1 << KVM_ARM_VCPU_HAS_EL2; } + kvm_arm_rme_vcpu_init(cpu); + /* Do KVM_ARM_VCPU_INIT ioctl */ ret = kvm_arm_vcpu_init(cpu); if (ret) { @@ -2163,6 +2165,29 @@ static int kvm_arch_put_sve(CPUState *cs, uint32_t vq, bool have_ffr) return 0; } +static int kvm_arm_rme_put_core_regs(CPUState *cs, Error **errp) +{ + int i, ret; + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + /* The RME ABI only allows us to set 8 GPRs and the PC */ + for (i = 0; i < 8; i++) { + ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.regs[i]), + &env->xregs[i]); + if (ret) { + return ret; + } + } + + ret = kvm_set_one_reg(cs, AARCH64_CORE_REG(regs.pc), &env->pc); + if (ret) { + return ret; + } + + return 0; +} + static int kvm_arm_put_core_regs(CPUState *cs, Error **errp) { uint64_t val; @@ -2274,7 +2299,11 @@ int kvm_arch_put_registers(CPUState *cs, KvmPutState level, Error **errp) int ret; ARMCPU *cpu = ARM_CPU(cs); - ret = kvm_arm_put_core_regs(cs, errp); + if (cpu->kvm_rme) { + ret = kvm_arm_rme_put_core_regs(cs, errp); + } else { + ret = kvm_arm_put_core_regs(cs, errp); + } if (ret) { return ret; } @@ -2361,6 +2390,23 @@ static int kvm_arch_get_sve(CPUState *cs, uint32_t vq, bool have_ffr) return 0; } +static int kvm_arm_rme_get_core_regs(CPUState *cs, Error **errp) +{ + int i, ret; + ARMCPU *cpu = ARM_CPU(cs); + CPUARMState *env = &cpu->env; + + for (i = 0; i < 8; i++) { + ret = kvm_get_one_reg(cs, AARCH64_CORE_REG(regs.regs[i]), + &env->xregs[i]); + if (ret) { + return ret; + } + } + + return 0; +} + static int kvm_arm_get_core_regs(CPUState *cs, Error **errp) { uint64_t val; @@ -2472,7 +2518,11 @@ int kvm_arch_get_registers(CPUState *cs, Error **errp) int ret; ARMCPU *cpu = ARM_CPU(cs); - ret = kvm_arm_get_core_regs(cs, errp); + if (cpu->kvm_rme) { + ret = kvm_arm_rme_get_core_regs(cs, errp); + } else { + ret = kvm_arm_get_core_regs(cs, errp); + } if (ret) { return ret; } diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h index 6d058b0e08a2..12ed1eee18b4 100644 --- a/target/arm/kvm_arm.h +++ b/target/arm/kvm_arm.h @@ -249,4 +249,14 @@ char *kvm_print_register_name(uint64_t regidx); */ int kvm_arm_rme_init(MachineState *ms, KVMState *s); +/** + * kvm_arm_rme_vcpu_init + * @cs: the CPU + * + * If the user requested a Realm, setup the given vCPU accordingly. Realm vCPUs + * behave a little differently, for example most of their register state is + * hidden from the host. + */ +void kvm_arm_rme_vcpu_init(ARMCPU *cpu); + #endif -- 2.43.0
