X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/3972ef6f830d65e9bacbd31257abedc055fd6dc8..ff05f37babe7874f28dcead6e9e4f1904d35a13a:/target-arm/helper.c diff --git a/target-arm/helper.c b/target-arm/helper.c index 2a68318cf5..27cfd12110 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -492,10 +492,16 @@ static const ARMCPRegInfo not_v8_cp_reginfo[] = { .writefn = dacr_write, .raw_writefn = raw_write, .bank_fieldoffsets = { offsetoflow32(CPUARMState, cp15.dacr_s), offsetoflow32(CPUARMState, cp15.dacr_ns) } }, - /* ??? This covers not just the impdef TLB lockdown registers but also - * some v7VMSA registers relating to TEX remap, so it is overly broad. + /* ARMv7 allocates a range of implementation defined TLB LOCKDOWN regs. + * For v6 and v5, these mappings are overly broad. */ - { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = CP_ANY, + { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 0, + .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP }, + { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 1, + .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP }, + { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 4, + .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP }, + { .name = "TLB_LOCKDOWN", .cp = 15, .crn = 10, .crm = 8, .opc1 = CP_ANY, .opc2 = CP_ANY, .access = PL1_RW, .type = ARM_CP_NOP }, /* Cache maintenance ops; some of this space may be overridden later. */ { .name = "CACHEMAINT", .cp = 15, .crn = 7, .crm = CP_ANY, @@ -555,6 +561,10 @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = { { .name = "TLBIMVAA", .cp = 15, .crn = 8, .crm = CP_ANY, .opc1 = CP_ANY, .opc2 = 3, .access = PL1_W, .writefn = tlbimvaa_write, .type = ARM_CP_NO_RAW }, + { .name = "PRRR", .cp = 15, .crn = 10, .crm = 2, + .opc1 = 0, .opc2 = 0, .access = PL1_RW, .type = ARM_CP_NOP }, + { .name = "NMRR", .cp = 15, .crn = 10, .crm = 2, + .opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_NOP }, REGINFO_SENTINEL }; @@ -592,6 +602,33 @@ static void cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, env->cp15.cpacr_el1 = value; } +static CPAccessResult cpacr_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + if (arm_feature(env, ARM_FEATURE_V8)) { + /* Check if CPACR accesses are to be trapped to EL2 */ + if (arm_current_el(env) == 1 && + (env->cp15.cptr_el[2] & CPTR_TCPAC) && !arm_is_secure(env)) { + return CP_ACCESS_TRAP_EL2; + /* Check if CPACR accesses are to be trapped to EL3 */ + } else if (arm_current_el(env) < 3 && + (env->cp15.cptr_el[3] & CPTR_TCPAC)) { + return CP_ACCESS_TRAP_EL3; + } + } + + return CP_ACCESS_OK; +} + +static CPAccessResult cptr_access(CPUARMState *env, const ARMCPRegInfo *ri) +{ + /* Check if CPTR accesses are set to trap to EL3 */ + if (arm_current_el(env) == 2 && (env->cp15.cptr_el[3] & CPTR_TCPAC)) { + return CP_ACCESS_TRAP_EL3; + } + + return CP_ACCESS_OK; +} + static const ARMCPRegInfo v6_cp_reginfo[] = { /* prefetch by MVA in v6, NOP in v7 */ { .name = "MVA_prefetch", @@ -614,7 +651,7 @@ static const ARMCPRegInfo v6_cp_reginfo[] = { { .name = "WFAR", .cp = 15, .crn = 6, .crm = 0, .opc1 = 0, .opc2 = 1, .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0, }, { .name = "CPACR", .state = ARM_CP_STATE_BOTH, .opc0 = 3, - .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, + .crn = 1, .crm = 0, .opc1 = 0, .opc2 = 2, .accessfn = cpacr_access, .access = PL1_RW, .fieldoffset = offsetof(CPUARMState, cp15.cpacr_el1), .resetvalue = 0, .writefn = cpacr_write }, REGINFO_SENTINEL @@ -994,19 +1031,17 @@ static const ARMCPRegInfo v7_cp_reginfo[] = { .resetvalue = 0 }, /* For non-long-descriptor page tables these are PRRR and NMRR; * regardless they still act as reads-as-written for QEMU. - * The override is necessary because of the overly-broad TLB_LOCKDOWN - * definition. */ /* MAIR0/1 are defined separately from their 64-bit counterpart which * allows them to assign the correct fieldoffset based on the endianness * handled in the field definitions. */ - { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE, + { .name = "MAIR0", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 0, .access = PL1_RW, .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair0_s), offsetof(CPUARMState, cp15.mair0_ns) }, .resetfn = arm_cp_reset_ignore }, - { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .type = ARM_CP_OVERRIDE, + { .name = "MAIR1", .state = ARM_CP_STATE_AA32, .cp = 15, .opc1 = 0, .crn = 10, .crm = 2, .opc2 = 1, .access = PL1_RW, .bank_fieldoffsets = { offsetof(CPUARMState, cp15.mair1_s), offsetof(CPUARMState, cp15.mair1_ns) }, @@ -1249,7 +1284,7 @@ static void gt_tval_write(CPUARMState *env, const ARMCPRegInfo *ri, int timeridx = ri->crm & 1; env->cp15.c14_timer[timeridx].cval = gt_get_countervalue(env) + - + sextract64(value, 0, 32); + sextract64(value, 0, 32); gt_recalc_timer(arm_env_get_cpu(env), timeridx); } @@ -1353,6 +1388,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { { .name = "CNTP_TVAL_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 2, .opc2 = 0, .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R, + .accessfn = gt_ptimer_access, .readfn = gt_tval_read, .writefn = gt_tval_write, }, { .name = "CNTV_TVAL", .cp = 15, .crn = 14, .crm = 3, .opc1 = 0, .opc2 = 0, @@ -1363,6 +1399,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { { .name = "CNTV_TVAL_EL0", .state = ARM_CP_STATE_AA64, .opc0 = 3, .opc1 = 3, .crn = 14, .crm = 3, .opc2 = 0, .type = ARM_CP_NO_RAW | ARM_CP_IO, .access = PL1_RW | PL0_R, + .accessfn = gt_vtimer_access, .readfn = gt_tval_read, .writefn = gt_tval_write, }, /* The counter itself */ @@ -1401,7 +1438,7 @@ static const ARMCPRegInfo generic_timer_cp_reginfo[] = { .access = PL1_RW | PL0_R, .type = ARM_CP_IO, .fieldoffset = offsetof(CPUARMState, cp15.c14_timer[GTIMER_PHYS].cval), - .resetvalue = 0, .accessfn = gt_vtimer_access, + .resetvalue = 0, .accessfn = gt_ptimer_access, .writefn = gt_cval_write, .raw_writefn = raw_write, }, { .name = "CNTV_CVAL", .cp = 15, .crm = 14, .opc1 = 3, @@ -2059,16 +2096,14 @@ static const ARMCPRegInfo mpidr_cp_reginfo[] = { }; static const ARMCPRegInfo lpae_cp_reginfo[] = { - /* NOP AMAIR0/1: the override is because these clash with the rather - * broadly specified TLB_LOCKDOWN entry in the generic cp_reginfo. - */ + /* NOP AMAIR0/1 */ { .name = "AMAIR0", .state = ARM_CP_STATE_BOTH, .opc0 = 3, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 0, - .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE, + .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, /* AMAIR1 is mapped to AMAIR_EL1[63:32] */ { .name = "AMAIR1", .cp = 15, .crn = 10, .crm = 3, .opc1 = 0, .opc2 = 1, - .access = PL1_RW, .type = ARM_CP_CONST | ARM_CP_OVERRIDE, + .access = PL1_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, { .name = "PAR", .cp = 15, .crm = 7, .opc1 = 0, .access = PL1_RW, .type = ARM_CP_64BIT, .resetvalue = 0, @@ -2479,6 +2514,25 @@ static const ARMCPRegInfo v8_el3_no_el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 0, .access = PL2_RW, .readfn = arm_cp_read_zero, .writefn = arm_cp_write_ignore }, + { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2, + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, + .resetvalue = 0 }, + { .name = "HMAIR1", .state = ARM_CP_STATE_AA32, + .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0, + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, + { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2, + .access = PL2_RW, .type = ARM_CP_CONST, .resetvalue = 0 }, REGINFO_SENTINEL }; @@ -2546,6 +2600,31 @@ static const ARMCPRegInfo v8_el2_cp_reginfo[] = { .opc0 = 3, .opc1 = 6, .crn = 4, .crm = 1, .opc2 = 0, .access = PL3_RW, .type = ARM_CP_ALIAS, .fieldoffset = offsetof(CPUARMState, sp_el[2]) }, + { .name = "CPTR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 1, .opc2 = 2, + .access = PL2_RW, .accessfn = cptr_access, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[2]) }, + { .name = "MAIR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 0, + .access = PL2_RW, .fieldoffset = offsetof(CPUARMState, cp15.mair_el[2]), + .resetvalue = 0 }, + { .name = "HMAIR1", .state = ARM_CP_STATE_AA32, + .opc1 = 4, .crn = 10, .crm = 2, .opc2 = 1, + .access = PL2_RW, .type = ARM_CP_ALIAS, + .fieldoffset = offsetofhigh32(CPUARMState, cp15.mair_el[2]) }, + { .name = "TCR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 2, .crm = 0, .opc2 = 2, + .access = PL2_RW, .writefn = vmsa_tcr_el1_write, + .resetfn = vmsa_ttbcr_reset, .raw_writefn = raw_write, + .fieldoffset = offsetof(CPUARMState, cp15.tcr_el[2]) }, + { .name = "SCTLR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 1, .crm = 0, .opc2 = 0, + .access = PL2_RW, .raw_writefn = raw_write, .writefn = sctlr_write, + .fieldoffset = offsetof(CPUARMState, cp15.sctlr_el[2]) }, + { .name = "TPIDR_EL2", .state = ARM_CP_STATE_BOTH, + .opc0 = 3, .opc1 = 4, .crn = 13, .crm = 0, .opc2 = 2, + .access = PL2_RW, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.tpidr_el[2]) }, REGINFO_SENTINEL }; @@ -2607,6 +2686,10 @@ static const ARMCPRegInfo el3_cp_reginfo[] = { .access = PL3_RW, .writefn = vbar_write, .fieldoffset = offsetof(CPUARMState, cp15.vbar_el[3]), .resetvalue = 0 }, + { .name = "CPTR_EL3", .state = ARM_CP_STATE_AA64, + .opc0 = 3, .opc1 = 6, .crn = 1, .crm = 1, .opc2 = 2, + .access = PL3_RW, .accessfn = cptr_access, .resetvalue = 0, + .fieldoffset = offsetof(CPUARMState, cp15.cptr_el[3]) }, REGINFO_SENTINEL }; @@ -4045,21 +4128,6 @@ uint32_t HELPER(rbit)(uint32_t x) #if defined(CONFIG_USER_ONLY) -int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw, - int mmu_idx) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - - env->exception.vaddress = address; - if (rw == 2) { - cs->exception_index = EXCP_PREFETCH_ABORT; - } else { - cs->exception_index = EXCP_DATA_ABORT; - } - return 1; -} - /* These should probably raise undefined insn exceptions. */ void HELPER(v7m_msr)(CPUARMState *env, uint32_t reg, uint32_t val) { @@ -4100,7 +4168,8 @@ uint32_t HELPER(get_r13_banked)(CPUARMState *env, uint32_t mode) return 0; } -unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx) +uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, + uint32_t cur_el, bool secure) { return 1; } @@ -4224,8 +4293,8 @@ const int8_t target_el_table[2][2][2][2][2][4] = { /* * Determine the target EL for physical exceptions */ -static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, - uint32_t cur_el, bool secure) +uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, + uint32_t cur_el, bool secure) { CPUARMState *env = cs->env_ptr; int rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW); @@ -4260,40 +4329,6 @@ static inline uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, return target_el; } -/* - * Determine the target EL for a given exception type. - */ -unsigned int arm_excp_target_el(CPUState *cs, unsigned int excp_idx) -{ - ARMCPU *cpu = ARM_CPU(cs); - CPUARMState *env = &cpu->env; - unsigned int cur_el = arm_current_el(env); - unsigned int target_el; - bool secure = arm_is_secure(env); - - switch (excp_idx) { - case EXCP_HVC: - case EXCP_HYP_TRAP: - target_el = 2; - break; - case EXCP_SMC: - target_el = 3; - break; - case EXCP_FIQ: - case EXCP_IRQ: - target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure); - break; - case EXCP_VIRQ: - case EXCP_VFIQ: - target_el = 1; - break; - default: - target_el = MAX(cur_el, 1); - break; - } - return target_el; -} - static void v7m_push(CPUARMState *env, uint32_t val) { CPUState *cs = CPU(arm_env_get_cpu(env)); @@ -4913,6 +4948,21 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx) return &env->cp15.tcr_el[regime_el(env, mmu_idx)]; } +/* Return the TTBR associated with this translation regime */ +static inline uint64_t regime_ttbr(CPUARMState *env, ARMMMUIdx mmu_idx, + int ttbrn) +{ + if (mmu_idx == ARMMMUIdx_S2NS) { + /* TODO: return VTTBR_EL2 */ + g_assert_not_reached(); + } + if (ttbrn == 0) { + return env->cp15.ttbr0_el[regime_el(env, mmu_idx)]; + } else { + return env->cp15.ttbr1_el[regime_el(env, mmu_idx)]; + } +} + /* Return true if the translation regime is using LPAE format page tables */ static inline bool regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx) @@ -5111,7 +5161,6 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx, uint32_t *table, uint32_t address) { /* Note that we can only get here for an AArch32 PL0/PL1 lookup */ - int el = regime_el(env, mmu_idx); TCR *tcr = regime_tcr(env, mmu_idx); if (address & tcr->mask) { @@ -5119,13 +5168,13 @@ static bool get_level1_table_address(CPUARMState *env, ARMMMUIdx mmu_idx, /* Translation table walk disabled for TTBR1 */ return false; } - *table = env->cp15.ttbr1_el[el] & 0xffffc000; + *table = regime_ttbr(env, mmu_idx, 1) & 0xffffc000; } else { if (tcr->raw_tcr & TTBCR_PD0) { /* Translation table walk disabled for TTBR0 */ return false; } - *table = env->cp15.ttbr0_el[el] & tcr->base_mask; + *table = regime_ttbr(env, mmu_idx, 0) & tcr->base_mask; } *table |= (address >> 18) & 0x3ffc; return true; @@ -5431,21 +5480,34 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, int32_t tbi = 0; TCR *tcr = regime_tcr(env, mmu_idx); int ap, ns, xn, pxn; + uint32_t el = regime_el(env, mmu_idx); + bool ttbr1_valid = true; /* TODO: - * This code assumes we're either a 64-bit EL1 or a 32-bit PL1; - * it doesn't handle the different format TCR for TCR_EL2, TCR_EL3, - * and VTCR_EL2, or the fact that those regimes don't have a split - * TTBR0/TTBR1. Attribute and permission bit handling should also - * be checked when adding support for those page table walks. + * This code does not handle the different format TCR for VTCR_EL2. + * This code also does not support shareability levels. + * Attribute and permission bit handling should also be checked when adding + * support for those page table walks. */ - if (arm_el_is_aa64(env, regime_el(env, mmu_idx))) { + if (arm_el_is_aa64(env, el)) { va_size = 64; - if (extract64(address, 55, 1)) - tbi = extract64(tcr->raw_tcr, 38, 1); - else - tbi = extract64(tcr->raw_tcr, 37, 1); + if (el > 1) { + tbi = extract64(tcr->raw_tcr, 20, 1); + } else { + if (extract64(address, 55, 1)) { + tbi = extract64(tcr->raw_tcr, 38, 1); + } else { + tbi = extract64(tcr->raw_tcr, 37, 1); + } + } tbi *= 8; + + /* If we are in 64-bit EL2 or EL3 then there is no TTBR1, so mark it + * invalid. + */ + if (el > 1) { + ttbr1_valid = false; + } } /* Determine whether this address is in the region controlled by @@ -5466,13 +5528,14 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, if (t0sz && !extract64(address, va_size - t0sz, t0sz - tbi)) { /* there is a ttbr0 region and we are in it (high bits all zero) */ ttbr_select = 0; - } else if (t1sz && !extract64(~address, va_size - t1sz, t1sz - tbi)) { + } else if (ttbr1_valid && t1sz && + !extract64(~address, va_size - t1sz, t1sz - tbi)) { /* there is a ttbr1 region and we are in it (high bits all one) */ ttbr_select = 1; } else if (!t0sz) { /* ttbr0 region is "everything not in the ttbr1 region" */ ttbr_select = 0; - } else if (!t1sz) { + } else if (!t1sz && ttbr1_valid) { /* ttbr1 region is "everything not in the ttbr0 region" */ ttbr_select = 1; } else { @@ -5489,7 +5552,7 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, * we will always flush the TLB any time the ASID is changed). */ if (ttbr_select == 0) { - ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr0); + ttbr = regime_ttbr(env, mmu_idx, 0); epd = extract32(tcr->raw_tcr, 7, 1); tsz = t0sz; @@ -5501,7 +5564,10 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, granule_sz = 11; } } else { - ttbr = A32_BANKED_CURRENT_REG_GET(env, ttbr1); + /* We should only be here if TTBR1 is valid */ + assert(ttbr1_valid); + + ttbr = regime_ttbr(env, mmu_idx, 1); epd = extract32(tcr->raw_tcr, 23, 1); tsz = t1sz; @@ -5519,7 +5585,9 @@ static int get_phys_addr_lpae(CPUARMState *env, target_ulong address, */ if (epd) { - /* Translation table walk disabled => Translation fault on TLB miss */ + /* Translation table walk disabled => Translation fault on TLB miss + * Note: This is always 0 on 64-bit EL2 and EL3. + */ goto do_fault; } @@ -5791,8 +5859,12 @@ static inline int get_phys_addr(CPUARMState *env, target_ulong address, } } -int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, - int access_type, int mmu_idx) +/* Walk the page table and (if the mapping exists) add the page + * to the TLB. Return 0 on success, or an ARM DFSR/IFSR fault + * register format value on failure. + */ +int arm_tlb_fill(CPUState *cs, vaddr address, + int access_type, int mmu_idx) { ARMCPU *cpu = ARM_CPU(cs); CPUARMState *env = &cpu->env; @@ -5800,8 +5872,6 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, target_ulong page_size; int prot; int ret; - uint32_t syn; - bool same_el = (arm_current_el(env) != 0); MemTxAttrs attrs = {}; ret = get_phys_addr(env, address, access_type, mmu_idx, &phys_addr, @@ -5815,27 +5885,7 @@ int arm_cpu_handle_mmu_fault(CPUState *cs, vaddr address, return 0; } - /* AArch64 syndrome does not have an LPAE bit */ - syn = ret & ~(1 << 9); - - /* For insn and data aborts we assume there is no instruction syndrome - * information; this is always true for exceptions reported to EL1. - */ - if (access_type == 2) { - syn = syn_insn_abort(same_el, 0, 0, syn); - cs->exception_index = EXCP_PREFETCH_ABORT; - } else { - syn = syn_data_abort(same_el, 0, 0, 0, access_type == 1, syn); - if (access_type == 1 && arm_feature(env, ARM_FEATURE_V6)) { - ret |= (1 << 11); - } - cs->exception_index = EXCP_DATA_ABORT; - } - - env->exception.syndrome = syn; - env->exception.vaddress = address; - env->exception.fsr = ret; - return 1; + return ret; } hwaddr arm_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)