From 0a6ca65e3f8a113c182c7df0a05889b123ba67a2 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Fri, 24 Sep 2021 16:14:01 -0700 Subject: [PATCH] MMU works --- cortex-a.py | 157 ++++++++++++++++++ hw/mcu/broadcom/bcm2711/io.c | 2 + hw/mcu/broadcom/bcm2711/mmu.c | 12 +- hw/mcu/broadcom/bcm2711/mmu.h | 5 +- src/portable/broadcom/synopsys/dcd_synopsys.c | 8 +- 5 files changed, 177 insertions(+), 7 deletions(-) create mode 100644 cortex-a.py diff --git a/cortex-a.py b/cortex-a.py new file mode 100644 index 00000000..9de16bae --- /dev/null +++ b/cortex-a.py @@ -0,0 +1,157 @@ +class Armv8AException(gdb.Command): + def __init__ (self): + super (Armv8AException, self).__init__ ("armv8a-exception", gdb.COMMAND_USER) + + def print_data_abort(self, frame, iss): + isv = (iss >> 23) & 0x1 + sas = (iss >> 21) & 0x3 + sse = (iss >> 20) & 0x1 + srt = (iss >> 15) & 0x1f + sf = (iss >> 14) & 0x1 + ar = (iss >> 13) & 0x1 + vncr = (iss >> 12) & 0x1 + _set = (iss >> 10) & 0x3 + fnv = (iss >> 9) & 0x1 + ea = (iss >> 8) & 0x1 + cm = (iss >> 7) & 0x1 + s1ptw = (iss >> 6) & 0x1 + wnr = (iss >> 5) & 0x1 + dfsc = iss & 0x1f + if isv: + # print("isv valid", sas, sse, srt, sf, ar) + access_sizes = ("Byte", "Halfword", "Word", "Doubleword") + print("Access size:", access_sizes[sas]) + print("Sign extended:", "Yes" if sse else "No") + print("Register:", hex(srt), "64-bit" if sf else "32-bit") + print("Acquire/Release:", "Yes" if ar else "No") + if dfsc == 0b010000: + print("Not on translation table walk") + if not fnv: + value = int(frame.read_register("FAR_EL2")) + print("FAR", hex(value)) + elif dfsc == 0b000101: + print("translation fault level 1") + elif dfsc == 0b010001: + print("tag check fault") + elif dfsc == 0b100001: + print("alignment fault") + else: + print(bin(dfsc)) + print(vncr, _set, fnv, ea, cm, s1ptw, wnr, dfsc) + + def print_instruction_abort(self, frame, iss): + _set = (iss >> 10) & 0x3 + fnv = (iss >> 9) & 0x1 + ea = (iss >> 8) & 0x1 + s1ptw = (iss >> 6) & 0x1 + ifsc = iss & 0x1f + if ifsc == 0b010000: + print("Not on translation table walk") + if not fnv: + value = int(frame.read_register("FAR_EL2")) + print("FAR", hex(value)) + elif ifsc == 0b00101: + print("translation fault level 1") + elif ifsc == 0b01001: + print("access flag fault level 1") + # elif dfsc == 0b100001: + # print("alignment fault") + else: + print(bin(ifsc)) + + def invoke (self, arg, from_tty): + frame = gdb.selected_frame() + value = int(frame.read_register("ESR_EL2")) + if value == 0: + return None + iss2 = (value >> 32) & 0x1ff + ec = (value >> 26) & 0x3ff + il = (value >> 25) & 0x1 + iss = value & 0xffffff + if ec == 0b000000: + print("Unknown fault") + elif ec == 0b000001: + print("Trapped WF*") + elif ec == 0b000011: + print("Trapped MCR or MRC") + elif ec == 0b000100: + print("Trapped MCRR or MRRC") + elif ec == 0b000101: + print("Trapped MCR or MRC") + elif ec == 0b000110: + print("Trapped LDC or STC") + elif ec == 0b000111: + print("Trapped SIMD") + elif ec == 0b001000: + print("Trapped VMRS") + elif ec == 0b001001: + print("Trapped pointer authentication") + elif ec == 0b001010: + print("Trapped LD64B or ST64B*") + elif ec == 0b001100: + print("Trapped MRRC") + elif ec == 0b001101: + print("Branch target exception") + elif ec == 0b001110: + print("Illegal execution state") + elif ec == 0b010001: + print("SVC instruction") + elif ec == 0b010010: + print("HVC instruction") + elif ec == 0b010011: + print("SMC instruction") + elif ec == 0b010101: + print("SVC instruction") + elif ec == 0b010110: + print("HVC instruction") + elif ec == 0b010111: + print("SMC instruction") + elif ec == 0b011000: + print("Trapped MRS, MRS or system instruction") + elif ec == 0b011001: + print("Trapped SVE") + elif ec == 0b011010: + print("Trapped ERET") + elif ec == 0b011100: + print("Failed pointer authentication") + elif ec == 0b100000: + print("Instruction abort from lower level") + elif ec == 0b100001: + print("Instruction abort from same level") + self.print_instruction_abort(frame, iss) + elif ec == 0b100010: + print("PC alignment failure") + elif ec == 0b100100: + print("Data abort from lower level") + elif ec == 0b100101: + print("Data abort from same level") + self.print_data_abort(frame, iss) + elif ec == 0b100110: + print("SP alignment fault") + elif ec == 0b101000: + print("32-bit floating point exception") + elif ec == 0b101100: + print("64-bit floating point exception") + elif ec == 0b101111: + print("SError interrupt") + elif ec == 0b110000: + print("Breakpoint from lower level") + elif ec == 0b110001: + print("Breakpoint from same level") + elif ec == 0b110010: + print("Software step from lower level") + elif ec == 0b110011: + print("Software step from same level") + elif ec == 0b110100: + print ("Watch point from same level") + elif ec == 0b110101: + print("Watch point from lower level") + elif ec == 0b111000: + print("Breakpoint in aarch32 mode") + elif ec == 0b111010: + print("Vector catch in aarch32") + elif ec == 0b111100: + print("Brk instruction in aarch64") + print(hex(int(value)), iss2, bin(ec), il, iss) + +Armv8AException() diff --git a/hw/mcu/broadcom/bcm2711/io.c b/hw/mcu/broadcom/bcm2711/io.c index 213d6f2f..8ccfdc69 100644 --- a/hw/mcu/broadcom/bcm2711/io.c +++ b/hw/mcu/broadcom/bcm2711/io.c @@ -3,6 +3,8 @@ // GPIO +// Pi 4 base address: 0xFE000000 +// Pi 3 base address: 0x3F000000 enum { PERIPHERAL_BASE = 0xFE000000, GPFSEL0 = PERIPHERAL_BASE + 0x200000, diff --git a/hw/mcu/broadcom/bcm2711/mmu.c b/hw/mcu/broadcom/bcm2711/mmu.c index 3c20436e..e5ae236b 100644 --- a/hw/mcu/broadcom/bcm2711/mmu.c +++ b/hw/mcu/broadcom/bcm2711/mmu.c @@ -5,7 +5,7 @@ #include "mmu.h" // Each entry is a gig. -volatile uint64_t level_1_table[32] __attribute__((aligned(4096))); +volatile uint64_t level_1_table[512] __attribute__((aligned(4096))); // Third gig has peripherals uint64_t level_2_0x0_c000_0000_to_0x1_0000_0000[512] __attribute__((aligned(4096))); @@ -14,9 +14,10 @@ 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_ACCESS_FLAG | MM_DESCRIPTOR_BLOCK | MM_DESCRIPTOR_VALID; - level_1_table[2] = ((uint64_t) level_2_0x0_c000_0000_to_0x1_0000_0000) | + level_1_table[3] = ((uint64_t) level_2_0x0_c000_0000_to_0x1_0000_0000) | MM_DESCRIPTOR_TABLE | MM_DESCRIPTOR_VALID; // Set peripherals to register access. @@ -24,6 +25,7 @@ void setup_mmu_flat_map(void) { 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_ACCESS_FLAG | MM_DESCRIPTOR_BLOCK | MM_DESCRIPTOR_VALID; } @@ -47,12 +49,14 @@ void setup_mmu_flat_map(void) { // 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" + "ISB\n\t" + // "AT S1EL2R %[ttbr0]" : /* No outputs. */ : [mair] "r" (mair), [tcr] "r" (tcr), [ttbr0] "r" (ttbr0), [sctlr] "r" (sctlr) ); - while (true) {} + //__asm__ ("brk #123"); + //while (true) {} } diff --git a/hw/mcu/broadcom/bcm2711/mmu.h b/hw/mcu/broadcom/bcm2711/mmu.h index 9f0a7db4..1fe081f3 100644 --- a/hw/mcu/broadcom/bcm2711/mmu.h +++ b/hw/mcu/broadcom/bcm2711/mmu.h @@ -13,11 +13,11 @@ #define MT_DEVICE_nGnRnE 0x0 #define MT_NORMAL_NC 0x1 #define MT_DEVICE_nGnRnE_FLAGS 0x00 -#define MT_NORMAL_NC_FLAGS 0x44 +#define MT_NORMAL_NC_FLAGS 0xff #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_T0SZ (64 - 36) #define TCR_PS (0x01 << 16) // 36-bit physical address #define TCR_TG0_4K (0 << 14) #define TCR_SH0_OUTER_SHAREABLE (0x2 << 12) @@ -36,6 +36,7 @@ // Block attributes #define MM_DESCRIPTOR_EXECUTE_NEVER (0x1ull << 54) #define MM_DESCRIPTOR_CONTIGUOUS (0x1ull << 52) +#define MM_DESCRIPTOR_ACCESS_FLAG (0x1ull << 10) #define MM_DESCRIPTOR_MAIR_INDEX(index) (index << 2) diff --git a/src/portable/broadcom/synopsys/dcd_synopsys.c b/src/portable/broadcom/synopsys/dcd_synopsys.c index 5967565a..aecae503 100644 --- a/src/portable/broadcom/synopsys/dcd_synopsys.c +++ b/src/portable/broadcom/synopsys/dcd_synopsys.c @@ -114,7 +114,7 @@ // MACRO TYPEDEF CONSTANT ENUM //--------------------------------------------------------------------+ -#define RHPORT_REGS_BASE 0x7e980000 +#define RHPORT_REGS_BASE 0xfe980000 #define GLOBAL_BASE(_port) ((USB_OTG_GlobalTypeDef*) RHPORT_REGS_BASE) #define DEVICE_BASE(_port) (USB_OTG_DeviceTypeDef *) (RHPORT_REGS_BASE + USB_OTG_DEVICE_BASE) @@ -438,6 +438,7 @@ void dcd_init (uint8_t rhport) { // Programming model begins in the last section of the chapter on the USB // peripheral in each Reference Manual. + TU_LOG(2, " dcd_init"); USB_OTG_GlobalTypeDef * usb_otg = GLOBAL_BASE(rhport); @@ -477,9 +478,14 @@ void dcd_init (uint8_t rhport) // Reset core after selecting PHY // Wait AHB IDLE, reset then wait until it is cleared while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_AHBIDL) == 0U) {} + + TU_LOG(2, " resetting"); usb_otg->GRSTCTL |= USB_OTG_GRSTCTL_CSRST; + TU_LOG(2, " waiting"); while ((usb_otg->GRSTCTL & USB_OTG_GRSTCTL_CSRST) == USB_OTG_GRSTCTL_CSRST) {} + TU_LOG(2, " reset done"); + // Restart PHY clock *((volatile uint32_t *)(RHPORT_REGS_BASE + USB_OTG_PCGCCTL_BASE)) = 0;