Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-2…
Browse files Browse the repository at this point in the history
…0200207' into staging

target-arm queue:
 * monitor: fix query-cpu-model-expansion crash when using machine type none
 * Support emulation of the ARMv8.1-VHE architecture feature
 * bcm2835_dma: fix bugs in TD mode handling
 * docs/arm-cpu-features: Make kvm-no-adjvtime comment clearer
 * stellaris, stm32f2xx_timer, armv7m_systick: fix minor memory leaks

# gpg: Signature made Fri 07 Feb 2020 14:32:28 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-20200207: (48 commits)
  stellaris: delay timer_new to avoid memleaks
  stm32f2xx_timer: delay timer_new to avoid memleaks
  armv7m_systick: delay timer_new to avoid memleaks
  docs/arm-cpu-features: Make kvm-no-adjvtime comment clearer
  bcm2835_dma: Re-initialize xlen in TD mode
  bcm2835_dma: Fix the ylen loop in TD mode
  target/arm: Raise only one interrupt in arm_cpu_exec_interrupt
  target/arm: Use bool for unmasked in arm_excp_unmasked
  target/arm: Pass more cpu state to arm_excp_unmasked
  target/arm: Move arm_excp_unmasked to cpu.c
  target/arm: Enable ARMv8.1-VHE in -cpu max
  target/arm: Update arm_cpu_do_interrupt_aarch64 for VHE
  target/arm: Update get_a64_user_mem_index for VHE
  target/arm: check TGE and E2H flags for EL0 pauth traps
  target/arm: Update {fp,sve}_exception_el for VHE
  target/arm: Update arm_phys_excp_target_el for TGE
  target/arm: Flush tlbs for E2&0 translation regime
  target/arm: Flush tlb for ASID changes in EL2&0 translation regime
  target/arm: Add VHE timer register redirection and aliasing
  target/arm: Add VHE system register redirection and aliasing
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed Feb 7, 2020
2 parents 42ccca1 + af6c91b commit 93c86ff
Show file tree
Hide file tree
Showing 19 changed files with 1,413 additions and 690 deletions.
2 changes: 1 addition & 1 deletion docs/arm-cpu-features.rst
Expand Up @@ -185,7 +185,7 @@ the list of KVM VCPU features and their descriptions.

kvm-no-adjvtime By default kvm-no-adjvtime is disabled. This
means that by default the virtual time
adjustment is enabled (vtime is *not not*
adjustment is enabled (vtime is not *not*
adjusted).

When virtual time adjustment is enabled each
Expand Down
7 changes: 6 additions & 1 deletion hw/arm/stellaris.c
Expand Up @@ -347,11 +347,15 @@ static void stellaris_gptm_init(Object *obj)
sysbus_init_mmio(sbd, &s->iomem);

s->opaque[0] = s->opaque[1] = s;
}

static void stellaris_gptm_realize(DeviceState *dev, Error **errp)
{
gptm_state *s = STELLARIS_GPTM(dev);
s->timer[0] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[0]);
s->timer[1] = timer_new_ns(QEMU_CLOCK_VIRTUAL, gptm_tick, &s->opaque[1]);
}


/* System controller. */

typedef struct {
Expand Down Expand Up @@ -1536,6 +1540,7 @@ static void stellaris_gptm_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);

dc->vmsd = &vmstate_stellaris_gptm;
dc->realize = stellaris_gptm_realize;
}

static const TypeInfo stellaris_gptm_info = {
Expand Down
8 changes: 5 additions & 3 deletions hw/dma/bcm2835_dma.c
Expand Up @@ -54,7 +54,7 @@
static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
{
BCM2835DMAChan *ch = &s->chan[c];
uint32_t data, xlen, ylen;
uint32_t data, xlen, xlen_td, ylen;
int16_t dst_stride, src_stride;

if (!(s->enable & (1 << c))) {
Expand All @@ -70,18 +70,19 @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
ch->stride = ldl_le_phys(&s->dma_as, ch->conblk_ad + 16);
ch->nextconbk = ldl_le_phys(&s->dma_as, ch->conblk_ad + 20);

ylen = 1;
if (ch->ti & BCM2708_DMA_TDMODE) {
/* 2D transfer mode */
ylen = (ch->txfr_len >> 16) & 0x3fff;
ylen += (ch->txfr_len >> 16) & 0x3fff;
xlen = ch->txfr_len & 0xffff;
dst_stride = ch->stride >> 16;
src_stride = ch->stride & 0xffff;
} else {
ylen = 1;
xlen = ch->txfr_len;
dst_stride = 0;
src_stride = 0;
}
xlen_td = xlen;

while (ylen != 0) {
/* Normal transfer mode */
Expand Down Expand Up @@ -117,6 +118,7 @@ static void bcm2835_dma_update(BCM2835DMAState *s, unsigned c)
if (--ylen != 0) {
ch->source_ad += src_stride;
ch->dest_ad += dst_stride;
xlen = xlen_td;
}
}
ch->cs |= BCM2708_DMA_END;
Expand Down
6 changes: 6 additions & 0 deletions hw/timer/armv7m_systick.c
Expand Up @@ -216,6 +216,11 @@ static void systick_instance_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &systick_ops, s, "systick", 0xe0);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
}

static void systick_realize(DeviceState *dev, Error **errp)
{
SysTickState *s = SYSTICK(dev);
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, systick_timer_tick, s);
}

