diff --git a/src/idt.c b/src/idt.c index 9bac021..6d57aa3 100644 --- a/src/idt.c +++ b/src/idt.c @@ -67,6 +67,9 @@ void init_idt(void) .Type = 0x06, .D = 1, .DPL = 0, .P = 1 }); } + idt[14] = init_gate((struct interrupt_gate_param) { .Offset = (u32) _asm_page_fault, .SegSelect = 0x08, + .Type = 0x06, .D = 1, .DPL = 0, .P = 1 }); + idt[32] = init_gate((struct interrupt_gate_param) { .Offset = (u32) _asm_irq_0, .SegSelect = 0x08, .Type = 0x06, .D = 1, .DPL = 0, .P = 1 }); diff --git a/src/int.S b/src/int.S index dfb5c46..fbadc20 100644 --- a/src/int.S +++ b/src/int.S @@ -1,5 +1,5 @@ -.extern isr_default_int, isr_clock_int, isr_kbd_int, syscall_handler -.global _asm_default_int, _asm_irq_0, _asm_irq_1, _asm_sycall_handler +.extern isr_default_int, isr_clock_int, isr_kbd_int, syscall_handler, isr_page_fault +.global _asm_default_int, _asm_irq_0, _asm_irq_1, _asm_sycall_handler, _asm_page_fault _asm_default_int: pushal @@ -19,6 +19,24 @@ _asm_default_int: popal iret +_asm_page_fault: + pushal + push %ds + push %es + push %fs + push %gs + push %ebx + mov $0x10,%bx + mov %bx,%ds + pop %ebx + call isr_page_fault + pop %gs + pop %fs + pop %es + pop %ds + popal + iret + _asm_irq_0: pushal push %ds diff --git a/src/int.h b/src/int.h index cc85126..2805ade 100644 --- a/src/int.h +++ b/src/int.h @@ -2,6 +2,7 @@ #define INT_H void _asm_default_int(void); +void _asm_page_fault(void); void _asm_irq_0(void); void _asm_irq_1(void); int _asm_sycall_handler(int eax, int ebx); diff --git a/src/isr.c b/src/isr.c index 5740a90..3c14e8f 100644 --- a/src/isr.c +++ b/src/isr.c @@ -10,6 +10,11 @@ void isr_default_int(void) DEBUG_INFO("An INT has been raised, entering default interrupt handler."); } +void isr_page_fault(void) +{ + DEBUG_INFO("A page fault exception occured"); +} + void isr_clock_int(void) { DEBUG_INFO("Enterring clock interrupt handler."); diff --git a/src/kernel.c b/src/kernel.c index 3f77bee..139551c 100644 --- a/src/kernel.c +++ b/src/kernel.c @@ -8,6 +8,7 @@ #include "tss.h" #include "launch_process.h" #include "elf.h" +#include "userland.h" extern char _binary_a_out_start[]; extern char _binary_a_out_end[]; @@ -21,9 +22,44 @@ void main(void) char *data_end = _binary_a_out_end; size_t data_size = (size_t)_binary_a_out_size; - load_elf(data_start); - launch_process(0x28, 0x30000, 0x20, 0x18, 0x20); + create_new_userland_page(0); + + DEBUG_INFO("PAGE DIR: %d", userland_data->userland_data[0].page_directories); + struct page_table_entry *ttt = userland_data->userland_data[0].page_directories[20].address << 12; + DEBUG_INFO("PAGE DIR: %d", ttt->address); + + asm volatile (" \ + mov $0x3020000, %eax \n \ + mov %eax, %cr3"); + + // DEBUG_INFO("BIN %b", 0x13000000); + allocate_new_page(0, 0x32400000); + + // asm volatile (" \ + // xor $0x80000000, %eax \n \ + // mov %eax, %cr0"); + + // u32 *data2 = 50466816; + // DEBUG_INFO("BIN %b", *data2); + + // u32 *data = 83886080; + // DEBUG_INFO("BIN %b", *data); + + // struct page_directory_entry *var = 0x3020000; + // DEBUG_INFO("address %d", var[76].address); + + // u32 *var = 0x13000000; + u32 *var = 0x32403400; + *var = 10; + DEBUG_INFO("%d", *var); + // asm volatile (" \ + // mov %0, %%eax \n \ + // mov %%eax, %%cr3" : "=m" (userland_data->userland_data[0].page_directories)); + + // load_elf(data_start); + + // launch_process(0x28, 0x30000, 0x20, 0x18, 0x20); for (;;) { @@ -41,7 +77,7 @@ void kernel_main(void) init_gdt(); init_idt(); pic_init(); - make_page(); + create_kernel_page(); asm volatile ("sti"); main(); diff --git a/src/paging.c b/src/paging.c index 02d4299..df55990 100644 --- a/src/paging.c +++ b/src/paging.c @@ -2,11 +2,17 @@ #include "debug.h" #include "serial.h" +#include "userland.h" struct page_directory_entry *page_dir; // = 0x3000000; //__attribute__((aligned(4096))); struct page_table_entry *page_table; // = 0x3010000; //__attribute__((aligned(4096))); -u8 page_avl[131072] = { 0 }; -int page_avl_index = 0x300000 / 8; +u8 page_avl[131072] = {0}; +int page_avl_index = (USERLAND_BASE_ADDRESS >> 12) / 8; +int userland_page_dir_index = 0; + +#define KERNEL_PAGE_DIR 0x3000000 +#define KERNEL_PAGE_TABLE 0x3010000 +#define NB_KERNEL_PAGE_DIR 20 int find_page_avl(void) { @@ -14,7 +20,7 @@ int find_page_avl(void) for (int j = 0; j < 8; j++) { if ((page_avl[i] & (1 << j)) == 0) { page_avl_index = i; - return i * 8 + j; + return (i * 8 + j) << 12; } } } @@ -25,7 +31,13 @@ int find_page_avl(void) void set_page(int address) { - page_avl[address / 8] |= (1 << (address % 8)); + page_avl[(address >> 12) / 8] |= (1 << ((address >> 12) % 8)); +} + +void clear_page(int address) +{ + page_avl[(address >> 12) / 8] |= (1 << ((address >> 12) % 8)); + page_avl[(address >> 12) / 8] ^= (1 << ((address >> 12) % 8)); } struct page_directory_param { @@ -95,24 +107,27 @@ struct page_table_entry create_page_table_entry(struct page_table_param param) return page_table; } -int make_page(void) +int create_kernel_page(void) { - page_dir = (struct page_directory_entry *) 0x3000000; - page_table = (struct page_table_entry *) 0x3010000; + page_dir = (struct page_directory_entry *) KERNEL_PAGE_DIR; + page_table = (struct page_table_entry *) KERNEL_PAGE_TABLE; - for (int i = 0; i < 1024; i++) + for (int i = 0; i < NB_KERNEL_PAGE_DIR; i++) { - page_table[i] = create_page_table_entry((struct page_table_param) { - .P = 1, .R_W = 1, .U = 1, .PWT = 0, .PCD = 0, - .A = 0, .D = 0, .PAT = 0, .G = 0, - .address = 1 * i}); + for (int j = 0; j < 1024; j++) + { + page_table[i * 1024 + j] = create_page_table_entry((struct page_table_param) { + .P = 1, .R_W = 1, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .D = 0, .PAT = 0, .G = 0, + .address = j + i * 1024}); + } + DEBUG_INFO("PAGE_TABLE %d", &page_table[i * 1024]); + page_dir[i] = create_page_directory_entry((struct page_directory_param) { + .P = 1, .R_W = 1, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .PS = 0, .address = &page_table[i * 1024]}); } - page_dir[0] = create_page_directory_entry((struct page_directory_param) { - .P = 1, .R_W = 1, .U = 1, .PWT = 0, .PCD = 0, - .A = 0, .PS = 0, .address = page_table}); - - for (int i = 1; i < 1024; i++) + for (int i = NB_KERNEL_PAGE_DIR; i < 1024; i++) { page_dir[i] = create_page_directory_entry((struct page_directory_param) { .P = 0, .R_W = 0, .U = 0, .PWT = 0, .PCD = 0, @@ -167,3 +182,112 @@ int make_page(void) return 0; } + +int create_new_userland_page(int uid) +{ + struct page_directory_entry *userland_page_dir = userland_data->userland_data[uid].page_directories; + struct page_table_entry *kernel_page_table = (struct page_table_entry *) KERNEL_PAGE_TABLE; + + for (int i = 0; i < NB_KERNEL_PAGE_DIR; i++) + { + DEBUG_INFO("PAGE_TABLE %d", &kernel_page_table[i * 1024]); + userland_page_dir[i] = create_page_directory_entry((struct page_directory_param) { + .P = 1, .R_W = 1, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .PS = 0, .address = &kernel_page_table[i * 1024]}); + } + + for (int i = 0; i < 1024; i++) + { + int avl_address = find_page_avl(); + set_page(avl_address); + userland_data->userland_data[uid].page_table[i] = create_page_table_entry((struct page_table_param) { + .P = 1, .R_W = 1, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .D = 0, .PAT = 0, .G = 0, + .address = (avl_address >> 12)}); + } + + userland_page_dir[NB_KERNEL_PAGE_DIR] = create_page_directory_entry((struct page_directory_param) { + .P = 1, .R_W = 1, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .PS = 0, .address = userland_data->userland_data[uid].page_table}); + + for (int i = NB_KERNEL_PAGE_DIR + 1; i < 1024; i++) + { + userland_page_dir[i] = create_page_directory_entry((struct page_directory_param) { + .P = 0, .R_W = 0, .U = 0, .PWT = 0, .PCD = 0, + .A = 0, .PS = 0, .address = 0}); + } +} + +// int find_empty_page(struct page_directory_entry *page_dir) +// { +// for (int i = 20; i < 1024; i++) +// { +// if (page_dir[i].address == 0) +// { +// int page_table_entry = 0; +// if (i != 20) +// { +// if ((page_table_entry = find_empty_page_table(page_dir[i - 1].address)) != -1) +// return (i - 1, ) +// } +// } +// } +// return -1; +// } + +// int find_empty_page_table(struct page_table_entry *page_table) +// { +// for (int i = 0; i < 1024; i++) +// { +// if (page_table[i].address == 0) +// { +// return i; +// } +// } +// return -1; +// } + +// int find_last_page_dir_entry(struct page_directory_entry *page_dir) +// { +// for (int i = NB_KERNEL_PAGE_DIR; i < 1024; i++) +// { +// if (page_dir[i].address == 0) +// return i - 1; +// } +// return -1; +// } + +int allocate_new_page(int uid, int address) +{ + struct page_directory_entry *userland_page_dir = userland_data->userland_data[uid].page_directories; + + int dir_address = address >> 22; + int table_address = (address >> 12) ^ ((address >> 22) << 10); + + DEBUG_INFO("dir_address %d", dir_address); + DEBUG_INFO("table_address %d", table_address); + + // CPU does't use page table when decoding page table, so it need the physical address + int new_page_table_real = (int) userland_data->userland_data[uid].page_table[dir_address].address; + struct page_table_entry *new_page_table = USERLAND_BASE_ADDRESS + dir_address * 1024 * 4; + + if (userland_page_dir[dir_address].address != 0 && new_page_table->address != 0) + clear_page(new_page_table->address); + + if (userland_page_dir[dir_address].address == 0) + { + userland_page_dir[dir_address] = create_page_directory_entry((struct page_directory_param) { + .P = 1, .R_W = 1, .U = 1, .PWT = 0, .PCD = 0, + .A = 0, .PS = 0, .address = new_page_table_real << 12}); + } + + for (struct page_table_entry *i = new_page_table; i < new_page_table + 1024; i++) + { + int avl_address = find_page_avl(); + set_page(avl_address); + *i = create_page_table_entry((struct page_table_param) { + .P = 1, .R_W = 1, .U = 1, .PWT = 0, .PCD = 0, + .A = 0, .D = 0, .PAT = 0, .G = 0, + .address = (avl_address >> 12)}); + } +} diff --git a/src/paging.h b/src/paging.h index f5ca0db..ebb0857 100644 --- a/src/paging.h +++ b/src/paging.h @@ -16,7 +16,8 @@ struct page_table_entry { u32 address : 20; } __attribute__((packed)); -int make_page(void); +int create_kernel_page(void); +int allocate_new_page(int uid, int address); // extern struct page_directory_entry page_dir[1024]; // extern struct page_table_entry page_table[1024]; diff --git a/src/serial.c b/src/serial.c index ba59ba2..143a771 100644 --- a/src/serial.c +++ b/src/serial.c @@ -24,6 +24,14 @@ int init_serial() int write_serial_nb(int nb, int ln) { + if (nb < 0) + { + while ((inb(PORT + 5) & 0x20) == 0); + outb(PORT, '-'); + write_serial_nb(-nb, ln); + return 0; + } + if (nb < 10) { while ((inb(PORT + 5) & 0x20) == 0); diff --git a/src/userland.c b/src/userland.c index 8555bd6..9662161 100644 --- a/src/userland.c +++ b/src/userland.c @@ -1,5 +1,7 @@ #include "userland.h" +struct userlands_data *userland_data = 0x3020000; + // void userland(void) // { // int res = 0; diff --git a/src/userland.h b/src/userland.h index 86da88f..97b22fb 100644 --- a/src/userland.h +++ b/src/userland.h @@ -1,6 +1,25 @@ #ifndef USERLAND_H #define USERLAND_H +#include +#include "paging.h" + +#define USERLAND_BASE_ADDRESS 0x5000000 + +struct userland_data +{ + struct page_directory_entry page_directories[1024]; + struct page_table_entry page_table[1024]; +}; + + +struct userlands_data { + struct userland_data userland_data[128]; + u32 page_dir[4]; +}; + +extern struct userlands_data *userland_data; + void userland(void); #endif /* !USERLAND_H */