2020-06-15 14:18:57 +00:00
|
|
|
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
|
|
|
|
│ vi: set et ft=c ts=8 sts=2 sw=2 fenc=utf-8 :vi │
|
|
|
|
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
|
|
|
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
|
|
|
|
│ │
|
2020-12-28 01:18:44 +00:00
|
|
|
|
│ 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. │
|
2020-06-15 14:18:57 +00:00
|
|
|
|
│ │
|
2020-12-28 01:18:44 +00:00
|
|
|
|
│ 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. │
|
2020-06-15 14:18:57 +00:00
|
|
|
|
╠──────────────────────────────────────────────────────────────────────────────╣
|
|
|
|
|
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
|
|
|
|
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
|
|
|
|
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
|
|
|
|
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
|
|
|
|
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
|
|
|
|
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
|
|
|
|
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
|
|
|
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#ifndef COSMOPOLITAN_LIBC_RUNTIME_PC_H_
|
|
|
|
|
#define COSMOPOLITAN_LIBC_RUNTIME_PC_H_
|
|
|
|
|
#include "libc/runtime/e820.internal.h"
|
|
|
|
|
#include "libc/runtime/mman.internal.h"
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#define BANE -140737488355328
|
2020-06-15 14:18:57 +00:00
|
|
|
|
#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 ──┬────┐ ││││││││
|
2020-08-25 11:23:25 +00:00
|
|
|
|
TOP of Stack Pointer ─────┐ │ ││││││││
|
2020-06-15 14:18:57 +00:00
|
|
|
|
B: FPU Busy ───────────┐│ │ │ ││││││││
|
|
|
|
|
││┌┴┐┌┼┐││││││││
|
|
|
|
|
│↓│ │↓↓↓││││││││*/
|
2021-02-26 02:30:17 +00:00
|
|
|
|
#define FPU_IE 0b0000000000000000000000001
|
|
|
|
|
#define FPU_DE 0b0000000000000000000000010
|
|
|
|
|
#define FPU_ZE 0b0000000000000000000000100
|
|
|
|
|
#define FPU_OE 0b0000000000000000000001000
|
|
|
|
|
#define FPU_UE 0b0000000000000000000010000
|
|
|
|
|
#define FPU_PE 0b0000000000000000000100000
|
2020-08-25 11:23:25 +00:00
|
|
|
|
#define FPU_SF 0b0000000000000000001000000
|
2020-06-15 14:18:57 +00:00
|
|
|
|
#define FPU_C0 0b0000000000000000100000000
|
|
|
|
|
#define FPU_C1 0b0000000000000001000000000
|
|
|
|
|
#define FPU_C2 0b0000000000000010000000000
|
|
|
|
|
#define FPU_C3 0b0000000000100000000000000
|
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
|
#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 */
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
|
#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 */
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
|
#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
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
2021-02-08 17:19:00 +00:00
|
|
|
|
#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 */
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
|
|
|
|
#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
|
2022-09-29 21:43:08 +00:00
|
|
|
|
#define GDT_LONG_TSS 56
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
|
|
|
|
#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┐
|
2020-10-27 10:39:46 +00:00
|
|
|
|
┌XD:No Inst. Fetches (if NXE) IsWritable (ignored on CR3) RW┐│
|
2020-06-15 14:18:57 +00:00
|
|
|
|
│ 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┐││││││
|
2023-02-24 19:49:08 +00:00
|
|
|
|
│ IsPage 2MB/1GB (if PDPTE/PDE) or PAT (if PT)┐│││││││
|
|
|
|
|
│ (If this maps page and CR4.PGE) Global┐││││││││
|
2020-06-15 14:18:57 +00:00
|
|
|
|
│ (If IsPage 2MB/1GB, see Intel V3A § 11.12) PAT │││││││││
|
|
|
|
|
│ │ │││││││││
|
2022-11-06 07:29:47 +00:00
|
|
|
|
│ ┌─────────────────────────────────────┤ │││││││││
|
|
|
|
|
│ Must Be 0┐│ Next Page Table Address (!IsPage) │ │││││││││
|
|
|
|
|
│ │├─────────────────────────────────────┤ │││││││││
|
|
|
|
|
│ ││ Physical Address 4KB │ │││││││││
|
|
|
|
|
│┌──┐┌─────┐│├────────────────────────────┐ │ign│││││││││
|
|
|
|
|
││PK││ ign │││ Physical Address 2MB │ │┌┴┐│││││││││
|
|
|
|
|
││ ││ ││├───────────────────┐ │ ││ ││││││││││
|
|
|
|
|
││ ││ │││ Phys. Addr. 1GB │ │ ││ ││││││││││
|
|
|
|
|
││ ││ │││ │ │ ││ ││││││││││
|
2020-06-15 14:18:57 +00:00
|
|
|
|
6666555555555544444444443333333333222222222211111111110000000000
|
|
|
|
|
3210987654321098765432109876543210987654321098765432109876543210*/
|
2022-05-13 20:31:21 +00:00
|
|
|
|
#define PAGE_V /* */ 0b000000000001
|
|
|
|
|
#define PAGE_RW /* */ 0b000000000010
|
|
|
|
|
#define PAGE_U /* */ 0b000000000100
|
2023-09-06 10:41:07 +00:00
|
|
|
|
#define PAGE_PCD /* */ 0b000000010000
|
2023-02-24 19:49:08 +00:00
|
|
|
|
#define PAGE_PS /* */ 0b000010000000
|
|
|
|
|
#define PAGE_G /* */ 0b000100000000
|
2022-05-13 20:31:21 +00:00
|
|
|
|
#define PAGE_IGN1 /* */ 0b111000000000
|
2022-11-06 07:29:47 +00:00
|
|
|
|
#define PAGE_RSRV /* blinkenlights/libc reservation */ 0b001000000000
|
2022-05-13 20:31:21 +00:00
|
|
|
|
#define PAGE_GROD /* blinkenlights MAP_GROWSDOWN */ 0b010000000000
|
|
|
|
|
#define PAGE_TA 0x00007ffffffff000
|
|
|
|
|
#define PAGE_PA2 0x00007fffffe00000
|
2022-12-18 01:51:20 +00:00
|
|
|
|
#define PAGE_IGN2 0x07f0000000000000
|
|
|
|
|
#define PAGE_REFC PAGE_IGN2 /* libc reference counting */
|
|
|
|
|
#define PAGE_1REF 0x0010000000000000 /* libc reference counting */
|
2022-05-13 20:31:21 +00:00
|
|
|
|
#define PAGE_XD 0x8000000000000000
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
|
|
|
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
|
|
|
|
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#define invlpg(p) asm volatile("invlpg\t(%0)" : : "r"(p) : "memory")
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
|
|
|
|
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 */
|
|
|
|
|
};
|
|
|
|
|
|
2021-02-24 04:23:19 +00:00
|
|
|
|
uint64_t *__get_virtual(struct mman *, uint64_t *, int64_t, bool);
|
|
|
|
|
uint64_t __clear_page(uint64_t);
|
|
|
|
|
uint64_t __new_page(struct mman *);
|
2023-03-06 00:12:11 +00:00
|
|
|
|
uint64_t *__invert_memory_area(struct mman *, uint64_t *, uint64_t, uint64_t,
|
|
|
|
|
uint64_t);
|
2022-12-18 01:51:20 +00:00
|
|
|
|
void __map_phdrs(struct mman *, uint64_t *, uint64_t, uint64_t);
|
|
|
|
|
void __reclaim_boot_pages(struct mman *, uint64_t, uint64_t);
|
|
|
|
|
void __ref_page(struct mman *, uint64_t *, uint64_t);
|
|
|
|
|
void __ref_pages(struct mman *, uint64_t *, uint64_t, uint64_t);
|
|
|
|
|
void __unref_page(struct mman *, uint64_t *, uint64_t);
|
2020-06-15 14:18:57 +00:00
|
|
|
|
|
2023-09-06 10:41:07 +00:00
|
|
|
|
/**
|
|
|
|
|
* Identity maps an area of physical memory to its negative address and
|
|
|
|
|
* marks it as permanently referenced and unreclaimable (so that it will
|
|
|
|
|
* never be added to the free list). This is useful for special-purpose
|
|
|
|
|
* physical memory regions, such as video frame buffers and memory-mapped
|
|
|
|
|
* I/O devices.
|
|
|
|
|
*/
|
|
|
|
|
forceinline void __invert_and_perm_ref_memory_area(struct mman *mm,
|
|
|
|
|
uint64_t *pml4t, uint64_t ps,
|
|
|
|
|
uint64_t size,
|
|
|
|
|
uint64_t pte_flags) {
|
|
|
|
|
__invert_memory_area(mm, pml4t, ps, size, pte_flags | PAGE_REFC);
|
|
|
|
|
}
|
|
|
|
|
|
2020-06-15 14:18:57 +00:00
|
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#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); \
|
|
|
|
|
})
|
|
|
|
|
|
2023-06-11 17:32:39 +00:00
|
|
|
|
#define __get_mm() ((struct mman *)(BANE + 0x0500))
|
|
|
|
|
#define __get_mm_phy() ((struct mman *)0x0500)
|
|
|
|
|
|
2020-06-15 14:18:57 +00:00
|
|
|
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
2021-02-24 04:23:19 +00:00
|
|
|
|
#endif /* COSMOPOLITAN_LIBC_RUNTIME_PC_H_ */
|