mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-08 19:00:27 +00:00
[metal] Load program pages beyond 1st 440 KiB to extended memory
o//examples/hellolua.com now runs correctly under QEMU (in legacy BIOS mode).
This commit is contained in:
parent
6da7709fb8
commit
771566c8f8
4 changed files with 104 additions and 20 deletions
106
ape/ape.S
106
ape/ape.S
|
@ -261,6 +261,9 @@ pc: cld
|
||||||
xor %dh,%dh # current head
|
xor %dh,%dh # current head
|
||||||
mov $v_ape_realsectors,%di # total sectors
|
mov $v_ape_realsectors,%di # total sectors
|
||||||
3: call pcread
|
3: call pcread
|
||||||
|
mov %es,%si # addr += 512
|
||||||
|
add $512>>4,%si
|
||||||
|
mov %si,%es
|
||||||
dec %di
|
dec %di
|
||||||
jnz 3b
|
jnz 3b
|
||||||
6: ljmp $0,$REAL(realmodeloader)
|
6: ljmp $0,$REAL(realmodeloader)
|
||||||
|
@ -349,6 +352,7 @@ dsknfo: push %bx
|
||||||
pop %ds
|
pop %ds
|
||||||
xchg %bx,%ax
|
xchg %bx,%ax
|
||||||
stosw #→ pc_drive_type, pc_drive_last_sector
|
stosw #→ pc_drive_type, pc_drive_last_sector
|
||||||
|
scasb
|
||||||
xchg %cx,%ax
|
xchg %cx,%ax
|
||||||
stosw #→ pc_drive_last_cylinder
|
stosw #→ pc_drive_last_cylinder
|
||||||
xchg %dx,%ax
|
xchg %dx,%ax
|
||||||
|
@ -387,9 +391,6 @@ pcread: push %ax
|
||||||
pop %cx
|
pop %cx
|
||||||
pop %ax
|
pop %ax
|
||||||
jc 9f
|
jc 9f
|
||||||
mov %es,%si # addr += 512
|
|
||||||
add $512>>4,%si
|
|
||||||
mov %si,%es
|
|
||||||
inc %al # ++sector
|
inc %al # ++sector
|
||||||
cmp mm+"struct mman::pc_drive_last_sector",%al
|
cmp mm+"struct mman::pc_drive_last_sector",%al
|
||||||
jbe 2f
|
jbe 2f
|
||||||
|
@ -1196,6 +1197,7 @@ _gdt:
|
||||||
the default mode of operation on modern cpus */
|
the default mode of operation on modern cpus */
|
||||||
|
|
||||||
realmodeloader:
|
realmodeloader:
|
||||||
|
call lhinit
|
||||||
call rlinit
|
call rlinit
|
||||||
call sinit4
|
call sinit4
|
||||||
.optfn _start16
|
.optfn _start16
|
||||||
|
@ -1203,6 +1205,25 @@ realmodeloader:
|
||||||
call longmodeloader
|
call longmodeloader
|
||||||
.endfn realmodeloader
|
.endfn realmodeloader
|
||||||
|
|
||||||
|
// Prepares to later load parts of the program that are not loaded yet.
|
||||||
|
//
|
||||||
|
// @param al next sector number
|
||||||
|
// @param cx next cylinder number
|
||||||
|
// @param dh next head number
|
||||||
|
// @param dl drive number
|
||||||
|
// @clob ax, cx, es, di
|
||||||
|
lhinit: cmp $0x40,%dl
|
||||||
|
je 9f
|
||||||
|
pushpop 0,%es
|
||||||
|
mov $mm+"struct mman::pc_drive_next_sector",%di
|
||||||
|
cld
|
||||||
|
stosb #→ pc_drive_next_sector
|
||||||
|
xchg %ax,%cx
|
||||||
|
stosw #→ pc_drive_next_cylinder
|
||||||
|
mov %dh,%al
|
||||||
|
stosb #→ pc_drive_next_head
|
||||||
|
9: ret
|
||||||
|
|
||||||
.section .sort.text.real.init.1,"ax",@progbits
|
.section .sort.text.real.init.1,"ax",@progbits
|
||||||
.type rlinit,@function
|
.type rlinit,@function
|
||||||
rlinit: .previous/*
|
rlinit: .previous/*
|
||||||
|
@ -1264,6 +1285,7 @@ longmodeloader:
|
||||||
call a20
|
call a20
|
||||||
call e820
|
call e820
|
||||||
call cpyhi
|
call cpyhi
|
||||||
|
call loadhi
|
||||||
call pinit
|
call pinit
|
||||||
call golong
|
call golong
|
||||||
.endfn longmodeloader
|
.endfn longmodeloader
|
||||||
|
@ -1407,7 +1429,27 @@ a20: cli
|
||||||
.endfn a20
|
.endfn a20
|
||||||
|
|
||||||
// Copies program pages loaded into base memory, to extended memory.
|
// Copies program pages loaded into base memory, to extended memory.
|
||||||
cpyhi: push %ds
|
//
|
||||||
|
// @clob esi, edi
|
||||||
|
cpyhi: push %es
|
||||||
|
movpp %ds,%es
|
||||||
|
call unreal
|
||||||
|
mov $IMAGE_BASE_REAL,%esi
|
||||||
|
mov $IMAGE_BASE_PHYSICAL,%edi
|
||||||
|
mov $v_ape_realdwords,%ecx
|
||||||
|
cld
|
||||||
|
rep movsl %ds:(%esi),%es:(%edi)
|
||||||
|
sti
|
||||||
|
pop %es
|
||||||
|
ret
|
||||||
|
.endfn cpyhi
|
||||||
|
|
||||||
|
// Disables interrupts and switches to "unreal mode".
|
||||||
|
//
|
||||||
|
// @return ds, es have same base addresses as before but can access
|
||||||
|
// 4 GiB of memory
|
||||||
|
// @clob eax
|
||||||
|
unreal: push %ds
|
||||||
push %es
|
push %es
|
||||||
cli
|
cli
|
||||||
lgdt REAL(_gdtrlo)
|
lgdt REAL(_gdtrlo)
|
||||||
|
@ -1416,26 +1458,58 @@ cpyhi: push %ds
|
||||||
mov %eax,%cr0
|
mov %eax,%cr0
|
||||||
jmp 0f
|
jmp 0f
|
||||||
0: pushpop GDT_LEGACY_DATA,%ds
|
0: pushpop GDT_LEGACY_DATA,%ds
|
||||||
push %ds
|
movpp %ds,%es
|
||||||
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
|
and $~CR0_PE,%al
|
||||||
mov %eax,%cr0
|
mov %eax,%cr0
|
||||||
jmp 1f
|
jmp 1f
|
||||||
1: sti
|
1: pop %es
|
||||||
pop %es
|
|
||||||
pop %ds
|
pop %ds
|
||||||
ret
|
ret
|
||||||
.endfn cpyhi
|
|
||||||
|
// Reads any remaining program pages into memory which have not yet
|
||||||
|
// been read by the boot sector.
|
||||||
|
//
|
||||||
|
// @clob eax, ecx, dx, esi, edi, bp
|
||||||
|
loadhi: mov $v_ape_highsectors,%bp
|
||||||
|
test %bp,%bp
|
||||||
|
jz 9f
|
||||||
|
mov $mm+"struct mman::pc_drive",%si
|
||||||
|
cld
|
||||||
|
lodsb #← pc_drive
|
||||||
|
xchg %ax,%dx
|
||||||
|
lodsw
|
||||||
|
lodsb #← pc_drive_next_sector
|
||||||
|
test %al,%al
|
||||||
|
jz 9f
|
||||||
|
xchg %ax,%cx
|
||||||
|
lodsw #← pc_drive_next_cylinder
|
||||||
|
xchg %ax,%cx
|
||||||
|
mov (%si),%dh #← pc_drive_next_head
|
||||||
|
push %es
|
||||||
|
#define SEG 0x79000
|
||||||
|
mov $IMAGE_BASE_PHYSICAL+v_ape_realbytes-SEG,%edi
|
||||||
|
push $SEG>>4
|
||||||
|
pop %es
|
||||||
|
0: call pcread
|
||||||
|
push %ax
|
||||||
|
call unreal
|
||||||
|
pop %ax
|
||||||
|
push %cx
|
||||||
|
xor %esi,%esi
|
||||||
|
xor %ecx,%ecx
|
||||||
|
mov $512/4,%cl
|
||||||
|
cld
|
||||||
|
rep movsl %es:(%esi),%es:(%edi)
|
||||||
|
sti
|
||||||
|
pop %cx
|
||||||
|
dec %bp
|
||||||
|
jnz 0b
|
||||||
|
pop %es
|
||||||
|
9: ret
|
||||||
|
|
||||||
// Initializes long mode paging.
|
// Initializes long mode paging.
|
||||||
pinit: push %ds
|
pinit: push %ds
|
||||||
push %es
|
push %es
|
||||||
#define SEG 0x79000
|
|
||||||
mov $SEG>>4,%ax
|
mov $SEG>>4,%ax
|
||||||
mov %ax,%ds
|
mov %ax,%ds
|
||||||
mov %ax,%es
|
mov %ax,%es
|
||||||
|
@ -1507,7 +1581,7 @@ long: movabs $BANE+PHYSICAL(0f),%rax
|
||||||
mov $mm,%rdi
|
mov $mm,%rdi
|
||||||
mov %cr3,%rsi
|
mov %cr3,%rsi
|
||||||
mov $IMAGE_BASE_PHYSICAL,%edx
|
mov $IMAGE_BASE_PHYSICAL,%edx
|
||||||
lea v_ape_realbytes(%rdx),%ecx
|
lea v_ape_allbytes(%rdx),%ecx
|
||||||
call __map_phdrs
|
call __map_phdrs
|
||||||
push $0x037f
|
push $0x037f
|
||||||
fldcw (%rsp)
|
fldcw (%rsp)
|
||||||
|
|
|
@ -568,8 +568,9 @@ HIDDEN(v_ape_realsectors =
|
||||||
ROUNDUP(RVA(_tdata_end), 512)) / 512);
|
ROUNDUP(RVA(_tdata_end), 512)) / 512);
|
||||||
HIDDEN(v_ape_realbytes = v_ape_realsectors * 512);
|
HIDDEN(v_ape_realbytes = v_ape_realsectors * 512);
|
||||||
HIDDEN(v_ape_realdwords = v_ape_realsectors * (512 / 4));
|
HIDDEN(v_ape_realdwords = v_ape_realsectors * (512 / 4));
|
||||||
HIDDEN(v_ape_highsectors =
|
HIDDEN(v_ape_allsectors = ROUNDUP(RVA(_tdata_end), 512) / 512);
|
||||||
(ROUNDUP(RVA(_tdata_end), 512) / 512) - v_ape_realsectors);
|
HIDDEN(v_ape_allbytes = v_ape_allsectors * 512);
|
||||||
|
HIDDEN(v_ape_highsectors = v_ape_allsectors - v_ape_realsectors);
|
||||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -652,7 +653,7 @@ CHURN(ADDR(.bss));
|
||||||
CHURN(_start);
|
CHURN(_start);
|
||||||
CHURN(ape_phdrs);
|
CHURN(ape_phdrs);
|
||||||
#if SupportsMetal()
|
#if SupportsMetal()
|
||||||
CHURN(v_ape_realsectors);
|
CHURN(v_ape_allsectors);
|
||||||
#endif
|
#endif
|
||||||
#if SupportsXnu()
|
#if SupportsXnu()
|
||||||
CHURN(ape_macho);
|
CHURN(ape_macho);
|
||||||
|
|
|
@ -177,9 +177,13 @@ noasan textreal void __setup_mman(struct mman *mm, uint64_t *pml4t,
|
||||||
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);
|
||||||
|
export_offsetof(struct mman, pc_drive);
|
||||||
export_offsetof(struct mman, e820);
|
export_offsetof(struct mman, e820);
|
||||||
export_offsetof(struct mman, e820_end);
|
export_offsetof(struct mman, e820_end);
|
||||||
export_offsetof(struct mman, bad_idt);
|
export_offsetof(struct mman, bad_idt);
|
||||||
|
export_offsetof(struct mman, pc_drive_next_sector);
|
||||||
|
export_offsetof(struct mman, pc_drive_next_cylinder);
|
||||||
|
export_offsetof(struct mman, pc_drive_next_head);
|
||||||
export_offsetof(struct mman, pc_video_type);
|
export_offsetof(struct mman, pc_video_type);
|
||||||
export_offsetof(struct mman, pc_video_stride);
|
export_offsetof(struct mman, pc_video_stride);
|
||||||
export_offsetof(struct mman, pc_video_width);
|
export_offsetof(struct mman, pc_video_width);
|
||||||
|
|
|
@ -19,7 +19,12 @@ struct mman {
|
||||||
unsigned char pc_drives_attached; /* 0x1d28 */
|
unsigned char pc_drives_attached; /* 0x1d28 */
|
||||||
unsigned char pc_drive_last_head; /* 0x1d29 */
|
unsigned char pc_drive_last_head; /* 0x1d29 */
|
||||||
unsigned char pc_drive; /* 0x1d2a */
|
unsigned char pc_drive; /* 0x1d2a */
|
||||||
char bad_idt[6]; /* 0x1d2b */
|
char bad_idt[2]; /* 0x1d2b — IDTR value for an invalid
|
||||||
|
IDT; really 6 bytes which
|
||||||
|
overlap w/ fields below */
|
||||||
|
unsigned char pc_drive_next_sector; /* 0x1d2d */
|
||||||
|
unsigned short pc_drive_next_cylinder; /* 0x1d2e */
|
||||||
|
unsigned char pc_drive_next_head; /* 0x1d30 */
|
||||||
unsigned char pc_video_type; /* 0x1d31 */
|
unsigned char pc_video_type; /* 0x1d31 */
|
||||||
unsigned short pc_video_stride; /* 0x1d32 — line width, including any
|
unsigned short pc_video_stride; /* 0x1d32 — line width, including any
|
||||||
invisible "pixels" — in
|
invisible "pixels" — in
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue