X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fdevices%2Fpci.c;h=05272a875b919b5148e2ff8283d2280d9247ec00;hb=64cc3bfb45f88a1880331093e87035a38c8f2bdb;hp=8266167a6d8f159aedf8c8eb2692d90e6020e47a;hpb=36c1666cf64c49302d906a79d8cafbf760452d86;p=palacios.git diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index 8266167..05272a8 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -37,7 +37,7 @@ -#ifndef CONFIG_DEBUG_PCI +#ifndef V3_CONFIG_DEBUG_PCI #undef PrintDebug #define PrintDebug(fmt, args...) #endif @@ -82,9 +82,9 @@ struct pci_bus { uint8_t dev_map[MAX_BUS_DEVICES / 8]; - int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev); - int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev); - struct vm_device * irq_bridge_dev; + int (*raise_pci_irq)(struct pci_device * pci_dev, void * dev_data); + int (*lower_pci_irq)(struct pci_device * pci_dev, void * dev_data); + void * irq_dev_data; }; @@ -104,7 +104,7 @@ struct pci_internal { -#ifdef CONFIG_DEBUG_PCI +#ifdef V3_CONFIG_DEBUG_PCI static void pci_dump_state(struct pci_internal * pci_state) { struct rb_node * node = v3_rb_first(&(pci_state->bus_list[0].devices)); @@ -228,8 +228,8 @@ static struct pci_device * get_device(struct pci_bus * bus, uint8_t dev_num, uin -static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * dev) { - struct pci_internal * pci_state = (struct pci_internal *)dev->private_data; +static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) { + struct pci_internal * pci_state = priv_data; int reg_offset = port & 0x3; uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset; @@ -259,8 +259,8 @@ static int addr_port_read(struct guest_info * core, ushort_t port, void * dst, u } -static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * dev) { - struct pci_internal * pci_state = (struct pci_internal *)dev->private_data; +static int addr_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) { + struct pci_internal * pci_state = priv_data; int reg_offset = port & 0x3; uint8_t * reg_addr = ((uint8_t *)&(pci_state->addr_reg.val)) + reg_offset; @@ -297,8 +297,8 @@ static int addr_port_write(struct guest_info * core, ushort_t port, void * src, } -static int data_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, struct vm_device * vmdev) { - struct pci_internal * pci_state = (struct pci_internal *)(vmdev->private_data); +static int data_port_read(struct guest_info * core, ushort_t port, void * dst, uint_t length, void * priv_data) { + struct pci_internal * pci_state = priv_data; struct pci_device * pci_dev = NULL; uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3); int i; @@ -466,8 +466,8 @@ static int bar_update(struct guest_info * info, struct pci_device * pci, int bar } -static int data_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, struct vm_device * vmdev) { - struct pci_internal * pci_state = (struct pci_internal *)vmdev->private_data; +static int data_port_write(struct guest_info * core, ushort_t port, void * src, uint_t length, void * priv_data) { + struct pci_internal * pci_state = priv_data; struct pci_device * pci_dev = NULL; uint_t reg_num = (pci_state->addr_reg.reg_num << 2) + (port & 0x3); int i; @@ -528,7 +528,7 @@ static int data_port_write(struct guest_info * core, ushort_t port, void * src, } else if ((cur_reg >= 0x30) && (cur_reg < 0x34)) { // Extension ROM update - pci_dev->ext_rom_update_flag = 1; + pci_dev->exp_rom_update_flag = 1; } else if (cur_reg == 0x04) { // COMMAND update uint8_t command = *((uint8_t *)src + i); @@ -586,9 +586,9 @@ static int data_port_write(struct guest_info * core, ushort_t port, void * src, pci_dev->bar_update_flag = 0; } - if ((pci_dev->ext_rom_update_flag) && (pci_dev->ext_rom_update)) { - pci_dev->ext_rom_update(pci_dev); - pci_dev->ext_rom_update_flag = 0; + if ((pci_dev->exp_rom_update_flag) && (pci_dev->exp_rom_update)) { + pci_dev->exp_rom_update(pci_dev, &(pci_dev->config_header.expansion_rom_address), pci_dev->priv_data); + pci_dev->exp_rom_update_flag = 0; } @@ -597,56 +597,142 @@ static int data_port_write(struct guest_info * core, ushort_t port, void * src, -static int pci_reset_device(struct vm_device * dev) { - PrintDebug("pci: reset device\n"); - return 0; -} -static int pci_start_device(struct vm_device * dev) { - PrintDebug("pci: start device\n"); - return 0; +static void init_pci_busses(struct pci_internal * pci_state) { + int i; + + for (i = 0; i < PCI_BUS_COUNT; i++) { + pci_state->bus_list[i].bus_num = i; + pci_state->bus_list[i].devices.rb_node = NULL; + memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map)); + } } -static int pci_stop_device(struct vm_device * dev) { - PrintDebug("pci: stop device\n"); +static int pci_free(struct pci_internal * pci_state) { + int i; + + + // cleanup devices + for (i = 0; i < PCI_BUS_COUNT; i++) { + struct pci_bus * bus = &(pci_state->bus_list[i]); + struct rb_node * node = v3_rb_first(&(bus->devices)); + struct pci_device * dev = NULL; + + while (node) { + dev = rb_entry(node, struct pci_device, dev_tree_node); + node = v3_rb_next(node); + + v3_rb_erase(&(dev->dev_tree_node), &(bus->devices)); + V3_Free(dev); + } + + } + + V3_Free(pci_state); return 0; } +#ifdef V3_CONFIG_CHECKPOINT +#include -static int pci_free(struct vm_device * dev) { - int i = 0; +static int pci_save(struct v3_chkpt_ctx * ctx, void * private_data) { + struct pci_internal * pci = (struct pci_internal *)private_data; + char buf[128]; + int i = 0; - for (i = 0; i < 4; i++){ - v3_dev_unhook_io(dev, CONFIG_ADDR_PORT + i); - v3_dev_unhook_io(dev, CONFIG_DATA_PORT + i); + v3_chkpt_save_32(ctx, "ADDR_REG", &(pci->addr_reg.val)); + v3_chkpt_save_16(ctx, "IO_BASE", &(pci->dev_io_base)); + + for (i = 0; i < PCI_BUS_COUNT; i++) { + struct pci_bus * bus = &(pci->bus_list[i]); + struct rb_node * node = v3_rb_first(&(bus->devices)); + struct pci_device * dev = NULL; + struct v3_chkpt_ctx * bus_ctx = NULL; + + snprintf(buf, 128, "pci-%d\n", i); + + bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf); + + while (node) { + struct v3_chkpt_ctx * dev_ctx = NULL; + int bar_idx = 0; + dev = rb_entry(node, struct pci_device, dev_tree_node); + + snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num); + dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf); + + v3_chkpt_save(dev_ctx, "CONFIG_SPACE", 256, dev->config_space); + + for (bar_idx = 0; bar_idx < 6; bar_idx++) { + snprintf(buf, 128, "BAR-%d", bar_idx); + v3_chkpt_save_32(dev_ctx, buf, &(dev->bar[bar_idx].val)); + } + + node = v3_rb_next(node); + } } - + + return 0; } - -static void init_pci_busses(struct pci_internal * pci_state) { - int i; +static int pci_load(struct v3_chkpt_ctx * ctx, void * private_data) { + struct pci_internal * pci = (struct pci_internal *)private_data; + char buf[128]; + int i = 0; + + v3_chkpt_load_32(ctx, "ADDR_REG", &(pci->addr_reg.val)); + v3_chkpt_load_16(ctx, "IO_BASE", &(pci->dev_io_base)); for (i = 0; i < PCI_BUS_COUNT; i++) { - pci_state->bus_list[i].bus_num = i; - pci_state->bus_list[i].devices.rb_node = NULL; - memset(pci_state->bus_list[i].dev_map, 0, sizeof(pci_state->bus_list[i].dev_map)); + struct pci_bus * bus = &(pci->bus_list[i]); + struct rb_node * node = v3_rb_first(&(bus->devices)); + struct pci_device * dev = NULL; + struct v3_chkpt_ctx * bus_ctx = NULL; + + snprintf(buf, 128, "pci-%d\n", i); + + bus_ctx = v3_chkpt_open_ctx(ctx->chkpt, ctx, buf); + + while (node) { + struct v3_chkpt_ctx * dev_ctx = NULL; + int bar_idx = 0; + dev = rb_entry(node, struct pci_device, dev_tree_node); + + snprintf(buf, 128, "pci-%d.%d-%d", i, dev->dev_num, dev->fn_num); + dev_ctx = v3_chkpt_open_ctx(bus_ctx->chkpt, bus_ctx, buf); + + v3_chkpt_load(dev_ctx, "CONFIG_SPACE", 256, dev->config_space); + + for (bar_idx = 0; bar_idx < 6; bar_idx++) { + snprintf(buf, 128, "BAR-%d", bar_idx); + v3_chkpt_load_32(dev_ctx, buf, &(dev->bar[bar_idx].val)); + } + + node = v3_rb_next(node); + } } + + + return 0; } +#endif + + static struct v3_device_ops dev_ops = { - .free = pci_free, - .reset = pci_reset_device, - .start = pci_start_device, - .stop = pci_stop_device, + .free = (int (*)(void *))pci_free, +#ifdef V3_CONFIG_CHECKPOINT + .save = pci_save, + .load = pci_load +#endif }; @@ -655,14 +741,16 @@ static struct v3_device_ops dev_ops = { static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { struct pci_internal * pci_state = V3_Malloc(sizeof(struct pci_internal)); int i = 0; - char * name = v3_cfg_val(cfg, "name"); + char * dev_id = v3_cfg_val(cfg, "ID"); + int ret = 0; PrintDebug("PCI internal at %p\n",(void *)pci_state); - struct vm_device * dev = v3_allocate_device(name, &dev_ops, pci_state); + struct vm_device * dev = v3_add_device(vm, dev_id, &dev_ops, pci_state); - if (v3_attach_device(vm, dev) == -1) { - PrintError("Could not attach device %s\n", name); + if (dev == NULL) { + PrintError("Could not attach device %s\n", dev_id); + V3_Free(pci_state); return -1; } @@ -675,8 +763,14 @@ static int pci_init(struct v3_vm_info * vm, v3_cfg_tree_t * cfg) { PrintDebug("Sizeof config header=%d\n", (int)sizeof(struct pci_config_header)); for (i = 0; i < 4; i++) { - v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write); - v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write); + ret |= v3_dev_hook_io(dev, CONFIG_ADDR_PORT + i, &addr_port_read, &addr_port_write); + ret |= v3_dev_hook_io(dev, CONFIG_DATA_PORT + i, &data_port_read, &data_port_write); + } + + if (ret != 0) { + PrintError("Error hooking PCI IO ports\n"); + v3_remove_device(dev); + return -1; } return 0; @@ -774,15 +868,15 @@ static inline int init_bars(struct v3_vm_info * vm, struct pci_device * pci_dev) int v3_pci_set_irq_bridge(struct vm_device * pci_bus, int bus_num, - int (*raise_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev), - int (*lower_pci_irq)(struct vm_device * dev, struct pci_device * pci_dev), - struct vm_device * bridge_dev) { + int (*raise_pci_irq)(struct pci_device * pci_dev, void * dev_data), + int (*lower_pci_irq)(struct pci_device * pci_dev, void * dev_data), + void * priv_data) { struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; pci_state->bus_list[bus_num].raise_pci_irq = raise_pci_irq; pci_state->bus_list[bus_num].lower_pci_irq = lower_pci_irq; - pci_state->bus_list[bus_num].irq_bridge_dev = bridge_dev; + pci_state->bus_list[bus_num].irq_dev_data = priv_data; return 0; } @@ -791,14 +885,14 @@ int v3_pci_raise_irq(struct vm_device * pci_bus, int bus_num, struct pci_device struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; struct pci_bus * bus = &(pci_state->bus_list[bus_num]); - return bus->raise_pci_irq(bus->irq_bridge_dev, dev); + return bus->raise_pci_irq(dev, bus->irq_dev_data); } int v3_pci_lower_irq(struct vm_device * pci_bus, int bus_num, struct pci_device * dev) { struct pci_internal * pci_state = (struct pci_internal *)pci_bus->private_data; struct pci_bus * bus = &(pci_state->bus_list[bus_num]); - return bus->lower_pci_irq(bus->irq_bridge_dev, dev); + return bus->lower_pci_irq(dev, bus->irq_dev_data); } // if dev_num == -1, auto assign @@ -810,8 +904,8 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, const char * name, struct v3_pci_bar * bars, int (*config_update)(uint_t reg_num, void * src, uint_t length, void * priv_data), - int (*cmd_update)(struct pci_device *pci_dev, uchar_t io_enabled, uchar_t mem_enabled), - int (*ext_rom_update)(struct pci_device * pci_dev), + int (*cmd_update)(struct pci_device * pci_dev, uchar_t io_enabled, uchar_t mem_enabled), + int (*exp_rom_update)(struct pci_device * pci_dev, uint32_t * src, void * priv_data), void * priv_data) { struct pci_internal * pci_state = (struct pci_internal *)pci->private_data; @@ -877,7 +971,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, // register update callbacks pci_dev->config_update = config_update; pci_dev->cmd_update = cmd_update; - pci_dev->ext_rom_update = ext_rom_update; + pci_dev->exp_rom_update = exp_rom_update; //copy bars @@ -923,7 +1017,7 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, // add the device add_device_to_bus(bus, pci_dev); -#ifdef CONFIG_DEBUG_PCI +#ifdef V3_CONFIG_DEBUG_PCI pci_dump_state(pci_state); #endif @@ -991,7 +1085,7 @@ struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci, // add the device add_device_to_bus(bus, pci_dev); -#ifdef CONFIG_DEBUG_PCI +#ifdef V3_CONFIG_DEBUG_PCI pci_dump_state(pci_state); #endif