From 829f92d00f05167f788375a2a4e0ff5342bb30f7 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Wed, 22 Sep 2021 15:19:02 -0700 Subject: [PATCH] Trying to setup the mmu --- hw/bsp/raspberrypi4/family.c | 24 +++++++------- hw/bsp/raspberrypi4/family.mk | 3 +- hw/mcu/broadcom/bcm2711/boot.s | 4 ++- hw/mcu/broadcom/bcm2711/link.ld | 16 ++++++--- hw/mcu/broadcom/bcm2711/mmu.c | 58 +++++++++++++++++++++++++++++++++ hw/mcu/broadcom/bcm2711/mmu.h | 44 +++++++++++++++++++++++++ 6 files changed, 132 insertions(+), 17 deletions(-) create mode 100644 hw/mcu/broadcom/bcm2711/mmu.c create mode 100644 hw/mcu/broadcom/bcm2711/mmu.h diff --git a/hw/bsp/raspberrypi4/family.c b/hw/bsp/raspberrypi4/family.c index b2665f42..6266d5a3 100644 --- a/hw/bsp/raspberrypi4/family.c +++ b/hw/bsp/raspberrypi4/family.c @@ -28,6 +28,7 @@ #include "board.h" #include "io.h" +#include "mmu.h" //--------------------------------------------------------------------+ // Forward USB interrupt events to TinyUSB IRQ Handler @@ -55,6 +56,7 @@ void board_init(void) gpio_initOutputPinWithPullNone(18); gpio_setPinOutputBool(18, true); gpio_initOutputPinWithPullNone(42); + setup_mmu_flat_map(); // gpio_initOutputPinWithPullNone(23); // gpio_initOutputPinWithPullNone(24); // gpio_initOutputPinWithPullNone(25); @@ -83,17 +85,17 @@ void board_init(void) // gpio_setPinOutputBool(25, true); print(); // gpio_setPinOutputBool(25, false); - while (true) { - // for (size_t i = 0; i < 5; i++) { - for (size_t j = 0; j < 10000000000; j++) { - __asm__("nop"); - } - gpio_setPinOutputBool(42, true); - for (size_t j = 0; j < 10000000000; j++) { - __asm__("nop"); - } - gpio_setPinOutputBool(42, false); - } + // while (true) { + // // for (size_t i = 0; i < 5; i++) { + // for (size_t j = 0; j < 10000000000; j++) { + // __asm__("nop"); + // } + // gpio_setPinOutputBool(42, true); + // for (size_t j = 0; j < 10000000000; j++) { + // __asm__("nop"); + // } + // gpio_setPinOutputBool(42, false); + // } // while (1) uart_update(); } diff --git a/hw/bsp/raspberrypi4/family.mk b/hw/bsp/raspberrypi4/family.mk index 2d5c78d2..1547beee 100644 --- a/hw/bsp/raspberrypi4/family.mk +++ b/hw/bsp/raspberrypi4/family.mk @@ -18,8 +18,9 @@ CFLAGS += \ SRC_C += \ src/portable/broadcom/synopsys/dcd_synopsys.c \ + $(MCU_DIR)/interrupts.c \ $(MCU_DIR)/io.c \ - $(MCU_DIR)/interrupts.c + $(MCU_DIR)/mmu.c CROSS_COMPILE = aarch64-none-elf- diff --git a/hw/mcu/broadcom/bcm2711/boot.s b/hw/mcu/broadcom/bcm2711/boot.s index 076b3a76..dcc58892 100644 --- a/hw/mcu/broadcom/bcm2711/boot.s +++ b/hw/mcu/broadcom/bcm2711/boot.s @@ -19,7 +19,7 @@ _start: adr x0, vectors // load VBAR_EL1 with virtual // msr vbar_el3, x0 // vector table address msr vbar_el1, x0 // vector table address - // msr vbar_el2, x0 // vector table address + msr vbar_el2, x0 // vector table address isb // Clean the BSS section @@ -45,6 +45,8 @@ irq_entry mov x0, #\type mrs x1, esr_el1 mrs x2, elr_el1 +mrs x3, esr_el2 +mrs x4, elr_el2 b err_hang .endm diff --git a/hw/mcu/broadcom/bcm2711/link.ld b/hw/mcu/broadcom/bcm2711/link.ld index 0d5ebe2a..43c4e722 100644 --- a/hw/mcu/broadcom/bcm2711/link.ld +++ b/hw/mcu/broadcom/bcm2711/link.ld @@ -1,12 +1,20 @@ SECTIONS { . = 0x80000; /* Kernel load address for AArch64 */ - .text : { KEEP(*(.text.boot)) *(.text .text.* .gnu.linkonce.t*) } - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r*) } + .text : { + KEEP(*(.text.boot)) + *(.text .text.* .gnu.linkonce.t*) + } + .rodata : { + . = ALIGN(4096); + *(.rodata .rodata.* .gnu.linkonce.r*) + } PROVIDE(_data = .); - .data : { *(.data .data.* .gnu.linkonce.d*) } + .data : { + . = ALIGN(4096); + *(.data .data.* .gnu.linkonce.d*) + } .bss (NOLOAD) : { - . = ALIGN(16); __bss_start = .; *(.bss .bss.*) *(COMMON) diff --git a/hw/mcu/broadcom/bcm2711/mmu.c b/hw/mcu/broadcom/bcm2711/mmu.c new file mode 100644 index 00000000..3c20436e --- /dev/null +++ b/hw/mcu/broadcom/bcm2711/mmu.c @@ -0,0 +1,58 @@ +#include +#include + + +#include "mmu.h" + +// Each entry is a gig. +volatile uint64_t level_1_table[32] __attribute__((aligned(4096))); + +// Third gig has peripherals +uint64_t level_2_0x0_c000_0000_to_0x1_0000_0000[512] __attribute__((aligned(4096))); + +void setup_mmu_flat_map(void) { + // Set the first gig to regular access. + level_1_table[0] = 0x0000000000000000 | + MM_DESCRIPTOR_MAIR_INDEX(MT_NORMAL_NC) | + MM_DESCRIPTOR_BLOCK | + MM_DESCRIPTOR_VALID; + level_1_table[2] = ((uint64_t) level_2_0x0_c000_0000_to_0x1_0000_0000) | + MM_DESCRIPTOR_TABLE | + MM_DESCRIPTOR_VALID; + // Set peripherals to register access. + for (uint64_t i = 480; i < 512; i++) { + level_2_0x0_c000_0000_to_0x1_0000_0000[i] = (0x00000000c0000000 + (i << 21)) | + MM_DESCRIPTOR_EXECUTE_NEVER | + MM_DESCRIPTOR_MAIR_INDEX(MT_DEVICE_nGnRnE) | + MM_DESCRIPTOR_BLOCK | + MM_DESCRIPTOR_VALID; + } + uint64_t mair = MAIR_VALUE; + uint64_t tcr = TCR_VALUE; + uint64_t ttbr0 = ((uint64_t) level_1_table) | MM_TTBR_CNP; + uint64_t sctlr = 0; + __asm__ volatile ( + // Set MAIR + "MSR MAIR_EL2, %[mair]\n\t" + // Set TTBR0 + "MSR TTBR0_EL2, %[ttbr0]\n\t" + // Set TCR + "MSR TCR_EL2, %[tcr]\n\t" + // The ISB forces these changes to be seen before the MMU is enabled. + "ISB\n\t" + // Read System Control Register configuration data + "MRS %[sctlr], SCTLR_EL2\n\t" + // Write System Control Register configuration data + "ORR %[sctlr], %[sctlr], #1\n\t" + // Set [M] bit and enable the MMU. + "MSR SCTLR_EL2, %[sctlr]\n\t" + // The ISB forces these changes to be seen by the next instruction + "ISB" + : /* No outputs. */ + : [mair] "r" (mair), + [tcr] "r" (tcr), + [ttbr0] "r" (ttbr0), + [sctlr] "r" (sctlr) + ); + while (true) {} +} diff --git a/hw/mcu/broadcom/bcm2711/mmu.h b/hw/mcu/broadcom/bcm2711/mmu.h new file mode 100644 index 00000000..9f0a7db4 --- /dev/null +++ b/hw/mcu/broadcom/bcm2711/mmu.h @@ -0,0 +1,44 @@ +#pragma once + + +// From: https://github.com/s-matyukevich/raspberry-pi-os/blob/master/docs/lesson06/rpi-os.md +/* + * Memory region attributes: + * + * n = AttrIndx[2:0] + * n MAIR + * DEVICE_nGnRnE 000 00000000 + * NORMAL_NC 001 01000100 + */ +#define MT_DEVICE_nGnRnE 0x0 +#define MT_NORMAL_NC 0x1 +#define MT_DEVICE_nGnRnE_FLAGS 0x00 +#define MT_NORMAL_NC_FLAGS 0x44 +#define MAIR_VALUE (MT_DEVICE_nGnRnE_FLAGS << (8 * MT_DEVICE_nGnRnE)) | (MT_NORMAL_NC_FLAGS << (8 * MT_NORMAL_NC)) + + +#define TCR_T0SZ (64 - 35) +#define TCR_PS (0x01 << 16) // 36-bit physical address +#define TCR_TG0_4K (0 << 14) +#define TCR_SH0_OUTER_SHAREABLE (0x2 << 12) +#define TCR_VALUE (TCR_T0SZ | TCR_PS | TCR_TG0_4K | TCR_SH0_OUTER_SHAREABLE) + +#define ENTRY_TYPE_TABLE_DESCRIPTOR 0x11 +#define ENTRY_TYPE_BLOCK_ENTRY 0x01 +#define ENTRY_TYPE_TABLE_ENTRY 0x11 +#define ENTRY_TYPE_INVALID 0x00 + +#define MM_DESCRIPTOR_VALID (0x1) + +#define MM_DESCRIPTOR_BLOCK (0x0 << 1) +#define MM_DESCRIPTOR_TABLE (0x1 << 1) + +// Block attributes +#define MM_DESCRIPTOR_EXECUTE_NEVER (0x1ull << 54) +#define MM_DESCRIPTOR_CONTIGUOUS (0x1ull << 52) + +#define MM_DESCRIPTOR_MAIR_INDEX(index) (index << 2) + +#define MM_TTBR_CNP (0x1) + +void setup_mmu_flat_map(void);