arm-hyp/tk1: add default SMMU translation for VM
This commit is contained in:
parent
17ec138bf2
commit
bb9e84e6ec
6 changed files with 84 additions and 18 deletions
9
Kconfig
9
Kconfig
|
|
@ -241,6 +241,15 @@ config ARM_HYPERVISOR_SUPPORT
|
|||
help
|
||||
Support for TK1 SoC-specific SystemMMU
|
||||
|
||||
config ARM_SMMU_VM_DEFAULT_MAPPING
|
||||
bool "Enable SystemMMU default mapping for guest VM"
|
||||
depends on PLAT_TK1 && ARM_SMMU
|
||||
help
|
||||
Enable the default translation for guest VM: all
|
||||
physical memory reserved for a VM is allowed to
|
||||
be accessed with read/write/nonsecure permissions.
|
||||
|
||||
|
||||
|
||||
source "$KERNEL_PATH/src/arch/arm/Kconfig"
|
||||
source "$KERNEL_PATH/src/plat/pc99/Kconfig"
|
||||
|
|
|
|||
|
|
@ -43,6 +43,14 @@
|
|||
#define VGICI_REQ_PADDR (ARM_PERIPHBASE + 0x4000) /* hyp view for requesting CPU */
|
||||
#define VGICI_ALL_PADDR (ARM_PERIPHBASE + 0x5000) /* hyp view for all CPUs */
|
||||
#define VGICI_VM_PADDR (ARM_PERIPHBASE + 0x6000) /* hyp view for VM view */
|
||||
#define PCIE_0_CFG_PADDR (0x01000000) /* PCIE lane 0 config register */
|
||||
#define PCIE_1_CFG_PADDR (0x01001000) /* PCIE lane 1 config register */
|
||||
#define PCIE_PCA0_1_PADDR (0x01002000) /* PCA 0 and 1 */
|
||||
#define PCIE_PADS_AFI_PADDR (0x01003000) /* Pads and AFI */
|
||||
#define PCIE_A1_PADDR (0x01000000) /* 16 MB */
|
||||
#define PCIE_A2_PADDR (0x02000000) /* 224 MB */
|
||||
#define PCIE_A3_PADDR (0x10000000) /* 763 MB */
|
||||
#define R8169_NIC_PADDR (0x13000000) /* r8169 NIC 1 MB */
|
||||
#define GRAPH_HOST_PADDR (0x54000000) /* 16 MB */
|
||||
#define GPU_PADDR (0x57000000) /* 144 MB */
|
||||
#define UP_TAG_PADDR (0x60000000) /* 4 KB */
|
||||
|
|
@ -83,7 +91,8 @@
|
|||
#define HDA_PADDR (0x70030000) /* 64 KB */
|
||||
#define MIOBFM_PADDR (0x70200000) /* 64 KB */
|
||||
#define AUDIO_PADDR (0x70300000) /* 64 KB */
|
||||
#define XUSB_HOST_PADDR (0x70090000) /* 40 KB */
|
||||
#define XUSB_HOST_PADDR (0x70090000) /* 36 KB */
|
||||
#define XUSB_PADCTL_PADDR (0x7009f000) /* 4 KB */
|
||||
#define XUSB_DEV_PADDR (0x700d0000) /* 40 KB */
|
||||
#define DDS_PADDR (0x700a0000) /* 8KB 4608 bytes */
|
||||
#define SDMMC_1_PADDR (0x700b0000) /* 4KB 512 bytes */
|
||||
|
|
@ -106,4 +115,9 @@
|
|||
#define USB3_PADDR (0x7d008000) /* 8 KB region, 6 KB */
|
||||
#define UARTA_PADDR (0x70006000)
|
||||
|
||||
/* physical memory regions allocated for virtual machines */
|
||||
#define VM_HOST_PA_START 0xb0000000
|
||||
#define VM_GUEST_PA_START 0x80000000
|
||||
#define VM_HOST_PA_SIZE 0x40000000
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -33,13 +33,17 @@ block iopde_pt {
|
|||
field_high address 22
|
||||
}
|
||||
|
||||
-- adding a 2-bit padding before address is because
|
||||
-- we do not support addressing more than 4 GiB memory
|
||||
|
||||
block iopde_4m {
|
||||
field read 1
|
||||
field write 1
|
||||
field nonsecure 1
|
||||
field page_size 1
|
||||
padding 6
|
||||
field_high address 12
|
||||
padding 2
|
||||
field_high address 10
|
||||
padding 10
|
||||
}
|
||||
|
||||
|
|
@ -50,5 +54,6 @@ block iopte {
|
|||
field write 1
|
||||
field nonsecure 1
|
||||
padding 7
|
||||
field_high address 22
|
||||
padding 2
|
||||
field_high address 20
|
||||
}
|
||||
|
|
|
|||
|
|
@ -388,7 +388,8 @@ decodeARMIOMapInvocation(
|
|||
}
|
||||
|
||||
|
||||
void deleteIOPageTable(cap_t io_pt_cap)
|
||||
void
|
||||
deleteIOPageTable(cap_t io_pt_cap)
|
||||
{
|
||||
|
||||
uint32_t asid;
|
||||
|
|
@ -428,7 +429,8 @@ void deleteIOPageTable(cap_t io_pt_cap)
|
|||
}
|
||||
}
|
||||
|
||||
void unmapIOPage(cap_t cap)
|
||||
void
|
||||
unmapIOPage(cap_t cap)
|
||||
{
|
||||
lookupIOPTSlot_ret_t lu_ret;
|
||||
iopde_t *pd;
|
||||
|
|
@ -500,7 +502,8 @@ decodeARMIOUnMapInvocation(
|
|||
return EXCEPTION_NONE;
|
||||
}
|
||||
|
||||
exception_t decodeARMIOSpaceInvocation(word_t invLabel, cap_t cap)
|
||||
exception_t
|
||||
decodeARMIOSpaceInvocation(word_t invLabel, cap_t cap)
|
||||
{
|
||||
userError("IOSpace capability has no invocations");
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
|
|
|
|||
|
|
@ -21,9 +21,8 @@
|
|||
/* Available physical memory regions on platform (RAM minus kernel image). */
|
||||
/* NOTE: Regions are not allowed to be adjacent! */
|
||||
|
||||
/* 1 MiB starting from 0xa7f00000 is reserved by the elfloader for monitor mode hooks */
|
||||
const p_region_t BOOT_RODATA avail_p_regs[] = {
|
||||
// { .start = 0x80000000, .end = 0xf0000000 }
|
||||
//{ .start = 0x80000000, .end = 0xb0000000 }
|
||||
{ .start = 0x80000000, .end = 0xa7f00000 }
|
||||
};
|
||||
|
||||
|
|
@ -41,13 +40,17 @@ BOOT_CODE p_region_t get_avail_p_reg(word_t i)
|
|||
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||
#define SECTION_SIZE (1 << SECTION_BITS)
|
||||
|
||||
#define VM_PA_START 0xb0000000
|
||||
#define VM_PA_SIZE 0x10000000
|
||||
|
||||
const p_region_t BOOT_RODATA dev_p_regs[] = {
|
||||
|
||||
{ VM_PA_START, VM_PA_START + VM_PA_SIZE },
|
||||
{ VM_HOST_PA_START, VM_HOST_PA_START + VM_HOST_PA_SIZE },
|
||||
{ VGICI_VM_PADDR, VGICI_VM_PADDR + PAGE_SIZE },
|
||||
{ PCIE_0_CFG_PADDR, PCIE_0_CFG_PADDR + PAGE_SIZE },
|
||||
{ PCIE_1_CFG_PADDR, PCIE_1_CFG_PADDR + PAGE_SIZE },
|
||||
{ PCIE_PCA0_1_PADDR, PCIE_PCA0_1_PADDR + PAGE_SIZE },
|
||||
{ PCIE_PADS_AFI_PADDR, PCIE_PADS_AFI_PADDR + PAGE_SIZE },
|
||||
{ PCIE_A2_PADDR, PCIE_A2_PADDR + SECTION_SIZE },
|
||||
{ R8169_NIC_PADDR, R8169_NIC_PADDR + SECTION_SIZE},
|
||||
{ GRAPH_HOST_PADDR, GRAPH_HOST_PADDR + (SECTION_SIZE * 16) }, /* 16 MB */
|
||||
{ GPU_PADDR, GPU_PADDR + (SECTION_SIZE * 144) }, /* 144 MB */
|
||||
{ UP_TAG_PADDR, UP_TAG_PADDR + PAGE_SIZE }, /* 4 KB */
|
||||
|
|
@ -90,7 +93,8 @@ const p_region_t BOOT_RODATA dev_p_regs[] = {
|
|||
{ HDA_PADDR, HDA_PADDR + (PAGE_SIZE * 16) }, /* 64 KB */
|
||||
{ MIOBFM_PADDR, MIOBFM_PADDR + (PAGE_SIZE * 16) }, /* 64 KB */
|
||||
{ AUDIO_PADDR, AUDIO_PADDR + (PAGE_SIZE * 16) }, /* 64 KB */
|
||||
{ XUSB_HOST_PADDR, XUSB_HOST_PADDR + (PAGE_SIZE * 10) }, /* 40 KB */
|
||||
{ XUSB_HOST_PADDR, XUSB_HOST_PADDR + (PAGE_SIZE * 9) }, /* 36 KB */
|
||||
{ XUSB_PADCTL_PADDR, XUSB_PADCTL_PADDR + PAGE_SIZE }, /* 4 KB */
|
||||
{ XUSB_DEV_PADDR, XUSB_DEV_PADDR + (PAGE_SIZE * 10) }, /* 40 KB */
|
||||
{ DDS_PADDR, DDS_PADDR + (PAGE_SIZE * 2) }, /* 8KB 4608 bytes */
|
||||
{ SDMMC_1_PADDR, SDMMC_1_PADDR + PAGE_SIZE }, /* 4KB 512 bytes */
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <types.h>
|
||||
#include <config.h>
|
||||
#include <plat/machine/smmu.h>
|
||||
#include <arch/linker.h>
|
||||
#include <plat/machine/devices.h>
|
||||
|
|
@ -133,6 +134,29 @@ plat_smmu_tlb_flush_all(void)
|
|||
#define MC_SECURITY_BIT 8
|
||||
#define MC_DECERR_EMEM_BIT 6
|
||||
|
||||
|
||||
|
||||
/* using 4 MiB mapping for the Linxu guest VM */
|
||||
#define IOPDE_4M_INDEX_SHIFT 22
|
||||
static void
|
||||
plat_smmu_vm_mapping(word_t iopd, word_t gpa, word_t pa, word_t size)
|
||||
{
|
||||
iopde_t *iopde = (iopde_t *)iopd;
|
||||
while (size > 0) {
|
||||
word_t index = gpa >> IOPDE_4M_INDEX_SHIFT;
|
||||
iopde_iopde_4m_ptr_new(
|
||||
iopde + index,
|
||||
1,
|
||||
1,
|
||||
1,
|
||||
pa
|
||||
);
|
||||
gpa += BIT(IOPDE_4M_INDEX_SHIFT);
|
||||
pa += BIT(IOPDE_4M_INDEX_SHIFT);
|
||||
size -= BIT(IOPDE_4M_INDEX_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
BOOT_CODE int
|
||||
plat_smmu_init(void)
|
||||
{
|
||||
|
|
@ -140,16 +164,24 @@ plat_smmu_init(void)
|
|||
int i = 0;
|
||||
|
||||
smmu_disable();
|
||||
printf("smmu disabled\n");
|
||||
|
||||
for (i = 0; i < ARM_PLAT_NUM_SMMU; i++) {
|
||||
iopde_t *pd = (iopde_t *)alloc_region(SMMU_PD_BITS);
|
||||
|
||||
if (pd == 0) {
|
||||
printf("Failed to allocate SMMU IOPageDirectory for ASID %d\n", asid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
memset(pd, 0, BIT(SMMU_PD_BITS));
|
||||
if (config_set(CONFIG_ARM_SMMU_VM_DEFAULT_MAPPING)) {
|
||||
plat_smmu_vm_mapping((word_t)pd, VM_GUEST_PA_START, VM_HOST_PA_START, VM_HOST_PA_SIZE);
|
||||
}
|
||||
cleanCacheRange_RAM((word_t)pd, ((word_t)pd + BIT(SMMU_PD_BITS)),
|
||||
addrFromPPtr(pd));
|
||||
|
||||
smmu_regs->smmu_ptb_asid = asid;
|
||||
|
||||
/* make it read/write/nonsecure but all translation entries are invalid */
|
||||
smmu_regs->smmu_ptb_data = make_ptb_data(pptr_to_paddr(pd), true, true, true);
|
||||
asid++;
|
||||
|
|
@ -167,7 +199,7 @@ plat_smmu_init(void)
|
|||
smmu_regs->smmu_msenc_asid = SMMU_MSENC_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_nv_asid = SMMU_NV_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_nv2_asid = SMMU_NV2_ASID | MODULE_ASID_ENABLE;
|
||||
//smmu_regs->smmu_ppcs_asid = SMMU_PPCS_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_ppcs_asid = SMMU_PPCS_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_sata_asid = SMMU_SATA_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_vde_asid = SMMU_VDE_ASID | MODULE_ASID_ENABLE;
|
||||
smmu_regs->smmu_vi_asid = SMMU_VI_ASID | MODULE_ASID_ENABLE;
|
||||
|
|
@ -190,7 +222,7 @@ plat_smmu_init(void)
|
|||
/* flush TLB */
|
||||
plat_smmu_tlb_flush_all();
|
||||
smmu_enable();
|
||||
printf("smmu enabled\n");
|
||||
|
||||
/* also need to unmask interrupts */
|
||||
smmu_regs->intmask = BIT(MC_APB_ASID_UPDATE_BIT) | BIT(MC_SMMU_PAGE_BIT) |
|
||||
BIT(MC_DECERR_MTS_BIT) | BIT(MC_SECERR_SEC_BIT) |
|
||||
|
|
@ -238,8 +270,6 @@ plat_smmu_handle_interrupt(void)
|
|||
{
|
||||
uint32_t status = smmu_regs->intstatus;
|
||||
uint32_t clear_status = 0;
|
||||
printf("status %x addr %x %x\n", status, smmu_regs->err_status, smmu_regs->err_adr);
|
||||
|
||||
|
||||
if (status & BIT(MC_DECERR_MTS_BIT)) {
|
||||
clear_status |= BIT(MC_DECERR_MTS_BIT);
|
||||
|
|
@ -265,6 +295,7 @@ plat_smmu_handle_interrupt(void)
|
|||
|
||||
/* we only care about SMMU translation failures */
|
||||
if (status & BIT(MC_SMMU_PAGE_BIT)) {
|
||||
#ifdef DEBUG
|
||||
uint32_t err_status = smmu_regs->err_status;
|
||||
uint32_t err_adr = smmu_regs->err_adr;
|
||||
int id = err_status & MC_ERR_ID_MASK;
|
||||
|
|
@ -277,7 +308,7 @@ plat_smmu_handle_interrupt(void)
|
|||
printf("SMMU Address translation error:\n");
|
||||
printf("ID: %d address: 0x%x type: %d direction: 0x%x\n", id, err_adr, type, rw);
|
||||
printf("IOPT permission: read 0x%x write 0x%x nonsecure 0x%x\n", read, write, nonsecure);
|
||||
|
||||
#endif
|
||||
clear_status |= BIT(MC_SMMU_PAGE_BIT);
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue