* 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:
commit
2663c41cfa
14
gdbstub.c
14
gdbstub.c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = {
|
||||
|
|
133
target/arm/cpu.h
133
target/arm/cpu.h
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,27 +10885,22 @@ 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)) {
|
||||
return 3;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (cur_el == 3 && !is_a64(env)) {
|
||||
/* Secure PL1 running at EL3 */
|
||||
/* 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;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
if (cur_el == 0) {
|
||||
if (cur_el <= 1) {
|
||||
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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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,
|
||||
uint32_t syndrome, uint32_t target_el)
|
||||
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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,8 +1179,8 @@ 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,
|
||||
syn_sve_access_trap(), s->sve_excp_el);
|
||||
gen_exception_insn_el(s, s->pc_curr, EXCP_UDEF,
|
||||
syn_sve_access_trap(), s->sve_excp_el);
|
||||
return false;
|
||||
}
|
||||
s->sve_access_checked = true;
|
||||
|
@ -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,8 +2082,8 @@ 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,
|
||||
syn_aa64_hvc(imm16), 2);
|
||||
gen_exception_insn_el(s, s->base.pc_next, EXCP_HVC,
|
||||
syn_aa64_hvc(imm16), 2);
|
||||
break;
|
||||
case 3: /* SMC */
|
||||
if (s->current_el == 0) {
|
||||
|
@ -2093,8 +2093,8 @@ 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,
|
||||
syn_aa64_smc(imm16), 3);
|
||||
gen_exception_insn_el(s, s->base.pc_next, EXCP_SMC,
|
||||
syn_aa64_smc(imm16), 3);
|
||||
break;
|
||||
default:
|
||||
unallocated_encoding(s);
|
||||
|
@ -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 {
|
||||
|
|
|
@ -143,8 +143,8 @@ 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,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
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,14 +765,13 @@ 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,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,8 +260,8 @@ 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,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
gen_exception_insn_el(s, s->pc_curr, EXCP_NOCP,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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,8 +8504,8 @@ 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,
|
||||
syn_uncategorized(), s->fp_excp_el);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
uint32_t syn, uint32_t target_el);
|
||||
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));
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue