From: Jack Lange Date: Thu, 10 Sep 2009 23:26:54 +0000 (-0500) Subject: added pci passthrough and a few other things X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?p=palacios.git;a=commitdiff_plain;h=3a4e54ec208ea3589963b410d2d73292bbc4a8fe added pci passthrough and a few other things --- diff --git a/palacios/include/devices/pci.h b/palacios/include/devices/pci.h index 68ac2dc..41598d4 100644 --- a/palacios/include/devices/pci.h +++ b/palacios/include/devices/pci.h @@ -32,13 +32,14 @@ typedef enum { PCI_BAR_IO, - PCI_BAR_MEM16, + PCI_BAR_MEM24, PCI_BAR_MEM32, PCI_BAR_MEM64_LOW, PCI_BAR_MEM64_HIGH, + PCI_BAR_PASSTHROUGH, PCI_BAR_NONE } pci_bar_type_t; -typedef enum {PCI_STD_DEVICE, PCI_TO_PCI_BRIDGE, PCI_CARDBUS, PCI_MULTIFUNCTION} pci_device_type_t; +typedef enum {PCI_STD_DEVICE, PCI_TO_PCI_BRIDGE, PCI_CARDBUS, PCI_MULTIFUNCTION, PCI_PASSTHROUGH} pci_device_type_t; @@ -66,6 +67,11 @@ struct v3_pci_bar { int (*io_read)(ushort_t port, void * dst, uint_t length, void * private_data); int (*io_write)(ushort_t port, void * src, uint_t length, void * private_data); }; + + struct { + int (*bar_init)(int bar_num, uint32_t * dst,void * private_data); + int (*bar_write)(int bar_num, uint32_t * src, void * private_data); + }; }; void * private_data; @@ -78,13 +84,17 @@ struct v3_pci_bar { #define PCI_IO_MASK 0xfffffffc -#define PCI_MEM32_MASK 0xfffffff0 +#define PCI_MEM_MASK 0xfffffff0 +#define PCI_MEM24_MASK 0x000ffff0 #define PCI_IO_BASE(bar_val) (bar_val & PCI_IO_MASK) -#define PCI_MEM32_BASE(bar_val) (bar_val & PCI_MEM32_MASK) +#define PCI_MEM32_BASE(bar_val) (bar_val & PCI_MEM_MASK) +#define PCI_MEM24_BASE(bar_val) (bar_val & PCI_MEM24_MASK) struct pci_device { + pci_device_type_t type; + union { uint8_t config_space[256]; @@ -112,10 +122,14 @@ struct pci_device { struct vm_device * vm_dev; //the corresponding virtual device - int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length); + 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 (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data); + int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_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 ext_rom_update_flag; int bar_update_flag; @@ -141,10 +155,22 @@ v3_pci_register_device(struct vm_device * pci, int fn_num, const char * name, struct v3_pci_bar * bars, - int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length), + int (*config_update)(uint_t reg_num, void * src, uint_t length, void * private_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), - struct vm_device * dev); + struct vm_device * dev, void * priv_data); + + +struct pci_device * +v3_pci_register_passthrough_device(struct vm_device * pci, + int bus_num, + int dev_num, + int fn_num, + const char * name, + int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data), + int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data), + struct vm_device * dev, + void * private_data); #endif diff --git a/palacios/include/devices/pci_passthrough.h b/palacios/include/devices/pci_passthrough.h new file mode 100644 index 0000000..8ac8580 --- /dev/null +++ b/palacios/include/devices/pci_passthrough.h @@ -0,0 +1,36 @@ +/* + * 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) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __DEVICES_PCI_PASSTHROUGH_H__ +#define __DEVICES_PCI_PASSTHROUGH_H__ + +#ifdef __V3VEE__ + +struct pci_passthrough_cfg { + char pci_bus_name[32]; + + char name[32]; + uint16_t vendor_id; + uint16_t device_id; +}; + + +#endif + +#endif diff --git a/palacios/include/palacios/vmm_io.h b/palacios/include/palacios/vmm_io.h index e2f4be5..1ceff4d 100644 --- a/palacios/include/palacios/vmm_io.h +++ b/palacios/include/palacios/vmm_io.h @@ -38,12 +38,12 @@ void v3_init_io_map(struct guest_info * info); /* External API */ -int v3_hook_io_port(struct guest_info * info, uint_t port, +int v3_hook_io_port(struct guest_info * info, uint16_t port, int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data), int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), void * priv_data); -int v3_unhook_io_port(struct guest_info * info, uint_t port); +int v3_unhook_io_port(struct guest_info * info, uint16_t port); @@ -74,7 +74,7 @@ struct v3_io_map { void * arch_data; }; -struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port); +struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint16_t port); void v3_print_io_map(struct guest_info * info); diff --git a/palacios/include/palacios/vmm_mem.h b/palacios/include/palacios/vmm_mem.h index 927577e..553497d 100644 --- a/palacios/include/palacios/vmm_mem.h +++ b/palacios/include/palacios/vmm_mem.h @@ -114,7 +114,7 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr); -void print_shadow_map(struct guest_info * info); +void v3_print_mem_map(struct guest_info * info); diff --git a/palacios/include/palacios/vmm_sym_swap.h b/palacios/include/palacios/vmm_sym_swap.h index 4e5f9cc..5f09c3b 100644 --- a/palacios/include/palacios/vmm_sym_swap.h +++ b/palacios/include/palacios/vmm_sym_swap.h @@ -55,8 +55,8 @@ struct v3_sym_swap_state { struct hashtable * shdw_ptr_ht; }; - - +// Present = 0 and Dirty = 0 +// fixme static inline int is_swapped_pte32(pte32_t * pte) { return ((pte->present == 0) && (*(uint32_t *)pte != 0)); } diff --git a/palacios/src/devices/Kconfig b/palacios/src/devices/Kconfig index 6f63f23..dde39ab 100644 --- a/palacios/src/devices/Kconfig +++ b/palacios/src/devices/Kconfig @@ -199,6 +199,13 @@ config PCI help Includes the Virtual PCI Bus +config PASSTHROUGH_PCI + bool "Passthrough PCI" + default y + depends on PCI && EXPERIMENTAL + help + Enables hardware devices to be passed through to the VM + config DEBUG_PCI bool "PCI debugging" depends on PCI && DEBUG_ON diff --git a/palacios/src/devices/Makefile b/palacios/src/devices/Makefile index f720996..0e716aa 100644 --- a/palacios/src/devices/Makefile +++ b/palacios/src/devices/Makefile @@ -25,3 +25,5 @@ obj-$(CONFIG_NET_HD) += net_hd.o obj-$(CONFIG_CGA) += cga.o obj-$(CONFIG_TELNET_CONSOLE) += telnet_cons.o + +obj-$(CONFIG_PASSTHROUGH_PCI) += pci_passthrough.o \ No newline at end of file diff --git a/palacios/src/devices/generic.c b/palacios/src/devices/generic.c index fbeff20..c6dd8d6 100644 --- a/palacios/src/devices/generic.c +++ b/palacios/src/devices/generic.c @@ -92,11 +92,11 @@ static int generic_write_port_passthrough(uint16_t port, void * src, v3_outw(port,((uint16_t*)src)[0]); break; case 4: - v3_outdw(port,((uint_t*)src)[0]); + v3_outdw(port,((uint32_t *)src)[0]); break; default: for (i = 0; i < length; i++) { - v3_outb(port, ((uchar_t*)src)[i]); + v3_outb(port, ((uchar_t *)src)[i]); } } diff --git a/palacios/src/devices/i440fx.c b/palacios/src/devices/i440fx.c index 2408cdd..da26d6b 100644 --- a/palacios/src/devices/i440fx.c +++ b/palacios/src/devices/i440fx.c @@ -94,7 +94,7 @@ static int i440_init(struct guest_info * vm, void * cfg_data) { pci_dev = v3_pci_register_device(state->pci, PCI_STD_DEVICE, 0, 0, 0, "i440FX", bars, - NULL, NULL, NULL, dev); + NULL, NULL, NULL, dev, NULL); if (!pci_dev) { return -1; diff --git a/palacios/src/devices/ide.c b/palacios/src/devices/ide.c index 1776e9c..b1c13a6 100644 --- a/palacios/src/devices/ide.c +++ b/palacios/src/devices/ide.c @@ -1397,7 +1397,7 @@ static void init_channel(struct ide_channel * channel) { } -static int pci_config_update(struct pci_device * pci_dev, uint_t reg_num, int length) { +static int pci_config_update(uint_t reg_num, void * src, uint_t length, void * private_data) { PrintDebug("PCI Config Update\n"); PrintDebug("\t\tInterupt register (Dev=%s), irq=%d\n", pci_dev->name, pci_dev->config_header.intr_line); @@ -1566,7 +1566,7 @@ static int ide_init(struct guest_info * vm, void * cfg_data) { pci_dev = v3_pci_register_device(ide->pci_bus, PCI_STD_DEVICE, 0, sb_pci->dev_num, 1, "PIIX3_IDE", bars, - pci_config_update, NULL, NULL, dev); + pci_config_update, NULL, NULL, dev, dev); if (pci_dev == NULL) { PrintError("Failed to register IDE BUS %d with PCI\n", i); diff --git a/palacios/src/devices/lnx_virtio_balloon.c b/palacios/src/devices/lnx_virtio_balloon.c index fed0c83..e7a18aa 100644 --- a/palacios/src/devices/lnx_virtio_balloon.c +++ b/palacios/src/devices/lnx_virtio_balloon.c @@ -481,7 +481,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) { pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 0, PCI_AUTO_DEV_NUM, 0, "LNX_VIRTIO_BALLOON", bars, - NULL, NULL, NULL, dev); + NULL, NULL, NULL, dev, NULL); if (!pci_dev) { PrintError("Could not register PCI Device\n"); diff --git a/palacios/src/devices/lnx_virtio_blk.c b/palacios/src/devices/lnx_virtio_blk.c index f71b559..0059fb6 100644 --- a/palacios/src/devices/lnx_virtio_blk.c +++ b/palacios/src/devices/lnx_virtio_blk.c @@ -628,7 +628,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) { pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 0, PCI_AUTO_DEV_NUM, 0, "LNX_VIRTIO_BLK", bars, - NULL, NULL, NULL, dev); + NULL, NULL, NULL, dev, NULL); if (!pci_dev) { PrintError("Could not register PCI Device\n"); diff --git a/palacios/src/devices/lnx_virtio_sym.c b/palacios/src/devices/lnx_virtio_sym.c index 8f4401e..ad5cbbd 100644 --- a/palacios/src/devices/lnx_virtio_sym.c +++ b/palacios/src/devices/lnx_virtio_sym.c @@ -414,7 +414,7 @@ static int virtio_init(struct guest_info * vm, void * cfg_data) { pci_dev = v3_pci_register_device(pci_bus, PCI_STD_DEVICE, 0, PCI_AUTO_DEV_NUM, 0, "LNX_VIRTIO_SYM", bars, - NULL, NULL, NULL, dev); + NULL, NULL, NULL, dev, NULL); if (!pci_dev) { PrintError("Could not register PCI Device\n"); diff --git a/palacios/src/devices/pci.c b/palacios/src/devices/pci.c index b65aefc..49ed5d5 100644 --- a/palacios/src/devices/pci.c +++ b/palacios/src/devices/pci.c @@ -323,6 +323,15 @@ static int data_port_read(ushort_t port, void * dst, uint_t length, struct vm_de return length; } + if (pci_dev->type == PCI_PASSTHROUGH) { + if (pci_dev->config_read(reg_num, dst, length, pci_dev->priv_data) == -1) { + PrintError("Failed to handle configuration update for passthrough pci_device\n"); + return -1; + } + + return 0; + } + for (i = 0; i < length; i++) { *(uint8_t *)((uint8_t *)dst + i) = pci_dev->config_space[reg_num + i]; } @@ -414,6 +423,7 @@ static int bar_update(struct pci_device * pci, int bar_num, uint32_t new_val) { PrintError("Could not hook PCI IO port (old port=%u) (new port=%u)\n", PCI_IO_BASE(bar->val) + i, PCI_IO_BASE(new_val) + i); + v3_print_io_map(pci->vm_dev->vm); return -1; } } @@ -463,7 +473,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d return length; } - PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (%x) addr_reg = %x (val=%x, len=%d)\n", + PrintDebug("Writing PCI Data register. bus = %d, dev = %d, fn = %d, reg = %d (0x%x) addr_reg = 0x%x (val=0x%x, len=%d)\n", pci_state->addr_reg.bus_num, pci_state->addr_reg.dev_num, pci_state->addr_reg.fn_num, @@ -480,6 +490,15 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d return -1; } + if (pci_dev->type == PCI_PASSTHROUGH) { + if (pci_dev->config_write(reg_num, src, length, pci_dev->priv_data) == -1) { + PrintError("Failed to handle configuration update for passthrough pci_device\n"); + return -1; + } + + return 0; + } + for (i = 0; i < length; i++) { uint_t cur_reg = reg_num + i; @@ -530,7 +549,7 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d } if (pci_dev->config_update) { - pci_dev->config_update(pci_dev, reg_num, length); + pci_dev->config_update(reg_num, src, length, pci_dev->priv_data); } // Scan for BAR updated @@ -539,13 +558,22 @@ static int data_port_write(ushort_t port, void * src, uint_t length, struct vm_d if (pci_dev->bar[i].updated) { int bar_offset = 0x10 + 4 * i; - *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask; - // check special flags.... - // bar_update - if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) { - PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i); - return -1; + if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) { + if (pci_dev->bar[i].bar_write(i, (uint32_t *)(pci_dev->config_space + bar_offset), pci_dev->bar[i].private_data) == -1) { + PrintError("Error in passthrough bar write operation\n"); + return -1; + } + } else { + + *(uint32_t *)(pci_dev->config_space + bar_offset) &= pci_dev->bar[i].mask; + // check special flags.... + + // bar_update + if (bar_update(pci_dev, i, *(uint32_t *)(pci_dev->config_space + bar_offset)) == -1) { + PrintError("PCI Device %s: Bar update Error Bar=%d\n", pci_dev->name, i); + return -1; + } } pci_dev->bar[i].updated = 0; @@ -718,13 +746,18 @@ static inline int init_bars(struct pci_device * pci_dev) { *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val; - } else if (pci_dev->bar[i].type == PCI_BAR_MEM16) { + } else if (pci_dev->bar[i].type == PCI_BAR_MEM24) { PrintError("16 Bit memory ranges not supported (reg: %d)\n", i); return -1; } else if (pci_dev->bar[i].type == PCI_BAR_NONE) { pci_dev->bar[i].val = 0x00000000; pci_dev->bar[i].mask = 0x00000000; // This ensures that all updates will be dropped *(uint32_t *)(pci_dev->config_space + bar_offset) = pci_dev->bar[i].val; + } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) { + + // Call the bar init function to get the local cached value + pci_dev->bar[i].bar_init(i, &(pci_dev->bar[i].val), pci_dev->bar[i].private_data); + } else { PrintError("Invalid BAR type for bar #%d\n", i); return -1; @@ -771,10 +804,10 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, int fn_num, const char * name, struct v3_pci_bar * bars, - int (*config_update)(struct pci_device * pci_dev, uint_t reg_num, int length), + 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), - struct vm_device * dev) { + struct vm_device * dev, void * priv_data) { struct pci_internal * pci_state = (struct pci_internal *)pci->private_data; struct pci_bus * bus = &(pci_state->bus_list[bus_num]); @@ -812,8 +845,10 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, memset(pci_dev, 0, sizeof(struct pci_device)); + + pci_dev->type = dev_type; - switch (dev_type) { + switch (pci_dev->type) { case PCI_STD_DEVICE: pci_dev->config_header.header_type = 0x00; break; @@ -825,12 +860,15 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, return NULL; } + + pci_dev->bus_num = bus_num; pci_dev->dev_num = dev_num; pci_dev->fn_num = fn_num; strncpy(pci_dev->name, name, sizeof(pci_dev->name)); pci_dev->vm_dev = dev; + pci_dev->priv_data = priv_data; // register update callbacks pci_dev->config_update = config_update; @@ -862,6 +900,9 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, pci_dev->bar[i].default_base_addr = bars[i].default_base_addr; pci_dev->bar[i].mem_read = bars[i].mem_read; pci_dev->bar[i].mem_write = bars[i].mem_write; + } else if (pci_dev->bar[i].type == PCI_BAR_PASSTHROUGH) { + pci_dev->bar[i].bar_init = bars[i].bar_init; + pci_dev->bar[i].bar_write = bars[i].bar_write; } else { pci_dev->bar[i].num_pages = 0; pci_dev->bar[i].default_base_addr = 0; @@ -884,3 +925,73 @@ struct pci_device * v3_pci_register_device(struct vm_device * pci, return pci_dev; } + + + +// if dev_num == -1, auto assign +struct pci_device * v3_pci_register_passthrough_device(struct vm_device * pci, + int bus_num, + int dev_num, + int fn_num, + const char * name, + int (*config_write)(uint_t reg_num, void * src, uint_t length, void * private_data), + int (*config_read)(uint_t reg_num, void * dst, uint_t length, void * private_data), + struct vm_device * dev, + void * private_data) { + + struct pci_internal * pci_state = (struct pci_internal *)pci->private_data; + struct pci_bus * bus = &(pci_state->bus_list[bus_num]); + struct pci_device * pci_dev = NULL; + + if (dev_num > MAX_BUS_DEVICES) { + PrintError("Requested Invalid device number (%d)\n", dev_num); + return NULL; + } + + if (dev_num == PCI_AUTO_DEV_NUM) { + PrintDebug("Searching for free device number\n"); + if ((dev_num = get_free_dev_num(bus)) == -1) { + PrintError("No more available PCI slots on bus %d\n", bus->bus_num); + return NULL; + } + } + + PrintDebug("Checking for PCI Device\n"); + + if (get_device(bus, dev_num, fn_num) != NULL) { + PrintError("PCI Device already registered at slot %d on bus %d\n", + dev_num, bus->bus_num); + return NULL; + } + + + pci_dev = (struct pci_device *)V3_Malloc(sizeof(struct pci_device)); + + if (pci_dev == NULL) { + PrintError("Could not allocate pci device\n"); + return NULL; + } + + memset(pci_dev, 0, sizeof(struct pci_device)); + + pci_dev->bus_num = bus_num; + pci_dev->dev_num = dev_num; + pci_dev->fn_num = fn_num; + + strncpy(pci_dev->name, name, sizeof(pci_dev->name)); + pci_dev->vm_dev = dev; + pci_dev->priv_data = private_data; + + // register update callbacks + pci_dev->config_write = config_write; + pci_dev->config_read = config_read; + + // add the device + add_device_to_bus(bus, pci_dev); + +#ifdef CONFIG_DEBUG_PCI + pci_dump_state(pci_state); +#endif + + return pci_dev; +} diff --git a/palacios/src/devices/pci_passthrough.c b/palacios/src/devices/pci_passthrough.c new file mode 100644 index 0000000..5c5a468 --- /dev/null +++ b/palacios/src/devices/pci_passthrough.c @@ -0,0 +1,565 @@ +/* + * 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) 2008, Jack Lange + * Copyright (c) 2008, The V3VEE Project + * All rights reserved. + * + * Author: Jack Lange + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +/* This is the generic passthrough PCI virtual device */ + +/* + * The basic idea is that we do not change the hardware PCI configuration + * Instead we modify the guest environment to map onto the physical configuration + * + * The pci subsystem handles most of the configuration space, except for the bar registers. + * We handle them here, by either letting them go directly to hardware or remapping through virtual hooks + * + * Memory Bars are always remapped via the shadow map, + * IO Bars are selectively remapped through hooks if the guest changes them + */ + +#include +#include +#include +#include + + +#include +#include +#include + + +// Hardcoded... Are these standard?? +#define PCI_CFG_ADDR 0xcf8 +#define PCI_CFG_DATA 0xcfc + +#define PCI_BUS_MAX 4 +#define PCI_DEV_MAX 32 +#define PCI_FN_MAX 7 + +#define PCI_DEVICE 0x0 +#define PCI_PCI_BRIDGE 0x1 +#define PCI_CARDBUS_BRIDGE 0x2 + +#define PCI_HDR_SIZE 256 + + +union pci_addr_reg { + uint32_t value; + struct { + uint_t rsvd1 : 2; + uint_t reg : 6; + uint_t func : 3; + uint_t dev : 5; + uint_t bus : 8; + uint_t rsvd2 : 7; + uint_t enable : 1; + } __attribute__((packed)); +} __attribute__((packed)); + + +typedef enum { PT_BAR_NONE, + PT_BAR_IO, + PT_BAR_MEM32, + PT_BAR_MEM24, + PT_BAR_MEM64_LOW, + PT_BAR_MEM64_HIGH } pt_bar_type_t; + +struct pt_bar { + uint32_t size; + pt_bar_type_t type; + uint32_t addr; + + uint32_t val; +}; + +struct pt_dev_state { + union { + uint8_t config_space[256]; + struct pci_config_header real_hdr; + } __attribute__((packed)); + + struct pt_bar phys_bars[6]; + struct pt_bar virt_bars[6]; + + + struct vm_device * pci_bus; + struct pci_device * pci_dev; + + union pci_addr_reg phys_pci_addr; + + char name[32]; +}; + + +static inline uint32_t pci_cfg_read32(uint32_t addr) { + v3_outdw(PCI_CFG_ADDR, addr); + return v3_indw(PCI_CFG_DATA); +} + + + +static inline void pci_cfg_write32(uint32_t addr, uint32_t val) { + v3_outdw(PCI_CFG_ADDR, addr); + v3_outdw(PCI_CFG_DATA, val); +} + + + +static inline uint16_t pci_cfg_read16(uint32_t addr) { + v3_outw(PCI_CFG_ADDR, addr); + return v3_inw(PCI_CFG_DATA); +} + + + +static inline void pci_cfg_write16(uint32_t addr, uint16_t val) { + v3_outw(PCI_CFG_ADDR, addr); + v3_outw(PCI_CFG_DATA, val); +} + + + +static inline uint8_t pci_cfg_read8(uint32_t addr) { + v3_outb(PCI_CFG_ADDR, addr); + return v3_inb(PCI_CFG_DATA); +} + + + +static inline void pci_cfg_write8(uint32_t addr, uint8_t val) { + v3_outb(PCI_CFG_ADDR, addr); + v3_outb(PCI_CFG_DATA, val); +} + + +// We initialize this +static int pci_bar_init(int bar_num, uint32_t * dst,void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; + const uint32_t bar_base_reg = 4; + union pci_addr_reg pci_addr = {state->phys_pci_addr.value}; + uint32_t bar_val = 0; + uint32_t max_val = 0; + //addr_t irq_state = 0; + struct pt_bar * pbar = &(state->phys_bars[bar_num]); + + + // should read from cached header + pci_addr.reg = bar_base_reg + bar_num; + + PrintDebug("PCI Address = 0x%x\n", pci_addr.value); + + bar_val = pci_cfg_read32(pci_addr.value); + pbar->val = bar_val; + + if ((bar_val & 0x3) == 0x1) { + int i = 0; + + // IO bar + pbar->type = PT_BAR_IO; + pbar->addr = PCI_IO_BASE(bar_val); + + max_val = bar_val | PCI_IO_MASK; + + // Cycle the physical bar, to determine the actual size + // Disable irqs, to try to prevent accesses to the space via a interrupt handler + // This is not SMP safe!! + // What we probably want to do is write a 0 to the command register + //irq_state = v3_irq_save(); + + pci_cfg_write32(pci_addr.value, max_val); + max_val = pci_cfg_read32(pci_addr.value); + pci_cfg_write32(pci_addr.value, bar_val); + + //v3_irq_restore(irq_state); + + pbar->size = ~PCI_IO_BASE(max_val) + 1; + + + // setup a set of null io hooks + // This allows the guest to do passthrough IO to these ports + // While still reserving them in the IO map + for (i = 0; i < pbar->size; i++) { + v3_hook_io_port(dev->vm, pbar->addr + i, NULL, NULL, NULL); + } + + } else { + + // might be memory, might be nothing + + max_val = bar_val | PCI_MEM_MASK; + + // Cycle the physical bar, to determine the actual size + // Disable irqs, to try to prevent accesses to the space via a interrupt handler + // This is not SMP safe!! + // What we probably want to do is write a 0 to the command register + //irq_state = v3_irq_save(); + + pci_cfg_write32(pci_addr.value, max_val); + max_val = pci_cfg_read32(pci_addr.value); + pci_cfg_write32(pci_addr.value, bar_val); + + //v3_irq_restore(irq_state); + + + if (max_val == 0) { + pbar->type = PT_BAR_NONE; + } else { + + // if its a memory region, setup passthrough mem mapping + + if ((bar_val & 0x6) == 0x0) { + // MEM 32 + pbar->type = PT_BAR_MEM32; + pbar->addr = PCI_MEM32_BASE(bar_val); + pbar->size = ~PCI_MEM32_BASE(max_val) + 1; + + PrintDebug("Adding 32 bit PCI mem region: start=0x%x, end=0x%x\n", + pbar->addr, pbar->addr + pbar->size); + + v3_add_shadow_mem(dev->vm, + pbar->addr, + pbar->addr + pbar->size - 1, + pbar->addr); + + } else if ((bar_val & 0x6) == 0x2) { + // Mem 24 + pbar->type = PT_BAR_MEM24; + pbar->addr = PCI_MEM24_BASE(bar_val); + pbar->size = ~PCI_MEM24_BASE(max_val) + 1; + + v3_add_shadow_mem(dev->vm, + pbar->addr, + pbar->addr + pbar->size - 1, + pbar->addr); + + } else if ((bar_val & 0x6) == 0x4) { + // Mem 64 + PrintError("64 Bit PCI bars not supported\n"); + return -1; + } else { + PrintError("Invalid Memory bar type\n"); + return -1; + } + + } + } + + + + + // Initially the virtual bars match the physical ones + memcpy(&(state->virt_bars[bar_num]), &(state->phys_bars[bar_num]), sizeof(struct pt_bar)); + + PrintDebug("bar_num=%d, bar_val=0x%x\n", bar_num, bar_val); + + PrintDebug("phys bar type=%d, addr=0x%x, size=%d\n", + pbar->type, pbar->addr, + pbar->size); + + PrintDebug("virt bar type=%d, addr=0x%x, size=%d\n", + state->virt_bars[bar_num].type, state->virt_bars[bar_num].addr, + state->virt_bars[bar_num].size); + + + + // Update the pci subsystem versions + *dst = bar_val; + + return 0; +} + +static int pt_io_read(uint16_t port, void * dst, uint_t length, void * priv_data) { + struct pt_bar * pbar = (struct pt_bar *)priv_data; + int port_offset = port % pbar->size; + + if (length == 1) { + *(uint8_t *)dst = v3_inb(pbar->addr + port_offset); + } else if (length == 2) { + *(uint16_t *)dst = v3_inw(pbar->addr + port_offset); + } else if (length == 4) { + *(uint32_t *)dst = v3_indw(pbar->addr + port_offset); + } else { + PrintError("Invalid PCI passthrough IO Redirection size read\n"); + return -1; + } + + return length; +} + + +static int pt_io_write(uint16_t port, void * src, uint_t length, void * priv_data) { + struct pt_bar * pbar = (struct pt_bar *)priv_data; + int port_offset = port % pbar->size; + + if (length == 1) { + v3_outb(pbar->addr + port_offset, *(uint8_t *)src); + } else if (length == 2) { + v3_outw(pbar->addr + port_offset, *(uint16_t *)src); + } else if (length == 4) { + v3_outdw(pbar->addr + port_offset, *(uint32_t *)src); + } else { + PrintError("Invalid PCI passthrough IO Redirection size write\n"); + return -1; + } + + return length; + +} + + + + + +static int pci_bar_write(int bar_num, uint32_t * src, void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; + + struct pt_bar * pbar = &(state->phys_bars[bar_num]); + struct pt_bar * vbar = &(state->virt_bars[bar_num]); + + PrintDebug("Bar update src=0x%x\n", *src); + + if (vbar->type == PT_BAR_NONE) { + return 0; + } else if (vbar->type == PT_BAR_IO) { + int i = 0; + + // unhook old ports + for (i = 0; i < vbar->size; i++) { + if (v3_unhook_io_port(dev->vm, vbar->addr + i) == -1) { + PrintError("Could not unhook previously hooked port.... %d (0x%x)\n", + vbar->addr + i, vbar->addr + i); + return -1; + } + } + + PrintDebug("Setting IO Port range size=%d\n", pbar->size); + + // clear the low bits to match the size + *src &= ~(pbar->size - 1); + + // Set reserved bits + *src |= (pbar->val & ~PCI_IO_MASK); + + vbar->addr = PCI_IO_BASE(*src); + + PrintDebug("Cooked src=0x%x\n", *src); + + PrintDebug("Rehooking passthrough IO ports starting at %d (0x%x)\n", + vbar->addr, vbar->addr); + + if (vbar->addr == pbar->addr) { + // Map the io ports as passthrough + for (i = 0; i < pbar->size; i++) { + v3_hook_io_port(dev->vm, pbar->addr + i, NULL, NULL, NULL); + } + } else { + // We have to manually handle the io redirection + for (i = 0; i < vbar->size; i++) { + v3_hook_io_port(dev->vm, vbar->addr + i, pt_io_read, pt_io_write, pbar); + } + } + } else if (vbar->type == PT_BAR_MEM32) { + // remove old mapping + struct v3_shadow_region * old_reg = v3_get_shadow_region(dev->vm, vbar->addr); + + if (old_reg == NULL) { + // uh oh... + PrintError("Could not find PCI Passthrough memory redirection region (addr=0x%x)\n", vbar->addr); + return -1; + } + + v3_delete_shadow_region(dev->vm, old_reg); + + // clear the low bits to match the size + *src &= ~(pbar->size - 1); + + // Set reserved bits + *src |= (pbar->val & ~PCI_MEM_MASK); + + PrintDebug("Cooked src=0x%x\n", *src); + + vbar->addr = PCI_MEM32_BASE(*src); + + PrintDebug("Adding pci Passthrough remapping: start=0x%x, size=%d, end=0x%x\n", + vbar->addr, vbar->size, vbar->addr + vbar->size); + + v3_add_shadow_mem(dev->vm, + vbar->addr, + vbar->addr + vbar->size - 1, + pbar->addr); + + } else { + PrintError("Unhandled Pasthrough PCI Bar type %d\n", vbar->type); + return -1; + } + + + vbar->val = *src; + + + return 0; +} + + +static int pt_config_update(uint_t reg_num, void * src, uint_t length, void * private_data) { + struct vm_device * dev = (struct vm_device *)private_data; + struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; + union pci_addr_reg pci_addr = {state->phys_pci_addr.value}; + + pci_addr.reg = reg_num; + + if (length == 1) { + pci_cfg_write8(pci_addr.value, *(uint8_t *)src); + } else if (length == 2) { + pci_cfg_write16(pci_addr.value, *(uint16_t *)src); + } else if (length == 4) { + pci_cfg_write32(pci_addr.value, *(uint32_t *)src); + } + + + return 0; +} + + + +static int find_real_pci_dev(uint16_t vendor_id, uint16_t device_id, struct pt_dev_state * state) { + union pci_addr_reg pci_addr = {0x80000000}; + uint_t i, j, k, m; + + union { + uint32_t value; + struct { + uint16_t vendor; + uint16_t device; + } __attribute__((packed)); + } __attribute__((packed)) pci_hdr = {0}; + + + + for (i = 0, pci_addr.bus = 0; i < PCI_BUS_MAX; i++, pci_addr.bus++) { + for (j = 0, pci_addr.dev = 0; j < PCI_DEV_MAX; j++, pci_addr.dev++) { + for (k = 0, pci_addr.func = 0; k < PCI_FN_MAX; k++, pci_addr.func++) { + + v3_outdw(PCI_CFG_ADDR, pci_addr.value); + pci_hdr.value = v3_indw(PCI_CFG_DATA); + + if ((pci_hdr.vendor == vendor_id) && (pci_hdr.device == device_id)) { + uint32_t * cfg_space = (uint32_t *)&state->real_hdr; + + state->phys_pci_addr = pci_addr; + + // Copy the configuration space to the local cached version + for (m = 0, pci_addr.reg = 0; m < PCI_HDR_SIZE; m += 4, pci_addr.reg++) { + cfg_space[pci_addr.reg] = pci_cfg_read32(pci_addr.value); + } + + + PrintDebug("Found device %x:%x (bus=%d, dev=%d, func=%d)\n", + vendor_id, device_id, + pci_addr.bus, pci_addr.dev, pci_addr.func); + + return 0; + } + } + } + } + + return -1; +} + + + +static int setup_virt_pci_dev(struct guest_info * info, struct vm_device * dev) { + struct pt_dev_state * state = (struct pt_dev_state *)dev->private_data; + struct pci_device * pci_dev = NULL; + struct v3_pci_bar bars[6]; + int bus_num = 0; + int i; + + for (i = 0; i < 6; i++) { + bars[i].type = PCI_BAR_PASSTHROUGH; + bars[i].private_data = dev; + bars[i].bar_init = pci_bar_init; + bars[i].bar_write = pci_bar_write; + } + + pci_dev = v3_pci_register_device(state->pci_bus, + PCI_STD_DEVICE, + bus_num, -1, 0, + state->name, bars, + pt_config_update, NULL, NULL, + dev, dev); + + // This will overwrite the bar registers.. but that should be ok. + memcpy(pci_dev->config_space, (uint8_t *)&(state->real_hdr), sizeof(struct pci_config_header)); + + return 0; +} + + +static struct v3_device_ops dev_ops = { + .free = NULL, + .reset = NULL, + .start = NULL, + .stop = NULL, +}; + + + +static int passthrough_init(struct guest_info * info, void * cfg_data) { + struct pci_passthrough_cfg * cfg = (struct pci_passthrough_cfg *)cfg_data; + struct pt_dev_state * state = V3_Malloc(sizeof(struct pt_dev_state)); + struct vm_device * dev = NULL; + struct vm_device * pci = v3_find_dev(info, cfg->pci_bus_name); + + + memset(state, 0, sizeof(struct pt_dev_state)); + + if (!pci) { + PrintError("Could not find PCI device\n"); + return -1; + } + + state->pci_bus = pci; + strncpy(state->name, cfg->name, 32); + + + + dev = v3_allocate_device("PCI_PASSTHROUGH", &dev_ops, state); + + if (v3_attach_device(info, dev) == -1) { + PrintError("Could not attach device %s\n", "PCI_PASSTHROUGH"); + return -1; + } + + + if (find_real_pci_dev(cfg->vendor_id, cfg->device_id, state) == -1) { + PrintError("Could not find PCI Device %x:%x\n", cfg->vendor_id, cfg->device_id); + return 0; + } + + setup_virt_pci_dev(info, dev); + + return 0; +} + + + + +device_register("PCI_PASSTHROUGH", passthrough_init) diff --git a/palacios/src/devices/piix3.c b/palacios/src/devices/piix3.c index 8b2f627..9a69ed0 100644 --- a/palacios/src/devices/piix3.c +++ b/palacios/src/devices/piix3.c @@ -421,7 +421,7 @@ static int setup_pci(struct vm_device * dev) { pci_dev = v3_pci_register_device(piix3->pci_bus, PCI_MULTIFUNCTION, bus_num, -1, 0, "PIIX3", bars, - NULL, NULL, NULL, dev); + NULL, NULL, NULL, dev, NULL); if (pci_dev == NULL) { PrintError("Could not register PCI Device for PIIX3\n"); return -1; diff --git a/palacios/src/palacios/vmm_config.c b/palacios/src/palacios/vmm_config.c index c728223..ed54ab5 100644 --- a/palacios/src/palacios/vmm_config.c +++ b/palacios/src/palacios/vmm_config.c @@ -31,7 +31,6 @@ #include #endif - #include #include #include @@ -40,6 +39,7 @@ #include #include +#include @@ -227,7 +227,7 @@ static int setup_memory_map(struct guest_info * info, struct v3_vm_config * conf } #endif - print_shadow_map(info); + v3_print_mem_map(info); return 0; } @@ -254,6 +254,7 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ if (config_ptr->enable_pci == 1) { struct ide_cfg ide_config = {"PCI", "PIIX3"}; + struct pci_passthrough_cfg pci_pt_cfg = {"PCI", "E1000", 0x8086, 0x100e}; v3_create_device(info, "PCI", NULL); v3_create_device(info, "i440FX", "PCI"); @@ -266,6 +267,9 @@ static int setup_devices(struct guest_info * info, struct v3_vm_config * config_ v3_create_device(info, "SYM_SWAP", "LNX_VIRTIO_BLK"); v3_create_device(info, "IDE", &ide_config); + + v3_create_device(info, "PCI_PASSTHROUGH", &pci_pt_cfg); + } else { v3_create_device(info, "IDE", NULL); } diff --git a/palacios/src/palacios/vmm_io.c b/palacios/src/palacios/vmm_io.c index 4dbd61d..c5cdb59 100644 --- a/palacios/src/palacios/vmm_io.c +++ b/palacios/src/palacios/vmm_io.c @@ -81,7 +81,7 @@ static inline struct v3_io_hook * insert_io_hook(struct guest_info * info, struc } -struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) { +struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint16_t port) { struct rb_node * n = info->io_map.map.rb_node; struct v3_io_hook * hook = NULL; @@ -105,7 +105,7 @@ struct v3_io_hook * v3_get_io_hook(struct guest_info * info, uint_t port) { -int v3_hook_io_port(struct guest_info * info, uint_t port, +int v3_hook_io_port(struct guest_info * info, uint16_t port, int (*read)(uint16_t port, void * dst, uint_t length, void * priv_data), int (*write)(uint16_t port, void * src, uint_t length, void * priv_data), void * priv_data) { @@ -129,7 +129,7 @@ int v3_hook_io_port(struct guest_info * info, uint_t port, io_hook->priv_data = priv_data; if (insert_io_hook(info, io_hook)) { - PrintError("Could not insert IO hook for port %d\n", port); + PrintError("Could not insert IO hook for port %u (0x%x)\n", port, port); V3_Free(io_hook); return -1; } @@ -138,7 +138,7 @@ int v3_hook_io_port(struct guest_info * info, uint_t port, if (info->io_map.update_map(info, port, ((read == NULL) ? 0 : 1), ((write == NULL) ? 0 : 1)) == -1) { - PrintError("Could not update IO map for port %d\n", port); + PrintError("Could not update IO map for port %u (0x%x)\n", port, port); V3_Free(io_hook); return -1; } @@ -147,21 +147,22 @@ int v3_hook_io_port(struct guest_info * info, uint_t port, return 0; } -int v3_unhook_io_port(struct guest_info * info, uint_t port) { - struct v3_io_hook * hook = v3_get_io_hook(info, port); +int v3_unhook_io_port(struct guest_info * info, uint16_t port) { + struct v3_io_hook * hook = v3_get_io_hook(info, port); - if (hook == NULL) { - return -1; - } + if (hook == NULL) { + PrintError("Could not find port to unhook %u (0x%x)\n", port, port); + return -1; + } - v3_rb_erase(&(hook->tree_node), &(info->io_map.map)); + v3_rb_erase(&(hook->tree_node), &(info->io_map.map)); - // set the arch map to default (this should be 1, 1) - info->io_map.update_map(info, port, 0, 0); + // set the arch map to default (this should be 1, 1) + info->io_map.update_map(info, port, 0, 0); - V3_Free(hook); + V3_Free(hook); - return 0; + return 0; } @@ -170,18 +171,18 @@ int v3_unhook_io_port(struct guest_info * info, uint_t port) { void v3_print_io_map(struct guest_info * info) { - struct v3_io_hook * tmp_hook = NULL; - struct rb_node * node = v3_rb_first(&(info->io_map.map)); + struct v3_io_hook * tmp_hook = NULL; + struct rb_node * node = v3_rb_first(&(info->io_map.map)); - PrintDebug("VMM IO Map\n"); + V3_Print("VMM IO Map\n"); - do { - tmp_hook = rb_entry(node, struct v3_io_hook, tree_node); + do { + tmp_hook = rb_entry(node, struct v3_io_hook, tree_node); - PrintDebug("IO Port: %hu (Read=%p) (Write=%p)\n", - tmp_hook->port, - (void *)(tmp_hook->read), (void *)(tmp_hook->write)); - } while ((node = v3_rb_next(node))); + V3_Print("IO Port: %hu (Read=%p) (Write=%p)\n", + tmp_hook->port, + (void *)(tmp_hook->read), (void *)(tmp_hook->write)); + } while ((node = v3_rb_next(node))); } @@ -268,45 +269,30 @@ uint_t v3_indw(uint16_t port) { /* FIX ME */ -static int default_write(uint16_t port, void *src, uint_t length, void * priv_data) { - /* +static int default_write(uint16_t port, void * src, uint_t length, void * priv_data) { + if (length == 1) { + v3_outb(port, *(uint8_t *)src); + } else if (length == 2) { + v3_outw(port, *(uint16_t *)src); + } else if (length == 4) { + v3_outdw(port, *(uint32_t *)src); + } else { + return -1; + } - if (length == 1) { - __asm__ __volatile__ ( - "outb %b0, %w1" - : - : "a" (*dst), "Nd" (port) - ); - } else if (length == 2) { - __asm__ __volatile__ ( - "outw %b0, %w1" - : - : "a" (*dst), "Nd" (port) - ); - } else if (length == 4) { - __asm__ __volatile__ ( - "outw %b0, %w1" - : - : "a" (*dst), "Nd" (port) - ); - } - */ - return 0; + return length; } static int default_read(uint16_t port, void * dst, uint_t length, void * priv_data) { + if (length == 1) { + *(uint8_t *)dst = v3_inb(port); + } else if (length == 2) { + *(uint16_t *)dst = v3_inw(port); + } else if (length == 4) { + *(uint32_t *)dst = v3_indw(port); + } else { + return -1; + } - /* - uint8_t value; - - __asm__ __volatile__ ( - "inb %w1, %b0" - : "=a" (value) - : "Nd" (port) - ); - - return value; - */ - - return 0; + return length; } diff --git a/palacios/src/palacios/vmm_mem.c b/palacios/src/palacios/vmm_mem.c index 000dac0..0f1c004 100644 --- a/palacios/src/palacios/vmm_mem.c +++ b/palacios/src/palacios/vmm_mem.c @@ -327,6 +327,8 @@ struct v3_shadow_region * v3_get_shadow_region(struct guest_info * info, addr_t if (guest_addr > info->mem_map.base_region.guest_end) { PrintError("Guest Address Exceeds Base Memory Size (ga=%p), (limit=%p)\n", (void *)guest_addr, (void *)info->mem_map.base_region.guest_end); + v3_print_mem_map(info); + return NULL; } @@ -393,15 +395,15 @@ addr_t v3_get_shadow_addr(struct v3_shadow_region * reg, addr_t guest_addr) { -void print_shadow_map(struct guest_info * info) { +void v3_print_mem_map(struct guest_info * info) { struct rb_node * node = v3_rb_first(&(info->mem_map.shdw_regions)); struct v3_shadow_region * reg = &(info->mem_map.base_region); int i = 0; - PrintDebug("Memory Layout:\n"); + V3_Print("Memory Layout:\n"); - PrintDebug("Base Region: 0x%p - 0x%p -> 0x%p\n", + V3_Print("Base Region: 0x%p - 0x%p -> 0x%p\n", (void *)(reg->guest_start), (void *)(reg->guest_end - 1), (void *)(reg->host_addr)); @@ -415,12 +417,12 @@ void print_shadow_map(struct guest_info * info) { do { reg = rb_entry(node, struct v3_shadow_region, tree_node); - PrintDebug("%d: 0x%p - 0x%p -> 0x%p\n", i, + V3_Print("%d: 0x%p - 0x%p -> 0x%p\n", i, (void *)(reg->guest_start), (void *)(reg->guest_end - 1), (void *)(reg->host_addr)); - PrintDebug("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", + V3_Print("\t(%s) (WriteHook = 0x%p) (ReadHook = 0x%p)\n", v3_shdw_region_type_to_str(reg->host_type), (void *)(reg->write_hook), (void *)(reg->read_hook)); diff --git a/palacios/src/palacios/vmm_sprintf.c b/palacios/src/palacios/vmm_sprintf.c index c1ca717..c573e3a 100644 --- a/palacios/src/palacios/vmm_sprintf.c +++ b/palacios/src/palacios/vmm_sprintf.c @@ -576,35 +576,35 @@ void v3_hexdump(const void * ptr, int length, const char * hdr, int flags) { cp = ptr; for (i = 0; i < length; i+= cols) { if (hdr != NULL) - PrintDebug("%s", hdr); + V3_Print("%s", hdr); if ((flags & HD_OMIT_COUNT) == 0) - PrintDebug("%04x ", i); + V3_Print("%04x ", i); if ((flags & HD_OMIT_HEX) == 0) { for (j = 0; j < cols; j++) { k = i + j; if (k < length) - PrintDebug("%c%02x", delim, cp[k]); + V3_Print("%c%02x", delim, cp[k]); else - PrintDebug(" "); + V3_Print(" "); } } if ((flags & HD_OMIT_CHARS) == 0) { - PrintDebug(" |"); + V3_Print(" |"); for (j = 0; j < cols; j++) { k = i + j; if (k >= length) - PrintDebug(" "); + V3_Print(" "); else if (cp[k] >= ' ' && cp[k] <= '~') - PrintDebug("%c", cp[k]); + V3_Print("%c", cp[k]); else - PrintDebug("."); + V3_Print("."); } - PrintDebug("|"); + V3_Print("|"); } - PrintDebug("\n"); + V3_Print("\n"); } } diff --git a/palacios/src/palacios/vmm_telemetry.c b/palacios/src/palacios/vmm_telemetry.c index 4a419a2..2d88d8b 100644 --- a/palacios/src/palacios/vmm_telemetry.c +++ b/palacios/src/palacios/vmm_telemetry.c @@ -205,7 +205,7 @@ void v3_print_telemetry(struct guest_info * info) { V3_Print("%s%s:%sCnt=%u,%sAvg. Time=%u\n", hdr_buf, code_str, - (strlen(code_str) > 14) ? "\t" : "\t\t", + (strlen(code_str) > 13) ? "\t" : "\t\t", evt->cnt, (evt->cnt >= 100) ? "\t" : "\t\t", (uint32_t)(evt->handler_time / evt->cnt));