diff --git a/Makefile b/Makefile index e9e61b85e..e2c63ea18 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,6 @@ include libc/str/str.mk # │ include third_party/xed/xed.mk # │ include third_party/zlib/zlib.mk # │ include libc/elf/elf.mk # │ -include ape/lib/apelib.mk # │ include ape/ape.mk # │ include libc/fmt/fmt.mk #─┘ include libc/calls/calls.mk #─┐ @@ -173,8 +172,6 @@ include test/libc/time/test.mk include test/libc/stdio/test.mk include test/libc/release/test.mk include test/libc/test.mk -include test/ape/lib/test.mk -include test/ape/test.mk include test/net/http/test.mk include test/net/test.mk include test/tool/build/lib/test.mk @@ -244,7 +241,6 @@ COSMOPOLITAN_OBJECTS = \ LIBC_TIME \ LIBC_ZIPOS \ THIRD_PARTY_ZLIB \ - APE_LIB \ THIRD_PARTY_MUSL \ LIBC_STDIO \ THIRD_PARTY_REGEX \ diff --git a/ape/ape.S b/ape/ape.S index 4c9714258..eedbfb64c 100644 --- a/ape/ape.S +++ b/ape/ape.S @@ -32,17 +32,16 @@ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ │ αcτµαlly pδrταblε εxεcµταblε § program header │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/config.h" -#include "ape/lib/pc.h" #include "ape/macros.internal.h" #include "ape/notice.inc" #include "ape/relocations.h" +#include "libc/dce.h" #include "libc/elf/def.h" #include "libc/macho.internal.h" #include "libc/nexgen32e/uart.internal.h" #include "libc/nexgen32e/vidya.internal.h" #include "libc/nt/pedef.internal.h" -#include "libc/dce.h" +#include "libc/runtime/pc.internal.h" #include "libc/sysv/consts/prot.h" #define USE_SYMBOL_HACK 0 @@ -62,9 +61,6 @@ __ro: .endobj __ro,globl,hidden # ←for gdb readibility .previous .section .rodata.str1.1,"a",@progbits cstr: .endobj cstr,globl,hidden # ←for gdb readibility - .previous - .section .sort.rodata.real.str1.1,"a",@progbits -rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility .previous .section .head,"ax",@progbits @@ -105,7 +101,7 @@ rlstr: .endobj rlstr,globl,hidden # ←for gdb readibility │ αcτµαlly pδrταblε εxεcµταblε § the old technology │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#if SupportsWindows() || SupportsUefi() || SupportsXnu() +#if SupportsWindows() || SupportsMetal() || SupportsXnu() // MZ Literally Executable Header // @@ -131,14 +127,14 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski .ascii "JT" # MZ: OEM identifier .short 0 # MZ: OEM information .org 0x40-4 # MZ: bytes reserved for you -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() .long RVA(ape_pe) # PE: the new technology #else .long 0 #endif .endfn ape_mz,globl,hidden -#else /* !(SupportsWindows() || SupportsUefi() || SupportsXnu()) */ +#else /* !(SupportsWindows() || SupportsMetal() || SupportsXnu()) */ // ELF Literally Executable Header // @@ -168,7 +164,7 @@ ape_mz: .asciz "MZqFpD='\n" # Mark 'Zibo' Joseph Zbikowski .short ape_elf_shnum # 3c: e_shnum .short ape_elf_shstrndx # 3e: e_shstrndx -#endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */ +#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ #if SupportsMetal() @@ -218,17 +214,17 @@ pc: cld .byte 0x0f,0x1f,0207 # nop rdi binbase .short (0x7c00-IMAGE_BASE_VIRTUAL)/512 #endif - mov $REAL_STACK_FRAME>>4,%di # we need a stack - xor %cx,%cx + mov $0x70000>>4,%di # we need a stack + xor %cx,%cx # 0x7f000-0x80000 mov %cx,%es rlstack %di,%cx - push %cs # memcpy() [relocate this page] - pop %ds - call 1f -1: pop %si + push %cs # determine load address + pop %ds # and relocate this code + call 1f # to a way lower address +1: pop %si # and we'll make cs zero sub $RVA(1b),%si mov $IMAGE_BASE_REAL>>4,%ax - push %ax # save real base + push %ax # save IMAGE_BASE_REAL>>4 push %ax pop %es xor %di,%di @@ -238,18 +234,18 @@ pc: cld .byte 0x0f,0x1f,0207 # nop rdi binbase .short (IMAGE_BASE_REAL-0x7c00)/512 #endif - ljmp $0,$REAL(1f) # longjmp() -1: mov %cx,%ds # %ds and %cs are now zero - mov $XLM_SIZE,%cx # memset to clear real bss - mov $XLM_BASE_REAL>>4,%ax + ljmp $0,$REAL(1f) +1: mov %cx,%ds + mov $IMAGE_BASE_REAL-0x0500,%cx # clears bss + mov $0x0500>>4,%ax # struct mman mov %ax,%es xor %ax,%ax xor %di,%di rep stosb - cmp $0x40,%dl # statfs() [disk geometry] + cmp $0x40,%dl je 6f call dsknfo - pop %es # restore real base + pop %es # restore IMAGE_BASE_REAL>>4 mov $1,%al # current sector xor %cx,%cx # current cylinder xor %dh,%dh # current head @@ -257,15 +253,7 @@ pc: cld 3: call pcread dec %di jnz 3b -6: mov $XLM(LOADSTATE),%di # ax,cx,dx,es - stosw - xchg %cx,%ax - stosw - xchg %dx,%ax - stosw - mov %es,%ax - stosw - ljmp $0,$REAL(realmodeloader) +6: ljmp $0,$REAL(realmodeloader) .endfn pc // Determines disk geometry. @@ -326,7 +314,7 @@ dsknfo: push %bx movpp %es,%ds xor %si,%si mov %si,%es - mov $XLM(DRIVE_BASE_TABLE),%si + mov $0x1510,%si # mman::pc_drive_base_table xchg %si,%di movsw #→ headunloadtime, headloadtime movsw #→ shutofftime, bytespersector @@ -379,11 +367,11 @@ pcread: push %ax add $512>>4,%si mov %si,%es inc %al # ++sector - cmp XLM(DRIVE_LAST_SECTOR),%al + cmp 0x151c,%al # mman::pc_drive_last_sector jbe 2f mov $1,%al inc %dh # ++head - cmp XLM(DRIVE_LAST_HEAD),%dh + cmp 0x1520,%dh # mman::pc_drive_last_head jbe 2f xor %dh,%dh inc %cx # ++cylinder @@ -395,6 +383,82 @@ pcread: push %ax jmp pcread .endfn pcread +// Video put string. +// +// @param di is the string +// @clob bp,bx +// @mode real +rvputs: mov %di,%si +0: lodsb + test %al,%al + je 1f + mov $7,%bx # normal mda/cga style page zero + mov $0x0e,%ah # teletype output al cp437 + int $0x10 # vidya service + jmp 0b +1: ret + .endfn rvputs + +// Abnormally halts startup. +// +// @param di message +// @mode real +// @noreturn +rldie: push %di + mov $REAL(str.error),%di + call rvputs + pop %di + call rvputs + mov $REAL(str.crlf),%di + call rvputs +0: rep nop + jmp 0b + .endfn rldie + +// Initializes present PC serial lines. +sinit4: mov $4,%cx + mov $0x400,%si # BDA.COM1 +0: lodsw + test %ax,%ax + jz 1f + push %cx + push %si + xchg %ax,%di + mov $REAL(sconf),%si + call sinit + pop %si + pop %cx +1: loop 0b + ret + .endfn sinit4,global,hidden + +// Initializes Serial Line Communications 8250 UART 16550A +// +// @param word di tty port +// @param char (*{es:,e,r}si)[4] register initial values +// @mode long,legacy,real +// @see www.lammertbies.nl/comm/info/serial-uart.html +sinit: mov %di,%dx + test %dx,%dx + jz 2f + push %dx + push %si + xor %cx,%cx + mov $UART_LCR,%cl + add %cx,%dx + lodsb %ds:(%si),%al + pop %si + or $UART_DLAB,%al + out %al,%dx + pop %dx +1: lodsb %ds:(%si),%al + out %al,%dx + inc %dx + dec %cx + jns 1b +2: ret + .endfn sinit,global,hidden + /*───────────────────────────────────────────────────────────────────────────│─╗ │ αcτµαlly pδrταblε εxεcµταblε § partition table ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ @@ -469,9 +533,7 @@ ape_disk: ╚────────────────────────────────────────────────────────────────────────────│─╝ the bourne executable & linkable format */ -#if SupportsSystemv() - -#if SupportsWindows() || SupportsUefi() || SupportsXnu() +#if SupportsWindows() || SupportsMetal() || SupportsXnu() apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "o=\"$(command -v \"$0\")\"\n" #if SupportsXnu() @@ -526,10 +588,11 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .ascii "fi\n" .ascii "exit $R\n" .endobj apesh -#endif /* SupportsWindows() || SupportsUefi() || SupportsXnu() */ +#endif /* SupportsWindows() || SupportsMetal() || SupportsXnu() */ +#if SupportsSystemv() || SupportsMetal() .section .elf.phdrs,"a",@progbits - .long PT_LOAD # text segment + .long PT_LOAD .long PF_R|PF_X .stub ape_rom_offset,quad .stub ape_rom_vaddr,quad @@ -537,7 +600,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_rom_filesz,quad .stub ape_rom_memsz,quad .stub ape_rom_align,quad - .long PT_LOAD # data segment + .long PT_LOAD .long PF_R|PF_W .stub ape_ram_offset,quad .stub ape_ram_vaddr,quad @@ -545,20 +608,16 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_ram_filesz,quad .stub ape_ram_memsz,quad .stub ape_ram_align,quad -#if SupportsLinux() -// Linux ignores mprotect() and returns 0 without this lool -// It has nothing to do with the stack, which is still exec - .long PT_GNU_STACK # p_type - .long PF_R|PF_W # p_flags - .quad 0 # p_offset - .quad 0 # p_vaddr - .quad 0 # p_paddr - .quad 0 # p_filesz - .quad 0 # p_memsz - .quad 16 # p_align -#endif + .long PT_GNU_STACK + .long PF_R|PF_W + .stub ape_stack_offset,quad + .stub ape_stack_vaddr,quad + .stub ape_stack_paddr,quad + .stub ape_stack_filesz,quad + .stub ape_stack_memsz,quad + .stub ape_stack_align,quad #if SupportsOpenbsd() || SupportsNetbsd() - .long PT_NOTE # notes + .long PT_NOTE .long PF_R .stub ape_note_offset,quad .stub ape_note_vaddr,quad @@ -568,6 +627,7 @@ apesh: .ascii "'\n#'\"\n" # sixth edition shebang .stub ape_note_align,quad #endif .previous +#endif /* SupportsSystemv() || SupportsMetal() */ #if SupportsOpenbsd() .section .note.openbsd.ident,"a",@progbits @@ -597,8 +657,6 @@ netbsd.ident: .previous #endif /* SupportsNetbsd() */ -#endif /* SupportsSystemv() */ - /* ▄▄███▄ ▄▄████████▄ ▄█████████████▄ @@ -812,7 +870,7 @@ PETEXT = 0b01110000000000000000000001100000 PEDATA = 0b11000000000000000000000011000000 PEIMPS = 0b11000000000000000000000001000000 -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() .section .pe.header,"a",@progbits .align __SIZEOF_POINTER__ @@ -832,7 +890,7 @@ ape_pe: .ascin "PE",4 .long 0 # SizeOfUninitializedData .long RVA(ape_pe_entry) # EntryPoint .long 0 # BaseOfCode - .quad IMAGE_BASE_VIRTUAL # ImageBase + .quad ape_pe_base # ImageBase .long 4096 # SectionAlignment .long 4096 # FileAlignment .short v_ntversion # MajorOperatingSystemVersion @@ -846,11 +904,7 @@ ape_pe: .ascin "PE",4 .long RVA(_ehead) # SizeOfHeaders .long 0 # Checksum .short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console -#if SupportsWindows() - .short DLLEXE # DllCharacteristics -#else - .short 0 # DllCharacteristics -#endif + .stub v_ntdllchar,short # DllCharacteristics .quad 0x0000000000100000 # StackReserve .quad 0x00000000000fc000 # StackCommit .quad 0 # HeapReserve @@ -858,12 +912,8 @@ ape_pe: .ascin "PE",4 .long 0 # LoaderFlags .long 16 # NumberOfDirectoryEntries .long 0,0 # ExportsDirectory -#if SupportsWindows() - .long RVA(ape_idata_idt) # ImportsDirectory + .stub ape_idata,long # ImportsDirectory .stub ape_idata_idtsize,long # ImportsDirectorySize -#else - .long 0,0 # ImportsDirectory -#endif .long 0,0 # ResourcesDirectory .long 0,0 # ExceptionsDirectory .long 0,0 # SecurityDirectory @@ -874,12 +924,8 @@ ape_pe: .ascin "PE",4 .long 0,0 # ThreadLocalStorage .long 0,0 # LoadConfigurationDirectory .long 0,0 # BoundImportDirectory -#if SupportsWindows() - .long RVA(ape_idata_iat) # ImportAddressDirectory + .stub ape_idata,long # ImportAddressDirectory .stub ape_idata_iatsize,long # ImportAddressDirectorySize -#else - .long 0,0 # ImportAddressDirectory -#endif .long 0,0 # DelayImportDescriptor .long 0,0 # ComPlusRuntimeHeader .long 0,0 # Reserved @@ -896,7 +942,7 @@ ape_pe: .ascin "PE",4 .long 0 # Line Number Table Offset .short 0 # Relocation Count .short 0 # Line Number Count - .long PETEXT # Flags + .long PETEXT # Flags .previous .section .pe.sections,"a",@progbits @@ -909,10 +955,10 @@ ape_pe: .ascin "PE",4 .long 0 # Line Number Table Offset .short 0 # Relocation Count .short 0 # Line Number Count - .long PEDATA # Flags + .long PEDATA # Flags .previous -#endif /* SupportsWindows() || SupportsUefi() */ +#endif /* SupportsWindows() || SupportsMetal() */ .section .idata.ro.idt.1,"a",@progbits .type ape_idata_idtend,@object @@ -950,13 +996,6 @@ ape_idata_iatend: better code/data separation (.head is rwx[real] rx[long]) */ // NUL-Terminated Strings. -ape.str: -str.ape: - .byte 0xe0,0x63,0xe7,0xe6,0xe0,0x6c,0x6c,0x79 #αcτµαlly - .byte 0x20,0x70,0xeb,0x72,0xe7,0xe0,0x62,0x6c # pδrταbl - .byte 0xee,0x20,0xee,0x78,0xee,0x63,0xe6,0xe7 #ε εxεcµτ - .byte 0xe0,0x62,0x6c,0xee,0x0d,0x0a,0x00 #αblε. - .endobj str.ape str.error: .asciz "error: " .endobj str.error @@ -969,19 +1008,12 @@ str.cpuid: str.oldskool: .asciz "oldskool" .endobj str.oldskool -str.dsknfo: - .asciz "dsknfo" - .endobj str.dsknfo str.e820: .asciz "e820" .endobj str.e820 -str.memory: - .asciz "nomem" - .endobj str.memory str.long: .asciz "nolong" .endobj str.long - .endobj ape.str // Serial Line Configuration (8250 UART 16550) // If it's hacked, it'll at least get hacked very slowly. @@ -1071,8 +1103,8 @@ ape_grub: .align 4 ape_grub_entry: .code32 - cmp $GRUB_EAX,%eax - jne triplf +/ cmp $GRUB_EAX,%eax +/ jne triplf push $0 popf mov $0x40,%dl @@ -1088,18 +1120,12 @@ ape_grub_entry: ╚──────────────────────────────────────────────────────────────────────────────╝ the default mode of operation on modern cpus */ - nop - nop - nop - nop realmodeloader: - call16 rlinit - call16 sinit4 - mov $REAL(str.ape),%di - call16 rvputs + call rlinit + call sinit4 .optfn _start16 - call16 _start16 - call16 longmodeloader + call _start16 + call longmodeloader .endfn realmodeloader .section .sort.text.real.init.1,"ax",@progbits @@ -1112,86 +1138,6 @@ rlinit: .previous/* ret .previous -// Initializes present PC serial lines. -sinit4: mov $4,%cx - mov $kBiosDataAreaXlm+COM1,%si -0: lodsw - test %ax,%ax - jz 1f - push %cx - push %si - xchg %ax,%di - mov $REAL(sconf),%si - call16 sinit - pop %si - pop %cx -1: loop 0b - ret - .endfn sinit4,global,hidden - -// Initializes Serial Line Communications 8250 UART 16550A -// -// @param word di tty port -// @param char (*{es:,e,r}si)[4] register initial values -// @mode long,legacy,real -// @see www.lammertbies.nl/comm/info/serial-uart.html -sinit: mov %di,%dx - test %dx,%dx - jz 2f - push %dx - push %si - xorw %cx,%cx - mov $UART_LCR,%cl - add %cx,%dx - lodsb %ds:(%si),%al - pop %si - or $UART_DLAB,%al - out %al,%dx - pop %dx -1: lodsb %ds:(%si),%al - out %al,%dx - add $1,%dx - sub $1,%cx - jns 1b -2: ret - .endfn sinit,global,hidden - -// Video put string. -// -// @param di is the string -// @mode real -rvputs: push %bp - push %bx - mov %di,%si -0: lodsb - test %al,%al - je 1f - mov $7,%bx # normal mda/cga style page zero - mov $0x0e,%ah # teletype output al cp437 - int $0x10 # vidya service - jmp 0b -1: pop %bx - pop %bp - ret - .endfn rvputs - -// Abnormally halts startup. -// -// @param di message -// @mode real -// @noreturn -rldie: push %di - mov $REAL(str.error),%di - call16 rvputs - pop %di - call16 rvputs - mov $REAL(str.crlf),%di - call16 rvputs - xor %ax,%ax # get keystroke - int $0x16 # keyboard service - call16 triplf - .endfn rldie - /* █ █▒ █ █ █▓▄ █ █ @@ -1239,18 +1185,11 @@ rldie: push %di long mode is long */ longmodeloader: - call16 lcheck - call16 a20 - mov $XLM(E820),%di - mov $XLM_E820_SIZE,%si - call16 e820 - jc 9f - call16 unreal -// call hiload - call16 pinit - call16 golong -9: mov $REAL(str.e820),%ax - call16 rldie + call lcheck + call a20 + call e820 + call pinit + call golong .endfn longmodeloader // Long Mode Hardware Check @@ -1286,35 +1225,25 @@ lcheck: pushf # check for i8086 / i8088 / i80186 jne 10f xor %ax,%ax 1: ret -9: mov $REAL(str.oldskool),%ax +9: mov $REAL(str.oldskool),%di jmp 20f -10: mov $REAL(str.long),%ax +10: mov $REAL(str.long),%di jmp 20f -12: mov $REAL(str.cpuid),%ax - jmp 20f -20: call16 rldie +12: mov $REAL(str.cpuid),%di +20: call rldie .endfn lcheck // Gets memory map from BIOS. -// -// @param di paragraph aligned buffer -// @param si bytes in buffer to fill -// @return number of bytes written or CF on error -// @mode real -e820: push %bp - mov %sp,%bp - pushl $'S'<<24|'M'<<16|'A'<<8|'P' # magic @ -4(%bp) - push %bx - shr $4,%di +e820: mov $0x0510>>4,%di # mman::e820 mov %di,%es xor %edi,%edi # es:di is destination buffer xor %ebx,%ebx # ebx is an api state tracker 1: mov $0xE820,%eax # magic mov $8+8+4+4,%ecx # sizeof(struct SmapEntry) - mov -4(%bp),%edx # magic + mov $0x534d4150,%edx # magic number int $0x15 # ax,bx,cx,dx,di → ax,bx,cx jc 9f # cf = unsupported or abuse - cmp -4(%bp),%eax # more magic means success + cmp %edx,%eax # more magic means success jne 9f test %cx,%cx # discard empty results jz 5f @@ -1324,78 +1253,14 @@ e820: push %bp jnz 5f 4: add $8+8+4+4,%di # keep entry 5: test %ebx,%ebx # last entry? - jz 7f - cmp %si,%di # out of buf? + jz 8f + cmp $0x1000,%di jb 1b -7: mov %di,%ax -8: pop %bx - leave - ret -9: stc - jmp 8b +8: ret +9: mov $REAL(str.e820),%di + call rldie .endfn e820 -// Unreal Mode. -// Makes 4gb of real memory accessible via %fs segment. -unreal: cli - lgdt REAL(gdt) - mov %cr0,%eax - or $CR0_PE,%al - mov %eax,%cr0 - jmp 1f -1: mov $GDT_LEGACY_DATA,%cx - mov %cx,%fs - and $~CR0_PE,%al - mov %eax,%cr0 - ljmp $0,$REAL(1f) -1: sti - ret - .endfn unreal - -// Loads remainder of executable off disk. -hiload: push %bx - mov $IMAGE_BASE_REAL,%esi # relocate, again - mov $IMAGE_BASE_PHYSICAL,%ebx - mov $v_ape_realsectors,%ecx - shl $9,%ecx - or $-4,%edx -0: add $4,%edx - cmp %edx,%ecx - je 1f - mov %fs:(%esi,%edx),%eax - mov %eax,%fs:(%ebx,%edx) - jmp 0b -1: lea (%ebx,%edx),%ebx - mov $v_ape_highsectors,%di # then copy rest off disk - mov $REAL_SCRATCH_AREA>>4,%ax # to real memory buffer - mov %ax,%es - mov XLM(LOADSTATE)+0,%ax - mov XLM(LOADSTATE)+2,%cx - mov XLM(LOADSTATE)+4,%dx -0: test %di,%di - jz 9f - mov %di,%ax - push %bx - xor %bx,%bx - call16 pcread - pop %bx - sub %ax,%di - push %cx - mov %ax,%cx # copy real buffer to high - shl $9,%cx # no way bios loaded >64k - xor %si,%si -1: mov %es:(%si),%eax - mov %eax,%fs:(%ebx) - add $4,%ebx - add $4,%si - sub $4,%cx - jnz 1b - pop %cx - jmp 0b -9: pop %bx - ret - .endfn hiload - // Asks keyboard to grant system 65,519 more bytes of memory. // // Yup. @@ -1426,26 +1291,26 @@ a20: cli pop %ds jne 3f mov $1,%ax - call16 1f + call 1f mov $0xad,%al out %al,$0x64 - call16 1f + call 1f mov $0xd0,%al out %al,$0x64 - call16 2f + call 2f in $0x60,%al push %ax - call16 1f + call 1f mov $0xd1,%al out %al,$0x64 - call16 1f + call 1f pop %ax or $2,%al out %al,$0x60 - call16 1f + call 1f mov $0xae,%al out %al,$0x64 - call16 1f + call 1f jmp a20 1: in $0x64,%al test $2,%al @@ -1460,33 +1325,26 @@ a20: cli .endfn a20 // Initializes long mode paging. -// -// Modern computers access memory via four levels of indirection: -// -// register char (*(*(*(*ram)[512])[512])[512])[4096] asm(cr3) -// -// Your page tables grow down in memory, starting from the real -// stack segment base. This function only defines enough tables -// to get us started. -#define TIP REAL_STACK_FRAME pinit: push %ds - mov $(TIP-0x4000)>>4,%ax +#define SEG 0x79000 + mov $SEG>>4,%ax mov %ax,%ds - movl $TIP-0x2000+PAGE_V+PAGE_RW,0x3000 # PML4T→PDPT - movl $TIP-0x3000+PAGE_V+PAGE_RW,0x2000 # PDPT→PDT - movl $TIP-0x4000+PAGE_V+PAGE_RW,0x1000 # PDT→PD - mov $0x100000/0x1000,%cx # PD→512kb + movl $0x7d000+PAGE_V+PAGE_RW,0x7e000-SEG # PDPT←PML4T (+) + movl $0x7c000+PAGE_V+PAGE_RW,0x7e800-SEG # PDPT←PML4T (-) + movl $0x7b000+PAGE_V+PAGE_RW,0x7d000-SEG # PDT←PDPT (+) + movl $0x7a000+PAGE_V+PAGE_RW,0x7c000-SEG # PDT←PDPT (-) + movl $0x79000+PAGE_V+PAGE_RW,0x7b000-SEG # PD←PDT (+) + movl $0x79000+PAGE_V+PAGE_RW,0x7a000-SEG # PD←PDT (-) + mov $512,%cx # PD±2MB mov $PAGE_V+PAGE_RW,%eax xor %si,%si 0: mov %eax,(%si) add $0x1000,%eax add $8,%si loop 0b - movb $0,0 # unmap null - pop %ds - movl $TIP-0x4000,XLM(PAGE_TABLE_STACK_POINTER) # STACK→XLM - mov $TIP-0x1000,%eax # PML4T→CR3 + mov $0x7e000,%eax # PML4T←CR3 mov %eax,%cr3 + pop %ds ret .endfn pinit @@ -1494,7 +1352,7 @@ pinit: push %ds // // @see Intel Manual V3A §4.1.2 golong: cli - lidt XLM(BADIDT) + lidt 0x1522 # mman::bad_idt mov %cr4,%eax or $CR4_PAE|CR4_PGE|CR4_OSFXSR,%eax mov %eax,%cr4 @@ -1511,7 +1369,6 @@ golong: cli .endfn golong // Long mode is long. -// @noreturn .code64 long: push $GDT_LONG_DATA pop %rax @@ -1520,39 +1377,59 @@ long: push $GDT_LONG_DATA mov %eax,%es mov %eax,%fs mov %eax,%gs + mov $0x80000,%esp + xor %r12d,%r12d + xor %r13d,%r13d + xor %r14d,%r14d + xor %r15d,%r15d + xor %ebx,%ebx xor %ebp,%ebp - mov $REAL_STACK_FRAME+FRAMESIZE,%esp - call __map_image - ezlea metal.thunk,ax + push %rbp + mov $0x0500,%rdi # mman + mov %cr3,%rsi + mov $IMAGE_BASE_REAL,%edx + call __map_phdrs + push $0x037f + fldcw (%rsp) + movabs $1f,%rax jmp *%rax - .endfn long - -// Long mode in virtual address space. -// @noreturn -metal.thunk: +1: movabs $ape_stack_vaddr,%rsp + add $ape_stack_memsz,%rsp #if USE_SYMBOL_HACK .byte 0x0f,0x1f,0207 # nop rdi binbase .long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512 #endif -// 𝑠𝑙𝑖𝑑𝑒 - .endfn metal.thunk -metal: xor %eax,%eax # clear bss - mov $ape_bss_vaddr,%edi - mov $ape_bss_memsz,%ecx - rep stosb -0: .weak __hostos + movl $0,0x7b000 # unmap null 2mb + .weak __hostos ezlea __hostos,ax test %rax,%rax jz 1f movb $METAL,(%rax) -1: push $0 # auxv[0][1] - push $0 # auxv[0][0] - push $0 # envp[0] - push $0 # argv[0] - push $0 # argc - xor %edi,%edi # not freebsd +1: xor %eax,%eax + xor %ecx,%ecx + xor %edx,%edx + xor %edi,%edi + xor %esi,%esi + xor %r8d,%r8d + xor %r9d,%r9d + xor %r10d,%r10d + xor %r11d,%r11d + push $0 # auxv[1][1] + push $0 # auxv[1][0] + push $.Larg0 # auxv[0][1] + push $31 # auxv[0][0] AT_EXECFN + push $0 # envp[1] + push $.Lenv0 # envp[0] + push $0 # argv[1] + push $.Larg0 # argv[0] + push $1 # argc jmp _start - .endfn metal + .endfn long + + .rodata.str1.1 +.Larg0: .asciz "ape.com" +.Lenv0: .asciz "METAL=1" + .previous #endif /* SupportsMetal() */ diff --git a/ape/ape.lds b/ape/ape.lds index 376cc9da7..794ce1134 100644 --- a/ape/ape.lds +++ b/ape/ape.lds @@ -175,7 +175,7 @@ #ifdef __LINKER__ #include "ape/macros.internal.h" -#include "ape/config.h" +#include "ape/relocations.h" #include "libc/dce.h" #include "libc/nt/pedef.internal.h" #include "libc/zip.h" @@ -196,11 +196,12 @@ SECTIONS { /*BEGIN: linux addressability guarantee */ /*BEGIN: bsd addressability guarantee */ - .head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : { + .head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : AT(IMAGE_BASE_REAL) { HIDDEN(_base = .); /* Real Mode */ KEEP(*(.head)) + KEEP(*(.text.head)) /* Executable & Linkable Format */ . = ALIGN(__SIZEOF_POINTER__); @@ -220,16 +221,14 @@ SECTIONS { HIDDEN(ape_pe_sections = .); KEEP(*(.pe.sections)) HIDDEN(ape_pe_sections_end = .); - . += 1; /* Mach-O */ KEEP(*(.macho)) . = ALIGN(__SIZEOF_POINTER__); HIDDEN(ape_macho_end = .); - . += 1; KEEP(*(.ape.pad.head)) - . = ALIGN(SupportsWindows() || SupportsUefi() ? PAGESIZE : 16); + . = ALIGN(SupportsWindows() || SupportsMetal() ? PAGESIZE : 16); HIDDEN(_ehead = .); } :Head @@ -239,8 +238,8 @@ SECTIONS { /* Code that needs to be addressable in Real Mode */ *(.text.real) KEEP(*(SORT_BY_NAME(.sort.text.real.*))) - *(.rodata.real) - KEEP(*(SORT_BY_NAME(.sort.rodata.real.*))) + /**(.rodata.real) + KEEP(*(SORT_BY_NAME(.sort.rodata.real.*)))*/ HIDDEN(_ereal = .); /*END: realmode addressability guarantee */ @@ -282,7 +281,6 @@ SECTIONS { KEEP(*(.ape.pad.privileged)); HIDDEN(__privileged_start = .); HIDDEN(__test_end = .); - . += 1; *(.privileged) HIDDEN(__privileged_end = .); @@ -308,7 +306,6 @@ SECTIONS { /* Windows DLL Import Directory */ KEEP(*(.idata.ro)); KEEP(*(SORT_BY_NAME(.idata.ro.*))) - . += 1; . = ALIGN(__SIZEOF_POINTER__); PROVIDE_HIDDEN(__init_array_start = .); @@ -381,11 +378,6 @@ SECTIONS { KEEP(*(SORT_BY_NAME(.sort.bss.*))) - /* eXtreme Low Memory w/ Userspace Remapping */ - . = ALIGN(0x1000); - *(.xlm) - . = ALIGN(0x1000); - . = ALIGN(0x10000); /* for brk()/sbrk() allocation */ HIDDEN(_end = .); PROVIDE_HIDDEN(end = .); @@ -465,6 +457,13 @@ HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr); HIDDEN(ape_ram_align = PAGESIZE); HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr)); +HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz); +HIDDEN(ape_stack_vaddr = 0x700000000000 - STACKSIZE); +HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz); +HIDDEN(ape_stack_filesz = 0); +HIDDEN(ape_stack_memsz = STACKSIZE); +HIDDEN(ape_stack_align = 16); + HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr)); HIDDEN(ape_note_vaddr = ape_note); HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset); @@ -500,14 +499,18 @@ SHSTUB2(ape_macho_dd_skip, RVA(ape_macho) / 8); SHSTUB2(ape_macho_dd_count, (ape_macho_end - ape_macho) / 8); #endif -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() #define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain)) PFSTUB4(ape_pe_offset, ape_pe - ape_mz); HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24)); HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40); -HIDDEN(ape_idata_idtsize = ape_idata_idtend - ape_idata_idt); -HIDDEN(ape_idata_iatsize = ape_idata_iatend - ape_idata_iat); +HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL); +HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0); +HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0); +HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0); +HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0); HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1); +HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0); HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5); HIDDEN(v_ntsubsystem = (LINK_WINDOWS ? (DEFINED(GetMessage) @@ -519,7 +522,7 @@ HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain); #if SupportsMetal() HIDDEN(v_ape_realsectors = - MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL, + MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_edata), 4096)) / 512); HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512)); HIDDEN(v_ape_highsectors = @@ -609,7 +612,7 @@ CHURN(v_ape_realsectors); #if SupportsXnu() CHURN(ape_macho); #endif -#if SupportsWindows() || SupportsUefi() +#if SupportsWindows() || SupportsMetal() CHURN(ape_mz); CHURN(ape_pe); CHURN(ape_pe_offset); diff --git a/ape/ape.mk b/ape/ape.mk index 26fefdaef..cc23be31b 100644 --- a/ape/ape.mk +++ b/ape/ape.mk @@ -31,12 +31,10 @@ APE_HDRS = $(filter %.h,$(APE_FILES)) APE_INCS = $(filter %.inc,$(APE_FILES)) APE_SRCS = $(filter %.S,$(APE_FILES)) APE_OBJS = $(APE_SRCS:%.S=o/$(MODE)/%.o) -APE_DEPS = $(APE_LIB) APE_CHECKS = $(APE_HDRS:%=o/%.ok) o/$(MODE)/ape/ape.lds: \ ape/ape.lds \ - ape/config.h \ ape/macros.internal.h \ libc/dce.h \ libc/zip.h @@ -49,6 +47,4 @@ $(APE_OBJS): $(BUILD_FILES) \ ape/ape.mk .PHONY: o/$(MODE)/ape -o/$(MODE)/ape: $(APE) \ - $(APE_CHECKS) \ - o/$(MODE)/ape/lib +o/$(MODE)/ape: $(APE) $(APE_CHECKS) diff --git a/ape/config.h b/ape/config.h deleted file mode 100644 index 440a65285..000000000 --- a/ape/config.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef APE_CONFIG_H_ -#define APE_CONFIG_H_ -#include "ape/relocations.h" -#include "libc/macros.h" - -/* - * Post-Initialization Read-Only Code Size Threshold. - * - * An executable needs to have at least this much code, before the - * linker adds non-mandatory 4kb alignments. The benefit is better - * memory protection. The tradeoff is sparser binaries. - */ -#ifndef APE_PIRO_THRESHOLD -#ifdef CONFIG_DBG -#define APE_PIRO_THRESHOLD 0x1000 -#else -#define APE_PIRO_THRESHOLD 0x10000 -#endif -#endif - -#ifndef METAL_STDIN -#define METAL_STDIN COM1 -#endif -#ifndef METAL_STDOUT -#define METAL_STDOUT COM1 -#endif -#ifndef METAL_STDERR -#define METAL_STDERR COM1 -#endif - -#ifndef VIDYA_MODE -#define VIDYA_MODE VIDYA_MODE_CGA -#endif - -/* FPU Control Word (x87) Exception Masks - @see Intel Manual V1 §8.1.5 - - IM: Invalid Operation ───────────────┐ - DM: Denormal Operand ───────────────┐│ - ZM: Zero Divide ───────────────────┐││ - OM: Overflow ─────────────────────┐│││ - UM: Underflow ───────────────────┐││││ - PM: Precision ──────────────────┐│││││ - PC: Precision Control ────────┐ ││││││ - {float,∅,double,long double} │ ││││││ - RC: Rounding Control ───────┐ │ ││││││ - {even, →-∞, →+∞, →0} │┌┤ ││││││ - ┌┤││ ││││││ - d││││rr││││││*/ -#define X87_NORMAL 0b000000000001101111111 -#define X87_DTOA 0b000000000001000000000 -#define X87_DTOA_MASK 0b000000000001100000000 -#ifndef X87_DEFAULT -#define X87_DEFAULT X87_NORMAL -#endif - -#ifndef UART_BAUD_RATE -#define UART_BAUD_RATE 9600 /* bits per second ∈ [50,115200] */ -#endif -#define UART_CONF_DLR (1843200 /*hz*/ / 16 /*wut*/ / (UART_BAUD_RATE)) -#ifndef UART_CONF_IIR -/* ┌interrupt trigger level {1,4,8,14} - │ ┌enable 64 byte fifo (UART 16750+) - │ │ ┌select dma mode - │ │ │┌clear transmit fifo - │ │ ││┌clear receive fifo - ├┐│ │││┌enable fifos*/ -#define UART_CONF_IIR 0b00000000 -#endif -#ifndef UART_CONF_LCR -/* ┌dlab: flips configuration mode state - │┌enable break signal - ││ ┌parity {none,odd,even,high,low} - ││ │ ┌extra stop bit - ││ │ │┌data word length (bits+5) - ││┌┴┐│├┐*/ -#define UART_CONF_LCR 0b01000011 -#endif - -#define XLM(VAR) (XLM_BASE_REAL + XLM_##VAR) -#define XLMV(VAR) (__xlm + XLM_##VAR) -#define XLM_BASE_REAL 0x1000 -#define XLM_E820 0 -#define XLM_E820_SIZE 0x2000 -#define XLM_BIOS_DATA_AREA 0x2000 -#define XLM_BIOS_DATA_AREA_SIZE 256 -#define XLM_DRIVE_BASE_TABLE 0x2200 /* drive values are contiguous */ -#define XLM_DRIVE_BASE_TABLE_SIZE 11 -#define XLM_DRIVE_TYPE 0x220b -#define XLM_DRIVE_TYPE_SIZE 1 -#define XLM_DRIVE_LAST_SECTOR 0x220c /* 1-based inclusive, e.g. 18 */ -#define XLM_DRIVE_LAST_SECTOR_SIZE 1 -#define XLM_DRIVE_LAST_CYLINDER 0x220d /* 0-based incl, e.g. 79 */ -#define XLM_DRIVE_LAST_CYLINDER_SIZE 2 -#define XLM_DRIVE_ATTACHED 0x220f -#define XLM_DRIVE_ATTACHED_SIZE 1 -#define XLM_DRIVE_LAST_HEAD 0x2210 /* 0-based inclusive, e.g. 1 */ -#define XLM_DRIVE_LAST_HEAD_SIZE 1 -#define XLM_DRIVE 0x2211 -#define XLM_DRIVE_SIZE 1 -#define XLM_HAVEEXTMEMKB 0x2212 -#define XLM_HAVEEXTMEMKB_SIZE 4 -#define XLM_VIDEO_POSITION_FAR_POINTER 0x2216 /* video cursor far pointer */ -#define XLM_VIDEO_POSITION_FAR_POINTER_SIZE 4 -#define XLM_PAGE_TABLE_STACK_POINTER 0x2220 -#define XLM_PAGE_TABLE_STACK_POINTER_SIZE 8 -#define XLM_BADIDT 0x2230 -#define XLM_BADIDT_SIZE 6 -#define XLM_LOADSTATE 0x2240 -#define XLM_LOADSTATE_SIZE 8 -#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000) -#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE) - -#if !defined(__LINKER__) && !defined(__ASSEMBLER__) -extern char __xlm[XLM_SIZE]; -#endif /* !defined(__LINKER__) && !defined(__ASSEMBLER__) */ - -#endif /* APE_CONFIG_H_ */ diff --git a/ape/lib/apelib.mk b/ape/lib/apelib.mk deleted file mode 100644 index f7cf68669..000000000 --- a/ape/lib/apelib.mk +++ /dev/null @@ -1,45 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += APE_LIB - -APE_LIB_ARTIFACTS += APE_LIB_A -APE_LIB = $(APE_LIB_A_DEPS) $(APE_LIB_A) -APE_LIB_A = o/$(MODE)/ape/lib/apelib.a -APE_LIB_A_FILES := $(wildcard ape/lib/*) -APE_LIB_A_HDRS = $(filter %.h,$(APE_LIB_A_FILES)) -APE_LIB_A_SRCS_S = $(filter %.S,$(APE_LIB_A_FILES)) -APE_LIB_A_SRCS_C = $(filter %.c,$(APE_LIB_A_FILES)) - -APE_LIB_A_SRCS = \ - $(APE_LIB_A_SRCS_S) \ - $(APE_LIB_A_SRCS_C) - -APE_LIB_A_OBJS = \ - $(APE_LIB_A_SRCS_S:%.S=o/$(MODE)/%.o) \ - $(APE_LIB_A_SRCS_C:%.c=o/$(MODE)/%.o) - -APE_LIB_A_DIRECTDEPS = \ - LIBC_NEXGEN32E \ - LIBC_INTRIN \ - LIBC_STR \ - LIBC_STUBS - -APE_LIB_A_CHECKS = $(APE_LIB_A_HDRS:%=o/$(MODE)/%.ok) -APE_LIB_A_DEPS = $(call uniq,$(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)))) - -$(APE_LIB_A): ape/lib/ $(APE_LIB_A).pkg $(APE_LIB_A_OBJS) -$(APE_LIB_A).pkg: $(APE_LIB_A_OBJS) $(foreach x,$(APE_LIB_A_DIRECTDEPS),$($(x)_A).pkg) - -APE_LIB_LIBS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x))) -APE_LIB_SRCS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_SRCS)) -APE_LIB_HDRS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_HDRS)) -APE_LIB_BINS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_BINS)) -APE_LIB_CHECKS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_CHECKS)) -APE_LIB_OBJS = $(foreach x,$(APE_LIB_ARTIFACTS),$($(x)_OBJS)) -$(APE_LIB_OBJS): $(BUILD_FILES) libc/str/str.mk - -.PHONY: o/$(MODE)/ape/lib -o/$(MODE)/ape/lib: \ - $(APE_LIB_CHECKS) \ - $(APE_LIB_A) diff --git a/ape/lib/bootdr.S b/ape/lib/bootdr.S deleted file mode 100644 index 735105f91..000000000 --- a/ape/lib/bootdr.S +++ /dev/null @@ -1,35 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - -// Resets personal computer. -// -// @param di drive number, e.g. A:\ is 0x00, C:\ is 0x80 -// @mode real -// @noreturn -bootdr: push %bp - mov %sp,%bp - mov %di,%dx - int $0x19 - ljmp $0xf000,$0xfff0 - .endfn bootdr,globl diff --git a/ape/lib/e820map.S b/ape/lib/e820map.S deleted file mode 100644 index 3a9a71ea0..000000000 --- a/ape/lib/e820map.S +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl e820map - .hidden e820map - .type e820map,@object - .size e820map,XLM_E820_SIZE - e820map = ape_xlm + XLM_E820 - - .globl e820map_xlm - .hidden e820map_xlm - .type e820map_xlm,@object - .size e820map_xlm,XLM_E820_SIZE - e820map_xlm = XLM(E820) diff --git a/ape/lib/flattenhighmemory.c b/ape/lib/flattenhighmemory.c deleted file mode 100644 index 08cec8374..000000000 --- a/ape/lib/flattenhighmemory.c +++ /dev/null @@ -1,55 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/config.h" -#include "ape/lib/pc.h" -#include "libc/bits/bits.h" -#include "libc/macros.h" - -/** - * Virtualizes physical memory. - * - * This function removes memory holes (discovered by e820() earlier) and - * creates the illusion of flat contiguous memory for as much RAM as the - * BIOS reports usable. Memory is safe to use and remap afterwards. - * - * @see ape/ape.S - */ -textreal void flattenhighmemory(struct SmapEntry *e820, struct PageTable *pml4t, - uint64_t *ptsp) { - uint64_t *entry, paddr, vaddr; - struct SmapEntry *smap, *hole; - for (smap = hole = e820, vaddr = IMAGE_BASE_VIRTUAL; smap->size; ++smap) { - while (smap->size && smap->type != kMemoryUsable) smap++; - paddr = ROUNDUP(MAX(IMAGE_BASE_PHYSICAL, smap->addr), PAGESIZE); - while (paddr < ROUNDDOWN(smap->addr + smap->size, PAGESIZE)) { - while (hole->size && - (hole->type == kMemoryUsable || hole->addr + hole->size < paddr)) { - hole++; - } - if (paddr >= hole->addr && paddr < hole->addr + hole->size) { - paddr = ROUNDUP(hole->addr + hole->size, PAGESIZE); - } else { - entry = __getpagetableentry(vaddr, 3, pml4t, ptsp); - *entry = paddr | PAGE_V | PAGE_RW; - vaddr += 0x1000; - paddr += 0x1000; - } - } - } -} diff --git a/ape/lib/g_pml4t.S b/ape/lib/g_pml4t.S deleted file mode 100644 index 129561894..000000000 --- a/ape/lib/g_pml4t.S +++ /dev/null @@ -1,31 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl g_pml4t - .hidden g_pml4t - .type g_pml4t,@object - .size g_pml4t,0x1000 - g_pml4t = REAL_STACK_FRAME - 0x1000 diff --git a/ape/lib/g_ptsp.S b/ape/lib/g_ptsp.S deleted file mode 100644 index 261d2a0b8..000000000 --- a/ape/lib/g_ptsp.S +++ /dev/null @@ -1,37 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl g_ptsp - .hidden g_ptsp - .type g_ptsp,@object - .size g_ptsp,XLM_PAGE_TABLE_STACK_POINTER_SIZE - g_ptsp = ape_xlm + XLM_PAGE_TABLE_STACK_POINTER - - .globl g_ptsp_xlm - .hidden g_ptsp_xlm - .type g_ptsp_xlm,@object - .size g_ptsp_xlm,XLM_PAGE_TABLE_STACK_POINTER_SIZE - g_ptsp_xlm = XLM(PAGE_TABLE_STACK_POINTER) diff --git a/ape/lib/getpagetableentry.c b/ape/lib/getpagetableentry.c deleted file mode 100644 index 8e036a46a..000000000 --- a/ape/lib/getpagetableentry.c +++ /dev/null @@ -1,42 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "libc/assert.h" - -static textreal uint64_t __pushpagetable(uint64_t *ptsp) { - return (*ptsp -= PAGESIZE) | PAGE_V | PAGE_RW; -} - -textreal uint64_t *__getpagetableentry(int64_t vaddr, unsigned depth, - struct PageTable *pml4t, - uint64_t *ptsp) { - uint64_t *entry; - unsigned char shift; - assert(depth <= 3); - assert(!(*ptsp & 0xfff)); - assert(!((uintptr_t)pml4t & 0xfff)); - shift = 39; - for (;;) { - entry = &pml4t->p[(vaddr >> shift) & 511]; - if (!depth--) return entry; - shift -= 9; - if (!*entry) *entry = __pushpagetable(ptsp); - pml4t = (void *)(*entry & PAGE_TA); - } -} diff --git a/ape/lib/kbiosdataarea.S b/ape/lib/kbiosdataarea.S deleted file mode 100644 index 664dba4b0..000000000 --- a/ape/lib/kbiosdataarea.S +++ /dev/null @@ -1,45 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/config.h" -#include "ape/macros.internal.h" -#include "ape/notice.inc" -.section .real,"ax",@progbits -.source __FILE__ -.code16 - - .globl kBiosDataArea - .hidden kBiosDataArea - .type kBiosDataArea,@object - .size kBiosDataArea,XLM_BIOS_DATA_AREA_SIZE - kBiosDataArea = ape_xlm + XLM_BIOS_DATA_AREA - - .globl kBiosDataAreaXlm - .hidden kBiosDataAreaXlm - .type kBiosDataAreaXlm,@object - .size kBiosDataAreaXlm,XLM_BIOS_DATA_AREA_SIZE - kBiosDataAreaXlm = XLM(BIOS_DATA_AREA) - - .section .sort.text.real.init.2.kBiosDataArea,"ax",@progbits - movpp %ds,%es # copy bios data to valid page - mov $PC_BIOS_DATA_AREA,%si - mov $XLM(BIOS_DATA_AREA),%di - mov $XLM_BIOS_DATA_AREA_SIZE,%cx - rep movsb - .previous diff --git a/ape/lib/pageunmap.c b/ape/lib/pageunmap.c deleted file mode 100644 index 9e731b455..000000000 --- a/ape/lib/pageunmap.c +++ /dev/null @@ -1,26 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" - -textreal void pageunmap(int64_t vaddr) { - uint64_t *entry; - entry = __getpagetableentry(vaddr, 3, &g_pml4t, &g_ptsp_xlm); - *entry &= ~PAGE_V; - asm volatile("invlpg\t(%0)" : /* no outputs */ : "r"(vaddr) : "memory"); -} diff --git a/ape/lib/smapsort.c b/ape/lib/smapsort.c deleted file mode 100644 index 24e1981e2..000000000 --- a/ape/lib/smapsort.c +++ /dev/null @@ -1,46 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" - -textreal static unsigned smapcount(const struct SmapEntry *se) { - unsigned i = 0; - while (se[i].size) ++i; - return i; -} - -textreal static void smapsorter(size_t n, struct SmapEntry a[n]) { - struct SmapEntry t; - unsigned i, j; - for (i = 1; i < n; ++i) { - j = i; - t = a[i]; - while (j > 0 && (intptr_t)t.addr - (intptr_t)a[j - 1].addr) { - a[j] = a[j - 1]; - --j; - } - a[j] = t; - } -} - -/** - * Sorts BIOS e820 memory map. - */ -textreal void smapsort(struct SmapEntry *smap) { - smapsorter(smapcount(smap), smap); -} diff --git a/ape/macros.internal.h b/ape/macros.internal.h index 4537da0ae..578f7a885 100644 --- a/ape/macros.internal.h +++ b/ape/macros.internal.h @@ -26,13 +26,6 @@ * @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε. */ -// Calls function in real mode. -// It's needed because LLVM 8 LLD doesn't support R_X86_64_PC16. - .macro call16 name:req - mov $REAL(\name),%ax - call *%ax - .endm - // Calls near (i.e. pc+pcrel<64kB) FUNCTION. // @mode long,legacy,real // @cost 9 bytes overhead diff --git a/ape/relocations.h b/ape/relocations.h index 1500d2b64..38895bbf4 100644 --- a/ape/relocations.h +++ b/ape/relocations.h @@ -11,6 +11,8 @@ In some cases it's necessary to use addend macros that change virtual addresses into the other two types: physical and real. */ +#define IMAGE_BASE_REAL 0x2000 + #ifndef IMAGE_BASE_VIRTUAL #define IMAGE_BASE_VIRTUAL 0x400000 #endif @@ -19,26 +21,6 @@ #define IMAGE_BASE_PHYSICAL 0x100000 #endif -#ifndef REAL_SCRATCH_AREA -/** - * Location of anything goes memory for real mode. - * - * The MBR won't load program content beyond this address, so we have - * room for buffers, page tables, etc. before we reach the stack frame. - */ -#define REAL_SCRATCH_AREA 0x40000 -#endif - -#ifndef REAL_STACK_FRAME -/** - * Location of real mode 64kb stack frame. - * - * This address was chosen because memory beyond 0x80000 can't be - * accessed safely without consulting e820. - */ -#define REAL_STACK_FRAME 0x70000 -#endif - /** * Returns Relative Virtual Address. */ diff --git a/build/bootstrap/compile.com b/build/bootstrap/compile.com index 44d4fb7d1..d8d154d69 100755 Binary files a/build/bootstrap/compile.com and b/build/bootstrap/compile.com differ diff --git a/build/definitions.mk b/build/definitions.mk index 2c5549448..2e3d49ac2 100644 --- a/build/definitions.mk +++ b/build/definitions.mk @@ -166,7 +166,8 @@ DEFAULT_LDFLAGS = \ --gc-sections \ --build-id=none \ --no-dynamic-linker \ - -z max-page-size=0x1000 + -z max-page-size=0x1000 \ + --cref -Map=$@.map ZIPOBJ_FLAGS = \ -b$(IMAGE_BASE_VIRTUAL) diff --git a/examples/e820.c b/examples/e820.c new file mode 100644 index 000000000..28d9919cc --- /dev/null +++ b/examples/e820.c @@ -0,0 +1,44 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/fmt/itoa.h" +#include "libc/macros.h" +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/stdio/stdio.h" + +const char *DescribeMemoryType(int type) { + switch (type) { + case kMemoryUsable: + return "kMemoryUsable"; + case kMemoryUnusable: + return "kMemoryUnusable"; + case kMemoryAcpiReclaimable: + return "kMemoryAcpiReclaimable"; + case kMemoryAcpiNvs: + return "kMemoryAcpiNvs"; + case kMemoryBad: + return "kMemoryBad"; + default: + return "UNKNOWN"; + } +} + +int main(int argc, char *argv[]) { + int i; + const char *ts; + struct mman *mm; + mm = (struct mman *)(BANE + 0x0500); + for (i = 0; i < mm->e820n; ++i) { + printf("%p-%p %s\n", mm->e820[i].addr, mm->e820[i].size, + DescribeMemoryType(mm->e820[i].type)); + } + for (;;) asm("pause"); + return 0; +} diff --git a/examples/examples.mk b/examples/examples.mk index c011a62aa..61a20e695 100644 --- a/examples/examples.mk +++ b/examples/examples.mk @@ -33,7 +33,6 @@ EXAMPLES_BINS = \ $(EXAMPLES_COMS:%=%.dbg) EXAMPLES_DIRECTDEPS = \ - APE_LIB \ DSP_CORE \ DSP_SCALE \ DSP_TTY \ diff --git a/examples/malloc.c b/examples/malloc.c new file mode 100644 index 000000000..60e8f65fa --- /dev/null +++ b/examples/malloc.c @@ -0,0 +1,19 @@ +#if 0 +/*─────────────────────────────────────────────────────────────────╗ +│ To the extent possible under law, Justine Tunney has waived │ +│ all copyright and related or neighboring rights to this file, │ +│ as it is written in the following disclaimers: │ +│ • http://unlicense.org/ │ +│ • http://creativecommons.org/publicdomain/zero/1.0/ │ +╚─────────────────────────────────────────────────────────────────*/ +#endif +#include "libc/mem/mem.h" +#include "libc/stdio/stdio.h" +#include "libc/str/str.h" + +int main(int argc, char *argv[]) { + char *s = malloc(1024 * 1024 * 2 + argc); + strcpy(s, "hello"); + puts(s); + return 0; +} diff --git a/libc/calls/efi.h b/libc/calls/efi.h deleted file mode 100644 index 6131f3957..000000000 --- a/libc/calls/efi.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef COSMOPOLITAN_LIBC_CALLS_EFI_H_ -#define COSMOPOLITAN_LIBC_CALLS_EFI_H_ -#include "libc/nt/efi.h" -#if !(__ASSEMBLER__ + __LINKER__ + 0) -COSMOPOLITAN_C_START_ - -extern EFI_HANDLE __efi_image_handle; -extern EFI_SYSTEM_TABLE *__efi_system_table; - -COSMOPOLITAN_C_END_ -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* COSMOPOLITAN_LIBC_CALLS_EFI_H_ */ diff --git a/libc/calls/fstat.c b/libc/calls/fstat.c index 4c2daa7c7..b6c20fceb 100644 --- a/libc/calls/fstat.c +++ b/libc/calls/fstat.c @@ -31,9 +31,9 @@ int fstat(int fd, struct stat *st) { if (__isfdkind(fd, kFdZip)) { return weaken(__zipos_fstat)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, st); - } else if (!IsWindows() && !IsMetal() && !IsUefi()) { + } else if (!IsWindows() && !IsMetal()) { return sys_fstat(fd, st); - } else if (IsMetal() || IsUefi()) { + } else if (IsMetal()) { return fstat_metal(fd, st); } else { if (!__isfdkind(fd, kFdFile)) return ebadf(); diff --git a/libc/calls/g_fds.c b/libc/calls/g_fds.c index 769ebae34..ab33efb7f 100644 --- a/libc/calls/g_fds.c +++ b/libc/calls/g_fds.c @@ -30,7 +30,7 @@ hidden textstartup void InitializeFileDescriptors(void) { fds = VEIL("r", &g_fds); pushmov(&fds->n, ARRAYLEN(fds->__init_p)); fds->p = fds->__init_p; - if (IsMetal() || IsUefi()) { + if (IsMetal()) { pushmov(&fds->f, 3ull); fds->__init_p[STDIN_FILENO].kind = pushpop(kFdSerial); fds->__init_p[STDOUT_FILENO].kind = pushpop(kFdSerial); diff --git a/libc/calls/internal.h b/libc/calls/internal.h index f2d5deeb7..057120d9f 100644 --- a/libc/calls/internal.h +++ b/libc/calls/internal.h @@ -197,7 +197,7 @@ u32 sys_getgid(void) hidden; u32 sys_getsid(int) hidden; u32 sys_gettid(void) hidden; u32 sys_getuid(void) hidden; -void *sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden; +void *__sys_mmap(void *, u64, u32, u32, i64, i64, i64) hidden; void *sys_mremap(void *, u64, u64, i32, void *) hidden; void sys_exit(int) hidden; @@ -295,12 +295,6 @@ unsigned __wincrash_nt(struct NtExceptionPointers *); int fstat_metal(int, struct stat *); -/*───────────────────────────────────────────────────────────────────────────│─╗ -│ cosmopolitan § syscalls » uefi ─╬─│┼ -╚────────────────────────────────────────────────────────────────────────────│*/ - -int sys_nanosleep_uefi(const struct timespec *, struct timespec *); - /*───────────────────────────────────────────────────────────────────────────│─╗ │ cosmopolitan § syscalls » drivers ─╬─│┼ ╚────────────────────────────────────────────────────────────────────────────│*/ diff --git a/libc/calls/nanosleep.c b/libc/calls/nanosleep.c index 7276d848c..fda4656f2 100644 --- a/libc/calls/nanosleep.c +++ b/libc/calls/nanosleep.c @@ -29,12 +29,10 @@ int nanosleep(const struct timespec *req, struct timespec *rem) { if (req->tv_sec < 0 || !(0 <= req->tv_nsec && req->tv_nsec <= 999999999)) { return einval(); } - if (!IsWindows() && !IsMetal() && !IsUefi() && !IsXnu()) { + if (!IsWindows() && !IsMetal() && !IsXnu()) { return sys_nanosleep(req, rem); } else if (IsXnu()) { return sys_nanosleep_xnu(req, rem); - } else if (IsUefi()) { - return sys_nanosleep_uefi(req, rem); } else if (IsMetal()) { return enosys(); /* TODO: Sleep on Metal */ } else { diff --git a/libc/calls/readv-serial.c b/libc/calls/readv-serial.c index a09090b4d..46dfa5db5 100644 --- a/libc/calls/readv-serial.c +++ b/libc/calls/readv-serial.c @@ -16,9 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/calls/internal.h" #include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" static bool IsDataAvailable(struct Fd *fd) { return inb(fd->handle + UART_LSR) & UART_TTYDA; diff --git a/libc/calls/readv.c b/libc/calls/readv.c index c38fab845..a7e525d34 100644 --- a/libc/calls/readv.c +++ b/libc/calls/readv.c @@ -36,8 +36,7 @@ ssize_t readv(int fd, const struct iovec *iov, int iovlen) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return weaken(__zipos_read)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); - } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n && - g_fds.p[fd].kind == kFdSerial) { + } else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { return readv_serial(&g_fds.p[fd], iov, iovlen); } else if (!IsWindows()) { return sys_readv(fd, iov, iovlen); diff --git a/libc/calls/sigaction.c b/libc/calls/sigaction.c index 4810c7331..fbdda5854 100644 --- a/libc/calls/sigaction.c +++ b/libc/calls/sigaction.c @@ -144,7 +144,7 @@ int(sigaction)(int sig, const struct sigaction *act, struct sigaction *oldact) { sizeof(struct sigaction) > sizeof(struct sigaction_freebsd) && sizeof(struct sigaction) > sizeof(struct sigaction_openbsd) && sizeof(struct sigaction) > sizeof(struct sigaction_netbsd)); - if (IsMetal() || IsUefi()) return enosys(); /* TODO: Signals on Metal */ + if (IsMetal()) return enosys(); /* TODO: Signals on Metal */ if (!(0 < sig && sig < NSIG)) return einval(); if (sig == SIGKILL || sig == SIGSTOP) return einval(); if (!act) { diff --git a/libc/calls/writev-serial.c b/libc/calls/writev-serial.c index 634a12075..3afba48b5 100644 --- a/libc/calls/writev-serial.c +++ b/libc/calls/writev-serial.c @@ -16,9 +16,9 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/calls/internal.h" #include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" ssize_t writev_serial(struct Fd *fd, const struct iovec *iov, int iovlen) { size_t i, j, wrote = 0; diff --git a/libc/calls/writev.c b/libc/calls/writev.c index 3b4544fdd..b882f5350 100644 --- a/libc/calls/writev.c +++ b/libc/calls/writev.c @@ -39,8 +39,7 @@ ssize_t writev(int fd, const struct iovec *iov, int iovlen) { if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) { return weaken(__zipos_write)( (struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1); - } else if ((SupportsMetal() || SupportsUefi()) && fd < g_fds.n && - g_fds.p[fd].kind == kFdSerial) { + } else if (SupportsMetal() && fd < g_fds.n && g_fds.p[fd].kind == kFdSerial) { return writev_serial(&g_fds.p[fd], iov, iovlen); } else if (!IsWindows()) { return sys_writev(fd, iov, iovlen); diff --git a/libc/crt/crt.S b/libc/crt/crt.S index 525b0447e..dc5dc3fbd 100644 --- a/libc/crt/crt.S +++ b/libc/crt/crt.S @@ -21,7 +21,6 @@ #include "libc/notice.inc" #include "libc/runtime/internal.h" .section .start,"ax",@progbits -.align 16 // System Five userspace program entrypoint. // @@ -37,7 +36,7 @@ _start: #endif 0: mov (%rsp),%ebx # argc lea 8(%rsp),%rsi # argv - lea 24(%rsp,%rbx,8),%rdx # envp + lea 16(%rsp,%rbx,8),%rdx # envp .frame0 // bofram 9f .weak ape_idata_iat diff --git a/libc/dce.h b/libc/dce.h index ba6c25fab..e100c4da0 100644 --- a/libc/dce.h +++ b/libc/dce.h @@ -20,7 +20,6 @@ #define OPENBSD 16 #define FREEBSD 32 #define NETBSD 64 -#define UEFI 128 #ifdef NDEBUG #define NoDebug() 1 @@ -73,7 +72,6 @@ #define SupportsLinux() ((SUPPORT_VECTOR & LINUX) == LINUX) #define SupportsMetal() ((SUPPORT_VECTOR & METAL) == METAL) #define SupportsWindows() ((SUPPORT_VECTOR & WINDOWS) == WINDOWS) -#define SupportsUefi() ((SUPPORT_VECTOR & UEFI) == UEFI) #define SupportsXnu() ((SUPPORT_VECTOR & XNU) == XNU) #define SupportsFreebsd() ((SUPPORT_VECTOR & FREEBSD) == FREEBSD) #define SupportsOpenbsd() ((SUPPORT_VECTOR & OPENBSD) == OPENBSD) @@ -86,7 +84,6 @@ #define IsLinux() (SupportsLinux() && (__hostos & LINUX)) #define IsMetal() (SupportsMetal() && (__hostos & METAL)) #define IsWindows() (SupportsWindows() && (__hostos & WINDOWS)) -#define IsUefi() (SupportsUefi() && (__hostos & UEFI)) #define IsXnu() (SupportsXnu() && (__hostos & XNU)) #define IsFreebsd() (SupportsFreebsd() && (__hostos & FREEBSD)) #define IsOpenbsd() (SupportsOpenbsd() && (__hostos & OPENBSD)) @@ -97,7 +94,6 @@ #define IsLinux() $LINUX,__hostos(%rip) #define IsMetal() $METAL,__hostos(%rip) #define IsWindows() $WINDOWS,__hostos(%rip) -#define IsUefi() $UEFI,__hostos(%rip) #define IsBsd() $XNU|FREEBSD|OPENBSD|NETBSD,__hostos(%rip) #define IsXnu() $XNU,__hostos(%rip) #define IsFreebsd() $FREEBSD,__hostos(%rip) diff --git a/libc/integral/c.inc b/libc/integral/c.inc index 7175a3b16..3d4872e8c 100644 --- a/libc/integral/c.inc +++ b/libc/integral/c.inc @@ -603,6 +603,7 @@ typedef uint64_t uintmax_t; #define textstartup _Section(".text.startup") noinstrument #define textexit _Section(".text.exit") noinstrument #define textreal _Section(".text.real") +#define texthead _Section(".text.head") #define textwindows _Section(".text.windows") #define antiquity _Section(".text.antiquity") #else @@ -610,6 +611,7 @@ typedef uint64_t uintmax_t; #define textstartup #define textexit #define textreal +#define texthead #define textwindows #define antiquity #endif diff --git a/libc/intrin/asan.c b/libc/intrin/asan.c index 48c539ee9..441634f82 100644 --- a/libc/intrin/asan.c +++ b/libc/intrin/asan.c @@ -28,7 +28,7 @@ #include "libc/mem/hook/hook.internal.h" #include "libc/nt/enum/version.h" #include "libc/nt/runtime.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/sysv/consts/auxv.h" @@ -744,7 +744,7 @@ void __asan_map_shadow(uintptr_t p, size_t n) { b = ROUNDUP((uintptr_t)SHADOW(ROUNDUP((uintptr_t)p + n, 8)), 1 << 16) >> 16; for (; a < b; ++a) { if (!__asan_is_mapped(a)) { - sm = weaken(__mmap)( + sm = weaken(sys_mmap)( (void *)((uintptr_t)a << 16), 1 << 16, PROT_READ | PROT_WRITE, MAP_PRIVATE | *weaken(MAP_ANONYMOUS) | MAP_FIXED, -1, 0); if (sm.addr == MAP_FAILED || @@ -796,7 +796,7 @@ static textstartup void __asan_shadow_existing_mappings(void) { } static textstartup bool IsMemoryManagementRuntimeLinked(void) { - return weaken(_mmi) && weaken(__mmap) && weaken(MAP_ANONYMOUS) && + return weaken(_mmi) && weaken(sys_mmap) && weaken(MAP_ANONYMOUS) && weaken(FindMemoryInterval) && weaken(TrackMemoryInterval); } @@ -809,7 +809,7 @@ textstartup void __asan_init(int argc, char **argv, char **envp, __asan_exit(0); /* So `make MODE=dbg test` passes w/ Windows7 */ } REQUIRE(_mmi); - REQUIRE(__mmap); + REQUIRE(sys_mmap); REQUIRE(MAP_ANONYMOUS); REQUIRE(FindMemoryInterval); REQUIRE(TrackMemoryInterval); diff --git a/libc/macros.internal.inc b/libc/macros.internal.inc index 6db866e8d..aa4670a2c 100644 --- a/libc/macros.internal.inc +++ b/libc/macros.internal.inc @@ -27,6 +27,9 @@ .macro .real .section .text.real,"ax",@progbits .endm +.macro .head + .section .text.head,"ax",@progbits +.endm .macro .text.startup .section .text.startup,"ax",@progbits .endm diff --git a/libc/nexgen32e/kcpuids.S b/libc/nexgen32e/kcpuids.S index d3f71dd20..e6da54be8 100644 --- a/libc/nexgen32e/kcpuids.S +++ b/libc/nexgen32e/kcpuids.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/dce.h" #include "libc/macros.h" #include "libc/nexgen32e/kcpuids.h" diff --git a/libc/nexgen32e/triplf.S b/libc/nexgen32e/triplf.S index e530ba409..52219de06 100644 --- a/libc/nexgen32e/triplf.S +++ b/libc/nexgen32e/triplf.S @@ -17,7 +17,6 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "ape/macros.internal.h" -#include "ape/config.h" .real .source __FILE__ .code16 # ∩ .code32 ∩ .code64 @@ -26,7 +25,8 @@ // // @see youtu.be/GIKfEAF2Yhw?t=67 // @mode long,legacy,real -triplf: push %bp +triplf: ud2 + push %bp mov %sp,%bp sub $8,%sp movpp %bp,%si diff --git a/libc/nexgen32e/xlm.S b/libc/nexgen32e/xlm.S deleted file mode 100644 index 73d6819ab..000000000 --- a/libc/nexgen32e/xlm.S +++ /dev/null @@ -1,32 +0,0 @@ -/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│ -│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/macros.h" -#include "libc/notice.inc" -#include "ape/config.h" - -// eXtreme Low Memory. -// @see ape/config.h - .section .xlm,"aw",@nobits - .align 4096 -__xlm: .rept XLM_SIZE - .byte 0 - .endr - .endobj __xlm,globl,hidden - .previous - .source __FILE__ diff --git a/libc/nt/efi.h b/libc/nt/efi.h index c04b70c13..89b1c240e 100644 --- a/libc/nt/efi.h +++ b/libc/nt/efi.h @@ -258,6 +258,9 @@ typedef EFI_STATUS(EFIAPI *EFI_GET_MEMORY_MAP)( typedef EFI_STATUS(EFIAPI *EFI_ALLOCATE_POOL)(EFI_MEMORY_TYPE PoolType, uintptr_t Size, void *out_Buffer); typedef EFI_STATUS(EFIAPI *EFI_FREE_POOL)(void *Buffer); +typedef void(EFIAPI *EFI_SET_MEM)(void *Buffer, uintptr_t Size, uint8_t Value); +typedef void(EFIAPI *EFI_COPY_MEM)(void *Destination, void *Source, + uintptr_t Length); typedef EFI_STATUS(EFIAPI *EFI_CHECK_EVENT)(EFI_EVENT Event); typedef EFI_STATUS(EFIAPI *EFI_CLOSE_EVENT)(EFI_EVENT Event); @@ -346,6 +349,8 @@ typedef EFI_STATUS(EFIAPI *EFI_IMAGE_LOAD)(bool BootPolicy, uintptr_t SourceSize, EFI_HANDLE *out_ImageHandle); typedef EFI_STATUS(EFIAPI *EFI_IMAGE_UNLOAD)(EFI_HANDLE ImageHandle); +typedef EFI_STATUS(EFIAPI *EFI_EXIT_BOOT_SERVICES)(EFI_HANDLE ImageHandle, + uintptr_t MapKey); typedef struct { EFI_TABLE_HEADER Hdr; @@ -393,7 +398,7 @@ typedef struct { void *StartImage; EFI_EXIT Exit; EFI_IMAGE_UNLOAD UnloadImage; - void *ExitBootServices; + EFI_EXIT_BOOT_SERVICES ExitBootServices; EFI_GET_NEXT_MONOTONIC_COUNT GetNextMonotonicCount; EFI_STALL Stall; EFI_SET_WATCHDOG_TIMER SetWatchdogTimer; @@ -408,8 +413,8 @@ typedef struct { void *InstallMultipleProtocolInterfaces; void *UninstallMultipleProtocolInterfaces; void *CalculateCrc32; - void *CopyMem; - void *SetMem; + EFI_COPY_MEM CopyMem; + EFI_SET_MEM SetMem; EFI_CREATE_EVENT_EX CreateEventEx; } EFI_BOOT_SERVICES; diff --git a/libc/runtime/arch_prctl.c b/libc/runtime/arch_prctl.c index 4dfa5bbb5..2dbd6ffa0 100644 --- a/libc/runtime/arch_prctl.c +++ b/libc/runtime/arch_prctl.c @@ -16,13 +16,13 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" #include "libc/bits/bits.h" #include "libc/calls/calls.h" #include "libc/dce.h" #include "libc/nexgen32e/msr.h" #include "libc/nexgen32e/x86feature.h" #include "libc/runtime/interruptiblecall.h" +#include "libc/runtime/pc.internal.h" #include "libc/sysv/consts/sig.h" #include "libc/sysv/errfuns.h" diff --git a/libc/calls/nanosleep-uefi.c b/libc/runtime/directmap-metal.c similarity index 60% rename from libc/calls/nanosleep-uefi.c rename to libc/runtime/directmap-metal.c index 94b84164f..1d751ad30 100644 --- a/libc/calls/nanosleep-uefi.c +++ b/libc/runtime/directmap-metal.c @@ -17,19 +17,48 @@ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/calls.h" -#include "libc/calls/efi.h" -#include "libc/nt/efi.h" +#include "libc/macros.h" +#include "libc/runtime/directmap.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/str/str.h" +#include "libc/sysv/consts/map.h" +#include "libc/sysv/consts/prot.h" #include "libc/sysv/errfuns.h" -int sys_nanosleep_uefi(const struct timespec *req, struct timespec *rem) { - if (__efi_system_table->BootServices->Stall( - req->tv_sec * 1000000 + req->tv_nsec / 1000) == EFI_SUCCESS) { - if (rem) { - rem->tv_sec = 0; - rem->tv_nsec = 0; +static uint64_t sys_mmap_metal_break; + +noasan struct DirectMap sys_mmap_metal(void *paddr, size_t size, int prot, + int flags, int fd, int64_t off) { + size_t i; + struct mman *mm; + struct DirectMap res; + uint64_t addr, page, *pte, *pml4t; + mm = (struct mman *)(BANE + 0x0500); + pml4t = __get_pml4t(); + size = ROUNDUP(size, 4096); + addr = (uint64_t)paddr; + if (!(flags & MAP_FIXED)) { + for (i = 0; i < size; i += 4096) { + pte = __get_virtual(mm, pml4t, addr, false); + if (pte && (*pte & PAGE_V)) { + addr = MAX(addr, sys_mmap_metal_break) + i + 4096; + i = 0; + } } - return 0; - } else { - return eintr(); + sys_mmap_metal_break = MAX(addr + size, sys_mmap_metal_break); } + for (i = 0; i < size; i += 4096) { + page = __new_page(mm); + pte = __get_virtual(mm, pml4t, addr + i, true); + if (pte && page) { + __clear_page(BANE + page); + *pte = page | ((prot & PROT_WRITE) ? PAGE_RW : 0) | PAGE_U | PAGE_V; + } else { + addr = -1; + break; + } + } + res.addr = (void *)addr; + res.maphandle = -1; + return res; } diff --git a/libc/runtime/directmapnt.c b/libc/runtime/directmap-nt.c similarity index 98% rename from libc/runtime/directmapnt.c rename to libc/runtime/directmap-nt.c index e47e40b27..464fdf537 100644 --- a/libc/runtime/directmapnt.c +++ b/libc/runtime/directmap-nt.c @@ -24,7 +24,7 @@ #include "libc/nt/memory.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/overlapped.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/sysv/consts/map.h" #include "libc/sysv/consts/prot.h" diff --git a/libc/runtime/directmap.c b/libc/runtime/directmap.c index bc521e05a..b6ef53172 100644 --- a/libc/runtime/directmap.c +++ b/libc/runtime/directmap.c @@ -18,7 +18,7 @@ ╚─────────────────────────────────────────────────────────────────────────────*/ #include "libc/calls/internal.h" #include "libc/nt/runtime.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" /** * Obtains memory mapping directly from system. @@ -28,11 +28,13 @@ * bypassed by calling this function. However the caller is responsible * for passing the magic memory handle on Windows NT to CloseHandle(). */ -noasan struct DirectMap __mmap(void *addr, size_t size, int prot, int flags, - int fd, int64_t off) { - if (!IsWindows()) { - return (struct DirectMap){sys_mmap(addr, size, prot, flags, fd, off, off), +noasan struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, + int fd, int64_t off) { + if (!IsWindows() && !IsMetal()) { + return (struct DirectMap){__sys_mmap(addr, size, prot, flags, fd, off, off), kNtInvalidHandleValue}; + } else if (IsMetal()) { + return sys_mmap_metal(addr, size, prot, flags, fd, off); } else { return sys_mmap_nt(addr, size, prot, flags, fd != -1 ? g_fds.p[fd].handle : kNtInvalidHandleValue, diff --git a/libc/runtime/directmap.h b/libc/runtime/directmap.internal.h similarity index 69% rename from libc/runtime/directmap.h rename to libc/runtime/directmap.internal.h index 80b9adebc..6bafebc93 100644 --- a/libc/runtime/directmap.h +++ b/libc/runtime/directmap.internal.h @@ -8,8 +8,10 @@ struct DirectMap { int64_t maphandle; }; -struct DirectMap __mmap(void *, size_t, int, int, int, int64_t); +struct DirectMap sys_mmap(void *, size_t, int, int, int, int64_t); struct DirectMap sys_mmap_nt(void *, size_t, int, int, int64_t, int64_t); +struct DirectMap sys_mmap_metal(void *, size_t, int, int, int, int64_t); +int sys_munmap_metal(void *, size_t); COSMOPOLITAN_C_END_ #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ diff --git a/libc/runtime/e820.internal.h b/libc/runtime/e820.internal.h new file mode 100644 index 000000000..7653869cd --- /dev/null +++ b/libc/runtime/e820.internal.h @@ -0,0 +1,21 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_E820_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_E820_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct SmapEntry { + uint64_t addr; + uint64_t size; + enum { + kMemoryUsable = 1, + kMemoryUnusable = 2, + kMemoryAcpiReclaimable = 3, + kMemoryAcpiNvs = 4, + kMemoryBad = 5 + } type; + uint32_t acpi3; +}; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_E820_H_ */ diff --git a/libc/runtime/efimain.greg.c b/libc/runtime/efimain.greg.c index 72e61f931..170ade5dd 100644 --- a/libc/runtime/efimain.greg.c +++ b/libc/runtime/efimain.greg.c @@ -16,17 +16,23 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/efi.h" +#include "libc/bits/bits.h" #include "libc/dce.h" #include "libc/macros.h" #include "libc/nt/efi.h" #include "libc/nt/thunk/msabi.h" +#include "libc/runtime/e820.internal.h" #include "libc/runtime/internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" +#include "libc/str/str.h" + +/* TOOD: Why can't we change CR3? Could it really need PML5T? */ +/* TOOD: Why does QEMU in UEFI mode take ten seconds to boot? */ struct EfiArgs { - char *args[4096]; - char argblock[ARG_MAX]; + char *Args[0x400 / sizeof(char *)]; + char ArgBlock[0xC00]; }; static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; @@ -36,15 +42,14 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; * * This entrypoint is mutually exclusive from WinMain since * Windows apps and EFI apps use the same PE binary format. - * By default, we build binaries to support Windows. If you - * want to your APE executable to boot on UEFI instead then - * you need to run the following build command: + * So if you want to trade away Windows so that you can use + * UEFI instead of the normal BIOS boot process, do this: * - * make -j8 CPPFLAGS=-DSUPPORT_VECTOR=251 + * STATIC_YOINK("EfiMain"); + * int main() { ... } * - * That'll remove all the Windows code and turn EFI on. You - * can also remove by BIOS code too, by changing 251 to 249 - * but it shouldn't matter. Here's how to emulate EFI apps: + * You can use QEMU to test this, but please note that UEFI + * goes thousands of times slower than the normal BIOS boot * * qemu-system-x86_64 \ * -bios OVMF.fd \ @@ -54,41 +59,129 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; * FS0: * deathstar.com * - * If you're using the amalgamated release binaries then it - * should be possible to enable UEFI mode by having this at - * the top of your main source file to hint the APE linker: - * - * STATIC_YOINK("EfiMain"); - * int main() { ... } - * * @see libc/dce.h */ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { - intptr_t argc; - struct EfiArgs *ea; - EFI_LOADED_IMAGE *img; - extern char os asm("__hostos"); - os = UEFI; - __efi_image_handle = ImageHandle; - __efi_system_table = SystemTable; - SystemTable->BootServices->AllocatePool(EfiConventionalMemory, sizeof(*ea), - &ea); + bool ispml5t; + int type, x87cw; + struct mman *mm; + uint32_t DescVersion; + uintptr_t i, j, MapSize; + struct EfiArgs *ArgBlock; + EFI_LOADED_IMAGE *ImgInfo; + EFI_MEMORY_DESCRIPTOR *Map; + uintptr_t Args, MapKey, DescSize; + uint64_t p, pe, cr4, *m, *pd, *sp, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2; + extern char __os asm("__hostos"); + + __os = METAL; + + /* + * Allocates and clears PC-compatible memory and copies image. + */ + SystemTable->BootServices->AllocatePages( + EfiConventionalMemory, AllocateAddress, + MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, 0); + SystemTable->BootServices->SetMem(0, 0x80000, 0); + SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base, + _end - _base); + + /* + * Converts UEFI shell arguments to argv. + */ + ArgBlock = (struct EfiArgs *)0x7e000; SystemTable->BootServices->HandleProtocol(ImageHandle, - &kEfiLoadedImageProtocol, &img); - argc = GetDosArgv(img->LoadOptions, ea->argblock, ARG_MAX, ea->args, - ARRAYLEN(ea->args)); - asm("push\t$0\n\t" /* auxv[0][1] */ - "push\t$0\n\t" /* auxv[0][0] */ - "push\t$0\n\t" /* envp[0] */ - "sub\t%2,%%rsp\n\t" - "mov\t%%rsp,%%rdi\n\t" - "rep movsb\n\t" /* argv */ - "push\t%0\n\t" /* argc */ - "xor\t%%edi,%%edi\n\t" - ".weak\t_start\n\t" - "jmp\t_start" - : /* no outputs */ - : "a"(argc), "S"(ea->args), "c"((argc + 1) * 8)); + &kEfiLoadedImageProtocol, &ImgInfo); + Args = GetDosArgv(ImgInfo->LoadOptions, ArgBlock->ArgBlock, + sizeof(ArgBlock->ArgBlock), ArgBlock->Args, + ARRAYLEN(ArgBlock->Args)); + + /* + * Asks UEFI which parts of our RAM we're allowed to use. + */ + Map = NULL; + MapSize = 0; + SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, + &DescVersion); + SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, Map); + SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, + &DescVersion); + asm("xor\t%0,%0" : "=r"(mm)); /* gcc assumes null isn't mapped */ + for (j = i = 0; i < MapSize / sizeof(EFI_MEMORY_DESCRIPTOR); ++i) { + if (Map[i].Type != EfiConventionalMemory) continue; + mm->e820[j].addr = Map[i].PhysicalStart; + mm->e820[j].size = Map[i].NumberOfPages * 4096; + mm->e820[j].type = kMemoryUsable; + ++j; + } + SystemTable->BootServices->FreePool(Map); + + /* + * Sets up page tables. + */ + pd = (uint64_t *)0x79000; + pdt1 = (uint64_t *)0x7b000; + pdt2 = (uint64_t *)0x7a000; + pdpt1 = (uint64_t *)0x7d000; + pdpt2 = (uint64_t *)0x7c000; + pml4t = (uint64_t *)0x7e000; + for (i = 0; i < 512; ++i) { + pd[i] = 0x1000 * i + PAGE_V + PAGE_RW; + } + pdt1[0] = (intptr_t)pd + PAGE_V + PAGE_RW; + pdt2[0] = (intptr_t)pd + PAGE_V + PAGE_RW; + pdpt1[0] = (intptr_t)pdt1 + PAGE_V + PAGE_RW; + pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW; + pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW; + pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW; + __map_phdrs(mm, pml4t, 1024 * 1024); + + /* + * Asks UEFI to handover control? + */ + SystemTable->BootServices->ExitBootServices(ImageHandle, MapKey); + + /* + * Launches program. + */ + asm volatile("fldcw\t%3\n\t" + "mov\t%4,%%cr3\n\t" + ".weak\tape_stack_vaddr\n\t" + ".weak\tape_stack_memsz\n\t" + "movabs\t$ape_stack_vaddr,%%rsp\n\t" + "add\t$ape_stack_memsz,%%rsp\n\t" + "push\t$0\n\t" /* auxv[1][1] */ + "push\t$0\n\t" /* auxv[1][0] */ + "push\t(%1)\n\t" /* auxv[0][1] */ + "push\t$31\n\t" /* auxv[0][0] AT_EXECFN */ + "push\t$0\n\t" /* envp[0] */ + "sub\t%2,%%rsp\n\t" + "mov\t%%rsp,%%rdi\n\t" + "rep movsb\n\t" /* argv */ + "push\t%0\n\t" /* argc */ + "xor\t%%edi,%%edi\n\t" + "xor\t%%eax,%%eax\n\t" + "xor\t%%ebx,%%ebx\n\t" + "xor\t%%ecx,%%ecx\n\t" + "xor\t%%edx,%%edx\n\t" + "xor\t%%edi,%%edi\n\t" + "xor\t%%esi,%%esi\n\t" + "xor\t%%ebp,%%ebp\n\t" + "xor\t%%r8d,%%r8d\n\t" + "xor\t%%r9d,%%r9d\n\t" + "xor\t%%r10d,%%r10d\n\t" + "xor\t%%r11d,%%r11d\n\t" + "xor\t%%r12d,%%r12d\n\t" + "xor\t%%r13d,%%r13d\n\t" + "xor\t%%r14d,%%r14d\n\t" + "xor\t%%r15d,%%r15d\n\t" + ".weak\t_start\n\t" + "jmp\t_start" + : /* no outputs */ + : "a"(Args), "S"(ArgBlock->Args), "c"((Args + 1) * 8), + "m"(x87cw), "r"(pml4t) + : "memory"); + unreachable; } diff --git a/libc/runtime/exit.c b/libc/runtime/exit.c index 6cfa3cdd9..673a23705 100644 --- a/libc/runtime/exit.c +++ b/libc/runtime/exit.c @@ -20,8 +20,8 @@ #include "libc/runtime/internal.h" #include "libc/runtime/runtime.h" -extern const uintptr_t __fini_array_start[]; -extern const uintptr_t __fini_array_end[]; +extern const uintptr_t __fini_array_start[] __attribute__((__weak__)); +extern const uintptr_t __fini_array_end[] __attribute__((__weak__)); /** * Exits process with grace. @@ -39,7 +39,7 @@ wontreturn void exit(int exitcode) { if (weaken(__cxa_finalize)) { weaken(__cxa_finalize)(NULL); } - for (p = *weaken(__fini_array_end); p > *weaken(__fini_array_start);) { + for (p = __fini_array_end; p > __fini_array_start;) { ((void (*)(void))(*--p))(); } _Exit(exitcode); diff --git a/libc/runtime/exit2.c b/libc/runtime/exit2.c index fd5464756..438fc680f 100644 --- a/libc/runtime/exit2.c +++ b/libc/runtime/exit2.c @@ -21,11 +21,14 @@ /** * Terminates process, ignoring destructors and atexit() handlers. * - * @param rc is exit code ∈ [0,256) + * When running on bare metal, this function will reboot your computer + * by hosing the interrupt descriptors and triple faulting the system. + * + * @param exitcode is masked with 255 * @asyncsignalsafe * @vforksafe * @noreturn */ -wontreturn void _exit(int rc) { - _Exit(rc); +wontreturn void _exit(int exitcode) { + _Exit(exitcode); } diff --git a/libc/runtime/exit3.c b/libc/runtime/exit3.c index d950c8bf2..657a63503 100644 --- a/libc/runtime/exit3.c +++ b/libc/runtime/exit3.c @@ -16,29 +16,36 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/efi.h" #include "libc/calls/internal.h" #include "libc/dce.h" #include "libc/nexgen32e/vendor.internal.h" #include "libc/nt/runtime.h" -#include "libc/runtime/runtime.h" +#include "libc/nt/thunk/msabi.h" +#include "libc/sysv/consts/nr.h" /** * Terminates process, ignoring destructors and atexit() handlers. * - * @param rc is exit code ∈ [0,256) + * When running on bare metal, this function will reboot your computer + * by hosing the interrupt descriptors and triple faulting the system. + * + * @param exitcode is masked with 255 * @asyncsignalsafe * @vforksafe * @noreturn */ -wontreturn void _Exit(int rc) { - if ((!IsWindows() && !IsMetal() && !IsUefi()) || - (IsMetal() && IsGenuineCosmo())) { - sys_exit(rc); - } else if (IsUefi()) { - __efi_system_table->BootServices->Exit(__efi_image_handle, rc, 0, NULL); +privileged wontreturn void _Exit(int exitcode) { + if ((!IsWindows() && !IsMetal()) || (IsMetal() && IsGenuineCosmo())) { + asm volatile("syscall" + : /* no outputs */ + : "a"(__NR_exit_group), "D"(exitcode) + : "memory"); } else if (IsWindows()) { - ExitProcess(rc & 0xff); + extern void(__msabi * __imp_ExitProcess)(uint32_t); + __imp_ExitProcess(exitcode & 0xff); } - triplf(); + asm("push\t$0\n\t" + "cli\n\t" + "lidt\t(%rsp)"); + for (;;) asm("ud2"); } diff --git a/libc/runtime/fork-nt.c b/libc/runtime/fork-nt.c index caefa4ab2..88b836974 100644 --- a/libc/runtime/fork-nt.c +++ b/libc/runtime/fork-nt.c @@ -36,7 +36,7 @@ #include "libc/nt/signals.h" #include "libc/nt/synchronization.h" #include "libc/nt/thread.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" diff --git a/ape/lib/mapimage.c b/libc/runtime/metalprintf.greg.c similarity index 53% rename from ape/lib/mapimage.c rename to libc/runtime/metalprintf.greg.c index 7eea964a7..93781a6c4 100644 --- a/ape/lib/mapimage.c +++ b/libc/runtime/metalprintf.greg.c @@ -1,7 +1,7 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ │vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ +│ Copyright 2021 Justine Alexandra Roberts Tunney │ │ │ │ Permission to use, copy, modify, and/or distribute this software for │ │ any purpose with or without fee is hereby granted, provided that the │ @@ -16,21 +16,65 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "ape/relocations.h" +#include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" -textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) { - uint64_t *e; - for (; a < b; a += 0x1000) { - e = __getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm); - *e = (IMAGE_BASE_REAL + a) | k; +#define PUTC(C) \ + do { \ + while (!(inb(0x3F8 + UART_LSR) & UART_TTYTXR)) { \ + asm("pause"); \ + } \ + outb(0x3F8, C); \ + } while (0) + +/** + * Prints string to serial port. + * + * This only supports %d and %s. It'll will work even if .rodata hasn't + * been loaded into memory yet. + */ +hidden textreal void(MetalPrintf)(const char *fmt, ...) { + int i; + char c; + unsigned u; + va_list va; + const char *s; + unsigned long d; + va_start(va, fmt); + for (;;) { + switch ((c = *fmt++)) { + case '\0': + va_end(va); + return; + case '%': + switch ((c = *fmt++)) { + case 's': + for (s = va_arg(va, const char *); s && *s; ++s) { + PUTC(*s); + } + break; + case 'd': + d = va_arg(va, unsigned long); + for (i = 16; i--;) { + u = (d >> (i * 4)) & 0xf; + if (u < 10) { + c = '0' + u; + } else { + u -= 10; + c = 'a' + u; + } + PUTC(c); + } + break; + default: + PUTC(c); + break; + } + break; + default: + PUTC(c); + break; + } } } - -textreal void __map_image(void) { - __map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL); - __map_segment(PAGE_V | PAGE_U | PAGE_RW, - (uintptr_t)_etext - IMAGE_BASE_VIRTUAL, - (uintptr_t)_end - IMAGE_BASE_VIRTUAL); -} diff --git a/libc/runtime/metalprintf.internal.h b/libc/runtime/metalprintf.internal.h new file mode 100644 index 000000000..0dd23224f --- /dev/null +++ b/libc/runtime/metalprintf.internal.h @@ -0,0 +1,16 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +void MetalPrintf(const char *, ...); + +#define MetalPrintf(FMT, ...) \ + do { \ + const char StackFmt[] = FMT; \ + MetalPrintf(StackFmt, ##__VA_ARGS__); \ + } while (0) + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_METALPRINTF_H_ */ diff --git a/ape/lib/apm.h b/libc/runtime/mman.greg.c similarity index 58% rename from ape/lib/apm.h rename to libc/runtime/mman.greg.c index 79a38ae1b..4657f4f30 100644 --- a/ape/lib/apm.h +++ b/libc/runtime/mman.greg.c @@ -1,5 +1,5 @@ /*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi│ +│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ ╞══════════════════════════════════════════════════════════════════════════════╡ │ Copyright 2020 Justine Alexandra Roberts Tunney │ │ │ @@ -30,29 +30,131 @@ │░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│ │░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ -│ αcτµαlly pδrταblε εxεcµταblε § green energy │ +│ αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#ifndef APE_LIB_APM_H_ -#define APE_LIB_APM_H_ +#include "ape/relocations.h" +#include "libc/elf/def.h" +#include "libc/elf/struct/phdr.h" +#include "libc/macros.h" +#include "libc/nexgen32e/uart.internal.h" +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/metalprintf.internal.h" +#include "libc/runtime/pc.internal.h" +#include "libc/runtime/runtime.h" /** - * @fileoverview Advanced Power Management. - * - *

