Ring3: Summarized all known problems for AARCH64.

This commit is contained in:
Mikhail Krichanov 2024-06-04 13:48:37 +03:00
parent 038a03aa34
commit ea5ad0fb34
8 changed files with 139 additions and 14 deletions

View File

@ -92,7 +92,8 @@
UefiCpuPkg/UefiCpuPkg.dec UefiCpuPkg/UefiCpuPkg.dec
OvmfPkg/OvmfPkg.dec OvmfPkg/OvmfPkg.dec
ArmPkg/ArmPkg.dec ArmPkg/ArmPkg.dec
ArmVirtPkg/ArmVirtPkg.dec
[LibraryClasses] [LibraryClasses]
BaseMemoryLib BaseMemoryLib
CacheMaintenanceLib CacheMaintenanceLib

View File

@ -69,8 +69,22 @@ call:
// (x4) &CoreSp // (x4) &CoreSp
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
ASM_FUNC(ArmCallRing3) ASM_FUNC(ArmCallRing3)
// Save FP and LR on Core Stack. // Save registers.
stp x29, x30, [sp, #-0x10]! sub sp, sp, #0x100
stp q8, q9, [sp, #0xe0]
stp q10, q11, [sp, #0xc0]
stp q12, q13, [sp, #0xa0]
stp q14, q15, [sp, #0x80]
stp xzr, x16, [sp, #0x70]
stp x17, x18, [sp, #0x60]
stp x19, x20, [sp, #0x50]
stp x21, x22, [sp, #0x40]
stp x23, x24, [sp, #0x30]
stp x25, x26, [sp, #0x20]
stp x27, x28, [sp, #0x10]
stp x29, x30, [sp]
// Disable interrupts. // Disable interrupts.
msr daifset, #0xf msr daifset, #0xf
isb isb
@ -112,9 +126,21 @@ ASM_FUNC(ReturnToCore)
msr far_el1, xzr msr far_el1, xzr
// Switch to Core Stack. // Switch to Core Stack.
mov sp, x1 mov sp, x1
// Restore Stack. // Restore registers and Stack.
ldp x29, x30, [sp] ldp q8, q9, [sp, #0xe0]
add sp, sp, #0x10 ldp q10, q11, [sp, #0xc0]
ldp q12, q13, [sp, #0xa0]
ldp q14, q15, [sp, #0x80]
ldr x16, [sp, #0x78]
ldp x17, x18, [sp, #0x60]
ldp x19, x20, [sp, #0x50]
ldp x21, x22, [sp, #0x40]
ldp x23, x24, [sp, #0x30]
ldp x25, x26, [sp, #0x20]
ldp x27, x28, [sp, #0x10]
ldp x29, x30, [sp]
add sp, sp, #0x100
// Enable interrupts. // Enable interrupts.
msr daifclr, #0xf msr daifclr, #0xf
isb isb

View File

@ -6,12 +6,14 @@
**/ **/
#include <Chipset/AArch64.h> #include <Chipset/AArch64.h>
#include <Guid/EarlyPL011BaseAddress.h>
#include <Library/ArmLib.h> #include <Library/ArmLib.h>
#include <Library/DefaultExceptionHandlerLib.h> #include <Library/DefaultExceptionHandlerLib.h>
#include "DxeMain.h" #include "DxeMain.h"
STATIC UINTN mCoreSp; STATIC UINTN mCoreSp;
UINTN gUartBaseAddress;
EFI_STATUS EFI_STATUS
EFIAPI EFIAPI
@ -70,6 +72,12 @@ SysCallBootService (
DisableSMAP (); DisableSMAP ();
CopyMem ((VOID *)((UINTN)Physical + sizeof (UINTN)), (VOID *)UserRsp, 8 * sizeof (UINTN)); CopyMem ((VOID *)((UINTN)Physical + sizeof (UINTN)), (VOID *)UserRsp, 8 * sizeof (UINTN));
SetUefiImageMemoryAttributes (
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP
);
EnableSMAP (); EnableSMAP ();
Status = CallBootService ( Status = CallBootService (
@ -78,6 +86,12 @@ SysCallBootService (
(RING3_STACK *)(UINTN)Physical (RING3_STACK *)(UINTN)Physical
); );
SetUefiImageMemoryAttributes (
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP | EFI_MEMORY_USER
);
CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN))); CoreFreePages (Physical, EFI_SIZE_TO_PAGES (9 * sizeof (UINTN)));
return Status; return Status;
@ -86,10 +100,17 @@ SysCallBootService (
VOID VOID
EFIAPI EFIAPI
InitializeMsr ( InitializeMsr (
VOID IN OUT EFI_CONFIGURATION_TABLE *Table,
IN UINTN NumberOfEntries
) )
{ {
UINTN Tcr; UINTN Tcr;
UINTN Index;
EARLY_PL011_BASE_ADDRESS *UartBase;
EFI_PHYSICAL_ADDRESS Physical;
EFI_HOB_GENERIC_HEADER *Ring3Hob;
UINT16 HobLength;
EFI_STATUS Status;
// //
// If HCR_EL2.NV is 1 and the current Exception level is EL1, // If HCR_EL2.NV is 1 and the current Exception level is EL1,
// then EL1 read accesses to the CurrentEL register return a value of 0x2 in bits[3:2]. // then EL1 read accesses to the CurrentEL register return a value of 0x2 in bits[3:2].
@ -103,6 +124,49 @@ InitializeMsr (
Tcr = ArmGetTCR (); Tcr = ArmGetTCR ();
Tcr |= TCR_EL1_HPD0_MASK | TCR_EL1_HPD1_MASK; Tcr |= TCR_EL1_HPD0_MASK | TCR_EL1_HPD1_MASK;
ArmSetTCR (Tcr); ArmSetTCR (Tcr);
//
// Problem 1: Uart is memory maped.
//
for (Index = 0; Index < NumberOfEntries; ++Index) {
if (CompareGuid (&gEfiHobListGuid, &(Table[Index].VendorGuid))) {
UartBase = GET_GUID_HOB_DATA (Table[Index].VendorTable);
gUartBaseAddress = UartBase->DebugAddress;
//
// Copy Hob into Ring3.
//
Status = CoreAllocatePages (
AllocateAnyPages,
EfiRing3MemoryType,
1,
&Physical
);
if (EFI_ERROR (Status)) {
DEBUG ((DEBUG_ERROR, "Core: Failed to allocate memory for Ring3Hob.\n"));
ASSERT (FALSE);
}
DEBUG ((DEBUG_ERROR, "UartBaseAddress = %p.\n", gUartBaseAddress));
Ring3Hob = (EFI_HOB_GENERIC_HEADER *)(UINTN)Physical;
HobLength = (UINT16)((sizeof (EFI_HOB_GUID_TYPE) + sizeof (EARLY_PL011_BASE_ADDRESS) + 0x7) & (~0x7));
Ring3Hob->HobType = EFI_HOB_TYPE_GUID_EXTENSION;
Ring3Hob->HobLength = HobLength;
Ring3Hob->Reserved = 0;
CopyGuid (&((EFI_HOB_GUID_TYPE *)Ring3Hob)->Name, &gEarlyPL011BaseAddressGuid);
Ring3Hob = (EFI_HOB_GENERIC_HEADER *)((UINTN)Ring3Hob + HobLength);
Ring3Hob->HobType = EFI_HOB_TYPE_END_OF_HOB_LIST;
Ring3Hob->HobLength = sizeof (EFI_HOB_GENERIC_HEADER);
Ring3Hob->Reserved = 0;
Table[Index].VendorTable = (VOID *)(UINTN)Physical;
UartBase = GET_GUID_HOB_DATA (Table[Index].VendorTable);
UartBase->DebugAddress = gUartBaseAddress;
}
}
if (ArmHasPan ()) { if (ArmHasPan ()) {
// //

View File

@ -10,7 +10,8 @@
VOID VOID
EFIAPI EFIAPI
InitializeMsr ( InitializeMsr (
VOID IN OUT EFI_CONFIGURATION_TABLE *Table,
IN UINTN NumberOfEntries
) )
{ {

View File

@ -12,7 +12,8 @@
VOID VOID
EFIAPI EFIAPI
InitializeMsr ( InitializeMsr (
VOID IN OUT EFI_CONFIGURATION_TABLE *Table,
IN UINTN NumberOfEntries
) )
{ {
UINT64 Msr; UINT64 Msr;

View File

@ -18,7 +18,8 @@ VOID *gRing3Interfaces;
VOID VOID
EFIAPI EFIAPI
InitializeMsr ( InitializeMsr (
VOID IN OUT EFI_CONFIGURATION_TABLE *Table,
IN UINTN NumberOfEntries
); );
EFI_STATUS EFI_STATUS
@ -141,7 +142,10 @@ InitializeRing3 (
SetUefiImageMemoryAttributes ((UINTN)gRing3CallStackBase, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER); SetUefiImageMemoryAttributes ((UINTN)gRing3CallStackBase, SizeOfStack, EFI_MEMORY_XP | EFI_MEMORY_USER);
DEBUG ((DEBUG_ERROR, "Core: gRing3CallStackTop = %p\n", gRing3CallStackTop)); DEBUG ((DEBUG_ERROR, "Core: gRing3CallStackTop = %p\n", gRing3CallStackTop));
InitializeMsr (); InitializeMsr (
gRing3Data->SystemTable.ConfigurationTable,
gRing3Data->SystemTable.NumberOfTableEntries
);
return Status; return Status;
} }

View File

@ -13,6 +13,10 @@ EFI_FILE_PROTOCOL mRing3FileProtocol;
EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *mRing3SimpleFileSystemPointer; EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *mRing3SimpleFileSystemPointer;
#if defined (MDE_CPU_AARCH64)
extern UINTN gUartBaseAddress;
#endif
typedef struct { typedef struct {
EFI_FILE_PROTOCOL Protocol; EFI_FILE_PROTOCOL Protocol;
EFI_FILE_PROTOCOL *Ring3File; EFI_FILE_PROTOCOL *Ring3File;
@ -69,8 +73,16 @@ GoToRing3 (
EFI_MEMORY_XP | EFI_MEMORY_USER EFI_MEMORY_XP | EFI_MEMORY_USER
); );
} }
#elif defined (MDE_CPU_AARCH64)
//
// Necessary fix for DEBUG printings.
//
SetUefiImageMemoryAttributes (
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP | EFI_MEMORY_USER
);
#endif #endif
Status = CallRing3 (Input); Status = CallRing3 (Input);
#if defined (MDE_CPU_X64) || defined (MDE_CPU_IA32) #if defined (MDE_CPU_X64) || defined (MDE_CPU_IA32)
@ -81,6 +93,21 @@ GoToRing3 (
EFI_MEMORY_XP EFI_MEMORY_XP
); );
} }
#elif defined (MDE_CPU_AARCH64)
//
// Problem 2: Uart memory maped page is not allocated at the very beginnig
// and can be used for translation table later.
//
DisableSMAP ();
//
// Problem 3: QEMU ramdomly breaks GP registers' context.
//
SetUefiImageMemoryAttributes (
gUartBaseAddress,
EFI_PAGE_SIZE,
EFI_MEMORY_XP
);
EnableSMAP ();
#endif #endif
CoreFreePages (Ring3Pages, PagesNumber); CoreFreePages (Ring3Pages, PagesNumber);

View File

@ -12,7 +12,8 @@
VOID VOID
EFIAPI EFIAPI
InitializeMsr ( InitializeMsr (
VOID IN OUT EFI_CONFIGURATION_TABLE *Table,
IN UINTN NumberOfEntries
) )
{ {
UINT64 Msr; UINT64 Msr;