diff options
author | Peter Maydell | 2018-11-19 16:58:17 +0100 |
---|---|---|
committer | Peter Maydell | 2018-11-19 16:58:17 +0100 |
commit | d304cf014bf9feec3dcd7ee65c75a7f52206ecdf (patch) | |
tree | 71e2846c88fa62b4caea9edbe9049d346235f289 /target/arm/kvm64.c | |
parent | Merge remote-tracking branch 'remotes/kevin/tags/for-upstream' into staging (diff) | |
parent | MAINTAINERS: list myself as maintainer for various Arm boards (diff) | |
download | qemu-d304cf014bf9feec3dcd7ee65c75a7f52206ecdf.tar.gz qemu-d304cf014bf9feec3dcd7ee65c75a7f52206ecdf.tar.xz qemu-d304cf014bf9feec3dcd7ee65c75a7f52206ecdf.zip |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20181119' into staging
target-arm queue:
* various MAINTAINERS file updates
* hw/block/onenand: use qemu_log_mask() for reporting
* hw/block/onenand: Fix off-by-one error allowing out-of-bounds read
on the n800 and n810 machine models
* target/arm: fix smc incorrectly trapping to EL3 when secure is off
* hw/arm/stm32f205: Fix the UART and Timer region size
* target/arm: read ID registers for KVM guests so they can be
used to gate "is feature X present" checks
# gpg: Signature made Mon 19 Nov 2018 15:56:44 GMT
# gpg: using RSA key 3C2525ED14360CDE
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>"
# gpg: aka "Peter Maydell <pmaydell@gmail.com>"
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>"
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20181119:
MAINTAINERS: list myself as maintainer for various Arm boards
hw/block/onenand: use qemu_log_mask() for reporting
hw/block/onenand: Fix off-by-one error allowing out-of-bounds read
target/arm: fix smc incorrectly trapping to EL3 when secure is off
hw/arm/stm32f205: Fix the UART and Timer region size
MAINTAINERS: Add entries for missing ARM boards
target/arm: Fill in ARMISARegisters for kvm32
target/arm: Introduce read_sys_reg32 for kvm32
target/arm: Fill in ARMISARegisters for kvm64
target/arm: Install ARMISARegisters from kvm host
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target/arm/kvm64.c')
-rw-r--r-- | target/arm/kvm64.c | 90 |
1 files changed, 88 insertions, 2 deletions
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c index 46fbe6d8ff..0a502091e7 100644 --- a/target/arm/kvm64.c +++ b/target/arm/kvm64.c @@ -456,17 +456,40 @@ static inline void unset_feature(uint64_t *features, int feature) *features &= ~(1ULL << feature); } +static int read_sys_reg32(int fd, uint32_t *pret, uint64_t id) +{ + uint64_t ret; + struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)&ret }; + int err; + + assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); + err = ioctl(fd, KVM_GET_ONE_REG, &idreg); + if (err < 0) { + return -1; + } + *pret = ret; + return 0; +} + +static int read_sys_reg64(int fd, uint64_t *pret, uint64_t id) +{ + struct kvm_one_reg idreg = { .id = id, .addr = (uintptr_t)pret }; + + assert((id & KVM_REG_SIZE_MASK) == KVM_REG_SIZE_U64); + return ioctl(fd, KVM_GET_ONE_REG, &idreg); +} + bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) { /* Identify the feature bits corresponding to the host CPU, and * fill out the ARMHostCPUClass fields accordingly. To do this * we have to create a scratch VM, create a single CPU inside it, * and then query that CPU for the relevant ID registers. - * For AArch64 we currently don't care about ID registers at - * all; we just want to know the CPU type. */ int fdarray[3]; uint64_t features = 0; + int err; + /* Old kernels may not know about the PREFERRED_TARGET ioctl: however * we know these will only support creating one kind of guest CPU, * which is its preferred CPU type. Fortunately these old kernels @@ -487,8 +510,71 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf) ahcf->target = init.target; ahcf->dtb_compatible = "arm,arm-v8"; + err = read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr0, + ARM64_SYS_REG(3, 0, 0, 4, 0)); + if (unlikely(err < 0)) { + /* + * Before v4.15, the kernel only exposed a limited number of system + * registers, not including any of the interesting AArch64 ID regs. + * For the most part we could leave these fields as zero with minimal + * effect, since this does not affect the values seen by the guest. + * + * However, it could cause problems down the line for QEMU, + * so provide a minimal v8.0 default. + * + * ??? Could read MIDR and use knowledge from cpu64.c. + * ??? Could map a page of memory into our temp guest and + * run the tiniest of hand-crafted kernels to extract + * the values seen by the guest. + * ??? Either of these sounds like too much effort just + * to work around running a modern host kernel. + */ + ahcf->isar.id_aa64pfr0 = 0x00000011; /* EL1&0, AArch64 only */ + err = 0; + } else { + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64pfr1, + ARM64_SYS_REG(3, 0, 0, 4, 1)); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar0, + ARM64_SYS_REG(3, 0, 0, 6, 0)); + err |= read_sys_reg64(fdarray[2], &ahcf->isar.id_aa64isar1, + ARM64_SYS_REG(3, 0, 0, 6, 1)); + + /* + * Note that if AArch32 support is not present in the host, + * the AArch32 sysregs are present to be read, but will + * return UNKNOWN values. This is neither better nor worse + * than skipping the reads and leaving 0, as we must avoid + * considering the values in every case. + */ + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar0, + ARM64_SYS_REG(3, 0, 0, 2, 0)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar1, + ARM64_SYS_REG(3, 0, 0, 2, 1)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar2, + ARM64_SYS_REG(3, 0, 0, 2, 2)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar3, + ARM64_SYS_REG(3, 0, 0, 2, 3)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar4, + ARM64_SYS_REG(3, 0, 0, 2, 4)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar5, + ARM64_SYS_REG(3, 0, 0, 2, 5)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.id_isar6, + ARM64_SYS_REG(3, 0, 0, 2, 7)); + + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr0, + ARM64_SYS_REG(3, 0, 0, 3, 0)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr1, + ARM64_SYS_REG(3, 0, 0, 3, 1)); + err |= read_sys_reg32(fdarray[2], &ahcf->isar.mvfr2, + ARM64_SYS_REG(3, 0, 0, 3, 2)); + } + kvm_arm_destroy_scratch_host_vcpu(fdarray); + if (err < 0) { + return false; + } + /* We can assume any KVM supporting CPU is at least a v8 * with VFPv4+Neon; this in turn implies most of the other * feature bits. |