commit 727b47915b7d4d76ed69d6d8c8b13a232b3fb8b6
parent 23aced7b0db54cc9239d2bd0912903ab5cd6081b
Author: Brian Swetland <swetland@frotz.net>
Date: Wed, 18 May 2022 22:18:08 -0700
xos: improved syscall plumbing, libxos, demo app
- xos/syscall-tmpl.h provides templates for syscalls
- used for user/kernel headers, library stubs, kernel glue
- add libxos for syscall stubs and helpers
- add xos-mandelbrot demo app
Diffstat:
12 files changed, 203 insertions(+), 15 deletions(-)
diff --git a/project/xos-kernel.app.mk b/project/xos-kernel.app.mk
@@ -6,6 +6,7 @@ MOD_SRC += hw/src/context-switch.S
MOD_SRC += hw/src/debug-printf.c hw/src/debug-io.c hw/src/print-exception.c
MOD_LIB := c
MOD_INC := xos/inc
-MOD_EXT := out/ex25-user.bin
+MOD_EXT := out/xos-mandelbrot.bin
MOD_LDSCRIPT := make/kernel.ram.ld
+MOD_QEMU_FB := 1
include make/app.mk
diff --git a/project/xos-mandelbrot.app.mk b/project/xos-mandelbrot.app.mk
@@ -0,0 +1,10 @@
+
+MOD_NAME := xos-mandelbrot
+MOD_SRC := hw/src/start.S xos/user/mandelbrot.c
+MOD_LIB := gfx xos c
+MOD_LDSCRIPT := make/user.ram.ld
+
+# TODO: fix this
+MOD_INC := xos/inc
+
+include make/app.mk
diff --git a/project/xos.lib.mk b/project/xos.lib.mk
@@ -0,0 +1,6 @@
+
+MOD_NAME := xos
+MOD_SRC := xos/lib/syscalls.S xos/lib/debug-io.c
+MOD_INC := xos/inc
+MOD_LIB := c
+include make/lib.mk
diff --git a/xos/inc/xos/syscall-tmpl.h b/xos/inc/xos/syscall-tmpl.h
@@ -0,0 +1,8 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+__SYSCALL(0,void,exit,(int n))
+__SYSCALL(1,void,xputc,(unsigned ch))
+__SYSCALL(2,status_t,thread_create,(handle_t *out, void *entry, void *arg))
+
+#define SYSCALL_COUNT 3
diff --git a/xos/inc/xos/syscalls.h b/xos/inc/xos/syscalls.h
@@ -0,0 +1,10 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#pragma once
+#include <xos/status.h>
+#include <xos/types.h>
+
+#define __SYSCALL(n,rtype,name,args) rtype name args;
+#include <xos/syscall-tmpl.h>
+#undef __SYSCALL
diff --git a/xos/inc/xos/types.h b/xos/inc/xos/types.h
@@ -0,0 +1,13 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#pragma once
+
+#include <stdint.h>
+
+typedef uint32_t handle_t;
+typedef uint32_t status_t;
+typedef uint32_t paddr_t;
+typedef uint32_t vaddr_t;
+
+
diff --git a/xos/lib/debug-io.c b/xos/lib/debug-io.c
@@ -0,0 +1,27 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0.
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#include <hw/debug.h>
+
+void xputs(const char* s) {
+ while (*s != 0) {
+ xputc(*s++);
+ }
+}
+
+int xgetc(void) {
+ return -1;
+}
+
+void xprintf(const char* fmt, ...) {
+ char msg[128];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(msg, sizeof(msg), fmt, ap);
+ va_end(ap);
+ xputs(msg);
+}
+
diff --git a/xos/lib/syscalls.S b/xos/lib/syscalls.S
@@ -0,0 +1,6 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#define __SYSCALL(n,rtype,name,args) .globl name; name:; addi t0, x0, n; ecall; ret
+
+#include <xos/syscall-tmpl.h>
diff --git a/xos/src/entry.S b/xos/src/entry.S
@@ -127,8 +127,13 @@ exception_entry:
la ra, trap_exit
j exception_handler
+syscall_table:
+#define __SYSCALL(n,rtype,name,args) .word sys_##name
+#include <xos/syscall-tmpl.h>
+syscall_table_end:
+
syscall_entry:
- li t1, 2 // SYSCALL_COUNT
+ li t1, SYSCALL_COUNT
bgeu t0, t1, illegal_syscall
// fn = [syscall_table + (syscall_number << 2)]
@@ -148,11 +153,6 @@ syscall_entry:
j trap_exit
-syscall_table:
- .word sys_exit
- .word sys_xputc
-syscall_table_end:
-
illegal_syscall:
addi t0, zero, XOS_ERR_BAD_SYSCALL
sw t0, 0x20(sp)
diff --git a/xos/src/kernel.c b/xos/src/kernel.c
@@ -26,6 +26,17 @@ typedef struct {
thread_t thread;
} kstack_top_t;
+#define FRAMEBUFFER_SIZE (640*480*2)
+
+void map_framebuffer(uint32_t* pgdir) {
+ paddr_t pa = FRAMEBUFFER_BASE;
+ vaddr_t va = 0x20000000;
+ for (unsigned n = 0; n < FRAMEBUFFER_SIZE; n += PAGE_SIZE) {
+ // TODO: remove the pa from the freelist
+ vm_map_4k(pgdir, va + n, pa + n, USER_RW);
+ }
+}
+
void start_user_program(void) {
vaddr_t user_start = 0x10000000;
vaddr_t user_stack = 0x10400000;
@@ -41,6 +52,8 @@ void start_user_program(void) {
// allocate a 4KB (1 page) for user stack
vm_map_4k(kpgdir, user_stack - 1*PAGE_SIZE, ppage_alloc_z(), USER_RW);
+ map_framebuffer(kpgdir);
+
// allow S-MODE writes to U-MODE pages
csr_set(CSR_SSTATUS, SSTATUS_SUM);
@@ -131,15 +144,17 @@ void start(void) {
start_user_program();
}
-status_t sys_xputc(uint32_t ch) {
+status_t sys_thread_create(handle_t* out, void *entry, void *arg) {
+ return XOS_ERR_NOT_SUPPORTED;
+}
+
+void sys_xputc(unsigned ch) {
xputc(ch);
- return XOS_OK;
}
-status_t sys_exit(int n) {
+void sys_exit(int n) {
xprintf("\n[ user exit (status %d) ]\n", n);
for (;;) ;
- return XOS_OK;
}
void interrupt_handler(void) {
diff --git a/xos/src/kernel.h b/xos/src/kernel.h
@@ -4,6 +4,7 @@
#pragma once
#include <xos/status.h>
+#include <xos/types.h>
#include <hw/riscv.h>
#include <hw/context.h>
@@ -17,10 +18,6 @@
void panic(const char* msg);
// vm.c
-typedef uint32_t paddr_t;
-typedef uint32_t vaddr_t;
-typedef uint32_t status_t;
-
static inline void* pa_to_kva(paddr_t pa) {
return (void*) (pa + (KVA_BASE - KPA_BASE));
}
@@ -59,3 +56,6 @@ typedef struct {
uint32_t reserved3;
} thread_t;
+// syscall entry points
+#define __SYSCALL(n,rtype,name,args) rtype sys_##name args;
+#include <xos/syscall-tmpl.h>
diff --git a/xos/usr/mandelbrot.c b/xos/usr/mandelbrot.c
@@ -0,0 +1,92 @@
+// Copyright 2022, Brian Swetland <swetland@frotz.net>
+// Licensed under the Apache License, Version 2.0
+
+#include <xos/syscalls.h>
+#include <hw/debug.h>
+#include <gfx/gfx.h>
+#include <string.h>
+
+uint16_t colors[12] = {
+ 0x1111, 0x2222, 0x3333, 0x4444, 0x5555, 0x6666,
+ 0x7777, 0x8888, 0x9999, 0xAAAA, 0xBBBB, 0xCCCC,
+};
+
+int render(gfx_surface_t* _gs,
+ uint32_t px0, uint32_t py0,
+ uint32_t px1, uint32_t py1) {
+ gfx_surface_t gs;
+ memcpy(&gs, _gs, sizeof(gs));
+
+ for (int py = py0; py < py1; py++) {
+ int y0 = 650 - (1300 * py) / gs.height;
+ for (int px = px0; px < px1; px++) {
+ int x0 = -1250 + (1750 * px) / gs.width;
+ int x = 0, y = 0;
+ for (int i = 0; i < 500; i++) {
+ int x2 = x * x / 1000;
+ int y2 = y * y / 1000;
+ if ((x2 + y2) > 4000) {
+ gs.fgcolor = colors[(i > 11) ? 11 : i];
+ gfx_plot(&gs, px, py);
+ goto done;
+ }
+ y = 2 * x * y / 1000 + y0;
+ x = x2 - y2 + x0;
+ }
+ gs.fgcolor = 0;
+ gfx_plot(&gs, px, py);
+ done:
+ ;
+ }
+ }
+
+ return 2;
+}
+
+#if 0
+int t1(void* arg) {
+ gfx_surface_t *gs = arg;
+ gfx_fill(gs, 0, 0, 320, 240, gfx_color(gs, C_WHITE));
+ gfx_puts(gs, 0, 240-16, "Thread One");
+ return render(gs, 0, 0, 320, 240);
+}
+int t2(void* arg) {
+ gfx_surface_t *gs = arg;
+ gfx_fill(gs, 320, 240, 640, 480, gfx_color(gs, C_GRAY75));
+ gfx_puts(gs, 320, 480-16, "Thread Two");
+ return render(gs, 320, 240, 640, 480);
+}
+int t3(void* arg) {
+ gfx_surface_t *gs = arg;
+ gfx_fill(gs, 320, 0, 640, 240, gfx_color(gs, C_GRAY25));
+ gfx_puts(gs, 320, 240-16, "Thread Three");
+ return render(gs, 320, 0, 640, 240);
+}
+int t4(void* arg) {
+ gfx_surface_t *gs = arg;
+ gfx_fill(gs, 0, 240, 320, 480, gfx_color(gs, C_GRAY50));
+ gfx_puts(gs, 0, 480-16, "Thread Four");
+ return render(gs, 0, 240, 320, 480);
+}
+#endif
+
+static gfx_surface_t screen;
+
+void start(void) {
+ xprintf("X/OS Example - Mandelbrot\n\n");
+
+ screen.width = 640;
+ screen.height = 480;
+ screen.stride = 640;
+ screen.pixels = (void*) 0x20000000;
+ screen.pixfmt = PIXFMT_RGB565;
+ screen.fgcolor = C_WHITE;
+ screen.bgcolor = C_BLUE;
+ gfx_init(&screen);
+
+ gfx_clear(&screen, C_BLUE);
+ render(&screen, 0, 0, 640, 480);
+
+ exit(0);
+}
+