Compare commits

..

42 Commits

Author SHA1 Message Date
44f5d687b0 changed main to a signal demo 2025-04-21 20:50:39 +02:00
1f5a358b19 fix: make iso 2025-04-21 13:29:56 +02:00
e15f0af292 fix: kpanic clearing registers and hlt correctly 2025-04-21 13:23:56 +02:00
8e2017bd29 clean 2025-04-18 17:31:08 +02:00
11125325ca Merge branch 'main' of git.chauvet.pro:starnakin/42_KFS 2025-04-18 17:20:43 +02:00
81c54647d2 feature: clear registers when kpanic is called 2025-04-18 17:19:56 +02:00
fc79a47957 add signal api 2025-04-18 17:07:56 +02:00
6c8c158a1f core: add physical allocator (not supposed to work but smh kinda does) 2025-04-18 14:42:07 +02:00
65f08e3887 feature: layout command to change between us and fr layouts 2025-04-18 13:56:11 +02:00
a14cc5df28 clean: remove physical memory utils 2025-04-17 17:12:03 +02:00
2e09db2dd1 fix: memory is now working completely (size issue)
fix: reboot with invalid opcode
2025-04-17 15:09:22 +02:00
5e561bfa15 wip: multiple pds and switch to kernel pd when needed 2025-02-10 13:25:19 +01:00
8dd5373e7f wip: start to add multiple pd for each task 2025-02-07 15:48:13 +01:00
3b798e5daa core: remove bozo typedef for types 2025-02-07 12:35:32 +01:00
70739744ac fix: fault address always display 2025-02-07 11:30:12 +01:00
1e981755de fix: do not edit task if it's the current 2025-02-07 11:29:39 +01:00
3766464c47 add: zombify task 2025-02-07 11:28:22 +01:00
a9ed5947a8 clean: add '\n' 2025-02-04 11:57:54 +01:00
db4ed04dd6 fix: kpanic print address of the fault only when page fault occured 2025-02-04 11:57:43 +01:00
7b7cc86999 wip: multitasking: add status forked 2025-02-03 13:11:38 +01:00
18486a6705 fix: infinite loop when scheduler call before create_kernel_task 2025-01-30 14:04:15 +01:00
c9a92819b4 fix: fork return pid instead uid 2025-01-30 10:47:36 +01:00
f75e121251 fix: fork: call scheduler before fork 2025-01-30 10:47:15 +01:00
9c89433db5 fix: task: use 8bit represent ptr instead of 32 to fix stack ptr 2025-01-29 13:30:42 +01:00
69686a2c91 fix: fork: set child espat the right postion 2025-01-29 12:41:57 +01:00
1ca8c68cf5 wip: fork and wait are almost working (missing child's stack) 2025-01-28 15:44:09 +01:00
e60969b37a fix: multitasking: switch to task 2025-01-28 15:10:13 +01:00
dbdf851dd2 feature: fork added and exit_task is almost working 2025-01-28 13:38:39 +01:00
d7626df19c core: change types from uint32_t to u32 (e.g) 2025-01-27 11:26:15 +01:00
95fec015f2 fix: simple multitasking work !!!!
add a stack at every task, and execute task while multitasking switching
2025-01-24 12:33:29 +01:00
dc84d5856b fix: switch to task: dereference variable rightly 2025-01-23 15:53:42 +01:00
19eea56a7e fix: switch to task: dereference variable rightly 2025-01-23 15:25:49 +01:00
8c63eac00e fix: no switch to task when only one task 2025-01-23 14:48:53 +01:00
d4db6acf61 fix: infinite loop when only one task 2025-01-23 14:27:28 +01:00
540226fb0f Merge branch 'main' of git.chauvet.pro:starnakin/42_KFS 2025-01-23 14:13:04 +01:00
2d6b24842e fix: a bunch of stuff related to multitasking 2025-01-23 14:12:38 +01:00
494a0f425c add: bzero 2025-01-22 14:44:50 +01:00
2ba4037af2 core: add debug flags to use gdb 2025-01-22 14:41:41 +01:00
7ba3eead14 core: change main debug func 2025-01-22 14:06:44 +01:00
35b73e8004 clean: remove useless code 2025-01-22 14:06:44 +01:00
4ec1a4962d fix: (maybe): remove gdt address 2025-01-22 14:06:44 +01:00
24c7ea8b19 clean: remove useless code 2025-01-22 14:06:44 +01:00
58 changed files with 60416 additions and 1575 deletions

2
.gitignore vendored
View File

@ -4,4 +4,4 @@ obj
compile_commands.json compile_commands.json
tags tags
base_fonts base_fonts
*.txt *.log

View File

@ -1,9 +1,9 @@
NAME := bozOS NAME := bozOS
AS := i386-elf-as AS := i386-elf-as
ASFLAGS := ASFLAGS := -g
CC := i386-elf-gcc CC := i386-elf-gcc
CFLAGS := -std=gnu99 -ffreestanding -Wall -Wextra -iquotelibbozo/headers -iquoteheaders -MMD -fno-omit-frame-pointer -fstack-protector-all -g CFLAGS := -std=gnu99 -ffreestanding -Wall -Wextra -iquotelibbozo/headers -iquoteheaders -MMD -fno-omit-frame-pointer -fstack-protector-all -g3
LD := $(CC) LD := $(CC)
LDFLAGS := -T boot/linker.ld -ffreestanding -nostdlib LDFLAGS := -T boot/linker.ld -ffreestanding -nostdlib
LIBS := -L libbozo/build/ -lbozo -lgcc LIBS := -L libbozo/build/ -lbozo -lgcc
@ -54,7 +54,7 @@ fast-run-iso: fast-iso
qemu-system-i386 -cdrom build/$(NAME).iso -vga std qemu-system-i386 -cdrom build/$(NAME).iso -vga std
debug: fast-iso debug: fast-iso
qemu-system-i386 -cdrom build/$(NAME).iso -vga std -d int -M smm=off 2> logs qemu-system-i386 -s -S -cdrom build/$(NAME).iso -vga std -D qemu.log -d in_asm,int -M smm=off
clean: clean:
make -C libbozo clean make -C libbozo clean

View File

@ -1,9 +1,6 @@
#pragma once #pragma once
// boolean types
#include <stdbool.h> #include <stdbool.h>
// size_t, already in libft.h but for readability
#include <stddef.h> #include <stddef.h>
// Remove this and replace it with <assert.h> header // Remove this and replace it with <assert.h> header
@ -64,8 +61,8 @@ typedef struct Zone {
* For TINY and SMALL, the zone will be divided in blocks. * For TINY and SMALL, the zone will be divided in blocks.
* For LARGE, it will be entire page(s). * For LARGE, it will be entire page(s).
*/ */
extern Zone *vzones[3];
extern Zone *kzones[3]; extern Zone *kzones[3];
extern Zone *zones[3];
/*----------- UTILS ----------*/ /*----------- UTILS ----------*/
block_type_t get_type(size_t size); block_type_t get_type(size_t size);
@ -74,17 +71,17 @@ size_t align_mem(size_t addr);
/*----------------------------*/ /*----------------------------*/
/*-------- ALLOCATOR ---------*/ /*-------- ALLOCATOR ---------*/
int new_kzone(block_type_t type, size_t size);
int new_vzone(block_type_t type, size_t size); int new_vzone(block_type_t type, size_t size);
int new_kzone(block_type_t type, size_t size);
/*----------------------------*/ /*----------------------------*/
void *kmalloc(size_t size);
void kfree(void *ptr);
void *krealloc(void *ptr, size_t size);
void *vmalloc(size_t size); void *vmalloc(size_t size);
void vfree(void *ptr); void vfree(void *ptr);
void *vrealloc(void *ptr, size_t size); void *vrealloc(void *ptr, size_t size);
void show_kalloc_mem(void);
void show_valloc_mem(void); void show_valloc_mem(void);
size_t ksize(void *virt_addr);
size_t vsize(void *virt_addr); size_t vsize(void *virt_addr);
void *kmalloc(size_t size);
void kfree(void *ptr);
void *krealloc(void *ptr, size_t size);
void show_kalloc_mem(void);
size_t ksize(void *phys_addr);

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#define BASE_BIN "01" #define BASE_BIN "01"
#define BASE_OCTA BASE_BIN "234567" #define BASE_OCTA BASE_BIN "234567"
#define BASE_DECA BASE_OCTA "89" #define BASE_DECA BASE_OCTA "89"
#define BASE_HEXA BASE_DECA "abcdef" #define BASE_HEXA BASE_DECA "abcdef"

View File

@ -6,7 +6,8 @@ void date_cmd(char *arg);
void poweroff_cmd(char *arg); void poweroff_cmd(char *arg);
void stack_cmd(char *arg); void stack_cmd(char *arg);
void help_cmd(char *arg); void help_cmd(char *arg);
void reboot_cmd(char* arg); void reboot_cmd(char *arg);
void heap_cmd(char *arg); void heap_cmd(char *arg);
void clear_cmd(char *arg); void clear_cmd(char *arg);
void merdella_cmd(char *arg); void merdella_cmd(char *arg);
void layout_cmd(char *arg);

View File

@ -2,6 +2,7 @@
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include <stdint.h> #include <stdint.h>
#define PRINT_PTR(X) kprintf("%s:%u %s: %p\n", __FILE__, __LINE__, #X, X) #define PRINT_PTR(X) kprintf("%s:%u %s: %p\n", __FILE__, __LINE__, #X, X)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,10 +1,10 @@
#pragma once #pragma once
#include "tss.h" #include "tss.h"
#include <stdint.h> #include <stdint.h>
#define GDT_ADDRESS 0xC0105040 #define GDT_SIZE 8
#define GDT_SIZE 8
// https://wiki.osdev.org/Global_Descriptor_Table#GDTR // https://wiki.osdev.org/Global_Descriptor_Table#GDTR
struct gdt_descriptor { struct gdt_descriptor {

File diff suppressed because one or more lines are too long

View File

@ -24,7 +24,8 @@ static inline void cli(void)
__asm__ volatile("cli"); __asm__ volatile("cli");
} }
static inline void sti(void) // aka sti
static inline void toris(void)
{ {
__asm__ volatile("sti"); __asm__ volatile("sti");
} }

View File

@ -3,7 +3,35 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
[[__maybe_unused__]] static const char *keymap[128] = { [[__maybe_unused__]] static const char *azerty_keymap[128] = {
[2] = "&1", [3] = "é2", [4] = "\"3", [5] = "'4", [6] = "(5",
[7] = "-6", [8] = "è7", [9] = "_8", [10] = "ç9", [11] = "à0",
[12] = "", [13] = "=+", [14] = NULL, [15] = NULL, [16] = "aA",
[17] = "zZ", [18] = "eE", [19] = "rR", [20] = "tT", [21] = "yY",
[22] = "uU", [23] = "iI", [24] = "oO", [25] = "pP", [26] = "",
[27] = "", [28] = "\n\n", [30] = "qQ", [31] = "sS", [32] = "dD",
[33] = "fF", [34] = "gG", [35] = "hH", [36] = "jJ", [37] = "kK",
[38] = "lL", [39] = "mM", [40] = "ù%", [41] = NULL, [42] = NULL,
[43] = "", [44] = "wW", [45] = "xX", [46] = "cC", [47] = "vV",
[48] = "bB", [49] = "nN", [50] = ",?", [51] = ";.", [52] = ":/",
[53] = "", [54] = NULL, [55] = NULL, [56] = NULL, [57] = " ",
[58] = NULL, [59] = NULL, [60] = NULL, [61] = NULL, [62] = NULL,
[63] = NULL, [64] = NULL, [65] = NULL, [66] = NULL, [67] = NULL,
[68] = NULL, [69] = NULL, [70] = NULL, [71] = NULL, [72] = NULL,
[73] = NULL, [74] = NULL, [75] = NULL, [76] = NULL, [77] = NULL,
[78] = NULL, [79] = NULL, [80] = NULL, [81] = NULL, [82] = NULL,
[83] = NULL, [84] = NULL, [85] = NULL, [86] = NULL, [87] = NULL,
[88] = NULL, [89] = NULL, [90] = NULL, [91] = NULL, [92] = NULL,
[93] = NULL, [94] = NULL, [95] = NULL, [96] = NULL, [97] = NULL,
[98] = NULL, [99] = NULL, [100] = NULL, [101] = NULL, [102] = NULL,
[103] = NULL, [104] = NULL, [105] = NULL, [106] = NULL, [107] = NULL,
[108] = NULL, [109] = NULL, [110] = NULL, [111] = NULL, [112] = NULL,
[113] = NULL, [114] = NULL, [115] = NULL, [116] = NULL, [117] = NULL,
[118] = NULL, [119] = NULL, [120] = NULL, [121] = NULL, [122] = NULL,
[123] = NULL, [124] = NULL, [125] = NULL, [126] = NULL, [127] = NULL,
};
[[__maybe_unused__]] static const char *qwerty_keymap[128] = {
[2] = "1!", [3] = "2@", [4] = "3#", [5] = "4$", [6] = "5%", [2] = "1!", [3] = "2@", [4] = "3#", [5] = "4$", [6] = "5%",
[7] = "6^", [8] = "7&", [9] = "8*", [10] = "9(", [11] = "0)", [7] = "6^", [8] = "7&", [9] = "8*", [10] = "9(", [11] = "0)",
[12] = "-_", [13] = "=+", [14] = NULL, [15] = NULL, [16] = "qQ", [12] = "-_", [13] = "=+", [14] = NULL, [15] = NULL, [16] = "qQ",

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "multiboot.h" #include "multiboot.h"
#include <stdint.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@ -15,9 +16,9 @@
#define PD_SIZE 1024 #define PD_SIZE 1024
#define PAGE_MASK 0xFFFFF000 #define PAGE_MASK 0xFFFFF000
#define HEAP_END 0xC0000000 #define HEAP_END 0xC0000000
#define HEAP_START ((uint32_t) & _kernel_end - HEAP_END) #define HEAP_START ((uint32_t)&_kernel_end - HEAP_END)
#define KERNEL_START ((uint32_t) & _kernel_start) #define KERNEL_START ((uint32_t)&_kernel_start)
#define KERNEL_END ((uint32_t) & _kernel_end - HEAP_END) #define KERNEL_END ((uint32_t)&_kernel_end - HEAP_END)
#define PT_START 256 #define PT_START 256
#define GET_PAGE_ADDR(pd_index, pt_index) \ #define GET_PAGE_ADDR(pd_index, pt_index) \
@ -44,7 +45,9 @@ struct frame_zone {
extern uint32_t _kernel_end; extern uint32_t _kernel_end;
extern uint32_t _kernel_start; extern uint32_t _kernel_start;
extern uint32_t boot_page_directory; extern uint32_t boot_page_directory;
extern uint32_t *page_directory; extern uint32_t boot_page_table1;
extern uint32_t *kernel_pd;
extern uint32_t *current_pd;
extern uint32_t page_table_default[1024]; extern uint32_t page_table_default[1024];
extern uint32_t mem_size; extern uint32_t mem_size;
extern multiboot_memory_map_t *mmap_addr; extern multiboot_memory_map_t *mmap_addr;
@ -55,7 +58,9 @@ uint32_t *virt_to_phys(uint32_t *virt_addr);
void init_memory(multiboot_info_t *mbd, uint32_t magic); void init_memory(multiboot_info_t *mbd, uint32_t magic);
void *alloc_frame(void); void *alloc_frame(void);
int free_frame(void *frame_ptr); int free_frame(void *frame_ptr);
int8_t add_single_page(void *frame);
void *alloc_pages(size_t size, void **phys_addr); void *alloc_pages(size_t size, void **phys_addr);
int free_pages(void *page_ptr, size_t size); int free_pages(void *page_ptr, size_t size);
void init_page_table(uint32_t page_table[1024], uint16_t start); void init_page_table(uint32_t page_table[1024], uint16_t start);
int16_t add_page_table(uint16_t pd_index); int16_t add_page_table(uint16_t pd_index);
void switch_pd(uint32_t *pd, uint32_t *cr3);

View File

@ -27,4 +27,4 @@ struct rtc_date {
uint32_t year; uint32_t year;
}; };
struct rtc_date get_date(void); struct rtc_date get_date(void);

View File

@ -1,9 +1,12 @@
#pragma once #pragma once
#define SIG_DFL -1 #include <stdbool.h>
#define SIG_IGN 0 #include <stdint.h>
enum { #define SIG_DFL 0
#define SIG_IGN -1
typedef enum {
SIGABRT, // Abort signal from abort(3) SIGABRT, // Abort signal from abort(3)
SIGALRM, // Timer signal from alarm(2) SIGALRM, // Timer signal from alarm(2)
SIGBUS, // Bus error (bad memory access) SIGBUS, // Bus error (bad memory access)
@ -44,11 +47,16 @@ enum {
SIGXFSZ, // File size limit exceeded (4.2BSD); see setrlimit(2) SIGXFSZ, // File size limit exceeded (4.2BSD); see setrlimit(2)
SIGWINCH, // Window resize signal (4.3BSD, Sun) SIGWINCH, // Window resize signal (4.3BSD, Sun)
SIG_INT, // Interrupt from keyboard SIG_INT, // Interrupt from keyboard
}; LAST
} SIGNAL_CODE;
typedef void (*sighandler_t)(int); typedef void (*signal_handler_t)(int);
struct signal { void signal(SIGNAL_CODE sig_num, void *handler);
int signum; void kill(int pid, SIGNAL_CODE sig_num);
sighandler_t handler; void exec_signal_pending(void);
};
struct signal_data {
void *handlers[LAST];
uint32_t pending;
};

View File

@ -1,31 +1,44 @@
#pragma once #pragma once
#include "list.h" #include "list.h"
#include "memory.h"
#include "signal.h"
#include <stdint.h> #include <stdint.h>
extern struct task *current_task; extern struct task *current_task;
enum status { ZOMBIE, THREAD, RUN }; enum status { ZOMBIE, THREAD, RUN, WAIT, SLEEP, STOPPED, FORKED };
enum owner { OWNER_KERNEL, OWNER_USER }; enum owner { OWNER_KERNEL, OWNER_USER };
#define STACK_SIZE PAGE_SIZE * 4
struct task { struct task {
uint32_t *esp; uint8_t *esp;
uint32_t *esp0; uint8_t *esp0;
uint32_t *cr3; // physical uint32_t *cr3; // physical
uint32_t *heap; // virtual uint32_t *heap; // virtual
uint32_t *eip; uint32_t *eip;
uint16_t pid; uint16_t pid;
uint8_t status; uint8_t status;
uint8_t owner_id; uint8_t uid;
struct task *daddy; struct task *daddy;
struct task *child; struct task *child;
struct list **signals; struct signal_data signals;
struct task *next; struct task *next;
struct task *prev; struct task *prev;
}; };
void scheduler(void); void scheduler(void);
void switch_to_task(struct task *next_task); void switch_to_task(struct task *next_task);
struct task *create_task(uint8_t uid);
int8_t create_kernel_task(void);
void remove_task(struct task *task);
struct task *copy_task(const struct task *task);
void kfork(struct task *daddy);
void zombify_task(struct task *task);
// utils
void exec_fn(void (*fn)(void)); void exec_fn(void (*fn)(void));
int create_kernel_task(void); uint16_t fork(void);
uint16_t wait(void);

View File

@ -3,6 +3,7 @@
#include "font.h" #include "font.h"
#include "icon.h" #include "icon.h"
#include "keyboard.h" #include "keyboard.h"
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>

View File

@ -2,4 +2,4 @@
#include <stdint.h> #include <stdint.h>
void sleep(uint64_t delay); void sleep(uint64_t delay);

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "icon.h" #include "icon.h"
#include <stdint.h> #include <stdint.h>
struct vbe_interface { struct vbe_interface {

View File

@ -12,3 +12,4 @@ void *memcpy(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);
void *memset(void *str, int c, size_t n); void *memset(void *str, 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);
void bzero(void *s, size_t n);

View File

@ -0,0 +1,6 @@
#include "string.h"
void bzero(void *s, size_t n)
{
memset(s, 0, n);
}

View File

@ -1,3 +1,4 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>

View File

@ -1,3 +1,4 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>

9
libbozo/src/types.sh Executable file
View File

@ -0,0 +1,9 @@
# !/bin/bash
sed -i 's/u8/uint8_t/g' **/*.c
sed -i 's/i8/int8_t/g' **/*.c
sed -i 's/u16/uint16_t/g' **/*.c
sed -i 's/i16/int16_t/g' **/*.c
sed -i 's/u32/uint32_t/g' **/*.c
sed -i 's/i32/int32_t/g' **/*.c
sed -i 's/u64/uint64_t/g' **/*.c
sed -i 's/i64/int64_t/g' **/*.c

View File

@ -25,7 +25,7 @@ static void set_pit_count(unsigned count)
outb(0x40, count & 0xFF); // Low byte outb(0x40, count & 0xFF); // Low byte
outb(0x40, (count & 0xFF00) >> 8); // High byte outb(0x40, (count & 0xFF00) >> 8); // High byte
sti(); toris();
} }
void clock_init(struct registers *regs) void clock_init(struct registers *regs)
@ -38,7 +38,7 @@ void clock_init(struct registers *regs)
static void clock_handler(struct registers *regs) static void clock_handler(struct registers *regs)
{ {
(void)regs; (void)regs;
if (scheduler_counter % 10) if (scheduler_counter % 10 == 0)
scheduler(); scheduler();
scheduler_counter++; scheduler_counter++;
sleep_counter--; sleep_counter--;

View File

@ -7,7 +7,7 @@ extern void set_gdt(uint32_t gdt_ptr);
struct tss TSS; struct tss TSS;
uint8_t gdt_entries[GDT_SIZE * 8]; uint8_t gdt_entries[GDT_SIZE * 8];
struct gdt_descriptor *gdtr = (struct gdt_descriptor *)GDT_ADDRESS; struct gdt_descriptor gdtr;
static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit, static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit,
uint8_t access, uint8_t granularity) uint8_t access, uint8_t granularity)
@ -37,8 +37,8 @@ static void set_gdt_entry_value(uint8_t *target, uint32_t base, uint32_t limit,
void init_gdt(void) void init_gdt(void)
{ {
gdtr->size = 8 * GDT_SIZE - 1; gdtr.size = 8 * GDT_SIZE - 1;
gdtr->base = (uint32_t)&gdt_entries[0]; gdtr.base = (uint32_t)&gdt_entries[0];
set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment set_gdt_entry_value(gdt_entries + 0x00, 0, 0, 0, 0); // Null segment
@ -95,5 +95,5 @@ void init_gdt(void)
set_gdt_entry_value(gdt_entries + GDT_OFFSET_TSS, (uint32_t)&TSS, set_gdt_entry_value(gdt_entries + GDT_OFFSET_TSS, (uint32_t)&TSS,
sizeof(struct tss) - 1, 0x89, 0); sizeof(struct tss) - 1, 0x89, 0);
set_gdt(((uint32_t)gdtr)); set_gdt(((uint32_t)&gdtr));
} }

View File

@ -1,6 +1,7 @@
#include "interrupts.h" #include "interrupts.h"
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "power.h"
#include "utils.h" #include "utils.h"
#include <stddef.h> #include <stddef.h>
@ -35,6 +36,8 @@ void isr_handler(struct registers *regs)
{ {
uint8_t i = 0; uint8_t i = 0;
while (i < ARRAY_SIZE(faults)) { while (i < ARRAY_SIZE(faults)) {
if (i == 6)
reboot();
if (i == regs->int_no) if (i == regs->int_no)
kpanic("interrupt: %s\n", faults[i]); kpanic("interrupt: %s\n", faults[i]);
i++; i++;

View File

@ -38,10 +38,7 @@ irq_common_stub:
iret iret
irq0: irq0:
push eax
mov eax, [esp + 4]
mov [esp_backup], esp mov [esp_backup], esp
pop eax
push 0 push 0
push 32 push 32
jmp irq_common_stub jmp irq_common_stub

View File

@ -1,3 +1,4 @@
#include <cpuid.h> #include <cpuid.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>

View File

@ -1,10 +0,0 @@
#include "signal.h"
#include <stddef.h>
void (*signal(int sig, void (*func)(int)))(int)
{
// TODO after multi tasking and processes
(void)sig;
(void)func;
return NULL;
}

View File

@ -30,21 +30,9 @@
#error "This tutorial needs to be compiled with a ix86-elf compiler" #error "This tutorial needs to be compiled with a ix86-elf compiler"
#endif #endif
static void uwu(void) static void bozo(int int_code)
{ {
kprintf("uwu\n"); kprintf("apagnan code\n");
}
static void owo(void)
{
while (true)
kprintf("owo\n");
}
static void awa(void)
{
while (true)
; // kprintf("awa\n");
} }
void kernel_main(multiboot_info_t *mbd, uint32_t magic) void kernel_main(multiboot_info_t *mbd, uint32_t magic)
@ -54,14 +42,11 @@ void kernel_main(multiboot_info_t *mbd, uint32_t magic)
init_idt(); init_idt();
init_memory(mbd, magic); init_memory(mbd, magic);
load_drivers(); load_drivers();
/* kprintf(KERN_ALERT */
/* "I see no way to confuse an array of 256 seg:off pairs with a
* " */
/* "complex 8*unknown quantity -byte descriptor table. -- Troy "
*/
/* "Martin 03:50, 22 March 2009 (UTC)\n"); */
create_kernel_task(); create_kernel_task();
exec_fn(awa); kill(0, 4);
// exec_fn(owo); for (size_t i = 0; i < 10000; i++)
free_pages(alloc_pages(1, NULL), 1);
signal(4, bozo);
kill(0, 4);
shell_init(); shell_init();
} }

View File

@ -4,9 +4,12 @@
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "power.h" #include "power.h"
#include "string.h"
#include "terminal.h" #include "terminal.h"
extern uint32_t page_table1[1024]; extern uint32_t page_table1[1024];
extern const char *faults[];
void clear_registers(void);
__attribute__((noreturn)) void kpanic(const char *format, ...) __attribute__((noreturn)) void kpanic(const char *format, ...)
{ {
@ -14,20 +17,20 @@ __attribute__((noreturn)) void kpanic(const char *format, ...)
/* terminal_set_bg_color(VGA_COLOR_BLUE); */ /* terminal_set_bg_color(VGA_COLOR_BLUE); */
/* terminal_clear(); */ /* terminal_clear(); */
kprintf("kpanic: ");
va_start(va, format); va_start(va, format);
kvprintf(format, &va); kvprintf(format, &va);
va_end(va); va_end(va);
uint32_t faulting_address; uint32_t faulting_address;
__asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address)); // __asm__ __volatile__("mov %%cr2, %0" : "=r"(faulting_address));
kprintf("fault at address: %p\n", faulting_address); // kprintf("fault at address: %p\n", faulting_address);
/* for (int i = 16; i < 32; i++) */ /* for (int i = 16; i < 32; i++) */
/* kprintf("%p\n", page_table1[i]); */ /* kprintf("%p\n", page_table1[i]); */
/* show_valloc_mem(); */ // show_valloc_mem();
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* print_stack(); */ /* print_stack(); */
/* kprintf("\n\n"); */ /* kprintf("\n\n"); */
/* kprintf("PRESS SPACE TO REBOOT"); */ /* kprintf("PRESS SPACE TO REBOOT"); */
while (terminal_getkey().scan_code != KEY_SPACE) __asm__ __volatile__("jmp panic");
;
reboot();
} }

View File

@ -4,12 +4,19 @@
#include <stdint.h> #include <stdint.h>
uint32_t *page_directory = &boot_page_directory; uint32_t *kernel_pd = &boot_page_directory;
uint32_t *current_pd;
uint32_t page_table_default[1024] __attribute__((aligned(PAGE_SIZE))); uint32_t page_table_default[1024] __attribute__((aligned(PAGE_SIZE)));
uint32_t frame_zones_page_table[1024] __attribute__((aligned(PAGE_SIZE))); uint32_t frame_zones_page_table[1024] __attribute__((aligned(PAGE_SIZE)));
uint32_t mem_size; uint32_t mem_size;
struct frame_zone *head; struct frame_zone *head;
void switch_pd(uint32_t *pd, uint32_t *cr3)
{
current_pd = pd;
asm volatile("mov %0, %%cr3" ::"r"(cr3));
}
static void lst_add_back(struct frame_zone **root, struct frame_zone *element) static void lst_add_back(struct frame_zone **root, struct frame_zone *element)
{ {
if (!*root) { if (!*root) {
@ -61,8 +68,7 @@ static void add_frame_node(multiboot_memory_map_t *mmmt)
end_addr = ROUND_CEIL(start_addr + len, PAGE_SIZE); end_addr = ROUND_CEIL(start_addr + len, PAGE_SIZE);
init_page_table(frame_zones_page_table, 0); init_page_table(frame_zones_page_table, 0);
page_directory[1022] = kernel_pd[1022] = ((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
((uint32_t)frame_zones_page_table - HEAP_END) | 0x03;
frame_zones_page_table[index] = frame_zones_page_table[index] =
((uint32_t)start_addr & PAGE_MASK) | INIT_FLAGS; ((uint32_t)start_addr & PAGE_MASK) | INIT_FLAGS;
@ -108,9 +114,10 @@ static void init_frame_zones(void)
void init_memory(multiboot_info_t *mbd, uint32_t magic) void init_memory(multiboot_info_t *mbd, uint32_t magic)
{ {
for (uint16_t i = 0; i < 0x300; i++) for (uint16_t i = 0; i < 0x300; i++)
page_directory[i] = 0x02; kernel_pd[i] = 0x02;
init_page_table(page_table_default, 0); init_page_table(page_table_default, 0);
page_directory[0] = ((uint32_t)page_table_default - HEAP_END) | 0x03; kernel_pd[0] = ((uint32_t)page_table_default - HEAP_END) | 0x03;
current_pd = kernel_pd;
init_multiboot(mbd, magic); init_multiboot(mbd, magic);
init_frame_zones(); init_frame_zones();
} }

View File

@ -6,13 +6,14 @@
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "string.h" #include "string.h"
#include "task.h"
#include "utils.h" #include "utils.h"
static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr, static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
uint32_t **page_table_ptr) uint32_t **page_table_ptr)
{ {
for (*pd_index_ptr = 1; *pd_index_ptr < 768; (*pd_index_ptr)++) { for (*pd_index_ptr = 1; *pd_index_ptr < 768; (*pd_index_ptr)++) {
if (page_directory[(*pd_index_ptr)] == 0x02) { if (current_pd[(*pd_index_ptr)] == 0x02) {
if (add_page_table(*pd_index_ptr) < 0) if (add_page_table(*pd_index_ptr) < 0)
return -2; return -2;
} }
@ -32,6 +33,20 @@ static int16_t find_next_block(size_t nb_pages, uint16_t *pd_index_ptr,
return -1; return -1;
} }
int8_t add_single_page(void *frame)
{
uint16_t pd_index;
uint32_t *page_table;
const int16_t i = find_next_block(1, &pd_index, &page_table);
if (i < 0) {
kprintf(KERN_CRIT "impossible to add page to page directory\n");
return -1;
}
page_table[i] = ((uint32_t)frame & PAGE_MASK) | INIT_FLAGS;
return 0;
}
void *alloc_pages(size_t size, void **phys_addr) void *alloc_pages(size_t size, void **phys_addr)
{ {
const uint32_t nb_pages = CEIL(size, PAGE_SIZE); const uint32_t nb_pages = CEIL(size, PAGE_SIZE);

View File

@ -17,6 +17,6 @@ int16_t add_page_table(uint16_t pd_index)
uint32_t *page_table = uint32_t *page_table =
(uint32_t *)GET_PAGE_ADDR(0, PT_START + pd_index); (uint32_t *)GET_PAGE_ADDR(0, PT_START + pd_index);
init_page_table(page_table, 0); init_page_table(page_table, 0);
page_directory[pd_index] = ((uint32_t)frame & PAGE_MASK) | 0x03; kernel_pd[pd_index] = ((uint32_t)frame & PAGE_MASK) | 0x03;
return 0; return 0;
} }

View File

@ -0,0 +1,70 @@
#include "alloc.h"
#include "debug.h"
#include "kpanic.h"
#include "kprintf.h"
#include "memory.h"
#include "task.h"
Zone *kzones[3];
static void add_zone(Zone *zone, block_type_t type)
{
// We put the zone at the beginning of the list
if (kzones[type]) {
assert(kzones[type] != zone);
zone->next = kzones[type];
kzones[type]->prev = zone;
}
kzones[type] = zone;
}
static void new_block(Zone *zone, uint32_t zone_size)
{
Block *new_block = (Block *)align_mem((uint32_t)zone + sizeof(Zone));
// Metadata
new_block->in_use = false;
new_block->size = zone_size - sizeof(Zone) - sizeof(Block);
new_block->sub_size = new_block->size;
new_block->ptr = (Block *)((uint32_t)new_block + sizeof(Block));
new_block->zone = zone;
// Init future linked lists
new_block->prev = NULL;
new_block->prev_free = NULL;
new_block->prev_used = NULL;
new_block->next = NULL;
new_block->next_free = NULL;
new_block->next_used = NULL;
if (zone->free) {
zone->free->prev = new_block;
zone->free->prev_free = new_block;
new_block->next = zone->free;
new_block->next_free = zone->free;
}
zone->free = new_block;
assert(zone->free == new_block);
}
int new_kzone(block_type_t type, uint32_t size)
{
// assert(current_task->pid);
void *heap = alloc_frame();
if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_frame failed\n");
return (-1);
}
Zone *zone = (Zone *)heap;
zone->type = type;
zone->size = size;
zone->used = NULL;
zone->next = NULL;
zone->prev = NULL;
new_block(zone, size);
add_zone(heap, type);
return (0);
}

52
src/memory/phys/info.c Normal file
View File

@ -0,0 +1,52 @@
#include "alloc.h"
#include "kprintf.h"
#include <stdint.h>
// FULL_INFO is to display (or not) both used and unused blocks
#define FULL_INFO 1
void show_kalloc_mem(void)
{
char *const zones_name[3] = {"TINY", "SMALL", "LARGE"};
uint32_t total_size = 0;
for (block_type_t type = 0; type < 3; ++type) {
int count = 0;
for (Zone *zone_it = kzones[type]; zone_it != NULL;
zone_it = zone_it->next) {
if (zone_it->used)
kprintf("---------- IN_USE %s [n°%d - %p] "
"----------\n",
zones_name[type], count, zone_it);
for (Block *block_it = zone_it->used; block_it != NULL;
block_it = block_it->next_used) {
/* i++; */
/* if (i < 10) */
kprintf("%p - %p : %u bytes\n", block_it->ptr,
(uint32_t)block_it->ptr +
block_it->sub_size + sizeof(Block),
block_it->sub_size);
total_size += block_it->sub_size;
}
if (zone_it->used)
kprintf("\n");
count++;
#if FULL_INFO
if (zone_it->free)
kprintf("---------- AVAILABLE %s [n°%d - %p] "
"----------\n",
zones_name[type], count, zone_it);
for (Block *block_it = zone_it->free; block_it != NULL;
block_it = block_it->next_free) {
kprintf("%p - %p : %u bytes\n", block_it->ptr,
(uint32_t)block_it->ptr +
block_it->sub_size + sizeof(Block),
block_it->sub_size);
}
if (zone_it->free)
kprintf("\n");
#endif
}
}
kprintf("Total: %u\n", total_size);
}

116
src/memory/phys/kfree.c Normal file
View File

@ -0,0 +1,116 @@
#include "alloc.h"
#include "kprintf.h"
#include "memory.h"
#include <stdint.h>
static void remove_used(Block *to_free)
{
Block *left = to_free->prev_used;
Block *right = to_free->next_used;
to_free->next_used = NULL;
to_free->prev_used = NULL;
if (!left && !right) {
to_free->zone->used = NULL;
return;
}
if (!left)
to_free->zone->used = right;
else
left->next_used = right;
if (right)
right->prev_used = left;
}
/*
* If all the blocks of the zone have been kfreed,
* we can unmap the zone and delete it from the list of zones
*/
static int unmap_zone(Zone *zone)
{
int err = 0;
block_type_t type = zone->type;
Zone *left = zone->prev;
Zone *right = zone->next;
zone->prev = NULL;
zone->next = NULL;
if (!left && !right) {
kzones[type] = NULL;
goto unmap;
}
if (!left)
kzones[type] = right;
else
left->next = right;
if (right)
right->prev = left;
unmap:
err = free_pages((void *)zone, zone->size);
if (err)
kprintf(KERN_ERR "error: munmap failed\n");
return (err);
}
/*
* If the newly kfreed block is next to another previously
* kfreed block, merge both of these and update the size
*/
static Block *merge_blocks(Block *left, Block *right)
{
if (right->next)
right->next->prev = left;
if (right->next_free) {
right->next_free->prev_free = left;
left->next_free = right->next_free;
}
left->next = right->next;
left->size += right->size + sizeof(Block);
return (left);
}
// Simply add the new block to the list of available blocks
static int add_available(Block *available, Block *merged)
{
Zone *zone = available->zone;
if (merged != zone->free && available != zone->free)
available->next_free = zone->free;
if (zone->free)
zone->free->prev_free = available;
zone->free = available;
if (zone->type == LARGE)
return (unmap_zone(zone));
return (0);
}
/*
* ptr: pointer to kfree, if the pointer is invalid the kfree()
* function will have an undefined behavior (most likely segfault)
*
* First, we remove the block from the list of in_use blocks
* Then, we check if the block needs to be merged with another
* neighboring block, if so we replace the previous block by the
* newly merged block
* Finally, we add the block to the list of available blocks
*/
void kfree(void *ptr)
{
if (ptr == NULL)
return;
Block *to_free = (Block *)((uint32_t)ptr - sizeof(Block));
Block *to_merge = NULL;
to_free->in_use = false;
remove_used(to_free);
if (to_free->prev && !to_free->prev->in_use) {
to_merge = to_free;
to_free = merge_blocks(to_free->prev, to_free);
}
if (to_free->next && !to_free->next->in_use) {
to_merge = to_free->next;
to_free = merge_blocks(to_free, to_free->next);
}
int err = add_available(to_free, to_merge);
if (err)
kprintf(KERN_ERR "kfree: fatal error\n");
}

162
src/memory/phys/kmalloc.c Normal file
View File

@ -0,0 +1,162 @@
#include "alloc.h"
#include "debug.h"
#include "kprintf.h"
#include "terminal.h"
#include <stdint.h>
/*
* Find first available (not in_use) block
* in a zone matching the size we need
*/
static Block *find_block(Zone *head, uint32_t size)
{
for (Zone *zone_it = head; zone_it != NULL; zone_it = zone_it->next) {
for (Block *block_it = zone_it->free; block_it != NULL;
block_it = block_it->next_free) {
assert(block_it);
assert(!block_it->in_use);
if (size <= block_it->size) {
assert(block_it->zone == zone_it);
return (block_it);
}
}
}
return (NULL);
}
// PARTIALLY DEPRECATED
/*
* This will split the newly allocated block to use
* the remaining bytes for a new block
* This is our linked list of blocks
* ... -> [5] -> [6] -> ...
* After the allocation, this will become
* ... -> [5] -> [new] -> [6] -> ...
*
* For an example of [5].size = 32 and requiring a kmalloc of 10
* Let's say the metadata takes a size of 2:
* ... -> [metadata][data][remaining size] -> [6]
* ^ ^ ^
* 2 10 20
*
* So now our block [new] will become:
* [5] -> [metadata][available data] -> [6]
* ^ ^
* 2 18
* We can see that it now has its own metadata and available
* data and it points towards [6]
*/
static void frag_block(Zone *zone, Block *old_block, uint32_t size)
{
Block *new_block = (Block *)align_mem((uint32_t)old_block + size);
assert(new_block <
(Block *)((uint32_t)zone + get_zone_size(zone->type)));
if (old_block->size - align_mem(size) < sizeof(Block)) {
zone->free = NULL;
goto last_block;
}
// Newly created block metadata
new_block->size = old_block->size - align_mem(size);
new_block->sub_size = new_block->size;
new_block->in_use = false;
new_block->ptr = (void *)((uint32_t)new_block + sizeof(Block));
new_block->zone = zone;
new_block->prev = old_block;
new_block->next = old_block->next;
old_block->next = new_block;
new_block->prev_used = NULL;
new_block->next_used = NULL;
new_block->prev_free = old_block->prev_free;
new_block->next_free = NULL;
if (new_block != old_block->next_free)
new_block->next_free = old_block->next_free;
if (zone->free == old_block)
zone->free = new_block;
last_block:
old_block->next_free = NULL;
old_block->prev_free = NULL;
// Newly in_use block metadata
old_block->in_use = true;
old_block->size = size - sizeof(Block);
old_block->sub_size = old_block->size;
if (zone->used == NULL) {
zone->used = old_block;
return;
}
old_block->prev_used = NULL;
old_block->next_used = zone->used;
zone->used->prev_used = old_block;
zone->used = old_block;
}
// Set the block to used and unset free
static void save_block(Zone *head, Block *block, Zone *zone)
{
zone->free = NULL;
block->in_use = true;
if (head->used) {
head->used->prev_used = block;
head->used->prev = block;
block->next = head->used;
block->next_used = head->used;
}
head->used = block;
}
/*
* size: size needed by the user to get allocated
*
* First, we init the allocator if it's the first time
* Then we search if there is an available block in all
* the zones currently mapped
* If no block has been found (NULL), we create 1 new zone of
* the corresponding type
* We then search again for an available block (should not be NULL)
* Finally, if type == LARGE, we just have to change the block to used
* else, we frag the block to use just what's needed
*
* ptr: returns the aligned pointer of the block (after the metadata)
*/
void *kmalloc(uint32_t size)
{
void *ptr = NULL;
if (size == 0) {
kprintf(KERN_WARNING "kmalloc: can't kmalloc(0)\n");
return NULL;
}
// Find the zone we need to search
block_type_t type = get_type(size);
Zone *head = kzones[type];
// Find an available block in a zone of type "type"
Block *available = find_block(head, size);
if (available == NULL) {
uint32_t full_size;
if (type == LARGE)
full_size = size + sizeof(Block) + sizeof(Zone);
else
full_size = get_zone_size(type);
if (new_kzone(type, full_size) == -1)
return NULL;
head = kzones[type];
available = find_block(head, size);
}
assert(available != NULL);
if (type == LARGE)
save_block(head, available, available->zone);
else
frag_block(available->zone, available, size + sizeof(Block));
ptr = available->ptr;
return ptr;
}

View File

@ -0,0 +1,37 @@
#include "alloc.h"
#include "string.h"
#include <stdint.h>
// Prototype for kfree and kmalloc
void kfree(void *ptr);
void *kmalloc(uint32_t size);
/*
* ptr: block to resize (undefined behavior if invalid)
* size: size needed by the user to get kreallocated
*
* If we have a size <= to the previous size, we don't have
* to do anything, we just change sub_size for info purposes
* and return the same pointer
* Else, we allocate a new block and copy the content of
* the previous block in the new one and kfree the old block
*
* ptr: returns the aligned pointer of the kreallocated block
*/
void *krealloc(void *ptr, uint32_t size)
{
void *new_ptr = NULL;
if (ptr == NULL)
return NULL;
Block *block = (Block *)((uint32_t)ptr - sizeof(Block));
if (block->size >= size) {
block->sub_size = size;
return (ptr);
}
new_ptr = kmalloc(size);
if (new_ptr == NULL)
return NULL;
memmove(new_ptr, ptr, block->size);
kfree(ptr);
return (new_ptr);
}

9
src/memory/phys/ksize.c Normal file
View File

@ -0,0 +1,9 @@
#include "alloc.h"
#include <stdint.h>
uint32_t ksize(void *ptr)
{
Block *meta_data = (Block *)((uint32_t)ptr - sizeof(Block));
return meta_data->sub_size;
}

View File

@ -3,18 +3,19 @@
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "task.h"
Zone *zones[3]; Zone *vzones[3];
static void add_zone(Zone *zone, block_type_t type) static void add_zone(Zone *zone, block_type_t type)
{ {
// We put the zone at the beginning of the list // We put the zone at the beginning of the list
if (zones[type]) { if (vzones[type]) {
assert(zones[type] != zone); assert(vzones[type] != zone);
zone->next = zones[type]; zone->next = vzones[type];
zones[type]->prev = zone; vzones[type]->prev = zone;
} }
zones[type] = zone; vzones[type] = zone;
} }
static void new_block(Zone *zone, uint32_t zone_size) static void new_block(Zone *zone, uint32_t zone_size)
@ -48,6 +49,7 @@ static void new_block(Zone *zone, uint32_t zone_size)
int new_vzone(block_type_t type, uint32_t size) int new_vzone(block_type_t type, uint32_t size)
{ {
// assert(current_task->pid);
void *heap = alloc_pages(size, NULL); void *heap = alloc_pages(size, NULL);
if (heap == NULL) { if (heap == NULL) {
kprintf(KERN_ERR "error: alloc_pages failed\n"); kprintf(KERN_ERR "error: alloc_pages failed\n");

View File

@ -12,7 +12,7 @@ void show_valloc_mem(void)
for (block_type_t type = 0; type < 3; ++type) { for (block_type_t type = 0; type < 3; ++type) {
int count = 0; int count = 0;
for (Zone *zone_it = zones[type]; zone_it != NULL; for (Zone *zone_it = vzones[type]; zone_it != NULL;
zone_it = zone_it->next) { zone_it = zone_it->next) {
if (zone_it->used) if (zone_it->used)
kprintf("---------- IN_USE %s [n°%d - %p] " kprintf("---------- IN_USE %s [n°%d - %p] "

View File

@ -37,11 +37,11 @@ static int unmap_zone(Zone *zone)
zone->next = NULL; zone->next = NULL;
if (!left && !right) { if (!left && !right) {
zones[type] = NULL; vzones[type] = NULL;
goto unmap; goto unmap;
} }
if (!left) if (!left)
zones[type] = right; vzones[type] = right;
else else
left->next = right; left->next = right;
if (right) if (right)

View File

@ -52,6 +52,11 @@ static void frag_block(Zone *zone, Block *old_block, uint32_t size)
assert(new_block < assert(new_block <
(Block *)((uint32_t)zone + get_zone_size(zone->type))); (Block *)((uint32_t)zone + get_zone_size(zone->type)));
if (old_block->size - align_mem(size) < sizeof(Block)) {
zone->free = NULL;
goto last_block;
}
// Newly created block metadata // Newly created block metadata
new_block->size = old_block->size - align_mem(size); new_block->size = old_block->size - align_mem(size);
new_block->sub_size = new_block->size; new_block->sub_size = new_block->size;
@ -74,6 +79,7 @@ static void frag_block(Zone *zone, Block *old_block, uint32_t size)
if (zone->free == old_block) if (zone->free == old_block)
zone->free = new_block; zone->free = new_block;
last_block:
old_block->next_free = NULL; old_block->next_free = NULL;
old_block->prev_free = NULL; old_block->prev_free = NULL;
@ -131,7 +137,7 @@ void *vmalloc(uint32_t size)
// Find the zone we need to search // Find the zone we need to search
block_type_t type = get_type(size); block_type_t type = get_type(size);
Zone *head = zones[type]; Zone *head = vzones[type];
// Find an available block in a zone of type "type" // Find an available block in a zone of type "type"
Block *available = find_block(head, size); Block *available = find_block(head, size);
@ -143,7 +149,7 @@ void *vmalloc(uint32_t size)
full_size = get_zone_size(type); full_size = get_zone_size(type);
if (new_vzone(type, full_size) == -1) if (new_vzone(type, full_size) == -1)
return NULL; return NULL;
head = zones[type]; head = vzones[type];
available = find_block(head, size); available = find_block(head, size);
} }
assert(available != NULL); assert(available != NULL);

View File

@ -38,7 +38,7 @@ static void init_vbe(multiboot_info_t *mbd_virt)
((mbd_virt->framebuffer_addr + i * PAGE_SIZE) & PAGE_MASK) | ((mbd_virt->framebuffer_addr + i * PAGE_SIZE) & PAGE_MASK) |
INIT_FLAGS; INIT_FLAGS;
} }
page_directory[800] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03; kernel_pd[800] = ((uint32_t)vbe_page_table - HEAP_END) | 0x03;
display.buff = (uint32_t *)GET_PAGE_ADDR(800, 0) + display.buff = (uint32_t *)GET_PAGE_ADDR(800, 0) +
(mbd_virt->framebuffer_addr % PAGE_SIZE); (mbd_virt->framebuffer_addr % PAGE_SIZE);
display.height = mbd_virt->framebuffer_height; display.height = mbd_virt->framebuffer_height;
@ -53,8 +53,7 @@ void init_multiboot(multiboot_info_t *mbd, uint32_t magic)
kpanic("invalid magic number! (git good skill issue)"); kpanic("invalid magic number! (git good skill issue)");
init_page_table(multiboot_page_table, 0); init_page_table(multiboot_page_table, 0);
page_directory[1023] = kernel_pd[1023] = ((uint32_t)multiboot_page_table - HEAP_END) | 0x03;
((uint32_t)multiboot_page_table - HEAP_END) | 0x03;
size_t pt_index = CEIL( size_t pt_index = CEIL(
(uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE); (uint32_t)mbd % PAGE_SIZE + sizeof(multiboot_info_t), PAGE_SIZE);

26
src/multitasking/fork.c Normal file
View File

@ -0,0 +1,26 @@
#include "interrupts.h"
#include "kprintf.h"
#include "task.h"
uint16_t fork(void)
{
current_task->status = FORKED;
scheduler();
return current_task->child ? current_task->child->pid : 0;
}
void kfork(struct task *daddy)
{
cli();
struct task *child = copy_task(daddy);
if (!child) {
kprintf(KERN_ALERT "Fork failed ! retry at the next loop");
toris();
return;
}
child->daddy = daddy;
daddy->child = child;
daddy->status = RUN;
child->status = RUN;
toris();
}

View File

@ -1,16 +1,35 @@
#include "alloc.h"
#include "debug.h" #include "debug.h"
#include "interrupts.h"
#include "kprintf.h" #include "kprintf.h"
#include "task.h" #include "task.h"
#include "time.h" #include "time.h"
#include <stddef.h>
struct task *current_task; struct task *current_task;
void scheduler(void) void scheduler(void)
{ {
if (!current_task) // ZOMBIE, THREAD, RUN, WAIT, SLEEP, STOPPED, FORKED
void (*func[])(struct task *) = {
zombify_task, NULL, NULL, NULL, NULL, remove_task, kfork,
};
if (!current_task) // || current_task->next == current_task)
return; return;
cli();
switch_pd(kernel_pd, (uint32_t *)((uint32_t)kernel_pd - HEAP_END));
struct task *it = current_task->next; struct task *it = current_task->next;
while (it->status != RUN) while (it && it->status != RUN) {
if (it != current_task && func[it->status]) {
struct task *new_it = it->prev;
func[it->status](it);
it = new_it;
}
it = it->next; it = it->next;
}
switch_to_task(it); switch_to_task(it);
exec_signal_pending();
toris();
} }

View File

@ -9,35 +9,50 @@ switch_to_task:
push edi push edi
push esi push esi
mov eax, [current_task]
// save the current stack pointer to the old stack // save the current stack pointer to the old stack
mov [current_task+0], esp mov [eax+0], esp
mov edi, [esp_backup] // get eip
mov [current_task+16], edi // save instruction before Interrupt
// stack pointer + the 4 regs pushed // stack pointer + the 4 regs pushed
// and + 1 to get the argument (next task) // and + 1 to get the argument (next task)
mov esi, [esp+(4+1)*4] mov esi, [esp+(4+1)*4]
mov [current_task], esi mov [current_task], esi
mov esp, [current_task] // esp mov eax, [current_task]
mov eax, [current_task+4] // esp0
mov ebx, [current_task+8] // cr3
mov [TSS+4], eax // tss.esp0
mov ecx, cr3
// if cr3 hasn't change, do nothing mov esp, [eax+0] // get esp
cmp ecx, ebx
je .END mov ecx, [eax+12] // get task's pd
// mov cr3, ebx mov [current_pd], ecx
mov ecx, [eax+8]
mov cr3, ecx
// TODO replace the eip store in stack by the [current_task+16](current_task->eip)
mov edi, [current_task+16]
mov [esp_backup], edi
.END:
pop esi pop esi
pop edi pop edi
pop ebp pop ebp
pop ebx pop ebx
ret // this will also change eip to the next task's instructions
mov ecx, 0
cmp [eax+16], ecx
je .END
sti
push [eax+16] // store func_ptr
mov [eax+16], ecx // clear eip in current_task
push 0
call pic_send_eoi
pop edx // remove pic_send_eoi argument
pop edx // get func_ptr
call edx
call exit_task
.END:
ret

View File

@ -1,40 +1,73 @@
#include "task.h" #include "task.h"
#include "alloc.h" #include "alloc.h"
#include "debug.h" #include "debug.h"
#include "interrupts.h"
#include "kpanic.h" #include "kpanic.h"
#include "kprintf.h" #include "kprintf.h"
#include "memory.h" #include "memory.h"
#include "string.h"
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
uint32_t esp_backup; uint32_t esp_backup;
static struct task *create_task(uint8_t owner_id) struct task *create_task(uint8_t uid)
{ {
static uint32_t pid = 1; static uint32_t pid = 1;
switch_pd(kernel_pd, (uint32_t *)((uint32_t)kernel_pd - HEAP_END));
struct task *new_task = vmalloc(sizeof(struct task)); struct task *new_task = vmalloc(sizeof(struct task));
if (!new_task) if (!new_task) {
switch_pd(current_task->heap, current_task->cr3);
return NULL; return NULL;
new_task->owner_id = owner_id; }
switch_pd(current_task->heap, current_task->cr3);
new_task->status = RUN;
new_task->uid = uid;
new_task->esp = new_task->esp0 + STACK_SIZE;
new_task->pid = pid++; new_task->pid = pid++;
// Allocate new pd
new_task->heap = alloc_pages(4096, (void **)&new_task->cr3); new_task->heap = alloc_pages(4096, (void **)&new_task->cr3);
if (!new_task->heap) { if (!new_task->heap) {
vfree(new_task); vfree(new_task);
return NULL; return NULL;
} }
new_task->heap[768] = ((uint32_t)boot_page_table1 - HEAP_END) | 0x03;
memcpy(new_task->heap, current_task->heap, 4096);
switch_pd(new_task->heap, new_task->cr3);
// Allocate new stack on the newly allocated pd
new_task->esp0 = alloc_pages(STACK_SIZE, NULL);
switch_pd(current_task->heap, current_task->cr3);
if (!new_task->esp0) {
vfree(new_task);
free_pages(new_task->heap, 4096);
return NULL;
}
new_task->next = current_task->next;
new_task->prev = current_task;
current_task->next = new_task;
new_task->signals.pending = SIG_IGN;
return new_task; return new_task;
} }
int create_kernel_task(void) int8_t create_kernel_task(void)
{ {
struct task *new_task = vmalloc(sizeof(struct task)); struct task *new_task = vmalloc(sizeof(struct task));
if (!new_task) if (!new_task)
return 1; return -1;
new_task->owner_id = 0; new_task->status = RUN;
new_task->uid = 0;
new_task->pid = 0; new_task->pid = 0;
new_task->heap = page_directory; new_task->heap = kernel_pd;
new_task->cr3 = (uint32_t *)((uint32_t)kernel_pd - HEAP_END);
new_task->prev = new_task; new_task->prev = new_task;
new_task->next = new_task; new_task->next = new_task;
new_task->signals.pending = SIG_IGN;
current_task = new_task; current_task = new_task;
return 0; return 0;
} }
@ -44,16 +77,60 @@ void exec_fn(void (*fn)(void))
struct task *new_task = create_task(OWNER_KERNEL); struct task *new_task = create_task(OWNER_KERNEL);
if (!new_task) if (!new_task)
kpanic("failed to create new task"); kpanic("failed to create new task");
new_task->status = RUN;
new_task->eip = (uint32_t *)fn; new_task->eip = (uint32_t *)fn;
new_task->prev = current_task;
new_task->next = current_task->next;
current_task->next = new_task;
} }
/* void zombify_task(struct task *task)
* Create task {
* Allocate new pd => kmalloc(4096) cli(); // Technically useless
* Add pd address to the struct task free_pages(task->heap, 4096);
* free_pages(task->esp0, STACK_SIZE);
*/ task->esp0 = NULL;
task->heap = NULL;
toris();
}
void remove_task(struct task *task)
{
cli();
struct task *left = task->prev;
struct task *right = task->next;
if (task->child) {
remove_task(task->child);
task->child = NULL;
}
if (task->heap)
free_pages(task->heap, 4096);
if (task->esp0)
free_pages(task->esp0, STACK_SIZE);
left->next = right;
right->prev = left;
vfree(task);
toris();
}
struct task *copy_task(const struct task *task)
{
struct task *new_task = create_task(task->uid);
if (!new_task)
return NULL;
memcpy(new_task->esp0, task->esp0, STACK_SIZE);
new_task->esp = new_task->esp0 + (task->esp - task->esp0);
new_task->status = task->status;
return new_task;
}
void exit_task(void)
{
cli();
if (current_task->daddy && current_task->daddy->status != WAIT)
current_task->status = ZOMBIE;
else {
if (current_task->daddy->status == WAIT)
current_task->daddy->status = RUN;
current_task->status = STOPPED;
}
toris();
scheduler();
}

17
src/multitasking/wait.c Normal file
View File

@ -0,0 +1,17 @@
#include "interrupts.h"
#include "task.h"
uint16_t wait(void)
{
if (current_task->child == NULL)
return -1;
cli();
if (current_task->child->status == ZOMBIE)
current_task->child->status = STOPPED;
else
current_task->status = WAIT;
uint16_t child_pid = current_task->child->pid;
toris();
scheduler();
return child_pid;
}

19
src/panic.s Normal file
View File

@ -0,0 +1,19 @@
.intel_syntax noprefix
.section .text
.global panic
panic:
xor eax, eax
xor ebx, ebx
xor ecx, ecx
xor edx, edx
xor esp, esp
xor ebp, ebp
xor esi, esi
xor edi, edi
cli
loop:
hlt
jmp loop

View File

@ -0,0 +1,19 @@
#include "keyboard.h"
#include "kprintf.h"
#include "string.h"
extern char const **keymap;
void layout_cmd(char *arg)
{
if (!strcmp(arg, "us") || !strcmp(arg, "qwerty")) {
kprintf("Successfully changed layout to us/qwerty\n");
keymap = qwerty_keymap;
} else if (!strcmp(arg, "fr") || !strcmp(arg, "azerty")) {
kprintf("Successfully changed layout to fr/azerty\n");
keymap = azerty_keymap;
} else {
kprintf(
"Invalid argument: please type us|qwerty or fr|azerty\n");
}
}

View File

@ -30,6 +30,7 @@ const struct shell_command cmds[] = {
{"date", "Display the current time and date", date_cmd}, {"date", "Display the current time and date", date_cmd},
{"merdella", "Surprise", merdella_cmd}, {"merdella", "Surprise", merdella_cmd},
{"color", "Change the screen color", color_cmd}, {"color", "Change the screen color", color_cmd},
{"layout", "Change the current layout (us or fr)", layout_cmd},
}; };
#define NB_CMDS ARRAY_SIZE(cmds) #define NB_CMDS ARRAY_SIZE(cmds)

49
src/signal/signal.c Normal file
View File

@ -0,0 +1,49 @@
#include "signal.h"
#include "kprintf.h"
#include "task.h"
#include <stdint.h>
void signal(SIGNAL_CODE sig_num, void *handler)
{
current_task->signals.handlers[sig_num] = handler;
}
void kill(int pid, SIGNAL_CODE sig_num)
{
struct task *task = current_task;
while (task->pid != pid)
task = task->next;
task->signals.pending = sig_num;
}
static void display_signal(SIGNAL_CODE sig_num)
{
kprintf("signal: %d\n", sig_num);
}
static void exec_signal(SIGNAL_CODE sig_num)
{
void *handler = current_task->signals.handlers[sig_num];
if (handler == SIG_IGN)
return;
if (handler == SIG_DFL) {
display_signal(sig_num);
return;
}
signal_handler_t func = handler;
func(sig_num);
}
void exec_signal_pending(void)
{
uint32_t signal_code = current_task->signals.pending;
if (signal_code != SIG_IGN) {
exec_signal(signal_code);
current_task->signals.pending = SIG_IGN;
}
}

View File

@ -8,5 +8,5 @@ uintptr_t __stack_chk_guard = STACK_CHK_GUARD;
__attribute__((noreturn)) void __stack_chk_fail(void) __attribute__((noreturn)) void __stack_chk_fail(void)
{ {
kpanic("Stack smashing detected"); kpanic("Stack smashing detected\n");
} }

View File

@ -4,6 +4,8 @@
#include "sys/io.h" #include "sys/io.h"
#include "terminal.h" #include "terminal.h"
char const **keymap = qwerty_keymap;
struct key_event terminal_getkey(void) struct key_event terminal_getkey(void)
{ {
static bool caps_mode = false; static bool caps_mode = false;

View File

@ -2,7 +2,7 @@
#include "debug.h" #include "debug.h"
#include "font.h" #include "font.h"
#include "fonts/consolas_regular_13.h" #include "fonts/consolas_regular_13.h"
/* #include "icons/image.h" */ // #include "icons/image.h"
#include "kprintf.h" #include "kprintf.h"
#include "shell.h" #include "shell.h"
#include "string.h" #include "string.h"
@ -28,7 +28,7 @@ void terminal_initialize(void)
screens[i].column = 0; screens[i].column = 0;
screens[i].default_color = 0xffffff; screens[i].default_color = 0xffffff;
screens[i].fg_color = screens[i].default_color; screens[i].fg_color = screens[i].default_color;
/* screens[i].background = &image_icon; */ // screens[i].background = &image_icon;
screens[i].font = consolas_regular_13_font; screens[i].font = consolas_regular_13_font;
memset(screens[i].line, 0, sizeof(screen->line)); memset(screens[i].line, 0, sizeof(screen->line));
} }
@ -52,13 +52,12 @@ void terminal_remove_last_char(void)
for (uint32_t x = 0; x < node.width; x++) { for (uint32_t x = 0; x < node.width; x++) {
// Current bg is taking too much memory // Current bg is taking too much memory
// so we do a black bg for now // so we do a black bg for now
/* struct icon *bg = screen->background; */ // struct icon *bg = screen->background;
/* uint32_t pixel = 0; */ // uint32_t pixel = 0;
/* if (bg->width > pos_x + x && bg->height > pos_y + y) // if (bg->width > pos_x + x && bg->height > pos_y + y)
*/ // pixel = bg->pixels[(pos_y + y) * bg->width +
/* pixel = bg->pixels[(pos_y + y) * bg->width + */ // (pos_x + x)];
/* (pos_x + x)]; */ put_pixel(0, pos_x + x, pos_y + y + node.yoffset);
put_pixel(0, pos_x + x, pos_y + y);
} }
} }
} }