mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-31 19:43:32 +00:00
220 lines
15 KiB
C
220 lines
15 KiB
C
/*-*- 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 0b0000000000000000000000001
|
||
#define FPU_DE 0b0000000000000000000000010
|
||
#define FPU_ZE 0b0000000000000000000000100
|
||
#define FPU_OE 0b0000000000000000000001000
|
||
#define FPU_UE 0b0000000000000000000010000
|
||
#define FPU_PE 0b0000000000000000000100000
|
||
#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 /* */ 0b000000000001
|
||
#define PAGE_RW /* */ 0b000000000010
|
||
#define PAGE_U /* */ 0b000000000100
|
||
#define PAGE_4KB /* */ 0b000010000000
|
||
#define PAGE_2MB /* */ 0b000110000000
|
||
#define PAGE_1GB /* */ 0b000110000000
|
||
#define PAGE_IGN1 /* */ 0b111000000000
|
||
#define PAGE_RSRV /* blinkenlights reservation */ 0b001000000000
|
||
#define PAGE_GROD /* blinkenlights MAP_GROWSDOWN */ 0b010000000000
|
||
#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_ */
|