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