mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-04 02:08:30 +00:00
Support malloc() on bare metal
Your Actually Portable Executables now contains a simple virtual memory that works similarly to the Linux Kernel in the sense that it maps your physical memory to negative addresses. This is needed to support mmap() and malloc(). This functionality has zero code size impact. For example the MODE=tiny LIFE.COM executable is still only 12KB in size. The APE bootloader code has also been simplified to improve readibility and further elevate the elegance by which we're able to support so many platforms thereby enhancing verifiability so that we may engender trust in this bootloading process.
This commit is contained in:
parent
ac3b1dfb21
commit
edd9297eba
89 changed files with 900 additions and 1417 deletions
|
@ -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_ */
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 ─╬─│┼
|
||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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__
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
|
|
@ -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,
|
||||
|
|
|
@ -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) */
|
21
libc/runtime/e820.internal.h
Normal file
21
libc/runtime/e820.internal.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
80
libc/runtime/metalprintf.greg.c
Normal file
80
libc/runtime/metalprintf.greg.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*-*- 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 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 │
|
||||
│ 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/nexgen32e/uart.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
16
libc/runtime/metalprintf.internal.h
Normal file
16
libc/runtime/metalprintf.internal.h
Normal file
|
@ -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_ */
|
160
libc/runtime/mman.greg.c
Normal file
160
libc/runtime/mman.greg.c
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*-*- 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. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § no-frills virtual memory management │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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"
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
24
libc/runtime/mman.internal.h
Normal file
24
libc/runtime/mman.internal.h
Normal file
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
213
libc/runtime/pc.internal.h
Normal file
213
libc/runtime/pc.internal.h
Normal file
|
@ -0,0 +1,213 @@
|
|||
/*-*- 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│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ 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. │
|
||||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#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
|
||||
|
||||
#define kInterruptFlag (1u << 9)
|
||||
|
||||
/* FPU Status Word (x87)
|
||||
@see Intel Manual V1 §8.1.3
|
||||
IE: Invalid Operation ────────────────┐
|
||||
DE: Denormalized Operand ────────────┐│
|
||||
ZE: Zero Divide ────────────────────┐││
|
||||
OE: Overflow Flag ─────────────────┐│││
|
||||
UE: Underflow Flag ───────────────┐││││
|
||||
PE: Precision Flag ──────────────┐│││││
|
||||
SF: Stack Fault ────────────────┐││││││
|
||||
ES: Exception Summary Status ──┐│││││││
|
||||
C0-3: Condition Codes ──┬────┐ ││││││││
|
||||
TOP of Stack Pointer ─────┐ │ ││││││││
|
||||
B: FPU Busy ───────────┐│ │ │ ││││││││
|
||||
││┌┴┐┌┼┐││││││││
|
||||
│↓│ │↓↓↓││││││││*/
|
||||
#define FPU_IE 0b0000000000100000000000001
|
||||
#define FPU_ZE 0b0000000000100000000000100
|
||||
#define FPU_SF 0b0000000000000000001000000
|
||||
#define FPU_C0 0b0000000000000000100000000
|
||||
#define FPU_C1 0b0000000000000001000000000
|
||||
#define FPU_C2 0b0000000000000010000000000
|
||||
#define FPU_C3 0b0000000000100000000000000
|
||||
|
||||
#define CR0_PE 0x01 /* protected mode enabled */
|
||||
#define CR0_MP 0x02 /* monitor coprocessor */
|
||||
#define CR0_EM 0x04 /* no x87 fpu present if set */
|
||||
#define CR0_TS 0x08 /* task switched x87 */
|
||||
#define CR0_ET 0x10 /* extension type 287 or 387 */
|
||||
#define CR0_NE 0x20 /* enable x87 error reporting */
|
||||
#define CR0_WP 0x00010000 /* write protect read-only pages @pl0 */
|
||||
#define CR0_AM 0x00040000 /* alignment mask */
|
||||
#define CR0_NW 0x20000000 /* global write-through cache disable */
|
||||
#define CR0_CD 0x40000000 /* global cache disable */
|
||||
#define CR0_PG 0x80000000 /* paging enabled */
|
||||
|
||||
#define CR4_VME 0x01 /* virtual 8086 mode extension */
|
||||
#define CR4_PVI 0x02 /* protected mode virtual interrupts */
|
||||
#define CR4_TSD 0x04 /* time stamp disable (rdtsc) */
|
||||
#define CR4_DE 0x08 /* debugging extensions */
|
||||
#define CR4_PSE 0x10 /* page size extension */
|
||||
#define CR4_PAE 0x20 /* physical address extension */
|
||||
#define CR4_MCE 0x40 /* machine check exception */
|
||||
#define CR4_PGE 0x80 /* page global enabled */
|
||||
#define CR4_OSFXSR 0x0200 /* enable SSE and fxsave/fxrestor */
|
||||
#define CR4_OSXMMEXCPT 0x0400 /* enable unmasked SSE exceptions */
|
||||
#define CR4_LA57 0x1000 /* enable level-5 paging */
|
||||
#define CR4_VMXE 0x2000 /* enable VMX operations */
|
||||
#define CR4_SMXE 0x4000 /* enable SMX operations */
|
||||
#define CR4_FSGSBASE 0x00010000 /* enable *FSBASE and *GSBASE instructions */
|
||||
#define CR4_PCIDE 0x00020000 /* enable process-context identifiers */
|
||||
#define CR4_OSXSAVE 0x00040000 /* enable XSAVE */
|
||||
|
||||
#define XCR0_X87 0x01
|
||||
#define XCR0_SSE 0x02
|
||||
#define XCR0_AVX 0x04
|
||||
#define XCR0_BNDREG 0x08
|
||||
#define XCR0_BNDCSR 0x10
|
||||
#define XCR0_OPMASK 0x20
|
||||
#define XCR0_ZMM_HI256 0x40
|
||||
#define XCR0_HI16_ZMM 0x80
|
||||
|
||||
#define EFER 0xc0000080 /* extended feature enable register */
|
||||
#define EFER_SCE 0x01 /* system call extensions */
|
||||
#define EFER_LME 0x0100 /* long mode enable */
|
||||
#define EFER_LMA 0x0400 /* long mode active */
|
||||
#define EFER_NXE 0x0800 /* no-execute enable */
|
||||
|
||||
#define GDT_REAL_CODE 8
|
||||
#define GDT_REAL_DATA 16
|
||||
#define GDT_LEGACY_CODE 24
|
||||
#define GDT_LEGACY_DATA 32
|
||||
#define GDT_LONG_CODE 40
|
||||
#define GDT_LONG_DATA 48
|
||||
|
||||
#define PIC1 0x20 /* IO base address for master PIC */
|
||||
#define PIC2 0xA0 /* IO base address for slave PIC */
|
||||
#define PIC1_CMD PIC1
|
||||
#define PIC1_DATA (PIC1 + 1)
|
||||
#define PIC2_CMD PIC2
|
||||
#define PIC2_DATA (PIC2 + 1)
|
||||
#define PIC_EOI 0x20 /* End-of-interrupt command code */
|
||||
#define PIC_READ_IRR 0x0a /* OCW3 irq ready next CMD read */
|
||||
#define PIC_READ_ISR 0x0b /* OCW3 irq service next CMD read */
|
||||
|
||||
/* Long Mode Paging
|
||||
@see Intel Manual V.3A §4.1 §4.5
|
||||
IsValid (ignored on CR3) V┐
|
||||
┌XD:No Inst. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
||||
│ Permit User-Mode Access - u┐││
|
||||
│ Page-level Write-Through - PWT┐│││
|
||||
│ Page-level Cache Disable - PCD┐││││
|
||||
│ Set if has been read - Accessed┐│││││
|
||||
│ Set if has been written - Dirty┐││││││
|
||||
│ IsPage (if PDPTE/PDE) or PAT (if PT)┐│││││││
|
||||
│ (If this maps 2MB/1GB page and CR4.PGE) Global┐││││││││
|
||||
│ (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT │││││││││
|
||||
│ │ │││││││││
|
||||
│ ┌────────────────────────────────────┤ │││││││││
|
||||
│ Must Be 0┐│ Next Page Table Address (!IsPage) │ │││││││││
|
||||
│ │├────────────────────────────────────┤ │││││││││
|
||||
│ ││ Physical Address 4KB │ │││││││││
|
||||
│┌───┐┌─────┐│├───────────────────────────┐ │ign│││││││││
|
||||
││PKE││ ign │││ Physical Address 2MB │ │┌┴┐│││││││││
|
||||
││ ││ ││├──────────────────┐ │ ││ ││││││││││
|
||||
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
||||
││ ││ │││ │ │ ││ ││││││││││
|
||||
6666555555555544444444443333333333222222222211111111110000000000
|
||||
3210987654321098765432109876543210987654321098765432109876543210*/
|
||||
#define PAGE_V /* */ 0b000000001
|
||||
#define PAGE_RW /* */ 0b000000010
|
||||
#define PAGE_U /* */ 0b000000100
|
||||
#define PAGE_4KB /* */ 0b010000000
|
||||
#define PAGE_2MB /* */ 0b110000000
|
||||
#define PAGE_1GB /* */ 0b110000000
|
||||
#define PAGE_TA 0x00007ffffffff000
|
||||
#define PAGE_PA2 0x00007fffffe00000
|
||||
#define PAGE_XD 0x8000000000000000
|
||||
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define invlpg(p) asm volatile("invlpg\t(%0)" : : "r"(p) : "memory")
|
||||
|
||||
struct IdtDescriptor {
|
||||
uint16_t offset_1; /* offset bits 0..15 */
|
||||
uint16_t selector; /* a code segment selector in GDT or LDT */
|
||||
uint8_t ist; /* bits 0..2 hold stack table offset, rest are zero */
|
||||
uint8_t type_attr; /* type and attributes */
|
||||
uint16_t offset_2; /* offset bits 16..31 */
|
||||
uint32_t offset_3; /* offset bits 32..63 */
|
||||
uint32_t zero; /* reserved */
|
||||
};
|
||||
|
||||
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;
|
||||
asm volatile("inb\t%1,%0" : "=a"(al) : "dN"(port));
|
||||
return al;
|
||||
}
|
||||
|
||||
forceinline void outb(unsigned short port, unsigned char byte) {
|
||||
asm volatile("outb\t%0,%1"
|
||||
: /* no inputs */
|
||||
: "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 /* COSMOPOLITAN_LIBC_RUNTIME_PC_H_ */
|
|
@ -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
|
||||
|
|
|
@ -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(
|
||||
|
|
2
libc/sysv/calls/__sys_mmap.s
Normal file
2
libc/sysv/calls/__sys_mmap.s
Normal file
|
@ -0,0 +1,2 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall __sys_mmap,0x0c50c51dd20c5009,globl,hidden
|
|
@ -1,2 +0,0 @@
|
|||
.include "o/libc/sysv/macros.internal.inc"
|
||||
.scall sys_mmap,0x0c50c51dd20c5009,globl,hidden
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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__
|
||||
|
||||
|
|
|
@ -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 \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue