* refactor exception routing code

* fix SCR_EL3 RAO/RAZ bits
  * gdbstub: Don't use GDB syscalls if no GDB is attached
  * semihosting/config: Merge --semihosting-config option groups
  * tests/qtest: Reduce npcm7xx_sdhci test image size
 -----BEGIN PGP SIGNATURE-----
 
 iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmKjbBoZHHBldGVyLm1h
 eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3iMGEACAA+c88ifpbMlqmDaxPArw
 pcUNbwAel9IzCMSb/SiX0JYyf6omGx84RfKQ7hoCGnn23L47tTcRwGDXkr0vOKLG
 +JUXvkIYO9Ylp0M/PnJFL90aO7B6uMGQVfK57yjn+URlchm+wzphI/6V1jGLMVk/
 UaUHCOW2jFWXxsiUnj3HTyh46T+ZPMMebv4ZEaMH41jZs8D8DrEM65UFmCaBljPB
 eEZPMRUClveosB6O9cj9qAHT5198Za7emzvsWie6AQFI/7TVxQ5oPf8QaeB74w28
 EypXlIlMvOqF0W3mE00IPAgi8f/PgB0X6iqiwXxo+nFwm3J6rPoxo7aI5psXHQn4
 uo2U9Ngvz/A2KVm+j7Qpgst70MScDJey7h1c4w//P8gjqLGL8OxJiyGz+rv+xLkd
 L9Q4gIRJ0FK6brOVZX5aRXMqsnDzVZ8Ki5b6tCoAnfNNAq5y8i3gOss/DDYTKmO0
 C4Ectuq65Qodp82EeMPW25UT1EouCQVDgD2VkaPumI3uVn6+XKDGpM36UOctPOXm
 6RsGvJAWsV7k0llAKjrl8p+B+bCoT6hH41oFkpl96nJuTdx7tS3+OccvEINKZwT1
 rJ5q7IcwbMJwVTbZIJckDXvbTwcj/A9e0SqSOb7AbBiHuATUZxyRbwsQFpazigsa
 t7Lj+Y/obz5shrq3BsIlYQ==
 =yMh4
 -----END PGP SIGNATURE-----

Merge tag 'pull-target-arm-20220610' of https://git.linaro.org/people/pmaydell/qemu-arm into staging

 * refactor exception routing code
 * fix SCR_EL3 RAO/RAZ bits
 * gdbstub: Don't use GDB syscalls if no GDB is attached
 * semihosting/config: Merge --semihosting-config option groups
 * tests/qtest: Reduce npcm7xx_sdhci test image size

# -----BEGIN PGP SIGNATURE-----
#
# iQJNBAABCAA3FiEE4aXFk81BneKOgxXPPCUl7RQ2DN4FAmKjbBoZHHBldGVyLm1h
# eWRlbGxAbGluYXJvLm9yZwAKCRA8JSXtFDYM3iMGEACAA+c88ifpbMlqmDaxPArw
# pcUNbwAel9IzCMSb/SiX0JYyf6omGx84RfKQ7hoCGnn23L47tTcRwGDXkr0vOKLG
# +JUXvkIYO9Ylp0M/PnJFL90aO7B6uMGQVfK57yjn+URlchm+wzphI/6V1jGLMVk/
# UaUHCOW2jFWXxsiUnj3HTyh46T+ZPMMebv4ZEaMH41jZs8D8DrEM65UFmCaBljPB
# eEZPMRUClveosB6O9cj9qAHT5198Za7emzvsWie6AQFI/7TVxQ5oPf8QaeB74w28
# EypXlIlMvOqF0W3mE00IPAgi8f/PgB0X6iqiwXxo+nFwm3J6rPoxo7aI5psXHQn4
# uo2U9Ngvz/A2KVm+j7Qpgst70MScDJey7h1c4w//P8gjqLGL8OxJiyGz+rv+xLkd
# L9Q4gIRJ0FK6brOVZX5aRXMqsnDzVZ8Ki5b6tCoAnfNNAq5y8i3gOss/DDYTKmO0
# C4Ectuq65Qodp82EeMPW25UT1EouCQVDgD2VkaPumI3uVn6+XKDGpM36UOctPOXm
# 6RsGvJAWsV7k0llAKjrl8p+B+bCoT6hH41oFkpl96nJuTdx7tS3+OccvEINKZwT1
# rJ5q7IcwbMJwVTbZIJckDXvbTwcj/A9e0SqSOb7AbBiHuATUZxyRbwsQFpazigsa
# t7Lj+Y/obz5shrq3BsIlYQ==
# =yMh4
# -----END PGP SIGNATURE-----
# gpg: Signature made Fri 10 Jun 2022 09:06:50 AM PDT
# gpg:                using RSA key E1A5C593CD419DE28E8315CF3C2525ED14360CDE
# gpg:                issuer "peter.maydell@linaro.org"
# gpg: Good signature from "Peter Maydell <peter.maydell@linaro.org>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@gmail.com>" [full]
# gpg:                 aka "Peter Maydell <pmaydell@chiark.greenend.org.uk>" [full]

* tag 'pull-target-arm-20220610' of https://git.linaro.org/people/pmaydell/qemu-arm: (28 commits)
  semihosting/config: Merge --semihosting-config option groups
  gdbstub: Don't use GDB syscalls if no GDB is attached
  target/arm: SCR_EL3.RW is RAO/WI without AArch32 EL[12]
  target/arm: Adjust format test in scr_write
  tests/qtest: Reduce npcm7xx_sdhci test image size
  target/arm: Fix Secure PL1 tests in fp_exception_el
  target/arm: Move arm_debug_target_el to debug_helper.c
  target/arm: Create raise_exception_debug
  target/arm: Remove default_exception_el
  target/arm: Introduce helper_exception_with_syndrome
  target/arm: Introduce gen_exception_el_v
  target/arm: Introduce gen_exception
  target/arm: Rename gen_exception to gen_exception_el
  target/arm: Move gen_exception to translate.c
  target/arm: Remove TBFLAG_ANY.DEBUG_TARGET_EL
  target/arm: Create helper_exception_swstep
  target/arm: Introduce gen_exception_insn
  target/arm: Rename gen_exception_insn to gen_exception_insn_el
  target/arm: Introduce gen_exception_insn_el_v
  target/arm: Rename helper_exception_with_syndrome
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson 2022-06-10 13:16:48 -07:00
commit 2663c41cfa
16 changed files with 390 additions and 362 deletions

