mirror of
https://github.com/ipxe/ipxe
synced 2026-01-05 03:10:58 +03:00
[librm] Prepare for long-mode memory map
The bulk of the iPXE binary (the .textdata section) is physically relocated at runtime to the top of the 32-bit address space in order to allow space for an OS to be loaded. The relocation is achieved with the assistance of segmentation: we adjust the code and data segment bases so that the link-time addresses remain valid. Segmentation is not available (for normal code and data segments) in long mode. We choose to compile the C code with -mcmodel=kernel and use a link-time address of 0xffffffffeb000000. This choice allows us to identity-map the entirety of the 32-bit address space, and to alias our chosen link-time address to the physical location of our .textdata section. (This requires the .textdata section to always be aligned to a page boundary.) We simultaneously choose to set the 32-bit virtual address segment bases such that the link-time addresses may simply be truncated to 32 bits in order to generate a valid 32-bit virtual address. This allows symbols in .textdata to be trivially accessed by both 32-bit and 64-bit code. There is no (sensible) way in 32-bit assembly code to generate the required R_X86_64_32S relocation records for these truncated symbols. However, subtracting the fixed constant 0xffffffff00000000 has the same effect as truncation, and can be represented in a standard R_X86_64_32 relocation record. We define the VIRTUAL() macro to abstract away this truncation operation, and apply it to all references by 32-bit (or 16-bit) assembly code to any symbols within the .textdata section. We define "virt_offset" for a 64-bit build as "the value to be added to an address within .textdata in order to obtain its physical address". With this definition, the low 32 bits of "virt_offset" can be treated by 32-bit code as functionally equivalent to "virt_offset" in a 32-bit build. We define "text16" and "data16" for a 64-bit build as the physical addresses of the .text16 and .data16 sections. Since a physical address within the 32-bit address space may be used directly as a 64-bit virtual address (thanks to the identity map), this definition provides the most natural access to variables in .text16 and .data16. Note that this requires a minor adjustment in prot_to_real(), which accesses .text16 using 32-bit virtual addresses. Signed-off-by: Michael Brown <mcb30@ipxe.org>
This commit is contained in:
@@ -32,13 +32,13 @@ _virt_to_phys:
|
||||
pushl %ebp
|
||||
|
||||
/* Change return address to a physical address */
|
||||
movl virt_offset, %ebp
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
addl %ebp, 12(%esp)
|
||||
|
||||
/* Switch to physical code segment */
|
||||
cli
|
||||
pushl $PHYSICAL_CS
|
||||
leal 1f(%ebp), %eax
|
||||
leal VIRTUAL(1f)(%ebp), %eax
|
||||
pushl %eax
|
||||
lret
|
||||
1:
|
||||
@@ -78,7 +78,7 @@ _phys_to_virt:
|
||||
|
||||
/* Switch to virtual code segment */
|
||||
cli
|
||||
ljmp $VIRTUAL_CS, $1f
|
||||
ljmp $VIRTUAL_CS, $VIRTUAL(1f)
|
||||
1:
|
||||
/* Reload data segment registers */
|
||||
movl $VIRTUAL_DS, %eax
|
||||
@@ -88,7 +88,7 @@ _phys_to_virt:
|
||||
movl %eax, %gs
|
||||
|
||||
/* Reload stack segment and adjust %esp */
|
||||
movl virt_offset, %ebp
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
movl %eax, %ss
|
||||
subl %ebp, %esp
|
||||
|
||||
@@ -134,7 +134,7 @@ _intr_to_virt:
|
||||
|
||||
/* Reload stack segment and adjust %esp if necessary */
|
||||
je 1f
|
||||
movl virt_offset, %ebp
|
||||
movl VIRTUAL(virt_offset), %ebp
|
||||
movl %eax, %ss
|
||||
subl %ebp, %esp
|
||||
1:
|
||||
|
||||
Reference in New Issue
Block a user