aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWojtek Kosior <kwojtus@protonmail.com>2019-12-30 14:36:31 +0100
committerWojtek Kosior <kwojtus@protonmail.com>2019-12-30 14:36:31 +0100
commit26685f5203bc38cfa082b96182a406f4f7e6435a (patch)
tree5566b6812c7cc127da597a08a6824616b2aa5bb5
parentee8668f9fcd952e4952706789bdde7fd223dacb5 (diff)
downloadrpi-MMU-example-26685f5203bc38cfa082b96182a406f4f7e6435a.tar.gz
rpi-MMU-example-26685f5203bc38cfa082b96182a406f4f7e6435a.zip
implement getchar() and putchar() in terms of supervisor call
-rw-r--r--Makefile6
-rw-r--r--PL0_test.c27
-rw-r--r--PL0_utils.c27
-rw-r--r--PL0_utils.h10
-rw-r--r--interrupts.c22
-rw-r--r--svc.S5
-rw-r--r--svc_interface.h11
7 files changed, 88 insertions, 20 deletions
diff --git a/Makefile b/Makefile
index d44fc2b..48bbd14 100644
--- a/Makefile
+++ b/Makefile
@@ -5,6 +5,8 @@ ARM_OBJECTS=kernel.o paging.o demo_functionality.o PL0_test.o uart.o loader_stag
KERNEL_STAGE2_OBJECTS=setup.o interrupt_vector.o interrupts.o uart.o demo_functionality.o paging.o ramfs_embeddable.o ramfs.o
+PL_0_TEST_OBJECTS=PL0_utils.o svc.o PL0_test.o uart.o
+
RAMFS_FILES=PL_0_test.img
all : kernel.img
@@ -21,8 +23,8 @@ all : kernel.img
%_embeddable.o : %.img
arm-none-eabi-objcopy -I binary -O elf32-littlearm -B arm $^ $@
-PL_0_test.elf : PL0_test.ld PL0_test.o uart.o
- arm-none-eabi-gcc -T $< -o $@ $(ELFFLAGS) PL0_test.o uart.o
+PL_0_test.elf : PL0_test.ld $(PL_0_TEST_OBJECTS)
+ arm-none-eabi-gcc -T $< -o $@ $(ELFFLAGS) $(PL_0_TEST_OBJECTS)
kernel_stage1.o : kernel_stage1.S kernel_stage2.img
arm-none-eabi-as -mcpu=cortex-a7 $< -o $@
diff --git a/PL0_test.c b/PL0_test.c
index 2e008a2..f476eb7 100644
--- a/PL0_test.c
+++ b/PL0_test.c
@@ -1,34 +1,29 @@
-#include "uart.h"
-#include "psr.h"
+#include "PL0_utils.h"
// entry point - must remain the only function in the file!
void PL0_main(void)
{
- // If all went correct, Success! gets printed
- uart_puts("Success!\n\r");
-
- uart_puts("calling supervisor\n\r");
-
- asm volatile("svc #0");
-
- uart_puts("back from supervisor call\n\r");
+ // If loading program to userspace and handling of svc are
+ // implemented correctly, this shall get printed
+ puts("Hello userspace!");
- // if we're indeed in PL0, we should crash now, when trying to access
- // memory we're not allowed to
+ // if we're indeed in PL0, we should trigger the abort handler now,
+ // when trying to access memory we're not allowed to
+ puts("Attempting to meddle with kernel memory from userspace :d");
char first_kernel_byte[2];
- first_kernel_byte[0] = *(char*) ((uint32_t) 0x0);
+ first_kernel_byte[0] = *(char*) 0x0;
first_kernel_byte[1] = '\0';
uart_puts(first_kernel_byte);
while (1)
{
- char c = uart_getc();
+ char c = getchar();
- uart_putc(c);
+ putchar(c);
if (c == '\r')
- uart_putc('\n');
+ putchar('\n');
}
}
diff --git a/PL0_utils.c b/PL0_utils.c
new file mode 100644
index 0000000..2cede90
--- /dev/null
+++ b/PL0_utils.c
@@ -0,0 +1,27 @@
+#include <stddef.h>
+#include <stdint.h>
+
+#include "svc_interface.h"
+
+// most generic definition possible
+// the actual function defined in svc.S
+uint32_t svc(enum svc_type, ...);
+
+void putchar(int character)
+{
+ svc(UART_PUTCHAR, character);
+}
+
+int getchar(void)
+{
+ return svc(UART_GETCHAR);
+}
+
+void puts(char *string)
+{
+ for (size_t i = 0; string[i]; i++)
+ putchar(string[i]);
+
+ putchar('\n');
+ putchar('\r');
+}
diff --git a/PL0_utils.h b/PL0_utils.h
new file mode 100644
index 0000000..ba72fd3
--- /dev/null
+++ b/PL0_utils.h
@@ -0,0 +1,10 @@
+#ifndef PL0_UTILS_H
+#define PL0_UTILS_H
+
+void putchar(int character);
+
+int getchar(void);
+
+void puts(char *string);
+
+#endif // PL0_UTILS_H
diff --git a/interrupts.c b/interrupts.c
index 7932d23..f47bc1d 100644
--- a/interrupts.c
+++ b/interrupts.c
@@ -1,4 +1,5 @@
#include "uart.h"
+#include "svc_interface.h"
void setup(void);
@@ -24,9 +25,26 @@ void undefined_instruction_vector(void)
}
}
-void supervisor_call_handler(void)
+uint32_t supervisor_call_handler(enum svc_type request, uint32_t arg1,
+ uint32_t arg2, uint32_t arg3)
{
- uart_puts("something svc happened\n\r");
+ (void) arg2; (void) arg3; // unused for now
+
+ switch(request) {
+ case UART_PUTCHAR:
+ uart_putc(arg1);
+ break;
+ case UART_GETCHAR:
+ return uart_getc();
+ case UART_WRITE:
+ uart_puts("UART_WRITE not implemented!!!!!\n\r");
+ break;
+ default:
+ // perhaps we should kill the process now?
+ uart_puts("unknown supervisor call type!!!!!\n\r");
+ }
+
+ return 0; // a dummy value
}
void abort_handler(void)
diff --git a/svc.S b/svc.S
new file mode 100644
index 0000000..65200d8
--- /dev/null
+++ b/svc.S
@@ -0,0 +1,5 @@
+.global svc
+
+svc:
+ svc #0
+ mov pc, lr
diff --git a/svc_interface.h b/svc_interface.h
new file mode 100644
index 0000000..aa478ce
--- /dev/null
+++ b/svc_interface.h
@@ -0,0 +1,11 @@
+#ifndef SVC_INTERFACE_H
+#define SVC_INTERFACE_H
+
+enum svc_type
+ {
+ UART_PUTCHAR,
+ UART_GETCHAR,
+ UART_WRITE
+ };
+
+#endif // SVC_INTERFACE_H