diff --git a/exosphere/mmu.h b/exosphere/mmu.h index a52991e60..602f447ef 100644 --- a/exosphere/mmu.h +++ b/exosphere/mmu.h @@ -67,7 +67,23 @@ #define MMU_PTE_BLOCK_NG BIT(11) #define MMU_PTE_BLOCK_PXN BITL(53) #define MMU_PTE_BLOCK_UXN BITL(54) -#define MMU_PTE_BLOCK_UXN MMU_PTE_BLOCK_UXN +#define MMU_PTE_BLOCK_XN MMU_PTE_BLOCK_UXN + +/* + * AP[2:1] + */ +#define MMU_AP_PRIV_RW (0 << 6) +#define MMU_AP_RW (1 << 6) +#define MMU_AP_PRIV_RO (2 << 6) +#define MMU_AP_RO (3 << 6) + +/* + * S2AP[2:1] (for stage2 translations; secmon doesn't use it) + */ +#define MMU_S2AP_NONE (0 << 6) +#define MMU_S2AP_RO (1 << 6) +#define MMU_S2AP_WO (2 << 6) +#define MMU_S2AP_RW (3 << 6) /* * AttrIndx[2:0] @@ -101,8 +117,8 @@ #define TCR_EL2_RSVD (BIT(31) | BIT(23)) #define TCR_EL3_RSVD (BIT(31) | BIT(23)) -static inline void mmu_init_table(unsigned int level, uintptr_t *tbl) { - for(size_t i = 0; i < MMU_Lx_MASK(level); i++) { +static inline void mmu_init_table(uintptr_t *tbl, size_t num_entries) { + for(size_t i = 0; i < num_entries; i++) { tbl[i] = MMU_PTE_TYPE_FAULT; } } @@ -120,8 +136,8 @@ static inline void mmu_map_table(unsigned int level, uintptr_t *tbl, uintptr_t b tbl[mmu_compute_index(level, base_addr)] = (uintptr_t)next_lvl_tbl_pa | attrs | MMU_PTE_TYPE_TABLE; } -static inline void mmu_map_block_l012(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, uint64_t attrs) { - tbl[mmu_compute_index(level, base_addr)] = phys_addr | attrs | MMU_PTE_TYPE_BLOCK; +static inline void mmu_map_block(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, uint64_t attrs) { + tbl[mmu_compute_index(level, base_addr)] = phys_addr | attrs | MMU_PTE_BLOCK_AF | MMU_PTE_TYPE_BLOCK; } static inline void mmu_map_page(uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, uint64_t attrs) { @@ -132,10 +148,10 @@ static inline void mmu_unmap(unsigned int level, uintptr_t *tbl, uintptr_t base_ tbl[mmu_compute_index(level, base_addr)] = MMU_PTE_TYPE_FAULT; } -static inline void mmu_map_block_range_l012(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, size_t size, uint64_t attrs) { +static inline void mmu_map_block_range(unsigned int level, uintptr_t *tbl, uintptr_t base_addr, uintptr_t phys_addr, size_t size, uint64_t attrs) { size = (size >> MMU_Lx_SHIFT(level)) << MMU_Lx_SHIFT(level); for(size_t offset = 0; offset < size; offset += MMU_Lx_SHIFT(level)) { - mmu_map_block_l012(level, tbl, base_addr + offset, phys_addr + offset, attrs); + mmu_map_block(level, tbl, base_addr + offset, phys_addr + offset, attrs); } } @@ -153,4 +169,92 @@ static inline void mmu_unmap_range(unsigned int level, uintptr_t *tbl, uintptr_t } } +/* Switch specific stuff */ + +static const struct { + uintptr_t pa; + size_t size; + bool is_secure; +} devices[] = +{ + { 0x50041000, 0x1000, true }, /* ARM Interrupt Distributor */ + { 0x50042000, 0x2000, true }, /* Interrupt Controller Physical CPU interface */ + { 0x70006000, 0x1000, false }, /* UART-A */ + { 0x60006000, 0x1000, false }, /* Clock and Reset */ + { 0x7000E000, 0x1000, true }, /* RTC, PMC */ + { 0x60005000, 0x1000, true }, /* TMRs, WDTs */ + { 0x6000C000, 0x1000, true }, /* System Registers */ + { 0x70012000, 0x2000, true }, /* SE */ + { 0x700F0000, 0x1000, true }, /* SYSCTR0 */ + { 0x70019000, 0x1000, true }, /* MC */ + { 0x7000F000, 0x1000, true }, /* FUSE (0x7000F800) */ + { 0x70000000, 0x4000, true }, /* MISC */ + { 0x60007000, 0x1000, true }, /* Flow Controller */ + { 0x40002000, 0x1000, true }, /* iRAM-A */ + { 0x7000D000, 0x1000, true }, /* I2C-5,6 - SPI 2B-1 to 4 */ + { 0x6000D000, 0x1000, true }, /* GPIO-1 - GPIO-8 */ + { 0x7000C000, 0x1000, true }, /* I2C-I2C4 */ + { 0x6000F000, 0x1000, true }, /* Exception vectors */ +}; + +#define MMIO_DEVID_GICD 0 +#define MMIO_DEVID_ICC 1 +#define MMIO_DEVID_UART_A 2 +#define MMIO_DEVID_CLKRST 3 +#define MMIO_DEVID_RTC_PMC 4 +#define MMIO_DEVID_TMRs_WDTs 5 +#define MMIO_DEVID_SYSREGS 6 +#define MMIO_DEVID_SE 7 +#define MMIO_DEVID_SYSCTR0 8 +#define MMIO_DEVID_MC 9 +#define MMIO_DEVID_FUSE 10 +#define MMIO_DEVID_MISC 11 +#define MMIO_DEVID_FLOWCTRL 12 +#define MMIO_DEVID_NXBOOTLOADER_MAILBOX 13 +#define MMIO_DEVID_I2C56_SPI2B 14 +#define MMIO_DEVID_GPIO 15 +#define MMIO_DEVID_DTV_I2C234 16 +#define MMIO_DEVID_EXCEPTION_VECTORS 17 + +#ifndef MMIO_USE_IDENTIY_MAPPING +#define MMIO_BASE 0x1F0080000ull + +static inline uintptr_t mmio_get_device_address(unsigned int device_id) { + size_t offset = 0; + for(unsigned int i = 0; i < devid; i++) { + offset += devices[i].size; + offset += 0x1000; /* guard page */ + } + + return MMIO_BASE + offset; +} + +#else +static inline uintptr_t mmio_get_device_address(unsigned int devid) { + return devices[devid]; +} +#endif + +static inline void mmio_map_all_devices(uintptr_t *mmu_l3_tbl) { + static const uint64_t secure_device_attributes = MMU_PTE_BLOCK_XN | MMU_PTE_BLOCK_INNER_SHAREBLE | MMU_PTE_BLOCK_MEMTYPE(1); + static const uint64_t device_attributes = MMU_PTE_TABLE_NS | secure_device_attributes; + + for(size_t i = 0, offset = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { + uint64_t attributes = devices[i].is_secure ? secure_device_attributes : device_attributes; + mmu_map_page_range(mmu_l3_tbl, MMIO_BASE + offset, devices[i].pa, devices[i].size, attributes); + + offset += devices[i].size; + offset += 0x1000; /* insert guard page */ + } +} + +static inline void mmio_unmap_all_devices(uintptr_t *mmu_l3_tbl) { + for(size_t i = 0, offset = 0; i < sizeof(devices) / sizeof(devices[0]); i++) { + mmu_unmap_page_range(mmu_l3_tbl, MMIO_BASE + offset, devices[i].pa, devices[i].size); + + offset += devices[i].size; + offset += 0x1000; /* insert guard page */ + } +} + #endif