aboutsummaryrefslogtreecommitdiff
path: root/src/sys
diff options
context:
space:
mode:
authorChristian Cunningham <cc@localhost>2022-03-24 09:38:08 -0700
committerChristian Cunningham <cc@localhost>2022-03-24 09:38:08 -0700
commit93bf62580a68533dc8252b9a2a055c02f34ecb67 (patch)
tree1b1ca92ebbe107a998136a1442c0dba5be885e13 /src/sys
parent3e64dda5d5c350cc325650133f7e64967f1efe84 (diff)
Modularized
Diffstat (limited to 'src/sys')
-rw-r--r--src/sys/core.c58
-rw-r--r--src/sys/kernel.S32
-rw-r--r--src/sys/power.c39
-rw-r--r--src/sys/schedule.S53
-rw-r--r--src/sys/schedule.c468
5 files changed, 0 insertions, 650 deletions
diff --git a/src/sys/core.c b/src/sys/core.c
deleted file mode 100644
index d76b712..0000000
--- a/src/sys/core.c
+++ /dev/null
@@ -1,58 +0,0 @@
-#include <cpu/irq.h>
-#include <cpu.h>
-#include <drivers/uart.h>
-#include <globals.h>
-#include <graphics/lfb.h>
-#include <lib/kmem.h>
-#include <lib/mmu.h>
-#include <lib/strings.h>
-#include <symbols.h>
-#include <sys/core.h>
-#include <sys/power.h>
-#include <sys/schedule.h>
-#include <util/mutex.h>
-#include <util/status.h>
-#include <util/time.h>
-
-// Initialize IRQs
-void sysinit(void)
-{
- // Initialize System Globals
- stimeh = *(unsigned long*)SYS_TIMER_CHI;
- stimel = *(unsigned long*)SYS_TIMER_CLO;
- *(unsigned long*) SYS_TIMER_C0 = 2000000 + stimeh; // 2 second trigger
- uart_init();
- ///...
-
- // Route GPU interrupts to Core 0
- store32(0x00, GPU_INTERRUPTS_ROUTING);
-
- // Mask Overrun of UART0
- store32(1<<4, UART0_IMSC);
- // Enable UART GPU IRQ
- store32(1<<25, IRQ_ENABLE2);
- // Enable Timer
- //// Get the frequency
- cntfrq = read_cntfrq();
- // Clear cntv interrupt and set next 1 second timer
- write_cntv_tval(cntfrq);
- // Route timer to core0 fiq
- routing_core0cntv_to_core0fiq();
- // Enable timer
- enablecntv();
- // Enable system timer
- store32(SYS_TIMER_SC_M0, IRQ_ENABLE1);
-
- // Graphics Initialize
- lfb_init();
- lfb_showpicture();
-
- // Initialize Memory Management Unit
- mmu_init();
-
- // Initialize Mutex Manager
- mutex_init();
-
- // Start Scheduler
- init_scheduler();
-}
diff --git a/src/sys/kernel.S b/src/sys/kernel.S
deleted file mode 100644
index 71b22a1..0000000
--- a/src/sys/kernel.S
+++ /dev/null
@@ -1,32 +0,0 @@
-.section ".text.kernel"
-
-.include "macros.inc"
-
-.globl kernel_main
-kernel_main:
- bl sysinit
- bl status
- ldr r2, =ttbr_msg
- mov r0, #23
- mov r1, #0
- mov r3, #0xFF00
- bl draw_cstring
- // Initialize System Cycle Counter
- mov r0, #1
- mcr p15, 0, r0, c9, c14, 0
- mov r0, #1
- mcr p15, 0, r0, c9, c12, 0
- mov r0, #0x80000000
- mcr p15, 0, r0, c9, c12, 1
-
- // Intentional undefined instruction
- // .word 0xf7f0a000
- cpsie ai, #0x10
- svc #2 // Start scheduling!
-2:
- wfe
- b 2b
-
-.section .data
-ttbr_msg:
- .asciz "MMU Initialized!"
diff --git a/src/sys/power.c b/src/sys/power.c
deleted file mode 100644
index c4f12a9..0000000
--- a/src/sys/power.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <symbols.h>
-#include <sys/core.h>
-#include <sys/power.h>
-
-//https://github.com/raspberrypi/linux/blob/aeaa2460db088fb2c97ae56dec6d7d0058c68294/drivers/watchdog/bcm2835_wdt.c
-void wdt_start(void)
-{
- store32(BCM2835_PERI_BASE + PM_WDOG, PM_PASSWORD | (SECS_TO_WDOG_TICS(100) & PM_WDOG_TIME_SET));
- unsigned long cur = load32(BCM2835_PERI_BASE + PM_RSTC);
- store32(BCM2835_PERI_BASE + PM_RSTC, PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) | PM_RSTC_WRCFG_FULL_RESET);
-}
-
-void wdt_stop(void)
-{
- store32(BCM2835_PERI_BASE + PM_RSTC, PM_PASSWORD | PM_RSTC_RESET);
-}
-
-void __bcm2835_restart(unsigned char partition)
-{
- unsigned long val, rsts;
- rsts = (partition & 1) | ((partition & 0b10) << 1) |
- ((partition & 0b100) << 2) | ((partition & 0b1000) << 3) |
- ((partition & 0b10000) << 4) | ((partition & 0b100000) << 5);
- val = load32(BCM2835_PERI_BASE + PM_RSTS);
- val &= PM_RSTS_PARTITION_CLR;
- val |= PM_PASSWORD | rsts;
- store32(BCM2835_PERI_BASE + PM_RSTS, val);
- store32(BCM2835_PERI_BASE + PM_WDOG, 10 | PM_PASSWORD);
- val = load32(BCM2835_PERI_BASE + PM_RSTC);
- val &= PM_RSTC_WRCFG_CLR;
- val |= PM_PASSWORD | PM_RSTC_WRCFG_FULL_RESET;
- store32(BCM2835_PERI_BASE + PM_RSTC, val);
- delay(1);
-}
-
-void bcm2835_power_off(void)
-{
- __bcm2835_restart(63); // Partition 63 => Halt
-}
diff --git a/src/sys/schedule.S b/src/sys/schedule.S
deleted file mode 100644
index a47252c..0000000
--- a/src/sys/schedule.S
+++ /dev/null
@@ -1,53 +0,0 @@
-.section ".text"
-.globl schedule
-
-.include "macros.inc"
-
-// Assumption: Enter in SVC mode
-schedule:
- preserve_ctx
- ldr r1, =irqlr
- ldr r0, [r1]
- cmp r0, #0
- beq 1f
- // Replace LR with IRQ's LR
- ldr r3, =scheduler
- ldr r2, [r3, #0] // struct Thread* rthread
- str r0, [r2, #0] // svc_lr -> void* pc
- // Clear IRQ's LR
- mov r0, #0
- str r0, [r1]
-1:
- bl next_thread // Thread* next -> r0
- ldr r3, =scheduler
- str r0, [r3, #0] // next -> rthread
- restore_ctx
- subs pc, lr, #0
-
-.globl cleanup
-cleanup:
- bl c_cleanup
- // usrloop -> rthread
- ldr r3, =scheduler
- ldr r2, =usrloopthread
- str r2, [r3, #0]
- ldr sp, [r2, #4]
- ldmfd sp!,{lr}
- ldmfd sp!,{r0-r12}
- ldr lr, =kernel_usr_task_loop
- // svc sched
- svc #2
-.globl kernel_usr_task_loop
-kernel_usr_task_loop:
- wfe
- b kernel_usr_task_loop
-
-.globl add_thread
-add_thread:
- mrs r3, cpsr
- and r3, #0x1F
- cmp r3, #0x10
- beq 1f
- b svc_add_thread
-1: svc #3
- bx lr
diff --git a/src/sys/schedule.c b/src/sys/schedule.c
deleted file mode 100644
index 9b6d46e..0000000
--- a/src/sys/schedule.c
+++ /dev/null
@@ -1,468 +0,0 @@
-#include <cpu.h>
-#include <globals.h>
-#include <graphics/lfb.h>
-#include <drivers/uart.h>
-#include <lib/kmem.h>
-#include <sys/schedule.h>
-#include <util/mutex.h>
-
-extern void kernel_usr_task_loop(void);
-
-void init_scheduler(void)
-{
- // Set rthread to usrloopthread - an infinitely running thread so that the pointer will never be null
- usrloopthread.pc = (void*)kernel_usr_task_loop;
- usrloopthread.sp = (void*)0x5FC8;
- *(unsigned long**)usrloopthread.sp = (unsigned long*)kernel_usr_task_loop;
- usrloopthread.sp_base = -1;
- usrloopthread.mptr = 0;
- usrloopthread.pid = -1;
- usrloopthread.priority = -1;
- usrloopthread.old_priority = -1;
- usrloopthread.status = THREAD_READY;
- usrloopthread.offset = -1;
- scheduler.rthread = &usrloopthread;
-
- // Initialize Scheduling Queues
- for (unsigned long p = 0; p < PRIORITIES; p++) {
- // Ready Init
- scheduler.ready[p].start.value = 0;
- scheduler.ready[p].start.next = &scheduler.ready[p].end;
- scheduler.ready[p].start.entry_type = START_ENTRY;
- scheduler.ready[p].end.value = 0;
- scheduler.ready[p].end.next = &scheduler.ready[p].start;
- scheduler.ready[p].end.entry_type = END_ENTRY;
- // Mutex Wait Init
- scheduler.mwait[p].start.value = 0;
- scheduler.mwait[p].start.next = &scheduler.mwait[p].end;
- scheduler.mwait[p].start.entry_type = START_ENTRY;
- scheduler.mwait[p].end.value = 0;
- scheduler.mwait[p].end.next = &scheduler.mwait[p].start;
- scheduler.mwait[p].end.entry_type = END_ENTRY;
- // Signal Wait Init
- scheduler.swait[p].start.value = 0;
- scheduler.swait[p].start.next = &scheduler.swait[p].end;
- scheduler.swait[p].start.entry_type = START_ENTRY;
- scheduler.swait[p].end.value = 0;
- scheduler.swait[p].end.next = &scheduler.swait[p].start;
- scheduler.swait[p].end.entry_type = END_ENTRY;
- }
-
- // Initialize nextpid
- nextpid = FIRST_AVAIL_PID;
-
- // Initialize Threads - Stack Base and Offsets
- for (unsigned long i = 0; i < MAX_THREADS; i++) {
- struct Thread* t = &threads[i];
- t->offset = i;
- t->sp_base = 0x20000000 - STACK_SIZE*i;
- thread_entries[i].value = t;
- thread_entries[i].next = &thread_entries[(i+1)];
- thread_entries[i].entry_type = VALUE_ENTRY;
- }
- // Initialize the free queue
- scheduler.free_threads.start.value = 0;
- scheduler.free_threads.start.entry_type = START_ENTRY;
- scheduler.free_threads.end.value = 0;
- scheduler.free_threads.end.entry_type = END_ENTRY;
- scheduler.free_threads.start.next = &thread_entries[0];
- scheduler.free_threads.end.next = &thread_entries[MAX_THREADS-1];
- thread_entries[MAX_THREADS-1].next = &scheduler.free_threads.end;
-}
-
-void push_thread_to_queue(struct Thread* t, unsigned char type, unsigned char priority)
-{
- struct Entry* entry = &thread_entries[t->offset];
- struct Queue* queue;
- if (type == THREAD_READY) {
- queue = &scheduler.ready[priority];
- } else if (type == THREAD_MWAIT) {
- queue = &scheduler.mwait[priority];
- } else if (type == THREAD_SWAIT) {
- queue = &scheduler.swait[priority];
- } else {
- return;
- }
- push_to_queue(entry, queue);
- //queue->end.next->next = entry;
- //queue->end.next = entry;
- //entry->next = &queue->end;
-}
-
-void prepend_thread_to_queue(struct Thread* t, unsigned char type, unsigned char priority)
-{
- struct Entry* entry = &thread_entries[t->offset];
- struct Queue* queue;
- if (type == THREAD_READY) {
- queue = &scheduler.ready[priority];
- } else if (type == THREAD_MWAIT) {
- queue = &scheduler.mwait[priority];
- } else if (type == THREAD_SWAIT) {
- queue = &scheduler.swait[priority];
- } else {
- return;
- }
- prepend_to_queue(entry, queue);
-}
-
-struct Entry* pop_thread_from_queue(unsigned char type, unsigned char priority)
-{
- struct Entry* entry = 0;
- struct Queue* queue;
- if (type == THREAD_READY) {
- queue = &scheduler.ready[priority];
- } else if (type == THREAD_MWAIT) {
- queue = &scheduler.mwait[priority];
- } else if (type == THREAD_SWAIT) {
- queue = &scheduler.swait[priority];
- } else {
- return entry;
- }
- return pop_from_queue(queue);
-}
-
-struct Entry* find_pid(unsigned long pid)
-{
- for (unsigned char p = 0; p < PRIORITIES; p++) {
- struct Queue* queue;
- struct Entry* prev;
- struct Entry* entry;
-
- queue = &scheduler.ready[p];
- prev = &queue->start;
- entry = prev->next;
- while (entry->entry_type != END_ENTRY) {
- if (((struct Thread*)entry->value)->pid == pid)
- return prev;
- prev = entry;
- entry = entry->next;
- }
-
- queue = &scheduler.mwait[p];
- prev = &queue->start;
- entry = prev->next;
- while (entry->entry_type != END_ENTRY) {
- if (((struct Thread*)entry->value)->pid == pid)
- return prev;
- prev = entry;
- entry = entry->next;
- }
-
- queue = &scheduler.swait[p];
- prev = &queue->start;
- entry = prev->next;
- while (entry->entry_type != END_ENTRY) {
- if (((struct Thread*)entry->value)->pid == pid)
- return prev;
- prev = entry;
- entry = entry->next;
- }
- }
- return 0;
-}
-
-struct Entry* find_mutex_wait_next(void* m)
-{
- for (unsigned char p = 0; p < PRIORITIES; p++) {
- struct Queue* queue = &scheduler.mwait[p];
- struct Entry* prev = &queue->start;
- struct Entry* entry = prev->next;
- while (entry->entry_type != END_ENTRY) {
- if (((struct Thread*)entry->value)->mptr == m)
- return prev;
- prev = entry;
- entry = entry->next;
- }
- }
- return 0;
-}
-
-struct Entry* find_signal_wait_next(void* s)
-{
- for (unsigned char p = 0; p < PRIORITIES; p++) {
- struct Queue* queue = &scheduler.swait[p];
- struct Entry* prev = &queue->start;
- struct Entry* entry = prev->next;
- while (entry->entry_type != END_ENTRY) {
- if (((struct Thread*)entry->value)->mptr == s)
- return prev;
- prev = entry;
- entry = entry->next;
- }
- }
- return 0;
-}
-
-struct Entry* get_unused_thread(void)
-{
- struct Queue* q = &scheduler.free_threads;
- // If we have no available free threads
- // return null pointer
- if (q->start.next->entry_type == END_ENTRY)
- return 0;
- // Otherwise, get the next thread
- return pop_from_queue(q);
-}
-
-unsigned char find_duplicate(void* pc)
-{
- for (unsigned char p = 0; p < PRIORITIES; p++) {
- struct Queue* queue = &scheduler.ready[p];
- struct Entry* entry = queue->start.next;
- while (entry->entry_type == VALUE_ENTRY) {
- if (((struct Thread*)entry->value)->pc == pc) {
- return 1;
- }
- }
- }
- return 0;
-}
-
-unsigned char add_thread_without_duplicate(void* pc, void* arg, unsigned char priority)
-{
- if (!find_duplicate(pc)) {
- return add_thread(pc, arg, priority);
- }
- return 1;
-}
-
-unsigned char svc_add_thread(void* pc, void* arg, unsigned char priority)
-{
- struct Entry* thread_entry = get_unused_thread();
- // The only point-of-failure is not having a thread available
- if (thread_entry == 0)
- return 1;
- struct Thread* thread = thread_entry->value;
- /// Thread Setup
- thread->pc = pc;
- unsigned long* argp = (void*)thread->sp_base;
- argp -= 13;
- *argp = (unsigned long)arg; // Set r0 to the argument
- argp -= 1;
- *(unsigned long**)argp = (unsigned long*)cleanup; // Set lr to the cleanup function
- thread->sp = argp;
- thread->status = THREAD_READY;
- thread->mptr = (void*)0;
- thread->pid = nextpid++;
- // Reset next pid on overflow
- if (nextpid < FIRST_AVAIL_PID) {
- nextpid = FIRST_AVAIL_PID;
- }
- // Cap Priority Level
- if (priority >= PRIORITIES)
- thread->priority = PRIORITIES - 1;
- else
- thread->priority = priority;
- // This thread is new
- thread->old_priority = -1;
- // Reserved for non-preemptible tasking
- thread->preempt = 0;
- /// Add Thread to Scheduler
- push_thread_to_queue(thread, THREAD_READY, thread->priority);
- return 0;
-}
-
-void uart_scheduler(void)
-{
- uart_string("Scheduler Info\n==============\nCurrent\n");
- uart_hex((unsigned long)scheduler.rthread);
- uart_char(' ');
- kmemshow32((void*)scheduler.rthread, 9);
- unsigned long length;
- for(int p = 0; p < PRIORITIES; p++) {
- uart_string("Priority ");
- uart_10(p);
- uart_char('\n');
- struct Queue* queue;
- struct Entry* entry;
-
- queue = &scheduler.ready[p];
- uart_string("Ready Queue\n");
- entry = queue->start.next;
- length = 0;
- while (entry->entry_type != END_ENTRY) {
- uart_hex((unsigned long)entry->value);
- uart_char(' ');
- kmemshow32((void*)entry->value, 9);
- entry = entry->next;
- length++;
- }
- uart_hexn(length);
-
- queue = &scheduler.mwait[p];
- uart_string("Mutex Wait Queue\n");
- entry = queue->start.next;
- length = 0;
- while (entry->entry_type != END_ENTRY) {
- uart_hex((unsigned long)entry->value);
- uart_char(' ');
- kmemshow32((void*)entry->value, 9);
- entry = entry->next;
- length++;
- }
- uart_hexn(length);
-
- queue = &scheduler.swait[p];
- uart_string("Signal Wait Queue\n");
- entry = queue->start.next;
- length = 0;
- while (entry->entry_type != END_ENTRY) {
- uart_hex((unsigned long)entry->value);
- uart_char(' ');
- kmemshow32((void*)entry->value, 9);
- entry = entry->next;
- length++;
- }
- uart_hexn(length);
- }
- // Count number of free threads
- struct Queue* queue = &scheduler.free_threads;
- struct Entry* entry = queue->start.next;
- while (entry->entry_type != END_ENTRY) {
- entry = entry->next;
- length++;
- }
- uart_hexn(length);
- uart_string("==============\n");
-}
-
-struct Thread* next_thread(void)
-{
- // Recurse through all priorities to try to find a ready thread
- for (int p = 0; p < PRIORITIES; p++) {
- struct Queue* rq = &scheduler.ready[p];
- if (rq->start.next->entry_type == END_ENTRY)
- continue;
- return rq->start.next->value;
- }
- // No thread found, use basic usrloopthread while waiting for new thread
- return &usrloopthread;
-}
-
-void c_cleanup(void)
-{
- struct Thread* rt = scheduler.rthread;
- struct Entry* e = pop_thread_from_queue(THREAD_READY, rt->priority);
- // Add to free threads
- push_to_queue(e, &scheduler.free_threads);
-}
-
-void yield(void)
-{
- struct Thread* rthread = scheduler.rthread;
- // usrloopthread should not be yielded
- if (rthread == &usrloopthread)
- return;
- // Put current thread at the end of its ready queue,
- // thus any threads of the same priority can be run first
- unsigned char priority = rthread->priority;
- struct Entry* tq;
- // Remove from top of queue
- tq = pop_thread_from_queue(THREAD_READY, priority);
- if (tq != 0) {
- // Add to bottom of queue
- push_thread_to_queue(tq->value, THREAD_READY, priority);
- }
-}
-
-void sched_mutex_yield(void* m)
-{
- struct Thread* rthread = scheduler.rthread;
- // usrloopthread should not be yielded
- if (rthread == &usrloopthread)
- return;
- unsigned char priority = rthread->priority;
- // Signify which lock this thread is waiting for
- rthread->mptr = m;
- struct Entry* rt;
- // Remove from top of running queue
- rt = pop_thread_from_queue(THREAD_READY, priority);
- if (rt != 0)
- // Push to bottom of wait queue
- push_thread_to_queue(rt->value, THREAD_MWAIT, priority);
- // Find the thread that has the mutex locked
- struct Mutex* mtex = m;
- struct Entry* mutex_next = find_pid(mtex->pid);
- if (mutex_next == 0)
- return;
- // The next thread is the one with the lock
- struct Entry* mutex_thread_entry = mutex_next->next;
- // Check if it is lower priority
- if (((struct Thread*)mutex_thread_entry->value)->priority > priority) {
- // Remove it from the old priority queue
- remove_next_from_queue(mutex_next);
- struct Thread* t = mutex_thread_entry->value;
- // Preserve the old priority
- if (t->old_priority == 0xFF)
- t->old_priority = t->priority;
- t->priority = priority;
- // Add it to the higher priority queue
- push_thread_to_queue(t, THREAD_READY, priority);
- }
-}
-
-void sched_semaphore_yield(void* s)
-{
- struct Thread* rthread = scheduler.rthread;
- // usrloopthread should not be yielded
- if (rthread == &usrloopthread)
- return;
- unsigned char priority = rthread->priority;
- // Signify which lock this thread is waiting for
- rthread->mptr = s;
- struct Entry* rt;
- // Remove from top of running queue
- rt = pop_thread_from_queue(THREAD_READY, priority);
- if (rt != 0)
- // Push to bottom of wait queue
- push_thread_to_queue(rt->value, THREAD_SWAIT, priority);
-}
-
-void sched_mutex_resurrect(void* m)
-{
- // Find any mutex to resurrect
- struct Entry* prev = find_mutex_wait_next(m);
- if (prev == 0)
- return;
- struct Entry* entry = prev->next;
- struct Thread* thread = entry->value;
- // Resurrect the thread
- thread->mptr = 0;
- // Remove from wait queue
- entry = remove_next_from_queue(prev);
- if (entry == 0)
- return;
- // Add to ready queue
- push_thread_to_queue(entry->value, THREAD_READY, ((struct Thread*)entry->value)->priority);
- // Demote current thread
- struct Thread* rthread = scheduler.rthread;
- unsigned long p = rthread->priority;
- unsigned long op = rthread->old_priority;
- // Restore the original priority level
- if (op != 0xFF) {
- struct Entry* tentry = pop_thread_from_queue(THREAD_READY, p);
- ((struct Thread*)tentry->value)->priority = op;
- ((struct Thread*)tentry->value)->old_priority = 0xFF;
- prepend_thread_to_queue(tentry->value, THREAD_READY, op);
- }
-}
-
-void sched_semaphore_resurrect(void* s, unsigned long count)
-{
- while (count--) {
- // Find any signal/ semaphore to resurrect
- struct Entry* prev = find_signal_wait_next(s);
- if (prev == 0)
- return;
- struct Entry* entry = prev->next;
- struct Thread* thread = entry->value;
- // Resurrect the thread
- thread->mptr = 0;
- // Remove from wait queue
- entry = remove_next_from_queue(prev);
- if (entry == 0)
- return;
- // Add to ready queue
- push_thread_to_queue(entry->value, THREAD_READY, ((struct Thread*)entry->value)->priority);
- }
-}