summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile36
-rw-r--r--include/endian.h17
-rw-r--r--include/stddef.h7
-rw-r--r--include/stdint.h19
-rw-r--r--include/string.h8
-rw-r--r--lib/Makefile21
-rw-r--r--lib/build/memset.obin0 -> 1328 bytes
-rw-r--r--lib/string/memset.c14
-rw-r--r--mainboard/virt/conf/mainboard.conf4
-rw-r--r--sys/Makefile36
-rw-r--r--sys/dev/sbi.c39
-rw-r--r--sys/include/fdt.h37
-rw-r--r--sys/include/kernel_earlyprintf.h6
-rw-r--r--sys/include/mm/kalloc.h11
-rw-r--r--sys/include/sbi.h16
-rw-r--r--sys/kern/entry.S (renamed from kernel/boot/entry.S)23
-rw-r--r--sys/kern/init.c11
-rw-r--r--sys/kern/kernel.lds (renamed from kernel/lds/kernel.ld)15
-rw-r--r--sys/kern/kernel_earlyprintf.c11
-rw-r--r--sys/kern/mm/kalloc.c40
20 files changed, 337 insertions, 34 deletions
diff --git a/Makefile b/Makefile
index 3c2a981..e683c86 100644
--- a/Makefile
+++ b/Makefile
@@ -1,30 +1,22 @@
TARGET?=virt
CROSS_COMPILE?=riscv64-unknown-elf-
+GDB_PORT?=1234
+CFLAGS=-nostdlib -ffreestanding -mcmodel=medany -nostdinc -I${.CURDIR}/include
+.export
-BUILDDIR=build/${TARGET}
-TARGETDIR=mainboard/${TARGET}
+sys: ${SRC} lib/build/libc.a
+ @echo "building kernel"
+ (${MAKE} -C sys -e)
-CFLAGS=-nostdlib -ffreestanding -mcmodel=medany
+lib/build/libc.a:
+ @echo "building libc"
+ (${MAKE} -C lib -e)
-.if !exists(${TARGETDIR}/conf/mainboard.mk)
-.error 'ERROR: invalid target "${TARGET}"'
-.else
-.include <${TARGETDIR}/conf/mainboard.mk>
-.endif
-
-all: ${BUILDDIR}/kernel.elf
+debug: sys
+ (${MAKE} -C sys -e debug)
clean:
- rm -rf ${BUILDDIR}
-
-${BUILDDIR}/kernel.elf: ${SRC}
- mkdir -p ${BUILDDIR}
- ${CROSS_COMPILE}gcc ${SRC} \
- -Wl,--defsym=LOAD_ADDR=${LOAD_ADDR}\
- -Wl,--defsym=PAGE_SIZE=${PAGE_SIZE}\
- -Wl,--defsym=NPROC=${NPROC}\
- -DPAGE_SIZE=${PAGE_SIZE}\
- ${CFLAGS} -T kernel/lds/kernel.ld ${LDFLAGS}\
- -o $@
+ (${MAKE} -C sys -e clean)
+ (${MAKE} -C lib -e clean)
-.PHONY: all clean
+.PHONY: sys debug all clean
diff --git a/include/endian.h b/include/endian.h
new file mode 100644
index 0000000..79b4c93
--- /dev/null
+++ b/include/endian.h
@@ -0,0 +1,17 @@
+#ifndef _ENDIAN_H
+#define _ENDIAN_H
+
+#include <stdint.h>
+
+#define LITTLE_ENDIAN 1234
+#define BIG_ENDIAN 4321
+#define BYTE_ORDER __BYTE_ORDER__
+
+static inline uint32_t
+__bswap32(uint32_t x)
+{
+ uint8_t *p = (uint8_t*)&x;
+ return ((p[0] << 030) | (p[1] << 020) | (p[2] << 010) | p[3]);
+}
+
+#endif /* _ENDIAN_H */
diff --git a/include/stddef.h b/include/stddef.h
new file mode 100644
index 0000000..998f53d
--- /dev/null
+++ b/include/stddef.h
@@ -0,0 +1,7 @@
+#ifndef _STDDEF_H
+#define _STDDEF_H
+
+#define NULL ((void*)0)
+typedef unsigned long size_t;
+
+#endif /* _STDDEF_H_ */
diff --git a/include/stdint.h b/include/stdint.h
new file mode 100644
index 0000000..4afd32d
--- /dev/null
+++ b/include/stdint.h
@@ -0,0 +1,19 @@
+#ifndef _STDINT_H
+#define _STDINT_H
+
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long uint64_t;
+
+
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long int64_t;
+
+
+#endif /* _STDINT_H */
+
+
diff --git a/include/string.h b/include/string.h
new file mode 100644
index 0000000..a8edd63
--- /dev/null
+++ b/include/string.h
@@ -0,0 +1,8 @@
+#ifndef _STRING_H
+#define _STRING_H
+
+#include <stddef.h>
+
+void *memset(void *s, int c, size_t n);
+
+#endif /* _STRING_H */
diff --git a/lib/Makefile b/lib/Makefile
new file mode 100644
index 0000000..b44c1f6
--- /dev/null
+++ b/lib/Makefile
@@ -0,0 +1,21 @@
+BUILDDIR=build/${TARGET}
+TARGETDIR=../mainboard/${TARGET}
+
+.if !exists(${TARGETDIR}/conf/mainboard.conf)
+.error 'ERROR: invalid target "${TARGET}"'
+.else
+.include <${TARGETDIR}/conf/mainboard.conf>
+.endif
+
+SRC=\
+ string/memset.c
+
+
+${BUILDDIR}/libc.a: ${SRC}
+ mkdir -p ${BUILDDIR}
+ cd ${BUILDDIR} && ${CROSS_COMPILE}gcc -c ${CFLAGS} ${SRC:%=../../%}
+ cd ${BUILDDIR} && ${CROSS_COMPILE}ar -rcs ${@:T} ${SRC:T:%.c=%.o}
+
+
+clean:
+ rm -rf ${BUILDDIR}
diff --git a/lib/build/memset.o b/lib/build/memset.o
new file mode 100644
index 0000000..a5c0c8c
--- /dev/null
+++ b/lib/build/memset.o
Binary files differ
diff --git a/lib/string/memset.c b/lib/string/memset.c
new file mode 100644
index 0000000..59e3bea
--- /dev/null
+++ b/lib/string/memset.c
@@ -0,0 +1,14 @@
+#include <stddef.h>
+#include <string.h>
+
+void *
+memset(void *s, int c, size_t n)
+{
+ char *xs = s;
+
+ while (n--)
+ *xs++ = c;
+
+ return s;
+}
+
diff --git a/mainboard/virt/conf/mainboard.conf b/mainboard/virt/conf/mainboard.conf
new file mode 100644
index 0000000..77e8e2a
--- /dev/null
+++ b/mainboard/virt/conf/mainboard.conf
@@ -0,0 +1,4 @@
+LOAD_ADDR=0x80200000
+PAGE_SIZE=4096
+NPROC=1
+DEBUG=qemu-system-riscv64 -nographic -machine virt -smp ${NPROC} -m 128M -bios default -gdb tcp::${GDB_PORT} -kernel
diff --git a/sys/Makefile b/sys/Makefile
new file mode 100644
index 0000000..865a5a3
--- /dev/null
+++ b/sys/Makefile
@@ -0,0 +1,36 @@
+BUILDDIR=build/${TARGET}
+TARGETDIR=../mainboard/${TARGET}
+
+.if !exists(${TARGETDIR}/conf/mainboard.conf)
+.error 'ERROR: invalid target "${TARGET}"'
+.else
+.include <${TARGETDIR}/conf/mainboard.conf>
+.endif
+
+SRC=\
+ kern/entry.S\
+ kern/init.c\
+ kern/kernel_earlyprintf.c\
+ kern/mm/kalloc.c\
+ dev/sbi.c
+
+${BUILDDIR}/kernel.elf: ${SRC}
+ mkdir -p ${BUILDDIR}
+ ${CROSS_COMPILE}gcc ${SRC} \
+ -Wl,--defsym=LOAD_ADDR=${LOAD_ADDR}\
+ -Wl,--defsym=PAGE_SIZE=${PAGE_SIZE}\
+ -Wl,--defsym=NPROC=${NPROC}\
+ -DPAGE_SIZE=${PAGE_SIZE}\
+ -I ./include\
+ ${CFLAGS} -T kern/kernel.lds ${LDFLAGS}\
+ -L../lib/${BUILDDIR}/\
+ -l:libc.a\
+ -o $@
+
+debug: ${BUILDDIR}/kernel.elf
+ ${DEBUG} ${BUILDDIR}/kernel.elf
+
+clean:
+ rm -rf ${BUILDDIR}
+
+.PHONY: debug clean
diff --git a/sys/dev/sbi.c b/sys/dev/sbi.c
new file mode 100644
index 0000000..0c9e3f2
--- /dev/null
+++ b/sys/dev/sbi.c
@@ -0,0 +1,39 @@
+#include <sbi.h>
+
+struct sbiret
+sbi_ecall(int ext, int fid, unsigned long arg0,
+ unsigned long arg1, unsigned long arg2,
+ unsigned long arg3, unsigned long arg4,
+ unsigned long arg5)
+{
+ struct sbiret ret;
+
+ register unsigned long a0 asm ("a0") = (unsigned long)(arg0);
+ register unsigned long a1 asm ("a1") = (unsigned long)(arg1);
+ register unsigned long a2 asm ("a2") = (unsigned long)(arg2);
+ register unsigned long a3 asm ("a3") = (unsigned long)(arg3);
+ register unsigned long a4 asm ("a4") = (unsigned long)(arg4);
+ register unsigned long a5 asm ("a5") = (unsigned long)(arg5);
+ register unsigned long a6 asm ("a6") = (unsigned long)(fid);
+ register unsigned long a7 asm ("a7") = (unsigned long)(ext);
+ asm volatile ("ecall"
+ : "+r" (a0), "+r" (a1)
+ : "r" (a2), "r" (a3), "r" (a4), "r" (a5), "r" (a6), "r" (a7)
+ : "memory");
+ ret.err = a0;
+ ret.val = a1;
+
+ return ret;
+}
+
+void
+sbi_console_putchar(int c)
+{
+ sbi_ecall(1, 0, c, 0, 0, 0, 0, 0);
+}
+
+void
+sbi_shutdown(void)
+{
+ sbi_ecall(8, 0, 0, 0, 0, 0, 0, 0);
+}
diff --git a/sys/include/fdt.h b/sys/include/fdt.h
new file mode 100644
index 0000000..92e5695
--- /dev/null
+++ b/sys/include/fdt.h
@@ -0,0 +1,37 @@
+#include <stdint.h>
+#include <endian.h>
+
+#ifndef _FDT_H
+#define _FDT_H
+
+#define FDT_HEADER_MAGIC 0xd00dfeed
+
+static inline uint32_t
+fdt_uint32(uint32_t x)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+return __bswap32(x);
+#else
+return x;
+#endif
+}
+
+struct fdt_header {
+ uint32_t magic; /* FDT_HEADER_MAGIC */
+ uint32_t totalsize; /* size of the whole device tree, in bytes */
+ uint32_t off_dt_struct; /* offset to structure block */
+ uint32_t off_dt_strings; /* offset to strings block */
+ uint32_t off_mem_rsvmap; /* offset to memory reservation block */
+ uint32_t version; /* dt spec version */
+ uint32_t last_comp_version; /* last compatible version. spec says this needs to be 16 */
+ uint32_t boot_cpuid_phys; /* physical id of the systems boot cpu */
+ uint32_t size_dt_strings; /* size of strings block */
+ uint32_t size_dt_struct; /* size of structure block */
+};
+
+struct fdt_reserve_entry {
+ uint64_t address;
+ uint64_t size;
+};
+
+#endif /* _FDT_H */
diff --git a/sys/include/kernel_earlyprintf.h b/sys/include/kernel_earlyprintf.h
new file mode 100644
index 0000000..051d7e5
--- /dev/null
+++ b/sys/include/kernel_earlyprintf.h
@@ -0,0 +1,6 @@
+#ifndef _KPRINTF_H
+#define _KPRINTF_H
+
+int kernel_earlyputs(const char *);
+
+#endif /* _KPRINTF_H */
diff --git a/sys/include/mm/kalloc.h b/sys/include/mm/kalloc.h
new file mode 100644
index 0000000..e99d624
--- /dev/null
+++ b/sys/include/mm/kalloc.h
@@ -0,0 +1,11 @@
+#ifndef _KALLOC_H
+#define _KALLOC_H
+
+void *kalloc(void);
+
+void *kzalloc(void);
+
+void kfree(void *);
+
+#endif /* _KALLOC_H */
+
diff --git a/sys/include/sbi.h b/sys/include/sbi.h
new file mode 100644
index 0000000..0dbcd02
--- /dev/null
+++ b/sys/include/sbi.h
@@ -0,0 +1,16 @@
+#ifndef _SBICALL_H
+#define _SBICALL_H
+
+struct sbiret {
+ long err;
+ long val;
+};
+
+struct sbiret sbi_ecall(int _eid, int _fid, unsigned long _a0, unsigned long _a1,
+ unsigned long _a2, unsigned long _a3, unsigned long _a4, unsigned long _a5);
+
+void sbi_console_putchar(int c);
+void sbi_shutdown(void);
+
+#endif /* _SBICALL_H */
+
diff --git a/kernel/boot/entry.S b/sys/kern/entry.S
index 4c977a3..5ad0490 100644
--- a/kernel/boot/entry.S
+++ b/sys/kern/entry.S
@@ -1,4 +1,4 @@
-.section .text.init
+.section ".text.init"
.globl _start
_start:
@@ -12,25 +12,28 @@ _start:
.option pop
la sp, __stack_start
- mv t0, a0
li t1, PAGE_SIZE
- mul t0, t0, t1
- add sp, sp, t0
+ mul t1, t1, a0
+ add sp, sp, t1
li a2, 1
lla a3, _boot_hart
- amoswap.w, a3, a2, (a3)
- bnez a3, mp_entry
+ amoswap.w a3, a2, (a3)
+ bnez a3, _spin
la a2, __bss_start
la a3, __bss_end
1:
- sd zero, (a2)
+ sd zero, (a2)
addi a2, a2, __SIZEOF_POINTER__
blt a2, a3, 1b
- call boot
+ call init
-_boot_hart:
- .dword 0
+_spin:
+ wfi
+ j _spin
+
+.section ".data"
+_boot_hart: .word 0
diff --git a/sys/kern/init.c b/sys/kern/init.c
new file mode 100644
index 0000000..a49c304
--- /dev/null
+++ b/sys/kern/init.c
@@ -0,0 +1,11 @@
+#include <fdt.h>
+#include <kernel_earlyprintf.h>
+
+void
+init(unsigned long hartid, struct fdt_header *fdt)
+{
+ kernel_earlyputs("booting...\n");
+ if (fdt_uint32(fdt->magic) == FDT_HEADER_MAGIC)
+ kernel_earlyputs("found flattened device tree!\n");
+
+}
diff --git a/kernel/lds/kernel.ld b/sys/kern/kernel.lds
index 052aa32..2e2fe29 100644
--- a/kernel/lds/kernel.ld
+++ b/sys/kern/kernel.lds
@@ -8,13 +8,13 @@ SECTIONS
.text :
{
- provide(__text_start = .);
+ PROVIDE(__text_start = .);
*(.text.init)
*(.text .text.*)
. = ALIGN(8);
PROVIDE(__text_end = .);
}
- . = ALIGN(PAGE_SIZE);
+ . = ALIGN(PAGE_SIZE);
PROVIDE(__global_pointer$ = .);
@@ -41,6 +41,17 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
+ .bss :
+ {
+ PROVIDE(__bss_start = .);
+ *(.sbss .sbss.*)
+ *(.bss .bss.*)
+ . = ALIGN(8);
+ PROVIDE(__bss_end = .);
+ }
+
+ . = ALIGN(PAGE_SIZE);
+
PROVIDE(__stack_start = .);
PROVIDE(__stack_end = __stack_start + (PAGE_SIZE * NPROC));
PROVIDE(__heap_start = __stack_end);
diff --git a/sys/kern/kernel_earlyprintf.c b/sys/kern/kernel_earlyprintf.c
new file mode 100644
index 0000000..e6c85c4
--- /dev/null
+++ b/sys/kern/kernel_earlyprintf.c
@@ -0,0 +1,11 @@
+#include <kernel_earlyprintf.h>
+#include <sbi.h>
+
+int
+kernel_earlyputs(const char *str)
+{
+ do {
+ sbi_console_putchar(*str);
+ } while (*(str++) != '\0');
+}
+
diff --git a/sys/kern/mm/kalloc.c b/sys/kern/mm/kalloc.c
new file mode 100644
index 0000000..b17d432
--- /dev/null
+++ b/sys/kern/mm/kalloc.c
@@ -0,0 +1,40 @@
+#include <stddef.h>
+#include <string.h>
+#include <mm/kalloc.h>
+
+typedef struct freenode {
+ struct freenode *next;
+} freenode_t;
+
+freenode_t *head = NULL;
+
+void *
+kalloc(void)
+{
+ freenode_t *p = head;
+
+ if (p == NULL)
+ return NULL;
+
+ head = p->next;
+ return p;
+}
+
+void *
+kzalloc(void)
+{
+ freenode_t *p = kalloc();
+ memset(p, 0, PAGE_SIZE);
+ return p;
+}
+
+void
+kfree(void *p)
+{
+ if (p == NULL || (unsigned long)p % PAGE_SIZE)
+ return;
+
+ freenode_t *tmp = head;
+ head = p;
+ head->next = tmp;
+}