|
@@ -22,6 +22,7 @@
|
|
#include <mach/mach_time.h>
|
|
#include <mach/mach_time.h>
|
|
|
|
|
|
#include "exec/address-spaces.h"
|
|
#include "exec/address-spaces.h"
|
|
|
|
+#include "hw/boards.h"
|
|
#include "hw/irq.h"
|
|
#include "hw/irq.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "qemu/main-loop.h"
|
|
#include "sysemu/cpus.h"
|
|
#include "sysemu/cpus.h"
|
|
@@ -304,6 +305,8 @@ static const bool windows_workaround_enabled = true;
|
|
|
|
|
|
static void hvf_wfi(CPUState *cpu);
|
|
static void hvf_wfi(CPUState *cpu);
|
|
|
|
|
|
|
|
+static uint32_t chosen_ipa_bit_size;
|
|
|
|
+
|
|
typedef struct HVFVTimer {
|
|
typedef struct HVFVTimer {
|
|
/* Vtimer value during migration and paused state */
|
|
/* Vtimer value during migration and paused state */
|
|
uint64_t vtimer_val;
|
|
uint64_t vtimer_val;
|
|
@@ -846,6 +849,20 @@ static uint64_t hvf_get_reg(CPUState *cpu, int rt)
|
|
return val;
|
|
return val;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#if !defined(CONFIG_HVF_PRIVATE)
|
|
|
|
+
|
|
|
|
+static void clamp_id_aa64mmfr0_parange_to_ipa_size(uint64_t *id_aa64mmfr0)
|
|
|
|
+{
|
|
|
|
+ uint32_t ipa_size = chosen_ipa_bit_size ?
|
|
|
|
+ chosen_ipa_bit_size : hvf_arm_get_max_ipa_bit_size();
|
|
|
|
+
|
|
|
|
+ /* Clamp down the PARange to the IPA size the kernel supports. */
|
|
|
|
+ uint8_t index = round_down_to_parange_index(ipa_size);
|
|
|
|
+ *id_aa64mmfr0 = (*id_aa64mmfr0 & ~R_ID_AA64MMFR0_PARANGE_MASK) | index;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
|
static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
|
{
|
|
{
|
|
ARMISARegisters host_isar = {};
|
|
ARMISARegisters host_isar = {};
|
|
@@ -889,6 +906,10 @@ static bool hvf_arm_get_host_cpu_features(ARMHostCPUFeatures *ahcf)
|
|
r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr);
|
|
r |= hv_vcpu_get_sys_reg(fd, HV_SYS_REG_MIDR_EL1, &ahcf->midr);
|
|
r |= hv_vcpu_destroy(fd);
|
|
r |= hv_vcpu_destroy(fd);
|
|
|
|
|
|
|
|
+#if !defined(CONFIG_HVF_PRIVATE)
|
|
|
|
+ clamp_id_aa64mmfr0_parange_to_ipa_size(&host_isar.id_aa64mmfr0);
|
|
|
|
+#endif
|
|
|
|
+
|
|
ahcf->isar = host_isar;
|
|
ahcf->isar = host_isar;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -924,7 +945,6 @@ static hv_return_t hvf_vcpu_get_actlr(hv_vcpu_t vcpu, uint64_t* value)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
static hv_return_t hvf_vcpu_set_actlr(hv_vcpu_t vcpu, uint64_t value)
|
|
static hv_return_t hvf_vcpu_set_actlr(hv_vcpu_t vcpu, uint64_t value)
|
|
{
|
|
{
|
|
#if defined(CONFIG_HVF_PRIVATE)
|
|
#if defined(CONFIG_HVF_PRIVATE)
|
|
@@ -938,6 +958,34 @@ static hv_return_t hvf_vcpu_set_actlr(hv_vcpu_t vcpu, uint64_t value)
|
|
#endif
|
|
#endif
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+#if !defined(CONFIG_HVF_PRIVATE)
|
|
|
|
+
|
|
|
|
+uint32_t hvf_arm_get_default_ipa_bit_size(void)
|
|
|
|
+{
|
|
|
|
+ uint32_t default_ipa_size;
|
|
|
|
+ hv_return_t ret = hv_vm_config_get_default_ipa_size(&default_ipa_size);
|
|
|
|
+ assert_hvf_ok(ret);
|
|
|
|
+
|
|
|
|
+ return default_ipa_size;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+uint32_t hvf_arm_get_max_ipa_bit_size(void)
|
|
|
|
+{
|
|
|
|
+ uint32_t max_ipa_size;
|
|
|
|
+ hv_return_t ret = hv_vm_config_get_max_ipa_size(&max_ipa_size);
|
|
|
|
+ assert_hvf_ok(ret);
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * We clamp any IPA size we want to back the VM with to a valid PARange
|
|
|
|
+ * value so the guest doesn't try and map memory outside of the valid range.
|
|
|
|
+ * This logic just clamps the passed in IPA bit size to the first valid
|
|
|
|
+ * PARange value <= to it.
|
|
|
|
+ */
|
|
|
|
+ return round_down_to_parange_bit_size(max_ipa_size);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+#endif
|
|
|
|
+
|
|
void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
|
void hvf_arm_set_cpu_features_from_host(ARMCPU *cpu)
|
|
{
|
|
{
|
|
if (!arm_host_cpu_features.dtb_compatible) {
|
|
if (!arm_host_cpu_features.dtb_compatible) {
|
|
@@ -967,14 +1015,22 @@ hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range)
|
|
{
|
|
{
|
|
hv_return_t ret;
|
|
hv_return_t ret;
|
|
hv_vm_config_t config = hv_vm_config_create();
|
|
hv_vm_config_t config = hv_vm_config_create();
|
|
|
|
+
|
|
#if defined(CONFIG_HVF_PRIVATE)
|
|
#if defined(CONFIG_HVF_PRIVATE)
|
|
if (hvf_tso_mode) {
|
|
if (hvf_tso_mode) {
|
|
_hv_vm_config_set_isa(config, HV_VM_CONFIG_ISA_PRIVATE);
|
|
_hv_vm_config_set_isa(config, HV_VM_CONFIG_ISA_PRIVATE);
|
|
}
|
|
}
|
|
- ret = hv_vm_create(config);
|
|
|
|
#else
|
|
#else
|
|
- ret = hv_vm_create(config);
|
|
|
|
|
|
+ ret = hv_vm_config_set_ipa_size(config, pa_range);
|
|
|
|
+ if (ret != HV_SUCCESS) {
|
|
|
|
+ goto cleanup;
|
|
|
|
+ }
|
|
|
|
+ chosen_ipa_bit_size = pa_range;
|
|
#endif
|
|
#endif
|
|
|
|
+
|
|
|
|
+ ret = hv_vm_create(config);
|
|
|
|
+
|
|
|
|
+cleanup:
|
|
os_release(config);
|
|
os_release(config);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
@@ -1045,6 +1101,13 @@ int hvf_arch_init_vcpu(CPUState *cpu)
|
|
&arm_cpu->isar.id_aa64mmfr0);
|
|
&arm_cpu->isar.id_aa64mmfr0);
|
|
assert_hvf_ok(ret);
|
|
assert_hvf_ok(ret);
|
|
|
|
|
|
|
|
+#if !defined(CONFIG_HVF_PRIVATE)
|
|
|
|
+ clamp_id_aa64mmfr0_parange_to_ipa_size(&arm_cpu->isar.id_aa64mmfr0);
|
|
|
|
+ ret = hv_vcpu_set_sys_reg(cpu->accel->fd, HV_SYS_REG_ID_AA64MMFR0_EL1,
|
|
|
|
+ arm_cpu->isar.id_aa64mmfr0);
|
|
|
|
+ assert_hvf_ok(ret);
|
|
|
|
+#endif
|
|
|
|
+
|
|
/* enable TSO mode */
|
|
/* enable TSO mode */
|
|
if (hvf_tso_mode) {
|
|
if (hvf_tso_mode) {
|
|
uint64_t actlr;
|
|
uint64_t actlr;
|