Stash pop
This commit is contained in:
parent
e35fd04d1b
commit
f7503e6c6f
21
Makefile
21
Makefile
@ -18,7 +18,7 @@ AR = $(shell cat psinfo/$(PLAT)/ar.txt)
|
||||
NASM = $(shell cat psinfo/$(PLAT)/nasm.txt)
|
||||
EMU = $(shell cat psinfo/$(PLAT)/emu.txt)
|
||||
CFLAGS = -Isysroot/usr/include -Wextra -Wall -Wno-unused-parameter -g -ffreestanding
|
||||
QFLAGS = -hda ext2.img -m 2G -boot d -cdrom os.iso -serial file:serout #-chardev socket,id=s1,port=3000,host=localhost -serial chardev:s1
|
||||
QFLAGS = -m 2G -boot d -cdrom os.iso -serial file:serout #-chardev socket,id=s1,port=3000,host=localhost -serial chardev:s1
|
||||
CWD = $(shell pwd)
|
||||
|
||||
.PHONY: sysroot
|
||||
@ -31,19 +31,29 @@ run: os.iso
|
||||
@$(EMU) $(QFLAGS) &
|
||||
tail -f serout
|
||||
|
||||
run_nobuild:
|
||||
rm -f serout
|
||||
touch serout
|
||||
@$(EMU) $(QFLAGS) &
|
||||
tail -f serout
|
||||
|
||||
debug: os.iso kernel/kernel.elf
|
||||
@$(EMU) -s $(QFLAGS) &
|
||||
gdb
|
||||
#gdbgui -g i386-elf-gdb --project $(CWD)
|
||||
|
||||
os.iso: kernel/kernel.elf init vfs devfs vga_drv initrd_drv tar_fs pci sysroot/usr/share/man # vfs devfs initrd vga_drv initrd_drv pci
|
||||
os.iso: kernel/kernel.elf init vfs devfs vga_drv initrd_drv tar_fs pci ps2 sysroot/usr/share/man # vfs devfs initrd vga_drv initrd_drv pci
|
||||
@cp kernel/kernel.elf sysroot/boot
|
||||
@cd initrd; tar -f ../sysroot/boot/initrd.tar -c *
|
||||
@grub-mkrescue -o $@ sysroot >/dev/null 2>/dev/null
|
||||
@grub-mkrescue -o $@ sysroot
|
||||
|
||||
crts: kernel/crt0.o
|
||||
@cp $^ sysroot/usr/lib
|
||||
|
||||
ps2: crts libc
|
||||
@cd $@ && make
|
||||
@cp $@/$@ initrd/$@
|
||||
|
||||
init: crts libc
|
||||
@cd $@ && make
|
||||
@cp $@/$@ initrd/$@
|
||||
@ -107,3 +117,8 @@ clean:
|
||||
doc: $(C_SOURCES) $(C_HEADERS)
|
||||
@doxygen kernel/Doxyfile > /dev/null
|
||||
@doxygen libc/Doxyfile > /dev/null
|
||||
|
||||
install:
|
||||
@echo Path to flash drive?; \
|
||||
read drive; \
|
||||
echo $$(drive);
|
||||
|
@ -123,5 +123,7 @@ int main() {
|
||||
serial_print("Could not open the VGA device file!\n");
|
||||
exit(1);
|
||||
}
|
||||
posix_spawn(NULL,"/initrd/pci",NULL,NULL,NULL,NULL);
|
||||
posix_spawn(NULL,"/initrd/ps2",NULL,NULL,NULL,NULL);
|
||||
// posix_spawn(NULL,"/initrd/pci",NULL,NULL,NULL,NULL);
|
||||
for(;;);
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ TYPEDEF_HIDES_STRUCT = YES
|
||||
EXTRACT_STATIC = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARN_AS_ERROR = YES
|
||||
INPUT = /Users/peterterpstra/Desktop/projects/os/kernel
|
||||
INPUT = ./kernel
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = kernel/cpu/x86_64
|
||||
HTML_DYNAMIC_SECTIONS = YES
|
||||
|
@ -34,7 +34,7 @@ typedef struct {
|
||||
|
||||
#define IDT_ENTRIES 256 //!< Number of entries in the IDT
|
||||
|
||||
static idt_gate_t idt[IDT_ENTRIES]; //!< The IDT
|
||||
idt_gate_t idt[IDT_ENTRIES] __attribute__((aligned(4096))); //!< The IDT
|
||||
static idt_register_t idt_reg; //!< The value to load into the IDTR
|
||||
|
||||
#define LOW_16(address) (uint16_t)((address) & 0xFFFF) //!< Macro to get the low 16 bits of an address
|
||||
|
@ -6,7 +6,6 @@
|
||||
#include "../../vga_err.h"
|
||||
#include "../../address_spaces.h"
|
||||
#include "../halt.h"
|
||||
#include "../isr.h"
|
||||
#include "../paging.h"
|
||||
#include "../serial.h"
|
||||
//#include "../../rpc.h"
|
||||
@ -20,8 +19,15 @@
|
||||
#include <sys/syscalls.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
void irq_handler(registers_t* r);
|
||||
static isr_t irq_handlers[16]; //!< Handlers for the PIC interrupts
|
||||
/**
|
||||
* Represents a registeted interrupt handler
|
||||
*/
|
||||
typedef struct {
|
||||
pid_t pid; //!< The PID thast registered the handler, or 0 if it it a kernel handler
|
||||
void* handler; //!< The address of the handler
|
||||
} isr_handler_info;
|
||||
|
||||
static isr_handler_info irq_handlers[16]={0}; //!< Handlers for the PIC interrupts
|
||||
|
||||
void isr_install() {
|
||||
idt_set_gate(0,(uint32_t)isr0);
|
||||
@ -203,7 +209,7 @@ void isr_handler(registers_t* r) {
|
||||
case 80:
|
||||
switch (r->eax) {
|
||||
case SYSCALL_CREATEPROC:
|
||||
tasking_create_task((void*)r->ebx,(void*)r->ecx,0,(void*)r->edx,(void*)r->esi,0);
|
||||
tasking_create_task((void*)r->ebx,(void*)r->ecx,0,(void*)r->edx,(void*)r->esi,0,0);
|
||||
break;
|
||||
case SYSCALL_YIELD:
|
||||
tasking_yield();
|
||||
@ -259,7 +265,7 @@ void isr_handler(registers_t* r) {
|
||||
memcpy((char*)r->ebx,initrd,initrd_sz);
|
||||
break;
|
||||
case SYSCALL_NEW_THREAD: {
|
||||
uint32_t tid=tasking_new_thread((void*)r->ebx,tasking_get_PID(),(void*)r->edx);
|
||||
uint32_t tid=tasking_new_thread((void*)r->ebx,tasking_get_PID(),(void*)r->edx,0);
|
||||
if ((uint32_t*)r->ecx!=NULL) {
|
||||
*((uint32_t*)r->ecx)=tid;
|
||||
}
|
||||
@ -289,7 +295,8 @@ void isr_handler(registers_t* r) {
|
||||
case SYSCALL_RPC_IS_INIT:
|
||||
r->ecx=kernel_rpc_is_init((pid_t)r->ebx);
|
||||
break;
|
||||
default:
|
||||
case SYSCALL_REGISTER_IRQ_HANDLER:
|
||||
isr_register_handler((int)r->ebx,tasking_get_PID(),(void*)r->ecx);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -298,11 +305,12 @@ void isr_handler(registers_t* r) {
|
||||
}
|
||||
|
||||
|
||||
void isr_register_handler(int n,isr_t handler) {
|
||||
void isr_register_handler(int n,pid_t pid,void* handler) {
|
||||
if (n>16) {
|
||||
return;
|
||||
}
|
||||
irq_handlers[n] = handler;
|
||||
irq_handlers[n].pid = pid;
|
||||
irq_handlers[n].handler = handler;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -315,12 +323,12 @@ void irq_handler(registers_t* r) {
|
||||
if (r->int_no >= 40) port_byte_out(0xA0,0x20); /* slave */
|
||||
port_byte_out(0x20,0x20); /* master */
|
||||
/* Handle the interrupt in a more modular way */
|
||||
if (irq_handlers[r->int_no-32] != NULL) {
|
||||
isr_t handler = irq_handlers[r->int_no-32];
|
||||
if((uint32_t)handler<32768) {
|
||||
kernel_rpc_call((pid_t)handler,"irq_handler",NULL,NULL);
|
||||
if (irq_handlers[r->int_no-32].handler!=NULL) {
|
||||
isr_handler_info info = irq_handlers[r->int_no-32];
|
||||
if(info.pid==0) {
|
||||
((isr_t)info.handler)(r);
|
||||
} else {
|
||||
handler(r);
|
||||
tasking_new_thread(info.handler,info.pid,(void*)(r->int_no-32),1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define ISR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Saved state of the CPU when an interrupt occurs
|
||||
@ -38,9 +39,12 @@ void isr_install();
|
||||
|
||||
/**
|
||||
* Register an IRQ handler
|
||||
* \param n the IRQ to register a handler for
|
||||
* \param handler the handler to register
|
||||
*
|
||||
* If the PID is 0, the handler will be called directly, otherwise a thread will be made in the PID starting at the handler's address.
|
||||
* \param n The IRQ to register a handler for
|
||||
* \param pid The PID that will handle the interrupt.
|
||||
* \param handler The address of the handler.
|
||||
*/
|
||||
void isr_register_handler(int n,isr_t handler);
|
||||
void isr_register_handler(int n,pid_t pid,void* handler);
|
||||
|
||||
#endif
|
||||
|
@ -190,6 +190,18 @@ void unmap_pages(void* start_virt,int num_pages,int free_phys) {
|
||||
}
|
||||
}
|
||||
|
||||
extern int idt;
|
||||
|
||||
/**
|
||||
* Makes the IDT readonly
|
||||
*/
|
||||
void paging_readonly_idt() {
|
||||
void* idt_addr=&idt;
|
||||
void* idt_phys=virt_to_phys(idt_addr);
|
||||
map_pages(idt_addr,idt_phys,1,0,0);
|
||||
invl_page(idt_addr);
|
||||
}
|
||||
|
||||
void paging_init() {
|
||||
for (size_t i=0;i<NUM_KERN_FRAMES;i++) {
|
||||
pg_struct_entry* entry=&kern_page_tables[i];
|
||||
|
@ -49,7 +49,7 @@ switch_to_thread_asm:
|
||||
|
||||
global task_init
|
||||
|
||||
; Switch to usermode, given a usermode stack and EIP to switch to
|
||||
; Switch to usermode and enable interrupts, given a usermode stack and EIP to switch to
|
||||
|
||||
task_init:
|
||||
pop ecx ; ecx = user ESP
|
||||
@ -69,6 +69,26 @@ task_init:
|
||||
push ebx ; push user EIP
|
||||
iret
|
||||
|
||||
|
||||
global task_init_no_int
|
||||
|
||||
; Switch to usermode, given a usermode stack and EIP to switch to
|
||||
|
||||
task_init_no_int:
|
||||
pop ecx ; ecx = user ESP
|
||||
pop ebx ; ebx = user EIP
|
||||
mov ax, 0x23 ; Load data segment selectors with the usermode data segment
|
||||
mov ds, ax
|
||||
mov es, ax
|
||||
mov fs, ax
|
||||
mov gs, ax
|
||||
push 0x23 ; Push SS
|
||||
push ecx ; push user ESP
|
||||
pushf ; push flagstrew
|
||||
push 0x1B ; push CS
|
||||
push ebx ; push user EIP
|
||||
iret
|
||||
|
||||
global wait_for_unblocked_thread_asm
|
||||
|
||||
wait_for_unblocked_thread_asm:
|
||||
|
@ -56,7 +56,7 @@ static int new_kstack() {
|
||||
return num;
|
||||
}
|
||||
|
||||
void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip) {
|
||||
void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip,char is_irq_handler) {
|
||||
size_t kstack_num=new_kstack();
|
||||
if (kmode) {
|
||||
size_t top_idx=(1024*(kstack_num+1));
|
||||
@ -74,7 +74,11 @@ void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip)
|
||||
user_stack[0]=param2;
|
||||
user_stack[1]=param1;
|
||||
});
|
||||
if (is_irq_handler) {
|
||||
kstacks[top_idx-3]=(void*)task_init_no_int;
|
||||
} else {
|
||||
kstacks[top_idx-3]=(void*)task_init;
|
||||
}
|
||||
kstacks[top_idx-2]=(void*)user_stack;
|
||||
kstacks[top_idx-1]=(void*)eip;
|
||||
}
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define ISR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Saved state of the CPU when an interrupt occurs
|
||||
@ -38,9 +39,12 @@ void isr_install();
|
||||
|
||||
/**
|
||||
* Register an IRQ handler
|
||||
* \param n the IRQ to register a handler for
|
||||
* \param handler the handler to register
|
||||
*
|
||||
* If the PID is 0, the handler will be called directly, otherwise a thread will be made in the PID starting at the handler's address.
|
||||
* \param n The IRQ to register a handler for
|
||||
* \param pid The PID that will handle the interrupt.
|
||||
* \param handler The address of the handler.
|
||||
*/
|
||||
void isr_register_handler(int n,isr_t handler);
|
||||
void isr_register_handler(int n,pid_t pid,void* handler);
|
||||
|
||||
#endif
|
||||
|
@ -18,6 +18,11 @@ void switch_to_thread_asm(Thread* thread);
|
||||
*/
|
||||
void task_init();
|
||||
|
||||
/**
|
||||
* Initializes a usermode task without interrupts enabled
|
||||
*/
|
||||
void task_init_no_int();
|
||||
|
||||
/**
|
||||
* An assembly helper for waiting for an unblocked thread
|
||||
* Starts interrupts, halts, then clears interrupts.
|
||||
@ -31,8 +36,9 @@ void wait_for_unblocked_thread_asm();
|
||||
* \param param2 The thread's start function second parameter
|
||||
* \param kmode Whether the thread is a kernel mode thread
|
||||
* \param eip The start address of the thread
|
||||
* \param is_irq_handler Whether the kernel stack is for an interrupt handler thread
|
||||
*/
|
||||
void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip);
|
||||
void setup_kstack(Thread* thread,void* param1,void* param2,char kmode,void* eip,char is_irq_handler);
|
||||
|
||||
/**
|
||||
* Frees a kernel stack so it can be used again
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cpu/serial.h"
|
||||
#include "cpu/halt.h"
|
||||
|
||||
#define KMALLOC_BMAP_SZ (((KMALLOC_SZ*1024)/4)/8) //!< The size of the kmalloc bitmap
|
||||
|
||||
@ -85,6 +87,8 @@ void* kmalloc(size_t size) {
|
||||
}
|
||||
}
|
||||
if (remaining_blks!=0) {
|
||||
serial_printf("Kmalloc fail!\n");
|
||||
halt();
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i=0;i<num_4b_grps;i++) {
|
||||
|
@ -123,6 +123,8 @@ void* pmem_alloc(int num_pages) {
|
||||
}
|
||||
}
|
||||
if (remaining_blks!=0) {
|
||||
serial_printf("Out of memory! Halting!\n");
|
||||
halt();
|
||||
return NULL;
|
||||
}
|
||||
for (int i=0;i<num_pages;i++) {
|
||||
|
@ -94,7 +94,7 @@ void* kernel_rpc_call(pid_t pid,char* name,void* buf,size_t size) {
|
||||
map_pages(virtaddr,physaddr,(size/PAGE_SZ)+1,1,1);
|
||||
});
|
||||
}
|
||||
pid_t tid=tasking_new_thread(func->code,pid,virtaddr);
|
||||
pid_t tid=tasking_new_thread(func->code,pid,virtaddr,0);
|
||||
tasking_set_rpc_calling_thread(pid,tid);
|
||||
// Block the thread and wait for an unblock from rpc_return
|
||||
tasking_block(THREAD_WAITING_FOR_RPC);
|
||||
|
@ -90,7 +90,7 @@ void schedule_thread(Thread* thread) {
|
||||
}
|
||||
}
|
||||
|
||||
void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,void* param2,char isThread) {
|
||||
void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,void* param2,char isThread,char is_irq_handler) {
|
||||
if (next_pid>MAX_PROCS && !isThread) {
|
||||
serial_printf("Failed to create a process, as 32k processes have been created already.\n");
|
||||
halt(); //Cannot ever create more than 32k processes, as I don't currently reuse PIDs.
|
||||
@ -118,9 +118,19 @@ void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,v
|
||||
num_procs++;
|
||||
}
|
||||
proc->first_thread=thread;
|
||||
setup_kstack(thread,param1,param2,kmode,eip);
|
||||
setup_kstack(thread,param1,param2,kmode,eip,is_irq_handler);
|
||||
schedule_thread(thread);
|
||||
// serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid);
|
||||
serial_printf("Created thread with PID %d and TID %d.\n",proc->pid,thread->tid);
|
||||
serial_printf("Structure values:\n");
|
||||
serial_printf("kernel_esp=%x\n",thread->kernel_esp);
|
||||
serial_printf("kernel_esp_top=%x\n",thread->kernel_esp_top);
|
||||
serial_printf("address_space=%x\n",thread->address_space);
|
||||
serial_printf("tid=%d\n",thread->tid);
|
||||
serial_printf("state=%d\n",thread->state);
|
||||
serial_printf("next_thread_in_process=%x\n",thread->next_thread_in_process);
|
||||
serial_printf("next_ready_to_run=%x\n",thread->next_ready_to_run);
|
||||
serial_printf("prev_ready_to_run=%x\n",thread->prev_ready_to_run);
|
||||
serial_printf("process=%x\n",thread->process);
|
||||
}
|
||||
|
||||
void tasking_init() {
|
||||
@ -128,7 +138,7 @@ void tasking_init() {
|
||||
memset(&processes[i],0,sizeof(Process));
|
||||
}
|
||||
|
||||
tasking_create_task(NULL,get_address_space(),1,NULL,NULL,0);
|
||||
tasking_create_task(NULL,get_address_space(),1,NULL,NULL,0,0);
|
||||
}
|
||||
|
||||
char tasking_is_privleged() {
|
||||
@ -147,8 +157,8 @@ int* tasking_get_errno_address() {
|
||||
return ¤t_thread->errno;
|
||||
}
|
||||
|
||||
pid_t tasking_new_thread(void* start,pid_t pid,void* param) {
|
||||
tasking_create_task(start,NULL,0,param,(void*)pid,1);
|
||||
pid_t tasking_new_thread(void* start,pid_t pid,void* param,char is_irq_handler) {
|
||||
tasking_create_task(start,NULL,0,param,(void*)pid,1,is_irq_handler);
|
||||
return processes[pid].first_thread->tid;
|
||||
}
|
||||
|
||||
@ -389,7 +399,6 @@ void* tasking_get_rpc_ret_buf() {
|
||||
|
||||
void tasking_thread_exit() {
|
||||
tasking_block(THREAD_EXITED);
|
||||
free_kstack(current_thread->kernel_esp_top);
|
||||
}
|
||||
|
||||
char tasking_check_proc_exists(pid_t pid) {
|
||||
|
@ -57,7 +57,7 @@ typedef struct Thread {
|
||||
pid_t rpc_calling_pid; //!< The PID of the thread that called this RPC (only used for RPC handler threads)
|
||||
pid_t rpc_calling_tid; //!< The TID of the thread that called this RPC (only used for RPC handler threads)
|
||||
void* rpc_ret_buf; //!< The return buffer of the RPC call that the thread made
|
||||
} Thread;
|
||||
} __attribute__((packed)) Thread;
|
||||
|
||||
extern Thread* current_thread;
|
||||
|
||||
@ -69,8 +69,9 @@ extern Thread* current_thread;
|
||||
* \param param1 The thread's start function first parameter
|
||||
* \param param2 The thread's start function second parameter
|
||||
* \param isThread Whether we are creating a new process or a thread in a process. If we are creating a theead, param2_arg becomes the PID for the newly created thread.
|
||||
* \param is_irq_handler Whether the new task is an irq handler task
|
||||
*/
|
||||
void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,void* param2,char isThread);
|
||||
void tasking_create_task(void* eip,void* address_space,char kmode,void* param1,void* param2,char isThread,char is_irq_handler);
|
||||
/**
|
||||
* Initialize tasking
|
||||
*/
|
||||
@ -100,9 +101,10 @@ int* tasking_get_errno_address();
|
||||
* \param start The start address of the task
|
||||
* \param pid The PID that gets the new thread
|
||||
* \param param The thread's start function parameter
|
||||
* \param is_irq_handler Whether the new thread is an irq handler thread
|
||||
* \return the TID of the thread
|
||||
*/
|
||||
pid_t tasking_new_thread(void* start,pid_t pid,void* param);
|
||||
pid_t tasking_new_thread(void* start,pid_t pid,void* param,char is_irq_handler);
|
||||
|
||||
/**
|
||||
* Terminate the current thread
|
||||
|
@ -19,7 +19,7 @@ void timer_init(int freq) {
|
||||
} else {
|
||||
serial_printf("Setting PIT to %dHz using divisor of %d\n",freq,div);
|
||||
}
|
||||
isr_register_handler(0,timer_handler);
|
||||
isr_register_handler(0,0,timer_handler);
|
||||
port_byte_out(0x43,0b00110110); // Set timer 0 to lobyte/hibyte access, and mode 3 (square wave generator)
|
||||
port_byte_out(0x40,div&0xFF);
|
||||
port_byte_out(0x40,(div>>8)&0xFF);
|
||||
|
@ -5,7 +5,7 @@ TYPEDEF_HIDES_STRUCT = YES
|
||||
EXTRACT_STATIC = YES
|
||||
WARN_NO_PARAMDOC = YES
|
||||
WARN_AS_ERROR = YES
|
||||
INPUT = /Users/peterterpstra/Desktop/projects/os/libc
|
||||
INPUT = ./libc
|
||||
RECURSIVE = YES
|
||||
EXCLUDE = libc/elf.h libc/grub/multiboot2.h
|
||||
HTML_DYNAMIC_SECTIONS = YES
|
||||
|
@ -28,5 +28,6 @@
|
||||
#define SYSCALL_RPC_RET 18
|
||||
#define SYSCALL_RPC_MARK_AS_INIT 21
|
||||
#define SYSCALL_RPC_IS_INIT 22
|
||||
#define SYSCALL_REGISTER_IRQ_HANDLER 23
|
||||
|
||||
#endif
|
||||
|
BIN
tar_fs/tar_fs
BIN
tar_fs/tar_fs
Binary file not shown.
0
vga_drv/vtconsole.c
Executable file → Normal file
0
vga_drv/vtconsole.c
Executable file → Normal file
0
vga_drv/vtconsole.h
Executable file → Normal file
0
vga_drv/vtconsole.h
Executable file → Normal file
Loading…
Reference in New Issue
Block a user