arm/tk1: connect objects with SMMU invocations
This commit is contained in:
parent
55e58e1a41
commit
508e87477f
6 changed files with 112 additions and 7 deletions
|
|
@ -63,6 +63,10 @@ typedef word_t vm_rights_t;
|
|||
#define PT_BITS 8
|
||||
#endif /* ARM_HYP */
|
||||
|
||||
/* NOTE: the macros are defined based on Tegra K1 SMMU page table sizes */
|
||||
#define ARM_IOPTE_SIZE_BITS 2
|
||||
#define ARM_IOPT_BITS 10
|
||||
|
||||
|
||||
#define PDE_PTR(r) ((pde_t *)(r))
|
||||
#define PDE_REF(p) ((unsigned int)p)
|
||||
|
|
@ -366,6 +370,9 @@ cap_get_archCapPtr(cap_t cap)
|
|||
return VCPU_PTR(cap_vcpu_cap_get_capVCPUPtr(cap));
|
||||
#endif
|
||||
|
||||
case cap_io_page_table_cap:
|
||||
return (void *)(cap_io_page_table_cap_get_capIOPTBasePtr(cap));
|
||||
|
||||
default:
|
||||
/* Unreachable, but GCC can't figure that out */
|
||||
return NULL;
|
||||
|
|
|
|||
|
|
@ -95,4 +95,6 @@ exception_t decodeARMMMUInvocation(word_t invLabel, word_t length, cptr_t cptr,
|
|||
word_t *buffer);
|
||||
|
||||
|
||||
bool_t CONST isIOSpaceFrame(cap_t cap);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -20,11 +20,18 @@ typedef enum _object {
|
|||
seL4_ARM_PageDirectoryObject,
|
||||
#ifdef ARM_HYP
|
||||
seL4_ARM_VCPUObject,
|
||||
#endif
|
||||
#ifdef CONFIG_ARM_SMMU
|
||||
seL4_ARM_IOPageTableObject,
|
||||
#endif
|
||||
seL4_ObjectTypeCount
|
||||
} seL4_ArchObjectType;
|
||||
|
||||
typedef seL4_Word object_t;
|
||||
|
||||
#ifndef CONFIG_ARM_SMMU
|
||||
#define seL4_ARM_IOPageTableObject 0xffff
|
||||
#endif
|
||||
|
||||
#endif /* __ARCH_OBJECTTYPE_H */
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <plat/machine/devices.h>
|
||||
#include <plat/machine/hardware.h>
|
||||
#include <armv/context_switch.h>
|
||||
#include <arch/object/iospace.h>
|
||||
|
||||
/* ARM uses multiple identical mappings in a page table / page directory to construct
|
||||
* large mappings. In both cases it happens to be 16 entries, which can be calculated by
|
||||
|
|
@ -1131,6 +1132,16 @@ isValidVTableRoot(cap_t cap)
|
|||
cap_page_directory_cap_get_capPDIsMapped(cap);
|
||||
}
|
||||
|
||||
bool_t CONST
|
||||
isIOSpaceFrame(cap_t cap)
|
||||
{
|
||||
#ifdef CONFIG_ARM_SMMU
|
||||
return cap_get_capType(cap) == cap_small_frame_cap && cap_small_frame_cap_get_capFIsIOSpace(cap);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
setVMRoot(tcb_t *tcb)
|
||||
{
|
||||
|
|
@ -2547,6 +2558,13 @@ decodeARMFrameInvocation(word_t invLabel, word_t length,
|
|||
vm_page_size_t frameSize;
|
||||
vm_attributes_t attr;
|
||||
|
||||
if (isIOSpaceFrame(cap)) {
|
||||
userError("ARMFrameRemap: Attempting to remap frame mapped into an IOSpace");
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
|
||||
return EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
|
||||
if (unlikely(length < 2 || excaps.excaprefs[0] == NULL)) {
|
||||
current_syscall_error.type =
|
||||
seL4_TruncatedMessage;
|
||||
|
|
@ -2647,8 +2665,16 @@ decodeARMFrameInvocation(word_t invLabel, word_t length,
|
|||
}
|
||||
|
||||
case ARMPageUnmap: {
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return performPageInvocationUnmap(cap, cte);
|
||||
if (isIOSpaceFrame(cap)) {
|
||||
return decodeARMIOUnMapInvocation(invLabel, length, cte, cap, excaps);
|
||||
} else {
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
return performPageInvocationUnmap(cap, cte);
|
||||
}
|
||||
}
|
||||
|
||||
case ARMPageMapIO: {
|
||||
return decodeARMIOMapInvocation(invLabel, length, cte, cap, excaps, buffer);
|
||||
}
|
||||
|
||||
case ARMPageClean_Data:
|
||||
|
|
|
|||
|
|
@ -74,6 +74,20 @@ Arch_deriveCap(cte_t *slot, cap_t cap)
|
|||
return ret;
|
||||
#endif
|
||||
|
||||
case cap_io_space_cap:
|
||||
ret.cap = cap;
|
||||
ret.status = EXCEPTION_NONE;
|
||||
|
||||
case cap_io_page_table_cap:
|
||||
if (cap_io_page_table_cap_get_capIOPTIsMapped(cap)) {
|
||||
ret.cap = cap;
|
||||
ret.status = EXCEPTION_NONE;
|
||||
} else {
|
||||
current_syscall_error.type = seL4_IllegalOperation;
|
||||
ret.cap = cap_null_cap_new();
|
||||
ret.status = EXCEPTION_SYSCALL_ERROR;
|
||||
}
|
||||
return ret;
|
||||
default:
|
||||
/* This assert has no equivalent in haskell,
|
||||
* as the options are restricted by type */
|
||||
|
|
@ -140,6 +154,10 @@ Arch_finaliseCap(cap_t cap, bool_t final)
|
|||
|
||||
case cap_small_frame_cap:
|
||||
if (cap_small_frame_cap_get_capFMappedASID(cap)) {
|
||||
if (isIOSpaceFrame(cap)) {
|
||||
unmapIOPage(cap);
|
||||
break;
|
||||
}
|
||||
unmapPage(ARMSmallPage,
|
||||
cap_small_frame_cap_get_capFMappedASID(cap),
|
||||
cap_small_frame_cap_get_capFMappedAddress(cap),
|
||||
|
|
@ -163,6 +181,18 @@ Arch_finaliseCap(cap_t cap, bool_t final)
|
|||
}
|
||||
break;
|
||||
#endif
|
||||
|
||||
case cap_io_space_cap:
|
||||
break;
|
||||
|
||||
case cap_io_page_table_cap:
|
||||
if (final && cap_io_page_table_cap_get_capIOPTIsMapped(cap)) {
|
||||
deleteIOPageTable(cap);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return cap_null_cap_new();
|
||||
|
|
@ -270,6 +300,15 @@ Arch_recycleCap(bool_t is_final, cap_t cap)
|
|||
return cap;
|
||||
#endif
|
||||
|
||||
case cap_io_space_cap:
|
||||
Arch_finaliseCap(cap, is_final);
|
||||
return cap;
|
||||
|
||||
case cap_io_page_table_cap:
|
||||
clearMemory((void *)cap_get_capPtr(cap), cap_get_capSizeBits(cap));
|
||||
Arch_finaliseCap(cap, is_final);
|
||||
return cap;
|
||||
|
||||
default:
|
||||
fail("Arch_recycleCap: invalid cap type");
|
||||
}
|
||||
|
|
@ -344,6 +383,19 @@ Arch_sameRegionAs(cap_t cap_a, cap_t cap_b)
|
|||
break;
|
||||
#endif
|
||||
|
||||
case cap_io_space_cap:
|
||||
if (cap_get_capType(cap_b) == cap_io_space_cap) {
|
||||
return cap_io_space_cap_get_capModuleID(cap_a) ==
|
||||
cap_io_space_cap_get_capModuleID(cap_b);
|
||||
}
|
||||
break;
|
||||
|
||||
case cap_io_page_table_cap:
|
||||
if (cap_get_capType(cap_b) == cap_io_page_table_cap) {
|
||||
return cap_io_page_table_cap_get_capIOPTBasePtr(cap_a) ==
|
||||
cap_io_page_table_cap_get_capIOPTBasePtr(cap_b);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -390,6 +442,8 @@ Arch_getObjectSize(word_t t)
|
|||
return PTE_SIZE_BITS + PT_BITS;
|
||||
case seL4_ARM_PageDirectoryObject:
|
||||
return PDE_SIZE_BITS + PD_BITS;
|
||||
case seL4_ARM_IOPageTableObject:
|
||||
return ARM_IOPTE_SIZE_BITS + ARM_IOPT_BITS;
|
||||
#ifdef ARM_HYP
|
||||
case seL4_ARM_VCPUObject:
|
||||
return VCPU_SIZE_BITS;
|
||||
|
|
@ -516,13 +570,18 @@ Arch_decodeInvocation(word_t invLabel, word_t length, cptr_t cptr,
|
|||
cte_t *slot, cap_t cap, extra_caps_t excaps,
|
||||
word_t *buffer)
|
||||
{
|
||||
switch (cap_get_capType(cap)) {
|
||||
case cap_io_space_cap:
|
||||
return decodeARMIOSpaceInvocation(invLabel, cap);
|
||||
case cap_io_page_table_cap:
|
||||
return decodeARMIOPTInvocation(invLabel, length, slot, cap, excaps, buffer);
|
||||
#ifdef ARM_HYP
|
||||
if (cap_get_capType(cap) == cap_vcpu_cap) {
|
||||
return decodeARMVCPUInvocation(invLabel, length, cptr, slot, cap, excaps, buffer);
|
||||
|
||||
case cap_vcpu_cap:
|
||||
return decodeARMVCPUInvocation(invLabel, length, cptr, slot, cap, excaps, buffer);
|
||||
#endif /* end of ARM_HYP */
|
||||
default:
|
||||
return decodeARMMMUInvocation(invLabel, length, cptr, slot, cap, excaps, buffer);
|
||||
}
|
||||
#endif /* ARM_HYP */
|
||||
return decodeARMMMUInvocation(invLabel, length, cptr, slot, cap, excaps, buffer);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -329,7 +329,9 @@ decodeARMIOMapInvocation(
|
|||
plat_smmu_tlb_flush_all();
|
||||
plat_smmu_ptc_flush_all();
|
||||
|
||||
#ifdef CONFIG_ARM_SMMU
|
||||
cap = cap_small_frame_cap_set_capFIsIOSpace(cap, 1);
|
||||
#endif
|
||||
cap = cap_small_frame_cap_set_capFMappedASID(cap, asid);
|
||||
cap = cap_small_frame_cap_set_capFMappedAddress(cap, io_address);
|
||||
slot->cap = cap;
|
||||
|
|
@ -421,7 +423,9 @@ decodeARMIOUnMapInvocation(
|
|||
{
|
||||
unmapIOPage(slot->cap);
|
||||
slot->cap = cap_small_frame_cap_set_capFMappedAddress(slot->cap, 0);
|
||||
#ifdef CONFIG_ARM_SMMU
|
||||
slot->cap = cap_small_frame_cap_set_capFIsIOSpace(slot->cap, 0);
|
||||
#endif
|
||||
slot->cap = cap_small_frame_cap_set_capFMappedASID(slot->cap, asidInvalid);
|
||||
|
||||
setThreadState(ksCurThread, ThreadState_Restart);
|
||||
|
|
|
|||
Loading…
Reference in a new issue