Message ID | 20240820142949.533381-12-edgar.iglesias@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | xen: pvh: Partial QOM:fication with new x86 PVH machine | expand |
On Tue, 20 Aug 2024, Edgar E. Iglesias wrote: > From: "Edgar E. Iglesias" <edgar.iglesias@amd.com> > > Add a Xen PVH x86 machine based on the abstract PVH Machine. > > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@amd.com> Reviewed-by: Stefano Stabellini <sstabellini@kernel.org> > --- > hw/i386/xen/meson.build | 1 + > hw/i386/xen/xen-pvh.c | 121 ++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 122 insertions(+) > create mode 100644 hw/i386/xen/xen-pvh.c > > diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build > index 3f0df8bc07..c73c62b8e3 100644 > --- a/hw/i386/xen/meson.build > +++ b/hw/i386/xen/meson.build > @@ -4,6 +4,7 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files( > )) > i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files( > 'xen-hvm.c', > + 'xen-pvh.c', > )) > > i386_ss.add(when: 'CONFIG_XEN_BUS', if_true: files( > diff --git a/hw/i386/xen/xen-pvh.c b/hw/i386/xen/xen-pvh.c > new file mode 100644 > index 0000000000..45645667e9 > --- /dev/null > +++ b/hw/i386/xen/xen-pvh.c > @@ -0,0 +1,121 @@ > +/* > + * QEMU Xen PVH x86 Machine > + * > + * Copyright (c) 2024 Advanced Micro Devices, Inc. > + * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > + > +#include "qemu/osdep.h" > +#include "qemu/error-report.h" > +#include "hw/boards.h" > +#include "sysemu/sysemu.h" > +#include "hw/xen/arch_hvm.h" > +#include <xen/hvm/hvm_info_table.h> > +#include "hw/xen/xen-pvh-common.h" > + > +#define TYPE_XEN_PVH_X86 MACHINE_TYPE_NAME("xenpvh") > +OBJECT_DECLARE_SIMPLE_TYPE(XenPVHx86State, XEN_PVH_X86) > + > +struct XenPVHx86State { > + /*< private >*/ > + XenPVHMachineState parent; > + > + DeviceState **cpu; > +}; > + > +static DeviceState *xen_pvh_cpu_new(MachineState *ms, > + int64_t apic_id) > +{ > + Object *cpu = object_new(ms->cpu_type); > + > + object_property_add_child(OBJECT(ms), "cpu[*]", cpu); > + object_property_set_uint(cpu, "apic-id", apic_id, &error_fatal); > + qdev_realize(DEVICE(cpu), NULL, &error_fatal); > + object_unref(cpu); > + > + return DEVICE(cpu); > +} > + > +static void xen_pvh_init(MachineState *ms) > +{ > + XenPVHx86State *xp = XEN_PVH_X86(ms); > + int i; > + > + /* Create dummy cores. This will indirectly create the APIC MSI window. */ > + xp->cpu = g_malloc(sizeof xp->cpu[0] * ms->smp.max_cpus); > + for (i = 0; i < ms->smp.max_cpus; i++) { > + xp->cpu[i] = xen_pvh_cpu_new(ms, i); > + } > +} > + > +static void xen_pvh_instance_init(Object *obj) > +{ > + XenPVHMachineState *s = XEN_PVH_MACHINE(obj); > + > + /* Default values. */ > + s->cfg.ram_low = (MemMapEntry) { 0x0, 0x80000000U }; > + s->cfg.ram_high = (MemMapEntry) { 0xC000000000ULL, 0x4000000000ULL }; > + s->cfg.pci_intx_irq_base = 16; > +} > + > +/* > + * Deliver INTX interrupts to Xen guest. > + */ > +static void xen_pvh_set_pci_intx_irq(void *opaque, int irq, int level) > +{ > + /* > + * Since QEMU emulates all of the swizziling > + * We don't want Xen to do any additional swizzling in > + * xen_set_pci_intx_level() so we always set device to 0. > + */ > + if (xen_set_pci_intx_level(xen_domid, 0, 0, 0, irq, level)) { > + error_report("xendevicemodel_set_pci_intx_level failed"); > + } > +} > + > +static void xen_pvh_machine_class_init(ObjectClass *oc, void *data) > +{ > + XenPVHMachineClass *xpc = XEN_PVH_MACHINE_CLASS(oc); > + MachineClass *mc = MACHINE_CLASS(oc); > + > + mc->desc = "Xen PVH x86 machine"; > + mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; > + > + /* mc->max_cpus holds the MAX value allowed in the -smp cmd-line opts. */ > + mc->max_cpus = HVM_MAX_VCPUS; > + > + /* We have an implementation specific init to create CPU objects. */ > + xpc->init = xen_pvh_init; > + > + /* > + * PCI INTX routing. > + * > + * We describe the mapping between the 4 INTX interrupt and GSIs > + * using xen_set_pci_link_route(). xen_pvh_set_pci_intx_irq is > + * used to deliver the interrupt. > + */ > + xpc->set_pci_intx_irq = xen_pvh_set_pci_intx_irq; > + xpc->set_pci_link_route = xen_set_pci_link_route; > + > + /* List of supported features known to work on PVH x86. */ > + xpc->has_pci = true; > + > + xen_pvh_class_setup_common_props(xpc); > +} > + > +static const TypeInfo xen_pvh_x86_machine_type = { > + .name = TYPE_XEN_PVH_X86, > + .parent = TYPE_XEN_PVH_MACHINE, > + .class_init = xen_pvh_machine_class_init, > + .instance_init = xen_pvh_instance_init, > + .instance_size = sizeof(XenPVHx86State), > +}; > + > +static void xen_pvh_machine_register_types(void) > +{ > + type_register_static(&xen_pvh_x86_machine_type); > +} > + > +type_init(xen_pvh_machine_register_types) > -- > 2.43.0 >
diff --git a/hw/i386/xen/meson.build b/hw/i386/xen/meson.build index 3f0df8bc07..c73c62b8e3 100644 --- a/hw/i386/xen/meson.build +++ b/hw/i386/xen/meson.build @@ -4,6 +4,7 @@ i386_ss.add(when: 'CONFIG_XEN', if_true: files( )) i386_ss.add(when: ['CONFIG_XEN', xen], if_true: files( 'xen-hvm.c', + 'xen-pvh.c', )) i386_ss.add(when: 'CONFIG_XEN_BUS', if_true: files( diff --git a/hw/i386/xen/xen-pvh.c b/hw/i386/xen/xen-pvh.c new file mode 100644 index 0000000000..45645667e9 --- /dev/null +++ b/hw/i386/xen/xen-pvh.c @@ -0,0 +1,121 @@ +/* + * QEMU Xen PVH x86 Machine + * + * Copyright (c) 2024 Advanced Micro Devices, Inc. + * Written by Edgar E. Iglesias <edgar.iglesias@amd.com> + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ + +#include "qemu/osdep.h" +#include "qemu/error-report.h" +#include "hw/boards.h" +#include "sysemu/sysemu.h" +#include "hw/xen/arch_hvm.h" +#include <xen/hvm/hvm_info_table.h> +#include "hw/xen/xen-pvh-common.h" + +#define TYPE_XEN_PVH_X86 MACHINE_TYPE_NAME("xenpvh") +OBJECT_DECLARE_SIMPLE_TYPE(XenPVHx86State, XEN_PVH_X86) + +struct XenPVHx86State { + /*< private >*/ + XenPVHMachineState parent; + + DeviceState **cpu; +}; + +static DeviceState *xen_pvh_cpu_new(MachineState *ms, + int64_t apic_id) +{ + Object *cpu = object_new(ms->cpu_type); + + object_property_add_child(OBJECT(ms), "cpu[*]", cpu); + object_property_set_uint(cpu, "apic-id", apic_id, &error_fatal); + qdev_realize(DEVICE(cpu), NULL, &error_fatal); + object_unref(cpu); + + return DEVICE(cpu); +} + +static void xen_pvh_init(MachineState *ms) +{ + XenPVHx86State *xp = XEN_PVH_X86(ms); + int i; + + /* Create dummy cores. This will indirectly create the APIC MSI window. */ + xp->cpu = g_malloc(sizeof xp->cpu[0] * ms->smp.max_cpus); + for (i = 0; i < ms->smp.max_cpus; i++) { + xp->cpu[i] = xen_pvh_cpu_new(ms, i); + } +} + +static void xen_pvh_instance_init(Object *obj) +{ + XenPVHMachineState *s = XEN_PVH_MACHINE(obj); + + /* Default values. */ + s->cfg.ram_low = (MemMapEntry) { 0x0, 0x80000000U }; + s->cfg.ram_high = (MemMapEntry) { 0xC000000000ULL, 0x4000000000ULL }; + s->cfg.pci_intx_irq_base = 16; +} + +/* + * Deliver INTX interrupts to Xen guest. + */ +static void xen_pvh_set_pci_intx_irq(void *opaque, int irq, int level) +{ + /* + * Since QEMU emulates all of the swizziling + * We don't want Xen to do any additional swizzling in + * xen_set_pci_intx_level() so we always set device to 0. + */ + if (xen_set_pci_intx_level(xen_domid, 0, 0, 0, irq, level)) { + error_report("xendevicemodel_set_pci_intx_level failed"); + } +} + +static void xen_pvh_machine_class_init(ObjectClass *oc, void *data) +{ + XenPVHMachineClass *xpc = XEN_PVH_MACHINE_CLASS(oc); + MachineClass *mc = MACHINE_CLASS(oc); + + mc->desc = "Xen PVH x86 machine"; + mc->default_cpu_type = TARGET_DEFAULT_CPU_TYPE; + + /* mc->max_cpus holds the MAX value allowed in the -smp cmd-line opts. */ + mc->max_cpus = HVM_MAX_VCPUS; + + /* We have an implementation specific init to create CPU objects. */ + xpc->init = xen_pvh_init; + + /* + * PCI INTX routing. + * + * We describe the mapping between the 4 INTX interrupt and GSIs + * using xen_set_pci_link_route(). xen_pvh_set_pci_intx_irq is + * used to deliver the interrupt. + */ + xpc->set_pci_intx_irq = xen_pvh_set_pci_intx_irq; + xpc->set_pci_link_route = xen_set_pci_link_route; + + /* List of supported features known to work on PVH x86. */ + xpc->has_pci = true; + + xen_pvh_class_setup_common_props(xpc); +} + +static const TypeInfo xen_pvh_x86_machine_type = { + .name = TYPE_XEN_PVH_X86, + .parent = TYPE_XEN_PVH_MACHINE, + .class_init = xen_pvh_machine_class_init, + .instance_init = xen_pvh_instance_init, + .instance_size = sizeof(XenPVHx86State), +}; + +static void xen_pvh_machine_register_types(void) +{ + type_register_static(&xen_pvh_x86_machine_type); +} + +type_init(xen_pvh_machine_register_types)