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