Arm: GICv3: Enable reading GICR_TYPER via two sys_read32() on AArch32
GICR_TYPER is a 64 bit register. On AArch32 when one uses sys_read64(), this results in ldrd instruction. When Zephyr runs as a VM, 'LDRD' instruction on an emulated MMIO region gets trapped to the hypervisor as data abort. Refer the following paragraph from ARM DDI 0487G.b ID072021 :- Section - "ISS encoding for an exception from a Data Abort", "For other faults reported in ESR_EL2, ISV is 0 except for the following stage 2 aborts: AArch32 instructions where the instruction: — Is an LDR, LDA, LDRT, LDRSH, LDRSHT, LDRH, LDAH, LDRHT, LDRSB, LDRSBT, LDRB, LDAB, LDRBT, STR, STL, STRT, STRH, STLH, STRHT, STRB, STLB, or STRBT instruction." As 'LDRD' is not in the list, so ISV==0. This implies that Arm could not decode the instruction for the hypervisor (in EL2) to execute it. Thus, we have abstracted this read into arm_gic_get_typer(). For AArch64, we use sys_read64() as before. For AArch32, we use sys_read32() twice to read the lower and upper 32 bits of GICR_TYPER. Thus, we ensure that when the access is trapped for AArch32, Arm generates a valid ISS so that hypervisor can execute it. Signed-off-by: Ayan Kumar Halder <ayankuma@amd.com>
This commit is contained in:
parent
460ac477c1
commit
2174501a10
1 changed files with 15 additions and 1 deletions
|
@ -507,6 +507,20 @@ static bool arm_gic_aff_matching(uint64_t gicr_aff, uint64_t aff)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline uint64_t arm_gic_get_typer(mem_addr_t addr)
|
||||
{
|
||||
uint64_t val;
|
||||
|
||||
#if defined(CONFIG_ARM)
|
||||
val = sys_read32(addr);
|
||||
val |= (uint64_t)sys_read32(addr + 4) << 32;
|
||||
#else
|
||||
val = sys_read64(addr);
|
||||
#endif
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static mem_addr_t arm_gic_iterate_rdists(void)
|
||||
{
|
||||
uint64_t aff = arm_gic_mpidr_to_affinity(GET_MPIDR());
|
||||
|
@ -514,7 +528,7 @@ static mem_addr_t arm_gic_iterate_rdists(void)
|
|||
for (mem_addr_t rdist_addr = GIC_RDIST_BASE;
|
||||
rdist_addr < GIC_RDIST_BASE + GIC_RDIST_SIZE;
|
||||
rdist_addr += 0x20000) {
|
||||
uint64_t val = sys_read64(rdist_addr + GICR_TYPER);
|
||||
uint64_t val = arm_gic_get_typer(rdist_addr + GICR_TYPER);
|
||||
uint64_t gicr_aff = GICR_TYPER_AFFINITY_VALUE_GET(val);
|
||||
|
||||
if (arm_gic_aff_matching(gicr_aff, aff)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue