From: Zhang Xiantao <[EMAIL PROTECTED]> Add ia64 platform support which is ported from pc.c.
Signed-off-by: Zhang Xiantao <[EMAIL PROTECTED]> Signed-off-by: Avi Kivity <[EMAIL PROTECTED]> diff --git a/qemu/hw/ipf.c b/qemu/hw/ipf.c new file mode 100644 index 0000000..012073d --- /dev/null +++ b/qemu/hw/ipf.c @@ -0,0 +1,390 @@ +/* + * Itanium Platforma Emulator derived from QEMU PC System Emulator + * + * Copyright (c) 2003-2004 Fabrice Bellard + * + * Copyright (c) 2007 Intel + * Ported for IA64 Platform Zhang Xiantao <[EMAIL PROTECTED]> + * + * 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 "vl.h" +#include "firmware.h" +#include "ia64intrin.h" +#ifdef USE_KVM +#include "qemu-kvm.h" +extern int kvm_allowed; +#endif + +/* output Bochs bios info messages */ +//#define DEBUG_BIOS + +#define FW_FILENAME "Flash.fd" + +/* Leave a chunk of memory at the top of RAM for the BIOS ACPI tables. */ +#define ACPI_DATA_SIZE 0x10000 + +static fdctrl_t *floppy_controller; +static PCIDevice *i440fx_state; + +static const int ide_iobase[2] = { 0x1f0, 0x170 }; +static const int ide_iobase2[2] = { 0x3f6, 0x376 }; +static const int ide_irq[2] = { 14, 15 }; + +#define NE2000_NB_MAX 6 + +static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 }; +static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 }; + +static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 }; +static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 }; + +static int parallel_io[MAX_PARALLEL_PORTS] = { 0x378, 0x278, 0x3bc }; +static int parallel_irq[MAX_PARALLEL_PORTS] = { 7, 7, 7 }; + +#ifdef HAS_AUDIO +static void audio_init (PCIBus *pci_bus, qemu_irq *pic) +{ + struct soundhw *c; + int audio_enabled = 0; + + for (c = soundhw; !audio_enabled && c->name; ++c) { + audio_enabled = c->enabled; + } + + if (audio_enabled) { + AudioState *s; + + s = AUD_init (); + if (s) { + for (c = soundhw; c->name; ++c) { + if (c->enabled) { + if (c->isa) { + c->init.init_isa (s, pic); + } + else { + if (pci_bus) { + c->init.init_pci (pci_bus, s); + } + } + } + } + } + } +} +#endif + +static void pc_init_ne2k_isa(NICInfo *nd, qemu_irq *pic) +{ + static int nb_ne2k = 0; + + if (nb_ne2k == NE2000_NB_MAX) + return; + isa_ne2000_init(ne2000_io[nb_ne2k], pic[ne2000_irq[nb_ne2k]], nd); + nb_ne2k++; +} + +#ifdef USE_KVM +extern kvm_context_t kvm_context; +extern int kvm_allowed; + +void kvm_sync_icache(unsigned long address, int len) +{ + int l; + + for(l = 0; l < (len + 32); l += 32) + __ia64_fc(address + l); + + ia64_sync_i(); + ia64_srlz_i(); +} +#endif + +static void main_cpu_reset(void *opaque) +{ + CPUState *env = opaque; + cpu_reset(env); +} +static void pic_irq_request(void *opaque, int irq, int level) +{ + fprintf(stderr,"pic_irq_request called!\n"); +} + +/* IPF hardware initialisation */ +static void ipf_init1(ram_addr_t ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, int snapshot, + const char *kernel_filename, const char *kernel_cmdline, + const char *initrd_filename, + int pci_enabled) +{ + char buf[1024]; + int i; + ram_addr_t ram_addr, vga_ram_addr; + ram_addr_t above_4g_mem_size = 0; + PCIBus *pci_bus; + int piix3_devfn = -1; + CPUState *env; + NICInfo *nd; + qemu_irq *cpu_irq; + qemu_irq *i8259; + + if (ram_size >= 0xc0000000 ) { + above_4g_mem_size = ram_size - 0xc0000000; + ram_size = 0xc0000000; + } + + /* init CPUs */ + for(i = 0; i < smp_cpus; i++) { + env = cpu_init(); + if (i != 0) + env->hflags |= HF_HALTED_MASK; + register_savevm("cpu", i, 4, cpu_save, cpu_load, env); + qemu_register_reset(main_cpu_reset, env); + } + + /* allocate RAM */ +#ifdef USE_KVM +#ifdef KVM_CAP_USER_MEMORY + if (kvm_allowed && kvm_qemu_check_extension(KVM_CAP_USER_MEMORY)) { + ram_addr = qemu_ram_alloc(0xa0000); + cpu_register_physical_memory(0, 0xa0000, ram_addr); + kvm_cpu_register_physical_memory(0, 0xa0000, ram_addr); + + ram_addr = qemu_ram_alloc(0x20000); // Workaround 0xa0000-0xc0000 + + ram_addr = qemu_ram_alloc(0x40000); + cpu_register_physical_memory(0xc0000, 0x40000, ram_addr); + kvm_cpu_register_physical_memory(0xc0000, 0x40000, ram_addr); + + ram_addr = qemu_ram_alloc(ram_size - 0x100000); + cpu_register_physical_memory(0x100000, ram_size - 0x100000, ram_addr); + kvm_cpu_register_physical_memory(0x100000, ram_size - 0x100000, + ram_addr); + } else +#endif +#endif + { + ram_addr = qemu_ram_alloc(ram_size); + cpu_register_physical_memory(0, ram_size, ram_addr); + } + /* allocate VGA RAM */ + vga_ram_addr = qemu_ram_alloc(vga_ram_size); + + /* above 4giga memory allocation */ + if (above_4g_mem_size > 0) { + ram_addr = qemu_ram_alloc(above_4g_mem_size); + cpu_register_physical_memory(0x100000000, above_4g_mem_size, ram_addr); +#ifdef USE_KVM + if (kvm_allowed) + kvm_cpu_register_physical_memory(0x100000000, above_4g_mem_size, + ram_addr); +#endif + } + + /*Load firware to its proper position.*/ +#ifdef USE_KVM + if (kvm_allowed) { + int r; + unsigned long image_size; + char *image = NULL; + char *fw_image_start; + ram_addr_t fw_offset = qemu_ram_alloc(GFW_SIZE); + char *fw_start = phys_ram_base + fw_offset; + + snprintf(buf, sizeof(buf), "%s/%s", bios_dir, FW_FILENAME); + image = read_image(buf, &image_size ); + if (NULL == image || !image_size) { + fprintf(stderr, "Error when reading Guest Firmware!\n"); + return ; + } + fw_image_start = fw_start + GFW_SIZE - image_size; + +#ifdef KVM_CAP_USER_MEMORY + r = kvm_qemu_check_extension(KVM_CAP_USER_MEMORY); + if (r) { + cpu_register_physical_memory(GFW_START, GFW_SIZE, fw_offset); + kvm_cpu_register_physical_memory(GFW_START,GFW_SIZE, fw_offset); + memcpy(fw_image_start, image, image_size); + } + else +#endif + { + fw_start = kvm_create_phys_mem(kvm_context, (uint32_t)(-image_size), + image_size, 0, 1); + if (!fw_start) + exit(1); + fw_image_start = fw_start + GFW_SIZE - image_size; + memcpy(fw_image_start, image, image_size); + } + free(image); + kvm_sync_icache((unsigned long)fw_image_start, image_size); + kvm_ia64_build_hob(ram_size, smp_cpus, fw_start); + } +#endif + + cpu_irq = qemu_allocate_irqs(pic_irq_request, first_cpu, 1); + i8259 = i8259_init(cpu_irq[0]); + + if (pci_enabled) { + pci_bus = i440fx_init(&i440fx_state, i8259); + piix3_devfn = piix3_init(pci_bus, -1); + } else { + pci_bus = NULL; + } + + if (cirrus_vga_enabled) { + if (pci_enabled) { + pci_cirrus_vga_init(pci_bus, + ds, phys_ram_base + vga_ram_addr, + vga_ram_addr, vga_ram_size); + } else { + isa_cirrus_vga_init(ds, phys_ram_base + vga_ram_addr, + vga_ram_addr, vga_ram_size); + } + } else { + if (pci_enabled) { + pci_vga_init(pci_bus, ds, phys_ram_base + vga_ram_addr, + vga_ram_addr, vga_ram_size, 0, 0); + } else { + isa_vga_init(ds, phys_ram_base + vga_ram_addr, + vga_ram_addr, vga_ram_size); + } + } + + if (pci_enabled) { + pic_set_alt_irq_func(isa_pic, NULL, NULL); + } + + for(i = 0; i < MAX_SERIAL_PORTS; i++) { + if (serial_hds[i]) { + serial_init(serial_io[i], i8259[serial_irq[i]], serial_hds[i]); + } + } + + for(i = 0; i < MAX_PARALLEL_PORTS; i++) { + if (parallel_hds[i]) { + parallel_init(parallel_io[i], i8259[parallel_irq[i]], + parallel_hds[i]); + } + } + + for(i = 0; i < nb_nics; i++) { + nd = &nd_table[i]; + if (!nd->model) { + if (pci_enabled) { + nd->model = "ne2k_pci"; + } else { + nd->model = "ne2k_isa"; + } + } + if (strcmp(nd->model, "ne2k_isa") == 0) { + pc_init_ne2k_isa(nd, i8259); + } else if (pci_enabled) { + if (strcmp(nd->model, "?") == 0) + fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n"); + pci_nic_init(pci_bus, nd, -1); + } else if (strcmp(nd->model, "?") == 0) { + fprintf(stderr, "qemu: Supported ISA NICs: ne2k_isa\n"); + exit(1); + } else { + fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model); + exit(1); + } + } + +#undef USE_HYPERCALL // Disable hypercall now, due to shor of support for VT-i. +#ifdef USE_HYPERCALL + pci_hypercall_init(pci_bus); +#endif + if (pci_enabled) { + pci_piix3_ide_init(pci_bus, bs_table, piix3_devfn + 1, i8259); + } else { + for(i = 0; i < 2; i++) { + isa_ide_init(ide_iobase[i], ide_iobase2[i], i8259[ide_irq[i]], + bs_table[2 * i], bs_table[2 * i + 1]); + } + } + + i8042_init(i8259[1], i8259[12], 0x60); + DMA_init(0); +#ifdef HAS_AUDIO + audio_init(pci_enabled ? pci_bus : NULL, i8259); +#endif + + floppy_controller = fdctrl_init(i8259[6], 2, 0, 0x3f0, fd_table); + + /*Disable cmos support for ia64.*/ + //cmos_init(ram_size, above_4g_mem_size, boot_device, bs_table, smp_cpus); + + if (pci_enabled && usb_enabled) { + usb_uhci_piix3_init(pci_bus, piix3_devfn + 2); + } + + if (pci_enabled && acpi_enabled) { + uint8_t *eeprom_buf = qemu_mallocz(8 * 256); /* XXX: make this persistent */ + i2c_bus *smbus; + + /* TODO: Populate SPD eeprom data. */ + smbus = piix4_pm_init(pci_bus, piix3_devfn + 3, 0xb100); + for (i = 0; i < 8; i++) { + smbus_eeprom_device_init(smbus, 0x50 + i, eeprom_buf + (i * 256)); + } + } + + if (i440fx_state) { + i440fx_init_memory_mappings(i440fx_state); + } +#if 0 + /* ??? Need to figure out some way for the user to + specify SCSI devices. */ + if (pci_enabled) { + void *scsi; + BlockDriverState *bdrv; + + scsi = lsi_scsi_init(pci_bus, -1); + bdrv = bdrv_new("scsidisk"); + bdrv_open(bdrv, "scsi_disk.img", 0); + lsi_scsi_attach(scsi, bdrv, -1); + bdrv = bdrv_new("scsicd"); + bdrv_open(bdrv, "scsi_cd.iso", 0); + bdrv_set_type_hint(bdrv, BDRV_TYPE_CDROM); + lsi_scsi_attach(scsi, bdrv, -1); + } +#endif +} + +static void ipf_init_pci(ram_addr_t ram_size, int vga_ram_size, int boot_device, + DisplayState *ds, const char **fd_filename, + int snapshot, + const char *kernel_filename, + const char *kernel_cmdline, + const char *initrd_filename, + const char *cpu_model) +{ + ipf_init1(ram_size, vga_ram_size, boot_device, + ds, fd_filename, snapshot, + kernel_filename, kernel_cmdline, + initrd_filename, 1); +} + +QEMUMachine ipf_machine = { + "itanium", + "Itanium Platform", + ipf_init_pci, +}; ------------------------------------------------------------------------- SF.Net email is sponsored by: Check out the new SourceForge.net Marketplace. It's the best place to buy or sell services for just about anything Open Source. http://sourceforge.net/services/buy/index.php _______________________________________________ kvm-commits mailing list kvm-commits@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/kvm-commits