summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/heap.c6
-rw-r--r--src/kernel/kernel.c23
-rw-r--r--src/kernel/libc.c8
-rw-r--r--src/kernel/page.c97
-rw-r--r--src/kernel/random.c7
-rw-r--r--src/kernel/smp.c30
-rw-r--r--src/kernel/smp_racetest.c (renamed from src/kernel/testmalloc.c)21
-rw-r--r--src/kernel/smp_trampoline.asm1
8 files changed, 165 insertions, 28 deletions
diff --git a/src/kernel/heap.c b/src/kernel/heap.c
index db6392f..e2dcbc7 100644
--- a/src/kernel/heap.c
+++ b/src/kernel/heap.c
@@ -26,10 +26,11 @@
typedef struct __attribute__((packed)) heap_chunk {
- unsigned int free:1;
unsigned int size:4; //will use with flags later if needed
unsigned int lsize:4;
- unsigned long reserved:55;
+ unsigned int free:1;
+ unsigned int mutex:1;
+ unsigned long reserved:54;
struct heap_chunk *fd;
struct heap_chunk *bk;
} chunk;
@@ -203,6 +204,7 @@ void *malloc(size_t size) {
return (void *)on_chunk + sizeof(chunk);
}
+
void *realloc(void *old_chunk, size_t size) {
void *new_chunk = malloc(size);
memcpy(new_chunk, old_chunk, CHUNK_SIZE_FROM_INDEX(((chunk *)(old_chunk-24))->size));
diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c
index ab60f18..0aa394e 100644
--- a/src/kernel/kernel.c
+++ b/src/kernel/kernel.c
@@ -18,15 +18,24 @@
#include <smp.h>
//testing headers
-//#include <testmalloc.h>
+#include <smp_racetest.h>
void kmain() {
+ printf("Kernal started on core %i\n", get_coreid());
+ sync_malloc();
PANIC(KERNEL_PANIC_KERNEL_RETURNED);
}
+static bool smp_unlocked = false;
void smp_kinit() {
- printf("Kernal started on core <<<<< \n");
+
+ asm(".wait_for_release:\n"
+ "mov al, [%0]\n"
+ "test al, al\n"
+ "jz .wait_for_release\n"
+ ::"m"(smp_unlocked));
+
smp_load_idt();
kmain();
}
@@ -39,7 +48,8 @@ void kernel_init() {
pmap_size = map_complete_physical();
init_klog();
init_pmap(pmap_size);
- printf("\nKernal started on CPU 1!\n");
+ printf("\nKernal started on core 1!\n");
+ //test_malloc(100);
find_root_sdp();
@@ -52,7 +62,12 @@ void kernel_init() {
clear_screen();
debug_pzone();
- smp_boot();
+ smp_prepare();
+
+ //the rest of this needs to get done before the cores start executing
+ init_pmap_smp();
+ smp_unlocked = true;
+
fix_stack();
unmap_lowmem();
kmain();
diff --git a/src/kernel/libc.c b/src/kernel/libc.c
index 4278281..f46c59f 100644
--- a/src/kernel/libc.c
+++ b/src/kernel/libc.c
@@ -1,5 +1,6 @@
#include <stddef.h>
#include <stdint.h>
+#include <stdbool.h>
// TODO clean up variable names
int strncmp(const char *s1, const char *s2, unsigned int n) {
int i;
@@ -18,6 +19,13 @@ size_t strlen(const char *s) {
return(len);
}
+bool is_empty(const char *s, size_t size) {
+ for(size_t i = 0; i < size; i++) {
+ if(s[i]) return false;
+ }
+ return true;
+}
+
int strcmp(const char *s1, const char *s2) {
int i;
for(i = 0; ((s1[i] != '\0') && (s2[i] != '\0')); i++) {
diff --git a/src/kernel/page.c b/src/kernel/page.c
index dea3941..0b286a4 100644
--- a/src/kernel/page.c
+++ b/src/kernel/page.c
@@ -7,11 +7,15 @@
#include <addr.h>
#include <stdbool.h>
#include <cpuid.h>
+#include <smp.h>
+
+#include <heap.h>
//just using char because c is a lil bitch and won't let us use void
extern char _kernel_shared_zone_begin;
-
+//expects core_id
+#define waitlist_i(y) (((core_id) * sizeof(uintptr_t)) + (y))
// PAGE MAPPING
#define PAGEMAP_LOCATION 0x10000
@@ -22,12 +26,21 @@ extern char _kernel_shared_zone_begin;
typedef struct phys_map {
struct phys_map *next;
unsigned int max_buddy;
+
+ //has to be a 16 bit variable
+ uint16_t mutex; //we might improve the speed of this later
+
uint64_t bsize[MAX_BUDDY_ORDER];
uint64_t *buddy[MAX_BUDDY_ORDER];
} pmap_t;
static pmap_t *first_pmap;
+//I'd like to find out a way to get rid of this... we only use it once
+static unsigned int pmap_count = 0;
+
+static pmap_t **waiting_pmaps;
+
#define MEM_AVAILABLE 1
#define MEM_RESERVED 2
#define MEM_APCI_RECLAIMABLE 3
@@ -161,10 +174,10 @@ void debug_pmap() {
//TODO I know you don't want to, but you need to thoroughly check this.
void pfree(void *addr, size_t size) {
int blevel = 0;
- uint64_t *onbyte; //the byte out buddy resides on in the current level
- uint64_t page_bitloc; // how many bits we are away from buddy[0]. Helps calculate bitshifts
- int bbitlen; //length of free'd area in current level
- int lshift; //lshift is how many bits we shift over, rightbit is what it sounds like dumbass
+ uint64_t *onbyte;
+ uint64_t page_bitloc;
+ int bbitlen;
+ int lshift;
pmap_t *pmap = first_pmap;
/* note: there's no security check to see if the page is actually allocated,
@@ -176,7 +189,7 @@ void pfree(void *addr, size_t size) {
if(((uintptr_t)addr & 4095) || (size & 4095)) {
PANIC(KERNEL_PANIC_INVALID_PFREE);
- return; //TODO [minor] some more specificity, not a huge deal
+ return;
}
size /= 0x1000;
for(; pmap != 0; pmap = pmap->next) {
@@ -221,7 +234,7 @@ void pfree(void *addr, size_t size) {
if(bbitlen <= 1) {
*onbyte |= ((uint64_t)1 << lshift);
break;
- } else if(bbitlen & 1) { //check me
+ } else if(bbitlen & 1) {
size -= (1 << blevel);
*onbyte |= ((uint64_t)1 << (bbitlen + lshift));
}
@@ -232,12 +245,16 @@ void pfree(void *addr, size_t size) {
void *palloc(size_t size) {
+ uint8_t core_id = get_coreid();
bool self_alloc;
int min_blevel, blevel;
- uint64_t bbit, unshifted_entry, threshold, bloc; //TODO move when you've confirmed casting stuff
+ uint64_t bbit, unshifted_entry, threshold, bloc;
uint64_t buddy_i, *ret, *bentry;
int itercount;
+ bool unlocked_pmaps_searched = false;
pmap_t *pmap = first_pmap;
+ unsigned int waitingp_i = 0;
+ unsigned int searchingp_i;
if(size == 0) return 0;
@@ -263,7 +280,19 @@ void *palloc(size_t size) {
}
for(blevel = min_blevel; blevel < MAX_BUDDY_ORDER; blevel++) {
- for(pmap = first_pmap; pmap != 0; pmap = pmap->next) {
+ //for(pmap = first_pmap; pmap != 0; pmap = pmap->next) {
+ //while(!unlocked_pmaps_searched ||
+ // is_empty(waiting_pmaps[core_id], sizeof(&pmap) * pmap_count)) {
+ pmap = first_pmap;
+ while(pmap) {
+
+ if(get_set_mutex(&pmap->mutex)) {
+ if(!unlocked_pmaps_searched) waiting_pmaps[waitlist_i(waitingp_i++)] = pmap;
+ goto get_next_pmap;
+ }
+
+
+ if(unlocked_pmaps_searched) waiting_pmaps[waitlist_i(waitingp_i)] = 0;
for(buddy_i = 0; buddy_i < pmap->bsize[blevel]; buddy_i++) {
if(pmap->buddy[blevel][buddy_i] > (uint64_t)0) {
@@ -295,11 +324,42 @@ void *palloc(size_t size) {
}
*bentry |= (unshifted_entry << bloc);
}
- if(!self_alloc) bzero(ret, size * 0x1000);
+ pmap->mutex = 0;
+ if(!self_alloc) bzero(ret, size * 0x1000); //TODO do we really need to bezero here?
return ret;
}
}
+get_next_pmap:
+ pmap->mutex = 0;
+ if(unlocked_pmaps_searched) {
+ pmap = 0;
+ for(searchingp_i = waitingp_i + 1; searchingp_i < pmap_count; searchingp_i++) {
+ if(waiting_pmaps[waitlist_i(searchingp_i)]) {
+ pmap = waiting_pmaps[waitlist_i(searchingp_i)];
+ break;
+ }
+ }
+ if(!pmap) {
+ for(searchingp_i = 0; searchingp_i <= waitingp_i; searchingp_i++) {
+ if(waiting_pmaps[waitlist_i(searchingp_i)]) {
+ pmap = waiting_pmaps[waitlist_i(searchingp_i)];
+ break;
+ }
+ }
+ }
+ }
+ else {
+ if(!pmap->next) {
+ pmap = waiting_pmaps ? waiting_pmaps[waitlist_i(0)] : 0;
+ unlocked_pmaps_searched = true;
+ }
+ else {
+ pmap = pmap->next;
+ }
+ }
}
+ unlocked_pmaps_searched = false;
+ waitingp_i = 0;
}
return 0;
}
@@ -374,12 +434,19 @@ size_t map_complete_physical() {
}
}
-pmap_t *init_pmap(size_t pagetable_size) {
+void init_pmap_smp() {
+ size_t pmap_arrsize = corecount * pmap_count * sizeof(waiting_pmaps);
+ waiting_pmaps = malloc(pmap_arrsize);
+ bzero(waiting_pmaps, pmap_arrsize);
+}
+
+void *init_pmap(size_t pagetable_size) {
pmap_t *pmap, *last_pmap;
struct memory_table *zones = (void *)ZONE_MAP;
int budorder, zone_i;
uint64_t pmap_size, pmap_bbitsize, zone_size;
bool first_pmap_i = true;
+
@@ -387,6 +454,7 @@ pmap_t *init_pmap(size_t pagetable_size) {
if((zones[zone_i].type == MEM_AVAILABLE) && (zones[zone_i].ACPI & 1) &&
zones[zone_i].length >= (0x2000)) {
printf("found allocatable map at %p\n", zones[zone_i].base);
+ pmap_count++;
last_pmap = pmap;
if(zones[zone_i].base == (void *)0x100000) {
zone_size = zones[zone_i].length - (((uint64_t)&_kernel_shared_zone_begin - 0x100000) + pagetable_size);
@@ -396,7 +464,6 @@ pmap_t *init_pmap(size_t pagetable_size) {
zone_size = zones[zone_i].length;
pmap = PHYS_TO_VIRT(zones[zone_i].base);
}
-
if(first_pmap_i) {
pmap->next = NULL;
first_pmap_i = false;
@@ -405,6 +472,8 @@ pmap_t *init_pmap(size_t pagetable_size) {
pmap->next = last_pmap;
}
+ pmap->mutex = 0;
+
for(budorder = 0; budorder < MAX_BUDDY_ORDER; budorder++) {
pmap_bbitsize = zone_size / (0x1000 << budorder);
pmap->bsize[budorder] = DIV_ROUND_UP(pmap_bbitsize , 64);
@@ -440,8 +509,8 @@ pmap_t *init_pmap(size_t pagetable_size) {
}
pmap_size = (uint64_t)(pmap->buddy[pmap->max_buddy] + pmap->bsize[pmap->max_buddy]) - (uint64_t)pmap;
- first_pmap = pmap; //we spoof palloc into allocating from the specific required pmap.
- palloc(pmap_size); //TODO (MAJOR BUG) something isn't right, I don't think
+ first_pmap = pmap;
+ palloc(pmap_size);
}
}
return pmap;
diff --git a/src/kernel/random.c b/src/kernel/random.c
index 404223a..c959f6c 100644
--- a/src/kernel/random.c
+++ b/src/kernel/random.c
@@ -7,10 +7,9 @@ static bool hw_random = false;
static unsigned long int seed = -1;
void randinit() {
- unsigned int unused, eax, ecx;
- eax = 0;
+ unsigned int unused, ecx;
ecx = 0;
- __get_cpuid(1, &eax, &unused, &ecx, &unused);
+ __get_cpuid(1, &unused, &unused, &ecx, &unused);
hw_random = (ecx >> 30) & 1;
printf("Kernel random source: %s.\n", (hw_random) ? "rdrand" : "pseudo");
}
@@ -31,6 +30,6 @@ unsigned int randint() {
seed = 1103515245 * seed + 12345;
return(unsigned int)(seed / 65536) % 32768;
}
- return 0;
+ return random_long;
}
diff --git a/src/kernel/smp.c b/src/kernel/smp.c
index ff08f93..a55fe49 100644
--- a/src/kernel/smp.c
+++ b/src/kernel/smp.c
@@ -53,11 +53,30 @@ struct cpu_info {
static struct gdt_descriptor gdtr;
+struct cores_info cores;
-void smp_boot() {
+struct apicid_to_coreid_deleteme { //WILL BE DELETED AFTER THREADING EXISTS TODO
+ uint8_t apic_id;
+ uint8_t core_id;
+};
+
+static struct apicid_to_coreid_deleteme *apicid_to_coreid;
+
+
+uint8_t get_coreid() { //WILL BE DELETED AFTER THREADING EXISTS TODO
+ uint32_t ebx, unused_cpuid;
+ uint8_t apic_id;
+ __get_cpuid(1, &unused_cpuid, &ebx, &unused_cpuid, &unused_cpuid);
+ apic_id = ebx >> 24;
+ for(uint8_t core = 0; core < corecount; core++) {
+ if(apicid_to_coreid[core].apic_id == apic_id) return apicid_to_coreid[core].core_id;
+ }
+ return 0;
+}
+
+void smp_prepare() {
uint8_t cores_active = 1;
uint8_t stack_i = 0, core_i;
- struct cores_info cores;
struct icr_reg icr;
struct cpu_info *stackarray;
get_coreinfo(&cores);
@@ -72,11 +91,18 @@ void smp_boot() {
corecount = cores.corecount;
stackarray = malloc(sizeof(struct cpu_info) * (cores.corecount - 1));
+ apicid_to_coreid = malloc(sizeof(struct apicid_to_coreid_deleteme) * (cores.corecount - 1));
for(core_i = 0; core_i < cores.corecount; core_i++) {
+
+ //WILL BE DELETED AFTER THREADING EXISTS TODO
+ apicid_to_coreid[core_i].apic_id = cores.apic_id[core_i];
+ apicid_to_coreid[core_i].core_id = core_i;
+
if(cores.apic_id[core_i] == cores.bsp) continue;
stackarray[stack_i].apic_id = cores.apic_id[core_i];
stackarray[stack_i].stack = palloc(0x1000);
stackarray[stack_i].secondary_bsp = (stack_i)? false : true;
+
stack_i++;
}
for(stack_i = 0; stack_i < (cores.corecount - 1); stack_i++) {
diff --git a/src/kernel/testmalloc.c b/src/kernel/smp_racetest.c
index 5733c7c..f86e030 100644
--- a/src/kernel/testmalloc.c
+++ b/src/kernel/smp_racetest.c
@@ -4,9 +4,13 @@
#include <heap.h>
#include <libc.h>
#include <random.h>
+#include <smp.h>
+#include <paging.h>
//will delete later
+static uint8_t lockeroni = 0;
+
void test_malloc(unsigned int cnt) {
void *testchunks[cnt];
unsigned int rindex[cnt], testchunk_size, i, x;
@@ -15,7 +19,7 @@ void test_malloc(unsigned int cnt) {
for(x = 0; x < cnt; x++) {
testchunk_size = (CHUNK_SIZE_FROM_INDEX(randint() % 7) - 24);
testchunks[x] = malloc(testchunk_size);
- //printf("ALLOCATING CHUNK %p SIZE %i\n", (void *)testchunks[x] - 24, testchunk_size);
+ printf("ALLOCATING CHUNK %p SIZE %i\n", (void *)testchunks[x] - 24, testchunk_size);
}
for(x = 0; x < cnt;) {
i = randint() % cnt;
@@ -23,13 +27,26 @@ void test_malloc(unsigned int cnt) {
rindex[i] = x;
x++;
}
+
for(x = 0; x < cnt; x++) {
//printf("FREEING CHUNK %p\n", (void *)testchunks[rindex[x]]);
free(testchunks[rindex[x]]);
}
+
printf("\nmalloc tester:\n");
printf("THIS NEEDS TO BE EMPTY______________\n");
debug_heap();
printf("____________________________________\n");
-
+ unlock(&lockeroni);
+}
+uint8_t cores_waiting = 4;
+void sync_malloc() {
+ void *mtest;
+ asm("lock decb [%0]\n"
+ "spinlock:\n"
+ "cmpb [%0], 0\n"
+ "jnz spinlock\n"
+ ::"m"(cores_waiting));
+ mtest = palloc(0x1000);
+ printf("Make sure none of these match -> %lx\n", mtest);
}
diff --git a/src/kernel/smp_trampoline.asm b/src/kernel/smp_trampoline.asm
index 20c971e..cc91c3a 100644
--- a/src/kernel/smp_trampoline.asm
+++ b/src/kernel/smp_trampoline.asm
@@ -185,6 +185,7 @@ pause
jnz .wait_for_gdt
lgdt [final_gdt_descriptor]
+
mov rax, smp_kinit
jmp rax