mirror of
https://github.com/acidanthera/audk.git
synced 2025-08-22 18:18:09 +02:00
The early ID map used by ArmVirtQemu uses ASID scoped non-global mappings, as this allows us to switch to the permanent ID map seamlessly without the need for explicit TLB maintenance. However, this triggers a known erratum on ThunderX, which does not tolerate non-global mappings that are executable at EL1, as this appears to result in I-cache corruption. (Linux disables the KPTI based Meltdown mitigation on ThunderX for the same reason) So work around this, by detecting the CPU implementor and part number, and proceeding without the early ID map if a ThunderX CPU is detected. Note that this requires the C code to be built with strict alignment again, as we may end up executing it with the MMU and caches off. Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Acked-by: Laszlo Ersek <lersek@redhat.com> Tested-by: dann frazier <dann.frazier@canonical.com>
129 lines
4.2 KiB
ArmAsm
129 lines
4.2 KiB
ArmAsm
//
|
|
// Copyright (c) 2022, Google LLC. All rights reserved.
|
|
//
|
|
// SPDX-License-Identifier: BSD-2-Clause-Patent
|
|
//
|
|
//
|
|
|
|
#include <AsmMacroIoLibV8.h>
|
|
|
|
.macro mov_i, reg:req, imm:req
|
|
movz \reg, :abs_g1:\imm
|
|
movk \reg, :abs_g0_nc:\imm
|
|
.endm
|
|
|
|
.set MAIR_DEV_nGnRnE, 0x00
|
|
.set MAIR_MEM_NC, 0x44
|
|
.set MAIR_MEM_WT, 0xbb
|
|
.set MAIR_MEM_WBWA, 0xff
|
|
.set mairval, MAIR_DEV_nGnRnE | (MAIR_MEM_NC << 8) | (MAIR_MEM_WT << 16) | (MAIR_MEM_WBWA << 24)
|
|
|
|
.set TCR_TG0_4KB, 0x0 << 14
|
|
.set TCR_TG1_4KB, 0x2 << 30
|
|
.set TCR_IPS_SHIFT, 32
|
|
.set TCR_EPD1, 0x1 << 23
|
|
.set TCR_SH_INNER, 0x3 << 12
|
|
.set TCR_RGN_OWB, 0x1 << 10
|
|
.set TCR_RGN_IWB, 0x1 << 8
|
|
.set tcrval, TCR_TG0_4KB | TCR_TG1_4KB | TCR_EPD1 | TCR_RGN_OWB
|
|
.set tcrval, tcrval | TCR_RGN_IWB | TCR_SH_INNER
|
|
|
|
.set SCTLR_ELx_I, 0x1 << 12
|
|
.set SCTLR_ELx_SA, 0x1 << 3
|
|
.set SCTLR_ELx_C, 0x1 << 2
|
|
.set SCTLR_ELx_M, 0x1 << 0
|
|
.set SCTLR_EL1_SPAN, 0x1 << 23
|
|
.set SCTLR_EL1_WXN, 0x1 << 19
|
|
.set SCTLR_EL1_SED, 0x1 << 8
|
|
.set SCTLR_EL1_ITD, 0x1 << 7
|
|
.set SCTLR_EL1_RES1, (0x1 << 11) | (0x1 << 20) | (0x1 << 22) | (0x1 << 28) | (0x1 << 29)
|
|
.set sctlrval, SCTLR_ELx_M | SCTLR_ELx_C | SCTLR_ELx_SA | SCTLR_EL1_ITD | SCTLR_EL1_SED
|
|
.set sctlrval, sctlrval | SCTLR_ELx_I | SCTLR_EL1_SPAN | SCTLR_EL1_RES1
|
|
|
|
|
|
ASM_FUNC(ArmPlatformPeiBootAction)
|
|
#ifdef CAVIUM_ERRATUM_27456
|
|
/*
|
|
* On Cavium ThunderX, using non-global mappings that are executable at EL1
|
|
* results in I-cache corruption. So just avoid the early ID mapping there.
|
|
*
|
|
* MIDR implementor 0x43
|
|
* MIDR part numbers 0xA1 0xA2 (but not 0xAF)
|
|
*/
|
|
mrs x0, midr_el1 // read the MIDR into X0
|
|
ubfx x1, x0, #24, #8 // grab implementor id
|
|
ubfx x0, x0, #7, #9 // grab part number bits [11:3]
|
|
cmp x1, #0x43 // compare implementor id
|
|
ccmp x0, #0xA0 >> 3, #0, eq // compare part# bits [11:3]
|
|
b.eq 0f
|
|
#endif
|
|
mrs x0, CurrentEL // check current exception level
|
|
tbnz x0, #3, 0f // omit early ID map if above EL1
|
|
|
|
mov_i x0, mairval
|
|
mov_i x1, tcrval
|
|
adrp x2, idmap
|
|
orr x2, x2, #0xff << 48 // set non-zero ASID
|
|
mov_i x3, sctlrval
|
|
|
|
mrs x6, id_aa64mmfr0_el1 // get the supported PA range
|
|
and x6, x6, #0xf // isolate PArange bits
|
|
cmp x6, #6 // 0b0110 == 52 bits
|
|
sub x6, x6, #1 // subtract 1
|
|
cinc x6, x6, ne // add back 1 unless PArange == 52 bits
|
|
bfi x1, x6, #32, #3 // copy updated PArange into TCR_EL1.IPS
|
|
|
|
cmp x6, #3 // 0b0011 == 42 bits
|
|
sub x6, x6, #1 // subtract 1
|
|
cinc x6, x6, lt // add back 1 unless VA range >= 42
|
|
|
|
mov x7, #32
|
|
sub x6, x7, x6, lsl #2 // T0SZ for PArange != 42
|
|
mov x7, #64 - 42 // T0SZ for PArange == 42
|
|
csel x6, x6, x7, ne
|
|
orr x1, x1, x6 // set T0SZ field in TCR
|
|
|
|
cmp x6, #64 - 40 // VA size < 40 bits?
|
|
add x4, x2, #0x1000 // advance to level 1 descriptor
|
|
csel x2, x4, x2, gt
|
|
|
|
msr mair_el1, x0 // set up the 1:1 mapping
|
|
msr tcr_el1, x1
|
|
msr ttbr0_el1, x2
|
|
isb
|
|
|
|
tlbi vmalle1 // invalidate any cached translations
|
|
ic iallu // invalidate the I-cache
|
|
dsb nsh
|
|
isb
|
|
|
|
msr sctlr_el1, x3 // enable MMU and caches
|
|
isb
|
|
|
|
0:b ArmEnableVFP // enable SIMD before entering C code
|
|
|
|
//UINTN
|
|
//ArmPlatformGetCorePosition (
|
|
// IN UINTN MpId
|
|
// );
|
|
// With this function: CorePos = (ClusterId * 4) + CoreId
|
|
ASM_FUNC(ArmPlatformGetCorePosition)
|
|
mov x0, xzr
|
|
ret
|
|
|
|
//UINTN
|
|
//ArmPlatformGetPrimaryCoreMpId (
|
|
// VOID
|
|
// );
|
|
ASM_FUNC(ArmPlatformGetPrimaryCoreMpId)
|
|
MOV32 (w0, FixedPcdGet32 (PcdArmPrimaryCore))
|
|
ret
|
|
|
|
//UINTN
|
|
//ArmPlatformIsPrimaryCore (
|
|
// IN UINTN MpId
|
|
// );
|
|
ASM_FUNC(ArmPlatformIsPrimaryCore)
|
|
mov x0, #1
|
|
ret
|