From 93bf62580a68533dc8252b9a2a055c02f34ecb67 Mon Sep 17 00:00:00 2001 From: Christian Cunningham Date: Thu, 24 Mar 2022 09:38:08 -0700 Subject: Modularized --- kernel/lib/kmem.c | 38 ++++++++++++++++ kernel/lib/mmu.S | 45 +++++++++++++++++++ kernel/lib/mmu.c | 33 ++++++++++++++ kernel/lib/queue.c | 55 ++++++++++++++++++++++++ kernel/lib/strings.c | 119 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 290 insertions(+) create mode 100644 kernel/lib/kmem.c create mode 100644 kernel/lib/mmu.S create mode 100644 kernel/lib/mmu.c create mode 100644 kernel/lib/queue.c create mode 100644 kernel/lib/strings.c (limited to 'kernel/lib') diff --git a/kernel/lib/kmem.c b/kernel/lib/kmem.c new file mode 100644 index 0000000..9861f12 --- /dev/null +++ b/kernel/lib/kmem.c @@ -0,0 +1,38 @@ +#include +#include +#include + +// Output longs at address +void kmemshow32(void* data, unsigned long length) +{ + unsigned long* ptr = data; + for(unsigned long i = 0; i < length; i++) { + uart_hex(*ptr); + ptr+=1; + if (i != length-1) + uart_char(' '); + } + uart_char('\n'); +} + +// Output bytes at address +void kmemshow(void* data, unsigned long length) +{ + unsigned char* ptr = data; + for(unsigned long i = 0; i < length; i++) { + char tmp = *ptr>>4; + tmp += 0x30; + if (tmp > 0x39) + tmp += 0x7; + uart_char(tmp); + tmp = *ptr&0xF; + tmp += 0x30; + if (tmp > 0x39) + tmp += 0x7; + uart_char(tmp); + ptr+=1; + if (i != length-1) + uart_char(' '); + } + uart_char('\n'); +} diff --git a/kernel/lib/mmu.S b/kernel/lib/mmu.S new file mode 100644 index 0000000..faca3cc --- /dev/null +++ b/kernel/lib/mmu.S @@ -0,0 +1,45 @@ +.section .text +.globl mmu_start +mmu_start: + mov r2, #0 + // Invalidate Caches + mcr p15,0,r2,c7,c1,6 + // Invalidate TLB entries + mcr p15,0,r2,c8,c7,0 + // Data synchronisation barrier + mcr p15,0,r2,c7,c10,4 + + // Set all domains to 0b11 + mvn r2, #0 + bic r2, #0xC + mcr p15,0,r2,c3,c0,0 + + // Set the translation table base address (remember to align 16 KiB!) + mcr p15,0,r0,c2,c0,0 + mcr p15,0,r0,c2,c0,1 + mov r3, #0 + mcr p15,0,r3,c2,c0,2 + + // Set the bits mentioned above + mrc p15,0,r2,c1,c0,0 + orr r2,r2,r1 + mcr p15,0,r2,c1,c0,0 + bx lr + +.globl mmu_stop +mmu_stop: + mrc p15,0,r2,c1,c0,0 + bic r2,#0x1000 + bic r2,#0x0004 + bic r2,#0x0001 + mcr p15,0,r2,c1,c0,0 + bx lr + +.globl tlb_invalidate +tlb_invalidate: + mov r2, #0 + // Invalidate Entries + mcr p15, 0, r2, c8, c7, 0 + // DSB + mcr p15, 0, r2, c7, c10, 4 + bx lr diff --git a/kernel/lib/mmu.c b/kernel/lib/mmu.c new file mode 100644 index 0000000..e9dda7a --- /dev/null +++ b/kernel/lib/mmu.c @@ -0,0 +1,33 @@ +#include + +#define CACHABLE 0x08 +#define BUFFERABLE 0x04 +#define NO_PERMISSIONS_REQUIRED 0b11 << 10 +#define MMU_TABLE_BASE 0x00004000 + +void mmu_start(unsigned long base, unsigned long flags); + +void mmu_section(unsigned long virtual, unsigned long physical, unsigned long flags) +{ + unsigned long offset = virtual >> 20; + unsigned long* entry = (unsigned long*)(MMU_TABLE_BASE | (offset << 2)); + unsigned long physval = (physical & 0xFFF00000) | (flags & 0x7FFC) | 0x00C02; + *entry = physval; +} + +extern unsigned long __bss_end; +void mmu_init(void) +{ + for (unsigned long addr = 0x00000000;; addr += 0x00100000) { + if (addr < (unsigned long)&__bss_end + 0x00100000) { + mmu_section(addr, addr, CACHABLE | BUFFERABLE); + } else { + mmu_section(addr, addr, NO_PERMISSIONS_REQUIRED); + } + if (addr == 0x02000000) + mmu_section(addr, addr, CACHABLE | BUFFERABLE | NO_PERMISSIONS_REQUIRED); + if (addr == 0xFFF00000) + break; + } + mmu_start(MMU_TABLE_BASE,0x00000001|0x1000|0x0004); +} diff --git a/kernel/lib/queue.c b/kernel/lib/queue.c new file mode 100644 index 0000000..1fc35f6 --- /dev/null +++ b/kernel/lib/queue.c @@ -0,0 +1,55 @@ +#include + +void push_to_queue(struct Entry* e, struct Queue* q) +{ + q->end.next->next = e; + q->end.next = e; + e->next = &q->end; +} + +void prepend_to_queue(struct Entry* e, struct Queue* q) +{ + e->next = q->start.next; + q->start.next = e; + if (e->next->entry_type == END_ENTRY) + q->end.next = e; +} + +struct Entry* pop_from_queue(struct Queue* q) +{ + if (q->start.next->entry_type == END_ENTRY) + return 0; + struct Entry* e = q->start.next; + q->start.next = e->next; + if (e->next->entry_type == END_ENTRY) + q->end.next = &q->start; + return e; +} + +struct Entry* remove_next_from_queue(struct Entry* e) +{ + struct Entry* prev = e; + struct Entry* remove = e->next; + struct Entry* next = remove->next; + if (remove->entry_type != VALUE_ENTRY) + return 0; + prev->next = next; + if (next->entry_type == END_ENTRY) + next->next = prev; + return remove; +} + +struct Entry* find_value(void* value, struct Queue* q) +{ + struct Entry* prev; + struct Entry* entry; + prev = &q->start; + entry = prev->next; + while (entry->entry_type != END_ENTRY) { + if (entry->value == value) + return prev; + prev = entry; + entry = prev->next; + } + return 0; +} diff --git a/kernel/lib/strings.c b/kernel/lib/strings.c new file mode 100644 index 0000000..674af19 --- /dev/null +++ b/kernel/lib/strings.c @@ -0,0 +1,119 @@ +#include +#include + +unsigned long strlen(string_t s) +{ + unsigned long len = 0; + while (s[len] != 0) { + len += 1; + } + return len; +} + +void strcpy(string_t src, string_t dest) +{ + unsigned long idx = 0; + while (src[idx] != 0) { + dest[idx] = src[idx]; + idx++; + } + dest[idx] = src[idx]; +} + +unsigned char strcmp(string_t a, string_t b) +{ + unsigned long idx = 0; + while (a[idx] != 0 && b[idx] != 0) { + if (a[idx] != b[idx]) { + return 0; + } + idx += 1; + } + return a[idx] == b[idx]; +} + +unsigned char strcmpn(string_t a, string_t b, unsigned int n) +{ + unsigned long idx = 0; + while (a[idx] != 0 && b[idx] != 0 && idx+1 < n) { + if (a[idx] != b[idx]) { + return 0; + } + idx += 1; + } + return a[idx] == b[idx]; +} + +char* zhex32_to_str(unsigned long value) +{ + static char data[10]; + char tmp = 0; + char isz = -1; + for (int i = 0; i < 8; i++) { + tmp = (value >> 4*(8-i-1))&0xF; + if (isz == 0xFF && tmp != 0) + isz = i; + if(tmp > 0x9) + tmp += 7; + tmp += 0x30; + data[i] = tmp; + } + return data+isz; +} + +char* hex32_to_str(unsigned long value) +{ + static char data[10]; + char tmp = 0; + for (int i = 0; i < 8; i++) { + tmp = (value >> 4*(8-i-1))&0xF; + if(tmp > 0x9) + tmp += 7; + tmp += 0x30; + data[i] = tmp; + } + return data; +} + +char* u32_to_str(unsigned long value) +{ + unsigned long t = value; + unsigned long c; + static char data[12]; + char* dptr = data + 9; + for (int i = 0; i <= 10; i++) { + c = t%10; + *dptr = 0x30 + (c&0xF); + t /= 10; + if (t==0) + break; + dptr -= 1; + } + return dptr; +} + +char* s32_to_str(unsigned long value) +{ + long t = value; + unsigned long c; + char is_neg = 0; + if (t < 0) { + t = -t; + is_neg = 1; + } + static char data[13]; + char* dptr = data + 10; + for (int i = 0; i <= 10; i++) { + c = t%10; + *dptr = 0x30 + (c&0xF); + t /= 10; + if (t==0) + break; + dptr -= 1; + } + if (is_neg) { + dptr -= 1; + *dptr = '-'; + } + return dptr; +} -- cgit v1.2.1