Merge remote-tracking branch 'remotes/pmaydell/tags/pull-target-arm-20200207' 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>
This commit is contained in:
Peter Maydell
2020-02-07 18:02:52 +00:00
19 changed files with 1415 additions and 692 deletions
+1 -1
View File
@@ -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
+6 -1
View File
@@ -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 {
@@ -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 = {
+5 -3
View File
@@ -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))) {
@@ -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 */
@@ -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;
+6
View File
@@ -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);
}
@@ -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 = {
+5
View File
@@ -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);
}
@@ -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 = {
+1 -1
View File
@@ -29,6 +29,6 @@
# define TARGET_PAGE_BITS_MIN 10
#endif
#define NB_MMU_MODES 8
#define NB_MMU_MODES 9
#endif
+1
View File
@@ -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)
+139 -23
View File
@@ -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)
@@ -1272,7 +1387,6 @@ static void arm_cpu_realizefn(DeviceState *dev, Error **errp)
}
}
{
uint64_t scale;
@@ -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
+162 -261
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -672,6 +672,7 @@ static void aarch64_max_initfn(Object *obj)
t = cpu->isar.id_aa64mmfr1;
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* HPD */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1);
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1);
cpu->isar.id_aa64mmfr1 = t;
/* Replicate the same data to the 32-bit id registers. */
+38 -12
View File
@@ -20,6 +20,7 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
int ctx_cmps = extract32(cpu->dbgdidr, 20, 4);
int bt;
uint32_t contextidr;
uint64_t hcr_el2;
/*
* Links to unimplemented or non-context aware breakpoints are
@@ -40,24 +41,44 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
}
bt = extract64(bcr, 20, 4);
/*
* We match the whole register even if this is AArch32 using the
* short descriptor format (in which case it holds both PROCID and ASID),
* since we don't implement the optional v7 context ID masking.
*/
contextidr = extract64(env->cp15.contextidr_el[1], 0, 32);
hcr_el2 = arm_hcr_el2_eff(env);
switch (bt) {
case 3: /* linked context ID match */
if (arm_current_el(env) > 1) {
/* Context matches never fire in EL2 or (AArch64) EL3 */
switch (arm_current_el(env)) {
default:
/* Context matches never fire in AArch64 EL3 */
return false;
case 2:
if (!(hcr_el2 & HCR_E2H)) {
/* Context matches never fire in EL2 without E2H enabled. */
return false;
}
contextidr = env->cp15.contextidr_el[2];
break;
case 1:
contextidr = env->cp15.contextidr_el[1];
break;
case 0:
if ((hcr_el2 & (HCR_E2H | HCR_TGE)) == (HCR_E2H | HCR_TGE)) {
contextidr = env->cp15.contextidr_el[2];
} else {
contextidr = env->cp15.contextidr_el[1];
}
break;
}
return (contextidr == extract64(env->cp15.dbgbvr[lbn], 0, 32));
case 5: /* linked address mismatch (reserved in AArch64) */
break;
case 7: /* linked contextidr_el1 match */
contextidr = env->cp15.contextidr_el[1];
break;
case 13: /* linked contextidr_el2 match */
contextidr = env->cp15.contextidr_el[2];
break;
case 9: /* linked VMID match (reserved if no EL2) */
case 11: /* linked context ID and VMID match (reserved if no EL2) */
case 15: /* linked full context ID match */
default:
/*
* Links to Unlinked context breakpoints must generate no
@@ -66,7 +87,12 @@ static bool linked_bp_matches(ARMCPU *cpu, int lbn)
return false;
}
return false;
/*
* We match the whole register even if this is AArch32 using the
* short descriptor format (in which case it holds both PROCID and ASID),
* since we don't implement the optional v7 context ID masking.
*/
return contextidr == (uint32_t)env->cp15.dbgbvr[lbn];
}
static bool bp_wp_matches(ARMCPU *cpu, int n, bool is_wp)
+1 -1
View File
@@ -70,7 +70,7 @@ static void daif_check(CPUARMState *env, uint32_t op,
uint32_t imm, uintptr_t ra)
{
/* DAIF update to PSTATE. This is OK from EL0 only if UMA is set. */
if (arm_current_el(env) == 0 && !(env->cp15.sctlr_el[1] & SCTLR_UMA)) {
if (arm_current_el(env) == 0 && !(arm_sctlr(env, 0) & SCTLR_UMA)) {
raise_exception_ra(env, EXCP_UDEF,
syn_aa64_sysregtrap(0, extract32(op, 0, 3),
extract32(op, 3, 3), 4,
+900 -311
View File
File diff suppressed because it is too large Load Diff
+63 -10
View File
@@ -769,6 +769,39 @@ bool arm_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
static inline int arm_to_core_mmu_idx(ARMMMUIdx mmu_idx)
{
return mmu_idx & ARM_MMU_IDX_COREIDX_MASK;
}
static inline ARMMMUIdx core_to_arm_mmu_idx(CPUARMState *env, int mmu_idx)
{
if (arm_feature(env, ARM_FEATURE_M)) {
return mmu_idx | ARM_MMU_IDX_M;
} else {
return mmu_idx | ARM_MMU_IDX_A;
}
}
int arm_mmu_idx_to_el(ARMMMUIdx mmu_idx);
/*
* Return the MMU index for a v7M CPU with all relevant information
* manually specified.
*/
ARMMMUIdx arm_v7m_mmu_idx_all(CPUARMState *env,
bool secstate, bool priv, bool negpri);
/*
* Return the MMU index for a v7M CPU in the specified security and
* privilege state.
*/
ARMMMUIdx arm_v7m_mmu_idx_for_secstate_and_priv(CPUARMState *env,
bool secstate, bool priv);
/* Return the MMU index for a v7M CPU in the specified security state */
ARMMMUIdx arm_v7m_mmu_idx_for_secstate(CPUARMState *env, bool secstate);
/* Return true if the stage 1 translation regime is using LPAE format page
* tables */
bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx);
@@ -804,24 +837,44 @@ static inline void arm_call_el_change_hook(ARMCPU *cpu)
}
}
/* Return true if this address translation regime has two ranges. */
static inline bool regime_has_2_ranges(ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
return true;
default:
return false;
}
}
/* Return true if this address translation regime is secure */
static inline bool regime_is_secure(CPUARMState *env, ARMMMUIdx mmu_idx)
{
switch (mmu_idx) {
case ARMMMUIdx_S12NSE0:
case ARMMMUIdx_S12NSE1:
case ARMMMUIdx_S1NSE0:
case ARMMMUIdx_S1NSE1:
case ARMMMUIdx_S1E2:
case ARMMMUIdx_S2NS:
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
case ARMMMUIdx_E20_0:
case ARMMMUIdx_E20_2:
case ARMMMUIdx_Stage1_E0:
case ARMMMUIdx_Stage1_E1:
case ARMMMUIdx_E2:
case ARMMMUIdx_Stage2:
case ARMMMUIdx_MPrivNegPri:
case ARMMMUIdx_MUserNegPri:
case ARMMMUIdx_MPriv:
case ARMMMUIdx_MUser:
return false;
case ARMMMUIdx_S1E3:
case ARMMMUIdx_S1SE0:
case ARMMMUIdx_S1SE1:
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
case ARMMMUIdx_MSPrivNegPri:
case ARMMMUIdx_MSUserNegPri:
case ARMMMUIdx_MSPriv:
@@ -975,7 +1028,7 @@ ARMMMUIdx arm_mmu_idx(CPUARMState *env);
#ifdef CONFIG_USER_ONLY
static inline ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env)
{
return ARMMMUIdx_S1NSE0;
return ARMMMUIdx_Stage1_E0;
}
#else
ARMMMUIdx arm_stage1_mmu_idx(CPUARMState *env);
+9 -6
View File
@@ -137,17 +137,20 @@ CpuModelExpansionInfo *qmp_query_cpu_model_expansion(CpuModelExpansionType type,
}
if (kvm_enabled()) {
const char *cpu_type = current_machine->cpu_type;
int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
bool supported = false;
if (!strcmp(model->name, "host") || !strcmp(model->name, "max")) {
/* These are kvmarm's recommended cpu types */
supported = true;
} else if (strlen(model->name) == len &&
!strncmp(model->name, cpu_type, len)) {
/* KVM is enabled and we're using this type, so it works. */
supported = true;
} else if (current_machine->cpu_type) {
const char *cpu_type = current_machine->cpu_type;
int len = strlen(cpu_type) - strlen(ARM_CPU_TYPE_SUFFIX);
if (strlen(model->name) == len &&
!strncmp(model->name, cpu_type, len)) {
/* KVM is enabled and we're using this type, so it works. */
supported = true;
}
}
if (!supported) {
error_setg(errp, "We cannot guarantee the CPU type '%s' works "
+5 -9
View File
@@ -371,7 +371,10 @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
if (el < 2 && arm_feature(env, ARM_FEATURE_EL2)) {
uint64_t hcr = arm_hcr_el2_eff(env);
bool trap = !(hcr & HCR_API);
/* FIXME: ARMv8.1-VHE: trap only applies to EL1&0 regime. */
if (el == 0) {
/* Trap only applies to EL1&0 regime. */
trap &= (hcr & (HCR_E2H | HCR_TGE)) != (HCR_E2H | HCR_TGE);
}
/* FIXME: ARMv8.3-NV: HCR_NV trap takes precedence for ERETA[AB]. */
if (trap) {
pauth_trap(env, 2, ra);
@@ -386,14 +389,7 @@ static void pauth_check_trap(CPUARMState *env, int el, uintptr_t ra)
static bool pauth_key_enabled(CPUARMState *env, int el, uint32_t bit)
{
uint32_t sctlr;
if (el == 0) {
/* FIXME: ARMv8.1-VHE S2 translation regime. */
sctlr = env->cp15.sctlr_el[1];
} else {
sctlr = env->cp15.sctlr_el[el];
}
return (sctlr & bit) != 0;
return (arm_sctlr(env, el) & bit) != 0;
}
uint64_t HELPER(pacia)(CPUARMState *env, uint64_t x, uint64_t y)
+29 -18
View File
@@ -105,25 +105,36 @@ void a64_translate_init(void)
offsetof(CPUARMState, exclusive_high), "exclusive_high");
}
static inline int get_a64_user_mem_index(DisasContext *s)
/*
* Return the core mmu_idx to use for A64 "unprivileged load/store" insns
*/
static int get_a64_user_mem_index(DisasContext *s)
{
/* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
* if EL1, access as if EL0; otherwise access at current EL
/*
* If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
* which is the usual mmu_idx for this cpu state.
*/
ARMMMUIdx useridx;
ARMMMUIdx useridx = s->mmu_idx;
switch (s->mmu_idx) {
case ARMMMUIdx_S12NSE1:
useridx = ARMMMUIdx_S12NSE0;
break;
case ARMMMUIdx_S1SE1:
useridx = ARMMMUIdx_S1SE0;
break;
case ARMMMUIdx_S2NS:
g_assert_not_reached();
default:
useridx = s->mmu_idx;
break;
if (s->unpriv) {
/*
* We have pre-computed the condition for AccType_UNPRIV.
* Therefore we should never get here with a mmu_idx for
* which we do not know the corresponding user mmu_idx.
*/
switch (useridx) {
case ARMMMUIdx_E10_1:
useridx = ARMMMUIdx_E10_0;
break;
case ARMMMUIdx_E20_2:
useridx = ARMMMUIdx_E20_0;
break;
case ARMMMUIdx_SE10_1:
useridx = ARMMMUIdx_SE10_0;
break;
default:
g_assert_not_reached();
}
}
return arm_to_core_mmu_idx(useridx);
}
@@ -175,8 +186,7 @@ static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
if (tbi == 0) {
/* Load unmodified address */
tcg_gen_mov_i64(dst, src);
} else if (s->current_el >= 2) {
/* FIXME: ARMv8.1-VHE S2 translation regime. */
} else if (!regime_has_2_ranges(s->mmu_idx)) {
/* Force tag byte to all zero */
tcg_gen_extract_i64(dst, src, 0, 56);
} else {
@@ -14172,6 +14182,7 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
dc->unpriv = FIELD_EX32(tb_flags, TBFLAG_A64, UNPRIV);
dc->vec_len = 0;
dc->vec_stride = 0;
dc->cp_regs = arm_cpu->cp_regs;
+40 -34
View File
@@ -152,14 +152,14 @@ static inline int get_a32_user_mem_index(DisasContext *s)
* otherwise, access as if at PL0.
*/
switch (s->mmu_idx) {
case ARMMMUIdx_S1E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_S12NSE0:
case ARMMMUIdx_S12NSE1:
return arm_to_core_mmu_idx(ARMMMUIdx_S12NSE0);
case ARMMMUIdx_S1E3:
case ARMMMUIdx_S1SE0:
case ARMMMUIdx_S1SE1:
return arm_to_core_mmu_idx(ARMMMUIdx_S1SE0);
case ARMMMUIdx_E2: /* this one is UNPREDICTABLE */
case ARMMMUIdx_E10_0:
case ARMMMUIdx_E10_1:
return arm_to_core_mmu_idx(ARMMMUIdx_E10_0);
case ARMMMUIdx_SE3:
case ARMMMUIdx_SE10_0:
case ARMMMUIdx_SE10_1:
return arm_to_core_mmu_idx(ARMMMUIdx_SE10_0);
case ARMMMUIdx_MUser:
case ARMMMUIdx_MPriv:
return arm_to_core_mmu_idx(ARMMMUIdx_MUser);
@@ -172,7 +172,6 @@ static inline int get_a32_user_mem_index(DisasContext *s)
case ARMMMUIdx_MSUserNegPri:
case ARMMMUIdx_MSPrivNegPri:
return arm_to_core_mmu_idx(ARMMMUIdx_MSUserNegPri);
case ARMMMUIdx_S2NS:
default:
g_assert_not_reached();
}
@@ -10848,38 +10847,48 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
*/
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3);
dc->thumb = FIELD_EX32(tb_flags, TBFLAG_A32, THUMB);
dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
dc->thumb = FIELD_EX32(tb_flags, TBFLAG_AM32, THUMB);
dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
condexec = FIELD_EX32(tb_flags, TBFLAG_A32, CONDEXEC);
condexec = FIELD_EX32(tb_flags, TBFLAG_AM32, CONDEXEC);
dc->condexec_mask = (condexec & 0xf) << 1;
dc->condexec_cond = condexec >> 4;
core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
#if !defined(CONFIG_USER_ONLY)
dc->user = (dc->current_el == 0);
#endif
dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
dc->vec_stride = 0;
if (arm_feature(env, ARM_FEATURE_M)) {
dc->vfp_enabled = 1;
dc->be_data = MO_TE;
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_M32, HANDLER);
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
regime_is_secure(env, dc->mmu_idx);
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_M32, STACKCHECK);
dc->v8m_fpccr_s_wrong =
FIELD_EX32(tb_flags, TBFLAG_M32, FPCCR_S_WRONG);
dc->v7m_new_fp_ctxt_needed =
FIELD_EX32(tb_flags, TBFLAG_M32, NEW_FP_CTXT_NEEDED);
dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_M32, LSPACT);
} else {
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
dc->c15_cpar = 0;
dc->be_data =
FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
dc->debug_target_el =
FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
dc->sctlr_b = FIELD_EX32(tb_flags, TBFLAG_A32, SCTLR_B);
dc->hstr_active = FIELD_EX32(tb_flags, TBFLAG_A32, HSTR_ACTIVE);
dc->ns = FIELD_EX32(tb_flags, TBFLAG_A32, NS);
dc->vfp_enabled = FIELD_EX32(tb_flags, TBFLAG_A32, VFPEN);
if (arm_feature(env, ARM_FEATURE_XSCALE)) {
dc->c15_cpar = FIELD_EX32(tb_flags, TBFLAG_A32, XSCALE_CPAR);
} else {
dc->vec_len = FIELD_EX32(tb_flags, TBFLAG_A32, VECLEN);
dc->vec_stride = FIELD_EX32(tb_flags, TBFLAG_A32, VECSTRIDE);
}
}
dc->v7m_handler_mode = FIELD_EX32(tb_flags, TBFLAG_A32, HANDLER);
dc->v8m_secure = arm_feature(env, ARM_FEATURE_M_SECURITY) &&
regime_is_secure(env, dc->mmu_idx);
dc->v8m_stackcheck = FIELD_EX32(tb_flags, TBFLAG_A32, STACKCHECK);
dc->v8m_fpccr_s_wrong = FIELD_EX32(tb_flags, TBFLAG_A32, FPCCR_S_WRONG);
dc->v7m_new_fp_ctxt_needed =
FIELD_EX32(tb_flags, TBFLAG_A32, NEW_FP_CTXT_NEEDED);
dc->v7m_lspact = FIELD_EX32(tb_flags, TBFLAG_A32, LSPACT);
dc->cp_regs = cpu->cp_regs;
dc->features = env->features;
@@ -10901,9 +10910,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
dc->is_ldex = false;
if (!arm_feature(env, ARM_FEATURE_M)) {
dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
}
dc->page_start = dc->base.pc_first & TARGET_PAGE_MASK;
@@ -11340,10 +11346,10 @@ static const TranslatorOps thumb_translator_ops = {
/* generate intermediate code for basic block 'tb'. */
void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns)
{
DisasContext dc;
DisasContext dc = { };
const TranslatorOps *ops = &arm_translator_ops;
if (FIELD_EX32(tb->flags, TBFLAG_A32, THUMB)) {
if (FIELD_EX32(tb->flags, TBFLAG_AM32, THUMB)) {
ops = &thumb_translator_ops;
}
#ifdef TARGET_AARCH64
+3 -1
View File
@@ -73,6 +73,8 @@ typedef struct DisasContext {
* ie A64 LDX*, LDAX*, A32/T32 LDREX*, LDAEX*.
*/
bool is_ldex;
/* True if AccType_UNPRIV should be used for LDTR et al */
bool unpriv;
/* True if v8.3-PAuth is active. */
bool pauth_active;
/* True with v8.5-BTI and SCTLR_ELx.BT* set. */
@@ -126,7 +128,7 @@ static inline int default_exception_el(DisasContext *s)
* exceptions can only be routed to ELs above 1, so we target the higher of
* 1 or the current EL.
*/
return (s->mmu_idx == ARMMMUIdx_S1SE0 && s->secure_routed_to_el3)
return (s->mmu_idx == ARMMMUIdx_SE10_0 && s->secure_routed_to_el3)
? 3 : MAX(1, s->current_el);
}