@@ -263,6 +263,15 @@ void apic_designate_bsp(DeviceState *dev, bool bsp)
}
}
+void apic_force_x2apic(DeviceState *dev)
+{
+ if (dev == NULL) {
+ return;
+ }
+
+ APIC_COMMON(dev)->force_x2apic = true;
+}
+
static void apic_reset_common(DeviceState *dev)
{
APICCommonState *s = APIC_COMMON(dev);
@@ -271,6 +280,9 @@ static void apic_reset_common(DeviceState *dev)
bsp = s->apicbase & MSR_IA32_APICBASE_BSP;
s->apicbase = APIC_DEFAULT_ADDRESS | bsp | MSR_IA32_APICBASE_ENABLE;
+ if (s->force_x2apic) {
+ s->apicbase |= MSR_IA32_APICBASE_EXTD;
+ }
s->id = s->initial_apic_id;
apic_reset_irq_delivered();
@@ -19,6 +19,7 @@ void apic_init_reset(DeviceState *s);
void apic_sipi(DeviceState *s);
void apic_poll_irq(DeviceState *d);
void apic_designate_bsp(DeviceState *d, bool bsp);
+void apic_force_x2apic(DeviceState *d);
int apic_get_highest_priority_irr(DeviceState *dev);
/* pc.c */
@@ -187,6 +187,7 @@ struct APICCommonState {
DeviceState *vapic;
hwaddr vapic_paddr; /* note: persistence via kvmvapic */
bool legacy_instance_id;
+ bool force_x2apic;
};
typedef struct VAPICState {
@@ -137,6 +137,11 @@ int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp)
tdx_caps->nr_cpuid_configs = TDX1_MAX_NR_CPUID_CONFIGS;
tdx_ioctl(KVM_TDX_CAPABILITIES, 0, tdx_caps);
+ if (!kvm_enable_x2apic()) {
+ error_report("Failed to enable x2apic in KVM");
+ exit(1);
+ }
+
qemu_add_machine_init_done_late_notifier(&tdx_machine_done_late_notify);
return 0;
}
@@ -279,6 +284,8 @@ void tdx_post_init_vcpu(CPUState *cpu)
hob = tdx_get_hob_entry(tdx);
_tdx_ioctl(cpu, KVM_TDX_INIT_VCPU, 0, (void *)hob->address);
+
+ apic_force_x2apic(X86_CPU(cpu)->apic_state);
}
static bool tdx_guest_get_debug(Object *obj, Error **errp)