mirror of https://github.com/xemu-project/xemu.git
Merge remote-tracking branch 'mst/for_anthony' into staging
This commit is contained in:
commit
81e34a2401
6
hw/pci.c
6
hw/pci.c
|
@ -1145,8 +1145,7 @@ uint32_t pci_default_read_config(PCIDevice *d,
|
||||||
uint32_t address, int len)
|
uint32_t address, int len)
|
||||||
{
|
{
|
||||||
uint32_t val = 0;
|
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);
|
memcpy(&val, d->config + address, len);
|
||||||
return le32_to_cpu(val);
|
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)
|
void pci_default_write_config(PCIDevice *d, uint32_t addr, uint32_t val, int l)
|
||||||
{
|
{
|
||||||
int i, was_irq_disabled = pci_irq_disabled(d);
|
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 wmask = d->wmask[addr + i];
|
||||||
uint8_t w1cmask = d->w1cmask[addr + i];
|
uint8_t w1cmask = d->w1cmask[addr + i];
|
||||||
assert(!(wmask & w1cmask));
|
assert(!(wmask & w1cmask));
|
||||||
|
|
|
@ -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);
|
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)
|
void pci_data_write(PCIBus *s, uint32_t addr, uint32_t val, int len)
|
||||||
{
|
{
|
||||||
PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
|
PCIDevice *pci_dev = pci_dev_find_by_addr(s, addr);
|
||||||
uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
|
uint32_t config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
|
||||||
|
|
||||||
if (!pci_dev)
|
if (!pci_dev) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
|
PCI_DPRINTF("%s: %s: addr=%02" PRIx32 " val=%08" PRIx32 " len=%d\n",
|
||||||
__func__, pci_dev->name, config_addr, val, len);
|
__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)
|
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 config_addr = addr & (PCI_CONFIG_SPACE_SIZE - 1);
|
||||||
uint32_t val;
|
uint32_t val;
|
||||||
|
|
||||||
assert(len == 1 || len == 2 || len == 4);
|
|
||||||
if (!pci_dev) {
|
if (!pci_dev) {
|
||||||
return ~0x0;
|
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",
|
PCI_DPRINTF("%s: %s: addr=%02"PRIx32" val=%08"PRIx32" len=%d\n",
|
||||||
__func__, pci_dev->name, config_addr, val, len);
|
__func__, pci_dev->name, config_addr, val, len);
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,12 @@ struct PCIHostState {
|
||||||
PCIBus *bus;
|
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);
|
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);
|
uint32_t pci_data_read(PCIBus *s, uint32_t addr, int len);
|
||||||
|
|
||||||
|
|
|
@ -56,23 +56,39 @@ static void pcie_mmcfg_data_write(PCIBus *s,
|
||||||
uint32_t mmcfg_addr, uint32_t val, int len)
|
uint32_t mmcfg_addr, uint32_t val, int len)
|
||||||
{
|
{
|
||||||
PCIDevice *pci_dev = pcie_dev_find_by_mmcfg_addr(s, mmcfg_addr);
|
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;
|
return;
|
||||||
|
}
|
||||||
pci_dev->config_write(pci_dev,
|
addr = PCIE_MMCFG_CONFOFFSET(mmcfg_addr);
|
||||||
PCIE_MMCFG_CONFOFFSET(mmcfg_addr), val, len);
|
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) {
|
if (!pci_dev) {
|
||||||
return ~0x0;
|
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,
|
static void pcie_mmcfg_data_writeb(void *opaque,
|
||||||
|
|
|
@ -120,7 +120,6 @@ static void vhost_dev_unassign_memory(struct vhost_dev *dev,
|
||||||
if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
|
if (start_addr <= reg->guest_phys_addr && memlast >= reglast) {
|
||||||
--dev->mem->nregions;
|
--dev->mem->nregions;
|
||||||
--to;
|
--to;
|
||||||
assert(to >= 0);
|
|
||||||
++overlap_middle;
|
++overlap_middle;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -594,4 +594,5 @@ void virtio_blk_exit(VirtIODevice *vdev)
|
||||||
{
|
{
|
||||||
VirtIOBlock *s = to_virtio_blk(vdev);
|
VirtIOBlock *s = to_virtio_blk(vdev);
|
||||||
unregister_savevm(s->qdev, "virtio-blk", s);
|
unregister_savevm(s->qdev, "virtio-blk", s);
|
||||||
|
virtio_cleanup(vdev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1073,6 +1073,6 @@ void virtio_net_exit(VirtIODevice *vdev)
|
||||||
qemu_bh_delete(n->tx_bh);
|
qemu_bh_delete(n->tx_bh);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtio_cleanup(&n->vdev);
|
|
||||||
qemu_del_vlan_client(&n->nic->nc);
|
qemu_del_vlan_client(&n->nic->nc);
|
||||||
|
virtio_cleanup(&n->vdev);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
#include "kvm.h"
|
#include "kvm.h"
|
||||||
#include "blockdev.h"
|
#include "blockdev.h"
|
||||||
#include "virtio-pci.h"
|
#include "virtio-pci.h"
|
||||||
|
#include "range.h"
|
||||||
|
|
||||||
/* from Linux's linux/virtio_pci.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);
|
VirtIOPCIProxy *proxy = DO_UPCAST(VirtIOPCIProxy, pci_dev, pci_dev);
|
||||||
|
|
||||||
if (PCI_COMMAND == address) {
|
pci_default_write_config(pci_dev, address, val, len);
|
||||||
if (!(val & PCI_COMMAND_MASTER)) {
|
|
||||||
if (!(proxy->flags & VIRTIO_PCI_FLAG_BUS_MASTER_BUG)) {
|
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_pci_stop_ioeventfd(proxy);
|
||||||
virtio_set_status(proxy->vdev,
|
virtio_set_status(proxy->vdev,
|
||||||
proxy->vdev->status & ~VIRTIO_CONFIG_S_DRIVER_OK);
|
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);
|
msix_write_config(pci_dev, address, val, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -834,6 +834,7 @@ void virtio_cleanup(VirtIODevice *vdev)
|
||||||
if (vdev->config)
|
if (vdev->config)
|
||||||
qemu_free(vdev->config);
|
qemu_free(vdev->config);
|
||||||
qemu_free(vdev->vq);
|
qemu_free(vdev->vq);
|
||||||
|
qemu_free(vdev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void virtio_vmstate_change(void *opaque, int running, int reason)
|
static void virtio_vmstate_change(void *opaque, int running, int reason)
|
||||||
|
|
19
net.c
19
net.c
|
@ -150,12 +150,11 @@ void qemu_macaddr_default_if_unset(MACAddr *macaddr)
|
||||||
static char *assign_name(VLANClientState *vc1, const char *model)
|
static char *assign_name(VLANClientState *vc1, const char *model)
|
||||||
{
|
{
|
||||||
VLANState *vlan;
|
VLANState *vlan;
|
||||||
|
VLANClientState *vc;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
int id = 0;
|
int id = 0;
|
||||||
|
|
||||||
QTAILQ_FOREACH(vlan, &vlans, next) {
|
QTAILQ_FOREACH(vlan, &vlans, next) {
|
||||||
VLANClientState *vc;
|
|
||||||
|
|
||||||
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
QTAILQ_FOREACH(vc, &vlan->clients, next) {
|
||||||
if (vc != vc1 && strcmp(vc->model, model) == 0) {
|
if (vc != vc1 && strcmp(vc->model, model) == 0) {
|
||||||
id++;
|
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);
|
snprintf(buf, sizeof(buf), "%s.%d", model, id);
|
||||||
|
|
||||||
return qemu_strdup(buf);
|
return qemu_strdup(buf);
|
||||||
|
@ -653,6 +658,8 @@ VLANClientState *qemu_find_netdev(const char *id)
|
||||||
VLANClientState *vc;
|
VLANClientState *vc;
|
||||||
|
|
||||||
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
|
QTAILQ_FOREACH(vc, &non_vlan_clients, next) {
|
||||||
|
if (vc->info->type == NET_CLIENT_TYPE_NIC)
|
||||||
|
continue;
|
||||||
if (!strcmp(vc->name, id)) {
|
if (!strcmp(vc->name, id)) {
|
||||||
return vc;
|
return vc;
|
||||||
}
|
}
|
||||||
|
@ -1212,7 +1219,7 @@ int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
|
||||||
VLANClientState *vc;
|
VLANClientState *vc;
|
||||||
|
|
||||||
vc = qemu_find_netdev(id);
|
vc = qemu_find_netdev(id);
|
||||||
if (!vc || vc->info->type == NET_CLIENT_TYPE_NIC) {
|
if (!vc) {
|
||||||
qerror_report(QERR_DEVICE_NOT_FOUND, id);
|
qerror_report(QERR_DEVICE_NOT_FOUND, id);
|
||||||
return -1;
|
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:
|
done:
|
||||||
|
|
||||||
if (!vc) {
|
if (!vc) {
|
||||||
|
|
Loading…
Reference in New Issue