Compare commits
10 Commits
term_fix
...
458ba375f3
| Author | SHA1 | Date | |
|---|---|---|---|
|
458ba375f3
|
|||
| b920c87bab | |||
|
4fbd9b3987
|
|||
|
8aad1235c3
|
|||
|
38710653be
|
|||
|
7f997f6611
|
|||
|
7bb542d901
|
|||
|
4a90de9521
|
|||
|
c46157fad0
|
|||
| 6e633b44b7 |
6
Makefile
6
Makefile
@@ -1,8 +1,10 @@
|
|||||||
SOURCES = src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
|
SOURCES = src/boot/boot.c src/sched/scheduler.c src/sched/process.c src/mem/heap/kheap.c src/mem/paging/vmm.c src/mem/paging/paging.c src/mem/paging/pmm.c src/string/string.c src/io/kbd/ps2.c src/io/serial/serial.c src/io/term/printf.c src/io/term/term.c src/idt/idt.c src/mem/gdt/gdt.c src/mem/misc/utils.c src/time/timer.c src/kmain.c
|
||||||
|
|
||||||
|
PROBLEMATIC_FLAGS=-Wno-unused-parameter -Wno-unused-variable
|
||||||
|
|
||||||
build:
|
build:
|
||||||
rm -f *.o
|
rm -f *.o
|
||||||
x86_64-elf-gcc -g -c -Isrc $(SOURCES) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
x86_64-elf-gcc -g -c -Isrc $(SOURCES) $(PROBLEMATIC_FLAGS) -Wall -Wextra -std=gnu99 -nostdlib -ffreestanding -fno-stack-protector -fno-omit-frame-pointer -fno-stack-check -fno-PIC -ffunction-sections -fdata-sections -mcmodel=kernel
|
||||||
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
objcopy -O elf64-x86-64 -B i386 -I binary zap-light16.psf zap-light16.o
|
||||||
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
nasm -f elf64 src/idt/idt.S -o idt_stub.o
|
||||||
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
x86_64-elf-ld -o pepperk -T linker.ld *.o
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -11,18 +11,27 @@ To run it with QEMU, `make run`
|
|||||||
|
|
||||||
The basics that I'm targeting are:
|
The basics that I'm targeting are:
|
||||||
|
|
||||||
|
### Basic utility of what we call a "kernel"
|
||||||
|
|
||||||
- Fix terminal driver (backspace issues, scrolling) OR add Flanterm or equivalent
|
- Fix terminal driver (backspace issues, scrolling) OR add Flanterm or equivalent
|
||||||
- Implement paging / see what Limine does at boot with memory management
|
- Implement tasks, and task switching + context switching and spinlock acquire/release
|
||||||
- Implement tasks, and task switching
|
|
||||||
- Load an executable
|
- Load an executable
|
||||||
- Scheduler (round-robin using the PIT timer interrupt)
|
- Filesystem (TAR for read-only initfs, then maybe read-write using FAT12/16/32 or easier fs) w/ VFS layer
|
||||||
- Filesystem (TAR for read-only initfs, then maybe read-write using FAT12/16/32
|
|
||||||
- Getting to userspace (syscalls)
|
- Getting to userspace (syscalls)
|
||||||
- Porting musl libc or equivalent
|
- Porting musl libc or equivalent
|
||||||
|
|
||||||
In the future, maybe?
|
### Scalability/maintenance/expansion features
|
||||||
|
|
||||||
- SMP support
|
- Documentation
|
||||||
|
- SOME error handling in functions
|
||||||
|
- Unit tests
|
||||||
|
- Good error codes (like Linux kernel: ENOMEM, ENOENT, ...)
|
||||||
|
- Make the panic function work within itself without dependencies + error message (and still get cpu context?)
|
||||||
|
|
||||||
|
### Optional features
|
||||||
|
|
||||||
|
In the future, maybe?
|
||||||
|
- SMP support (Limine provides functionality to make this easier)
|
||||||
- Parsing the ACPI tables and using them for something
|
- Parsing the ACPI tables and using them for something
|
||||||
- Replacing the PIT timer with APIC
|
- Replacing the PIT timer with APIC
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
target remote localhost:1234
|
target remote localhost:1234
|
||||||
set disassembly-flavor intel
|
set disassembly-flavor intel
|
||||||
display/8i $rip
|
display/4i $rip
|
||||||
|
|||||||
41
src/boot/boot.c
Normal file
41
src/boot/boot.c
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Limine requests for boot
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <limine.h>
|
||||||
|
|
||||||
|
// Framebuffer request
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
volatile struct limine_framebuffer_request framebuffer_request = {
|
||||||
|
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Memory map request
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
volatile struct limine_memmap_request memmap_request = {
|
||||||
|
.id = LIMINE_MEMMAP_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Higher Half Direct Map
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
volatile struct limine_hhdm_request hhdm_request = {
|
||||||
|
.id = LIMINE_HHDM_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
// Executable Address/Kernel Address (find base phys/virt address of kernel)
|
||||||
|
__attribute__((used, section(".limine_requests")))
|
||||||
|
volatile struct limine_kernel_address_request kerneladdr_request = {
|
||||||
|
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
||||||
|
.revision = 0
|
||||||
|
};
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests_start")))
|
||||||
|
volatile LIMINE_REQUESTS_START_MARKER;
|
||||||
|
|
||||||
|
__attribute__((used, section(".limine_requests_end")))
|
||||||
|
volatile LIMINE_REQUESTS_END_MARKER;
|
||||||
37
src/config.h
Normal file
37
src/config.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PepperOS configuration file
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CONFIG_H
|
||||||
|
#define CONFIG_H
|
||||||
|
|
||||||
|
/* version */
|
||||||
|
#define PEPPEROS_VERSION_MAJOR "0"
|
||||||
|
#define PEPPEROS_VERSION_MINOR "0"
|
||||||
|
#define PEPPEROS_VERSION_PATCH "1"
|
||||||
|
#define PEPPEROS_SPLASH "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n"
|
||||||
|
|
||||||
|
/* process */
|
||||||
|
#define PROCESS_NAME_MAX 64
|
||||||
|
#define PROCESS_STACK_SIZE 0x10000 // 64kb
|
||||||
|
#define PROCESS_BASE 0x400000
|
||||||
|
#define PROCESS_STACK_BASE 0x1000000
|
||||||
|
|
||||||
|
/* sched */
|
||||||
|
// 1 tick = 1 ms => quantum = 10ms
|
||||||
|
#define SCHEDULER_QUANTUM 10
|
||||||
|
|
||||||
|
/* kernel */
|
||||||
|
#define KERNEL_BASE 0xFFFFFFFF80000000ULL
|
||||||
|
// 2 MB should be enough (as of now, the whole kernel ELF is around 75kb)
|
||||||
|
#define KERNEL_SIZE 0x200000
|
||||||
|
|
||||||
|
/* heap */
|
||||||
|
#define KHEAP_SIZE (16*1024*1024)
|
||||||
|
|
||||||
|
/* term */
|
||||||
|
#define TERM_HISTORY_MAX_LINES 256
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
; Assembly stub for the IDT
|
;
|
||||||
|
; @author xamidev <xamidev@riseup.net>
|
||||||
|
; @brief Stub for Interrupt Descriptor Table handlers
|
||||||
|
; @license GPL-3.0-only
|
||||||
|
;
|
||||||
|
|
||||||
bits 64
|
bits 64
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Interrupt Descriptor Table setup and dispatching
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include "idt.h"
|
#include "idt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -5,6 +11,8 @@
|
|||||||
#include "io/kbd/ps2.h"
|
#include "io/kbd/ps2.h"
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
#include "sched/scheduler.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
struct interrupt_descriptor idt[256];
|
struct interrupt_descriptor idt[256];
|
||||||
struct idtr idt_reg;
|
struct idtr idt_reg;
|
||||||
@@ -79,11 +87,7 @@ static void page_fault_handler(struct cpu_status_t* ctx)
|
|||||||
CHECK_BIT(ctx->error_code, 7) ? " SGX_VIOLATION" : "",
|
CHECK_BIT(ctx->error_code, 7) ? " SGX_VIOLATION" : "",
|
||||||
cr2);
|
cr2);
|
||||||
|
|
||||||
/* if (CHECK_BIT(ctx->error_code, 0))
|
panic(ctx, "page fault");
|
||||||
{
|
|
||||||
panic(ctx);
|
|
||||||
} */
|
|
||||||
panic(ctx);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gp_fault_handler(struct cpu_status_t* ctx)
|
static void gp_fault_handler(struct cpu_status_t* ctx)
|
||||||
@@ -109,7 +113,7 @@ static void gp_fault_handler(struct cpu_status_t* ctx)
|
|||||||
index);
|
index);
|
||||||
}
|
}
|
||||||
|
|
||||||
panic(ctx);
|
panic(ctx, "gp fault");
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
||||||
@@ -184,9 +188,16 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
|||||||
DEBUG("Control Protection Exception!");
|
DEBUG("Control Protection Exception!");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 32:
|
case 32: // Timer Interrupt
|
||||||
//DEBUG("Timer Interrupt");
|
|
||||||
ticks++;
|
ticks++;
|
||||||
|
|
||||||
|
if (ticks % SCHEDULER_QUANTUM == 0)
|
||||||
|
{
|
||||||
|
CLEAR_INTERRUPTS;
|
||||||
|
scheduler_schedule();
|
||||||
|
SET_INTERRUPTS;
|
||||||
|
}
|
||||||
|
|
||||||
// Send an EOI so that we can continue having interrupts
|
// Send an EOI so that we can continue having interrupts
|
||||||
outb(0x20, 0x20);
|
outb(0x20, 0x20);
|
||||||
break;
|
break;
|
||||||
@@ -202,4 +213,4 @@ struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Interrupt Descriptor Table setup and dispatching
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef IDT_H
|
#ifndef IDT_H
|
||||||
#define IDT_H
|
#define IDT_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,8 @@
|
|||||||
// PS/2 Keyboard support
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PS/2 Keyboard driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include "io/serial/serial.h"
|
#include "io/serial/serial.h"
|
||||||
#include "ps2.h"
|
#include "ps2.h"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PS/2 Keyboard driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef PS2_H
|
#ifndef PS2_H
|
||||||
#define PS2_H
|
#define PS2_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Debug serial driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include "serial.h"
|
#include "serial.h"
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Debug serial driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef SERIAL_H
|
#ifndef SERIAL_H
|
||||||
#define SERIAL_H
|
#define SERIAL_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Framebuffer-based terminal driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
// Terminal output
|
// Terminal output
|
||||||
/*
|
/*
|
||||||
There are a couple of bugs here and there but for now I don't care too much
|
There are a couple of bugs here and there but for now I don't care too much
|
||||||
@@ -10,6 +16,7 @@ because this shitty implementation will be replaced one day by Flanterm
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include "term.h"
|
#include "term.h"
|
||||||
#include "mem/misc/utils.h"
|
#include "mem/misc/utils.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
extern struct boot_context boot_ctx;
|
extern struct boot_context boot_ctx;
|
||||||
|
|
||||||
@@ -37,7 +44,7 @@ static Cursor cursor = {0, 0};
|
|||||||
static uint8_t* fb;
|
static uint8_t* fb;
|
||||||
static struct limine_framebuffer* framebuffer;
|
static struct limine_framebuffer* framebuffer;
|
||||||
|
|
||||||
uint8_t lines_length[MAX_LINES];
|
uint8_t lines_length[TERM_HISTORY_MAX_LINES];
|
||||||
|
|
||||||
static inline size_t term_max_cols(void)
|
static inline size_t term_max_cols(void)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Framebuffer-based terminal driver
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef TERM_H
|
#ifndef TERM_H
|
||||||
#define TERM_H
|
#define TERM_H
|
||||||
|
|
||||||
@@ -11,8 +17,6 @@ enum TermColors
|
|||||||
WHITE = 0xffffff
|
WHITE = 0xffffff
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_LINES 256
|
|
||||||
|
|
||||||
#define PSF1_FONT_MAGIC 0x0436
|
#define PSF1_FONT_MAGIC 0x0436
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
|
|||||||
14
src/kernel.h
14
src/kernel.h
@@ -1,10 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Kernel global macros
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef KERNEL_H
|
#ifndef KERNEL_H
|
||||||
#define KERNEL_H
|
#define KERNEL_H
|
||||||
|
|
||||||
#define PEPPEROS_VERSION_MAJOR "0"
|
|
||||||
#define PEPPEROS_VERSION_MINOR "0"
|
|
||||||
#define PEPPEROS_VERSION_PATCH "1"
|
|
||||||
|
|
||||||
enum ErrorCodes
|
enum ErrorCodes
|
||||||
{
|
{
|
||||||
ENOMEM,
|
ENOMEM,
|
||||||
@@ -20,11 +22,13 @@ enum ErrorCodes
|
|||||||
|
|
||||||
#define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__)
|
#define DEBUG(log, ...) fctprintf((void*)&skputc, 0, "debug: [%s]: " log "\r\n", __FILE__, ##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define DIE_DEBUG(str) fctprintf((void*)&skputc, 0, str)
|
||||||
|
|
||||||
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
|
#define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
|
||||||
|
|
||||||
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
|
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
|
||||||
|
|
||||||
void panic(struct cpu_status_t* ctx);
|
void panic(struct cpu_status_t* ctx, const char* str);
|
||||||
void hcf();
|
void hcf();
|
||||||
#define assert(check) do { if(!(check)) hcf(); } while(0)
|
#define assert(check) do { if(!(check)) hcf(); } while(0)
|
||||||
|
|
||||||
|
|||||||
119
src/kmain.c
119
src/kmain.c
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PepperOS kernel entry point
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
@@ -14,57 +20,35 @@
|
|||||||
#include "mem/paging/paging.h"
|
#include "mem/paging/paging.h"
|
||||||
#include "mem/paging/vmm.h"
|
#include "mem/paging/vmm.h"
|
||||||
#include "mem/heap/kheap.h"
|
#include "mem/heap/kheap.h"
|
||||||
|
#include "sched/process.h"
|
||||||
|
#include "sched/scheduler.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
// Limine version used
|
// Limine version used
|
||||||
__attribute__((used, section(".limine_requests")))
|
__attribute__((used, section(".limine_requests")))
|
||||||
static volatile LIMINE_BASE_REVISION(3);
|
volatile LIMINE_BASE_REVISION(3);
|
||||||
|
|
||||||
// Framebuffer request
|
// Halt and catch fire (makes machine stall)
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_framebuffer_request framebuffer_request = {
|
|
||||||
.id = LIMINE_FRAMEBUFFER_REQUEST,
|
|
||||||
.revision = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Memory map request
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_memmap_request memmap_request = {
|
|
||||||
.id = LIMINE_MEMMAP_REQUEST,
|
|
||||||
.revision = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Higher Half Direct Map
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_hhdm_request hhdm_request = {
|
|
||||||
.id = LIMINE_HHDM_REQUEST,
|
|
||||||
.revision = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Executable Address/Kernel Address (find base phys/virt address of kernel)
|
|
||||||
__attribute__((used, section(".limine_requests")))
|
|
||||||
static volatile struct limine_kernel_address_request kerneladdr_request = {
|
|
||||||
.id = LIMINE_KERNEL_ADDRESS_REQUEST,
|
|
||||||
.revision = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests_start")))
|
|
||||||
static volatile LIMINE_REQUESTS_START_MARKER;
|
|
||||||
|
|
||||||
__attribute__((used, section(".limine_requests_end")))
|
|
||||||
static volatile LIMINE_REQUESTS_END_MARKER;
|
|
||||||
|
|
||||||
// Panic (should dump registers etc. in the future)
|
|
||||||
void hcf()
|
void hcf()
|
||||||
{
|
{
|
||||||
for (;;)
|
CLEAR_INTERRUPTS; for (;;)asm("hlt");
|
||||||
{
|
|
||||||
asm("hlt");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void panic(struct cpu_status_t* ctx)
|
// Doing nothing (can be interrupted)
|
||||||
|
void idle() {for(;;)asm("hlt");}
|
||||||
|
|
||||||
|
void panic(struct cpu_status_t* ctx, const char* str)
|
||||||
{
|
{
|
||||||
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\nrax=%p rbx=%p rcx=%p rdx=%p\nrsi=%p rdi=%p r8=%p r9=%p\nr10=%p r11=%p r12=%p r13=%p\nr14=%p r15=%p\n\nflags=%p\nstack at rbp=%p\nHalting...",
|
CLEAR_INTERRUPTS;
|
||||||
|
if (ctx == NULL)
|
||||||
|
{
|
||||||
|
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m Something went horribly wrong! (no cpu ctx)");
|
||||||
|
DIE_DEBUG(str);
|
||||||
|
skputc('\n');
|
||||||
|
DEBUG("\x1b[38;5;231m\x1b[48;5;196mend Kernel panic - halting...\x1b[0m");
|
||||||
|
hcf();
|
||||||
|
}
|
||||||
|
DEBUG("\x1b[38;5;231m\x1b[48;5;196mKernel panic!!!\x1b[0m at rip=%p\nSomething went horribly wrong! vect=0x%.2x errcode=0x%x\n\rrax=%p rbx=%p rcx=%p rdx=%p\n\rrsi=%p rdi=%p r8=%p r9=%p\n\rr10=%p r11=%p r12=%p r13=%p\n\rr14=%p r15=%p\n\n\rflags=%p\n\rstack at rbp=%p\n\rHalting...",
|
||||||
ctx->iret_rip,
|
ctx->iret_rip,
|
||||||
ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi,
|
ctx->vector_number, ctx->error_code, ctx->rax, ctx->rbx, ctx->rcx, ctx->rdx, ctx->rsi, ctx->rdi,
|
||||||
ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags,
|
ctx->r8, ctx->r9, ctx->r10, ctx->r11, ctx->r12, ctx->r13, ctx->r14, ctx->r15, ctx->iret_flags,
|
||||||
@@ -72,10 +56,31 @@ void panic(struct cpu_status_t* ctx)
|
|||||||
hcf();
|
hcf();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* splash = "pepperOS version "PEPPEROS_VERSION_MAJOR"."PEPPEROS_VERSION_MINOR"."PEPPEROS_VERSION_PATCH"\n";
|
|
||||||
|
|
||||||
struct boot_context boot_ctx;
|
struct boot_context boot_ctx;
|
||||||
|
|
||||||
|
extern volatile struct limine_framebuffer_request framebuffer_request;
|
||||||
|
extern volatile struct limine_memmap_request memmap_request;
|
||||||
|
extern volatile struct limine_hhdm_request hhdm_request;
|
||||||
|
extern volatile struct limine_kernel_address_request kerneladdr_request;
|
||||||
|
|
||||||
|
extern struct process_t* processes_list;
|
||||||
|
extern struct process_t* current_process;
|
||||||
|
|
||||||
|
void pedicel_main(void* arg)
|
||||||
|
{
|
||||||
|
panic(NULL, "we did it!");
|
||||||
|
}
|
||||||
|
|
||||||
|
void two_main(void* arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void three_main(void* arg)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// This is our entry point
|
// This is our entry point
|
||||||
void kmain()
|
void kmain()
|
||||||
{
|
{
|
||||||
@@ -97,7 +102,6 @@ void kmain()
|
|||||||
gdt_init();
|
gdt_init();
|
||||||
idt_init();
|
idt_init();
|
||||||
timer_init();
|
timer_init();
|
||||||
SET_INTERRUPTS;
|
|
||||||
|
|
||||||
pmm_init(boot_ctx.mmap, boot_ctx.hhdm);
|
pmm_init(boot_ctx.mmap, boot_ctx.hhdm);
|
||||||
|
|
||||||
@@ -106,23 +110,20 @@ void kmain()
|
|||||||
|
|
||||||
kheap_init();
|
kheap_init();
|
||||||
|
|
||||||
void* ptr = kmalloc(10); DEBUG("(KMALLOC TEST) Allocated 10 bytes at 0x%p", ptr);
|
|
||||||
void* ptr2 = kmalloc(200); DEBUG("(KMALLOC TEST) Allocated 200 bytes at 0x%p", ptr2);
|
|
||||||
kfree(ptr);
|
|
||||||
void* ptr3 = kmalloc(5); DEBUG("(KMALLOC TEST) Allocated 5 bytes at 0x%p", ptr3);
|
|
||||||
|
|
||||||
vmm_init();
|
vmm_init();
|
||||||
|
|
||||||
|
struct process_t* pedicel = process_create("pedicel", (void*)pedicel_main, 0);
|
||||||
|
//struct process_t* two = process_create("two", (void*)two_main, 0);
|
||||||
|
//struct process_t* three = process_create("three", (void*)three_main, 0);
|
||||||
|
process_display_list(processes_list);
|
||||||
|
|
||||||
|
scheduler_init();
|
||||||
|
|
||||||
|
SET_INTERRUPTS;
|
||||||
|
|
||||||
keyboard_init(FR);
|
keyboard_init(FR);
|
||||||
|
|
||||||
term_init();
|
term_init();
|
||||||
kputs(splash);
|
kputs(PEPPEROS_SPLASH);
|
||||||
|
|
||||||
for (int i=0; i<10; i++)
|
idle();
|
||||||
{
|
|
||||||
printf("testing, attention please %d\n", i);
|
|
||||||
}
|
|
||||||
// term_scroll();
|
|
||||||
|
|
||||||
hcf();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Global Descriptor Table (for legacy reasons)
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include "gdt.h"
|
#include "gdt.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "io/serial/serial.h"
|
#include "io/serial/serial.h"
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Global Descriptor Table (for legacy reasons)
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef GDT_H
|
#ifndef GDT_H
|
||||||
#define GDT_H
|
#define GDT_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,16 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Kernel heap
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include "kheap.h"
|
#include "kheap.h"
|
||||||
#include "mem/paging/paging.h"
|
#include "mem/paging/paging.h"
|
||||||
#include "mem/paging/pmm.h"
|
#include "mem/paging/pmm.h"
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include "sched/process.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
extern uint64_t kernel_phys_base;
|
extern uint64_t kernel_phys_base;
|
||||||
extern uint64_t kernel_virt_base;
|
extern uint64_t kernel_virt_base;
|
||||||
@@ -15,12 +23,24 @@ static uintptr_t end;
|
|||||||
// Kernel root table (level 4)
|
// Kernel root table (level 4)
|
||||||
extern uint64_t *kernel_pml4;
|
extern uint64_t *kernel_pml4;
|
||||||
|
|
||||||
static void kheap_map_page()
|
static void kheap_grow(size_t size)
|
||||||
|
{
|
||||||
|
size_t pages = ALIGN_UP(size + sizeof(struct heap_block_t), PAGE_SIZE) / PAGE_SIZE;
|
||||||
|
|
||||||
|
if (pages == 0) pages = 1;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pages; i++)
|
||||||
|
{
|
||||||
|
kheap_map_page();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void kheap_map_page()
|
||||||
{
|
{
|
||||||
uintptr_t phys = pmm_alloc();
|
uintptr_t phys = pmm_alloc();
|
||||||
paging_map_page(kernel_pml4, end, phys, PTE_PRESENT | PTE_WRITABLE | PTE_NOEXEC);
|
paging_map_page(kernel_pml4, end, phys, PTE_PRESENT | PTE_WRITABLE | PTE_NOEXEC);
|
||||||
end += PAGE_SIZE;
|
end += PAGE_SIZE;
|
||||||
DEBUG("Mapped first kheap page");
|
//DEBUG("Mapped first kheap page");
|
||||||
}
|
}
|
||||||
|
|
||||||
void kheap_init()
|
void kheap_init()
|
||||||
@@ -43,6 +63,7 @@ void* kmalloc(size_t size)
|
|||||||
{
|
{
|
||||||
// No size, no memory allocated!
|
// No size, no memory allocated!
|
||||||
if (!size) return NULL;
|
if (!size) return NULL;
|
||||||
|
size = ALIGN(size);
|
||||||
|
|
||||||
struct heap_block_t* curr = head;
|
struct heap_block_t* curr = head;
|
||||||
|
|
||||||
@@ -52,17 +73,16 @@ void* kmalloc(size_t size)
|
|||||||
if (curr->free && curr->size >= size)
|
if (curr->free && curr->size >= size)
|
||||||
{
|
{
|
||||||
// We split the block if it is big enough
|
// We split the block if it is big enough
|
||||||
if (curr->size > size + sizeof(struct heap_block_t))
|
if (curr->size >= size + BLOCK_MIN_SIZE)
|
||||||
{
|
{
|
||||||
struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size);
|
//struct heap_block_t* new_block = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size);
|
||||||
// We have to subtract the size of our block struct
|
struct heap_block_t* split = (struct heap_block_t*)((uintptr_t)curr + sizeof(*curr) + size);
|
||||||
new_block->size = curr->size - size - sizeof(struct heap_block_t);
|
|
||||||
new_block->free = true;
|
split->size = curr->size - size - sizeof(*curr);
|
||||||
|
split->free = true;
|
||||||
// Then we chain up the block in the list
|
split->next = curr->next;
|
||||||
new_block->next = curr->next;
|
|
||||||
curr->next = new_block;
|
|
||||||
|
|
||||||
|
curr->next = split;
|
||||||
curr->size = size;
|
curr->size = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,14 +94,14 @@ void* kmalloc(size_t size)
|
|||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're hear it means we didn't have enough memory
|
// If we're here it means we didn't have enough memory
|
||||||
// for the block allocation. So we will allocate more..
|
// for the block allocation. So we will allocate more..
|
||||||
uintptr_t old_end = end;
|
uintptr_t old_end = end;
|
||||||
kheap_map_page();
|
kheap_grow(size + sizeof(struct heap_block_t));
|
||||||
|
|
||||||
struct heap_block_t* block = (struct heap_block_t*)old_end;
|
struct heap_block_t* block = (struct heap_block_t*)old_end;
|
||||||
block->size = PAGE_SIZE - sizeof(struct heap_block_t);
|
block->size = ALIGN_UP(end - old_end - sizeof(struct heap_block_t), 16);
|
||||||
block->free = false;
|
block->free = true;
|
||||||
block->next = NULL;
|
block->next = NULL;
|
||||||
|
|
||||||
// Put the block at the end of the list
|
// Put the block at the end of the list
|
||||||
@@ -92,7 +112,7 @@ void* kmalloc(size_t size)
|
|||||||
}
|
}
|
||||||
curr->next = block;
|
curr->next = block;
|
||||||
|
|
||||||
return (void*)((uintptr_t)block + sizeof(struct heap_block_t));
|
return kmalloc(size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void kfree(void* ptr)
|
void kfree(void* ptr)
|
||||||
@@ -103,4 +123,25 @@ void kfree(void* ptr)
|
|||||||
// Set it free!
|
// Set it free!
|
||||||
struct heap_block_t* block = (struct heap_block_t*)((uintptr_t)ptr - sizeof(struct heap_block_t));
|
struct heap_block_t* block = (struct heap_block_t*)((uintptr_t)ptr - sizeof(struct heap_block_t));
|
||||||
block->free = true;
|
block->free = true;
|
||||||
|
|
||||||
|
// merge adjacent free blocks (coalescing)
|
||||||
|
struct heap_block_t* curr = head;
|
||||||
|
while (curr && curr->next)
|
||||||
|
{
|
||||||
|
if (curr->free && curr->next->free)
|
||||||
|
{
|
||||||
|
curr->size += sizeof(*curr) + curr->next->size;
|
||||||
|
curr->next = curr->next->next;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
curr = curr->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should alloc enough for a stack (at least 64kb) to be used for a process.
|
||||||
|
// Should return a pointer to top of the stack (as stack grows DOWNWARDS)
|
||||||
|
void* kalloc_stack()
|
||||||
|
{
|
||||||
|
uint8_t* ptr = kmalloc(PROCESS_STACK_SIZE);
|
||||||
|
return ptr ? ptr+PROCESS_STACK_SIZE : NULL;
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Kernel heap
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef KHEAP_H
|
#ifndef KHEAP_H
|
||||||
#define KHEAP_H
|
#define KHEAP_H
|
||||||
|
|
||||||
@@ -6,9 +12,6 @@
|
|||||||
// When the kernel heap is ready, we can alloc our VM object linked list
|
// When the kernel heap is ready, we can alloc our VM object linked list
|
||||||
// and then continue working on the VMM.
|
// and then continue working on the VMM.
|
||||||
|
|
||||||
// 16MB should be enough for some linked lists
|
|
||||||
#define KHEAP_SIZE (16*1024*1024)
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
@@ -22,5 +25,7 @@ struct heap_block_t
|
|||||||
void kheap_init();
|
void kheap_init();
|
||||||
void* kmalloc(size_t size);
|
void* kmalloc(size_t size);
|
||||||
void kfree(void* ptr);
|
void kfree(void* ptr);
|
||||||
|
void* kalloc_stack();
|
||||||
|
void kheap_map_page();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Common memory utilities
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Common memory utilities
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef MEM_UTILS_H
|
#ifndef MEM_UTILS_H
|
||||||
#define MEM_UTILS_H
|
#define MEM_UTILS_H
|
||||||
|
|
||||||
@@ -8,6 +14,7 @@ void* memset(void* s, int c, size_t n);
|
|||||||
void* memmove(void *dest, const void* src, size_t n);
|
void* memmove(void *dest, const void* src, size_t n);
|
||||||
int memcmp(const void* s1, const void* s2, size_t n);
|
int memcmp(const void* s1, const void* s2, size_t n);
|
||||||
|
|
||||||
|
// DEBUG
|
||||||
void memmap_display(struct limine_memmap_response* response);
|
void memmap_display(struct limine_memmap_response* response);
|
||||||
void hhdm_display(struct limine_hhdm_response* hhdm);
|
void hhdm_display(struct limine_hhdm_response* hhdm);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief x64 4-level paging implementation
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include "paging.h"
|
#include "paging.h"
|
||||||
#include "pmm.h"
|
#include "pmm.h"
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Paging on x86 uses four different page table levels:
|
Paging on x86 uses four different page table levels:
|
||||||
@@ -69,7 +76,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_
|
|||||||
root_table[pml4_i] = VIRT_TO_PHYS(pdpt) | PTE_PRESENT | PTE_WRITABLE;
|
root_table[pml4_i] = VIRT_TO_PHYS(pdpt) | PTE_PRESENT | PTE_WRITABLE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pdpt = (uint64_t *)PHYS_TO_VIRT(root_table[pml4_i] & ~0xFFFULL);
|
pdpt = (uint64_t *)PHYS_TO_VIRT(root_table[pml4_i] & PTE_ADDR_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PDPT: same here
|
// PDPT: same here
|
||||||
@@ -79,7 +86,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_
|
|||||||
pdpt[pdpt_i] = VIRT_TO_PHYS(pd) | PTE_PRESENT | PTE_WRITABLE;
|
pdpt[pdpt_i] = VIRT_TO_PHYS(pd) | PTE_PRESENT | PTE_WRITABLE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pd = (uint64_t *)PHYS_TO_VIRT(pdpt[pdpt_i] & ~0xFFFULL);
|
pd = (uint64_t *)PHYS_TO_VIRT(pdpt[pdpt_i] & PTE_ADDR_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PD: and here
|
// PD: and here
|
||||||
@@ -89,7 +96,7 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_
|
|||||||
pd[pd_i] = VIRT_TO_PHYS(pt) | PTE_PRESENT | PTE_WRITABLE;
|
pd[pd_i] = VIRT_TO_PHYS(pt) | PTE_PRESENT | PTE_WRITABLE;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
pt = (uint64_t *)PHYS_TO_VIRT(pd[pd_i] & ~0xFFFULL);
|
pt = (uint64_t *)PHYS_TO_VIRT(pd[pd_i] & PTE_ADDR_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
// PT: finally, populate the page table entry
|
// PT: finally, populate the page table entry
|
||||||
@@ -102,13 +109,16 @@ void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_
|
|||||||
uint64_t kernel_phys_base;
|
uint64_t kernel_phys_base;
|
||||||
uint64_t kernel_virt_base;
|
uint64_t kernel_virt_base;
|
||||||
|
|
||||||
void paging_init(struct limine_kernel_address_response* kaddr, struct limine_framebuffer* fb)
|
extern struct boot_context boot_ctx;
|
||||||
|
|
||||||
|
void paging_init()
|
||||||
{
|
{
|
||||||
// We should map the kernel, GDT, IDT, stack, framebuffer.
|
// We should map the kernel, GDT, IDT, stack, framebuffer.
|
||||||
// Optionally we could map ACPI tables (we can find them in the Limine memmap)
|
// Optionally we could map ACPI tables (we can find them in the Limine memmap)
|
||||||
|
|
||||||
kernel_phys_base = kaddr->physical_base;
|
kernel_phys_base = boot_ctx.kaddr->physical_base;
|
||||||
kernel_virt_base = kaddr->virtual_base;
|
kernel_virt_base = boot_ctx.kaddr->virtual_base;
|
||||||
|
struct limine_framebuffer* fb = boot_ctx.fb;
|
||||||
|
|
||||||
DEBUG("Kernel lives at virt=0x%p phys=0x%p", kernel_virt_base, kernel_phys_base);
|
DEBUG("Kernel lives at virt=0x%p phys=0x%p", kernel_virt_base, kernel_phys_base);
|
||||||
|
|
||||||
@@ -117,14 +127,38 @@ void paging_init(struct limine_kernel_address_response* kaddr, struct limine_fra
|
|||||||
// for debug
|
// for debug
|
||||||
uint64_t page_count = 0;
|
uint64_t page_count = 0;
|
||||||
|
|
||||||
// HHDM map first 1 GB using given offset
|
// Find max physical address from limine memmap
|
||||||
for (uint64_t i=0; i<0x40000000; i += PAGE_SIZE)
|
uint64_t max_phys = 0;
|
||||||
|
for (uint64_t i=0; i<boot_ctx.mmap->entry_count; i++)
|
||||||
|
{
|
||||||
|
struct limine_memmap_entry* entry = boot_ctx.mmap->entries[i];
|
||||||
|
if (entry->length == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint64_t top = entry->base + entry->length;
|
||||||
|
if (top > max_phys)
|
||||||
|
{
|
||||||
|
max_phys = top;
|
||||||
|
}
|
||||||
|
//DEBUG("max_phys=0x%p", max_phys);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4GB
|
||||||
|
if (max_phys > 0x100000000)
|
||||||
|
{
|
||||||
|
DEBUG("WARNING: max_phys capped to 4GB (0x100000000) (from max_phys=%p)", max_phys);
|
||||||
|
max_phys = 0x100000000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// HHDM map up to max_phys or 4GB, whichever is smaller, using given offset
|
||||||
|
for (uint64_t i=0; i<max_phys; i += PAGE_SIZE)
|
||||||
{
|
{
|
||||||
//paging_kmap_page(i+hhdm_off, i, PTE_WRITABLE);
|
//paging_kmap_page(i+hhdm_off, i, PTE_WRITABLE);
|
||||||
paging_map_page(kernel_pml4, i+hhdm_off, i, PTE_WRITABLE);
|
paging_map_page(kernel_pml4, i+hhdm_off, i, PTE_WRITABLE | PTE_PRESENT);
|
||||||
page_count++;
|
page_count++;
|
||||||
}
|
}
|
||||||
DEBUG("Mapped %u pages for first 1GB (HHDM)", page_count); page_count = 0;
|
DEBUG("Mapped %u pages up to 0x%p (HHDM)", page_count, max_phys); page_count = 0;
|
||||||
|
|
||||||
// Map the kernel (according to virt/phys_base given by Limine)
|
// Map the kernel (according to virt/phys_base given by Limine)
|
||||||
// SOME DAY when we want a safer kernel we should map .text as Read/Exec
|
// SOME DAY when we want a safer kernel we should map .text as Read/Exec
|
||||||
|
|||||||
@@ -1,13 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief x64 4-level paging implementation
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef PAGING_H
|
#ifndef PAGING_H
|
||||||
#define PAGING_H
|
#define PAGING_H
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
#define BITS_PER_ROW 64
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <limine.h>
|
#include <limine.h>
|
||||||
|
#include "mem/heap/kheap.h"
|
||||||
|
|
||||||
void paging_init(struct limine_kernel_address_response* kaddr, struct limine_framebuffer* fb);
|
void paging_init();
|
||||||
void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_t flags);
|
void paging_map_page(uint64_t* root_table, uint64_t virt, uint64_t phys, uint64_t flags);
|
||||||
|
|
||||||
extern uint64_t hhdm_off;
|
extern uint64_t hhdm_off;
|
||||||
@@ -15,10 +21,14 @@ extern uint64_t hhdm_off;
|
|||||||
#define PHYS_TO_VIRT(x) ((void*)((uintptr_t)(x) + hhdm_off))
|
#define PHYS_TO_VIRT(x) ((void*)((uintptr_t)(x) + hhdm_off))
|
||||||
#define VIRT_TO_PHYS(x) ((uintptr_t)(x) - hhdm_off)
|
#define VIRT_TO_PHYS(x) ((uintptr_t)(x) - hhdm_off)
|
||||||
|
|
||||||
|
#define PTE_ADDR_MASK 0x000FFFFFFFFFF000
|
||||||
// Stole it
|
// Stole it
|
||||||
#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
|
#define ALIGN_UP(x, align) (((x) + ((align) - 1)) & ~((align) - 1))
|
||||||
#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
|
#define ALIGN_DOWN(x, align) ((x) & ~((align) - 1))
|
||||||
#define PAGE_ALIGN_DOWN(x) ((x) & ~0xFFFULL)
|
#define PAGE_ALIGN_DOWN(x) ((x) & PTE_ADDR_MASK)
|
||||||
|
|
||||||
|
#define ALIGN(size) ALIGN_UP(size, 16)
|
||||||
|
#define BLOCK_MIN_SIZE (sizeof(struct heap_block_t) + 16)
|
||||||
|
|
||||||
#define PML4_INDEX(x) (((x) >> 39) & 0x1FF)
|
#define PML4_INDEX(x) (((x) >> 39) & 0x1FF)
|
||||||
#define PDPT_INDEX(x) (((x) >> 30) & 0x1FF)
|
#define PDPT_INDEX(x) (((x) >> 30) & 0x1FF)
|
||||||
@@ -35,10 +45,4 @@ extern uint64_t hhdm_off;
|
|||||||
#define PTE_HUGE (1ULL << 7)
|
#define PTE_HUGE (1ULL << 7)
|
||||||
#define PTE_NOEXEC (1ULL << 63)
|
#define PTE_NOEXEC (1ULL << 63)
|
||||||
|
|
||||||
// Specified in linker.ld
|
|
||||||
#define KERNEL_BASE 0xFFFFFFFF80000000ULL
|
|
||||||
|
|
||||||
// 2 MB should be enough (as of now, the whole kernel ELF is around 75kb)
|
|
||||||
#define KERNEL_SIZE 0x200000
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,4 +1,8 @@
|
|||||||
// OMG here we are. I'm cooked.
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Physical memory manager from freelist
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pmm - Physical Memory Manager
|
pmm - Physical Memory Manager
|
||||||
@@ -62,7 +66,10 @@ static uintptr_t g_freelist = 0;
|
|||||||
|
|
||||||
uintptr_t pmm_alloc()
|
uintptr_t pmm_alloc()
|
||||||
{
|
{
|
||||||
if (!g_freelist) return 0;
|
if (!g_freelist)
|
||||||
|
{
|
||||||
|
panic(NULL, "PMM is out of memory!");
|
||||||
|
}
|
||||||
uintptr_t addr = g_freelist;
|
uintptr_t addr = g_freelist;
|
||||||
g_freelist = *(uintptr_t*) PHYS_TO_VIRT(g_freelist);
|
g_freelist = *(uintptr_t*) PHYS_TO_VIRT(g_freelist);
|
||||||
return addr;
|
return addr;
|
||||||
@@ -100,4 +107,4 @@ void pmm_init(struct limine_memmap_response* memmap, struct limine_hhdm_response
|
|||||||
// Now we have biggest USABLE region,
|
// Now we have biggest USABLE region,
|
||||||
// so to populate the free list we just iterate through it
|
// so to populate the free list we just iterate through it
|
||||||
pmm_init_freelist();
|
pmm_init_freelist();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Physical memory manager from freelist
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef PAGING_PMM_H
|
#ifndef PAGING_PMM_H
|
||||||
#define PAGING_PMM_H
|
#define PAGING_PMM_H
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Virtual memory manager
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The VMM (virtual memory manager) will have two roles:
|
The VMM (virtual memory manager) will have two roles:
|
||||||
- mapping pages
|
- mapping pages
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Virtual memory manager
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef VMM_H
|
#ifndef VMM_H
|
||||||
#define VMM_H
|
#define VMM_H
|
||||||
|
|
||||||
|
|||||||
129
src/sched/process.c
Normal file
129
src/sched/process.c
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Process linked list implementation
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "process.h"
|
||||||
|
#include "mem/heap/kheap.h"
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "string/string.h"
|
||||||
|
#include "mem/gdt/gdt.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
struct process_t* processes_list;
|
||||||
|
struct process_t* current_process;
|
||||||
|
|
||||||
|
size_t next_free_pid = 0;
|
||||||
|
|
||||||
|
void process_init()
|
||||||
|
{
|
||||||
|
processes_list = NULL;
|
||||||
|
current_process = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for debug
|
||||||
|
void process_display_list(struct process_t* processes_list)
|
||||||
|
{
|
||||||
|
int process_view_id = 0;
|
||||||
|
struct process_t* tmp = processes_list;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
DEBUG("{%d: %p} -> ", process_view_id, tmp);
|
||||||
|
tmp = tmp->next;
|
||||||
|
process_view_id++;
|
||||||
|
}
|
||||||
|
DEBUG("NULL");
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_t* process_create(char* name, void(*function)(void*), void* arg)
|
||||||
|
{
|
||||||
|
CLEAR_INTERRUPTS;
|
||||||
|
struct process_t* proc = (struct process_t*)kmalloc(sizeof(struct process_t));
|
||||||
|
|
||||||
|
struct cpu_status_t* ctx = (struct cpu_status_t*)kmalloc(sizeof(struct cpu_status_t));
|
||||||
|
|
||||||
|
// No more memory?
|
||||||
|
if (!proc) return NULL;
|
||||||
|
if (!ctx) return NULL;
|
||||||
|
|
||||||
|
strncpy(proc->name, name, PROCESS_NAME_MAX);
|
||||||
|
proc->pid = next_free_pid++;
|
||||||
|
proc->status = READY;
|
||||||
|
|
||||||
|
proc->context = ctx;
|
||||||
|
proc->context->iret_ss = KERNEL_DATA_SEGMENT; // process will live in kernel mode
|
||||||
|
proc->context->iret_rsp = (uint64_t)kalloc_stack();
|
||||||
|
proc->context->iret_flags = 0x202; //bit 2 and 9 set (Interrupt Flag)
|
||||||
|
proc->context->iret_cs = KERNEL_CODE_SEGMENT;
|
||||||
|
proc->context->iret_rip = (uint64_t)function; // beginning of executable code
|
||||||
|
proc->context->rdi = (uint64_t)arg; // 1st arg is in rdi (as per x64 calling convention)
|
||||||
|
proc->context->rbp = 0;
|
||||||
|
|
||||||
|
proc->next = 0;
|
||||||
|
|
||||||
|
process_add(&processes_list, proc);
|
||||||
|
|
||||||
|
SET_INTERRUPTS;
|
||||||
|
return proc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_add(struct process_t** processes_list, struct process_t* process)
|
||||||
|
{
|
||||||
|
if (!process) return;
|
||||||
|
process->next = NULL;
|
||||||
|
|
||||||
|
if (*processes_list == NULL)
|
||||||
|
{
|
||||||
|
// List is empty
|
||||||
|
*processes_list = process;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_t* tmp = *processes_list;
|
||||||
|
while (tmp->next != NULL)
|
||||||
|
{
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
// We're at last process before NULL
|
||||||
|
tmp->next = process;
|
||||||
|
// process->next = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_delete(struct process_t** processes_list, struct process_t* process)
|
||||||
|
{
|
||||||
|
if (!processes_list || !*processes_list || !process) return;
|
||||||
|
|
||||||
|
if (*processes_list == process)
|
||||||
|
{
|
||||||
|
// process to delete is at head
|
||||||
|
*processes_list = process->next;
|
||||||
|
process->next = NULL;
|
||||||
|
kfree(process);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_t* tmp = *processes_list;
|
||||||
|
while (tmp->next && tmp->next != process)
|
||||||
|
{
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp->next == NULL)
|
||||||
|
{
|
||||||
|
// Didn't find the process
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We're at process before the one we want to delete
|
||||||
|
tmp->next = process->next;
|
||||||
|
process->next = NULL;
|
||||||
|
kfree(process);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct process_t* process_get_next(struct process_t* process)
|
||||||
|
{
|
||||||
|
if (!process) return NULL;
|
||||||
|
return process->next;
|
||||||
|
}
|
||||||
39
src/sched/process.h
Normal file
39
src/sched/process.h
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Process definition
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef PROCESS_H
|
||||||
|
#define PROCESS_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
READY,
|
||||||
|
RUNNING,
|
||||||
|
DEAD
|
||||||
|
} status_t;
|
||||||
|
|
||||||
|
struct process_t
|
||||||
|
{
|
||||||
|
size_t pid;
|
||||||
|
char name[PROCESS_NAME_MAX];
|
||||||
|
|
||||||
|
status_t status;
|
||||||
|
struct cpu_status_t* context;
|
||||||
|
void* root_page_table; // Process PML4 (should contain kernel PML4 in higher half [256-511]
|
||||||
|
struct process_t* next;
|
||||||
|
};
|
||||||
|
|
||||||
|
void process_init();
|
||||||
|
struct process_t* process_create(char* name, void(*function)(void*), void* arg);
|
||||||
|
void process_add(struct process_t** processes_list, struct process_t* process);
|
||||||
|
void process_delete(struct process_t** processes_list, struct process_t* process);
|
||||||
|
struct process_t* process_get_next(struct process_t* process);
|
||||||
|
|
||||||
|
void process_display_list(struct process_t* processes_list);
|
||||||
|
|
||||||
|
#endif
|
||||||
46
src/sched/scheduler.c
Normal file
46
src/sched/scheduler.c
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Round-robin scheduler
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "kernel.h"
|
||||||
|
#include "process.h"
|
||||||
|
|
||||||
|
extern struct process_t* processes_list;
|
||||||
|
extern struct process_t* current_process;
|
||||||
|
|
||||||
|
void scheduler_init()
|
||||||
|
{
|
||||||
|
// Choose first process?
|
||||||
|
current_process = processes_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
||||||
|
{
|
||||||
|
current_process->context = context;
|
||||||
|
current_process->status = READY;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
struct process_t* prev_process = current_process;
|
||||||
|
if (current_process->next != NULL)
|
||||||
|
{
|
||||||
|
current_process = current_process->next;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
current_process = processes_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current_process != NULL && current_process->status == DEAD)
|
||||||
|
{
|
||||||
|
process_delete(&prev_process, current_process);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
current_process->status = RUNNING;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DEBUG("current_process={pid=%u name='%s'}", current_process->pid, current_process->name);
|
||||||
|
return current_process->context;
|
||||||
|
}
|
||||||
13
src/sched/scheduler.h
Normal file
13
src/sched/scheduler.h
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Round-robin scheduler
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SCHEDULER_H
|
||||||
|
#define SCHEDULER_H
|
||||||
|
|
||||||
|
void scheduler_schedule();
|
||||||
|
void scheduler_init();
|
||||||
|
|
||||||
|
#endif
|
||||||
7
src/sched/task.S
Normal file
7
src/sched/task.S
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
; Task (process) switching
|
||||||
|
|
||||||
|
bits 64
|
||||||
|
|
||||||
|
global switch_to_task
|
||||||
|
switch_to_task:
|
||||||
|
|
||||||
@@ -1,6 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief String manipulation utilities
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
char* strcpy(char *dest, const char *src)
|
char* strcpy(char *dest, const char *src)
|
||||||
{
|
{
|
||||||
char *temp = dest;
|
char *temp = dest;
|
||||||
while((*dest++ = *src++));
|
while((*dest++ = *src++));
|
||||||
return temp;
|
return temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/2488563/strcat-implementation
|
||||||
|
char *strcat(char *dest, const char *src){
|
||||||
|
size_t i,j;
|
||||||
|
for (i = 0; dest[i] != '\0'; i++)
|
||||||
|
;
|
||||||
|
for (j = 0; src[j] != '\0'; j++)
|
||||||
|
dest[i+j] = src[j];
|
||||||
|
dest[i+j] = '\0';
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/14159625/implementation-of-strncpy
|
||||||
|
void strncpy(char* dst, const char* src, size_t n)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while(i++ != n && (*dst++ = *src++));
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,14 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief String manipulation functions
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef STRING_H
|
#ifndef STRING_H
|
||||||
#define STRING_H
|
#define STRING_H
|
||||||
|
|
||||||
char *strcpy(char *dest, const char *src);
|
char *strcpy(char *dest, const char *src);
|
||||||
|
char *strcat(char *dest, const char *src);
|
||||||
|
void strncpy(char* dst, const char* src, size_t n);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief Programmable Interval Timer init and enabling
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "io/serial/serial.h"
|
#include "io/serial/serial.h"
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
/*
|
||||||
|
* @author xamidev <xamidev@riseup.net>
|
||||||
|
* @brief PIT functions
|
||||||
|
* @license GPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
#ifndef TIMER_H
|
#ifndef TIMER_H
|
||||||
#define TIMER_H
|
#define TIMER_H
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user