diff --git a/Makefile b/Makefile index 9ac5771..8bb638f 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ -TOOLPREFIX = riscv-none-elf +TOOLPREFIX = riscv64-linux-gnu +# TOOLPREFIX = toolchain/xpack-riscv-none-elf-gcc-14.2.0-3/bin/riscv-none-elf +# TOOLPREFIX = toolchain/gcc/bin/riscv-none-elf CC = $(TOOLPREFIX)-gcc AS = $(TOOLPREFIX)-as @@ -17,19 +19,21 @@ CFLAGS += -mcmodel=medany CFLAGS += -march=rv64gc -mabi=lp64 CFLAGS += -ffreestanding -fno-common -nostdlib -mno-relax -CFLAGS += -I. -CFLAGS += -Ilib -CFLAGS += -Ikern - CFLAGS += -fno-stack-protector # Prevents code that needs libc / runtime support CFLAGS += -MD # Generate header dependency files (.d) CFLAGS += -fno-pie -no-pie # Fixed address linking CFLAGS += -ggdb -gdwarf-2 # GDB debug info CFLAGS += -fno-omit-frame-pointer # More reliable backtraces in GDB +CFLAGS += -I. +CFLAGS += -I./kern +CFLAGS += -I./kern/libkern + all: kernel.elf -kernel.elf: entry.o start.o lib/string.o lib/proc.o lib/proc.o lib/uart.o lib/panic.o kern/kalloc.o lib/memory.o kern/ispinlock.o lib/spinlock.o +main: main.o + +kernel.elf: entry.o start.o kern/libkern/string.o kern/libkern/proc.o kern/libkern/uart.o kern/libkern/panic.o kern/kalloc.o kern/libkern/memory.o kern/ispinlock.o kern/libkern/spinlock.o kern/libkern/string.o kern/libkern/mini-printf.o @echo LD $@ @$(LD) $(LDFLAGS) -o $@ $^ @@ -47,6 +51,7 @@ qemu: kernel.elf clean: rm -f *.o *.elf *.d lib/*.o lib/*.d + fd -I -e o -x rm # TODO: Should only depend on posix -include *.d diff --git a/kern/ispinlock.h b/kern/ispinlock.h index d71af17..e30d4b6 100644 --- a/kern/ispinlock.h +++ b/kern/ispinlock.h @@ -1,5 +1,5 @@ #pragma once -#include +#include typedef struct { volatile uint32_t v; // 0 = unlocked, 1 = locked diff --git a/kern/kalloc.c b/kern/kalloc.c index d3d254c..0adbdc9 100644 --- a/kern/kalloc.c +++ b/kern/kalloc.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include // Physical memory allocator, for user processes, // kernel stacks, page-table pages, diff --git a/lib/endian.h b/kern/libkern/endian.h similarity index 100% rename from lib/endian.h rename to kern/libkern/endian.h diff --git a/lib/memory.c b/kern/libkern/memory.c similarity index 100% rename from lib/memory.c rename to kern/libkern/memory.c diff --git a/lib/memory.h b/kern/libkern/memory.h similarity index 94% rename from lib/memory.h rename to kern/libkern/memory.h index 8a012a2..01b275a 100644 --- a/lib/memory.h +++ b/kern/libkern/memory.h @@ -1,7 +1,7 @@ #ifndef MEMORY_KERNEL_H #define MEMORY_KERNEL_H -#include +#include /* These are hardcoded for now */ #define KERNBASE 0x80000000L diff --git a/kern/libkern/mini-printf.c b/kern/libkern/mini-printf.c new file mode 100644 index 0000000..ec0ff14 --- /dev/null +++ b/kern/libkern/mini-printf.c @@ -0,0 +1,311 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013,2014 Michal Ludvig + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * ---- + * + * This is a minimal snprintf() implementation optimised + * for embedded systems with a very limited program memory. + * mini_snprintf() doesn't support _all_ the formatting + * the glibc does but on the other hand is a lot smaller. + * Here are some numbers from my STM32 project (.bin file size): + * no snprintf(): 10768 bytes + * mini snprintf(): 11420 bytes (+ 652 bytes) + * glibc snprintf(): 34860 bytes (+24092 bytes) + * Wasting nearly 24kB of memory just for snprintf() on + * a chip with 32kB flash is crazy. Use mini_snprintf() instead. + * + */ + +#include "mini-printf.h" + +static int +mini_strlen(const char *s) +{ + int len = 0; + while (s[len] != '\0') len++; + return len; +} + +static int +mini_itoa(long value, unsigned int radix, int uppercase, int unsig, + char *buffer) +{ + char *pbuffer = buffer; + int negative = 0; + int i, len; + + /* No support for unusual radixes. */ + if (radix > 16) + return 0; + + if (value < 0 && !unsig) { + negative = 1; + value = -value; + } + + /* This builds the string back to front ... */ + do { + int digit = value % radix; + *(pbuffer++) = (digit < 10 ? '0' + digit : (uppercase ? 'A' : 'a') + digit - 10); + value /= radix; + } while (value > 0); + + if (negative) + *(pbuffer++) = '-'; + + *(pbuffer) = '\0'; + + /* ... now we reverse it (could do it recursively but will + * conserve the stack space) */ + len = (pbuffer - buffer); + for (i = 0; i < len / 2; i++) { + char j = buffer[i]; + buffer[i] = buffer[len-i-1]; + buffer[len-i-1] = j; + } + + return len; +} + +static int +mini_pad(char* ptr, int len, char pad_char, int pad_to, char *buffer) +{ + int i; + int overflow = 0; + char * pbuffer = buffer; + if(pad_to == 0) pad_to = len; + if(len > pad_to) { + len = pad_to; + overflow = 1; + } + for(i = pad_to - len; i > 0; i --) { + *(pbuffer++) = pad_char; + } + for(i = len; i > 0; i --) { + *(pbuffer++) = *(ptr++); + } + len = pbuffer - buffer; + if(overflow) { + for (i = 0; i < 3 && pbuffer > buffer; i ++) { + *(pbuffer-- - 1) = '*'; + } + } + return len; +} + +struct mini_buff { + char *buffer, *pbuffer; + unsigned int buffer_len; +}; + +static int +_puts(char *s, int len, void *buf) +{ + if(!buf) return len; + struct mini_buff *b = buf; + char * p0 = b->buffer; + int i; + /* Copy to buffer */ + for (i = 0; i < len; i++) { + if(b->pbuffer == b->buffer + b->buffer_len - 1) { + break; + } + *(b->pbuffer ++) = s[i]; + } + *(b->pbuffer) = 0; + return b->pbuffer - p0; +} + +#ifdef MINI_PRINTF_ENABLE_OBJECTS +static int (*mini_handler) (void* data, void* obj, int ch, int lhint, char** bf) = 0; +static void (*mini_handler_freeor)(void* data, void*) = 0; +static void * mini_handler_data = 0; + +void mini_printf_set_handler( + void* data, + int (*handler)(void* data, void* obj, int ch, int len_hint, char** buf), + void (*freeor)(void* data, void* buf)) +{ + mini_handler = handler; + mini_handler_freeor = freeor; + mini_handler_data = data; +} +#endif + +int +mini_vsnprintf(char *buffer, unsigned int buffer_len, const char *fmt, va_list va) +{ + struct mini_buff b; + b.buffer = buffer; + b.pbuffer = buffer; + b.buffer_len = buffer_len; + if(buffer_len == 0) buffer = (void*) 0; + int n = mini_vpprintf(_puts, (buffer != (void*)0)?&b:(void*)0, fmt, va); + if(buffer == (void*) 0) { + return n; + } + return b.pbuffer - b.buffer; +} + +int +mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va) +{ + char bf[24]; + char bf2[24]; + char ch; +#ifdef MINI_PRINTF_ENABLE_OBJECTS + void* obj; +#endif + if(puts == (void*)0) { + /* run puts in counting mode. */ + puts = _puts; buf = (void*)0; + } + int n = 0; + while ((ch=*(fmt++))) { + int len; + if (ch!='%') { + len = 1; + len = puts(&ch, len, buf); + } else { + char pad_char = ' '; + int pad_to = 0; + char l = 0; + char *ptr; + + ch=*(fmt++); + + /* Zero padding requested */ + if (ch == '0') pad_char = '0'; + while (ch >= '0' && ch <= '9') { + pad_to = pad_to * 10 + (ch - '0'); + ch=*(fmt++); + } + if(pad_to > (signed int) sizeof(bf)) { + pad_to = sizeof(bf); + } + if (ch == 'l') { + l = 1; + ch=*(fmt++); + } + + switch (ch) { + case 0: + goto end; + case 'u': + case 'd': + if(l) { + len = mini_itoa(va_arg(va, unsigned long), 10, 0, (ch=='u'), bf2); + } else { + if(ch == 'u') { + len = mini_itoa((unsigned long) va_arg(va, unsigned int), 10, 0, 1, bf2); + } else { + len = mini_itoa((long) va_arg(va, int), 10, 0, 0, bf2); + } + } + len = mini_pad(bf2, len, pad_char, pad_to, bf); + len = puts(bf, len, buf); + break; + + case 'x': + case 'X': + if(l) { + len = mini_itoa(va_arg(va, unsigned long), 16, (ch=='X'), 1, bf2); + } else { + len = mini_itoa((unsigned long) va_arg(va, unsigned int), 16, (ch=='X'), 1, bf2); + } + len = mini_pad(bf2, len, pad_char, pad_to, bf); + len = puts(bf, len, buf); + break; + + case 'c' : + ch = (char)(va_arg(va, int)); + len = mini_pad(&ch, 1, pad_char, pad_to, bf); + len = puts(bf, len, buf); + break; + + case 's' : + ptr = va_arg(va, char*); + len = mini_strlen(ptr); + if (pad_to > 0) { + len = mini_pad(ptr, len, pad_char, pad_to, bf); + len = puts(bf, len, buf); + } else { + len = puts(ptr, len, buf); + } + break; +#ifdef MINI_PRINTF_ENABLE_OBJECTS + case 'O' : /* Object by content (e.g. str) */ + case 'R' : /* Object by representation (e.g. repr)*/ + obj = va_arg(va, void*); + len = mini_handler(mini_handler_data, obj, ch, pad_to, &ptr); + if (pad_to > 0) { + len = mini_pad(ptr, len, pad_char, pad_to, bf); + len = puts(bf, len, buf); + } else { + len = puts(ptr, len, buf); + } + mini_handler_freeor(mini_handler_data, ptr); + break; +#endif + default: + len = 1; + len = puts(&ch, len, buf); + break; + } + } + n = n + len; + } +end: + return n; +} + + +int +mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...) +{ + int ret; + va_list va; + va_start(va, fmt); + ret = mini_vsnprintf(buffer, buffer_len, fmt, va); + va_end(va); + + return ret; +} + +int +mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...) +{ + int ret; + va_list va; + va_start(va, fmt); + ret = mini_vpprintf(puts, buf, fmt, va); + va_end(va); + + return ret; +} + diff --git a/kern/libkern/mini-printf.h b/kern/libkern/mini-printf.h new file mode 100644 index 0000000..7667b50 --- /dev/null +++ b/kern/libkern/mini-printf.h @@ -0,0 +1,73 @@ +/* + * The Minimal snprintf() implementation + * + * Copyright (c) 2013 Michal Ludvig + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the auhor nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +#ifndef __MINI_PRINTF__ +#define __MINI_PRINTF__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#ifdef MINI_PRINTF_ENABLE_OBJECTS +/* If enabled, callback for object types (O and R). + * void* arguments matching %O and %R are sent to handler as obj. + * the result string created by handler at *buf is freed by freeor. + * */ +void mini_printf_set_handler( + void * data, + /* handler returns number of chars in *buf; *buf is not NUL-terminated. */ + int (*handler)(void* data, void* obj, int ch, int len_hint, char** buf), + void (*freeor)(void* data, void* buf)); +#endif + +/* String IO interface; returns number of bytes written, not including the ending NUL. + * Always appends a NUL at the end, therefore buffer_len shall be at least 1 in normal operation. + * If buffer is NULL or buffer_len is 0, returns number of bytes to be written, not including the ending NUL. + */ +int mini_vsnprintf(char* buffer, unsigned int buffer_len, const char *fmt, va_list va); +int mini_snprintf(char* buffer, unsigned int buffer_len, const char *fmt, ...); + +/* Stream IO interface; returns number of bytes written. + * If puts is NULL, number of bytes to be written. + * puts shall return number of bytes written. + */ +int mini_vpprintf(int (*puts)(char* s, int len, void* buf), void* buf, const char *fmt, va_list va); +int mini_pprintf(int (*puts)(char*s, int len, void* buf), void* buf, const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#define vsnprintf mini_vsnprintf +#define snprintf mini_snprintf + +#endif diff --git a/lib/panic.c b/kern/libkern/panic.c similarity index 100% rename from lib/panic.c rename to kern/libkern/panic.c diff --git a/lib/panic.h b/kern/libkern/panic.h similarity index 100% rename from lib/panic.h rename to kern/libkern/panic.h diff --git a/lib/proc.c b/kern/libkern/proc.c similarity index 100% rename from lib/proc.c rename to kern/libkern/proc.c diff --git a/riscv.h b/kern/libkern/riscv.h similarity index 98% rename from riscv.h rename to kern/libkern/riscv.h index d56bdce..ddc19e7 100644 --- a/riscv.h +++ b/kern/libkern/riscv.h @@ -1,7 +1,7 @@ #ifndef RISCV_KERNEL_H #define RISCV_KERNEL_H -#include +#include /** Page Size */ #define PGSIZE 4096 // bytes per page diff --git a/lib/spinlock.c b/kern/libkern/spinlock.c similarity index 100% rename from lib/spinlock.c rename to kern/libkern/spinlock.c diff --git a/lib/spinlock.h b/kern/libkern/spinlock.h similarity index 98% rename from lib/spinlock.h rename to kern/libkern/spinlock.h index eb4f4b3..9629e60 100644 --- a/lib/spinlock.h +++ b/kern/libkern/spinlock.h @@ -1,7 +1,7 @@ #ifndef KERNEL_Spinlock_H #define KERNEL_Spinlock_H -#include "types.h" +#include /** Mutual exclusion spin lock */ struct Spinlock { diff --git a/kern/libkern/stdarg.h b/kern/libkern/stdarg.h new file mode 100644 index 0000000..1113127 --- /dev/null +++ b/kern/libkern/stdarg.h @@ -0,0 +1,11 @@ +#ifndef _STDARG_H +#define _STDARG_H + +typedef __builtin_va_list va_list; + +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_arg(ap, type) __builtin_va_arg(ap, type) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(dest, src) __builtin_va_copy(dest, src) + +#endif diff --git a/types.h b/kern/libkern/stdint.h similarity index 94% rename from types.h rename to kern/libkern/stdint.h index 69e74d4..37c912f 100644 --- a/types.h +++ b/kern/libkern/stdint.h @@ -13,4 +13,4 @@ typedef uint64_t size_t; typedef uint64_t uintptr_t; -typedef u8 bool; +// typedef u8 bool; diff --git a/kern/libkern/string.c b/kern/libkern/string.c index 99a0ea2..e6c0000 100644 --- a/kern/libkern/string.c +++ b/kern/libkern/string.c @@ -114,14 +114,112 @@ void *memset(void *dest, int c, size_t n) { return dest; } -int memcmp(const void *s1, const void *s2, size_t n) { - if (n != 0) { - const unsigned char *p1 = s1, *p2 = s2; +// int memcmp(const void *s1, const void *s2, size_t n) { +// if (n != 0) { +// const unsigned char *p1 = s1, *p2 = s2; +// +// do { +// if (*p1++ != *p2++) +// return (*--p1 - *--p2); +// } while (--n != 0); +// } +// return (0); +// } - do { - if (*p1++ != *p2++) - return (*--p1 - *--p2); - } while (--n != 0); +char *itoa(int value, char *str, int base) { + char *p = str; + char *p1, *p2; + unsigned int uvalue = value; + int negative = 0; + + if (base < 2 || base > 36) { + *str = '\0'; + return str; } - return (0); + + if (value < 0 && base == 10) { + negative = 1; + uvalue = -value; + } + + // Convert to string + do { + int digit = uvalue % base; + *p++ = (digit < 10) ? '0' + digit : 'a' + (digit - 10); + uvalue /= base; + } while (uvalue); + + if (negative) + *p++ = '-'; + + *p = '\0'; + + // Reverse string + p1 = str; + p2 = p - 1; + while (p1 < p2) { + char tmp = *p1; + *p1++ = *p2; + *p2-- = tmp; + } + + return str; +} + +// void *memset(void *dst, int c, size_t length) { +// u8 *ptr = (u8 *)dst; +// const u8 value = (u8)c; +// +// while (length--) *(ptr++) = value; +// +// return dst; +// } + +// void *memcpy(void *dst, const void *src, size_t len) { +// u8 *d = (u8 *)dst; +// const u8 *s = (const u8 *)src; +// for (size_t i = 0; i < len; i++) { +// d[i] = s[i]; +// } +// return dst; +// } + +// void *memmove(void *dst, const void *src, size_t len) { +// u8 *d = (u8 *)dst; +// const u8 *s = (const u8 *)src; +// if (d < s) { +// for (size_t i = 0; i < len; i++) { +// d[i] = s[i]; +// } +// } else if (d > s) { +// for (size_t i = len; i > 0; i--) { +// d[i - 1] = s[i - 1]; +// } +// } +// return dst; +// } + +int memcmp(const void *s1, const void *s2, size_t len) { + const u8 *a = (const u8 *)s1; + const u8 *b = (const u8 *)s2; + for (size_t i = 0; i < len; i++) { + if (a[i] != b[i]) { + return (int)a[i] - (int)b[i]; + } + } + return 0; +} + +size_t strlen(const char *s) { + const char *p = s; + while (*p) ++p; + return (size_t)(p - s); +} + +size_t strnlen(const char *s, size_t maxlen) { + size_t len = 0; + while (len < maxlen && s[len] != '\0') { + len++; + } + return len; } diff --git a/kern/libkern/string.h b/kern/libkern/string.h index 01d3853..d2ff7b5 100644 --- a/kern/libkern/string.h +++ b/kern/libkern/string.h @@ -1,7 +1,45 @@ -#pragma once -#include +#ifndef KERNEL_STRING_H +#define KERNEL_STRING_H -void *memcpy(void *s1, const void *s2, size_t n); -void *memmove(void *s1, const void *s2, size_t n); -void *memset(void *dest, int c, size_t n); -int memcmp(const void *s1, const void *s2, size_t n); +#include + +// void *memcpy(void *s1, const void *s2, size_t n); +// void *memmove(void *s1, const void *s2, size_t n); +// void *memset(void *dest, int c, size_t n); +// int memcmp(const void *s1, const void *s2, size_t n); + +/** Integer to ascii */ +char *itoa(int value, char *str, int base); + +/** Fill memory with constant byte */ +void *memset(void *dst, int c, size_t len); + +/** Copy `len` bytes from `src` to `dst`. Undefined if regions overlap. */ +void *memcpy(void *dst, const void *src, size_t len); + +/** Copy `len` bytes from `src` to `dst`, safe for overlapping regions. */ +void *memmove(void *dst, const void *src, size_t len); + +/** Compare `len` bytes of `s1` and `s2`. + * Returns 0 if equal, <0 if s1 < s2, >0 if s1 > s2. */ +int memcmp(const void *s1, const void *s2, size_t len); + +/** Returns the length of a null-terminated string */ +size_t strlen(const char *s); + +/** Return length of string `s`, up to a max of `maxlen` bytes */ +size_t strnlen(const char *s, size_t maxlen); + +// TODO: These: +/* +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); + +char *strcpy(char *dst, const char *src); +char *strncpy(char *dst, const char *src, size_t n); + +char *strchr(const char *s, int c); +char *strrchr(const char *s, int c); +*/ + +#endif diff --git a/lib/uart.c b/kern/libkern/uart.c similarity index 100% rename from lib/uart.c rename to kern/libkern/uart.c diff --git a/lib/uart.h b/kern/libkern/uart.h similarity index 100% rename from lib/uart.h rename to kern/libkern/uart.h diff --git a/kern/proc.h b/kern/proc.h index b594fc9..26659f3 100644 --- a/kern/proc.h +++ b/kern/proc.h @@ -1,3 +1,6 @@ +#include +#include +#include #include typedef enum { @@ -37,6 +40,7 @@ struct Cpu { int intena; // Were interrupts enabled before push_off()? }; +/** Saved registers for kernel context switches. */ typedef struct { /* 0 */ uint64_t kernel_satp; // kernel page table /* 8 */ uint64_t kernel_sp; // top of process's kernel stack @@ -75,3 +79,10 @@ typedef struct { /* 272 */ uint64_t t5; /* 280 */ uint64_t t6; } TrapFrame_t; + +struct Cpu *mycpu(void); + +extern struct Cpu cpus[NCPU]; + +/** Per-process state */ +struct Proc {}; diff --git a/lib/proc.h b/lib/proc.h deleted file mode 100644 index 1208b2b..0000000 --- a/lib/proc.h +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include -#include - -struct Cpu *mycpu(void); - -/** Saved registers for kernel context switches. */ -struct Context {}; - -/** Per-CPU state. */ -struct Cpu { - struct Proc *proc; // The process running on this cpu, or null. - struct Context context; // swtch() here to enter scheduler(). - int noff; // Depth of push_off() nesting. - int intena; // Were interrupts enabled before push_off()? -}; - -extern struct Cpu cpus[NCPU]; - -/** Per-process state */ -struct Proc {}; diff --git a/lib/string.c b/lib/string.c deleted file mode 100644 index 69fb5c7..0000000 --- a/lib/string.c +++ /dev/null @@ -1,99 +0,0 @@ -#include - -char *itoa(int value, char *str, int base) { - char *p = str; - char *p1, *p2; - unsigned int uvalue = value; - int negative = 0; - - if (base < 2 || base > 36) { - *str = '\0'; - return str; - } - - if (value < 0 && base == 10) { - negative = 1; - uvalue = -value; - } - - // Convert to string - do { - int digit = uvalue % base; - *p++ = (digit < 10) ? '0' + digit : 'a' + (digit - 10); - uvalue /= base; - } while (uvalue); - - if (negative) - *p++ = '-'; - - *p = '\0'; - - // Reverse string - p1 = str; - p2 = p - 1; - while (p1 < p2) { - char tmp = *p1; - *p1++ = *p2; - *p2-- = tmp; - } - - return str; -} - -void *memset(void *dst, int c, size_t length) { - u8 *ptr = (u8 *)dst; - const u8 value = (u8)c; - - while (length--) *(ptr++) = value; - - return dst; -} - -void *memcpy(void *dst, const void *src, size_t len) { - u8 *d = (u8 *)dst; - const u8 *s = (const u8 *)src; - for (size_t i = 0; i < len; i++) { - d[i] = s[i]; - } - return dst; -} - -void *memmove(void *dst, const void *src, size_t len) { - u8 *d = (u8 *)dst; - const u8 *s = (const u8 *)src; - if (d < s) { - for (size_t i = 0; i < len; i++) { - d[i] = s[i]; - } - } else if (d > s) { - for (size_t i = len; i > 0; i--) { - d[i - 1] = s[i - 1]; - } - } - return dst; -} - -int memcmp(const void *s1, const void *s2, size_t len) { - const u8 *a = (const u8 *)s1; - const u8 *b = (const u8 *)s2; - for (size_t i = 0; i < len; i++) { - if (a[i] != b[i]) { - return (int)a[i] - (int)b[i]; - } - } - return 0; -} - -size_t strlen(const char *s) { - const char *p = s; - while (*p) ++p; - return (size_t)(p - s); -} - -size_t strnlen(const char *s, size_t maxlen) { - size_t len = 0; - while (len < maxlen && s[len] != '\0') { - len++; - } - return len; -} diff --git a/lib/string.h b/lib/string.h deleted file mode 100644 index 00805c7..0000000 --- a/lib/string.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef KERNEL_STRING_H -#define KERNEL_STRING_H - -#include - -/** Integer to ascii */ -char *itoa(int value, char *str, int base); - -/** Fill memory with constant byte */ -void *memset(void *dst, int c, size_t len); - -/** Copy `len` bytes from `src` to `dst`. Undefined if regions overlap. */ -void *memcpy(void *dst, const void *src, size_t len); - -/** Copy `len` bytes from `src` to `dst`, safe for overlapping regions. */ -void *memmove(void *dst, const void *src, size_t len); - -/** Compare `len` bytes of `s1` and `s2`. - * Returns 0 if equal, <0 if s1 < s2, >0 if s1 > s2. */ -int memcmp(const void *s1, const void *s2, size_t len); - -/** Returns the length of a null-terminated string */ -size_t strlen(const char *s); - -/** Return length of string `s`, up to a max of `maxlen` bytes */ -size_t strnlen(const char *s, size_t maxlen); - -// TODO: These: -/* -int strcmp(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); - -char *strcpy(char *dst, const char *src); -char *strncpy(char *dst, const char *src, size_t n); - -char *strchr(const char *s, int c); -char *strrchr(const char *s, int c); -*/ - -#endif diff --git a/start.c b/start.c index d0b47c5..10503d1 100644 --- a/start.c +++ b/start.c @@ -4,7 +4,7 @@ #include #include #include -#include +#include #include /**