aboutsummaryrefslogtreecommitdiff
path: root/target-arm/kvm32.c
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2014-12-11 16:47:23 +0000
committerPeter Maydell <peter.maydell@linaro.org>2014-12-11 16:47:23 +0000
commitb141290478f847ecaa25561f3b31fbf1ddde95e6 (patch)
tree5a4a648e7bee0d53bf6c4d588ff013411d479804 /target-arm/kvm32.c
parent7c3843332db39c2f27405b882a505144d62b3664 (diff)
parent25f2895e0e437a3548f9794846001fb5d5ab853d (diff)
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20141211' into staging
target-arm queue: * pass semihosting exit code out to system * more TrustZone support code (still not enabled yet) * allow user to direct semihosting to gdb or native explicitly rather than always auto-guessing the destination * fix memory leak in realview_init * fix coverity warning in hw/arm/boot * get state migration working for AArch64 CPUs * check errors in kvm_arm_reset_vcpu # gpg: Signature made Thu 11 Dec 2014 12:16:19 GMT using RSA key ID 14360CDE # gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" * remotes/pmaydell/tags/pull-target-arm-20141211: (33 commits) target-arm: Check error conditions on kvm_arm_reset_vcpu target-arm: Support save/load for 64 bit CPUs target-arm/kvm: make reg sync code common between kvm32/64 arm_gic_kvm: Tell kernel about number of IRQs hw/arm/boot: fix uninitialized scalar variable warning reported by coverity hw/arm/realview.c: Fix memory leak in realview_init() target-arm: make MAIR0/1 banked target-arm: make c13 cp regs banked (FCSEIDR, ...) target-arm: make VBAR banked target-arm: make PAR banked target-arm: make IFAR/DFAR banked target-arm: make DFSR banked target-arm: make IFSR banked target-arm: make DACR banked target-arm: make TTBCR banked target-arm: make TTBR0/1 banked target-arm: make CSSELR banked target-arm: respect SCR.FW, SCR.AW and SCTLR.NMFI target-arm: add SCTLR_EL3 and make SCTLR banked target-arm: add MVBAR support ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target-arm/kvm32.c')
-rw-r--r--target-arm/kvm32.c100
1 files changed, 6 insertions, 94 deletions
diff --git a/target-arm/kvm32.c b/target-arm/kvm32.c
index 5ec4eb1f3..94030d1ac 100644
--- a/target-arm/kvm32.c
+++ b/target-arm/kvm32.c
@@ -51,17 +51,17 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
struct kvm_one_reg idregs[] = {
{
.id = KVM_REG_ARM | KVM_REG_SIZE_U32
- | ENCODE_CP_REG(15, 0, 0, 0, 0, 0),
+ | ENCODE_CP_REG(15, 0, 0, 0, 0, 0, 0),
.addr = (uintptr_t)&midr,
},
{
.id = KVM_REG_ARM | KVM_REG_SIZE_U32
- | ENCODE_CP_REG(15, 0, 0, 1, 0, 0),
+ | ENCODE_CP_REG(15, 0, 0, 0, 1, 0, 0),
.addr = (uintptr_t)&id_pfr0,
},
{
.id = KVM_REG_ARM | KVM_REG_SIZE_U32
- | ENCODE_CP_REG(15, 0, 0, 2, 0, 0),
+ | ENCODE_CP_REG(15, 0, 0, 0, 2, 0, 0),
.addr = (uintptr_t)&id_isar0,
},
{
@@ -138,7 +138,7 @@ bool kvm_arm_get_host_cpu_features(ARMHostCPUClass *ahcc)
return true;
}
-static bool reg_syncs_via_tuple_list(uint64_t regidx)
+bool kvm_arm_reg_syncs_via_cpreg_list(uint64_t regidx)
{
/* Return true if the regidx is a register we should synchronize
* via the cpreg_tuples array (ie is not a core reg we sync by
@@ -153,24 +153,11 @@ static bool reg_syncs_via_tuple_list(uint64_t regidx)
}
}
-static int compare_u64(const void *a, const void *b)
-{
- if (*(uint64_t *)a > *(uint64_t *)b) {
- return 1;
- }
- if (*(uint64_t *)a < *(uint64_t *)b) {
- return -1;
- }
- return 0;
-}
-
int kvm_arch_init_vcpu(CPUState *cs)
{
- int i, ret, arraylen;
+ int ret;
uint64_t v;
struct kvm_one_reg r;
- struct kvm_reg_list rl;
- struct kvm_reg_list *rlp;
ARMCPU *cpu = ARM_CPU(cs);
if (cpu->kvm_target == QEMU_KVM_ARM_TARGET_NONE) {
@@ -206,73 +193,7 @@ int kvm_arch_init_vcpu(CPUState *cs)
return -EINVAL;
}
- /* Populate the cpreg list based on the kernel's idea
- * of what registers exist (and throw away the TCG-created list).
- */
- rl.n = 0;
- ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, &rl);
- if (ret != -E2BIG) {
- return ret;
- }
- rlp = g_malloc(sizeof(struct kvm_reg_list) + rl.n * sizeof(uint64_t));
- rlp->n = rl.n;
- ret = kvm_vcpu_ioctl(cs, KVM_GET_REG_LIST, rlp);
- if (ret) {
- goto out;
- }
- /* Sort the list we get back from the kernel, since cpreg_tuples
- * must be in strictly ascending order.
- */
- qsort(&rlp->reg, rlp->n, sizeof(rlp->reg[0]), compare_u64);
-
- for (i = 0, arraylen = 0; i < rlp->n; i++) {
- if (!reg_syncs_via_tuple_list(rlp->reg[i])) {
- continue;
- }
- switch (rlp->reg[i] & KVM_REG_SIZE_MASK) {
- case KVM_REG_SIZE_U32:
- case KVM_REG_SIZE_U64:
- break;
- default:
- fprintf(stderr, "Can't handle size of register in kernel list\n");
- ret = -EINVAL;
- goto out;
- }
-
- arraylen++;
- }
-
- cpu->cpreg_indexes = g_renew(uint64_t, cpu->cpreg_indexes, arraylen);
- cpu->cpreg_values = g_renew(uint64_t, cpu->cpreg_values, arraylen);
- cpu->cpreg_vmstate_indexes = g_renew(uint64_t, cpu->cpreg_vmstate_indexes,
- arraylen);
- cpu->cpreg_vmstate_values = g_renew(uint64_t, cpu->cpreg_vmstate_values,
- arraylen);
- cpu->cpreg_array_len = arraylen;
- cpu->cpreg_vmstate_array_len = arraylen;
-
- for (i = 0, arraylen = 0; i < rlp->n; i++) {
- uint64_t regidx = rlp->reg[i];
- if (!reg_syncs_via_tuple_list(regidx)) {
- continue;
- }
- cpu->cpreg_indexes[arraylen] = regidx;
- arraylen++;
- }
- assert(cpu->cpreg_array_len == arraylen);
-
- if (!write_kvmstate_to_list(cpu)) {
- /* Shouldn't happen unless kernel is inconsistent about
- * what registers exist.
- */
- fprintf(stderr, "Initial read of kernel register state failed\n");
- ret = -EINVAL;
- goto out;
- }
-
-out:
- g_free(rlp);
- return ret;
+ return kvm_arm_init_cpreg_list(cpu);
}
typedef struct Reg {
@@ -508,12 +429,3 @@ int kvm_arch_get_registers(CPUState *cs)
return 0;
}
-
-void kvm_arm_reset_vcpu(ARMCPU *cpu)
-{
- /* Re-init VCPU so that all registers are set to
- * their respective reset values.
- */
- kvm_arm_vcpu_init(CPU(cpu));
- write_kvmstate_to_list(cpu);
-}