summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/typedefs.h2
-rw-r--r--kernel/Makefile8
-rw-r--r--kernel/arch/i386/mmu.c26
-rw-r--r--kernel/cpu/idt.c37
-rw-r--r--kernel/cpu/idt.h10
-rw-r--r--kernel/cpu/int_syscall.s3
-rw-r--r--kernel/cpu/syscall.c20
-rw-r--r--kernel/drivers/pit.c15
-rw-r--r--kernel/drivers/rtl8139.c6
-rw-r--r--kernel/fs/ext2.c26
-rw-r--r--kernel/halts.c2
-rw-r--r--kernel/includes/mmu.h1
-rw-r--r--kernel/includes/syscalls.h7
-rw-r--r--kernel/init/kernel.c8
-rw-r--r--kernel/ipc.c7
-rw-r--r--kernel/poll.c2
-rw-r--r--kernel/process.s114
-rw-r--r--kernel/sched/scheduler.c116
-rw-r--r--kernel/sched/scheduler.h15
-rw-r--r--kernel/syscalls/msleep.c2
-rwxr-xr-xmeta/debug.sh3
-rwxr-xr-xmeta/userland.sh2
-rw-r--r--userland/libc/include/syscall.h7
-rw-r--r--userland/libppm/ppm.c29
24 files changed, 368 insertions, 100 deletions
diff --git a/include/typedefs.h b/include/typedefs.h
index e290716..e2226fd 100644
--- a/include/typedefs.h
+++ b/include/typedefs.h
@@ -9,3 +9,5 @@ typedef int8_t i8;
typedef int16_t i16;
typedef int32_t i32;
typedef int64_t i64;
+
+#define U32_MAX 4294967295
diff --git a/kernel/Makefile b/kernel/Makefile
index a36e84c..4ac7368 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -1,7 +1,9 @@
CC="i686-sb-gcc"
AS="i686-sb-as"
-OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o
-CFLAGS = -O3 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+OBJ = arch/i386/boot.o init/kernel.o cpu/gdt.o cpu/reload_gdt.o cpu/idt.o cpu/io.o libc/stdio/print.o drivers/keyboard.o log.o drivers/pit.o libc/string/memcpy.o libc/string/strlen.o libc/string/memcmp.o drivers/ata.o libc/string/memset.o cpu/syscall.o read_eip.o libc/exit/assert.o process.o cpu/int_syscall.o libc/string/strcpy.o arch/i386/mmu.o kmalloc.o fs/ext2.o fs/vfs.o fs/devfs.o cpu/spinlock.o random.o libc/string/strcmp.o crypto/ChaCha20/chacha20.o crypto/SHA1/sha1.o fs/tmpfs.o libc/string/isequal.o drivers/pst.o halts.o syscalls/ppoll.o syscalls/ftruncate.o kubsan.o syscalls/mmap.o drivers/serial.o syscalls/accept.o syscalls/bind.o syscalls/socket.o socket.o poll.o fs/fifo.o hashmap/hashmap.o fs/shm.o syscalls/shm.o elf.o ksbrk.o sched/scheduler.o syscalls/stat.o libc/string/copy.o libc/string/strncpy.o drivers/mouse.o libc/string/strlcpy.o libc/string/strcat.o drivers/vbe.o syscalls/msleep.o syscalls/uptime.o syscalls/mkdir.o drivers/pci.o drivers/rtl8139.o network/ethernet.o network/arp.o network/bytes.o network/ipv4.o network/udp.o syscalls/recvfrom.o math.o syscalls/sendto.o signal.o syscalls/kill.o syscalls/sigaction.o network/tcp.o drivers/ahci.o crypto/xoshiro256plusplus/xoshiro256plusplus.o syscalls/chdir.o syscalls/getcwd.o syscalls/isatty.o syscalls/randomfill.o syscalls/open.o syscalls/write.o syscalls/pwrite.o ipc.o syscalls/ipc.o syscalls/port.o syscalls/map_frames.o syscalls/virtual_to_physical.o syscalls/install_irq.o switch_task.o
+CFLAGS = -O0 -fsanitize=vla-bound,shift-exponent,pointer-overflow,shift,signed-integer-overflow,bounds -ggdb -ffreestanding -Wall -Werror -mgeneral-regs-only -Wimplicit-fallthrough -I./libc/include/ -I. -Wno-pointer-sign -DKERNEL
+#LDFLAGS=-flto -Ofast
+LDFLAGS=
INCLUDE=-I./includes/ -I../include/ -I./libc/include/
all: myos.iso
@@ -13,7 +15,7 @@ all: myos.iso
$(AS) $< -o $@
myos.bin: $(OBJ)
- $(CC) $(INCLUDE) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc
+ $(CC) $(INCLUDE) $(LDFLAGS) -shared -T linker.ld -o myos.bin -ffreestanding -nostdlib $(CFLAGS) $^ -lgcc
myos.iso: myos.bin
cp myos.bin isodir/boot
diff --git a/kernel/arch/i386/mmu.c b/kernel/arch/i386/mmu.c
index 288e12a..f958455 100644
--- a/kernel/arch/i386/mmu.c
+++ b/kernel/arch/i386/mmu.c
@@ -332,6 +332,24 @@ int mmu_allocate_region(void *ptr, size_t n, mmu_flags flags,
return 1;
}
+void *mmu_map_user_frames(void *const ptr, size_t s) {
+ void *const r = get_free_virtual_memory(s);
+ size_t num_pages = s / 0x1000;
+ for (size_t i = 0; i <= num_pages; i++) {
+ Page *p = get_page((void *)(r + i * 0x1000), NULL, PAGE_ALLOCATE, 0);
+ assert(p);
+ int rw = 1;
+ int is_kernel = 0;
+ p->present = 1;
+ p->rw = rw;
+ p->user = !is_kernel;
+ p->frame = (uintptr_t)(ptr + i * 0x1000) / 0x1000;
+ kprintf("mapped user frame: %x\n", p->frame);
+ write_to_frame((uintptr_t)ptr + i * 0x1000, 1);
+ }
+ return r;
+}
+
void *mmu_map_frames(void *const ptr, size_t s) {
void *const r = mmu_find_unallocated_virtual_range((void *)0xEF000000, s);
size_t num_pages = s / 0x1000;
@@ -457,10 +475,8 @@ void *physical_to_virtual(void *address) {
void *virtual_to_physical(void *address, PageDirectory *directory) {
if (0 == directory)
directory = get_active_pagedirectory();
- return (void *)((get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0)
- ->frame *
- 0x1000) +
- (((uintptr_t)address) & 0xFFF));
+ Page *p = get_page((void *)address, directory, PAGE_NO_ALLOCATE, 0);
+ return (void *)((u32)p->frame * 0x1000) + (((uintptr_t)address) & 0xFFF);
}
extern u32 inital_esp;
@@ -595,7 +611,7 @@ void paging_init(u64 memsize) {
switch_page_directory(kernel_directory);
// Make null dereferences crash.
get_page(NULL, kernel_directory, PAGE_ALLOCATE, 0)->present = 0;
- for (int i = 0; i < 16; i++)
+ for (int i = 0; i < 25; i++)
create_table(770 + i);
kernel_directory = clone_directory(kernel_directory);
diff --git a/kernel/cpu/idt.c b/kernel/cpu/idt.c
index 46782b5..f4d025a 100644
--- a/kernel/cpu/idt.c
+++ b/kernel/cpu/idt.c
@@ -69,11 +69,36 @@ __attribute__((interrupt)) void double_fault(registers_t *regs) {
for (;;)
;
}
+
+void tmp_jump_process(u32, u32, u32, u32);
+void jump_process(const process_t *p) {
+ // tmp_jump_process(p->eip, p->cr3->physical_address, p->ebp, p->esp);
+}
+
+void none_save_switch(void);
+extern PageDirectory *active_directory;
__attribute__((interrupt)) void page_fault(registers_t *regs) {
- if (0xFFFFDEAD == regs->eip) {
- asm("sti");
- for (;;)
- switch_task();
+ volatile uint32_t cr2;
+ asm volatile("mov %%cr2, %0" : "=r"(cr2));
+ kprintf("CR2: %x\n", cr2);
+ if (0xFFFFDEAD == cr2) {
+ /*
+ process_t *current = get_current_task();
+ if (!current) {
+ kprintf("WHYYYYYY!\n");
+ for (;;)
+ asm("cli");
+ }
+ current->useresp = regs->esp;*/
+ // active_directory = current->cr3;
+// get_current_task()->esp = get_current_task()->saved_esp;
+// get_current_task()->ebp = get_current_task()->saved_ebp;
+// get_current_task()->eip = get_current_task()->saved_eip;
+ for (;;) {
+ switch_task(0);
+ }
+ // jump_process(current);
+ return;
}
klog("Page Fault", LOG_ERROR);
if (get_current_task()) {
@@ -83,10 +108,6 @@ __attribute__((interrupt)) void page_fault(registers_t *regs) {
kprintf("Error Code: %x\n", regs->error_code);
kprintf("Instruction Pointer: %x\n", regs->eip);
- volatile uint32_t cr2;
- asm volatile("mov %%cr2, %0" : "=r"(cr2));
- kprintf("CR2: %x\n", cr2);
-
if (regs->error_code & (1 << 0))
kprintf("page-protection violation\n");
else
diff --git a/kernel/cpu/idt.h b/kernel/cpu/idt.h
index 9341887..fdd6a3e 100644
--- a/kernel/cpu/idt.h
+++ b/kernel/cpu/idt.h
@@ -55,13 +55,9 @@ typedef struct registers registers_t;
struct interrupt_frame;
struct registers {
- u32 error_code;
- u32 eip;
- u32 cs;
- u32 eflags;
- u32 esp;
- u32 ss;
-};
+ uintptr_t error_code;
+ uintptr_t eip, cs, eflags, esp, ss;
+} __attribute__((packed));
void idt_init(void);
__attribute__((no_caller_saved_registers)) void EOI(unsigned char irq);
diff --git a/kernel/cpu/int_syscall.s b/kernel/cpu/int_syscall.s
index 8c3c25f..ec7693a 100644
--- a/kernel/cpu/int_syscall.s
+++ b/kernel/cpu/int_syscall.s
@@ -2,6 +2,7 @@
.global int_syscall
.extern syscall_function_handler
int_syscall:
+ push esp
push ebp
push edi
push esi
@@ -10,7 +11,7 @@ int_syscall:
push ebx
push eax
call syscall_function_handler
- add esp, 4
+ add esp, 8
pop ebx
pop ecx
pop edx
diff --git a/kernel/cpu/syscall.c b/kernel/cpu/syscall.c
index 3a2b1ca..5e51d53 100644
--- a/kernel/cpu/syscall.c
+++ b/kernel/cpu/syscall.c
@@ -7,6 +7,7 @@
#include <fs/tmpfs.h>
#include <fs/vfs.h>
#include <kmalloc.h>
+#include <network/ethernet.h>
#include <string.h>
#include <syscalls.h>
#include <typedefs.h>
@@ -35,6 +36,11 @@ int syscall_exec(SYS_EXEC_PARAMS *args) {
return -1;
}
+void syscall_tmp_handle_packet(void *packet, u32 len) {
+ kprintf("syscall tmp handle packet\n");
+ handle_ethernet((u8 *)packet, len);
+}
+
int syscall_pipe(int fd[2]) {
pipe(fd); // FIXME: Error checking
return 0;
@@ -75,7 +81,7 @@ void syscall_wait(int *status) {
return;
}
get_current_task()->halts[WAIT_CHILD_HALT] = 1;
- switch_task();
+ switch_task(1);
if (status)
*status = get_current_task()->child_rc;
}
@@ -159,10 +165,20 @@ void (*syscall_functions[])() = {
(void(*))syscall_ipc_read,
(void(*))syscall_ipc_write,
(void(*))syscall_ipc_write_to_process,
+ (void(*))syscall_outw,
+ (void(*))syscall_inl,
+ (void(*))syscall_outl,
+ (void(*))syscall_map_frames,
+ (void(*))syscall_virtual_to_physical,
+ (void(*))syscall_install_irq,
+ (void(*))syscall_tmp_handle_packet,
};
void syscall_function_handler(u32 eax, u32 arg1, u32 arg2, u32 arg3, u32 arg4,
- u32 arg5) {
+ u32 arg5, u32 ebp, u32 esp) {
+ if (esp <= 0x90000000) {
+ get_current_task()->useresp = esp;
+ }
assert(eax < sizeof(syscall_functions) / sizeof(syscall_functions[0]));
syscall_functions[eax](arg1, arg2, arg3, arg4, arg5);
}
diff --git a/kernel/drivers/pit.c b/kernel/drivers/pit.c
index 567ac2d..8f9c35c 100644
--- a/kernel/drivers/pit.c
+++ b/kernel/drivers/pit.c
@@ -41,17 +41,24 @@ void set_pit_count(u16 hertz) {
outb(PIT_IO_CHANNEL_0, (divisor & 0xFF00) >> 8);
}
-__attribute__((interrupt)) void
-int_clock(__attribute__((unused)) struct interrupt_frame *frame) {
+__attribute__((interrupt)) void int_clock(registers_t *regs) {
+ process_t *p = get_current_task();
+ if (p) {
+ // FIXME: For some reason eflags is the esp? I have read the
+ // manual multilpe times and still can't figure out why.
+ if (regs->eflags <= 0x90000000 && regs->eflags) {
+ p->useresp = regs->eflags;
+ }
+ }
outb(0x20, 0x20);
pit_counter++;
if (pit_counter >= hertz / 1000) {
pit_counter = 0;
clock_num_ms_ticks++;
}
- switch_task();
+ switch_task(1);
}
void pit_install(void) {
- install_handler(int_clock, INT_32_INTERRUPT_GATE(0x0), 0x20);
+ install_handler(int_clock, INT_32_INTERRUPT_GATE(0x3), 0x20);
}
diff --git a/kernel/drivers/rtl8139.c b/kernel/drivers/rtl8139.c
index dd81533..b07ccef 100644
--- a/kernel/drivers/rtl8139.c
+++ b/kernel/drivers/rtl8139.c
@@ -3,6 +3,7 @@
#include <cpu/io.h>
#include <drivers/pci.h>
#include <drivers/rtl8139.h>
+#include <ipc.h>
#include <mmu.h>
#include <network/arp.h>
#include <network/ethernet.h>
@@ -104,6 +105,9 @@ __attribute__((interrupt)) void rtl8139_handler(void *regs) {
}
void rtl8139_send_data(u8 *data, u16 data_size) {
+ kprintf("ipc_write\n");
+ ipc_write(0, data, data_size);
+ /*
const struct PCI_DEVICE *device = &rtl8139;
// FIXME: It should block or fail if there is too little space for the
// buffer
@@ -120,7 +124,7 @@ void rtl8139_send_data(u8 *data, u16 data_size) {
outl(device->gen.base_mem_io + 0x20 + send_buffers_loop * 4,
(u32)virtual_to_physical(send_buffers[send_buffers_loop], NULL));
outl(device->gen.base_mem_io + 0x10 + send_buffers_loop * 4, data_size);
- send_buffers_loop += 1;
+ send_buffers_loop += 1;*/
}
void get_mac_address(u8 mac[6]) {
diff --git a/kernel/fs/ext2.c b/kernel/fs/ext2.c
index cb4a0d4..60800a9 100644
--- a/kernel/fs/ext2.c
+++ b/kernel/fs/ext2.c
@@ -30,30 +30,39 @@ void get_inode_data_size(int inode_num, u64 *file_size) {
}
struct BLOCK_CACHE {
+ u32 usage;
u32 block_num;
u8 block[1024];
};
-#define NUM_BLOCK_CACHE 30
-struct BLOCK_CACHE cache[NUM_BLOCK_CACHE] = {0};
-u8 last_taken_cache = 0;
+#define NUM_BLOCK_CACHE 3000
+struct BLOCK_CACHE *cache;
+
+u32 cold_cache_hits = 0;
void cached_read_block(u32 block, void *address, size_t size, size_t offset) {
int free_found = -1;
for (int i = 0; i < NUM_BLOCK_CACHE; i++) {
if (cache[i].block_num == block) {
+ cache[i].usage += 1;
memcpy(address, cache[i].block + offset, size);
return;
}
- if (0 == cache[i].block_num)
+ if (0 == cache[i].block_num) {
free_found = i;
+ }
}
if (-1 == free_found) {
- free_found = last_taken_cache;
- last_taken_cache++;
- if (last_taken_cache >= NUM_BLOCK_CACHE)
- last_taken_cache = 0;
+ u32 min_usage_value = U32_MAX;
+ int min_index = 0;
+ for (int i = 0; i < NUM_BLOCK_CACHE; i++) {
+ if (cache[i].usage < min_usage_value) {
+ min_usage_value = cache[i].usage;
+ min_index = i;
+ }
+ }
+ free_found = min_index;
}
struct BLOCK_CACHE *c = &cache[free_found];
@@ -763,6 +772,7 @@ int ext2_create_file(const char *path, int mode) {
vfs_inode_t *ext2_mount(void) {
int fd = vfs_open("/dev/sda", O_RDWR, 0);
+ cache = kcalloc(3000, sizeof(struct BLOCK_CACHE));
// TODO: Can this be done better? Maybe create a seperate function in
// the VFS?
mount_fd = get_current_task()->file_descriptors[fd];
diff --git a/kernel/halts.c b/kernel/halts.c
index b70a4ef..6f60a79 100644
--- a/kernel/halts.c
+++ b/kernel/halts.c
@@ -13,7 +13,6 @@ int create_disconnect_inode_halt(vfs_inode_t *inode) {
return -1;
p->disconnect_halt_inode[i] = inode;
-
return i;
}
@@ -53,7 +52,6 @@ int create_write_inode_halt(vfs_inode_t *inode) {
return -1;
p->write_halt_inode[i] = inode;
-
return i;
}
diff --git a/kernel/includes/mmu.h b/kernel/includes/mmu.h
index 8990bdf..49b4886 100644
--- a/kernel/includes/mmu.h
+++ b/kernel/includes/mmu.h
@@ -44,6 +44,7 @@ void *mmu_map_frames(void *ptr, size_t s);
void mmu_map_physical(void *dst, PageDirectory *d, void *physical,
size_t length);
void mmu_free_pages(void *a, u32 n);
+void *mmu_map_user_frames(void *const ptr, size_t s);
void flush_tlb(void);
void paging_init(u64 memsize);
diff --git a/kernel/includes/syscalls.h b/kernel/includes/syscalls.h
index cdf4f5a..ee3e417 100644
--- a/kernel/includes/syscalls.h
+++ b/kernel/includes/syscalls.h
@@ -7,10 +7,17 @@
#include <typedefs.h>
#include <types.h>
+void syscall_outw(u16 port, u16 word);
+u32 syscall_inl(u16 port);
+void syscall_outl(u16 port, u32 l);
+
int syscall_ipc_register_endpoint(u32 endpoint);
int syscall_ipc_read(u8 *buffer, u32 length, u32 *sender_pid);
int syscall_ipc_write(int ipc_id, u8 *buffer, u32 length);
int syscall_ipc_write_to_process(int pid, u8 *buffer, u32 length);
+u32 syscall_map_frames(u32 address, u32 size);
+u32 syscall_virtual_to_physical(u32 virtual);
+int syscall_install_irq(void (*irq_handler)(), u8 irq);
typedef struct SYS_ACCEPT_PARAMS {
int socket;
diff --git a/kernel/init/kernel.c b/kernel/init/kernel.c
index 24da680..67aab12 100644
--- a/kernel/init/kernel.c
+++ b/kernel/init/kernel.c
@@ -94,7 +94,7 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
add_keyboard();
add_mouse();
- rtl8139_init();
+ // rtl8139_init();
display_driver_init(mb);
add_vbe_device();
@@ -105,6 +105,8 @@ void kernel_main(u32 kernel_end, unsigned long magic, unsigned long addr,
kprintf("exec() failed\n");
}
}
- for (;;)
- ;
+ for (;;) {
+ asm("sti");
+ switch_task(0);
+ }
}
diff --git a/kernel/ipc.c b/kernel/ipc.c
index 3422cc7..6367511 100644
--- a/kernel/ipc.c
+++ b/kernel/ipc.c
@@ -47,9 +47,12 @@ int ipc_read(u8 *buffer, u32 length, u32 *sender_pid) {
for (;;) {
ipc_message = &handler->data[read_ptr];
if (!ipc_message->is_used) {
- asm("sti");
- continue;
+ return 0;
+// kprintf("switch\n");
+// switch_task();
+// continue;
}
+ kprintf("breaking out\n");
break;
}
ipc_message->is_used = 0;
diff --git a/kernel/poll.c b/kernel/poll.c
index 211faf7..ee92a8c 100644
--- a/kernel/poll.c
+++ b/kernel/poll.c
@@ -21,7 +21,7 @@ int poll(struct pollfd *fds, size_t nfds, int timeout) {
disconnect_locks[i] = create_disconnect_fdhalt(f);
}
- switch_task();
+ switch_task(1);
for (size_t i = 0; i < nfds; i++) {
if (fds[i].fd < 0)
diff --git a/kernel/process.s b/kernel/process.s
index 24e1869..9f8ee71 100644
--- a/kernel/process.s
+++ b/kernel/process.s
@@ -31,3 +31,117 @@ copy_page_physical:
popf
pop ebx
ret
+
+
+.extern current_task_TCB
+.global TCB
+
+.section .data
+
+ .struct 0
+TCB:
+TCB.ESP:
+ .space 4
+TCB.CR3:
+ .space 4
+TCB.ESP0:
+ .space 4
+
+.global switch_to_task
+.global insert_eip_on_stack
+.global internal_fork
+.extern create_process
+
+.section .text
+
+internal_fork:
+ push ebp
+ mov ecx, esp
+ mov ebp, esp
+
+ mov eax, [ebp+8] # current_task
+
+ lea edx, after_internal_fork
+ push edx
+ push ecx
+ push eax
+ call create_process
+ add esp, 0xC
+
+ pop ebp
+ ret
+after_internal_fork:
+ pop ebp
+ mov eax, 0
+ ret
+
+insert_eip_on_stack:
+ push ebp
+ mov ebp, esp
+ mov eax, [ebp+8] # cr3
+ mov ecx, [ebp+8+4] # address
+ mov edx, [ebp+8+4+4] # value
+
+ push ebx
+
+ mov ebx, cr3
+ mov cr3, eax
+
+ mov [ecx], edx
+
+ mov cr3, ebx
+
+ pop ebx
+ pop ebp
+ ret
+
+# C declaration:
+# void switch_to_task(thread_control_block *next_thread);
+#
+# WARNING: Caller is expected to disable IRQs before calling, and enable IRQs again after function returns
+
+switch_to_task:
+ cli
+
+ # Save previous task's state
+
+ # Notes:
+ # For cdecl; EAX, ECX, and EDX are already saved by the caller and don't need to be saved again
+ # EIP is already saved on the stack by the caller's "CALL" instruction
+ # The task isn't able to change CR3 so it doesn't need to be saved
+ # Segment registers are constants (while running kernel code) so they don't need to be saved
+
+ push ebx
+ push esi
+ push edi
+ push ebp
+
+ mov edi,[current_task_TCB] # edi = address of the previous task's "thread control block"
+ mov [edi+TCB.ESP],esp # Save ESP for previous task's kernel stack in the thread's TCB
+
+ # Load next task's state
+
+ mov esi,[esp+(4+1)*4] # esi = address of the next task's "thread control block" (parameter passed on stack)
+ mov [current_task_TCB],esi # Current task's TCB is the next task TCB
+
+ mov esp,[esi+TCB.ESP] # Load ESP for next task's kernel stack from the thread's TCB
+ mov eax,[esi+TCB.CR3] # eax = address of page directory for next task
+ mov ebx,[esi+TCB.ESP0] # ebx = address for the top of the next task's kernel stack
+# mov [TSS.ESP0],ebx # Adjust the ESP0 field in the TSS (used by CPU for for CPL=3 -> CPL=0 privilege level changes)
+# mov ecx,cr3 # ecx = previous task's virtual address space
+
+# FIXME: This branch gets a from the assembler, something about "relaxed branches".
+# this branch would probably not be used anyway but should be checked on later anyway.
+# cmp eax,ecx # Does the virtual address space need to being changed?
+
+# je .doneVAS # no, virtual address space is the same, so don't reload it and cause TLB flushes
+ mov cr3,eax # yes, load the next task's virtual address space
+#.doneVAS:
+
+ pop ebp
+ pop edi
+ pop esi
+ pop ebx
+
+ sti
+ ret # Load next task's EIP from its kernel stack
diff --git a/kernel/sched/scheduler.c b/kernel/sched/scheduler.c
index e2e4aa0..8019e5a 100644
--- a/kernel/sched/scheduler.c
+++ b/kernel/sched/scheduler.c
@@ -6,6 +6,11 @@
#include <errno.h>
#include <fs/vfs.h>
+// FIXME: Use the process_t struct instead or keep this contained in it.
+TCB *current_task_TCB;
+
+void switch_to_task(TCB *next_thread);
+
#define STACK_LOCATION ((void *)0x90000000)
#define STACK_SIZE 0x80000
#define HEAP_SIZE 0x400000
@@ -39,7 +44,10 @@ void set_signal_handler(int sig, void (*handler)(int)) {
current_task->signal_handlers[sig] = handler;
}
-process_t *create_process(process_t *p) {
+void insert_eip_on_stack(u32 cr3, u32 address, u32 value);
+
+process_t *create_process(process_t *p, u32 esp, u32 eip) {
+ kprintf("CREATE_PROCESS\n");
process_t *r;
r = kcalloc(1, sizeof(process_t));
r->dead = 0;
@@ -61,8 +69,31 @@ process_t *create_process(process_t *p) {
r->parent = p;
r->child = NULL;
r->halt_list = NULL;
+ r->interrupt_handler = NULL;
+
+ r->tcb = kcalloc(1, sizeof(struct TCB));
+ kprintf("r->tcb: %x\n", r->tcb);
+ kprintf("r->cr3: %x\n", r->cr3);
+ kprintf("p: %x\n", p);
+ r->tcb->CR3 = r->cr3->physical_address;
+
+ // Temporarily switch to the page directory to be able to place the
+ // "entry_instruction_pointer" onto the stack.
+
+ if (esp) {
+ esp -= 4;
+ insert_eip_on_stack(r->cr3->physical_address, esp, eip);
+ esp -= 4;
+ insert_eip_on_stack(r->cr3->physical_address, esp, 0x1337);
+ esp -= 4;
+ insert_eip_on_stack(r->cr3->physical_address, esp, 0x1488);
+ esp -= 4;
+ esp -= 4;
+ insert_eip_on_stack(r->cr3->physical_address, esp, 0xF00DBABE);
+ r->tcb->ESP = esp;
+ }
- mmu_allocate_region((void *)(0x80000000 - 0x1000), 0x1000, MMU_FLAG_RW,
+ mmu_allocate_region((void *)(0x80000000 - 0x8000), 0x8000, MMU_FLAG_RW,
r->cr3);
r->signal_handler_stack = 0x80000000;
@@ -109,7 +140,11 @@ int get_free_fd(process_t *p, int allocate) {
}
void tasking_init(void) {
- current_task = ready_queue = create_process(NULL);
+ current_task = ready_queue = create_process(NULL, 0, 0);
+ current_task_TCB = current_task->tcb;
+ current_task->tcb->CR3 = current_task->cr3->physical_address;
+ // // Switch to itself to update the internal values
+ // switch_task(0);
}
int i = 0;
@@ -164,7 +199,7 @@ void exit(int status) {
}
current_task->dead = 1;
// This function will enable interrupts
- switch_task();
+ switch_task(1);
}
u32 setup_stack(u32 stack_pointer, int argc, char **argv) {
@@ -231,7 +266,7 @@ int exec(const char *filename, char **argv) {
ASSERT_NOT_REACHED;
return 0;
}
-
+/*
int fork(void) {
process_t *parent_task = (process_t *)current_task;
@@ -255,12 +290,36 @@ int fork(void) {
new_task->eip = eip;
asm("\
- mov %%esp, %0;\
- mov %%ebp, %1;"
+ mov %%esp, %0;\
+ mov %%ebp, %1;"
: "=r"(new_task->esp), "=r"(new_task->ebp));
+ asm("\
+ mov %%esp, %0;"
+ : "=r"(new_task->tcb->ESP));
asm("sti");
return new_task->pid;
}
+*/
+
+process_t *internal_fork(process_t *parent);
+int fork(void) {
+ process_t *new_task;
+ new_task = internal_fork(current_task);
+ if (NULL == new_task) {
+ return 0;
+ }
+
+ process_t *tmp_task = (process_t *)ready_queue;
+ for (; tmp_task->next;)
+ tmp_task = tmp_task->next;
+
+ tmp_task->next = new_task;
+
+ new_task->child_rc = -1;
+ new_task->parent = current_task;
+ current_task->child = new_task;
+ return new_task->pid;
+}
int is_halted(process_t *process) {
for (int i = 0; i < 2; i++)
@@ -292,7 +351,7 @@ process_t *next_task(process_t *c) {
return c;
}
-int task_save_state(void) {
+int task_save_state() {
asm("mov %%esp, %0" : "=r"(current_task->esp));
asm("mov %%ebp, %0" : "=r"(current_task->ebp));
@@ -329,44 +388,19 @@ int kill(pid_t pid, int sig) {
}
void jump_signal_handler(void *func, u32 esp);
-void switch_task() {
- if (!current_task)
- return;
- if (0 == task_save_state()) {
+void none_save_switch() {
+}
+
+void switch_task(int save) {
+ if (!current_task) {
return;
}
current_task = next_task((process_t *)current_task);
-
active_directory = current_task->cr3;
- if (current_task->incoming_signal) {
- u8 sig = current_task->incoming_signal;
- current_task->incoming_signal = 0;
- asm("mov %0, %%cr3" ::"r"(current_task->cr3->physical_address));
-
- void *handler = current_task->signal_handlers[sig];
- if (9 == sig) {
- klog("Task recieved SIGKILL", LOG_NOTE);
- exit(0);
- }
- if (!handler) {
- klog("Task recieved unhandeled signal. Killing process.", LOG_WARN);
- exit(1);
- }
- jump_signal_handler(handler, current_task->signal_handler_stack);
- } else {
- asm(" \
- mov %0, %%esp; \
- mov %1, %%ebp; \
- mov %2, %%ecx; \
- mov %3, %%cr3; \
- mov $0x1, %%eax; \
- jmp *%%ecx" ::"r"(current_task->esp),
- "r"(current_task->ebp), "r"(current_task->eip),
- "r"(current_task->cr3->physical_address));
- }
+ switch_to_task(current_task->tcb);
}
MemoryMap **get_free_map(void) {
@@ -378,8 +412,8 @@ MemoryMap **get_free_map(void) {
}
void *get_free_virtual_memory(size_t length) {
- void *n =
- (void *)((uintptr_t)(get_current_task()->data_segment_end) + length);
+ void *n = (void *)((uintptr_t)(get_current_task()->data_segment_end) +
+ length + 0x1000);
void *rc = get_current_task()->data_segment_end;
get_current_task()->data_segment_end = align_page(n);
diff --git a/kernel/sched/scheduler.h b/kernel/sched/scheduler.h
index 17e5d56..01276dc 100644
--- a/kernel/sched/scheduler.h
+++ b/kernel/sched/scheduler.h
@@ -14,7 +14,7 @@
int fork(void);
int exec(const char *filename, char **argv);
-void switch_task();
+void switch_task(int save);
void tasking_init(void);
void exit(int status);
@@ -34,14 +34,23 @@ typedef struct {
typedef struct Process process_t;
+typedef struct TCB {
+ uint32_t ESP;
+ uint32_t CR3;
+ uint32_t ESP0;
+} __attribute__((packed)) TCB;
+
struct Process {
u32 pid;
char program_name[100];
char current_working_directory[MAX_PATH];
u32 eip, esp, ebp;
+ u32 saved_eip, saved_esp, saved_ebp;
+ u32 useresp;
u8 incoming_signal;
u32 signal_handler_stack;
void *signal_handlers[20];
+ void *interrupt_handler;
PageDirectory *cr3;
struct IpcMailbox ipc_mailbox;
vfs_fd_t *file_descriptors[100];
@@ -53,6 +62,9 @@ struct Process {
void *data_segment_end;
process_t *next;
process_t *parent;
+
+ TCB *tcb;
+
// TODO: Create a linkedlist of childs so that the parent process
// can do stuff such as reap zombies and get status.
process_t *child;
@@ -66,4 +78,5 @@ bool get_task_from_pid(u32 pid, process_t **out);
process_t *get_current_task(void);
int get_free_fd(process_t *p, int allocate);
void free_process(void);
+void *get_free_virtual_memory(size_t length);
#endif
diff --git a/kernel/syscalls/msleep.c b/kernel/syscalls/msleep.c
index a752d94..47cc785 100644
--- a/kernel/syscalls/msleep.c
+++ b/kernel/syscalls/msleep.c
@@ -5,5 +5,5 @@
void syscall_msleep(u32 ms) {
get_current_task()->sleep_until = pit_num_ms() + ms;
- switch_task();
+ switch_task(1);
}
diff --git a/meta/debug.sh b/meta/debug.sh
index d1eeedb..2cb3d90 100755
--- a/meta/debug.sh
+++ b/meta/debug.sh
@@ -2,5 +2,6 @@
scriptdir="$(dirname "$0")"
cd "$scriptdir"
cd ..
-qemu-system-i386 -no-reboot -no-shutdown -serial file:./logs/serial.log -hda ./meta/ext2.img -m 1G -cdrom ./kernel/myos.iso -s -S &
+#qemu-system-i386 -no-reboot -no-shutdown -serial file:./logs/serial.log -hda ./meta/ext2.img -m 1G -cdrom ./kernel/myos.iso -s -S &
+qemu-system-i386 -netdev user,id=n0,hostfwd=tcp:127.0.0.1:6001-:6000 -device rtl8139,netdev=n0 -object filter-dump,id=id,netdev=n0,file=./logs/netout -no-reboot -no-shutdown -chardev stdio,id=char0,logfile=./logs/serial.log,signal=off -serial chardev:char0 -drive id=disk,file=./meta/ext2.img,if=none -device ahci,id=ahci -device ide-hd,drive=disk,bus=ahci.0 -m 512M -cdrom ./kernel/myos.iso -s -S &
gdb -x .gdbinit
diff --git a/meta/userland.sh b/meta/userland.sh
index 94ab441..de6cbd5 100755
--- a/meta/userland.sh
+++ b/meta/userland.sh
@@ -15,8 +15,10 @@ make -C ./userland/windowserver
make -C ./userland/test
make -C ./userland/minibox
make -C ./userland/libppm
+make -C ./userland/rtl8139
mkdir sysroot
+sudo cp ./userland/rtl8139/rtl8139 ./sysroot/rtl8139
sudo cp ./userland/libppm/ppm ./sysroot/ppm
sudo cp ./userland/sh/sh ./sysroot/sh
sudo cp ./userland/terminal/term ./sysroot/term
diff --git a/userland/libc/include/syscall.h b/userland/libc/include/syscall.h
index b50c061..72f781d 100644
--- a/userland/libc/include/syscall.h
+++ b/userland/libc/include/syscall.h
@@ -45,6 +45,13 @@
#define SYS_IPC_READ 36
#define SYS_IPC_WRITE 37
#define SYS_IPC_WRITE_TO_PROCESS 38
+#define SYS_OUTW 39
+#define SYS_INL 40
+#define SYS_OUTL 41
+#define SYS_MAP_FRAMES 42
+#define SYS_VIRTUAL_TO_PHYSICAL 43
+#define SYS_INSTALL_IRQ 44
+#define SYS_TMP_KERNEL_HANDLE_PACKET 45
int syscall(uint32_t eax, uint32_t ebx, uint32_t ecx, uint32_t edx,
uint32_t esi, uint32_t edi);
diff --git a/userland/libppm/ppm.c b/userland/libppm/ppm.c
index 030c68d..9013e27 100644
--- a/userland/libppm/ppm.c
+++ b/userland/libppm/ppm.c
@@ -64,36 +64,47 @@ int load_ppm6_file(FILE *fp, const struct PPM_IMAGE *img, uint32_t buf_width,
printf("end malloc\n");
printf("fread");
- int rc = fread(rgb, 3, n_pixels, fp);
+ const int rc = fread(rgb, 3, n_pixels, fp);
if (0 == rc)
return 0;
printf("end fread");
uint32_t *p = rgb;
+ u32 buf_size = buf_height * buf_width;
if (1 == modifier) {
- for (; rc--; p = ((uint8_t *)p) + 3) {
- uint32_t v = *p;
- buffer[cy * buf_width + cx] =
- ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16);
+ for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) {
+ if (cx > buf_width) {
+ i--;
+ } else {
+ uint32_t v = *p;
+ buffer[cy * buf_width + cx] =
+ ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16);
+ }
cx++;
if (cx == img->width) {
cx = 0;
cy++;
+ i--;
continue;
}
}
} else {
- for (; rc--; p = ((uint8_t *)p) + 3) {
+ for (int i = 0; i < rc && i < buf_size; i++, p = ((uint8_t *)p) + 3) {
((uint8_t *)p)[0] *= modifier;
((uint8_t *)p)[1] *= modifier;
((uint8_t *)p)[2] *= modifier;
- uint32_t v = *p;
- buffer[cy * buf_width + cx] =
- ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16);
+ if (cx > buf_width) {
+ i--;
+ } else {
+ uint32_t v = *p;
+ buffer[cy * buf_width + cx] =
+ ((v & 0xFF) << 16) | ((v & 0xFF00)) | ((v & 0xFF0000) >> 16);
+ }
cx++;
if (cx == img->width) {
cx = 0;
cy++;
+ i--;
continue;
}
}