Message ID | 1295965760-31508-6-git-send-email-anthony.perard@citrix.com |
---|---|
State | New |
Headers | show |
On 01/25/2011 08:29 AM, anthony.perard@citrix.com wrote: > From: Anthony PERARD<anthony.perard@citrix.com> > > Add the Xen FV (Fully Virtualized) machine to Qemu; > this is groundwork to add Xen device model support in Qemu. > > Signed-off-by: Anthony PERARD<anthony.perard@citrix.com> > Signed-off-by: Stefano Stabellini<stefano.stabellini@eu.citrix.com> > --- > Makefile.target | 3 + > hw/xen_common.h | 5 ++ > hw/xen_machine_fv.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 167 insertions(+), 0 deletions(-) > create mode 100644 hw/xen_machine_fv.c > > diff --git a/Makefile.target b/Makefile.target > index d09719f..07cc21e 100644 > --- a/Makefile.target > +++ b/Makefile.target > @@ -213,6 +213,9 @@ obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o > obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o > obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o > > +# xen full virtualized machine > +obj-i386-$(CONFIG_XEN) += xen_machine_fv.o > + > # Inter-VM PCI shared memory > obj-$(CONFIG_KVM) += ivshmem.o > > diff --git a/hw/xen_common.h b/hw/xen_common.h > index 33df207..b98d107 100644 > --- a/hw/xen_common.h > +++ b/hw/xen_common.h > @@ -18,6 +18,11 @@ > * We don't support Xen prior to 3.3.0. > */ > > +/* Before Xen 4.0.0 */ > +#if CONFIG_XEN_CTRL_INTERFACE_VERSION< 400 > +# define HVM_MAX_VCPUS 32 > +#endif > + > /* Xen unstable */ > #if CONFIG_XEN_CTRL_INTERFACE_VERSION< 410 > typedef int qemu_xc_interface; > diff --git a/hw/xen_machine_fv.c b/hw/xen_machine_fv.c > new file mode 100644 > index 0000000..657c1e8 > --- /dev/null > +++ b/hw/xen_machine_fv.c > @@ -0,0 +1,159 @@ > +/* > + * QEMU Xen FV Machine > + * > + * Copyright (c) 2003-2007 Fabrice Bellard > + * Copyright (c) 2007 Red Hat > + * > + * Permission is hereby granted, free of charge, to any person obtaining a copy > + * of this software and associated documentation files (the "Software"), to deal > + * in the Software without restriction, including without limitation the rights > + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell > + * copies of the Software, and to permit persons to whom the Software is > + * furnished to do so, subject to the following conditions: > + * > + * The above copyright notice and this permission notice shall be included in > + * all copies or substantial portions of the Software. > + * > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL > + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, > + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN > + * THE SOFTWARE. > + */ > + > +#include "hw.h" > +#include "pc.h" > +#include "pci.h" > +#include "usb-uhci.h" > +#include "net.h" > +#include "boards.h" > +#include "ide.h" > +#include "sysemu.h" > +#include "blockdev.h" > +#include "arch_init.h" > + > +#include "xen_common.h" > +#include "xen/hvm/hvm_info_table.h" > + > +#define MAX_IDE_BUS 2 > + > +static void xen_init_fv(ram_addr_t ram_size, > + const char *boot_device, > + const char *kernel_filename, > + const char *kernel_cmdline, > + const char *initrd_filename, > + const char *cpu_model) > +{ > + int i; > + ram_addr_t below_4g_mem_size, above_4g_mem_size = 0; > + PCIBus *pci_bus; > + PCII440FXState *i440fx_state; > + int piix3_devfn = -1; > + qemu_irq *cpu_irq; > + qemu_irq *isa_irq; > + qemu_irq *i8259; > + qemu_irq *cmos_s3; > + qemu_irq *smi_irq; > + IsaIrqState *isa_irq_state; > + DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; > + FDCtrl *floppy_controller; > + BusState *idebus[MAX_IDE_BUS]; > + ISADevice *rtc_state; > + > + CPUState *env; > + > + /* Initialize a dummy CPU */ > + if (cpu_model == NULL) { > +#ifdef TARGET_X86_64 > + cpu_model = "qemu64"; > +#else > + cpu_model = "qemu32"; > +#endif > + } > + env = cpu_init(cpu_model); > + env->halted = 1; > + > + cpu_irq = pc_allocate_cpu_irq(); > + i8259 = i8259_init(cpu_irq[0]); > + isa_irq_state = qemu_mallocz(sizeof (*isa_irq_state)); > + isa_irq_state->i8259 = i8259; > + > + isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); > + > + pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq, ram_size); > + isa_bus_irqs(isa_irq); > + > + pc_register_ferr_irq(isa_reserve_irq(13)); > + > + pc_vga_init(pci_bus); > + > + /* init basic PC hardware */ > + pc_basic_device_init(isa_irq,&floppy_controller,&rtc_state); > + > + for (i = 0; i< nb_nics; i++) { > + NICInfo *nd =&nd_table[i]; > + > + if (nd->model&& strcmp(nd->model, "ne2k_isa") == 0) > + pc_init_ne2k_isa(nd); > + else > + pci_nic_init_nofail(nd, "e1000", NULL); > + } > + > + if (drive_get_max_bus(IF_IDE)>= MAX_IDE_BUS) { > + fprintf(stderr, "qemu: too many IDE bus\n"); > + exit(1); > + } > + > + for (i = 0; i< MAX_IDE_BUS * MAX_IDE_DEVS; i++) { > + hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); > + } > + > + PCIDevice *dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); > + idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); > + idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); > + > + audio_init(isa_irq, pci_bus); > + > + if (ram_size>= 0xe0000000) { > + above_4g_mem_size = ram_size - 0xe0000000; > + below_4g_mem_size = 0xe0000000; > + } else { > + below_4g_mem_size = ram_size; > + } > + pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, > + idebus[0], idebus[1], floppy_controller, rtc_state); > + > + if (usb_enabled) { > + usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); > + } > + > + if (acpi_enabled) { > + cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1); > + smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); > + piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, > + isa_reserve_irq(9), *cmos_s3, *smi_irq, 0); > + } > + > + if (i440fx_state) { > + i440fx_init_memory_mappings(i440fx_state); > + } > + > + pc_pci_device_init(pci_bus); > +} > It's not obvious to me why you can't make use of most of the normal pc code here. Regards, Anthony Liguori > + > +static QEMUMachine xenfv_machine = { > + .name = "xenfv", > + .desc = "Xen Fully-virtualized PC", > + .init = xen_init_fv, > + .max_cpus = HVM_MAX_VCPUS, > + .default_machine_opts = "accel=xen", > +}; > + > +static void xenfv_machine_init(void) > +{ > + qemu_register_machine(&xenfv_machine); > +} > + > +machine_init(xenfv_machine_init); >
On Wed, 26 Jan 2011, Anthony Liguori wrote: > > +static void xen_init_fv(ram_addr_t ram_size, > > + const char *boot_device, > > + const char *kernel_filename, > > + const char *kernel_cmdline, > > + const char *initrd_filename, > > + const char *cpu_model) > > +{ > > + int i; > > + ram_addr_t below_4g_mem_size, above_4g_mem_size = 0; > > + PCIBus *pci_bus; > > + PCII440FXState *i440fx_state; > > + int piix3_devfn = -1; > > + qemu_irq *cpu_irq; > > + qemu_irq *isa_irq; > > + qemu_irq *i8259; > > + qemu_irq *cmos_s3; > > + qemu_irq *smi_irq; > > + IsaIrqState *isa_irq_state; > > + DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; > > + FDCtrl *floppy_controller; > > + BusState *idebus[MAX_IDE_BUS]; > > + ISADevice *rtc_state; > > + > > + CPUState *env; > > + > > + /* Initialize a dummy CPU */ > > + if (cpu_model == NULL) { > > +#ifdef TARGET_X86_64 > > + cpu_model = "qemu64"; > > +#else > > + cpu_model = "qemu32"; > > +#endif > > + } > > + env = cpu_init(cpu_model); > > + env->halted = 1; > > + > > + cpu_irq = pc_allocate_cpu_irq(); > > + i8259 = i8259_init(cpu_irq[0]); > > + isa_irq_state = qemu_mallocz(sizeof (*isa_irq_state)); > > + isa_irq_state->i8259 = i8259; > > + > > + isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); > > + > > + pci_bus = i440fx_init(&i440fx_state,&piix3_devfn, isa_irq, ram_size); > > + isa_bus_irqs(isa_irq); > > + > > + pc_register_ferr_irq(isa_reserve_irq(13)); > > + > > + pc_vga_init(pci_bus); > > + > > + /* init basic PC hardware */ > > + pc_basic_device_init(isa_irq,&floppy_controller,&rtc_state); > > + > > + for (i = 0; i< nb_nics; i++) { > > + NICInfo *nd =&nd_table[i]; > > + > > + if (nd->model&& strcmp(nd->model, "ne2k_isa") == 0) > > + pc_init_ne2k_isa(nd); > > + else > > + pci_nic_init_nofail(nd, "e1000", NULL); > > + } > > + > > + if (drive_get_max_bus(IF_IDE)>= MAX_IDE_BUS) { > > + fprintf(stderr, "qemu: too many IDE bus\n"); > > + exit(1); > > + } > > + > > + for (i = 0; i< MAX_IDE_BUS * MAX_IDE_DEVS; i++) { > > + hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); > > + } > > + > > + PCIDevice *dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); > > + idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); > > + idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); > > + > > + audio_init(isa_irq, pci_bus); > > + > > + if (ram_size>= 0xe0000000) { > > + above_4g_mem_size = ram_size - 0xe0000000; > > + below_4g_mem_size = 0xe0000000; > > + } else { > > + below_4g_mem_size = ram_size; > > + } > > + pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, > > + idebus[0], idebus[1], floppy_controller, rtc_state); > > + > > + if (usb_enabled) { > > + usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); > > + } > > + > > + if (acpi_enabled) { > > + cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1); > > + smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); > > + piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, > > + isa_reserve_irq(9), *cmos_s3, *smi_irq, 0); > > + } > > + > > + if (i440fx_state) { > > + i440fx_init_memory_mappings(i440fx_state); > > + } > > + > > + pc_pci_device_init(pci_bus); > > +} > > > > It's not obvious to me why you can't make use of most of the normal pc > code here. I think we could, but we would need to add few "if (xen_available())".
diff --git a/Makefile.target b/Makefile.target index d09719f..07cc21e 100644 --- a/Makefile.target +++ b/Makefile.target @@ -213,6 +213,9 @@ obj-$(CONFIG_XEN) += xen_backend.o xen_devconfig.o obj-$(CONFIG_XEN) += xen_console.o xenfb.o xen_disk.o xen_nic.o obj-i386-$(CONFIG_XEN) += xen_machine_pv.o xen_domainbuild.o +# xen full virtualized machine +obj-i386-$(CONFIG_XEN) += xen_machine_fv.o + # Inter-VM PCI shared memory obj-$(CONFIG_KVM) += ivshmem.o diff --git a/hw/xen_common.h b/hw/xen_common.h index 33df207..b98d107 100644 --- a/hw/xen_common.h +++ b/hw/xen_common.h @@ -18,6 +18,11 @@ * We don't support Xen prior to 3.3.0. */ +/* Before Xen 4.0.0 */ +#if CONFIG_XEN_CTRL_INTERFACE_VERSION < 400 +# define HVM_MAX_VCPUS 32 +#endif + /* Xen unstable */ #if CONFIG_XEN_CTRL_INTERFACE_VERSION < 410 typedef int qemu_xc_interface; diff --git a/hw/xen_machine_fv.c b/hw/xen_machine_fv.c new file mode 100644 index 0000000..657c1e8 --- /dev/null +++ b/hw/xen_machine_fv.c @@ -0,0 +1,159 @@ +/* + * QEMU Xen FV Machine + * + * Copyright (c) 2003-2007 Fabrice Bellard + * Copyright (c) 2007 Red Hat + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "hw.h" +#include "pc.h" +#include "pci.h" +#include "usb-uhci.h" +#include "net.h" +#include "boards.h" +#include "ide.h" +#include "sysemu.h" +#include "blockdev.h" +#include "arch_init.h" + +#include "xen_common.h" +#include "xen/hvm/hvm_info_table.h" + +#define MAX_IDE_BUS 2 + +static void xen_init_fv(ram_addr_t ram_size, + const char *boot_device, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + int i; + ram_addr_t below_4g_mem_size, above_4g_mem_size = 0; + PCIBus *pci_bus; + PCII440FXState *i440fx_state; + int piix3_devfn = -1; + qemu_irq *cpu_irq; + qemu_irq *isa_irq; + qemu_irq *i8259; + qemu_irq *cmos_s3; + qemu_irq *smi_irq; + IsaIrqState *isa_irq_state; + DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS]; + FDCtrl *floppy_controller; + BusState *idebus[MAX_IDE_BUS]; + ISADevice *rtc_state; + + CPUState *env; + + /* Initialize a dummy CPU */ + if (cpu_model == NULL) { +#ifdef TARGET_X86_64 + cpu_model = "qemu64"; +#else + cpu_model = "qemu32"; +#endif + } + env = cpu_init(cpu_model); + env->halted = 1; + + cpu_irq = pc_allocate_cpu_irq(); + i8259 = i8259_init(cpu_irq[0]); + isa_irq_state = qemu_mallocz(sizeof (*isa_irq_state)); + isa_irq_state->i8259 = i8259; + + isa_irq = qemu_allocate_irqs(isa_irq_handler, isa_irq_state, 24); + + pci_bus = i440fx_init(&i440fx_state, &piix3_devfn, isa_irq, ram_size); + isa_bus_irqs(isa_irq); + + pc_register_ferr_irq(isa_reserve_irq(13)); + + pc_vga_init(pci_bus); + + /* init basic PC hardware */ + pc_basic_device_init(isa_irq, &floppy_controller, &rtc_state); + + for (i = 0; i < nb_nics; i++) { + NICInfo *nd = &nd_table[i]; + + if (nd->model && strcmp(nd->model, "ne2k_isa") == 0) + pc_init_ne2k_isa(nd); + else + pci_nic_init_nofail(nd, "e1000", NULL); + } + + if (drive_get_max_bus(IF_IDE) >= MAX_IDE_BUS) { + fprintf(stderr, "qemu: too many IDE bus\n"); + exit(1); + } + + for (i = 0; i < MAX_IDE_BUS * MAX_IDE_DEVS; i++) { + hd[i] = drive_get(IF_IDE, i / MAX_IDE_DEVS, i % MAX_IDE_DEVS); + } + + PCIDevice *dev = pci_piix3_ide_init(pci_bus, hd, piix3_devfn + 1); + idebus[0] = qdev_get_child_bus(&dev->qdev, "ide.0"); + idebus[1] = qdev_get_child_bus(&dev->qdev, "ide.1"); + + audio_init(isa_irq, pci_bus); + + if (ram_size >= 0xe0000000) { + above_4g_mem_size = ram_size - 0xe0000000; + below_4g_mem_size = 0xe0000000; + } else { + below_4g_mem_size = ram_size; + } + pc_cmos_init(below_4g_mem_size, above_4g_mem_size, boot_device, + idebus[0], idebus[1], floppy_controller, rtc_state); + + if (usb_enabled) { + usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); + } + + if (acpi_enabled) { + cmos_s3 = qemu_allocate_irqs(pc_cmos_set_s3_resume, rtc_state, 1); + smi_irq = qemu_allocate_irqs(pc_acpi_smi_interrupt, first_cpu, 1); + piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100, + isa_reserve_irq(9), *cmos_s3, *smi_irq, 0); + } + + if (i440fx_state) { + i440fx_init_memory_mappings(i440fx_state); + } + + pc_pci_device_init(pci_bus); +} + +static QEMUMachine xenfv_machine = { + .name = "xenfv", + .desc = "Xen Fully-virtualized PC", + .init = xen_init_fv, + .max_cpus = HVM_MAX_VCPUS, + .default_machine_opts = "accel=xen", +}; + +static void xenfv_machine_init(void) +{ + qemu_register_machine(&xenfv_machine); +} + +machine_init(xenfv_machine_init);