1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <config.h> 10#include <arch/object/structures.h> 11#include <arch/api/types.h> 12#include <mode/model/statedata.h> 13 14static inline void setHardwareASID(hw_asid_t hw_asid) 15{ 16#if defined(CONFIG_ARM_ERRATA_430973) 17 flushBTAC(); 18#endif 19 writeContextID(hw_asid); 20} 21 22static inline void armv_contextSwitch_HWASID(pde_t *cap_pd, hw_asid_t hw_asid) 23{ 24#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 25 writeContextIDAndPD(hw_asid, addrFromPPtr(cap_pd)); 26#else 27 /* 28 * On ARMv7, speculative refills that complete between switching 29 * ASID and PD can cause TLB entries to be Tagged with the wrong 30 * ASID. The correct method to avoid this problem is to 31 * either cycle the context switch through a reserved ASID or 32 * through a page directory that has only global mappings. 33 * The reserved Page directory method has shown to perform better 34 * than the reserved ASID method. 35 * 36 * We do not call setCurrentPD here as we want to perform a 37 * minimal number of DSB and ISBs and the second PD switch we 38 * do does not need a DSB 39 */ 40 dsb(); 41 writeTTBR0Ptr(addrFromPPtr(armKSGlobalPD)); 42 isb(); 43 setHardwareASID(hw_asid); 44 writeTTBR0Ptr(addrFromPPtr(cap_pd)); 45 isb(); 46#endif 47} 48 49static inline void armv_contextSwitch(pde_t *cap_pd, asid_t asid) 50{ 51 armv_contextSwitch_HWASID(cap_pd, getHWASID(asid)); 52} 53 54