Message ID | 20190704144233.27968-9-anthony.perard@citrix.com (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | Specific platform to run OVMF in Xen PVH and HVM guests | expand |
On 07/04/19 16:42, Anthony PERARD wrote: > This patch allows the ResetVector to be run indenpendently from build > time addresses. > > The goal of the patch is to avoid having to create RAM just below 4G > when creating a Xen PVH guest while being compatible with the way > hvmloader currently load OVMF, just below 4G. > > Only the new PVH entry point will do the calculation. > > The ResetVector will figure out its current running address by creating > a temporary stack, make a call and calculate the difference between the > build time address and the address at run time. > > This patch copies and make the necessary modification to some other asm > files: > - copy of UefiCpuPkg/.../Flat32ToFlat64.asm: > Allow Transition32FlatTo64Flat to be run from anywhere in memory > - copy of UefiCpuPkg/../SearchForBfvBase.asm: > Add a extra parameter to indicate where to start the search for the > boot firmware volume. > > Ref: https://bugzilla.tianocore.org/show_bug.cgi?id=1689 > Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> > Acked-by: Laszlo Ersek <lersek@redhat.com> > --- > > Notes: > v3: > - rebased, SPDX > - fix commit message There are more changes in v3 than that. First, some comment updates -- OK. Second (and actually this goes back to another unlisted v3 change, namely on patch#6 first): - in v2: - in patch #6, you store EAX to ESP at the top of xenPVHMain - in patch #8, you stash EAX in EBP at the top of xenPVHMain, then store EBP to ESP at the end of xenPVHMain - in v3: - in patch #6, you zero ESP at the top of xenPVHMain - in patch #8 (this patch), you move the zeroing to the end of xenPVHMain To the extent that I care :) , this looks OK to me -- and so my A-b stands --, but this change could be relevant for xen-devel reviewers, and should be pointed out. Thanks Laszlo > .../XenResetVector/Ia16/Real16ToFlat32.asm | 3 + > .../XenResetVector/Ia32/Flat32ToFlat64.asm | 68 +++++++++++++++ > .../XenResetVector/Ia32/SearchForBfvBase.asm | 87 +++++++++++++++++++ > OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm | 43 +++++++-- > 4 files changed, 194 insertions(+), 7 deletions(-) > create mode 100644 OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm > create mode 100644 OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm > > diff --git a/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm > index 5c329bfaea..36ea74f7fe 100644 > --- a/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm > +++ b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm > @@ -54,6 +54,9 @@ jumpTo32BitAndLandHere: > mov gs, ax > mov ss, ax > > + ; parameter for Flat32SearchForBfvBase > + xor eax, eax ; Start searching from top of 4GB for BfvBase > + > OneTimeCallRet TransitionFromReal16To32BitFlat > > ALIGN 2 > diff --git a/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm > new file mode 100644 > index 0000000000..661a8e7028 > --- /dev/null > +++ b/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm > @@ -0,0 +1,68 @@ > +;------------------------------------------------------------------------------ > +; @file > +; Transition from 32 bit flat protected mode into 64 bit flat protected mode > +; > +; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR> > +; Copyright (c) 2019, Citrix Systems, Inc. > +; > +; SPDX-License-Identifier: BSD-2-Clause-Patent > +; > +;------------------------------------------------------------------------------ > + > +BITS 32 > + > +; > +; Modified: EAX, EBX, ECX, EDX, ESP > +; > +Transition32FlatTo64Flat: > + > + OneTimeCall SetCr3ForPageTables64 > + > + mov eax, cr4 > + bts eax, 5 ; enable PAE > + mov cr4, eax > + > + mov ecx, 0xc0000080 > + rdmsr > + bts eax, 8 ; set LME > + wrmsr > + > + mov eax, cr0 > + bts eax, 31 ; set PG > + mov cr0, eax ; enable paging > + > + ; > + ; backup ESP > + ; > + mov ebx, esp > + > + ; > + ; recalculate delta > + ; > + mov esp, PVH_SPACE(16) > + call .delta > +.delta: > + pop edx > + sub edx, ADDR_OF(.delta) > + > + ; > + ; push return addr and seg to the stack, then return far > + ; > + push dword LINEAR_CODE64_SEL > + mov eax, ADDR_OF(jumpTo64BitAndLandHere) > + add eax, edx ; add delta > + push eax > + retf > + > +BITS 64 > +jumpTo64BitAndLandHere: > + > + ; > + ; restore ESP > + ; > + mov esp, ebx > + > + debugShowPostCode POSTCODE_64BIT_MODE > + > + OneTimeCallRet Transition32FlatTo64Flat > + > diff --git a/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm b/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm > new file mode 100644 > index 0000000000..190389c46f > --- /dev/null > +++ b/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm > @@ -0,0 +1,87 @@ > +;------------------------------------------------------------------------------ > +; @file > +; Search for the Boot Firmware Volume (BFV) base address > +; > +; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR> > +; Copyright (c) 2019, Citrix Systems, Inc. > +; > +; SPDX-License-Identifier: BSD-2-Clause-Patent > +; > +;------------------------------------------------------------------------------ > + > +;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ > +; { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } } > +%define FFS_GUID_DWORD0 0x8c8ce578 > +%define FFS_GUID_DWORD1 0x4f1c8a3d > +%define FFS_GUID_DWORD2 0x61893599 > +%define FFS_GUID_DWORD3 0xd32dc385 > + > +BITS 32 > + > +; > +; Modified: EAX, EBX, ECX > +; Preserved: EDI, ESP > +; > +; @param[in] EAX Start search from here > +; @param[out] EBP Address of Boot Firmware Volume (BFV) > +; > +Flat32SearchForBfvBase: > + > + mov ecx, eax > +searchingForBfvHeaderLoop: > + ; > + ; We check for a firmware volume at every 4KB address in the 16MB > + ; just below where we started, ECX. > + ; > + sub eax, 0x1000 > + mov ebx, ecx > + sub ebx, eax > + cmp ebx, 0x01000000 > + ; if ECX-EAX > 16MB; jump notfound > + ja searchedForBfvHeaderButNotFound > + > + ; > + ; Check FFS GUID > + ; > + cmp dword [eax + 0x10], FFS_GUID_DWORD0 > + jne searchingForBfvHeaderLoop > + cmp dword [eax + 0x14], FFS_GUID_DWORD1 > + jne searchingForBfvHeaderLoop > + cmp dword [eax + 0x18], FFS_GUID_DWORD2 > + jne searchingForBfvHeaderLoop > + cmp dword [eax + 0x1c], FFS_GUID_DWORD3 > + jne searchingForBfvHeaderLoop > + > + ; > + ; Check FV Length > + ; > + cmp dword [eax + 0x24], 0 > + jne searchingForBfvHeaderLoop > + mov ebx, eax > + add ebx, dword [eax + 0x20] > + cmp ebx, ecx > + jnz searchingForBfvHeaderLoop > + > + jmp searchedForBfvHeaderAndItWasFound > + > +searchedForBfvHeaderButNotFound: > + ; > + ; Hang if the SEC entry point was not found > + ; > + debugShowPostCode POSTCODE_BFV_NOT_FOUND > + > + ; > + ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed > + ; for debugging purposes. > + ; > + mov eax, 0xBFBFBFBF > + mov ebp, eax > + jmp $ > + > +searchedForBfvHeaderAndItWasFound: > + mov ebp, eax > + > + debugShowPostCode POSTCODE_BFV_FOUND > + > + OneTimeCallRet Flat32SearchForBfvBase > + > diff --git a/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm b/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm > index f42df3dba2..2df0f12e18 100644 > --- a/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm > +++ b/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm > @@ -16,25 +16,42 @@ xenPVHMain: > ; > mov di, 'BP' > > - ; > - ; ESP will be used as initial value of the EAX register > - ; in Main.asm > - ; > - xor esp, esp > - > ; > ; Store "Start of day" struct pointer for later use > ; > mov dword[PVH_SPACE (0)], ebx > mov dword[PVH_SPACE (4)], 'XPVH' > > + ; > + ; calculate delta between build-addr and run position > + ; > + mov esp, PVH_SPACE(16) ; create a temporary stack > + call .delta > +.delta: > + pop edx ; get addr of .delta > + sub edx, ADDR_OF(.delta) ; calculate delta > + > + ; > + ; Find address of GDT and gdtr and fix the later > + ; > mov ebx, ADDR_OF(gdtr) > + add ebx, edx ; add delta gdtr > + mov eax, ADDR_OF(GDT_BASE) > + add eax, edx ; add delta to GDT_BASE > + mov dword[ebx + 2], eax ; fix GDT_BASE addr in gdtr > lgdt [ebx] > > mov eax, SEC_DEFAULT_CR0 > mov cr0, eax > > - jmp LINEAR_CODE_SEL:ADDR_OF(.jmpToNewCodeSeg) > + ; > + ; push return addr to the stack, then return far > + ; > + push dword LINEAR_CODE_SEL ; segment to select > + mov eax, ADDR_OF(.jmpToNewCodeSeg) ; return addr > + add eax, edx ; add delta to return addr > + push eax > + retf > .jmpToNewCodeSeg: > > mov eax, SEC_DEFAULT_CR4 > @@ -47,6 +64,18 @@ xenPVHMain: > mov gs, ax > mov ss, ax > > + ; > + ; ESP will be used as initial value of the EAX register > + ; in Main.asm > + ; > + xor esp, esp > + > + ; > + ; parameter for Flat32SearchForBfvBase > + ; > + mov eax, ADDR_OF(fourGigabytes) > + add eax, edx ; add delta > + > ; > ; Jump to the main routine of the pre-SEC code > ; skiping the 16-bit part of the routine and >
diff --git a/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm index 5c329bfaea..36ea74f7fe 100644 --- a/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm +++ b/OvmfPkg/XenResetVector/Ia16/Real16ToFlat32.asm @@ -54,6 +54,9 @@ jumpTo32BitAndLandHere: mov gs, ax mov ss, ax + ; parameter for Flat32SearchForBfvBase + xor eax, eax ; Start searching from top of 4GB for BfvBase + OneTimeCallRet TransitionFromReal16To32BitFlat ALIGN 2 diff --git a/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm b/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm new file mode 100644 index 0000000000..661a8e7028 --- /dev/null +++ b/OvmfPkg/XenResetVector/Ia32/Flat32ToFlat64.asm @@ -0,0 +1,68 @@ +;------------------------------------------------------------------------------ +; @file +; Transition from 32 bit flat protected mode into 64 bit flat protected mode +; +; Copyright (c) 2008 - 2018, Intel Corporation. All rights reserved.<BR> +; Copyright (c) 2019, Citrix Systems, Inc. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +BITS 32 + +; +; Modified: EAX, EBX, ECX, EDX, ESP +; +Transition32FlatTo64Flat: + + OneTimeCall SetCr3ForPageTables64 + + mov eax, cr4 + bts eax, 5 ; enable PAE + mov cr4, eax + + mov ecx, 0xc0000080 + rdmsr + bts eax, 8 ; set LME + wrmsr + + mov eax, cr0 + bts eax, 31 ; set PG + mov cr0, eax ; enable paging + + ; + ; backup ESP + ; + mov ebx, esp + + ; + ; recalculate delta + ; + mov esp, PVH_SPACE(16) + call .delta +.delta: + pop edx + sub edx, ADDR_OF(.delta) + + ; + ; push return addr and seg to the stack, then return far + ; + push dword LINEAR_CODE64_SEL + mov eax, ADDR_OF(jumpTo64BitAndLandHere) + add eax, edx ; add delta + push eax + retf + +BITS 64 +jumpTo64BitAndLandHere: + + ; + ; restore ESP + ; + mov esp, ebx + + debugShowPostCode POSTCODE_64BIT_MODE + + OneTimeCallRet Transition32FlatTo64Flat + diff --git a/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm b/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm new file mode 100644 index 0000000000..190389c46f --- /dev/null +++ b/OvmfPkg/XenResetVector/Ia32/SearchForBfvBase.asm @@ -0,0 +1,87 @@ +;------------------------------------------------------------------------------ +; @file +; Search for the Boot Firmware Volume (BFV) base address +; +; Copyright (c) 2008 - 2009, Intel Corporation. All rights reserved.<BR> +; Copyright (c) 2019, Citrix Systems, Inc. +; +; SPDX-License-Identifier: BSD-2-Clause-Patent +; +;------------------------------------------------------------------------------ + +;#define EFI_FIRMWARE_FILE_SYSTEM2_GUID \ +; { 0x8c8ce578, 0x8a3d, 0x4f1c, { 0x99, 0x35, 0x89, 0x61, 0x85, 0xc3, 0x2d, 0xd3 } } +%define FFS_GUID_DWORD0 0x8c8ce578 +%define FFS_GUID_DWORD1 0x4f1c8a3d +%define FFS_GUID_DWORD2 0x61893599 +%define FFS_GUID_DWORD3 0xd32dc385 + +BITS 32 + +; +; Modified: EAX, EBX, ECX +; Preserved: EDI, ESP +; +; @param[in] EAX Start search from here +; @param[out] EBP Address of Boot Firmware Volume (BFV) +; +Flat32SearchForBfvBase: + + mov ecx, eax +searchingForBfvHeaderLoop: + ; + ; We check for a firmware volume at every 4KB address in the 16MB + ; just below where we started, ECX. + ; + sub eax, 0x1000 + mov ebx, ecx + sub ebx, eax + cmp ebx, 0x01000000 + ; if ECX-EAX > 16MB; jump notfound + ja searchedForBfvHeaderButNotFound + + ; + ; Check FFS GUID + ; + cmp dword [eax + 0x10], FFS_GUID_DWORD0 + jne searchingForBfvHeaderLoop + cmp dword [eax + 0x14], FFS_GUID_DWORD1 + jne searchingForBfvHeaderLoop + cmp dword [eax + 0x18], FFS_GUID_DWORD2 + jne searchingForBfvHeaderLoop + cmp dword [eax + 0x1c], FFS_GUID_DWORD3 + jne searchingForBfvHeaderLoop + + ; + ; Check FV Length + ; + cmp dword [eax + 0x24], 0 + jne searchingForBfvHeaderLoop + mov ebx, eax + add ebx, dword [eax + 0x20] + cmp ebx, ecx + jnz searchingForBfvHeaderLoop + + jmp searchedForBfvHeaderAndItWasFound + +searchedForBfvHeaderButNotFound: + ; + ; Hang if the SEC entry point was not found + ; + debugShowPostCode POSTCODE_BFV_NOT_FOUND + + ; + ; 0xbfbfbfbf in the EAX & EBP registers helps signal what failed + ; for debugging purposes. + ; + mov eax, 0xBFBFBFBF + mov ebp, eax + jmp $ + +searchedForBfvHeaderAndItWasFound: + mov ebp, eax + + debugShowPostCode POSTCODE_BFV_FOUND + + OneTimeCallRet Flat32SearchForBfvBase + diff --git a/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm b/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm index f42df3dba2..2df0f12e18 100644 --- a/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm +++ b/OvmfPkg/XenResetVector/Ia32/XenPVHMain.asm @@ -16,25 +16,42 @@ xenPVHMain: ; mov di, 'BP' - ; - ; ESP will be used as initial value of the EAX register - ; in Main.asm - ; - xor esp, esp - ; ; Store "Start of day" struct pointer for later use ; mov dword[PVH_SPACE (0)], ebx mov dword[PVH_SPACE (4)], 'XPVH' + ; + ; calculate delta between build-addr and run position + ; + mov esp, PVH_SPACE(16) ; create a temporary stack + call .delta +.delta: + pop edx ; get addr of .delta + sub edx, ADDR_OF(.delta) ; calculate delta + + ; + ; Find address of GDT and gdtr and fix the later + ; mov ebx, ADDR_OF(gdtr) + add ebx, edx ; add delta gdtr + mov eax, ADDR_OF(GDT_BASE) + add eax, edx ; add delta to GDT_BASE + mov dword[ebx + 2], eax ; fix GDT_BASE addr in gdtr lgdt [ebx] mov eax, SEC_DEFAULT_CR0 mov cr0, eax - jmp LINEAR_CODE_SEL:ADDR_OF(.jmpToNewCodeSeg) + ; + ; push return addr to the stack, then return far + ; + push dword LINEAR_CODE_SEL ; segment to select + mov eax, ADDR_OF(.jmpToNewCodeSeg) ; return addr + add eax, edx ; add delta to return addr + push eax + retf .jmpToNewCodeSeg: mov eax, SEC_DEFAULT_CR4 @@ -47,6 +64,18 @@ xenPVHMain: mov gs, ax mov ss, ax + ; + ; ESP will be used as initial value of the EAX register + ; in Main.asm + ; + xor esp, esp + + ; + ; parameter for Flat32SearchForBfvBase + ; + mov eax, ADDR_OF(fourGigabytes) + add eax, edx ; add delta + ; ; Jump to the main routine of the pre-SEC code ; skiping the 16-bit part of the routine and