#define FW_CFG_PPC_HEIGHT (FW_CFG_ARCH_LOCAL + 0x01)
#define FW_CFG_PPC_DEPTH (FW_CFG_ARCH_LOCAL + 0x02)
#define FW_CFG_PPC_TBFREQ (FW_CFG_ARCH_LOCAL + 0x03)
+#define FW_CFG_PPC_IS_KVM (FW_CFG_ARCH_LOCAL + 0x05)
+#define FW_CFG_PPC_KVM_HC (FW_CFG_ARCH_LOCAL + 0x06)
+#define FW_CFG_PPC_KVM_PID (FW_CFG_ARCH_LOCAL + 0x07)
#define PPC_SERIAL_MM_BAUDBASE 399193
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
if (kvm_enabled()) {
#ifdef CONFIG_KVM
+ uint8_t *hypercall;
+
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
+ hypercall = qemu_malloc(16);
+ kvmppc_get_hypercall(env, hypercall, 16);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
#endif
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_HEIGHT, graphic_height);
fw_cfg_add_i16(fw_cfg, FW_CFG_PPC_DEPTH, graphic_depth);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_IS_KVM, kvm_enabled());
if (kvm_enabled()) {
#ifdef CONFIG_KVM
+ uint8_t *hypercall;
+
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, kvmppc_get_tbfreq());
+ hypercall = qemu_malloc(16);
+ kvmppc_get_hypercall(env, hypercall, 16);
+ fw_cfg_add_bytes(fw_cfg, FW_CFG_PPC_KVM_HC, hypercall, 16);
+ fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_KVM_PID, getpid());
#endif
} else {
fw_cfg_add_i32(fw_cfg, FW_CFG_PPC_TBFREQ, get_ticks_per_sec());
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;
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__ */