Made the IDE/PCI system configurable via the config struct.
Starting to add the north/south bridges as virtual devices
DMA still not working....
devices/ide.o \
devices/ram_cd.o \
devices/ram_hd.o \
+ devices/i440fx.o \
+ devices/piix3.o \
# devices/cdrom.o \
# devices/ramdisk.o \
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
+ * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@northwestern.edu>
+ * Chang Seok Bae <jhuell@gmail.com>
+ * Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#ifndef __DEVICES_PIIX3_H__
+#define __DEVICES_PIIX3_H__
+
+
+#ifdef __V3VEE__
+
+#include <palacios/vm_dev.h>
+
+
+struct vm_device * v3_create_piix3(struct vm_device * pci);
+
+#endif // ! __V3VEE__
+
+#endif
int enable_profiling;
int enable_nested_paging;
- int use_ramdisk;
+ int enable_pci;
+
+ int use_ram_cd;
+ int use_ram_hd;
+
void * ramdisk;
int ramdisk_size;
};
// 32 bits access
drive_id->dword_io = 1;
-#if 0
+
// enable DMA access
drive_id->dma_enable = 1;
-#endif
+
// enable LBA access
drive_id->lba_enable = 1;
// Drive Capacity (48 bit LBA)
drive_id->lba_capacity_2 = drive->hd_ops->get_capacity(drive->private_data);
-#if 0
+
// lower byte is the maximum multiple sector size...
drive_id->rw_multiples = 0x8000 | MAX_MULT_SECTORS;
-#endif
-#if 0
+
+
// words 64-70, 54-58 valid
drive_id->field_valid = 0x0007; // DMA + pkg cmd valid
-#endif
+
// copied from CFA540A
- drive_id->buf[63] = 0x0103; // variable (DMA stuff)
+ // drive_id->buf[63] = 0x0103; // variable (DMA stuff)
//drive_id->buf[63] = 0x0000; // variable (DMA stuff)
+ drive_id->buf[63] = 0x0007;
+
// drive_id->buf[64] = 0x0001; // PIO
drive_id->buf[65] = 0x00b4;
// drive_id->buf[80] = 0x1e; // supports up to ATA/ATAPI-4
drive_id->major_rev_num = 0x0040; // supports up to ATA/ATAPI-6
-#if 0
+
drive_id->buf[83] |= 0x0400; // supports 48 bit LBA
drive_id->dma_ultra = 0x2020; // Ultra_DMA_Mode_5_Selected | Ultra_DMA_Mode_5_Supported;
-#endif
+
}
struct ide_internal {
struct ide_channel channels[2];
struct vm_device * pci;
+ struct vm_device * southbridge;
struct pci_device * busmaster_pci;
};
static int init_ide_state(struct vm_device * dev) {
struct ide_internal * ide = (struct ide_internal *)(dev->private_data);
- struct v3_pci_bar bars[6];
- struct pci_device * pci_dev = NULL;
int i, j;
- for (i = 0; i < 2; i++) {
+
+ /*
+ Check if the PIIX 3 actually represents both IDE channels in a single PCI entry */
+
+ for (i = 0; i < 1; i++) {
init_channel(&(ide->channels[i]));
// JRL: this is a terrible hack...
ide->channels[i].irq = PRI_DEFAULT_IRQ + i;
- for (j = 0; j < 6; j++) {
- bars[j].type = PCI_BAR_NONE;
- }
+ if (ide->pci) {
+ struct v3_pci_bar bars[6];
+ struct pci_device * pci_dev = NULL;
- bars[4].type = PCI_BAR_IO;
- bars[4].default_base_port = PRI_DEFAULT_DMA_PORT + (i * 0x8);
- bars[4].num_ports = 8;
-
- if (i == 0) {
- bars[4].io_read = read_pri_dma_port;
- bars[4].io_write = write_pri_dma_port;
- } else {
- bars[4].io_read = read_sec_dma_port;
- bars[4].io_write = write_sec_dma_port;
- }
-
- pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
- pci_config_update, NULL, NULL, dev);
+ for (j = 0; j < 6; j++) {
+ bars[j].type = PCI_BAR_NONE;
+ }
- if (pci_dev == NULL) {
- PrintError("Failed to register IDE BUS %d with PCI\n", i);
- return -1;
- }
- ide->channels[i].pci_dev = pci_dev;
+ bars[4].type = PCI_BAR_IO;
+ bars[4].default_base_port = PRI_DEFAULT_DMA_PORT + (i * 0x8);
+ bars[4].num_ports = 8;
+
+ if (i == 0) {
+ bars[4].io_read = read_pri_dma_port;
+ bars[4].io_write = write_pri_dma_port;
+ } else {
+ bars[4].io_read = read_sec_dma_port;
+ bars[4].io_write = write_sec_dma_port;
+ }
- pci_dev->config_header.vendor_id = 0x1095;
- pci_dev->config_header.device_id = 0x0646;
- pci_dev->config_header.revision = 0x8f07;
- pci_dev->config_header.subclass = 0x01;
- pci_dev->config_header.class = 0x01;
+ pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "V3_IDE", -1, bars,
+ pci_config_update, NULL, NULL, dev);
- pci_dev->config_header.intr_line = PRI_DEFAULT_IRQ + i;
- pci_dev->config_header.intr_pin = 1;
- }
+ if (pci_dev == NULL) {
+ PrintError("Failed to register IDE BUS %d with PCI\n", i);
+ return -1;
+ }
+ ide->channels[i].pci_dev = pci_dev;
+ /* This is for CMD646 devices
+ pci_dev->config_header.vendor_id = 0x1095;
+ pci_dev->config_header.device_id = 0x0646;
+ pci_dev->config_header.revision = 0x8f07;
+ */
+ pci_dev->config_header.vendor_id = 0x8086;
+ pci_dev->config_header.device_id = 0x7010;
+ pci_dev->config_header.revision = 0x8000;
+
+ pci_dev->config_header.subclass = 0x01;
+ pci_dev->config_header.class = 0x01;
+
+
+ pci_dev->config_header.command = 0;
+ pci_dev->config_header.status = 0x0280;
+
+ // pci_dev->config_header.intr_line = PRI_DEFAULT_IRQ + i;
+ // pci_dev->config_header.intr_pin = 1;
+ }
+
- /* Register PIIX3 Busmaster PCI device */
- for (j = 0; j < 6; j++) {
- bars[j].type = PCI_BAR_NONE;
}
- pci_dev = v3_pci_register_device(ide->pci, PCI_STD_DEVICE, 0, "PIIX3 IDE", -1, bars,
- NULL, NULL, NULL, dev);
-
-
- ide->busmaster_pci = pci_dev;
-
- pci_dev->config_header.vendor_id = 0x8086;
- pci_dev->config_header.device_id = 0x7010;
- pci_dev->config_header.revision = 0x80;
- pci_dev->config_header.subclass = 0x01;
- pci_dev->config_header.class = 0x01;
-
-
return 0;
}
};
-struct vm_device * v3_create_ide(struct vm_device * pci) {
+struct vm_device * v3_create_ide(struct vm_device * pci, struct vm_device * southbridge) {
struct ide_internal * ide = (struct ide_internal *)V3_Malloc(sizeof(struct ide_internal));
struct vm_device * device = v3_create_device("IDE", &dev_ops, ide);
ide->pci = pci;
+ ide->southbridge = southbridge;
PrintDebug("IDE: Creating IDE bus x 2\n");
static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) {
struct v3_pci_bar * bar = &(pci->bar[bar_num]);
- PrintError("Updating BAR Register (Dev=%s) (bar=%d) (old_val=%x) (new_val=%x)\n",
+ PrintDebug("Updating BAR Register (Dev=%s) (bar=%d) (old_val=%x) (new_val=%x)\n",
pci->name, bar_num, bar->val, new_val);
switch (bar->type) {
case PCI_BAR_IO: {
int i = 0;
- PrintError("\tRehooking %d IO ports from base %x to %x\n",
+ PrintDebug("\tRehooking %d IO ports from base %x to %x\n",
bar->num_ports, PCI_IO_BASE(bar->val), PCI_IO_BASE(new_val));
// only do this if pci device is enabled....
break;
}
case PCI_BAR_NONE: {
- PrintError("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n",
+ PrintDebug("Reprogramming an unsupported BAR register (Dev=%s) (bar=%d) (val=%x)\n",
pci->name, bar_num, new_val);
break;
}
--- /dev/null
+/*
+ * This file is part of the Palacios Virtual Machine Monitor developed
+ * by the V3VEE Project with funding from the United States National
+ * Science Foundation and the Department of Energy.
+ *
+ * The V3VEE Project is a joint project between Northwestern University
+ * and the University of New Mexico. You can find out more at
+ * http://www.v3vee.org
+ *
+ * Copyright (c) 2009, Lei Xia <lxia@northwestern.edu>
+ * Copyright (c) 2009, Chang Seok Bae <jhuell@gmail.com>
+ * Copyright (c) 2009, Jack Lange <jarusl@cs.northwestern.edu>
+ * Copyright (c) 2009, The V3VEE Project <http://www.v3vee.org>
+ * All rights reserved.
+ *
+ * Author: Lei Xia <lxia@northwestern.edu>
+ * Chang Seok Bae <jhuell@gmail.com>
+ * Jack Lange <jarusl@cs.northwestern.edu>
+ *
+ * This is free software. You are permitted to use,
+ * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
+ */
+
+#include <devices/piix3.h>
+#include <palacios/vmm.h>
+#include <devices/pci.h>
+
+
+struct piix3_state {
+ uint8_t pci_dev_num;
+
+ struct vm_device * pci;
+
+};
+
+
+static int init_piix3(struct vm_device * dev) {
+
+ return 0;
+}
+
+
+static int deinit_piix3(struct vm_device * dev) {
+ return 0;
+}
+
+
+static struct vm_device_ops dev_ops = {
+ .init = init_piix3,
+ .deinit = deinit_piix3,
+ .reset = NULL,
+ .start = NULL,
+ .stop = NULL,
+};
+
+
+struct vm_device * v3_create_piix3(struct vm_device * pci) {
+ struct piix3_state * piix3 = (struct piix3_state *)V3_Malloc(sizeof(struct piix3_state));
+ struct vm_device * dev = NULL;
+
+ piix3->pci = pci;
+
+ dev = v3_create_device("PIIX3", &dev_ops, piix3);
+
+ PrintDebug("Created PIIX3\n");
+
+ return dev;
+}
#include <devices/ide.h>
+
+#ifndef DEBUG_IDE
+#undef PrintDebug
+#define PrintDebug(fmt, args...)
+#endif
+
struct hd_state {
addr_t disk_image;
uint32_t capacity; // in bytes
//v3_update_time(info, yield_stop - yield_start);
gap = yield_stop - yield_start;
- v3_raise_irq(info, 0);
+ if (!v3_intr_pending(info)) {
+ v3_raise_irq(info, 0);
+ }
PrintDebug("GeekOS Yield Done (%d cycles)\n", gap);
#endif
if (!guest_ctrl->exit_int_info.valid) {
info->intr_state.irq_pending = 0;
- // PrintDebug("Injecting Interrupt %d\n", info->intr_state.irq_vector);
+ // PrintDebug("Injected Interrupt %d\n", info->intr_state.irq_vector);
v3_injecting_intr(info, info->intr_state.irq_vector, EXTERNAL_IRQ);
} else {
#ifdef DEBUG_INTERRUPTS
// Disable printing io exits due to bochs debug messages
//if (!((exit_code == VMEXIT_IOIO) && ((ushort_t)(guest_ctrl->exit_info1 >> 16) == 0x402))) {
-
- // PrintDebug("SVM Returned: Exit Code: 0x%x \t\t(tsc=%ul)\n",exit_code, (uint_t)info->time_state.guest_tsc);
if ((0) && (exit_code <= VMEXIT_EXCP14)) {
uchar_t instr[32];
switch (exit_code) {
case VMEXIT_IOIO: {
struct svm_io_info * io_info = (struct svm_io_info *)&(guest_ctrl->exit_info1);
-
+
if (io_info->type == 0) {
if (io_info->str) {
#include <devices/io_apic.h>
#include <devices/para_net.h>
#include <devices/pci.h>
-
+#include <devices/i440fx.h>
+#include <devices/piix3.h>
#include <palacios/vmm_host_events.h>
static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ptr) {
+
struct vm_device * ide = NULL;
- //struct vm_device * ram_cd = NULL;
- struct vm_device * ram_hd = NULL;
- struct vm_device * pci = v3_create_pci();
+ struct vm_device * ramdisk = NULL;
+
+ struct vm_device * pci = NULL;
+ struct vm_device * northbridge = NULL;
+ struct vm_device * southbridge = NULL;
+
struct vm_device * nvram = v3_create_nvram();
- //struct vm_device * timer = v3_create_timer();
struct vm_device * pic = v3_create_pic();
struct vm_device * keyboard = v3_create_keyboard();
struct vm_device * pit = v3_create_pit();
struct vm_device * ioapic = v3_create_io_apic(apic);
struct vm_device * para_net = v3_create_para_net();
+
//struct vm_device * serial = v3_create_serial();
struct vm_device * generic = NULL;
- int use_ramdisk = config_ptr->use_ramdisk;
+
int use_generic = USE_GENERIC;
- ide = v3_create_ide(pci);
+ if (config_ptr->enable_pci == 1) {
+ pci = v3_create_pci();
+ northbridge = v3_create_i440fx(pci);
+ southbridge = v3_create_piix3(pci);
+ ide = v3_create_ide(pci, southbridge);
+ } else {
+ ide = v3_create_ide(NULL, NULL);
+ }
+
- if (use_ramdisk) {
- PrintDebug("Creating Ramdisk\n");
- //ram_cd = v3_create_ram_cd(ide, 0, 0,
- // (addr_t)(config_ptr->ramdisk),
- // config_ptr->ramdisk_size);
- ram_hd = v3_create_ram_hd(ide, 0, 0,
- (addr_t)(config_ptr->ramdisk),
- config_ptr->ramdisk_size);
+ if (config_ptr->use_ram_cd == 1) {
+ PrintDebug("Creating Ram CD\n");
+ ramdisk = v3_create_ram_cd(ide, 0, 0,
+ (addr_t)(config_ptr->ramdisk),
+ config_ptr->ramdisk_size);
+ } else if (config_ptr->use_ram_hd == 1) {
+ PrintDebug("Creating Ram HD\n");
+ ramdisk = v3_create_ram_hd(ide, 0, 0,
+ (addr_t)(config_ptr->ramdisk),
+ config_ptr->ramdisk_size);
}
}
- v3_attach_device(info, pci);
+
v3_attach_device(info, nvram);
- //v3_attach_device(info, timer);
v3_attach_device(info, pic);
v3_attach_device(info, pit);
v3_attach_device(info, keyboard);
v3_attach_device(info, para_net);
+ if (config_ptr->enable_pci == 1) {
+ v3_attach_device(info, pci);
+ v3_attach_device(info, northbridge);
+ v3_attach_device(info, southbridge);
+ }
+
v3_attach_device(info, ide);
- if (use_ramdisk) {
- // v3_attach_device(info, ram_cd);
- v3_attach_device(info, ram_hd);
+
+ if (ramdisk != NULL) {
+ v3_attach_device(info, ramdisk);
}
if (use_generic) {
PrintDebugDevMgr(info);
-
- // give keyboard interrupts to vm
- // no longer needed since we have a keyboard device
- //hook_irq(&vm_info, 1);
-
-#if 0
- // give floppy controller to vm
- v3_hook_passthrough_irq(info, 6);
-#endif
-
-
- if (!use_ramdisk) {
- PrintDebug("Hooking IDE IRQs\n");
-
- //primary ide
- v3_hook_passthrough_irq(info, 14);
-
- // secondary ide
- v3_hook_passthrough_irq(info, 15);
- }
-
-
return 0;
}
// Make the PCI bus invisible (at least it's configuration)
- v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
- v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data
+ //v3_generic_add_port_range(generic, 0xcf8, 0xcf8, GENERIC_PRINT_AND_IGNORE); // PCI Config Address
+ //v3_generic_add_port_range(generic, 0xcfc, 0xcfc, GENERIC_PRINT_AND_IGNORE); // PCI Config Data