On 12/05/13 23:53, Andrew Fish wrote:
> 
> On Dec 5, 2013, at 2:38 PM, Laszlo Ersek <ler...@redhat.com
> <mailto:ler...@redhat.com>> wrote:
>>
>> Does gas support mode switches in one file? I found examples on the
>> net (for nasm I think) where people were thunking to real mode and
>> back to protected mode in a single assembly file, and they could use
>> native mnemonics for each part. (They just switched the assembler's
>> mode in sync with execution modes.)
> 
> Unfortunately the llvm assembler does not support 16-bit mode :(, and we
> try to keep the .S assembly common….
> 
> So it is possible, but then we have to add a big #ifdef for llvm/clang
> to use the .byte hackery to make that work. 
> 
> Given the thrash on these 2 files, maybe it worth doing the GNU native
> mnemonics version to get things working and then porting that back to
> llvm after it is stable? I can help with llvm/clang/Xcode related issues
> and porting.

Progress! :)

Please see the attached patches. They are just proof of concept, but I'm
getting "aaabbbccc".

And it's not a KVM problem, so I'm removing the KVM list from the
address list. If it would be polite I can send a thread-closer to that
list separately. (Paolo?)

Thanks!
Laszlo
From 9da03de536b0d809c8567a62da89565ddbb570b0 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <ler...@redhat.com>
Date: Thu, 5 Dec 2013 17:51:18 +0100
Subject: [PATCH 1/3] S3ResumeBootOs(): debug dump GDT before calling
 AsmTransferControl()

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c | 74 +++++++++++++++++++++++
 1 file changed, 74 insertions(+)

diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c 
b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index 6aa3bbc..494592e 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -546,10 +546,84 @@ S3ResumeBootOs (
         );
     }
   } else {
+    IA32_DESCRIPTOR    Desc;
+    IA32_GDT           *Entry;
+    STATIC CONST CHAR8 * CONST Types[] = {
+      "D RO",
+      "D RO A",
+      "D RW",
+      "D RW A",
+      "D RO down",
+      "D RO down A",
+      "D RW down",
+      "D RW down A",
+      "C EO",
+      "C EO A",
+      "C ER",
+      "C ER A",
+      "C EO conf",
+      "C EO conf A",
+      "C ER conf",
+      "C ER conf A"
+    };
+    STATIC CONST CHAR8 * CONST System[] = {
+      "system",
+      "code/data",
+    };
+    STATIC CONST CHAR8 * CONST Gran[] = {
+      "1B",
+      "4KB"
+    };
+
+    ZeroMem (&Desc, sizeof Desc);
+
     //
     // 16bit Realmode waking vector
     //
     DEBUG (( EFI_D_ERROR, "Transfer to 16bit OS waking vector - %x\r\n", 
(UINTN)Facs->FirmwareWakingVector));
+    DEBUG ((DEBUG_VERBOSE, "%a: CS=0x%04x DS=0x%04x ES=0x%04x FS=0x%04x "
+      "GS=0x%04x SS=0x%04x, interrupts %a\n",
+      __FUNCTION__,
+      AsmReadCs(),
+      AsmReadDs(),
+      AsmReadEs(),
+      AsmReadFs(),
+      AsmReadGs(),
+      AsmReadSs(),
+      GetInterruptState () ? "enabled" : "disabled"));
+
+    AsmReadGdtr (&Desc);
+    DEBUG ((DEBUG_VERBOSE, "%a: Desc.Limit=0x%04x\n", __FUNCTION__,
+      Desc.Limit));
+    Entry = (IA32_GDT *) Desc.Base;
+    while ((UINTN) Entry < Desc.Base + (Desc.Limit + 1)) {
+      DEBUG ((DEBUG_VERBOSE,
+        "0x%04Lx: 0x%016Lx: "
+        "Base=0x%08x "
+        "Limit=0x%05x "
+        "Type=0x%x (%-11a) "
+        "S=0x%x (%-9a) "
+        "DPL=0x%x "
+        "Present=%d "
+        "Avail=%d "
+        "64-bitC=%d "
+        "D/B=%d "
+        "LimitGran=0x%x (%-3a)\n",
+        (UINT64) Entry - Desc.Base, Entry->Uint64,
+        Entry->Bits.BaseLow  | (Entry->Bits.BaseMid << 16) | ((UINT32) 
Entry->Bits.BaseHigh << 24),
+        Entry->Bits.LimitLow | (Entry->Bits.LimitHigh << 16),
+        Entry->Bits.Type, Types[Entry->Bits.Type],
+        Entry->Bits.System, System[Entry->Bits.System],
+        Entry->Bits.Dpl,
+        Entry->Bits.Present,
+        Entry->Bits.Software,
+        Entry->Bits.Reserved,
+        Entry->Bits.DefaultSize,
+        Entry->Bits.Granularity, Gran[Entry->Bits.Granularity]
+        ));
+      ++Entry;
+    }
+
     AsmTransferControl (Facs->FirmwareWakingVector, 0x0);
   }
 
