diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2013-02-07 14:46:46 +0400 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2013-06-12 19:42:18 +0400 |
commit | 0d854a60b1d7d39a37b25dd28f63cfa0df637b91 (patch) | |
tree | ff120873a6046e586e135aadae9c83510910e8e5 /arch/arm64/kvm/reset.c | |
parent | e82e030556e42e823e174e0c3bd97988d1a09d1f (diff) | |
download | linux-0d854a60b1d7d39a37b25dd28f63cfa0df637b91.tar.xz |
arm64: KVM: enable initialization of a 32bit vcpu
Wire the init of a 32bit vcpu by allowing 32bit modes in pstate,
and providing sensible defaults out of reset state.
This feature is of course conditioned by the presence of 32bit
capability on the physical CPU, and is checked by the KVM_CAP_ARM_EL1_32BIT
capability.
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64/kvm/reset.c')
-rw-r--r-- | arch/arm64/kvm/reset.c | 26 |
1 files changed, 25 insertions, 1 deletions
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c index 766150ac76ed..70a7816535cd 100644 --- a/arch/arm64/kvm/reset.c +++ b/arch/arm64/kvm/reset.c @@ -38,16 +38,32 @@ static const struct kvm_regs default_regs_reset = { PSR_F_BIT | PSR_D_BIT), }; +static const struct kvm_regs default_regs_reset32 = { + .regs.pstate = (COMPAT_PSR_MODE_SVC | COMPAT_PSR_A_BIT | + COMPAT_PSR_I_BIT | COMPAT_PSR_F_BIT), +}; + static const struct kvm_irq_level default_vtimer_irq = { .irq = 27, .level = 1, }; +static bool cpu_has_32bit_el1(void) +{ + u64 pfr0; + + pfr0 = read_cpuid(ID_AA64PFR0_EL1); + return !!(pfr0 & 0x20); +} + int kvm_arch_dev_ioctl_check_extension(long ext) { int r; switch (ext) { + case KVM_CAP_ARM_EL1_32BIT: + r = cpu_has_32bit_el1(); + break; default: r = 0; } @@ -70,7 +86,15 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu) switch (vcpu->arch.target) { default: - cpu_reset = &default_regs_reset; + if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) { + if (!cpu_has_32bit_el1()) + return -EINVAL; + cpu_reset = &default_regs_reset32; + vcpu->arch.hcr_el2 &= ~HCR_RW; + } else { + cpu_reset = &default_regs_reset; + } + cpu_vtimer_irq = &default_vtimer_irq; break; } |