From 93bf62580a68533dc8252b9a2a055c02f34ecb67 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Thu, 24 Mar 2022 09:38:08 -0700 Subject: Modularized --- kernel/util/lock.c | 20 ++++++++ kernel/util/mutex.c | 110 ++++++++++++++++++++++++++++++++++++++++++ kernel/util/status.c | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++ kernel/util/time.c | 76 +++++++++++++++++++++++++++++ 4 files changed, 339 insertions(+) create mode 100644 kernel/util/lock.c create mode 100644 kernel/util/mutex.c create mode 100644 kernel/util/status.c create mode 100644 kernel/util/time.c (limited to 'kernel/util') diff --git a/kernel/util/lock.c b/kernel/util/lock.c new file mode 100644 index 0000000..c9fe654 --- /dev/null +++ b/kernel/util/lock.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +void lock(struct Lock* l) +{ + unsigned long mode = getmode() & 0x1F; + if (mode == 0x10) { + sys1(SYS_LOCK, l); + } +} + +void unlock(struct Lock* l) +{ + unsigned long mode = getmode() & 0x1F; + if (mode == 0x10) { + sys1(SYS_UNLOCK, l); + } +} diff --git a/kernel/util/mutex.c b/kernel/util/mutex.c new file mode 100644 index 0000000..8e85f8f --- /dev/null +++ b/kernel/util/mutex.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include +#include + +void mutex_init(void) +{ + for (unsigned long m = 0; m < MAX_MUTEXS; m++) { + mutexs[m].pid = 0; + mutexs[m].addr = 0; + mutex_entries[m].value = &mutexs[m]; + mutex_entries[m].entry_type = VALUE_ENTRY; + mutex_entries[m].next = &mutex_entries[m+1]; + } + // Initialize Free Mutexs + mutex_manager.free.start.value = 0; + mutex_manager.free.start.next = &mutex_entries[0]; + mutex_manager.free.start.entry_type = START_ENTRY; + mutex_manager.free.end.value = 0; + mutex_manager.free.end.next = &mutex_entries[MAX_MUTEXS-1]; + mutex_entries[MAX_MUTEXS-1].next = &mutex_manager.free.end; + mutex_manager.free.end.entry_type = END_ENTRY; + // Initialize In-use Mutexs + mutex_manager.used.start.value = 0; + mutex_manager.used.start.next = &mutex_manager.used.end; + mutex_manager.used.start.entry_type = START_ENTRY; + mutex_manager.used.end.value = 0; + mutex_manager.used.end.next = &mutex_manager.used.start; + mutex_manager.used.end.entry_type = END_ENTRY; +} + +struct Mutex* create_mutex(void* addr) +{ + struct Entry* e = pop_from_queue(&mutex_manager.free); + if (e == 0) + return 0; + struct Mutex* m = e->value; + m->pid = 0; + m->addr = addr; + push_to_queue(e, &mutex_manager.used); + return e->value; +} + +unsigned char delete_mutex(struct Mutex* m) +{ + struct Entry* entry = find_value(m, &mutex_manager.used); + if (entry == 0) + return 1; + // Remove it from the queue + struct Entry* theentry = remove_next_from_queue(entry); + // Add it to the free queue + prepend_to_queue(theentry, &mutex_manager.free); + return 0; +} + +void uart_mutexes(void) +{ + struct Entry* entry = mutex_manager.used.start.next; + while (entry->entry_type == VALUE_ENTRY) + { + struct Mutex* m = entry->value; + uart_hex((unsigned long)m); + uart_char(' '); + uart_hex(m->pid); + uart_char(' '); + uart_hexn((unsigned long)m->addr); + entry = entry->next; + } + unsigned long count = 0; + entry = mutex_manager.free.start.next; + while (entry->entry_type == VALUE_ENTRY) { + count++; + entry = entry->next; + } + uart_hexn(count); +} + +void lock_mutex(struct Mutex* m) +{ + struct Thread* rthread = scheduler.rthread; + unsigned long rpid = rthread->pid; + unsigned long mode = getmode() & 0x1F; + if (mode == 0x10) { + // Find this mutex + struct Entry* mentry = find_value(m, &mutex_manager.used); + // If it is not a managed mutex, break away + if (mentry == 0) + return; + struct Entry* entry = mutex_manager.used.start.next; + // Ensure this thread locks all mutexs sequentially + // To avoid a deadlock + while (entry->entry_type == VALUE_ENTRY) { + struct Mutex* vmutex = entry->value; + // If this thread had locked it + // Toggle the lock to prevent deadlock + if (vmutex->pid == rpid) { + sys1(SYS_UNLOCK, vmutex); + sys1(SYS_LOCK, vmutex); + } + entry = entry->next; + } + sys1(SYS_LOCK, m); + } +} + +void unlock_mutex(struct Mutex* m) +{ + unlock((struct Lock*)m); +} diff --git a/kernel/util/status.c b/kernel/util/status.c new file mode 100644 index 0000000..456e89d --- /dev/null +++ b/kernel/util/status.c @@ -0,0 +1,133 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void output_irq_status(void) +{ + // Basic IRQ + unsigned long ib_val = load32(IRQ_BASIC_ENABLE); + // IRQ 1 + unsigned long i1_val = load32(IRQ_ENABLE1); + // IRQ 2 + unsigned long i2_val = load32(IRQ_ENABLE2); + // FIQ + unsigned long f_val = load32(FIQ_CONTROL); + + // Check GPU Interrupt Routing + unsigned long g_val = load32(GPU_INTERRUPTS_ROUTING); + draw_cletter(0, 1, (g_val & 0b11) + 0x30, 0x1EA1A1); + draw_cletter(1, 1, ((g_val >> 2) & 0b11) + 0x30, 0x1EA1A1); + + draw_chex32(4, 1, ib_val, 0x1EA1A1); + draw_chex32(4+9, 1, i1_val, 0x1EA1A1); + draw_chex32(4+9*2, 1, i2_val, 0x1EA1A1); + draw_chex32(4+9*3, 1, f_val, 0x1EA1A1); + + // Check UART IRQ + if (i2_val & (1<<25)) { + draw_cstring(0, 2, "UART", 0x00FF00); + } else if (f_val == 57) { + draw_cstring(0, 2, "UART", 0xFFA500); + } else { + draw_cstring(0, 2, "UART", 0xFF0000); + } + + // Check UART IRQ + if (i1_val & (1<<0)) { + draw_cstring(5, 2, "STIMERCMP", 0x00FF00); + } else if (f_val == 1) { + draw_cstring(5, 2, "STIMERCMP", 0xFFA500); + } else { + draw_cstring(5, 2, "STIMERCMP", 0xFF0000); + } + + if (load32(CORE0_TIMER_IRQCNTL) & 0xF) { + draw_cstring(4+9+2, 2, "LTIMER", 0x00FF00); + } else if (load32(CORE0_TIMER_IRQCNTL) & 0xF0) { + draw_cstring(4+9+2, 2, "LTIMER", 0xFFA500); + } else { + draw_cstring(4+9+2, 2, "LTIMER", 0xFF0000); + } +} + +void time_status(void) +{ + // Report Sys Timer Stataus + unsigned long systime; + draw_string(0, 8, "Sys Timer Status"); + systime = *(volatile unsigned long*)SYS_TIMER_CS; + draw_hex32(17, 8, systime); + draw_string(17+8, 8, ":"); + unsigned long long tval = get_time(); + draw_hex32(17+8, 8, (tval >> 32)); + draw_hex32(17+8+8, 8, tval); + systime = *(volatile unsigned long*)SYS_TIMER_C0; + draw_hex32(19+14+8+1, 8, systime); + draw_string(19+14+9+8, 8, "|"); + draw_string(19+14+18, 8, " "); + draw_u10(19+14+18, 8, ((unsigned long)tval)/1000000); +} + +void status(void) +{ + // OS Info + draw_cstring(7, 0, "v", 0x00FFFF); + draw_cstring(0, 0, os_name, 0xFF0000); + draw_cstring(8, 0, os_info_v, 0x00FFFF); + + // GPU IRQ Statuses + output_irq_status(); + + // Timer Status + draw_cstring(0, 3, "TIMER", 0x00FF00); + // Output the frequency + draw_string(6, 3, "@"); + unsigned long frq = read_cntfrq()/1000; + unsigned long fs_len = draw_u10(8, 3, frq) + 1; + draw_string(8+fs_len, 3, "kHz"); + // Output the value + unsigned long v = read_cntv_tval(); + unsigned long vs_len = draw_u10(8+fs_len+4, 3, v)+1; + draw_string(8+fs_len+4 +vs_len, 3, " "); + draw_letter(8+fs_len+4 +vs_len+1, 3, '|'); + draw_hex32(8+fs_len+7+vs_len, 3, v); + + // Video Status + draw_cstring(0, 4, "VIDEO", 0x00FF00); + unsigned long gw_len = draw_u10(6, 4, gwidth); + unsigned long gh_len = draw_u10(6+gw_len+1, 4, gheight) + 1; + draw_letter(6+gw_len, 4, 'x'); + if(gisrgb) + draw_string(6+gw_len+gh_len + 1, 4, "RGB"); + else + draw_string(6+gw_len+gh_len + 1, 4, "BGR"); + + // Core Stacks + draw_string(0, 5, "SVC IRQ FIQ User/SYS\n"); + unsigned long sp = (unsigned long)getsvcstack(); + draw_hex32(0, 6, sp); + sp = (unsigned long)getirqstack(); + draw_hex32(9, 6, sp); + sp = (unsigned long)getfiqstack(); + draw_hex32(9*2, 6, sp); + sp = (unsigned long)getsysstack(); + draw_hex32(9*3, 6, sp); + + // Report Core that updated status + unsigned long coren; + asm volatile ( + "mrc p15, #0, %0, c0, c0, #5\n" + "and %0, %0, #3" : "=r"(coren) :: "cc"); + draw_string(0, 7, "Status Updated by Core #"); + draw_hex32(24, 7, coren); + + time_status(); +} diff --git a/kernel/util/time.c b/kernel/util/time.c new file mode 100644 index 0000000..abb9c8d --- /dev/null +++ b/kernel/util/time.c @@ -0,0 +1,76 @@ +#include +#include + +// CCNT - Cycle Timer (Close to ns resolution) + +void routing_core0cntv_to_core0fiq(void) +{ + store32(0x80, CORE0_TIMER_IRQCNTL); +} + +void routing_core0cntv_to_core0irq(void) +{ + store32(0x08, CORE0_TIMER_IRQCNTL); +} + +unsigned long read_core0timer_pending(void) +{ + unsigned long tmp; + tmp = load32(CORE0_IRQ_SOURCE); + return tmp; +} + +unsigned long long read_cntvct(void) +{ + unsigned long long val; + asm volatile("mrrc p15, 1, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +unsigned long long read_cntvoff(void) +{ + unsigned long long val; + asm volatile("mrrc p15, 4, %Q0, %R0, c14" : "=r" (val)); + return (val); +} + +unsigned long read_cntv_tval(void) +{ + unsigned long val; + asm volatile ("mrc p15, 0, %0, c14, c3, 0" : "=r"(val) ); + return val; +} + +void write_cntv_tval(unsigned long val) +{ + asm volatile ("mcr p15, 0, %0, c14, c3, 0" :: "r"(val) ); + return; +} + +unsigned long read_cntfrq(void) +{ + unsigned long val; + asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r"(val) ); + return val; +} + +unsigned long long get_time(void) +{ + union { + unsigned long long tval; + struct { + unsigned long high; + unsigned long low; + } tvalb; + } t; + t.tvalb.low = *(unsigned long*)SYS_TIMER_CLO; + t.tvalb.high = *(unsigned long*)SYS_TIMER_CHI; + return t.tval; +} + +void wait_msec(unsigned int n) +{ + unsigned long start = *(volatile unsigned long*)SYS_TIMER_CHI; + while (*(volatile unsigned long*)SYS_TIMER_CHI - start < n) + asm volatile("nop"); +} -- cgit v1.2.1