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