93 lines
2.8 KiB
C
93 lines
2.8 KiB
C
#include <log.h>
|
|
#include <mem.h>
|
|
#include <pager.h>
|
|
#include <string.h>
|
|
#include <sysconfig.h>
|
|
#include <translation_table.h>
|
|
|
|
#define LEVEL2_TABLE_ENTRIES 256
|
|
|
|
static union TARMV8MMU_LEVEL2_DESCRIPTOR *l2_table;
|
|
static size_t mem = 0;
|
|
extern uint8_t _etext;
|
|
|
|
static union TARMV8MMU_LEVEL3_DESCRIPTOR *
|
|
new_level_l3_table(uintptr_t base_addr) {
|
|
union TARMV8MMU_LEVEL3_DESCRIPTOR *l3_table =
|
|
(union TARMV8MMU_LEVEL3_DESCRIPTOR *)gilbraltar_palloc();
|
|
|
|
for (unsigned page = 0; page < ARMV8MMU_TABLE_ENTRIES; page++) {
|
|
struct TARMV8MMU_LEVEL3_PAGE_DESCRIPTOR *desc = &l3_table[page].page;
|
|
|
|
desc->value11 = 3;
|
|
desc->attr_indx = ATTR_INDX_NORMAL;
|
|
desc->ns = 0;
|
|
desc->ap = ATTR_IB_AP_RW_EL1;
|
|
desc->sh = ATTR_IB_SH_INNER_SHAREABLE;
|
|
desc->af = 1;
|
|
desc->ng = 0;
|
|
desc->reserved0_1 = 0;
|
|
desc->output_addr = ARMV8MMUL3PAGEADDR(base_addr);
|
|
desc->reserved0_2 = 0;
|
|
desc->continuous = 0;
|
|
desc->pxn = 0;
|
|
desc->uxn = 1;
|
|
desc->ignored = 0;
|
|
|
|
if (base_addr >= (uint64_t)&_etext) {
|
|
desc->pxn = 1;
|
|
|
|
if ((base_addr >= mem && base_addr < GIGABYTE) ||
|
|
base_addr > (8 * GIGABYTE - 1)) {
|
|
desc->attr_indx = ATTR_INDX_DEVICE;
|
|
desc->sh = ATTR_IB_SH_OUTER_SHAREABLE;
|
|
} else if (base_addr >= MEM_COHERENT_REGION &&
|
|
base_addr < MEM_HEAP_START) {
|
|
desc->attr_indx = ATTR_INDX_COHERENT;
|
|
desc->sh = ATTR_IB_SH_OUTER_SHAREABLE;
|
|
}
|
|
}
|
|
|
|
base_addr += ARMV8MMU_LEVEL3_PAGE_SIZE;
|
|
}
|
|
|
|
return (l3_table);
|
|
}
|
|
|
|
uintptr_t gilbraltar_translation_table_base(void) {
|
|
return ((uintptr_t)l2_table);
|
|
}
|
|
|
|
void gilbraltar_translation_table_init(size_t size) {
|
|
l2_table = (union TARMV8MMU_LEVEL2_DESCRIPTOR *)gilbraltar_palloc();
|
|
gilbraltar_log(DEBUG, "L2 table allocated.\r\n");
|
|
|
|
memset(l2_table, 0, PAGE_SIZE);
|
|
|
|
for (unsigned entry = 0; entry < LEVEL2_TABLE_ENTRIES; entry++) {
|
|
uint64_t base_addr =
|
|
(uint64_t)entry * ARMV8MMU_TABLE_ENTRIES * ARMV8MMU_LEVEL3_PAGE_SIZE;
|
|
|
|
if (base_addr >= 8 * GIGABYTE &&
|
|
!(MEM_IOMEM_AXI_START <= base_addr && base_addr <= MEM_IOMEM_AXI_END) &&
|
|
!(MEM_IOMEM_SOC_START <= base_addr && base_addr <= MEM_IOMEM_SOC_END) &&
|
|
!(MEM_IOMEM_PCIE_START <= base_addr && base_addr <= MEM_IOMEM_PCIE_END))
|
|
continue; // as far as we can
|
|
|
|
gilbraltar_log(DEBUG, "New L3 table.\r\n");
|
|
union TARMV8MMU_LEVEL3_DESCRIPTOR *l3_table = new_level_l3_table(base_addr);
|
|
struct TARMV8MMU_LEVEL2_TABLE_DESCRIPTOR *desc = &l2_table[entry].table;
|
|
|
|
desc->value11 = 3;
|
|
desc->ignored1 = 0;
|
|
desc->table_addr = ARMV8MMUL2TABLEADDR((uint64_t)l3_table);
|
|
desc->reserved0 = 0;
|
|
desc->ignored2 = 0;
|
|
desc->pxn_table = 0;
|
|
desc->uxn_table = 0;
|
|
desc->ap_table = AP_TABLE_ALL_ACCESS;
|
|
desc->ns_table = 0;
|
|
}
|
|
|
|
data_sync_barrier();
|
|
}
|