Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ add_custom_target(run
-drive file=os.img,format=raw
-serial stdio
-device isa-debug-exit,iobase=0xf4,iosize=0x04
-netdev user,id=net0
-device virtio-net-pci,netdev=net0
-audiodev pa,id=speaker
-machine pcspk-audiodev=speaker
-d int
-D qemu.log
DEPENDS os)
6 changes: 5 additions & 1 deletion kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ set(COMPILE_OPTIONS

add_library(drivers OBJECT
src/arch/x86_64/drivers/keyboard/keyboard.c
src/arch/x86_64/drivers/timer/timer.c
src/arch/x86_64/drivers/mouse/mouse.c
src/arch/x86_64/drivers/pci/pci.c
src/arch/x86_64/drivers/speaker/speaker.c
src/arch/x86_64/drivers/timer/apic.c
src/arch/x86_64/drivers/timer/pit.c
src/arch/x86_64/klib/trap.c
)

Expand Down
66 changes: 61 additions & 5 deletions kernel/src/arch/x86_64/acpi/acpi.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ bool rsdt_map(void) {
return verify_mapping(rsdt);
}

static bool rsdt_entry_verify(void *entry) {
uint8_t sum = 0;
struct description_header *header = (struct description_header *) entry;
uint8_t *addr = (uint8_t *) entry;
for (size_t i = 0; i < header->length; i++) {
sum += addr[i];
}
return !sum;
}

bool rsdt_verify(void) {
uint8_t sum = 0;
for (size_t i = 0; i < rsdt->length; i++) {
Expand All @@ -84,19 +94,18 @@ static size_t rsdt_get_entry_count(void) {

static struct madt *madt = NULL;

bool madt_find(void) {
static void *rsdt_get_entry(char *signature) {
size_t length = rsdt_get_entry_count();

for (size_t i = 0; i < length; i++) {
struct description_header *description_header =
kmap_page((void *) (uint64_t) rsdt->entry[i], PAGE_PRESENT);

if (!memcmp(description_header->signature, MADT_SIGNATURE, 4)) {
madt = (struct madt *) (uint64_t) rsdt->entry[i];
return true;
if (!memcmp(description_header->signature, signature, 4)) {
return (struct madt *) (uint64_t) rsdt->entry[i];
}
}
return false;
return NULL;
}

bool madt_map(void) {
Expand All @@ -113,6 +122,12 @@ bool madt_verify(void) {
return !sum;
}


bool madt_find(void) {
madt = rsdt_get_entry(MADT_SIGNATURE);
return madt != NULL;
}

uint32_t madt_get_lapic_address(void) {
return madt->local_interrupt_controller_address;
}
Expand All @@ -121,6 +136,8 @@ static struct madt_entry **madt_entries = NULL;
static size_t max_madt_entries = 0;

size_t ioapic_count_entries(void) {
if (madt_entries != NULL) return max_madt_entries;

// all entries are after madt
struct madt_entry *madt_entry =
(struct madt_entry *) ((uint8_t *) madt + sizeof(struct madt));
Expand All @@ -146,3 +163,42 @@ size_t ioapic_count_entries(void) {
struct madt_entry **get_madt_entries(void) {
return madt_entries;
}

#define MCFG_SIGNATURE "MCFG"

static struct mcfg *mcfg = NULL;

bool mcfg_find(void) {
mcfg = rsdt_get_entry(MCFG_SIGNATURE);
return mcfg != NULL;
}

bool mcfg_verify(void) {
return rsdt_entry_verify(mcfg);
}

bool mcfg_map(void) {
mcfg = kmap_page(mcfg, PAGE_PRESENT);
return verify_mapping(mcfg);
}

static struct mcfg_entry **mcfg_entries = NULL;
static size_t max_mcfg_entries = 0;

size_t mcfg_count_entries(void) {
if (mcfg_entries != NULL) return max_madt_entries;

struct mcfg_entry *mcfg_entry =
(struct mcfg_entry *) ((uint8_t *) mcfg + sizeof(struct mcfg));

uint8_t *end = (uint8_t *) mcfg + mcfg->length;
max_mcfg_entries = (end - (uint8_t *) mcfg_entry) / sizeof(struct mcfg_entry);

mcfg_entries = kmalloc(sizeof(*mcfg_entries) * max_mcfg_entries);

for (size_t i = 0; (uint8_t *) mcfg_entry < end; i++) {
mcfg_entries[i] = mcfg_entry;
mcfg_entry = (struct mcfg_entry *) ((uint8_t *) mcfg_entry + sizeof(struct mcfg_entry));
}
return max_madt_entries;
}
29 changes: 29 additions & 0 deletions kernel/src/arch/x86_64/acpi/acpi.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,23 @@ struct madt_entry_apicio {
uint32_t global_system_interrupt_base;
} __attribute__((packed));

struct mcfg_entry {
uint64_t address;
// PCI segment group number
uint16_t pci_group;
uint8_t start_PCI_bus;
uint8_t end_PCI_bus;
uint32_t reserved;
} __attribute__((packed));

// from here: https://wiki.osdev.org/PCI_Express
// not specified in ACPI spec (probs needs to find it in pcie spec)
struct mcfg {
DESCRIPTION_HEADER
uint8_t reserved[8];
struct mcfg_entry data[];
} __attribute__((packed));

// Finds the rsdp and sets the address
bool rsdp_find(void);

Expand Down Expand Up @@ -102,3 +119,15 @@ size_t ioapic_count_entries(void);

// Returns a array of addresses to madts
struct madt_entry **get_madt_entries(void);

// Finds the mcfg
bool mcfg_find(void);

// Verifies the mcfg
bool mcfg_verify(void);

// Maps the mcfg to a virtual memory address
bool mcfg_map(void);

// Counts the entries of the mcfg
size_t mcfg_count_entries(void);
22 changes: 4 additions & 18 deletions kernel/src/arch/x86_64/apic/lapic.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

#include "../cpu/cpuid.h"
#include "../cpu/msr.h"
#include "../memory/paging.h"
#include "../serial/serial.h"

#define IA32_APIC_BASE_MSR 0x1B
Expand Down Expand Up @@ -39,8 +38,6 @@ static uintptr_t cpu_get_apic_base(void) {
// todo: read from acpi to figure out ioapicbase
// todo: since its not guaranteed to be same in all systems

#define BASE_LAPIC 0xFEE00000

void write_reg(void *lapicbase, uint32_t reg, uint32_t value) {
uint32_t volatile *lapic = (uint32_t volatile *) lapicbase;
lapic[reg] = value;
Expand All @@ -51,6 +48,8 @@ uint32_t read_reg(void *lapicbase, uint32_t reg) {
return lapic[reg];
}

#define BASE_LAPIC 0xFEE00000

#define PIC1 0x20 /* IO base address for master PIC */
#define PIC2 0xA0 /* IO base address for slave PIC */
#define PIC1_DATA (PIC1 + 1)
Expand All @@ -77,19 +76,6 @@ void send_apic_eoi(void) {
*(uint32_t volatile *) ((uint64_t) lapic + 0xB0) = 0;
}

// Refer to Intel IA-32 Volume 3 12.5.4 APIC Timer
void init_apic_timer(uint32_t initial_count, uint8_t vector) {
// be divisble by 1 (every 10ms) (Figure 12-10)
*(uint32_t volatile *) ((uint64_t) lapic + 0x3E0) = 1011;
// set initial count (Figure 12-11)
*(uint32_t volatile *) ((uint64_t) lapic + 0x380) = initial_count;
// Refer to 12.5.1 (Timer mode and vector in Figure 12-8)
// 0 = one shot, 1 = periodic, 2 = TSC-deadline
#define APIC_TIMER_MODE 0
*(uint32_t volatile *) ((uint64_t) lapic + 0x320) =
vector | (APIC_TIMER_MODE << 17);
}

uint32_t get_apic_timer_current(void) {
return *(uint32_t volatile *) ((uint64_t) lapic + 0x390);
void *apic_get_address(void) {
return lapic;
}
9 changes: 4 additions & 5 deletions kernel/src/arch/x86_64/apic/lapic.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <stdbool.h>
#include <stdint.h>

#include "../memory/paging.h"

// Checks whether apic is supported
bool apic_is_supported(void);

Expand All @@ -24,8 +26,5 @@ void write_reg(void *ioapicaddr, uint32_t reg, uint32_t value);
// Signal end of interrupt to apic
void send_apic_eoi(void);

// Initialises the apic timer
void init_apic_timer(uint32_t initial_count, uint8_t vector);

// Get the current count of apic timer
uint32_t get_apic_timer_current(void);
// Get apic address
void *apic_get_address(void);
4 changes: 2 additions & 2 deletions kernel/src/arch/x86_64/cpu/idt.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ static uint16_t idt_segment_descriptor(uint16_t index) {
return ((index & 0xFFF) << 3);
}

void setup_interrupt_gate(uint32_t irq, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist) {
struct interrupt_descriptor *interrupt_descriptor = &interrupt_descriptors[irq];
void setup_interrupt_gate(uint32_t vector, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist) {
struct interrupt_descriptor *interrupt_descriptor = &interrupt_descriptors[vector];

// present bit must be set for descriptor to be valid
interrupt_descriptor->type_attributes |= 1 << 15;
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/arch/x86_64/cpu/idt.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,6 @@ enum gate_type {
TRAP_64_GATE = 0xF
};

void setup_interrupt_gate(uint32_t irq, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist);
void setup_interrupt_gate(uint32_t vector, void *base, enum gate_type type, uint8_t privilege_level, uint8_t ist);

void load_idt(void);
Loading