88 lines
2.6 KiB
Python
88 lines
2.6 KiB
Python
# -*- coding: utf-8 -*-
|
|
SMMU_BASE = 0xFD800000
|
|
STREAM_TABLE_ADDR = 0x40010000 # aligned to 2⁶
|
|
CONTEXT_DESCRIPTOR_ADDR = 0x40020000 # aligned to 2⁶
|
|
PAGE_TABLE_L1_ADDR = 0x40030000
|
|
PAGE_TABLE_L2_ADDR = 0x40031000
|
|
PAGE_TABLE_L3_ADDR = 0x40032000
|
|
|
|
SMMU_CR0 = 0x20
|
|
SMMU_STRTAB_BASE = 0x80
|
|
SMMU_STRTAB_BASE_CFG = 0x88
|
|
SMMU_S_INIT = 0x803c
|
|
STREAM_TABLE_ENTRY_SIZE = 64
|
|
|
|
|
|
def peek(addr):
|
|
return self.Machine.SystemBus.ReadQuadWord(addr)
|
|
|
|
|
|
def poke(addr, val):
|
|
return self.Machine.SystemBus.WriteQuadWord(addr, val)
|
|
|
|
|
|
def poke32(addr, val):
|
|
return self.Machine.SystemBus.WriteDoubleWord(addr, val)
|
|
|
|
|
|
def mc_setup_smmu(stream_id):
|
|
# Set up SMMU and map two 4KB pages
|
|
# 0x0 -> 0x0
|
|
# 0x1000 -> 0x00000001'00000000
|
|
|
|
# L0 Table is not used in VMSAv8-32
|
|
|
|
# L1 Table -> L2 Table, Valid=1, Table=1
|
|
poke(PAGE_TABLE_L1_ADDR, PAGE_TABLE_L2_ADDR | 0b11)
|
|
|
|
# L2 Table -> L3 Table
|
|
poke(PAGE_TABLE_L2_ADDR, PAGE_TABLE_L3_ADDR | 0b11)
|
|
|
|
# L3 Table -> Page entry template
|
|
page_template = 0
|
|
page_template |= 1 << 0 # Valid
|
|
page_template |= 1 << 1 # Table
|
|
page_template |= 0 << 2 # AttrIndx
|
|
page_template |= 1 << 5 # NS
|
|
page_template |= 0b01 << 6 # AP
|
|
page_template |= 0b11 << 8 # SH
|
|
page_template |= 1 << 10 # AccessFlag
|
|
|
|
# L3 Table entry for 0x0 -> 0x0 (index 0)
|
|
poke(PAGE_TABLE_L3_ADDR + 0 * 8, page_template | 0x0)
|
|
# L3 Table entry for 0x1000 -> 0x100000000 (index 1)
|
|
poke(PAGE_TABLE_L3_ADDR + 1 * 8, page_template | 0x100000000)
|
|
|
|
# Context descriptor
|
|
cd = 0
|
|
cd |= 16 << 0 # T0SZ
|
|
cd |= 0b00 << 6 # TG0
|
|
cd |= 16 << 16 # T1SZ
|
|
cd |= 0b10 << 22 # TG1
|
|
cd |= 0b1 << 31 # V
|
|
cd |= 0 << 41 # AA64
|
|
poke(CONTEXT_DESCRIPTOR_ADDR + 0, cd)
|
|
poke(CONTEXT_DESCRIPTOR_ADDR + 8, PAGE_TABLE_L1_ADDR)
|
|
# Rest as zeroes
|
|
for i in range(2, 8):
|
|
poke(CONTEXT_DESCRIPTOR_ADDR + i * 8, 0)
|
|
|
|
# Stream table entry for the CPU
|
|
ste_addr = STREAM_TABLE_ADDR + stream_id * STREAM_TABLE_ENTRY_SIZE
|
|
ste = 0
|
|
ste |= 1 << 0 # V
|
|
ste |= 0b101 << 1 # Config = TranslateStage1
|
|
ste |= CONTEXT_DESCRIPTOR_ADDR # s1ContextPtr, aligned to 2⁶
|
|
poke(ste_addr, ste)
|
|
# Rest as zeroes
|
|
for i in range(1, 8):
|
|
poke(ste_addr + i * 8, 0)
|
|
|
|
# Put that stream table into the SMMU
|
|
poke(SMMU_BASE + SMMU_STRTAB_BASE, STREAM_TABLE_ADDR) # aligned to 2⁶
|
|
poke32(SMMU_BASE + SMMU_STRTAB_BASE_CFG, 5) # log2size
|
|
# Enable SMMU translations
|
|
poke32(SMMU_BASE + SMMU_CR0, 1) # SMMUEN
|
|
# Invalidate everything to load STEs
|
|
poke32(SMMU_BASE + SMMU_S_INIT, 1) # INV_ALL
|