aboutsummaryrefslogtreecommitdiff
path: root/target-ppc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2010-08-03 15:22:42 +0200
committerAlexander Graf <agraf@suse.de>2010-08-26 18:13:38 +0200
commit45024f094c223e8096f366520414cdf1a74dbff3 (patch)
tree6e2931a361a98ea331cf36aff8f2bb25572f3efa /target-ppc
parent2446333cd5b5c985f6517dee7004e542ecacd21c (diff)
PPC: Add PV hypercall transport through fw_cfg
On KVM for PPC we need to tell the guest which instructions to use when doing a hypercall. The clean way to do this is to go through an ioctl from userspace and passing it on to the guest using the device tree. So let's do the qemu part here: read out the hypercall and pass it on to the guest's fw_cfg so openBIOS can read it out and expose it again. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r--target-ppc/kvm.c32
-rw-r--r--target-ppc/kvm_ppc.h1
2 files changed, 33 insertions, 0 deletions
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 1079ce1e61..14d6365ee2 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -327,6 +327,38 @@ uint32_t kvmppc_get_tbfreq(void)
return retval;
}
+int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len)
+{
+ uint32_t *hc = (uint32_t*)buf;
+
+#ifdef KVM_CAP_PPC_GET_PVINFO
+ struct kvm_ppc_pvinfo pvinfo;
+
+ if (kvm_check_extension(env->kvm_state, KVM_CAP_PPC_GET_PVINFO) &&
+ !kvm_vm_ioctl(env->kvm_state, KVM_PPC_GET_PVINFO, &pvinfo)) {
+ memcpy(buf, pvinfo.hcall, buf_len);
+
+ return 0;
+ }
+#endif
+
+ /*
+ * Fallback to always fail hypercalls:
+ *
+ * li r3, -1
+ * nop
+ * nop
+ * nop
+ */
+
+ hc[0] = 0x3860ffff;
+ hc[1] = 0x60000000;
+ hc[2] = 0x60000000;
+ hc[3] = 0x60000000;
+
+ return 0;
+}
+
bool kvm_arch_stop_on_emulation_error(CPUState *env)
{
return true;
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index e8d66e88e4..65e31c9b9e 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -15,5 +15,6 @@ int kvmppc_read_host_property(const char *node_path, const char *prop,
void *val, size_t len);
uint32_t kvmppc_get_tbfreq(void);
+int kvmppc_get_hypercall(CPUState *env, uint8_t *buf, int buf_len);
#endif /* __KVM_PPC_H__ */