summaryrefslogtreecommitdiff
path: root/src/cpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/cpu')
-rw-r--r--src/cpu/kvm/arm_cpu.cc21
-rw-r--r--src/cpu/kvm/arm_cpu.hh2
2 files changed, 23 insertions, 0 deletions
diff --git a/src/cpu/kvm/arm_cpu.cc b/src/cpu/kvm/arm_cpu.cc
index d1082c53e..e131202a4 100644
--- a/src/cpu/kvm/arm_cpu.cc
+++ b/src/cpu/kvm/arm_cpu.cc
@@ -49,6 +49,7 @@
#include "debug/Kvm.hh"
#include "debug/KvmContext.hh"
#include "debug/KvmInt.hh"
+#include "sim/pseudo_inst.hh"
using namespace ArmISA;
@@ -310,6 +311,26 @@ ArmKvmCPU::updateThreadContext()
updateTCStateMisc();
}
+Tick
+ArmKvmCPU::onKvmExitHypercall()
+{
+ ThreadContext *tc(getContext(0));
+ const uint32_t reg_ip(tc->readIntRegFlat(INTREG_R12));
+ const uint8_t func((reg_ip >> 8) & 0xFF);
+ const uint8_t subfunc(reg_ip & 0xFF);
+
+ DPRINTF(Kvm, "KVM Hypercall: 0x%x/0x%x\n", func, subfunc);
+ const uint64_t ret(PseudoInst::pseudoInst(getContext(0), func, subfunc));
+
+ // Just set the return value using the KVM API instead of messing
+ // with the context. We could have used the context, but that
+ // would have required us to request a full context sync.
+ setOneReg(REG_CORE32(usr_regs.ARM_r0), ret & 0xFFFFFFFF);
+ setOneReg(REG_CORE32(usr_regs.ARM_r1), (ret >> 32) & 0xFFFFFFFF);
+
+ return 0;
+}
+
const ArmKvmCPU::RegIndexVector &
ArmKvmCPU::getRegList() const
{
diff --git a/src/cpu/kvm/arm_cpu.hh b/src/cpu/kvm/arm_cpu.hh
index 687cb48b1..786320cfd 100644
--- a/src/cpu/kvm/arm_cpu.hh
+++ b/src/cpu/kvm/arm_cpu.hh
@@ -94,6 +94,8 @@ class ArmKvmCPU : public BaseKvmCPU
void updateKvmState();
void updateThreadContext();
+ Tick onKvmExitHypercall();
+
/**
* Get a list of registers supported by getOneReg() and setOneReg().
*/