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