-- 
1.8.3.1

From bf9b478244c3786b044c03b062e0337d0342bebf Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <ler...@redhat.com>
Date: Thu, 5 Dec 2013 19:45:06 +0100
Subject: [PATCH 2/3] annotate segments and rewrite trampoline naively

Also, 16-bit segments must have a limit granularity of 1 byte, rather than
4 KB. Change those two GDT entries accordingly.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c  |  23 ++++-
 .../Acpi/BootScriptExecutorDxe/X64/S3Asm.S         | 102 +++++++++++++++++----
 2 files changed, 106 insertions(+), 19 deletions(-)

diff --git a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c 
b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
index 494592e..97cbb1c 100644
--- a/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
+++ b/UefiCpuPkg/Universal/Acpi/S3Resume2Pei/S3Resume.c
@@ -235,11 +235,30 @@ GLOBAL_REMOVE_IF_UNREFERENCED IA32_GDT mGdtEntries[] = {
 /* selector { Global Segment Descriptor                              } */
 /* 0x00 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
 /* 0x08 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
+//
+// 32-bit code:
+//
 /* 0x10 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
+
+//
+// 32-bit data:
+//
 /* 0x18 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 1,  1,  0}},
 /* 0x20 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
-/* 0x28 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
-/* 0x30 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 0,  1,  0}},
+
+//
+// 16-bit code (segment limit granularity = 1 byte):
+//
+/* 0x28 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  0, 0,  0,  0}},
+
+//
+// 16-bit data (segment limit granularity = 1 byte):
+//
+/* 0x30 */  {{0xFFFF, 0,  0,  0x3,  1,  0,  1,  0xF,  0,  0, 0,  0,  0}},
+
+//
+// 64-bit code:
+//
 /* 0x38 */  {{0xFFFF, 0,  0,  0xB,  1,  0,  1,  0xF,  0,  1, 0,  1,  0}},
 /* 0x40 */  {{0,      0,  0,  0,    0,  0,  0,  0,    0,  0, 0,  0,  0}},
 };
diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S 
b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
index e59fd04..a70faa8 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/X64/S3Asm.S
@@ -16,10 +16,20 @@
 
 ASM_GLOBAL ASM_PFX(AsmTransferControl)
 ASM_PFX(AsmTransferControl):
+.code64
     # rcx S3WakingVector    :DWORD
     # rdx AcpiLowMemoryBase :DWORD
+
+    # interrupts are disabled
+    # DS=ES=FS=GS=SS=0x18 (32-bit data)
+
+    # save current GDTR value (10 bytes) for reloading in 32-bit mode
+    sgdt gdt(%rip)
+
+    # 9.8.5.4 Switching Out of IA-32e Mode Operation; SDM Vol3A
+    # we're switching to compat mode here by selecting CS=0x10
     lea   _AsmTransferControl_al_0000(%rip), %eax 
-    movq  $0x2800000000, %r8 
+    movq  $0x1000000000, %r8 
     orq   %r8, %rax
     pushq %rax
     shrd  $20, %ecx, %ebx
@@ -27,29 +37,87 @@ ASM_PFX(AsmTransferControl):
     movw  %cx, %bx
     movl  %ebx, jmp_addr(%rip) 
     lret
+
+gdt:
+    .word 0 # limit
+    .quad 0 # base
+
 _AsmTransferControl_al_0000:
-    .byte    0x0b8, 0x30, 0      # mov ax, 30h as selector
-    movl  %eax, %ds
-    movl  %eax, %es
-    movl  %eax, %fs
-    movl  %eax, %gs
-    movl  %eax, %ss
-    movq  %cr0, %rax
-    movq  %cr4, %rbx
-    .byte    0x66
-    andl  $0x7ffffffe, %eax 
-    andb  $0xdf, %bl 
-    movq  %rax, %cr0
-    .byte    0x66
-    movl  $0x0c0000080, %ecx 
+.code32
+    # at this point we have IA-32e Paging:
+    # CR0.PG=1, CR4.PAE=1, IA32_EFER.LME=1
+    # first we must clear CR0.PG; see 4.1.2 in SDM Vol3A
+    movl  %cr0, %eax
+    andl  $0x7fffffff, %eax
+    movl  %eax, %cr0
+
+    # CR0.PG=0, CR4.PAE=1, IA32_EFER.LME=1
+    # now clear CR4.PAE
+    movl  %cr4, %ebx
+    andb  $0xdf, %bl
+    movl  %ebx, %cr4
+
+    # CR0.PG=0, CR4.PAE=0, IA32_EFER.LME=1
+    # clear IA32_EFER.LME
+    movl  $0x0c0000080, %ecx
     rdmsr
     andb  $0xfe, %ah 
     wrmsr
