[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v3 12/27] ArmVirtualizationPkg: Xen/PV relocatable platformlib instance
On 03/02/15 19:19, Ard Biesheuvel wrote: Add a ArmPlatformLib instance that can deal with the self relocation and truly dynamic discovery of system RAM base and size. Contributed-under: TianoCore Contribution Agreement 1.0 Acked-by: Laszlo Ersek <lersek@xxxxxxxxxx> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@xxxxxxxxxx> --- .../AARCH64/MemnodeParser.S | 232 +++++++++++++++++++++ .../AARCH64/RelocatableVirtHelper.S | 161 ++++++++++++++ .../ArmXenRelocatablePlatformLib.inf | 59 ++++++ .../ArmXenRelocatablePlatformLib/RelocatableVirt.c | 71 +++++++ .../ArmXenRelocatablePlatformLib/XenVirtMem.c | 83 ++++++++ 5 files changed, 606 insertions(+) create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c create mode 100644 ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S new file mode 100644 index 000000000000..cce2c4800c51 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/MemnodeParser.S @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2014, Linaro Ltd. All rights reserved. + * + * This program and the accompanying materials + * are licensed and made available under the terms and conditions of the BSD License + * which accompanies this distribution. The full text of the license may be found at + * http://opensource.org/licenses/bsd-license.php + * + * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, + * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. + */ + +/* + * Theory of operation + * ------------------- + * + * This code parses a Flattened Device Tree binary (DTB) to find the base of + * system RAM. It is written in assembly so that it can be executed before a + * stack has been set up. + * + * To find the base of system RAM, we have to traverse the FDT to find a memory + * node. In the context of this implementation, the first node that has a + * device_type property with the value 'memory' and a 'reg' property is + * acceptable, and the name of the node (memory[@xxx]) is ignored, as are any + * other nodes that match the above constraints. + * + * In pseudo code, this implementation does the following: + * + * for each node { + * have_device_type = false + * have_reg = false + * + * for each property { + * if property value == 'memory' { + * if property name == 'device_type' { + * have_device_type = true + * } + * } else { + * if property name == 'reg' { + * have_reg = true + * membase = property value[0] + * memsize = property value[1] + * } + * } + * } + * if have_device_type and have_reg { + * return membase and memsize + * } + * } + * return NOT_FOUND + */ + +#define FDT_MAGIC 0xedfe0dd0 + +#define FDT_BEGIN_NODE 0x1 +#define FDT_END_NODE 0x2 +#define FDT_PROP 0x3 +#define FDT_END 0x9 + + xMEMSIZE .req x0 + xMEMBASE .req x1 + + xLR .req x8 + xDTP .req x9 + xSTRTAB .req x10 Either add a comment to say what means xDTP and xSTRTAB or rename the definitions (eg: renaming xDTP into xDT_PTR and xSTRTAB into xSTR_TABLE). I would prefer the second option but I would not block the patch if you prefer adding the comments. + xMEMNODE .req x11 + + .text + .align 3 +_memory: + .asciz "memory" +_reg: + .asciz "reg" +_device_type: + .asciz "device_type" + + /* + * Compare strings in x4 and x5, return in w7 + */ + .align 3 +strcmp: + ldrb w2, [x4], #1 + ldrb w3, [x5], #1 + subs w7, w2, w3 + cbz w2, 0f + cbz w3, 0f + beq strcmp +0: ret + + .globl find_memnode +find_memnode: + // preserve link register + mov xLR, x30 + mov xDTP, x0 + mov xMEMNODE, #0 This line is duplicated. You do the operation again after the label 'begin_node:'. You can remove this line. + + /* + * Check the DTB magic at offset 0 + */ + movz w4, #:abs_g0_nc:FDT_MAGIC + movk w4, #:abs_g1:FDT_MAGIC + ldr w5, [xDTP] + cmp w4, w5 + bne err_invalid_magic + + /* + * Read the string offset and store it for later use + */ + ldr w4, [xDTP, #12] + rev w4, w4 + add xSTRTAB, xDTP, x4 + + /* + * Read the struct offset and add it to the DT pointer + */ + ldr w5, [xDTP, #8] + rev w5, w5 + add xDTP, xDTP, x5 + + /* + * Check current tag for FDT_BEGIN_NODE + */ + ldr w5, [xDTP] + rev w5, w5 + cmp w5, #FDT_BEGIN_NODE + bne err_unexpected_begin_tag + +begin_node: + mov xMEMNODE, #0 + add xDTP, xDTP, #4 + + /* + * Advance xDTP past NULL terminated string + */ +0: ldrb w4, [xDTP], #1 + cbnz w4, 0b + +next_tag: + add xDTP, xDTP, #3 + and xDTP, xDTP, #~3 I was guessing this line was to ensure the xDT_PTR was aligned. But a comment would be nice. + + /* + * Read the next tag, could be BEGIN_NODE, END_NODE, PROP, END + */ + ldr w5, [xDTP] + rev w5, w5 + cmp w5, #FDT_BEGIN_NODE + beq begin_node + cmp w5, #FDT_END_NODE + beq end_node + cmp w5, #FDT_PROP + beq prop_node + cmp w5, #FDT_END + beq err_end_of_fdt + b err_unexpected_tag + +prop_node: + /* + * If propname == 'reg', record as membase and memsize + * If propname == 'device_type' and value == 'memory', + * set the 'is_memnode' flag for this node + */ + ldr w6, [xDTP, #4] + add xDTP, xDTP, #12 + rev w6, w6 + mov x5, xDTP + adr x4, _memory + bl strcmp + + /* + * Get handle to property name + */ + ldr w5, [xDTP, #-4] + rev w5, w5 + add x5, xSTRTAB, x5 + + cbz w7, check_device_type + + /* + * Check for 'reg' property + */ + adr x4, _reg + bl strcmp + cbnz w7, inc_and_next_tag + + /* + * Extract two 64-bit quantities from the 'reg' property. These values + * will only be used if the node also turns out to have a device_type + * property with a value of 'memory'. + * + * NOTE: xDTP is only guaranteed to be 32 bit aligned, and we are most + * likely executing with the MMU off, so we cannot use 64 bit + * wide accesses here. + */ + ldp w4, w5, [xDTP] + orr xMEMBASE, x4, x5, lsl #32 + ldp w4, w5, [xDTP, #8] + orr xMEMSIZE, x4, x5, lsl #32 + rev xMEMBASE, xMEMBASE + rev xMEMSIZE, xMEMSIZE + orr xMEMNODE, xMEMNODE, #2 + b inc_and_next_tag + +check_device_type: + /* + * Check whether the current property's name is 'device_type' + */ + adr x4, _device_type + bl strcmp + cbnz w7, inc_and_next_tag + orr xMEMNODE, xMEMNODE, #1 + +inc_and_next_tag: + add xDTP, xDTP, x6 + b next_tag + +end_node: + /* + * Check for device_type = memory and reg = xxxx + * If we have both, we are done + */ + add xDTP, xDTP, #4 + cmp xMEMNODE, #3 + bne next_tag + + ret xLR + +err_invalid_magic: +err_unexpected_begin_tag: +err_unexpected_tag: +err_end_of_fdt: + wfi diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S new file mode 100644 index 000000000000..58071b5ae62a --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/AARCH64/RelocatableVirtHelper.S @@ -0,0 +1,161 @@ +# +# Copyright (c) 2011-2013, ARM Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +# + +#include <AsmMacroIoLibV8.h> +#include <Base.h> +#include <Library/ArmLib.h> +#include <Library/PcdLib.h> +#include <AutoGen.h> + +.text +.align 2 + +GCC_ASM_EXPORT(ArmPlatformPeiBootAction) +GCC_ASM_EXPORT(ArmPlatformIsPrimaryCore) +GCC_ASM_EXPORT(ArmPlatformGetPrimaryCoreMpId) +GCC_ASM_EXPORT(ArmPlatformGetCorePosition) +GCC_ASM_EXPORT(ArmGetPhysAddrTop) + +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCore) +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdArmPrimaryCoreMask) +GCC_ASM_IMPORT(_gPcd_FixedAtBuild_PcdCoreCount) + +.LFdtMagic: + .byte 0xd0, 0x0d, 0xfe, 0xed + +.LArm64LinuxMagic: + .byte 0x41, 0x52, 0x4d, 0x64 + +ASM_PFX(ArmPlatformPeiBootAction): Add a comment at the top of this function to tell which parameters are passed to the UEFI firmware by Xen. It is already commented in the code but it would be nice to clarify the inputs. + mov x29, x30 // preserve LR + + // + // If we are booting from RAM using the Linux kernel boot protocol, x0 will + // point to the DTB image in memory. Otherwise, we are just coming out of + // reset, and x0 will be 0. Check also the FDT magic. + // + cbz x0, .Lout + ldr w8, .LFdtMagic + ldr w9, [x0] + cmp w8, w9 + bne .Lout + + // + // The base of the runtime image has been preserved in x1. Check whether + // the expected magic number can be found in the header. + // + ldr w8, .LArm64LinuxMagic + ldr w9, [x1, #0x38] + cmp w8, w9 + bne .Lout + + // + // + // OK, so far so good. We have confirmed that we likely have a DTB and are + // booting via the arm64 Linux boot protocol. Update the base-of-image PCD + // to the actual relocated value, and add the shift of PcdFdBaseAddress to + // PcdFvBaseAddress as well + // + adr x8, PcdGet64 (PcdFdBaseAddress) + adr x9, PcdGet64 (PcdFvBaseAddress) + ldr x6, [x8] + ldr x7, [x9] + sub x7, x7, x6 + add x7, x7, x1 + str x1, [x8] + str x7, [x9] + + // + // Copy the DTB to the slack space right after the header at the base of this + // image, and record the pointer in PcdDeviceTreeInitialBaseAddress. + // + adr x8, PcdGet64 (PcdDeviceTreeInitialBaseAddress) + add x1, x1, #0x40 Be more explicit on which header you are referring to. Maybe make a reference to the FDF. + str x1, [x8] + + ldr w8, [x0, #4] // get DTB size (BE) + mov x9, x1 + rev w8, w8 + add x8, x8, x0 +0:ldp x6, x7, [x0], #16 + stp x6, x7, [x9], #16 + cmp x0, x8 + blt 0b + + // + // Discover the memory size and offset from the DTB, and record in the + // respective PCDs + // + mov x0, x1 + bl find_memnode // returns (size, base) size in (x0, x1) + cbz x0, .Lout + + adr x8, PcdGet64 (PcdSystemMemorySize) + adr x9, PcdGet64 (PcdSystemMemoryBase) + str x0, [x8] + str x1, [x9] + +.Lout: + ret x29 + +//UINTN +//ArmPlatformGetPrimaryCoreMpId ( +// VOID +// ); +ASM_PFX(ArmPlatformGetPrimaryCoreMpId): + LoadConstantToReg (_gPcd_FixedAtBuild_PcdArmPrimaryCore, x0) + ldrh w0, [x0] + ret + +//UINTN +//ArmPlatformIsPrimaryCore ( +// IN UINTN MpId +// ); +ASM_PFX(ArmPlatformIsPrimaryCore): + mov x0, #1 + ret + +//UINTN +//ArmPlatformGetCorePosition ( +// IN UINTN MpId +// ); +// With this function: CorePos = (ClusterId * 4) + CoreId +ASM_PFX(ArmPlatformGetCorePosition): + and x1, x0, #ARM_CORE_MASK + and x0, x0, #ARM_CLUSTER_MASK + add x0, x1, x0, LSR #6 + ret + +//EFI_PHYSICAL_ADDRESS +//GetPhysAddrTop ( +// VOID +// ); +ASM_PFX(ArmGetPhysAddrTop): + mrs x0, id_aa64mmfr0_el1 + adr x1, .LPARanges + and x0, x0, #7 + ldrb w1, [x1, x0] + mov x0, #1 + lsl x0, x0, x1 + ret + +// +// Bits 0..2 of the AA64MFR0_EL1 system register encode the size of the +// physical address space support on this CPU: +// 0 == 32 bits, 1 == 36 bits, etc etc +// 6 and 7 are reserved +// +.LPARanges: + .byte 32, 36, 40, 42, 44, 48, -1, -1 + +ASM_FUNCTION_REMOVE_IF_UNREFERENCED diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf new file mode 100644 index 000000000000..17bb0f9292e2 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/ArmXenRelocatablePlatformLib.inf @@ -0,0 +1,59 @@ +#/* @file +# Copyright (c) 2011-2014, ARM Limited. All rights reserved. +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = ArmXenRelocatablePlatformLib + FILE_GUID = c8602718-4faa-4119-90ca-cae72509ac4c + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = ArmPlatformLib|SEC PEIM + +[Packages] + MdePkg/MdePkg.dec + MdeModulePkg/MdeModulePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + ArmPkg/ArmPkg.dec + ArmPlatformPkg/ArmPlatformPkg.dec + ArmPlatformPkg/ArmVirtualizationPkg/ArmVirtualizationPkg.dec + +[LibraryClasses] + IoLib + ArmLib + PrintLib + +[Sources.common] + RelocatableVirt.c + XenVirtMem.c + +[Sources.AARCH64] + AARCH64/RelocatableVirtHelper.S + AARCH64/MemnodeParser.S + +[FeaturePcd] + gEmbeddedTokenSpaceGuid.PcdCacheEnable + gArmPlatformTokenSpaceGuid.PcdSystemMemoryInitializeInSec + +[PatchPcd] + gArmVirtualizationTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress + gArmTokenSpaceGuid.PcdFdBaseAddress + gArmTokenSpaceGuid.PcdFvBaseAddress + gArmTokenSpaceGuid.PcdSystemMemoryBase + gArmTokenSpaceGuid.PcdSystemMemorySize + +[FixedPcd] + gArmPlatformTokenSpaceGuid.PcdCoreCount + gArmTokenSpaceGuid.PcdArmPrimaryCoreMask + gArmTokenSpaceGuid.PcdArmPrimaryCore + gArmTokenSpaceGuid.PcdFdSize diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c new file mode 100644 index 000000000000..c10c09fed2bd --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/RelocatableVirt.c @@ -0,0 +1,71 @@ +/** @file +* +* Copyright (c) 2011-2013, ARM Limited. All rights reserved. +* Copyright (c) 2014, Linaro Limited. All rights reserved. +* Copyright (c) 2014, Red Hat, Inc. +* +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Library/IoLib.h> +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <ArmPlatform.h> +#include <Pi/PiBootMode.h> + +/** + Return the current Boot Mode + + This function returns the boot reason on the platform + + @return Return the current Boot Mode of the platform + +**/ +EFI_BOOT_MODE +ArmPlatformGetBootMode ( + VOID + ) +{ + return BOOT_WITH_FULL_CONFIGURATION; +} + +/** + This function is called by PrePeiCore, in the SEC phase. +**/ +RETURN_STATUS +ArmPlatformInitialize ( + IN UINTN MpId + ) +{ + // + // We are relying on ArmPlatformInitializeSystemMemory () being called from + // InitializeMemory (), which only occurs if the following feature is disabled + // + ASSERT (!FeaturePcdGet (PcdSystemMemoryInitializeInSec)); + return RETURN_SUCCESS; +} + +VOID +ArmPlatformInitializeSystemMemory ( + VOID + ) +{ +} + +VOID +ArmPlatformGetPlatformPpiList ( + OUT UINTN *PpiListSize, + OUT EFI_PEI_PPI_DESCRIPTOR **PpiList + ) +{ + *PpiListSize = 0; + *PpiList = NULL; +} diff --git a/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c new file mode 100644 index 000000000000..657b840059c2 --- /dev/null +++ b/ArmPlatformPkg/ArmVirtualizationPkg/Library/ArmXenRelocatablePlatformLib/XenVirtMem.c @@ -0,0 +1,83 @@ +/** @file +* +* Copyright (c) 2014, Linaro Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include <Library/ArmPlatformLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/PcdLib.h> +#include <Library/IoLib.h> +#include <Library/MemoryAllocationLib.h> +#include <ArmPlatform.h> + +// Number of Virtual Memory Map Descriptors +#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 2 + +// DDR attributes +#define DDR_ATTRIBUTES_CACHED ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK +#define DDR_ATTRIBUTES_UNCACHED ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED + +EFI_PHYSICAL_ADDRESS +ArmGetPhysAddrTop ( + VOID + ); + +/** + Return the Virtual Memory Map of your platform + + This Virtual Memory Map is used by MemoryInitPei Module to initialize the MMU + on your platform. + + @param[out] VirtualMemoryMap Array of ARM_MEMORY_REGION_DESCRIPTOR + describing a Physical-to-Virtual Memory + mapping. This array must be ended by a + zero-filled entry + +**/ +VOID +ArmPlatformGetVirtualMemoryMap ( + IN ARM_MEMORY_REGION_DESCRIPTOR** VirtualMemoryMap + ) +{ + ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable; + + ASSERT (VirtualMemoryMap != NULL); + + VirtualMemoryTable = AllocatePages ( + EFI_SIZE_TO_PAGES ( + sizeof (ARM_MEMORY_REGION_DESCRIPTOR) + * MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS + ) + ); + + if (VirtualMemoryTable == NULL) { + DEBUG ((EFI_D_ERROR, "%a: Error: Failed AllocatePages()\n", __FUNCTION__)); + return; + } + + // + // Map the entire physical memory space as cached. The only device + // we care about is the GIC, which will be stage 2 mapped as a device + // by the hypervisor, which will override the cached mapping we install + // here. + // + VirtualMemoryTable[0].PhysicalBase = 0x0; + VirtualMemoryTable[0].VirtualBase = 0x0; + VirtualMemoryTable[0].Length = ArmGetPhysAddrTop (); + VirtualMemoryTable[0].Attributes = DDR_ATTRIBUTES_CACHED; + + // End of Table + ZeroMem (&VirtualMemoryTable[1], sizeof (ARM_MEMORY_REGION_DESCRIPTOR)); + + *VirtualMemoryMap = VirtualMemoryTable; +} -- 1.8.3.2 -- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you. ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2557590 ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2548782 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |