aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--PL0_test.ld5
-rw-r--r--demo_functionality.c96
-rw-r--r--demo_functionality.h4
-rw-r--r--interrupts.h128
-rw-r--r--kernel.c28
-rw-r--r--memory.h28
6 files changed, 182 insertions, 107 deletions
diff --git a/PL0_test.ld b/PL0_test.ld
index 45bee5e..430e098 100644
--- a/PL0_test.ld
+++ b/PL0_test.ld
@@ -4,11 +4,6 @@ SECTIONS
{
/* 0b10101010101000000000000000000000 */
. = 0xaaa00000;
-
- /* For some reason ld warns when _start is not defined. */
- /* Other .elf files link ok - only PL0_test.elf seems to */
- /* expect _start to be deifned. */
- _start = .;
__start = .;
__text_start = .;
.text :
diff --git a/demo_functionality.c b/demo_functionality.c
index 3375550..691cdb1 100644
--- a/demo_functionality.c
+++ b/demo_functionality.c
@@ -2,7 +2,6 @@
#include "psr.h"
#include "memory.h"
#include "translation_table_descriptors.h"
-#include "libkernel.h"
void demo_paging_support(void)
{
@@ -53,73 +52,35 @@ void demo_current_mode(void)
uart_puts(mode_name);
}
-#define TRANSLATION_TABLE \
- ((short_section_descriptor_t volatile*) TRANSLATION_TABLE_BASE)
-
-extern char
- __renamed_start,
- __renamed_end,
- __renamed_size;
-
-void demo_setup_libkernel(void) {
- short_section_descriptor_t volatile *libkernel_section_entry =
- &TRANSLATION_TABLE[LIBKERNEL_SECTION_NUMBER];
-
- short_section_descriptor_t
- libkernel_section = *libkernel_section_entry;
-
- // make libkernel section executable and read-only for
- // unprivileged code
- libkernel_section.ACCESS_PERMISSIONS_2 =
- AP_2_0_MODEL_RW_PL1_RO_PL0 >> 2;
- libkernel_section.ACCESS_PERMISSIONS_1_0 =
- AP_2_0_MODEL_RW_PL1_RO_PL0 & 0b011;
-
- *libkernel_section_entry = libkernel_section;
-
- // invalidate main Translation Lookup Buffer (just in case)
- asm("mcr p15, 0, %0, c8, c7, 0\n\r"
- "isb" :: "r" (0) : "memory");
-
- // copy libkernel code to libkernel section
- for (size_t i = 0; i < (size_t) &__renamed_size; i++)
- ((volatile char*) LIBKERNEL_SECTION_START)[i] =
- (&__renamed_start)[i];
-}
-
extern char
_binary_PL_0_test_img_start,
_binary_PL_0_test_img_end,
_binary_PL_0_test_img_size;
-void demo_setup_PL0(void)
+void demo_go_unprivileged(void)
{
- short_section_descriptor_t volatile *PL0_section_entry =
- &TRANSLATION_TABLE[PL0_SECTION_NUMBER];
- short_section_descriptor_t volatile *UART_memory_section_entry =
- &TRANSLATION_TABLE[((uint32_t) GPIO_BASE) >> 20];
+ short_section_descriptor_t *translation_table =
+ (short_section_descriptor_t*) TRANSLATION_TABLE_BASE;
- short_section_descriptor_t
- PL0_section = *PL0_section_entry,
- UART_memory_section = *UART_memory_section_entry;
+ volatile short_section_descriptor_t *PL0_section =
+ &translation_table[PL0_SECTION_NUMBER];
+ volatile short_section_descriptor_t *UART_memory_section =
+ &translation_table[((uint32_t) GPIO_BASE) >> 20];
- // set up address of PL0 section
- PL0_section.SECTION_BASE_ADDRESS_31_20 =
+ PL0_section->SECTION_BASE_ADDRESS_31_20 =
UNPRIVILEGED_MEMORY_START >> 20;
// make the selected section and uart section available for PL0
- PL0_section.ACCESS_PERMISSIONS_2 =
+ PL0_section->ACCESS_PERMISSIONS_2 =
AP_2_0_MODEL_RW_ALL >> 2;
- PL0_section.ACCESS_PERMISSIONS_1_0 =
+ PL0_section->ACCESS_PERMISSIONS_1_0 =
AP_2_0_MODEL_RW_ALL & 0b011;
- UART_memory_section.ACCESS_PERMISSIONS_2 =
+ UART_memory_section->ACCESS_PERMISSIONS_2 =
AP_2_0_MODEL_RW_ALL >> 2;
- UART_memory_section.ACCESS_PERMISSIONS_1_0 =
+ UART_memory_section->ACCESS_PERMISSIONS_1_0 =
AP_2_0_MODEL_RW_ALL & 0b011;
-
- *PL0_section_entry = PL0_section;
- *UART_memory_section_entry = UART_memory_section;
+
// invalidate main Translation Lookup Buffer (just in case)
asm("mcr p15, 0, %0, c8, c7, 0\n\r"
@@ -135,32 +96,19 @@ void demo_setup_PL0(void)
uart_puts((char*) VIRTUAL_PL0_MEMORY_START);
- // now paste a userspace program to that section
+ // now paste a userspace program to that section, jump to it and
+ // switch to PL0
for (size_t i = 0; i < (size_t) &_binary_PL_0_test_img_size; i++)
((volatile char*) VIRTUAL_PL0_MEMORY_START)[i] =
(&_binary_PL_0_test_img_start)[i];
- uart_puts("copied PL0 and libkernel code to their sections");
-}
-
-void demo_go_unprivileged(void)
-{
- size_t call_unprivileged_offset =
- (size_t) &call_unprivileged - (size_t) &__renamed_start;
-
- void *call_unprivileged_new_location =
- (void*) (LIBKERNEL_SECTION_START + call_unprivileged_offset);
-
- // call call_unprivileged from libkernel
- asm volatile("mov r5, %0\n\r"
- "mov r0, %1\n\r"
- "mov r4, #0\n\r"
- "movt r4, #"PL0_SECTION_NUMBER_STR"1111\n\r"
- "mov sp, r4\n\r" // setting stack is important :D
- "blx r5\n\r" ::
- "r" (call_unprivileged_new_location),
- "r" (VIRTUAL_PL0_MEMORY_START)
- : "memory", "r4", "r5", "r0");
+ // jump to that copied code (switch to PL0 is done by that code)
+ asm volatile("mov r5, #0\n\r"
+ "movt r5, #"PL0_SECTION_NUMBER_STR"1111\n\r"
+ "mov sp, r5\n\r" // setting stack is important :D
+ "mov r5, #0\n\r"
+ "movt r5, #"PL0_SECTION_NUMBER_STR"0000\n\r"
+ "blx r5\n\r");
}
extern char
diff --git a/demo_functionality.h b/demo_functionality.h
index 12f5807..57fd6f0 100644
--- a/demo_functionality.h
+++ b/demo_functionality.h
@@ -5,10 +5,6 @@ void demo_paging_support(void);
void demo_current_mode(void);
-void demo_setup_libkernel(void);
-
-void demo_setup_PL0(void);
-
void demo_go_unprivileged(void);
void demo_setup_interrupts(void);
diff --git a/interrupts.h b/interrupts.h
new file mode 100644
index 0000000..9f80668
--- /dev/null
+++ b/interrupts.h
@@ -0,0 +1,128 @@
+#ifndef RPI_MMU_EXAMPLE_INTERRUPTS_H
+#define RPI_MMU_EXAMPLE_INTERRUPTS_H
+
+#include <stdint.h>
+
+ //offset of peripherals+ offset for first addresable register for interupt controller
+#define RPI_INTERRUPT_CONTROLLER_BASE ( 0x3F000000UL + 0xB200 )
+
+// Bits in the Enable_Basic_IRQs register to enable various interrupts.
+// According to the BCM2835 ARM Peripherals manual, section 7.5 */
+
+#define RPI_BASIC_ARM_TIMER_IRQ (1 << 0)
+#define RPI_BASIC_ARM_MAILBOX_IRQ (1 << 1)
+#define RPI_BASIC_ARM_DOORBELL_0_IRQ (1 << 2)
+#define RPI_BASIC_ARM_DOORBELL_1_IRQ (1 << 3)
+#define RPI_BASIC_GPU_0_HALTED_IRQ (1 << 4)
+#define RPI_BASIC_GPU_1_HALTED_IRQ (1 << 5)
+#define RPI_BASIC_ACCESS_ERROR_1_IRQ (1 << 6)
+#define RPI_BASIC_ACCESS_ERROR_0_IRQ (1 << 7)
+
+// @brief The interrupt controller memory mapped register set
+typedef struct {
+ volatile uint32_t IRQ_basic_pending;
+ volatile uint32_t IRQ_pending_1;
+ volatile uint32_t IRQ_pending_2;
+ volatile uint32_t FIQ_control;
+ volatile uint32_t Enable_IRQs_1;
+ volatile uint32_t Enable_IRQs_2;
+ volatile uint32_t Enable_Basic_IRQs;
+ volatile uint32_t Disable_IRQs_1;
+ volatile uint32_t Disable_IRQs_2;
+ volatile uint32_t Disable_Basic_IRQs;
+} rpi_irq_controller_t;
+
+extern rpi_irq_controller_t* RPI_GetIrqController(void);
+
+//TIMER
+
+/*--------------------------------------------------------------------------}
+{ LOCAL TIMER INTERRUPT ROUTING REGISTER - QA7_rev3.4.pdf page 18 }
+{--------------------------------------------------------------------------*/
+typedef union
+{
+ struct
+ {
+ enum {
+ LOCALTIMER_TO_CORE0_IRQ = 0,
+ LOCALTIMER_TO_CORE1_IRQ = 1,
+ LOCALTIMER_TO_CORE2_IRQ = 2,
+ LOCALTIMER_TO_CORE3_IRQ = 3,
+ LOCALTIMER_TO_CORE0_FIQ = 4,
+ LOCALTIMER_TO_CORE1_FIQ = 5,
+ LOCALTIMER_TO_CORE2_FIQ = 6,
+ LOCALTIMER_TO_CORE3_FIQ = 7,
+ } Routing: 3; // @0-2 Local Timer routing
+ unsigned unused : 29; // @3-31
+ };
+ uint32_t Raw32; // Union to access all 32 bits as a uint32_t
+} local_timer_int_route_reg_t;
+
+/*--------------------------------------------------------------------------}
+{ LOCAL TIMER CONTROL AND STATUS REGISTER - QA7_rev3.4.pdf page 17 }
+{--------------------------------------------------------------------------*/
+typedef union
+{
+ struct
+ {
+ unsigned ReloadValue : 28; // @0-27 Reload value
+ unsigned TimerEnable : 1; // @28 Timer enable (1 = enabled)
+ unsigned IntEnable : 1; // @29 Interrupt enable (1= enabled)
+ unsigned unused : 1; // @30 Unused
+ unsigned IntPending : 1; // @31 Timer Interrupt flag (Read-Only)
+ };
+ uint32_t Raw32; // Union to access all 32 bits as a uint32_t
+} local_timer_ctrl_status_reg_t;
+
+/*--------------------------------------------------------------------------}
+{ LOCAL TIMER CLEAR AND RELOAD REGISTER - QA7_rev3.4.pdf page 18 }
+{--------------------------------------------------------------------------*/
+typedef union
+{
+ struct
+ {
+ unsigned unused : 30; // @0-29 unused
+ unsigned Reload : 1; // @30 Local timer-reloaded when written as 1
+ unsigned IntClear : 1; // @31 Interrupt flag clear when written as 1
+ };
+ uint32_t Raw32; // Union to access all 32 bits as a uint32_t
+} local_timer_clr_reload_reg_t;
+
+/*--------------------------------------------------------------------------}
+{ GENERIC TIMER INTERRUPT CONTROL REGISTER - QA7_rev3.4.pdf page 13 }
+{--------------------------------------------------------------------------*/
+typedef union
+{
+ struct
+ {
+ unsigned nCNTPSIRQ_IRQ : 1; // @0 Secure physical timer event IRQ enabled, This bit is only valid if bit 4 is clear otherwise it is ignored.
+ unsigned nCNTPNSIRQ_IRQ : 1; // @1 Non-secure physical timer event IRQ enabled, This bit is only valid if bit 5 is clear otherwise it is ignored
+ unsigned nCNTHPIRQ_IRQ : 1; // @2 Hypervisor physical timer event IRQ enabled, This bit is only valid if bit 6 is clear otherwise it is ignored
+ unsigned nCNTVIRQ_IRQ : 1; // @3 Virtual physical timer event IRQ enabled, This bit is only valid if bit 7 is clear otherwise it is ignored
+ unsigned nCNTPSIRQ_FIQ : 1; // @4 Secure physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (0)
+ unsigned nCNTPNSIRQ_FIQ : 1; // @5 Non-secure physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (1)
+ unsigned nCNTHPIRQ_FIQ : 1; // @6 Hypervisor physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (2)
+ unsigned nCNTVIRQ_FIQ : 1; // @7 Virtual physical timer event FIQ enabled, If set, this bit overrides the IRQ bit (3)
+ unsigned reserved : 24; // @8-31 reserved
+ };
+ uint32_t Raw32; // Union to access all 32 bits as a uint32_t
+} generic_timer_int_ctrl_reg_t;
+
+struct __attribute__((__packed__, aligned(4))) QA7Registers {
+ local_timer_int_route_reg_t TimerRouting; // 0x24
+ uint32_t GPIORouting; // 0x28
+ uint32_t AXIOutstandingCounters; // 0x2C
+ uint32_t AXIOutstandingIrq; // 0x30
+ local_timer_ctrl_status_reg_t TimerControlStatus; // 0x34
+ local_timer_clr_reload_reg_t TimerClearReload; // 0x38
+ uint32_t unused; // 0x3C
+ generic_timer_int_ctrl_reg_t Core0TimerIntControl; // 0x40
+ generic_timer_int_ctrl_reg_t Core1TimerIntControl; // 0x44
+ generic_timer_int_ctrl_reg_t Core2TimerIntControl; // 0x48
+ generic_timer_int_ctrl_reg_t Core3TimerIntControl; // 0x4C
+};
+#define QA7 ((volatile __attribute__((aligned(4))) struct QA7Registers*)(uintptr_t)(0x40000040))
+//40000040
+
+int enable_timer(void);
+#endif //RPI_MMU_EXAMPLE_INTERRUPTS_H
diff --git a/kernel.c b/kernel.c
index fc629e1..096cd9a 100644
--- a/kernel.c
+++ b/kernel.c
@@ -1,6 +1,7 @@
#include "uart.h"
#include "demo_functionality.h"
#include "paging.h"
+#include "interrupts.h"
void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
{
@@ -21,6 +22,10 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
// prints some info
demo_paging_support();
+
+
+ // prints some info and switches to system mode
+ demo_mode_to_system();
// prints some info
demo_current_mode();
@@ -30,13 +35,30 @@ void kernel_main(uint32_t r0, uint32_t r1, uint32_t atags)
demo_setup_libkernel();
demo_setup_PL0();
+ enable_timer();
+ // enable interrupts
demo_setup_interrupts();
-
- // prints some info and sets up a section for PL0 code, loads a blob
+
+ *(int *)(0x3000B210) = 1;
+ *(int *)(0x3000B204) = 1;
+
+
+ asm("LDR r0, =0x3F00B200\n\r"
+ "MOV r1, #2\n\r"
+ "STR r1, [r0, #0x00]\n\r");
+
+ *(int *)(0x7E00B210) = 1;
+ *(int *)(0x7E00B214) = 1;
+ *(int *)(0x7E00B218) = 1;
+ uart_putc(*(int*)(0x40000034) );
+ *(int *)(0x40000034) = 1;
+
+
+ // prints some info and sets up a section for PL0 code, loads a blob
// there and jumps to it... never, ever, ever returns
demo_go_unprivileged();
-
+
while(1);
while (1)
diff --git a/memory.h b/memory.h
index 1c9ae35..1472a8b 100644
--- a/memory.h
+++ b/memory.h
@@ -1,17 +1,13 @@
#ifndef MEMORY_H
#define MEMORY_H
-#include "paging.h"
-
-#define SECTION_SIZE (((uint32_t) 1) << 20)
-
#define INTERRUPT_VECTOR_TABLE_START ((uint32_t) 0x0)
#define STACK_START ((uint32_t) 0x4000)
#define STACK_END ((uint32_t) 0x8000)
-extern const char __end;
-extern const char __start;
+extern char __end;
+extern char __start;
#define KERNEL_START ((uint32_t) &__start)
#define KERNEL_END ((uint32_t) &__end)
@@ -24,21 +20,11 @@ extern const char __start;
#define TRANSLATION_TABLE_END \
(TRANSLATION_TABLE_BASE + (uint32_t) (4096 * 4))
-#define LIBKERNEL_SECTION_START \
- (((TRANSLATION_TABLE_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
- + SECTION_SIZE)
-
-#define LIBKERNEL_SECTION_END \
- (LIBKERNEL_SECTION_START + SECTION_SIZE)
+#define PRIVILEGED_MEMORY_END TRANSLATION_TABLE_END
-// section for libkernel is flat-mapped
-#define LIBKERNEL_SECTION_NUMBER (LIBKERNEL_SECTION_START >> 20)
-
-#define PRIVILEGED_MEMORY_END LIBKERNEL_SECTION_END
-
-#define UNPRIVILEGED_MEMORY_START PRIVILEGED_MEMORY_END
-#define UNPRIVILEGED_MEMORY_END \
- (UNPRIVILEGED_MEMORY_START + SECTION_SIZE)
+#define UNPRIVILEGED_MEMORY_START \
+ (((PRIVILEGED_MEMORY_END - (uint32_t) 1) & ~((uint32_t) 0xfffff)) \
+ + (uint32_t) 0x100000)
#define PL0_SECTION_NUMBER ((uint32_t) 0b101010101010)
#define PL0_SECTION_NUMBER_STR "0b101010101010"
@@ -46,4 +32,4 @@ extern const char __start;
#define VIRTUAL_PL0_MEMORY_START (PL0_SECTION_NUMBER << 20)
#endif // MEMORY_H
-
+