Files
Justine Tunney 40291c9db3 Improve signal handling and math
- Polyfill ucontext_t on FreeBSD/OpenBSD/NetBSD
- Add tests confirming signals can edit CPU state
- Work towards supporting ZIP filesystem on bare metal
- Add more tinymath unit tests for POSIX conformance
- Add X87 and SSE status flags to crash report
- Fix some bugs in blinkenlights
- Fix llvm build breakage
2021-02-25 18:33:33 -08:00

218 lines
14 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 /* */ 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_ */