-    movq  %rbx, %cr4
-    .byte    0x0ea              # jmp far jmp_addr
+
+    # CR0.PG=0, CR4.PAE=0, IA32_EFER.LME=0, paging has been turned off
+    # clear CR3 to flush TLB (9.9.2)
+    movl $0, %eax
+    movl %eax, %cr3
+
+    # reload GDTR with 6-byte operand pointing to the same GDT
+    # current selectors remain valid:CS=0x10, DS=ES=FS=GS=SS=0x18
+    lgdt gdt
+
+    # print three "a" characters to the qemu debug port
+    movw $0x402, %dx
+    movb $0x61, %al
+    outb %al, %dx
+    outb %al, %dx
+    outb %al, %dx
+
+    # new CS=0x28 switches to 16-bit protected mode
+    leal _AsmTransferControl_al_0001, %eax
+    pushl $0x28
+    pushl %eax
+    lret
+
+_AsmTransferControl_al_0001:
+.code16
+    # print three "b" characters to the qemu debug port
+    movb $0x62, %al
+    outb %al, %dx
+    outb %al, %dx
+    outb %al, %dx
+
+    # set 16-bit data segments
+    movw  $0x30, %ax
+    movw  %ax, %ds
+    movw  %ax, %es
+    movw  %ax, %fs
+    movw  %ax, %gs
+    movw  %ax, %ss
+
+    # enter real mode by clearing CR0.PE
+    movl   %cr0, %eax
+    andl   $0xfffffffe, %eax
+    movl   %eax, %cr0
+
+    # print three "c" characters to the qemu debug port
+    movb $0x63, %al
+    outb %al, %dx
+    outb %al, %dx
+    outb %al, %dx
+
+    .byte  0xea # jmp far jmp_addr
 jmp_addr:
     .long    0
 
+.code64
 ASM_GLOBAL ASM_PFX(AsmTransferControl32)
 ASM_PFX(AsmTransferControl32):
     # S3WakingVector    :DWORD
-- 
1.8.3.1

From aae435f5f49a77a040583baf6a5bd5f3a5ed1101 Mon Sep 17 00:00:00 2001
From: Laszlo Ersek <ler...@redhat.com>
Date: Fri, 6 Dec 2013 03:41:41 +0100
Subject: [PATCH 3/3] it wouldn't hurt to keep 16-bit code under 1MB!

BootScriptExecutorDxe is loaded during the 64-bit DXE phase. When the
DXE_SMM_READY_TO_LOCK protocol installation notification is triggered,
BootScriptExecutorDxe finds its own original image in the firmware, and
reloads and relocates it to reserved memory.

A callback point into this relocated image is saved in SMRAM / LockBox.

S3Resume2Pei retrieves the entry point from the lockbox, and calls the
callback. The resume trampoline code, part of which must run as 16-bit
code, is part of the relocated BootScriptExecutorDxe image. So, it
wouldn't hurt if BootScriptExecutorDxe relocated / stashed itself during
DXE into such  reserved memory where the 16-bit code would have a chance
to run, when called from PEI after resume.

Of course we wreak havoc in the OS's low memory, but we're at least
choking on the last jump now!

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Laszlo Ersek <ler...@redhat.com>
---
 MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c 
b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
index 651a9de..0e1b59b 100644
--- a/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
+++ b/MdeModulePkg/Universal/Acpi/BootScriptExecutorDxe/ScriptExecute.c
@@ -267,7 +267,7 @@ ReadyToLockEventNotify (
   Status = PeCoffLoaderGetImageInfo (&ImageContext);
   ASSERT_EFI_ERROR (Status);
   Pages = EFI_SIZE_TO_PAGES(BufferSize + ImageContext.SectionAlignment);
-  FfsBuffer = 0xFFFFFFFF;
+  FfsBuffer = 0xFFFFF;
   Status = gBS->AllocatePages (
                   AllocateMaxAddress,
                   EfiReservedMemoryType,
-- 
1.8.3.1

------------------------------------------------------------------------------
Sponsored by Intel(R) XDK 
Develop, test and display web and hybrid apps with a single code base.
Download it for free now!
http://pubads.g.doubleclick.net/gampad/clk?id=111408631&iu=/4140/ostg.clktrk
_______________________________________________
edk2-devel mailing list
edk2-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/edk2-devel

Reply via email to