Merge remote-tracking branch 'stefanha/net' into staging

# By Brad Smith (2) and others
# Via Stefan Hajnoczi
* stefanha/net:
  ne2000: mark I/O as LITTLE_ENDIAN
  vmxnet3: Eliminate __packed redefined warning
  e1000: add interrupt mitigation support
  net: Rename send_queue to incoming_queue
  tap: Use numbered tap/tun devices on all *BSD OS's

Message-id: 1378481624-20964-1-git-send-email-stefanha@redhat.com
Signed-off-by: Anthony Liguori <anthony@codemonkey.ws>
This commit is contained in:
Anthony Liguori 2013-09-11 14:45:18 -05:00
commit ce2b69417c
10 changed files with 174 additions and 29 deletions

View File

@ -339,14 +339,25 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
.desc = "Standard PC (i440FX + PIIX, 1996)", \
.hot_add_cpu = pc_hot_add_cpu
#define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v1_7 = {
PC_I440FX_1_7_MACHINE_OPTIONS,
.name = "pc-i440fx-1.7",
.alias = "pc",
.init = pc_init_pci,
.is_default = 1,
};
#define PC_I440FX_1_6_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
static QEMUMachine pc_i440fx_machine_v1_6 = {
PC_I440FX_1_6_MACHINE_OPTIONS,
.name = "pc-i440fx-1.6",
.alias = "pc",
.init = pc_init_pci_1_6,
.is_default = 1,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_6,
{ /* end of list */ }
},
};
static QEMUMachine pc_i440fx_machine_v1_5 = {
@ -735,6 +746,7 @@ static QEMUMachine xenfv_machine = {
static void pc_machine_init(void)
{
qemu_register_machine(&pc_i440fx_machine_v1_7);
qemu_register_machine(&pc_i440fx_machine_v1_6);
qemu_register_machine(&pc_i440fx_machine_v1_5);
qemu_register_machine(&pc_i440fx_machine_v1_4);

View File

@ -258,13 +258,25 @@ static void pc_q35_init_1_4(QEMUMachineInitArgs *args)
.desc = "Standard PC (Q35 + ICH9, 2009)", \
.hot_add_cpu = pc_hot_add_cpu
#define PC_Q35_1_7_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v1_7 = {
PC_Q35_1_7_MACHINE_OPTIONS,
.name = "pc-q35-1.7",
.alias = "q35",
.init = pc_q35_init,
};
#define PC_Q35_1_6_MACHINE_OPTIONS PC_Q35_MACHINE_OPTIONS
static QEMUMachine pc_q35_machine_v1_6 = {
PC_Q35_1_6_MACHINE_OPTIONS,
.name = "pc-q35-1.6",
.alias = "q35",
.init = pc_q35_init_1_6,
.compat_props = (GlobalProperty[]) {
PC_COMPAT_1_6,
{ /* end of list */ }
},
};
static QEMUMachine pc_q35_machine_v1_5 = {
@ -293,6 +305,7 @@ static QEMUMachine pc_q35_machine_v1_4 = {
static void pc_q35_machine_init(void)
{
qemu_register_machine(&pc_q35_machine_v1_7);
qemu_register_machine(&pc_q35_machine_v1_6);
qemu_register_machine(&pc_q35_machine_v1_5);
qemu_register_machine(&pc_q35_machine_v1_4);

View File

@ -135,9 +135,16 @@ typedef struct E1000State_st {
QEMUTimer *autoneg_timer;
QEMUTimer *mit_timer; /* Mitigation timer. */
bool mit_timer_on; /* Mitigation timer is running. */
bool mit_irq_level; /* Tracks interrupt pin level. */
uint32_t mit_ide; /* Tracks E1000_TXD_CMD_IDE bit. */
/* Compatibility flags for migration to/from qemu 1.3.0 and older */
#define E1000_FLAG_AUTONEG_BIT 0
#define E1000_FLAG_MIT_BIT 1
#define E1000_FLAG_AUTONEG (1 << E1000_FLAG_AUTONEG_BIT)
#define E1000_FLAG_MIT (1 << E1000_FLAG_MIT_BIT)
uint32_t compat_flags;
} E1000State;
@ -158,7 +165,8 @@ enum {
defreg(TORH), defreg(TORL), defreg(TOTH), defreg(TOTL),
defreg(TPR), defreg(TPT), defreg(TXDCTL), defreg(WUFC),
defreg(RA), defreg(MTA), defreg(CRCERRS),defreg(VFTA),
defreg(VET),
defreg(VET), defreg(RDTR), defreg(RADV), defreg(TADV),
defreg(ITR),
};
static void
@ -245,10 +253,21 @@ static const uint32_t mac_reg_init[] = {
E1000_MANC_RMCP_EN,
};
/* Helper function, *curr == 0 means the value is not set */
static inline void
mit_update_delay(uint32_t *curr, uint32_t value)
{
if (value && (*curr == 0 || value < *curr)) {
*curr = value;
}
}
static void
set_interrupt_cause(E1000State *s, int index, uint32_t val)
{
PCIDevice *d = PCI_DEVICE(s);
uint32_t pending_ints;
uint32_t mit_delay;
if (val && (E1000_DEVID >= E1000_DEV_ID_82547EI_MOBILE)) {
/* Only for 8257x */
@ -266,7 +285,57 @@ set_interrupt_cause(E1000State *s, int index, uint32_t val)
*/
s->mac_reg[ICS] = val;
qemu_set_irq(d->irq[0], (s->mac_reg[IMS] & s->mac_reg[ICR]) != 0);
pending_ints = (s->mac_reg[IMS] & s->mac_reg[ICR]);
if (!s->mit_irq_level && pending_ints) {
/*
* Here we detect a potential raising edge. We postpone raising the
* interrupt line if we are inside the mitigation delay window
* (s->mit_timer_on == 1).
* We provide a partial implementation of interrupt mitigation,
* emulating only RADV, TADV and ITR (lower 16 bits, 1024ns units for
* RADV and TADV, 256ns units for ITR). RDTR is only used to enable
* RADV; relative timers based on TIDV and RDTR are not implemented.
*/
if (s->mit_timer_on) {
return;
}
if (s->compat_flags & E1000_FLAG_MIT) {
/* Compute the next mitigation delay according to pending
* interrupts and the current values of RADV (provided
* RDTR!=0), TADV and ITR.
* Then rearm the timer.
*/
mit_delay = 0;
if (s->mit_ide &&
(pending_ints & (E1000_ICR_TXQE | E1000_ICR_TXDW))) {
mit_update_delay(&mit_delay, s->mac_reg[TADV] * 4);
}
if (s->mac_reg[RDTR] && (pending_ints & E1000_ICS_RXT0)) {
mit_update_delay(&mit_delay, s->mac_reg[RADV] * 4);
}
mit_update_delay(&mit_delay, s->mac_reg[ITR]);
if (mit_delay) {
s->mit_timer_on = 1;
timer_mod(s->mit_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) +
mit_delay * 256);
}
s->mit_ide = 0;
}
}
s->mit_irq_level = (pending_ints != 0);
qemu_set_irq(d->irq[0], s->mit_irq_level);
}
static void
e1000_mit_timer(void *opaque)
{
E1000State *s = opaque;
s->mit_timer_on = 0;
/* Call set_interrupt_cause to update the irq level (if necessary). */
set_interrupt_cause(s, 0, s->mac_reg[ICR]);
}
static void
@ -307,6 +376,10 @@ static void e1000_reset(void *opaque)
int i;
timer_del(d->autoneg_timer);
timer_del(d->mit_timer);
d->mit_timer_on = 0;
d->mit_irq_level = 0;
d->mit_ide = 0;
memset(d->phy_reg, 0, sizeof d->phy_reg);
memmove(d->phy_reg, phy_reg_init, sizeof phy_reg_init);
memset(d->mac_reg, 0, sizeof d->mac_reg);
@ -572,6 +645,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp)
struct e1000_context_desc *xp = (struct e1000_context_desc *)dp;
struct e1000_tx *tp = &s->tx;
s->mit_ide |= (txd_lower & E1000_TXD_CMD_IDE);
if (dtype == E1000_TXD_CMD_DEXT) { // context descriptor
op = le32_to_cpu(xp->cmd_and_length);
tp->ipcss = xp->lower_setup.ip_fields.ipcss;
@ -1047,7 +1121,8 @@ static uint32_t (*macreg_readops[])(E1000State *, int) = {
getreg(TORL), getreg(TOTL), getreg(IMS), getreg(TCTL),
getreg(RDH), getreg(RDT), getreg(VET), getreg(ICS),
getreg(TDBAL), getreg(TDBAH), getreg(RDBAH), getreg(RDBAL),
getreg(TDLEN), getreg(RDLEN),
getreg(TDLEN), getreg(RDLEN), getreg(RDTR), getreg(RADV),
getreg(TADV), getreg(ITR),
[TOTH] = mac_read_clr8, [TORH] = mac_read_clr8, [GPRC] = mac_read_clr4,
[GPTC] = mac_read_clr4, [TPR] = mac_read_clr4, [TPT] = mac_read_clr4,
@ -1069,6 +1144,8 @@ static void (*macreg_writeops[])(E1000State *, int, uint32_t) = {
[TDH] = set_16bit, [RDH] = set_16bit, [RDT] = set_rdt,
[IMC] = set_imc, [IMS] = set_ims, [ICR] = set_icr,
[EECD] = set_eecd, [RCTL] = set_rx_control, [CTRL] = set_ctrl,
[RDTR] = set_16bit, [RADV] = set_16bit, [TADV] = set_16bit,
[ITR] = set_16bit,
[RA ... RA+31] = &mac_writereg,
[MTA ... MTA+127] = &mac_writereg,
[VFTA ... VFTA+127] = &mac_writereg,
@ -1150,6 +1227,11 @@ static void e1000_pre_save(void *opaque)
E1000State *s = opaque;
NetClientState *nc = qemu_get_queue(s->nic);
/* If the mitigation timer is active, emulate a timeout now. */
if (s->mit_timer_on) {
e1000_mit_timer(s);
}
if (!(s->compat_flags & E1000_FLAG_AUTONEG)) {
return;
}
@ -1171,6 +1253,14 @@ static int e1000_post_load(void *opaque, int version_id)
E1000State *s = opaque;
NetClientState *nc = qemu_get_queue(s->nic);
if (!(s->compat_flags & E1000_FLAG_MIT)) {
s->mac_reg[ITR] = s->mac_reg[RDTR] = s->mac_reg[RADV] =
s->mac_reg[TADV] = 0;
s->mit_irq_level = false;
}
s->mit_ide = 0;
s->mit_timer_on = false;
/* nc.link_down can't be migrated, so infer link_down according
* to link status bit in mac_reg[STATUS].
* Alternatively, restart link negotiation if it was in progress. */
@ -1190,6 +1280,28 @@ static int e1000_post_load(void *opaque, int version_id)
return 0;
}
static bool e1000_mit_state_needed(void *opaque)
{
E1000State *s = opaque;
return s->compat_flags & E1000_FLAG_MIT;
}
static const VMStateDescription vmstate_e1000_mit_state = {
.name = "e1000/mit_state",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_UINT32(mac_reg[RDTR], E1000State),
VMSTATE_UINT32(mac_reg[RADV], E1000State),
VMSTATE_UINT32(mac_reg[TADV], E1000State),
VMSTATE_UINT32(mac_reg[ITR], E1000State),
VMSTATE_BOOL(mit_irq_level, E1000State),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_e1000 = {
.name = "e1000",
.version_id = 2,
@ -1267,6 +1379,14 @@ static const VMStateDescription vmstate_e1000 = {
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, MTA, 128),
VMSTATE_UINT32_SUB_ARRAY(mac_reg, E1000State, VFTA, 128),
VMSTATE_END_OF_LIST()
},
.subsections = (VMStateSubsection[]) {
{
.vmsd = &vmstate_e1000_mit_state,
.needed = e1000_mit_state_needed,
}, {
/* empty */
}
}
};
@ -1316,6 +1436,8 @@ pci_e1000_uninit(PCIDevice *dev)
timer_del(d->autoneg_timer);
timer_free(d->autoneg_timer);
timer_del(d->mit_timer);
timer_free(d->mit_timer);
memory_region_destroy(&d->mmio);
memory_region_destroy(&d->io);
qemu_del_nic(d->nic);
@ -1371,6 +1493,7 @@ static int pci_e1000_init(PCIDevice *pci_dev)
add_boot_device_path(d->conf.bootindex, dev, "/ethernet-phy@0");
d->autoneg_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, e1000_autoneg_timer, d);
d->mit_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, e1000_mit_timer, d);
return 0;
}
@ -1385,6 +1508,8 @@ static Property e1000_properties[] = {
DEFINE_NIC_PROPERTIES(E1000State, conf),
DEFINE_PROP_BIT("autonegotiation", E1000State,
compat_flags, E1000_FLAG_AUTONEG_BIT, true),
DEFINE_PROP_BIT("mitigation", E1000State,
compat_flags, E1000_FLAG_MIT_BIT, true),
DEFINE_PROP_END_OF_LIST(),
};

View File

@ -693,7 +693,7 @@ static void ne2000_write(void *opaque, hwaddr addr,
static const MemoryRegionOps ne2000_ops = {
.read = ne2000_read,
.write = ne2000_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.endianness = DEVICE_LITTLE_ENDIAN,
};
/***********************************************************/

View File

@ -34,7 +34,6 @@
#define __le16 uint16_t
#define __le32 uint32_t
#define __le64 uint64_t
#define __packed QEMU_PACKED
#if defined(HOST_WORDS_BIGENDIAN)
#define __BIG_ENDIAN_BITFIELD
@ -749,7 +748,6 @@ struct Vmxnet3_DriverShared {
#undef __le16
#undef __le32
#undef __le64
#undef __packed
#if defined(HOST_WORDS_BIGENDIAN)
#undef __BIG_ENDIAN_BITFIELD
#endif

View File

@ -225,7 +225,15 @@ void pvpanic_init(ISABus *bus);
int e820_add_entry(uint64_t, uint64_t, uint32_t);
#define PC_COMPAT_1_6 \
{\
.driver = "e1000",\
.property = "mitigation",\
.value = "off",\
}
#define PC_COMPAT_1_5 \
PC_COMPAT_1_6, \
{\
.driver = "Conroe-" TYPE_X86_CPU,\
.property = "model",\

View File

@ -69,7 +69,7 @@ struct NetClientState {
int link_down;
QTAILQ_ENTRY(NetClientState) next;
NetClientState *peer;
NetQueue *send_queue;
NetQueue *incoming_queue;
char *model;
char *name;
char info_str[256];

View File

@ -347,7 +347,7 @@ bool net_hub_flush(NetClientState *nc)
QLIST_FOREACH(port, &source_port->hub->ports, next) {
if (port != source_port) {
ret += qemu_net_queue_flush(port->nc.send_queue);
ret += qemu_net_queue_flush(port->nc.incoming_queue);
}
}
return ret ? true : false;

View File

@ -207,7 +207,7 @@ static void qemu_net_client_setup(NetClientState *nc,
}
QTAILQ_INSERT_TAIL(&net_clients, nc, next);
nc->send_queue = qemu_new_net_queue(nc);
nc->incoming_queue = qemu_new_net_queue(nc);
nc->destructor = destructor;
}
@ -289,8 +289,8 @@ static void qemu_cleanup_net_client(NetClientState *nc)
static void qemu_free_net_client(NetClientState *nc)
{
if (nc->send_queue) {
qemu_del_net_queue(nc->send_queue);
if (nc->incoming_queue) {
qemu_del_net_queue(nc->incoming_queue);
}
if (nc->peer) {
nc->peer->peer = NULL;
@ -431,7 +431,7 @@ void qemu_purge_queued_packets(NetClientState *nc)
return;
}
qemu_net_queue_purge(nc->peer->send_queue, nc);
qemu_net_queue_purge(nc->peer->incoming_queue, nc);
}
void qemu_flush_queued_packets(NetClientState *nc)
@ -444,7 +444,7 @@ void qemu_flush_queued_packets(NetClientState *nc)
}
return;
}
if (qemu_net_queue_flush(nc->send_queue)) {
if (qemu_net_queue_flush(nc->incoming_queue)) {
/* We emptied the queue successfully, signal to the IO thread to repoll
* the file descriptor (for tap, for example).
*/
@ -468,7 +468,7 @@ static ssize_t qemu_send_packet_async_with_flags(NetClientState *sender,
return size;
}
queue = sender->peer->send_queue;
queue = sender->peer->incoming_queue;
return qemu_net_queue_send(queue, sender, flags, buf, size, sent_cb);
}
@ -543,7 +543,7 @@ ssize_t qemu_sendv_packet_async(NetClientState *sender,
return iov_size(iov, iovcnt);
}
queue = sender->peer->send_queue;
queue = sender->peer->incoming_queue;
return qemu_net_queue_send_iov(queue, sender,
QEMU_NET_PACKET_FLAG_NONE,

View File

@ -44,8 +44,6 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
struct stat s;
#endif
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
defined(__OpenBSD__) || defined(__APPLE__)
/* if no ifname is given, always start the search from tap0/tun0. */
int i;
char dname[100];
@ -76,15 +74,6 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
dname, strerror(errno));
return -1;
}
#else
TFR(fd = open("/dev/tap", O_RDWR));
if (fd < 0) {
fprintf(stderr,
"warning: could not open /dev/tap: no virtual network emulation: %s\n",
strerror(errno));
return -1;
}
#endif
#ifdef TAPGIFNAME
if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) {