SELFOUR-1277: implement PageRemap for riscv

This commit is contained in:
Anna Lyons 2018-04-04 11:21:06 +10:00
parent 1dcd652546
commit 6114fd3081
2 changed files with 104 additions and 2 deletions

View file

@ -32,6 +32,25 @@
<param dir="in" name="rights" type="seL4_CapRights_t"/>
<param dir="in" name="attr" type="seL4_RISCV_VMAttributes"/>
</method>
<method id="RISCVPageRemap" name="Remap">
<brief>
Remap a page.
</brief>
<description>
See <autoref label="ch:vspace"/>.
</description>
<param dir="in" name="pt" type="seL4_RISCV_PageTable"/>
<param dir="in" name="rights" type="seL4_CapRights_t">
<description>
Rights for the mapping. Possible values for this type are given in <autoref label="sec:cap_rights"/>.
</description>
</param>
<param dir="in" name="attr" type="seL4_RISCV_VMAttributes">
<description>
VM Attributes for the mapping. Possible values for this type are given in <autoref label="ch:vspace"/>.
</description>
</param>
</method>
<method id="RISCVPageUnmap" name="Unmap"/>
<method id="RISCVPageGetAddress" name="GetAddress">
<param dir="out" name="paddr" type="seL4_Word"/>

View file

@ -1060,14 +1060,97 @@ decodeRISCVFrameInvocation(word_t label, unsigned int length,
map_ret.pte_entries);
}
case RISCVPageRemap: {
word_t vaddr, w_rightsMask;
paddr_t frame_paddr;
cap_t lvl1ptCap;
pte_t *lvl1pt;
asid_t asid;
vm_rights_t capVMRights, vmRights;
vm_page_size_t frameSize;
vm_attributes_t attr;
if (unlikely(length < 2 || extraCaps.excaprefs[0] == NULL)) {
userError("RISCVPageRemap: Truncated message.");
current_syscall_error.type = seL4_TruncatedMessage;
return EXCEPTION_SYSCALL_ERROR;
}
w_rightsMask = getSyscallArg(0, buffer);
attr = vmAttributesFromWord(getSyscallArg(1, buffer));
lvl1ptCap = extraCaps.excaprefs[0]->cap;
frameSize = cap_frame_cap_get_capFSize(cap);
capVMRights = cap_frame_cap_get_capFVMRights(cap);
if (unlikely(cap_get_capType(lvl1ptCap) != cap_page_table_cap)) {
userError("RISCVPageRemap: Invalid level 1 pt cap.");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
if (unlikely(!isVTableRoot(lvl1ptCap))) {
userError("RISCVPageReMap: Invalid level 1 pt cap.");
current_syscall_error.type =
seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
if (unlikely(cap_frame_cap_get_capFMappedASID(cap)) == asidInvalid) {
userError("RISCVPageRemap: Cap is not mapped");
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 0;
return EXCEPTION_SYSCALL_ERROR;
}
vaddr = cap_frame_cap_get_capFMappedAddress(cap);
asid = cap_page_table_cap_get_capPTMappedASID(lvl1ptCap);
lvl1pt = PTE_PTR(cap_page_table_cap_get_capPTBasePtr(lvl1ptCap));
findVSpaceForASID_ret_t find_ret = findVSpaceForASID(asid);
if (find_ret.status != EXCEPTION_NONE) {
current_syscall_error.type = seL4_FailedLookup;
current_syscall_error.failedLookupWasSource = false;
return EXCEPTION_SYSCALL_ERROR;
}
if (find_ret.vspace_root != lvl1pt) {
current_syscall_error.type = seL4_InvalidCapability;
current_syscall_error.invalidCapNumber = 1;
return EXCEPTION_SYSCALL_ERROR;
}
/* Check if this page is already mapped */
// RVTODO: lookup leaf node and see if remaining bits == frameSize
lookupPTSlot_ret_t lu_ret = lookupPTSlot(lvl1pt, vaddr, RISCVpageAtPTLevel(frameSize));
if (unlikely(lu_ret.status != EXCEPTION_NONE)) {
userError("RISCVPageMap: No PageTable for this page %p", vaddr);
current_syscall_error.type = seL4_FailedLookup;
current_syscall_error.failedLookupWasSource = false;
return EXCEPTION_SYSCALL_ERROR;
}
vmRights = maskVMRights(capVMRights, rightsFromWord(w_rightsMask));
frame_paddr = addrFromPPtr((void *)
cap_frame_cap_get_capFBasePtr(cap));
create_mappings_pte_return_t map_ret;
map_ret = createSafeMappingEntries_PTE(frame_paddr, vaddr,
frameSize, vmRights,
attr, lvl1pt);
if (unlikely(map_ret.status != EXCEPTION_NONE)) {
return map_ret.status;
}
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return performPageInvocationRemapPTE(map_ret.pte, map_ret.pte_entries);
}
case RISCVPageUnmap: {
setThreadState(NODE_STATE(ksCurThread), ThreadState_Restart);
return performPageInvocationUnmap(cap, cte);
}
// RVTODO: what happend to PageReMap
case RISCVPageGetAddress: {
/* Check that there are enough message registers */