feat: introduced tasking, added paging (no vm), moved malloc, added
syscalls, other stuff
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
cmake_minimum_required(VERSION 3.15)
|
cmake_minimum_required(VERSION 3.15)
|
||||||
project(new_kernel C ASM)
|
project(new_kernel C ASM)
|
||||||
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
#set(CMAKE_VERBOSE_MAKEFILE ON)
|
||||||
set(CMAKE_C_FLAGS "-I/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include -g -ffreestanding -Wall -Wextra -fno-exceptions -fno-stack-protector -nostdinc -nostdlib -fno-pie -m32")
|
set(CMAKE_C_FLAGS "-I/usr/lib/gcc/x86_64-pc-linux-gnu/10.2.0/include -mno-sse -g -ffreestanding -Wall -Wextra -fno-exceptions -fno-stack-protector -nostdinc -nostdlib -fno-pie -m32")
|
||||||
#set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf")
|
#set(CMAKE_ASM_NASM_OBJECT_FORMAT "elf")
|
||||||
set(CMAKE_ASM_FLAGS --32)
|
set(CMAKE_ASM_FLAGS --32)
|
||||||
#set(CMAKE_ASM-ATT_FLAGS --32)
|
#set(CMAKE_ASM-ATT_FLAGS --32)
|
||||||
|
|||||||
@@ -92,6 +92,11 @@ _start:
|
|||||||
*/
|
*/
|
||||||
cli
|
cli
|
||||||
lgdt (gdtr)
|
lgdt (gdtr)
|
||||||
|
movw $0x10,%ax # kernel data segment descriptor
|
||||||
|
movw %ax,%ds
|
||||||
|
movw %ax,%es
|
||||||
|
movw %ax,%fs
|
||||||
|
movw %ax,%gs
|
||||||
ljmp $0x8, $continue_boot
|
ljmp $0x8, $continue_boot
|
||||||
|
|
||||||
continue_boot:
|
continue_boot:
|
||||||
|
|||||||
16
kernel/attributes.h
Normal file
16
kernel/attributes.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 24-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_ATTRIBUTES_H
|
||||||
|
#define NEW_KERNEL_ATTRIBUTES_H
|
||||||
|
|
||||||
|
// function
|
||||||
|
#define noreturn __attribute((noreturn))
|
||||||
|
#define cdecl __attribute((cdecl))
|
||||||
|
// structure
|
||||||
|
#define packed __attribute((packed))
|
||||||
|
// field
|
||||||
|
#define at_aligned(size) __attribute((aligned(size)))
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_ATTRIBUTES_H
|
||||||
144
kernel/command.c
Normal file
144
kernel/command.c
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "command.h"
|
||||||
|
#include "kprint.h"
|
||||||
|
#include "libk.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include <libc/kprintf.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <libc/string.h>
|
||||||
|
#include <mem/mem.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
#include <cpu/timer.h>
|
||||||
|
#include <drivers/pci.h>
|
||||||
|
#include <drivers/ide.h>
|
||||||
|
#include <fs/blockdev.h>
|
||||||
|
#include <fs/mbr.h>
|
||||||
|
#include <libc/readline.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
|
#define BOOTLOADER_NAME_MAX_LENGTH 64
|
||||||
|
#define CMDLINE_MAX_LENGTH 256
|
||||||
|
|
||||||
|
char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH];
|
||||||
|
char cmdline[CMDLINE_MAX_LENGTH];
|
||||||
|
|
||||||
|
typedef void (*cmd_handler_func)(const char *);
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *cmd;
|
||||||
|
cmd_handler_func handler;
|
||||||
|
} cmd_handler;
|
||||||
|
|
||||||
|
void print(const char *arg);
|
||||||
|
|
||||||
|
void ide(const char *arg);
|
||||||
|
|
||||||
|
void echo(const char *arg);
|
||||||
|
|
||||||
|
void help(const char *arg);
|
||||||
|
|
||||||
|
cmd_handler cmd_handlers[] = {
|
||||||
|
{"help", help},
|
||||||
|
{"echo", echo},
|
||||||
|
{"print", print},
|
||||||
|
{"ide", ide},
|
||||||
|
{NULL, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
void print_bootinfo() {
|
||||||
|
printf("Bootloader name: %s\n"
|
||||||
|
"cmdline: %s\n",
|
||||||
|
(bootloader_name[0] == 0 ? "NULL" : bootloader_name),
|
||||||
|
(cmdline[0] == 0 ? "NULL" : cmdline));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void help(const char *arg) {
|
||||||
|
kprint("Available commands:\n");
|
||||||
|
int index = 0;
|
||||||
|
while (true) {
|
||||||
|
if (cmd_handlers[index].cmd == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
printf("%s\n", cmd_handlers[index].cmd);
|
||||||
|
index += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void echo(const char *arg) {
|
||||||
|
printf("%s\n", arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void print(const char *arg) {
|
||||||
|
if (strcmp(arg, "mmap") == 0) {
|
||||||
|
print_mmap_info();
|
||||||
|
} else if (strcmp(arg, "malloc") == 0) {
|
||||||
|
print_malloc_info();
|
||||||
|
} else if (strcmp(arg, "tick") == 0) {
|
||||||
|
print_current_tick();
|
||||||
|
} else if (strcmp(arg, "bootinfo") == 0) {
|
||||||
|
print_bootinfo();
|
||||||
|
} else if (strcmp(arg, "pci") == 0) {
|
||||||
|
pci_print_info();
|
||||||
|
} else if (strcmp(arg, "ide") == 0) {
|
||||||
|
ide_print_devices();
|
||||||
|
} else {
|
||||||
|
printf("Unknown print %s\n", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ide(const char *arg) {
|
||||||
|
if (strcmp(arg, "block_devices") == 0) {
|
||||||
|
block_dev_print_info();
|
||||||
|
} else if (strcmp(arg, "ide_devices") == 0) {
|
||||||
|
ide_print_devices();
|
||||||
|
} else if (strcmp(arg, "mbr") == 0) {
|
||||||
|
mbr_read_from_ide(0);
|
||||||
|
} else {
|
||||||
|
printf("Unknown print %s\n", arg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void store_bootloader_info(multiboot_info_t *multiboot_info) {
|
||||||
|
// get bootloader and cmdline
|
||||||
|
if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) {
|
||||||
|
int cmdline_length = strlen((const char *) multiboot_info->cmdline);
|
||||||
|
if (cmdline_length > CMDLINE_MAX_LENGTH) {
|
||||||
|
k_panics("cmdline to long!\n");
|
||||||
|
}
|
||||||
|
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
|
||||||
|
}
|
||||||
|
if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
|
||||||
|
int bootloader_length = strlen((const char *) multiboot_info->boot_loader_name);
|
||||||
|
if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) {
|
||||||
|
k_panics("bootloader name to long!\n");
|
||||||
|
}
|
||||||
|
memcpy(bootloader_name, (char *) multiboot_info->boot_loader_name, bootloader_length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void noreturn main_loop(void* data) {
|
||||||
|
while (true) {
|
||||||
|
char *msg = readline(NULL);
|
||||||
|
char *args = strchr(msg, ' ') + 1;
|
||||||
|
args[-1] = 0;
|
||||||
|
int test_index = 0;
|
||||||
|
while (true) {
|
||||||
|
if (cmd_handlers[test_index].cmd == 0) {
|
||||||
|
printf("Unknown command: %s\n", msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) {
|
||||||
|
cmd_handlers[test_index].handler(args);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
test_index++;
|
||||||
|
}
|
||||||
|
free(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
kernel/command.h
Normal file
14
kernel/command.h
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_COMMAND_H
|
||||||
|
#define NEW_KERNEL_COMMAND_H
|
||||||
|
|
||||||
|
#include "multiboot.h"
|
||||||
|
|
||||||
|
void store_bootloader_info(multiboot_info_t *multiboot_info);
|
||||||
|
|
||||||
|
void main_loop(void* data);
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_COMMAND_H
|
||||||
20
kernel/cpu/cpu.h
Normal file
20
kernel/cpu/cpu.h
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_CPU_H
|
||||||
|
#define NEW_KERNEL_CPU_H
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t edi, esi, ebx, ebp, eip;
|
||||||
|
} task_registers_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t ds; // pushed in common handler
|
||||||
|
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // pusha/popa
|
||||||
|
uint32_t int_no, err_code; // pushed by handlers
|
||||||
|
uint32_t eip, cs, eflags, useresp, ss; // isr/iret
|
||||||
|
} isr_registers_t;
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_CPU_H
|
||||||
@@ -4,3 +4,30 @@
|
|||||||
|
|
||||||
#include "cpuidx.h"
|
#include "cpuidx.h"
|
||||||
|
|
||||||
|
#include <types.h>
|
||||||
|
#include <cpuid.h>
|
||||||
|
#include <libc/kprintf.h>
|
||||||
|
|
||||||
|
union cpu_name {
|
||||||
|
uint32_t parts[3];
|
||||||
|
struct {
|
||||||
|
char name[12];
|
||||||
|
char end;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void cpuidx_print_info() {
|
||||||
|
union cpu_name name;
|
||||||
|
__get_cpuid(0, NULL, &name.parts[0], &name.parts[2], &name.parts[1]);
|
||||||
|
name.end = 0;
|
||||||
|
printf("CPU: %s\n", &name.name);
|
||||||
|
|
||||||
|
cpu_features_ecx features_ecx;
|
||||||
|
cpu_features_edx features_edx;
|
||||||
|
__get_cpuid(1, NULL, NULL, (uint32_t *) &features_ecx, (uint32_t *) &features_edx);
|
||||||
|
|
||||||
|
printf("");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -5,10 +5,76 @@
|
|||||||
#ifndef NEW_KERNEL_CPUIDX_H
|
#ifndef NEW_KERNEL_CPUIDX_H
|
||||||
#define NEW_KERNEL_CPUIDX_H
|
#define NEW_KERNEL_CPUIDX_H
|
||||||
|
|
||||||
#include <cpuid.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
enum {
|
typedef struct {
|
||||||
|
bool sse3: 1;
|
||||||
|
bool pclmul: 1;
|
||||||
|
bool dtes64: 1;
|
||||||
|
bool monitor: 1;
|
||||||
|
bool ds_cpl: 1;
|
||||||
|
bool vmx: 1;
|
||||||
|
bool smx: 1;
|
||||||
|
bool est: 1;
|
||||||
|
bool tm2: 1;
|
||||||
|
bool ssse3: 1;
|
||||||
|
bool cid: 1;
|
||||||
|
bool reserved: 1;
|
||||||
|
bool fma: 1;
|
||||||
|
bool cx16: 1;
|
||||||
|
bool etprd: 1;
|
||||||
|
bool pdcm: 1;
|
||||||
|
bool pcide: 1;
|
||||||
|
bool dca: 1;
|
||||||
|
bool sse4_1: 1;
|
||||||
|
bool sse4_2: 1;
|
||||||
|
bool x2APIC: 1;
|
||||||
|
bool movbe: 1;
|
||||||
|
bool popcnt: 1;
|
||||||
|
bool reserved2: 1;
|
||||||
|
bool aes: 1;
|
||||||
|
bool xsave: 1;
|
||||||
|
bool osxsave: 1;
|
||||||
|
bool avx: 1;
|
||||||
|
} cpu_features_ecx ;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool fpu: 1;
|
||||||
|
bool vme: 1;
|
||||||
|
bool de: 1;
|
||||||
|
bool pse: 1;
|
||||||
|
bool tsc: 1;
|
||||||
|
bool msr: 1;
|
||||||
|
bool pae: 1;
|
||||||
|
bool mce: 1;
|
||||||
|
bool cx8: 1;
|
||||||
|
bool apic: 1;
|
||||||
|
bool reserved: 1;
|
||||||
|
bool sep: 1;
|
||||||
|
bool mtrr: 1;
|
||||||
|
bool pge: 1;
|
||||||
|
bool mca: 1;
|
||||||
|
bool cmov: 1;
|
||||||
|
bool pat: 1;
|
||||||
|
bool pse36: 1;
|
||||||
|
bool psn: 1;
|
||||||
|
bool clf: 1;
|
||||||
|
bool reserved2: 1;
|
||||||
|
bool dtes: 1;
|
||||||
|
bool acpi: 1;
|
||||||
|
bool mmx: 1;
|
||||||
|
bool fxsr: 1;
|
||||||
|
bool sse: 1;
|
||||||
|
bool sse2: 1;
|
||||||
|
bool ss: 1;
|
||||||
|
bool htt: 1;
|
||||||
|
bool tm1: 1;
|
||||||
|
bool ia64: 1;
|
||||||
|
bool pbe: 1;
|
||||||
|
|
||||||
|
} cpu_features_edx ;
|
||||||
|
|
||||||
|
enum cpu_features {
|
||||||
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
CPUID_FEAT_ECX_SSE3 = 1 << 0,
|
||||||
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
CPUID_FEAT_ECX_PCLMUL = 1 << 1,
|
||||||
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
CPUID_FEAT_ECX_DTES64 = 1 << 2,
|
||||||
@@ -68,16 +134,6 @@ enum {
|
|||||||
CPUID_FEAT_EDX_PBE = 1 << 31
|
CPUID_FEAT_EDX_PBE = 1 << 31
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline void cpuid(int code, uint32_t *a, uint32_t *d) {
|
void cpuidx_print_info();
|
||||||
asm volatile("cpuid":"=a"(*a), "=d"(*d):"a"(code):"ecx", "ebx");
|
|
||||||
}
|
|
||||||
|
|
||||||
/** issue a complete request, storing general registers output as a string
|
|
||||||
*/
|
|
||||||
static inline int cpuid_string(int code, uint32_t where[4]) {
|
|
||||||
asm volatile("cpuid":"=a"(*where), "=b"(*(where + 1)),
|
|
||||||
"=c"(*(where + 2)), "=d"(*(where + 3)):"a"(code));
|
|
||||||
return (int) where[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif //NEW_KERNEL_CPUIDX_H
|
#endif //NEW_KERNEL_CPUIDX_H
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
|
|
||||||
#ifndef MY_KERNEL_IDT_H
|
#ifndef MY_KERNEL_IDT_H
|
||||||
#define MY_KERNEL_IDT_H
|
#define MY_KERNEL_IDT_H
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
#define KERNEL_CS 0x08
|
#define KERNEL_CS 0x08
|
||||||
|
|
||||||
/* How every interrupt gate (handler) is defined */
|
/* How every interrupt gate (handler) is defined */
|
||||||
@@ -19,12 +21,12 @@ typedef struct {
|
|||||||
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
|
* Bits 3-0: bits 1110 = decimal 14 = "32 bit interrupt gate" */
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
uint16_t high_offset; /* Higher 16 bits of handler function address */
|
uint16_t high_offset; /* Higher 16 bits of handler function address */
|
||||||
} __attribute__((packed)) idt_gate_t;
|
} packed idt_gate_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
uint32_t base;
|
uint32_t base;
|
||||||
} __attribute__((packed)) idt_register_t;
|
} packed idt_register_t;
|
||||||
|
|
||||||
#define IDT_REGISTERS 256
|
#define IDT_REGISTERS 256
|
||||||
|
|
||||||
|
|||||||
@@ -109,6 +109,8 @@ irq_common_stub:
|
|||||||
.global irq14
|
.global irq14
|
||||||
.global irq15
|
.global irq15
|
||||||
|
|
||||||
|
.global isr128
|
||||||
|
|
||||||
# 0: Divide By Zero Exception
|
# 0: Divide By Zero Exception
|
||||||
isr0:
|
isr0:
|
||||||
cli
|
cli
|
||||||
@@ -424,3 +426,9 @@ irq15:
|
|||||||
push $47
|
push $47
|
||||||
jmp irq_common_stub
|
jmp irq_common_stub
|
||||||
|
|
||||||
|
# Syscall
|
||||||
|
isr128:
|
||||||
|
cli
|
||||||
|
push $0
|
||||||
|
push $128
|
||||||
|
jmp isr_common_stub
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
#include "isr.h"
|
#include "isr.h"
|
||||||
|
|
||||||
#include <cpu/idt.h>
|
#include <cpu/idt.h>
|
||||||
|
#include <cpu/syscall_handler.h>
|
||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <drivers/ports.h>
|
#include <drivers/ports.h>
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
|
#include <libk.h>
|
||||||
|
|
||||||
#define PIC_END_OF_INTERRUPT 0x20
|
#define PIC_END_OF_INTERRUPT 0x20
|
||||||
|
|
||||||
@@ -48,6 +50,7 @@ void isr_install() {
|
|||||||
set_idt_gate(31, (uint32_t) isr31);
|
set_idt_gate(31, (uint32_t) isr31);
|
||||||
|
|
||||||
// Remap the PIC
|
// Remap the PIC
|
||||||
|
// todo make readable
|
||||||
port_byte_out(0x20, 0x11);
|
port_byte_out(0x20, 0x11);
|
||||||
port_byte_out(0xA0, 0x11);
|
port_byte_out(0xA0, 0x11);
|
||||||
port_byte_out(0x21, 0x20);
|
port_byte_out(0x21, 0x20);
|
||||||
@@ -77,6 +80,8 @@ void isr_install() {
|
|||||||
set_idt_gate(46, (uint32_t) irq14);
|
set_idt_gate(46, (uint32_t) irq14);
|
||||||
set_idt_gate(47, (uint32_t) irq15);
|
set_idt_gate(47, (uint32_t) irq15);
|
||||||
|
|
||||||
|
set_idt_gate(128, (uint32_t) isr128);
|
||||||
|
|
||||||
set_idt(); // Load with ASM
|
set_idt(); // Load with ASM
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -118,15 +123,20 @@ char *exception_messages[] = {
|
|||||||
"Reserved"
|
"Reserved"
|
||||||
};
|
};
|
||||||
|
|
||||||
void isr_handler(registers_t r) {
|
void isr_handler(isr_registers_t r) {
|
||||||
|
if (r.int_no == 128) {
|
||||||
|
syscall_handle(&r);
|
||||||
|
return;
|
||||||
|
}
|
||||||
printf("Received interrupt: %d - %s\n", r.int_no, exception_messages[r.int_no]);
|
printf("Received interrupt: %d - %s\n", r.int_no, exception_messages[r.int_no]);
|
||||||
|
k_panic();
|
||||||
}
|
}
|
||||||
|
|
||||||
void register_interrupt_handler(uint8_t n, isr_t handler) {
|
void register_interrupt_handler(uint8_t n, isr_t handler) {
|
||||||
interrupt_handlers[n] = handler;
|
interrupt_handlers[n] = handler;
|
||||||
}
|
}
|
||||||
|
|
||||||
void irq_handler(registers_t r) {
|
void irq_handler(isr_registers_t r) {
|
||||||
/* After every interrupt we need to send an EOI to the PICs
|
/* After every interrupt we need to send an EOI to the PICs
|
||||||
* or they will not send another interrupt again */
|
* or they will not send another interrupt again */
|
||||||
if (r.int_no >= 40) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
|
if (r.int_no >= 40) port_byte_out(PORT_PIC_SLAVE_COMMAND, PIC_END_OF_INTERRUPT); /* slave */
|
||||||
@@ -135,6 +145,6 @@ void irq_handler(registers_t r) {
|
|||||||
/* Handle the interrupt in a more modular way */
|
/* Handle the interrupt in a more modular way */
|
||||||
if (interrupt_handlers[r.int_no] != NULL) {
|
if (interrupt_handlers[r.int_no] != NULL) {
|
||||||
isr_t handler = interrupt_handlers[r.int_no];
|
isr_t handler = interrupt_handlers[r.int_no];
|
||||||
handler(r);
|
handler(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,6 +7,8 @@
|
|||||||
#ifndef MY_KERNEL_ISR_H
|
#ifndef MY_KERNEL_ISR_H
|
||||||
#define MY_KERNEL_ISR_H
|
#define MY_KERNEL_ISR_H
|
||||||
|
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
|
||||||
/* ISRs reserved for CPU exceptions */
|
/* ISRs reserved for CPU exceptions */
|
||||||
extern void isr0();
|
extern void isr0();
|
||||||
|
|
||||||
@@ -105,6 +107,8 @@ extern void irq14();
|
|||||||
|
|
||||||
extern void irq15();
|
extern void irq15();
|
||||||
|
|
||||||
|
extern void isr128();
|
||||||
|
|
||||||
#define IRQ0 32
|
#define IRQ0 32
|
||||||
#define IRQ1 33
|
#define IRQ1 33
|
||||||
#define IRQ2 34
|
#define IRQ2 34
|
||||||
@@ -122,19 +126,12 @@ extern void irq15();
|
|||||||
#define IRQ14 46
|
#define IRQ14 46
|
||||||
#define IRQ15 47
|
#define IRQ15 47
|
||||||
|
|
||||||
typedef struct {
|
typedef void (*isr_t)(isr_registers_t*);
|
||||||
uint32_t ds;
|
|
||||||
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax;
|
|
||||||
uint32_t int_no, err_code;
|
|
||||||
uint32_t eip, cs, eflags, useresp, ss;
|
|
||||||
} registers_t;
|
|
||||||
|
|
||||||
typedef void (*isr_t)(registers_t);
|
|
||||||
|
|
||||||
void register_interrupt_handler(uint8_t n, isr_t handler);
|
void register_interrupt_handler(uint8_t n, isr_t handler);
|
||||||
|
|
||||||
void isr_install();
|
void isr_install();
|
||||||
|
|
||||||
void isr_handler(registers_t r);
|
void isr_handler(isr_registers_t r);
|
||||||
|
|
||||||
#endif //MY_KERNEL_ISR_H
|
#endif //MY_KERNEL_ISR_H
|
||||||
|
|||||||
20
kernel/cpu/syscall_handler.c
Normal file
20
kernel/cpu/syscall_handler.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 24-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "syscall_handler.h"
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <tasks/task.h>
|
||||||
|
|
||||||
|
void syscall_handle(isr_registers_t *registers) {
|
||||||
|
switch (registers->eax) {
|
||||||
|
case SYSCALL_START_SCHEDULER:
|
||||||
|
task_start_first();
|
||||||
|
break;
|
||||||
|
case SYSCALL_YIELD_JOB:
|
||||||
|
task_switch_next();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
kernel/cpu/syscall_handler.h
Normal file
11
kernel/cpu/syscall_handler.h
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 24-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_SYSCALL_HANDLER_H
|
||||||
|
#define NEW_KERNEL_SYSCALL_HANDLER_H
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
|
||||||
|
void syscall_handle(isr_registers_t *registers);
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_SYSCALL_HANDLER_H
|
||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <libk.h>
|
#include <libk.h>
|
||||||
#include <kprint.h>
|
#include <kprint.h>
|
||||||
|
#include <tasks/task.h>
|
||||||
|
|
||||||
// https://wiki.osdev.org/PIT
|
// https://wiki.osdev.org/PIT
|
||||||
#define PIT_MODE_BIN_BCD (1 << 0)
|
#define PIT_MODE_BIN_BCD (1 << 0)
|
||||||
@@ -34,8 +35,13 @@
|
|||||||
|
|
||||||
uint32_t tick = 0;
|
uint32_t tick = 0;
|
||||||
|
|
||||||
static void timer_callback(registers_t regs) {
|
static void timer_callback(isr_registers_t *regs) {
|
||||||
tick++;
|
tick++;
|
||||||
|
task_switch_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t timer_get_tick() {
|
||||||
|
return tick;
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep(uint32_t milliseconds) {
|
void sleep(uint32_t milliseconds) {
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ int init_timer(uint32_t freq);
|
|||||||
|
|
||||||
void print_current_tick();
|
void print_current_tick();
|
||||||
|
|
||||||
|
uint32_t timer_get_tick();
|
||||||
|
|
||||||
void sleep(uint32_t milliseconds);
|
void sleep(uint32_t milliseconds);
|
||||||
|
|
||||||
#endif //MY_KERNEL_TIMER_H
|
#endif //MY_KERNEL_TIMER_H
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <cpu/timer.h>
|
#include <cpu/timer.h>
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
#include <fs/blockdev.h>
|
#include <fs/blockdev.h>
|
||||||
#include <mem/mem.h>
|
#include <mem/malloc.h>
|
||||||
|
|
||||||
#define ATA_SR_BSY 0x80 // Busy
|
#define ATA_SR_BSY 0x80 // Busy
|
||||||
#define ATA_SR_DRDY 0x40 // Drive ready
|
#define ATA_SR_DRDY 0x40 // Drive ready
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <drivers/ports.h>
|
#include <drivers/ports.h>
|
||||||
#include <cpu/isr.h>
|
#include <cpu/isr.h>
|
||||||
#include <libc/ringqueue.h>
|
#include <libc/ringqueue.h>
|
||||||
#include <mem/mem.h>
|
|
||||||
#include <libk.h>
|
#include <libk.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
|
||||||
|
|
||||||
const char scancode_map_lowercase[] = {
|
const char scancode_map_lowercase[] = {
|
||||||
@@ -119,7 +119,7 @@ void publish_key_event(unsigned char scan_code) {
|
|||||||
ring_buffer_put(keyboard_event_buffer, &event);
|
ring_buffer_put(keyboard_event_buffer, &event);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboard_callback(registers_t regs) {
|
static void keyboard_callback(isr_registers_t *regs) {
|
||||||
unsigned char status = port_byte_in(PORT_PS2_STATUS);
|
unsigned char status = port_byte_in(PORT_PS2_STATUS);
|
||||||
// check if data available
|
// check if data available
|
||||||
if ((status & 0b00000001) == 0) {
|
if ((status & 0b00000001) == 0) {
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <libk.h>
|
#include <libk.h>
|
||||||
#include <mem/mem.h>
|
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
|
|
||||||
#define MAX_BLOCK_DEVS 64
|
#define MAX_BLOCK_DEVS 64
|
||||||
@@ -21,7 +21,7 @@ uint8_t block_dev_register_driver(block_dev_driver *driver) {
|
|||||||
return BLOCK_DEV_REGISTER_DRIVER_FULL;
|
return BLOCK_DEV_REGISTER_DRIVER_FULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy((uint8_t *) &block_dev_drivers[last_block_driver++], (const uint8_t *) driver, sizeof(block_dev_drivers));
|
memcpy((uint8_t *) &block_dev_drivers[last_block_driver++], (const uint8_t *) driver, sizeof(block_dev_driver));
|
||||||
return BLOCK_DEV_REGISTER_DRIVER_OK;
|
return BLOCK_DEV_REGISTER_DRIVER_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,8 @@
|
|||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
#include <mem/mem.h>
|
#include <mem/malloc.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
#define FAT_TYPE_12 1
|
#define FAT_TYPE_12 1
|
||||||
#define FAT_TYPE_16 2
|
#define FAT_TYPE_16 2
|
||||||
@@ -31,7 +32,7 @@ typedef struct {
|
|||||||
uint16_t heads_sides;
|
uint16_t heads_sides;
|
||||||
uint32_t hidden_sectors;
|
uint32_t hidden_sectors;
|
||||||
uint32_t large_total_sectors;
|
uint32_t large_total_sectors;
|
||||||
} __attribute((packed)) bpb;
|
} packed bpb;
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
uint8_t drive_number;
|
uint8_t drive_number;
|
||||||
@@ -40,7 +41,7 @@ typedef struct {
|
|||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
uint8_t label[11];
|
uint8_t label[11];
|
||||||
uint8_t system_id[8];
|
uint8_t system_id[8];
|
||||||
} __attribute((packed)) ebr_12_16;
|
} packed ebr_12_16;
|
||||||
struct {
|
struct {
|
||||||
uint32_t sectors_per_fat;
|
uint32_t sectors_per_fat;
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
@@ -55,21 +56,21 @@ typedef struct {
|
|||||||
uint32_t serial;
|
uint32_t serial;
|
||||||
uint8_t label[11];
|
uint8_t label[11];
|
||||||
uint8_t system_id[8];
|
uint8_t system_id[8];
|
||||||
} __attribute((packed)) ebr_32;
|
} packed ebr_32;
|
||||||
};
|
};
|
||||||
} __attribute((packed)) fat_bpb;
|
} packed fat_bpb;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t hours: 5;
|
uint8_t hours: 5;
|
||||||
uint8_t minutes: 6;
|
uint8_t minutes: 6;
|
||||||
uint8_t seconds: 5;
|
uint8_t seconds: 5;
|
||||||
} __attribute((packed)) time_83;
|
} packed time_83;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t hours: 5;
|
uint8_t hours: 5;
|
||||||
uint8_t minutes: 6;
|
uint8_t minutes: 6;
|
||||||
uint8_t seconds: 5;
|
uint8_t seconds: 5;
|
||||||
} __attribute((packed)) date_83;
|
} packed date_83;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
union {
|
union {
|
||||||
@@ -86,7 +87,7 @@ typedef struct {
|
|||||||
date_83 last_mod_date;
|
date_83 last_mod_date;
|
||||||
uint16_t low_first_cluster;
|
uint16_t low_first_cluster;
|
||||||
uint32_t file_size;
|
uint32_t file_size;
|
||||||
} __attribute((packed)) name_83;
|
} packed name_83;
|
||||||
struct {
|
struct {
|
||||||
uint8_t order;
|
uint8_t order;
|
||||||
uint16_t text_1[5];
|
uint16_t text_1[5];
|
||||||
@@ -96,9 +97,9 @@ typedef struct {
|
|||||||
uint16_t text_2[6];
|
uint16_t text_2[6];
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
uint16_t text_3[2];
|
uint16_t text_3[2];
|
||||||
} __attribute((packed)) long_name;
|
} packed long_name;
|
||||||
};
|
};
|
||||||
} __attribute((packed)) fat_directory_entry;
|
} packed fat_directory_entry;
|
||||||
|
|
||||||
uint8_t fat_check_device(const block_device *device, uint8_t *first_sector);
|
uint8_t fat_check_device(const block_device *device, uint8_t *first_sector);
|
||||||
|
|
||||||
@@ -128,7 +129,8 @@ uint8_t fat_check_device(const block_device *device, uint8_t *first_sector) {
|
|||||||
|
|
||||||
uint32_t total_sectors = bpb.bpb.total_sectors == 0 ? bpb.bpb.large_total_sectors : bpb.bpb.total_sectors;
|
uint32_t total_sectors = bpb.bpb.total_sectors == 0 ? bpb.bpb.large_total_sectors : bpb.bpb.total_sectors;
|
||||||
uint32_t fat_size = bpb.bpb.sectors_per_fat == 0 ? bpb.ebr_32.sectors_per_fat : bpb.bpb.sectors_per_fat;
|
uint32_t fat_size = bpb.bpb.sectors_per_fat == 0 ? bpb.ebr_32.sectors_per_fat : bpb.bpb.sectors_per_fat;
|
||||||
uint32_t root_dir_sectors = ((bpb.bpb.directories * 32) + (bpb.bpb.bytes_per_sector - 1)) / bpb.bpb.bytes_per_sector;
|
uint32_t root_dir_sectors =
|
||||||
|
((bpb.bpb.directories * 32) + (bpb.bpb.bytes_per_sector - 1)) / bpb.bpb.bytes_per_sector;
|
||||||
uint32_t first_data_sector = bpb.bpb.reserved_sectors + (bpb.bpb.fats * fat_size) + root_dir_sectors;
|
uint32_t first_data_sector = bpb.bpb.reserved_sectors + (bpb.bpb.fats * fat_size) + root_dir_sectors;
|
||||||
uint32_t first_fat_sector = bpb.bpb.reserved_sectors;
|
uint32_t first_fat_sector = bpb.bpb.reserved_sectors;
|
||||||
uint32_t data_sectors = total_sectors - (bpb.bpb.reserved_sectors + (bpb.bpb.fats * fat_size) + root_dir_sectors);
|
uint32_t data_sectors = total_sectors - (bpb.bpb.reserved_sectors + (bpb.bpb.fats * fat_size) + root_dir_sectors);
|
||||||
@@ -163,7 +165,8 @@ typedef struct {
|
|||||||
} table_result;
|
} table_result;
|
||||||
|
|
||||||
table_result
|
table_result
|
||||||
get_fat_table_value(uint8_t fat_type, const uint8_t *fat_table, uint32_t active_cluster, uint32_t first_fat_cluster, uint32_t sector_size) {
|
get_fat_table_value(uint8_t fat_type, const uint8_t *fat_table, uint32_t active_cluster, uint32_t first_fat_cluster,
|
||||||
|
uint32_t sector_size) {
|
||||||
uint32_t fat_offset;
|
uint32_t fat_offset;
|
||||||
table_result result = {
|
table_result result = {
|
||||||
.value = 0,
|
.value = 0,
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
#include "mbr.h"
|
#include "mbr.h"
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <drivers/ide.h>
|
#include <drivers/ide.h>
|
||||||
#include <mem/mem.h>
|
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
#include <fs/blockdev.h>
|
#include <fs/blockdev.h>
|
||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t bootable;
|
uint8_t bootable;
|
||||||
@@ -21,14 +22,14 @@ typedef struct {
|
|||||||
uint16_t ending_cylinder: 10;
|
uint16_t ending_cylinder: 10;
|
||||||
uint32_t start_lba;
|
uint32_t start_lba;
|
||||||
uint32_t num_lbas;
|
uint32_t num_lbas;
|
||||||
} __attribute((packed)) mbr_partition_table_entry;
|
} packed mbr_partition_table_entry;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t unique_id;
|
uint32_t unique_id;
|
||||||
uint16_t reserved;
|
uint16_t reserved;
|
||||||
mbr_partition_table_entry entries[4];
|
mbr_partition_table_entry entries[4];
|
||||||
uint8_t signature[2];
|
uint8_t signature[2];
|
||||||
} __attribute((packed)) mbr_table;
|
} packed mbr_table;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
const block_device *device;
|
const block_device *device;
|
||||||
|
|||||||
145
kernel/kernel.c
145
kernel/kernel.c
@@ -1,6 +1,4 @@
|
|||||||
#include <drivers/ports.h>
|
|
||||||
#include <drivers/vgascreen.h>
|
#include <drivers/vgascreen.h>
|
||||||
#include <libc/libc.h>
|
|
||||||
#include <cpu/isr.h>
|
#include <cpu/isr.h>
|
||||||
#include <cpu/timer.h>
|
#include <cpu/timer.h>
|
||||||
#include <drivers/keyboard.h>
|
#include <drivers/keyboard.h>
|
||||||
@@ -8,8 +6,6 @@
|
|||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
#include <drivers/serial.h>
|
#include <drivers/serial.h>
|
||||||
#include <kprint.h>
|
#include <kprint.h>
|
||||||
#include <libc/readline.h>
|
|
||||||
#include <libc/string.h>
|
|
||||||
#include <libk.h>
|
#include <libk.h>
|
||||||
#include <drivers/pci.h>
|
#include <drivers/pci.h>
|
||||||
#include <drivers/ide.h>
|
#include <drivers/ide.h>
|
||||||
@@ -18,118 +14,22 @@
|
|||||||
#include <fs/blockdev.h>
|
#include <fs/blockdev.h>
|
||||||
#include <fs/fat.h>
|
#include <fs/fat.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include <cpu/cpuidx.h>
|
||||||
#define BOOTLOADER_NAME_MAX_LENGTH 64
|
#include <mem/malloc.h>
|
||||||
#define CMDLINE_MAX_LENGTH 256
|
#include <tasks/task.h>
|
||||||
|
#include <syscall.h>
|
||||||
|
#include <command.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
const int version_major = 0,
|
const int version_major = 0,
|
||||||
version_minor = 0,
|
version_minor = 0,
|
||||||
version_patch = 1;
|
version_patch = 1;
|
||||||
|
|
||||||
char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH];
|
|
||||||
char cmdline[CMDLINE_MAX_LENGTH];
|
|
||||||
|
|
||||||
typedef void (*cmd_handler_func)(const char *);
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
char *cmd;
|
|
||||||
cmd_handler_func handler;
|
|
||||||
} cmd_handler;
|
|
||||||
|
|
||||||
void print(const char *arg);
|
|
||||||
|
|
||||||
void ide(const char *arg);
|
|
||||||
|
|
||||||
void echo(const char *arg);
|
|
||||||
|
|
||||||
void help(const char *arg);
|
|
||||||
|
|
||||||
cmd_handler cmd_handlers[] = {
|
|
||||||
{"help", help},
|
|
||||||
{"echo", echo},
|
|
||||||
{"print", print},
|
|
||||||
{"ide", ide},
|
|
||||||
{NULL, NULL},
|
|
||||||
};
|
|
||||||
|
|
||||||
void print_bootinfo() {
|
|
||||||
printf("Bootloader name: %s\n"
|
|
||||||
"cmdline: %s\n",
|
|
||||||
(bootloader_name[0] == 0 ? "NULL" : bootloader_name),
|
|
||||||
(cmdline[0] == 0 ? "NULL" : cmdline));
|
|
||||||
}
|
|
||||||
|
|
||||||
void help(const char *arg) {
|
|
||||||
kprint("Available commands:\n");
|
|
||||||
int index = 0;
|
|
||||||
while (true) {
|
|
||||||
if (cmd_handlers[index].cmd == NULL) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
printf("%s\n", cmd_handlers[index].cmd);
|
|
||||||
index += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void echo(const char *arg) {
|
|
||||||
printf("%s\n", arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
void print(const char *arg) {
|
|
||||||
if (strcmp(arg, "mmap") == 0) {
|
|
||||||
print_mmap_info();
|
|
||||||
} else if (strcmp(arg, "malloc") == 0) {
|
|
||||||
print_malloc_info();
|
|
||||||
} else if (strcmp(arg, "tick") == 0) {
|
|
||||||
print_current_tick();
|
|
||||||
} else if (strcmp(arg, "bootinfo") == 0) {
|
|
||||||
print_bootinfo();
|
|
||||||
} else if (strcmp(arg, "pci") == 0) {
|
|
||||||
pci_print_info();
|
|
||||||
} else if (strcmp(arg, "ide") == 0) {
|
|
||||||
ide_print_devices();
|
|
||||||
} else {
|
|
||||||
printf("Unknown print %s\n", arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ide(const char *arg) {
|
|
||||||
if (strcmp(arg, "block_devices") == 0) {
|
|
||||||
block_dev_print_info();
|
|
||||||
} else if (strcmp(arg, "ide_devices") == 0) {
|
|
||||||
ide_print_devices();
|
|
||||||
} else if (strcmp(arg, "mbr") == 0) {
|
|
||||||
mbr_read_from_ide(0);
|
|
||||||
} else {
|
|
||||||
printf("Unknown print %s\n", arg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main_loop();
|
|
||||||
|
|
||||||
void store_bootloader_info(multiboot_info_t *multiboot_info) {
|
|
||||||
// get bootloader and cmdline
|
|
||||||
if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) {
|
|
||||||
int cmdline_length = strlen((const char *) multiboot_info->cmdline);
|
|
||||||
if (cmdline_length > CMDLINE_MAX_LENGTH) {
|
|
||||||
k_panics("cmdline to long!\n");
|
|
||||||
}
|
|
||||||
memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length);
|
|
||||||
}
|
|
||||||
if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) {
|
|
||||||
int bootloader_length = strlen((const char *) multiboot_info->boot_loader_name);
|
|
||||||
if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) {
|
|
||||||
k_panics("bootloader name to long!\n");
|
|
||||||
}
|
|
||||||
memcpy(bootloader_name, (char *) multiboot_info->boot_loader_name, bootloader_length);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void init_mmap(multiboot_info_t *multiboot_info) {
|
void init_mmap(multiboot_info_t *multiboot_info) {
|
||||||
if (multiboot_info->flags & (1 << 6)) {
|
if (multiboot_info->flags & (1 << 6)) {
|
||||||
init_mmap_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
|
mmap_init_multiboot((struct multiboot_mmap_entry *) multiboot_info->mmap_addr,
|
||||||
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
|
multiboot_info->mmap_length / sizeof(struct multiboot_mmap_entry));
|
||||||
|
malloc_init();
|
||||||
// todo fallback on other mechanisms?
|
// todo fallback on other mechanisms?
|
||||||
} else {
|
} else {
|
||||||
k_panics("mmap invalid!\n");
|
k_panics("mmap invalid!\n");
|
||||||
@@ -156,7 +56,7 @@ void init_block_devices() {
|
|||||||
block_dev_scan_repeat();
|
block_dev_scan_repeat();
|
||||||
}
|
}
|
||||||
|
|
||||||
void kmain(multiboot_info_t *multiboot_info) {
|
void noreturn kmain(multiboot_info_t *multiboot_info) {
|
||||||
isr_install();
|
isr_install();
|
||||||
vga_clear_screen();
|
vga_clear_screen();
|
||||||
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
|
vga_clear_screen(' ', VGA_WHITE | (VGA_GRAY << VGA_SHIFT_BG));
|
||||||
@@ -164,6 +64,8 @@ void kmain(multiboot_info_t *multiboot_info) {
|
|||||||
serial_init();
|
serial_init();
|
||||||
kprint_register(serial_kprint);
|
kprint_register(serial_kprint);
|
||||||
|
|
||||||
|
cpuidx_print_info();
|
||||||
|
|
||||||
store_bootloader_info(multiboot_info);
|
store_bootloader_info(multiboot_info);
|
||||||
init_mmap(multiboot_info);
|
init_mmap(multiboot_info);
|
||||||
|
|
||||||
@@ -176,27 +78,6 @@ void kmain(multiboot_info_t *multiboot_info) {
|
|||||||
|
|
||||||
printf("Booted successfully v%d.%d.%d\n", version_major, version_minor, version_patch);
|
printf("Booted successfully v%d.%d.%d\n", version_major, version_minor, version_patch);
|
||||||
|
|
||||||
// enter main loop
|
task_spawn(main_loop, NULL);
|
||||||
while (true) {
|
syscall_start_scheduler();
|
||||||
main_loop();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void main_loop() {
|
|
||||||
char *msg = readline(NULL);
|
|
||||||
char *args = strchr(msg, ' ') + 1;
|
|
||||||
args[-1] = 0;
|
|
||||||
int test_index = 0;
|
|
||||||
while (true) {
|
|
||||||
if (cmd_handlers[test_index].cmd == 0) {
|
|
||||||
printf("Unknown command: %s\n", msg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) {
|
|
||||||
cmd_handlers[test_index].handler(args);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
test_index++;
|
|
||||||
}
|
|
||||||
free(msg);
|
|
||||||
}
|
}
|
||||||
@@ -15,7 +15,7 @@ int memcpy(uint8_t *dst, const uint8_t *src, int amount) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int memset(char *dst, char data, int amount) {
|
int memset(uint8_t *dst, char data, int amount) {
|
||||||
for (int i = 0; i < amount; ++i) {
|
for (int i = 0; i < amount; ++i) {
|
||||||
dst[i] = data;
|
dst[i] = data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
int memcpy(uint8_t *dst, const uint8_t *src, int amount);
|
int memcpy(uint8_t *dst, const uint8_t *src, int amount);
|
||||||
|
|
||||||
int memset(char *dst, char data, int amount);
|
int memset(uint8_t *dst, char data, int amount);
|
||||||
|
|
||||||
char *itoa(int value, char *buffer, int base);
|
char *itoa(int value, char *buffer, int base);
|
||||||
|
|
||||||
|
|||||||
@@ -6,8 +6,8 @@
|
|||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <kprint.h>
|
#include <kprint.h>
|
||||||
#include <mem/mem.h>
|
|
||||||
#include <drivers/keyboard.h>
|
#include <drivers/keyboard.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
|
||||||
#define RESULT_SIZE 256
|
#define RESULT_SIZE 256
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include "ringqueue.h"
|
#include "ringqueue.h"
|
||||||
#include <libc/libc.h>
|
#include <libc/libc.h>
|
||||||
#include <mem/mem.h>
|
#include <mem/malloc.h>
|
||||||
|
|
||||||
#define calc_pos(buffer, index) ((buffer->object_size) * (index))
|
#define calc_pos(buffer, index) ((buffer->object_size) * (index))
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ int strncmp(const char *s1, const char *s2, int n) {
|
|||||||
if (s1[i] > s2[i]) {
|
if (s1[i] > s2[i]) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
if (s2[i] < s1[i]) {
|
if (s1[i] < s2[i]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,14 @@
|
|||||||
// Created by rick on 02-02-21.
|
// Created by rick on 02-02-21.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
#include "libk.h"
|
#include "libk.h"
|
||||||
#include "kprint.h"
|
#include "kprint.h"
|
||||||
|
|
||||||
|
bool k_addr_in_kspace(void* addr) {
|
||||||
|
return addr > kernel_start && addr < kernel_end;
|
||||||
|
}
|
||||||
|
|
||||||
void k_wait_for_interrupt() {
|
void k_wait_for_interrupt() {
|
||||||
__asm__ __volatile__("hlt;");
|
__asm__ __volatile__("hlt;");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,14 @@
|
|||||||
|
|
||||||
#ifndef NEW_KERNEL_LIBK_H
|
#ifndef NEW_KERNEL_LIBK_H
|
||||||
#define NEW_KERNEL_LIBK_H
|
#define NEW_KERNEL_LIBK_H
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern void* _kernel_start;
|
||||||
|
extern void* _kernel_end;
|
||||||
|
#define kernel_start ((uint32_t)(&_kernel_start))
|
||||||
|
#define kernel_end ((uint32_t)(&_kernel_end))
|
||||||
|
|
||||||
|
bool k_addr_in_kspace(void *addr);
|
||||||
|
|
||||||
void k_wait_for_interrupt();
|
void k_wait_for_interrupt();
|
||||||
|
|
||||||
|
|||||||
90
kernel/mem/malloc.c
Normal file
90
kernel/mem/malloc.c
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <libc/kprintf.h>
|
||||||
|
#include <tasks/task.h>
|
||||||
|
#include "malloc.h"
|
||||||
|
#include "pmm.h"
|
||||||
|
|
||||||
|
#define MALLOC_TYPE_FREE 0
|
||||||
|
#define MALLOC_TYPE_USED 1
|
||||||
|
|
||||||
|
int malloc_entries = 0;
|
||||||
|
int malloc_used = 0;
|
||||||
|
|
||||||
|
typedef struct malloc_map {
|
||||||
|
struct malloc_map *next;
|
||||||
|
struct malloc_map *prev;
|
||||||
|
uint32_t size;
|
||||||
|
int type;
|
||||||
|
} malloc_map;
|
||||||
|
|
||||||
|
malloc_map *first_malloc_entry;
|
||||||
|
|
||||||
|
void malloc_init() {
|
||||||
|
first_malloc_entry = pmm_get_pages(16);
|
||||||
|
first_malloc_entry->next = first_malloc_entry;
|
||||||
|
first_malloc_entry->prev = first_malloc_entry;
|
||||||
|
first_malloc_entry->size = PAGE_SIZE * 16;
|
||||||
|
first_malloc_entry->type = MALLOC_TYPE_FREE;
|
||||||
|
malloc_entries++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void split_malloc_map(malloc_map *entry, unsigned int size) {
|
||||||
|
malloc_entries++;
|
||||||
|
malloc_map *new_entry = entry + sizeof(malloc_map) + size;
|
||||||
|
new_entry->size = entry->size - size - sizeof(malloc_map);
|
||||||
|
new_entry->next = entry->next;
|
||||||
|
new_entry->prev = entry;
|
||||||
|
new_entry->type = MALLOC_TYPE_FREE;
|
||||||
|
entry->next->prev = new_entry;
|
||||||
|
entry->next = new_entry;
|
||||||
|
entry->size = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *malloc(size_t size) {
|
||||||
|
// todo replace this horrible mess!
|
||||||
|
// this lacks any page alignment and what so ever
|
||||||
|
void* result = NULL;
|
||||||
|
task_lock_acquire();
|
||||||
|
malloc_map *current_map = first_malloc_entry;
|
||||||
|
// iterate through maps
|
||||||
|
do {
|
||||||
|
if (current_map->type == MALLOC_TYPE_USED) {
|
||||||
|
goto malloc_find_next;
|
||||||
|
}
|
||||||
|
if ((unsigned int) current_map->size < size) {
|
||||||
|
goto malloc_find_next;
|
||||||
|
}
|
||||||
|
if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) {
|
||||||
|
// big enough to split
|
||||||
|
split_malloc_map(current_map, size);
|
||||||
|
}
|
||||||
|
malloc_used++;
|
||||||
|
current_map->type = MALLOC_TYPE_USED;
|
||||||
|
result = ((void *) current_map) + sizeof(malloc_map);
|
||||||
|
break;
|
||||||
|
|
||||||
|
malloc_find_next:
|
||||||
|
current_map = current_map->next;
|
||||||
|
} while (current_map != first_malloc_entry);
|
||||||
|
task_lock_free();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void free(void *mem) {
|
||||||
|
if (mem == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
malloc_used--;
|
||||||
|
malloc_map *map = (mem - sizeof(malloc_map));
|
||||||
|
map->type = MALLOC_TYPE_FREE;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void print_malloc_info() {
|
||||||
|
printf("Malloc avail entries: %d\n"
|
||||||
|
"Malloc used entries: %d\n", malloc_entries, malloc_used);
|
||||||
|
}
|
||||||
|
|
||||||
17
kernel/mem/malloc.h
Normal file
17
kernel/mem/malloc.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_MALLOC_H
|
||||||
|
#define NEW_KERNEL_MALLOC_H
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
void malloc_init();
|
||||||
|
|
||||||
|
void print_malloc_info();
|
||||||
|
|
||||||
|
void *malloc(size_t size);
|
||||||
|
|
||||||
|
void free(void *mem);
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_MALLOC_H
|
||||||
117
kernel/mem/mem.c
117
kernel/mem/mem.c
@@ -2,9 +2,12 @@
|
|||||||
// Created by rick on 22-04-20.
|
// Created by rick on 22-04-20.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include "pmm.h"
|
||||||
#include <types.h>
|
#include <types.h>
|
||||||
#include <mem/mem.h>
|
#include <mem/mem.h>
|
||||||
#include <libc/kprintf.h>
|
#include <libc/kprintf.h>
|
||||||
|
#include <libk.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
#define MEMMAP_ENTRIES 16
|
#define MEMMAP_ENTRIES 16
|
||||||
|
|
||||||
@@ -15,26 +18,13 @@
|
|||||||
#define MMAP_TYPE_NVS 4
|
#define MMAP_TYPE_NVS 4
|
||||||
#define MMAP_TYPE_BADRAM 5
|
#define MMAP_TYPE_BADRAM 5
|
||||||
#define MMAP_TYPE_KERNEL 6
|
#define MMAP_TYPE_KERNEL 6
|
||||||
#define MMAP_TYPE_MALLOC 7
|
#define MMAP_TYPE_PAGING 7
|
||||||
|
|
||||||
#define MALLOC_TYPE_FREE 0
|
|
||||||
#define MALLOC_TYPE_USED 1
|
|
||||||
|
|
||||||
#define kilobyte (1024)
|
|
||||||
//#define kernel_start (one_meg)
|
|
||||||
#define kernel_size (32 * kilobyte)
|
|
||||||
#define kernel_end (kernel_start + kernel_size)
|
|
||||||
extern void *kernel_start;
|
|
||||||
//extern void *kernel_end;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
void *address;
|
uint32_t address;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
} __attribute((packed)) mmap_entry;
|
} packed mmap_entry;
|
||||||
|
|
||||||
int malloc_entries = 0;
|
|
||||||
int malloc_used = 0;
|
|
||||||
|
|
||||||
int last_memmap_entry = 0;
|
int last_memmap_entry = 0;
|
||||||
mmap_entry memmap[MEMMAP_ENTRIES] = {
|
mmap_entry memmap[MEMMAP_ENTRIES] = {
|
||||||
@@ -56,114 +46,51 @@ mmap_entry memmap[MEMMAP_ENTRIES] = {
|
|||||||
{0, 0, 0},
|
{0, 0, 0},
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct malloc_map {
|
|
||||||
struct malloc_map *next;
|
|
||||||
struct malloc_map *pref;
|
|
||||||
uint32_t size;
|
|
||||||
int type;
|
|
||||||
} malloc_map;
|
|
||||||
|
|
||||||
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
|
void use_mmap_entry(struct multiboot_mmap_entry *entry) {
|
||||||
mmap_entry *mm_entry = &memmap[last_memmap_entry++];
|
mmap_entry *mm_entry = &memmap[last_memmap_entry++];
|
||||||
mm_entry->address = (void *) entry->addr;
|
mm_entry->address = (void *) entry->addr;
|
||||||
mm_entry->length = entry->len;
|
mm_entry->length = entry->len;
|
||||||
mm_entry->type = entry->type;
|
mm_entry->type = entry->type;
|
||||||
if (last_memmap_entry == 1) {
|
|
||||||
// not using first map entry for now
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// check if the entry overlaps with the kernel address space
|
// check if the entry overlaps with the kernel address space
|
||||||
if (kernel_start >= mm_entry->address && kernel_start <= mm_entry->address + mm_entry->length) {
|
if (kernel_start >= mm_entry->address && kernel_start <= mm_entry->address + mm_entry->length) {
|
||||||
|
uint32_t page_after_kernel = kernel_end + PAGE_SIZE & ~(PAGE_SIZE - 1);
|
||||||
|
uint32_t kernel_size_full_pages = page_after_kernel - mm_entry->address;
|
||||||
// todo make this something proper
|
// todo make this something proper
|
||||||
struct multiboot_mmap_entry extra_entry;
|
struct multiboot_mmap_entry extra_entry;
|
||||||
extra_entry.size = entry->size;
|
extra_entry.size = entry->size;
|
||||||
extra_entry.type = entry->type;
|
extra_entry.type = entry->type;
|
||||||
extra_entry.addr = entry->addr + kernel_size;
|
extra_entry.addr = page_after_kernel;
|
||||||
extra_entry.len = entry->size - kernel_size;
|
extra_entry.len = entry->size - kernel_size_full_pages;
|
||||||
use_mmap_entry(&extra_entry);
|
use_mmap_entry(&extra_entry);
|
||||||
|
|
||||||
mm_entry->length = kernel_size;
|
mm_entry->length = kernel_size_full_pages;
|
||||||
mm_entry->type = MMAP_TYPE_KERNEL;
|
mm_entry->type = MMAP_TYPE_KERNEL;
|
||||||
}
|
}
|
||||||
if (mm_entry->type == MMAP_TYPE_AVAILABLE && (unsigned int) mm_entry->length > sizeof(malloc_map)) {
|
|
||||||
mm_entry->type = MMAP_TYPE_MALLOC;
|
|
||||||
malloc_map *map = (malloc_map *) mm_entry->address;
|
|
||||||
map->type = MALLOC_TYPE_FREE;
|
|
||||||
map->size = mm_entry->length - sizeof(malloc_map);
|
|
||||||
map->pref = map;
|
|
||||||
map->next = map;
|
|
||||||
malloc_entries++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_mmap_multiboot(struct multiboot_mmap_entry *entries, uint32_t count) {
|
void mmap_init_multiboot(struct multiboot_mmap_entry *entries, uint32_t count) {
|
||||||
for (uint32_t i = 0; i < count; ++i) {
|
for (uint32_t i = 0; i < count; ++i) {
|
||||||
use_mmap_entry(&entries[i]);
|
use_mmap_entry(&entries[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void split_malloc_map(malloc_map *entry, unsigned int size) {
|
// init page manager
|
||||||
malloc_entries++;
|
for (int i = 0; i < last_memmap_entry; ++i) {
|
||||||
malloc_map *new_entry = entry + sizeof(malloc_map) + size;
|
mmap_entry *entry = &memmap[i];
|
||||||
new_entry->size = entry->size - size - sizeof(malloc_map);
|
if (entry->type != MMAP_TYPE_AVAILABLE) {
|
||||||
new_entry->next = entry->next;
|
|
||||||
new_entry->pref = entry;
|
|
||||||
new_entry->type = MALLOC_TYPE_FREE;
|
|
||||||
entry->next->pref = new_entry;
|
|
||||||
entry->next = new_entry;
|
|
||||||
entry->size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void *malloc(size_t size) {
|
|
||||||
// todo replace this horrible mess!
|
|
||||||
// this lacks any page alignment and what so ever
|
|
||||||
for (int i = 0; i < MEMMAP_ENTRIES; ++i) {
|
|
||||||
if (memmap[i].type != MMAP_TYPE_MALLOC) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// get first first_map of address
|
if (entry->address < kernel_start) {
|
||||||
malloc_map *first_map = (malloc_map *) memmap[i].address;
|
continue; // skip for now
|
||||||
malloc_map *current_map = first_map;
|
|
||||||
// iterate through maps
|
|
||||||
do {
|
|
||||||
if (current_map->type == MALLOC_TYPE_USED) {
|
|
||||||
goto malloc_find_next;
|
|
||||||
}
|
|
||||||
if ((unsigned int) current_map->size < size) {
|
|
||||||
goto malloc_find_next;
|
|
||||||
}
|
|
||||||
if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) {
|
|
||||||
// big enough to split
|
|
||||||
split_malloc_map(current_map, size);
|
|
||||||
}
|
|
||||||
malloc_used++;
|
|
||||||
current_map->type = MALLOC_TYPE_USED;
|
|
||||||
return ((void *) current_map) + sizeof(malloc_map);
|
|
||||||
|
|
||||||
malloc_find_next:
|
|
||||||
current_map = current_map->next;
|
|
||||||
} while (current_map != first_map);
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void free(void *mem) {
|
pmm_init((void *) entry->address, entry->length);
|
||||||
if (mem == NULL) {
|
entry->type = MMAP_TYPE_PAGING;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
malloc_used--;
|
|
||||||
malloc_map *map = (mem - sizeof(malloc_map));
|
|
||||||
map->type = MALLOC_TYPE_FREE;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
void print_malloc_info() {
|
|
||||||
printf("Malloc avail entries: %d\n"
|
|
||||||
"Malloc used entries: %d\n", malloc_entries, malloc_used);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void print_mmap_info() {
|
void print_mmap_info() {
|
||||||
|
printf("Kernel start: %8x\n"
|
||||||
|
"Kernel end: %8x\n", kernel_start, kernel_end);
|
||||||
for (int i = 0; i < 16; ++i) {
|
for (int i = 0; i < 16; ++i) {
|
||||||
if (memmap[i].type == 0) {
|
if (memmap[i].type == 0) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -7,14 +7,8 @@
|
|||||||
|
|
||||||
#include <multiboot.h>
|
#include <multiboot.h>
|
||||||
|
|
||||||
void init_mmap_multiboot(struct multiboot_mmap_entry *entries, uint32_t count);
|
void mmap_init_multiboot(struct multiboot_mmap_entry *entries, uint32_t count);
|
||||||
|
|
||||||
void print_malloc_info();
|
|
||||||
|
|
||||||
void print_mmap_info();
|
void print_mmap_info();
|
||||||
|
|
||||||
void *malloc(size_t size);
|
|
||||||
|
|
||||||
void free(void *mem);
|
|
||||||
|
|
||||||
#endif //NEW_KERNEL_MEM_H
|
#endif //NEW_KERNEL_MEM_H
|
||||||
|
|||||||
98
kernel/mem/pmm.c
Normal file
98
kernel/mem/pmm.c
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <libk.h>
|
||||||
|
#include "pmm.h"
|
||||||
|
|
||||||
|
#define NUM_PAGING_INFOS 16
|
||||||
|
|
||||||
|
#define BLOCK_USED 1
|
||||||
|
#define BLOCK_FREE 0
|
||||||
|
|
||||||
|
#define bitmap_block_byte(block) ((block) / 8)
|
||||||
|
#define bitmap_block_bit(block) ((block) % 8)
|
||||||
|
|
||||||
|
#define bitmap_set(addr, block) (addr)[bitmap_block_byte(block)] = ((addr)[bitmap_block_byte(block)] | (1 << (bitmap_block_bit(block))))
|
||||||
|
#define bitmap_unset(addr, block) (addr)[bitmap_block_byte(block)] = ((addr)[bitmap_block_byte(block)] & ~(1 << (bitmap_block_bit(block))))
|
||||||
|
|
||||||
|
#define bitmap_get(addr, block) ((addr)[bitmap_block_byte(block)] >> bitmap_block_bit(block))
|
||||||
|
|
||||||
|
#define page_to_addr(base_addr, block) ((base_addr) + ((block) * PAGE_SIZE))
|
||||||
|
#define addr_to_page(base_addr, addr) (((addr) - (base_addr)) / PAGE_SIZE)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
union {
|
||||||
|
uint8_t *page_bitmap;
|
||||||
|
void *first_page;
|
||||||
|
};
|
||||||
|
uint32_t num_pages;
|
||||||
|
size_t size;
|
||||||
|
struct {
|
||||||
|
bool present: 1;
|
||||||
|
} flags;
|
||||||
|
} paging_info;
|
||||||
|
|
||||||
|
uint8_t last_paging_info = 0;
|
||||||
|
paging_info paging_infos[NUM_PAGING_INFOS];
|
||||||
|
|
||||||
|
void pmm_init(void *start_addr, size_t size) {
|
||||||
|
uint32_t num_pages = size / PAGE_SIZE;
|
||||||
|
uint32_t bitmap_size = num_pages / 8;
|
||||||
|
uint32_t bitmap_pages = bitmap_size / PAGE_SIZE;
|
||||||
|
paging_infos[last_paging_info].page_bitmap = start_addr;
|
||||||
|
paging_infos[last_paging_info].num_pages = num_pages;
|
||||||
|
paging_infos[last_paging_info].size = size;
|
||||||
|
paging_infos[last_paging_info].flags.present = true;
|
||||||
|
|
||||||
|
memset(start_addr, BLOCK_FREE, bitmap_pages);
|
||||||
|
for (uint32_t i = 0; i < bitmap_pages; ++i) {
|
||||||
|
bitmap_set((uint8_t *) start_addr, i);
|
||||||
|
}
|
||||||
|
last_paging_info++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *pmm_get_pages(uint32_t num_pages) {
|
||||||
|
for (int i = 0; i < last_paging_info; ++i) {
|
||||||
|
paging_info *info = &paging_infos[i];
|
||||||
|
if (!info->flags.present) continue;
|
||||||
|
|
||||||
|
for (uint32_t j = 0; j < info->num_pages; ++j) {
|
||||||
|
if (bitmap_get(info->page_bitmap, j) == BLOCK_FREE) {
|
||||||
|
uint32_t k;
|
||||||
|
bool usable = true;
|
||||||
|
for (k = j + 1; k < j + num_pages; ++k) {
|
||||||
|
if (bitmap_get(info->page_bitmap, k) == BLOCK_USED) {
|
||||||
|
usable = false;
|
||||||
|
j = k; // skip ahead
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!usable) break;
|
||||||
|
for (k = j; k < j + num_pages; ++k) {
|
||||||
|
bitmap_set(info->page_bitmap, k);
|
||||||
|
}
|
||||||
|
return page_to_addr(info->first_page, j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
k_panics("No page found!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pmm_free_pages(void *page, uint32_t num_pages) {
|
||||||
|
for (int i = 0; i < last_paging_info; ++i) {
|
||||||
|
paging_info *info = &paging_infos[i];
|
||||||
|
if (!info->flags.present) continue;
|
||||||
|
// check if page is in memory area
|
||||||
|
if (page < info->first_page || page > (info->first_page + info->size)) continue;
|
||||||
|
|
||||||
|
// free page
|
||||||
|
uint32_t first_page = addr_to_page(info->first_page, page);
|
||||||
|
for (uint32_t current_page = first_page; current_page < first_page + num_pages; ++current_page) {
|
||||||
|
bitmap_unset(info->page_bitmap, current_page);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
kernel/mem/pmm.h
Normal file
16
kernel/mem/pmm.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 23-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_PMM_H
|
||||||
|
#define NEW_KERNEL_PMM_H
|
||||||
|
#include <types.h>
|
||||||
|
|
||||||
|
// 4k blocks
|
||||||
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
void pmm_init(void* start_addr, size_t size);
|
||||||
|
void *pmm_get_pages(uint32_t num_pages);
|
||||||
|
void pmm_free_pages(void* page, uint32_t num_pages);
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_PMM_H
|
||||||
22
kernel/syscall.c
Normal file
22
kernel/syscall.c
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "syscall.h"
|
||||||
|
#include <types.h>
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
|
void syscall1(uint32_t arg1) {
|
||||||
|
__asm__("int $0x80"
|
||||||
|
:
|
||||||
|
: "a"(arg1));
|
||||||
|
}
|
||||||
|
|
||||||
|
void syscall_yield_job() {
|
||||||
|
syscall1(SYSCALL_YIELD_JOB);
|
||||||
|
}
|
||||||
|
|
||||||
|
void noreturn syscall_start_scheduler() {
|
||||||
|
syscall1(SYSCALL_START_SCHEDULER);
|
||||||
|
while (1) { __asm__("hlt"); };
|
||||||
|
}
|
||||||
17
kernel/syscall.h
Normal file
17
kernel/syscall.h
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_SYSCALL_H
|
||||||
|
#define NEW_KERNEL_SYSCALL_H
|
||||||
|
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
|
#define SYSCALL_START_SCHEDULER 0x01
|
||||||
|
#define SYSCALL_YIELD_JOB 0x02
|
||||||
|
|
||||||
|
void syscall_yield_job();
|
||||||
|
|
||||||
|
void noreturn syscall_start_scheduler();
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_SYSCALL_H
|
||||||
42
kernel/tasks/task.S
Normal file
42
kernel/tasks/task.S
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
.code32
|
||||||
|
|
||||||
|
.global __task_entry_point
|
||||||
|
__task_entry_point:
|
||||||
|
# Load segments
|
||||||
|
popl %eax
|
||||||
|
movw %ax,%ds
|
||||||
|
movw %ax,%es
|
||||||
|
movw %ax,%fs
|
||||||
|
movw %ax,%gs
|
||||||
|
# pop isr_registers
|
||||||
|
popa
|
||||||
|
# Remove errono etc.
|
||||||
|
addl $8,%esp # Cleans up the pushed error code and pushed ISR number
|
||||||
|
sti
|
||||||
|
# return to program
|
||||||
|
iret # pops 5 things at once: CS, EIP, EFLAGS, SS, and ESP
|
||||||
|
.global __task_entry_point_inner
|
||||||
|
__task_entry_point_inner:
|
||||||
|
add $8, %esp # Remove useresp and ss (only exists in user space)
|
||||||
|
call task_entry_point
|
||||||
|
.global switch_task
|
||||||
|
switch_task:
|
||||||
|
movl 4(%esp), %eax
|
||||||
|
movl 8(%esp), %edx
|
||||||
|
test %eax, %eax
|
||||||
|
jz _st_no_store
|
||||||
|
pushl %ebp
|
||||||
|
pushl %ebx
|
||||||
|
pushl %esi
|
||||||
|
pushl %edi
|
||||||
|
movl %esp, (%eax)
|
||||||
|
_st_no_store:
|
||||||
|
movl %edx, %esp
|
||||||
|
popl %edi
|
||||||
|
popl %esi
|
||||||
|
popl %ebx
|
||||||
|
popl %ebp
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
131
kernel/tasks/task.c
Normal file
131
kernel/tasks/task.c
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "task.h"
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <libc/libc.h>
|
||||||
|
#include <mem/malloc.h>
|
||||||
|
#include <mem/pmm.h>
|
||||||
|
|
||||||
|
#include <attributes.h>
|
||||||
|
|
||||||
|
#define stack_end(task) ((task)->stack + ((task)->stack_page_count * PAGE_SIZE))
|
||||||
|
|
||||||
|
typedef struct task {
|
||||||
|
bool present: 1;
|
||||||
|
uint8_t wait_irq: 4;
|
||||||
|
|
||||||
|
uint32_t tid;
|
||||||
|
|
||||||
|
struct task *next;
|
||||||
|
|
||||||
|
void* stack;
|
||||||
|
uint32_t stack_page_count;
|
||||||
|
|
||||||
|
task_registers_t *task_registers;
|
||||||
|
} task_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
task_registers_t task_registers;
|
||||||
|
isr_registers_t isr_registers;
|
||||||
|
task_entrypoint entrypoint;
|
||||||
|
void *entry_data;
|
||||||
|
char alignment[4];
|
||||||
|
} packed task_stack_start;
|
||||||
|
|
||||||
|
bool task_locked = false;
|
||||||
|
|
||||||
|
task_t *first_task = NULL;
|
||||||
|
task_t *last_task = NULL;
|
||||||
|
task_t *current_task = NULL;
|
||||||
|
|
||||||
|
uint32_t last_tid = 0;
|
||||||
|
|
||||||
|
extern switch_task(task_registers_t**, task_registers_t*);
|
||||||
|
extern cdecl noreturn void __task_entry_point();
|
||||||
|
extern noreturn void __task_entry_point_inner();
|
||||||
|
// explicit cdecl calling convention
|
||||||
|
void cdecl noreturn task_entry_point(task_entrypoint entrypoint, void *entry_data) {
|
||||||
|
entrypoint(entry_data);
|
||||||
|
// task_end_self();
|
||||||
|
while (true); // halt
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_lock_acquire() {
|
||||||
|
task_locked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_lock_free() {
|
||||||
|
task_locked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_switch_next_inner(task_t *next_task) {
|
||||||
|
if (task_locked) {
|
||||||
|
return; // don't switch while the task is locked
|
||||||
|
}
|
||||||
|
if (next_task == current_task) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
task_t *previous_task = current_task;
|
||||||
|
current_task = next_task;
|
||||||
|
// switch task
|
||||||
|
switch_task(previous_task == NULL ? NULL : &previous_task->task_registers, current_task->task_registers);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_start_first() {
|
||||||
|
task_switch_next_inner(first_task);
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_switch_next() {
|
||||||
|
if (current_task == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
task_switch_next_inner(current_task->next == NULL ? first_task : current_task->next);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t task_spawn(task_entrypoint entrypoint, void *entry_data) {
|
||||||
|
task_t *new_task = malloc(sizeof(task_t));
|
||||||
|
memset((uint8_t *) new_task, 0, sizeof(task_t));
|
||||||
|
new_task->tid = last_tid++;
|
||||||
|
|
||||||
|
new_task->stack = pmm_get_pages(16);
|
||||||
|
new_task->stack_page_count = 16;
|
||||||
|
// todo check for null
|
||||||
|
|
||||||
|
|
||||||
|
if (first_task == NULL) {
|
||||||
|
// first task
|
||||||
|
first_task = new_task;
|
||||||
|
} else {
|
||||||
|
last_task->next = new_task;
|
||||||
|
}
|
||||||
|
last_task = new_task;
|
||||||
|
|
||||||
|
// prepare stack
|
||||||
|
// cdecl format
|
||||||
|
task_stack_start* stack = (task_stack_start *) (stack_end(new_task) - sizeof(task_stack_start));
|
||||||
|
memset((uint8_t *) stack, 0, sizeof(task_stack_start));
|
||||||
|
// setup isr return frame
|
||||||
|
stack->isr_registers.cs = 0x08; // todo proper gdt setup
|
||||||
|
stack->isr_registers.ds = 0x10; // todo
|
||||||
|
// stack->isr_registers.ss = 0x10; // todo
|
||||||
|
|
||||||
|
stack->isr_registers.eip = (uint32_t) __task_entry_point_inner;
|
||||||
|
stack->isr_registers.eflags = 0x200;
|
||||||
|
// setup task switch frame
|
||||||
|
stack->task_registers.eip = (uint32_t) __task_entry_point;
|
||||||
|
stack->task_registers.ebp = (uint32_t) stack_end(new_task);
|
||||||
|
// setup entrypoint
|
||||||
|
stack->entrypoint = entrypoint;
|
||||||
|
stack->entry_data = entry_data;
|
||||||
|
|
||||||
|
new_task->task_registers = &stack->task_registers;
|
||||||
|
|
||||||
|
new_task->present = true;
|
||||||
|
return new_task->tid;
|
||||||
|
}
|
||||||
|
|
||||||
|
void task_end(uint32_t pid) {
|
||||||
|
}
|
||||||
24
kernel/tasks/task.h
Normal file
24
kernel/tasks/task.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// Created by rick on 22-02-21.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef NEW_KERNEL_TASK_H
|
||||||
|
#define NEW_KERNEL_TASK_H
|
||||||
|
|
||||||
|
#include <cpu/cpu.h>
|
||||||
|
|
||||||
|
typedef void (*task_entrypoint)(void *entry_data);
|
||||||
|
|
||||||
|
void task_start_first();
|
||||||
|
|
||||||
|
void task_switch_next();
|
||||||
|
|
||||||
|
uint32_t task_spawn(task_entrypoint, void *entry_data);
|
||||||
|
|
||||||
|
void task_end(uint32_t pid);
|
||||||
|
|
||||||
|
void task_lock_acquire();
|
||||||
|
|
||||||
|
void task_lock_free();
|
||||||
|
|
||||||
|
#endif //NEW_KERNEL_TASK_H
|
||||||
@@ -9,7 +9,7 @@ SECTIONS
|
|||||||
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
|
/* Begin putting sections at 1 MiB, a conventional place for kernels to be
|
||||||
loaded at by the bootloader. */
|
loaded at by the bootloader. */
|
||||||
. = 1M;
|
. = 1M;
|
||||||
kernel_start = .;
|
_kernel_start = .;
|
||||||
|
|
||||||
/* First put the multiboot header, as it is required to be put very early
|
/* First put the multiboot header, as it is required to be put very early
|
||||||
early in the image or the bootloader won't recognize the file format.
|
early in the image or the bootloader won't recognize the file format.
|
||||||
@@ -38,6 +38,7 @@ SECTIONS
|
|||||||
*(COMMON)
|
*(COMMON)
|
||||||
*(.bss)
|
*(.bss)
|
||||||
}
|
}
|
||||||
|
_kernel_end = .;
|
||||||
|
|
||||||
/DISCARD/ : {
|
/DISCARD/ : {
|
||||||
*(.eh_frame);
|
*(.eh_frame);
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -hda tmp.img -d guest_errors,int -m 1G > /dev/null &
|
nohup qemu-system-i386 -cpu max -S -s -kernel cmake-build-debug/my-kernel.bin -hda tmp.img -d guest_errors,int -m 1G > /dev/null &
|
||||||
disown
|
disown
|
||||||
|
|||||||
Reference in New Issue
Block a user