View File

@ -443,6 +443,15 @@ static int get_char(void)
}
#endif
/*
* Return true if there is a GDB currently connected to the stub
* and attached to a CPU
*/
static bool gdb_attached(void)
{
return gdbserver_state.init && gdbserver_state.c_cpu;
}
static enum {
GDB_SYS_UNKNOWN,
GDB_SYS_ENABLED,
@ -464,8 +473,7 @@ int use_gdb_syscalls(void)
/* -semihosting-config target=auto */
/* On the first call check if gdb is connected and remember. */
if (gdb_syscall_mode == GDB_SYS_UNKNOWN) {
gdb_syscall_mode = gdbserver_state.init ?
GDB_SYS_ENABLED : GDB_SYS_DISABLED;
gdb_syscall_mode = gdb_attached() ? GDB_SYS_ENABLED : GDB_SYS_DISABLED;
}
return gdb_syscall_mode == GDB_SYS_ENABLED;
}
@ -2886,7 +2894,7 @@ void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va)
target_ulong addr;
uint64_t i64;
if (!gdbserver_state.init) {
if (!gdb_attached()) {
return;
}

View File

@ -27,6 +27,7 @@
QemuOptsList qemu_semihosting_config_opts = {
.name = "semihosting-config",
.merge_lists = true,
.implied_opt_name = "enable",
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
.desc = {

View File

@ -2986,27 +2986,6 @@ typedef enum ARMASIdx {
ARMASIdx_TagS = 3,
} ARMASIdx;
/* Return the Exception Level targeted by debug exceptions. */
static inline int arm_debug_target_el(CPUARMState *env)
{
bool secure = arm_is_secure(env);
bool route_to_el2 = false;
if (arm_is_el2_enabled(env)) {
route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
env->cp15.mdcr_el2 & MDCR_TDE;
}
if (route_to_el2) {
return 2;
} else if (arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3) && secure) {
return 3;
} else {
return 1;
}
}
static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
{
/* If all the CLIDR.Ctypem bits are 0 there are no caches, and
@ -3015,107 +2994,6 @@ static inline bool arm_v7m_csselr_razwi(ARMCPU *cpu)
return (cpu->clidr & R_V7M_CLIDR_CTYPE_ALL_MASK) != 0;
}
/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
static inline bool aa64_generate_debug_exceptions(CPUARMState *env)
{
int cur_el = arm_current_el(env);
int debug_el;
if (cur_el == 3) {
return false;
}
/* MDCR_EL3.SDD disables debug events from Secure state */
if (arm_is_secure_below_el3(env)
&& extract32(env->cp15.mdcr_el3, 16, 1)) {
return false;
}
/*
* Same EL to same EL debug exceptions need MDSCR_KDE enabled
* while not masking the (D)ebug bit in DAIF.
*/
debug_el = arm_debug_target_el(env);
if (cur_el == debug_el) {
return extract32(env->cp15.mdscr_el1, 13, 1)
&& !(env->daif & PSTATE_D);
}
/* Otherwise the debug target needs to be a higher EL */
return debug_el > cur_el;
}
static inline bool aa32_generate_debug_exceptions(CPUARMState *env)
{
int el = arm_current_el(env);
if (el == 0 && arm_el_is_aa64(env, 1)) {
return aa64_generate_debug_exceptions(env);
}
if (arm_is_secure(env)) {
int spd;
if (el == 0 && (env->cp15.sder & 1)) {
/* SDER.SUIDEN means debug exceptions from Secure EL0
* are always enabled. Otherwise they are controlled by
* SDCR.SPD like those from other Secure ELs.
*/
return true;
}
spd = extract32(env->cp15.mdcr_el3, 14, 2);
switch (spd) {
case 1:
/* SPD == 0b01 is reserved, but behaves as 0b00. */
case 0:
/* For 0b00 we return true if external secure invasive debug
* is enabled. On real hardware this is controlled by external
* signals to the core. QEMU always permits debug, and behaves
* as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
*/
return true;
case 2:
return false;
case 3:
return true;
}
}
return el != 2;
}
/* Return true if debugging exceptions are currently enabled.
* This corresponds to what in ARM ARM pseudocode would be
* if UsingAArch32() then
* return AArch32.GenerateDebugExceptions()
* else
* return AArch64.GenerateDebugExceptions()
* We choose to push the if() down into this function for clarity,
* since the pseudocode has it at all callsites except for the one in
* CheckSoftwareStep(), where it is elided because both branches would
* always return the same value.
*/
static inline bool arm_generate_debug_exceptions(CPUARMState *env)
{
if (env->aarch64) {
return aa64_generate_debug_exceptions(env);
} else {
return aa32_generate_debug_exceptions(env);
}
}
/* Is single-stepping active? (Note that the "is EL_D AArch64?" check
* implicitly means this always returns false in pre-v8 CPUs.)
*/
static inline bool arm_singlestep_active(CPUARMState *env)
{
return extract32(env->cp15.mdscr_el1, 0, 1)
&& arm_el_is_aa64(env, arm_debug_target_el(env))
&& arm_generate_debug_exceptions(env);
}
static inline bool arm_sctlr_b(CPUARMState *env)
{
return
@ -3205,11 +3083,9 @@ FIELD(TBFLAG_ANY, BE_DATA, 3, 1)
FIELD(TBFLAG_ANY, MMUIDX, 4, 4)
/* Target EL if we take a floating-point-disabled exception */
FIELD(TBFLAG_ANY, FPEXC_EL, 8, 2)
/* For A-profile only, target EL for debug exceptions. */
FIELD(TBFLAG_ANY, DEBUG_TARGET_EL, 10, 2)
/* Memory operations require alignment: SCTLR_ELx.A or CCR.UNALIGN_TRP */
FIELD(TBFLAG_ANY, ALIGN_MEM, 12, 1)
FIELD(TBFLAG_ANY, PSTATE__IL, 13, 1)
FIELD(TBFLAG_ANY, ALIGN_MEM, 10, 1)
FIELD(TBFLAG_ANY, PSTATE__IL, 11, 1)
/*
* Bit usage when in AArch32 state, both A- and M-profile.
@ -3978,6 +3854,11 @@ static inline bool isar_feature_aa64_aa32_el1(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL1) >= 2;
}
static inline bool isar_feature_aa64_aa32_el2(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, EL2) >= 2;
}
static inline bool isar_feature_aa64_ras(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, RAS) != 0;

View File

@ -11,6 +11,153 @@
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
/* Return the Exception Level targeted by debug exceptions. */
static int arm_debug_target_el(CPUARMState *env)
{
bool secure = arm_is_secure(env);
bool route_to_el2 = false;
if (arm_is_el2_enabled(env)) {
route_to_el2 = env->cp15.hcr_el2 & HCR_TGE ||
env->cp15.mdcr_el2 & MDCR_TDE;
}
if (route_to_el2) {
return 2;
} else if (arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3) && secure) {
return 3;
} else {
return 1;
}
}
/*
* Raise an exception to the debug target el.
* Modify syndrome to indicate when origin and target EL are the same.
*/
G_NORETURN static void
raise_exception_debug(CPUARMState *env, uint32_t excp, uint32_t syndrome)
{
int debug_el = arm_debug_target_el(env);
int cur_el = arm_current_el(env);
/*
* If singlestep is targeting a lower EL than the current one, then
* DisasContext.ss_active must be false and we can never get here.
* Similarly for watchpoint and breakpoint matches.
*/
assert(debug_el >= cur_el);
syndrome |= (debug_el == cur_el) << ARM_EL_EC_SHIFT;
raise_exception(env, excp, syndrome, debug_el);
}
/* See AArch64.GenerateDebugExceptionsFrom() in ARM ARM pseudocode */
static bool aa64_generate_debug_exceptions(CPUARMState *env)
{
int cur_el = arm_current_el(env);
int debug_el;
if (cur_el == 3) {
return false;
}
/* MDCR_EL3.SDD disables debug events from Secure state */
if (arm_is_secure_below_el3(env)
&& extract32(env->cp15.mdcr_el3, 16, 1)) {
return false;
}
/*
* Same EL to same EL debug exceptions need MDSCR_KDE enabled
* while not masking the (D)ebug bit in DAIF.
*/
debug_el = arm_debug_target_el(env);
if (cur_el == debug_el) {
return extract32(env->cp15.mdscr_el1, 13, 1)
&& !(env->daif & PSTATE_D);
}
/* Otherwise the debug target needs to be a higher EL */
return debug_el > cur_el;
}
static bool aa32_generate_debug_exceptions(CPUARMState *env)
{
int el = arm_current_el(env);
if (el == 0 && arm_el_is_aa64(env, 1)) {
return aa64_generate_debug_exceptions(env);
}
if (arm_is_secure(env)) {
int spd;
if (el == 0 && (env->cp15.sder & 1)) {
/*
* SDER.SUIDEN means debug exceptions from Secure EL0
* are always enabled. Otherwise they are controlled by
* SDCR.SPD like those from other Secure ELs.
*/
return true;
}
spd = extract32(env->cp15.mdcr_el3, 14, 2);
switch (spd) {
case 1:
/* SPD == 0b01 is reserved, but behaves as 0b00. */
case 0:
/*
* For 0b00 we return true if external secure invasive debug
* is enabled. On real hardware this is controlled by external
* signals to the core. QEMU always permits debug, and behaves
* as if DBGEN, SPIDEN, NIDEN and SPNIDEN are all tied high.
*/
return true;
case 2:
return false;
case 3:
return true;
}
}
return el != 2;
}
/*
* Return true if debugging exceptions are currently enabled.
* This corresponds to what in ARM ARM pseudocode would be
* if UsingAArch32() then
* return AArch32.GenerateDebugExceptions()
* else
* return AArch64.GenerateDebugExceptions()
* We choose to push the if() down into this function for clarity,
* since the pseudocode has it at all callsites except for the one in
* CheckSoftwareStep(), where it is elided because both branches would
* always return the same value.
*/
bool arm_generate_debug_exceptions(CPUARMState *env)
{
if (is_a64(env)) {
return aa64_generate_debug_exceptions(env);
} else {
return aa32_generate_debug_exceptions(env);
}
}
/*
* Is single-stepping active? (Note that the "is EL_D AArch64?" check
* implicitly means this always returns false in pre-v8 CPUs.)
*/
bool arm_singlestep_active(CPUARMState *env)
{
return extract32(env->cp15.mdscr_el1, 0, 1)
&& arm_el_is_aa64(env, arm_debug_target_el(env))
&& arm_generate_debug_exceptions(env);
}
/* Return true if the linked breakpoint entry lbn passes its checks */
static bool linked_bp_matches(ARMCPU *cpu, int lbn)
{
@ -273,6 +420,32 @@ bool arm_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
return check_watchpoints(cpu);
}
/*
* Return the FSR value for a debug exception (watchpoint, hardware
* breakpoint or BKPT insn) targeting the specified exception level.
*/
static uint32_t arm_debug_exception_fsr(CPUARMState *env)
{
ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
int target_el = arm_debug_target_el(env);
bool using_lpae = false;
if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
using_lpae = true;
} else {
if (arm_feature(env, ARM_FEATURE_LPAE) &&
(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
using_lpae = true;
}
}
if (using_lpae) {
return arm_fi_to_lfsc(&fi);
} else {
return arm_fi_to_sfsc(&fi);
}
}
void arm_debug_excp_handler(CPUState *cs)
{
/*
@ -286,19 +459,16 @@ void arm_debug_excp_handler(CPUState *cs)
if (wp_hit) {
if (wp_hit->flags & BP_CPU) {
bool wnr = (wp_hit->flags & BP_WATCHPOINT_HIT_WRITE) != 0;
bool same_el = arm_debug_target_el(env) == arm_current_el(env);
cs->watchpoint_hit = NULL;
env->exception.fsr = arm_debug_exception_fsr(env);
env->exception.vaddress = wp_hit->hitaddr;
raise_exception(env, EXCP_DATA_ABORT,
syn_watchpoint(same_el, 0, wnr),
arm_debug_target_el(env));
raise_exception_debug(env, EXCP_DATA_ABORT,
syn_watchpoint(0, 0, wnr));
}
} else {
uint64_t pc = is_a64(env) ? env->pc : env->regs[15];
bool same_el = (arm_debug_target_el(env) == arm_current_el(env));
/*
* (1) GDB breakpoints should be handled first.
@ -318,12 +488,46 @@ void arm_debug_excp_handler(CPUState *cs)
* exception/security level.
*/
env->exception.vaddress = 0;
raise_exception(env, EXCP_PREFETCH_ABORT,
syn_breakpoint(same_el),
arm_debug_target_el(env));
raise_exception_debug(env, EXCP_PREFETCH_ABORT, syn_breakpoint(0));
}
}
/*
* Raise an EXCP_BKPT with the specified syndrome register value,
* targeting the correct exception level for debug exceptions.
*/
void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
{
int debug_el = arm_debug_target_el(env);
int cur_el = arm_current_el(env);
/* FSR will only be used if the debug target EL is AArch32. */
env->exception.fsr = arm_debug_exception_fsr(env);
/*
* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
* values to the guest that it shouldn't be able to see at its
* exception/security level.
*/
env->exception.vaddress = 0;
/*
* Other kinds of architectural debug exception are ignored if
* they target an exception level below the current one (in QEMU
* this is checked by arm_generate_debug_exceptions()). Breakpoint
* instructions are special because they always generate an exception
* to somewhere: if they can't go to the configured debug exception
* level they are taken to the current exception level.
*/
if (debug_el < cur_el) {
debug_el = cur_el;
}
raise_exception(env, EXCP_BKPT, syndrome, debug_el);
}
void HELPER(exception_swstep)(CPUARMState *env, uint32_t syndrome)
{
raise_exception_debug(env, EXCP_UDEF, syndrome);
}
#if !defined(CONFIG_USER_ONLY)
vaddr arm_adjust_watchpoint_address(CPUState *cs, vaddr addr, int len)

View File

@ -1738,13 +1738,19 @@ static void scr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
uint32_t valid_mask = 0x3fff;
ARMCPU *cpu = env_archcpu(env);
if (ri->state == ARM_CP_STATE_AA64) {
if (arm_feature(env, ARM_FEATURE_AARCH64) &&
!cpu_isar_feature(aa64_aa32_el1, cpu)) {
value |= SCR_FW | SCR_AW; /* these two bits are RES1. */
}
valid_mask &= ~SCR_NET;
/*
* Because SCR_EL3 is the "real" cpreg and SCR is the alias, reset always
* passes the reginfo for SCR_EL3, which has type ARM_CP_STATE_AA64.
* Instead, choose the format based on the mode of EL3.
*/
if (arm_el_is_aa64(env, 3)) {
value |= SCR_FW | SCR_AW; /* RES1 */
valid_mask &= ~SCR_NET; /* RES0 */
if (!cpu_isar_feature(aa64_aa32_el1, cpu) &&
!cpu_isar_feature(aa64_aa32_el2, cpu)) {
value |= SCR_RW; /* RAO/WI */
}
if (cpu_isar_feature(aa64_ras, cpu)) {
valid_mask |= SCR_TERR;
}
@ -10879,26 +10885,21 @@ int fp_exception_el(CPUARMState *env, int cur_el)
int fpen = FIELD_EX64(env->cp15.cpacr_el1, CPACR_EL1, FPEN);
switch (fpen) {
case 1:
if (cur_el != 0) {
break;
}
/* fall through */
case 0:
case 2:
if (cur_el == 0 || cur_el == 1) {
/* Trap to PL1, which might be EL1 or EL3 */
if (arm_is_secure(env) && !arm_el_is_aa64(env, 3)) {
/* Trap from Secure PL0 or PL1 to Secure PL1. */
if (!arm_el_is_aa64(env, 3)
&& (cur_el == 3 || arm_is_secure_below_el3(env))) {
return 3;
}
if (cur_el <= 1) {
return 1;
}
if (cur_el == 3 && !is_a64(env)) {
/* Secure PL1 running at EL3 */
return 3;
}
break;
case 1:
if (cur_el == 0) {
return 1;
}
break;
case 3:
break;
}
}
@ -11102,18 +11103,10 @@ static CPUARMTBFlags rebuild_hflags_m32(CPUARMState *env, int fp_el,
return rebuild_hflags_common_32(env, fp_el, mmu_idx, flags);
}
static CPUARMTBFlags rebuild_hflags_aprofile(CPUARMState *env)
{
CPUARMTBFlags flags = {};
DP_TBFLAG_ANY(flags, DEBUG_TARGET_EL, arm_debug_target_el(env));
return flags;
}
static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
ARMMMUIdx mmu_idx)
{
CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
CPUARMTBFlags flags = {};
int el = arm_current_el(env);
if (arm_sctlr(env, el) & SCTLR_A) {
@ -11139,7 +11132,7 @@ static CPUARMTBFlags rebuild_hflags_a32(CPUARMState *env, int fp_el,
static CPUARMTBFlags rebuild_hflags_a64(CPUARMState *env, int el, int fp_el,
ARMMMUIdx mmu_idx)
{
CPUARMTBFlags flags = rebuild_hflags_aprofile(env);
CPUARMTBFlags flags = {};
ARMMMUIdx stage1 = stage_1_mmu_idx(mmu_idx);
uint64_t tcr = regime_tcr(env, mmu_idx)->raw_tcr;
uint64_t sctlr;

View File

@ -44,9 +44,11 @@ DEF_HELPER_FLAGS_2(usad8, TCG_CALL_NO_RWG_SE, i32, i32, i32)
DEF_HELPER_FLAGS_3(sel_flags, TCG_CALL_NO_RWG_SE,
i32, i32, i32, i32)
DEF_HELPER_2(exception_internal, void, env, i32)
DEF_HELPER_4(exception_with_syndrome, void, env, i32, i32, i32)
DEF_HELPER_2(exception_bkpt_insn, void, env, i32)
DEF_HELPER_2(exception_internal, noreturn, env, i32)
DEF_HELPER_3(exception_with_syndrome, noreturn, env, i32, i32)
DEF_HELPER_4(exception_with_syndrome_el, noreturn, env, i32, i32, i32)
DEF_HELPER_2(exception_bkpt_insn, noreturn, env, i32)
DEF_HELPER_2(exception_swstep, noreturn, env, i32)
DEF_HELPER_2(exception_pc_alignment, noreturn, env, tl)
DEF_HELPER_1(setend, void, env)
DEF_HELPER_2(wfi, void, env, i32)

View File

@ -793,31 +793,6 @@ static inline TCR *regime_tcr(CPUARMState *env, ARMMMUIdx mmu_idx)
return &env->cp15.tcr_el[regime_el(env, mmu_idx)];
}
/* Return the FSR value for a debug exception (watchpoint, hardware
* breakpoint or BKPT insn) targeting the specified exception level.
*/
static inline uint32_t arm_debug_exception_fsr(CPUARMState *env)
{
ARMMMUFaultInfo fi = { .type = ARMFault_Debug };
int target_el = arm_debug_target_el(env);
bool using_lpae = false;
if (target_el == 2 || arm_el_is_aa64(env, target_el)) {
using_lpae = true;
} else {
if (arm_feature(env, ARM_FEATURE_LPAE) &&
(env->cp15.tcr_el[target_el].raw_tcr & TTBCR_EAE)) {
using_lpae = true;
}
}
if (using_lpae) {
return arm_fi_to_lfsc(&fi);
} else {
return arm_fi_to_sfsc(&fi);
}
}
/**
* arm_num_brps: Return number of implemented breakpoints.
* Note that the ID register BRPS field is "number of bps - 1",
@ -1098,21 +1073,6 @@ ARMVAParameters aa64_va_parameters(CPUARMState *env, uint64_t va,
int aa64_va_parameter_tbi(uint64_t tcr, ARMMMUIdx mmu_idx);
int aa64_va_parameter_tbid(uint64_t tcr, ARMMMUIdx mmu_idx);
static inline int exception_target_el(CPUARMState *env)
{
int target_el = MAX(1, arm_current_el(env));
/*
* No such thing as secure EL1 if EL3 is aarch32,
* so update the target EL to EL3 in this case.
*/
if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
target_el = 3;
}
return target_el;
}
/* Determine if allocation tags are available. */
static inline bool allocation_tag_access_enabled(CPUARMState *env, int el,
uint64_t sctlr)
@ -1339,6 +1299,9 @@ void define_cortex_a72_a57_a53_cp_reginfo(ARMCPU *cpu);
bool el_is_in_host(CPUARMState *env, int el);
void aa32_max_features(ARMCPU *cpu);
int exception_target_el(CPUARMState *env);
bool arm_singlestep_active(CPUARMState *env);
bool arm_generate_debug_exceptions(CPUARMState *env);
/* Powers of 2 for sve_vq_map et al. */
#define SVE_VQ_POW2_MAP \

View File

@ -28,6 +28,21 @@
#define SIGNBIT (uint32_t)0x80000000
#define SIGNBIT64 ((uint64_t)1 << 63)
int exception_target_el(CPUARMState *env)
{
int target_el = MAX(1, arm_current_el(env));
/*
* No such thing as secure EL1 if EL3 is aarch32,
* so update the target EL to EL3 in this case.
*/
if (arm_is_secure(env) && !arm_el_is_aa64(env, 3) && target_el == 1) {
target_el = 3;
}
return target_el;
}
void raise_exception(CPUARMState *env, uint32_t excp,
uint32_t syndrome, uint32_t target_el)
{
@ -366,7 +381,7 @@ void HELPER(yield)(CPUARMState *env)
* those EXCP values which are special cases for QEMU to interrupt
* execution and not to be used for exceptions which are passed to
* the guest (those must all have syndrome information and thus should
* use exception_with_syndrome).
* use exception_with_syndrome*).
*/
void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
{
@ -378,39 +393,20 @@ void HELPER(exception_internal)(CPUARMState *env, uint32_t excp)
}
/* Raise an exception with the specified syndrome register value */
void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
void HELPER(exception_with_syndrome_el)(CPUARMState *env, uint32_t excp,
uint32_t syndrome, uint32_t target_el)
{
raise_exception(env, excp, syndrome, target_el);
}
/* Raise an EXCP_BKPT with the specified syndrome register value,
* targeting the correct exception level for debug exceptions.
/*
* Raise an exception with the specified syndrome register value
* to the default target el.
*/
void HELPER(exception_bkpt_insn)(CPUARMState *env, uint32_t syndrome)
void HELPER(exception_with_syndrome)(CPUARMState *env, uint32_t excp,
uint32_t syndrome)
{
int debug_el = arm_debug_target_el(env);
int cur_el = arm_current_el(env);
/* FSR will only be used if the debug target EL is AArch32. */
env->exception.fsr = arm_debug_exception_fsr(env);
/* FAR is UNKNOWN: clear vaddress to avoid potentially exposing
* values to the guest that it shouldn't be able to see at its
* exception/security level.
*/
env->exception.vaddress = 0;
/*
* Other kinds of architectural debug exception are ignored if
* they target an exception level below the current one (in QEMU
* this is checked by arm_generate_debug_exceptions()). Breakpoint
* instructions are special because they always generate an exception
* to somewhere: if they can't go to the configured debug exception
* level they are taken to the current exception level.
*/
if (debug_el < cur_el) {
debug_el = cur_el;
}
raise_exception(env, EXCP_BKPT, syndrome, debug_el);
raise_exception(env, excp, syndrome, exception_target_el(env));
}
uint32_t HELPER(cpsr_read)(CPUARMState *env)

View File

@ -185,12 +185,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm,
| (rt2 << 10) | (rt << 5) | (crm << 1) | isread;
}
static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit)
static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_16bit,
int coproc)
{
/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 coproc == 0xa */
/* AArch32 FP trap or any AArch64 FP/SIMD trap: TA == 0 */
return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT)
| (is_16bit ? 0 : ARM_EL_IL)
| (cv << 24) | (cond << 20) | 0xa;
| (cv << 24) | (cond << 20) | coproc;
}
static inline uint32_t syn_simd_access_trap(int cv, int cond, bool is_16bit)

View File

@ -1161,8 +1161,9 @@ static bool fp_access_check(DisasContext *s)
assert(!s->fp_access_checked);
s->fp_access_checked = true;
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false, 0),
s->fp_excp_el);
return false;
}
s->fp_access_checked = true;
@ -1178,7 +1179,7 @@ bool sve_access_check(DisasContext *s)
assert(!s->sve_access_checked);
s->sve_access_checked = true;
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
syn_sve_access_trap(), s->sve_excp_el);
return false;
}
@ -1815,8 +1816,7 @@ static void gen_sysreg_undef(DisasContext *s, bool isread,
} else {
syndrome = syn_uncategorized();
}
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome,
default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syndrome);
}
/* MRS - move from system register
@ -2069,7 +2069,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
case 1: /* SVC */
gen_ss_advance(s);
gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
syn_aa64_svc(imm16), default_exception_el(s));
syn_aa64_svc(imm16));
break;
case 2: /* HVC */
if (s->current_el == 0) {
@ -2082,7 +2082,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
gen_a64_set_pc_im(s->pc_curr);
gen_helper_pre_hvc(cpu_env);
gen_ss_advance(s);
gen_exception_insn(s, s->base.pc_next, EXCP_HVC,
gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
syn_aa64_hvc(imm16), 2);
break;
case 3: /* SMC */
@ -2093,7 +2093,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
gen_a64_set_pc_im(s->pc_curr);
gen_helper_pre_smc(cpu_env, tcg_constant_i32(syn_aa64_smc(imm16)));
gen_ss_advance(s);
gen_exception_insn(s, s->base.pc_next, EXCP_SMC,
gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
syn_aa64_smc(imm16), 3);
break;
default:
@ -14585,11 +14585,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->condjmp = 0;
dc->aarch64 = true;
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
* there is no secure EL1, so we route exceptions to EL3.
*/
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3);
dc->thumb = false;
dc->sctlr_b = 0;
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
@ -14645,7 +14640,6 @@ static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
dc->ss_active = EX_TBFLAG_ANY(tb_flags, SS_ACTIVE);
dc->pstate_ss = EX_TBFLAG_ANY(tb_flags, PSTATE__SS);
dc->is_ldex = false;
dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
/* Bound the number of insns to execute to those left on the page. */
bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
@ -14724,8 +14718,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
* Illegal execution state. This has priority over BTI
* exceptions, but comes after instruction abort exceptions.
*/
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_illegalstate(), default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
return;
}
@ -14757,8 +14750,7 @@ static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
&& s->guarded_page
&& !btype_destination_ok(insn, s->bt, s->btype)) {
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_btitrap(s->btype),
default_exception_el(s));
syn_btitrap(s->btype));
return;
}
} else {

View File

@ -143,7 +143,7 @@ static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a)
tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel);
if (s->fp_excp_el != 0) {
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
syn_uncategorized(), s->fp_excp_el);
return true;
}
@ -376,7 +376,7 @@ static bool gen_M_fp_sysreg_write(DisasContext *s, int regno,
if (!vfp_access_check_m(s, true)) {
/*
* This was only a conditional exception, so override
* gen_exception_insn()'s default to DISAS_NORETURN
* gen_exception_insn_el()'s default to DISAS_NORETURN
*/
s->base.is_jmp = DISAS_NEXT;
break;
@ -532,7 +532,7 @@ static bool gen_M_fp_sysreg_read(DisasContext *s, int regno,
if (!vfp_access_check_m(s, true)) {
/*
* This was only a conditional exception, so override
* gen_exception_insn()'s default to DISAS_NORETURN
* gen_exception_insn_el()'s default to DISAS_NORETURN
*/
s->base.is_jmp = DISAS_NEXT;
break;
@ -765,13 +765,12 @@ static bool trans_NOCP(DisasContext *s, arg_nocp *a)
}
if (a->cp != 10) {
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
syn_uncategorized(), default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_NOCP, syn_uncategorized());
return true;
}
if (s->fp_excp_el != 0) {
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
syn_uncategorized(), s->fp_excp_el);
return true;
}

View File

@ -100,8 +100,7 @@ bool mve_eci_check(DisasContext *s)
return true;
default:
/* Reserved value: INVSTATE UsageFault */
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
return false;
}
}