APM is useful for exiting programs, without needing to ask the - * human to flip a physical switch or pass QEMU's -no-reboot flag. - * - *

Implementation Detail: Supporting ACPI would literally - * require implementing a programming language. - * - * @see APM BIOS Interface Specification v1.2 - * @since IBM PC/AT + * Allocates new page of physical memory. */ +noasan texthead uint64_t __new_page(struct mman *mm) { + uint64_t p; + if (mm->pdpi == mm->e820n) { + /* TODO: reclaim free pages */ + return 0; + } + while (mm->pdp >= mm->e820[mm->pdpi].addr + mm->e820[mm->pdpi].size) { + if (++mm->pdpi == mm->e820n) return 0; + mm->pdp = mm->e820[mm->pdpi].addr; + } + p = mm->pdp; + mm->pdp += 4096; + return p; +} -#define APM_SERVICE 0x15 +/** + * Returns pointer to page table entry for page at virtual address. + * Additional page tables are allocated if needed as a side-effect. + */ +noasan texthead uint64_t *__get_virtual(struct mman *mm, uint64_t *t, + int64_t vaddr, bool maketables) { + uint64_t *e, p; + unsigned char h; + for (h = 39;; h -= 9) { + e = t + ((vaddr >> h) & 511); + if (h == 12) return e; + if (!(*e & PAGE_V)) { + if (!maketables) return NULL; + if (!(p = __new_page(mm))) return NULL; + *e = p | PAGE_V | PAGE_RW; + } + t = (uint64_t *)(BANE + (*e & PAGE_TA)); + } +} -#if !(__ASSEMBLER__ + __LINKER__ + 0) +/** + * Sorts, rounds, and filters BIOS memory map. + */ +static noasan texthead void __normalize_e820(struct mman *mm) { + uint64_t a, b; + uint64_t x, y; + unsigned i, j, n; + for (n = i = 0; mm->e820[i].size; ++i) { + mm->e820[n] = mm->e820[i]; + x = mm->e820[n].addr; + y = mm->e820[n].addr + mm->e820[n].size; + a = ROUNDUP(x, 4096); + b = ROUNDDOWN(y, 4096) - a; + if (b > 0 && mm->e820[i].type == kMemoryUsable) { + mm->e820[n].addr = a; + mm->e820[n].size = b; + ++n; + } + } + for (i = 1; i < n; ++i) { + for (j = i; j > 0 && mm->e820[i].addr < mm->e820[j - 1].addr; --j) { + mm->e820[j] = mm->e820[j - 1]; + } + mm->e820[j] = mm->e820[i]; + } + mm->pdp = MAX(0x80000, mm->e820[0].addr); + mm->pdpi = 0; + mm->e820n = n; +} -void apmoff(void) wontreturn; +/** + * Identity maps all usable physical memory to its negative address. + */ +static noasan texthead void __invert_memory(struct mman *mm, uint64_t *pml4t) { + uint64_t i, j, *m, p, pe; + for (i = 0; i < mm->e820n; ++i) { + for (p = mm->e820[i].addr, pe = mm->e820[i].addr + mm->e820[i].size; + p + 0x200000 < pe; p += 4096) { + m = __get_virtual(mm, pml4t, BANE + p, true); + if (m && !(*m & PAGE_V)) { + *m = p | PAGE_V | PAGE_RW; + } + } + } +} -#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* APE_LIB_APM_H_ */ +noasan texthead void __setup_mman(struct mman *mm, uint64_t *pml4t) { + __normalize_e820(mm); + __invert_memory(mm, pml4t); +} + +/** + * 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) { + struct Elf64_Phdr *p; + uint64_t i, f, v, m, *e; + extern char ape_phdrs[] __attribute__((__weak__)); + extern char ape_phdrs_end[] __attribute__((__weak__)); + __setup_mman(mm, pml4t); + for (p = (struct Elf64_Phdr *)REAL(ape_phdrs), m = 0; + p < (struct Elf64_Phdr *)REAL(ape_phdrs_end); ++p) { + if (p->p_type == PT_LOAD || p->p_type == PT_GNU_STACK) { + f = PAGE_V | PAGE_U; + if (p->p_flags & PF_W) f |= PAGE_RW; + for (i = 0; i < p->p_memsz; i += 4096) { + if (i < p->p_filesz) { + v = b + p->p_offset + i; + m = MAX(m, v); + } else { + v = __clear_page(__new_page(mm)); + } + *__get_virtual(mm, pml4t, p->p_vaddr + i, true) = (v & PAGE_TA) | f; + } + } + } + mm->pdp = MAX(mm->pdp, m); +} diff --git a/libc/runtime/mman.internal.h b/libc/runtime/mman.internal.h new file mode 100644 index 000000000..9863579c1 --- /dev/null +++ b/libc/runtime/mman.internal.h @@ -0,0 +1,24 @@ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ +#include "libc/runtime/e820.internal.h" +#if !(__ASSEMBLER__ + __LINKER__ + 0) +COSMOPOLITAN_C_START_ + +struct mman { + int64_t pdp; /* 0x0500 */ + int32_t pdpi; /* 0x0508 */ + int32_t e820n; /* 0x050a */ + struct SmapEntry e820[256]; /* 0x0510 */ + char pc_drive_base_table[11]; /* 0x1510 */ + unsigned char pc_drive_type; /* 0x151b */ + unsigned char pc_drive_last_sector; /* 0x151c */ + unsigned short pc_drive_last_cylinder; /* 0x151d */ + unsigned char pc_drives_attached; /* 0x151f */ + unsigned char pc_drive_last_head; /* 0x1520 */ + unsigned char pc_drive; /* 0x1521 */ + char bad_idt[6]; /* 0x1522 */ +}; + +COSMOPOLITAN_C_END_ +#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_MMAN_H_ */ diff --git a/libc/runtime/mmap.c b/libc/runtime/mmap.c index a7bfc537c..671231932 100644 --- a/libc/runtime/mmap.c +++ b/libc/runtime/mmap.c @@ -24,7 +24,7 @@ #include "libc/intrin/asan.internal.h" #include "libc/macros.h" #include "libc/rand/rand.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" @@ -87,10 +87,10 @@ void *mmap(void *addr, size_t size, int prot, int flags, int fd, int64_t off) { } f = flags | MAP_FIXED; if (IsOpenbsd() && (f & MAP_GROWSDOWN)) { /* openbsd:dubstack */ - dm = __mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off); + dm = sys_mmap(addr, size, prot, f & ~MAP_GROWSDOWN, fd, off); if (dm.addr == MAP_FAILED) return MAP_FAILED; } - dm = __mmap(addr, size, prot, f, fd, off); + dm = sys_mmap(addr, size, prot, f, fd, off); if (dm.addr == MAP_FAILED || dm.addr != addr) { return MAP_FAILED; } diff --git a/libc/calls/efi.c b/libc/runtime/munmap-metal.c similarity index 82% rename from libc/calls/efi.c rename to libc/runtime/munmap-metal.c index dca380c0a..fba4a6ce9 100644 --- a/libc/calls/efi.c +++ b/libc/runtime/munmap-metal.c @@ -16,8 +16,18 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "libc/calls/efi.h" -#include "libc/nt/efi.h" +#include "libc/runtime/directmap.internal.h" +#include "libc/runtime/pc.internal.h" -EFI_HANDLE __efi_image_handle; -EFI_SYSTEM_TABLE *__efi_system_table; +int sys_munmap_metal(void *addr, size_t size) { + size_t i; + uint64_t *e; + struct mman *mm; + mm = (struct mman *)(BANE + 0x0500); + for (i = 0; i < size; i += 4096) { + e = __get_virtual(mm, __get_pml4t(), (uint64_t)addr + i, false); + if (e) *e = ~PAGE_V; + invlpg(e); + } + return 0; +} diff --git a/libc/runtime/munmap.c b/libc/runtime/munmap.c index 6a008e6bd..3309882ee 100644 --- a/libc/runtime/munmap.c +++ b/libc/runtime/munmap.c @@ -19,6 +19,7 @@ #include "libc/calls/internal.h" #include "libc/dce.h" #include "libc/macros.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" #include "libc/sysv/errfuns.h" @@ -46,5 +47,6 @@ int munmap(void *addr, size_t size) { if (!ALIGNED(addr) || !CANONICAL(addr) || !size) return einval(); if (UntrackMemoryIntervals(addr, size) == -1) return -1; if (IsWindows()) return 0; + if (IsMetal()) sys_munmap_metal(addr, size); return sys_munmap(addr, size); } diff --git a/ape/lib/pc.h b/libc/runtime/pc.internal.h similarity index 89% rename from ape/lib/pc.h rename to libc/runtime/pc.internal.h index badd3d21a..b78ff07de 100644 --- a/ape/lib/pc.h +++ b/libc/runtime/pc.internal.h @@ -32,9 +32,12 @@ ╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│ │ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#ifndef APE_LIB_PC_H_ -#define APE_LIB_PC_H_ +#ifndef COSMOPOLITAN_LIBC_RUNTIME_PC_H_ +#define COSMOPOLITAN_LIBC_RUNTIME_PC_H_ +#include "libc/runtime/e820.internal.h" +#include "libc/runtime/mman.internal.h" +#define BANE -140737488355328 #define BOOTSIG 0xaa55 /* master boot record signature */ #define PC_BIOS_DATA_AREA 0x400 @@ -154,35 +157,13 @@ #define PAGE_4KB /* */ 0b010000000 #define PAGE_2MB /* */ 0b110000000 #define PAGE_1GB /* */ 0b110000000 -#define PAGE_TA 0b11111111111111111111111111111111111111000000000000 -#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000 +#define PAGE_TA 0x00007ffffffff000 +#define PAGE_PA2 0x00007fffffe00000 #define PAGE_XD 0x8000000000000000 #if !(__ASSEMBLER__ + __LINKER__ + 0) -#include "ape/config.h" -struct thatispacked GlobalDescriptorTable { - uint16_t size; - uint64_t *entries; -}; - -/** - * Memory hole map. - * @see wiki.osdev.org/Detecting_Memory_(x86) - * @since 2002 - */ -struct SmapEntry { - uint64_t addr; - uint64_t size; - enum { - kMemoryUsable = 1, - kMemoryUnusable = 2, - kMemoryAcpiReclaimable = 3, - kMemoryAcpiNvs = 4, - kMemoryBad = 5 - } type; - uint32_t __acpi3; /* is abstracted */ -}; +#define invlpg(p) asm volatile("invlpg\t(%0)" : : "r"(p) : "memory") struct IdtDescriptor { uint16_t offset_1; /* offset bits 0..15 */ @@ -194,37 +175,10 @@ struct IdtDescriptor { uint32_t zero; /* reserved */ }; -struct thatispacked PageTable { - uint64_t p[512]; -} forcealign(PAGESIZE); - -extern struct PageTable g_pml4t; -extern struct GlobalDescriptorTable gdt; - -extern const unsigned char kBiosDataArea[256]; -extern const unsigned char kBiosDataAreaXlm[256]; - -extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)]; -extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)]; - -extern uint64_t g_ptsp; -extern uint64_t g_ptsp_xlm; - -void bootdr(char drive) wontreturn; - -void smapsort(struct SmapEntry *); -uint64_t *__getpagetableentry(int64_t, unsigned, struct PageTable *, - uint64_t *); -void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *); -void pageunmap(int64_t); - -forceinline unsigned long eflags(void) { - unsigned long res; - asm("pushf\n\t" - "pop\t%0" - : "=rm"(res)); - return res; -} +uint64_t *__get_virtual(struct mman *, uint64_t *, int64_t, bool); +uint64_t __clear_page(uint64_t); +uint64_t __new_page(struct mman *); +void __map_phdrs(struct mman *, uint64_t *, uint64_t); forceinline unsigned char inb(unsigned short port) { unsigned char al; @@ -238,5 +192,22 @@ forceinline void outb(unsigned short port, unsigned char byte) { : "a"(byte), "dN"(port)); } +#define __clear_page(page) \ + ({ \ + long di, cx; \ + uintptr_t Page = (uintptr_t)(page); \ + asm("rep stosb" \ + : "=D"(di), "=c"(cx), "=m"(*(char(*)[4096])Page) \ + : "0"(Page), "1"(4096), "a"(0)); \ + Page; \ + }) + +#define __get_pml4t() \ + ({ \ + intptr_t cr3; \ + asm("mov\t%%cr3,%0" : "=r"(cr3)); \ + (uint64_t *)(BANE + cr3); \ + }) + #endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */ -#endif /* APE_LIB_PC_H_ */ +#endif /* COSMOPOLITAN_LIBC_RUNTIME_PC_H_ */ diff --git a/libc/runtime/runtime.mk b/libc/runtime/runtime.mk index 4b04a50a3..26a2c5e4c 100644 --- a/libc/runtime/runtime.mk +++ b/libc/runtime/runtime.mk @@ -76,6 +76,10 @@ o/$(MODE)/libc/runtime/winmain.greg.o: \ OVERRIDE_CFLAGS += \ $(NO_MAGIC) +o/$(MODE)/libc/runtime/mman.greg.o: \ + OVERRIDE_CFLAGS += \ + -ffreestanding + o/$(MODE)/libc/runtime/ftrace.greg.o: \ OVERRIDE_CFLAGS += \ -mgeneral-regs-only diff --git a/libc/runtime/winmain.greg.c b/libc/runtime/winmain.greg.c index 106bc5f6c..b4b5516a6 100644 --- a/libc/runtime/winmain.greg.c +++ b/libc/runtime/winmain.greg.c @@ -36,7 +36,7 @@ #include "libc/nt/process.h" #include "libc/nt/runtime.h" #include "libc/nt/struct/teb.h" -#include "libc/runtime/directmap.h" +#include "libc/runtime/directmap.internal.h" #include "libc/runtime/internal.h" #include "libc/runtime/memtrack.h" #include "libc/runtime/runtime.h" @@ -74,7 +74,7 @@ static noasan textwindows void NormalizeCmdExe(int version) { hstdout = GetStdHandle(pushpop(kNtStdOutputHandle)); hstderr = GetStdHandle(pushpop(kNtStdErrorHandle)); if (GetFileType((handle = hstdin)) == kNtFileTypeChar) { - SetTrueColor(); + /* SetTrueColor(); */ SetConsoleCP(kNtCpUtf8); GetConsoleMode(handle, &mode); SetConsoleMode(handle, mode | kNtEnableProcessedInput | @@ -84,7 +84,7 @@ static noasan textwindows void NormalizeCmdExe(int version) { } if (GetFileType((handle = hstdout)) == kNtFileTypeChar || GetFileType((handle = hstderr)) == kNtFileTypeChar) { - SetTrueColor(); + /* SetTrueColor(); */ SetConsoleOutputCP(kNtCpUtf8); GetConsoleMode(handle, &mode); SetConsoleMode( diff --git a/libc/sysv/calls/__sys_mmap.s b/libc/sysv/calls/__sys_mmap.s new file mode 100644 index 000000000..2c27b450b --- /dev/null +++ b/libc/sysv/calls/__sys_mmap.s @@ -0,0 +1,2 @@ +.include "o/libc/sysv/macros.internal.inc" +.scall __sys_mmap,0x0c50c51dd20c5009,globl,hidden diff --git a/libc/sysv/calls/sys_mmap.s b/libc/sysv/calls/sys_mmap.s deleted file mode 100644 index 141c2e0bd..000000000 --- a/libc/sysv/calls/sys_mmap.s +++ /dev/null @@ -1,2 +0,0 @@ -.include "o/libc/sysv/macros.internal.inc" -.scall sys_mmap,0x0c50c51dd20c5009,globl,hidden diff --git a/libc/sysv/syscalls.sh b/libc/sysv/syscalls.sh index 718c9f083..f3307864d 100755 --- a/libc/sysv/syscalls.sh +++ b/libc/sysv/syscalls.sh @@ -44,7 +44,7 @@ scall __sys_lstat 0x1b90280282154006 globl hidden # needs __stat2linux(); block scall sys_poll 0x0d10fc0d120e6007 globl hidden scall sys_ppoll 0xfff06d221ffff10f globl hidden # consider INTON/INTOFF tutorial in examples/unbourne.c scall sys_lseek 0x0c70c71de20c7008 globl hidden # netbsd+openbsd:evilpad -scall sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad +scall __sys_mmap 0x0c50c51dd20c5009 globl hidden # netbsd+openbsd:pad scall sys_msync 0x115100041204101a globl hidden scall sys_mprotect 0x04a04a04a204a00a globl hidden scall sys_munmap 0x049049049204900b globl hidden diff --git a/libc/sysv/systemfive.S b/libc/sysv/systemfive.S index e3b1d6cd5..b41ed340f 100644 --- a/libc/sysv/systemfive.S +++ b/libc/sysv/systemfive.S @@ -104,7 +104,7 @@ __systemfive: .privileged .Lanchorpoint: -#if SupportsLinux() || SupportsMetal() || SupportsUefi() +#if SupportsLinux() || SupportsMetal() systemfive_linux: and $0xfff,%eax cmp $0xfff,%eax @@ -198,10 +198,6 @@ systemfive_xnu: testb $XNU,(%rdi) # @see libc/crt/crt.S jnz _init_systemfive_xnu #endif -#if SupportsUefi() - testb $UEFI,(%rdi) # @see ape/ape.S - jnz _init_systemfive_uefi -#endif #if SupportsMetal() testb $METAL,(%rdi) # @see ape/ape.S jnz _init_systemfive_metal @@ -240,13 +236,6 @@ _init_systemfive_metal: ezlea syscon_linux,si jmp _init_systemfive_os #endif -#if SupportsUefi() -_init_systemfive_uefi: - pushb systemfive_linux-.Lanchorpoint - push $UEFI - ezlea syscon_linux,si - jmp _init_systemfive_os -#endif #if SupportsWindows() _init_systemfive_windows: pushb systemfive_enosys-.Lanchorpoint @@ -323,20 +312,22 @@ _init_systemfive_magnums: // 𝑠𝑙𝑖𝑑𝑒 #if SupportsSystemv() && !defined(TINY) _init_systemfive_stack: # determinism ftw! -#if SupportsWindows() || SupportsMetal() || SupportsUefi() - testb $WINDOWS|METAL|UEFI,__hostos(%rip) +#if SupportsWindows() || SupportsMetal() + testb $WINDOWS|METAL,__hostos(%rip) jnz _init_systemfive_done #endif push %rdi push %rsi mov __NR_mmap,%eax - mov $0x700000000000-STACKSIZE,%rdi - mov $STACKSIZE,%esi + movabs $ape_stack_vaddr,%rdi + mov $ape_stack_memsz,%esi mov $PROT_READ|PROT_WRITE,%edx mov $MAP_PRIVATE|MAP_FIXED,%r10d or MAP_ANONYMOUS,%r10d or $-1,%r8d xor %r9d,%r9d + push %rdi # vaddr of stack + push %rsi # size of stack push %r9 # openbsd:pad push %r9 # openbsd:align #if SupportsOpenbsd() @@ -351,6 +342,8 @@ _init_systemfive_stack: # determinism ftw! syscall pop %r9 pop %r9 + pop %r9 # size of stack + pop %r11 # vaddr of stack jnc 2f 1: mov %eax,%edi mov __NR_exit_group,%eax @@ -360,17 +353,23 @@ _init_systemfive_stack: # determinism ftw! .weak _mmi ezlea _mmi,cx test %rcx,%rcx + push %r9 # save the stack size jz 3f + lea -1(%r11,%r9),%r9 # need incl. interval + shr $16,%r11 # for the stack range + shr $16,%r9 movb $1,(%rcx) # _mmi.i - movl $(0x700000000000-STACKSIZE)>>16,8(%rcx) # _mmi.p[0].x - movl $(0x700000000000-1)>>16,12(%rcx) # _mmi.p[0].y + mov %r11d,8(%rcx) # _mmi.p[0].x + mov %r9d,12(%rcx) # _mmi.p[0].y mov %edx,20(%rcx) # _mmi.p[0].prot mov %r10d,24(%rcx) # _mmi.p[0].flags -3: pop %rsi +3: pop %r9 # restore stack size + pop %rsi pop %rdi leave pop %rcx - lea STACKSIZE-16(%rax),%rsp # openbsd:stackbound + lea (%rax,%r9),%rsp + sub $ape_stack_align,%rsp # openbsd:stackbound mov %rbp,(%rsp) push %rcx push %rbp @@ -414,7 +413,7 @@ syscon_end: .type syscon_end,@object .globl syscon_start .globl syscon_end -#if SupportsLinux() || SupportsMetal() || SupportsUefi() +#if SupportsLinux() || SupportsMetal() .section .sort.rodata.syscon.linux.1,"a",@progbits .align 1 syscon_linux:/* @@ -468,3 +467,7 @@ syscon_windows:/* .type syscon_windows,@object .globl syscon_windows #endif + + .weak ape_stack_vaddr + .weak ape_stack_memsz + .weak ape_stack_align diff --git a/libc/testlib/testlib.mk b/libc/testlib/testlib.mk index dacb0f6e1..85ccc3c6a 100644 --- a/libc/testlib/testlib.mk +++ b/libc/testlib/testlib.mk @@ -78,7 +78,6 @@ LIBC_TESTLIB_A_OBJS = \ $(LIBC_TESTLIB_A_ASSETS:%=o/$(MODE)/%.zip.o) LIBC_TESTLIB_A_DIRECTDEPS = \ - APE_LIB \ LIBC_ALG \ LIBC_CALLS \ LIBC_FMT \ diff --git a/libc/tinymath/c2rangr.S b/libc/tinymath/c2rangr.S index fb4fceae7..e23ec047c 100644 --- a/libc/tinymath/c2rangr.S +++ b/libc/tinymath/c2rangr.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/copysignl.S b/libc/tinymath/copysignl.S index a18af04d4..79cfde3e6 100644 --- a/libc/tinymath/copysignl.S +++ b/libc/tinymath/copysignl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/fmodl.S b/libc/tinymath/fmodl.S index 355b0a66f..dc9e4372f 100644 --- a/libc/tinymath/fmodl.S +++ b/libc/tinymath/fmodl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/lroundl.S b/libc/tinymath/lroundl.S index 52a7da0d9..ff5dd4b9e 100644 --- a/libc/tinymath/lroundl.S +++ b/libc/tinymath/lroundl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/remainderl.S b/libc/tinymath/remainderl.S index 72fc72479..a98f987f5 100644 --- a/libc/tinymath/remainderl.S +++ b/libc/tinymath/remainderl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/roundl.S b/libc/tinymath/roundl.S index 185e8a2d7..d22894cdb 100644 --- a/libc/tinymath/roundl.S +++ b/libc/tinymath/roundl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" // Rounds to nearest integer, away from zero. diff --git a/libc/tinymath/sincosl.S b/libc/tinymath/sincosl.S index da6725702..09097fea3 100644 --- a/libc/tinymath/sincosl.S +++ b/libc/tinymath/sincosl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/tinymath/tanl.S b/libc/tinymath/tanl.S index 3958a13f2..e7808a9ab 100644 --- a/libc/tinymath/tanl.S +++ b/libc/tinymath/tanl.S @@ -16,7 +16,7 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" +#include "libc/runtime/pc.internal.h" #include "libc/macros.h" .source __FILE__ diff --git a/libc/zipos/zipos.mk b/libc/zipos/zipos.mk index 052cec6c0..cc35b0792 100644 --- a/libc/zipos/zipos.mk +++ b/libc/zipos/zipos.mk @@ -27,7 +27,6 @@ LIBC_ZIPOS_A_CHECKS = \ $(LIBC_ZIPOS_A_HDRS:%=o/$(MODE)/%.ok) LIBC_ZIPOS_A_DIRECTDEPS = \ - APE_LIB \ LIBC_CALLS \ LIBC_MEM \ LIBC_NEXGEN32E \ diff --git a/test/ape/lib/getpagetableentry_test.c b/test/ape/lib/getpagetableentry_test.c deleted file mode 100644 index 74d55bacc..000000000 --- a/test/ape/lib/getpagetableentry_test.c +++ /dev/null @@ -1,65 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "libc/mem/mem.h" -#include "libc/runtime/gc.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -TEST(getpagetableentry, testLowestAddress) { - static struct PageTable pml4t; - static struct PageTable stack[3]; - uint64_t ptsp = (uintptr_t)&stack + sizeof(stack); - memset(&pml4t, 0, sizeof(pml4t)); - memset(&stack, 0, sizeof(stack)); - uint64_t vaddr = 0; - uint64_t paddr = 0x31337000; - *__getpagetableentry(vaddr, 3, &pml4t, &ptsp) = paddr | PAGE_V; - EXPECT_EQ(&stack[2].p[0], pml4t.p[0] & PAGE_TA); /* pml4t → pdpt */ - EXPECT_EQ(&stack[1].p[0], stack[2].p[0] & PAGE_TA); /* pdpt → pdt */ - EXPECT_EQ(&stack[0].p[0], stack[1].p[0] & PAGE_TA); /* pdt → pd */ - EXPECT_EQ(stack[0].p[0] & PAGE_TA, paddr); /* page */ - EXPECT_EQ(&stack, ptsp); - EXPECT_TRUE(pml4t.p[0] & PAGE_V); - EXPECT_TRUE(stack[2].p[0] & PAGE_V); - EXPECT_TRUE(stack[1].p[0] & PAGE_V); - EXPECT_TRUE(stack[0].p[0] & PAGE_V); - EXPECT_FALSE(stack[0].p[1] & PAGE_V); -} - -TEST(getpagetableentry, testHigherAddress) { - static struct PageTable pml4t; - static struct PageTable stack[3]; - uint64_t ptsp = (uintptr_t)&stack + sizeof(stack); - memset(&pml4t, 0, sizeof(pml4t)); - memset(&stack, 0, sizeof(stack)); - uint64_t vaddr = 0x133731337000; - uint64_t paddr = 0x123000; - *__getpagetableentry(vaddr, 3, &pml4t, &ptsp) = paddr | PAGE_V; - EXPECT_EQ(&stack[2].p[0], pml4t.p[38] & PAGE_TA); /* pml4t → pdpt */ - EXPECT_EQ(&stack[1].p[0], stack[2].p[220] & PAGE_TA); /* pdpt → pdt */ - EXPECT_EQ(&stack[0].p[0], stack[1].p[393] & PAGE_TA); /* pdt → pd */ - EXPECT_EQ(stack[0].p[311] & PAGE_TA, paddr); /* page */ - EXPECT_EQ(&stack, ptsp); - EXPECT_TRUE(pml4t.p[38] & PAGE_V); - EXPECT_TRUE(stack[2].p[220] & PAGE_V); - EXPECT_TRUE(stack[1].p[393] & PAGE_V); - EXPECT_TRUE(stack[0].p[311] & PAGE_V); - EXPECT_FALSE(stack[0].p[0] & PAGE_V); -} diff --git a/test/ape/lib/smapsort_test.c b/test/ape/lib/smapsort_test.c deleted file mode 100644 index 3454a68bd..000000000 --- a/test/ape/lib/smapsort_test.c +++ /dev/null @@ -1,81 +0,0 @@ -/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│ -│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│ -╞══════════════════════════════════════════════════════════════════════════════╡ -│ Copyright 2020 Justine Alexandra Roberts Tunney │ -│ │ -│ Permission to use, copy, modify, and/or distribute this software for │ -│ any purpose with or without fee is hereby granted, provided that the │ -│ above copyright notice and this permission notice appear in all copies. │ -│ │ -│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │ -│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │ -│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │ -│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │ -│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │ -│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │ -│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ -│ PERFORMANCE OF THIS SOFTWARE. │ -╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/lib/pc.h" -#include "libc/mem/mem.h" -#include "libc/str/str.h" -#include "libc/testlib/testlib.h" - -TEST(smapsort, testEmpty_doesntOverrunBuffer) { - struct SmapEntry *smap = malloc(sizeof(struct SmapEntry)); - memset(smap, 0, sizeof(struct SmapEntry)); - smapsort(smap); - EXPECT_EQ(0, smap[0].addr); - EXPECT_EQ(0, smap[0].size); - free(smap); -} - -/* TEST(smapsort, testSorted_doesNothing) { */ -/* struct SmapEntry *smap = tmalloc(4 * sizeof(struct SmapEntry)); */ -/* memset(smap, 0, 4 * sizeof(struct SmapEntry)); */ -/* smap[0].addr = 0; */ -/* smap[0].size = 0x7000; */ -/* smap[0].type = kMemoryUsable; */ -/* smap[1].addr = 0x7000; */ -/* smap[1].size = 0x1000; */ -/* smap[1].type = kMemoryUnusable; */ -/* smap[2].addr = 0x14000; */ -/* smap[2].size = 0x1000; */ -/* smap[2].type = kMemoryBad; */ -/* smapsort(smap); */ -/* EXPECT_EQ(0, smap[0].addr); */ -/* EXPECT_EQ(0x7000, smap[0].size); */ -/* EXPECT_EQ(kMemoryUsable, smap[0].type); */ -/* EXPECT_EQ(0x7000, smap[1].addr); */ -/* EXPECT_EQ(0x1000, smap[1].size); */ -/* EXPECT_EQ(kMemoryUnusable, smap[1].type); */ -/* EXPECT_EQ(0x14000, smap[2].addr); */ -/* EXPECT_EQ(0x1000, smap[2].size); */ -/* EXPECT_EQ(kMemoryBad, smap[2].type); */ -/* tfree(smap); */ -/* } */ - -/* TEST(smapsort, testUnsorted_sortsByAddress) { */ -/* struct SmapEntry *smap = tmalloc(4 * sizeof(struct SmapEntry)); */ -/* memset(smap, 0, 4 * sizeof(struct SmapEntry)); */ -/* smap[2].addr = 0; */ -/* smap[2].size = 0x7000; */ -/* smap[2].type = kMemoryUsable; */ -/* smap[0].addr = 0x7000; */ -/* smap[0].size = 0x1000; */ -/* smap[0].type = kMemoryUnusable; */ -/* smap[1].addr = 0x14000; */ -/* smap[1].size = 0x1000; */ -/* smap[1].type = kMemoryBad; */ -/* smapsort(smap); */ -/* EXPECT_EQ(0, smap[0].addr); */ -/* EXPECT_EQ(0x7000, smap[0].size); */ -/* EXPECT_EQ(kMemoryUsable, smap[0].type); */ -/* EXPECT_EQ(0x7000, smap[1].addr); */ -/* EXPECT_EQ(0x1000, smap[1].size); */ -/* EXPECT_EQ(kMemoryUnusable, smap[1].type); */ -/* EXPECT_EQ(0x14000, smap[2].addr); */ -/* EXPECT_EQ(0x1000, smap[2].size); */ -/* EXPECT_EQ(kMemoryBad, smap[2].type); */ -/* tfree(smap); */ -/* } */ diff --git a/test/ape/lib/test.mk b/test/ape/lib/test.mk deleted file mode 100644 index e340fa8f2..000000000 --- a/test/ape/lib/test.mk +++ /dev/null @@ -1,55 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -PKGS += TEST_APE_LIB - -TEST_APE_LIB_SRCS := $(wildcard test/ape/lib/*.c) -TEST_APE_LIB_SRCS_TEST = $(filter %_test.c,$(TEST_APE_LIB_SRCS)) - -TEST_APE_LIB_OBJS = \ - $(TEST_APE_LIB_SRCS:%.c=o/$(MODE)/%.o) - -TEST_APE_LIB_COMS = \ - $(TEST_APE_LIB_SRCS:%.c=o/$(MODE)/%.com) - -TEST_APE_LIB_BINS = \ - $(TEST_APE_LIB_COMS) \ - $(TEST_APE_LIB_COMS:%=%.dbg) - -TEST_APE_LIB_TESTS = \ - $(TEST_APE_LIB_SRCS_TEST:%.c=o/$(MODE)/%.com.ok) - -TEST_APE_LIB_CHECKS = \ - $(TEST_APE_LIB_SRCS_TEST:%.c=o/$(MODE)/%.com.runs) - -TEST_APE_LIB_DIRECTDEPS = \ - APE_LIB \ - LIBC_INTRIN \ - LIBC_LOG \ - LIBC_MEM \ - LIBC_NEXGEN32E \ - LIBC_RUNTIME \ - LIBC_STR \ - LIBC_STUBS \ - LIBC_TESTLIB \ - LIBC_X - -TEST_APE_LIB_DEPS := \ - $(call uniq,$(foreach x,$(TEST_APE_LIB_DIRECTDEPS),$($(x)))) - -o/$(MODE)/test/ape/lib.pkg: \ - $(TEST_APE_LIB_OBJS) \ - $(foreach x,$(TEST_APE_LIB_DIRECTDEPS),$($(x)_A).pkg) - -o/$(MODE)/test/ape/lib/%.com.dbg: \ - $(TEST_APE_LIB_DEPS) \ - o/$(MODE)/test/ape/lib/%.o \ - o/$(MODE)/test/ape/lib.pkg \ - $(LIBC_TESTMAIN) \ - $(CRT) \ - $(APE) - @$(APELINK) - -.PHONY: o/$(MODE)/test/ape/lib -o/$(MODE)/test/ape/lib: $(TEST_APE_LIB_BINS) \ - $(TEST_APE_LIB_CHECKS) diff --git a/test/ape/test.mk b/test/ape/test.mk deleted file mode 100644 index cd60a65f0..000000000 --- a/test/ape/test.mk +++ /dev/null @@ -1,5 +0,0 @@ -#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐ -#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ - -.PHONY: o/$(MODE)/test/ape -o/$(MODE)/test/ape: o/$(MODE)/test/ape/lib diff --git a/test/test.mk b/test/test.mk index ac1c02d1f..02f1f4274 100644 --- a/test/test.mk +++ b/test/test.mk @@ -2,8 +2,7 @@ #───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘ .PHONY: o/$(MODE)/test -o/$(MODE)/test: o/$(MODE)/test/ape \ - o/$(MODE)/test/dsp \ +o/$(MODE)/test: o/$(MODE)/test/dsp \ o/$(MODE)/test/libc \ o/$(MODE)/test/net \ o/$(MODE)/test/tool diff --git a/third_party/chibicc/test/test.h b/third_party/chibicc/test/test.h index 7d1a35376..e6a6e4c7c 100644 --- a/third_party/chibicc/test/test.h +++ b/third_party/chibicc/test/test.h @@ -3,7 +3,7 @@ #include "libc/stdio/stdio.h" #include "libc/str/str.h" -STATIC_YOINK("__mmap"); /* asan needs it */ +STATIC_YOINK("sys_mmap"); /* asan needs it */ STATIC_YOINK("TrackMemoryInterval"); /* asan needs it */ #define ASSERT(x, y) Assert2(x, y, #y, __FILE__, __LINE__) diff --git a/tool/build/blinkenlights.c b/tool/build/blinkenlights.c index fa3b3cebd..47a336f23 100644 --- a/tool/build/blinkenlights.c +++ b/tool/build/blinkenlights.c @@ -2109,9 +2109,9 @@ static void OnE820(void) { if (Read32(m->dx) == 0x534D4150 && Read32(m->cx) == 24 && addr + sizeof(p) <= m->real.n) { if (!Read32(m->bx)) { - Write64(p + 000, 0); - Write64(p + 010, m->real.n); - Write32(p + 014, 1); + Write64(p + 0, 0); + Write64(p + 8, m->real.n); + Write32(p + 16, 1); memcpy(m->real.p + addr, p, sizeof(p)); SetWriteAddr(m, addr, sizeof(p)); Write32(m->cx, sizeof(p)); @@ -2716,6 +2716,7 @@ static void Tui(void) { ExecuteInstruction(m); ++opcount; if (!(action & CONTINUE) || interactive) { + if (!(action & CONTINUE)) ReactiveDraw(); ScrollMemoryViews(); } } else { @@ -2737,8 +2738,11 @@ static void Tui(void) { } while (tuimode); } else { if (OnHalt(interrupt)) { + ReactiveDraw(); + ScrollMemoryViews(); goto KeepGoing; } + ReactiveDraw(); ScrollOp(&pan.disassembly, GetDisIndex()); } TuiCleanup(); diff --git a/tool/build/compile.c b/tool/build/compile.c index be45681a4..0ea18f0ab 100644 --- a/tool/build/compile.c +++ b/tool/build/compile.c @@ -115,6 +115,7 @@ struct Command command; const char *const kSafeEnv[] = { "ADDR2LINE", // needed by GetAddr2linePath "MAKEFLAGS", // needed by IsRunningUnderMake + "MODE", // needed by test scripts "PATH", // needed by clang "PWD", // just seems plain needed "TERM", // needed by IsTerminalInarticulate diff --git a/tool/build/dis.c b/tool/build/dis.c index ac6e78a71..9bd17419b 100644 --- a/tool/build/dis.c +++ b/tool/build/dis.c @@ -281,9 +281,8 @@ int main(int argc, char *argv[]) { struct stat st; const char *path; if (argc == 1) { - path = "o/v127/examples/hello2.com.dbg"; - /* fprintf(stderr, "USAGE: %s ELF\n", program_invocation_name); */ - /* exit(1); */ + fprintf(stderr, "USAGE: %s ELF\n", program_invocation_name); + exit(1); } else { path = argv[1]; } diff --git a/tool/build/lib/diself.c b/tool/build/lib/diself.c index 03965f0f1..6231d6c24 100644 --- a/tool/build/lib/diself.c +++ b/tool/build/lib/diself.c @@ -100,6 +100,7 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) { d->syms.p[j].unique = i; d->syms.p[j].size = st[i].st_size; d->syms.p[j].name = st[i].st_name; + CHECK_GE(st[i].st_value, 0); d->syms.p[j].addr = st[i].st_value; d->syms.p[j].rank = -islocal + -isweak + -isabs + isprotected + isobject + isfunc; @@ -112,7 +113,14 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) { } static void DisSortSyms(struct Dis *d) { + size_t i, j; qsort(d->syms.p, d->syms.i, sizeof(struct DisSym), (void *)DisSymCompare); + for (i = 0; i < d->syms.i; ++i) { + if (!strcmp("_end", d->syms.stab + d->syms.p[i].name)) { + d->syms.i = i; + break; + } + } } static void DisCanonizeSyms(struct Dis *d) { @@ -178,6 +186,10 @@ long DisFindSym(struct Dis *d, int64_t addr) { l = m + 1; } } + if (r && d->syms.p[r - 1].addr < 256) { + /* XXX: prevent skewed binbase from doing weirdness */ + return -1; + } if (r && (addr == d->syms.p[r - 1].addr || (addr > d->syms.p[r - 1].addr && (addr <= d->syms.p[r - 1].addr + d->syms.p[r - 1].size || diff --git a/tool/build/lib/fpu.c b/tool/build/lib/fpu.c index dcaf02f4f..75178447a 100644 --- a/tool/build/lib/fpu.c +++ b/tool/build/lib/fpu.c @@ -16,9 +16,8 @@ │ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │ │ PERFORMANCE OF THIS SOFTWARE. │ ╚─────────────────────────────────────────────────────────────────────────────*/ -#include "ape/config.h" -#include "ape/lib/pc.h" #include "libc/math.h" +#include "libc/runtime/pc.internal.h" #include "libc/runtime/runtime.h" #include "libc/str/str.h" #include "tool/build/lib/case.h" @@ -988,7 +987,7 @@ static void OpFnop(struct Machine *m) { } void OpFinit(struct Machine *m) { - m->fpu.cw = X87_NORMAL; + m->fpu.cw = 0x037f; m->fpu.sw = 0; m->fpu.tw = -1; } diff --git a/tool/emacs/cosmo-c-keywords.el b/tool/emacs/cosmo-c-keywords.el index 1af8f1ca3..bd3372244 100644 --- a/tool/emacs/cosmo-c-keywords.el +++ b/tool/emacs/cosmo-c-keywords.el @@ -194,6 +194,7 @@ "forcealign" "typeof" "textreal" + "texthead" "autotype" "_Section" "_Vector_size")) diff --git a/tool/net/net.mk b/tool/net/net.mk index 35fd28468..df3978d5e 100644 --- a/tool/net/net.mk +++ b/tool/net/net.mk @@ -18,7 +18,6 @@ TOOL_NET_BINS = \ $(TOOL_NET_COMS:%=%.dbg) TOOL_NET_DIRECTDEPS = \ - APE_LIB \ LIBC_ALG \ LIBC_BITS \ LIBC_CALLS \