.text
.globl start, halt, got_base
- .extern kernel_stack, glbl_core_data
+ .extern glbl_core_data, exception_vectors
// Used to track phys memory allocator limit globally.
alloc_top .req x11
// Register x1 contains a pointer to the UEFI memory map
//
- //init stack
- ldr x15, =kernel_stack
- mov sp, x15
- add sp, sp, #KERNEL_STACK_SIZE
+ // set exception vectors for EL1 and EL2
+ adrp x15, exception_vectors
+ msr vbar_el1, x15
+ msr vbar_el2, x15
ldr PIC_REGISTER, got_base
/**
* extern "C" void halt(void) __attribute__((noreturn))
*/
-halt:
- b .
+halt: wfi
+ b halt
/**********************************************************************/
.ltorg
#include <kernel.h>
#include <serial.h>
#include <uefi_mmap.h>
+#include <sysreg.h>
+#include <multiboot.h>
-/**
- * \brief Kernel stack.
- *
- * This is the one and only kernel stack for a kernel instance.
+/*
+ * Create kernel page tables (high 256G)
+ * We use GB sections (level 1 entries that point to memory)
*/
-uintptr_t kernel_stack[KERNEL_STACK_SIZE / sizeof(uintptr_t)] __attribute__ ((aligned(16)));
+static void paging_init(void)
+{
+ return;
+}
+static void paging_dump(void)
+{
+ lvaddr_t lvl0 = sysreg_read_ttbr0();
+ lvl0 = lvl0;
+}
+
+bool is_bsp = true;
__attribute__((noreturn))
-void arch_init(void *arg1, EFI_MEMORY_DESCRIPTOR *uefi_mmap);
+void arch_init(void *pointer, EFI_MEMORY_DESCRIPTOR *uefi_mmap);
// Currently
-void arch_init(void *arg1, EFI_MEMORY_DESCRIPTOR *uefi_mmap)
+void arch_init(void *pointer, EFI_MEMORY_DESCRIPTOR *uefi_mmap)
{
- // set console port: UART0 is the one that's connected to the DB9
+ // break to attach gdb here
+ __asm volatile ("wfi":::);
+
+ // set both console ports: UART0 is the one that's connected to the DB9
// connector on the back of the mustang boxes.
serial_console_port = 0;
+ serial_debug_port = 0;
// init serial console, skip hwinit, as the port is guaranteed to be
// initialized by UEFI.
serial_console_init(false);
- // print something
- printf("Barrelfish APM88xxxx CPU driver starting at addr 0x%"
- PRIxLVADDR" on core %"PRIuCOREID" xxxxxxxxxx\n",
- local_phys_to_mem((lpaddr_t)&kernel_first_byte), my_core_id);
+ if (is_bsp) {
+ printf("ACPI root table (RSDP): %p\n", pointer);
+ printf("UEFI memory map pointer: %p\n", uefi_mmap);
- printf("ACPI root table (RSDP): %p\n", arg1);
- printf("UEFI memory map pointer: %p\n", uefi_mmap);
+ printf("First memory map entry:\n");
+ printf(" Type: %x\n", uefi_mmap->Type);
+ printf(" PhysStart: 0x%lx\n", uefi_mmap->PhysicalStart);
+ printf(" VirtStart: 0x%lx\n", uefi_mmap->VirtualStart);
+ printf(" #pages: %lu\n", uefi_mmap->NumberOfPages);
+ printf(" Attrs: %lx\n", uefi_mmap->Attribute);
- uint32_t *mmap_ptr = (uint32_t *)uefi_mmap;
+ struct multiboot_info *mb = pointer;
+ mb = mb;
- printf("Test 1: %p\n", mmap_ptr);
- printf("Test 2: %p\n", mmap_ptr+1);
- printf("Test 3: %p\n", mmap_ptr+2);
- printf("Test 4: %p\n", mmap_ptr+3);
- printf("Test 5: %p\n", mmap_ptr+4);
-#if 0
- for (int i = 0; i < 8; i++) {
- printf("%016lx: 0x%08x\n", (uint64_t)(mmap_ptr+i), mmap_ptr[i]);
+ // TODO: finish BSP core init
+ } else {
+ // TODO: AP core init
}
- printf("First memory map entry:\n");
- printf(" Type: %x\n", uefi_mmap->Type);
- printf(" PhysStart: 0x%lx\n", uefi_mmap->PhysicalStart);
- printf(" VirtStart: 0x%lx\n", uefi_mmap->VirtualStart);
- printf(" #pages: %lu\n", uefi_mmap->NumberOfPages);
- printf(" Attrs: %lx\n", uefi_mmap->Attribute);
-
-#endif
+ // print something
+ printf("Barrelfish APM88xxxx CPU driver starting at addr 0x%"
+ PRIxLVADDR" on core %"PRIuCOREID"\n",
+ local_phys_to_mem((lpaddr_t)&kernel_first_byte), my_core_id);
- *(uint32_t*)0x1c020000 = 'a';
+ paging_dump();
+ paging_init();
while(1) {
- __asm volatile ("nop":::);
+ __asm volatile ("wfi":::);
}
}
#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
-
void paging_context_switch(lpaddr_t ttbr)
{
panic("NYI");
// #ports
#define NUM_PORTS 4
-unsigned serial_console_port, serial_debug_port;
+unsigned serial_console_port = 0;
+unsigned serial_debug_port = 0;
// port base addresses for lookup by port no
static const mackerel_addr_t portbases[NUM_PORTS] =
errval_t serial_init(unsigned port, bool initialize_hw)
{
+ // XXX: remove once we have data section
+ port = 0;
if (port >= NUM_PORTS) {
return SYS_ERR_SERIAL_PORT_INVALID;
}
+ if (ports[port].base == portbases[port]) {
+ return SYS_ERR_OK;
+ }
+
apm88xxxx_pc16550_t *uart = &ports[port];
apm88xxxx_pc16550_initialize(uart, portbases[port]);
*/
void serial_putchar(unsigned port, char c)
{
+ // XXX: remove once we have data section
+ port = 0;
assert(port < NUM_PORTS);
assert(ports[port].base != 0);
// Wait until FIFO can hold more characters
#include <exceptions.h>
// macro for creating table entries that are nicely aligned
-.macro vector_entry label idx
+.macro vector_entry label
// every entry is at 128 byte boundary
.align 7
b \label
.endm
+// macro for getting current exception level (result in arg)
+.macro get_cur_el reg
+ mrs \reg, currentel
+ ubfm \reg, \reg, #2, #3 // extract currentel[3:2]
+.endm
+
// macro for saving exception frame: needs to match with struct layout in C
// code
.macro push_state_to_exn_frame
stp x0, x1, [sp, #-16]!
// save old SP: 48 + 32 * 8
add x1, sp, #288
+ get_cur_el x0
+ cmp x0, #1
+ b.ne push_get_el2_state_\@
// save ELR_EL1
mrs x2, elr_el1
// save SPSR_EL1
mrs x3, spsr_el1
+ b push_el_state_cont_\@
+push_get_el2_state_\@:
+ // save ELR_EL1
+ mrs x2, elr_el2
+ // save SPSR_EL1
+ mrs x3, spsr_el2
+push_el_state_cont_\@:
// store pair of lr and sp just after x29
stp x30, x1, [sp, #240]
// store pair of elr_el1, and spsr_el1 just after sp
// macro for restoring from exception frame: needs to match with struct layout
// in C code
.macro pop_state_from_exn_frame
- // load elr_el1, spsr_el1
+ // load elr, spsr
ldp x21, x22, [sp, #256]
ldp x0, x1, [sp], #16
ldp x2, x3, [sp], #16
ldp x4, x5, [sp], #16
ldp x6, x7, [sp], #16
ldp x8, x9, [sp], #16
+ get_cur_el x10
+ cmp x10, #1
+ b.ne pop_restore_el2_state_\@
// set elr and spsr
msr elr_el1, x21
msr spsr_el1, x22
+ b pop_state_cont_\@
+pop_restore_el2_state_\@:
+ cmp x10, #2
+ b.ne halt
+ // set elr and spsr
+ msr elr_el2, x21
+ msr spsr_el2, x22
+pop_state_cont_\@:
ldp x10, x11, [sp], #16
ldp x12, x13, [sp], #16
ldp x14, x15, [sp], #16
.align 12
exception_vectors:
// current EL with SP_EL0: NYI/unused
- vector_entry invalid_handler 0 // sync
- vector_entry invalid_handler 1 // IRQ/vIRQ
- vector_entry invalid_handler 2 // FIQ/vFIQ
- vector_entry invalid_handler 3 // SError/vSError
+ vector_entry invalid_handler // sync
+ vector_entry invalid_handler // IRQ/vIRQ
+ vector_entry invalid_handler // FIQ/vFIQ
+ vector_entry invalid_handler // SError/vSError
// current EL with SP_ELcur
- vector_entry sync_handler 4 // sync
- vector_entry irq_handler 5 // IRQ/vIRQ
- vector_entry fiq_handler 6 // FIQ/vFIQ
- vector_entry serror_handler 7 // SError/vSError
+ vector_entry sync_handler // sync
+ vector_entry irq_handler // IRQ/vIRQ
+ vector_entry fiq_handler // FIQ/vFIQ
+ vector_entry serror_handler // SError/vSError
- // lower EL running AArch64
- vector_entry invalid_handler 8 // sync
- vector_entry invalid_handler 9 // IRQ/vIRQ
- vector_entry invalid_handler 10 // FIQ/vFIQ
- vector_entry invalid_handler 11 // SError/vSError
+ // lower EL running AArch64: NYI
+ vector_entry invalid_handler // sync
+ vector_entry invalid_handler // IRQ/vIRQ
+ vector_entry invalid_handler // FIQ/vFIQ
+ vector_entry invalid_handler // SError/vSError
// lower EL running AArch32: unsupported
- vector_entry invalid_handler 12 // sync
- vector_entry invalid_handler 13 // IRQ/vIRQ
- vector_entry invalid_handler 14 // FIQ/vFIQ
- vector_entry invalid_handler 15 // SError/vSError
+ vector_entry invalid_handler // sync
+ vector_entry invalid_handler // IRQ/vIRQ
+ vector_entry invalid_handler // FIQ/vFIQ
+ vector_entry invalid_handler // SError/vSError
// we are using unsigned bitfield moves (ubfm, C6-789) to extract fields from
.global invalid_handler
.type invalid_handler @function
invalid_handler:
- mrs x20, elr_el1 // store exception link register to x20
- mrs x21, spsr_el1 // store saved pstate to x21
- mrs x22, esr_el1 // store exception syndrome register to x22
+ mrs x20, elr_el1 // store exception link register to x20
+ mrs x21, spsr_el1 // store saved pstate to x21
+ mrs x22, esr_el1 // store exception syndrome register to x22
+
+ ubfm x23, x22, #ESR_EC_L, #ESR_EC_H
+ ubfm x24, x22, #ESR_ISS_L, #ESR_ISS_H
- ubfm x23, x22, #ESR_EC_L, #ESR_EC_H
- ubfm x24, x22, #ESR_ISS_L, #ESR_ISS_H
+ b halt
- // abort()
-1: wfi
- b 1b
//
// void sync_handler(void)
sync_handler:
push_state_to_exn_frame
- // extract exception details from ESR
+ // get current EL
+ get_cur_el x0
+ cmp x0, #1
+ // != -> check for EL2
+ b.ne sync_handler_check_el2
+ // == -> extract from esr_el
+ // extract exception details from ESR_EL1
mrs x1, esr_el1
+ b sync_handler_common
+sync_handler_check_el2:
+ cmp x0, #2
+ b.ne halt
+ // == -> use el2 registers
+ // extract exception details from ESR_EL1
+ mrs x1, esr_el2
+
+sync_handler_common:
// Exception Class to x2
ubfm x2, x1, #ESR_EC_L, #ESR_EC_H
// Fault to x3
b.eq handle_pf_abort
// otherwise, goto unknown_handler(esr)
b.ne handle_sync_abort
+ b sync_handler_epi
handle_pf_abort:
// goto invalid_handler if fault == 0
cbz x3, invalid_handler
mov x0, sp
bl page_fault
+sync_handler_epi:
pop_state_from_exn_frame
eret
#include <arm_hal.h>
#include <exec.h>
#include <misc.h>
-#include <cp15.h> // for invalidating tlb and cache
+#include <sysreg.h> // for invalidating tlb and cache
//static arch_registers_state_t upcall_state;
+++ /dev/null
-/*
- * Copyright (c) 2009 ETH Zurich.
- * All rights reserved.
- *
- * This file is distributed under the terms in the attached LICENSE file.
- * If you do not find this file, copies can be found by writing to:
- * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
- */
-
-#ifndef __CP15_H__
-#define __CP15_H__
-
-/**
- * \brief Read domain access control register
- */
-static inline uint32_t cp15_read_dacr(void)
-{
- panic("NYI");
-}
-
-/**
- * \brief Read instruction fault status register.
- */
-static inline uint32_t cp15_read_ifsr(void)
-{
- panic("NYI");
-}
-
-/**
- * \brief Read data fault status register.
- */
-static inline uint32_t cp15_read_dfsr(void)
-{
- panic("NYI");
-}
-
-/**
- * \brief Read fault address register.
- */
-static inline uint32_t cp15_read_far(void)
-{
- panic("NYI");
-}
-
-static inline lpaddr_t cp15_read_ttbr0(void)
-{
- panic("NYI");
-}
-
-static inline lpaddr_t cp15_read_ttbr1(void)
-{
- panic("NYI");
-}
-
-static inline void cp15_write_ttbr0(lpaddr_t ttbr)
-{
- panic("NYI");
-}
-
-static inline void cp15_write_ttbr1(lpaddr_t ttbr)
-{
- panic("NYI");
-}
-
-static inline uint32_t cp15_read_ttbcr(void)
-{
- panic("NYI");
-}
-
-static inline void cp15_write_ttbcr(uint32_t ttbcr)
-{
- panic("NYI");
-}
-
-extern void cp15_invalidate_d_cache(void);
-extern void cp15_invalidate_i_and_d_caches(void);
-extern void cp15_invalidate_i_and_d_caches_fast(void);
-extern void cp15_invalidate_tlb_fn(void);
-extern void cp15_enable_mmu(void);
-extern void cp15_enable_alignment(void);
-
-static inline uint32_t cp15_read_cache_status(void){
- panic("NYI");
-}
-
-
-static inline void cp15_disable_cache(void){
-
- cp15_invalidate_i_and_d_caches_fast();
-
- panic("NYI");
-
- printf("WARNING! Caching has been disabled, configuration is: %"PRIx32"\n", cp15_read_cache_status());
-
-}
-
-static inline void cp15_invalidate_tlb(void)
-{
- panic("NYI");
-}
-
-static inline uint8_t cp15_get_cpu_id(void) {
- panic("NYI");
-}
-
-/*
- * Get the configuration base address
- * This is described in the Cortex A9 TRM, 4.2.32
- */
-static inline uint32_t cp15_read_cbar(void)
-{
- panic("NYI");
-}
-
-#endif // __CP15_H__
#include <capabilities.h>
#include <barrelfish_kpi/cpu.h>
#include <barrelfish_kpi/paging_arch.h>
-#include <cp15.h>
+#include <sysreg.h>
/**
* Setup bootstrap page table with direct and relocated mappings for kernel.
static inline void do_one_tlb_flush(genvaddr_t vaddr)
{
// TODO: figure out selective flushing for ARM
- cp15_invalidate_tlb();
+ sysreg_invalidate_tlb();
}
static inline void do_selective_tlb_flush(genvaddr_t vaddr, genvaddr_t vend)
{
// TODO: figure out selective flushing for ARM
- cp15_invalidate_tlb();
+ sysreg_invalidate_tlb();
}
static inline void do_full_tlb_flush(void)
{
- cp15_invalidate_tlb();
+ sysreg_invalidate_tlb();
}
--- /dev/null
+/*
+ * Copyright (c) 2015 ETH Zurich.
+ * All rights reserved.
+ *
+ * This file is distributed under the terms in the attached LICENSE file.
+ * If you do not find this file, copies can be found by writing to:
+ * ETH Zurich D-INFK, Universitaetstr. 6, CH-8092 Zurich. Attn: Systems Group.
+ */
+
+#ifndef __SYSREG_H__
+#define __SYSREG_H__
+
+/**
+ * \brief Read domain access control register
+ */
+static inline uint32_t sysreg_read_dacr(void)
+{
+ panic("NYI");
+}
+
+/**
+ * \brief Read instruction fault status register.
+ */
+static inline uint32_t sysreg_read_ifsr(void)
+{
+ panic("NYI");
+}
+
+/**
+ * \brief Read data fault status register.
+ */
+static inline uint32_t sysreg_read_dfsr(void)
+{
+ panic("NYI");
+}
+
+/**
+ * \brief Read fault address register.
+ */
+static inline uint32_t sysreg_read_far(void)
+{
+ panic("NYI");
+}
+
+static inline uintptr_t get_current_el(void)
+{
+ uintptr_t currentel;
+ __asm volatile ("mrs %[curel], currentel" : [curel] "=r" (currentel));
+ return (currentel >> 2) & 0x3;
+}
+
+static inline lpaddr_t sysreg_read_ttbr0_el1(void)
+{
+ lpaddr_t ttbr0;
+ __asm volatile ("mrs %[ttbr], ttbr0_el1" : [ttbr] "=r" (ttbr0));
+ return ttbr0;
+}
+
+static inline lpaddr_t sysreg_read_ttbr0_el2(void)
+{
+ lpaddr_t ttbr0;
+ __asm volatile ("mrs %[ttbr], ttbr0_el2" : [ttbr] "=r" (ttbr0));
+ return ttbr0;
+}
+
+static inline lpaddr_t sysreg_read_ttbr0(void)
+{
+ uintptr_t currentel = get_current_el();
+ if (currentel == 1) {
+ return sysreg_read_ttbr0_el1();
+ } else if (currentel == 2) {
+ return sysreg_read_ttbr0_el2();
+ }
+ panic("%s: Unsupported EL: %d\n", __FUNCTION__, currentel);
+}
+
+static inline void sysreg_write_ttbr0_el1(lpaddr_t ttbr)
+{
+ __asm volatile ("msr ttbr0_el1, %[ttbr]" : [ttbr] "=r" (ttbr));
+}
+
+static inline void sysreg_write_ttbr0_el2(lpaddr_t ttbr)
+{
+ __asm volatile ("msr ttbr0_el2, %[ttbr]" : [ttbr] "=r" (ttbr));
+}
+
+static inline void sysreg_write_ttbr0(lpaddr_t ttbr)
+{
+ uintptr_t currentel = get_current_el();
+ if (currentel == 1) {
+ sysreg_write_ttbr0_el1(ttbr);
+ } else if (currentel == 2) {
+ sysreg_write_ttbr0_el2(ttbr);
+ }
+ panic("%s: Unsupported EL: %d\n", __FUNCTION__, currentel);
+}
+
+static inline lpaddr_t sysreg_read_ttbr1_el1(void)
+{
+ lpaddr_t ttbr1;
+ __asm volatile ("mrs %[ttbr], ttbr1_el1" : [ttbr] "=r" (ttbr1));
+ return ttbr1;
+}
+
+static inline lpaddr_t sysreg_read_ttbr1_el2(void)
+{
+ lpaddr_t ttbr1;
+ __asm volatile ("mrs %[ttbr], ttbr1_el2" : [ttbr] "=r" (ttbr1));
+ return ttbr1;
+}
+
+static inline lpaddr_t sysreg_read_ttbr1(void)
+{
+ uintptr_t currentel = get_current_el();
+ if (currentel == 1) {
+ return sysreg_read_ttbr1_el1();
+ } else if (currentel == 2) {
+ return sysreg_read_ttbr1_el2();
+ }
+ panic("%s: Unsupported EL: %d\n", __FUNCTION__, currentel);
+}
+
+static inline void sysreg_write_ttbr1_el1(lpaddr_t ttbr)
+{
+ __asm volatile ("msr ttbr1_el1, %[ttbr]" : [ttbr] "=r" (ttbr));
+}
+
+static inline void sysreg_write_ttbr1_el2(lpaddr_t ttbr)
+{
+ __asm volatile ("msr ttbr1_el2, %[ttbr]" : [ttbr] "=r" (ttbr));
+}
+
+static inline lpaddr_t sysreg_write_ttbr1(lpaddr_t ttbr)
+{
+ uintptr_t currentel = get_current_el();
+ if (currentel == 1) {
+ sysreg_write_ttbr1_el1(ttbr);
+ } else if (currentel == 2) {
+ sysreg_write_ttbr1_el2(ttbr);
+ }
+ panic("%s: Unsupported EL: %d\n", __FUNCTION__, currentel);
+}
+
+static inline uint32_t sysreg_read_ttbcr(void)
+{
+ panic("NYI");
+}
+
+static inline void sysreg_write_ttbcr(uint32_t ttbcr)
+{
+ panic("NYI");
+}
+
+static inline uint32_t sysreg_read_cache_status(void){
+ panic("NYI");
+}
+
+
+static inline void sysreg_disable_cache(void){
+
+ panic("NYI");
+
+ printf("WARNING! Caching has been disabled, configuration is: %"PRIx32"\n", sysreg_read_cache_status());
+
+}
+
+static inline void sysreg_invalidate_tlb(void)
+{
+ panic("NYI");
+}
+
+static inline uint8_t sysreg_get_cpu_id(void) {
+ panic("NYI");
+}
+
+/*
+ * Get the configuration base address
+ * This is described in the Cortex A9 TRM, 4.2.32
+ */
+static inline uint32_t sysreg_read_cbar(void)
+{
+ panic("NYI");
+}
+
+#endif // __SYSREG_H__