diff --git a/src/arch/arm/locked_mem.hh b/src/arch/arm/locked_mem.hh index ad52da4fb5..a01b838b46 100644 --- a/src/arch/arm/locked_mem.hh +++ b/src/arch/arm/locked_mem.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013,2017 ARM Limited + * Copyright (c) 2012-2013,2017, 2020 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -50,6 +50,7 @@ #include "arch/arm/miscregs.hh" #include "arch/arm/isa_traits.hh" +#include "arch/arm/utility.hh" #include "debug/LLSC.hh" #include "mem/packet.hh" #include "mem/request.hh" @@ -80,8 +81,8 @@ handleLockedSnoop(XC *xc, PacketPtr pkt, Addr cacheBlockMask) xc->getCpuPtr()->name()); xc->setMiscReg(MISCREG_LOCKFLAG, false); // Implement ARMv8 WFE/SEV semantics + sendEvent(xc); xc->setMiscReg(MISCREG_SEV_MAILBOX, true); - xc->getCpuPtr()->wakeup(xc->threadId()); } } @@ -155,8 +156,8 @@ globalClearExclusive(XC *xc) DPRINTF(LLSC,"Clearing lock and signaling sev\n"); xc->setMiscReg(MISCREG_LOCKFLAG, false); // Implement ARMv8 WFE/SEV semantics + sendEvent(xc); xc->setMiscReg(MISCREG_SEV_MAILBOX, true); - xc->getCpuPtr()->wakeup(xc->threadId()); } } // namespace ArmISA diff --git a/src/cpu/base.cc b/src/cpu/base.cc index 084c1e5296..fb99712e89 100644 --- a/src/cpu/base.cc +++ b/src/cpu/base.cc @@ -185,6 +185,17 @@ BaseCPU::~BaseCPU() { } +void +BaseCPU::postInterrupt(ThreadID tid, int int_num, int index) +{ + interrupts[tid]->post(int_num, index); + // Only wake up syscall emulation if it is not waiting on a futex. + // This is to model the fact that instructions such as ARM SEV + // should wake up a WFE sleep, but not a futex syscall WAIT. */ + if (FullSystem || !system->futexMap.is_waiting(threadContexts[tid])) + wakeup(tid); +} + void BaseCPU::armMonitor(ThreadID tid, Addr address) { diff --git a/src/cpu/base.hh b/src/cpu/base.hh index 2b4ac3cfdb..629aaecbdf 100644 --- a/src/cpu/base.hh +++ b/src/cpu/base.hh @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013, 2017 ARM Limited + * Copyright (c) 2011-2013, 2017, 2020 ARM Limited * All rights reserved * * The license below extends only to copyright in the software and shall @@ -232,12 +232,7 @@ class BaseCPU : public ClockedObject virtual void wakeup(ThreadID tid) = 0; void - postInterrupt(ThreadID tid, int int_num, int index) - { - interrupts[tid]->post(int_num, index); - if (FullSystem) - wakeup(tid); - } + postInterrupt(ThreadID tid, int int_num, int index); void clearInterrupt(ThreadID tid, int int_num, int index) diff --git a/src/sim/futex_map.cc b/src/sim/futex_map.cc index f7dde9cc5f..7dabaf2bab 100644 --- a/src/sim/futex_map.cc +++ b/src/sim/futex_map.cc @@ -82,11 +82,10 @@ FutexMap::wakeup(Addr addr, uint64_t tgid, int count) // must only count threads that were actually // woken up by this syscall. auto& tc = waiterList.front().tc; - if (tc->status() == ThreadContext::Suspended) { - tc->activate(); - woken_up++; - } + tc->activate(); + woken_up++; waiterList.pop_front(); + waitingTcs.erase(tc); } if (waiterList.empty()) @@ -108,6 +107,7 @@ FutexMap::suspend_bitset(Addr addr, uint64_t tgid, ThreadContext *tc, } else { it->second.push_back(WaiterState(tc, bitmask)); } + waitingTcs.emplace(tc); /** Suspend the thread context */ tc->suspend(); @@ -133,6 +133,7 @@ FutexMap::wakeup_bitset(Addr addr, uint64_t tgid, int bitmask) if (waiter.checkMask(bitmask)) { waiter.tc->activate(); iter = waiterList.erase(iter); + waitingTcs.erase(waiter.tc); woken_up++; } else { ++iter; @@ -188,3 +189,9 @@ FutexMap::requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2) return woken_up + requeued; } + +bool +FutexMap::is_waiting(ThreadContext *tc) +{ + return waitingTcs.find(tc) != waitingTcs.end(); +} diff --git a/src/sim/futex_map.hh b/src/sim/futex_map.hh index 13caa1291a..081b8506a1 100644 --- a/src/sim/futex_map.hh +++ b/src/sim/futex_map.hh @@ -30,6 +30,7 @@ #define __FUTEX_MAP_HH__ #include +#include #include @@ -111,6 +112,16 @@ class FutexMap : public std::unordered_map * requeued. */ int requeue(Addr addr1, uint64_t tgid, int count, int count2, Addr addr2); + + /** + * Determine if the given thread context is currently waiting on a + * futex wait operation on any of the futexes tracked by this FutexMap. + */ + bool is_waiting(ThreadContext *tc); + + private: + + std::unordered_set waitingTcs; }; #endif // __FUTEX_MAP_HH__