From 3a26360d1df3c3519a45636ec2189429d3df0ecb Mon Sep 17 00:00:00 2001 From: Anthony Liguori Date: Tue, 1 Nov 2011 16:49:17 -0500 Subject: [PATCH 01/28] spapr: fix build Signed-off-by: Anthony Liguori --- hw/spapr_pci.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c index 2a5e6374c3..7162588543 100644 --- a/hw/spapr_pci.c +++ b/hw/spapr_pci.c @@ -51,7 +51,7 @@ static PCIDevice *find_dev(sPAPREnvironment *spapr, continue; } - QLIST_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) { + QTAILQ_FOREACH(qdev, &phb->host_state.bus->qbus.children, sibling) { PCIDevice *dev = (PCIDevice *)qdev; if (dev->devfn == devfn) { return dev; @@ -397,7 +397,7 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb, /* Populate PCI devices and allocate IRQs */ devices = 0; - QLIST_FOREACH(qdev, &bus->qbus.children, sibling) { + QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) { PCIDevice *dev = DO_UPCAST(PCIDevice, qdev, qdev); int irq_index = pci_spapr_map_irq(dev, 0); uint32_t *irqmap = interrupt_map[devices]; From db9eae1c49fe2766a7709d7b2c4cdfcd91b9c25b Mon Sep 17 00:00:00 2001 From: Xu He Jie Date: Thu, 27 Oct 2011 10:15:13 +0800 Subject: [PATCH 02/28] kvm_init didn't set return value after create vm failed And kvm_ioctl(s, KVM_CREATE_VM, 0)'s return value can be < -1, so change the check of vmfd at label 'err'. Signed-off-by: Xu He Jie Signed-off-by: Anthony Liguori --- kvm-all.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kvm-all.c b/kvm-all.c index c09ddf7ac5..4c466d6aba 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -740,6 +740,7 @@ int kvm_init(void) fprintf(stderr, "Please add the 'switch_amode' kernel parameter to " "your host kernel command line\n"); #endif + ret = s->vmfd; goto err; } @@ -798,7 +799,7 @@ int kvm_init(void) err: if (s) { - if (s->vmfd != -1) { + if (s->vmfd >= 0) { close(s->vmfd); } if (s->fd != -1) { From fa39a30fe4b92adb77178f388947da922d41648d Mon Sep 17 00:00:00 2001 From: Juan Quintela Date: Tue, 25 Oct 2011 19:18:58 +0200 Subject: [PATCH 03/28] savevm: qemu_fille_buffer() used to return one error for reads of size 0. Signed-off-by: Juan Quintela Signed-off-by: Anthony Liguori --- savevm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/savevm.c b/savevm.c index f01838fb2d..bee16c0b7b 100644 --- a/savevm.c +++ b/savevm.c @@ -476,6 +476,8 @@ static void qemu_fill_buffer(QEMUFile *f) if (len > 0) { f->buf_size += len; f->buf_offset += len; + } else if (len == 0) { + f->last_error = -EIO; } else if (len != -EAGAIN) f->last_error = len; } From e589728b6fffaa74f8d535dab5ad65700dc606bb Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 7 Oct 2011 15:59:01 +0200 Subject: [PATCH 04/28] checkpatch: remove rule on non-indented labels There are 508 non-indented (non-default) labels, and 511 that are indented. So the rule is debatable at least. Actually, in the common case of labels at the outermost scope, there is really just one place where to put the label, so the rule is just wrong IMHO. Signed-off-by: Paolo Bonzini Signed-off-by: Anthony Liguori --- scripts/checkpatch.pl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl index 0eba357cc2..7a71324f6a 100755 --- a/scripts/checkpatch.pl +++ b/scripts/checkpatch.pl @@ -2206,12 +2206,6 @@ sub process { ERROR("space prohibited before that close parenthesis ')'\n" . $herecurr); } -#goto labels aren't indented, allow a single space however - if ($line=~/^.\s+[A-Za-z\d_]+:(?![0-9]+)/ and - !($line=~/^. [A-Za-z\d_]+:/) and !($line=~/^.\s+default:/)) { - WARN("labels should not be indented\n" . $herecurr); - } - # Return is not a function. if (defined($stat) && $stat =~ /^.\s*return(\s*)(\(.*);/s) { my $spacing = $1; From ae878b172e8fe4a4237874de2d3bb879699d8af5 Mon Sep 17 00:00:00 2001 From: Stefan Weil Date: Fri, 7 Oct 2011 21:15:20 +0200 Subject: [PATCH 05/28] ui/vnc: Fix use of free() instead of g_free() Please note that mechlist still uses malloc / strdup / free. Signed-off-by: Stefan Weil Signed-off-by: Anthony Liguori --- ui/vnc-auth-sasl.c | 8 ++++---- ui/vnc-enc-hextile.c | 4 ++-- ui/vnc-tls.c | 2 +- ui/vnc.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index e96095ab94..23b1bf5c4d 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -34,7 +34,7 @@ void vnc_sasl_client_cleanup(VncState *vs) vs->sasl.runSSF = vs->sasl.waitWriteSSF = vs->sasl.wantSSF = 0; vs->sasl.encodedLength = vs->sasl.encodedOffset = 0; vs->sasl.encoded = NULL; - free(vs->sasl.username); + g_free(vs->sasl.username); free(vs->sasl.mechlist); vs->sasl.username = vs->sasl.mechlist = NULL; sasl_dispose(&vs->sasl.conn); @@ -506,7 +506,7 @@ void start_auth_sasl(VncState *vs) goto authabort; if (!(remoteAddr = vnc_socket_remote_addr("%s;%s", vs->csock))) { - free(localAddr); + g_free(localAddr); goto authabort; } @@ -518,8 +518,8 @@ void start_auth_sasl(VncState *vs) NULL, /* Callbacks, not needed */ SASL_SUCCESS_DATA, &vs->sasl.conn); - free(localAddr); - free(remoteAddr); + g_free(localAddr); + g_free(remoteAddr); localAddr = remoteAddr = NULL; if (err != SASL_OK) { diff --git a/ui/vnc-enc-hextile.c b/ui/vnc-enc-hextile.c index d2905c88f0..c860dbb2e5 100644 --- a/ui/vnc-enc-hextile.c +++ b/ui/vnc-enc-hextile.c @@ -80,8 +80,8 @@ int vnc_hextile_send_framebuffer_update(VncState *vs, int x, last_bg, last_fg, &has_bg, &has_fg); } } - free(last_fg); - free(last_bg); + g_free(last_fg); + g_free(last_bg); return 1; } diff --git a/ui/vnc-tls.c b/ui/vnc-tls.c index ffbd1725a4..3aaa93928a 100644 --- a/ui/vnc-tls.c +++ b/ui/vnc-tls.c @@ -413,7 +413,7 @@ void vnc_tls_client_cleanup(struct VncState *vs) vs->tls.session = NULL; } vs->tls.wiremode = VNC_WIREMODE_CLEAR; - free(vs->tls.dname); + g_free(vs->tls.dname); } diff --git a/ui/vnc.c b/ui/vnc.c index 32d4cb70cd..40018f70f1 100644 --- a/ui/vnc.c +++ b/ui/vnc.c @@ -2911,7 +2911,7 @@ int vnc_display_open(DisplayState *ds, const char *display) if ((saslErr = sasl_server_init(NULL, "qemu")) != SASL_OK) { fprintf(stderr, "Failed to initialize SASL auth %s", sasl_errstring(saslErr, NULL, NULL)); - free(vs->display); + g_free(vs->display); vs->display = NULL; return -1; } @@ -2925,7 +2925,7 @@ int vnc_display_open(DisplayState *ds, const char *display) else vs->lsock = inet_connect(display, SOCK_STREAM); if (-1 == vs->lsock) { - free(vs->display); + g_free(vs->display); vs->display = NULL; return -1; } else { @@ -2946,10 +2946,10 @@ int vnc_display_open(DisplayState *ds, const char *display) vs->lsock = inet_listen(display, dpy, 256, SOCK_STREAM, 5900); } if (-1 == vs->lsock) { - free(dpy); + g_free(dpy); return -1; } else { - free(vs->display); + g_free(vs->display); vs->display = dpy; } } From 7f540ab5248a62c6ca4f6346a3564d0eff0069db Mon Sep 17 00:00:00 2001 From: Christophe Fergeau Date: Mon, 17 Oct 2011 13:37:34 +0200 Subject: [PATCH 06/28] ps2: migrate ledstate Make the ps2 device track its ledstate so that we can migrate it. Otherwise it gets lost across migration, and spice-server gets confused about the actual keyboard state and sends bogus caps/scroll/num key events. This fixes RH bug #729294 We only need to migrate the state when it is different of the default one (0). Signed-off-by: Christophe Fergeau Signed-off-by: Juan Quintela Signed-off-by: Anthony Liguori --- hw/ps2.c | 46 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/hw/ps2.c b/hw/ps2.c index 24228c1539..1d9057bbf5 100644 --- a/hw/ps2.c +++ b/hw/ps2.c @@ -92,6 +92,7 @@ typedef struct { not the keyboard controller. */ int translate; int scancode_set; /* 1=XT, 2=AT, 3=PS/2 */ + int ledstate; } PS2KbdState; typedef struct { @@ -195,11 +196,17 @@ uint32_t ps2_read_data(void *opaque) return val; } +static void ps2_set_ledstate(PS2KbdState *s, int ledstate) +{ + s->ledstate = ledstate; + kbd_put_ledstate(ledstate); +} + static void ps2_reset_keyboard(PS2KbdState *s) { s->scan_enabled = 1; s->scancode_set = 2; - kbd_put_ledstate(0); + ps2_set_ledstate(s, 0); } void ps2_write_keyboard(void *opaque, int val) @@ -274,7 +281,7 @@ void ps2_write_keyboard(void *opaque, int val) s->common.write_cmd = -1; break; case KBD_CMD_SET_LEDS: - kbd_put_ledstate(val); + ps2_set_ledstate(s, val); ps2_queue(&s->common, KBD_REPLY_ACK); s->common.write_cmd = -1; break; @@ -557,6 +564,33 @@ static const VMStateDescription vmstate_ps2_common = { } }; +static bool ps2_keyboard_ledstate_needed(void *opaque) +{ + PS2KbdState *s = opaque; + + return s->ledstate != 0; /* 0 is default state */ +} + +static int ps2_kbd_ledstate_post_load(void *opaque, int version_id) +{ + PS2KbdState *s = opaque; + + kbd_put_ledstate(s->ledstate); + return 0; +} + +static const VMStateDescription vmstate_ps2_keyboard_ledstate = { + .name = "ps2kbd/ledstate", + .version_id = 3, + .minimum_version_id = 2, + .minimum_version_id_old = 2, + .post_load = ps2_kbd_ledstate_post_load, + .fields = (VMStateField []) { + VMSTATE_INT32(ledstate, PS2KbdState), + VMSTATE_END_OF_LIST() + } +}; + static int ps2_kbd_post_load(void* opaque, int version_id) { PS2KbdState *s = (PS2KbdState*)opaque; @@ -578,6 +612,14 @@ static const VMStateDescription vmstate_ps2_keyboard = { VMSTATE_INT32(translate, PS2KbdState), VMSTATE_INT32_V(scancode_set, PS2KbdState,3), VMSTATE_END_OF_LIST() + }, + .subsections = (VMStateSubsection []) { + { + .vmsd = &vmstate_ps2_keyboard_ledstate, + .needed = ps2_keyboard_ledstate_needed, + }, { + /* empty */ + } } }; From d9d1055ef1426da47b626883fffdc934c5f5ab91 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:45 +1100 Subject: [PATCH 07/28] Define DMA address and direction types As a preliminary to adding more extensive DMA and IOMMU infrastructure support into qemu, this patch defines a dma_addr_t for storing DMA bus addresses and a DMADirection enum which describes whether a DMA is from an external device to main memory or from main memory to an external device. For now dma_addr_t is just defined to be target_phys_addr_t, but in future, we can change this to support machines where we have bus addresses which don't necessarily have the same format as CPU physical addresses. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- dma.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/dma.h b/dma.h index 2bdc236c4c..56e163a58f 100644 --- a/dma.h +++ b/dma.h @@ -18,6 +18,15 @@ typedef struct ScatterGatherEntry ScatterGatherEntry; #if defined(TARGET_PHYS_ADDR_BITS) +typedef target_phys_addr_t dma_addr_t; + +#define DMA_ADDR_FMT TARGET_FMT_plx + +typedef enum { + DMA_DIRECTION_TO_DEVICE = 0, + DMA_DIRECTION_FROM_DEVICE = 1, +} DMADirection; + struct ScatterGatherEntry { target_phys_addr_t base; target_phys_addr_t len; From d32311810fd3da5b68912e71cec6c7e59b1ee3eb Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:46 +1100 Subject: [PATCH 08/28] Use dma_addr_t type for scatter/gather code This patch uses the newly created dma_addr_t type throughout the scatter/gather handling code in dma-helpers.c whenever we need to represent a dma bus address. This makes a better distinction as to what is a bus address and what is a cpu physical address. Since we don't support IOMMUs yet, they can't be very different for now, but that will change in future, and this preliminary helps clarify what's going on. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- dma-helpers.c | 5 ++--- dma.h | 9 ++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/dma-helpers.c b/dma-helpers.c index 86d2d0a997..bdcd38cd27 100644 --- a/dma-helpers.c +++ b/dma-helpers.c @@ -18,8 +18,7 @@ void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint) qsg->size = 0; } -void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base, - target_phys_addr_t len) +void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len) { if (qsg->nsg == qsg->nalloc) { qsg->nalloc = 2 * qsg->nalloc + 1; @@ -45,7 +44,7 @@ typedef struct { bool to_dev; bool in_cancel; int sg_cur_index; - target_phys_addr_t sg_cur_byte; + dma_addr_t sg_cur_byte; QEMUIOVector iov; QEMUBH *bh; DMAIOFunc *io_func; diff --git a/dma.h b/dma.h index 56e163a58f..a13209d7eb 100644 --- a/dma.h +++ b/dma.h @@ -28,20 +28,19 @@ typedef enum { } DMADirection; struct ScatterGatherEntry { - target_phys_addr_t base; - target_phys_addr_t len; + dma_addr_t base; + dma_addr_t len; }; struct QEMUSGList { ScatterGatherEntry *sg; int nsg; int nalloc; - target_phys_addr_t size; + dma_addr_t size; }; void qemu_sglist_init(QEMUSGList *qsg, int alloc_hint); -void qemu_sglist_add(QEMUSGList *qsg, target_phys_addr_t base, - target_phys_addr_t len); +void qemu_sglist_add(QEMUSGList *qsg, dma_addr_t base, dma_addr_t len); void qemu_sglist_destroy(QEMUSGList *qsg); #endif From ec17457588ad944794502cfe1c76a34ff8a11618 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:47 +1100 Subject: [PATCH 09/28] Add stub functions for PCI device models to do PCI DMA This patch adds functions to pci.[ch] to perform PCI DMA operations. At present, these are just stubs which perform directly cpu physical memory accesses. Stubs are included which are analogous to cpu_physical_memory_{read,write}(), the stX_phys() and ldX_phys() functions and cpu_physical_memory_{map,unmap}(). In addition, a wrapper around qemu_sglist_init() is provided, which also takes a PCIDevice *. It's assumed that _init() is the only sglist function which will need wrapping, the idea being that once we have IOMMU support whatever IOMMU context handle the wrapper derives from the PCI device will be stored within the sglist structure for later use. Using these stubs, however, distinguishes PCI device DMA transactions from other accesses to physical memory, which will allow PCI IOMMU support to be added in one place, rather than updating every PCI driver at that time. That is, it allows us to update individual PCI drivers to support an IOMMU without having yet determined the details of how the IOMMU emulation will operate. This will let us remove the most bitrot-sensitive part of an IOMMU patch in advance. Signed-off-by: David Gibson Signed-off-by: Alexey Kardashevskiy Signed-off-by: Anthony Liguori --- hw/pci.h | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/hw/pci.h b/hw/pci.h index 98f30f748c..4b2e7859e6 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -5,6 +5,7 @@ #include "qdev.h" #include "memory.h" +#include "dma.h" /* PCI includes legacy ISA access. */ #include "isa.h" @@ -483,4 +484,70 @@ static inline uint32_t pci_config_size(const PCIDevice *d) return pci_is_express(d) ? PCIE_CONFIG_SPACE_SIZE : PCI_CONFIG_SPACE_SIZE; } +/* DMA access functions */ +static inline int pci_dma_rw(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len, DMADirection dir) +{ + cpu_physical_memory_rw(addr, buf, len, dir == DMA_DIRECTION_FROM_DEVICE); + return 0; +} + +static inline int pci_dma_read(PCIDevice *dev, dma_addr_t addr, + void *buf, dma_addr_t len) +{ + return pci_dma_rw(dev, addr, buf, len, DMA_DIRECTION_TO_DEVICE); +} + +static inline int pci_dma_write(PCIDevice *dev, dma_addr_t addr, + const void *buf, dma_addr_t len) +{ + return pci_dma_rw(dev, addr, (void *) buf, len, DMA_DIRECTION_FROM_DEVICE); +} + +#define PCI_DMA_DEFINE_LDST(_l, _s, _bits) \ + static inline uint##_bits##_t ld##_l##_pci_dma(PCIDevice *dev, \ + dma_addr_t addr) \ + { \ + return ld##_l##_phys(addr); \ + } \ + static inline void st##_s##_pci_dma(PCIDevice *dev, \ + dma_addr_t addr, uint##_bits##_t val) \ + { \ + st##_s##_phys(addr, val); \ + } + +PCI_DMA_DEFINE_LDST(ub, b, 8); +PCI_DMA_DEFINE_LDST(uw_le, w_le, 16) +PCI_DMA_DEFINE_LDST(l_le, l_le, 32); +PCI_DMA_DEFINE_LDST(q_le, q_le, 64); +PCI_DMA_DEFINE_LDST(uw_be, w_be, 16) +PCI_DMA_DEFINE_LDST(l_be, l_be, 32); +PCI_DMA_DEFINE_LDST(q_be, q_be, 64); + +#undef PCI_DMA_DEFINE_LDST + +static inline void *pci_dma_map(PCIDevice *dev, dma_addr_t addr, + dma_addr_t *plen, DMADirection dir) +{ + target_phys_addr_t len = *plen; + void *buf; + + buf = cpu_physical_memory_map(addr, &len, dir == DMA_DIRECTION_FROM_DEVICE); + *plen = len; + return buf; +} + +static inline void pci_dma_unmap(PCIDevice *dev, void *buffer, dma_addr_t len, + DMADirection dir, dma_addr_t access_len) +{ + cpu_physical_memory_unmap(buffer, len, dir == DMA_DIRECTION_FROM_DEVICE, + access_len); +} + +static inline void pci_dma_sglist_init(QEMUSGList *qsg, PCIDevice *dev, + int alloc_hint) +{ + qemu_sglist_init(qsg, alloc_hint); +} + #endif From 3ada003aee2004d24f23b9cd6f4eda87d9601ddb Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:48 +1100 Subject: [PATCH 10/28] rtl8139: Use PCI DMA stub functions This updates the rtl8139 device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/rtl8139.c | 106 ++++++++++++++++++++++++++------------------------- 1 file changed, 54 insertions(+), 52 deletions(-) diff --git a/hw/rtl8139.c b/hw/rtl8139.c index 37539508c5..4c379932e3 100644 --- a/hw/rtl8139.c +++ b/hw/rtl8139.c @@ -53,6 +53,7 @@ #include "hw.h" #include "pci.h" +#include "dma.h" #include "qemu-timer.h" #include "net.h" #include "loader.h" @@ -427,9 +428,6 @@ typedef struct RTL8139TallyCounters /* Clears all tally counters */ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters); -/* Writes tally counters to specified physical memory address */ -static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* counters); - typedef struct RTL8139State { PCIDevice dev; uint8_t phys[8]; /* mac address */ @@ -512,6 +510,9 @@ typedef struct RTL8139State { int rtl8139_mmio_io_addr_dummy; } RTL8139State; +/* Writes tally counters to memory via DMA */ +static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr); + static void rtl8139_set_next_tctr_time(RTL8139State *s, int64_t current_time); static void prom9346_decode_command(EEprom9346 *eeprom, uint8_t command) @@ -773,15 +774,15 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) if (size > wrapped) { - cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, - buf, size-wrapped ); + pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr, + buf, size-wrapped); } /* reset buffer pointer */ s->RxBufAddr = 0; - cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, - buf + (size-wrapped), wrapped ); + pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr, + buf + (size-wrapped), wrapped); s->RxBufAddr = wrapped; @@ -790,13 +791,13 @@ static void rtl8139_write_buffer(RTL8139State *s, const void *buf, int size) } /* non-wrapping path or overwrapping enabled */ - cpu_physical_memory_write( s->RxBuf + s->RxBufAddr, buf, size ); + pci_dma_write(&s->dev, s->RxBuf + s->RxBufAddr, buf, size); s->RxBufAddr += size; } #define MIN_BUF_SIZE 60 -static inline target_phys_addr_t rtl8139_addr64(uint32_t low, uint32_t high) +static inline dma_addr_t rtl8139_addr64(uint32_t low, uint32_t high) { #if TARGET_PHYS_ADDR_BITS > 32 return low | ((target_phys_addr_t)high << 32); @@ -979,24 +980,24 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* w3 high 32bit of Rx buffer ptr */ int descriptor = s->currCPlusRxDesc; - target_phys_addr_t cplus_rx_ring_desc; + dma_addr_t cplus_rx_ring_desc; cplus_rx_ring_desc = rtl8139_addr64(s->RxRingAddrLO, s->RxRingAddrHI); cplus_rx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading RX descriptor %d from host memory at " - "%08x %08x = "TARGET_FMT_plx"\n", descriptor, s->RxRingAddrHI, + "%08x %08x = "DMA_ADDR_FMT"\n", descriptor, s->RxRingAddrHI, s->RxRingAddrLO, cplus_rx_ring_desc); uint32_t val, rxdw0,rxdw1,rxbufLO,rxbufHI; - cpu_physical_memory_read(cplus_rx_ring_desc, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4); rxdw0 = le32_to_cpu(val); - cpu_physical_memory_read(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4); rxdw1 = le32_to_cpu(val); - cpu_physical_memory_read(cplus_rx_ring_desc+8, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_rx_ring_desc+8, (uint8_t *)&val, 4); rxbufLO = le32_to_cpu(val); - cpu_physical_memory_read(cplus_rx_ring_desc+12, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_rx_ring_desc+12, (uint8_t *)&val, 4); rxbufHI = le32_to_cpu(val); DPRINTF("+++ C+ mode RX descriptor %d %08x %08x %08x %08x\n", @@ -1060,16 +1061,16 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ return size_; } - target_phys_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); + dma_addr_t rx_addr = rtl8139_addr64(rxbufLO, rxbufHI); /* receive/copy to target memory */ if (dot1q_buf) { - cpu_physical_memory_write(rx_addr, buf, 2 * ETHER_ADDR_LEN); - cpu_physical_memory_write(rx_addr + 2 * ETHER_ADDR_LEN, - buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN, - size - 2 * ETHER_ADDR_LEN); + pci_dma_write(&s->dev, rx_addr, buf, 2 * ETHER_ADDR_LEN); + pci_dma_write(&s->dev, rx_addr + 2 * ETHER_ADDR_LEN, + buf + 2 * ETHER_ADDR_LEN + VLAN_HLEN, + size - 2 * ETHER_ADDR_LEN); } else { - cpu_physical_memory_write(rx_addr, buf, size); + pci_dma_write(&s->dev, rx_addr, buf, size); } if (s->CpCmd & CPlusRxChkSum) @@ -1079,7 +1080,7 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* write checksum */ val = cpu_to_le32(crc32(0, buf, size_)); - cpu_physical_memory_write( rx_addr+size, (uint8_t *)&val, 4); + pci_dma_write(&s->dev, rx_addr+size, (uint8_t *)&val, 4); /* first segment of received packet flag */ #define CP_RX_STATUS_FS (1<<29) @@ -1125,9 +1126,9 @@ static ssize_t rtl8139_do_receive(VLANClientState *nc, const uint8_t *buf, size_ /* update ring data */ val = cpu_to_le32(rxdw0); - cpu_physical_memory_write(cplus_rx_ring_desc, (uint8_t *)&val, 4); + pci_dma_write(&s->dev, cplus_rx_ring_desc, (uint8_t *)&val, 4); val = cpu_to_le32(rxdw1); - cpu_physical_memory_write(cplus_rx_ring_desc+4, (uint8_t *)&val, 4); + pci_dma_write(&s->dev, cplus_rx_ring_desc+4, (uint8_t *)&val, 4); /* update tally counter */ ++s->tally_counters.RxOk; @@ -1307,50 +1308,51 @@ static void RTL8139TallyCounters_clear(RTL8139TallyCounters* counters) counters->TxUndrn = 0; } -static void RTL8139TallyCounters_physical_memory_write(target_phys_addr_t tc_addr, RTL8139TallyCounters* tally_counters) +static void RTL8139TallyCounters_dma_write(RTL8139State *s, dma_addr_t tc_addr) { + RTL8139TallyCounters *tally_counters = &s->tally_counters; uint16_t val16; uint32_t val32; uint64_t val64; val64 = cpu_to_le64(tally_counters->TxOk); - cpu_physical_memory_write(tc_addr + 0, (uint8_t *)&val64, 8); + pci_dma_write(&s->dev, tc_addr + 0, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->RxOk); - cpu_physical_memory_write(tc_addr + 8, (uint8_t *)&val64, 8); + pci_dma_write(&s->dev, tc_addr + 8, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->TxERR); - cpu_physical_memory_write(tc_addr + 16, (uint8_t *)&val64, 8); + pci_dma_write(&s->dev, tc_addr + 16, (uint8_t *)&val64, 8); val32 = cpu_to_le32(tally_counters->RxERR); - cpu_physical_memory_write(tc_addr + 24, (uint8_t *)&val32, 4); + pci_dma_write(&s->dev, tc_addr + 24, (uint8_t *)&val32, 4); val16 = cpu_to_le16(tally_counters->MissPkt); - cpu_physical_memory_write(tc_addr + 28, (uint8_t *)&val16, 2); + pci_dma_write(&s->dev, tc_addr + 28, (uint8_t *)&val16, 2); val16 = cpu_to_le16(tally_counters->FAE); - cpu_physical_memory_write(tc_addr + 30, (uint8_t *)&val16, 2); + pci_dma_write(&s->dev, tc_addr + 30, (uint8_t *)&val16, 2); val32 = cpu_to_le32(tally_counters->Tx1Col); - cpu_physical_memory_write(tc_addr + 32, (uint8_t *)&val32, 4); + pci_dma_write(&s->dev, tc_addr + 32, (uint8_t *)&val32, 4); val32 = cpu_to_le32(tally_counters->TxMCol); - cpu_physical_memory_write(tc_addr + 36, (uint8_t *)&val32, 4); + pci_dma_write(&s->dev, tc_addr + 36, (uint8_t *)&val32, 4); val64 = cpu_to_le64(tally_counters->RxOkPhy); - cpu_physical_memory_write(tc_addr + 40, (uint8_t *)&val64, 8); + pci_dma_write(&s->dev, tc_addr + 40, (uint8_t *)&val64, 8); val64 = cpu_to_le64(tally_counters->RxOkBrd); - cpu_physical_memory_write(tc_addr + 48, (uint8_t *)&val64, 8); + pci_dma_write(&s->dev, tc_addr + 48, (uint8_t *)&val64, 8); val32 = cpu_to_le32(tally_counters->RxOkMul); - cpu_physical_memory_write(tc_addr + 56, (uint8_t *)&val32, 4); + pci_dma_write(&s->dev, tc_addr + 56, (uint8_t *)&val32, 4); val16 = cpu_to_le16(tally_counters->TxAbt); - cpu_physical_memory_write(tc_addr + 60, (uint8_t *)&val16, 2); + pci_dma_write(&s->dev, tc_addr + 60, (uint8_t *)&val16, 2); val16 = cpu_to_le16(tally_counters->TxUndrn); - cpu_physical_memory_write(tc_addr + 62, (uint8_t *)&val16, 2); + pci_dma_write(&s->dev, tc_addr + 62, (uint8_t *)&val16, 2); } /* Loads values of tally counters from VM state file */ @@ -1842,7 +1844,7 @@ static int rtl8139_transmit_one(RTL8139State *s, int descriptor) DPRINTF("+++ transmit reading %d bytes from host memory at 0x%08x\n", txsize, s->TxAddr[descriptor]); - cpu_physical_memory_read(s->TxAddr[descriptor], txbuffer, txsize); + pci_dma_read(&s->dev, s->TxAddr[descriptor], txbuffer, txsize); /* Mark descriptor as transferred */ s->TxStatus[descriptor] |= TxHostOwns; @@ -1963,25 +1965,24 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) int descriptor = s->currCPlusTxDesc; - target_phys_addr_t cplus_tx_ring_desc = - rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]); + dma_addr_t cplus_tx_ring_desc = rtl8139_addr64(s->TxAddr[0], s->TxAddr[1]); /* Normal priority ring */ cplus_tx_ring_desc += 16 * descriptor; DPRINTF("+++ C+ mode reading TX descriptor %d from host memory at " - "%08x0x%08x = 0x"TARGET_FMT_plx"\n", descriptor, s->TxAddr[1], + "%08x0x%08x = 0x"DMA_ADDR_FMT"\n", descriptor, s->TxAddr[1], s->TxAddr[0], cplus_tx_ring_desc); uint32_t val, txdw0,txdw1,txbufLO,txbufHI; - cpu_physical_memory_read(cplus_tx_ring_desc, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_tx_ring_desc, (uint8_t *)&val, 4); txdw0 = le32_to_cpu(val); - cpu_physical_memory_read(cplus_tx_ring_desc+4, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_tx_ring_desc+4, (uint8_t *)&val, 4); txdw1 = le32_to_cpu(val); - cpu_physical_memory_read(cplus_tx_ring_desc+8, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_tx_ring_desc+8, (uint8_t *)&val, 4); txbufLO = le32_to_cpu(val); - cpu_physical_memory_read(cplus_tx_ring_desc+12, (uint8_t *)&val, 4); + pci_dma_read(&s->dev, cplus_tx_ring_desc+12, (uint8_t *)&val, 4); txbufHI = le32_to_cpu(val); DPRINTF("+++ C+ mode TX descriptor %d %08x %08x %08x %08x\n", descriptor, @@ -2047,7 +2048,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) } int txsize = txdw0 & CP_TX_BUFFER_SIZE_MASK; - target_phys_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); + dma_addr_t tx_addr = rtl8139_addr64(txbufLO, txbufHI); /* make sure we have enough space to assemble the packet */ if (!s->cplus_txbuffer) @@ -2086,10 +2087,11 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* append more data to the packet */ DPRINTF("+++ C+ mode transmit reading %d bytes from host memory at " - TARGET_FMT_plx" to offset %d\n", txsize, tx_addr, - s->cplus_txbuffer_offset); + DMA_ADDR_FMT" to offset %d\n", txsize, tx_addr, + s->cplus_txbuffer_offset); - cpu_physical_memory_read(tx_addr, s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize); + pci_dma_read(&s->dev, tx_addr, + s->cplus_txbuffer + s->cplus_txbuffer_offset, txsize); s->cplus_txbuffer_offset += txsize; /* seek to next Rx descriptor */ @@ -2116,7 +2118,7 @@ static int rtl8139_cplus_transmit_one(RTL8139State *s) /* update ring data */ val = cpu_to_le32(txdw0); - cpu_physical_memory_write(cplus_tx_ring_desc, (uint8_t *)&val, 4); + pci_dma_write(&s->dev, cplus_tx_ring_desc, (uint8_t *)&val, 4); /* Now decide if descriptor being processed is holding the last segment of packet */ if (txdw0 & CP_TX_LS) @@ -2475,7 +2477,7 @@ static void rtl8139_TxStatus_write(RTL8139State *s, uint32_t txRegOffset, uint32 target_phys_addr_t tc_addr = rtl8139_addr64(s->TxStatus[0] & ~0x3f, s->TxStatus[1]); /* dump tally counters to specified memory location */ - RTL8139TallyCounters_physical_memory_write( tc_addr, &s->tally_counters); + RTL8139TallyCounters_dma_write(s, tc_addr); /* mark dump completed */ s->TxStatus[0] &= ~0x8; From 16ef60c9a8eeee269f7cbc95219a431b1d7cbf29 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:49 +1100 Subject: [PATCH 11/28] eepro100: Use PCI DMA stub functions This updates the eepro100 device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Alexey Kardashevskiy Signed-off-by: Anthony Liguori --- hw/eepro100.c | 121 ++++++++++++++++++++------------------------------ 1 file changed, 49 insertions(+), 72 deletions(-) diff --git a/hw/eepro100.c b/hw/eepro100.c index 4e3c52f50a..7d59e7136d 100644 --- a/hw/eepro100.c +++ b/hw/eepro100.c @@ -46,6 +46,7 @@ #include "net.h" #include "eeprom93xx.h" #include "sysemu.h" +#include "dma.h" /* QEMU sends frames smaller than 60 bytes to ethernet nics. * Such frames are rejected by real nics and their emulations. @@ -315,38 +316,6 @@ static const uint16_t eepro100_mdi_mask[] = { 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, }; -/* Read a 16 bit little endian value from physical memory. */ -static uint16_t e100_ldw_le_phys(target_phys_addr_t addr) -{ - /* Load 16 bit (little endian) word from emulated hardware. */ - uint16_t val; - cpu_physical_memory_read(addr, &val, sizeof(val)); - return le16_to_cpu(val); -} - -/* Read a 32 bit little endian value from physical memory. */ -static uint32_t e100_ldl_le_phys(target_phys_addr_t addr) -{ - /* Load 32 bit (little endian) word from emulated hardware. */ - uint32_t val; - cpu_physical_memory_read(addr, &val, sizeof(val)); - return le32_to_cpu(val); -} - -/* Write a 16 bit little endian value to physical memory. */ -static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val) -{ - val = cpu_to_le16(val); - cpu_physical_memory_write(addr, &val, sizeof(val)); -} - -/* Write a 32 bit little endian value to physical memory. */ -static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val) -{ - val = cpu_to_le32(val); - cpu_physical_memory_write(addr, &val, sizeof(val)); -} - #define POLYNOMIAL 0x04c11db6 /* From FreeBSD */ @@ -744,21 +713,26 @@ static void dump_statistics(EEPRO100State * s) * values which really matter. * Number of data should check configuration!!! */ - cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size); - e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames); - e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames); - e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors); - e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors); + pci_dma_write(&s->dev, s->statsaddr, + (uint8_t *) &s->statistics, s->stats_size); + stl_le_pci_dma(&s->dev, s->statsaddr + 0, + s->statistics.tx_good_frames); + stl_le_pci_dma(&s->dev, s->statsaddr + 36, + s->statistics.rx_good_frames); + stl_le_pci_dma(&s->dev, s->statsaddr + 48, + s->statistics.rx_resource_errors); + stl_le_pci_dma(&s->dev, s->statsaddr + 60, + s->statistics.rx_short_frame_errors); #if 0 - e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames); - e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames); + stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames); + stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames); missing("CU dump statistical counters"); #endif } static void read_cb(EEPRO100State *s) { - cpu_physical_memory_read(s->cb_address, &s->tx, sizeof(s->tx)); + pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx)); s->tx.status = le16_to_cpu(s->tx.status); s->tx.command = le16_to_cpu(s->tx.command); s->tx.link = le32_to_cpu(s->tx.link); @@ -788,18 +762,17 @@ static void tx_command(EEPRO100State *s) } assert(tcb_bytes <= sizeof(buf)); while (size < tcb_bytes) { - uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address); - uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4); + uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address); + uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4); #if 0 - uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6); + uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6); #endif tbd_address += 8; TRACE(RXTX, logout ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n", tx_buffer_address, tx_buffer_size)); tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); - cpu_physical_memory_read(tx_buffer_address, &buf[size], - tx_buffer_size); + pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size); size += tx_buffer_size; } if (tbd_array == 0xffffffff) { @@ -810,16 +783,19 @@ static void tx_command(EEPRO100State *s) if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) { /* Extended Flexible TCB. */ for (; tbd_count < 2; tbd_count++) { - uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address); - uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4); - uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6); + uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, + tbd_address); + uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, + tbd_address + 4); + uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, + tbd_address + 6); tbd_address += 8; TRACE(RXTX, logout ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n", tx_buffer_address, tx_buffer_size)); tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); - cpu_physical_memory_read(tx_buffer_address, &buf[size], - tx_buffer_size); + pci_dma_read(&s->dev, tx_buffer_address, + &buf[size], tx_buffer_size); size += tx_buffer_size; if (tx_buffer_el & 1) { break; @@ -828,16 +804,16 @@ static void tx_command(EEPRO100State *s) } tbd_address = tbd_array; for (; tbd_count < s->tx.tbd_count; tbd_count++) { - uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address); - uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4); - uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6); + uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address); + uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4); + uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6); tbd_address += 8; TRACE(RXTX, logout ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n", tx_buffer_address, tx_buffer_size)); tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size); - cpu_physical_memory_read(tx_buffer_address, &buf[size], - tx_buffer_size); + pci_dma_read(&s->dev, tx_buffer_address, + &buf[size], tx_buffer_size); size += tx_buffer_size; if (tx_buffer_el & 1) { break; @@ -862,7 +838,7 @@ static void set_multicast_list(EEPRO100State *s) TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count)); for (i = 0; i < multicast_count; i += 6) { uint8_t multicast_addr[6]; - cpu_physical_memory_read(s->cb_address + 10 + i, multicast_addr, 6); + pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6); TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6))); unsigned mcast_idx = compute_mcast_idx(multicast_addr); assert(mcast_idx < 64); @@ -896,12 +872,12 @@ static void action_command(EEPRO100State *s) /* Do nothing. */ break; case CmdIASetup: - cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6); + pci_dma_read(&s->dev, s->cb_address + 8, &s->conf.macaddr.a[0], 6); TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6))); break; case CmdConfigure: - cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0], - sizeof(s->configuration)); + pci_dma_read(&s->dev, s->cb_address + 8, + &s->configuration[0], sizeof(s->configuration)); TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16))); TRACE(OTHER, logout("configuration: %s\n", @@ -938,7 +914,8 @@ static void action_command(EEPRO100State *s) break; } /* Write new status. */ - e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C); + stw_le_pci_dma(&s->dev, s->cb_address, + s->tx.status | ok_status | STATUS_C); if (bit_i) { /* CU completed action. */ eepro100_cx_interrupt(s); @@ -1005,7 +982,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* Dump statistical counters. */ TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val)); dump_statistics(s); - e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005); + stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005); break; case CU_CMD_BASE: /* Load CU base. */ @@ -1016,7 +993,7 @@ static void eepro100_cu_command(EEPRO100State * s, uint8_t val) /* Dump and reset statistical counters. */ TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val)); dump_statistics(s); - e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007); + stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007); memset(&s->statistics, 0, sizeof(s->statistics)); break; case CU_SRESUME: @@ -1310,10 +1287,10 @@ static void eepro100_write_port(EEPRO100State *s) case PORT_SELFTEST: TRACE(OTHER, logout("selftest address=0x%08x\n", address)); eepro100_selftest_t data; - cpu_physical_memory_read(address, &data, sizeof(data)); + pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data)); data.st_sign = 0xffffffff; data.st_result = 0; - cpu_physical_memory_write(address, &data, sizeof(data)); + pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data)); break; case PORT_SELECTIVE_RESET: TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address)); @@ -1729,8 +1706,8 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size } /* !!! */ eepro100_rx_t rx; - cpu_physical_memory_read(s->ru_base + s->ru_offset, &rx, - sizeof(eepro100_rx_t)); + pci_dma_read(&s->dev, s->ru_base + s->ru_offset, + (uint8_t *) &rx, sizeof(eepro100_rx_t)); uint16_t rfd_command = le16_to_cpu(rx.command); uint16_t rfd_size = le16_to_cpu(rx.size); @@ -1746,10 +1723,10 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size #endif TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n", rfd_command, rx.link, rx.rx_buf_addr, rfd_size)); - e100_stw_le_phys(s->ru_base + s->ru_offset + - offsetof(eepro100_rx_t, status), rfd_status); - e100_stw_le_phys(s->ru_base + s->ru_offset + - offsetof(eepro100_rx_t, count), size); + stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + + offsetof(eepro100_rx_t, status), rfd_status); + stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset + + offsetof(eepro100_rx_t, count), size); /* Early receive interrupt not supported. */ #if 0 eepro100_er_interrupt(s); @@ -1763,8 +1740,8 @@ static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size #if 0 assert(!(s->configuration[17] & BIT(0))); #endif - cpu_physical_memory_write(s->ru_base + s->ru_offset + - sizeof(eepro100_rx_t), buf, size); + pci_dma_write(&s->dev, s->ru_base + s->ru_offset + + sizeof(eepro100_rx_t), buf, size); s->statistics.rx_good_frames++; eepro100_fr_interrupt(s); s->ru_offset = le32_to_cpu(rx.link); From 93f43c48887a4e5b651965955eedd8e838e53db3 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:50 +1100 Subject: [PATCH 12/28] ac97: Use PCI DMA stub functions This updates the ac97 device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/ac97.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/ac97.c b/hw/ac97.c index bc69d4e345..6800af43a4 100644 --- a/hw/ac97.c +++ b/hw/ac97.c @@ -18,6 +18,7 @@ #include "audiodev.h" #include "audio/audio.h" #include "pci.h" +#include "dma.h" enum { AC97_Reset = 0x00, @@ -224,7 +225,7 @@ static void fetch_bd (AC97LinkState *s, AC97BusMasterRegs *r) { uint8_t b[8]; - cpu_physical_memory_read (r->bdbar + r->civ * 8, b, 8); + pci_dma_read (&s->dev, r->bdbar + r->civ * 8, b, 8); r->bd_valid = 1; r->bd.addr = le32_to_cpu (*(uint32_t *) &b[0]) & ~3; r->bd.ctl_len = le32_to_cpu (*(uint32_t *) &b[4]); @@ -973,7 +974,7 @@ static int write_audio (AC97LinkState *s, AC97BusMasterRegs *r, while (temp) { int copied; to_copy = audio_MIN (temp, sizeof (tmpbuf)); - cpu_physical_memory_read (addr, tmpbuf, to_copy); + pci_dma_read (&s->dev, addr, tmpbuf, to_copy); copied = AUD_write (s->voice_po, tmpbuf, to_copy); dolog ("write_audio max=%x to_copy=%x copied=%x\n", max, to_copy, copied); @@ -1054,7 +1055,7 @@ static int read_audio (AC97LinkState *s, AC97BusMasterRegs *r, *stop = 1; break; } - cpu_physical_memory_write (addr, tmpbuf, acquired); + pci_dma_write (&s->dev, addr, tmpbuf, acquired); temp -= acquired; addr += acquired; nread += acquired; From 3204db98de7dd0bd25a2223fd324313c610cc029 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:51 +1100 Subject: [PATCH 13/28] es1370: Use PCI DMA stub functions This updates the es1370 device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/es1370.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/hw/es1370.c b/hw/es1370.c index 2daadde0e6..c5c16b0484 100644 --- a/hw/es1370.c +++ b/hw/es1370.c @@ -30,6 +30,7 @@ #include "audiodev.h" #include "audio/audio.h" #include "pci.h" +#include "dma.h" /* Missing stuff: SCTRL_P[12](END|ST)INC @@ -802,7 +803,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, if (!acquired) break; - cpu_physical_memory_write (addr, tmpbuf, acquired); + pci_dma_write (&s->dev, addr, tmpbuf, acquired); temp -= acquired; addr += acquired; @@ -816,7 +817,7 @@ static void es1370_transfer_audio (ES1370State *s, struct chan *d, int loop_sel, int copied, to_copy; to_copy = audio_MIN ((size_t) temp, sizeof (tmpbuf)); - cpu_physical_memory_read (addr, tmpbuf, to_copy); + pci_dma_read (&s->dev, addr, tmpbuf, to_copy); copied = AUD_write (voice, tmpbuf, to_copy); if (!copied) break; From 62ecbd353d25e62c4a6c327ea88ba5404e13507a Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:52 +1100 Subject: [PATCH 14/28] e1000: Use PCI DMA stub functions This updates the e1000 device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/e1000.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/hw/e1000.c b/hw/e1000.c index ce8fc8b510..986ed9cf79 100644 --- a/hw/e1000.c +++ b/hw/e1000.c @@ -31,6 +31,7 @@ #include "net/checksum.h" #include "loader.h" #include "sysemu.h" +#include "dma.h" #include "e1000_hw.h" @@ -465,7 +466,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) bytes = split_size; if (tp->size + bytes > msh) bytes = msh - tp->size; - cpu_physical_memory_read(addr, tp->data + tp->size, bytes); + pci_dma_read(&s->dev, addr, tp->data + tp->size, bytes); if ((sz = tp->size + bytes) >= hdr && tp->size < hdr) memmove(tp->header, tp->data, hdr); tp->size = sz; @@ -480,7 +481,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) // context descriptor TSE is not set, while data descriptor TSE is set DBGOUT(TXERR, "TCP segmentaion Error\n"); } else { - cpu_physical_memory_read(addr, tp->data + tp->size, split_size); + pci_dma_read(&s->dev, addr, tp->data + tp->size, split_size); tp->size += split_size; } @@ -496,7 +497,7 @@ process_tx_desc(E1000State *s, struct e1000_tx_desc *dp) } static uint32_t -txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp) +txdesc_writeback(E1000State *s, dma_addr_t base, struct e1000_tx_desc *dp) { uint32_t txd_upper, txd_lower = le32_to_cpu(dp->lower.data); @@ -505,8 +506,8 @@ txdesc_writeback(target_phys_addr_t base, struct e1000_tx_desc *dp) txd_upper = (le32_to_cpu(dp->upper.data) | E1000_TXD_STAT_DD) & ~(E1000_TXD_STAT_EC | E1000_TXD_STAT_LC | E1000_TXD_STAT_TU); dp->upper.data = cpu_to_le32(txd_upper); - cpu_physical_memory_write(base + ((char *)&dp->upper - (char *)dp), - (void *)&dp->upper, sizeof(dp->upper)); + pci_dma_write(&s->dev, base + ((char *)&dp->upper - (char *)dp), + (void *)&dp->upper, sizeof(dp->upper)); return E1000_ICR_TXDW; } @@ -521,7 +522,7 @@ static uint64_t tx_desc_base(E1000State *s) static void start_xmit(E1000State *s) { - target_phys_addr_t base; + dma_addr_t base; struct e1000_tx_desc desc; uint32_t tdh_start = s->mac_reg[TDH], cause = E1000_ICS_TXQE; @@ -533,14 +534,14 @@ start_xmit(E1000State *s) while (s->mac_reg[TDH] != s->mac_reg[TDT]) { base = tx_desc_base(s) + sizeof(struct e1000_tx_desc) * s->mac_reg[TDH]; - cpu_physical_memory_read(base, (void *)&desc, sizeof(desc)); + pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc)); DBGOUT(TX, "index %d: %p : %x %x\n", s->mac_reg[TDH], (void *)(intptr_t)desc.buffer_addr, desc.lower.data, desc.upper.data); process_tx_desc(s, &desc); - cause |= txdesc_writeback(base, &desc); + cause |= txdesc_writeback(s, base, &desc); if (++s->mac_reg[TDH] * sizeof(desc) >= s->mac_reg[TDLEN]) s->mac_reg[TDH] = 0; @@ -668,7 +669,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) { E1000State *s = DO_UPCAST(NICState, nc, nc)->opaque; struct e1000_rx_desc desc; - target_phys_addr_t base; + dma_addr_t base; unsigned int n, rdt; uint32_t rdh_start; uint16_t vlan_special = 0; @@ -713,7 +714,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) desc_size = s->rxbuf_size; } base = rx_desc_base(s) + sizeof(desc) * s->mac_reg[RDH]; - cpu_physical_memory_read(base, (void *)&desc, sizeof(desc)); + pci_dma_read(&s->dev, base, (void *)&desc, sizeof(desc)); desc.special = vlan_special; desc.status |= (vlan_status | E1000_RXD_STAT_DD); if (desc.buffer_addr) { @@ -722,9 +723,9 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) if (copy_size > s->rxbuf_size) { copy_size = s->rxbuf_size; } - cpu_physical_memory_write(le64_to_cpu(desc.buffer_addr), - (void *)(buf + desc_offset + vlan_offset), - copy_size); + pci_dma_write(&s->dev, le64_to_cpu(desc.buffer_addr), + (void *)(buf + desc_offset + vlan_offset), + copy_size); } desc_offset += desc_size; desc.length = cpu_to_le16(desc_size); @@ -738,7 +739,7 @@ e1000_receive(VLANClientState *nc, const uint8_t *buf, size_t size) } else { // as per intel docs; skip descriptors with null buf addr DBGOUT(RX, "Null RX descriptor!!\n"); } - cpu_physical_memory_write(base, (void *)&desc, sizeof(desc)); + pci_dma_write(&s->dev, base, (void *)&desc, sizeof(desc)); if (++s->mac_reg[RDH] * sizeof(desc) >= s->mac_reg[RDLEN]) s->mac_reg[RDH] = 0; From 9ba4524cda1348cbe741535f77815dca6a57da05 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:53 +1100 Subject: [PATCH 15/28] lsi53c895a: Use PCI DMA stub functions This updates the lsi53c895a device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/lsi53c895a.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/hw/lsi53c895a.c b/hw/lsi53c895a.c index 2984cea633..fcc27d726f 100644 --- a/hw/lsi53c895a.c +++ b/hw/lsi53c895a.c @@ -15,6 +15,8 @@ #include "hw.h" #include "pci.h" #include "scsi.h" +#include "block_int.h" +#include "dma.h" //#define DEBUG_LSI //#define DEBUG_LSI_REG @@ -390,10 +392,7 @@ static inline uint32_t read_dword(LSIState *s, uint32_t addr) { uint32_t buf; - /* XXX: an optimization here used to fast-path the read from scripts - * memory. But that bypasses any iommu. - */ - cpu_physical_memory_read(addr, (uint8_t *)&buf, 4); + pci_dma_read(&s->dev, addr, (uint8_t *)&buf, 4); return cpu_to_le32(buf); } @@ -532,7 +531,7 @@ static void lsi_bad_selection(LSIState *s, uint32_t id) static void lsi_do_dma(LSIState *s, int out) { uint32_t count; - target_phys_addr_t addr; + dma_addr_t addr; SCSIDevice *dev; assert(s->current); @@ -558,7 +557,7 @@ static void lsi_do_dma(LSIState *s, int out) else if (s->sbms) addr |= ((uint64_t)s->sbms << 32); - DPRINTF("DMA addr=0x" TARGET_FMT_plx " len=%d\n", addr, count); + DPRINTF("DMA addr=0x" DMA_ADDR_FMT " len=%d\n", addr, count); s->csbc += count; s->dnad += count; s->dbc -= count; @@ -567,9 +566,9 @@ static void lsi_do_dma(LSIState *s, int out) } /* ??? Set SFBR to first data byte. */ if (out) { - cpu_physical_memory_read(addr, s->current->dma_buf, count); + pci_dma_read(&s->dev, addr, s->current->dma_buf, count); } else { - cpu_physical_memory_write(addr, s->current->dma_buf, count); + pci_dma_write(&s->dev, addr, s->current->dma_buf, count); } s->current->dma_len -= count; if (s->current->dma_len == 0) { @@ -762,7 +761,7 @@ static void lsi_do_command(LSIState *s) DPRINTF("Send command len=%d\n", s->dbc); if (s->dbc > 16) s->dbc = 16; - cpu_physical_memory_read(s->dnad, buf, s->dbc); + pci_dma_read(&s->dev, s->dnad, buf, s->dbc); s->sfbr = buf[0]; s->command_complete = 0; @@ -813,7 +812,7 @@ static void lsi_do_status(LSIState *s) s->dbc = 1; status = s->status; s->sfbr = status; - cpu_physical_memory_write(s->dnad, &status, 1); + pci_dma_write(&s->dev, s->dnad, &status, 1); lsi_set_phase(s, PHASE_MI); s->msg_action = 1; lsi_add_msg_byte(s, 0); /* COMMAND COMPLETE */ @@ -827,7 +826,7 @@ static void lsi_do_msgin(LSIState *s) len = s->msg_len; if (len > s->dbc) len = s->dbc; - cpu_physical_memory_write(s->dnad, s->msg, len); + pci_dma_write(&s->dev, s->dnad, s->msg, len); /* Linux drivers rely on the last byte being in the SIDL. */ s->sidl = s->msg[len - 1]; s->msg_len -= len; @@ -859,7 +858,7 @@ static void lsi_do_msgin(LSIState *s) static uint8_t lsi_get_msgbyte(LSIState *s) { uint8_t data; - cpu_physical_memory_read(s->dnad, &data, 1); + pci_dma_read(&s->dev, s->dnad, &data, 1); s->dnad++; s->dbc--; return data; @@ -1011,8 +1010,8 @@ static void lsi_memcpy(LSIState *s, uint32_t dest, uint32_t src, int count) DPRINTF("memcpy dest 0x%08x src 0x%08x count %d\n", dest, src, count); while (count) { n = (count > LSI_BUF_SIZE) ? LSI_BUF_SIZE : count; - cpu_physical_memory_read(src, buf, n); - cpu_physical_memory_write(dest, buf, n); + pci_dma_read(&s->dev, src, buf, n); + pci_dma_write(&s->dev, dest, buf, n); src += n; dest += n; count -= n; @@ -1080,7 +1079,7 @@ again: /* 32-bit Table indirect */ offset = sxt24(addr); - cpu_physical_memory_read(s->dsa + offset, (uint8_t *)buf, 8); + pci_dma_read(&s->dev, s->dsa + offset, (uint8_t *)buf, 8); /* byte count is stored in bits 0:23 only */ s->dbc = cpu_to_le32(buf[0]) & 0xffffff; s->rbc = s->dbc; @@ -1439,7 +1438,7 @@ again: n = (insn & 7); reg = (insn >> 16) & 0xff; if (insn & (1 << 24)) { - cpu_physical_memory_read(addr, data, n); + pci_dma_read(&s->dev, addr, data, n); DPRINTF("Load reg 0x%x size %d addr 0x%08x = %08x\n", reg, n, addr, *(int *)data); for (i = 0; i < n; i++) { @@ -1450,7 +1449,7 @@ again: for (i = 0; i < n; i++) { data[i] = lsi_reg_readb(s, reg + i); } - cpu_physical_memory_write(addr, data, n); + pci_dma_write(&s->dev, addr, data, n); } } } From 14fecf26d06de52658a343cf78077a80c60cc121 Mon Sep 17 00:00:00 2001 From: Eduard - Gabriel Munteanu Date: Mon, 31 Oct 2011 17:06:54 +1100 Subject: [PATCH 16/28] pcnet-pci: Use PCI DMA stub functions This updates the pcnet-pci device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: Eduard - Gabriel Munteanu Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/pcnet-pci.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index fb2a00caad..41a6e07c0e 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -31,6 +31,7 @@ #include "net.h" #include "loader.h" #include "qemu-timer.h" +#include "dma.h" #include "pcnet.h" @@ -230,13 +231,13 @@ static const MemoryRegionOps pcnet_mmio_ops = { static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, uint8_t *buf, int len, int do_bswap) { - cpu_physical_memory_write(addr, buf, len); + pci_dma_write(dma_opaque, addr, buf, len); } static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, uint8_t *buf, int len, int do_bswap) { - cpu_physical_memory_read(addr, buf, len); + pci_dma_read(dma_opaque, addr, buf, len); } static void pci_pcnet_cleanup(VLANClientState *nc) @@ -302,6 +303,7 @@ static int pci_pcnet_init(PCIDevice *pci_dev) s->irq = pci_dev->irq[0]; s->phys_mem_read = pci_physical_memory_read; s->phys_mem_write = pci_physical_memory_write; + s->dma_opaque = pci_dev; if (!pci_dev->qdev.hotplugged) { static int loaded = 0; From fa0ce55c7157f6fd1cf385d1f59f87baea1d9704 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:55 +1100 Subject: [PATCH 17/28] intel-hda: Use PCI DMA stub functions This updates the intel-hda device emulation to use the explicit PCI DMA functions, instead of directly calling physical memory access functions. Signed-off-by: David Gibson Signed-off-by: Alexey Kardashevskiy Signed-off-by: Anthony Liguori --- hw/intel-hda.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/hw/intel-hda.c b/hw/intel-hda.c index 675b6591e9..02def4c1e1 100644 --- a/hw/intel-hda.c +++ b/hw/intel-hda.c @@ -24,6 +24,7 @@ #include "audiodev.h" #include "intel-hda.h" #include "intel-hda-defs.h" +#include "dma.h" /* --------------------------------------------------------------------- */ /* hda bus */ @@ -328,7 +329,7 @@ static void intel_hda_corb_run(IntelHDAState *d) rp = (d->corb_rp + 1) & 0xff; addr = intel_hda_addr(d->corb_lbase, d->corb_ubase); - verb = ldl_le_phys(addr + 4*rp); + verb = ldl_le_pci_dma(&d->pci, addr + 4*rp); d->corb_rp = rp; dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __FUNCTION__, rp, verb); @@ -360,8 +361,8 @@ static void intel_hda_response(HDACodecDevice *dev, bool solicited, uint32_t res ex = (solicited ? 0 : (1 << 4)) | dev->cad; wp = (d->rirb_wp + 1) & 0xff; addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase); - stl_le_phys(addr + 8*wp, response); - stl_le_phys(addr + 8*wp + 4, ex); + stl_le_pci_dma(&d->pci, addr + 8*wp, response); + stl_le_pci_dma(&d->pci, addr + 8*wp + 4, ex); d->rirb_wp = wp; dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n", @@ -426,8 +427,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, dprint(d, 3, "dma: entry %d, pos %d/%d, copy %d\n", st->be, st->bp, st->bpl[st->be].len, copy); - cpu_physical_memory_rw(st->bpl[st->be].addr + st->bp, - buf, copy, !output); + pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output); st->lpib += copy; st->bp += copy; buf += copy; @@ -449,7 +449,7 @@ static bool intel_hda_xfer(HDACodecDevice *dev, uint32_t stnr, bool output, } if (d->dp_lbase & 0x01) { addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase); - stl_le_phys(addr + 8*s, st->lpib); + stl_le_pci_dma(&d->pci, addr + 8*s, st->lpib); } dprint(d, 3, "dma: --\n"); @@ -471,7 +471,7 @@ static void intel_hda_parse_bdl(IntelHDAState *d, IntelHDAStream *st) g_free(st->bpl); st->bpl = g_malloc(sizeof(bpl) * st->bentries); for (i = 0; i < st->bentries; i++, addr += 16) { - cpu_physical_memory_read(addr, buf, 16); + pci_dma_read(&d->pci, addr, buf, 16); st->bpl[i].addr = le64_to_cpu(*(uint64_t *)buf); st->bpl[i].len = le32_to_cpu(*(uint32_t *)(buf + 8)); st->bpl[i].flags = le32_to_cpu(*(uint32_t *)(buf + 12)); From 552908fef5b67ad9d96b76d7cb8371ebc26c9bc8 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:56 +1100 Subject: [PATCH 18/28] PCI IDE: Use PCI DMA stub functions This updates the PCI IDE device emulation to use the explicit PCI DMA wrapper to initialize its scatter/gathjer structure. This means this driver should not need further changes when the sglist interface is extended to support IOMMUs. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/ide/pci.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/hw/ide/pci.c b/hw/ide/pci.c index f133c422b6..49b823df79 100644 --- a/hw/ide/pci.c +++ b/hw/ide/pci.c @@ -62,7 +62,8 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) } prd; int l, len; - qemu_sglist_init(&s->sg, s->nsector / (BMDMA_PAGE_SIZE / 512) + 1); + pci_dma_sglist_init(&s->sg, &bm->pci_dev->dev, + s->nsector / (BMDMA_PAGE_SIZE / 512) + 1); s->io_buffer_size = 0; for(;;) { if (bm->cur_prd_len == 0) { @@ -70,7 +71,7 @@ static int bmdma_prepare_buf(IDEDMA *dma, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) return s->io_buffer_size != 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8); bm->cur_addr += 8; prd.addr = le32_to_cpu(prd.addr); prd.size = le32_to_cpu(prd.size); @@ -112,7 +113,7 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write) if (bm->cur_prd_last || (bm->cur_addr - bm->addr) >= BMDMA_PAGE_SIZE) return 0; - cpu_physical_memory_read(bm->cur_addr, (uint8_t *)&prd, 8); + pci_dma_read(&bm->pci_dev->dev, bm->cur_addr, (uint8_t *)&prd, 8); bm->cur_addr += 8; prd.addr = le32_to_cpu(prd.addr); prd.size = le32_to_cpu(prd.size); @@ -127,11 +128,11 @@ static int bmdma_rw_buf(IDEDMA *dma, int is_write) l = bm->cur_prd_len; if (l > 0) { if (is_write) { - cpu_physical_memory_write(bm->cur_prd_addr, - s->io_buffer + s->io_buffer_index, l); + pci_dma_write(&bm->pci_dev->dev, bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l); } else { - cpu_physical_memory_read(bm->cur_prd_addr, - s->io_buffer + s->io_buffer_index, l); + pci_dma_read(&bm->pci_dev->dev, bm->cur_prd_addr, + s->io_buffer + s->io_buffer_index, l); } bm->cur_prd_addr += l; bm->cur_prd_len -= l; @@ -326,7 +327,7 @@ void bmdma_cmd_writeb(BMDMAState *bm, uint32_t val) bm->cmd = val & 0x09; } -static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr, +static uint64_t bmdma_addr_read(void *opaque, dma_addr_t addr, unsigned width) { BMDMAState *bm = opaque; @@ -340,7 +341,7 @@ static uint64_t bmdma_addr_read(void *opaque, target_phys_addr_t addr, return data; } -static void bmdma_addr_write(void *opaque, target_phys_addr_t addr, +static void bmdma_addr_write(void *opaque, dma_addr_t addr, uint64_t data, unsigned width) { BMDMAState *bm = opaque; From 68d553587c0aa271c3eb2902921b503740d775b6 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:57 +1100 Subject: [PATCH 19/28] usb-ehci: Use PCI DMA stub functions This updates the usb-ehci device emulation to use the explicit PCI DMA wrapper to initialize its scatter/gathjer structure. This means this driver should not need further changes when the sglist interface is extended to support IOMMUs. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/usb-ehci.c | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c index bd374c1de6..cdd5aae1e9 100644 --- a/hw/usb-ehci.c +++ b/hw/usb-ehci.c @@ -1101,12 +1101,13 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val) // TODO : Put in common header file, duplication from usb-ohci.c /* Get an array of dwords from main memory */ -static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) +static inline int get_dwords(EHCIState *ehci, uint32_t addr, + uint32_t *buf, int num) { int i; for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { - cpu_physical_memory_rw(addr,(uint8_t *)buf, sizeof(*buf), 0); + pci_dma_read(&ehci->dev, addr, (uint8_t *)buf, sizeof(*buf)); *buf = le32_to_cpu(*buf); } @@ -1114,13 +1115,14 @@ static inline int get_dwords(uint32_t addr, uint32_t *buf, int num) } /* Put an array of dwords in to main memory */ -static inline int put_dwords(uint32_t addr, uint32_t *buf, int num) +static inline int put_dwords(EHCIState *ehci, uint32_t addr, + uint32_t *buf, int num) { int i; for(i = 0; i < num; i++, buf++, addr += sizeof(*buf)) { uint32_t tmp = cpu_to_le32(*buf); - cpu_physical_memory_rw(addr,(uint8_t *)&tmp, sizeof(tmp), 1); + pci_dma_write(&ehci->dev, addr, (uint8_t *)&tmp, sizeof(tmp)); } return 1; @@ -1169,7 +1171,8 @@ static int ehci_qh_do_overlay(EHCIQueue *q) q->qh.bufptr[1] &= ~BUFPTR_CPROGMASK_MASK; q->qh.bufptr[2] &= ~BUFPTR_FRAMETAG_MASK; - put_dwords(NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); + put_dwords(q->ehci, NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, + sizeof(EHCIqh) >> 2); return 0; } @@ -1177,12 +1180,12 @@ static int ehci_qh_do_overlay(EHCIQueue *q) static int ehci_init_transfer(EHCIQueue *q) { uint32_t cpage, offset, bytes, plen; - target_phys_addr_t page; + dma_addr_t page; cpage = get_field(q->qh.token, QTD_TOKEN_CPAGE); bytes = get_field(q->qh.token, QTD_TOKEN_TBYTES); offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK; - qemu_sglist_init(&q->sgl, 5); + pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5); while (bytes > 0) { if (cpage > 4) { @@ -1428,7 +1431,7 @@ static int ehci_process_itd(EHCIState *ehci, return USB_RET_PROCERR; } - qemu_sglist_init(&ehci->isgl, 2); + pci_dma_sglist_init(&ehci->isgl, &ehci->dev, 2); if (off + len > 4096) { /* transfer crosses page border */ uint32_t len2 = off + len - 4096; @@ -1532,7 +1535,8 @@ static int ehci_state_waitlisthead(EHCIState *ehci, int async) /* Find the head of the list (4.9.1.1) */ for(i = 0; i < MAX_QH; i++) { - get_dwords(NLPTR_GET(entry), (uint32_t *) &qh, sizeof(EHCIqh) >> 2); + get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &qh, + sizeof(EHCIqh) >> 2); ehci_trace_qh(NULL, NLPTR_GET(entry), &qh); if (qh.epchar & QH_EPCHAR_H) { @@ -1629,7 +1633,8 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async) goto out; } - get_dwords(NLPTR_GET(q->qhaddr), (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); + get_dwords(ehci, NLPTR_GET(q->qhaddr), + (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2); ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh); if (q->async == EHCI_ASYNC_INFLIGHT) { @@ -1698,7 +1703,7 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async) assert(!async); entry = ehci_get_fetch_addr(ehci, async); - get_dwords(NLPTR_GET(entry),(uint32_t *) &itd, + get_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd, sizeof(EHCIitd) >> 2); ehci_trace_itd(ehci, entry, &itd); @@ -1706,8 +1711,8 @@ static int ehci_state_fetchitd(EHCIState *ehci, int async) return -1; } - put_dwords(NLPTR_GET(entry), (uint32_t *) &itd, - sizeof(EHCIitd) >> 2); + put_dwords(ehci, NLPTR_GET(entry), (uint32_t *) &itd, + sizeof(EHCIitd) >> 2); ehci_set_fetch_addr(ehci, async, itd.next); ehci_set_state(ehci, async, EST_FETCHENTRY); @@ -1722,7 +1727,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async) assert(!async); entry = ehci_get_fetch_addr(ehci, async); - get_dwords(NLPTR_GET(entry), (uint32_t *)&sitd, + get_dwords(ehci, NLPTR_GET(entry), (uint32_t *)&sitd, sizeof(EHCIsitd) >> 2); ehci_trace_sitd(ehci, entry, &sitd); @@ -1784,7 +1789,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async) { int again = 0; - get_dwords(NLPTR_GET(q->qtdaddr),(uint32_t *) &q->qtd, sizeof(EHCIqtd) >> 2); + get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd, + sizeof(EHCIqtd) >> 2); ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd); if (q->qtd.token & QTD_TOKEN_ACTIVE) { @@ -1827,7 +1833,7 @@ static void ehci_flush_qh(EHCIQueue *q) uint32_t dwords = sizeof(EHCIqh) >> 2; uint32_t addr = NLPTR_GET(q->qhaddr); - put_dwords(addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3); + put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3); } static int ehci_state_execute(EHCIQueue *q, int async) @@ -1947,8 +1953,8 @@ static int ehci_state_writeback(EHCIQueue *q, int async) /* Write back the QTD from the QH area */ ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd); - put_dwords(NLPTR_GET(q->qtdaddr),(uint32_t *) &q->qh.next_qtd, - sizeof(EHCIqtd) >> 2); + put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd, + sizeof(EHCIqtd) >> 2); /* * EHCI specs say go horizontal here. @@ -2148,7 +2154,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci) } list |= ((ehci->frindex & 0x1ff8) >> 1); - cpu_physical_memory_rw(list, (uint8_t *) &entry, sizeof entry, 0); + pci_dma_read(&ehci->dev, list, (uint8_t *) &entry, sizeof entry); entry = le32_to_cpu(entry); DPRINTF("PERIODIC state adv fr=%d. [%08X] -> %08X\n", From fff23ee9a5de74ab111b3cea9eec56782e7d7c50 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Mon, 31 Oct 2011 17:06:58 +1100 Subject: [PATCH 20/28] usb-uhci: Use PCI DMA stub functions This updates the usb-uhci device emulation to use the explicit PCI DMA wrapper to initialize its scatter/gathjer structure. This means this driver should not need further changes when the sglist interface is extended to support IOMMUs. Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/usb-uhci.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hw/usb-uhci.c b/hw/usb-uhci.c index 171d7870b7..f9e3ea5bfc 100644 --- a/hw/usb-uhci.c +++ b/hw/usb-uhci.c @@ -178,7 +178,7 @@ static UHCIAsync *uhci_async_alloc(UHCIState *s) async->done = 0; async->isoc = 0; usb_packet_init(&async->packet); - qemu_sglist_init(&async->sgl, 1); + pci_dma_sglist_init(&async->sgl, &s->dev, 1); return async; } @@ -876,7 +876,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) uint32_t link = async->td; uint32_t int_mask = 0, val; - cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td)); + pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td)); le32_to_cpus(&td.link); le32_to_cpus(&td.ctrl); le32_to_cpus(&td.token); @@ -888,8 +888,8 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet) /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); - cpu_physical_memory_write((link & ~0xf) + 4, - (const uint8_t *)&val, sizeof(val)); + pci_dma_write(&s->dev, (link & ~0xf) + 4, + (const uint8_t *)&val, sizeof(val)); uhci_async_free(s, async); } else { async->done = 1; @@ -952,7 +952,7 @@ static void uhci_process_frame(UHCIState *s) DPRINTF("uhci: processing frame %d addr 0x%x\n" , s->frnum, frame_addr); - cpu_physical_memory_read(frame_addr, (uint8_t *)&link, 4); + pci_dma_read(&s->dev, frame_addr, (uint8_t *)&link, 4); le32_to_cpus(&link); int_mask = 0; @@ -976,7 +976,7 @@ static void uhci_process_frame(UHCIState *s) break; } - cpu_physical_memory_read(link & ~0xf, (uint8_t *) &qh, sizeof(qh)); + pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &qh, sizeof(qh)); le32_to_cpus(&qh.link); le32_to_cpus(&qh.el_link); @@ -996,7 +996,7 @@ static void uhci_process_frame(UHCIState *s) } /* TD */ - cpu_physical_memory_read(link & ~0xf, (uint8_t *) &td, sizeof(td)); + pci_dma_read(&s->dev, link & ~0xf, (uint8_t *) &td, sizeof(td)); le32_to_cpus(&td.link); le32_to_cpus(&td.ctrl); le32_to_cpus(&td.token); @@ -1010,8 +1010,8 @@ static void uhci_process_frame(UHCIState *s) if (old_td_ctrl != td.ctrl) { /* update the status bits of the TD */ val = cpu_to_le32(td.ctrl); - cpu_physical_memory_write((link & ~0xf) + 4, - (const uint8_t *)&val, sizeof(val)); + pci_dma_write(&s->dev, (link & ~0xf) + 4, + (const uint8_t *)&val, sizeof(val)); } if (ret < 0) { @@ -1039,8 +1039,8 @@ static void uhci_process_frame(UHCIState *s) /* update QH element link */ qh.el_link = link; val = cpu_to_le32(qh.el_link); - cpu_physical_memory_write((curr_qh & ~0xf) + 4, - (const uint8_t *)&val, sizeof(val)); + pci_dma_write(&s->dev, (curr_qh & ~0xf) + 4, + (const uint8_t *)&val, sizeof(val)); if (!depth_first(link)) { /* done with this QH */ From 46d95bfec7f9429d5228078219413d7e33496d65 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Fri, 30 Sep 2011 15:26:16 +1000 Subject: [PATCH 21/28] virtio: Add PCI memory BAR in addition to PIO BAR Currently, virtio devices are usually presented to the guest as an emulated PCI device, virtio_pci. Although the actual IO operations are done through system memory, the configuration of the virtio device is done through the one PCI IO space BAR that virtio_pci presents. But PCI IO space (aka PIO) is deprecated for modern PCI devices, and on some systems with many PCI domains accessing PIO space can be problematic. For example on the existing PowerVM implementation of the PAPR spec, PCI PIO access is not supported at all. We're hoping that our KVM implementation will support PCI PIO (once we support PCI at all), but it will probably have some irritating limitations. This patch, therefore, extends the virtio_pci device to have a PCI memory space (MMIO) BAR as well as the IO BAR. The MMIO BAR contains exactly the same registers, in exactly the same layout as the existing PIO BAR. Because the PIO BAR is still present, existing guest drivers should still work fine. With this change in place, future guest drivers can check for an MMIO BAR and use that if present (falling back to PIO when possible to support older qemu versions). Signed-off-by: David Gibson Signed-off-by: Anthony Liguori --- hw/virtio-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c index ca5923c495..83a4b358f5 100644 --- a/hw/virtio-pci.c +++ b/hw/virtio-pci.c @@ -654,6 +654,8 @@ void virtio_init_pci(VirtIOPCIProxy *proxy, VirtIODevice *vdev) "virtio-pci", size); pci_register_bar(&proxy->pci_dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &proxy->bar); + pci_register_bar(&proxy->pci_dev, 2, PCI_BASE_ADDRESS_SPACE_MEMORY, + &proxy->bar); if (!kvm_has_many_ioeventfds()) { proxy->flags &= ~VIRTIO_PCI_FLAG_USE_IOEVENTFD; From f809c0d66bf1d9a8a4282b5a089b7eead45428fc Mon Sep 17 00:00:00 2001 From: Peter Maydell Date: Tue, 1 Nov 2011 18:32:55 +0000 Subject: [PATCH 22/28] configure: Suppress messages from pkg_config probe for check Suppress confusing messages from pkg_config when probing for 'check' by sending them to /dev/null as we do with other similar probes. Signed-off-by: Peter Maydell Signed-off-by: Anthony Liguori --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 850efc0f16..254b801fd5 100755 --- a/configure +++ b/configure @@ -1828,7 +1828,7 @@ if test "$check_utests" != "no" ; then #include int main(void) { suite_create("qemu test"); return 0; } EOF - check_libs=`$pkg_config --libs check` + check_libs=`$pkg_config --libs check 2>/dev/null` if compile_prog "" $check_libs ; then check_utests=yes libs_tools="$check_libs $libs_tools" From 443916d1d9f1094a43d28c6b8cc60e3e7e27eb36 Mon Sep 17 00:00:00 2001 From: Stefan Berger Date: Wed, 28 Sep 2011 06:41:32 -0400 Subject: [PATCH 23/28] Move filedescriptor parsing code from net.c into qemu_parse_fd() Move the parsing of a filedescriptor into a common function qemu_parse_fd() so others can use it as well. Have net.c call this function. v2: - moving qemu_parse_fd into cutils.c Signed-off-by: Stefan Berger Signed-off-by: Anthony Liguori --- cutils.c | 12 ++++++++++++ net.c | 7 +------ qemu-common.h | 1 + 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/cutils.c b/cutils.c index c91f88732e..5d995bc4e5 100644 --- a/cutils.c +++ b/cutils.c @@ -415,3 +415,15 @@ int64_t strtosz(const char *nptr, char **end) { return strtosz_suffix(nptr, end, STRTOSZ_DEFSUFFIX_MB); } + +int qemu_parse_fd(const char *param) +{ + int fd; + char *endptr = NULL; + + fd = strtol(param, &endptr, 10); + if (*endptr || (fd == 0 && param == endptr)) { + return -1; + } + return fd; +} diff --git a/net.c b/net.c index d05930c91f..cb52050bfd 100644 --- a/net.c +++ b/net.c @@ -733,12 +733,7 @@ int net_handle_fd_param(Monitor *mon, const char *param) return -1; } } else { - char *endptr = NULL; - - fd = strtol(param, &endptr, 10); - if (*endptr || (fd == 0 && param == endptr)) { - return -1; - } + fd = qemu_parse_fd(param); } return fd; diff --git a/qemu-common.h b/qemu-common.h index 1c15cb17a7..2ce47aa12d 100644 --- a/qemu-common.h +++ b/qemu-common.h @@ -129,6 +129,7 @@ time_t mktimegm(struct tm *tm); int qemu_fls(int i); int qemu_fdatasync(int fd); int fcntl_setfl(int fd, int flag); +int qemu_parse_fd(const char *param); /* * strtosz() suffixes used to specify the default treatment of an From 2284451019a796eb2a37d70544e19d686de7f8c0 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Tue, 27 Sep 2011 17:26:23 +0300 Subject: [PATCH 24/28] event_notifier: move to top-level directory Has no business in hw/. Signed-off-by: Avi Kivity Signed-off-by: Anthony Liguori --- hw/event_notifier.c => event_notifier.c | 1 - hw/event_notifier.h => event_notifier.h | 0 2 files changed, 1 deletion(-) rename hw/event_notifier.c => event_notifier.c (98%) rename hw/event_notifier.h => event_notifier.h (100%) diff --git a/hw/event_notifier.c b/event_notifier.c similarity index 98% rename from hw/event_notifier.c rename to event_notifier.c index 13f3656460..2c735556a1 100644 --- a/hw/event_notifier.c +++ b/event_notifier.c @@ -10,7 +10,6 @@ * the COPYING file in the top-level directory. */ -#include "hw.h" #include "event_notifier.h" #ifdef CONFIG_EVENTFD #include diff --git a/hw/event_notifier.h b/event_notifier.h similarity index 100% rename from hw/event_notifier.h rename to event_notifier.h From 816f89256ef36c8fd20e70ac393110cf2322e223 Mon Sep 17 00:00:00 2001 From: Wayne Xia Date: Wed, 12 Oct 2011 11:32:41 +0800 Subject: [PATCH 25/28] Sort the help info shown in monitor at runtime This patch would try sort the command list in monitor at runtime. As a result, command help and help info would show a more friendly sorted command list. For eg: (qemu)help acl_add acl_policy acl_remove acl_reset acl_show balloon block_passwd ... the command list is sorted. v3: using qsort function to sort the command list. Tested-by: Wenyi Gao Signed-off-by: Wayne Xia Signed-off-by: Anthony Liguori --- monitor.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/monitor.c b/monitor.c index 7c2a9b95f8..5ea35de849 100644 --- a/monitor.c +++ b/monitor.c @@ -199,8 +199,8 @@ static inline int mon_print_count_get(const Monitor *mon) { return 0; } static QLIST_HEAD(mon_list, Monitor) mon_list; -static const mon_cmd_t mon_cmds[]; -static const mon_cmd_t info_cmds[]; +static mon_cmd_t mon_cmds[]; +static mon_cmd_t info_cmds[]; static const mon_cmd_t qmp_cmds[]; @@ -2591,13 +2591,14 @@ int monitor_get_fd(Monitor *mon, const char *fdname) return -1; } -static const mon_cmd_t mon_cmds[] = { +/* mon_cmds and info_cmds would be sorted at runtime */ +static mon_cmd_t mon_cmds[] = { #include "hmp-commands.h" { NULL, NULL, }, }; /* Please update hmp-commands.hx when adding or changing commands */ -static const mon_cmd_t info_cmds[] = { +static mon_cmd_t info_cmds[] = { { .name = "version", .args_type = "", @@ -4832,6 +4833,25 @@ static void monitor_event(void *opaque, int event) } } +static int +compare_mon_cmd(const void *a, const void *b) +{ + return strcmp(((const mon_cmd_t *)a)->name, + ((const mon_cmd_t *)b)->name); +} + +static void sortcmdlist(void) +{ + int array_num; + int elem_size = sizeof(mon_cmd_t); + + array_num = sizeof(mon_cmds)/elem_size-1; + qsort((void *)mon_cmds, array_num, elem_size, compare_mon_cmd); + + array_num = sizeof(info_cmds)/elem_size-1; + qsort((void *)info_cmds, array_num, elem_size, compare_mon_cmd); +} + /* * Local variables: @@ -4874,6 +4894,8 @@ void monitor_init(CharDriverState *chr, int flags) QLIST_INSERT_HEAD(&mon_list, mon, entry); if (!default_mon || (flags & MONITOR_IS_DEFAULT)) default_mon = mon; + + sortcmdlist(); } static void bdrv_password_cb(Monitor *mon, const char *password, void *opaque) From 488a1a5dfe9a9ba57fa6c6b6b98136ea494e0296 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 26 Sep 2011 19:01:44 +0200 Subject: [PATCH 26/28] pcnet: Move BCR defines to header This moves BCR defines to the common header and immediately makes use of them to add BCR_APROMWE, replacing the open-coded write check in pcnet_aprom_writeb. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/pcnet-pci.c | 4 ++-- hw/pcnet.c | 18 ------------------ hw/pcnet.h | 19 +++++++++++++++++++ 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 41a6e07c0e..4f97f965f4 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -56,9 +56,9 @@ static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val) #ifdef PCNET_DEBUG printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val); #endif - /* Check APROMWE bit to enable write access */ - if (pcnet_bcr_readw(s,2) & 0x100) + if (BCR_APROMWE(s)) { s->prom[addr & 15] = val; + } } static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr) diff --git a/hw/pcnet.c b/hw/pcnet.c index cf16fd4d01..add3ec2559 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -58,24 +58,6 @@ struct qemu_ether_header { uint16_t ether_type; }; -/* BUS CONFIGURATION REGISTERS */ -#define BCR_MSRDA 0 -#define BCR_MSWRA 1 -#define BCR_MC 2 -#define BCR_LNKST 4 -#define BCR_LED1 5 -#define BCR_LED2 6 -#define BCR_LED3 7 -#define BCR_FDC 9 -#define BCR_BSBC 18 -#define BCR_EECAS 19 -#define BCR_SWS 20 -#define BCR_PLAT 22 - -#define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080) -#define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100) -#define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF) - #define CSR_INIT(S) !!(((S)->csr[0])&0x0001) #define CSR_STRT(S) !!(((S)->csr[0])&0x0002) #define CSR_STOP(S) !!(((S)->csr[0])&0x0004) diff --git a/hw/pcnet.h b/hw/pcnet.h index cd86bde9d0..52cc52e940 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -6,6 +6,25 @@ #include "memory.h" +/* BUS CONFIGURATION REGISTERS */ +#define BCR_MSRDA 0 +#define BCR_MSWRA 1 +#define BCR_MC 2 +#define BCR_LNKST 4 +#define BCR_LED1 5 +#define BCR_LED2 6 +#define BCR_LED3 7 +#define BCR_FDC 9 +#define BCR_BSBC 18 +#define BCR_EECAS 19 +#define BCR_SWS 20 +#define BCR_PLAT 22 + +#define BCR_APROMWE(S) !!((S)->bcr[BCR_MC ] & 0x0100) +#define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080) +#define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100) +#define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF) + typedef struct PCNetState_st PCNetState; struct PCNetState_st { From 7ba7974197090285fdb413c6e1c41aaacd44b9c4 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Mon, 26 Sep 2011 19:01:45 +0200 Subject: [PATCH 27/28] pcnet-pci: Fix PIO word access to PROM Implement the various IO access widths according to the spec. This specifically unbreaks word and dword access to the PROM area that is mapped into IO space. It also drops redundant upper limit checks and spurious "return void". Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/pcnet-pci.c | 48 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index 4f97f965f4..ea5dfdef76 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -76,12 +76,24 @@ static uint64_t pcnet_ioport_read(void *opaque, target_phys_addr_t addr, { PCNetState *d = opaque; - if (addr < 16 && size == 1) { - return pcnet_aprom_readb(d, addr); - } else if (addr >= 0x10 && addr < 0x20 && size == 2) { - return pcnet_ioport_readw(d, addr); - } else if (addr >= 0x10 && addr < 0x20 && size == 4) { - return pcnet_ioport_readl(d, addr); + if (addr < 0x10) { + if (!BCR_DWIO(d) && size == 1) { + return pcnet_aprom_readb(d, addr); + } else if (!BCR_DWIO(d) && (addr & 1) == 0 && size == 2) { + return pcnet_aprom_readb(d, addr) | + (pcnet_aprom_readb(d, addr + 1) << 8); + } else if (BCR_DWIO(d) && (addr & 3) == 0 && size == 4) { + return pcnet_aprom_readb(d, addr) | + (pcnet_aprom_readb(d, addr + 1) << 8) | + (pcnet_aprom_readb(d, addr + 2) << 16) | + (pcnet_aprom_readb(d, addr + 3) << 24); + } + } else { + if (size == 2) { + return pcnet_ioport_readw(d, addr); + } else if (size == 4) { + return pcnet_ioport_readl(d, addr); + } } return ((uint64_t)1 << (size * 8)) - 1; } @@ -91,12 +103,24 @@ static void pcnet_ioport_write(void *opaque, target_phys_addr_t addr, { PCNetState *d = opaque; - if (addr < 16 && size == 1) { - return pcnet_aprom_writeb(d, addr, data); - } else if (addr >= 0x10 && addr < 0x20 && size == 2) { - return pcnet_ioport_writew(d, addr, data); - } else if (addr >= 0x10 && addr < 0x20 && size == 4) { - return pcnet_ioport_writel(d, addr, data); + if (addr < 0x10) { + if (!BCR_DWIO(d) && size == 1) { + pcnet_aprom_writeb(d, addr, data); + } else if (!BCR_DWIO(d) && (addr & 1) == 0 && size == 2) { + pcnet_aprom_writeb(d, addr, data & 0xff); + pcnet_aprom_writeb(d, addr + 1, data >> 8); + } else if (BCR_DWIO(d) && (addr & 3) == 0 && size == 4) { + pcnet_aprom_writeb(d, addr, data & 0xff); + pcnet_aprom_writeb(d, addr + 1, (data >> 8) & 0xff); + pcnet_aprom_writeb(d, addr + 2, (data >> 16) & 0xff); + pcnet_aprom_writeb(d, addr + 3, data >> 24); + } + } else { + if (size == 2) { + pcnet_ioport_writew(d, addr, data); + } else if (size == 4) { + pcnet_ioport_writel(d, addr, data); + } } } From e1c2008af64487e7d3cec615612b7f467ebe9bc8 Mon Sep 17 00:00:00 2001 From: Jan Kiszka Date: Fri, 7 Oct 2011 12:27:25 +0200 Subject: [PATCH 28/28] pcnet: Add link state support Update lnkst on link state changes so that guests can obtain this information via reading back the LED output pin. Works for Linux but not for guests that depend on the missing PHY. Signed-off-by: Jan Kiszka Signed-off-by: Anthony Liguori --- hw/lance.c | 1 + hw/pcnet-pci.c | 1 + hw/pcnet.c | 7 +++++++ hw/pcnet.h | 1 + 4 files changed, 10 insertions(+) diff --git a/hw/lance.c b/hw/lance.c index d83e7f57a9..93d5fda35b 100644 --- a/hw/lance.c +++ b/hw/lance.c @@ -97,6 +97,7 @@ static NetClientInfo net_lance_info = { .size = sizeof(NICState), .can_receive = pcnet_can_receive, .receive = pcnet_receive, + .link_status_changed = pcnet_set_link_status, .cleanup = lance_cleanup, }; diff --git a/hw/pcnet-pci.c b/hw/pcnet-pci.c index ea5dfdef76..4e164da3ac 100644 --- a/hw/pcnet-pci.c +++ b/hw/pcnet-pci.c @@ -288,6 +288,7 @@ static NetClientInfo net_pci_pcnet_info = { .size = sizeof(NICState), .can_receive = pcnet_can_receive, .receive = pcnet_receive, + .link_status_changed = pcnet_set_link_status, .cleanup = pci_pcnet_cleanup, }; diff --git a/hw/pcnet.c b/hw/pcnet.c index add3ec2559..cba253ba7b 100644 --- a/hw/pcnet.c +++ b/hw/pcnet.c @@ -1197,6 +1197,13 @@ ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_) return size_; } +void pcnet_set_link_status(VLANClientState *nc) +{ + PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque; + + d->lnkst = nc->link_down ? 0 : 0x40; +} + static void pcnet_transmit(PCNetState *s) { target_phys_addr_t xmit_cxda = 0; diff --git a/hw/pcnet.h b/hw/pcnet.h index 52cc52e940..edc81c90ac 100644 --- a/hw/pcnet.h +++ b/hw/pcnet.h @@ -58,6 +58,7 @@ uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr); uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap); int pcnet_can_receive(VLANClientState *nc); ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_); +void pcnet_set_link_status(VLANClientState *nc); void pcnet_common_cleanup(PCNetState *d); int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info); extern const VMStateDescription vmstate_pcnet;