Compare commits
3 Commits
92ccd189e7
...
182c6e2956
Author | SHA1 | Date | |
---|---|---|---|
182c6e2956 | |||
9d8849a425 | |||
3f6df79885 |
@ -17,7 +17,7 @@ CFLAGS += -I. \
|
||||
-DUACPI_BAREBONES_MODE
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
CFLAGS += -I./hal/x86_64/uACPI/include
|
||||
CFLAGS += -Ihal/x86_64/uACPI/include
|
||||
endif
|
||||
|
||||
ifeq ($(PUTCHAR_),fb)
|
||||
@ -58,8 +58,7 @@ SRCFILES := $(wildcard *.c) \
|
||||
$(wildcard flanterm/src/flanterm_backends/*.c)
|
||||
|
||||
ifeq ($(ARCH),x86_64)
|
||||
SRCFILES += $(wildcard hal/x86_64/uACPI/source/*.c)
|
||||
SRCFILES += $(wildcard hal/x86_64/port-uACPI/*.c)
|
||||
SRCFILES += $(wildcard hal/x86_64/uACPI/source/*.c)
|
||||
endif
|
||||
|
||||
CFILES := $(filter %.c,$(SRCFILES))
|
||||
|
@ -2,5 +2,6 @@
|
||||
#define COMPILER_ATTR_H_
|
||||
|
||||
#define PACKED __attribute__((packed))
|
||||
#define ALIGNED(x) __attribute__((aligned((x))))
|
||||
|
||||
#endif // COMPILER_ATTR_H_
|
||||
|
@ -1,32 +1,80 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "uacpi/uacpi.h"
|
||||
#include "uacpi/utilities.h"
|
||||
#include "hal/hal.h"
|
||||
#include "kprintf.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
#include "compiler/attr.h"
|
||||
#include "acpi.h"
|
||||
#include "assert.h"
|
||||
#include "util/util.h"
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "uacpi/uacpi.h"
|
||||
#include "uacpi/acpi.h"
|
||||
#include "apic.h"
|
||||
|
||||
#define PREINIT_BUFFER_SIZE 0x1000
|
||||
struct acpi_madt *MADT = NULL;
|
||||
|
||||
// uACPI
|
||||
|
||||
void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char *s) {
|
||||
char *t = NULL;
|
||||
switch (lvl) {
|
||||
case UACPI_LOG_INFO: t = "Info"; break;
|
||||
case UACPI_LOG_WARN: t = "Warn"; break;
|
||||
case UACPI_LOG_DEBUG: t = "Dbg"; break;
|
||||
case UACPI_LOG_ERROR: t = "Err"; break;
|
||||
case UACPI_LOG_TRACE: t = "Trc"; break;
|
||||
}
|
||||
LOG("uACPI", "%s %s", t, s);
|
||||
}
|
||||
|
||||
void uacpi_kernel_unmap(void *addr, uacpi_size len) {
|
||||
// .
|
||||
}
|
||||
|
||||
void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
|
||||
return (void *)(BOOT_INFO.hhdm_off + addr);
|
||||
}
|
||||
|
||||
uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out) {
|
||||
*out = BOOT_INFO.rsdp;
|
||||
return UACPI_STATUS_OK;
|
||||
}
|
||||
|
||||
void acpi_init(void) {
|
||||
uacpi_status ret;
|
||||
uacpi_status r;
|
||||
|
||||
void *preinit_buffer = dlmalloc(PREINIT_BUFFER_SIZE);
|
||||
ret = uacpi_setup_early_table_access(preinit_buffer, PREINIT_BUFFER_SIZE);
|
||||
if (uacpi_unlikely_error(ret)) {
|
||||
ERR("acpi", "init err %s\n", uacpi_status_to_string(ret));
|
||||
size_t tmpbufsize = 0x1000;
|
||||
void *tmpbuf = dlmalloc(tmpbufsize);
|
||||
if (tmpbuf == NULL) {
|
||||
ERR("hal", "could not allocate uACPI tmp buf\n");
|
||||
hal_hang();
|
||||
}
|
||||
|
||||
/* if (uacpi_unlikely_error(ret)) { */
|
||||
/* ERR("acpi", "init err %s\n", uacpi_status_to_string(ret)); */
|
||||
/* hal_hang(); */
|
||||
/* } */
|
||||
|
||||
/* if (uacpi_unlikely_error(ret)) { */
|
||||
/* ERR("acpi", "init err %s\n", uacpi_status_to_string(ret)); */
|
||||
/* hal_hang(); */
|
||||
/* } */
|
||||
r = uacpi_setup_early_table_access(tmpbuf, tmpbufsize);
|
||||
if (uacpi_unlikely_error(r)) {
|
||||
ERR("hal", "uACPI init early table failed\n");
|
||||
hal_hang();
|
||||
}
|
||||
|
||||
LOG("hal", "acpi init\n");
|
||||
}
|
||||
|
||||
uint8_t acpi_remapirq(uint8_t irq) {
|
||||
uint64_t cur = (uint64_t)&MADT->entries;
|
||||
uint64_t end = cur + MADT->hdr.length;
|
||||
|
||||
while (cur < end) {
|
||||
struct acpi_entry_hdr *ent = (struct acpi_entry_hdr *)cur;
|
||||
|
||||
if (ent->type == ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE) {
|
||||
struct acpi_madt_interrupt_source_override *override = (struct acpi_madt_interrupt_source_override *)ent;
|
||||
if (override->source == irq) {
|
||||
return override->gsi;
|
||||
}
|
||||
}
|
||||
|
||||
cur += ent->length;
|
||||
}
|
||||
|
||||
return irq;
|
||||
}
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef HAL_ACPI_H_
|
||||
#define HAL_ACPI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "uacpi/acpi.h"
|
||||
|
||||
extern struct acpi_madt *MADT;
|
||||
|
||||
void acpi_init(void);
|
||||
uint8_t acpi_remapirq(uint8_t irq);
|
||||
|
||||
#endif // HAL_ACPI_H_
|
||||
|
125
kernel/hal/x86_64/apic.c
Normal file
125
kernel/hal/x86_64/apic.c
Normal file
@ -0,0 +1,125 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "apic.h"
|
||||
#include "uacpi/tables.h"
|
||||
#include "uacpi/acpi.h"
|
||||
#include "kprintf.h"
|
||||
#include "hal/hal.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "assert.h"
|
||||
#include "util/util.h"
|
||||
#include "cpu.h"
|
||||
#include "util/mmio.h"
|
||||
#include "acpi.h"
|
||||
|
||||
|
||||
typedef struct LApic {
|
||||
struct LApic *next;
|
||||
uint8_t id;
|
||||
} LApic;
|
||||
|
||||
uint8_t *IOAPIC;
|
||||
uint8_t *LAPIC;
|
||||
LApic *LAPICS = NULL;
|
||||
|
||||
void ioapic_write(uint8_t *base, uint8_t reg, uint32_t data) {
|
||||
mmiowrite32(base + IOAPIC_IOREGSEL, reg);
|
||||
mmiowrite32(base + IOAPIC_IOWIN, data);
|
||||
}
|
||||
|
||||
uint32_t ioapic_read(uint8_t *base, uint8_t reg) {
|
||||
mmiowrite32(base + IOAPIC_IOREGSEL, reg);
|
||||
return mmioread32(base + IOAPIC_IOWIN);
|
||||
}
|
||||
|
||||
void ioapic_setentry(uint8_t *base, uint8_t idx, uint64_t data) {
|
||||
ioapic_write(base, IOAPIC_IOREDTBL + idx * 2, (uint32_t) data);
|
||||
ioapic_write(base, IOAPIC_IOREDTBL + idx * 2 + 1, (uint32_t) (data >> 32));
|
||||
}
|
||||
|
||||
void ioapic_init(void) {
|
||||
uint32_t x = ioapic_read(IOAPIC, IOAPIC_IOAPICVER);
|
||||
uint32_t count = ((x >> 16) & 0xff) + 1;
|
||||
LOG("hal", "IOAPIC pins = %d\n", count);
|
||||
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
ioapic_setentry(IOAPIC, i, 1 << 16);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t lapic_read(uint32_t reg) {
|
||||
return mmioread32(LAPIC + reg);
|
||||
}
|
||||
|
||||
void lapic_write(uint32_t reg, uint32_t data) {
|
||||
mmiowrite32(LAPIC + reg, data);
|
||||
}
|
||||
|
||||
void lapic_init(void) {
|
||||
lapic_write(LAPIC_TPR, 0);
|
||||
lapic_write(LAPIC_DFR, 0xffffffff);
|
||||
lapic_write(LAPIC_LDR, 0x01000000);
|
||||
lapic_write(LAPIC_SVR, 0x100 | 0xff);
|
||||
}
|
||||
|
||||
uint32_t lapic_getid(void) {
|
||||
return lapic_read(LAPIC_ID) >> 24;
|
||||
}
|
||||
|
||||
void lapic_sendinit(uint32_t id) {
|
||||
lapic_write(LAPIC_ICRHI, id << ICR_DEST_SHIFT);
|
||||
lapic_write(LAPIC_ICRLO, ICR_INIT | ICR_PHYS | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND);
|
||||
while (lapic_read(LAPIC_ICRLO) & ICR_SEND_PENDING);
|
||||
}
|
||||
|
||||
void lapic_sendstartup(uint32_t id, uint32_t vec) {
|
||||
lapic_write(LAPIC_ICRHI, id << ICR_DEST_SHIFT);
|
||||
lapic_write(LAPIC_ICRLO, vec | ICR_STARTUP | ICR_PHYS | ICR_ASSERT | ICR_EDGE | ICR_NO_SHORTHAND);
|
||||
while (lapic_read(LAPIC_ICRLO) & ICR_SEND_PENDING);
|
||||
}
|
||||
|
||||
void apic_init(void) {
|
||||
uacpi_status r;
|
||||
|
||||
uacpi_table madt;
|
||||
r = uacpi_table_find_by_signature("APIC", &madt);
|
||||
if (r != UACPI_STATUS_OK) {
|
||||
ERR("hal", "could not find MADT\n");
|
||||
hal_hang();
|
||||
}
|
||||
MADT = madt.ptr;
|
||||
|
||||
LAPIC = (uint8_t *)(MADT->local_interrupt_controller_address + BOOT_INFO.hhdm_off);
|
||||
|
||||
uint64_t cur = (uint64_t)&MADT->entries;
|
||||
uint64_t end = cur + MADT->hdr.length;
|
||||
|
||||
while (cur < end) {
|
||||
struct acpi_entry_hdr *ent = (struct acpi_entry_hdr *)cur;
|
||||
|
||||
if (ent->type == ACPI_MADT_ENTRY_TYPE_IOAPIC) {
|
||||
struct acpi_madt_ioapic *ioapic = (struct acpi_madt_ioapic *)ent;
|
||||
IOAPIC = (uint8_t *)(ioapic->address + BOOT_INFO.hhdm_off);
|
||||
LOG("hal", "IOAPIC p=%p v=%p id=%d gsi=%d\n", ioapic->address, IOAPIC, ioapic->id, ioapic->gsi_base);
|
||||
} else if (ent->type == ACPI_MADT_ENTRY_TYPE_LAPIC) {
|
||||
struct acpi_madt_lapic *lapic = (struct acpi_madt_lapic *)ent;
|
||||
|
||||
LApic *new = dlmalloc(sizeof(*new));
|
||||
ASSERT("hal", new != NULL, "out of memory\n");
|
||||
new->id = lapic->id;
|
||||
LL_APPEND(LAPICS, new);
|
||||
LOG("hal", "LAPIC id=%d\n", lapic->id);
|
||||
} else if (ent->type == ACPI_MADT_ENTRY_TYPE_LAPIC_ADDRESS_OVERRIDE) {
|
||||
struct acpi_madt_lapic_address_override *override= (struct acpi_madt_lapic_address_override *)ent;
|
||||
uint8_t *prev = LAPIC;
|
||||
LAPIC = (uint8_t *)(override->address + BOOT_INFO.hhdm_off);
|
||||
LOG("hal", "LAPIC override %p -> %p (v)\n", prev, LAPIC);
|
||||
}
|
||||
|
||||
cur += ent->length;
|
||||
}
|
||||
|
||||
lapic_init();
|
||||
ioapic_init();
|
||||
}
|
70
kernel/hal/x86_64/apic.h
Normal file
70
kernel/hal/x86_64/apic.h
Normal file
@ -0,0 +1,70 @@
|
||||
#ifndef HAL_APIC_H_
|
||||
#define HAL_APIC_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define IOAPIC_IOREGSEL 0x00
|
||||
#define IOAPIC_IOWIN 0x10
|
||||
|
||||
#define IOAPIC_IOAPICID 0x00
|
||||
#define IOAPIC_IOAPICVER 0x01
|
||||
#define IOAPIC_IOAPICARB 0x02
|
||||
#define IOAPIC_IOREDTBL 0x10
|
||||
|
||||
#define LAPIC_ID 0x0020
|
||||
#define LAPIC_VER 0x0030
|
||||
#define LAPIC_TPR 0x0080
|
||||
#define LAPIC_APR 0x0090
|
||||
#define LAPIC_PPR 0x00A0
|
||||
#define LAPIC_EOI 0x00B0
|
||||
#define LAPIC_RRD 0x00C0
|
||||
#define LAPIC_LDR 0x00D0
|
||||
#define LAPIC_DFR 0x00E0
|
||||
#define LAPIC_SVR 0x00F0
|
||||
#define LAPIC_ISR 0x0100
|
||||
#define LAPIC_TMR 0x0180
|
||||
#define LAPIC_IRR 0x0200
|
||||
#define LAPIC_ESR 0x0280
|
||||
#define LAPIC_ICRLO 0x0300
|
||||
#define LAPIC_ICRHI 0x0310
|
||||
#define LAPIC_TIMER 0x0320
|
||||
#define LAPIC_THERMAL 0x0330
|
||||
#define LAPIC_PERF 0x0340
|
||||
#define LAPIC_LINT0 0x0350
|
||||
#define LAPIC_LINT1 0x0360
|
||||
#define LAPIC_ERROR 0x0370
|
||||
#define LAPIC_TICR 0x0380
|
||||
#define LAPIC_TCCR 0x0390
|
||||
#define LAPIC_TDCR 0x03E0
|
||||
|
||||
#define ICR_FIXED 0x00000000
|
||||
#define ICR_LOWEST 0x00000100
|
||||
#define ICR_SMI 0x00000200
|
||||
#define ICR_NMI 0x00000400
|
||||
#define ICR_INIT 0x00000500
|
||||
#define ICR_STARTUP 0x00000600
|
||||
#define ICR_PHYS 0x00000000
|
||||
#define ICR_LOGC 0x00000800
|
||||
#define ICR_IDLE 0x00000000
|
||||
#define ICR_SEND_PENDING 0x00001000
|
||||
#define ICR_DEASSERT 0x00000000
|
||||
#define ICR_ASSERT 0x00004000
|
||||
#define ICR_EDGE 0x00000000
|
||||
#define ICR_LEVEL 0x00008000
|
||||
#define ICR_NO_SHORTHAND 0x00000000
|
||||
#define ICR_SELF 0x00040000
|
||||
#define ICR_ALL_INC_SELF 0x00080000
|
||||
#define ICR_ALL_EXCL_SELF 0x000C0000
|
||||
|
||||
#define ICR_DEST_SHIFT 24
|
||||
|
||||
extern uint8_t *IOAPIC;
|
||||
|
||||
void apic_init(void);
|
||||
void ioapic_setentry(uint8_t *base, uint8_t idx, uint64_t data);
|
||||
uint32_t ioapic_read(uint8_t *base, uint8_t reg);
|
||||
void ioapic_write(uint8_t *base, uint8_t reg, uint32_t data);
|
||||
void lapic_write(uint32_t reg, uint32_t data);
|
||||
uint32_t lapic_read(uint32_t reg);
|
||||
|
||||
#endif // HAL_APIC_H_
|
14
kernel/hal/x86_64/cpu.c
Normal file
14
kernel/hal/x86_64/cpu.c
Normal file
@ -0,0 +1,14 @@
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
uint64_t cpu_rdmsr(uint32_t id) {
|
||||
uint32_t lo, hi;
|
||||
asm volatile("rdmsr" : "=m"(lo), "=d"(hi) : "c"(id));
|
||||
return ((uint64_t)lo) | ((uint64_t)hi << 32);
|
||||
}
|
||||
|
||||
uint64_t cpu_wrmsr(uint32_t id, uint64_t val) {
|
||||
uint32_t lo = val & 0xffffffff, hi = (val >> 32) & 0xffffffff;
|
||||
asm volatile("wrmsr" :: "a"(lo), "d"(hi), "c"(id) : "memory");
|
||||
return val;
|
||||
}
|
7
kernel/hal/x86_64/cpu.h
Normal file
7
kernel/hal/x86_64/cpu.h
Normal file
@ -0,0 +1,7 @@
|
||||
#ifndef HAL_CPU_H_
|
||||
#define HAL_CPU_H_
|
||||
|
||||
uint64_t cpu_rdmsr(uint32_t id);
|
||||
uint64_t cpu_wrmsr(uint32_t id, uint64_t val);
|
||||
|
||||
#endif // HAL_CPU_H_
|
@ -2,8 +2,18 @@
|
||||
#include <stddef.h>
|
||||
#include "compiler/attr.h"
|
||||
#include "hal/hal.h"
|
||||
#include "gdt.h"
|
||||
|
||||
#define GDT_SIZE 5
|
||||
#define GDT_PRESENT 0x80
|
||||
#define GDT_TSS 0x89
|
||||
|
||||
#define KSTACK 8192
|
||||
ALIGNED(16) static uint8_t kernelstack[KSTACK];
|
||||
|
||||
#define ISTS 7
|
||||
#define ISTACK 4096
|
||||
ALIGNED(16) static uint8_t iststacks[ISTS][ISTACK];
|
||||
|
||||
typedef struct {
|
||||
uint16_t limitlow;
|
||||
@ -31,64 +41,73 @@ typedef struct {
|
||||
uint64_t rsp1;
|
||||
uint64_t rsp2;
|
||||
uint64_t resv1;
|
||||
uint64_t ist[7];
|
||||
uint64_t ist[ISTS];
|
||||
uint64_t resv2;
|
||||
uint16_t resv3;
|
||||
uint16_t iopb_off;
|
||||
} PACKED Tss;
|
||||
|
||||
static Tss tss = {0};
|
||||
static ExtendedGdt *curgdt = NULL;
|
||||
ALIGNED(16) static Tss tss = {0};
|
||||
ALIGNED(16) static ExtendedGdt gdt = {0};
|
||||
|
||||
#define KCODE 0x08
|
||||
#define KDATA 0x10
|
||||
#define UCODE 0x18
|
||||
#define UDATA 0x20
|
||||
#define TSS 0x28
|
||||
|
||||
#define GDT_PRESENT 0x80
|
||||
#define GDT_TSS 0x89
|
||||
|
||||
static uint64_t gdt_curretbase(void) {
|
||||
GdtPtr gdtr;
|
||||
asm volatile("sgdt %0" : "=m"(gdtr));
|
||||
return gdtr.base;
|
||||
}
|
||||
|
||||
void gdt_setentry(GdtEntry *entry, uint32_t base, uint32_t limit, uint8_t access, uint8_t gran) {
|
||||
entry->baselow = base & 0xffff;
|
||||
entry->basemid = (base >> 16) & 0xff;
|
||||
entry->basehigh = (base >> 24) & 0xff;
|
||||
entry->limitlow = limit & 0xffff;
|
||||
entry->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0);
|
||||
entry->access = access;
|
||||
void gdt_setentry(GdtEntry *ent, uint32_t base, uint32_t limit, uint32_t acc, uint8_t gran) {
|
||||
ent->baselow = base & 0xffff;
|
||||
ent->basemid = (base >> 16) & 0xff;
|
||||
ent->basehigh = (base >> 24) & 0xff;
|
||||
ent->limitlow = limit & 0xffff;
|
||||
ent->gran = ((limit >> 16) & 0x0f) | (gran & 0xf0);
|
||||
ent->access = acc;
|
||||
}
|
||||
|
||||
void gdt_init(void) {
|
||||
uint64_t base = gdt_curretbase();
|
||||
curgdt = (ExtendedGdt *)base;
|
||||
|
||||
hal_memset(&tss, 0, sizeof(tss));
|
||||
tss.iopb_off = sizeof(tss);
|
||||
|
||||
tss.rsp0 = (uint64_t)(kernelstack + sizeof(kernelstack));
|
||||
|
||||
for (size_t i = 0; i < ISTS; i++) {
|
||||
tss.ist[i] = (uint64_t)(iststacks[i] + sizeof(iststacks[i]));
|
||||
}
|
||||
|
||||
uint64_t tss_base = (uint64_t)&tss;
|
||||
uint32_t tss_limit = sizeof(tss) - 1;
|
||||
|
||||
gdt_setentry(&curgdt->tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
|
||||
gdt_setentry(&gdt.old[0], 0, 0, 0, 0);
|
||||
gdt_setentry(&gdt.old[1], 0, 0xFFFFF, 0x9a, 0xA0);
|
||||
gdt_setentry(&gdt.old[2], 0, 0xFFFFF, 0x92, 0xA0);
|
||||
gdt_setentry(&gdt.old[3], 0, 0xFFFFF, 0xfa, 0xA0);
|
||||
gdt_setentry(&gdt.old[4], 0, 0xFFFFF, 0xf2, 0xA0);
|
||||
|
||||
GdtEntry *tsshigh = &curgdt->tsshigh;
|
||||
tsshigh->baselow = (tss_base >> 32) & 0xffff;
|
||||
tsshigh->basemid = (tss_base >> 48) & 0xff;
|
||||
tsshigh->basehigh = (tss_base >> 56) & 0xff;
|
||||
tsshigh->access = 0;
|
||||
tsshigh->gran = 0;
|
||||
tsshigh->limitlow = 0;
|
||||
gdt_setentry(&gdt.tsslow, tss_base & 0xFFFFFFFF, tss_limit, GDT_PRESENT | GDT_TSS, 0x0);
|
||||
|
||||
uint32_t tssbasehi = tss_base >> 32;
|
||||
gdt.tsshigh.limitlow = tssbasehi & 0xffff;
|
||||
gdt.tsshigh.baselow = (tssbasehi >> 16) & 0xffff;
|
||||
gdt.tsshigh.basemid = 0;
|
||||
gdt.tsshigh.basehigh = 0;
|
||||
gdt.tsshigh.access = 0;
|
||||
gdt.tsshigh.gran = 0;
|
||||
|
||||
GdtPtr gdtr;
|
||||
asm volatile("sgdt %0" : "=m"(gdtr));
|
||||
gdtr.limit = sizeof(ExtendedGdt) - 1;
|
||||
gdtr.limit = sizeof(gdt) - 1;
|
||||
gdtr.base = (uint64_t)&gdt;
|
||||
asm volatile("lgdt %0" :: "m"(gdtr));
|
||||
|
||||
asm volatile("ltr %0" :: "r"((uint16_t)0x28));
|
||||
asm volatile(
|
||||
"pushq %[kcode]\n"
|
||||
"lea 1f(%%rip), %%rax\n"
|
||||
"pushq %%rax\n"
|
||||
"lretq\n"
|
||||
"1:\n"
|
||||
"movw %[kdata], %%ax\n"
|
||||
"movw %%ax, %%ds\n"
|
||||
"movw %%ax, %%es\n"
|
||||
"movw %%ax, %%ss\n"
|
||||
:
|
||||
: [kcode] "i"(KCODE), [kdata] "i"(KDATA)
|
||||
: "rax", "memory"
|
||||
);
|
||||
|
||||
asm volatile("ltr %0" :: "r"((uint16_t)TSS));
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef HAL_GDT_H_
|
||||
#define HAL_GDT_H_
|
||||
|
||||
#define KCODE 0x08
|
||||
#define KDATA 0x10
|
||||
#define UCODE 0x18
|
||||
#define UDATA 0x20
|
||||
#define TSS 0x28
|
||||
|
||||
void gdt_init(void);
|
||||
|
||||
#endif // HAL_GDT_H_
|
||||
|
@ -4,8 +4,11 @@
|
||||
#include "kprintf.h"
|
||||
#include "serial.h"
|
||||
#include "gdt.h"
|
||||
#include "idt.h"
|
||||
#include "acpi.h"
|
||||
#include "intr.h"
|
||||
#include "pic.h"
|
||||
#include "apic.h"
|
||||
#include "pit.h"
|
||||
|
||||
void hal_init(void) {
|
||||
if (!serial_init()) {
|
||||
@ -23,5 +26,11 @@ __attribute__((noreturn)) void hal_hang(void) {
|
||||
|
||||
void hal_init_withmalloc(void) {
|
||||
acpi_init();
|
||||
pic_init();
|
||||
apic_init();
|
||||
intr_init();
|
||||
pit_init();
|
||||
ioapic_setentry(IOAPIC, acpi_remapirq(0x00), INTR_TIMER);
|
||||
hal_intr_enable();
|
||||
}
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
#include <stdint.h>
|
||||
#include "idt.h"
|
||||
#include "kprintf.h"
|
||||
|
||||
#define ENTRIES 256
|
||||
static IdtGate idtgates[ENTRIES] = {0};
|
||||
static Idt idt;
|
||||
|
||||
void idt_setgate(int i, uint64_t handler, uint8_t flags) {
|
||||
idtgates[i].isrlow = (uint16_t)handler;
|
||||
idtgates[i].kernelcs = 40;
|
||||
idtgates[i].ist = 0;
|
||||
idtgates[i].resv = 0;
|
||||
idtgates[i].attrs = flags;
|
||||
idtgates[i].isrmid = (uint16_t)(handler >> 16);
|
||||
idtgates[i].isrhigh = (uint16_t)(handler >> 32);
|
||||
}
|
||||
|
||||
void idt_init(void) {
|
||||
idt.base = (uint64_t)&idtgates;
|
||||
idt.limit = ENTRIES * sizeof(IdtGate) - 1;
|
||||
asm volatile("lidt %0" :: "m"(idt) : "memory");
|
||||
|
||||
LOG("idt", "idt init\n");
|
||||
}
|
@ -1,24 +0,0 @@
|
||||
#ifndef HAL_IDT_H_
|
||||
#define HAL_IDT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include "compiler/attr.h"
|
||||
|
||||
typedef struct {
|
||||
uint16_t isrlow;
|
||||
uint16_t kernelcs;
|
||||
uint8_t ist;
|
||||
uint8_t attrs;
|
||||
uint16_t isrmid;
|
||||
uint32_t isrhigh;
|
||||
uint32_t resv;
|
||||
} PACKED IdtGate;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} PACKED Idt;
|
||||
|
||||
void idt_init(void);
|
||||
|
||||
#endif // HAL_IDT_H_
|
@ -1,9 +0,0 @@
|
||||
.global hal_intr_enable
|
||||
hal_intr_enable:
|
||||
sti
|
||||
ret
|
||||
|
||||
.global hal_intr_disable
|
||||
hal_intr_disable:
|
||||
cli
|
||||
ret
|
201
kernel/hal/x86_64/intr.c
Normal file
201
kernel/hal/x86_64/intr.c
Normal file
@ -0,0 +1,201 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "intr.h"
|
||||
#include "io.h"
|
||||
#include "gdt.h"
|
||||
#include "hal/hal.h"
|
||||
#include "kprintf.h"
|
||||
#include "compiler/attr.h"
|
||||
#include "pic.h"
|
||||
#include "apic.h"
|
||||
#include "pit.h"
|
||||
|
||||
void hal_intr_disable(void) {
|
||||
asm volatile("cli");
|
||||
}
|
||||
|
||||
void hal_intr_enable(void) {
|
||||
asm volatile("sti");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint16_t intrlow;
|
||||
uint16_t kernelcs;
|
||||
uint8_t ist;
|
||||
uint8_t attrs;
|
||||
uint16_t intrmid;
|
||||
uint32_t intrhigh;
|
||||
uint32_t resv;
|
||||
} PACKED IdtGate;
|
||||
|
||||
typedef struct {
|
||||
uint16_t limit;
|
||||
uint64_t base;
|
||||
} PACKED Idt;
|
||||
|
||||
#define ENTRIES 256
|
||||
ALIGNED(0x10) static IdtGate idtgates[ENTRIES] = {0};
|
||||
static Idt idt = {0};
|
||||
|
||||
void idt_setentry(int i, uint64_t handler, uint8_t ist, uint8_t flags) {
|
||||
idtgates[i].intrlow = handler & 0xffff;
|
||||
idtgates[i].kernelcs = KCODE;
|
||||
idtgates[i].ist = ist;
|
||||
idtgates[i].attrs = flags;
|
||||
idtgates[i].intrmid = (handler >> 16) & 0xFFFF;
|
||||
idtgates[i].intrhigh = (handler >> 32) & 0xFFFFFFFF;
|
||||
idtgates[i].resv = 0;
|
||||
}
|
||||
|
||||
void idt_init(void) {
|
||||
idt.base = (uint64_t)&idtgates;
|
||||
idt.limit = ENTRIES * sizeof(IdtGate) - 1;
|
||||
asm volatile("lidt %0" :: "m"(idt) : "memory");
|
||||
|
||||
LOG("hal", "idt init\n");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
uint64_t r15;
|
||||
uint64_t r14;
|
||||
uint64_t r13;
|
||||
uint64_t r12;
|
||||
uint64_t r11;
|
||||
uint64_t r10;
|
||||
uint64_t r9;
|
||||
uint64_t r8;
|
||||
uint64_t rsi;
|
||||
uint64_t rdi;
|
||||
uint64_t rbp;
|
||||
uint64_t rdx;
|
||||
uint64_t rcx;
|
||||
uint64_t rbx;
|
||||
uint64_t rax;
|
||||
} PACKED CpuRegs;
|
||||
|
||||
typedef struct {
|
||||
uint64_t cr8;
|
||||
uint64_t cr4;
|
||||
uint64_t cr3;
|
||||
uint64_t cr2;
|
||||
uint64_t cr0;
|
||||
} PACKED CpuCtrlRegs;
|
||||
|
||||
typedef struct {
|
||||
CpuCtrlRegs ctrl;
|
||||
CpuRegs regs;
|
||||
uint64_t trapnum;
|
||||
uint64_t errnum;
|
||||
|
||||
uint64_t rip;
|
||||
uint64_t cs;
|
||||
uint64_t rflags;
|
||||
uint64_t rsp;
|
||||
uint64_t ss;
|
||||
} PACKED IntrStackFrame;
|
||||
|
||||
extern void *ISR_REDIRTABLE[];
|
||||
|
||||
static const char *exceptions[] = {
|
||||
"#DE", "#DB", "NMI",
|
||||
"#BP", "#OF", "#BR",
|
||||
"#UD", "#NM", "#DF",
|
||||
"CSO", "#TS", "#NP",
|
||||
"#SS", "#GP", "#PF",
|
||||
"RES", "#MF", "#AC",
|
||||
"#MC", "#XM", "#VE",
|
||||
"#CP",
|
||||
};
|
||||
|
||||
void intr_init(void) {
|
||||
#define MKINTR(N, IST) \
|
||||
extern void intr_vec##N(void); \
|
||||
idt_setentry(N, (uint64_t)&intr_vec##N, IST, 0x8E);
|
||||
|
||||
MKINTR(0, 0);
|
||||
MKINTR(1, 0);
|
||||
MKINTR(2, 2);
|
||||
MKINTR(4, 0);
|
||||
MKINTR(5, 0);
|
||||
MKINTR(6, 0);
|
||||
MKINTR(7, 0);
|
||||
MKINTR(8, 1);
|
||||
MKINTR(9, 0);
|
||||
MKINTR(10, 0);
|
||||
MKINTR(11, 0);
|
||||
MKINTR(12, 0);
|
||||
MKINTR(13, 0);
|
||||
MKINTR(14, 0);
|
||||
MKINTR(15, 0);
|
||||
MKINTR(16, 0);
|
||||
MKINTR(17, 0);
|
||||
MKINTR(18, 0);
|
||||
MKINTR(19, 0);
|
||||
MKINTR(20, 0);
|
||||
MKINTR(21, 0);
|
||||
MKINTR(22, 0);
|
||||
MKINTR(23, 0);
|
||||
MKINTR(24, 0);
|
||||
MKINTR(25, 0);
|
||||
MKINTR(26, 0);
|
||||
MKINTR(27, 0);
|
||||
MKINTR(28, 0);
|
||||
MKINTR(29, 0);
|
||||
MKINTR(30, 0);
|
||||
MKINTR(31, 0);
|
||||
MKINTR(32, 0);
|
||||
MKINTR(33, 0);
|
||||
MKINTR(34, 0);
|
||||
MKINTR(35, 0);
|
||||
MKINTR(36, 0);
|
||||
MKINTR(37, 0);
|
||||
MKINTR(38, 0);
|
||||
MKINTR(39, 0);
|
||||
MKINTR(40, 3);
|
||||
MKINTR(41, 0);
|
||||
MKINTR(42, 0);
|
||||
MKINTR(43, 0);
|
||||
MKINTR(44, 0);
|
||||
MKINTR(45, 0);
|
||||
MKINTR(46, 0);
|
||||
MKINTR(47, 0);
|
||||
|
||||
idt_init();
|
||||
}
|
||||
|
||||
void intr_dumpframe(IntrStackFrame *frame) {
|
||||
kprintf("r15=%016lx r14=%016lx r13=%016lx r12=%016lx\n"
|
||||
"r11=%016lx r10=%016lx r9 =%016lx r8 =%016lx\n"
|
||||
"rsi=%016lx rdi=%016lx rbp=%016lx rdx=%016lx\n"
|
||||
"rcx=%016lx rbx=%016lx rax=%016lx\n"
|
||||
"cr8=%016lx cr4=%016lx cr3=%016lx cr2=%016lx\n"
|
||||
"cr0=%016lx rip=%016lx cs =%016lx rfl=%016lx\n"
|
||||
"rsp=%016lx ss =%016lx trp=%016lx err=%016lx\n",
|
||||
frame->regs.r15, frame->regs.r14, frame->regs.r13, frame->regs.r12,
|
||||
frame->regs.r11, frame->regs.r10, frame->regs.r9, frame->regs.r8,
|
||||
frame->regs.rsi, frame->regs.rdi, frame->regs.rbp, frame->regs.rdx,
|
||||
frame->regs.rcx, frame->regs.rbx, frame->regs.rax,
|
||||
frame->ctrl.cr8, frame->ctrl.cr4, frame->ctrl.cr3,
|
||||
frame->ctrl.cr2, frame->ctrl.cr0, frame->rip, frame->cs, frame->rflags,
|
||||
frame->rsp, frame->ss, frame->trapnum, frame->errnum
|
||||
);
|
||||
}
|
||||
|
||||
void intr_handleintr(IntrStackFrame *frame) {
|
||||
if (frame->trapnum >= 0 && frame->trapnum <= 31) {
|
||||
// EXCEPTION
|
||||
ERR("ERROR", "%s, 0x%lX\n", exceptions[frame->trapnum], frame->errnum);
|
||||
intr_dumpframe(frame);
|
||||
hal_hang();
|
||||
} else if (frame->trapnum >= 32 && frame->trapnum <= 47) {
|
||||
if (frame->trapnum == INTR_TIMER) {
|
||||
kprintf("ACK %d\n", PIT_TICKS);
|
||||
PIT_TICKS++;
|
||||
io_out8(PIC2_CMD, 0x20);
|
||||
}
|
||||
|
||||
io_out8(PIC1_CMD, 0x20);
|
||||
lapic_write(LAPIC_EOI, 0x00);
|
||||
}
|
||||
}
|
||||
|
11
kernel/hal/x86_64/intr.h
Normal file
11
kernel/hal/x86_64/intr.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef HAL_INTR_H_
|
||||
#define HAL_INTR_H_
|
||||
|
||||
#define INTR_IRQBASE 0x20
|
||||
#define INTR_IRQTIMER 0x00
|
||||
#define INTR_TIMER 0x20
|
||||
#define INTR_SPURIOUS 0xff
|
||||
|
||||
void intr_init(void);
|
||||
|
||||
#endif // HAL_INTR_H_
|
279
kernel/hal/x86_64/intr0.S
Normal file
279
kernel/hal/x86_64/intr0.S
Normal file
@ -0,0 +1,279 @@
|
||||
.extern intr_handleintr
|
||||
|
||||
.global intr_vec0
|
||||
.global intr_vec1
|
||||
.global intr_vec2
|
||||
.global intr_vec3
|
||||
.global intr_vec4
|
||||
.global intr_vec5
|
||||
.global intr_vec6
|
||||
.global intr_vec7
|
||||
.global intr_vec8
|
||||
.global intr_vec9
|
||||
.global intr_vec10
|
||||
.global intr_vec11
|
||||
.global intr_vec12
|
||||
.global intr_vec13
|
||||
.global intr_vec14
|
||||
.global intr_vec15
|
||||
.global intr_vec16
|
||||
.global intr_vec17
|
||||
.global intr_vec18
|
||||
.global intr_vec19
|
||||
.global intr_vec20
|
||||
.global intr_vec21
|
||||
.global intr_vec22
|
||||
.global intr_vec23
|
||||
.global intr_vec24
|
||||
.global intr_vec25
|
||||
.global intr_vec26
|
||||
.global intr_vec27
|
||||
.global intr_vec28
|
||||
.global intr_vec29
|
||||
.global intr_vec30
|
||||
.global intr_vec31
|
||||
.global intr_vec32
|
||||
.global intr_vec33
|
||||
.global intr_vec34
|
||||
.global intr_vec35
|
||||
.global intr_vec36
|
||||
.global intr_vec37
|
||||
.global intr_vec38
|
||||
.global intr_vec39
|
||||
.global intr_vec40
|
||||
.global intr_vec41
|
||||
.global intr_vec42
|
||||
.global intr_vec43
|
||||
.global intr_vec44
|
||||
.global intr_vec45
|
||||
.global intr_vec46
|
||||
.global intr_vec47
|
||||
|
||||
.macro _PUSHAQ
|
||||
push %rax
|
||||
push %rbx
|
||||
push %rcx
|
||||
push %rdx
|
||||
push %rbp
|
||||
push %rdi
|
||||
push %rsi
|
||||
push %r8
|
||||
push %r9
|
||||
push %r10
|
||||
push %r11
|
||||
push %r12
|
||||
push %r13
|
||||
push %r14
|
||||
push %r15
|
||||
.endm
|
||||
|
||||
.macro _POPAQ
|
||||
pop %r15
|
||||
pop %r14
|
||||
pop %r13
|
||||
pop %r12
|
||||
pop %r11
|
||||
pop %r10
|
||||
pop %r9
|
||||
pop %r8
|
||||
pop %rsi
|
||||
pop %rdi
|
||||
pop %rbp
|
||||
pop %rdx
|
||||
pop %rcx
|
||||
pop %rbx
|
||||
pop %rax
|
||||
.endm
|
||||
|
||||
.macro _PUSHACR
|
||||
mov %cr0, %rax
|
||||
push %rax
|
||||
|
||||
mov %cr2, %rax
|
||||
push %rax
|
||||
|
||||
mov %cr3, %rax
|
||||
push %rax
|
||||
|
||||
mov %cr4, %rax
|
||||
push %rax
|
||||
|
||||
mov %cr8, %rax
|
||||
push %rax
|
||||
.endm
|
||||
|
||||
.macro _POPACR
|
||||
add $0x28, %rsp
|
||||
.endm
|
||||
|
||||
.macro _vecintr_errorcode_present_save num
|
||||
pushq $\num
|
||||
_PUSHAQ
|
||||
_PUSHACR
|
||||
.endm
|
||||
|
||||
.macro _vecintr_plain_save num
|
||||
pushq $0x0
|
||||
pushq $\num
|
||||
_PUSHAQ
|
||||
_PUSHACR
|
||||
.endm
|
||||
|
||||
siema:
|
||||
jmp siema
|
||||
|
||||
.macro _vecintr_bodygen
|
||||
mov %rsp, %rdi
|
||||
call intr_handleintr
|
||||
_POPACR
|
||||
_POPAQ
|
||||
add $0x10, %rsp
|
||||
iretq
|
||||
.endm
|
||||
|
||||
intr_vec0:
|
||||
_vecintr_plain_save 0
|
||||
_vecintr_bodygen
|
||||
intr_vec1:
|
||||
_vecintr_plain_save 1
|
||||
_vecintr_bodygen
|
||||
intr_vec2:
|
||||
_vecintr_plain_save 2
|
||||
_vecintr_bodygen
|
||||
intr_vec3:
|
||||
_vecintr_plain_save 3
|
||||
_vecintr_bodygen
|
||||
intr_vec4:
|
||||
_vecintr_plain_save 4
|
||||
_vecintr_bodygen
|
||||
intr_vec5:
|
||||
_vecintr_plain_save 5
|
||||
_vecintr_bodygen
|
||||
intr_vec6:
|
||||
_vecintr_plain_save 6
|
||||
_vecintr_bodygen
|
||||
intr_vec7:
|
||||
_vecintr_plain_save 7
|
||||
_vecintr_bodygen
|
||||
intr_vec8:
|
||||
_vecintr_errorcode_present_save 8
|
||||
_vecintr_bodygen
|
||||
intr_vec9:
|
||||
_vecintr_plain_save 9
|
||||
_vecintr_bodygen
|
||||
intr_vec10:
|
||||
_vecintr_errorcode_present_save 10
|
||||
_vecintr_bodygen
|
||||
intr_vec11:
|
||||
_vecintr_errorcode_present_save 11
|
||||
_vecintr_bodygen
|
||||
intr_vec12:
|
||||
_vecintr_errorcode_present_save 12
|
||||
_vecintr_bodygen
|
||||
intr_vec13:
|
||||
_vecintr_errorcode_present_save 13
|
||||
_vecintr_bodygen
|
||||
intr_vec14:
|
||||
_vecintr_errorcode_present_save 14
|
||||
_vecintr_bodygen
|
||||
intr_vec15:
|
||||
_vecintr_plain_save 15
|
||||
_vecintr_bodygen
|
||||
intr_vec16:
|
||||
_vecintr_plain_save 16
|
||||
_vecintr_bodygen
|
||||
intr_vec17:
|
||||
_vecintr_errorcode_present_save 17
|
||||
_vecintr_bodygen
|
||||
intr_vec18:
|
||||
_vecintr_plain_save 18
|
||||
_vecintr_bodygen
|
||||
intr_vec19:
|
||||
_vecintr_plain_save 19
|
||||
_vecintr_bodygen
|
||||
intr_vec20:
|
||||
_vecintr_plain_save 20
|
||||
_vecintr_bodygen
|
||||
intr_vec21:
|
||||
_vecintr_errorcode_present_save 21
|
||||
_vecintr_bodygen
|
||||
intr_vec22:
|
||||
_vecintr_plain_save 22
|
||||
_vecintr_bodygen
|
||||
intr_vec23:
|
||||
_vecintr_plain_save 23
|
||||
_vecintr_bodygen
|
||||
intr_vec24:
|
||||
_vecintr_plain_save 24
|
||||
_vecintr_bodygen
|
||||
intr_vec25:
|
||||
_vecintr_plain_save 25
|
||||
_vecintr_bodygen
|
||||
intr_vec26:
|
||||
_vecintr_plain_save 26
|
||||
_vecintr_bodygen
|
||||
intr_vec27:
|
||||
_vecintr_plain_save 27
|
||||
_vecintr_bodygen
|
||||
intr_vec28:
|
||||
_vecintr_plain_save 28
|
||||
_vecintr_bodygen
|
||||
intr_vec29:
|
||||
_vecintr_errorcode_present_save 29
|
||||
_vecintr_bodygen
|
||||
intr_vec30:
|
||||
_vecintr_errorcode_present_save 30
|
||||
_vecintr_bodygen
|
||||
intr_vec31:
|
||||
_vecintr_plain_save 31
|
||||
_vecintr_bodygen
|
||||
|
||||
intr_vec32:
|
||||
_vecintr_plain_save 32
|
||||
_vecintr_bodygen
|
||||
intr_vec33:
|
||||
_vecintr_plain_save 33
|
||||
_vecintr_bodygen
|
||||
intr_vec34:
|
||||
_vecintr_plain_save 34
|
||||
_vecintr_bodygen
|
||||
intr_vec35:
|
||||
_vecintr_plain_save 35
|
||||
_vecintr_bodygen
|
||||
intr_vec36:
|
||||
_vecintr_plain_save 36
|
||||
_vecintr_bodygen
|
||||
intr_vec37:
|
||||
_vecintr_plain_save 37
|
||||
_vecintr_bodygen
|
||||
intr_vec38:
|
||||
_vecintr_plain_save 38
|
||||
_vecintr_bodygen
|
||||
intr_vec39:
|
||||
_vecintr_plain_save 39
|
||||
_vecintr_bodygen
|
||||
intr_vec40:
|
||||
_vecintr_plain_save 40
|
||||
_vecintr_bodygen
|
||||
intr_vec41:
|
||||
_vecintr_plain_save 41
|
||||
_vecintr_bodygen
|
||||
intr_vec42:
|
||||
_vecintr_plain_save 42
|
||||
_vecintr_bodygen
|
||||
intr_vec43:
|
||||
_vecintr_plain_save 43
|
||||
_vecintr_bodygen
|
||||
intr_vec44:
|
||||
_vecintr_plain_save 44
|
||||
_vecintr_bodygen
|
||||
intr_vec45:
|
||||
_vecintr_plain_save 45
|
||||
_vecintr_bodygen
|
||||
intr_vec46:
|
||||
_vecintr_plain_save 46
|
||||
_vecintr_bodygen
|
||||
intr_vec47:
|
||||
_vecintr_plain_save 47
|
||||
_vecintr_bodygen
|
||||
|
22
kernel/hal/x86_64/pic.c
Normal file
22
kernel/hal/x86_64/pic.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include "pic.h"
|
||||
#include "io.h"
|
||||
#include "intr.h"
|
||||
|
||||
void pic_init(void) {
|
||||
io_out8(PIC1_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
io_out8(PIC2_CMD, ICW1_INIT | ICW1_ICW4);
|
||||
|
||||
io_out8(PIC1_DATA, INTR_IRQBASE);
|
||||
io_out8(PIC2_DATA, INTR_IRQBASE+8);
|
||||
|
||||
io_out8(PIC1_DATA, 4);
|
||||
io_out8(PIC2_DATA, 2);
|
||||
|
||||
io_out8(PIC1_DATA, ICW4_8086);
|
||||
io_out8(PIC2_DATA, ICW4_8086);
|
||||
|
||||
io_out8(PIC1_DATA, 0xff);
|
||||
io_out8(PIC2_DATA, 0xff);
|
||||
}
|
23
kernel/hal/x86_64/pic.h
Normal file
23
kernel/hal/x86_64/pic.h
Normal file
@ -0,0 +1,23 @@
|
||||
#ifndef HAL_PIC_H_
|
||||
#define HAL_PIC_H_
|
||||
|
||||
#define PIC1_CMD 0x0020
|
||||
#define PIC1_DATA 0x0021
|
||||
#define PIC2_CMD 0x00A0
|
||||
#define PIC2_DATA 0x00A1
|
||||
|
||||
#define ICW1_ICW4 0x01
|
||||
#define ICW1_SINGLE 0x02
|
||||
#define ICW1_ADI 0x04
|
||||
#define ICW1_LTIM 0x08
|
||||
#define ICW1_INIT 0x10
|
||||
|
||||
#define ICW4_8086 0x01
|
||||
#define ICW4_AUTO 0x02
|
||||
#define ICW4_BUFSLAVE 0x04
|
||||
#define ICW4_BUFMASTER 0x0C
|
||||
#define ICW4_SFNM 0x10
|
||||
|
||||
void pic_init(void);
|
||||
|
||||
#endif // HAL_PIC_H_
|
40
kernel/hal/x86_64/pit.c
Normal file
40
kernel/hal/x86_64/pit.c
Normal file
@ -0,0 +1,40 @@
|
||||
#include <stdint.h>
|
||||
#include "pit.h"
|
||||
#include "io.h"
|
||||
|
||||
#define PIT_COUNTER0 0x40
|
||||
#define PIT_CMD 0x43
|
||||
#define PIT_CMD_BINARY 0x00
|
||||
#define PIT_CMD_BCD 0x01
|
||||
#define PIT_CMD_MODE0 0x00
|
||||
#define PIT_CMD_MODE1 0x02
|
||||
#define PIT_CMD_MODE2 0x04
|
||||
#define PIT_CMD_MODE3 0x06
|
||||
#define PIT_CMD_MODE4 0x08
|
||||
#define PIT_CMD_MODE5 0x0A
|
||||
#define PIT_CMD_LATCH 0x00
|
||||
#define PIT_CMD_RW_LOW 0x10
|
||||
#define PIT_CMD_RW_HI 0x20
|
||||
#define PIT_CMD_RW_BOTH 0x30
|
||||
#define PIT_CMD_COUNTER0 0x00
|
||||
#define PIT_CMD_COUNTER1 0x40
|
||||
#define PIT_CMD_COUNTER2 0x80
|
||||
#define PIT_CMD_READBACK 0xC0
|
||||
|
||||
#define PIT_FREQ 1193182
|
||||
|
||||
volatile uint32_t PIT_TICKS;
|
||||
|
||||
void pit_init(void) {
|
||||
uint32_t hz = 1000;
|
||||
uint32_t div = PIT_FREQ / hz;
|
||||
io_out8(PIT_CMD, PIT_CMD_BINARY | PIT_CMD_MODE3 | PIT_CMD_RW_BOTH | PIT_CMD_COUNTER0);
|
||||
io_out8(PIT_COUNTER0, div);
|
||||
io_out8(PIT_COUNTER0, div >> 8);
|
||||
}
|
||||
|
||||
void pit_wait(uint32_t ms) {
|
||||
uint32_t now = PIT_TICKS;
|
||||
++ms;
|
||||
while (PIT_TICKS - now < ms);
|
||||
}
|
11
kernel/hal/x86_64/pit.h
Normal file
11
kernel/hal/x86_64/pit.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef HAL_PIT_H_
|
||||
#define HAL_PIT_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern volatile uint32_t PIT_TICKS;
|
||||
|
||||
void pit_init(void);
|
||||
void pit_wait(uint32_t ms);
|
||||
|
||||
#endif // HAL_PIT_H_
|
@ -1,45 +0,0 @@
|
||||
#include "uacpi/uacpi.h"
|
||||
#include "dlmalloc/malloc.h"
|
||||
#include "bootinfo/bootinfo.h"
|
||||
#include "hal/x86_64/io.h"
|
||||
#include "kprintf.h"
|
||||
#include "compiler/builtins.h"
|
||||
|
||||
void *uacpi_kernel_alloc(uacpi_size size) {
|
||||
return dlmalloc(size);
|
||||
}
|
||||
|
||||
void uacpi_kernel_free(void *ptr) {
|
||||
return dlfree(ptr);
|
||||
}
|
||||
|
||||
void uacpi_kernel_log(uacpi_log_level lvl, const uacpi_char *s) {
|
||||
char *t;
|
||||
switch (lvl) {
|
||||
case UACPI_LOG_DEBUG: t = "Debug"; break;
|
||||
case UACPI_LOG_TRACE: t = "Trace"; break;
|
||||
case UACPI_LOG_INFO: t = "Info"; break;
|
||||
case UACPI_LOG_WARN: t = "Warn"; break;
|
||||
case UACPI_LOG_ERROR: t = "Error"; break;
|
||||
default:
|
||||
unreachable();
|
||||
break;
|
||||
}
|
||||
LOG("uACPI", "[%s] %s", t, s);
|
||||
}
|
||||
|
||||
void *uacpi_kernel_map(uacpi_phys_addr addr, uacpi_size len) {
|
||||
(void)len;
|
||||
return (void *)(BOOT_INFO.hhdm_off + addr);
|
||||
}
|
||||
|
||||
void uacpi_kernel_unmap(void *addr, uacpi_size len) {
|
||||
(void)addr;
|
||||
(void)len;
|
||||
}
|
||||
|
||||
uacpi_status uacpi_kernel_get_rsdp(uacpi_phys_addr *out) {
|
||||
*out = BOOT_INFO.rsdp;
|
||||
return UACPI_STATUS_OK;
|
||||
}
|
||||
|
@ -374,11 +374,12 @@ If you want to contribute:
|
||||
| [ilobilix](https://github.com/ilobilo/ilobilix) | Yet another monolithic Linux clone wannabe. Currently under a rewrite | 8,703,286 | AMD Ryzen 9 9950X3D |
|
||||
| [Crescent2](https://github.com/Qwinci/crescent2) | An NT driver compatible kernel and userspace | 6,818,418 | Intel Core i5-13600K |
|
||||
| [davix](https://github.com/dbstream/davix) | Yet another unix-like by some bored nerd | 6,364,623 | Intel Core i7-13700K |
|
||||
| [Ironclad](https://ironclad-os.org) | Formally verified, hard real-time capable kernel written in SPARK and Ada | 6,196,937 | Intel Core i9-13900KS |
|
||||
| [Managarm](https://github.com/managarm/managarm) | Pragmatic microkernel-based OS with fully asynchronous I/O | 5,618,646 | Intel Core i7-14700K |
|
||||
| [ChronOS](https://github.com/BUGO07/chronos) | Another basic hobby os held together by duct tape, made in rust | 5,416,703 | Intel Core Ultra 7 265KF |
|
||||
| [pmOS](https://gitlab.com/mishakov/pmos) | Microkernel-based operating system written from scratch with uACPI running in userspace | 5,354,445 | AMD Ryzen 9 5900X |
|
||||
| [menix](https://github.com/menix-os/menix) | A minimal and expandable Unix-like operating system | 5,239,043 | Intel Core Ultra 7 265KF |
|
||||
| [Ironclad](https://ironclad.nongnu.org) | Formally verified, hard real-time capable kernel written in SPARK and Ada | 4,802,816 | Intel Core i9-13900KS |
|
||||
| [Orange](https://github.com/cpplover0/orange) | Unix-like x86_64 OS with some microkernel features | 4,204,053 | AMD Ryzen 5 3600 |
|
||||
| [Astral](https://github.com/mathewnd/astral) | Operating system written in C which aims be POSIX-compliant | 4,189,189 | Intel Core i5-13600K |
|
||||
| [Keyronex](https://github.com/Keyronex/Keyronex) | Layered kernel with fundamentally asynchronous I/O and working set model-based memory management | 4,013,691 | AMD Ryzen 5800X |
|
||||
| [Orange](https://github.com/cppLover0/Orange) | x86_64 Unix-like OS | 2,377,330 | AMD Ryzen 5 3600 |
|
||||
@ -387,6 +388,7 @@ If you want to contribute:
|
||||
| [ElysiumOS](https://github.com/imwux/elysium-os) | Hybrid Unix-like kernel | 1,737,654 | AMD Ryzen 7 5800X3D |
|
||||
| [imaginarium](https://github.com/Khitiara/imaginarium) | Ziggy osdev experiments inspired by the NT kernel (using the zig general purpose allocator) | 1,504,436 | AMD Ryzen 7 3700X |
|
||||
| [BadgerOS](https://github.com/badgeteam/BadgerOS) | A monolithic lightweight UNIX clone | 1,018,518 | AMD Ryzen 5 3600 |
|
||||
| [Retro Rocket](https://github.com/brainboxdotcc/retro-rocket) | A BASIC _powered_ 64-bit SMP multitasking OS | 441,329 | Intel Xeon E5-2680 |
|
||||
| [Hyra](https://github.com/sigsegv7/Hyra) | Monolithic UNIX-like OS by [OSMORA.ORG](https://osmora.org) | 199,873 | Intel Core i3-3220 |
|
||||
|
||||
## License
|
||||
|
@ -9,6 +9,8 @@ extern "C" {
|
||||
|
||||
// Forward-declared to avoid including the entire acpi.h here
|
||||
struct acpi_fadt;
|
||||
struct acpi_entry_hdr;
|
||||
struct acpi_sdt_hdr;
|
||||
|
||||
typedef struct uacpi_table_identifiers {
|
||||
uacpi_object_name signature;
|
||||
@ -136,6 +138,30 @@ uacpi_status uacpi_set_table_installation_handler(
|
||||
uacpi_table_installation_handler handler
|
||||
);
|
||||
|
||||
typedef uacpi_iteration_decision (*uacpi_subtable_iteration_callback)
|
||||
(uacpi_handle, struct acpi_entry_hdr*);
|
||||
|
||||
/*
|
||||
* Iterate every subtable of a table such as MADT or SRAT.
|
||||
*
|
||||
* 'hdr' is the pointer to the main table, 'hdr_size' is the number of bytes in
|
||||
* the table before the beginning of the subtable records. 'cb' is the callback
|
||||
* invoked for each subtable with the 'user' context pointer passed for every
|
||||
* invocation.
|
||||
*
|
||||
* Example usage:
|
||||
* uacpi_table tbl;
|
||||
*
|
||||
* uacpi_table_find_by_signature(ACPI_MADT_SIGNATURE, &tbl);
|
||||
* uacpi_for_each_subtable(
|
||||
* tbl.hdr, sizeof(struct acpi_madt), parse_madt, NULL
|
||||
* );
|
||||
*/
|
||||
uacpi_status uacpi_for_each_subtable(
|
||||
struct acpi_sdt_hdr *hdr, size_t hdr_size,
|
||||
uacpi_subtable_iteration_callback cb, void *user
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -29,7 +29,13 @@ typedef enum uacpi_iteration_decision {
|
||||
UACPI_ITERATION_DECISION_CONTINUE = 0,
|
||||
UACPI_ITERATION_DECISION_BREAK,
|
||||
|
||||
// Only applicable for uacpi_namespace_for_each_child
|
||||
/*
|
||||
* Ignore all of the children of the current node and proceed directly to
|
||||
* its peer nodes.
|
||||
*
|
||||
* Only applicable for API that interacts with the AML namespace such as
|
||||
* uacpi_namespace_for_each_child, uacpi_find_deivces, etc.
|
||||
*/
|
||||
UACPI_ITERATION_DECISION_NEXT_PEER,
|
||||
} uacpi_iteration_decision;
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include <uacpi/namespace.h>
|
||||
|
||||
#define UACPI_MAJOR 3
|
||||
#define UACPI_MINOR 0
|
||||
#define UACPI_MINOR 1
|
||||
#define UACPI_PATCH 0
|
||||
|
||||
#ifdef UACPI_REDUCED_HARDWARE
|
||||
|
@ -1398,3 +1398,52 @@ uacpi_status uacpi_table_fadt(struct acpi_fadt **out_fadt)
|
||||
*out_fadt = &g_uacpi_rt_ctx.fadt;
|
||||
return UACPI_STATUS_OK;
|
||||
}
|
||||
|
||||
uacpi_status uacpi_for_each_subtable(
|
||||
struct acpi_sdt_hdr *hdr, size_t hdr_size,
|
||||
uacpi_subtable_iteration_callback cb, void *user
|
||||
)
|
||||
{
|
||||
void *cursor;
|
||||
size_t bytes_left;
|
||||
|
||||
cursor = UACPI_PTR_ADD(hdr, hdr_size);
|
||||
bytes_left = hdr->length - hdr_size;
|
||||
|
||||
if (uacpi_unlikely(bytes_left > hdr->length))
|
||||
return UACPI_STATUS_INVALID_TABLE_LENGTH;
|
||||
|
||||
while (bytes_left > sizeof(struct acpi_entry_hdr)) {
|
||||
struct acpi_entry_hdr *subtable_hdr = cursor;
|
||||
|
||||
if (uacpi_unlikely(subtable_hdr->length > bytes_left ||
|
||||
subtable_hdr->length < sizeof(*subtable_hdr))) {
|
||||
uacpi_error(
|
||||
"corrupted '%.4s' subtable length: %u (%zu bytes left)\n",
|
||||
hdr->signature, subtable_hdr->length, bytes_left
|
||||
);
|
||||
return UACPI_STATUS_INVALID_TABLE_LENGTH;
|
||||
}
|
||||
|
||||
switch (cb(user, subtable_hdr)) {
|
||||
case UACPI_ITERATION_DECISION_CONTINUE:
|
||||
break;
|
||||
case UACPI_ITERATION_DECISION_BREAK:
|
||||
return UACPI_STATUS_OK;
|
||||
default:
|
||||
return UACPI_STATUS_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
cursor = UACPI_PTR_ADD(cursor, subtable_hdr->length);
|
||||
bytes_left -= subtable_hdr->length;
|
||||
}
|
||||
|
||||
if (uacpi_unlikely(bytes_left != 0)) {
|
||||
uacpi_warn(
|
||||
"found %zu stray bytes in table '%.4s'\n",
|
||||
bytes_left, hdr->signature
|
||||
);
|
||||
}
|
||||
|
||||
return UACPI_STATUS_OK;
|
||||
}
|
||||
|
@ -464,6 +464,7 @@ def main() -> int:
|
||||
bare_cases: List[TestCase] = [
|
||||
BarebonesTestCase("basic-operation"),
|
||||
BarebonesTestCase("table-installation"),
|
||||
BarebonesTestCase("foreach-subtable"),
|
||||
]
|
||||
|
||||
with TestHeaderFooter("Barebones Mode Tests"):
|
||||
|
@ -54,6 +54,33 @@ static uint8_t test_mcfg[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
/*
|
||||
* 4 Local APICs [0, 1, 2, 3]
|
||||
* 2 IOAPICs [4, 5]
|
||||
* 2 ISOs [0->2, 9->9]
|
||||
* 4 NMIs [0, 1, 2, 3]
|
||||
*/
|
||||
static uint8_t test_apic[] = {
|
||||
0x41, 0x50, 0x49, 0x43, 0x90, 0x00, 0x00, 0x00,
|
||||
0x03, 0x1a, 0x48, 0x50, 0x51, 0x4f, 0x45, 0x4d,
|
||||
0x53, 0x4c, 0x49, 0x43, 0x2d, 0x4d, 0x50, 0x43,
|
||||
0x01, 0x00, 0x00, 0x00, 0x48, 0x50, 0x20, 0x20,
|
||||
0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0xe0, 0xfe,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x01,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x02, 0x02,
|
||||
0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x03, 0x03,
|
||||
0x01, 0x00, 0x00, 0x00, 0x01, 0x0c, 0x04, 0x00,
|
||||
0x00, 0x00, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0x0c, 0x05, 0x00, 0x00, 0x10, 0xc0, 0xfe,
|
||||
0x18, 0x00, 0x00, 0x00, 0x02, 0x0a, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x0a,
|
||||
0x00, 0x09, 0x09, 0x00, 0x00, 0x00, 0x0f, 0x00,
|
||||
0x04, 0x06, 0x00, 0x05, 0x00, 0x01, 0x04, 0x06,
|
||||
0x01, 0x05, 0x00, 0x01, 0x04, 0x06, 0x02, 0x05,
|
||||
0x00, 0x01, 0x04, 0x06, 0x03, 0x05, 0x00, 0x01
|
||||
};
|
||||
|
||||
static void ensure_signature_is(const char *signature, uacpi_table tbl)
|
||||
{
|
||||
if (strncmp(tbl.hdr->signature, signature, 4) == 0)
|
||||
@ -105,12 +132,123 @@ static void test_table_installation(void)
|
||||
uacpi_table_unref(&tbl);
|
||||
}
|
||||
|
||||
static uacpi_iteration_decision check_madt(
|
||||
uacpi_handle user, struct acpi_entry_hdr *hdr
|
||||
)
|
||||
{
|
||||
size_t *idx = user;
|
||||
struct acpi_madt_lapic *lapic;
|
||||
struct acpi_madt_ioapic *ioapic;
|
||||
struct acpi_madt_interrupt_source_override *iso;
|
||||
struct acpi_madt_lapic_nmi *nmi;
|
||||
|
||||
switch (*idx) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
if (hdr->type != ACPI_MADT_ENTRY_TYPE_LAPIC)
|
||||
goto out_unexpected;
|
||||
lapic = (struct acpi_madt_lapic*)hdr;
|
||||
if (lapic->id != *idx)
|
||||
error("unexpected LAPIC id %d (idx %d)\n", lapic->id, *idx);
|
||||
break;
|
||||
case 4:
|
||||
case 5:
|
||||
if (hdr->type != ACPI_MADT_ENTRY_TYPE_IOAPIC)
|
||||
goto out_unexpected;
|
||||
ioapic = (struct acpi_madt_ioapic*)hdr;
|
||||
if (ioapic->id != *idx)
|
||||
error("unexpected IOAPIC id %d (idx %d)\n", ioapic->id, *idx);
|
||||
break;
|
||||
case 6:
|
||||
case 7:
|
||||
if (hdr->type != ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE)
|
||||
goto out_unexpected;
|
||||
iso = (struct acpi_madt_interrupt_source_override*)hdr;
|
||||
if ((*idx == 6 && iso->source != 0) ||
|
||||
(*idx == 7 && iso->source != 9))
|
||||
error("unexpected ISO source %d (idx %d)\n", iso->source, *idx);
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
if (hdr->type != ACPI_MADT_ENTRY_TYPE_LAPIC_NMI)
|
||||
goto out_unexpected;
|
||||
nmi = (struct acpi_madt_lapic_nmi*)hdr;
|
||||
if (nmi->uid != (*idx - 8))
|
||||
error("unexpected LAPIC NMI uid %d (idx %d)\n", nmi->uid, *idx);
|
||||
break;
|
||||
default:
|
||||
goto out_unexpected;
|
||||
}
|
||||
|
||||
(*idx)++;
|
||||
return UACPI_ITERATION_DECISION_CONTINUE;
|
||||
|
||||
out_unexpected:
|
||||
error("unexpected MADT entry type %d (idx = %zu)\n", hdr->type, *idx);
|
||||
return UACPI_ITERATION_DECISION_BREAK;
|
||||
}
|
||||
|
||||
#define CHECK_SUBTEST_FAILED \
|
||||
if (st != UACPI_STATUS_INVALID_TABLE_LENGTH) \
|
||||
error("unexpected status %s\n", uacpi_status_to_string(st));
|
||||
|
||||
#define CHECK_SUBTEST_SUCCEEDED \
|
||||
if (idx != 12) \
|
||||
error("invalid number of iterations: %zu\n", idx);
|
||||
|
||||
#define FOREACH_SUBTEST(check_cond) \
|
||||
idx = 0; \
|
||||
st = uacpi_for_each_subtable( \
|
||||
tbl.hdr, sizeof(struct acpi_madt), check_madt, &idx \
|
||||
); \
|
||||
check_cond; \
|
||||
|
||||
static void test_foreach_subtable(void)
|
||||
{
|
||||
uacpi_status st;
|
||||
uacpi_table tbl;
|
||||
size_t idx = 0;
|
||||
|
||||
st = uacpi_table_install(test_apic, &tbl);
|
||||
ensure_ok_status(st);
|
||||
ensure_signature_is(ACPI_MADT_SIGNATURE, tbl);
|
||||
uacpi_table_unref(&tbl);
|
||||
|
||||
FOREACH_SUBTEST(CHECK_SUBTEST_SUCCEEDED);
|
||||
|
||||
// Make the size slightly larger, make sure we don't crash
|
||||
test_apic[4] += 1;
|
||||
FOREACH_SUBTEST(CHECK_SUBTEST_SUCCEEDED);
|
||||
|
||||
// Change the size to 1 byte and make sure we don't crash
|
||||
test_apic[4] = 1;
|
||||
FOREACH_SUBTEST(CHECK_SUBTEST_FAILED);
|
||||
|
||||
// Cutoff subtable
|
||||
test_apic[4] = sizeof(struct acpi_madt) + sizeof(struct acpi_entry_hdr) + 1;
|
||||
FOREACH_SUBTEST(CHECK_SUBTEST_FAILED);
|
||||
|
||||
test_apic[4] = sizeof(test_apic);
|
||||
// Out-of-bounds subtable
|
||||
test_apic[sizeof(test_apic) - 5]++;
|
||||
FOREACH_SUBTEST(CHECK_SUBTEST_FAILED);
|
||||
|
||||
// all pass
|
||||
test_apic[sizeof(test_apic) - 5]--;
|
||||
uacpi_table_unref(&tbl);
|
||||
}
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
void (*func)(void);
|
||||
} test_cases[] = {
|
||||
{ "basic-operation", test_basic_operation },
|
||||
{ "table-installation", test_table_installation },
|
||||
{ "foreach-subtable", test_foreach_subtable },
|
||||
};
|
||||
|
||||
static arg_spec_t TEST_CASE_ARG = ARG_POS("test-case", "name of the test case");
|
||||
|
@ -20,6 +20,8 @@ NORETURN static inline void error(const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
fprintf(stderr, "unexpected error: ");
|
||||
va_start(args, format);
|
||||
vfprintf(stderr, format, args);
|
||||
|
@ -63,11 +63,12 @@ void kmain(void) {
|
||||
paging_init();
|
||||
dlmalloc_check();
|
||||
hal_init_withmalloc();
|
||||
/* hal_intr_disable(); */
|
||||
storedev_init();
|
||||
baseimg_init();
|
||||
vfs_init();
|
||||
|
||||
kprintf(BANNER_TEXT "\n");
|
||||
/* kprintf(BANNER_TEXT "\n"); */
|
||||
|
||||
hal_hang();
|
||||
}
|
||||
|
@ -8,7 +8,6 @@
|
||||
Term TERM;
|
||||
|
||||
void term_init(void) {
|
||||
spinlock_init(&TERM.spinlock);
|
||||
TERM.ftctx = flanterm_fb_init(
|
||||
NULL, NULL,
|
||||
BOOT_INFO.fb->address,
|
||||
@ -32,9 +31,7 @@ void term_init(void) {
|
||||
}
|
||||
|
||||
void term_write(const char *s, size_t len) {
|
||||
spinlock_acquire(&TERM.spinlock);
|
||||
flanterm_write(TERM.ftctx, s, len);
|
||||
spinlock_release(&TERM.spinlock);
|
||||
}
|
||||
|
||||
#if PUTCHAR_ == PUTCHAR_FB
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "spinlock/spinlock.h"
|
||||
|
||||
typedef struct {
|
||||
SpinLock spinlock;
|
||||
struct flanterm_context *ftctx;
|
||||
} Term;
|
||||
|
||||
|
49
kernel/util/mmio.h
Normal file
49
kernel/util/mmio.h
Normal file
@ -0,0 +1,49 @@
|
||||
#ifndef UTIL_MMIO_H_
|
||||
#define UTIL_MMIO_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static inline void mmiowrite8(void *p, uint8_t data) {
|
||||
*(volatile uint8_t *)(p) = data;
|
||||
}
|
||||
|
||||
static inline uint8_t mmioread8(void *p) {
|
||||
return *(volatile uint8_t *)(p);
|
||||
}
|
||||
|
||||
static inline void mmiowrite16(void *p, uint16_t data) {
|
||||
*(volatile uint16_t *)(p) = data;
|
||||
}
|
||||
|
||||
static inline uint16_t mmioread16(void *p) {
|
||||
return *(volatile uint16_t *)(p);
|
||||
}
|
||||
|
||||
static inline void mmiowrite32(void *p, uint32_t data) {
|
||||
*(volatile uint32_t *)(p) = data;
|
||||
}
|
||||
|
||||
static inline uint32_t mmioread32(void *p) {
|
||||
return *(volatile uint32_t *)(p);
|
||||
}
|
||||
|
||||
static inline void mmiowrite64(void *p, uint64_t data) {
|
||||
*(volatile uint64_t *)(p) = data;
|
||||
}
|
||||
|
||||
static inline uint64_t mmioread64(void *p) {
|
||||
return *(volatile uint64_t *)(p);
|
||||
}
|
||||
|
||||
static inline void mmioreadn(void *dst, const volatile void *src, size_t bytes) {
|
||||
volatile uint8_t *s = (volatile uint8_t *)src;
|
||||
uint8_t *d = (uint8_t *)dst;
|
||||
while (bytes > 0) {
|
||||
*d = *s;
|
||||
++s;
|
||||
++d;
|
||||
--bytes;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // UTIL_MMIO_H_
|
Reference in New Issue
Block a user