aarch64,fastpath: Fixup ASID validation checks

When switching to the new thread, it's VSpace must have a valid ASID
mapping. This means that the ASID in the vspace cap must resolve to the
same vspace object as the vspace cap does. In addition, when the VSpace
object is for a stage 2 translation there must be a currently assigned
hardware VMID for the vspace. Otherwise the slowpath must be taken.

Once these checks are done, the TTBR registers can be directly updated
without needing to perform another ASID translation.

Signed-off-by: Kent McLeod <kent@kry10.com>
This commit is contained in:
Kent McLeod 2022-02-27 15:06:46 +11:00 committed by Kent McLeod
parent 1ae9360300
commit ebcfcb7016
3 changed files with 42 additions and 3 deletions

View file

@ -36,7 +36,7 @@ switchToThread_fp(tcb_t *thread, vspace_root_t *vroot, pde_t stored_hw_asid)
vcpu_switch(thread->tcbArch.tcbVCPU);
}
asid = (asid_t)(stored_hw_asid.words[0] & 0xffff);
armv_contextSwitch(vroot, asid);
armv_contextSwitch_HWASID(vroot, asid);
#ifdef CONFIG_BENCHMARK_TRACK_UTILISATION
benchmark_utilisation_switch(NODE_STATE(ksCurThread), thread);

View file

@ -9,6 +9,12 @@
#include <config.h>
#include <arch/kernel/vspace.h>
static inline void armv_contextSwitch_HWASID(vspace_root_t *vspace, asid_t asid)
{
setCurrentUserVSpaceRoot(ttbr_new(asid, pptr_to_paddr(vspace)));
}
/*
* In AARCH64, hardware and virtual asids are the same and are written
* when updating the translation table base register.

View file

@ -99,7 +99,23 @@ void NORETURN fastpath_call(word_t cptr, word_t msgInfo)
stored_hw_asid.words[0] = 0;
#endif
#ifdef CONFIG_ARCH_AARCH64
stored_hw_asid.words[0] = cap_vtable_root_get_mappedASID(newVTable);
/* Need to test that the ASID is still valid */
asid_t asid = cap_vtable_root_get_mappedASID(newVTable);
asid_map_t asid_map = findMapForASID(asid);
if (unlikely(asid_map_get_type(asid_map) != asid_map_asid_map_vspace ||
VSPACE_PTR(asid_map_asid_map_vspace_get_vspace_root(asid_map)) != cap_pd)) {
slowpath(SysCall);
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
/* Ensure the vmid is valid. */
if (unlikely(!asid_map_asid_map_vspace_get_stored_vmid_valid(asid_map))) {
slowpath(SysCall);
}
/* vmids are the tags used instead of hw_asids in hyp mode */
stored_hw_asid.words[0] = asid_map_asid_map_vspace_get_stored_hw_vmid(asid_map);
#else
stored_hw_asid.words[0] = asid;
#endif
#endif
#ifdef CONFIG_ARCH_RISCV
@ -352,7 +368,24 @@ void NORETURN fastpath_reply_recv(word_t cptr, word_t msgInfo)
stored_hw_asid.words[0] = 0;
#endif
#ifdef CONFIG_ARCH_AARCH64
stored_hw_asid.words[0] = cap_vtable_root_get_mappedASID(newVTable);
/* Need to test that the ASID is still valid */
asid_t asid = cap_vtable_root_get_mappedASID(newVTable);
asid_map_t asid_map = findMapForASID(asid);
if (unlikely(asid_map_get_type(asid_map) != asid_map_asid_map_vspace ||
VSPACE_PTR(asid_map_asid_map_vspace_get_vspace_root(asid_map)) != cap_pd)) {
slowpath(SysReplyRecv);
}
#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT
/* Ensure the vmid is valid. */
if (unlikely(!asid_map_asid_map_vspace_get_stored_vmid_valid(asid_map))) {
slowpath(SysReplyRecv);
}
/* vmids are the tags used instead of hw_asids in hyp mode */
stored_hw_asid.words[0] = asid_map_asid_map_vspace_get_stored_hw_vmid(asid_map);
#else
stored_hw_asid.words[0] = asid;
#endif
#endif
#ifdef CONFIG_ARCH_RISCV