diff --git a/kernel/Makefile.build b/kernel/Makefile.build index 2015eb2a..1d318aec 100644 --- a/kernel/Makefile.build +++ b/kernel/Makefile.build @@ -1,5 +1,5 @@ AALDIR=$(AALBASE)/$(TARGET) -OBJS=setup.o mem.o debug.o mikc.o listeners.o +OBJS=init.o mem.o debug.o mikc.o listeners.o ap.o syscall.o cls.o DEPSRCS=$(wildcard $(SRC)/*.c) include $(SRC)/configs/config.$(TARGET) diff --git a/kernel/ap.c b/kernel/ap.c index 945d486d..761c8153 100644 --- a/kernel/ap.c +++ b/kernel/ap.c @@ -4,16 +4,32 @@ #include #include +int num_processors = 1; +static volatile int ap_stop = 1; + void ap_idle(void) { int id = aal_mc_get_hardware_processor_id(); - kprintf(" %d", id); while (1) { cpu_halt(); } } +static void ap_wait(void) +{ + while (ap_stop) { + cpu_pause(); + } + + ap_idle(); +} + +void ap_start(void) +{ + ap_stop = 0; +} + void ap_init(void) { struct aal_mc_cpu_info *cpu_info; @@ -36,7 +52,10 @@ void ap_init(void) if (cpu_info->hw_ids[i] == bsp_hw_id) { continue; } - aal_mc_boot_cpu(cpu_info->hw_ids[i], (unsigned long)ap_idle); + aal_mc_boot_cpu(cpu_info->hw_ids[i], (unsigned long)ap_wait); + kprintf(" %d", cpu_info->hw_ids[i]); + + num_processors++; } kprintf(" .. Done\n"); } diff --git a/kernel/cls.c b/kernel/cls.c new file mode 100644 index 00000000..e802405d --- /dev/null +++ b/kernel/cls.c @@ -0,0 +1,28 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +extern int num_processors; + +static struct cpu_local_var *clv; + +void cpu_local_var_init(void) +{ + int z; + + z = sizeof(struct cpu_local_var) * num_processors; + z = (z + PAGE_SIZE - 1) >> PAGE_SHIFT; + + clv = allocate_pages(z, 0); +} + +struct cpu_local_var *get_cpu_local_var(int id) +{ + return clv + id; +} diff --git a/kernel/include/cls.h b/kernel/include/cls.h new file mode 100644 index 00000000..efba7195 --- /dev/null +++ b/kernel/include/cls.h @@ -0,0 +1,27 @@ +#ifndef __HEADER_CLS_H +#define __HEADER_CLS_H +/* + * CPU Local Storage (cls) + */ + +struct malloc_header { + struct malloc_header *next; + unsigned long size; +}; + +struct cpu_local_var { + /* malloc */ + struct malloc_header free_list; + /* Align to 64-byte */ +} __attribute__((aligned(64))); + + +struct cpu_local_var *get_cpu_local_var(int id); +static struct cpu_local_var *get_this_cpu_local_var(void) +{ + return get_cpu_local_var(aal_mc_get_processor_id()); +} + +#define cpu_local_var(name) get_this_cpu_local_var()->name + +#endif diff --git a/kernel/include/kmalloc.h b/kernel/include/kmalloc.h new file mode 100644 index 00000000..fca96b24 --- /dev/null +++ b/kernel/include/kmalloc.h @@ -0,0 +1,7 @@ +#ifndef __HEADER_KMALLOC_H +#define __HEADER_KMALLOC_H + +void *kmalloc(int size, int flag); +void kfree(void *ptr); + +#endif diff --git a/kernel/include/page.h b/kernel/include/page.h new file mode 100644 index 00000000..41b456d7 --- /dev/null +++ b/kernel/include/page.h @@ -0,0 +1,7 @@ +#ifndef __HEADER_PAGE_H +#define __HEADER_PAGE_H + +void *allocate_pages(int npages, enum aal_mc_ap_flag flag); +void free_pages(void *va, int npages); + +#endif diff --git a/kernel/init.c b/kernel/init.c new file mode 100644 index 00000000..14eda559 --- /dev/null +++ b/kernel/init.c @@ -0,0 +1,73 @@ +#include +#include +#include +#include +#include +#include +#include + +extern struct aal_kmsg_buf kmsg_buf; + +extern void arch_init(void); +extern void kmsg_init(void); +extern void mem_init(void); +extern void ikc_master_init(void); +extern void ap_init(void); +extern void arch_ready(void); +extern void mc_ikc_init(void); +extern void cpu_local_var_init(void); +extern void kmalloc_init(void); +extern void ap_start(void); + +static aal_mc_kernel_context_t idle_ctx; + +static void idle(void) +{ + while (1) { + cpu_enable_interrupt(); + cpu_halt(); + } +} + +extern int syscall(int, aal_mc_user_context_t *); + +static void handler_init(void) +{ + aal_mc_set_syscall_handler(syscall); +} + +static void rest_init(void) +{ + handler_init(); + + ap_init(); + cpu_local_var_init(); + kmalloc_init(); + mc_ikc_init(); + + ap_start(); +} + +int main(void) +{ + kmsg_init(); + + kputs("MCK started.\n"); + + arch_init(); + + mem_init(); + + ikc_master_init(); + + rest_init(); + + arch_ready(); + + kputs("MCK/AAL booted.\n"); + + aal_mc_init_context(&idle_ctx, NULL, idle); + aal_mc_switch_context(NULL, &idle_ctx); + + return 0; +} diff --git a/kernel/mem.c b/kernel/mem.c index 6387d063..6070125e 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -6,6 +6,8 @@ #include #include +#include + static struct aal_page_allocator_desc *pa_allocator; static unsigned long pa_start, pa_end; @@ -120,3 +122,103 @@ void mem_init(void) /* Prepare the kernel virtual map space */ virtual_allocator_init(); } + +void kmalloc_init(void) +{ + struct cpu_local_var *v = get_this_cpu_local_var(); + struct malloc_header *h = &v->free_list; + + h->next = &v->free_list; + h->size = 0; +} + +void *kmalloc(int size, int flag) +{ + struct cpu_local_var *v = get_this_cpu_local_var(); + struct malloc_header *h = &v->free_list, *prev, *p; + int u, req_page; + + if (size >= PAGE_SIZE * 4) { + return NULL; + } + + u = (size + sizeof(*h) - 1) / sizeof(*h); + + prev = h; + h = h->next; + + while (1) { + if (h == &v->free_list) { + req_page = ((u + 1) * sizeof(*h) + PAGE_SIZE - 1) + >> PAGE_SHIFT; + + h = allocate_pages(req_page, 0); + prev->next = h; + h->size = (req_page * PAGE_SIZE) / sizeof(*h) - 2; + /* Guard entry */ + p = h + h->size + 1; + p->next = &v->free_list; + h->next = p; + } + + if (h->size >= u) { + if (h->size == u || h->size == u + 1) { + prev->next = h->next; + return h + 1; + } else { /* Divide */ + h->size -= u + 1; + + p = h + h->size + 1; + p->size = u; + + return p + 1; + } + } + prev = h; + h = h->next; + } +} + +void kfree(void *ptr) +{ + struct cpu_local_var *v = get_this_cpu_local_var(); + struct malloc_header *h = &v->free_list, *p = ptr; + int combined = 0; + + h = h->next; + + p--; + + while ((p < h || p > h->next) && h != &v->free_list) { + h = h->next; + } + + if (h + h->size + 1 == p && h->size != 0) { + combined = 1; + h->size += p->size + 1; + } + if (h->next == p + p->size + 1 && h->next->size != 0) { + combined = 1; + h->size += h->next->size + 1; + h->next = h->next->next; + } + if (!combined) { + p->next = h->next; + h->next = p; + } +} + +void print_free_list(void) +{ + struct cpu_local_var *v = get_this_cpu_local_var(); + struct malloc_header *h = &v->free_list; + + h = h->next; + + kprintf("free_list : \n"); + while (h != &v->free_list) { + kprintf(" %p : %p, %d ->\n", h, h->next, h->size); + h = h->next; + } + kprintf("\n"); +} diff --git a/kernel/setup.c b/kernel/setup.c deleted file mode 100644 index cdef99af..00000000 --- a/kernel/setup.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include -#include -#include -#include - -extern struct aal_kmsg_buf kmsg_buf; - -extern void arch_init(void); -extern void kmsg_init(void); -extern void mem_init(void); -extern void ikc_master_init(void); -extern void arch_ready(void); -extern void mc_ikc_init(void); - -int main(void) -{ - kmsg_init(); - - kputs("MCK started.\n"); - - arch_init(); - - mem_init(); - - ikc_master_init(); - - mc_ikc_init(); - - arch_ready(); - cpu_enable_interrupt(); - - kputs("MCK/AAL booted.\n"); - - while (1) { - cpu_halt(); - } - return 0; -} diff --git a/kernel/syscall.c b/kernel/syscall.c new file mode 100644 index 00000000..c69d5354 --- /dev/null +++ b/kernel/syscall.c @@ -0,0 +1,13 @@ +#include +#include +#include +#include +#include +#include + +int syscall(int num, aal_mc_user_context_t *ctx) +{ + kprintf("System call #%d\n", num); + + return -ENOSYS; +}