Compare commits
3 Commits
e8a0a36889
...
d644126901
| Author | SHA1 | Date | |
|---|---|---|---|
|
d644126901
|
|||
|
8be2a744b4
|
|||
|
e9b57f70b1
|
+14
-1
@@ -13,19 +13,32 @@
|
|||||||
// we'll only use this as a requirement for paging, not more.
|
// we'll only use this as a requirement for paging, not more.
|
||||||
// This means base 0 and no limit (whole address space)
|
// This means base 0 and no limit (whole address space)
|
||||||
|
|
||||||
#define NUM_GDT_ENTRIES 5
|
#define NUM_GDT_ENTRIES 7
|
||||||
|
|
||||||
#define NULL_SELECTOR 0x00
|
#define NULL_SELECTOR 0x00
|
||||||
#define KERNEL_CODE_SEGMENT 0x08
|
#define KERNEL_CODE_SEGMENT 0x08
|
||||||
#define KERNEL_DATA_SEGMENT 0x10
|
#define KERNEL_DATA_SEGMENT 0x10
|
||||||
#define USER_CODE_SEGMENT 0x18
|
#define USER_CODE_SEGMENT 0x18
|
||||||
#define USER_DATA_SEGMENT 0x20
|
#define USER_DATA_SEGMENT 0x20
|
||||||
|
#define TSS_SEGMENT 0x28
|
||||||
|
|
||||||
struct GDTR {
|
struct GDTR {
|
||||||
uint16_t limit;
|
uint16_t limit;
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct tss {
|
||||||
|
uint32_t reserved0;
|
||||||
|
uint64_t rsp0;
|
||||||
|
uint64_t rsp1;
|
||||||
|
uint64_t rsp2;
|
||||||
|
uint64_t reserved1;
|
||||||
|
uint64_t ist[7];
|
||||||
|
uint64_t reserved2;
|
||||||
|
uint16_t reserved3;
|
||||||
|
uint16_t iopb;
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
void gdt_init(void);
|
void gdt_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+2
-2
@@ -36,7 +36,7 @@ struct idtr {
|
|||||||
// All general-purpose registers (except rsp) as stored on the stack,
|
// All general-purpose registers (except rsp) as stored on the stack,
|
||||||
// plus the values we pushed (vector number, error code) and the iret frame
|
// plus the values we pushed (vector number, error code) and the iret frame
|
||||||
// In reverse order because the stack grows downwards.
|
// In reverse order because the stack grows downwards.
|
||||||
struct cpu_status_t {
|
struct cpu_status {
|
||||||
uint64_t r15;
|
uint64_t r15;
|
||||||
uint64_t r14;
|
uint64_t r14;
|
||||||
uint64_t r13;
|
uint64_t r13;
|
||||||
@@ -63,6 +63,6 @@ struct cpu_status_t {
|
|||||||
uint64_t iret_ss;
|
uint64_t iret_ss;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cpu_status_t* syscall_handler(struct cpu_status_t* regs);
|
struct cpu_status* syscall_handler(struct cpu_status* regs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+1
-1
@@ -35,7 +35,7 @@ extern volatile uint64_t ticks;
|
|||||||
|
|
||||||
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
|
// printf("debug: [%s]: " log "\n", __FILE__, ##__VA_ARGS__);
|
||||||
|
|
||||||
void panic(struct cpu_status_t* ctx, const char* str);
|
void panic(struct cpu_status* ctx, const char* str);
|
||||||
void hcf(void);
|
void hcf(void);
|
||||||
void idle(void);
|
void idle(void);
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -16,11 +16,11 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct heap_block_t {
|
struct heap_block {
|
||||||
size_t size;
|
size_t size;
|
||||||
bool free; // 1byte
|
bool free; // 1byte
|
||||||
uint8_t reserved[7]; // (7+1 = 8 bytes)
|
uint8_t reserved[7]; // (7+1 = 8 bytes)
|
||||||
struct heap_block_t* next;
|
struct heap_block* next;
|
||||||
} __attribute__((aligned(16)));
|
} __attribute__((aligned(16)));
|
||||||
|
|
||||||
void kheap_init(void);
|
void kheap_init(void);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ extern uint64_t hhdm_off;
|
|||||||
#define PAGE_ALIGN_DOWN(x) ((x) & PTE_ADDR_MASK)
|
#define PAGE_ALIGN_DOWN(x) ((x) & PTE_ADDR_MASK)
|
||||||
|
|
||||||
#define ALIGN(size) ALIGN_UP(size, 16)
|
#define ALIGN(size) ALIGN_UP(size, 16)
|
||||||
#define BLOCK_MIN_SIZE (sizeof(struct heap_block_t) + 16)
|
#define BLOCK_MIN_SIZE (sizeof(struct heap_block) + 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)
|
||||||
|
|||||||
@@ -17,23 +17,23 @@ typedef enum {
|
|||||||
DEAD
|
DEAD
|
||||||
} status_t;
|
} status_t;
|
||||||
|
|
||||||
struct process_t {
|
struct process {
|
||||||
size_t pid;
|
size_t pid;
|
||||||
char name[PROCESS_NAME_MAX];
|
char name[PROCESS_NAME_MAX];
|
||||||
|
|
||||||
status_t status;
|
status_t status;
|
||||||
struct cpu_status_t* context;
|
struct cpu_status* context;
|
||||||
void* root_page_table; // Process PML4 (should contain kernel PML4 in higher half [256-511]
|
void* root_page_table; // Process PML4 (should contain kernel PML4 in higher half [256-511]
|
||||||
struct process_t* next;
|
struct process* next;
|
||||||
};
|
};
|
||||||
|
|
||||||
void process_init(void);
|
void process_init(void);
|
||||||
struct process_t* process_create(char* name, void(*function)(void*), void* arg);
|
struct process* process_create(char* name, void(*function)(void*), void* arg);
|
||||||
void process_add(struct process_t** processes_list, struct process_t* process);
|
void process_add(struct process** processes_list, struct process* process);
|
||||||
void process_delete(struct process_t** processes_list, struct process_t* process);
|
void process_delete(struct process** processes_list, struct process* process);
|
||||||
struct process_t* process_get_next(struct process_t* process);
|
struct process* process_get_next(struct process* process);
|
||||||
void process_exit(void);
|
void process_exit(void);
|
||||||
|
|
||||||
void process_display_list(struct process_t* processes_list);
|
void process_display_list(struct process* processes_list);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#ifndef SCHEDULER_H
|
#ifndef SCHEDULER_H
|
||||||
#define SCHEDULER_H
|
#define SCHEDULER_H
|
||||||
|
|
||||||
struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context);
|
struct cpu_status* scheduler_schedule(struct cpu_status* context);
|
||||||
void scheduler_init(void);
|
void scheduler_init(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -10,13 +10,13 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
struct spinlock_t
|
struct spinlock
|
||||||
{
|
{
|
||||||
bool locked;
|
bool locked;
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
};
|
};
|
||||||
|
|
||||||
void spinlock_acquire(struct spinlock_t* lock);
|
void spinlock_acquire(struct spinlock* lock);
|
||||||
void spinlock_release(struct spinlock_t* lock);
|
void spinlock_release(struct spinlock* lock);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
+64
-33
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* @author xamidev <xamidev@riseup.net>
|
* @author xamidev <xamidev@riseup.net>
|
||||||
* @brief Global Descriptor Table (for legacy reasons)
|
* @brief Global Descriptor Table and Task State Segment setup
|
||||||
* @license GPL-3.0-only
|
* @license GPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -14,6 +14,8 @@
|
|||||||
uint64_t gdt_entries[NUM_GDT_ENTRIES];
|
uint64_t gdt_entries[NUM_GDT_ENTRIES];
|
||||||
struct GDTR gdtr;
|
struct GDTR gdtr;
|
||||||
|
|
||||||
|
struct tss tss = {0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gdt_load - Loads Global Descriptor Table
|
* gdt_load - Loads Global Descriptor Table
|
||||||
*/
|
*/
|
||||||
@@ -51,6 +53,58 @@ static void gdt_flush()
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get_set_entry - Sets a GDT entry
|
||||||
|
* @num: Number of the entry (index in GDT)
|
||||||
|
* @flags: Flags (Granularity, Size, Long mode)
|
||||||
|
* @access: Access byte (contains Descriptor Privilege Level)
|
||||||
|
*
|
||||||
|
* This function fills a GDT entry with the specified @flags
|
||||||
|
* and @access byte. The base and limit fields are left to zero
|
||||||
|
* because we don't use segmentation for memory management.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void gdt_set_entry(int num, uint8_t flags, uint8_t access)
|
||||||
|
{
|
||||||
|
uint64_t gdt_entry = 0;
|
||||||
|
|
||||||
|
gdt_entry |= (access << 8);
|
||||||
|
gdt_entry |= (flags << 20);
|
||||||
|
|
||||||
|
// Rest (base, limit) is always zero
|
||||||
|
gdt_entries[num] = gdt_entry << 32;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* gdt_set_tss - Setup the TSS entry in the GDT
|
||||||
|
* @num: Number of the entry (index in GDT)
|
||||||
|
*
|
||||||
|
* This function sets up a Task State Segment entry
|
||||||
|
* in the Global Descriptor Table.
|
||||||
|
*
|
||||||
|
* The entry is 128-bit long, so it actually takes
|
||||||
|
* two 64-bit GDT entries.
|
||||||
|
*/
|
||||||
|
static void gdt_set_tss(int num)
|
||||||
|
{
|
||||||
|
uint64_t tss_base = (uint64_t)&tss;
|
||||||
|
uint64_t tss_limit = sizeof(struct tss) - 1;
|
||||||
|
|
||||||
|
tss.iopb = sizeof(struct tss);
|
||||||
|
|
||||||
|
uint64_t tss_low = 0;
|
||||||
|
tss_low |= (tss_limit & 0xFFFFULL);
|
||||||
|
tss_low |= (tss_base & 0xFFFFFFULL) << 16;
|
||||||
|
tss_low |= 0x89ULL << 40;
|
||||||
|
tss_low |= ((tss_limit >> 16) & 0xFULL) << 48;
|
||||||
|
tss_low |= ((tss_base >> 24) & 0xFFULL) << 56;
|
||||||
|
|
||||||
|
uint64_t tss_high = (tss_base >> 32) & 0xFFFFFFFFULL;
|
||||||
|
|
||||||
|
gdt_entries[num] = tss_low;
|
||||||
|
gdt_entries[num + 1] = tss_high;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* gdt_init - Global Descriptor Table initialization
|
* gdt_init - Global Descriptor Table initialization
|
||||||
*
|
*
|
||||||
@@ -62,38 +116,12 @@ static void gdt_flush()
|
|||||||
*/
|
*/
|
||||||
void gdt_init()
|
void gdt_init()
|
||||||
{
|
{
|
||||||
// Null descriptor (required)
|
gdt_set_entry(0, 0, 0); // Null descriptor (0x0)
|
||||||
gdt_entries[0] = 0;
|
gdt_set_entry(1, 0xA, 0x9B); // Kernel code (0x8)
|
||||||
|
gdt_set_entry(2, 0xC, 0x93); // Kernel data (0x10)
|
||||||
// Kernel code segment
|
gdt_set_entry(3, 0xA, 0xFB); // User code (0x18)
|
||||||
uint64_t kernel_code = 0;
|
gdt_set_entry(4, 0xC, 0xF3); // User data (0x20)
|
||||||
kernel_code |= 0b1101 << 8; // Selector type: accessed, read-enable, no conforming
|
gdt_set_tss(5); // TSS (0x28)
|
||||||
kernel_code |= 1 << 12; // not a system descriptor
|
|
||||||
kernel_code |= 0 << 13; // DPL field = 0
|
|
||||||
kernel_code |= 1 << 15; // Present
|
|
||||||
kernel_code |= 1 << 21; // Long mode
|
|
||||||
|
|
||||||
// Left shift 32 bits so we place our stuff in the upper 32 bits of the descriptor.
|
|
||||||
// The lower 32 bits contain limit and part of base and therefore are ignored in Long Mode
|
|
||||||
// (because we'll use paging; segmentation is used only for legacy)
|
|
||||||
gdt_entries[1] = kernel_code << 32;
|
|
||||||
|
|
||||||
uint64_t kernel_data = 0;
|
|
||||||
kernel_data |= 0b0011 << 8;
|
|
||||||
kernel_data |= 1 << 12;
|
|
||||||
kernel_data |= 0 << 13;
|
|
||||||
kernel_data |= 1 << 15;
|
|
||||||
kernel_data |= 1 << 21;
|
|
||||||
|
|
||||||
gdt_entries[2] = kernel_data << 32;
|
|
||||||
|
|
||||||
// We re-use the kernel descriptors here, and just update their DPL fields
|
|
||||||
// (Descriptor privilege level) from ring 0 -> to ring 3 (userspace)
|
|
||||||
uint64_t user_code = kernel_code | (3 << 13);
|
|
||||||
gdt_entries[3] = user_code;
|
|
||||||
|
|
||||||
uint64_t user_data = kernel_data | (3 << 13);
|
|
||||||
gdt_entries[4] = user_data;
|
|
||||||
|
|
||||||
// The -1 subtraction is some wizardry explained in the OSDev wiki -> GDT
|
// The -1 subtraction is some wizardry explained in the OSDev wiki -> GDT
|
||||||
gdtr.limit = NUM_GDT_ENTRIES * sizeof(uint64_t) - 1;
|
gdtr.limit = NUM_GDT_ENTRIES * sizeof(uint64_t) - 1;
|
||||||
@@ -103,5 +131,8 @@ void gdt_init()
|
|||||||
gdt_load();
|
gdt_load();
|
||||||
gdt_flush();
|
gdt_flush();
|
||||||
|
|
||||||
|
// Load task register with new TSS
|
||||||
|
asm volatile("ltr %%ax" : : "a"(TSS_SEGMENT) : "memory");
|
||||||
|
|
||||||
DEBUG("GDT initialized");
|
DEBUG("GDT initialized");
|
||||||
}
|
}
|
||||||
+3
-3
@@ -108,7 +108,7 @@ static inline uint64_t read_cr2(void)
|
|||||||
* Also displays an interpretation of the thrown error code.
|
* Also displays an interpretation of the thrown error code.
|
||||||
* Then halts the system. We could implement demand paging later.
|
* Then halts the system. We could implement demand paging later.
|
||||||
*/
|
*/
|
||||||
static void page_fault_handler(struct cpu_status_t* ctx)
|
static void page_fault_handler(struct cpu_status* ctx)
|
||||||
{
|
{
|
||||||
// It could be used to remap pages etc. to fix the fault, but right now what I'm more
|
// It could be used to remap pages etc. to fix the fault, but right now what I'm more
|
||||||
// interested in is getting more info out of those numbers cause i'm lost each time i have
|
// interested in is getting more info out of those numbers cause i'm lost each time i have
|
||||||
@@ -149,7 +149,7 @@ static void page_fault_handler(struct cpu_status_t* ctx)
|
|||||||
* Shows detail about a General Protection Fault,
|
* Shows detail about a General Protection Fault,
|
||||||
* and what may have caused it. Halts the system.
|
* and what may have caused it. Halts the system.
|
||||||
*/
|
*/
|
||||||
static void gp_fault_handler(struct cpu_status_t* ctx)
|
static void gp_fault_handler(struct cpu_status* ctx)
|
||||||
{
|
{
|
||||||
DEBUG("\x1b[38;5;231mGeneral Protection Fault at rip=0x%p, err=%u (%s)\x1b[0m",
|
DEBUG("\x1b[38;5;231mGeneral Protection Fault at rip=0x%p, err=%u (%s)\x1b[0m",
|
||||||
ctx->iret_rip,
|
ctx->iret_rip,
|
||||||
@@ -185,7 +185,7 @@ static void gp_fault_handler(struct cpu_status_t* ctx)
|
|||||||
* Return:
|
* Return:
|
||||||
* <context> - CPU context after interrupt
|
* <context> - CPU context after interrupt
|
||||||
*/
|
*/
|
||||||
struct cpu_status_t* interrupt_dispatch(struct cpu_status_t* context)
|
struct cpu_status* interrupt_dispatch(struct cpu_status* context)
|
||||||
{
|
{
|
||||||
if (context == NULL) {
|
if (context == NULL) {
|
||||||
panic(NULL, "Interrupt dispatch recieved NULL context!");
|
panic(NULL, "Interrupt dispatch recieved NULL context!");
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include <arch/x86.h>
|
#include <arch/x86.h>
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
|
||||||
struct cpu_status_t* syscall_handler(struct cpu_status_t* regs)
|
struct cpu_status* syscall_handler(struct cpu_status* regs)
|
||||||
{
|
{
|
||||||
DEBUG("Syscall %lx with argument %lx", regs->rdi, regs->rsi);
|
DEBUG("Syscall %lx with argument %lx", regs->rdi, regs->rsi);
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -47,7 +47,7 @@ void read_rflags(uint64_t rflags)
|
|||||||
* Will display to terminal if it is initialized, otherwise serial only.
|
* Will display to terminal if it is initialized, otherwise serial only.
|
||||||
* Can be called with or without a CPU context.
|
* Can be called with or without a CPU context.
|
||||||
*/
|
*/
|
||||||
void panic(struct cpu_status_t* ctx, const char* str)
|
void panic(struct cpu_status* ctx, const char* str)
|
||||||
{
|
{
|
||||||
CLEAR_INTERRUPTS;
|
CLEAR_INTERRUPTS;
|
||||||
panic_count += 1;
|
panic_count += 1;
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
extern struct init_status init;
|
extern struct init_status init;
|
||||||
|
|
||||||
extern int panic_count;
|
extern int panic_count;
|
||||||
struct spinlock_t serial_lock = {0};
|
struct spinlock serial_lock = {0};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* outb - Writes a byte to a CPU port
|
* outb - Writes a byte to a CPU port
|
||||||
|
|||||||
+2
-2
@@ -29,8 +29,8 @@ because this shitty implementation will be replaced one day by Flanterm
|
|||||||
extern struct flanterm_context* ft_ctx;
|
extern struct flanterm_context* ft_ctx;
|
||||||
extern struct init_status init;
|
extern struct init_status init;
|
||||||
|
|
||||||
struct spinlock_t term_lock = {0};
|
struct spinlock term_lock = {0};
|
||||||
struct spinlock_t printf_lock = {0};
|
struct spinlock printf_lock = {0};
|
||||||
|
|
||||||
extern int panic_count;
|
extern int panic_count;
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -63,9 +63,9 @@ extern volatile struct limine_hhdm_request hhdm_request;
|
|||||||
extern volatile struct limine_kernel_address_request kerneladdr_request;
|
extern volatile struct limine_kernel_address_request kerneladdr_request;
|
||||||
extern volatile struct limine_boot_time_request date_request;
|
extern volatile struct limine_boot_time_request date_request;
|
||||||
|
|
||||||
extern struct process_t* processes_list;
|
extern struct process* processes_list;
|
||||||
extern struct process_t* current_process;
|
extern struct process* current_process;
|
||||||
struct process_t* idle_proc;
|
struct process* idle_proc;
|
||||||
|
|
||||||
void idle_main(void* arg)
|
void idle_main(void* arg)
|
||||||
{
|
{
|
||||||
|
|||||||
+11
-11
@@ -17,7 +17,7 @@ extern uint64_t kernel_virt_base;
|
|||||||
|
|
||||||
uintptr_t kheap_start;
|
uintptr_t kheap_start;
|
||||||
|
|
||||||
static struct heap_block_t* head = NULL;
|
static struct heap_block* head = NULL;
|
||||||
static uintptr_t end;
|
static uintptr_t end;
|
||||||
|
|
||||||
// Kernel root table (level 4)
|
// Kernel root table (level 4)
|
||||||
@@ -55,8 +55,8 @@ void kheap_init()
|
|||||||
end = current_addr;
|
end = current_addr;
|
||||||
|
|
||||||
// Give linked list head its properties
|
// Give linked list head its properties
|
||||||
head = (struct heap_block_t*)kheap_start;
|
head = (struct heap_block*)kheap_start;
|
||||||
head->size = (end-kheap_start) - sizeof(struct heap_block_t);
|
head->size = (end-kheap_start) - sizeof(struct heap_block);
|
||||||
head->free = true;
|
head->free = true;
|
||||||
head->next = NULL;
|
head->next = NULL;
|
||||||
DEBUG("Kernel heap initialized, head=0x%p, size=%u bytes", head, head->size);
|
DEBUG("Kernel heap initialized, head=0x%p, size=%u bytes", head, head->size);
|
||||||
@@ -80,16 +80,16 @@ void* kmalloc(size_t size)
|
|||||||
if (!size) return NULL;
|
if (!size) return NULL;
|
||||||
size = ALIGN(size);
|
size = ALIGN(size);
|
||||||
|
|
||||||
struct heap_block_t* curr = head;
|
struct heap_block* curr = head;
|
||||||
|
|
||||||
while (curr) {
|
while (curr) {
|
||||||
// Is block free and big enough for us?
|
// Is block free and big enough for us?
|
||||||
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) + 16) {
|
if (curr->size >= size + sizeof(struct heap_block) + 16) {
|
||||||
struct heap_block_t* split = (struct heap_block_t*)((uintptr_t)curr + sizeof(struct heap_block_t) + size);
|
struct heap_block* split = (struct heap_block*)((uintptr_t)curr + sizeof(struct heap_block) + size);
|
||||||
|
|
||||||
split->size = curr->size - size - sizeof(struct heap_block_t);
|
split->size = curr->size - size - sizeof(struct heap_block);
|
||||||
split->free = true;
|
split->free = true;
|
||||||
split->next = curr->next;
|
split->next = curr->next;
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ void* kmalloc(size_t size)
|
|||||||
|
|
||||||
// Found a good block, we return it
|
// Found a good block, we return it
|
||||||
curr->free = false;
|
curr->free = false;
|
||||||
return (void*)((uintptr_t)curr + sizeof(struct heap_block_t));
|
return (void*)((uintptr_t)curr + sizeof(struct heap_block));
|
||||||
}
|
}
|
||||||
// Continue browsing the list if nothing good was found yet
|
// Continue browsing the list if nothing good was found yet
|
||||||
curr = curr->next;
|
curr = curr->next;
|
||||||
@@ -127,11 +127,11 @@ void kfree(void* ptr)
|
|||||||
if (!ptr) return;
|
if (!ptr) return;
|
||||||
|
|
||||||
// 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* block = (struct heap_block*)((uintptr_t)ptr - sizeof(struct heap_block));
|
||||||
block->free = true;
|
block->free = true;
|
||||||
|
|
||||||
// merge adjacent free blocks (coalescing)
|
// merge adjacent free blocks (coalescing)
|
||||||
struct heap_block_t* curr = head;
|
struct heap_block* curr = head;
|
||||||
while (curr && curr->next) {
|
while (curr && curr->next) {
|
||||||
if (curr->free && curr->next->free) {
|
if (curr->free && curr->next->free) {
|
||||||
curr->size += sizeof(*curr) + curr->next->size;
|
curr->size += sizeof(*curr) + curr->next->size;
|
||||||
@@ -169,7 +169,7 @@ void* kalloc_stack()
|
|||||||
void kheap_info()
|
void kheap_info()
|
||||||
{
|
{
|
||||||
uint64_t free_bytes = 0;
|
uint64_t free_bytes = 0;
|
||||||
struct heap_block_t* curr = (struct heap_block_t*)kheap_start;
|
struct heap_block* curr = (struct heap_block*)kheap_start;
|
||||||
|
|
||||||
while (curr) {
|
while (curr) {
|
||||||
if (curr->free == true) {
|
if (curr->free == true) {
|
||||||
|
|||||||
+12
-12
@@ -16,8 +16,8 @@
|
|||||||
|
|
||||||
extern struct flanterm_context* ft_ctx;
|
extern struct flanterm_context* ft_ctx;
|
||||||
|
|
||||||
struct process_t* processes_list;
|
struct process* processes_list;
|
||||||
struct process_t* current_process;
|
struct process* current_process;
|
||||||
|
|
||||||
extern uint64_t *kernel_pml4;
|
extern uint64_t *kernel_pml4;
|
||||||
|
|
||||||
@@ -39,10 +39,10 @@ void process_init()
|
|||||||
* This function prints the linked list of processes
|
* This function prints the linked list of processes
|
||||||
* to the DEBUG output.
|
* to the DEBUG output.
|
||||||
*/
|
*/
|
||||||
void process_display_list(struct process_t* processes_list)
|
void process_display_list(struct process* processes_list)
|
||||||
{
|
{
|
||||||
int process_view_id = 0;
|
int process_view_id = 0;
|
||||||
struct process_t* tmp = processes_list;
|
struct process* tmp = processes_list;
|
||||||
while (tmp != NULL) {
|
while (tmp != NULL) {
|
||||||
DEBUG("{%d: %p} -> ", process_view_id, tmp);
|
DEBUG("{%d: %p} -> ", process_view_id, tmp);
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
@@ -64,11 +64,11 @@ void process_display_list(struct process_t* processes_list)
|
|||||||
* Return:
|
* Return:
|
||||||
* <proc> - pointer to created process
|
* <proc> - pointer to created process
|
||||||
*/
|
*/
|
||||||
struct process_t* process_create(char* name, void(*function)(void*), void* arg)
|
struct process* process_create(char* name, void(*function)(void*), void* arg)
|
||||||
{
|
{
|
||||||
CLEAR_INTERRUPTS;
|
CLEAR_INTERRUPTS;
|
||||||
struct process_t* proc = (struct process_t*)kmalloc(sizeof(struct process_t));
|
struct process* proc = (struct process*)kmalloc(sizeof(struct process));
|
||||||
struct cpu_status_t* ctx = (struct cpu_status_t*)kmalloc(sizeof(struct cpu_status_t));
|
struct cpu_status* ctx = (struct cpu_status*)kmalloc(sizeof(struct cpu_status));
|
||||||
|
|
||||||
// No more memory?
|
// No more memory?
|
||||||
if (!proc) return NULL;
|
if (!proc) return NULL;
|
||||||
@@ -108,7 +108,7 @@ struct process_t* process_create(char* name, void(*function)(void*), void* arg)
|
|||||||
* @processes_list: pointer to the head of the linked list
|
* @processes_list: pointer to the head of the linked list
|
||||||
* @process: process to add at the end of the linked list
|
* @process: process to add at the end of the linked list
|
||||||
*/
|
*/
|
||||||
void process_add(struct process_t** processes_list, struct process_t* process)
|
void process_add(struct process** processes_list, struct process* process)
|
||||||
{
|
{
|
||||||
if (!process) return;
|
if (!process) return;
|
||||||
process->next = NULL;
|
process->next = NULL;
|
||||||
@@ -119,7 +119,7 @@ void process_add(struct process_t** processes_list, struct process_t* process)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct process_t* tmp = *processes_list;
|
struct process* tmp = *processes_list;
|
||||||
while (tmp->next != NULL) {
|
while (tmp->next != NULL) {
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ void process_add(struct process_t** processes_list, struct process_t* process)
|
|||||||
* @processes_list: pointer to head of linked list
|
* @processes_list: pointer to head of linked list
|
||||||
* @process: the process to delete from the list
|
* @process: the process to delete from the list
|
||||||
*/
|
*/
|
||||||
void process_delete(struct process_t** processes_list, struct process_t* process)
|
void process_delete(struct process** processes_list, struct process* process)
|
||||||
{
|
{
|
||||||
if (!processes_list || !*processes_list || !process) return;
|
if (!processes_list || !*processes_list || !process) return;
|
||||||
|
|
||||||
@@ -144,7 +144,7 @@ void process_delete(struct process_t** processes_list, struct process_t* process
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct process_t* tmp = *processes_list;
|
struct process* tmp = *processes_list;
|
||||||
while (tmp->next && tmp->next != process) {
|
while (tmp->next && tmp->next != process) {
|
||||||
tmp = tmp->next;
|
tmp = tmp->next;
|
||||||
}
|
}
|
||||||
@@ -167,7 +167,7 @@ void process_delete(struct process_t** processes_list, struct process_t* process
|
|||||||
* Return:
|
* Return:
|
||||||
* <process->next> - process right after the one specified
|
* <process->next> - process right after the one specified
|
||||||
*/
|
*/
|
||||||
struct process_t* process_get_next(struct process_t* process)
|
struct process* process_get_next(struct process* process)
|
||||||
{
|
{
|
||||||
if (!process) return NULL;
|
if (!process) return NULL;
|
||||||
return process->next;
|
return process->next;
|
||||||
|
|||||||
@@ -10,9 +10,9 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <io/serial/serial.h>
|
#include <io/serial/serial.h>
|
||||||
|
|
||||||
extern struct process_t* processes_list;
|
extern struct process* processes_list;
|
||||||
extern struct process_t* current_process;
|
extern struct process* current_process;
|
||||||
extern struct process_t* idle_proc;
|
extern struct process* idle_proc;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* scheduler_init - Choose the first process
|
* scheduler_init - Choose the first process
|
||||||
@@ -32,7 +32,7 @@ void scheduler_init()
|
|||||||
* Return:
|
* Return:
|
||||||
* <context> - CPU context for next process
|
* <context> - CPU context for next process
|
||||||
*/
|
*/
|
||||||
struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
struct cpu_status* scheduler_schedule(struct cpu_status* context)
|
||||||
{
|
{
|
||||||
if (context == NULL) {
|
if (context == NULL) {
|
||||||
panic(NULL, "Scheduler called with NULL context");
|
panic(NULL, "Scheduler called with NULL context");
|
||||||
@@ -51,7 +51,7 @@ struct cpu_status_t* scheduler_schedule(struct cpu_status_t* context)
|
|||||||
current_process->context = context;
|
current_process->context = context;
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
struct process_t* prev_process = current_process;
|
struct process* prev_process = current_process;
|
||||||
if (current_process->next != NULL) {
|
if (current_process->next != NULL) {
|
||||||
current_process = current_process->next;
|
current_process = current_process->next;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
* Saves the RFLAGS register, then acquires a lock.
|
* Saves the RFLAGS register, then acquires a lock.
|
||||||
* Pause instruction is used to ease the CPU.
|
* Pause instruction is used to ease the CPU.
|
||||||
*/
|
*/
|
||||||
void spinlock_acquire(struct spinlock_t* lock)
|
void spinlock_acquire(struct spinlock* lock)
|
||||||
{
|
{
|
||||||
uint64_t rflags;
|
uint64_t rflags;
|
||||||
asm volatile("pushfq ; pop %0 ; cli" : "=rm"(rflags) : : "memory");
|
asm volatile("pushfq ; pop %0 ; cli" : "=rm"(rflags) : : "memory");
|
||||||
@@ -36,7 +36,7 @@ void spinlock_acquire(struct spinlock_t* lock)
|
|||||||
* unlocks it (clears locked state).
|
* unlocks it (clears locked state).
|
||||||
* RFLAGS is then restored.
|
* RFLAGS is then restored.
|
||||||
*/
|
*/
|
||||||
void spinlock_release(struct spinlock_t* lock)
|
void spinlock_release(struct spinlock* lock)
|
||||||
{
|
{
|
||||||
uint64_t rflags = lock->rflags;
|
uint64_t rflags = lock->rflags;
|
||||||
__atomic_clear(&lock->locked, __ATOMIC_RELEASE);
|
__atomic_clear(&lock->locked, __ATOMIC_RELEASE);
|
||||||
|
|||||||
Reference in New Issue
Block a user