BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / c738dbb1e7e7a46a98436326234826eef71083e2

// Related

Nucleus

Barry CPU specific segment c738dbb (3 years, 2 months ago)
diff --git a/include/nucleus/cpu.h b/include/nucleus/cpu.h
index b1e4cae..f4d7175 100644
--- a/include/nucleus/cpu.h
+++ b/include/nucleus/cpu.h
@@ -2,9 +2,16 @@
 #define _NUCLEUS_CPU_H
 
 #include <stdint.h>
+#include <nucleus/types.h>
 
 typedef unsigned int cpu_t;
 
+/* Structure for CPU specific data */
+struct CPUData {
+	cpu_t id;
+	Task *task;
+};
+
 /* Structure for an Interrupt Frame */
 struct InterruptFrame {
 	uint32_t ds;
@@ -16,6 +23,8 @@ struct InterruptFrame {
 typedef void (*exc_handler_t)(struct InterruptFrame *);
 typedef void (*int_handler_t)(struct InterruptFrame *);
 
+extern struct CPUData __seg_gs *cpu;
+
 extern int apic;
 
 extern uintptr_t lapicPtr, ioapicPtr;
@@ -29,4 +38,7 @@ extern cpu_t lapicNums[];
 void register_exception(int num, exc_handler_t addr);
 void register_interrupt(int num, int_handler_t addr);
 
+void set_fs_base(uintptr_t base);
+void set_gs_base(uintptr_t base);
+
 #endif
diff --git a/include/nucleus/driver.h b/include/nucleus/driver.h
index 53df5ec..57eb42f 100644
--- a/include/nucleus/driver.h
+++ b/include/nucleus/driver.h
@@ -3,14 +3,13 @@
 
 #include <sys/types.h>
 #include <nucleus/object.h>
+#include <nucleus/types.h>
 #include <nucleus/vfs.h>
 
 #define MKDEV(maj,min) ((dev_t) (((maj & 0xFFFF) << 16) | (min & 0xFFFF)))
 #define MAJOR(dev) ((dev >> 16) & 0xFFFF)
 #define MINOR(dev) (dev & 0xFFFF)
 
-typedef struct Driver Driver;
-
 extern ObjectType driverType;
 
 unsigned short register_driver(unsigned short major, FileOps *ops);
diff --git a/include/nucleus/memory.h b/include/nucleus/memory.h
index 059ba9f..595d152 100644
--- a/include/nucleus/memory.h
+++ b/include/nucleus/memory.h
@@ -5,6 +5,7 @@
 #include <stddef.h>
 #include <sys/mman.h>
 #include <nucleus/object.h>
+#include <nucleus/types.h>
 
 #define PAGE_SIZE 0x1000
 
@@ -14,9 +15,6 @@
 typedef uint32_t page_t;
 typedef uint32_t page_table_t;
 typedef uint32_t page_dir_t;
-typedef struct Page Page;
-typedef struct VirtualMemory VirtualMemory;
-typedef struct VMRegion VMRegion;
 
 /* Page Table Entry flags */
 enum PTEFlag {
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index 139f7ca..9683410 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -4,6 +4,7 @@
 #include <sys/types.h>
 #include <stddef.h>
 #include <nucleus/cpu.h>
+#include <nucleus/types.h>
 
 typedef struct Spinlock Spinlock;
 typedef struct ObjectType ObjectType;
@@ -11,7 +12,6 @@ typedef struct Object Object;
 typedef struct ObjectList ObjectList;
 typedef struct Iterator Iterator;
 typedef int (*compare_callback_t)(void *, void *);
-typedef struct Task Task;
 
 /* Spinlock */
 struct Spinlock {
diff --git a/include/nucleus/task.h b/include/nucleus/task.h
index 1e91a33..80a2a71 100644
--- a/include/nucleus/task.h
+++ b/include/nucleus/task.h
@@ -6,11 +6,9 @@
 #include <nucleus/cpu.h>
 #include <nucleus/object.h>
 #include <nucleus/memory.h>
+#include <nucleus/types.h>
 #include <nucleus/vfs.h>
 
-typedef struct Task Task;
-typedef struct Signals Signals;
-
 /* Task priorities */
 enum Priority {
 	NONE,
@@ -57,12 +55,11 @@ struct Task {
 	Signals *signals;
 };
 
+#define current cpu->task
+
 extern ObjectType taskType;
 extern ObjectType signalsType;
 
-extern Task *currentTask[];
-#define current currentTask[CPUID]
-
 /* Check if super-user */
 static inline int
 super_user(void)
diff --git a/include/nucleus/types.h b/include/nucleus/types.h
new file mode 100644
index 0000000..d64d543
--- /dev/null
+++ b/include/nucleus/types.h
@@ -0,0 +1,28 @@
+#ifndef _NUCLEUS_TYPES_H
+#define _NUCLEUS_TYPES_H
+
+/* Driver */
+typedef struct Driver Driver;
+
+/* Memory */
+typedef struct Page Page;
+typedef struct VirtualMemory VirtualMemory;
+typedef struct VMRegion VMRegion;
+
+/* Task */
+typedef struct Task Task;
+typedef struct Signals Signals;
+
+/* VFS */
+typedef struct FSType FSType;
+typedef struct FileSystem FileSystem;
+typedef struct Files Files;
+typedef struct SuperBlock SuperBlock;
+typedef struct SuperOps SuperOps;
+typedef struct Inode Inode;
+typedef struct InodeOps InodeOps;
+typedef struct DirEntry DirEntry;
+typedef struct File File;
+typedef struct FileOps FileOps;
+
+#endif
diff --git a/include/nucleus/vfs.h b/include/nucleus/vfs.h
index 8dd295a..6bdf673 100644
--- a/include/nucleus/vfs.h
+++ b/include/nucleus/vfs.h
@@ -6,22 +6,12 @@
 #include <dirent.h>
 #include <nucleus/object.h>
 #include <nucleus/memory.h>
+#include <nucleus/types.h>
 
 #define NFILES 32
 #define NAME_MAX 255
 #define PATH_MAX 1024
 
-typedef struct FSType FSType;
-typedef struct FileSystem FileSystem;
-typedef struct Files Files;
-typedef struct SuperBlock SuperBlock;
-typedef struct SuperOps SuperOps;
-typedef struct Inode Inode;
-typedef struct InodeOps InodeOps;
-typedef struct DirEntry DirEntry;
-typedef struct File File;
-typedef struct FileOps FileOps;
-
 typedef Inode *(*mount_callback_t)(FSType *, int, const char *, void *);
 
 /* Structure for a Super Block */
diff --git a/kernel/acpi/apic.c b/kernel/acpi/apic.c
index 73da356..c7f8259 100644
--- a/kernel/acpi/apic.c
+++ b/kernel/acpi/apic.c
@@ -103,7 +103,7 @@ apic_start_timer(void)
 {
 	/* Wait for this processor's "turn" */
 	static cpu_t c = 0;
-	while (c != CPUID);
+	while (c != cpu->id);
 
 	/* Start LAPIC countdown from -1 */
 	LAPIC(0x3E0) = 3;
diff --git a/kernel/gdt.c b/kernel/gdt.c
index bd083a6..b9cebb6 100644
--- a/kernel/gdt.c
+++ b/kernel/gdt.c
@@ -15,12 +15,26 @@
 #include <nucleus/cpu.h>
 #include "desc.h"
 
+/* GDT Entry Indicies */
+enum GDTIndex {
+	GDT_NULL,
+	GDT_KERN_CODE,
+	GDT_KERN_DATA,
+	GDT_USER_CODE,
+	GDT_USER_DATA,
+	GDT_FS,
+	GDT_GS,
+	GDT_TSS,
+};
+
 /* Structure for a GDT Entry */
 static struct GDTEntry {
 	uint16_t limitLower, baseLower;
 	uint8_t baseMiddle, access, gran, baseHigher;
 } __attribute__((packed)) *gdt[MAX_CPUS]; /* Per CPU */
 
+#define GDT_OFFSET(i) (i * sizeof(struct GDTEntry))
+
 /* Structure for a TSS Entry */
 static struct TSSEntry {
 	uint32_t prevTSS;
@@ -58,7 +72,8 @@ cpu_load_gdt(void)
 	 * an existing page, the new structures should be allocated in there.
 	 * Otherwise, a new page frame should be allocated.
 	 */
-	size_t size = (sizeof(struct GDTEntry) * 6) + sizeof(struct TSSEntry);
+	size_t size = (sizeof(struct GDTEntry) * (GDT_TSS + 1))
+	            + sizeof(struct TSSEntry);
 	off_t idx = CPUID % (PAGE_SIZE / size);
 	off_t block = (CPUID / (PAGE_SIZE / size)) * (PAGE_SIZE / size);
 	if (idx == 0)
@@ -68,29 +83,52 @@ cpu_load_gdt(void)
 
 	memset(gdt[CPUID], 0, size);
 
-	gdt_set_gate(0, 0x00000000, 0x00000000, 0x00, 0x00); /* Null */
-	/* Ring 0 */
-	gdt_set_gate(1, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF); /* Code */
-	gdt_set_gate(2, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF); /* Data */
-	/* Ring 3 */
-	gdt_set_gate(3, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF); /* Code */
-	gdt_set_gate(4, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF); /* Data */
+	gdt_set_gate(GDT_NULL,      0x00000000, 0x00000000, 0x00, 0x00);
+	gdt_set_gate(GDT_KERN_CODE, 0x00000000, 0xFFFFFFFF, 0x9A, 0xCF);
+	gdt_set_gate(GDT_KERN_DATA, 0x00000000, 0xFFFFFFFF, 0x92, 0xCF);
+	gdt_set_gate(GDT_USER_CODE, 0x00000000, 0xFFFFFFFF, 0xFA, 0xCF);
+	gdt_set_gate(GDT_USER_DATA, 0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
+	gdt_set_gate(GDT_FS,        0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
+	gdt_set_gate(GDT_GS,        0x00000000, 0xFFFFFFFF, 0xF2, 0xCF);
 
-	uint32_t addr = (uint32_t) gdt[CPUID] + (sizeof(struct GDTEntry) * 6);
-	gdt_set_gate(5, addr, sizeof(struct TSSEntry) - 1, 0xE9, 0);
+	uint32_t addr = (uint32_t) (gdt[CPUID] + (GDT_TSS + 1));
+	gdt_set_gate(GDT_TSS, addr, sizeof(struct TSSEntry) - 1, 0xE9, 0);
 
 	tss[CPUID] = (void *) addr;
 	tss[CPUID]->ss0 = 0x10;
 	tss[CPUID]->esp0 = 0xF0800000 - sizeof(uintptr_t);
-	tss[CPUID]->cs = 0x08 | 0;
-	tss[CPUID]->ds = tss[CPUID]->es = tss[CPUID]->ss = 0x10 | 0;
-	tss[CPUID]->fs = tss[CPUID]->gs = 0x10 | 3;
+	tss[CPUID]->cs = GDT_OFFSET(GDT_KERN_CODE) | 0;
+	tss[CPUID]->ds = GDT_OFFSET(GDT_KERN_DATA) | 0;
+	tss[CPUID]->es = tss[CPUID]->ss = tss[CPUID]->ds;
+	tss[CPUID]->fs = tss[CPUID]->gs = GDT_OFFSET(GDT_FS) | 3;
 	tss[CPUID]->iomapBase = sizeof(struct TSSEntry);
 
 	struct DescRecord ptr = {
-		.limit = sizeof(struct GDTEntry) * 6,
+		.limit = sizeof(struct GDTEntry) * (GDT_TSS + 1),
 		.base = (uintptr_t) gdt[CPUID],
 	};
 	asm volatile("lgdt %0" :: "m" (ptr));
-	asm volatile("ltr %w0" :: "q" (0x28 | 3));
+	asm volatile("ltr %w0" :: "q" (GDT_OFFSET(GDT_TSS) | 3));
+}
+
+/* Set FS base */
+void
+set_fs_base(uintptr_t base)
+{
+	struct GDTEntry *fs = gdt[CPUID] + GDT_FS;
+	fs->baseLower = (base & 0xFFFF);
+	fs->baseMiddle = (base >> 16) & 0xFF;
+	fs->baseHigher = (base >> 24) & 0xFF;
+	asm volatile("mov %0, %%fs" :: "r" (GDT_OFFSET(GDT_FS) | 3));
+}
+
+/* Set FS base */
+void
+set_gs_base(uintptr_t base)
+{
+	struct GDTEntry *gs = gdt[CPUID] + GDT_GS;
+	gs->baseLower = (base & 0xFFFF);
+	gs->baseMiddle = (base >> 16) & 0xFF;
+	gs->baseHigher = (base >> 24) & 0xFF;
+	asm volatile("mov %0, %%gs" :: "r" (GDT_OFFSET(GDT_GS) | 3));
 }
diff --git a/kernel/idt.c b/kernel/idt.c
index a9f7c79..6aceb88 100644
--- a/kernel/idt.c
+++ b/kernel/idt.c
@@ -28,10 +28,14 @@ void (**interrupts)(struct InterruptFrame *);
 static void
 install_idt_entry(uint8_t num, void *addr)
 {
+	uint8_t type = 0x8E; /* Interrupt gate */
+	if (num < 32)
+		type = 0x8F; /* Trap gate for exceptions */
+
 	IDT[num].offsetLower = (uintptr_t) addr & 0xFFFF;
 	IDT[num].selector = 0x08;
 	IDT[num].zero = 0;
-	IDT[num].typeAttr = 0x8E | 0x60; /* Allowed from ring 3 */
+	IDT[num].typeAttr = type | 0x60; /* Allowed from ring 3 */
 	IDT[num].offsetHigher = (uintptr_t) addr >> 16;
 }
 
@@ -41,11 +45,12 @@ isr_handler(struct InterruptFrame frame)
 {
 	if (!exceptions[frame.intnum] && frame.intnum < 32)
 		panic("[CPU#%d] Failed to handle exception %d (%#.8x) @ %#.8x",
-		      CPUID, frame.intnum, frame.err, frame.eip);
+		      cpu->id, frame.intnum, frame.err, frame.eip);
 
 	/* Run registered handler */
-	if (exceptions[frame.intnum])
-		exceptions[frame.intnum](&frame);
+	exc_handler_t handler = exceptions[frame.intnum];
+	if (handler)
+		handler(&frame);
 
 	/* Send EOI */
 	if (frame.intnum >= 40 && frame.intnum < 48)
@@ -62,7 +67,7 @@ isr_handler(struct InterruptFrame frame)
 void
 register_exception(int num, exc_handler_t addr)
 {
-	if ((num >= 0 && num < 32) || num >= 48)
+	if (num >= 0 && num < 256)
 		exceptions[num] = addr;
 }
 
diff --git a/kernel/isr.S b/kernel/isr.S
index c807e7b..914d855 100644
--- a/kernel/isr.S
+++ b/kernel/isr.S
@@ -1,6 +1,8 @@
 /*
  * This file contains the interrupt service routine stubs.  For the most part
- * they just call into the generic handlers after setting up the stack for them.
+ * they just call into the generic handler after setting up the stack for it.
+ * It pushes the interrupt number and saved registers onto the stack for the
+ * handler to access.
  */
 
 .extern isr_handler
@@ -9,7 +11,6 @@
 .macro exc_err num
 .globl exc\num
 exc\num:
-	cli
 	push $\num
 	jmp isr_stub
 .endm
@@ -17,7 +18,6 @@ exc\num:
 .macro exc_noerr num
 .globl exc\num
 exc\num:
-	cli
 	push $0
 	push $\num
 	jmp isr_stub
@@ -76,7 +76,9 @@ isr_stub:
 	mov $0x10, %ax
 	mov %ax, %ds
 	mov %ax, %es
+	mov $0x28, %ax
 	mov %ax, %fs
+	mov $0x30, %ax
 	mov %ax, %gs
 
 	call isr_handler
@@ -85,10 +87,11 @@ isr_stub:
 	popl %ebx
 	mov %bx, %ds
 	mov %bx, %es
+	mov $0x28, %bx
 	mov %bx, %fs
+	mov $0x30, %bx
 	mov %bx, %gs
 
 	popa
 	addl $8, %esp
-	sti
 	iret
diff --git a/kernel/main.c b/kernel/main.c
index bf1fd8c..76d5ef1 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -17,6 +17,8 @@
 #include "desc.h"
 #include "acpi/acpi.h"
 
+struct CPUData __seg_gs *cpu = 0;
+
 extern char _bss[], _end[];
 void page_fault_handler(struct InterruptFrame *frame);
 
@@ -45,6 +47,8 @@ cpu_load(void)
 	/* Tables */
 	cpu_load_idt();
 	cpu_load_gdt();
+	set_gs_base((uintptr_t) kmalloc(sizeof(struct CPUData)));
+	cpu->id = CPUID;
 
 	asm volatile("sti");
 }
diff --git a/kernel/uname.c b/kernel/uname.c
index c930faf..cf0a931 100644
--- a/kernel/uname.c
+++ b/kernel/uname.c
@@ -9,7 +9,7 @@
 #include <nucleus/memory.h>
 
 static const char *SYSNAME = "Nucleus";
-static const char *RELEASE = "0.9.0";
+static const char *RELEASE = "0.9.1";
 static const char *VERSION = "SMP PREEMPT "__DATE__" "__TIME__;
 static const char *MACHINE = "x86";
 
diff --git a/memory/fault.c b/memory/fault.c
index 5f94b55..efc8b66 100644
--- a/memory/fault.c
+++ b/memory/fault.c
@@ -185,7 +185,7 @@ page_fault_handler(struct InterruptFrame *frame)
 	if (__builtin_expect(!region, 0)) {
 		page_t pg = get_page(addr);
 		panic("[CPU#%d] Page Fault [%d:%d] (%#.8x -> %#.8x [tbl:%d, pg:%d][%#.8x], %s, %s, %s)",
-		      CPUID, current->tgid, current->tid, frame->eip,
+		      cpu->id, current->tgid, current->tid, frame->eip,
 		      addr, (addr >> 12) / 1024, (addr >> 12) % 1024, pg,
 		      present ? "present" : "not present",
 		      write ? "write" : "read",
@@ -213,10 +213,10 @@ early_page_fault_handler(struct InterruptFrame *frame)
 	uint8_t write   = frame->err & (1 << 1);
 	uint8_t user    = frame->err & (1 << 2);
 	if (!PAGE_ADDR(addr))
-		panic("Null dereference @ %#.8x (CPU#%d)", frame->eip, CPUID);
+		panic("Null dereference @ %#.8x (CPU#%d)", frame->eip, cpu->id);
 	ASSERT(!present);
 	kprintf("Allocating frame for %#.8x [%#.8x] CPU#%d",
-	        addr, frame->eip,CPUID);
+	        addr, frame->eip, cpu->id);
 	/* Allocate a page */
 	set_page(addr, alloc_frame() | PTE_PRESENT | PTE_WRITE | PTE_GLOBAL);
 }
diff --git a/object/lock.c b/object/lock.c
index b3d2fb8..d7a7d11 100644
--- a/object/lock.c
+++ b/object/lock.c
@@ -15,7 +15,7 @@ holding(Spinlock *lock)
 {
 	if (current)
 		return (lock->locked && lock->owner == current);
-	return (lock->locked && lock->cpu == (CPUID + 1));
+	return (lock->locked && lock->cpu == (cpu->id + 1));
 }
 
 /* Initialise a lock */
@@ -44,7 +44,7 @@ acquire(Spinlock *lock)
 	if (current)
 		lock->owner = current;
 	else
-		lock->cpu = CPUID + 1;
+		lock->cpu = cpu->id + 1;
 }
 
 /* Release a lock */
diff --git a/task/clone.c b/task/clone.c
index 93c0b94..7f23de3 100644
--- a/task/clone.c
+++ b/task/clone.c
@@ -73,7 +73,7 @@ clone(int flags)
 	put(child);
 	exit_critical_section();
 end:
-	if (tid && !current->inSyscall) {
+	if (!tid && !current->inSyscall) {
 		outb(0x20, 0x20);
 		if (apic)
 			LAPIC(0xB0) = 0;
diff --git a/task/scheduler.c b/task/scheduler.c
index b35192c..02413bd 100644
--- a/task/scheduler.c
+++ b/task/scheduler.c
@@ -15,6 +15,8 @@ void context_switch(uintptr_t eip, page_dir_t pagedir,
                     uintptr_t esi, uintptr_t edi, uintptr_t ebx,
                     uintptr_t ebp, uintptr_t esp);
 
+extern uint8_t slice[];
+
 ObjectList *readyQueue[PRIORITY_COUNT];
 
 /* Switch to a task */
@@ -64,6 +66,7 @@ schedule(void)
 
 	Task *task = current;
 	ObjectList *queue = highest_priority_queue();
+	slice[cpu->id] = 0;
 
 	/* Idle if necessary */
 	if (!queue) {
diff --git a/task/syscall.c b/task/syscall.c
index 8e33ef4..effe6c2 100644
--- a/task/syscall.c
+++ b/task/syscall.c
@@ -113,7 +113,13 @@ syscall_handler(struct InterruptFrame *frame)
 	}
 
 	/* Call function */
-	asm volatile("call *%1" : "=a" (ret) : "r" (syscall->function));
+	asm volatile(
+		"sti;"
+		"call *%1;"
+		"cli"
+		: "=a" (ret)
+		: "r" (syscall->function)
+	);
 
 end:
 	exit_syscall_context();
diff --git a/task/time.c b/task/time.c
index 3f5a50a..d6a47d9 100644
--- a/task/time.c
+++ b/task/time.c
@@ -15,16 +15,16 @@ uint8_t slice[MAX_CPUS] = {0};
 void
 timer_handler(struct InterruptFrame *frame)
 {
-	if (CPUID == 0)
+	if (cpu->id == 0)
 		monotonic++;
 
 	if (!current)
 		return;
-	slice[CPUID]++;
+	slice[cpu->id]++;
 
 	/* Call scheduler */
-	if (slice[CPUID] < (current->priority * 10))
+	if (slice[cpu->id] < (current->priority * 10))
 		return;
-	slice[CPUID] = 0;
+	slice[cpu->id] = 0;
 	schedule();
 }