[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V11 5/8] Introduce Xen PCI Passthrough, qdevice (1/3)
> +void xen_pt_log(const PCIDevice *d, const char *f, ...) > +{ > + va_list ap; > + > + va_start(ap, f); > + if (d) { > + fprintf(stderr, "[%02x:%02x.%x] ", pci_bus_num(d->bus), %d at the end and in the other location pls fix it up.. > + PCI_SLOT(d->devfn), PCI_FUNC(d->devfn)); > + } > + vfprintf(stderr, f, ap); > + va_end(ap); > +} > + > +/* Config Space */ > + .. Is there a way to make this function (and the following one) squahed? > +static uint32_t xen_pt_pci_read_config(PCIDevice *d, uint32_t addr, int len) > +{ > + XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d); > + uint32_t val = 0; > + XenPTRegGroup *reg_grp_entry = NULL; > + XenPTReg *reg_entry = NULL; > + int rc = 0; > + int emul_len = 0; > + uint32_t find_addr = addr; > + > + if (xen_pt_pci_config_access_check(d, addr, len)) { > + goto exit; > + } > + > + /* find register group entry */ > + reg_grp_entry = xen_pt_find_reg_grp(s, addr); > + if (reg_grp_entry) { > + /* check 0-Hardwired register group */ > + if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) { > + /* no need to emulate, just return 0 */ > + val = 0; > + goto exit; > + } > + } > + > + /* read I/O device register value */ > + rc = xen_host_pci_get_block(&s->real_device, addr, (uint8_t *)&val, len); > + if (rc < 0) { > + XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc); > + memset(&val, 0xff, len); > + } > + > + /* just return the I/O device register value for > + * passthrough type register group */ > + if (reg_grp_entry == NULL) { > + goto exit; > + } > + > + /* adjust the read value to appropriate CFC-CFF window */ > + val <<= (addr & 3) << 3; > + emul_len = len; > + > + /* loop around the guest requested size */ > + while (emul_len > 0) { > + /* find register entry to be emulated */ > + reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr); > + if (reg_entry) { > + XenPTRegInfo *reg = reg_entry->reg; > + uint32_t real_offset = reg_grp_entry->base_offset + reg->offset; > + uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3); > + uint8_t *ptr_val = NULL; > + > + valid_mask <<= (find_addr - real_offset) << 3; > + ptr_val = (uint8_t *)&val + (real_offset & 3); > + > + /* do emulation based on register size */ > + switch (reg->size) { > + case 1: > + if (reg->u.b.read) { > + rc = reg->u.b.read(s, reg_entry, ptr_val, valid_mask); > + } > + break; > + case 2: > + if (reg->u.w.read) { > + rc = reg->u.w.read(s, reg_entry, > + (uint16_t *)ptr_val, valid_mask); > + } > + break; > + case 4: > + if (reg->u.dw.read) { > + rc = reg->u.dw.read(s, reg_entry, > + (uint32_t *)ptr_val, valid_mask); > + } > + break; > + } > + > + if (rc < 0) { > + xen_shutdown_fatal_error("Internal error: Invalid read " > + "emulation. (%s, rc: %d)\n", > + __func__, rc); > + return 0; > + } > + > + /* calculate next address to find */ > + emul_len -= reg->size; > + if (emul_len > 0) { > + find_addr = real_offset + reg->size; > + } > + } else { > + /* nothing to do with passthrough type register, > + * continue to find next byte */ > + emul_len--; > + find_addr++; > + } > + } > + > + /* need to shift back before returning them to pci bus emulator */ > + val >>= ((addr & 3) << 3); > + > +exit: > + XEN_PT_LOG_CONFIG(d, addr, val, len); > + return val; > +} > + > +static void xen_pt_pci_write_config(PCIDevice *d, uint32_t addr, > + uint32_t val, int len) > +{ > + XenPCIPassthroughState *s = DO_UPCAST(XenPCIPassthroughState, dev, d); > + int index = 0; > + XenPTRegGroup *reg_grp_entry = NULL; > + int rc = 0; > + uint32_t read_val = 0; > + int emul_len = 0; > + XenPTReg *reg_entry = NULL; > + uint32_t find_addr = addr; > + XenPTRegInfo *reg = NULL; > + > + if (xen_pt_pci_config_access_check(d, addr, len)) { > + return; > + } > + > + XEN_PT_LOG_CONFIG(d, addr, val, len); > + > + /* check unused BAR register */ > + index = xen_pt_bar_offset_to_index(addr); > + if ((index >= 0) && (val > 0 && val < XEN_PT_BAR_ALLF) && > + (s->bases[index].bar_flag == XEN_PT_BAR_FLAG_UNUSED)) { > + XEN_PT_WARN(d, "Guest attempt to set address to unused Base Address " > + "Register. (addr: 0x%02x, len: %d)\n", addr, len); > + } > + > + /* find register group entry */ > + reg_grp_entry = xen_pt_find_reg_grp(s, addr); > + if (reg_grp_entry) { > + /* check 0-Hardwired register group */ > + if (reg_grp_entry->reg_grp->grp_type == XEN_PT_GRP_TYPE_HARDWIRED) { > + /* ignore silently */ > + XEN_PT_WARN(d, "Access to 0-Hardwired register. " > + "(addr: 0x%02x, len: %d)\n", addr, len); > + return; > + } > + } > + > + rc = xen_host_pci_get_block(&s->real_device, addr, > + (uint8_t *)&read_val, len); > + if (rc < 0) { > + XEN_PT_ERR(d, "pci_read_block failed. return value: %d.\n", rc); > + memset(&read_val, 0xff, len); > + } > + > + /* pass directly to the real device for passthrough type register group > */ > + if (reg_grp_entry == NULL) { > + goto out; > + } > + > + memory_region_transaction_begin(); > + pci_default_write_config(d, addr, val, len); > + > + /* adjust the read and write value to appropriate CFC-CFF window */ > + read_val <<= (addr & 3) << 3; > + val <<= (addr & 3) << 3; > + emul_len = len; > + > + /* loop around the guest requested size */ > + while (emul_len > 0) { > + /* find register entry to be emulated */ > + reg_entry = xen_pt_find_reg(reg_grp_entry, find_addr); > + if (reg_entry) { > + reg = reg_entry->reg; > + uint32_t real_offset = reg_grp_entry->base_offset + reg->offset; > + uint32_t valid_mask = 0xFFFFFFFF >> ((4 - emul_len) << 3); > + uint8_t *ptr_val = NULL; > + > + valid_mask <<= (find_addr - real_offset) << 3; > + ptr_val = (uint8_t *)&val + (real_offset & 3); > + > + /* do emulation based on register size */ > + switch (reg->size) { > + case 1: > + if (reg->u.b.write) { > + rc = reg->u.b.write(s, reg_entry, ptr_val, > + read_val >> ((real_offset & 3) << 3), > + valid_mask); > + } > + break; > + case 2: > + if (reg->u.w.write) { > + rc = reg->u.w.write(s, reg_entry, (uint16_t *)ptr_val, > + (read_val >> ((real_offset & 3) << > 3)), > + valid_mask); > + } > + break; > + case 4: > + if (reg->u.dw.write) { > + rc = reg->u.dw.write(s, reg_entry, (uint32_t *)ptr_val, > + (read_val >> ((real_offset & 3) << > 3)), > + valid_mask); > + } > + break; > + } > + > + if (rc < 0) { > + xen_shutdown_fatal_error("Internal error: Invalid write" > + " emulation. (%s, rc: %d)\n", > + __func__, rc); > + return; > + } > + > + /* calculate next address to find */ > + emul_len -= reg->size; > + if (emul_len > 0) { > + find_addr = real_offset + reg->size; > + } > + } else { > + /* nothing to do with passthrough type register, > + * continue to find next byte */ > + emul_len--; > + find_addr++; > + } > + } > + > + /* need to shift back before passing them to xen_host_pci_device */ > + val >>= (addr & 3) << 3; > + > + memory_region_transaction_commit(); _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |