aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2020-11-25 15:47:02 -0700
committerJosh Rahm <joshuarahm@gmail.com>2020-11-25 15:47:02 -0700
commit6d22b0dfc7761a605758552d5824f8039ac5a00f (patch)
treede0cd4848c02b787d45b41afaca244606eceab5d /src
parentb07c6f6a9d926d4eac726b94963e479839382675 (diff)
downloadstm32l4-6d22b0dfc7761a605758552d5824f8039ac5a00f.tar.gz
stm32l4-6d22b0dfc7761a605758552d5824f8039ac5a00f.tar.bz2
stm32l4-6d22b0dfc7761a605758552d5824f8039ac5a00f.zip
Primitive ability to call kernel code from userspace.
Diffstat (limited to 'src')
-rw-r--r--src/kern/init.c11
-rw-r--r--src/kern/log.c2
-rw-r--r--src/kern/main.c140
-rw-r--r--src/kern/mpu/mpu_manager.c103
-rw-r--r--src/kern/panic.c1
-rw-r--r--src/kern/priv.c88
-rw-r--r--src/kern/svc.c51
-rw-r--r--src/kern/syscalls/logs.c7
-rw-r--r--src/user/syscall.c17
9 files changed, 198 insertions, 222 deletions
diff --git a/src/kern/init.c b/src/kern/init.c
index 8885c09..c776b4a 100644
--- a/src/kern/init.c
+++ b/src/kern/init.c
@@ -66,9 +66,6 @@ init1()
init3()
{
- klogf("--- System Restart ---\n");
- klogf("Setting the vector offset table to point to the start of flash.\n");
-
/* Set the vector offset table to be at the start
* of FLASH memory. */
SCB.vto_r = 0x08000000;
@@ -92,10 +89,6 @@ void run_init_routines()
++initfn) {
while (initfn == init_boundaries[initlevel] && initlevel < INIT_LEVEL_7) {
++initlevel;
-
- if (initlevel > 2) {
- klogf("[init%d]\n", initlevel);
- }
}
(*initfn)();
@@ -103,11 +96,7 @@ void run_init_routines()
while (initlevel < INIT_LEVEL_7) {
++initlevel;
-
- klogf("[init%d]\n", initlevel);
}
-
- klogf("Initialization Routines Complete. Onto main()\n");
}
/*
diff --git a/src/kern/log.c b/src/kern/log.c
index 3331249..e9bd424 100644
--- a/src/kern/log.c
+++ b/src/kern/log.c
@@ -18,8 +18,6 @@ init2()
regset(USART2.c_r1, usart_txeie, 1);
regset(USART2.c_r1, usart_rxneie, 1);
usart_set_enabled(&USART2, USART_ENABLE_TX | USART_ENABLE_RX);
-
- klogf("klog() enabled on USART2\n");
}
void klogf(const char* fmt, ...)
diff --git a/src/kern/main.c b/src/kern/main.c
index 4ed67be..3af8beb 100644
--- a/src/kern/main.c
+++ b/src/kern/main.c
@@ -8,6 +8,7 @@
#include "kern/mpu/mpu_manager.h"
#include "kern/panic.h"
#include "kern/priv.h"
+#include "user/syscall.h"
void on_hard_fault()
{
@@ -19,139 +20,34 @@ void on_systick() /* Overrides weak-symbol on_systick. */
klogf("Systick\n");
}
-#ifdef ARCH_STM32L4
+void configure_mpu()
+{
+ configure_flash_region((void*)0x08000000, REGION_SIZE_256Kb, NOT_PRIVILEGED);
+ configure_ram_region((void*)SRAM1_BASE, REGION_SIZE_64Kb, NOT_PRIVILEGED);
+ configure_ram_region((void*)SRAM2_BASE, REGION_SIZE_16Kb, NOT_PRIVILEGED);
+ configure_peripheral_region((void*)0x40000000, REGION_SIZE_512Mb, PRIVILEGED);
+ mpu_set_enabled(1);
+}
-int thing_in_sram_1;
+#ifdef ARCH_STM32L4
/* Main function. This gets executed from the interrupt vector defined above. */
int main()
{
- klogf("Hello, World! Clock Mhz: %d\n", (uint32_t)get_clock_mhz());
- klogf("Heap Start: %p\n", &HEAP_START);
- klogf("Heap End : %p\n", &HEAP_STOP);
-
- klogf("mpu: %p\n", &MPU);
- klogf("mpu.type_r: %p\n", MPU.type_r);
- klogf("mpu.ctrl_r: %p\n", MPU.ctrl_r);
- klogf("mpu.rn_r: %p\n", MPU.rn_r);
-
- thing_in_sram_1 = 0xdeadbeef;
-
- uint32_t control;
- asm volatile("mrs %0, control" : "=r"(control) :);
-
- /* Set the countdown to start from 10,000,0000. */
- SCB.strv_r = 10000000 / 20;
-
- /* Enable interrupts. */
- // regset(SCB.stcs_r, scb_tickint, 1);
-
- /* Start the systick. */
- regset(SCB.stcs_r, scb_enable, 1);
-
-
- klogf("&thing_in_sram_1: %p\n", &thing_in_sram_1);
- klogf(" thing_in_sram_1: %p\n", thing_in_sram_1);
- mpu_set_enabled(0);
-
- memory_region_opts_t memopts = { 0 };
- memopts.region = (void*) 0x08000000 /* Flash base */ ;
- memopts.bufferable = 0;
- memopts.cacheable = 1;
- memopts.sharable = 0;
- memopts.tex = 0;
- memopts.size = REGION_SIZE_256Kb;
- memopts.perms = ACCESS_PERMS_ONLY_PRIV_RO;
- memopts.subregion_disable = 0;
- memopts.executable = 1;
- memopts.enable = 1;
+ configure_mpu();
- mpu_configure_region(0, &memopts);
+ klogf("Outside of usermode, I can still log stuff using klogf()\n");
- memopts.region = (void*) SRAM1_BASE;
- memopts.bufferable = 0;
- memopts.cacheable = 1;
- memopts.sharable = 0;
- memopts.tex = 0;
- memopts.size = REGION_SIZE_64Kb;
- memopts.perms = ACCESS_PERMS_FULL;
- memopts.subregion_disable = 0;
- memopts.executable = 1;
- memopts.enable = 1;
-
- mpu_configure_region(1, &memopts);
-
- memopts.region = (void*) SRAM2_BASE;
- memopts.bufferable = 0;
- memopts.cacheable = 1;
- memopts.sharable = 0;
- memopts.tex = 0;
- memopts.size = REGION_SIZE_16Kb;
- memopts.perms = ACCESS_PERMS_FULL;
- memopts.subregion_disable = 0;
- memopts.executable = 1;
- memopts.enable = 1;
-
- mpu_configure_region(2, &memopts);
-
- memopts.region = (void*) 0x40000000 /* Peripheral base. */;
- memopts.bufferable = 1;
- memopts.cacheable = 0;
- memopts.sharable = 1;
- memopts.tex = 0;
- memopts.size = REGION_SIZE_512Mb;
- memopts.perms = ACCESS_PERMS_ONLY_PRIV;
- memopts.subregion_disable = 0;
- memopts.executable = 0;
- memopts.enable = 1;
-
- mpu_configure_region(3, &memopts);
-
- for (uint32_t i = 0; i < 8; ++ i) {
- MPU.rn_r = i;
- klogf("--- %d ---\n", i);
- klogf("mpu: %p\n", &MPU);
- klogf("mpu.type_r: %p\n", MPU.type_r);
- klogf("mpu.ctrl_r: %p\n", MPU.ctrl_r);
- klogf("mpu.rn_r: %p\n", MPU.rn_r);
- klogf("mpu.ras_r: %p\n", MPU.ras_r);
- klogf("mpu.rba_r: %p\n", MPU.rba_r);
- }
-
- // memopts.region = (void*) (SRAM1_BASE);
- // memopts.bufferable = 0;
- // memopts.cacheable = 1;
- // memopts.sharable = 1;
- // memopts.tex = 0;
- // memopts.size = REGION_SIZE_16Kb;
- // memopts.perms = ACCESS_PERMS_NO_ACCESS;
-
- klogf("CONTROL: %p\n", get_control_register());
- klogf("CONTROL: %p\n", get_control_register());
- klogf("MPU not enabled\n");
-
- volatile int x;
- klogf("x location: %p\n", &x);
-
- // mpu_set_enabled(1);
-
- x = 5;
- klogf("Still alive?\n");
-
- klogf("Entering User Mode\n");
enter_user_mode();
- asm volatile (
- "svc #21\n"
- );
-
- klogf("Should Kernel Panic\n");
+ logs("Now that I'm in user mode, I have to log stuff using a system call\n");
+ logs(
+ "because I no longer have direct accss to USART2 and cannot use\n"
+ "klogf()\n");
- for(;;);
- // klogf("MPU enabled\n");
- // klogf("&thing_in_sram_1: %p\n", &thing_in_sram_1);
- // klogf(" thing_in_sram_1: %p\n", thing_in_sram_1);
+ for (;;)
+ ;
}
#endif
diff --git a/src/kern/mpu/mpu_manager.c b/src/kern/mpu/mpu_manager.c
index 614766a..0d03c39 100644
--- a/src/kern/mpu/mpu_manager.c
+++ b/src/kern/mpu/mpu_manager.c
@@ -1,6 +1,6 @@
-#include "arch.h"
#include "kern/mpu/mpu_manager.h"
+#include "arch.h"
#include "arch/arm/cortex-m4/mpu.h"
#include "kern/common.h"
#include "kern/log.h"
@@ -40,8 +40,6 @@ void mpu_configure_region(int region_number, memory_region_opts_t* opts)
uint32_t rbar = region;
regset(rbar, mpu_region, region_number);
regset(rbar, mpu_valid, 1);
-
- klogf("Writing RBAR: %p\n", rbar);
uint32_t rasr = 0;
regset(rasr, mpu_en, opts->enable);
@@ -56,8 +54,103 @@ void mpu_configure_region(int region_number, memory_region_opts_t* opts)
regset(rasr, mpu_ap, opts->perms);
regset(rasr, mpu_xn, !opts->executable);
- klogf("Writing RASR: %p\n", rasr);
-
MPU.rba_r = rbar;
MPU.ras_r = rasr;
}
+
+static int find_unused_region_slot()
+{
+ // memory_region_opts_t memory_regions[8];
+
+ int i;
+ for (i = 0; i < sizeof(memory_regions) / sizeof(memory_region_opts_t);
+ ++i) {
+ if (!memory_regions[i].enable) {
+ return i;
+ }
+ }
+
+ return i;
+}
+
+void configure_peripheral_region(
+ void* peripheral_base, region_size_t region_size, privilege_t priv)
+{
+ int idx = find_unused_region_slot();
+
+ memory_region_opts_t memopts = {0};
+
+ memopts.region = peripheral_base;
+ memopts.bufferable = 1;
+ memopts.cacheable = 0;
+ memopts.sharable = 1;
+ memopts.tex = 0;
+ memopts.size = region_size;
+ switch (priv) {
+ case NOT_PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_FULL;
+ break;
+ case PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_ONLY_PRIV;
+ break;
+ }
+ memopts.subregion_disable = 0;
+ memopts.executable = 0;
+ memopts.enable = 1;
+
+ mpu_configure_region(idx, &memopts);
+}
+
+void configure_flash_region(
+ void* flash_base, region_size_t region_size, privilege_t priv)
+{
+ int idx = find_unused_region_slot();
+
+ memory_region_opts_t memopts = {0};
+ memopts.region = flash_base;
+ memopts.bufferable = 0;
+ memopts.cacheable = 1;
+ memopts.sharable = 0;
+ memopts.tex = 0;
+ memopts.size = region_size;
+ switch (priv) {
+ case NOT_PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_BOTH_RO;
+ break;
+ case PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_ONLY_PRIV_RO;
+ break;
+ }
+ memopts.subregion_disable = 0;
+ memopts.executable = 1;
+ memopts.enable = 1;
+
+ mpu_configure_region(idx, &memopts);
+}
+
+void configure_ram_region(
+ void* ram_base, region_size_t region_size, privilege_t priv)
+{
+ int idx = find_unused_region_slot();
+
+ memory_region_opts_t memopts = {0};
+ memopts.region = ram_base;
+ memopts.bufferable = 0;
+ memopts.cacheable = 1;
+ memopts.sharable = 0;
+ memopts.tex = 0;
+ memopts.size = region_size;
+ switch (priv) {
+ case NOT_PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_FULL;
+ break;
+ case PRIVILEGED:
+ memopts.perms = ACCESS_PERMS_ONLY_PRIV;
+ break;
+ }
+ memopts.subregion_disable = 0;
+ memopts.executable = 0;
+ memopts.enable = 1;
+
+ mpu_configure_region(idx, &memopts);
+}
diff --git a/src/kern/panic.c b/src/kern/panic.c
index 3e67b90..de1d143 100644
--- a/src/kern/panic.c
+++ b/src/kern/panic.c
@@ -28,7 +28,6 @@ _Noreturn void panic(const char* fmt, ...)
kerr_logf(" (%p) %p\n", &base[i], base[i]);
}
-
set_system_clock_MHz(4); /* reduce power usage while we do nothing. */
for(;;);
} else {
diff --git a/src/kern/priv.c b/src/kern/priv.c
index 085de85..3162639 100644
--- a/src/kern/priv.c
+++ b/src/kern/priv.c
@@ -3,87 +3,6 @@
#include "arch.h"
#include "kern/log.h"
-void handle_svc_call(uint32_t svc_number)
-{
- klogf("Handle SVC: %p\n", svc_number);
- for (;;)
- ;
-}
-
-asm(" .align 2\n"
- " .global on_svc\n"
- " .syntax unified\n"
- " .fpu softvfp\n"
- " .type on_svc, %function\n"
- "on_svc:\n"
- " tst lr,#4\n"
- " ite eq\n"
- " moveq r12,sp\n"
- " mrsne r12,psp\n"
- " ldr r12, [r12, #24]\n"
- " ldrh r12, [r12, #-2]\n"
- " bics r12, r12, #0xff00\n"
- " push {r4, lr}\n"
- " mov r0 , r12\n"
- " bl handle_svc_call\n"
- " pop {r4, lr}\n"
- " tst lr, #4\n"
- " ite eq\n"
- " moveq r12,sp\n"
- " mrsne r12,psp\n"
- " stm r12,{r0-r3}\n"
- " bx lr\n");
-
-// void on_svc() // ISR handler. Override from weak symbol.
-// {
-// asm volatile(
-// "push {r0-r12, lr}\n\t"
-// "ldr r0, [lr, #-4]\n\t"
-// "bic r0, r0, #0xff000000\n\t"
-// );
-
-// TST LR,#4 ; Called from Handler Mode?
-// MRSNE R12,PSP ; Yes, use PSP
-// MOVEQ R12,SP ; No, use MSP
-// LDR R12,[R12,#24] ; Read Saved PC from Stack
-// LDRH R12,[R12,#-2] ; Load Halfword
-// BICS R12,R12,#0xFF00 ; Extract SVC Number
-// uint32_t reg;
-// asm volatile(
-// "mov r12, sp\n\t"
-// "ldr r12, [r12,#24]\n\t"
-// // "ldrh r12,[r12, #-2]\n\t"
-// // "bics r12, r12, #0xff00\n\t"
-// "mov %0, r12\n\t": "=r"(reg));
-
-// uint32_t base[0];
-// uint32_t reg;
-//
-//
-// asm volatile("mov %0, sp\n\t" : "=r"(reg));
-// uint32_t* at = (uint32_t*) (reg + 44); /* Does GCC set up 5 stack frame
-// words? */
-//
-// klogf("Stack pointer: %p\n", reg);
-// klogf("Stack pointer +44: %p\n", (reg + 44));
-// klogf("At_: %p: %p\n\n", 0x80009f6, *(uint32_t*)0x80009f6);
-// klogf("At: %p: %p\n\n", at, *at);
-//
-//
-// int i = 0;
-// for (; i < 20 && &base[i] != (void*)STACK_TOP; ++ i) {
-// kerr_logf(" (%p) %p\n", &base[i], base[i]);
-// }
-//
-// // klogf("TEST %p\n", reg);
-//
-// for(;;);
-
-// register int svc_number asm ("r0");
-
-// klogf("SVC #: %p\n", svc_number);
-// }
-
void set_control_register(uint32_t reg)
{
asm volatile("msr control, %0" : "=r"(reg) :);
@@ -102,3 +21,10 @@ void enter_user_mode()
"mov r0, #1\n\t"
"msr control, r0\n\t");
}
+
+void jump_to_user_mode()
+{
+ asm volatile(
+ "mov r0, #1\n\t"
+ "msr control, r0\n\t");
+}
diff --git a/src/kern/svc.c b/src/kern/svc.c
new file mode 100644
index 0000000..5527364
--- /dev/null
+++ b/src/kern/svc.c
@@ -0,0 +1,51 @@
+#include "arch.h"
+#include "kern/common.h"
+#include "kern/log.h"
+#include "kern/syscall.h"
+
+void handle_svc_call(
+ uint32_t syscall_id, uint32_t syscall_arg, uint32_t svc_number)
+{
+ switch (svc_number) {
+ case 0x04:
+ switch (syscall_id) {
+#define SYSCALL(id, fn, kernfn, argt) \
+ case id: \
+ kernfn((argt)syscall_arg); \
+ break;
+#include "kern/syscall/syscall_tbl.inc"
+#undef SYSCALL
+ }
+ break;
+
+ default:
+ /* An illegal syscall. TODO kill whatever is happening. */
+ break;
+ }
+}
+
+/* The actual handling for the svc call. Overrides the weak
+ * symbol on_svc in irq.h */
+asm(" .align 2\n"
+ " .global on_svc\n"
+ " .syntax unified\n"
+ " .fpu softvfp\n"
+ " .type on_svc, %function\n"
+ "on_svc:\n"
+ " tst lr,#4\n"
+ " ite eq\n"
+ " moveq r12,sp\n"
+ " mrsne r12,psp\n"
+ " ldr r12, [r12, #24]\n"
+ " ldrh r12, [r12, #-2]\n"
+ " bics r12, r12, #0xff00\n"
+ " push {r4, lr}\n"
+ " mov r2 , r12\n"
+ " bl handle_svc_call\n"
+ " pop {r4, lr}\n"
+ " tst lr, #4\n"
+ " ite eq\n"
+ " moveq r12,sp\n"
+ " mrsne r12,psp\n"
+ " stm r12,{r0-r3}\n"
+ " bx lr\n");
diff --git a/src/kern/syscalls/logs.c b/src/kern/syscalls/logs.c
new file mode 100644
index 0000000..855672c
--- /dev/null
+++ b/src/kern/syscalls/logs.c
@@ -0,0 +1,7 @@
+#include "kern/syscall.h"
+#include "kern/log.h"
+
+void kern_logs(const char* str)
+{
+ klogf("[Log] - %s", str);
+}
diff --git a/src/user/syscall.c b/src/user/syscall.c
new file mode 100644
index 0000000..3aa0707
--- /dev/null
+++ b/src/user/syscall.c
@@ -0,0 +1,17 @@
+#include "user/syscall.h"
+
+#include <stdint.h>
+
+void __attribute__ ((noinline)) do_syscall(
+ volatile uint32_t id,
+ volatile uint32_t arg)
+{
+ asm volatile("svc #0x04");
+}
+
+#define SYSCALL(id, fn, kernfn, argt) \
+ void fn(argt arg) \
+{ \
+ do_syscall(id, (uint32_t) arg); \
+}
+#include "kern/syscall/syscall_tbl.inc"