Merge remote-tracking branch 'mst/for_anthony' into staging

This commit is contained in:
Anthony Liguori 2011-08-04 17:15:22 -05:00
commit 81e34a2401
10 changed files with 79 additions and 31 deletions

View File

@ -1145,8 +1145,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
uint32_t address, int len)
{
uint32_t val = 0;
assert(len == 1 || len == 2 || len == 4);
len = MIN(len, pci_config_size(d) - address);
memcpy(&val, d->config + address, len);
return le32_to_cpu(val);
}
@ -1154,9 +1153,8 @@ uint32_t pci_default_read_config(PCIDevice *d,
void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
{
int i, was_irq_disabled = pci_irq_disabled(d);
uint32_t config_size = pci_config_size(d);
for (i = 0; i < l && addr + i < config_size; val >>= 8, ++i) {
for (i = 0; i < l; val >>= 8, ++i) {
uint8_t wmask = d->wmask[addr + i];
uint8_t w1cmask = d->w1cmask[addr + i];
assert(!(wmask & w1cmask));

View File

@ -47,17 +47,33 @@ static inline PCIDevice *pci_dev_find_by_addr(PCIBus *bus, uint32_t addr)
return pci_find_device(bus, bus_num, devfn);
}
void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len)
{
assert(len <= 4);
pci_dev->config_write(pci_dev, addr, val, MIN(len, limit - addr));
}
uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t len)
{
assert(len <= 4);
return pci_dev->config_read(pci_dev, addr, MIN(len, limit - addr));
}
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
{
PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
if (!pci_dev)
if (!pci_dev) {
return;
}
PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
__func__, pci_dev->name, config_addr, val, len);
pci_dev->config_write(pci_dev, config_addr, val, len);
pci_host_config_write_common(pci_dev, config_addr, PCI_CONFIG_SPACE_SIZE,
val, len);
}
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
@ -66,12 +82,12 @@ uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len)
uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
uint32_t val;
assert(len == 1 || len == 2 || len == 4);
if (!pci_dev) {
return ~0x0;
}
val = pci_dev->config_read(pci_dev, config_addr, len);
val = pci_host_config_read_common(pci_dev, config_addr,
PCI_CONFIG_SPACE_SIZE, len);
PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
__func__, pci_dev->name, config_addr, val, len);

View File

@ -40,6 +40,12 @@ struct PCIHostState {
PCIBus *bus;
};
/* common internal helpers for PCI/PCIe hosts, cut off overflows */
void pci_host_config_write_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t val, uint32_t len);
uint32_t pci_host_config_read_common(PCIDevice *pci_dev, uint32_t addr,
uint32_t limit, uint32_t len);
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len);
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);

View File

@ -56,23 +56,39 @@ static void pcie_mmcfg_data_write(PCIBus *s,
uint32_t mmcfg_addr, uint32_t val, int len)
{
PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
uint32_t addr;
uint32_t limit;
if (!pci_dev)
if (!pci_dev) {
return;
pci_dev->config_write(pci_dev,
PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
}
addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
limit = pci_config_size(pci_dev);
if (limit <= addr) {
/* conventional pci device can be behind pcie-to-pci bridge.
256 <= addr < 4K has no effects. */
return;
}
pci_host_config_write_common(pci_dev, addr, limit, val, len);
}
static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t addr, int len)
static uint32_t pcie_mmcfg_data_read(PCIBus *s, uint32_t mmcfg_addr, int len)
{
PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, addr);
PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
uint32_t addr;
uint32_t limit;
assert(len == 1 || len == 2 || len == 4);
if (!pci_dev) {
return ~0x0;
}
return pci_dev->config_read(pci_dev, PCIE_MMCFG_CONFOFFSET(addr), len);
addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
limit = pci_config_size(pci_dev);
if (limit <= addr) {
/* conventional pci device can be behind pcie-to-pci bridge.
256 <= addr < 4K has no effects. */
return ~0x0;
}
return pci_host_config_read_common(pci_dev, addr, limit, len);
}
static void pcie_mmcfg_data_writeb(void *opaque,

View File

@ -120,7 +120,6 @@ static void vhost_dev_unassign_memory(struct vhost_dev *dev,
if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
--dev->mem->nregions;
--to;
assert(to >= 0);
++overlap_middle;
continue;
}

View File

@ -594,4 +594,5 @@ void virtio_blk_exit(VirtIODevice *vdev)
{
VirtIOBlock *s = to_virtio_blk(vdev);
unregister_savevm(s->qdev, "virtio-blk", s);
virtio_cleanup(vdev);
}

View File

@ -1073,6 +1073,6 @@ void virtio_net_exit(VirtIODevice *vdev)
qemu_bh_delete(n->tx_bh);
}
virtio_cleanup(&n->vdev);
qemu_del_vlan_client(&n->nic->nc);
virtio_cleanup(&n->vdev);
}

View File

@ -27,6 +27,7 @@
#include "kvm.h"
#include "blockdev.h"
#include "virtio-pci.h"
#include "range.h"
/* from Linux's linux/virtio_pci.h */
@ -516,17 +517,16 @@ static void virtio_write_config(PCIDevice *pci_dev, uint32_t address,
{
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
if (PCI_COMMAND == address) {
if (!(val & PCI_COMMAND_MASTER)) {
if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_pci_stop_ioeventfd(proxy);
virtio_set_status(proxy->vdev,
proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
}
pci_default_write_config(pci_dev, address, val, len);
if (range_covers_byte(address, len, PCI_COMMAND) &&
!(pci_dev->config[PCI_COMMAND] & PCI_COMMAND_MASTER) &&
!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
virtio_pci_stop_ioeventfd(proxy);
virtio_set_status(proxy->vdev,
proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
}
pci_default_write_config(pci_dev, address, val, len);
msix_write_config(pci_dev, address, val, len);
}

View File

@ -834,6 +834,7 @@ void virtio_cleanup(VirtIODevice *vdev)
if (vdev->config)
qemu_free(vdev->config);
qemu_free(vdev->vq);
qemu_free(vdev);
}
static void virtio_vmstate_change(void *opaque, int running, int reason)

19
net.c
View File

@ -150,12 +150,11 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr)
static char *assign_name(VLANClientState *vc1, const char *model)
{
VLANState *vlan;
VLANClientState *vc;
char buf[256];
int id = 0;
QTAILQ_FOREACH(vlan, &vlans, next) {
VLANClientState *vc;
QTAILQ_FOREACH(vc, &vlan->clients, next) {
if (vc != vc1 && strcmp(vc->model, model) == 0) {
id++;
@ -163,6 +162,12 @@ static char *assign_name(VLANClientState *vc1, const char *model)
}
}
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
if (vc != vc1 && strcmp(vc->model, model) == 0) {
id++;
}
}
snprintf(buf, sizeof(buf), "%s.%d", model, id);
return qemu_strdup(buf);
@ -653,6 +658,8 @@ VLANClientState *qemu_find_netdev(const char *id)
VLANClientState *vc;
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
if (vc->info->type == NET_CLIENT_TYPE_NIC)
continue;
if (!strcmp(vc->name, id)) {
return vc;
}
@ -1212,7 +1219,7 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
VLANClientState *vc;
vc = qemu_find_netdev(id);
if (!vc || vc->info->type == NET_CLIENT_TYPE_NIC) {
if (!vc) {
qerror_report(QERR_DEVICE_NOT_FOUND, id);
return -1;
}
@ -1270,7 +1277,11 @@ int do_set_link(Monitor *mon, const QDict *qdict, QObject **ret_data)
}
}
}
vc = qemu_find_netdev(name);
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
if (!strcmp(vc->name, name)) {
goto done;
}
}
done:
if (!vc) {