Revision | f77784446045231f7dfa46c9b872091241fa1557 (tree) |
---|---|
Time | 2018-12-13 23:41:24 |
Author | Richard Henderson <richard.henderson@lina...> |
Commiter | Peter Maydell |
target/arm: Introduce arm_hcr_el2_eff
Replace arm_hcr_el2_{fmo,imo,amo} with a more general routine
that also takes SCR_EL3.NS (aka arm_is_secure_below_el3) into
account, as documented for the plethora of bits in HCR_EL2.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Message-id: 20181210150501.7990-2-richard.henderson@linaro.org
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
@@ -85,8 +85,8 @@ static bool icv_access(CPUARMState *env, int hcr_flags) | ||
85 | 85 | * * access if NS EL1 and either IMO or FMO == 1: |
86 | 86 | * CTLR, DIR, PMR, RPR |
87 | 87 | */ |
88 | - bool flagmatch = ((hcr_flags & HCR_IMO) && arm_hcr_el2_imo(env)) || | |
89 | - ((hcr_flags & HCR_FMO) && arm_hcr_el2_fmo(env)); | |
88 | + uint64_t hcr_el2 = arm_hcr_el2_eff(env); | |
89 | + bool flagmatch = hcr_el2 & hcr_flags & (HCR_IMO | HCR_FMO); | |
90 | 90 | |
91 | 91 | return flagmatch && arm_current_el(env) == 1 |
92 | 92 | && !arm_is_secure_below_el3(env); |
@@ -1552,8 +1552,9 @@ static void icc_dir_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
1552 | 1552 | /* No need to include !IsSecure in route_*_to_el2 as it's only |
1553 | 1553 | * tested in cases where we know !IsSecure is true. |
1554 | 1554 | */ |
1555 | - route_fiq_to_el2 = arm_hcr_el2_fmo(env); | |
1556 | - route_irq_to_el2 = arm_hcr_el2_imo(env); | |
1555 | + uint64_t hcr_el2 = arm_hcr_el2_eff(env); | |
1556 | + route_fiq_to_el2 = hcr_el2 & HCR_FMO; | |
1557 | + route_irq_to_el2 = hcr_el2 & HCR_IMO; | |
1557 | 1558 | |
1558 | 1559 | switch (arm_current_el(env)) { |
1559 | 1560 | case 3: |
@@ -1895,8 +1896,8 @@ static CPAccessResult gicv3_irqfiq_access(CPUARMState *env, | ||
1895 | 1896 | if ((env->cp15.scr_el3 & (SCR_FIQ | SCR_IRQ)) == (SCR_FIQ | SCR_IRQ)) { |
1896 | 1897 | switch (el) { |
1897 | 1898 | case 1: |
1898 | - if (arm_is_secure_below_el3(env) || | |
1899 | - (arm_hcr_el2_imo(env) == 0 && arm_hcr_el2_fmo(env) == 0)) { | |
1899 | + /* Note that arm_hcr_el2_eff takes secure state into account. */ | |
1900 | + if ((arm_hcr_el2_eff(env) & (HCR_IMO | HCR_FMO)) == 0) { | |
1900 | 1901 | r = CP_ACCESS_TRAP_EL3; |
1901 | 1902 | } |
1902 | 1903 | break; |
@@ -1936,8 +1937,8 @@ static CPAccessResult gicv3_dir_access(CPUARMState *env, | ||
1936 | 1937 | static CPAccessResult gicv3_sgi_access(CPUARMState *env, |
1937 | 1938 | const ARMCPRegInfo *ri, bool isread) |
1938 | 1939 | { |
1939 | - if ((arm_hcr_el2_imo(env) || arm_hcr_el2_fmo(env)) && | |
1940 | - arm_current_el(env) == 1 && !arm_is_secure_below_el3(env)) { | |
1940 | + if (arm_current_el(env) == 1 && | |
1941 | + (arm_hcr_el2_eff(env) & (HCR_IMO | HCR_FMO)) != 0) { | |
1941 | 1942 | /* Takes priority over a possible EL3 trap */ |
1942 | 1943 | return CP_ACCESS_TRAP_EL2; |
1943 | 1944 | } |
@@ -1961,7 +1962,7 @@ static CPAccessResult gicv3_fiq_access(CPUARMState *env, | ||
1961 | 1962 | if (env->cp15.scr_el3 & SCR_FIQ) { |
1962 | 1963 | switch (el) { |
1963 | 1964 | case 1: |
1964 | - if (arm_is_secure_below_el3(env) || !arm_hcr_el2_fmo(env)) { | |
1965 | + if ((arm_hcr_el2_eff(env) & HCR_FMO) == 0) { | |
1965 | 1966 | r = CP_ACCESS_TRAP_EL3; |
1966 | 1967 | } |
1967 | 1968 | break; |
@@ -2000,7 +2001,7 @@ static CPAccessResult gicv3_irq_access(CPUARMState *env, | ||
2000 | 2001 | if (env->cp15.scr_el3 & SCR_IRQ) { |
2001 | 2002 | switch (el) { |
2002 | 2003 | case 1: |
2003 | - if (arm_is_secure_below_el3(env) || !arm_hcr_el2_imo(env)) { | |
2004 | + if ((arm_hcr_el2_eff(env) & HCR_IMO) == 0) { | |
2004 | 2005 | r = CP_ACCESS_TRAP_EL3; |
2005 | 2006 | } |
2006 | 2007 | break; |
@@ -1729,6 +1729,14 @@ static inline bool arm_is_secure(CPUARMState *env) | ||
1729 | 1729 | } |
1730 | 1730 | #endif |
1731 | 1731 | |
1732 | +/** | |
1733 | + * arm_hcr_el2_eff(): Return the effective value of HCR_EL2. | |
1734 | + * E.g. when in secure state, fields in HCR_EL2 are suppressed, | |
1735 | + * "for all purposes other than a direct read or write access of HCR_EL2." | |
1736 | + * Not included here is HCR_RW. | |
1737 | + */ | |
1738 | +uint64_t arm_hcr_el2_eff(CPUARMState *env); | |
1739 | + | |
1732 | 1740 | /* Return true if the specified exception level is running in AArch64 state. */ |
1733 | 1741 | static inline bool arm_el_is_aa64(CPUARMState *env, int el) |
1734 | 1742 | { |
@@ -2414,54 +2422,6 @@ bool write_cpustate_to_list(ARMCPU *cpu); | ||
2414 | 2422 | # define TARGET_VIRT_ADDR_SPACE_BITS 32 |
2415 | 2423 | #endif |
2416 | 2424 | |
2417 | -/** | |
2418 | - * arm_hcr_el2_imo(): Return the effective value of HCR_EL2.IMO. | |
2419 | - * Depending on the values of HCR_EL2.E2H and TGE, this may be | |
2420 | - * "behaves as 1 for all purposes other than direct read/write" or | |
2421 | - * "behaves as 0 for all purposes other than direct read/write" | |
2422 | - */ | |
2423 | -static inline bool arm_hcr_el2_imo(CPUARMState *env) | |
2424 | -{ | |
2425 | - switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { | |
2426 | - case HCR_TGE: | |
2427 | - return true; | |
2428 | - case HCR_TGE | HCR_E2H: | |
2429 | - return false; | |
2430 | - default: | |
2431 | - return env->cp15.hcr_el2 & HCR_IMO; | |
2432 | - } | |
2433 | -} | |
2434 | - | |
2435 | -/** | |
2436 | - * arm_hcr_el2_fmo(): Return the effective value of HCR_EL2.FMO. | |
2437 | - */ | |
2438 | -static inline bool arm_hcr_el2_fmo(CPUARMState *env) | |
2439 | -{ | |
2440 | - switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { | |
2441 | - case HCR_TGE: | |
2442 | - return true; | |
2443 | - case HCR_TGE | HCR_E2H: | |
2444 | - return false; | |
2445 | - default: | |
2446 | - return env->cp15.hcr_el2 & HCR_FMO; | |
2447 | - } | |
2448 | -} | |
2449 | - | |
2450 | -/** | |
2451 | - * arm_hcr_el2_amo(): Return the effective value of HCR_EL2.AMO. | |
2452 | - */ | |
2453 | -static inline bool arm_hcr_el2_amo(CPUARMState *env) | |
2454 | -{ | |
2455 | - switch (env->cp15.hcr_el2 & (HCR_TGE | HCR_E2H)) { | |
2456 | - case HCR_TGE: | |
2457 | - return true; | |
2458 | - case HCR_TGE | HCR_E2H: | |
2459 | - return false; | |
2460 | - default: | |
2461 | - return env->cp15.hcr_el2 & HCR_AMO; | |
2462 | - } | |
2463 | -} | |
2464 | - | |
2465 | 2425 | static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, |
2466 | 2426 | unsigned int target_el) |
2467 | 2427 | { |
@@ -2470,6 +2430,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, | ||
2470 | 2430 | bool secure = arm_is_secure(env); |
2471 | 2431 | bool pstate_unmasked; |
2472 | 2432 | int8_t unmasked = 0; |
2433 | + uint64_t hcr_el2; | |
2473 | 2434 | |
2474 | 2435 | /* Don't take exceptions if they target a lower EL. |
2475 | 2436 | * This check should catch any exceptions that would not be taken but left |
@@ -2479,6 +2440,8 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, | ||
2479 | 2440 | return false; |
2480 | 2441 | } |
2481 | 2442 | |
2443 | + hcr_el2 = arm_hcr_el2_eff(env); | |
2444 | + | |
2482 | 2445 | switch (excp_idx) { |
2483 | 2446 | case EXCP_FIQ: |
2484 | 2447 | pstate_unmasked = !(env->daif & PSTATE_F); |
@@ -2489,13 +2452,13 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, | ||
2489 | 2452 | break; |
2490 | 2453 | |
2491 | 2454 | case EXCP_VFIQ: |
2492 | - if (secure || !arm_hcr_el2_fmo(env) || (env->cp15.hcr_el2 & HCR_TGE)) { | |
2455 | + if (secure || !(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) { | |
2493 | 2456 | /* VFIQs are only taken when hypervized and non-secure. */ |
2494 | 2457 | return false; |
2495 | 2458 | } |
2496 | 2459 | return !(env->daif & PSTATE_F); |
2497 | 2460 | case EXCP_VIRQ: |
2498 | - if (secure || !arm_hcr_el2_imo(env) || (env->cp15.hcr_el2 & HCR_TGE)) { | |
2461 | + if (secure || !(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) { | |
2499 | 2462 | /* VIRQs are only taken when hypervized and non-secure. */ |
2500 | 2463 | return false; |
2501 | 2464 | } |
@@ -2534,7 +2497,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, | ||
2534 | 2497 | * to the CPSR.F setting otherwise we further assess the state |
2535 | 2498 | * below. |
2536 | 2499 | */ |
2537 | - hcr = arm_hcr_el2_fmo(env); | |
2500 | + hcr = hcr_el2 & HCR_FMO; | |
2538 | 2501 | scr = (env->cp15.scr_el3 & SCR_FIQ); |
2539 | 2502 | |
2540 | 2503 | /* When EL3 is 32-bit, the SCR.FW bit controls whether the |
@@ -2551,7 +2514,7 @@ static inline bool arm_excp_unmasked(CPUState *cs, unsigned int excp_idx, | ||
2551 | 2514 | * when setting the target EL, so it does not have a further |
2552 | 2515 | * affect here. |
2553 | 2516 | */ |
2554 | - hcr = arm_hcr_el2_imo(env); | |
2517 | + hcr = hcr_el2 & HCR_IMO; | |
2555 | 2518 | scr = false; |
2556 | 2519 | break; |
2557 | 2520 | default: |
@@ -1331,9 +1331,10 @@ static void csselr_write(CPUARMState *env, const ARMCPRegInfo *ri, | ||
1331 | 1331 | static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri) |
1332 | 1332 | { |
1333 | 1333 | CPUState *cs = ENV_GET_CPU(env); |
1334 | + uint64_t hcr_el2 = arm_hcr_el2_eff(env); | |
1334 | 1335 | uint64_t ret = 0; |
1335 | 1336 | |
1336 | - if (arm_hcr_el2_imo(env)) { | |
1337 | + if (hcr_el2 & HCR_IMO) { | |
1337 | 1338 | if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) { |
1338 | 1339 | ret |= CPSR_I; |
1339 | 1340 | } |
@@ -1343,7 +1344,7 @@ static uint64_t isr_read(CPUARMState *env, const ARMCPRegInfo *ri) | ||
1343 | 1344 | } |
1344 | 1345 | } |
1345 | 1346 | |
1346 | - if (arm_hcr_el2_fmo(env)) { | |
1347 | + if (hcr_el2 & HCR_FMO) { | |
1347 | 1348 | if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) { |
1348 | 1349 | ret |= CPSR_F; |
1349 | 1350 | } |
@@ -4008,6 +4009,51 @@ static void hcr_writelow(CPUARMState *env, const ARMCPRegInfo *ri, | ||
4008 | 4009 | hcr_write(env, NULL, value); |
4009 | 4010 | } |
4010 | 4011 | |
4012 | +/* | |
4013 | + * Return the effective value of HCR_EL2. | |
4014 | + * Bits that are not included here: | |
4015 | + * RW (read from SCR_EL3.RW as needed) | |
4016 | + */ | |
4017 | +uint64_t arm_hcr_el2_eff(CPUARMState *env) | |
4018 | +{ | |
4019 | + uint64_t ret = env->cp15.hcr_el2; | |
4020 | + | |
4021 | + if (arm_is_secure_below_el3(env)) { | |
4022 | + /* | |
4023 | + * "This register has no effect if EL2 is not enabled in the | |
4024 | + * current Security state". This is ARMv8.4-SecEL2 speak for | |
4025 | + * !(SCR_EL3.NS==1 || SCR_EL3.EEL2==1). | |
4026 | + * | |
4027 | + * Prior to that, the language was "In an implementation that | |
4028 | + * includes EL3, when the value of SCR_EL3.NS is 0 the PE behaves | |
4029 | + * as if this field is 0 for all purposes other than a direct | |
4030 | + * read or write access of HCR_EL2". With lots of enumeration | |
4031 | + * on a per-field basis. In current QEMU, this is condition | |
4032 | + * is arm_is_secure_below_el3. | |
4033 | + * | |
4034 | + * Since the v8.4 language applies to the entire register, and | |
4035 | + * appears to be backward compatible, use that. | |
4036 | + */ | |
4037 | + ret = 0; | |
4038 | + } else if (ret & HCR_TGE) { | |
4039 | + /* These bits are up-to-date as of ARMv8.4. */ | |
4040 | + if (ret & HCR_E2H) { | |
4041 | + ret &= ~(HCR_VM | HCR_FMO | HCR_IMO | HCR_AMO | | |
4042 | + HCR_BSU_MASK | HCR_DC | HCR_TWI | HCR_TWE | | |
4043 | + HCR_TID0 | HCR_TID2 | HCR_TPCP | HCR_TPU | | |
4044 | + HCR_TDZ | HCR_CD | HCR_ID | HCR_MIOCNCE); | |
4045 | + } else { | |
4046 | + ret |= HCR_FMO | HCR_IMO | HCR_AMO; | |
4047 | + } | |
4048 | + ret &= ~(HCR_SWIO | HCR_PTW | HCR_VF | HCR_VI | HCR_VSE | | |
4049 | + HCR_FB | HCR_TID1 | HCR_TID3 | HCR_TSC | HCR_TACR | | |
4050 | + HCR_TSW | HCR_TTLB | HCR_TVM | HCR_HCD | HCR_TRVM | | |
4051 | + HCR_TLOR); | |
4052 | + } | |
4053 | + | |
4054 | + return ret; | |
4055 | +} | |
4056 | + | |
4011 | 4057 | static const ARMCPRegInfo el2_cp_reginfo[] = { |
4012 | 4058 | { .name = "HCR_EL2", .state = ARM_CP_STATE_AA64, |
4013 | 4059 | .type = ARM_CP_IO, |
@@ -6526,12 +6572,13 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, | ||
6526 | 6572 | uint32_t cur_el, bool secure) |
6527 | 6573 | { |
6528 | 6574 | CPUARMState *env = cs->env_ptr; |
6529 | - int rw; | |
6530 | - int scr; | |
6531 | - int hcr; | |
6575 | + bool rw; | |
6576 | + bool scr; | |
6577 | + bool hcr; | |
6532 | 6578 | int target_el; |
6533 | 6579 | /* Is the highest EL AArch64? */ |
6534 | - int is64 = arm_feature(env, ARM_FEATURE_AARCH64); | |
6580 | + bool is64 = arm_feature(env, ARM_FEATURE_AARCH64); | |
6581 | + uint64_t hcr_el2; | |
6535 | 6582 | |
6536 | 6583 | if (arm_feature(env, ARM_FEATURE_EL3)) { |
6537 | 6584 | rw = ((env->cp15.scr_el3 & SCR_RW) == SCR_RW); |
@@ -6543,18 +6590,19 @@ uint32_t arm_phys_excp_target_el(CPUState *cs, uint32_t excp_idx, | ||
6543 | 6590 | rw = is64; |
6544 | 6591 | } |
6545 | 6592 | |
6593 | + hcr_el2 = arm_hcr_el2_eff(env); | |
6546 | 6594 | switch (excp_idx) { |
6547 | 6595 | case EXCP_IRQ: |
6548 | 6596 | scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ); |
6549 | - hcr = arm_hcr_el2_imo(env); | |
6597 | + hcr = hcr_el2 & HCR_IMO; | |
6550 | 6598 | break; |
6551 | 6599 | case EXCP_FIQ: |
6552 | 6600 | scr = ((env->cp15.scr_el3 & SCR_FIQ) == SCR_FIQ); |
6553 | - hcr = arm_hcr_el2_fmo(env); | |
6601 | + hcr = hcr_el2 & HCR_FMO; | |
6554 | 6602 | break; |
6555 | 6603 | default: |
6556 | 6604 | scr = ((env->cp15.scr_el3 & SCR_EA) == SCR_EA); |
6557 | - hcr = arm_hcr_el2_amo(env); | |
6605 | + hcr = hcr_el2 & HCR_AMO; | |
6558 | 6606 | break; |
6559 | 6607 | }; |
6560 | 6608 |