View File

@ -219,8 +219,18 @@ static void gen_update_fp_context(DisasContext *s)
static bool vfp_access_check_a(DisasContext *s, bool ignore_vfp_enabled)
{
if (s->fp_excp_el) {
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
/*
* The full syndrome is only used for HSR when HCPTR traps:
* For v8, when TA==0, coproc is RES0.
* For v7, any use of a Floating-point instruction or access
* to a Floating-point Extension register that is trapped to
* Hyp mode because of a trap configured in the HCPTR sets
* this field to 0xA.
*/
int coproc = arm_dc_feature(s, ARM_FEATURE_V8) ? 0 : 0xa;
uint32_t syn = syn_fp_access_trap(1, 0xe, false, coproc);
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF, syn, s->fp_excp_el);
return false;
}
@ -250,7 +260,7 @@ bool vfp_access_check_m(DisasContext *s, bool skip_context_update)
* the encoding space handled by the patterns in m-nocp.decode,
* and for them we may need to raise NOCP here.
*/
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
syn_uncategorized(), s->fp_excp_el);
return false;
}

View File

@ -1086,8 +1086,25 @@ static void gen_exception_internal_insn(DisasContext *s, uint32_t pc, int excp)
s->base.is_jmp = DISAS_NORETURN;
}
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, uint32_t target_el)
static void gen_exception_el_v(int excp, uint32_t syndrome, TCGv_i32 tcg_el)
{
gen_helper_exception_with_syndrome_el(cpu_env, tcg_constant_i32(excp),
tcg_constant_i32(syndrome), tcg_el);
}
static void gen_exception_el(int excp, uint32_t syndrome, uint32_t target_el)
{
gen_exception_el_v(excp, syndrome, tcg_constant_i32(target_el));
}
static void gen_exception(int excp, uint32_t syndrome)
{
gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
tcg_constant_i32(syndrome));
}
static void gen_exception_insn_el_v(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, TCGv_i32 tcg_el)
{
if (s->aarch64) {
gen_a64_set_pc_im(pc);
@ -1095,7 +1112,25 @@ void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
gen_set_condexec(s);
gen_set_pc_im(s, pc);
}
gen_exception(excp, syn, target_el);
gen_exception_el_v(excp, syn, tcg_el);
s->base.is_jmp = DISAS_NORETURN;
}
void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, uint32_t target_el)
{
gen_exception_insn_el_v(s, pc, excp, syn, tcg_constant_i32(target_el));
}
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn)
{
if (s->aarch64) {
gen_a64_set_pc_im(pc);
} else {
gen_set_condexec(s);
gen_set_pc_im(s, pc);
}
gen_exception(excp, syn);
s->base.is_jmp = DISAS_NORETURN;
}
@ -1110,19 +1145,7 @@ static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syn)
void unallocated_encoding(DisasContext *s)
{
/* Unallocated and reserved encodings are uncategorized */
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
default_exception_el(s));
}
static void gen_exception_el(DisasContext *s, int excp, uint32_t syn,
TCGv_i32 tcg_el)
{
gen_set_condexec(s);
gen_set_pc_im(s, s->pc_curr);
gen_helper_exception_with_syndrome(cpu_env,
tcg_constant_i32(excp),
tcg_constant_i32(syn), tcg_el);
s->base.is_jmp = DISAS_NORETURN;
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
}
/* Force a TB lookup after an instruction that changes the CPU state. */
@ -2735,8 +2758,6 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
* an exception and return false. Otherwise it will return true,
* and set *tgtmode and *regno appropriately.
*/
int exc_target = default_exception_el(s);
/* These instructions are present only in ARMv8, or in ARMv7 with the
* Virtualization Extensions.
*/
@ -2847,7 +2868,8 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
tcg_el = tcg_constant_i32(3);
}
gen_exception_el(s, EXCP_UDEF, syn_uncategorized(), tcg_el);
gen_exception_insn_el_v(s, s->pc_curr, EXCP_UDEF,
syn_uncategorized(), tcg_el);
tcg_temp_free_i32(tcg_el);
return false;
}
@ -2872,8 +2894,7 @@ static bool msr_banked_access_decode(DisasContext *s, int r, int sysm, int rn,
undef:
/* If we get here then some access check did not pass */
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_uncategorized(), exc_target);
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized());
return false;
}
@ -5097,7 +5118,8 @@ static void gen_srs(DisasContext *s,
* For the UNPREDICTABLE cases we choose to UNDEF.
*/
if (s->current_el == 1 && !s->ns && mode == ARM_CPU_MODE_MON) {
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(), 3);
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
syn_uncategorized(), 3);
return;
}
@ -8482,7 +8504,7 @@ static bool trans_WLS(DisasContext *s, arg_WLS *a)
* Do the check-and-raise-exception by hand.
*/
if (s->fp_excp_el) {
gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
syn_uncategorized(), s->fp_excp_el);
return true;
}
@ -8585,8 +8607,7 @@ static bool trans_LE(DisasContext *s, arg_LE *a)
tmp = load_cpu_field(v7m.ltpsize);
tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 4, skipexc);
tcg_temp_free_i32(tmp);
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
gen_set_label(skipexc);
}
@ -9056,8 +9077,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
* UsageFault exception.
*/
if (arm_dc_feature(s, ARM_FEATURE_M)) {
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized());
return;
}
@ -9066,8 +9086,7 @@ static void disas_arm_insn(DisasContext *s, unsigned int insn)
* Illegal execution state. This has priority over BTI
* exceptions, but comes after instruction abort exceptions.
*/
gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
syn_illegalstate(), default_exception_el(s));
gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_illegalstate());
return;
}
@ -9300,11 +9319,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->condjmp = 0;
dc->aarch64 = false;
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
* there is no secure EL1, so we route exceptions to EL3.
*/
dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
!arm_el_is_aa64(env, 3);
dc->thumb = EX_TBFLAG_AM32(tb_flags, THUMB);
dc->be_data = EX_TBFLAG_ANY(tb_flags, BE_DATA) ? MO_BE : MO_LE;
condexec = EX_TBFLAG_AM32(tb_flags, CONDEXEC);
@ -9354,7 +9368,6 @@ static void arm_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
dc->v7m_lspact = EX_TBFLAG_M32(tb_flags, LSPACT);
dc->mve_no_pred = EX_TBFLAG_M32(tb_flags, MVE_NO_PRED);
} else {
dc->debug_target_el = EX_TBFLAG_ANY(tb_flags, DEBUG_TARGET_EL);
dc->sctlr_b = EX_TBFLAG_A32(tb_flags, SCTLR__B);
dc->hstr_active = EX_TBFLAG_A32(tb_flags, HSTR_ACTIVE);
dc->ns = EX_TBFLAG_A32(tb_flags, NS);
@ -9636,8 +9649,7 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
* Illegal execution state. This has priority over BTI
* exceptions, but comes after instruction abort exceptions.
*/
gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF,
syn_illegalstate(), default_exception_el(dc));
gen_exception_insn(dc, dc->pc_curr, EXCP_UDEF, syn_illegalstate());
return;
}
@ -9710,8 +9722,8 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
*/
tcg_remove_ops_after(dc->insn_eci_rewind);
dc->condjmp = 0;
gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
default_exception_el(dc));
gen_exception_insn(dc, dc->pc_curr, EXCP_INVSTATE,
syn_uncategorized());
}
arm_post_translate_insn(dc);
@ -9757,16 +9769,15 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
switch (dc->base.is_jmp) {
case DISAS_SWI:
gen_ss_advance(dc);
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
default_exception_el(dc));
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
break;
case DISAS_HVC:
gen_ss_advance(dc);
gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
break;
case DISAS_SMC:
gen_ss_advance(dc);
gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
break;
case DISAS_NEXT:
case DISAS_TOO_MANY:
@ -9827,14 +9838,13 @@ static void arm_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
gen_helper_yield(cpu_env);
break;
case DISAS_SWI:
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb),
default_exception_el(dc));
gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
break;
case DISAS_HVC:
gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
gen_exception_el(EXCP_HVC, syn_aa32_hvc(dc->svc_imm), 2);
break;
case DISAS_SMC:
gen_exception(EXCP_SMC, syn_aa32_smc(), 3);
gen_exception_el(EXCP_SMC, syn_aa32_smc(), 3);
break;
}
}

View File

@ -43,8 +43,6 @@ typedef struct DisasContext {
int fp_excp_el; /* FP exception EL or 0 if enabled */
int sve_excp_el; /* SVE exception EL or 0 if enabled */
int vl; /* current vector length in bytes */
/* Flag indicating that exceptions from secure mode are routed to EL3. */
bool secure_routed_to_el3;
bool vfp_enabled; /* FP enabled via FPSCR.EN */
int vec_len;
int vec_stride;
@ -59,8 +57,6 @@ typedef struct DisasContext {
*/
uint32_t svc_imm;
int current_el;
/* Debug target exception level for single-step exceptions */
int debug_target_el;
GHashTable *cp_regs;
uint64_t features; /* CPU features bits */
bool aarch64;
@ -201,20 +197,6 @@ static inline int get_mem_index(DisasContext *s)
return arm_to_core_mmu_idx(s->mmu_idx);
}
/* Function used to determine the target exception EL when otherwise not known
* or default.
*/
static inline int default_exception_el(DisasContext *s)
{
/* If we are coming from secure EL0 in a system with a 32-bit EL3, then
* there is no secure EL1, so we route exceptions to EL3. Otherwise,
* 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_SE10_0 && s->secure_routed_to_el3)
? 3 : MAX(1, s->current_el);
}
static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
{
/* We don't need to save all of the syndrome so we mask and shift
@ -279,8 +261,9 @@ void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
void arm_gen_test_cc(int cc, TCGLabel *label);
MemOp pow2_align(unsigned i);
void unallocated_encoding(DisasContext *s);
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
void gen_exception_insn_el(DisasContext *s, uint64_t pc, int excp,
uint32_t syn, uint32_t target_el);
void gen_exception_insn(DisasContext *s, uint64_t pc, int excp, uint32_t syn);
/* Return state of Alternate Half-precision flag, caller frees result */
static inline TCGv_i32 get_ahp_flag(void)
@ -329,26 +312,12 @@ static inline void gen_ss_advance(DisasContext *s)
}
}
static inline void gen_exception(int excp, uint32_t syndrome,
uint32_t target_el)
{
gen_helper_exception_with_syndrome(cpu_env, tcg_constant_i32(excp),
tcg_constant_i32(syndrome),
tcg_constant_i32(target_el));
}
/* Generate an architectural singlestep exception */
static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
{
bool same_el = (s->debug_target_el == s->current_el);
/*
* If singlestep is targeting a lower EL than the current one,
* then s->ss_active must be false and we can never get here.
*/
assert(s->debug_target_el >= s->current_el);
gen_exception(EXCP_UDEF, syn_swstep(same_el, isv, ex), s->debug_target_el);
/* Fill in the same_el field of the syndrome in the helper. */
uint32_t syn = syn_swstep(false, isv, ex);
gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
}
/*

View File

@ -24,7 +24,7 @@
#define NPCM7XX_REG_SIZE 0x100
#define NPCM7XX_MMC_BA 0xF0842000
#define NPCM7XX_BLK_SIZE 512
#define NPCM7XX_TEST_IMAGE_SIZE (1 << 30)
#define NPCM7XX_TEST_IMAGE_SIZE (1 << 20)
char *sd_path;