244 lines
15 KiB
C
244 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 │
|
||
│ │
|
||
│ This program is free software; you can redistribute it and/or modify │
|
||
│ it under the terms of the GNU General Public License as published by │
|
||
│ the Free Software Foundation; version 2 of the License. │
|
||
│ │
|
||
│ This program is distributed in the hope that it will be useful, but │
|
||
│ WITHOUT ANY WARRANTY; without even the implied warranty of │
|
||
│ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU │
|
||
│ General Public License for more details. │
|
||
│ │
|
||
│ You should have received a copy of the GNU General Public License │
|
||
│ along with this program; if not, write to the Free Software │
|
||
│ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA │
|
||
│ 02110-1301 USA │
|
||
╠──────────────────────────────────────────────────────────────────────────────╣
|
||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░█▀█░█▀█░▀█▀░█░█░█▀█░█░░░█░░░█░█░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░█▀█░█░▄░░█░░█░█░█▀█░█░░░█░░░▀█▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀▀▀░░▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░█▀█░█▀█░█▀█░▀█▀░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░█▀▀░█ █░██▀░░█░░█▀█░█▀█░█░░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░▀░░░▀▀▀░▀░▀░░▀░░▀░▀░▀▀▀░▀▀▀░▀▀▀░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░│
|
||
│░░░░░░░█▀▀░█░█░█▀▀░█▀█░█░█░▀█▀░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░░░░░░░░░░░░░▄▄░░░▐█░░│
|
||
│░░░░░░░█▀▀░▄▀▄░█▀▀░█░▄░█░█░░█░░█▀█░█▀█░█░░█▀▀░░░░░░░░░░░░▄▄▄░░░▄██▄░░█▀░░░█░▄░│
|
||
│░░░░░░░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀▀▀░░▀░░▀░▀░▀▀▀░▀▀░▀▀▀░░░░░░░░░░▄██▀█▌░██▄▄░░▐█▀▄░▐█▀░░│
|
||
│░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░▐█▀▀▌░░░▄▀▌░▌░█░▌░░▌░▌░░│
|
||
╠──────────────────────────────────────────────────────▌▀▄─▐──▀▄─▐▄─▐▄▐▄─▐▄─▐▄─│
|
||
│ αcτµαlly pδrταblε εxεcµταblε § ibm personal computer │
|
||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||
#ifndef APE_LIB_PC_H_
|
||
#define APE_LIB_PC_H_
|
||
|
||
#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 (1u << 0) /* protected mode enabled */
|
||
#define CR0_MP (1u << 1) /* monitor coprocessor */
|
||
#define CR0_EM (1u << 2) /* no x87 fpu present if set */
|
||
#define CR0_TS (1u << 3) /* task switched x87 */
|
||
#define CR0_ET (1u << 4) /* extension type 287 or 387 */
|
||
#define CR0_NE (1u << 5) /* enable x87 error reporting */
|
||
#define CR0_WP (1u << 16) /* write protect read-only pages @pl0 */
|
||
#define CR0_AM (1u << 18) /* alignment mask */
|
||
#define CR0_NW (1u << 29) /* global write-through cache disable */
|
||
#define CR0_CD (1u << 30) /* global cache disable */
|
||
#define CR0_PG (1u << 31) /* paging enabled */
|
||
|
||
#define CR4_VME (1u << 0) /* virtual 8086 mode extension */
|
||
#define CR4_PVI (1u << 1) /* protected mode virtual interrupts */
|
||
#define CR4_TSD (1u << 2) /* time stamp disable (rdtsc) */
|
||
#define CR4_DE (1u << 3) /* debugging extensions */
|
||
#define CR4_PSE (1u << 4) /* page size extension */
|
||
#define CR4_PAE (1u << 5) /* physical address extension */
|
||
#define CR4_MCE (1u << 6) /* machine check exception */
|
||
#define CR4_PGE (1u << 7) /* page global enabled */
|
||
#define CR4_OSFXSR (1u << 9) /* enable SSE and fxsave/fxrestor */
|
||
#define CR4_OSXMMEXCPT (1u << 10) /* enable unmasked SSE exceptions */
|
||
#define CR4_LA57 (1u << 12) /* enable level-5 paging */
|
||
#define CR4_VMXE (1u << 13) /* enable VMX operations */
|
||
#define CR4_SMXE (1u << 14) /* enable SMX operations */
|
||
#define CR4_FSGSBASE (1u << 16) /* enable *FSBASE and *GSBASE instructions */
|
||
#define CR4_PCIDE (1u << 17) /* enable process-context identifiers */
|
||
#define CR4_OSXSAVE (1u << 18) /* enable XSAVE */
|
||
|
||
#define XCR0_X87 (1u << 0)
|
||
#define XCR0_SSE (1u << 1)
|
||
#define XCR0_AVX (1u << 2)
|
||
#define XCR0_BNDREG (1u << 3)
|
||
#define XCR0_BNDCSR (1u << 4)
|
||
#define XCR0_OPMASK (1u << 5)
|
||
#define XCR0_ZMM_HI256 (1u << 6)
|
||
#define XCR0_HI16_ZMM (1u << 7)
|
||
|
||
#define EFER 0xC0000080 /* extended feature enable register */
|
||
#define EFER_SCE (1u << 0) /* system call extensions */
|
||
#define EFER_LME (1u << 8) /* long mode enable */
|
||
#define EFER_LMA (1u << 10) /* long mode active */
|
||
#define EFER_NXE (1u << 11) /* 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 0b11111111111111111111111111111111111111000000000000
|
||
#define PAGE_PA2 0b11111111111111111111111111111000000000000000000000
|
||
#define PAGE_XD 0x8000000000000000
|
||
|
||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||
#include "ape/config.h"
|
||
|
||
struct thatispacked GlobalDescriptorTable {
|
||
uint16_t size;
|
||
uint64_t *entries;
|
||
};
|
||
|
||
/**
|
||
* Memory hole map.
|
||
* @see wiki.osdev.org/Detecting_Memory_(x86)
|
||
* @since 2002
|
||
*/
|
||
struct SmapEntry {
|
||
uint64_t addr;
|
||
uint64_t size;
|
||
enum {
|
||
kMemoryUsable = 1,
|
||
kMemoryUnusable = 2,
|
||
kMemoryAcpiReclaimable = 3,
|
||
kMemoryAcpiNvs = 4,
|
||
kMemoryBad = 5
|
||
} type;
|
||
uint32_t __acpi3; /* is abstracted */
|
||
};
|
||
|
||
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 */
|
||
};
|
||
|
||
struct thatispacked PageTable {
|
||
uint64_t p[512];
|
||
} forcealign(PAGESIZE);
|
||
|
||
extern struct PageTable g_pml4t;
|
||
extern struct GlobalDescriptorTable gdt;
|
||
|
||
extern const unsigned char kBiosDataArea[256];
|
||
extern const unsigned char kBiosDataAreaXlm[256];
|
||
|
||
extern struct SmapEntry e820map[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||
extern struct SmapEntry e820map_xlm[XLM_E820_SIZE / sizeof(struct SmapEntry)];
|
||
|
||
extern uint64_t g_ptsp;
|
||
extern uint64_t g_ptsp_xlm;
|
||
|
||
void bootdr(char drive) wontreturn;
|
||
|
||
void smapsort(struct SmapEntry *);
|
||
uint64_t *__getpagetableentry(int64_t, unsigned, struct PageTable *,
|
||
uint64_t *);
|
||
void flattenhighmemory(struct SmapEntry *, struct PageTable *, uint64_t *);
|
||
void pageunmap(int64_t);
|
||
|
||
forceinline unsigned long eflags(void) {
|
||
unsigned long res;
|
||
asm("pushf\n\t"
|
||
"pop\t%0"
|
||
: "=rm"(res));
|
||
return res;
|
||
}
|
||
|
||
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));
|
||
}
|
||
|
||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||
#endif /* APE_LIB_PC_H_ */
|