Hello, this patch for CpuDxe has been developed further, so now I send an actual version of it. I still think it will useful for all you.
Best regards, Konstantin Filatov Really this is a patch set, and I didn't merge it into a large patch applicable to the actual edk2-source. I have a reason for it. In this way this patch set will easier to understand, and it will scrutinized surely before a commit. The beginning of this patch set. fixed SetCodeSelector --- CpuDxe/X64/CpuAsm.S +++ CpuDxe/X64/CpuAsm.S @@ -51,13 +51,13 @@ ASM_PFX(InitializeExternalVectorTablePtr): #------------------------------------------------------------------------------ ASM_GLOBAL ASM_PFX(SetCodeSelector) ASM_PFX(SetCodeSelector): - subq $0x10, %rsp + subq $0x14, %rsp leaq L_setCodeSelectorLongJump(%rip), %rax movq %rax, (%rsp) - movw %cx, 4(%rsp) - .byte 0xFF, 0x2C, 0x24 # jmp (%rsp) note:fword jmp + movw %cx, 8(%rsp) + .byte 0x48, 0xFF, 0x2C, 0x24 # REX.W jmp (%rsp) note:fword jmp L_setCodeSelectorLongJump: - addq $0x10, %rsp + addq $0x14, %rsp ret #------------------------------------------------------------------------------ -- fixed a bug in CpuDxe in EFI IA32_DESCRIPTOR can have 64bit field Base regardless the name. --- CpuDxe/CpuDxe.c +++ CpuDxe/CpuDxe.c @@ -1192,7 +1192,7 @@ InitInterruptDescriptorTable ( // IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16); IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16); - IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1)); + IdtPtr->Base = (UINTN)(VOID*) gIdtTable; IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1); AsmWriteIdtr (IdtPtr); -- --- CpuDxe/CpuGdt.c +++ CpuDxe/CpuGdt.c @@ -194,7 +194,7 @@ InitGlobalDescriptorTable ( // // Write GDT register // - gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt; + gdtPtr.Base = (UINTN)(VOID*) gdt; gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1); AsmWriteGdtr (&gdtPtr); -- refactoring RestoreInterrupt...() in EFI --- CpuDxe/CpuDxe.c +++ CpuDxe/CpuDxe.c @@ -1110,13 +1110,9 @@ RestoreInterruptDescriptorTableHandlerAddress ( IN UINTN Index ) { - if (Index < mOrigIdtEntryCount) { - gIdtTable[Index].Bits.OffsetLow = mOrigIdtEntry[Index].Bits.OffsetLow; - gIdtTable[Index].Bits.OffsetHigh = mOrigIdtEntry[Index].Bits.OffsetHigh; -#if defined (MDE_CPU_X64) - gIdtTable[Index].Bits.OffsetUpper = mOrigIdtEntry[Index].Bits.OffsetUpper; -#endif - } + if (Index >= mOrigIdtEntryCount) + return; + CopyMem(gIdtTable + Index, mOrigIdtEntry + Index, sizeof(gIdtTable[Index])); } /** -- Fixed setting exception routines vector in EFI for on x64. --- CpuDxe/X64/CpuAsm.S +++ CpuDxe/X64/CpuAsm.S @@ -38,8 +38,8 @@ ExternalVectorTablePtr: ASM_GLOBAL ASM_PFX(InitializeExternalVectorTablePtr) ASM_PFX(InitializeExternalVectorTablePtr): - lea ExternalVectorTablePtr(%rip), %rax # save vector number - mov %rcx, (%rax) + leaq ExternalVectorTablePtr(%rip), %rax # save vector number + movq %rcx, (%rax) ret @@ -249,7 +249,7 @@ CommonInterruptEntry_al_0000: #; call into exception handler movq 8(%rbp), %rcx leaq ExternalVectorTablePtr(%rip), %rax - movl (%eax), %eax + movq (%rax), %rax movq (%rax,%rcx,8), %rax orq %rax, %rax # NULL? -- ported patch "fixed SetCodeSel() in EFI for x64" to MASM to allow build of EFI on Win32. --- CpuDxe/X64/CpuAsm.asm +++ CpuDxe/X64/CpuAsm.asm @@ -44,13 +44,19 @@ InitializeExternalVectorTablePtr ENDP ; ); ;------------------------------------------------------------------------------ SetCodeSelector PROC PUBLIC - sub rsp, 0x10 + sub rsp, 0x14 lea rax, setCodeSelectorLongJump mov [rsp], rax - mov [rsp+4], cx + mov [rsp+8], cx + ;* I'm not sure how to encode this. We need to jmp [esp], where in esp there is + ;* w16(selector):q64(address). + ;* in gcc version this is encoded as 48 ff 2c 24 [ rex.W ljmpq *(%esp) ] + ;* but in VC jmp qword ptr [rsp] generates code ff 24 24 [ jmpq *(%esp) ] + ;* so I've just inserted db 0x48 to emit REX.W and get original 48 ff 2c 24 + db 0x48 ; emit REX.W jmp fword ptr [rsp] setCodeSelectorLongJump: - add rsp, 0x10 + add rsp, 0x14 ret SetCodeSelector ENDP -- On AMD x64 JMP FAR cannot use 64-bit offset (see 24594, p. 137) and so cannot jump to code which is out of 32-bit space. Using IRETQ fixes this limitation. --- CpuDxe/X64/CpuAsm.S +++ CpuDxe/X64/CpuAsm.S @@ -51,13 +51,20 @@ ASM_PFX(InitializeExternalVectorTablePtr): #------------------------------------------------------------------------------ ASM_GLOBAL ASM_PFX(SetCodeSelector) ASM_PFX(SetCodeSelector): - subq $0x14, %rsp - leaq L_setCodeSelectorLongJump(%rip), %rax - movq %rax, (%rsp) - movw %cx, 8(%rsp) - .byte 0x48, 0xFF, 0x2C, 0x24 # REX.W jmp (%rsp) note:fword jmp + movq %ss, %rax + pushq %rax + movq %rsp, %rax + addq $8, %rax + pushq %rax + leaq L_setCodeSelectorLongJump(%rip), %rax + andq $0xffff, %rcx + pushfq + pushq %rcx + pushq %rax + # iretq is used, because this method of changing 32-bit code selector to 64-bit + # will work correctly on both Intel and AMD. + iretq L_setCodeSelectorLongJump: - addq $0x14, %rsp ret #------------------------------------------------------------------------------ -- --- CpuDxe/X64/CpuAsm.asm +++ CpuDxe/X64/CpuAsm.asm @@ -44,19 +44,20 @@ InitializeExternalVectorTablePtr ENDP ; ); ;------------------------------------------------------------------------------ SetCodeSelector PROC PUBLIC - sub rsp, 0x14 + mov rax, ss + push rax + mov rax, rsp + add rax, 8 + push rax lea rax, setCodeSelectorLongJump - mov [rsp], rax - mov [rsp+8], cx - ;* I'm not sure how to encode this. We need to jmp [esp], where in esp there is - ;* w16(selector):q64(address). - ;* in gcc version this is encoded as 48 ff 2c 24 [ rex.W ljmpq *(%esp) ] - ;* but in VC jmp qword ptr [rsp] generates code ff 24 24 [ jmpq *(%esp) ] - ;* so I've just inserted db 0x48 to emit REX.W and get original 48 ff 2c 24 - db 0x48 ; emit REX.W - jmp fword ptr [rsp] + and rcx, 0xffff + pushfq + push rcx + push rax + ; iretq is used, because this method of changing 32-bit code selector to 64-bit + ; will work correctly on both Intel and AMD. + iretq setCodeSelectorLongJump: - add rsp, 0x14 ret SetCodeSelector ENDP -- The end of this patch set. On 11/14/2012 02:40 PM, Konstantin Filatov wrote: > Hello, > > In order to make the upper memory usable, it has to be "tested". This > patch works for me and seems useful for TianoCore. > > This patch resolves a problem of 4gb limit. > > Best regards, > Konstantin Filatov > > Contributed-under: TianoCore Contribution Agreement 1.0 > Signed-off-by: Konstantin Filatov <kfila...@parallels.com> > > Index: UefiCpuPkg/CpuDxe/X64/CpuAsm.S > =================================================================== > --- UefiCpuPkg/CpuDxe/X64/CpuAsm.S (revision 13937) > +++ UefiCpuPkg/CpuDxe/X64/CpuAsm.S (working copy) > @@ -45,13 +45,13 @@ > > #------------------------------------------------------------------------------ > > > ASM_GLOBAL ASM_PFX(SetCodeSelector) > ASM_PFX(SetCodeSelector): > - subq $0x10, %rsp > + subq $0x14, %rsp > leaq L_setCodeSelectorLongJump(%rip), %rax > movq %rax, (%rsp) > - movw %cx, 4(%rsp) > - .byte 0xFF, 0x2C, 0x24 # jmp (%rsp) note:fword jmp > + movw %cx, 8(%rsp) > + .byte 0x48, 0xFF, 0x2C, 0x24 # REX.W jmp (%rsp) note:fword jmp > L_setCodeSelectorLongJump: > - addq $0x10, %rsp > + addq $0x14, %rsp > ret > > > #------------------------------------------------------------------------------ > > > Index: UefiCpuPkg/CpuDxe/CpuGdt.c > =================================================================== > --- UefiCpuPkg/CpuDxe/CpuGdt.c (revision 13937) > +++ UefiCpuPkg/CpuDxe/CpuGdt.c (working copy) > @@ -187,7 +187,7 @@ > // > // Write GDT register > // > - gdtPtr.Base = (UINT32)(UINTN)(VOID*) gdt; > + gdtPtr.Base = (UINTN)(VOID*) gdt; > gdtPtr.Limit = (UINT16) (sizeof (GdtTemplate) - 1); > AsmWriteGdtr (&gdtPtr); > > Index: UefiCpuPkg/CpuDxe/CpuDxe.c > =================================================================== > --- UefiCpuPkg/CpuDxe/CpuDxe.c (revision 13937) > +++ UefiCpuPkg/CpuDxe/CpuDxe.c (working copy) > @@ -1184,7 +1184,7 @@ > // > IdtPtrAlignmentBuffer = AllocatePool (sizeof (*IdtPtr) + 16); > IdtPtr = ALIGN_POINTER (IdtPtrAlignmentBuffer, 16); > - IdtPtr->Base = (UINT32)(((UINTN)(VOID*) gIdtTable) & (BASE_4GB-1)); > + IdtPtr->Base = (UINTN)(VOID*) gIdtTable; > IdtPtr->Limit = (UINT16) (sizeof (gIdtTable) - 1); > > AsmWriteIdtr (IdtPtr); > Index: OvmfPkg/PlatformPei/MemDetect.c > =================================================================== > --- OvmfPkg/PlatformPei/MemDetect.c (revision 13937) > +++ OvmfPkg/PlatformPei/MemDetect.c (working copy) > @@ -136,7 +136,7 @@ > MtrrSetMemoryAttribute (0, BASE_512KB + BASE_128KB, CacheWriteBack); > > if (UpperMemorySize != 0) { > - AddUntestedMemoryBaseSizeHob (BASE_4GB, UpperMemorySize); > + AddMemoryBaseSizeHob (BASE_4GB, UpperMemorySize); > > MtrrSetMemoryAttribute (BASE_4GB, UpperMemorySize, CacheWriteBack); > } > ------------------------------------------------------------------------------ Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS, MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft MVPs and experts. ON SALE this month only -- learn more at: http://p.sf.net/sfu/learnmore_122712 _______________________________________________ edk2-devel mailing list edk2-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/edk2-devel