2 * QEMU Xen PVH x86 Machine
4 * Copyright (c) 2024 Advanced Micro Devices, Inc.
5 * Written by Edgar E. Iglesias <edgar.iglesias@amd.com>
7 * SPDX-License-Identifier: GPL-2.0-or-later
10 #include "qemu/osdep.h"
11 #include "qemu/error-report.h"
12 #include "hw/boards.h"
13 #include "sysemu/sysemu.h"
14 #include "hw/xen/arch_hvm.h"
15 #include <xen/hvm/hvm_info_table.h>
16 #include "hw/xen/xen-pvh-common.h"
18 #define TYPE_XEN_PVH_X86 MACHINE_TYPE_NAME("xenpvh")
19 OBJECT_DECLARE_SIMPLE_TYPE(XenPVHx86State
, XEN_PVH_X86
)
21 struct XenPVHx86State
{
23 XenPVHMachineState parent
;
28 static DeviceState
*xen_pvh_cpu_new(MachineState
*ms
,
31 Object
*cpu
= object_new(ms
->cpu_type
);
33 object_property_add_child(OBJECT(ms
), "cpu[*]", cpu
);
34 object_property_set_uint(cpu
, "apic-id", apic_id
, &error_fatal
);
35 qdev_realize(DEVICE(cpu
), NULL
, &error_fatal
);
41 static void xen_pvh_init(MachineState
*ms
)
43 XenPVHx86State
*xp
= XEN_PVH_X86(ms
);
46 /* Create dummy cores. This will indirectly create the APIC MSI window. */
47 xp
->cpu
= g_malloc(sizeof xp
->cpu
[0] * ms
->smp
.max_cpus
);
48 for (i
= 0; i
< ms
->smp
.max_cpus
; i
++) {
49 xp
->cpu
[i
] = xen_pvh_cpu_new(ms
, i
);
53 static void xen_pvh_instance_init(Object
*obj
)
55 XenPVHMachineState
*s
= XEN_PVH_MACHINE(obj
);
58 s
->cfg
.ram_low
= (MemMapEntry
) { 0x0, 0x80000000U
};
59 s
->cfg
.ram_high
= (MemMapEntry
) { 0xC000000000ULL
, 0x4000000000ULL
};
60 s
->cfg
.pci_intx_irq_base
= 16;
64 * Deliver INTX interrupts to Xen guest.
66 static void xen_pvh_set_pci_intx_irq(void *opaque
, int irq
, int level
)
69 * Since QEMU emulates all of the swizziling
70 * We don't want Xen to do any additional swizzling in
71 * xen_set_pci_intx_level() so we always set device to 0.
73 if (xen_set_pci_intx_level(xen_domid
, 0, 0, 0, irq
, level
)) {
74 error_report("xendevicemodel_set_pci_intx_level failed");
78 static void xen_pvh_machine_class_init(ObjectClass
*oc
, void *data
)
80 XenPVHMachineClass
*xpc
= XEN_PVH_MACHINE_CLASS(oc
);
81 MachineClass
*mc
= MACHINE_CLASS(oc
);
83 mc
->desc
= "Xen PVH x86 machine";
84 mc
->default_cpu_type
= TARGET_DEFAULT_CPU_TYPE
;
86 /* mc->max_cpus holds the MAX value allowed in the -smp cmd-line opts. */
87 mc
->max_cpus
= HVM_MAX_VCPUS
;
89 /* We have an implementation specific init to create CPU objects. */
90 xpc
->init
= xen_pvh_init
;
92 /* Enable buffered IOREQs. */
93 xpc
->handle_bufioreq
= HVM_IOREQSRV_BUFIOREQ_ATOMIC
;
98 * We describe the mapping between the 4 INTX interrupt and GSIs
99 * using xen_set_pci_link_route(). xen_pvh_set_pci_intx_irq is
100 * used to deliver the interrupt.
102 xpc
->set_pci_intx_irq
= xen_pvh_set_pci_intx_irq
;
103 xpc
->set_pci_link_route
= xen_set_pci_link_route
;
105 /* List of supported features known to work on PVH x86. */
108 xen_pvh_class_setup_common_props(xpc
);
111 static const TypeInfo xen_pvh_x86_machine_type
= {
112 .name
= TYPE_XEN_PVH_X86
,
113 .parent
= TYPE_XEN_PVH_MACHINE
,
114 .class_init
= xen_pvh_machine_class_init
,
115 .instance_init
= xen_pvh_instance_init
,
116 .instance_size
= sizeof(XenPVHx86State
),
119 static void xen_pvh_machine_register_types(void)
121 type_register_static(&xen_pvh_x86_machine_type
);
124 type_init(xen_pvh_machine_register_types
)