Initial commit - slab allocator, kmalloc, other re
factors
This commit is contained in:
parent
1dd7b8b07f
commit
4e40a040dd
39 changed files with 863 additions and 412 deletions
6
.vscode/settings.json
vendored
Normal file
6
.vscode/settings.json
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"clangd.arguments": [
|
||||||
|
"--background-index"
|
||||||
|
]
|
||||||
|
|
||||||
|
}
|
||||||
7
Makefile
7
Makefile
|
|
@ -48,7 +48,7 @@ all:
|
||||||
$(CC) -c src/flanterm/src/flanterm.c -o $(BUILD_DIR)/flanterm.o $(CFLAGS)
|
$(CC) -c src/flanterm/src/flanterm.c -o $(BUILD_DIR)/flanterm.o $(CFLAGS)
|
||||||
$(CC) -c src/flanterm/src/flanterm_backends/fb.c -o $(BUILD_DIR)/fb.o $(CFLAGS)
|
$(CC) -c src/flanterm/src/flanterm_backends/fb.c -o $(BUILD_DIR)/fb.o $(CFLAGS)
|
||||||
$(CC) -c src/lib/string.c -o $(BUILD_DIR)/string.o $(CFLAGS)
|
$(CC) -c src/lib/string.c -o $(BUILD_DIR)/string.o $(CFLAGS)
|
||||||
$(CC) -c src/lib/stdio.c -o $(BUILD_DIR)/stdio.o $(CFLAGS)
|
$(CC) -c src/lib/kprint.c -o $(BUILD_DIR)/kprint.o $(CFLAGS)
|
||||||
$(CC) -c src/lib/io.c -o $(BUILD_DIR)/io.o $(CFLAGS)
|
$(CC) -c src/lib/io.c -o $(BUILD_DIR)/io.o $(CFLAGS)
|
||||||
$(CC) -c src/lib/spinlock.c -o $(BUILD_DIR)/spinlock.o $(CFLAGS)
|
$(CC) -c src/lib/spinlock.c -o $(BUILD_DIR)/spinlock.o $(CFLAGS)
|
||||||
|
|
||||||
|
|
@ -61,8 +61,11 @@ all:
|
||||||
$(CC) -c src/hal/timer.c -o $(BUILD_DIR)/timer.o $(CFLAGS)
|
$(CC) -c src/hal/timer.c -o $(BUILD_DIR)/timer.o $(CFLAGS)
|
||||||
$(CC) -c src/hal/smp.c -o $(BUILD_DIR)/smp.o $(CFLAGS)
|
$(CC) -c src/hal/smp.c -o $(BUILD_DIR)/smp.o $(CFLAGS)
|
||||||
$(CC) -c src/hal/tsc.c -o $(BUILD_DIR)/tsc.o $(CFLAGS)
|
$(CC) -c src/hal/tsc.c -o $(BUILD_DIR)/tsc.o $(CFLAGS)
|
||||||
|
$(CC) -c src/sys/rand.c -o $(BUILD_DIR)/rand.o $(CFLAGS)
|
||||||
$(CC) -c src/mm/pmm.c -o $(BUILD_DIR)/pmm.o $(CFLAGS)
|
$(CC) -c src/mm/pmm.c -o $(BUILD_DIR)/pmm.o $(CFLAGS)
|
||||||
$(CC) -c src/mm/vmm.c -o $(BUILD_DIR)/vmm.o $(CFLAGS)
|
$(CC) -c src/mm/vmm.c -o $(BUILD_DIR)/vmm.o $(CFLAGS)
|
||||||
|
$(CC) -c src/mm/page.c -o $(BUILD_DIR)/page.o $(CFLAGS)
|
||||||
|
$(CC) -c src/mm/slab.c -o $(BUILD_DIR)/slab.o $(CFLAGS)
|
||||||
$(CC) -c src/mm/kmalloc.c -o $(BUILD_DIR)/kmalloc.o $(CFLAGS)
|
$(CC) -c src/mm/kmalloc.c -o $(BUILD_DIR)/kmalloc.o $(CFLAGS)
|
||||||
$(CC) -c src/sys/acpi.c -o $(BUILD_DIR)/acpi.o $(CFLAGS)
|
$(CC) -c src/sys/acpi.c -o $(BUILD_DIR)/acpi.o $(CFLAGS)
|
||||||
$(CC) -c src/sys/pci.c -o $(BUILD_DIR)/pci.o $(CFLAGS)
|
$(CC) -c src/sys/pci.c -o $(BUILD_DIR)/pci.o $(CFLAGS)
|
||||||
|
|
@ -100,3 +103,5 @@ disk:
|
||||||
dd if=/dev/zero of=disk.img bs=1M count=128
|
dd if=/dev/zero of=disk.img bs=1M count=128
|
||||||
elftest:
|
elftest:
|
||||||
$(CC) src/elf/elftest.c -o $(BUILD_DIR)/elftest -ffreestanding -Isrc/include -static -fPIE -nostdlib
|
$(CC) src/elf/elftest.c -o $(BUILD_DIR)/elftest -ffreestanding -Isrc/include -static -fPIE -nostdlib
|
||||||
|
clean:
|
||||||
|
rm -r build/
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@
|
||||||
# Args are fed to QEMU, then GDB and everything else does shit automagically
|
# Args are fed to QEMU, then GDB and everything else does shit automagically
|
||||||
# 1st arg: terminal name to spawn GDB
|
# 1st arg: terminal name to spawn GDB
|
||||||
# 2nd arg: place to breakpoint in
|
# 2nd arg: place to breakpoint in
|
||||||
|
# 3rd+ arguments all get passed to QEMU
|
||||||
termname=$1
|
termname=$1
|
||||||
breakpoint=$2
|
breakpoint=$2
|
||||||
shift 2
|
shift 2
|
||||||
|
|
||||||
qemu-system-x86_64 "$@" &
|
qemu-system-x86_64 -s -S "$@" &
|
||||||
|
|
||||||
sleep 1
|
sleep 1
|
||||||
|
|
||||||
|
|
|
||||||
64
slaballoc.c
64
slaballoc.c
|
|
@ -1,64 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include "slaballoc.h"
|
|
||||||
|
|
||||||
char memory[4096 * 10];
|
|
||||||
|
|
||||||
int cnt = 0;
|
|
||||||
|
|
||||||
struct ma_kcache *head = NULL; // create standard sizes
|
|
||||||
|
|
||||||
|
|
||||||
uint64_t *alloc_contigious_pages(int num){
|
|
||||||
uint64_t *ret = (uint64_t*)(memory + cnt*4096);
|
|
||||||
cnt+=num;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
struct ma_slab *_ma_alloc_initial_slab(struct ma_kcache *kcache){
|
|
||||||
uint64_t *p = alloc_contigious_pages(1);
|
|
||||||
|
|
||||||
int bufnum = (4096 - sizeof(struct ma_slab)) / kcache->objsize; // Calculate the number of buffers in this slab
|
|
||||||
|
|
||||||
for(int i = 0; i < bufnum; i++){
|
|
||||||
(uint64_t*)((uint64_t)p + i * kcache->objsize)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t)){
|
|
||||||
|
|
||||||
struct ma_kcache *kcache = (struct ma_kcache*)alloc_contigious_pages(1);
|
|
||||||
|
|
||||||
head->next = kcache;
|
|
||||||
kcache->prev = head;
|
|
||||||
head = kcache;
|
|
||||||
|
|
||||||
int bufnum = (4096 - sizeof(struct ma_slab)) / size; // Calculate the number of buffers in this slab
|
|
||||||
|
|
||||||
struct ma_slab *slab_structure = (struct ma_slab*)((uint64_t)kcache - sizeof(struct ma_slab));
|
|
||||||
|
|
||||||
kcache->slabs_free = slab_structure;
|
|
||||||
|
|
||||||
return kcache;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void *ma_cache_alloc(struct ma_kcache *cache, uint64_t flags){
|
|
||||||
|
|
||||||
if(cache->slabs_free == NULL){
|
|
||||||
if(cache->slabs_partial == NULL){
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
common:
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(){
|
|
||||||
|
|
||||||
}
|
|
||||||
38
slaballoc.h
38
slaballoc.h
|
|
@ -1,38 +0,0 @@
|
||||||
#include <stddef.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <stdbool.h>
|
|
||||||
#define KCACHE_NAME_LEN 5
|
|
||||||
|
|
||||||
|
|
||||||
struct ma_bufctrl {
|
|
||||||
struct ma_bufctrl *next;
|
|
||||||
size_t *startaddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct ma_slab {
|
|
||||||
struct ma_slab *next;
|
|
||||||
struct ma_slab *prev;
|
|
||||||
|
|
||||||
struct ma_bufctrl *buf_list;
|
|
||||||
|
|
||||||
uint32_t refcount;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ma_kcache {
|
|
||||||
struct ma_kcache *next;
|
|
||||||
struct ma_kcache *prev;
|
|
||||||
|
|
||||||
uint32_t objsize;
|
|
||||||
uint32_t flags;
|
|
||||||
uint32_t num;
|
|
||||||
|
|
||||||
struct ma_slab *slabs_free;
|
|
||||||
struct ma_slab *slabs_partial;
|
|
||||||
struct ma_slab *slabs_used;
|
|
||||||
|
|
||||||
struct ma_bufctrl *bufctrl_arr;
|
|
||||||
|
|
||||||
char name[KCACHE_NAME_LEN];
|
|
||||||
};
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include "../hal/apic.h"
|
#include "../hal/apic.h"
|
||||||
#include "../sys/pci.h"
|
#include "../sys/pci.h"
|
||||||
#include "../mm/vmm.h"
|
#include "../mm/vmm.h"
|
||||||
|
|
@ -34,7 +34,7 @@ void ahci_init(){
|
||||||
pci_header_0_t *header = (pci_header_0_t *)pci_find_device(AHCI_CLASS_ID, AHCI_SUBCLASS_ID);
|
pci_header_0_t *header = (pci_header_0_t *)pci_find_device(AHCI_CLASS_ID, AHCI_SUBCLASS_ID);
|
||||||
|
|
||||||
if(!header){
|
if(!header){
|
||||||
klog(LOG_ERROR, __func__, "AHCI controller not found!");
|
klog(__func__, "AHCI controller not found!");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -50,7 +50,7 @@ void ahci_init(){
|
||||||
header->header.command |= AHCI_MSE | AHCI_BME | AHCI_INT_ENABLED;
|
header->header.command |= AHCI_MSE | AHCI_BME | AHCI_INT_ENABLED;
|
||||||
|
|
||||||
/* Map the AHCI registers */
|
/* Map the AHCI registers */
|
||||||
kernel_map_pages((uint64_t*)ahci_base_address, 1, PTE_BIT_RW | PTE_BIT_NX | PTE_BIT_UNCACHABLE);
|
kmap_pages((uint64_t*)ahci_base_address, 1, PTE_BIT_RW | PTE_BIT_NX | PTE_BIT_UNCACHABLE);
|
||||||
|
|
||||||
ahci_base_address += hhdmoffset;
|
ahci_base_address += hhdmoffset;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "../sys/acpi.h"
|
#include "../sys/acpi.h"
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
|
|
@ -27,7 +27,7 @@ uint64_t pmt_read_reg(gas_t X_PMTimerBlock){
|
||||||
return inl(X_PMTimerBlock.address);
|
return inl(X_PMTimerBlock.address);
|
||||||
}else{
|
}else{
|
||||||
serial_kprintf("address id: 0x{xn}", X_PMTimerBlock.address_space_id);
|
serial_kprintf("address id: 0x{xn}", X_PMTimerBlock.address_space_id);
|
||||||
klog(LOG_ERROR, __func__, "X_PMTimerBlock address space id isn't supported!");
|
klog(__func__, "X_PMTimerBlock address space id isn't supported!");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -36,7 +36,7 @@ int pmt_init(){
|
||||||
fadt = (fadt_t*)((uint64_t)find_acpi_table("FACP"));
|
fadt = (fadt_t*)((uint64_t)find_acpi_table("FACP"));
|
||||||
|
|
||||||
if(!fadt){
|
if(!fadt){
|
||||||
klog(LOG_ERROR, __func__, "Didn't find FADT table");
|
klog(__func__, "Didn't find FADT table");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "../sys/acpi.h"
|
#include "../sys/acpi.h"
|
||||||
#include "../hal/ioapic.h"
|
#include "../hal/ioapic.h"
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
|
|
||||||
#define COM1 0x3F8
|
#define COM1 0x3F8
|
||||||
|
|
||||||
|
|
@ -43,7 +43,7 @@ void serial_init(){
|
||||||
outb(COM1, 0xAE);
|
outb(COM1, 0xAE);
|
||||||
|
|
||||||
if(inb(COM1) != 0xAE){
|
if(inb(COM1) != 0xAE){
|
||||||
klog(LOG_WARN, __func__, "Serial controller failed test, serial output will not work");
|
klog(__func__, "Serial controller failed test, serial output will not work");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include "ioapic.h"
|
#include "ioapic.h"
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <cpuid.h> // GCC specific
|
#include <cpuid.h> // GCC specific
|
||||||
|
|
||||||
|
|
@ -55,7 +55,7 @@ void apic_sleep(uint64_t ms){
|
||||||
|
|
||||||
atomic_flag lapic_timer_flag = ATOMIC_FLAG_INIT;
|
atomic_flag lapic_timer_flag = ATOMIC_FLAG_INIT;
|
||||||
void lapic_timer_init(int us){
|
void lapic_timer_init(int us){
|
||||||
acquire_lock(&lapic_timer_flag);
|
acquire_spinlock(&lapic_timer_flag);
|
||||||
/* Stop the APIC timer */
|
/* Stop the APIC timer */
|
||||||
lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, 0);
|
lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, 0);
|
||||||
|
|
||||||
|
|
@ -80,7 +80,7 @@ void lapic_timer_init(int us){
|
||||||
/* Set the inital count to the calibration */
|
/* Set the inital count to the calibration */
|
||||||
lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, calibration);
|
lapic_write_reg(LAPIC_TIMER_INITIAL_CNT_REG, calibration);
|
||||||
|
|
||||||
free_lock(&lapic_timer_flag);
|
free_spinlock(&lapic_timer_flag);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
|
|
||||||
gdt_descriptor gdt[5] = {0};
|
gdt_descriptor gdt[5] = {0};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
idt_descriptor idt[256] = {0};
|
idt_descriptor idt[256] = {0};
|
||||||
|
|
@ -60,10 +60,10 @@ atomic_flag irq_register_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
/* Registers an IRQ with the specified vector. */
|
/* Registers an IRQ with the specified vector. */
|
||||||
kstatus register_irq_vector(uint8_t vector, void *base, uint8_t flags){
|
kstatus register_irq_vector(uint8_t vector, void *base, uint8_t flags){
|
||||||
acquire_lock(&irq_register_lock);
|
acquire_spinlock(&irq_register_lock);
|
||||||
|
|
||||||
if(!irq_list[vector].in_use){
|
if(!irq_list[vector].in_use){
|
||||||
free_lock(&irq_register_lock);
|
free_spinlock(&irq_register_lock);
|
||||||
return KERNEL_STATUS_ERROR;
|
return KERNEL_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,27 +74,27 @@ kstatus register_irq_vector(uint8_t vector, void *base, uint8_t flags){
|
||||||
|
|
||||||
s_load_idt();
|
s_load_idt();
|
||||||
|
|
||||||
free_lock(&irq_register_lock);
|
free_spinlock(&irq_register_lock);
|
||||||
|
|
||||||
return KERNEL_STATUS_SUCCESS;
|
return KERNEL_STATUS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Registers an IRQ and returns the vector */
|
/* Registers an IRQ and returns the vector */
|
||||||
int register_irq(void *base, uint8_t flags){
|
int register_irq(void *base, uint8_t flags){
|
||||||
acquire_lock(&irq_register_lock);
|
acquire_spinlock(&irq_register_lock);
|
||||||
|
|
||||||
for(size_t i = 0; i < MAX_IRQ; i++){
|
for(size_t i = 0; i < MAX_IRQ; i++){
|
||||||
if(!irq_list[i].in_use) {
|
if(!irq_list[i].in_use) {
|
||||||
set_idt_descriptor(i, base, flags);
|
set_idt_descriptor(i, base, flags);
|
||||||
irq_list[i].base = base;
|
irq_list[i].base = base;
|
||||||
irq_list[i].in_use = true;
|
irq_list[i].in_use = true;
|
||||||
free_lock(&irq_register_lock);
|
free_spinlock(&irq_register_lock);
|
||||||
s_load_idt();
|
s_load_idt();
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_lock(&irq_register_lock);
|
free_spinlock(&irq_register_lock);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include "../sys/acpi.h"
|
#include "../sys/acpi.h"
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
@ -53,7 +53,7 @@ void ioapic_init(void){
|
||||||
ioapic_t *ioapic = (ioapic_t*) find_ics(0x1);
|
ioapic_t *ioapic = (ioapic_t*) find_ics(0x1);
|
||||||
|
|
||||||
if(!ioapic){
|
if(!ioapic){
|
||||||
klog(LOG_ERROR, __func__, "IOAPIC ICS not found\n");
|
klog(__func__, "IOAPIC ICS not found\n");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include "smp.h"
|
#include "smp.h"
|
||||||
|
|
@ -42,7 +42,7 @@ atomic_flag ap_init_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
void ap_init(struct limine_smp_info *smp_info){
|
void ap_init(struct limine_smp_info *smp_info){
|
||||||
|
|
||||||
acquire_lock(&ap_init_lock);
|
acquire_spinlock(&ap_init_lock);
|
||||||
|
|
||||||
/* Load the GDT */
|
/* Load the GDT */
|
||||||
s_load_gdt();
|
s_load_gdt();
|
||||||
|
|
@ -71,7 +71,7 @@ void ap_init(struct limine_smp_info *smp_info){
|
||||||
/* Initialize APIC & APIC timer */
|
/* Initialize APIC & APIC timer */
|
||||||
ap_apic_init();
|
ap_apic_init();
|
||||||
|
|
||||||
free_lock(&ap_init_lock);
|
free_spinlock(&ap_init_lock);
|
||||||
|
|
||||||
for(;;);
|
for(;;);
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ void ap_init(struct limine_smp_info *smp_info){
|
||||||
void smp_init(){
|
void smp_init(){
|
||||||
|
|
||||||
if(!smp_request.response){
|
if(!smp_request.response){
|
||||||
klog(LOG_ERROR, __func__, "Failed to get SMP request");
|
klog(__func__, "Failed to get SMP request");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "../hal/apic.h"
|
#include "../hal/apic.h"
|
||||||
#include "../drivers/pmt.h"
|
#include "../drivers/pmt.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
|
|
||||||
/* Determines which timer will be used for calibration */
|
/* Determines which timer will be used for calibration */
|
||||||
|
|
@ -11,7 +11,7 @@ int calibration_timer = -1;
|
||||||
|
|
||||||
void timer_init(void){
|
void timer_init(void){
|
||||||
if(pmt_init() == -1){
|
if(pmt_init() == -1){
|
||||||
klog(LOG_INFO, __func__, "PMT Timer not found, falling back");
|
klog(__func__, "PMT Timer not found, falling back");
|
||||||
/* Fall back to PIT */
|
/* Fall back to PIT */
|
||||||
}else{
|
}else{
|
||||||
calibration_timer = PMT;
|
calibration_timer = PMT;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "../drivers/pmt.h"
|
#include "../drivers/pmt.h"
|
||||||
|
|
|
||||||
|
|
@ -15,4 +15,6 @@ typedef char link_symbol_ptr[];
|
||||||
#define PAGE_ROUND_UP(size) ALIGN_UP(size, PAGE_SIZE)
|
#define PAGE_ROUND_UP(size) ALIGN_UP(size, PAGE_SIZE)
|
||||||
#define PAGE_ROUND_DOWN(size) ALIGN_DOWN(size, PAGE_SIZE)
|
#define PAGE_ROUND_DOWN(size) ALIGN_DOWN(size, PAGE_SIZE)
|
||||||
|
|
||||||
|
#define SIZE_IN_PAGES(size) size/PAGE_SIZE
|
||||||
|
|
||||||
void *kmalloc(uint64_t size);
|
void *kmalloc(uint64_t size);
|
||||||
1
src/include/kmath.h
Normal file
1
src/include/kmath.h
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
#define abs(x) (x<0) ? -x : x
|
||||||
|
|
@ -8,7 +8,7 @@ enum {
|
||||||
LOG_SUCCESS,
|
LOG_SUCCESS,
|
||||||
};
|
};
|
||||||
|
|
||||||
void klog(int level, const char *func, const char *msg);
|
void klog(const char *func, const char *msg);
|
||||||
|
|
||||||
int kprintf(const char *format_string, ...);
|
int kprintf(const char *format_string, ...);
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#ifndef SPINLOCK_H
|
#ifndef SPINLOCK_H
|
||||||
#define SPINLOCK_H
|
#define SPINLOCK_H
|
||||||
|
|
||||||
void acquire_lock(atomic_flag *lock);
|
void acquire_spinlock(atomic_flag *lock);
|
||||||
void free_lock(atomic_flag *lock);
|
void free_spinlock(atomic_flag *lock);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include "../include/stdio.h"
|
#include "../include/kprint.h"
|
||||||
#include "../drivers/serial.h"
|
#include "../drivers/serial.h"
|
||||||
#include "../hal/tsc.h"
|
#include "../hal/tsc.h"
|
||||||
|
|
||||||
|
|
@ -22,39 +22,14 @@
|
||||||
|
|
||||||
extern bool serial_enabled;
|
extern bool serial_enabled;
|
||||||
|
|
||||||
void klog(int level, const char *func, const char *msg){
|
void klog(const char *func, const char *msg){
|
||||||
switch (level) {
|
kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg);
|
||||||
case LOG_INFO:
|
serial_kprintf("{ksk}: {s}\n", ANSI_COLOR_MAGENTA, func, ANSI_COLOR_RESET, msg);
|
||||||
kprintf("[{d}] info: {s}: {sn}", tsc_get_timestamp(), func, msg);
|
|
||||||
if(serial_enabled){
|
|
||||||
serial_kprintf("{k}KLOG_INFO{k}: {s}: {sn}", ANSI_COLOR_MAGENTA, ANSI_COLOR_RESET, func, msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case LOG_WARN:
|
|
||||||
kprintf("[{d}] {k}warning{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_YELLOW, ANSI_COLOR_RESET, func, msg);
|
|
||||||
if(serial_enabled){
|
|
||||||
serial_kprintf("{k}KLOG_WARN{k}: {s}: {sn}", ANSI_COLOR_YELLOW, ANSI_COLOR_RESET, func, msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case LOG_ERROR:
|
|
||||||
kprintf("[{d}] {k}error{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_RED, ANSI_COLOR_RESET, func, msg);
|
|
||||||
if(serial_enabled){
|
|
||||||
serial_kprintf("{k}KLOG_ERROR{k}: {s}: {sn}", ANSI_COLOR_RED, ANSI_COLOR_RESET, func, msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
case LOG_SUCCESS:
|
|
||||||
kprintf("[{d}] {k}success{k}: {s}: {sn}", tsc_get_timestamp(), ANSI_COLOR_GREEN, ANSI_COLOR_RESET, func, msg);
|
|
||||||
if(serial_enabled){
|
|
||||||
serial_kprintf("{k}KLOG_SUCCESS{k}: {s}: {sn}", ANSI_COLOR_GREEN, ANSI_COLOR_RESET, func, msg);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
atomic_flag printf_lock = ATOMIC_FLAG_INIT;
|
atomic_flag printf_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -75,7 +50,7 @@ atomic_flag printf_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
int kprintf(const char *format_string, ...){
|
int kprintf(const char *format_string, ...){
|
||||||
extern struct flanterm_context *ft_ctx;
|
extern struct flanterm_context *ft_ctx;
|
||||||
acquire_lock(&printf_lock);
|
acquire_spinlock(&printf_lock);
|
||||||
int state = NORMAL;
|
int state = NORMAL;
|
||||||
va_list a_list;
|
va_list a_list;
|
||||||
va_start(a_list, format_string);
|
va_start(a_list, format_string);
|
||||||
|
|
@ -138,7 +113,7 @@ int kprintf(const char *format_string, ...){
|
||||||
}
|
}
|
||||||
|
|
||||||
va_end(a_list);
|
va_end(a_list);
|
||||||
free_lock(&printf_lock);
|
free_spinlock(&printf_lock);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include <stdatomic.h>
|
#include <stdatomic.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
|
|
||||||
void acquire_lock(atomic_flag *lock){
|
void acquire_spinlock(atomic_flag *lock){
|
||||||
while(atomic_flag_test_and_set_explicit(lock, memory_order_acquire)){
|
while(atomic_flag_test_and_set_explicit(lock, memory_order_acquire)){
|
||||||
asm volatile("nop");
|
asm volatile("nop");
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,6 @@ void acquire_lock(atomic_flag *lock){
|
||||||
atomic_thread_fence(memory_order_acquire);
|
atomic_thread_fence(memory_order_acquire);
|
||||||
}
|
}
|
||||||
|
|
||||||
void free_lock(atomic_flag *lock){
|
void free_spinlock(atomic_flag *lock){
|
||||||
atomic_flag_clear_explicit(lock, memory_order_release);
|
atomic_flag_clear_explicit(lock, memory_order_release);
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
|
|
||||||
void *memset(void *dest, int c, uint64_t n){
|
void *memset(void *dest, int c, uint64_t n){
|
||||||
uint8_t *p = (uint8_t *)dest;
|
uint8_t *p = (uint8_t *)dest;
|
||||||
|
|
|
||||||
76
src/main.c
76
src/main.c
|
|
@ -1,8 +1,10 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "error.h"
|
||||||
#include "limine.h"
|
#include "limine.h"
|
||||||
#include "include/stdio.h"
|
|
||||||
#include "../flanterm/src/flanterm.h"
|
#include "../flanterm/src/flanterm.h"
|
||||||
#include "flanterm/src/flanterm_backends/fb.h"
|
#include "flanterm/src/flanterm_backends/fb.h"
|
||||||
#include "hal/gdt.h"
|
#include "hal/gdt.h"
|
||||||
|
|
@ -12,7 +14,9 @@
|
||||||
#include "hal/smp.h"
|
#include "hal/smp.h"
|
||||||
#include "hal/tsc.h"
|
#include "hal/tsc.h"
|
||||||
#include "mm/pmm.h"
|
#include "mm/pmm.h"
|
||||||
|
#include "mm/slab.h"
|
||||||
#include "mm/vmm.h"
|
#include "mm/vmm.h"
|
||||||
|
#include "mm/page.h"
|
||||||
#include "mm/kmalloc.h"
|
#include "mm/kmalloc.h"
|
||||||
#include "sys/acpi.h"
|
#include "sys/acpi.h"
|
||||||
#include "sys/pci.h"
|
#include "sys/pci.h"
|
||||||
|
|
@ -20,6 +24,7 @@
|
||||||
#include "drivers/pmt.h"
|
#include "drivers/pmt.h"
|
||||||
#include "drivers/ahci.h"
|
#include "drivers/ahci.h"
|
||||||
#include "scheduler/sched.h"
|
#include "scheduler/sched.h"
|
||||||
|
#include "sys/rand.h"
|
||||||
|
|
||||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
static volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||||
|
|
@ -77,46 +82,73 @@ void _start(void){
|
||||||
|
|
||||||
extern link_symbol_ptr text_start_addr, text_end_addr;
|
extern link_symbol_ptr text_start_addr, text_end_addr;
|
||||||
|
|
||||||
klog(LOG_INFO, "serial", "Initalizing serial controller");
|
|
||||||
serial_init();
|
serial_init();
|
||||||
klog(LOG_SUCCESS, "serial", "Done!");
|
krand_init();
|
||||||
|
|
||||||
klog(LOG_INFO, "gdt", "Setting up the GDT");
|
|
||||||
set_gdt();
|
set_gdt();
|
||||||
klog(LOG_SUCCESS, "gdt", "Done!");
|
|
||||||
|
|
||||||
klog(LOG_INFO, "idt", "Setting up the IDT");
|
|
||||||
set_idt();
|
set_idt();
|
||||||
klog(LOG_SUCCESS, "idt", "Done!");;
|
|
||||||
|
|
||||||
klog(LOG_INFO, "acpi", "Reading ACPI tables");
|
klog("acpi", "Reading ACPI tables");
|
||||||
acpi_init();
|
acpi_init();
|
||||||
klog(LOG_SUCCESS, "acpi", "Done!");
|
|
||||||
|
|
||||||
klog(LOG_INFO, "apic", "Initalizing APIC");
|
|
||||||
|
klog("apic", "Initalizing APIC");
|
||||||
apic_init();
|
apic_init();
|
||||||
klog(LOG_SUCCESS, "apic", "Done!");
|
|
||||||
|
|
||||||
tsc_init();
|
tsc_init();
|
||||||
|
|
||||||
|
|
||||||
klog(LOG_INFO, "pmm", "Setting up the PMM");
|
klog("pmm", "Setting up the PMM");
|
||||||
pmm_init();
|
pmm_init();
|
||||||
klog(LOG_SUCCESS, "pmm", "Done!");
|
|
||||||
|
|
||||||
klog(LOG_INFO, "vmm", "Setting up the page tables");
|
|
||||||
|
klog("vmm", "Setting up the page tables");
|
||||||
vmm_init();
|
vmm_init();
|
||||||
klog(LOG_SUCCESS, "vmm", "Done!");
|
init_page_array();
|
||||||
|
|
||||||
kernel_heap_init();
|
|
||||||
|
|
||||||
klog(LOG_INFO, "smp", "Starting APs");
|
//struct ma_kcache *cache = ma_cache_create("bird", 1048576, 0, 0, 0);
|
||||||
|
|
||||||
|
//uint64_t *d = ma_cache_alloc(cache, 0);
|
||||||
|
|
||||||
|
//cache_info(cache);
|
||||||
|
|
||||||
|
//memset(d, 0, 1048576);
|
||||||
|
|
||||||
|
//for(;;);
|
||||||
|
|
||||||
|
//cache_info(cache);
|
||||||
|
|
||||||
|
_kmalloc_init();
|
||||||
|
|
||||||
|
int *my_int;
|
||||||
|
|
||||||
|
for(int i = 0;i < 3000;i++){
|
||||||
|
my_int = kmalloc(512);
|
||||||
|
*my_int = rand();
|
||||||
|
kprintf("my int: {d} on iter: {d}\n", *my_int, i);
|
||||||
|
kstatus status = kfree(my_int);
|
||||||
|
if(status != KERNEL_STATUS_SUCCESS){
|
||||||
|
kprintf("status: {d}\n", status);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
kprintf("my int: {d}\n", *my_int);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//for(;;){}
|
||||||
|
|
||||||
|
klog("smp", "Starting APs");
|
||||||
smp_init();
|
smp_init();
|
||||||
klog(LOG_SUCCESS, "smp", "Done!");
|
|
||||||
|
|
||||||
klog(LOG_INFO, "pci", "Getting le pci");
|
|
||||||
|
klog("pci", "Getting le pci");
|
||||||
pci_init();
|
pci_init();
|
||||||
klog(LOG_SUCCESS, "pci", "Done!");
|
|
||||||
|
|
||||||
scheduler_init();
|
scheduler_init();
|
||||||
|
|
||||||
|
|
|
||||||
184
src/mm/kmalloc.c
184
src/mm/kmalloc.c
|
|
@ -1,167 +1,51 @@
|
||||||
#include <stdbool.h>
|
#include "slab.h"
|
||||||
#include <stdint.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <kprint.h>
|
||||||
#include <stdio.h>
|
#include <kmath.h>
|
||||||
#include <SFB25.h>
|
struct ma_kcache *kmalloc_caches[14] = {0};
|
||||||
#include <string.h>
|
|
||||||
#include <lock.h>
|
|
||||||
#include "pmm.h"
|
|
||||||
#include "vmm.h"
|
|
||||||
#include "kmalloc.h"
|
|
||||||
|
|
||||||
#define KERNEL_MAX_BLOCK 512
|
// Create various sizes of caches to be used by kmalloc
|
||||||
|
void _kmalloc_init(void){
|
||||||
typedef struct block_t {
|
kmalloc_caches[0] = ma_cache_create("kmalloc16", 16, 0, NULL, NULL);
|
||||||
uint64_t addr;
|
kmalloc_caches[1] = ma_cache_create("kmalloc32", 32, 0, NULL, NULL);
|
||||||
uint32_t size;
|
kmalloc_caches[2] = ma_cache_create("kmalloc64", 64, 0, NULL, NULL);
|
||||||
bool free;
|
kmalloc_caches[3] = ma_cache_create("kmalloc128", 128, 0, NULL, NULL);
|
||||||
} block_t;
|
kmalloc_caches[4] = ma_cache_create("kmalloc256", 256, 0, NULL, NULL);
|
||||||
|
kmalloc_caches[5] = ma_cache_create("kmalloc512", 512, 0, NULL, NULL);
|
||||||
block_t *base = NULL;
|
kmalloc_caches[6] = ma_cache_create("kmalloc1K", 1024, 0, NULL, NULL);
|
||||||
uint64_t *heap_addr = NULL;
|
kmalloc_caches[7] = ma_cache_create("kmalloc4K", 4096, 0, NULL, NULL);
|
||||||
|
kmalloc_caches[8] = ma_cache_create("kmalloc8K", 8192, 0, NULL, NULL);
|
||||||
void kernel_heap_init(){
|
kmalloc_caches[9] = ma_cache_create("kmalloc32K", 32768, 0, NULL, NULL);
|
||||||
extern struct limine_memmap_response *memmap_response;
|
kmalloc_caches[10] = ma_cache_create("kmalloc64K", 65536, 0, NULL, NULL);
|
||||||
extern uint64_t pmm_page_count;
|
kmalloc_caches[11] = ma_cache_create("kmalloc131K", 131072, 0, NULL, NULL);
|
||||||
|
kmalloc_caches[12] = ma_cache_create("kmalloc524K", 524288, 0, NULL, NULL);
|
||||||
/* Allocate memory for the blocks*/
|
kmalloc_caches[13] = ma_cache_create("kmalloc1M", 1048576, 0, NULL, NULL);
|
||||||
base = kernel_allocate_memory(KERNEL_MAX_BLOCK * sizeof(block_t), PTE_BIT_RW | PTE_BIT_NX);
|
|
||||||
|
|
||||||
if(!base){
|
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate memory for kernel heap blocks");
|
|
||||||
kkill();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(base, 0, KERNEL_MAX_BLOCK * sizeof(block_t));
|
size_t sizes[14] = {16, 32, 64, 128, 256, 512, 1024, 4096, 8192, 32768, 65536, 131072, 524288, 1048756};
|
||||||
|
|
||||||
/* Allocate memory for the heap */
|
void *kmalloc(size_t size){
|
||||||
heap_addr = kernel_allocate_memory(KERNEL_HEAP_SIZE, PTE_BIT_RW | PTE_BIT_NX);
|
if(size > 1048576){
|
||||||
|
klog(__func__, "Attempted to allocate more than max size (1M)");
|
||||||
if(!heap_addr){
|
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate memory for the kernel heap");
|
|
||||||
kkill();
|
|
||||||
}
|
|
||||||
|
|
||||||
base->free = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *kmalloc(uint64_t size){
|
|
||||||
|
|
||||||
/* First check if there is a free block which fits the size requirement */
|
|
||||||
for(int i = 0; i < KERNEL_MAX_BLOCK; i++){
|
|
||||||
if(base[i].addr && base[i].free && base[i].size >= size){
|
|
||||||
base[i].free = false;
|
|
||||||
return (void*)base[i].addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int i = 0;
|
|
||||||
/* Parse the list until you find the next free block */
|
|
||||||
while (!base[i].free && !base[i].addr){
|
|
||||||
if(i > KERNEL_MAX_BLOCK){
|
|
||||||
/* Over max block limit */
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
i++;
|
void *addr = NULL;
|
||||||
}
|
for(int i = 0; i < 14; i++){
|
||||||
|
if(sizes[i] >= size){
|
||||||
/* Fill this block in */
|
addr = ma_cache_alloc(kmalloc_caches[i], 0);
|
||||||
uint64_t addr = (uint64_t)heap_addr;
|
break;
|
||||||
|
|
||||||
/* Calculate address offset */
|
|
||||||
for(int j = 0; j < i; j++){
|
|
||||||
if(addr > ((uint64_t)heap_addr + KERNEL_HEAP_SIZE)){
|
|
||||||
/* Out of heap memory */
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr += base[j].size;
|
|
||||||
}
|
|
||||||
|
|
||||||
memset((uint64_t*)addr, 0, size);
|
|
||||||
|
|
||||||
base[i].addr = addr;
|
|
||||||
base[i].free = false;
|
|
||||||
base[i].size = size;
|
|
||||||
|
|
||||||
return (void*)addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kfree(void *addr){
|
|
||||||
for(int i = 0; i < KERNEL_MAX_BLOCK; i++){
|
|
||||||
if(base[i].addr == (uint64_t)addr){
|
|
||||||
base[i].free = true;
|
|
||||||
memset((void*)base[i].addr, 0, base[i].size);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
kprintf("kfree: attempted to free non-heap address!\n");
|
|
||||||
kkill();
|
|
||||||
}
|
|
||||||
|
|
||||||
void *krealloc(void *addr, uint64_t size) {
|
|
||||||
if(addr == NULL){
|
if(addr == NULL){
|
||||||
return kmalloc(size);
|
klog(__func__, "Failed to allocate heap memory!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0) {
|
|
||||||
kfree(addr);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the block corresponding to the pointer
|
|
||||||
int i;
|
|
||||||
for (i = 0; i < KERNEL_MAX_BLOCK; i++) {
|
|
||||||
if (base[i].addr == (uint64_t)addr) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == KERNEL_MAX_BLOCK) {
|
|
||||||
kprintf("krealloc: attempted to realloc non-heap address!\n");
|
|
||||||
kkill();
|
|
||||||
}
|
|
||||||
|
|
||||||
block_t *block = &base[i];
|
|
||||||
uint64_t old_size = block->size;
|
|
||||||
|
|
||||||
// If the current size is already sufficient, return the same pointer
|
|
||||||
if (old_size >= size) {
|
|
||||||
return addr;
|
return addr;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if this block is the last allocated block in the array
|
kstatus kfree(void *addr){
|
||||||
bool is_last = true;
|
return ma_cache_dealloc(addr);
|
||||||
for (int j = i + 1; j < KERNEL_MAX_BLOCK; j++) {
|
|
||||||
if (base[j].addr != 0) {
|
|
||||||
is_last = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's the last block, check if there's enough space to expand
|
|
||||||
if (is_last) {
|
|
||||||
uint64_t current_end = block->addr + block->size;
|
|
||||||
uint64_t heap_end = (uint64_t)heap_addr + KERNEL_HEAP_SIZE;
|
|
||||||
uint64_t available = heap_end - current_end;
|
|
||||||
|
|
||||||
if (available >= (size - old_size)) {
|
|
||||||
// Expand the block in place
|
|
||||||
block->size = size;
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate a new block, copy data, and free the old block
|
|
||||||
void *new_ptr = kmalloc(size);
|
|
||||||
if (!new_ptr) {
|
|
||||||
return NULL; // Allocation failed
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(new_ptr, addr, old_size);
|
|
||||||
kfree(addr);
|
|
||||||
|
|
||||||
return new_ptr;
|
|
||||||
}
|
}
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
|
#include "error.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
void kernel_heap_init();
|
|
||||||
|
|
||||||
void heap_free(uint64_t *addr);
|
void _kmalloc_init(void);
|
||||||
uint64_t *heap_alloc();
|
|
||||||
|
|
||||||
void *kmalloc(uint64_t size);
|
void *kmalloc(uint64_t size);
|
||||||
void kfree(void *addr);
|
kstatus kfree(void *addr);
|
||||||
|
|
||||||
#define KERNEL_HEAP_SIZE 0x10000000
|
|
||||||
|
|
|
||||||
61
src/mm/page.c
Normal file
61
src/mm/page.c
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "page.h"
|
||||||
|
#include <limine.h>
|
||||||
|
#include "vmm.h"
|
||||||
|
#include <SFB25.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
struct page *pages; // "virtually sparse array", it holds all the pages between the start of the first usable address to the last one.
|
||||||
|
|
||||||
|
extern struct limine_memmap_response *memmap_response;
|
||||||
|
|
||||||
|
extern uint64_t hhdmoffset;
|
||||||
|
|
||||||
|
// Get the page object which is associated with the page that the address `addr` resides in
|
||||||
|
struct page *get_page(void *addr){
|
||||||
|
void *canonical_addr = (void*)PAGE_ROUND_DOWN((uint64_t)addr);
|
||||||
|
uint64_t phys_addr = kget_phys_addr(canonical_addr);
|
||||||
|
|
||||||
|
if(phys_addr == 0){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t index = phys_addr / PAGE_SIZE;
|
||||||
|
return &pages[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_page_array(){
|
||||||
|
|
||||||
|
struct limine_memmap_entry **entries = memmap_response->entries;
|
||||||
|
|
||||||
|
size_t firstaddr = 0;
|
||||||
|
size_t lastaddr = 0;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < memmap_response->entry_count; i++){
|
||||||
|
switch(entries[i]->type){
|
||||||
|
case LIMINE_MEMMAP_USABLE:
|
||||||
|
if(firstaddr == 0){
|
||||||
|
firstaddr = entries[i]->base;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
lastaddr = entries[i]->base + entries[i]->length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t page_count = (lastaddr - firstaddr) / PAGE_SIZE;
|
||||||
|
|
||||||
|
pages = va_alloc_contigious_pages((page_count * sizeof(struct page)) / PAGE_SIZE);
|
||||||
|
|
||||||
|
if(pages == NULL){
|
||||||
|
klog(__func__, "Couldn't allocate page structure");
|
||||||
|
kkill();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(pages, 0, (page_count * sizeof(struct page)) / PAGE_SIZE);
|
||||||
|
|
||||||
|
}
|
||||||
10
src/mm/page.h
Normal file
10
src/mm/page.h
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
#include "slab.h"
|
||||||
|
|
||||||
|
typedef struct page {
|
||||||
|
struct ma_bufctl *bufctls; // The bufctls associated with the slab stored on this page. NULL if page isn't associated with a slab
|
||||||
|
struct ma_slab *slab;
|
||||||
|
}page;
|
||||||
|
|
||||||
|
struct page *get_page(void *addr);
|
||||||
|
|
||||||
|
void init_page_array();
|
||||||
14
src/mm/pmm.c
14
src/mm/pmm.c
|
|
@ -1,7 +1,6 @@
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <string.h>
|
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include "pmm.h"
|
#include "pmm.h"
|
||||||
#include "kmalloc.h"
|
#include "kmalloc.h"
|
||||||
|
|
@ -25,7 +24,7 @@ uint64_t *free_list = NULL;
|
||||||
atomic_flag pmm_lock = ATOMIC_FLAG_INIT;
|
atomic_flag pmm_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
void pmm_free(uint64_t *addr){
|
void pmm_free(uint64_t *addr){
|
||||||
acquire_lock(&pmm_lock);
|
acquire_spinlock(&pmm_lock);
|
||||||
uint64_t *virt_addr = (uint64_t*)((uint64_t)addr+hhdmoffset);
|
uint64_t *virt_addr = (uint64_t*)((uint64_t)addr+hhdmoffset);
|
||||||
/* Make the given page point to the previous free page */
|
/* Make the given page point to the previous free page */
|
||||||
|
|
||||||
|
|
@ -35,12 +34,12 @@ void pmm_free(uint64_t *addr){
|
||||||
free_list = virt_addr;
|
free_list = virt_addr;
|
||||||
|
|
||||||
pmm_free_page_count++;
|
pmm_free_page_count++;
|
||||||
free_lock(&pmm_lock);
|
free_spinlock(&pmm_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t *pmm_alloc(){
|
uint64_t *pmm_alloc(){
|
||||||
acquire_lock(&pmm_lock);
|
acquire_spinlock(&pmm_lock);
|
||||||
if(pmm_free_page_count <= 0){
|
if(pmm_free_page_count <= 0){
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -49,20 +48,19 @@ uint64_t *pmm_alloc(){
|
||||||
uint64_t *addr = (uint64_t*)((uint64_t)free_list - hhdmoffset);
|
uint64_t *addr = (uint64_t*)((uint64_t)free_list - hhdmoffset);
|
||||||
free_list = (uint64_t*)(*free_list);
|
free_list = (uint64_t*)(*free_list);
|
||||||
pmm_free_page_count--;
|
pmm_free_page_count--;
|
||||||
free_lock(&pmm_lock);
|
free_spinlock(&pmm_lock);
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pmm_init(){
|
void pmm_init(){
|
||||||
|
|
||||||
if(memmap_request.response == NULL){
|
if(memmap_request.response == NULL){
|
||||||
klog(LOG_ERROR, __func__, "Memmap response is null");
|
klog(__func__, "Memmap response is null");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
memmap_response = memmap_request.response;
|
memmap_response = memmap_request.response;
|
||||||
|
|
||||||
|
|
||||||
struct limine_memmap_entry **entries = memmap_response->entries;
|
struct limine_memmap_entry **entries = memmap_response->entries;
|
||||||
|
|
||||||
for(uint64_t i = 0; i < memmap_response->entry_count; i++){
|
for(uint64_t i = 0; i < memmap_response->entry_count; i++){
|
||||||
|
|
|
||||||
|
|
@ -11,4 +11,3 @@ typedef struct free_page_t {
|
||||||
void pmm_init(void);
|
void pmm_init(void);
|
||||||
uint64_t *pmm_alloc();
|
uint64_t *pmm_alloc();
|
||||||
void pmm_free(uint64_t *addr);
|
void pmm_free(uint64_t *addr);
|
||||||
|
|
||||||
|
|
|
||||||
437
src/mm/slab.c
Normal file
437
src/mm/slab.c
Normal file
|
|
@ -0,0 +1,437 @@
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "error.h"
|
||||||
|
#include "vmm.h"
|
||||||
|
#include "page.h"
|
||||||
|
#include "slab.h"
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <SFB25.h>
|
||||||
|
#include <lock.h>
|
||||||
|
|
||||||
|
struct ma_kcache *caches = NULL;
|
||||||
|
|
||||||
|
atomic_flag caches_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
|
|
||||||
|
enum SLAB_STATE {
|
||||||
|
FREE = 0,
|
||||||
|
PARTIAL,
|
||||||
|
USED
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Gets free object from slab and handles stuff
|
||||||
|
uint64_t *_ma_slab_get_free_obj(struct ma_slab *slab){
|
||||||
|
if(slab->free == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *addr = slab->free->startaddr;
|
||||||
|
|
||||||
|
if(addr == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(slab->free->next != NULL){
|
||||||
|
|
||||||
|
slab->free = slab->free->next;
|
||||||
|
}else{
|
||||||
|
slab->free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the slab from the free to the partial list on the first time it's allocated from
|
||||||
|
if(slab->refcount == 0){
|
||||||
|
if(slab->prev != NULL){
|
||||||
|
slab->prev->next = slab->next;
|
||||||
|
}else{
|
||||||
|
slab->cache->slabs_free = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If there is a partial slab head then make it the head and do other stuff */
|
||||||
|
if(slab->cache->slabs_partial != NULL){
|
||||||
|
slab->cache->slabs_partial->next = slab;
|
||||||
|
slab->prev = slab->cache->slabs_partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
slab->next = NULL;
|
||||||
|
slab->cache->slabs_partial = slab;
|
||||||
|
}
|
||||||
|
|
||||||
|
slab->refcount++;
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
kstatus _ma_alloc_slab(struct ma_kcache *kcache){
|
||||||
|
struct ma_slab *slab_structure = (struct ma_slab*)va_alloc_contigious_pages(1);
|
||||||
|
memset(slab_structure, 0, PAGE_SIZE);
|
||||||
|
|
||||||
|
// Put the addresses in the slab structure into the bufctls
|
||||||
|
if(kcache->objsize >= 512){
|
||||||
|
|
||||||
|
slab_structure->free = (struct ma_bufctl*)(va_alloc_contigious_pages(1)); // Store the bufctls off-page
|
||||||
|
memset(slab_structure->free, 0, 4096);
|
||||||
|
|
||||||
|
uint64_t slabsize = kcache->slabsize;
|
||||||
|
void *mstart = va_alloc_contigious_pages(kcache->slabsize);
|
||||||
|
|
||||||
|
for(size_t j = 0; j < kcache->slabsize; j++){
|
||||||
|
get_page((void*)((uint64_t)mstart + j*PAGE_SIZE))->slab = slab_structure;
|
||||||
|
get_page((void*)((uint64_t)mstart + j*PAGE_SIZE))->bufctls = slab_structure->free;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < (PAGE_SIZE * slabsize)/kcache->objsize; i++){
|
||||||
|
((struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i)))->startaddr = (size_t*)((uint64_t)mstart + i * kcache->objsize);
|
||||||
|
((struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i)))->next = (struct ma_bufctl*)((uint64_t)slab_structure->free + sizeof(struct ma_bufctl)*(i+1));
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
/* In this case the objects acts as bufctl structures. Small downside: there will always be a max of 252 objects per slab, no matter the size of the object, since
|
||||||
|
* they have to have enough space to store a bufctl structure (16 bytes).
|
||||||
|
*
|
||||||
|
* Their startaddr is the same as the address of the bufctl, since the objects act as the bufctls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
slab_structure->free = va_alloc_contigious_pages(kcache->slabsize);
|
||||||
|
|
||||||
|
get_page(slab_structure->free)->slab = slab_structure;
|
||||||
|
get_page(slab_structure->free)->bufctls = slab_structure->free;
|
||||||
|
|
||||||
|
uint64_t size = (kcache->objsize >= sizeof(struct ma_bufctl)) ? kcache->objsize : sizeof(struct ma_bufctl);
|
||||||
|
|
||||||
|
for(size_t i = 0; i < kcache->num; i++){
|
||||||
|
((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->startaddr = (size_t*)((uint64_t)slab_structure->free + i * size);
|
||||||
|
if(i+1 < kcache->num){
|
||||||
|
((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->next = (struct ma_bufctl*)((uint64_t)slab_structure->free + size*(i+1));
|
||||||
|
}else{
|
||||||
|
((struct ma_bufctl*)((uint64_t)slab_structure->free + size*i))->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kcache->slabs_free == NULL){
|
||||||
|
kcache->slabs_free = slab_structure;
|
||||||
|
}else{
|
||||||
|
// Change head
|
||||||
|
kcache->slabs_free->next = slab_structure;
|
||||||
|
slab_structure->prev = kcache->slabs_free;
|
||||||
|
kcache->slabs_free = slab_structure;
|
||||||
|
}
|
||||||
|
|
||||||
|
slab_structure->cache = kcache;
|
||||||
|
|
||||||
|
return KERNEL_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ma_move_slab(struct ma_slab *slab, enum SLAB_STATE newstate){
|
||||||
|
struct ma_kcache *cache = slab->cache;
|
||||||
|
struct ma_slab *sb = 0;
|
||||||
|
switch (newstate) {
|
||||||
|
case FREE:
|
||||||
|
if(cache->slabs_partial != NULL){
|
||||||
|
sb = cache->slabs_partial;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto free_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_used != NULL){
|
||||||
|
sb = cache->slabs_used;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto free_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
case PARTIAL:
|
||||||
|
if(cache->slabs_free != NULL){
|
||||||
|
sb = cache->slabs_free;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto partial_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_used != NULL){
|
||||||
|
sb = cache->slabs_used;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto partial_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
|
case USED:
|
||||||
|
if(cache->slabs_free != NULL){
|
||||||
|
sb = cache->slabs_free;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto used_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_partial != NULL){
|
||||||
|
sb = cache->slabs_partial;
|
||||||
|
while(sb != NULL){
|
||||||
|
if(sb == slab){
|
||||||
|
goto used_common;
|
||||||
|
}
|
||||||
|
sb = sb->prev;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
free_common:
|
||||||
|
// Preserve the linkage
|
||||||
|
if(sb->prev != NULL){
|
||||||
|
if(sb->next != NULL){
|
||||||
|
sb->next->prev = sb->prev;
|
||||||
|
}
|
||||||
|
sb->prev->next = sb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_free != NULL){
|
||||||
|
cache->slabs_free->next = slab;
|
||||||
|
slab->prev = cache->slabs_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->slabs_free = slab;
|
||||||
|
|
||||||
|
return;
|
||||||
|
partial_common:
|
||||||
|
if(sb->prev != NULL){
|
||||||
|
if(sb->next != NULL){
|
||||||
|
sb->next->prev = sb->prev;
|
||||||
|
}
|
||||||
|
sb->prev->next = sb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_partial != NULL){
|
||||||
|
cache->slabs_partial->next = slab;
|
||||||
|
slab->prev = cache->slabs_partial;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->slabs_partial = slab;
|
||||||
|
|
||||||
|
return;
|
||||||
|
used_common:
|
||||||
|
if(sb->prev != NULL){
|
||||||
|
if(sb->next != NULL){
|
||||||
|
sb->next->prev = sb->prev;
|
||||||
|
}
|
||||||
|
sb->prev->next = sb->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cache->slabs_used != NULL){
|
||||||
|
cache->slabs_used->next = slab;
|
||||||
|
slab->prev = cache->slabs_used;
|
||||||
|
}
|
||||||
|
|
||||||
|
cache->slabs_used = slab;
|
||||||
|
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t)){
|
||||||
|
|
||||||
|
acquire_spinlock(&caches_lock);
|
||||||
|
|
||||||
|
struct ma_kcache *kcache = (struct ma_kcache*)va_alloc_contigious_pages(1);
|
||||||
|
memset(kcache, 0, 4096);
|
||||||
|
|
||||||
|
memcpy(kcache->name, name, 16);
|
||||||
|
kcache->slabsize = (size / PAGE_SIZE) + 1;
|
||||||
|
kcache->num = (4096 * kcache->slabsize - sizeof(struct ma_slab)) / ((size >= sizeof(struct ma_bufctl)) ? size : sizeof(struct ma_bufctl)); // Calculate the number of buffers in this slab
|
||||||
|
kcache->objsize = size;
|
||||||
|
memset(&kcache->lock, 0, sizeof(atomic_flag));
|
||||||
|
|
||||||
|
_ma_alloc_slab(kcache);
|
||||||
|
|
||||||
|
if(caches != NULL){
|
||||||
|
caches->next = kcache;
|
||||||
|
kcache->prev = caches;
|
||||||
|
}
|
||||||
|
|
||||||
|
caches = kcache;
|
||||||
|
|
||||||
|
free_spinlock(&caches_lock);
|
||||||
|
|
||||||
|
return kcache;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *ma_cache_alloc(struct ma_kcache *kcache, uint32_t flags){
|
||||||
|
|
||||||
|
acquire_spinlock(&kcache->lock);
|
||||||
|
|
||||||
|
struct ma_slab *slab = NULL;
|
||||||
|
|
||||||
|
if(kcache->slabs_free == NULL){
|
||||||
|
if(kcache->slabs_partial == NULL){
|
||||||
|
_ma_alloc_slab(kcache);
|
||||||
|
slab = kcache->slabs_free;
|
||||||
|
}else{
|
||||||
|
slab = kcache->slabs_partial;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
slab = kcache->slabs_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t *addr = _ma_slab_get_free_obj(slab);
|
||||||
|
|
||||||
|
if(addr == NULL){
|
||||||
|
slab->free = NULL;
|
||||||
|
|
||||||
|
if(kcache->slabs_partial->prev != NULL){
|
||||||
|
kcache->slabs_partial = kcache->slabs_partial->prev;
|
||||||
|
}else{
|
||||||
|
kcache->slabs_partial = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(kcache->slabs_used != NULL){
|
||||||
|
kcache->slabs_used->next = slab;
|
||||||
|
slab->prev = kcache->slabs_used;
|
||||||
|
kcache->slabs_used = slab;
|
||||||
|
}else{
|
||||||
|
kcache->slabs_used = slab;
|
||||||
|
}
|
||||||
|
|
||||||
|
_ma_alloc_slab(kcache);
|
||||||
|
addr = _ma_slab_get_free_obj(kcache->slabs_free);
|
||||||
|
}
|
||||||
|
|
||||||
|
free_spinlock(&kcache->lock);
|
||||||
|
|
||||||
|
return addr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void cache_info(struct ma_kcache *cache){
|
||||||
|
kprintf("name: {s}\n", cache->name);
|
||||||
|
kprintf("objsize: {d}\n", cache->objsize);
|
||||||
|
kprintf("num: {d}\n", cache->num);
|
||||||
|
kprintf("slabsize: {d}\n", cache->slabsize);
|
||||||
|
|
||||||
|
int slabsfreecnt = 0;
|
||||||
|
if(cache->slabs_free == NULL){
|
||||||
|
kprintf("slabsfree: 0\n");
|
||||||
|
}else{
|
||||||
|
if(cache->slabs_free->prev == NULL){
|
||||||
|
kprintf("slabsfree: 1\n");
|
||||||
|
}else{
|
||||||
|
struct ma_slab *slab = cache->slabs_free;
|
||||||
|
|
||||||
|
while(slab->prev != NULL){
|
||||||
|
slab = slab->prev;
|
||||||
|
slabsfreecnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
kprintf("slabsfree : {d}\n", slabsfreecnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int slabspartcnt = 0;
|
||||||
|
if(cache->slabs_partial == NULL){
|
||||||
|
kprintf("slabspartial: 0\n");
|
||||||
|
}else{
|
||||||
|
if(cache->slabs_partial->prev == NULL){
|
||||||
|
kprintf("slabspartial: 1\n");
|
||||||
|
}else{
|
||||||
|
struct ma_slab *slab = cache->slabs_partial;
|
||||||
|
while(slab->prev != NULL){
|
||||||
|
slab = slab->prev;
|
||||||
|
slabspartcnt++;
|
||||||
|
}
|
||||||
|
kprintf("slabspartial: {d}\n", slabspartcnt+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int slabsfullcnt = 0;
|
||||||
|
if(cache->slabs_used == NULL){
|
||||||
|
kprintf("slabsused: 0\n");
|
||||||
|
}else{
|
||||||
|
if(cache->slabs_used->prev == NULL){
|
||||||
|
kprintf("slabsused: 1\n");
|
||||||
|
}else{
|
||||||
|
struct ma_slab *slab = cache->slabs_used;
|
||||||
|
while(slab->prev != NULL){
|
||||||
|
slab = slab->prev;
|
||||||
|
slabsfullcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
kprintf("slabsused : {d}\n", slabsfullcnt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ma_bufctl *addr_to_bufctl(void *object){
|
||||||
|
struct ma_slab *slab = get_page(object)->slab;
|
||||||
|
|
||||||
|
if(slab == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ma_bufctl *bufs = get_page(object)->bufctls;
|
||||||
|
|
||||||
|
if(bufs == NULL){
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = 0; i < slab->cache->num; i++){
|
||||||
|
if((bufs + i)->startaddr == object){
|
||||||
|
return (bufs + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
kstatus ma_cache_dealloc(void *object){
|
||||||
|
|
||||||
|
struct ma_slab *slab = get_page(object)->slab;
|
||||||
|
|
||||||
|
if(slab == NULL){
|
||||||
|
klog(__func__, "slab == null");
|
||||||
|
return KERNEL_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ma_bufctl *buf = addr_to_bufctl(object);
|
||||||
|
|
||||||
|
if(buf == NULL){
|
||||||
|
klog(__func__, "bufctl not found");
|
||||||
|
return KERNEL_STATUS_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->next = slab->free;
|
||||||
|
slab->free = buf;
|
||||||
|
|
||||||
|
slab->refcount--;
|
||||||
|
|
||||||
|
if(slab->refcount == slab->cache->num - 1){
|
||||||
|
_ma_move_slab(slab, PARTIAL);
|
||||||
|
}else if(slab->refcount == 0){
|
||||||
|
_ma_move_slab(slab, FREE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return KERNEL_STATUS_SUCCESS;
|
||||||
|
|
||||||
|
}
|
||||||
57
src/mm/slab.h
Normal file
57
src/mm/slab.h
Normal file
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include <stdatomic.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <error.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#define KCACHE_NAME_LEN 16
|
||||||
|
|
||||||
|
|
||||||
|
struct ma_bufctl {
|
||||||
|
struct ma_bufctl *next;
|
||||||
|
size_t *startaddr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ma_slab {
|
||||||
|
struct ma_kcache *cache;
|
||||||
|
|
||||||
|
struct ma_slab *next;
|
||||||
|
struct ma_slab *prev;
|
||||||
|
|
||||||
|
uint32_t refcount; // The amount of active (not free) objects in the slabs
|
||||||
|
|
||||||
|
struct ma_bufctl *free; // Linked list of free buffers in the slab. Is equal to NULL once there are no more free objects
|
||||||
|
};
|
||||||
|
|
||||||
|
/* objrefs are used to be able to quickly find out which slab and cache a object belongs to. objrefs belonging to the same slab are kept in one page, there is no mixing. */
|
||||||
|
struct ma_objref {
|
||||||
|
struct ma_objref *next;
|
||||||
|
struct ma_objref *prev;
|
||||||
|
void *addr; // Addr of the object
|
||||||
|
struct ma_slab *slab; // The slab which the obj belongs to
|
||||||
|
struct ma_kcache *kcache; // The cache which the obj belongs to
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ma_kcache {
|
||||||
|
struct ma_kcache *next;
|
||||||
|
struct ma_kcache *prev;
|
||||||
|
|
||||||
|
uint32_t objsize; // Size of the object which the cache stores
|
||||||
|
uint16_t flags; // Not useful yet
|
||||||
|
uint32_t num; // Number of objects per slab
|
||||||
|
uint32_t slabsize; // How many pages does a single slab take up. Useful for objects > PAGE_SIZE
|
||||||
|
|
||||||
|
struct ma_slab *slabs_free;
|
||||||
|
struct ma_slab *slabs_partial;
|
||||||
|
struct ma_slab *slabs_used;
|
||||||
|
|
||||||
|
atomic_flag lock;
|
||||||
|
|
||||||
|
char name[KCACHE_NAME_LEN];
|
||||||
|
};
|
||||||
|
|
||||||
|
void *ma_cache_alloc(struct ma_kcache *kcache, uint32_t flags);
|
||||||
|
kstatus ma_cache_dealloc(void *object);
|
||||||
|
struct ma_kcache *ma_cache_create(char *name, size_t size, uint32_t flags, void (*constructor)(void *, size_t), void (*destructor)(void *, size_t));
|
||||||
|
void cache_info(struct ma_kcache *cache);
|
||||||
99
src/mm/vmm.c
99
src/mm/vmm.c
|
|
@ -1,6 +1,7 @@
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
|
#include <stdatomic.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
|
@ -38,13 +39,13 @@ void vmm_init(){
|
||||||
struct limine_kernel_address_response *kernel_address = kernel_addr_request.response;
|
struct limine_kernel_address_response *kernel_address = kernel_addr_request.response;
|
||||||
|
|
||||||
if(!kernel_address){
|
if(!kernel_address){
|
||||||
klog(LOG_ERROR, __func__, "Kernel address not recieved");
|
klog(__func__, "Kernel address not recieved");
|
||||||
}
|
}
|
||||||
|
|
||||||
kernel_page_map = (uint64_t*)((uint64_t)pmm_alloc() + hhdmoffset);
|
kernel_page_map = (uint64_t*)((uint64_t)pmm_alloc() + hhdmoffset);
|
||||||
|
|
||||||
if(!kernel_page_map){
|
if(!kernel_page_map){
|
||||||
klog(LOG_ERROR, __func__, "Allocating block for page map failed");
|
klog(__func__, "Allocating block for page map failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(kernel_page_map, 0, PAGE_SIZE);
|
memset(kernel_page_map, 0, PAGE_SIZE);
|
||||||
|
|
@ -157,7 +158,7 @@ uint64_t *get_lower_table(uint64_t *page_map, uint64_t offset){
|
||||||
uint64_t *ret = pmm_alloc();
|
uint64_t *ret = pmm_alloc();
|
||||||
|
|
||||||
if(!ret){
|
if(!ret){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate page table");
|
klog(__func__, "Failed to allocate page table");
|
||||||
kprintf("page_map: 0x{xn}", (uint64_t)page_map);
|
kprintf("page_map: 0x{xn}", (uint64_t)page_map);
|
||||||
kprintf("offset: 0x{xn}", offset);
|
kprintf("offset: 0x{xn}", offset);
|
||||||
|
|
||||||
|
|
@ -177,7 +178,7 @@ atomic_flag page_table_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags){
|
void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t flags){
|
||||||
/* Probably slow, fix in future */
|
/* Probably slow, fix in future */
|
||||||
acquire_lock(&page_table_lock);
|
acquire_spinlock(&page_table_lock);
|
||||||
|
|
||||||
uint64_t pml4_offset = (virt_addr >> 39) & 0x1ff;
|
uint64_t pml4_offset = (virt_addr >> 39) & 0x1ff;
|
||||||
uint64_t pdp_offset = (virt_addr >> 30) & 0x1ff;
|
uint64_t pdp_offset = (virt_addr >> 30) & 0x1ff;
|
||||||
|
|
@ -187,24 +188,28 @@ void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, ui
|
||||||
uint64_t *pdp = get_lower_table(page_map, pml4_offset);
|
uint64_t *pdp = get_lower_table(page_map, pml4_offset);
|
||||||
|
|
||||||
if(!pdp){
|
if(!pdp){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PDP");
|
klog( __func__, "Failed to allocate PDP");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t *pd = get_lower_table(pdp, pdp_offset);
|
uint64_t *pd = get_lower_table(pdp, pdp_offset);
|
||||||
|
|
||||||
if(!pd){
|
if(!pd){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PD");
|
klog(__func__, "Failed to allocate PD");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t *pt = get_lower_table(pd, pd_offset);
|
uint64_t *pt = get_lower_table(pd, pd_offset);
|
||||||
|
|
||||||
if(!pt){
|
if(!pt){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PT");
|
klog( __func__, "Failed to allocate PT");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(pt[pt_offset] != 0){
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
pt[pt_offset] = phys_addr | flags;
|
pt[pt_offset] = phys_addr | flags;
|
||||||
|
|
||||||
asm volatile(
|
asm volatile(
|
||||||
|
|
@ -213,7 +218,9 @@ void vmm_map_page(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, ui
|
||||||
: : : "rax"
|
: : : "rax"
|
||||||
);
|
);
|
||||||
|
|
||||||
free_lock(&page_table_lock);
|
end:
|
||||||
|
|
||||||
|
free_spinlock(&page_table_lock);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -227,14 +234,14 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){
|
||||||
|
|
||||||
|
|
||||||
if(!pdp){
|
if(!pdp){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PDP");
|
klog(__func__, "Failed to allocate PDP");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t *pd = get_lower_table(pdp, pdp_offset);
|
uint64_t *pd = get_lower_table(pdp, pdp_offset);
|
||||||
|
|
||||||
if(!pd){
|
if(!pd){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PD");
|
klog( __func__, "Failed to allocate PD");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -242,7 +249,7 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){
|
||||||
uint64_t *pt = get_lower_table(pd, pd_offset);
|
uint64_t *pt = get_lower_table(pd, pd_offset);
|
||||||
|
|
||||||
if(!pt){
|
if(!pt){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate PT");
|
klog(__func__, "Failed to allocate PT");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -259,8 +266,37 @@ void vmm_free_page(uint64_t *page_map, uint64_t virt_addr){
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint64_t vmm_get_phys_addr(uint64_t *page_map, uint64_t virt_addr){
|
||||||
|
uint64_t pml4_offset = (virt_addr >> 39) & 0x1ff;
|
||||||
|
uint64_t pdp_offset = (virt_addr >> 30) & 0x1ff;
|
||||||
|
uint64_t pd_offset = (virt_addr >> 21) & 0x1ff;
|
||||||
|
uint64_t pt_offset = (virt_addr >> 12) & 0x1ff;
|
||||||
|
|
||||||
|
uint64_t pml4e = page_map[pml4_offset];
|
||||||
|
if (!(pml4e & 1)) return 0; //
|
||||||
|
uint64_t *pdp = (uint64_t *)((pml4e & 0x000ffffffffff000) + hhdmoffset);
|
||||||
|
|
||||||
|
uint64_t pdpe = pdp[pdp_offset];
|
||||||
|
if (!(pdpe & 1)) return 0;
|
||||||
|
uint64_t *pd = (uint64_t *)((pdpe & 0x000ffffffffff000) + hhdmoffset);
|
||||||
|
|
||||||
|
uint64_t pde = pd[pd_offset];
|
||||||
|
if (!(pde & 1)) return 0;
|
||||||
|
uint64_t *pt = (uint64_t *)((pde & 0x000ffffffffff000) + hhdmoffset);
|
||||||
|
|
||||||
|
uint64_t pte = pt[pt_offset];
|
||||||
|
if (!(pte & 1)) return 0;
|
||||||
|
|
||||||
|
return pte & 0x000ffffffffff000;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t kget_phys_addr(uint64_t *virt_addr){
|
||||||
|
return vmm_get_phys_addr(kernel_page_map, (uint64_t)virt_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Maps `size` number of free pages at the specified virtual address */
|
/* Maps `size` number of free pages at the specified virtual address */
|
||||||
int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags){
|
int vmm_map_contigious_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags){
|
||||||
for(uint64_t i = 0; i < size; i++){
|
for(uint64_t i = 0; i < size; i++){
|
||||||
vmm_map_page(page_map, virt_addr + i * PAGE_SIZE, (uint64_t)phys_addr, flags);
|
vmm_map_page(page_map, virt_addr + i * PAGE_SIZE, (uint64_t)phys_addr, flags);
|
||||||
}
|
}
|
||||||
|
|
@ -268,38 +304,49 @@ int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phy
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define VA_BASE 0x800815000
|
||||||
|
uint64_t va_base = VA_BASE;
|
||||||
|
atomic_flag va_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
|
/* Allocates some pages from the PMM and makes them contigious in the kernels memory map. */
|
||||||
|
void *va_alloc_contigious_pages(size_t pages){
|
||||||
|
acquire_spinlock(&va_lock);
|
||||||
|
|
||||||
/* Allocates and maps memory into the kernel address space */
|
if(pages == 0){
|
||||||
void *kernel_allocate_memory(uint64_t size, uint64_t flags){
|
free_spinlock(&va_lock);
|
||||||
|
|
||||||
if(size == 0){
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *ret = NULL;
|
size_t i;
|
||||||
for(uint64_t i = 0; i < size; i += PAGE_SIZE){
|
for(i = 0; i < pages; i++){
|
||||||
ret = pmm_alloc();
|
void *t = pmm_alloc();
|
||||||
|
|
||||||
|
if(t == NULL){
|
||||||
if(!ret){
|
free_spinlock(&va_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
vmm_map_page(kernel_page_map, (uint64_t)ret + hhdmoffset, (uint64_t)ret, PTE_BIT_PRESENT | flags);
|
vmm_map_page(kernel_page_map, va_base+hhdmoffset+i*PAGE_SIZE, (uint64_t)t, PTE_BIT_RW | PTE_BIT_PRESENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (void*)((uint64_t)ret + hhdmoffset);
|
uint64_t va_base_old = va_base;
|
||||||
|
|
||||||
|
va_base += i*PAGE_SIZE;
|
||||||
|
|
||||||
|
free_spinlock(&va_lock);
|
||||||
|
|
||||||
|
return (void*)(va_base_old+hhdmoffset);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Maps pages from phys_addr to phys_addr+size into the kernels address space */
|
/* Maps pages from phys_addr to phys_addr+size into the kernels address space */
|
||||||
void kernel_map_pages(void *phys_addr, uint64_t size, uint64_t flags){
|
void kmap_pages(void *phys_addr, uint64_t size, uint64_t flags){
|
||||||
for(uint64_t i = 0; i < size; i++){
|
for(uint64_t i = 0; i < size; i++){
|
||||||
vmm_map_page(kernel_page_map, (uint64_t)phys_addr + hhdmoffset + (i * PAGE_SIZE), (uint64_t)phys_addr + (i * PAGE_SIZE), PTE_BIT_PRESENT | flags);
|
vmm_map_page(kernel_page_map, (uint64_t)phys_addr + hhdmoffset + (i * PAGE_SIZE), (uint64_t)phys_addr + (i * PAGE_SIZE), PTE_BIT_PRESENT | flags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void kernel_unmap_pages(void *addr, uint64_t size){
|
void kunmap_pages(void *addr, uint64_t size){
|
||||||
for(uint64_t i = 0; i < size; i++){
|
for(uint64_t i = 0; i < size; i++){
|
||||||
vmm_free_page(kernel_page_map, (uint64_t)addr + i*PAGE_SIZE);
|
vmm_free_page(kernel_page_map, (uint64_t)addr + i*PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
10
src/mm/vmm.h
10
src/mm/vmm.h
|
|
@ -11,13 +11,15 @@
|
||||||
|
|
||||||
void tlb_flush(void);
|
void tlb_flush(void);
|
||||||
void vmm_map_page(uint64_t *page_map, uint64_t virt_address, uint64_t phys_address, uint64_t flags);
|
void vmm_map_page(uint64_t *page_map, uint64_t virt_address, uint64_t phys_address, uint64_t flags);
|
||||||
int vmm_map_continous_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags);
|
int vmm_map_contigious_pages(uint64_t *page_map, uint64_t virt_addr, uint64_t phys_addr, uint64_t size, uint64_t flags);
|
||||||
void vmm_free_page(uint64_t *page_map, uint64_t virt_addr);
|
void vmm_free_page(uint64_t *page_map, uint64_t virt_addr);
|
||||||
void vmm_init();
|
void vmm_init();
|
||||||
void vmm_set_ctx(uint64_t *page_map);
|
void vmm_set_ctx(uint64_t *page_map);
|
||||||
void *kernel_allocate_memory(uint64_t size, uint64_t flags);
|
uint64_t vmm_get_phys_addr(uint64_t *page_map, uint64_t virt_addr);
|
||||||
void kernel_map_pages(void *phys_addr, uint64_t size, uint64_t flags);
|
uint64_t kget_phys_addr(uint64_t *virt_addr);
|
||||||
void kernel_unmap_pages(void *addr, uint64_t size);
|
void *va_alloc_contigious_pages(uint64_t size);
|
||||||
|
void kmap_pages(void *phys_addr, uint64_t size, uint64_t flags);
|
||||||
|
void kunmap_pages(void *addr, uint64_t size);
|
||||||
|
|
||||||
typedef char link_symbol_ptr[];
|
typedef char link_symbol_ptr[];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include "../hal/smp.h"
|
#include "../hal/smp.h"
|
||||||
|
|
@ -61,7 +61,7 @@ kstatus add_task(uint64_t *entry){
|
||||||
proc *proc = alloc_process();
|
proc *proc = alloc_process();
|
||||||
|
|
||||||
if (proc == NULL) {
|
if (proc == NULL) {
|
||||||
klog(LOG_ERROR, __func__, "proc == null!");
|
klog(__func__, "proc == null!");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdalign.h>
|
#include <stdalign.h>
|
||||||
|
|
@ -53,7 +53,7 @@ uint64_t *find_acpi_table(char *signature){
|
||||||
void acpi_init(void){
|
void acpi_init(void){
|
||||||
|
|
||||||
if(rsdp_request.response == NULL){
|
if(rsdp_request.response == NULL){
|
||||||
klog(LOG_ERROR, "acpi", "RSDP request is NULL");
|
klog("acpi", "RSDP request is NULL");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -65,21 +65,21 @@ void acpi_init(void){
|
||||||
if(rsdp->revision >= 2){
|
if(rsdp->revision >= 2){
|
||||||
rsdt = NULL;
|
rsdt = NULL;
|
||||||
xsdt = (xsdt_t*)(rsdp->xsdt_address + hhdmoffset);
|
xsdt = (xsdt_t*)(rsdp->xsdt_address + hhdmoffset);
|
||||||
klog(LOG_INFO, "acpi", "Using XSDT header");
|
klog("acpi", "Using XSDT header");
|
||||||
kprintf("XSDT address: 0x{xn}", (uint64_t)xsdt);
|
kprintf("XSDT address: 0x{x}\n", (uint64_t)xsdt);
|
||||||
kprintf("OEMID: {ccccccn}", xsdt->header.oemid[0], xsdt->header.oemid[1], xsdt->header.oemid[2], xsdt->header.oemid[3], xsdt->header.oemid[4], xsdt->header.oemid[5]);
|
kprintf("OEMID: {cccccc}\n", xsdt->header.oemid[0], xsdt->header.oemid[1], xsdt->header.oemid[2], xsdt->header.oemid[3], xsdt->header.oemid[4], xsdt->header.oemid[5]);
|
||||||
}else{
|
}else{
|
||||||
xsdt = NULL;
|
xsdt = NULL;
|
||||||
rsdt = (rsdt_t*)(rsdp->rsdt_address + hhdmoffset);
|
rsdt = (rsdt_t*)(rsdp->rsdt_address + hhdmoffset);
|
||||||
klog(LOG_INFO, "acpi", "Using RSDT header");
|
klog("acpi", "Using RSDT header");
|
||||||
kprintf("RSDT address: 0x{xn}", (uint64_t)rsdt);
|
kprintf("RSDT address: 0x{x}\n", (uint64_t)rsdt);
|
||||||
kprintf("OEMID: {ccccccn}", rsdt->header.oemid[0], rsdt->header.oemid[1], rsdt->header.oemid[2], rsdt->header.oemid[3], rsdt->header.oemid[4], rsdt->header.oemid[5]);
|
kprintf("OEMID: {cccccc}\n", rsdt->header.oemid[0], rsdt->header.oemid[1], rsdt->header.oemid[2], rsdt->header.oemid[3], rsdt->header.oemid[4], rsdt->header.oemid[5]);
|
||||||
}
|
}
|
||||||
|
|
||||||
madt = (madt_t*)find_acpi_table("APIC");
|
madt = (madt_t*)find_acpi_table("APIC");
|
||||||
|
|
||||||
if(!madt){
|
if(!madt){
|
||||||
klog(LOG_ERROR, __func__, "MADT table not found");
|
klog(__func__, "MADT table not found");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <lock.h>
|
#include <lock.h>
|
||||||
#include "acpi.h"
|
#include "acpi.h"
|
||||||
|
|
@ -34,13 +34,13 @@ extern uint64_t *kernel_page_map;
|
||||||
atomic_flag pci_array_lock = ATOMIC_FLAG_INIT;
|
atomic_flag pci_array_lock = ATOMIC_FLAG_INIT;
|
||||||
|
|
||||||
void pci_add_device(pci_structure structure){
|
void pci_add_device(pci_structure structure){
|
||||||
acquire_lock(&pci_array_lock);
|
acquire_spinlock(&pci_array_lock);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
/* Find first unused space */
|
/* Find first unused space */
|
||||||
while(pci_array[i].func_addr[0] != 0){
|
while(pci_array[i].func_addr[0] != 0){
|
||||||
if(i >= PCI_DEVICE_BUS){
|
if(i >= PCI_DEVICE_BUS){
|
||||||
klog(LOG_ERROR, __func__, "No more space in the PCI array!");
|
klog(__func__, "No more space in the PCI array!");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
@ -56,24 +56,24 @@ void pci_add_device(pci_structure structure){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_lock(&pci_array_lock);
|
free_spinlock(&pci_array_lock);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pci_structure *pci_get_device(pci_structure structure){
|
pci_structure *pci_get_device(pci_structure structure){
|
||||||
acquire_lock(&pci_array_lock);
|
acquire_spinlock(&pci_array_lock);
|
||||||
pci_structure ret = {0};
|
pci_structure ret = {0};
|
||||||
|
|
||||||
for(int i = 0; i < PCI_DEVICE_BUS; i++){
|
for(int i = 0; i < PCI_DEVICE_BUS; i++){
|
||||||
if( structure.segment == pci_array[i].segment &&
|
if( structure.segment == pci_array[i].segment &&
|
||||||
structure.bus == pci_array[i].bus &&
|
structure.bus == pci_array[i].bus &&
|
||||||
structure.device == pci_array[i].device){
|
structure.device == pci_array[i].device){
|
||||||
|
free_spinlock(&pci_array_lock);
|
||||||
return &pci_array[i];
|
return &pci_array[i];
|
||||||
free_lock(&pci_array_lock);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free_lock(&pci_array_lock);
|
free_spinlock(&pci_array_lock);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -170,7 +170,7 @@ void pci_init(){
|
||||||
mcfg = (mcfg_t*)find_acpi_table("MCFG");
|
mcfg = (mcfg_t*)find_acpi_table("MCFG");
|
||||||
|
|
||||||
if(!mcfg){
|
if(!mcfg){
|
||||||
klog(LOG_ERROR, __func__, "Failed to find MCFG table");
|
klog(__func__, "Failed to find MCFG table");
|
||||||
kprintf("pci: device: PCIe not supported! Halting");
|
kprintf("pci: device: PCIe not supported! Halting");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
@ -180,13 +180,13 @@ void pci_init(){
|
||||||
parse_conf_space();
|
parse_conf_space();
|
||||||
|
|
||||||
/* Map the config space */
|
/* Map the config space */
|
||||||
kernel_map_pages((uint64_t*)(config_space_base_addr - hhdmoffset), (PCIE_CONF_SPACE_WIDTH * end_pci_num) / PAGE_SIZE, PTE_BIT_RW | PTE_BIT_NX);
|
kmap_pages((uint64_t*)(config_space_base_addr - hhdmoffset), (PCIE_CONF_SPACE_WIDTH * end_pci_num) / PAGE_SIZE, PTE_BIT_RW | PTE_BIT_NX);
|
||||||
|
|
||||||
/* Stores enough for an entire configuration space */
|
/* Stores enough for an entire configuration space */
|
||||||
pci_array = kmalloc((256 * 32) * sizeof(pci_structure));
|
pci_array = kmalloc((256 * 32) * sizeof(pci_structure));
|
||||||
|
|
||||||
if(!pci_array){
|
if(!pci_array){
|
||||||
klog(LOG_ERROR, __func__, "Failed to allocate memory for PCI structures!");
|
klog(__func__, "Failed to allocate memory for PCI structures!");
|
||||||
kkill();
|
kkill();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
36
src/sys/rand.c
Normal file
36
src/sys/rand.c
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <kprint.h>
|
||||||
|
#include <cpuid.h>
|
||||||
|
uint32_t next = 0;
|
||||||
|
|
||||||
|
uint16_t rand(void){
|
||||||
|
next = next * 1103515245 + 12345;
|
||||||
|
return (size_t) (next / 65536) % 32768;
|
||||||
|
}
|
||||||
|
|
||||||
|
void srand(uint32_t seed){
|
||||||
|
next = seed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void krand_init(){
|
||||||
|
uint32_t unused, ecx;
|
||||||
|
__get_cpuid(0x01, &unused, &unused, &ecx, &unused);
|
||||||
|
|
||||||
|
ecx = (ecx & 2) >> 1;
|
||||||
|
|
||||||
|
if(ecx == 1){
|
||||||
|
/* RDRAND supported */
|
||||||
|
klog(__func__, "using RDRAND for random number seed\n");
|
||||||
|
uint32_t rand;
|
||||||
|
asm volatile (
|
||||||
|
"rdrand %0"
|
||||||
|
: "=r" (rand)
|
||||||
|
);
|
||||||
|
srand(rand);
|
||||||
|
}else{
|
||||||
|
next = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
3
src/sys/rand.h
Normal file
3
src/sys/rand.h
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
#include <stddef.h>
|
||||||
|
void krand_init();
|
||||||
|
size_t rand(void);
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
#include "mm/vmm.h"
|
#include "mm/vmm.h"
|
||||||
#include "mm/kmalloc.h"
|
#include "mm/kmalloc.h"
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
#include <stdio.h>
|
#include <kprint.h>
|
||||||
#include <SFB25.h>
|
#include <SFB25.h>
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue