diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2019-03-25 15:58:49 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2019-03-25 15:58:49 +0000 |
commit | 50ccc488b0d4c3b8e2790c18bcd7329fc609a1c6 (patch) | |
tree | 843306c6ffcdec524acfcdcad97a94a4d83367e8 | |
parent | adb3321bfdeabeeb32b5ec545043a3f5f9fd8a7e (diff) | |
parent | f2b2f53f6429b5abd7cd86bd65747f5f13e195eb (diff) |
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20190325' into staging
target-arm queue:
* Fix non-parallel expansion of CASP
* nrf51_gpio: reflect pull-up/pull-down to IRQs
* Fix crash if guest tries to enable non-existent PMU counters
* Add PMUv2 to the Cortex-A15 and Cortex-A7
* Make pmccntr_op_start/finish static
# gpg: Signature made Mon 25 Mar 2019 14:19:47 GMT
# gpg: using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg: issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@gmail.com>" [ultimate]
# gpg: aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [ultimate]
# Primary key fingerprint: E1A5 C593 CD41 9DE2 8E83 15CF 3C25 25ED 1436 0CDE
* remotes/pmaydell/tags/pull-target-arm-20190325:
target/arm: make pmccntr_op_start/finish static
target/arm: cortex-a7 and cortex-a15 have pmus
target/arm: fix crash on pmu register access
target/arm: add PCI_TESTDEV back to default config
nrf51_gpio: reflect pull-up/pull-down to IRQs
target/arm: Fix non-parallel expansion of CASP
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | default-configs/arm-softmmu.mak | 1 | ||||
-rw-r--r-- | hw/gpio/nrf51_gpio.c | 65 | ||||
-rw-r--r-- | target/arm/cpu.c | 3 | ||||
-rw-r--r-- | target/arm/cpu.h | 11 | ||||
-rw-r--r-- | target/arm/helper.c | 8 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 2 |
6 files changed, 51 insertions, 39 deletions
diff --git a/default-configs/arm-softmmu.mak b/default-configs/arm-softmmu.mak index 2a7efc1167..613d19a06d 100644 --- a/default-configs/arm-softmmu.mak +++ b/default-configs/arm-softmmu.mak @@ -2,6 +2,7 @@ CONFIG_PCI=y CONFIG_PCI_DEVICES=y +CONFIG_PCI_TESTDEV=y CONFIG_VGA=y CONFIG_NAND=y CONFIG_ECC=y diff --git a/hw/gpio/nrf51_gpio.c b/hw/gpio/nrf51_gpio.c index 86e047d649..87a2f2a0dc 100644 --- a/hw/gpio/nrf51_gpio.c +++ b/hw/gpio/nrf51_gpio.c @@ -43,6 +43,17 @@ static bool is_connected(uint32_t config, uint32_t level) return state; } +static int pull_value(uint32_t config) +{ + int pull = extract32(config, 2, 2); + if (pull == NRF51_GPIO_PULLDOWN) { + return 0; + } else if (pull == NRF51_GPIO_PULLUP) { + return 1; + } + return -1; +} + static void update_output_irq(NRF51GPIOState *s, size_t i, bool connected, bool level) { @@ -61,43 +72,47 @@ static void update_output_irq(NRF51GPIOState *s, size_t i, static void update_state(NRF51GPIOState *s) { - uint32_t pull; + int pull; size_t i; - bool connected_out, dir, connected_in, out, input; + bool connected_out, dir, connected_in, out, in, input; for (i = 0; i < NRF51_GPIO_PINS; i++) { - pull = extract32(s->cnf[i], 2, 2); + pull = pull_value(s->cnf[i]); dir = extract32(s->cnf[i], 0, 1); connected_in = extract32(s->in_mask, i, 1); out = extract32(s->out, i, 1); + in = extract32(s->in, i, 1); input = !extract32(s->cnf[i], 1, 1); connected_out = is_connected(s->cnf[i], out) && dir; - update_output_irq(s, i, connected_out, out); - - /* Pin both driven externally and internally */ - if (connected_out && connected_in) { - qemu_log_mask(LOG_GUEST_ERROR, "GPIO pin %zu short circuited\n", i); - } - - /* - * Input buffer disconnected from internal/external drives, so - * pull-up/pull-down becomes relevant - */ - if (!input || (input && !connected_in && !connected_out)) { - if (pull == NRF51_GPIO_PULLDOWN) { - s->in = deposit32(s->in, i, 1, 0); - } else if (pull == NRF51_GPIO_PULLUP) { - s->in = deposit32(s->in, i, 1, 1); + if (!input) { + if (pull >= 0) { + /* Input buffer disconnected from external drives */ + s->in = deposit32(s->in, i, 1, pull); + } + } else { + if (connected_out && connected_in && out != in) { + /* Pin both driven externally and internally */ + qemu_log_mask(LOG_GUEST_ERROR, + "GPIO pin %zu short circuited\n", i); + } + if (!connected_in) { + /* + * Floating input: the output stimulates IN if connected, + * otherwise pull-up/pull-down resistors put a value on both + * IN and OUT. + */ + if (pull >= 0 && !connected_out) { + connected_out = true; + out = pull; + } + if (connected_out) { + s->in = deposit32(s->in, i, 1, out); + } } } - - /* Self stimulation through internal output driver */ - if (connected_out && !connected_in && input) { - s->in = deposit32(s->in, i, 1, out); - } + update_output_irq(s, i, connected_out, out); } - } /* diff --git a/target/arm/cpu.c b/target/arm/cpu.c index 96f0ff0ec7..504a4771fb 100644 --- a/target/arm/cpu.c +++ b/target/arm/cpu.c @@ -1109,6 +1109,7 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp) #endif } else { cpu->id_aa64dfr0 &= ~0xf00; + cpu->id_dfr0 &= ~(0xf << 24); cpu->pmceid0 = 0; cpu->pmceid1 = 0; } @@ -1744,6 +1745,7 @@ static void cortex_a7_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); set_feature(&cpu->env, ARM_FEATURE_EL2); set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7; cpu->midr = 0x410fc075; cpu->reset_fpsid = 0x41023075; @@ -1789,6 +1791,7 @@ static void cortex_a15_initfn(Object *obj) set_feature(&cpu->env, ARM_FEATURE_CBAR_RO); set_feature(&cpu->env, ARM_FEATURE_EL2); set_feature(&cpu->env, ARM_FEATURE_EL3); + set_feature(&cpu->env, ARM_FEATURE_PMU); cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15; cpu->midr = 0x412fc0f1; cpu->reset_fpsid = 0x410430f0; diff --git a/target/arm/cpu.h b/target/arm/cpu.h index 5f23c62132..d4d2836923 100644 --- a/target/arm/cpu.h +++ b/target/arm/cpu.h @@ -993,17 +993,6 @@ int cpu_arm_signal_handler(int host_signum, void *pinfo, void *puc); /** - * pmccntr_op_start/finish - * @env: CPUARMState - * - * Convert the counter in the PMCCNTR between its delta form (the typical mode - * when it's enabled) and the guest-visible value. These two calls must always - * surround any action which might affect the counter. - */ -void pmccntr_op_start(CPUARMState *env); -void pmccntr_op_finish(CPUARMState *env); - -/** * pmu_op_start/finish * @env: CPUARMState * diff --git a/target/arm/helper.c b/target/arm/helper.c index c8d3c213b6..a36f4b3d69 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -1259,6 +1259,10 @@ static bool pmu_counter_enabled(CPUARMState *env, uint8_t counter) int el = arm_current_el(env); uint8_t hpmn = env->cp15.mdcr_el2 & MDCR_HPMN; + if (!arm_feature(env, ARM_FEATURE_PMU)) { + return false; + } + if (!arm_feature(env, ARM_FEATURE_EL2) || (counter < hpmn || counter == 31)) { e = env->cp15.c9_pmcr & PMCRE; @@ -1333,7 +1337,7 @@ static void pmu_update_irq(CPUARMState *env) * etc. can be done logically. This is essentially a no-op if the counter is * not enabled at the time of the call. */ -void pmccntr_op_start(CPUARMState *env) +static void pmccntr_op_start(CPUARMState *env) { uint64_t cycles = cycles_get_count(env); @@ -1363,7 +1367,7 @@ void pmccntr_op_start(CPUARMState *env) * guest-visible count. A call to pmccntr_op_finish should follow every call to * pmccntr_op_start. */ -void pmccntr_op_finish(CPUARMState *env) +static void pmccntr_op_finish(CPUARMState *env) { if (pmu_counter_enabled(env, 31)) { #ifndef CONFIG_USER_ONLY diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index 1959046343..dcdeb80176 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -2510,7 +2510,7 @@ static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt, tcg_gen_qemu_ld_i64(d1, clean_addr, memidx, MO_64 | MO_ALIGN_16 | s->be_data); tcg_gen_addi_i64(a2, clean_addr, 8); - tcg_gen_qemu_ld_i64(d2, clean_addr, memidx, MO_64 | s->be_data); + tcg_gen_qemu_ld_i64(d2, a2, memidx, MO_64 | s->be_data); /* Compare the two words, also in memory order. */ tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1); |