Expand All @@ -238,6 +243,7 @@ static void systick_class_init(ObjectClass *klass, void *data)

dc->vmsd = &vmstate_systick;
dc->reset = systick_reset;
dc->realize = systick_realize;
}

static const TypeInfo armv7m_systick_info = {
Expand Down
5 changes: 5 additions & 0 deletions hw/timer/stm32f2xx_timer.c
Expand Up @@ -314,7 +314,11 @@ static void stm32f2xx_timer_init(Object *obj)
memory_region_init_io(&s->iomem, obj, &stm32f2xx_timer_ops, s,
"stm32f2xx_timer", 0x400);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->iomem);
}

static void stm32f2xx_timer_realize(DeviceState *dev, Error **errp)
{
STM32F2XXTimerState *s = STM32F2XXTIMER(dev);
s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, stm32f2xx_timer_interrupt, s);
}

Expand All @@ -325,6 +329,7 @@ static void stm32f2xx_timer_class_init(ObjectClass *klass, void *data)
dc->reset = stm32f2xx_timer_reset;
device_class_set_props(dc, stm32f2xx_timer_properties);
dc->vmsd = &vmstate_stm32f2xx_timer;
dc->realize = stm32f2xx_timer_realize;
}

static const TypeInfo stm32f2xx_timer_info = {
Expand Down
2 changes: 1 addition & 1 deletion target/arm/cpu-param.h
Expand Up @@ -29,6 +29,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif

#define NB_MMU_MODES 8
#define NB_MMU_MODES 9

#endif
1 change: 1 addition & 0 deletions target/arm/cpu-qom.h
Expand Up @@ -76,6 +76,7 @@ void arm_gt_ptimer_cb(void *opaque);
void arm_gt_vtimer_cb(void *opaque);
void arm_gt_htimer_cb(void *opaque);
void arm_gt_stimer_cb(void *opaque);
void arm_gt_hvtimer_cb(void *opaque);

#define ARM_AFF0_SHIFT 0
#define ARM_AFF0_MASK (0xFFULL << ARM_AFF0_SHIFT)
Expand Down
162 changes: 139 additions & 23 deletions target/arm/cpu.c
Expand Up @@ -410,58 +410,173 @@ static void arm_cpu_reset(CPUState *s)
arm_rebuild_hflags(env);
}

static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx,
unsigned int target_el,
unsigned int cur_el, bool secure,
uint64_t hcr_el2)
{
CPUARMState *env = cs->env_ptr;
bool pstate_unmasked;
bool unmasked = false;

/*
* Don't take exceptions if they target a lower EL.
* This check should catch any exceptions that would not be taken
* but left pending.
*/
if (cur_el > target_el) {
return false;
}

switch (excp_idx) {
case EXCP_FIQ:
pstate_unmasked = !(env->daif & PSTATE_F);
break;

case EXCP_IRQ:
pstate_unmasked = !(env->daif & PSTATE_I);
break;

case EXCP_VFIQ:
if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
/* VFIQs are only taken when hypervized and non-secure. */
return false;
}
return !(env->daif & PSTATE_F);
case EXCP_VIRQ:
if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized and non-secure. */
return false;
}
return !(env->daif & PSTATE_I);
default:
g_assert_not_reached();
}

