implement dynamically allocateable guest to host callbacks

This commit is contained in:
disjtqz
2023-10-11 11:58:15 -04:00
committed by Radosław Gliński
parent d0a6cec024
commit 43fd396db7
5 changed files with 243 additions and 43 deletions

View File

@@ -38,7 +38,9 @@ struct GuestPseudoStackTrace {
};
class Assembler;
class CodeCache;
using GuestTrampolineProc = void (*)(ppc::PPCContext* context, void* userarg1,
void* userarg2);
using SimpleGuestTrampolineProc = void (*)(ppc::PPCContext*);
class Backend {
public:
explicit Backend();
@@ -95,11 +97,74 @@ class Backend {
virtual bool PopulatePseudoStacktrace(GuestPseudoStackTrace* st) {
return false;
}
virtual uint32_t CreateGuestTrampoline(GuestTrampolineProc proc,
void* userdata1, void* userdata2,
bool long_term = false) {
return 0;
}
uint32_t CreateGuestTrampoline(void (*func)(ppc::PPCContext*),
bool long_term = false) {
return CreateGuestTrampoline(
reinterpret_cast<GuestTrampolineProc>(reinterpret_cast<void*>(func)),
nullptr, nullptr);
}
// if long-term, allocate towards the back of bitset to make allocating short
// term ones faster
uint32_t CreateLongTermGuestTrampoline(void (*func)(ppc::PPCContext*)) {
return CreateGuestTrampoline(
reinterpret_cast<GuestTrampolineProc>(reinterpret_cast<void*>(func)),
nullptr, nullptr, true);
}
virtual void FreeGuestTrampoline(uint32_t trampoline_addr) {}
protected:
Processor* processor_ = nullptr;
MachineInfo machine_info_;
CodeCache* code_cache_ = nullptr;
};
/*
* a set of guest trampolines that all have shared ownership.
*/
struct GuestTrampolineGroup
: public std::map<SimpleGuestTrampolineProc, uint32_t> {
Backend* const m_backend;
xe_mutex m_mutex;
uint32_t _NewTrampoline(SimpleGuestTrampolineProc proc, bool longterm) {
uint32_t result;
m_mutex.lock();
auto iter = this->find(proc);
if (iter == this->end()) {
uint32_t new_entry = longterm
? m_backend->CreateLongTermGuestTrampoline(proc)
: m_backend->CreateGuestTrampoline(proc);
this->emplace_hint(iter, proc, new_entry);
result = new_entry;
} else {
result = iter->second;
}
m_mutex.unlock();
return result;
}
public:
GuestTrampolineGroup(Backend* backend) : m_backend(backend) {}
~GuestTrampolineGroup() {
m_mutex.lock();
for (auto&& entry : *this) {
m_backend->FreeGuestTrampoline(entry.second);
}
m_mutex.unlock();
}
uint32_t NewLongtermTrampoline(SimpleGuestTrampolineProc proc) {
return _NewTrampoline(proc, true);
}
uint32_t NewTrampoline(SimpleGuestTrampolineProc proc) {
return _NewTrampoline(proc, false);
}
};
} // namespace backend
} // namespace cpu