Commit db655a96 authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/jasowang/tags/net-pull-request' into staging



# gpg: Signature made Fri 20 Jan 2017 02:58:57 GMT
# gpg:                using RSA key 0xEF04965B398D6211
# gpg: Good signature from "Jason Wang (Jason Wang on RedHat) <jasowang@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 215D 46F4 8246 689E C77F  3562 EF04 965B 398D 6211

* remotes/jasowang/tags/net-pull-request:
  tap: fix memory leak on failure in net_init_tap()
  hw/pci: use-after-free in pci_nic_init_nofail when nic device fails to initialize
  hw/net/dp8393x: Avoid unintentional sign extensions on addresses
  m68k: QOMify the MCF Fast Ethernet Controller device
  net: optimize checksum computation
  docs: Fix description of the sentence

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 4383fa7c fac7d7b1
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -158,7 +158,9 @@ secondary.

== Usage ==

Here, we use demo ip and port discribe more clearly.
Here is an example using demonstration IP and port addresses to more
clearly describe the usage.

Primary(ip:3.3.3.3):
-netdev tap,id=hn0,vhost=off,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown
-device e1000,id=e0,netdev=hn0,mac=52:a4:00:12:78:66
+24 −1
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include "cpu.h"
#include "hw/hw.h"
#include "hw/m68k/mcf.h"
#include "hw/m68k/mcf_fec.h"
#include "qemu/timer.h"
#include "hw/ptimer.h"
#include "sysemu/sysemu.h"
@@ -18,6 +19,7 @@
#include "net/net.h"
#include "hw/boards.h"
#include "hw/loader.h"
#include "hw/sysbus.h"
#include "elf.h"
#include "exec/address-spaces.h"

@@ -192,6 +194,26 @@ static void mcf5208_sys_init(MemoryRegion *address_space, qemu_irq *pic)
    }
}

static void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd, hwaddr base,
                         qemu_irq *irqs)
{
    DeviceState *dev;
    SysBusDevice *s;
    int i;

    qemu_check_nic_model(nd, TYPE_MCF_FEC_NET);
    dev = qdev_create(NULL, TYPE_MCF_FEC_NET);
    qdev_set_nic_properties(dev, nd);
    qdev_init_nofail(dev);

    s = SYS_BUS_DEVICE(dev);
    for (i = 0; i < FEC_NUM_IRQ; i++) {
        sysbus_connect_irq(s, i, irqs[i]);
    }

    memory_region_add_subregion(sysmem, base, sysbus_mmio_get_region(s, 0));
}

static void mcf5208evb_init(MachineState *machine)
{
    ram_addr_t ram_size = machine->ram_size;
@@ -243,9 +265,10 @@ static void mcf5208evb_init(MachineState *machine)
        fprintf(stderr, "Too many NICs\n");
        exit(1);
    }
    if (nd_table[0].used)
    if (nd_table[0].used) {
        mcf_fec_init(address_space_mem, &nd_table[0],
                     0xfc030000, pic + 36);
    }

    /*  0xfc000000 SCM.  */
    /*  0xfc004000 XBS.  */
+68 −27
Original line number Diff line number Diff line
@@ -174,6 +174,52 @@ typedef struct dp8393xState {
    AddressSpace as;
} dp8393xState;

/* Accessor functions for values which are formed by
 * concatenating two 16 bit device registers. By putting these
 * in their own functions with a uint32_t return type we avoid the
 * pitfall of implicit sign extension where ((x << 16) | y) is a
 * signed 32 bit integer that might get sign-extended to a 64 bit integer.
 */
static uint32_t dp8393x_cdp(dp8393xState *s)
{
    return (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP];
}

static uint32_t dp8393x_crba(dp8393xState *s)
{
    return (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0];
}

static uint32_t dp8393x_crda(dp8393xState *s)
{
    return (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA];
}

static uint32_t dp8393x_rbwc(dp8393xState *s)
{
    return (s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0];
}

static uint32_t dp8393x_rrp(dp8393xState *s)
{
    return (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP];
}

static uint32_t dp8393x_tsa(dp8393xState *s)
{
    return (s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0];
}

static uint32_t dp8393x_ttda(dp8393xState *s)
{
    return (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA];
}

static uint32_t dp8393x_wt(dp8393xState *s)
{
    return s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
}

static void dp8393x_update_irq(dp8393xState *s)
{
    int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0;
@@ -203,8 +249,7 @@ static void dp8393x_do_load_cam(dp8393xState *s)

    while (s->regs[SONIC_CDC] & 0x1f) {
        /* Fill current entry */
        address_space_rw(&s->as,
            (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
        address_space_rw(&s->as, dp8393x_cdp(s),
            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
        s->cam[index][0] = data[1 * width] & 0xff;
        s->cam[index][1] = data[1 * width] >> 8;
@@ -222,8 +267,7 @@ static void dp8393x_do_load_cam(dp8393xState *s)
    }

    /* Read CAM enable */
    address_space_rw(&s->as,
        (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP],
    address_space_rw(&s->as, dp8393x_cdp(s),
        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
    s->regs[SONIC_CE] = data[0 * width];
    DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
@@ -242,8 +286,7 @@ static void dp8393x_do_read_rra(dp8393xState *s)
    /* Read memory */
    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
    size = sizeof(uint16_t) * 4 * width;
    address_space_rw(&s->as,
        (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP],
    address_space_rw(&s->as, dp8393x_rrp(s),
        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);

    /* Update SONIC registers */
@@ -292,7 +335,7 @@ static void dp8393x_set_next_tick(dp8393xState *s)
        return;
    }

    ticks = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
    ticks = dp8393x_wt(s);
    s->wt_last_update = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    delay = NANOSECONDS_PER_SECOND * ticks / 5000000;
    timer_mod(s->watchdog, s->wt_last_update + delay);
@@ -309,7 +352,7 @@ static void dp8393x_update_wt_regs(dp8393xState *s)
    }

    elapsed = s->wt_last_update - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
    val = s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
    val = dp8393x_wt(s);
    val -= elapsed / 5000000;
    s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
    s->regs[SONIC_WT0] = (val >> 0)  & 0xffff;
@@ -356,12 +399,11 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)

    while (1) {
        /* Read memory */
        DPRINTF("Transmit packet at %08x\n",
                (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_CTDA]);
        size = sizeof(uint16_t) * 6 * width;
        s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
        DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s));
        address_space_rw(&s->as,
            ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * width,
            dp8393x_ttda(s) + sizeof(uint16_t) * width,
            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
        tx_len = 0;

@@ -386,8 +428,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
            if (tx_len + len > sizeof(s->tx_buffer)) {
                len = sizeof(s->tx_buffer) - tx_len;
            }
            address_space_rw(&s->as,
                (s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0],
            address_space_rw(&s->as, dp8393x_tsa(s),
                MEMTXATTRS_UNSPECIFIED, &s->tx_buffer[tx_len], len, 0);
            tx_len += len;

@@ -396,7 +437,7 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
                /* Read next fragment details */
                size = sizeof(uint16_t) * 3 * width;
                address_space_rw(&s->as,
                    ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * i) * width,
                    dp8393x_ttda(s) + sizeof(uint16_t) * (4 + 3 * i) * width,
                    MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
                s->regs[SONIC_TSA0] = data[0 * width];
                s->regs[SONIC_TSA1] = data[1 * width];
@@ -430,14 +471,16 @@ static void dp8393x_do_transmit_packets(dp8393xState *s)
        data[0 * width] = s->regs[SONIC_TCR] & 0x0fff; /* status */
        size = sizeof(uint16_t) * width;
        address_space_rw(&s->as,
            (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA],
            dp8393x_ttda(s),
            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);

        if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
            /* Read footer of packet */
            size = sizeof(uint16_t) * width;
            address_space_rw(&s->as,
                ((s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA]) + sizeof(uint16_t) * (4 + 3 * s->regs[SONIC_TFC]) * width,
                dp8393x_ttda(s) +
                             sizeof(uint16_t) *
                             (4 + 3 * s->regs[SONIC_TFC]) * width,
                MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
            s->regs[SONIC_CTDA] = data[0 * width] & ~0x1;
            if (data[0 * width] & 0x1) {
@@ -700,7 +743,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
    if (s->regs[SONIC_LLFA] & 0x1) {
        /* Are we still in resource exhaustion? */
        size = sizeof(uint16_t) * 1 * width;
        address = ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width;
        address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
                         (uint8_t *)data, size, 0);
        if (data[0 * width] & 0x1) {
@@ -719,8 +762,8 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
    checksum = cpu_to_le32(crc32(0, buf, rx_len));

    /* Put packet into RBA */
    DPRINTF("Receive packet at %08x\n", (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0]);
    address = (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0];
    DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
    address = dp8393x_crba(s);
    address_space_rw(&s->as, address,
        MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, rx_len, 1);
    address += rx_len;
@@ -729,13 +772,13 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
    rx_len += 4;
    s->regs[SONIC_CRBA1] = address >> 16;
    s->regs[SONIC_CRBA0] = address & 0xffff;
    available = (s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0];
    available = dp8393x_rbwc(s);
    available -= rx_len / 2;
    s->regs[SONIC_RBWC1] = available >> 16;
    s->regs[SONIC_RBWC0] = available & 0xffff;

    /* Update status */
    if (((s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0]) < s->regs[SONIC_EOBC]) {
    if (dp8393x_rbwc(s) < s->regs[SONIC_EOBC]) {
        s->regs[SONIC_RCR] |= SONIC_RCR_LPKT;
    }
    s->regs[SONIC_RCR] |= packet_type;
@@ -746,20 +789,19 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
    }

    /* Write status to memory */
    DPRINTF("Write status at %08x\n", (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]);
    DPRINTF("Write status at %08x\n", dp8393x_crda(s));
    data[0 * width] = s->regs[SONIC_RCR]; /* status */
    data[1 * width] = rx_len; /* byte count */
    data[2 * width] = s->regs[SONIC_TRBA0]; /* pkt_ptr0 */
    data[3 * width] = s->regs[SONIC_TRBA1]; /* pkt_ptr1 */
    data[4 * width] = s->regs[SONIC_RSC]; /* seq_no */
    size = sizeof(uint16_t) * 5 * width;
    address_space_rw(&s->as, (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA],
    address_space_rw(&s->as, dp8393x_crda(s),
        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);

    /* Move to next descriptor */
    size = sizeof(uint16_t) * width;
    address_space_rw(&s->as,
        ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 5 * width,
    address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
    s->regs[SONIC_LLFA] = data[0 * width];
    if (s->regs[SONIC_LLFA] & 0x1) {
@@ -767,8 +809,7 @@ static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
        s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
    } else {
        data[0 * width] = 0; /* in_use */
        address_space_rw(&s->as,
            ((s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA]) + sizeof(uint16_t) * 6 * width,
        address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 6 * width,
            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, sizeof(uint16_t), 1);
        s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
        s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
+53 −18
Original line number Diff line number Diff line
@@ -9,7 +9,9 @@
#include "hw/hw.h"
#include "net/net.h"
#include "hw/m68k/mcf.h"
#include "hw/m68k/mcf_fec.h"
#include "hw/net/mii.h"
#include "hw/sysbus.h"
/* For crc32 */
#include <zlib.h>
#include "exec/address-spaces.h"
@@ -27,9 +29,10 @@ do { printf("mcf_fec: " fmt , ## __VA_ARGS__); } while (0)
#define FEC_MAX_FRAME_SIZE 2032

typedef struct {
    MemoryRegion *sysmem;
    SysBusDevice parent_obj;

    MemoryRegion iomem;
    qemu_irq *irq;
    qemu_irq irq[FEC_NUM_IRQ];
    NICState *nic;
    NICConf conf;
    uint32_t irq_state;
@@ -68,7 +71,6 @@ typedef struct {
#define FEC_RESET   1

/* Map interrupt flags onto IRQ lines.  */
#define FEC_NUM_IRQ 13
static const uint32_t mcf_fec_irq_map[FEC_NUM_IRQ] = {
    FEC_INT_TXF,
    FEC_INT_TXB,
@@ -208,8 +210,10 @@ static void mcf_fec_enable_rx(mcf_fec_state *s)
    }
}

static void mcf_fec_reset(mcf_fec_state *s)
static void mcf_fec_reset(DeviceState *dev)
{
    mcf_fec_state *s = MCF_FEC_NET(dev);

    s->eir = 0;
    s->eimr = 0;
    s->rx_enabled = 0;
@@ -330,7 +334,7 @@ static void mcf_fec_write(void *opaque, hwaddr addr,
        s->ecr = value;
        if (value & FEC_RESET) {
            DPRINTF("Reset\n");
            mcf_fec_reset(s);
            mcf_fec_reset(opaque);
        }
        if ((s->ecr & FEC_EN) == 0) {
            s->rx_enabled = 0;
@@ -513,24 +517,55 @@ static NetClientInfo net_mcf_fec_info = {
    .receive = mcf_fec_receive,
};

void mcf_fec_init(MemoryRegion *sysmem, NICInfo *nd,
                  hwaddr base, qemu_irq *irq)
static void mcf_fec_realize(DeviceState *dev, Error **errp)
{
    mcf_fec_state *s;
    mcf_fec_state *s = MCF_FEC_NET(dev);

    s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf,
                          object_get_typename(OBJECT(dev)), dev->id, s);
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
}

    qemu_check_nic_model(nd, "mcf_fec");
static void mcf_fec_instance_init(Object *obj)
{
    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
    mcf_fec_state *s = MCF_FEC_NET(obj);
    int i;

    memory_region_init_io(&s->iomem, obj, &mcf_fec_ops, s, "fec", 0x400);
    sysbus_init_mmio(sbd, &s->iomem);
    for (i = 0; i < FEC_NUM_IRQ; i++) {
        sysbus_init_irq(sbd, &s->irq[i]);
    }
}

    s = (mcf_fec_state *)g_malloc0(sizeof(mcf_fec_state));
    s->sysmem = sysmem;
    s->irq = irq;
static Property mcf_fec_properties[] = {
    DEFINE_NIC_PROPERTIES(mcf_fec_state, conf),
    DEFINE_PROP_END_OF_LIST(),
};

    memory_region_init_io(&s->iomem, NULL, &mcf_fec_ops, s, "fec", 0x400);
    memory_region_add_subregion(sysmem, base, &s->iomem);
static void mcf_fec_class_init(ObjectClass *oc, void *data)
{
    DeviceClass *dc = DEVICE_CLASS(oc);

    s->conf.macaddr = nd->macaddr;
    s->conf.peers.ncs[0] = nd->netdev;
    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
    dc->realize = mcf_fec_realize;
    dc->desc = "MCF Fast Ethernet Controller network device";
    dc->reset = mcf_fec_reset;
    dc->props = mcf_fec_properties;
}

    s->nic = qemu_new_nic(&net_mcf_fec_info, &s->conf, nd->model, nd->name, s);
static const TypeInfo mcf_fec_info = {
    .name          = TYPE_MCF_FEC_NET,
    .parent        = TYPE_SYS_BUS_DEVICE,
    .instance_size = sizeof(mcf_fec_state),
    .instance_init = mcf_fec_instance_init,
    .class_init    = mcf_fec_class_init,
};

    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
static void mcf_fec_register_types(void)
{
    type_register_static(&mcf_fec_info);
}

type_init(mcf_fec_register_types)
+1 −8
Original line number Diff line number Diff line
@@ -1779,7 +1779,6 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
                               const char *default_devaddr)
{
    const char *devaddr = nd->devaddr ? nd->devaddr : default_devaddr;
    Error *err = NULL;
    PCIBus *bus;
    PCIDevice *pci_dev;
    DeviceState *dev;
@@ -1805,13 +1804,7 @@ PCIDevice *pci_nic_init_nofail(NICInfo *nd, PCIBus *rootbus,
    pci_dev = pci_create(bus, devfn, pci_nic_names[i]);
    dev = &pci_dev->qdev;
    qdev_set_nic_properties(dev, nd);

    object_property_set_bool(OBJECT(dev), true, "realized", &err);
    if (err) {
        error_report_err(err);
        object_unparent(OBJECT(dev));
        exit(1);
    }
    qdev_init_nofail(dev);

    return pci_dev;
}
Loading