/*
* Use the target EL, current execution state and SCR/HCR settings to
* determine whether the corresponding CPSR bit is used to mask the
* interrupt.
*/
if ((target_el > cur_el) && (target_el != 1)) {
/* Exceptions targeting a higher EL may not be maskable */
if (arm_feature(env, ARM_FEATURE_AARCH64)) {
/*
* 64-bit masking rules are simple: exceptions to EL3
* can't be masked, and exceptions to EL2 can only be
* masked from Secure state. The HCR and SCR settings
* don't affect the masking logic, only the interrupt routing.
*/
if (target_el == 3 || !secure) {
unmasked = true;
}
} else {
/*
* The old 32-bit-only environment has a more complicated
* masking setup. HCR and SCR bits not only affect interrupt
* routing but also change the behaviour of masking.
*/
bool hcr, scr;

switch (excp_idx) {
case EXCP_FIQ:
/*
* If FIQs are routed to EL3 or EL2 then there are cases where
* we override the CPSR.F in determining if the exception is
* masked or not. If neither of these are set then we fall back
* to the CPSR.F setting otherwise we further assess the state
* below.
*/
hcr = hcr_el2 & HCR_FMO;
scr = (env->cp15.scr_el3 & SCR_FIQ);

/*
* When EL3 is 32-bit, the SCR.FW bit controls whether the
* CPSR.F bit masks FIQ interrupts when taken in non-secure
* state. If SCR.FW is set then FIQs can be masked by CPSR.F
* when non-secure but only when FIQs are only routed to EL3.
*/
scr = scr && !((env->cp15.scr_el3 & SCR_FW) && !hcr);
break;
case EXCP_IRQ:
/*
* When EL3 execution state is 32-bit, if HCR.IMO is set then
* we may override the CPSR.I masking when in non-secure state.
* The SCR.IRQ setting has already been taken into consideration
* when setting the target EL, so it does not have a further
* affect here.
*/
hcr = hcr_el2 & HCR_IMO;
scr = false;
break;
default:
g_assert_not_reached();
}

if ((scr || hcr) && !secure) {
unmasked = true;
}
}
}

/*
* The PSTATE bits only mask the interrupt if we have not overriden the
* ability above.
*/
return unmasked || pstate_unmasked;
}

bool arm_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
{
CPUClass *cc = CPU_GET_CLASS(cs);
CPUARMState *env = cs->env_ptr;
uint32_t cur_el = arm_current_el(env);
bool secure = arm_is_secure(env);
uint64_t hcr_el2 = arm_hcr_el2_eff(env);
uint32_t target_el;
uint32_t excp_idx;
bool ret = false;

/* The prioritization of interrupts is IMPLEMENTATION DEFINED. */

if (interrupt_request & CPU_INTERRUPT_FIQ) {
excp_idx = EXCP_FIQ;
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
if (arm_excp_unmasked(cs, excp_idx, target_el)) {
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
cc->do_interrupt(cs);
ret = true;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_HARD) {
excp_idx = EXCP_IRQ;
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
if (arm_excp_unmasked(cs, excp_idx, target_el)) {
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
cc->do_interrupt(cs);
ret = true;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_VIRQ) {
excp_idx = EXCP_VIRQ;
target_el = 1;
if (arm_excp_unmasked(cs, excp_idx, target_el)) {
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
cc->do_interrupt(cs);
ret = true;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
goto found;
}
}
if (interrupt_request & CPU_INTERRUPT_VFIQ) {
excp_idx = EXCP_VFIQ;
target_el = 1;
if (arm_excp_unmasked(cs, excp_idx, target_el)) {
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
cc->do_interrupt(cs);
ret = true;
if (arm_excp_unmasked(cs, excp_idx, target_el,
cur_el, secure, hcr_el2)) {
goto found;
}
}
return false;

return ret;
found:
cs->exception_index = excp_idx;
env->exception.target_el = target_el;
cc->do_interrupt(cs);
return true;
}

#if !defined(CONFIG_USER_ONLY) || !defined(TARGET_AARCH64)
Expand Down Expand Up @@ -1272,7 +1387,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
}
}


{
uint64_t scale;

Expand All @@ -1295,6 +1409,8 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
arm_gt_htimer_cb, cpu);
cpu->gt_timer[GTIMER_SEC] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
arm_gt_stimer_cb, cpu);
cpu->gt_timer[GTIMER_HYPVIRT] = timer_new(QEMU_CLOCK_VIRTUAL, scale,
arm_gt_hvtimer_cb, cpu);
}
#endif

Expand Down

0 comments on commit 93c86ff

Please sign in to comment.