mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 19:00:27 +00:00
[metal] Copy program pages to extended memory at startup
This commit is contained in:
parent
aee50b1327
commit
e4b5fb76e4
6 changed files with 56 additions and 19 deletions
43
ape/ape.S
43
ape/ape.S
|
@ -1147,10 +1147,10 @@ sconf: .short 1843200/*hz*/ / 16/*wut*/ / 9600/*baud*/
|
||||||
|
|
||||||
// Global Descriptor Table
|
// Global Descriptor Table
|
||||||
.align 8
|
.align 8
|
||||||
_gdtrphy:
|
_gdtrlo:
|
||||||
.short 2f-1f-1 # table byte length
|
.short 2f-1f-1 # table byte length
|
||||||
.long REAL(1f) # table address (physical space)
|
.long REAL(1f) # table address (base memory space)
|
||||||
.endobj _gdtrphy,global,hidden
|
.endobj _gdtrlo,global,hidden
|
||||||
_gdtr:
|
_gdtr:
|
||||||
.short 2f-1f-1 # table byte length
|
.short 2f-1f-1 # table byte length
|
||||||
.quad 1f # table address (final virtual space)
|
.quad 1f # table address (final virtual space)
|
||||||
|
@ -1263,6 +1263,7 @@ longmodeloader:
|
||||||
call lcheck
|
call lcheck
|
||||||
call a20
|
call a20
|
||||||
call e820
|
call e820
|
||||||
|
call cpyhi
|
||||||
call pinit
|
call pinit
|
||||||
call golong
|
call golong
|
||||||
.endfn longmodeloader
|
.endfn longmodeloader
|
||||||
|
@ -1405,6 +1406,32 @@ a20: cli
|
||||||
5: ret
|
5: ret
|
||||||
.endfn a20
|
.endfn a20
|
||||||
|
|
||||||
|
// Copies program pages loaded into base memory, to extended memory.
|
||||||
|
cpyhi: push %ds
|
||||||
|
push %es
|
||||||
|
cli
|
||||||
|
lgdt REAL(_gdtrlo)
|
||||||
|
mov %cr0,%eax
|
||||||
|
or $CR0_PE,%al
|
||||||
|
mov %eax,%cr0
|
||||||
|
jmp 0f
|
||||||
|
0: pushpop GDT_LEGACY_DATA,%ds
|
||||||
|
push %ds
|
||||||
|
pop %es
|
||||||
|
mov $IMAGE_BASE_REAL,%esi
|
||||||
|
mov $IMAGE_BASE_PHYSICAL,%edi
|
||||||
|
mov $v_ape_realdwords,%ecx
|
||||||
|
cld
|
||||||
|
rep movsl %ds:(%esi),%es:(%edi)
|
||||||
|
and $~CR0_PE,%al
|
||||||
|
mov %eax,%cr0
|
||||||
|
jmp 1f
|
||||||
|
1: sti
|
||||||
|
pop %es
|
||||||
|
pop %ds
|
||||||
|
ret
|
||||||
|
.endfn cpyhi
|
||||||
|
|
||||||
// Initializes long mode paging.
|
// Initializes long mode paging.
|
||||||
pinit: push %ds
|
pinit: push %ds
|
||||||
push %es
|
push %es
|
||||||
|
@ -1449,7 +1476,7 @@ golong: cli
|
||||||
rdmsr
|
rdmsr
|
||||||
or $EFER_LME|EFER_SCE|EFER_NXE,%eax
|
or $EFER_LME|EFER_SCE|EFER_NXE,%eax
|
||||||
wrmsr
|
wrmsr
|
||||||
lgdt REAL(_gdtrphy)
|
lgdt REAL(_gdtrlo)
|
||||||
mov %cr0,%eax
|
mov %cr0,%eax
|
||||||
or $CR0_PE|CR0_PG|CR0_MP,%eax
|
or $CR0_PE|CR0_PG|CR0_MP,%eax
|
||||||
and $~CR0_EM,%eax
|
and $~CR0_EM,%eax
|
||||||
|
@ -1459,7 +1486,9 @@ golong: cli
|
||||||
|
|
||||||
// Long mode is long.
|
// Long mode is long.
|
||||||
.code64
|
.code64
|
||||||
long: xor %eax,%eax
|
long: movabs $BANE+PHYSICAL(0f),%rax
|
||||||
|
jmp *%rax
|
||||||
|
0: xor %eax,%eax
|
||||||
mov $GDT_LONG_DATA,%al
|
mov $GDT_LONG_DATA,%al
|
||||||
mov %eax,%ds
|
mov %eax,%ds
|
||||||
mov %eax,%ss
|
mov %eax,%ss
|
||||||
|
@ -1478,7 +1507,8 @@ long: xor %eax,%eax
|
||||||
push %rbp
|
push %rbp
|
||||||
mov $mm,%rdi
|
mov $mm,%rdi
|
||||||
mov %cr3,%rsi
|
mov %cr3,%rsi
|
||||||
mov $IMAGE_BASE_REAL,%edx
|
mov $IMAGE_BASE_PHYSICAL,%edx
|
||||||
|
lea v_ape_realbytes(%rdx),%ecx
|
||||||
call __map_phdrs
|
call __map_phdrs
|
||||||
push $0x037f
|
push $0x037f
|
||||||
fldcw (%rsp)
|
fldcw (%rsp)
|
||||||
|
@ -1609,6 +1639,7 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||||
.ldsvar _end
|
.ldsvar _end
|
||||||
.ldsvar _etext
|
.ldsvar _etext
|
||||||
.ldsvar v_ape_realsectors
|
.ldsvar v_ape_realsectors
|
||||||
|
.ldsvar v_ape_realbytes
|
||||||
.ldsvar v_ape_highsectors
|
.ldsvar v_ape_highsectors
|
||||||
.ldsvar ape_idata_ro
|
.ldsvar ape_idata_ro
|
||||||
.ldsvar ape_pad_rodata
|
.ldsvar ape_pad_rodata
|
||||||
|
|
|
@ -566,7 +566,8 @@ SHSTUB2(ape_loader_dd_count,
|
||||||
HIDDEN(v_ape_realsectors =
|
HIDDEN(v_ape_realsectors =
|
||||||
MIN(0x70000 - IMAGE_BASE_REAL,
|
MIN(0x70000 - IMAGE_BASE_REAL,
|
||||||
ROUNDUP(RVA(_tdata_end), 512)) / 512);
|
ROUNDUP(RVA(_tdata_end), 512)) / 512);
|
||||||
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
|
HIDDEN(v_ape_realbytes = v_ape_realsectors * 512);
|
||||||
|
HIDDEN(v_ape_realdwords = v_ape_realsectors * (512 / 4));
|
||||||
HIDDEN(v_ape_highsectors =
|
HIDDEN(v_ape_highsectors =
|
||||||
(ROUNDUP(RVA(_tdata_end), 512) / 512) - v_ape_realsectors);
|
(ROUNDUP(RVA(_tdata_end), 512) / 512) - v_ape_realsectors);
|
||||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||||
|
|
|
@ -68,7 +68,7 @@ textstartup noasan void InitializeMetalFile(void) {
|
||||||
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
|
MAP_SHARED_linux | MAP_ANONYMOUS_linux, -1, 0);
|
||||||
copied_base = dm.addr;
|
copied_base = dm.addr;
|
||||||
_npassert(copied_base != (void *)-1);
|
_npassert(copied_base != (void *)-1);
|
||||||
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_REAL), size);
|
memcpy(copied_base, (void *)(BANE + IMAGE_BASE_PHYSICAL), size);
|
||||||
__ape_com_base = copied_base;
|
__ape_com_base = copied_base;
|
||||||
__ape_com_size = size;
|
__ape_com_size = size;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
#include "libc/runtime/runtime.h"
|
#include "libc/runtime/runtime.h"
|
||||||
|
|
||||||
|
#define INVERT(x) (BANE + PHYSICAL(x))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocates new page of physical memory.
|
* Allocates new page of physical memory.
|
||||||
*/
|
*/
|
||||||
|
@ -53,7 +55,7 @@ noasan texthead uint64_t __new_page(struct mman *mm) {
|
||||||
}
|
}
|
||||||
while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) {
|
while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) {
|
||||||
if (++mm->pdpi == mm->e820n) return 0;
|
if (++mm->pdpi == mm->e820n) return 0;
|
||||||
mm->pdp = mm->e820[mm->pdpi].addr;
|
mm->pdp = MAX(mm->pdp, mm->e820[mm->pdpi].addr);
|
||||||
}
|
}
|
||||||
p = mm->pdp;
|
p = mm->pdp;
|
||||||
mm->pdp += 4096;
|
mm->pdp += 4096;
|
||||||
|
@ -84,7 +86,7 @@ noasan textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t,
|
||||||
/**
|
/**
|
||||||
* Sorts, rounds, and filters BIOS memory map.
|
* Sorts, rounds, and filters BIOS memory map.
|
||||||
*/
|
*/
|
||||||
static noasan textreal void __normalize_e820(struct mman *mm) {
|
static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
|
||||||
uint64_t a, b;
|
uint64_t a, b;
|
||||||
uint64_t x, y;
|
uint64_t x, y;
|
||||||
unsigned i, j, n;
|
unsigned i, j, n;
|
||||||
|
@ -107,7 +109,8 @@ static noasan textreal void __normalize_e820(struct mman *mm) {
|
||||||
}
|
}
|
||||||
mm->e820[j] = mm->e820[i];
|
mm->e820[j] = mm->e820[i];
|
||||||
}
|
}
|
||||||
mm->pdp = MAX(0x80000, mm->e820[0].addr);
|
top = ROUNDUP(top, 4096);
|
||||||
|
mm->pdp = MAX(top, mm->e820[0].addr);
|
||||||
mm->pdpi = 0;
|
mm->pdpi = 0;
|
||||||
mm->e820n = n;
|
mm->e820n = n;
|
||||||
}
|
}
|
||||||
|
@ -155,7 +158,8 @@ static noasan textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) {
|
||||||
: "i"(offsetof(type, member))); \
|
: "i"(offsetof(type, member))); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t) {
|
noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
||||||
|
uint64_t top) {
|
||||||
export_offsetof(struct mman, pc_drive_base_table);
|
export_offsetof(struct mman, pc_drive_base_table);
|
||||||
export_offsetof(struct mman, pc_drive_last_sector);
|
export_offsetof(struct mman, pc_drive_last_sector);
|
||||||
export_offsetof(struct mman, pc_drive_last_head);
|
export_offsetof(struct mman, pc_drive_last_head);
|
||||||
|
@ -170,21 +174,22 @@ noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t) {
|
||||||
export_offsetof(struct mman, pc_video_framebuffer_size);
|
export_offsetof(struct mman, pc_video_framebuffer_size);
|
||||||
export_offsetof(struct mman, pc_video_curs_info);
|
export_offsetof(struct mman, pc_video_curs_info);
|
||||||
export_offsetof(struct mman, pc_video_char_height);
|
export_offsetof(struct mman, pc_video_char_height);
|
||||||
__normalize_e820(mm);
|
__normalize_e820(mm, top);
|
||||||
__invert_memory(mm, pml4t);
|
__invert_memory(mm, pml4t);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps APE-defined ELF program headers into memory and clears BSS.
|
* Maps APE-defined ELF program headers into memory and clears BSS.
|
||||||
*/
|
*/
|
||||||
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b) {
|
noasan textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b,
|
||||||
|
uint64_t top) {
|
||||||
struct Elf64_Phdr *p;
|
struct Elf64_Phdr *p;
|
||||||
uint64_t i, f, v, m, *e;
|
uint64_t i, f, v, m, *e;
|
||||||
extern char ape_phdrs[] __attribute__((__weak__));
|
extern char ape_phdrs[] __attribute__((__weak__));
|
||||||
extern char ape_phdrs_end[] __attribute__((__weak__));
|
extern char ape_phdrs_end[] __attribute__((__weak__));
|
||||||
__setup_mman(mm, pml4t);
|
__setup_mman(mm, pml4t, top);
|
||||||
for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0;
|
for (p = (struct Elf64_Phdr *)INVERT(ape_phdrs), m = 0;
|
||||||
p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) {
|
p < (struct Elf64_Phdr *)INVERT(ape_phdrs_end); ++p) {
|
||||||
if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) {
|
if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) {
|
||||||
f = PAGE_RSRV | PAGE_U;
|
f = PAGE_RSRV | PAGE_U;
|
||||||
if (p->p_flags & PF_W)
|
if (p->p_flags & PF_W)
|
||||||
|
|
|
@ -135,7 +135,7 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
|
||||||
pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW;
|
pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW;
|
||||||
pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW;
|
pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW;
|
||||||
pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW;
|
pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW;
|
||||||
__map_phdrs(mm, pml4t, 1024 * 1024);
|
__map_phdrs(mm, pml4t, 1024 * 1024, 1024 * 1024 + (_end - _base));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Asks UEFI to handover control?
|
* Asks UEFI to handover control?
|
||||||
|
|
|
@ -188,7 +188,7 @@ uint64_t __clear_page(uint64_t);
|
||||||
uint64_t __new_page(struct mman *);
|
uint64_t __new_page(struct mman *);
|
||||||
void __invert_memory_area(struct mman *, uint64_t *, uint64_t, uint64_t,
|
void __invert_memory_area(struct mman *, uint64_t *, uint64_t, uint64_t,
|
||||||
uint64_t);
|
uint64_t);
|
||||||
void __map_phdrs(struct mman *, uint64_t *, uint64_t);
|
void __map_phdrs(struct mman *, uint64_t *, uint64_t, uint64_t);
|
||||||
|
|
||||||
forceinline unsigned char inb(unsigned short port) {
|
forceinline unsigned char inb(unsigned short port) {
|
||||||
unsigned char al;
|
unsigned char al;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue