#define hvf_enabled() (hvf_allowed)
extern bool hvf_kernel_irqchip;
#define hvf_irqchip_in_kernel() (hvf_kernel_irqchip)
+extern bool hvf_nested_virt;
+#define hvf_nested_virt_enabled() (hvf_nested_virt)
#else /* !CONFIG_HVF_IS_POSSIBLE */
#define hvf_enabled() 0
#define hvf_irqchip_in_kernel() 0
+#define hvf_nested_virt_enabled() 0
#endif /* !CONFIG_HVF_IS_POSSIBLE */
+void hvf_nested_virt_enable(bool nested_virt);
+
#define TYPE_HVF_ACCEL ACCEL_CLASS_NAME("hvf")
typedef struct HVFState HVFState;
#include "system/memory.h"
#include "hw/core/boards.h"
#include "hw/core/irq.h"
+#include "hw/arm/virt.h"
#include "qemu/main-loop.h"
#include "system/cpus.h"
#include "arm-powerctl.h"
(1ULL << ARM_FEATURE_PMU) |
(1ULL << ARM_FEATURE_GENERIC_TIMER);
+ if (hvf_nested_virt_enabled()) {
+ ahcf->features |= 1ULL << ARM_FEATURE_EL2;
+ }
+
for (i = 0; i < ARRAY_SIZE(regs); i++) {
r |= hv_vcpu_config_get_feature_reg(config, regs[i].reg,
&host_isar.idregs[regs[i].index]);
assert_hvf_ok(ret);
}
+static bool hvf_arm_el2_supported(void)
+{
+ bool is_nested_virt_supported;
+ if (__builtin_available(macOS 15.0, *)) {
+ hv_return_t ret = hv_vm_config_get_el2_supported(&is_nested_virt_supported);
+ assert_hvf_ok(ret);
+ } else {
+ return false;
+ }
+ return is_nested_virt_supported;
+}
+
+
hv_return_t hvf_arch_vm_create(MachineState *ms, uint32_t pa_range)
{
hv_return_t ret;
}
chosen_ipa_bit_size = pa_range;
+ if (__builtin_available(macOS 15.0, *)) {
+ if (hvf_nested_virt_enabled()) {
+ if (!hvf_arm_el2_supported()) {
+ error_report("Nested virtualization not supported on this system.");
+ goto cleanup;
+ }
+ ret = hv_vm_config_set_el2_enabled(config, true);
+ if (ret != HV_SUCCESS) {
+ error_report("Failed to enable nested virtualization.");
+ goto cleanup;
+ }
+ }
+ }
+
ret = hv_vm_create(config);
if (hvf_irqchip_in_kernel()) {
if (__builtin_available(macOS 15.0, *)) {
assert(ret == QEMU_ARM_POWERCTL_RET_SUCCESS);
}
+static int hvf_psci_get_target_el(void)
+{
+ if (hvf_nested_virt_enabled()) {
+ return 2;
+ }
+ return 1;
+}
/*
* Handle a PSCI call.
*
CPUState *target_cpu_state;
ARMCPU *target_cpu;
uint64_t entry;
- int target_el = 1;
int32_t ret = 0;
trace_arm_psci_call(param[0], param[1], param[2], param[3],
entry = param[2];
context_id = param[3];
ret = arm_set_cpu_on(mpidr, entry, context_id,
- target_el, target_aarch64);
+ hvf_psci_get_target_el(), target_aarch64);
break;
case QEMU_PSCI_0_1_FN_CPU_OFF:
case QEMU_PSCI_0_2_FN_CPU_OFF: