APIC, HPET, virtual memory
This commit is contained in:
3
aux/qemu_amd64.sh
Executable file
3
aux/qemu_amd64.sh
Executable file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
qemu-system-x86_64 -M q35 -m 4G -serial mon:stdio -cdrom mop3.iso
|
||||||
158
kernel/amd64/apic.c
Normal file
158
kernel/amd64/apic.c
Normal file
@@ -0,0 +1,158 @@
|
|||||||
|
#include <amd64/apic.h>
|
||||||
|
#include <libk/std.h>
|
||||||
|
#include <limine/requests.h>
|
||||||
|
#include <sys/debug.h>
|
||||||
|
#include <sys/mm.h>
|
||||||
|
#include <uacpi/acpi.h>
|
||||||
|
#include <uacpi/status.h>
|
||||||
|
#include <uacpi/tables.h>
|
||||||
|
#include <uacpi/uacpi.h>
|
||||||
|
|
||||||
|
#define IOAPICS_MAX 24
|
||||||
|
#define INTERRUPT_SRC_OVERRIDES_MAX 24
|
||||||
|
|
||||||
|
static struct acpi_madt_ioapic apics[IOAPICS_MAX];
|
||||||
|
/* clang-format off */
|
||||||
|
static struct acpi_madt_interrupt_source_override intr_src_overrides[INTERRUPT_SRC_OVERRIDES_MAX];
|
||||||
|
/* clang-format on */
|
||||||
|
static size_t ioapic_entries = 0;
|
||||||
|
static size_t intr_src_override_entries = 0;
|
||||||
|
|
||||||
|
extern void amd64_spin (void);
|
||||||
|
|
||||||
|
static uint32_t amd64_ioapic_read (uintptr_t vaddr, uint32_t reg) {
|
||||||
|
*(volatile uint32_t*)vaddr = reg;
|
||||||
|
return *(volatile uint32_t*)(vaddr + 0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_ioapic_write (uintptr_t vaddr, uint32_t reg, uint32_t value) {
|
||||||
|
*(volatile uint32_t*)vaddr = reg;
|
||||||
|
*(volatile uint32_t*)(vaddr + 0x10) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct acpi_madt_ioapic* amd64_ioapic_find (uint8_t irq) {
|
||||||
|
struct acpi_madt_ioapic* apic = NULL;
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < ioapic_entries; i++) {
|
||||||
|
apic = &apics[i];
|
||||||
|
uint32_t version = amd64_ioapic_read (
|
||||||
|
(uintptr_t)hhdm->offset + (uintptr_t)apic->address, 1);
|
||||||
|
uint32_t max = (version >> 16);
|
||||||
|
|
||||||
|
if ((apic->gsi_base <= irq) && ((apic->gsi_base + max) > irq))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return apic;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags,
|
||||||
|
uint64_t lapic_id) {
|
||||||
|
struct acpi_madt_ioapic* apic;
|
||||||
|
struct acpi_madt_interrupt_source_override* override;
|
||||||
|
bool found_override = false;
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < intr_src_override_entries; i++) {
|
||||||
|
override = &intr_src_overrides[i];
|
||||||
|
if (override->source == irq) {
|
||||||
|
found_override = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t calc_flags = (lapic_id << 56) | (flags) | (vec & 0xFF);
|
||||||
|
|
||||||
|
if (found_override) {
|
||||||
|
uint8_t polarity = ((override->flags & 0x03) == 0x03) ? 1 : 0;
|
||||||
|
uint8_t mode = (((override->flags >> 2) & 0x03) == 0x03) ? 1 : 0;
|
||||||
|
calc_flags = (lapic_id << 56) | (mode << 15) | (polarity << 14) |
|
||||||
|
(vec & 0xFF) | flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
apic = amd64_ioapic_find (irq);
|
||||||
|
|
||||||
|
if (apic == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
||||||
|
|
||||||
|
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address,
|
||||||
|
irq_reg, (uint32_t)calc_flags);
|
||||||
|
|
||||||
|
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address,
|
||||||
|
irq_reg + 1, (uint32_t)(calc_flags >> 32));
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_ioapic_mask (uint8_t irq) {
|
||||||
|
struct acpi_madt_ioapic* apic;
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
apic = amd64_ioapic_find (irq);
|
||||||
|
|
||||||
|
if (apic == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
||||||
|
|
||||||
|
uint32_t value = amd64_ioapic_read (
|
||||||
|
(uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg);
|
||||||
|
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address,
|
||||||
|
irq_reg, value | (1 << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_ioapic_unmask (uint8_t irq) {
|
||||||
|
struct acpi_madt_ioapic* apic;
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
apic = amd64_ioapic_find (irq);
|
||||||
|
|
||||||
|
if (apic == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint32_t irq_reg = ((irq - apic->gsi_base) * 2) + 0x10;
|
||||||
|
|
||||||
|
uint32_t value = amd64_ioapic_read (
|
||||||
|
(uintptr_t)hhdm->offset + (uintptr_t)apic->address, irq_reg);
|
||||||
|
amd64_ioapic_write ((uintptr_t)hhdm->offset + (uintptr_t)apic->address,
|
||||||
|
irq_reg, value & ~(1 << 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_ioapic_init (void) {
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
struct uacpi_table apic_table;
|
||||||
|
uacpi_status status =
|
||||||
|
uacpi_table_find_by_signature (ACPI_MADT_SIGNATURE, &apic_table);
|
||||||
|
if (status != UACPI_STATUS_OK) {
|
||||||
|
DEBUG ("Could not find MADT table!\n");
|
||||||
|
amd64_spin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_madt* apic = (struct acpi_madt*)apic_table.virt_addr;
|
||||||
|
struct acpi_entry_hdr* current = (struct acpi_entry_hdr*)apic->entries;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
if ((uintptr_t)current >= ((uintptr_t)apic->entries + apic->hdr.length -
|
||||||
|
sizeof (struct acpi_madt)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (current->type) {
|
||||||
|
case ACPI_MADT_ENTRY_TYPE_IOAPIC: {
|
||||||
|
struct acpi_madt_ioapic* ioapic = (struct acpi_madt_ioapic*)current;
|
||||||
|
mm_map_kernel_page ((uintptr_t)ioapic->address,
|
||||||
|
(uintptr_t)hhdm->offset + (uintptr_t)ioapic->address,
|
||||||
|
MM_PG_USER | MM_PG_RW);
|
||||||
|
apics[ioapic_entries++] = *ioapic;
|
||||||
|
} break;
|
||||||
|
case ACPI_MADT_ENTRY_TYPE_INTERRUPT_SOURCE_OVERRIDE: {
|
||||||
|
struct acpi_madt_interrupt_source_override* override =
|
||||||
|
(struct acpi_madt_interrupt_source_override*)current;
|
||||||
|
intr_src_overrides[intr_src_override_entries++] = *override;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
current = (struct acpi_entry_hdr*)((uintptr_t)current + current->length);
|
||||||
|
}
|
||||||
|
}
|
||||||
12
kernel/amd64/apic.h
Normal file
12
kernel/amd64/apic.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#ifndef _KERNEL_AMD64_APIC_H
|
||||||
|
#define _KERNEL_AMD64_APIC_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
|
void amd64_ioapic_route_irq (uint8_t vec, uint8_t irq, uint64_t flags,
|
||||||
|
uint64_t lapic_id);
|
||||||
|
void amd64_ioapic_mask (uint8_t irq);
|
||||||
|
void amd64_ioapic_unmask (uint8_t irq);
|
||||||
|
void amd64_ioapic_init (void);
|
||||||
|
|
||||||
|
#endif // _KERNEL_AMD64_APIC_H
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
|
#include <amd64/apic.h>
|
||||||
|
#include <amd64/hpet.h>
|
||||||
#include <amd64/init.h>
|
#include <amd64/init.h>
|
||||||
#include <aux/compiler.h>
|
#include <aux/compiler.h>
|
||||||
#include <limine/limine.h>
|
#include <limine/limine.h>
|
||||||
#include <mm/liballoc.h>
|
#include <mm/liballoc.h>
|
||||||
#include <mm/pmm.h>
|
#include <mm/pmm.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
#include <sys/mm.h>
|
||||||
#include <uacpi/uacpi.h>
|
#include <uacpi/uacpi.h>
|
||||||
|
|
||||||
#define UACPI_MEMORY_BUFFER_MAX 4096
|
#define UACPI_MEMORY_BUFFER_MAX 4096
|
||||||
@@ -13,14 +16,22 @@ ALIGNED (16) static uint8_t uacpi_memory_buffer[UACPI_MEMORY_BUFFER_MAX];
|
|||||||
void bootmain (void) {
|
void bootmain (void) {
|
||||||
amd64_init ();
|
amd64_init ();
|
||||||
pmm_init ();
|
pmm_init ();
|
||||||
|
mm_init ();
|
||||||
|
|
||||||
uacpi_setup_early_table_access ((void*)uacpi_memory_buffer,
|
uacpi_setup_early_table_access ((void*)uacpi_memory_buffer,
|
||||||
sizeof (uacpi_memory_buffer));
|
sizeof (uacpi_memory_buffer));
|
||||||
|
|
||||||
|
amd64_ioapic_init ();
|
||||||
|
amd64_hpet_init ();
|
||||||
|
|
||||||
int* a = malloc (sizeof (int));
|
int* a = malloc (sizeof (int));
|
||||||
*a = 6969;
|
*a = 6969;
|
||||||
DEBUG ("a=%p, *a=%d\n", a, *a);
|
DEBUG ("a=%p, *a=%d\n", a, *a);
|
||||||
|
|
||||||
|
amd64_hpet_sleep_micro (3000000);
|
||||||
|
|
||||||
|
DEBUG ("woke up!!!\n");
|
||||||
|
|
||||||
for (;;)
|
for (;;)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
73
kernel/amd64/hpet.c
Normal file
73
kernel/amd64/hpet.c
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
#include <amd64/hpet.h>
|
||||||
|
#include <libk/std.h>
|
||||||
|
#include <limine/requests.h>
|
||||||
|
#include <sys/debug.h>
|
||||||
|
#include <sys/mm.h>
|
||||||
|
#include <uacpi/acpi.h>
|
||||||
|
#include <uacpi/status.h>
|
||||||
|
#include <uacpi/tables.h>
|
||||||
|
#include <uacpi/uacpi.h>
|
||||||
|
|
||||||
|
#define HPET_MCVR 0xF0 /* Main Counter Value Register */
|
||||||
|
#define HPET_GCR 0x10 /* General Configuration Register */
|
||||||
|
#define HPET_GCIDR 0x00 /* General Capabilities and ID Register */
|
||||||
|
|
||||||
|
static bool hpet_32bits = 1;
|
||||||
|
static uintptr_t hpet_paddr;
|
||||||
|
static uint64_t hpet_clock_nano;
|
||||||
|
|
||||||
|
extern void amd64_spin (void);
|
||||||
|
|
||||||
|
static uint64_t amd64_hpet_read (uint32_t reg) {
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
uintptr_t hpet_vaddr = hpet_paddr + (uintptr_t)hhdm->offset;
|
||||||
|
return (hpet_32bits ? *(volatile uint32_t*)(hpet_vaddr + reg)
|
||||||
|
: *(volatile uint64_t*)(hpet_vaddr + reg));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_hpet_write (uint32_t reg, uint64_t value) {
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
uintptr_t hpet_vaddr = hpet_paddr + (uintptr_t)hhdm->offset;
|
||||||
|
if (hpet_32bits)
|
||||||
|
*(volatile uint32_t*)(hpet_vaddr + reg) = (value & 0xFFFFFFFF);
|
||||||
|
else
|
||||||
|
*(volatile uint64_t*)(hpet_vaddr + reg) = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t amd64_hpet_timestamp (void) {
|
||||||
|
return amd64_hpet_read (HPET_MCVR);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t amd64_hpet_current_nano (void) {
|
||||||
|
return amd64_hpet_timestamp () * hpet_clock_nano;
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_hpet_sleep_micro (uint64_t us) {
|
||||||
|
uint64_t start = amd64_hpet_timestamp ();
|
||||||
|
uint64_t conv = us * 1000;
|
||||||
|
while (((amd64_hpet_timestamp () - start) * hpet_clock_nano) < conv)
|
||||||
|
__asm__ volatile ("pause" ::: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_hpet_init (void) {
|
||||||
|
struct uacpi_table hpet_table;
|
||||||
|
uacpi_status status =
|
||||||
|
uacpi_table_find_by_signature (ACPI_HPET_SIGNATURE, &hpet_table);
|
||||||
|
if (status != UACPI_STATUS_OK) {
|
||||||
|
DEBUG ("Could not find HPET table!\n");
|
||||||
|
amd64_spin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct acpi_hpet* hpet = (struct acpi_hpet*)hpet_table.virt_addr;
|
||||||
|
hpet_paddr = (uintptr_t)hpet->address.address;
|
||||||
|
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
mm_map_kernel_page (hpet_paddr, (uintptr_t)hhdm->offset + hpet_paddr,
|
||||||
|
MM_PG_PRESENT | MM_PG_RW);
|
||||||
|
|
||||||
|
hpet_32bits = (amd64_hpet_read (HPET_GCIDR) & (1 << 13)) ? 0 : 1;
|
||||||
|
|
||||||
|
amd64_hpet_write (HPET_GCR, amd64_hpet_read (HPET_GCR) | 0x01);
|
||||||
|
|
||||||
|
hpet_clock_nano = amd64_hpet_read (HPET_GCIDR + 4) / 1000000;
|
||||||
|
}
|
||||||
10
kernel/amd64/hpet.h
Normal file
10
kernel/amd64/hpet.h
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _KERNEL_AMD64_HPET_H
|
||||||
|
#define _KERNEL_AMD64_HPET_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
|
uint64_t amd64_hpet_current_nano (void);
|
||||||
|
void amd64_hpet_sleep_micro (uint64_t us);
|
||||||
|
void amd64_hpet_init (void);
|
||||||
|
|
||||||
|
#endif // _KERNEL_AMD64_HPET_H
|
||||||
163
kernel/amd64/mm.c
Normal file
163
kernel/amd64/mm.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
#include <aux/compiler.h>
|
||||||
|
#include <libk/std.h>
|
||||||
|
#include <libk/string.h>
|
||||||
|
#include <limine/requests.h>
|
||||||
|
#include <mm/pmm.h>
|
||||||
|
#include <sync/spin_lock.h>
|
||||||
|
#include <sys/mm.h>
|
||||||
|
|
||||||
|
#define AMD64_PG_PRESENT (1 << 0)
|
||||||
|
#define AMD64_PG_RW (1 << 1)
|
||||||
|
#define AMD64_PG_USER (1 << 2)
|
||||||
|
|
||||||
|
#define AMD64_PG_TABLE_ENTRIES_MAX 512
|
||||||
|
|
||||||
|
struct pg_index {
|
||||||
|
uint16_t pml4, pml3, pml2, pml1;
|
||||||
|
} PACKED;
|
||||||
|
|
||||||
|
struct pd kernel_pd = {.lock = SPIN_LOCK_INIT};
|
||||||
|
|
||||||
|
static uintptr_t amd64_current_cr3 (void) {
|
||||||
|
uintptr_t cr3;
|
||||||
|
__asm__ volatile ("movq %%cr3, %0" : "=r"(cr3)::"memory");
|
||||||
|
return cr3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct pg_index amd64_mm_page_index (uint64_t vaddr) {
|
||||||
|
struct pg_index ret;
|
||||||
|
|
||||||
|
ret.pml4 = ((vaddr >> 39) & 0x1FF);
|
||||||
|
ret.pml3 = ((vaddr >> 30) & 0x1FF);
|
||||||
|
ret.pml2 = ((vaddr >> 21) & 0x1FF);
|
||||||
|
ret.pml1 = ((vaddr >> 12) & 0x1FF);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t* amd64_mm_next_table (uint64_t* table, uint64_t entry_idx,
|
||||||
|
bool alloc) {
|
||||||
|
uint64_t entry = table[entry_idx];
|
||||||
|
uint64_t paddr;
|
||||||
|
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
|
if (entry & AMD64_PG_PRESENT)
|
||||||
|
paddr = entry & ~0xFFFULL;
|
||||||
|
else {
|
||||||
|
if (!alloc)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
paddr = pmm_alloc (1);
|
||||||
|
|
||||||
|
if (paddr == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
memset ((void*)((uintptr_t)hhdm->offset + (uintptr_t)paddr), 0, PAGE_SIZE);
|
||||||
|
table[entry_idx] = paddr | AMD64_PG_PRESENT | AMD64_PG_RW;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (uint64_t*)((uintptr_t)hhdm->offset + (uintptr_t)paddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t amd64_mm_resolve_flags (uint32_t generic) {
|
||||||
|
uint64_t flags = 0;
|
||||||
|
|
||||||
|
flags |= ((generic & MM_PG_PRESENT) ? AMD64_PG_PRESENT : 0);
|
||||||
|
flags |= ((generic & MM_PG_RW) ? AMD64_PG_RW : 0);
|
||||||
|
flags |= ((generic & MM_PG_USER) ? AMD64_PG_USER : 0);
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void amd64_reload_cr3 (void) {
|
||||||
|
uint64_t cr3;
|
||||||
|
__asm__ volatile ("movq %%cr3, %0; movq %0, %%cr3" : "=r"(cr3)::"memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_map_page (struct pd* pd, uintptr_t paddr, uintptr_t vaddr,
|
||||||
|
uint32_t flags) {
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
bool do_reload = false;
|
||||||
|
|
||||||
|
if (flags & MM_PD_LOCK)
|
||||||
|
spin_lock (&pd->lock);
|
||||||
|
|
||||||
|
uint64_t amd64_flags = amd64_mm_resolve_flags (flags);
|
||||||
|
|
||||||
|
uint64_t* pml4 = (uint64_t*)(pd->cr3_paddr + (uintptr_t)hhdm->offset);
|
||||||
|
struct pg_index pg_index = amd64_mm_page_index (vaddr);
|
||||||
|
|
||||||
|
uint64_t* pml3 = amd64_mm_next_table (pml4, pg_index.pml4, true);
|
||||||
|
if (pml3 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pml2 = amd64_mm_next_table (pml3, pg_index.pml3, true);
|
||||||
|
if (pml2 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pml1 = amd64_mm_next_table (pml2, pg_index.pml2, true);
|
||||||
|
if (pml1 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pte = &pml1[pg_index.pml1];
|
||||||
|
|
||||||
|
*pte = ((paddr & ~0xFFFULL) | (amd64_flags & 0x7ULL));
|
||||||
|
do_reload = true;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (do_reload)
|
||||||
|
amd64_reload_cr3 ();
|
||||||
|
|
||||||
|
if (flags & MM_PD_LOCK)
|
||||||
|
spin_unlock (&pd->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_map_kernel_page (uintptr_t paddr, uintptr_t vaddr, uint32_t flags) {
|
||||||
|
mm_map_page (&kernel_pd, paddr, vaddr, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_unmap_page (struct pd* pd, uintptr_t vaddr, uint32_t flags) {
|
||||||
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
bool do_reload = false;
|
||||||
|
|
||||||
|
if (flags & MM_PD_LOCK)
|
||||||
|
spin_lock (&pd->lock);
|
||||||
|
|
||||||
|
uint64_t* pml4 = (uint64_t*)(pd->cr3_paddr + (uintptr_t)hhdm->offset);
|
||||||
|
struct pg_index pg_index = amd64_mm_page_index (vaddr);
|
||||||
|
|
||||||
|
uint64_t* pml3 = amd64_mm_next_table (pml4, pg_index.pml4, true);
|
||||||
|
if (pml3 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pml2 = amd64_mm_next_table (pml3, pg_index.pml3, true);
|
||||||
|
if (pml2 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pml1 = amd64_mm_next_table (pml2, pg_index.pml2, true);
|
||||||
|
if (pml1 == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
uint64_t* pte = &pml1[pg_index.pml1];
|
||||||
|
|
||||||
|
*pte &= ~AMD64_PG_PRESENT;
|
||||||
|
do_reload = true;
|
||||||
|
|
||||||
|
done:
|
||||||
|
if (do_reload)
|
||||||
|
amd64_reload_cr3 ();
|
||||||
|
|
||||||
|
if (flags & MM_PD_LOCK)
|
||||||
|
spin_unlock (&pd->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_unmap_kernel_page (uintptr_t vaddr, uint32_t flags) {
|
||||||
|
mm_unmap_page (&kernel_pd, vaddr, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mm_lock_kernel (void) { spin_lock (&kernel_pd.lock); }
|
||||||
|
|
||||||
|
void mm_unlock_kernel (void) { spin_unlock (&kernel_pd.lock); }
|
||||||
|
|
||||||
|
void mm_init (void) { kernel_pd.cr3_paddr = amd64_current_cr3 (); }
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
#ifndef _KERNEL_AMD64_MM_H
|
#ifndef _KERNEL_AMD64_MM_H
|
||||||
#define _KERNEL_AMD64_MM_H
|
#define _KERNEL_AMD64_MM_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
#include <sync/spin_lock.h>
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
struct pd {
|
||||||
|
spin_lock_t lock;
|
||||||
|
uintptr_t cr3_paddr;
|
||||||
|
};
|
||||||
|
|
||||||
#endif // _KERNEL_AMD64_MM_H
|
#endif // _KERNEL_AMD64_MM_H
|
||||||
|
|||||||
14
kernel/amd64/msr.c
Normal file
14
kernel/amd64/msr.c
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
#include <amd64/msr.h>
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
|
uint64_t amd64_rdmsr (uint32_t msr) {
|
||||||
|
uint32_t low, high;
|
||||||
|
__asm__ volatile ("rdmsr" : "=a"(low), "=d"(high) : "c"(msr));
|
||||||
|
return ((uint64_t)high << 32 | (uint64_t)low);
|
||||||
|
}
|
||||||
|
|
||||||
|
void amd64_wrmsr (uint32_t msr, uint64_t value) {
|
||||||
|
uint32_t low = (uint32_t)(value & 0xFFFFFFFF);
|
||||||
|
uint32_t high = (uint32_t)(value >> 32);
|
||||||
|
__asm__ volatile ("wrmsr" ::"c"(msr), "a"(low), "d"(high));
|
||||||
|
}
|
||||||
9
kernel/amd64/msr.h
Normal file
9
kernel/amd64/msr.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _KERNEL_AMD64_MSR_H
|
||||||
|
#define _KERNEL_AMD64_MSR_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
|
uint64_t amd64_rdmsr (uint32_t msr);
|
||||||
|
void amd64_wrmsr (uint32_t msr, uint64_t value);
|
||||||
|
|
||||||
|
#endif // _KERNEL_AMD64_MSR_H
|
||||||
@@ -4,7 +4,11 @@ c += amd64/bootmain.c \
|
|||||||
amd64/io.c \
|
amd64/io.c \
|
||||||
amd64/debug.c \
|
amd64/debug.c \
|
||||||
amd64/spin_lock.c \
|
amd64/spin_lock.c \
|
||||||
amd64/intr.c
|
amd64/intr.c \
|
||||||
|
amd64/apic.c \
|
||||||
|
amd64/msr.c \
|
||||||
|
amd64/hpet.c \
|
||||||
|
amd64/mm.c
|
||||||
|
|
||||||
S += amd64/intr_stub.S \
|
S += amd64/intr_stub.S \
|
||||||
amd64/spin.S
|
amd64/spin.S
|
||||||
@@ -17,4 +21,8 @@ o += amd64/bootmain.o \
|
|||||||
amd64/spin_lock.o \
|
amd64/spin_lock.o \
|
||||||
amd64/intr.o \
|
amd64/intr.o \
|
||||||
amd64/intr_stub.o \
|
amd64/intr_stub.o \
|
||||||
amd64/spin.o
|
amd64/spin.o \
|
||||||
|
amd64/apic.o \
|
||||||
|
amd64/msr.o \
|
||||||
|
amd64/hpet.o \
|
||||||
|
amd64/mm.o
|
||||||
|
|||||||
@@ -1,8 +1,24 @@
|
|||||||
#ifndef _KERNEL_SYS_MM_H
|
#ifndef _KERNEL_SYS_MM_H
|
||||||
#define _KERNEL_SYS_MM_H
|
#define _KERNEL_SYS_MM_H
|
||||||
|
|
||||||
|
#include <libk/std.h>
|
||||||
|
|
||||||
#if defined(__x86_64__)
|
#if defined(__x86_64__)
|
||||||
#include <amd64/mm.h>
|
#include <amd64/mm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define MM_PG_PRESENT (1 << 0)
|
||||||
|
#define MM_PG_RW (1 << 1)
|
||||||
|
#define MM_PG_USER (1 << 2)
|
||||||
|
#define MM_PD_LOCK (1 << 31)
|
||||||
|
|
||||||
|
void mm_map_page (struct pd* pd, uintptr_t paddr, uintptr_t vaddr,
|
||||||
|
uint32_t flags);
|
||||||
|
void mm_map_kernel_page (uintptr_t paddr, uintptr_t vaddr, uint32_t flags);
|
||||||
|
void mm_unmap_page (struct pd* pd, uintptr_t vaddr, uint32_t flags);
|
||||||
|
void mm_unmap_kernel_page (uintptr_t vaddr, uint32_t flags);
|
||||||
|
void mm_lock_kernel (void);
|
||||||
|
void mm_unlock_kernel (void);
|
||||||
|
void mm_init (void);
|
||||||
|
|
||||||
#endif // _KERNEL_SYS_MM_H
|
#endif // _KERNEL_SYS_MM_H
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
#include <libk/align.h>
|
||||||
#include <libk/std.h>
|
#include <libk/std.h>
|
||||||
#include <limine/requests.h>
|
#include <limine/requests.h>
|
||||||
#include <mm/liballoc.h>
|
#include <mm/liballoc.h>
|
||||||
#include <sys/debug.h>
|
#include <sys/debug.h>
|
||||||
|
#include <sys/mm.h>
|
||||||
#include <uacpi/kernel_api.h>
|
#include <uacpi/kernel_api.h>
|
||||||
#include <uacpi/status.h>
|
#include <uacpi/status.h>
|
||||||
|
|
||||||
@@ -17,11 +19,16 @@ uacpi_status uacpi_kernel_get_rsdp (uacpi_phys_addr* out_rsdp_address) {
|
|||||||
|
|
||||||
void* uacpi_kernel_map (uacpi_phys_addr addr, uacpi_size len) {
|
void* uacpi_kernel_map (uacpi_phys_addr addr, uacpi_size len) {
|
||||||
(void)len;
|
(void)len;
|
||||||
|
|
||||||
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
struct limine_hhdm_response* hhdm = limine_hhdm_request.response;
|
||||||
|
|
||||||
return (void*)((uintptr_t)hhdm->offset + (uintptr_t)addr);
|
return (void*)((uintptr_t)hhdm->offset + (uintptr_t)addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void uacpi_kernel_unmap (void* addr, uacpi_size len) { (void)addr, (void)len; }
|
void uacpi_kernel_unmap (void* addr, uacpi_size len) {
|
||||||
|
(void)addr;
|
||||||
|
(void)len;
|
||||||
|
}
|
||||||
|
|
||||||
void uacpi_kernel_log (uacpi_log_level level, const uacpi_char* msg) {
|
void uacpi_kernel_log (uacpi_log_level level, const uacpi_char* msg) {
|
||||||
const char* prefix = NULL;
|
const char* prefix = NULL;
|
||||||
|
|||||||
Reference in New Issue
Block a user