Skip to content
Snippets Groups Projects
Commit 682374db authored by Adrian Danis's avatar Adrian Danis Committed by Joel Beeren
Browse files

arm: Rearrange context switching code to make fastpath and regular code not duplicate functionality

parent d223dba2
No related branches found
No related tags found
No related merge requests found
......@@ -75,8 +75,8 @@ bool_t CONST isValidVTableRoot(cap_t cap);
exception_t checkValidIPCBuffer(vptr_t vptr, cap_t cap);
vm_rights_t CONST maskVMRights(vm_rights_t vm_rights,
cap_rights_t cap_rights_mask);
hw_asid_t getHWASID(asid_t asid);
hw_asid_t findFreeHWASID(void) VISIBLE;
void setCurrentASID(asid_t asid);
void flushPage(vm_page_size_t page_size, pde_t* pd, asid_t asid, word_t vptr);
void flushTable(pde_t* pd, asid_t asid, word_t vptr, pte_t* pt);
void flushSpace(asid_t asid);
......
......@@ -124,20 +124,26 @@ static inline void writeContextID(word_t id)
isb();
}
/** MODIFIES: [*] */
void setHardwareASID(hw_asid_t hw_asid);
/* Address space control */
/** MODIFIES: [*] */
/** DONT_TRANSLATE */
static inline void setCurrentPD(paddr_t addr)
static inline void writeTTBR0(paddr_t addr)
{
/* Mask supplied address (retain top 19 bits). Set the lookup cache bits:
* outer write-back cacheable, no allocate on write, inner non-cacheable.
*/
dsb();
asm volatile("mcr p15, 0, %0, c2, c0, 0" : :
"r"((addr & 0xffffe000) | 0x18));
}
static inline void setCurrentPD(paddr_t addr)
{
/* Mask supplied address (retain top 19 bits). Set the lookup cache bits:
* outer write-back cacheable, no allocate on write, inner non-cacheable.
*/
/* Before changing the PD ensure all memory stores have completed */
dsb();
writeTTBR0(addr);
/* Ensure the PD switch completes before we do anything else */
isb();
}
......
......@@ -13,7 +13,23 @@
#include <arch/object/structures.h>
#include <arch/api/types.h>
/** MODIFIES: [*] */
static inline void setHardwareASID(hw_asid_t hw_asid)
{
dsb();
flushBTAC();
writeContextID(hw_asid);
}
void armv_contextSwitch(pde_t* cap_pd, asid_t asid);
static inline void armv_contextSwitch_HWASID(pde_t* cap_pd, hw_asid_t hw_asid)
{
setCurrentPD(addrFromPPtr(cap_pd));
setHardwareASID(hw_asid);
}
static inline void armv_contextSwitch(pde_t* cap_pd, asid_t asid)
{
armv_contextSwitch_HWASID(cap_pd, getHWASID(asid));
}
#endif /* __ARMV_CONTEXT_SWITCH_H__ */
/*
* Copyright 2014, General Dynamics C4 Systems
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __ARMV_FASTPATH_H__
#define __ARMV_FASTPATH_H__
#include <arch/object/structures.h>
#include <arch/api/types.h>
#include <arch/types.h>
#include <plat/machine/hardware.h>
#include <arch/machine.h>
/** DONT_TRANSLATE */
static inline void dsb_fp(void)
{
/*
* Perform a data synchronisation barrier to be performed when we change
* address spaces.
*/
asm volatile (
"mcr p15, 0, %[zero], c7, c10, 4\n\t"
:
: [zero]"r"(0)
);
}
/* Change the translation root by updating TTBR0. */
/** DONT_TRANSLATE */
static inline void
setCurrentPD_fp(word_t pd_addr)
{
asm volatile (
"mcr p15, 0, %[pd_addr], c2, c0, 0\n\t" /* Write TTBR0. */
:
: [pd_addr]"r"(pd_addr | 0x18)
);
}
/* Change the current hardware ASID. */
/** DONT_TRANSLATE */
static inline void
setHardwareASID_fp(hw_asid_t asid)
{
asm volatile (
"mcr p15, 0, %[ctx], c13, c0, 1\n\t" /* Write context ID. */
"mcr p15, 0, %[zero], c7, c5, 6\n\t" /* Flush BTAC. */
:
: [ctx]"r"(asid),
[zero]"r"(0)
);
}
static inline void
armv_contextSwitch_fp(pde_t* cap_pd, hw_asid_t hw_asid)
{
/* No ASID/PD synchronisation required */
dsb_fp();
setCurrentPD_fp(addrFromPPtr(cap_pd));
setHardwareASID_fp(hw_asid);
}
#endif /* __ARMV_FASTPATH_H__ */
......@@ -13,7 +13,41 @@
#include <arch/object/structures.h>
#include <arch/api/types.h>
/** MODIFIES: [*] */
static inline void setHardwareASID(hw_asid_t hw_asid)
{
#if defined(CONFIG_ARM_ERRATA_430973)
flushBTAC();
#endif
writeContextID(hw_asid);
}
void armv_contextSwitch(pde_t* cap_pd, asid_t asid);
static inline void armv_contextSwitch_HWASID(pde_t *cap_pd, hw_asid_t hw_asid)
{
/*
* On ARMv7, speculative refills that complete between switching
* ASID and PD can cause TLB entries to be Tagged with the wrong
* ASID. The correct method to avoid this problem is to
* either cycle the context switch through a reserved ASID or
* through a page directory that has only global mappings.
* The reserved Page directory method has shown to perform better
* than the reserved ASID method.
*
* We do not call setCurrentPD here as we want to perform a
* minimal number of DSB and ISBs and the second PD switch we
* do does not need a DSB
*/
dsb();
writeTTBR0(addrFromPPtr(armKSGlobalPD));
isb();
setHardwareASID(hw_asid);
writeTTBR0(addrFromPPtr(cap_pd));
isb();
}
static inline void armv_contextSwitch(pde_t* cap_pd, asid_t asid)
{
armv_contextSwitch_HWASID(cap_pd, getHWASID(asid));
}
#endif /* __ARMV_CONTEXT_SWITCH_H__ */
/*
* Copyright 2014, General Dynamics C4 Systems
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#ifndef __ARMV_FASTPATH_H__
#define __ARMV_FASTPATH_H__
#include <arch/object/structures.h>
#include <arch/api/types.h>
#include <arch/types.h>
#include <plat/machine/hardware.h>
#include <arch/machine.h>
/* Change the translation root by updating TTBR0. */
static inline void
setCurrentPD_fp(word_t pd_addr)
{
pd_addr &= 0xffffe000;
pd_addr |= 0x18;
asm("mcr p15, 0, %0, c2, c0, 0" : : "r"(pd_addr));
asm("isb");
}
static inline void
armv_contextSwitch_fp(pde_t* cap_pd, hw_asid_t hw_asid)
{
/* ASID/PD synchronisation achieved through PD with no non-global mappings */
setCurrentPD_fp(addrFromPPtr(armKSGlobalPD));
setHardwareASID(hw_asid);
setCurrentPD_fp(addrFromPPtr(cap_pd));
}
#endif /* __ARMV_FASTPATH_H__ */
......@@ -11,7 +11,6 @@ DIRECTORIES += src/arch/arm/armv/${ARMV}
ARCH_ASM_SOURCES += armv/${ARMV}/machine_asm.S
ARCH_C_SOURCES += armv/${ARMV}/context_switch.c
ARCH_C_SOURCES += armv/${ARMV}/benchmark.c
ARCH_C_SOURCES += armv/${ARMV}/user_access.c
ARCH_C_SOURCES += armv/${ARMV}/cache.c
/*
* Copyright 2014, General Dynamics C4 Systems
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <armv/context_switch.h>
void armv_contextSwitch(pde_t* cap_pd, asid_t asid)
{
setCurrentPD(addrFromPPtr(cap_pd));
setCurrentASID(asid);
}
/** MODIFIES: [*] */
void setHardwareASID(hw_asid_t hw_asid)
{
dsb();
flushBTAC();
writeContextID(hw_asid);
}
......@@ -11,7 +11,6 @@ DIRECTORIES += src/arch/arm/armv/${ARMV}
ARCH_ASM_SOURCES += armv/${ARMV}/machine_asm.S
ARCH_C_SOURCES += armv/${ARMV}/context_switch.c
ARCH_C_SOURCES += armv/${ARMV}/benchmark.c
ARCH_C_SOURCES += armv/${ARMV}/user_access.c
ARCH_C_SOURCES += armv/${ARMV}/cache.c
/*
* Copyright 2014, General Dynamics C4 Systems
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(GD_GPL)
*/
#include <armv/context_switch.h>
/** MODIFIES: [*] */
void setHardwareASID(hw_asid_t hw_asid)
{
#if defined(CONFIG_ARM_ERRATA_430973)
flushBTAC();
#endif
writeContextID(hw_asid);
}
void armv_contextSwitch(pde_t* cap_pd, asid_t asid)
{
/*
* On ARMv7, speculative refills that complete between switching
* ASID and PD can cause TLB entries to be Tagged with the wrong
* ASID. The correct method to avoid this problem is to
* either cycle the context switch through a reserved ASID or
* through a page directory that has only global mappings.
* The reserved Page directory method has shown to perform better
* than the reserved ASID method.
*/
setCurrentPD(addrFromPPtr(armKSGlobalPD));
setCurrentASID(asid);
setCurrentPD(addrFromPPtr(cap_pd));
}
......@@ -20,7 +20,7 @@
#include <config.h>
#include <assert.h>
#include <arch/fastpath/fastpath.h>
#include <armv/fastpath.h>
#include <armv/context_switch.h>
/* When building the fastpath the assembler in traps.S makes these
* assumptions. Because compile_asserts are hard to do in assembler,
......@@ -95,7 +95,7 @@ switchToThread_fp(tcb_t *thread, pde_t *cap_pd, pde_t stored_hw_asid)
hw_asid = pde_pde_invalid_get_stored_hw_asid(stored_hw_asid);
armv_contextSwitch_fp(cap_pd, hw_asid);
armv_contextSwitch_HWASID(cap_pd, hw_asid);
*armKSGlobalsFrame = thread->tcbIPCBuffer;
ksCurThread = thread;
......
......@@ -859,7 +859,7 @@ findFreeHWASID(void)
return hw_asid;
}
static hw_asid_t
hw_asid_t
getHWASID(asid_t asid)
{
pde_t stored_hw_asid;
......@@ -876,16 +876,6 @@ getHWASID(asid_t asid)
}
}
void
setCurrentASID(asid_t asid)
{
hw_asid_t hw_asid;
assert(asid);
hw_asid = getHWASID(asid);
setHardwareASID(hw_asid);
}
/* Cache and TLB consistency */
void
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment