All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC
@ 2012-01-05 20:02 Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 1/5] Add xgmac ethernet model Mark Langsdorf
                   ` (6 more replies)
  0 siblings, 7 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, afaerber

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried voer from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in 
that series.

 Makefile.target      |    1 +
 hw/a9mpcore.c        |    7 +-
 hw/arm11mpcore.c     |   14 ++--
 hw/arm_gic.c         |   57 +++++++------
 hw/armv7m_nvic.c     |    7 +-
 hw/highbank.c        |  227 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   31 +++++++
 hw/realview_gic.c    |    3 +-
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 ++
 target-arm/machine.c |    2 +
 11 files changed, 320 insertions(+), 41 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v5 1/5] Add xgmac ethernet model
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-05 20:02 ` Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Rob Herring, afaerber, Mark Langsdorf

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  424 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 425 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 18be624..5780a5f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..c19fff5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,424 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    uint32_t c_phyaddr;
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(c_phyaddr, xgmac_state),
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("phyaddr", struct xgmac_state, c_phyaddr, 7),
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 1/5] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-05 20:02 ` Mark Langsdorf
  2012-01-06 15:37   ` Peter Maydell
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, afaerber, Mark Langsdorf

Increase the maximum number of GIC interrupts for a9mp and a11mp to 256,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretically number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v4, v5
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |    7 +++--
 hw/arm11mpcore.c  |   14 +++++++-----
 hw/arm_gic.c      |   57 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |    7 ++---
 hw/realview_gic.c |    3 +-
 5 files changed, 48 insertions(+), 40 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..8c8b72b 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,7 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 256),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..e4e4bb3 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, GIC_NIRQ);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,12 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The MPCore TRM says the on-chip controller has 224 external
+         * IRQ lines (+ 32 internal).  Some test chips only
+         * expose/report 32. More importantly Linux falls over if more
+         * than 32 are present!  Set the default to 64 and let chips
+         * with more working lines set it higher */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..5bfb01f 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,7 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+#define GIC_NIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -111,6 +112,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    int num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +135,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +224,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +281,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +297,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +312,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +324,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +336,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +353,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +428,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +453,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +470,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +483,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +499,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +510,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +520,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -735,17 +737,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +774,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +800,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +810,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq;
+    if (s->num_irq > GIC_NIRQ) {
+        hw_error("device requested %u out of %u interrupt lines, failing\n",
+                 num_irq, GIC_NIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..0de51f4 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -384,7 +381,9 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* 32 internal lines (16 used for system exceptions) plus 64 external
+    * interrupt lines.  */
+    gic_init(&s->gic, 96);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..cd7e53d 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,7 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 3/5] ahci: add support for non-PCI based controllers
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 1/5] Add xgmac ethernet model Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-05 20:02 ` Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 4/5] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v3
	Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..982ee31 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,33 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct PlatAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+} PlatAHCIState;
+
+static int plat_ahci_init(SysBusDevice *dev)
+{
+    PlatAHCIState *s = FROM_SYSBUS(PlatAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, 1);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo plat_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(PlatAHCIState),
+    .init         = plat_ahci_init,
+};
+
+static void plat_ahci_register(void)
+{
+    sysbus_register_withprop(&plat_ahci_info);
+}
+
+device_init(plat_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 4/5] arm: Add dummy support for co-processor 15's secure config register
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                   ` (2 preceding siblings ...)
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-05 20:02 ` Mark Langsdorf
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 4cfda17..acefd37 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1412,6 +1412,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1880,6 +1885,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                   ` (3 preceding siblings ...)
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 4/5] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-05 20:02 ` Mark Langsdorf
  2012-01-06 16:29   ` Peter Maydell
                     ` (2 more replies)
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  6 siblings, 3 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-05 20:02 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
 Makefile.target |    1 +
 hw/highbank.c   |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 228 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 5780a5f..56ca94d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -339,6 +339,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..73b6564
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,227 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "elf.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    cpu_reset(env);
+    env->cp15.c15_config_base_address = 0xfff10000;
+
+    /* Set entry point for secondary CPUs.  This assumes we're using
+       the init code from arm_boot.c.  Real hardware resets all CPUs
+       the same.  */
+    env->regs[15] = 0;
+}
+
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    uint32_t *regs;
+    MemoryRegion *iomem;
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    /* Override default RAM size */
+    if (ram_size == 0x8000000) {
+        if (sizeof(long) == 8) {
+            ram_size = 0xff900000;
+        } else {
+            ram_size = 0x80000000;
+        }
+    }
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
+            fprintf(stderr, "Unable to load sysram.bin\n");
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    iomem = g_new(MemoryRegion, 1);
+    regs = g_malloc0(0x200);
+    regs[0x40] = 0x05F20121;
+    regs[0x41] = 0x2;
+    regs[0x42] = 0x05F30121;
+    regs[0x43] = 0x05F40121;
+    memory_region_init_io(iomem, &hb_mem_ops, regs, "highbank_regs", 0x1000);
+    memory_region_add_subregion(sysmem, 0xfff3c000, iomem);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    qemu_check_nic_model(&nd_table[0], "xgmac");
+    dev = qdev_create(NULL, "xgmac");
+    qdev_set_nic_properties(dev, &nd_table[0]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+    qemu_check_nic_model(&nd_table[1], "xgmac");
+    dev = qdev_create(NULL, "xgmac");
+    qdev_set_nic_properties(dev, &nd_table[1]);
+    qdev_init_nofail(dev);
+    sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+    sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "highbank",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable
  2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-06 15:37   ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-06 15:37 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, afaerber

On 5 January 2012 20:02, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 256,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
>
> Set the maximum theoretically number of GIC interrupts to 1020 and
> update the save/restore code to only use the appropriate number for
> each SoC.

This commit message is a bit out of sync with the actual changes.
The first line says "increase the maximum to 256", but actually the
maximum has been set to 1020 (as you say later in the message).

> @@ -216,6 +216,7 @@ static SysBusDeviceInfo a9mp_priv_info = {
>     .qdev.reset = a9mp_priv_reset,
>     .qdev.props = (Property[]) {
>         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
> +        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 256),

The default should stay the same as the old hard-coded value, ie 96.
(256 is the A9 hardware maximum. In theory we could stick a check in
that the property was <256, but I don't think there's any point.)
We can throw in this comment, mostly for consistency with the one in
the 11MPCore sources (see below):

/* The Cortex-A9MP may have anything from 0 to 224 external interrupt IRQ
 * lines (+ 32 internal). We default to 64+32, which is the number provided
 * by the Cortex-A9MP test chip in the Realview PBX-A9 and Versatile
 * Express A9 development boards. Other boards may differ and should set
 * this property appropriately.
 */

> @@ -221,6 +217,12 @@ static SysBusDeviceInfo mpcore_priv_info = {
>     .qdev.size  = sizeof(mpcore_priv_state),
>     .qdev.props = (Property[]) {
>         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
> +        /* The MPCore TRM says the on-chip controller has 224 external
> +         * IRQ lines (+ 32 internal).  Some test chips only
> +         * expose/report 32. More importantly Linux falls over if more
> +         * than 32 are present!  Set the default to 64 and let chips
> +         * with more working lines set it higher */

Let's fix the inaccuracy in this comment while we're moving it around.

/* The ARM11 MPCore TRM says the on-chip controller may have anything
 * from 0 to 224 external interrupt IRQ lines (+ 32 internal). We default
 * to 32+32, which is the number provided by the ARM11 MPCore test
 * chip in the Realview Versatile EB coretile. Other boards may have
 * 11MPCores with different hardware config and should set this
 * property appropriately -- some Linux kernels may not boot if the hardware
 * has more IRQ lines than they expect.
 */

> diff --git a/hw/arm_gic.c b/hw/arm_gic.c
> index 0339cf5..5bfb01f 100644
> --- a/hw/arm_gic.c
> +++ b/hw/arm_gic.c
> @@ -11,6 +11,7 @@
>    controller, MPCore distributed interrupt controller and ARMv7-M
>    Nested Vectored Interrupt Controller.  */
>
> +#define GIC_NIRQ 1020

Having looked at the code that we get after this patch, I think it would be
a good idea to rename this macro now:

/* Maximum possible number of interrupts (this limit is imposed by
 * the GIC architecture)
 */
#define GIC_MAXIRQ 1020

(the renaming won't bloat the patch much as the macro's only used in
half a dozen places).

I think that will help to avoid confusion in future about the difference
between this and num_irq.

>  //#define DEBUG_GIC
>
>  #ifdef DEBUG_GIC
> @@ -111,6 +112,7 @@ typedef struct gic_state
>     struct gic_state *backref[NCPU];
>     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
>  #endif
> +    int num_irq;

It seems a little inconsistent that we use a uint32_t in the properties
but a plain int in the gic_init() prototype and here. Does using uint32_t
throughout cause any problems?

> @@ -295,7 +297,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
>         else
>             irq = (offset - 0x180) * 8;
>         irq += GIC_BASE_IRQ;
> -        if (irq >= GIC_NIRQ)
> +        if (irq >= s->num_irq)
>             goto bad_reg;

If you like you can add the extra braces that will shut checkpatch up
about these hunks, but I'm not going to insist on it. (I waver back and
forth about how much I care about this particular CODING_STYLE
shibboleth. This file is one of the older ones that was written before
we decided we loved braces.)

> @@ -808,7 +810,12 @@ static void gic_init(gic_state *s)
>  #if NCPU > 1
>     s->num_cpu = num_cpu;
>  #endif
> -    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
> +    s->num_irq = num_irq;

For the benefit of M profile (see below for further explanation)
this should be
   s->num_irq = num_irq + GIC_BASE_IRQ;

> +    if (s->num_irq > GIC_NIRQ) {
> +        hw_error("device requested %u out of %u interrupt lines, failing\n",
> +                 num_irq, GIC_NIRQ);

"requested number of interrupt lines %d exceeds GIC maximum of %d"

(you can drop the "failing" bit because hw_error() prefixes the string
with "hardware error" and we end up saying "Aborted", so the fact
we're failing is pretty clear anyway :-))

> @@ -384,7 +381,9 @@ static int armv7m_nvic_init(SysBusDevice *dev)
>  {
>     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
>
> -    gic_init(&s->gic);
> +   /* 32 internal lines (16 used for system exceptions) plus 64 external
> +    * interrupt lines.  */
> +    gic_init(&s->gic, 96);

This should have a property as well; the v7M architecture allows anything
up to 496 external interrupts. The default for the property should be 64,
meaning 64 external interrupts. (Not 96, because we'll add GIC_BASE_IRQ
to it in gic_init().)

The reason for this GIC_BASE_IRQ addition is that the M profile
specification doesn't consider the lines used for system exceptions
to be interrupts (they don't appear in the enable/set/clear register interfaces,
for example). Moreover, even where the architecture does consider
exceptions+interrupts as a continuous set, it goes 0..15 [exceptions]
and then 16 is external interrupt 0. The spacing of 32 is purely a QEMU
internal thing for implementation convenience, so we want to hide it from
the board-level users of armv7m_init() etc.

> @@ -37,7 +36,7 @@ static int realview_gic_init(SysBusDevice *dev)
>  {
>     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
>
> -    gic_init(&s->gic);

You can add a comment here:
/* The GICs on the RealView boards have a fixed nonconfigurable
 * number of interrupt lines, so we don't need to expose this as
 * a qdev property.
 */

just to explain why this one's different to the others.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-06 16:29   ` Peter Maydell
  2012-01-06 16:58     ` Mark Langsdorf
  2012-01-06 21:16     ` Mark Langsdorf
  2012-01-06 18:09   ` Andreas Färber
  2012-01-06 18:37   ` Igor Mitsyanko
  2 siblings, 2 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-06 16:29 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, Rob Herring, afaerber

On 5 January 2012 20:02, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Adds support for Calxeda's Highbank SoC.

Is there a test kernel image/etc we can use to confirm that this all works?

> --- /dev/null
> +++ b/hw/highbank.c
> @@ -0,0 +1,227 @@
> +/*
> + * Calxeda Highbank SoC emulation

Is it worth splitting the SoC emulation out from the board emulation, or
is the expectation that the SoC will be used in this board and only this
board?

> + *
> + * Copyright (c) 2010-2012 Calxeda
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2, as published by the Free Software Foundation.

2-or-later, please.

> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + *
> + */
> +
> +#include "sysbus.h"
> +#include "arm-misc.h"
> +#include "primecell.h"
> +#include "devices.h"
> +#include "loader.h"
> +#include "elf.h"
> +#include "net.h"
> +#include "sysemu.h"
> +#include "boards.h"
> +#include "sysbus.h"
> +#include "blockdev.h"
> +#include "exec-memory.h"

This looks like a lot of includes -- are they all required? (eg why elf.h?)

> +
> +#define SMP_BOOT_ADDR 0
> +#define NIRQ_GIC      160
> +
> +/* Board init.  */
> +static void highbank_cpu_reset(void *opaque)
> +{
> +    CPUState *env = opaque;
> +
> +    cpu_reset(env);
> +    env->cp15.c15_config_base_address = 0xfff10000;
> +
> +    /* Set entry point for secondary CPUs.  This assumes we're using
> +       the init code from arm_boot.c.  Real hardware resets all CPUs
> +       the same.  */
> +    env->regs[15] = 0;
> +}

The env->regs[] bit at least shouldn't be needed -- see commit
6ed221b637 which consolidated it into arm_boot.c. Ditto the
cpu_reset().

I think your attempt to set c15_config_base_address here may
be being defeated by the cpu_reset() call in
hw/arm_boot.c:do_cpu_reset(), but I haven't checked that.

> +static void hb_regs_write(void *opaque, target_phys_addr_t offset,
> +                          uint64_t value, unsigned size)
> +{
> +    uint32_t *regs = opaque;
> +
> +    if (offset == 0xf00) {
> +        if (value == 1 || value == 2) {
> +            qemu_system_reset_request();
> +        } else if (value == 3) {
> +            qemu_system_shutdown_request();
> +        }
> +    }
> +
> +    regs[offset/4] = value;
> +}

Please make this a proper qdev device (it can stay in this
file).

> +    /* Override default RAM size */
> +    if (ram_size == 0x8000000) {
> +        if (sizeof(long) == 8) {
> +            ram_size = 0xff900000;
> +        } else {
> +            ram_size = 0x80000000;
> +        }

Yuck. Model behaviour shouldn't depend on properties of
the host system like sizeof(long).

> +    }
> +    sysmem = get_system_memory();
> +    dram = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(dram, "highbank.dram", ram_size);
> +    /* SDRAM at address zero.  */
> +    memory_region_add_subregion(sysmem, 0, dram);
> +
> +    sysram = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
> +            fprintf(stderr, "Unable to load sysram.bin\n");
> +    }

Is this for some sort of BIOS-image equivalent?

> +    dev = qdev_create(NULL, "sp804");
> +    qdev_prop_set_uint32(dev, "freq0", 150000000);
> +    qdev_prop_set_uint32(dev, "freq1", 150000000);

So, er, we just committed a patch saying the timer frequency
could go up to 1MHz, and this is rather more than that :-)

> +    qemu_check_nic_model(&nd_table[0], "xgmac");
> +    dev = qdev_create(NULL, "xgmac");
> +    qdev_set_nic_properties(dev, &nd_table[0]);
> +    qdev_init_nofail(dev);

You need to guard the nic creation and wiring with
  if (nd_table[0].vlan) {
     ....
  }

to catch the case where the user requested no NIC at all
(ie the nd_table[] entry is unused).
(A command line with "-net user" and no other -net options
will provoke this.)

> +static QEMUMachine highbank_machine = {
> +    .name = "highbank",
> +    .desc = "highbank",

Can we have an actually descriptive description? :-)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 16:29   ` Peter Maydell
@ 2012-01-06 16:58     ` Mark Langsdorf
  2012-01-06 17:04       ` Peter Maydell
  2012-01-06 21:16     ` Mark Langsdorf
  1 sibling, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-06 16:58 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, Rob Herring, afaerber

On 01/06/2012 10:29 AM, Peter Maydell wrote:
> On 5 January 2012 20:02, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> From: Rob Herring <rob.herring@calxeda.com>
>>
>> Adds support for Calxeda's Highbank SoC.
> 
> Is there a test kernel image/etc we can use to confirm that this all works?

The 3.2 kernel should have all the necessary support for Highbank.

>> --- /dev/null
>> +++ b/hw/highbank.c
>> @@ -0,0 +1,227 @@
>> +/*
>> + * Calxeda Highbank SoC emulation
> 
> Is it worth splitting the SoC emulation out from the board emulation, or
> is the expectation that the SoC will be used in this board and only this
> board?

Rob and I expect that any board differences will be non-existent from
QEMU's perspective.

>> +
>> +#define SMP_BOOT_ADDR 0
>> +#define NIRQ_GIC      160
>> +
>> +/* Board init.  */
>> +static void highbank_cpu_reset(void *opaque)
>> +{
>> +    CPUState *env = opaque;
>> +
>> +    cpu_reset(env);
>> +    env->cp15.c15_config_base_address = 0xfff10000;
>> +
>> +    /* Set entry point for secondary CPUs.  This assumes we're using
>> +       the init code from arm_boot.c.  Real hardware resets all CPUs
>> +       the same.  */
>> +    env->regs[15] = 0;
>> +}
>
> I think your attempt to set c15_config_base_address here may
> be being defeated by the cpu_reset() call in
> hw/arm_boot.c:do_cpu_reset(), but I haven't checked that.

It works on our test boot.

>> +    /* Override default RAM size */
>> +    if (ram_size == 0x8000000) {
>> +        if (sizeof(long) == 8) {
>> +            ram_size = 0xff900000;
>> +        } else {
>> +            ram_size = 0x80000000;
>> +        }
> 
> Yuck. Model behaviour shouldn't depend on properties of
> the host system like sizeof(long).

The board is populated with 4G of DRAM, which we'd like
to support if the host can. Is there a better way to do
that?

>> +    }
>> +    sysmem = get_system_memory();
>> +    dram = g_new(MemoryRegion, 1);
>> +    memory_region_init_ram(dram, "highbank.dram", ram_size);
>> +    /* SDRAM at address zero.  */
>> +    memory_region_add_subregion(sysmem, 0, dram);
>> +
>> +    sysram = g_new(MemoryRegion, 1);
>> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
>> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
>> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
>> +            fprintf(stderr, "Unable to load sysram.bin\n");
>> +    }
> 
> Is this for some sort of BIOS-image equivalent?

Yes, uboot and the like. It isn't necessary to boot the system,
but it models the actual board a bit better.

>> +    dev = qdev_create(NULL, "sp804");
>> +    qdev_prop_set_uint32(dev, "freq0", 150000000);
>> +    qdev_prop_set_uint32(dev, "freq1", 150000000);
> 
> So, er, we just committed a patch saying the timer frequency
> could go up to 1MHz, and this is rather more than that :-)

You'd think I would have noticed.

The set frequencies patch doesn't check the maximum frequency,
so the logic is good. I can send a small patch to update the
documentation.

>> +    .name = "highbank",
>> +    .desc = "highbank",
> 
> Can we have an actually descriptive description? :-)

Sure. I'll update it and fix the other issues.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 16:58     ` Mark Langsdorf
@ 2012-01-06 17:04       ` Peter Maydell
  2012-01-06 17:34         ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-06 17:04 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, Rob Herring, afaerber

On 6 January 2012 16:58, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/06/2012 10:29 AM, Peter Maydell wrote:
>>> +    /* Override default RAM size */
>>> +    if (ram_size == 0x8000000) {
>>> +        if (sizeof(long) == 8) {
>>> +            ram_size = 0xff900000;
>>> +        } else {
>>> +            ram_size = 0x80000000;
>>> +        }
>>
>> Yuck. Model behaviour shouldn't depend on properties of
>> the host system like sizeof(long).
>
> The board is populated with 4G of DRAM, which we'd like
> to support if the host can. Is there a better way to do
> that?

Don't mess with the default, have the user specify a RAM size that
makes sense for their host machine. It's not fantastic but it's what
QEMU has at the moment.

I once tried to suggest a patchset which would allow boards to
specify their min/max/default RAM sizes but it got shot down.

>>> +    sysmem = get_system_memory();
>>> +    dram = g_new(MemoryRegion, 1);
>>> +    memory_region_init_ram(dram, "highbank.dram", ram_size);
>>> +    /* SDRAM at address zero.  */
>>> +    memory_region_add_subregion(sysmem, 0, dram);
>>> +
>>> +    sysram = g_new(MemoryRegion, 1);
>>> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
>>> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
>>> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
>>> +            fprintf(stderr, "Unable to load sysram.bin\n");
>>> +    }
>>
>> Is this for some sort of BIOS-image equivalent?
>
> Yes, uboot and the like. It isn't necessary to boot the system,
> but it models the actual board a bit better.

If it's not necessary, should we be failing if there isn't an image file
present?

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 17:04       ` Peter Maydell
@ 2012-01-06 17:34         ` Mark Langsdorf
  2012-01-06 17:46           ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-06 17:34 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, Rob Herring, afaerber

On 01/06/2012 11:04 AM, Peter Maydell wrote:
> On 6 January 2012 16:58, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/06/2012 10:29 AM, Peter Maydell wrote:

>>>> +    sysram = g_new(MemoryRegion, 1);
>>>> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
>>>> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
>>>> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
>>>> +            fprintf(stderr, "Unable to load sysram.bin\n");
>>>> +    }
>>>
>>> Is this for some sort of BIOS-image equivalent?
>>
>> Yes, uboot and the like. It isn't necessary to boot the system,
>> but it models the actual board a bit better.
> 
> If it's not necessary, should we be failing if there isn't an image file
> present?

Are we failing? We're printing out a warning message, but the
boot goes on.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 17:34         ` Mark Langsdorf
@ 2012-01-06 17:46           ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-06 17:46 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, Rob Herring, afaerber

On 6 January 2012 17:34, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/06/2012 11:04 AM, Peter Maydell wrote:
>> On 6 January 2012 16:58, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
>>>>> +            fprintf(stderr, "Unable to load sysram.bin\n");
>>>>> +    }

>> If it's not necessary, should we be failing if there isn't an image file
>> present?
>
> Are we failing? We're printing out a warning message, but the
> boot goes on.

Doh. Completely misread that bit of code :-)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-06 16:29   ` Peter Maydell
@ 2012-01-06 18:09   ` Andreas Färber
  2012-01-06 18:37   ` Igor Mitsyanko
  2 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-06 18:09 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: peter.maydell, qemu-devel, Rob Herring

Am 05.01.2012 21:02, schrieb Mark Langsdorf:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Adds support for Calxeda's Highbank SoC.
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---

> diff --git a/hw/highbank.c b/hw/highbank.c
> new file mode 100644
> index 0000000..73b6564
> --- /dev/null
> +++ b/hw/highbank.c

> +    sysram = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);

> +    if (load_image_targphys("sysram.bin", 0xfff88000, 0x8000) < 0) {
> +            fprintf(stderr, "Unable to load sysram.bin\n");
> +    }

This should be something like:

char* filename;

if (bios_name == NULL) {
    bios_name = "sysram.bin";
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename != NULL) {
    load_image_targpyhs(filename, ...);
    g_free(filename);
}

Not knowing ARM boot well myself, you might also want to check and use
get_image_size(filename) rather than hardcoding 0x8000?

Also I'm wondering what the use case here is. I can imagine two scenarios:

1) User wants to boot a -bios, which in turn may at runtime search for a
kernel on the emulated storage, like it would on real hardware. Then
loading a too large or missing BIOS should fail.

2) User wants to boot a -kernel. Then this should probably not complain
about issues with -bios at all, unless explicitly specified by the user.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-06 16:29   ` Peter Maydell
  2012-01-06 18:09   ` Andreas Färber
@ 2012-01-06 18:37   ` Igor Mitsyanko
  2012-01-06 18:45     ` Peter Maydell
  2012-01-06 18:48     ` Rob Herring
  2 siblings, 2 replies; 147+ messages in thread
From: Igor Mitsyanko @ 2012-01-06 18:37 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: peter.maydell, qemu-devel, Rob Herring, afaerber

On 01/06/2012 12:02 AM, Mark Langsdorf wrote:

Hello, Mark. According to technical specification on Calxeda website, 
highbank SoC has SD 3.0 host controller, are you planning to implement 
it in qemu? I'm asking because I recently have submitted a patch 
implementing SD 2.0 host controller, and it looks like these two 
specifications revisions are not very different from each other.

> +    if (!cpu_model) {
> +        cpu_model = "cortex-a9";
> +    }

Google said there is only cortexA9-based Highbank SoC version, maybe you 
should just hardcode cpu model?

> +    /* Override default RAM size */
> +    if (ram_size == 0x8000000) {
> +        if (sizeof(long) == 8) {
> +            ram_size = 0xff900000;
> +        } else {

This value looks a bit strange, usually DRAM consists of several banks 
512, 256 (or something like that) megabytes each, I couldn't find what 
DRAM configuration does the actual board have?

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 18:37   ` Igor Mitsyanko
@ 2012-01-06 18:45     ` Peter Maydell
  2012-01-06 19:10       ` Igor Mitsyanko
  2012-01-06 18:48     ` Rob Herring
  1 sibling, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-06 18:45 UTC (permalink / raw)
  To: Igor Mitsyanko; +Cc: Rob Herring, qemu-devel, Mark Langsdorf, afaerber

On 6 January 2012 18:37, Igor Mitsyanko <i.mitsyanko@gmail.com> wrote:
> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
>> +    if (!cpu_model) {
>> +        cpu_model = "cortex-a9";
>> +    }
>
>
> Google said there is only cortexA9-based Highbank SoC version, maybe you
> should just hardcode cpu model?

This is just boilerplate code for any random ARM board at the moment:
it defaults the CPU but lets the user override. We should either make
a decision to do something else for all boards, or follow the usual
convention here; I'm happy to do the latter.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 18:37   ` Igor Mitsyanko
  2012-01-06 18:45     ` Peter Maydell
@ 2012-01-06 18:48     ` Rob Herring
  1 sibling, 0 replies; 147+ messages in thread
From: Rob Herring @ 2012-01-06 18:48 UTC (permalink / raw)
  To: Igor Mitsyanko; +Cc: peter.maydell, qemu-devel, Mark Langsdorf, afaerber

On 01/06/2012 12:37 PM, Igor Mitsyanko wrote:
> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
> 
> Hello, Mark. According to technical specification on Calxeda website,
> highbank SoC has SD 3.0 host controller, are you planning to implement
> it in qemu? I'm asking because I recently have submitted a patch
> implementing SD 2.0 host controller, and it looks like these two
> specifications revisions are not very different from each other.
> 
It's a standard SDHCI controller. There was a model submitted by Vincent
Palatin a while back, but I didn't have much luck getting it working and
haven't debugged it further.

SD3.0 vs 2.0 is probably not going to make a difference from a QEMU
point of view.

Rob

>> +    if (!cpu_model) {
>> +        cpu_model = "cortex-a9";
>> +    }
> 
> Google said there is only cortexA9-based Highbank SoC version, maybe you
> should just hardcode cpu model?
> 
>> +    /* Override default RAM size */
>> +    if (ram_size == 0x8000000) {
>> +        if (sizeof(long) == 8) {
>> +            ram_size = 0xff900000;
>> +        } else {
> 
> This value looks a bit strange, usually DRAM consists of several banks
> 512, 256 (or something like that) megabytes each, I couldn't find what
> DRAM configuration does the actual board have?

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 18:45     ` Peter Maydell
@ 2012-01-06 19:10       ` Igor Mitsyanko
  2012-01-06 20:11         ` Andreas Färber
  0 siblings, 1 reply; 147+ messages in thread
From: Igor Mitsyanko @ 2012-01-06 19:10 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Mark Langsdorf, qemu-devel, Rob Herring, afaerber

On 01/06/2012 10:45 PM, Peter Maydell wrote:
> On 6 January 2012 18:37, Igor Mitsyanko<i.mitsyanko@gmail.com>  wrote:
>> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
>>> +    if (!cpu_model) {
>>> +        cpu_model = "cortex-a9";
>>> +    }
>>
>>
>> Google said there is only cortexA9-based Highbank SoC version, maybe you
>> should just hardcode cpu model?
>
> This is just boilerplate code for any random ARM board at the moment:
> it defaults the CPU but lets the user override. We should either make
> a decision to do something else for all boards, or follow the usual
> convention here; I'm happy to do the latter.
>

Are you saying that it's a mistake that we hardcoded cpu model and 
memory size for Exynos boards in our patches? It makes sense to use 
documented values in emulation, many boards in qemu currently do this. 
And probably nothing even going to work with wrong cpu model, I though 
this command line option is mostly for x86 target.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 19:10       ` Igor Mitsyanko
@ 2012-01-06 20:11         ` Andreas Färber
  2012-01-07  3:14           ` Peter Maydell
  2012-01-07  9:55           ` Igor Mitsyanko
  0 siblings, 2 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-06 20:11 UTC (permalink / raw)
  To: Igor Mitsyanko, Peter Maydell; +Cc: Mark Langsdorf, qemu-devel, Rob Herring

Am 06.01.2012 20:10, schrieb Igor Mitsyanko:
> On 01/06/2012 10:45 PM, Peter Maydell wrote:
>> On 6 January 2012 18:37, Igor Mitsyanko<i.mitsyanko@gmail.com>  wrote:
>>> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
>>>> +    if (!cpu_model) {
>>>> +        cpu_model = "cortex-a9";
>>>> +    }
>>>
>>>
>>> Google said there is only cortexA9-based Highbank SoC version, maybe you
>>> should just hardcode cpu model?
>>
>> This is just boilerplate code for any random ARM board at the moment:
>> it defaults the CPU but lets the user override. We should either make
>> a decision to do something else for all boards, or follow the usual
>> convention here; I'm happy to do the latter.
>>
> 
> Are you saying that it's a mistake that we hardcoded cpu model and
> memory size for Exynos boards in our patches?

No machine should silently change the user's -cpu to something else.
Either error out or warn the user, or let them face the consequences of
their parameters themselves.

Not sure how hardcoding the cpu_model would work with CPU features,
would they be still included or stripped out before. Peter?

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 16:29   ` Peter Maydell
  2012-01-06 16:58     ` Mark Langsdorf
@ 2012-01-06 21:16     ` Mark Langsdorf
  2012-01-07  3:20       ` Peter Maydell
  1 sibling, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-06 21:16 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel, Rob Herring, afaerber

On 01/06/2012 10:29 AM, Peter Maydell wrote:
> On 5 January 2012 20:02, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> +static void hb_regs_write(void *opaque, target_phys_addr_t offset,
>> +                          uint64_t value, unsigned size)
>> +{
>> +    uint32_t *regs = opaque;
>> +
>> +    if (offset == 0xf00) {
>> +        if (value == 1 || value == 2) {
>> +            qemu_system_reset_request();
>> +        } else if (value == 3) {
>> +            qemu_system_shutdown_request();
>> +        }
>> +    }
>> +
>> +    regs[offset/4] = value;
>> +}
> 
> Please make this a proper qdev device (it can stay in this
> file).

Assuming that I'm going to need save/restore support, what's
the proper syntax for saving uint32_t *regs? All the uses I
can find seem to be for an array of structs, not an array
of ints, and I keep hoping there's a simpler way.

Thanks,
Mark Langsdorf
Calxeda, Inc,.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 20:11         ` Andreas Färber
@ 2012-01-07  3:14           ` Peter Maydell
  2012-01-07  4:18             ` Andreas Färber
  2012-01-07  9:55           ` Igor Mitsyanko
  1 sibling, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-07  3:14 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Igor Mitsyanko, Mark Langsdorf, qemu-devel, Rob Herring

On 6 January 2012 20:11, Andreas Färber <afaerber@suse.de> wrote:
> Not sure how hardcoding the cpu_model would work with CPU features,
> would they be still included or stripped out before. Peter?

Interesting question. It's certainly more likely to work to have
a board where the only tweak you made to the CPU was to disable
Neon, say, but I'm not sure "likely to work" is a very firm criterion.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 21:16     ` Mark Langsdorf
@ 2012-01-07  3:20       ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-07  3:20 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, Rob Herring, afaerber

On 6 January 2012 21:16, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Assuming that I'm going to need save/restore support, what's
> the proper syntax for saving uint32_t *regs? All the uses I
> can find seem to be for an array of structs, not an array
> of ints, and I keep hoping there's a simpler way.

VMSTATE_UINT32_ARRAY is what you want. The VMSTATE_*_ARRAY macros
all work the same way:
  VMSTATE_UINT32_ARRAY(arrayname, structname, arraysize)
and there are plenty of examples in the tree if you grep for them.

You might also consider whether the hardware looks more like an
array of 128 R/W registers, or like the versatile board registers
modelled in hw/arm_sysreg.c. Not knowing this particular hardware
I can't recommend one way or the other, but that is the alternative
approach.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-07  3:14           ` Peter Maydell
@ 2012-01-07  4:18             ` Andreas Färber
  0 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-07  4:18 UTC (permalink / raw)
  To: Peter Maydell; +Cc: Igor Mitsyanko, Mark Langsdorf, qemu-devel, Rob Herring

Am 07.01.2012 04:14, schrieb Peter Maydell:
> On 6 January 2012 20:11, Andreas Färber <afaerber@suse.de> wrote:
>> Not sure how hardcoding the cpu_model would work with CPU features,
>> would they be still included or stripped out before. Peter?
> 
> Interesting question. It's certainly more likely to work to have
> a board where the only tweak you made to the CPU was to disable
> Neon, say, but I'm not sure "likely to work" is a very firm criterion.

What I meant was, if sometime we allow, e.g., '-cpu cortex-m4,+FPU',
will cpu_model technically contain "cortex-m4" or "cortex-m4,+FPU"?

If the latter, then we should not hardcode cpu_model anywhere.

I'm sure we can always find a scenario that doesn't work, but the
emulated instructions are rather unlikely to conflict with a
machine-specific memory layout and device instantiation, given that the
guest matches the emulated CPU features.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-07  9:55           ` Igor Mitsyanko
@ 2012-01-07  9:40             ` Andreas Färber
  0 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-07  9:40 UTC (permalink / raw)
  To: Igor Mitsyanko; +Cc: Peter Maydell, Rob Herring, qemu-devel, Mark Langsdorf

Am 07.01.2012 10:55, schrieb Igor Mitsyanko:
> On 06.01.2012 11:11 PM, Andreas Färber wrote:
>> Am 06.01.2012 20:10, schrieb Igor Mitsyanko:
>>> On 01/06/2012 10:45 PM, Peter Maydell wrote:
>>>> On 6 January 2012 18:37, Igor Mitsyanko<i.mitsyanko@gmail.com>   wrote:
>>>>> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
>>>>>> +    if (!cpu_model) {
>>>>>> +        cpu_model = "cortex-a9";
>>>>>> +    }
>>>>>
>>>>>
>>>>> Google said there is only cortexA9-based Highbank SoC version,
>>>>> maybe you
>>>>> should just hardcode cpu model?
>>>>
>>>> This is just boilerplate code for any random ARM board at the moment:
>>>> it defaults the CPU but lets the user override. We should either make
>>>> a decision to do something else for all boards, or follow the usual
>>>> convention here; I'm happy to do the latter.
>>>>
>>>
>>> Are you saying that it's a mistake that we hardcoded cpu model and
>>> memory size for Exynos boards in our patches?
>>
>> No machine should silently change the user's -cpu to something else.
>> Either error out or warn the user, or let them face the consequences of
>> their parameters themselves.
> 
> Machines do not instantiate cpus, they instantiate SoC models,

Currently, the machine does instantiate both CPU and devices, including
those on the SoC.

> which are
> solid (not modular) devices with explicitly specified (in datasheet or
> elsewhere) cpu core and peripheral devices, and if someone creates
> Highbank SoC instance with Cortex-M4 CPU core then it's no longer a
> Highbank SoC.

I somewhat agree that changing the CPU of an SoC should not be allowed,
if we make it easy enough to derive SoCs with another core. (You will
find further discussions of child<> vs. link<> in the qemu-test thread,
I think.)

Not having SoCs yet, -cpu roughly corresponds to exchanging
device-compatible SoCs on the board. With machine and SoC both called
Highbank here, that's kind of confusing.

One reason to allow -cpu (and -device) is to avoid for us getting
swamped with machines.

>> Not sure how hardcoding the cpu_model would work with CPU features,
>> would they be still included or stripped out before. Peter?
>>
> 
> What do you mean? All features are currently set during
> cpu_reset_model_id() as far as I know, it doesn't matter whether
> cpu_model was specified on command line or hardcoded into initialization
> code.

This again is referring to discussions of upcoming changes elsewhere.

Currently, ARM CPU reset derives CPU features from the CPUID in turn
derived from the CPU name. Peter wants to allow turning ARM CPU features
on and off like for i386, decoupling this from CPUID.

Of course we can always change things back and forth, but I usually
prefer future-proof solutions. :)

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank
  2012-01-06 20:11         ` Andreas Färber
  2012-01-07  3:14           ` Peter Maydell
@ 2012-01-07  9:55           ` Igor Mitsyanko
  2012-01-07  9:40             ` Andreas Färber
  1 sibling, 1 reply; 147+ messages in thread
From: Igor Mitsyanko @ 2012-01-07  9:55 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, Rob Herring, Andreas Färber, Mark Langsdorf

On 06.01.2012 11:11 PM, Andreas Färber wrote:
> Am 06.01.2012 20:10, schrieb Igor Mitsyanko:
>> On 01/06/2012 10:45 PM, Peter Maydell wrote:
>>> On 6 January 2012 18:37, Igor Mitsyanko<i.mitsyanko@gmail.com>   wrote:
>>>> On 01/06/2012 12:02 AM, Mark Langsdorf wrote:
>>>>> +    if (!cpu_model) {
>>>>> +        cpu_model = "cortex-a9";
>>>>> +    }
>>>>
>>>>
>>>> Google said there is only cortexA9-based Highbank SoC version, maybe you
>>>> should just hardcode cpu model?
>>>
>>> This is just boilerplate code for any random ARM board at the moment:
>>> it defaults the CPU but lets the user override. We should either make
>>> a decision to do something else for all boards, or follow the usual
>>> convention here; I'm happy to do the latter.
>>>
>>
>> Are you saying that it's a mistake that we hardcoded cpu model and
>> memory size for Exynos boards in our patches?
>
> No machine should silently change the user's -cpu to something else.
> Either error out or warn the user, or let them face the consequences of
> their parameters themselves.

Machines do not instantiate cpus, they instantiate SoC models, which are 
solid (not modular) devices with explicitly specified (in datasheet or 
elsewhere) cpu core and peripheral devices, and if someone creates 
Highbank SoC instance with Cortex-M4 CPU core then it's no longer a 
Highbank SoC. What I mean, peripheral devices on SoC are not 
configurable, you cannot add additional UART or I2C interface, why allow 
cpu model change?

> Not sure how hardcoding the cpu_model would work with CPU features,
> would they be still included or stripped out before. Peter?
>

What do you mean? All features are currently set during 
cpu_reset_model_id() as far as I know, it doesn't matter whether 
cpu_model was specified on command line or hardcoded into initialization 
code.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                   ` (4 preceding siblings ...)
  2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-09 16:59 ` Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
                     ` (5 more replies)
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  6 siblings, 6 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried voer from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in 
that series.

 Makefile.target      |    1 +
 hw/a9mpcore.c        |   13 ++-
 hw/arm11mpcore.c     |   17 ++-
 hw/arm_gic.c         |   68 +++++++------
 hw/arm_timer.c       |    3 -
 hw/armv7m_nvic.c     |   30 +++++--
 hw/highbank.c        |  267 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   31 ++++++
 hw/realview_gic.c    |    7 +-
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 ++
 target-arm/machine.c |    2 +
 12 files changed, 399 insertions(+), 52 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-10 17:52     ` Edgar E. Iglesias
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  424 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 425 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 18be624..5780a5f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..c19fff5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,424 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    uint32_t c_phyaddr;
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(c_phyaddr, xgmac_state),
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("phyaddr", struct xgmac_state, c_phyaddr, 7),
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretically number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v5
	Clarify the commit message
	Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
	Makes num-irq to uint32_t in all cases
	Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   30 ++++++++++++++++++-----
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..a522942 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the 
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..37b5d58 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects. 
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..44932c8 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,34 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* 32 internal lines (16 used for system exceptions) plus 64 external
+    * interrupt lines.  */
+    gic_init(&s->gic, 96);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines (with another 32 hidden internal exception lines). We
+         * default to 64+32
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-10 11:22     ` Andreas Färber
  2012-01-09 16:59   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                     ` (2 subsequent siblings)
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   31 +++++++++++++++++++++++++++++++
 1 files changed, 31 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..982ee31 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,33 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct PlatAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+} PlatAHCIState;
+
+static int plat_ahci_init(SysBusDevice *dev)
+{
+    PlatAHCIState *s = FROM_SYSBUS(PlatAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, 1);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo plat_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(PlatAHCIState),
+    .init         = plat_ahci_init,
+};
+
+static void plat_ahci_register(void)
+{
+    sysbus_register_withprop(&plat_ahci_info);
+}
+
+device_init(plat_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (2 preceding siblings ...)
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..00458fc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1440,6 +1440,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1908,6 +1913,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (3 preceding siblings ...)
  2012-01-09 16:59   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-09 16:59   ` [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v1
	Restructed the loading of sysram.bin and made it more clearly optional
	Made the regs structure into a proper qdev/sysbus object
	Removed some unnecessary include files
	Clarified the GPL version
	Simplified the reset function
	Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
	Added a guard for xgmac creation
	Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 5780a5f..56ca94d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -339,6 +339,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..823c2aa
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,267 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} highbank_regs_state;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, highbank_regs_state, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(highbank_regs_state),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+    highbank_regs_state *s;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    s = FROM_SYSBUS(highbank_regs_state, busdev);
+    memory_region_add_subregion(sysmem, 0xfff3c000, s->iomem);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (4 preceding siblings ...)
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-09 16:59   ` Mark Langsdorf
  2012-01-10 12:45     ` Andreas Färber
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-09 16:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 60e1c63..15d493f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-10 11:22     ` Andreas Färber
  0 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-10 11:22 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, peter.maydell, qemu-devel, Rob Herring, Alexander Graf

Am 09.01.2012 17:59, schrieb Mark Langsdorf:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Add support for ahci on sysbus.
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
> Changes from v3
>         Renamed plat-ahci to sysbus-ahci

The idea was to get rid of "plat" everywhere, not just in the qdev name.
Maybe I'm biased because platt is the German adjective for flat.

Please call it sysbus/SysBus consistently.

> Changes from v1, v2
>         Corrected indentation of PlatAHCIState members
>         Made plat_ahci_info into a single structure, not a list
> 
>  hw/ide/ahci.c |   31 +++++++++++++++++++++++++++++++
>  1 files changed, 31 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index 135d0ee..982ee31 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -25,6 +25,7 @@
>  #include <hw/msi.h>
>  #include <hw/pc.h>
>  #include <hw/pci.h>
> +#include <hw/sysbus.h>
>  
>  #include "monitor.h"
>  #include "dma.h"
> @@ -1214,3 +1215,33 @@ void ahci_reset(void *opaque)
>          ahci_reset_port(s, i);
>      }
>  }
> +
> +typedef struct PlatAHCIState {
> +    SysBusDevice busdev;
> +    AHCIState ahci;
> +} PlatAHCIState;
> +
> +static int plat_ahci_init(SysBusDevice *dev)
> +{
> +    PlatAHCIState *s = FROM_SYSBUS(PlatAHCIState, dev);
> +    ahci_init(&s->ahci, &dev->qdev, 1);

Maybe the number of ports (1) should be a qdev property?

> +
> +    sysbus_init_mmio(dev, &s->ahci.mem);
> +    sysbus_init_irq(dev, &s->ahci.irq);
> +
> +    qemu_register_reset(ahci_reset, &s->ahci);
> +    return 0;
> +}
> +
> +static SysBusDeviceInfo plat_ahci_info = {
> +    .qdev.name    = "sysbus-ahci",
> +    .qdev.size    = sizeof(PlatAHCIState),

You should prepare a dummy VMStateDescription to mark it as unmigratable
for now (cf. hw/ide/ich.c). Migration support is the upcoming series I
recently cc'ed you on.

Otherwise looking good.

Andreas

> +    .init         = plat_ahci_init,
> +};
> +
> +static void plat_ahci_register(void)
> +{
> +    sysbus_register_withprop(&plat_ahci_info);
> +}
> +
> +device_init(plat_ahci_register);

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer
  2012-01-09 16:59   ` [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer Mark Langsdorf
@ 2012-01-10 12:45     ` Andreas Färber
  2012-01-10 15:35       ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Andreas Färber @ 2012-01-10 12:45 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, peter.maydell, qemu-devel

Am 09.01.2012 17:59, schrieb Mark Langsdorf:
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
>  hw/arm_timer.c |    3 ---
>  1 files changed, 0 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/arm_timer.c b/hw/arm_timer.c
> index 60e1c63..15d493f 100644
> --- a/hw/arm_timer.c
> +++ b/hw/arm_timer.c
> @@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
>  
>      qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
>      sysbus_init_irq(dev, &s->irq);
> -    /* The timers are configurable between 32kHz and 1MHz
> -     * defaulting to 1MHz but overrideable as individual properties */

Wasn't this comment added by your "arm: Set frequencies for arm_timer"?

I didn't see a message indicating that series has been applied yet, so
you should probably fix the comment in the original patch instead of in
a follow-up patch. The point of adding the highbank emulation was to see
if the patches are sufficient, no?

Else, the commit message does not indicate what is incorrect/misleading
about it.

Andreas

>      s->timer[0] = arm_timer_init(s->freq0);
>      s->timer[1] = arm_timer_init(s->freq1);
> -
>      s->timer[0]->irq = qi[0];
>      s->timer[1]->irq = qi[1];
>      memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer
  2012-01-10 12:45     ` Andreas Färber
@ 2012-01-10 15:35       ` Peter Maydell
  2012-01-10 18:00         ` Andreas Färber
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 15:35 UTC (permalink / raw)
  To: Andreas Färber; +Cc: i.mitsyanko, qemu-devel, Mark Langsdorf

On 10 January 2012 12:45, Andreas Färber <afaerber@suse.de> wrote:
> Am 09.01.2012 17:59, schrieb Mark Langsdorf:
>> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
>> ---
>>  hw/arm_timer.c |    3 ---
>>  1 files changed, 0 insertions(+), 3 deletions(-)
>>
>> diff --git a/hw/arm_timer.c b/hw/arm_timer.c
>> index 60e1c63..15d493f 100644
>> --- a/hw/arm_timer.c
>> +++ b/hw/arm_timer.c
>> @@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
>>
>>      qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
>>      sysbus_init_irq(dev, &s->irq);
>> -    /* The timers are configurable between 32kHz and 1MHz
>> -     * defaulting to 1MHz but overrideable as individual properties */
>
> Wasn't this comment added by your "arm: Set frequencies for arm_timer"?
>
> I didn't see a message indicating that series has been applied yet, so
> you should probably fix the comment in the original patch instead of in
> a follow-up patch. The point of adding the highbank emulation was to see
> if the patches are sufficient, no?

It has been applied: commit 104a26a236.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC
  2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                   ` (5 preceding siblings ...)
  2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-10 16:45 ` Mark Langsdorf
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
                     ` (12 more replies)
  6 siblings, 13 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried voer from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in=20
that series.

 Makefile.target      |    1 +
 hw/a9mpcore.c        |   13 ++-
 hw/arm11mpcore.c     |   17 ++-
 hw/arm_gic.c         |   68 +++++++------
 hw/arm_timer.c       |    3 -
 hw/armv7m_nvic.c     |   30 +++++--
 hw/highbank.c        |  267 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   44 ++++++++
 hw/realview_gic.c    |    7 +-
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 ++
 target-arm/machine.c |    2 +
 12 files changed, 412 insertions(+), 52 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 17:34     ` Peter Maydell
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                     ` (11 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  424 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 425 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 18be624..5780a5f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..c19fff5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,424 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    uint32_t c_phyaddr;
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32(c_phyaddr, xgmac_state),
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("phyaddr", struct xgmac_state, c_phyaddr, 7),
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 17:47     ` Peter Maydell
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                     ` (10 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretically number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   30 ++++++++++++++++++-----
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..a522942 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the 
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..37b5d58 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects. 
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..44932c8 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,34 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* 32 internal lines (16 used for system exceptions) plus 64 external
+    * interrupt lines.  */
+    gic_init(&s->gic, 96);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines (with another 32 hidden internal exception lines). We
+         * default to 64+32
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 17:44     ` Andreas Färber
  2012-01-10 16:45   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                     ` (9 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v4
	replaced all references to Plat|plat_ with sysbus_
	made the number of ports into a qdev property
	added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..a3bd4b8 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct sysbus_ahci_state {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} sysbus_ahci_state;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    sysbus_ahci_state *s = FROM_SYSBUS(sysbus_ahci_state, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(sysbus_ahci_state),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", sysbus_ahci_state, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (2 preceding siblings ...)
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 17:55     ` Peter Maydell
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
                     ` (8 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..00458fc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1440,6 +1440,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1908,6 +1913,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (3 preceding siblings ...)
  2012-01-10 16:45   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 18:04     ` Peter Maydell
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
                     ` (7 subsequent siblings)
  12 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, Rob Herring, afaerber, Mark Langsdorf

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 268 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 5780a5f..56ca94d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -339,6 +339,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..823c2aa
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,267 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} highbank_regs_state;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, highbank_regs_state, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(highbank_regs_state),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+    highbank_regs_state *s;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    s = FROM_SYSBUS(highbank_regs_state, busdev);
+    memory_region_add_subregion(sysmem, 0xfff3c000, s->iomem);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (4 preceding siblings ...)
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-10 16:45   ` Mark Langsdorf
  2012-01-10 17:52     ` Peter Maydell
  2012-01-10 18:03     ` Andreas Färber
  2012-01-10 18:18   ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Peter Maydell
                     ` (6 subsequent siblings)
  12 siblings, 2 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 16:45 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v1
	Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 60e1c63..15d493f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-10 17:34     ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 17:34 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, Rob Herring, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This adds very basic support for XG-mac ethernet core from Synopsis and
> others. Missing things include:
>
> - statistics counters
> - WoL support
> - rx checksum offload
> - chained descriptors (only linear descriptor ring)
> - broadcast and multicast handling
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-10 17:44     ` Andreas Färber
  0 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-10 17:44 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, peter.maydell, qemu-devel, Rob Herring, Alexander Graf

Am 10.01.2012 17:45, schrieb Mark Langsdorf:
> From: Rob Herring <rob.herring@calxeda.com>
> 
> Add support for ahci on sysbus.
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Andreas Färber <afaerber@suse.de>

Thanks,
Andreas

> ---
> Changes from v4
> 	replaced all references to Plat|plat_ with sysbus_
> 	made the number of ports into a qdev property
> 	added dummy migration support
> Changes from v3
>         Renamed plat-ahci to sysbus-ahci
> Changes from v1, v2
>         Corrected indentation of PlatAHCIState members
>         Made plat_ahci_info into a single structure, not a list
> 
>  hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
>  1 files changed, 44 insertions(+), 0 deletions(-)
> 
> diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
> index 135d0ee..a3bd4b8 100644
> --- a/hw/ide/ahci.c
> +++ b/hw/ide/ahci.c
> @@ -25,6 +25,7 @@
>  #include <hw/msi.h>
>  #include <hw/pc.h>
>  #include <hw/pci.h>
> +#include <hw/sysbus.h>
>  
>  #include "monitor.h"
>  #include "dma.h"
> @@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
>          ahci_reset_port(s, i);
>      }
>  }
> +
> +typedef struct sysbus_ahci_state {
> +    SysBusDevice busdev;
> +    AHCIState ahci;
> +    uint32_t num_ports;
> +} sysbus_ahci_state;
> +
> +static const VMStateDescription vmstate_sysbus_ahci = {
> +    .name = "sysbus-ahci",
> +    .unmigratable = 1,
> +};
> +
> +static int sysbus_ahci_init(SysBusDevice *dev)
> +{
> +    sysbus_ahci_state *s = FROM_SYSBUS(sysbus_ahci_state, dev);
> +    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
> +
> +    sysbus_init_mmio(dev, &s->ahci.mem);
> +    sysbus_init_irq(dev, &s->ahci.irq);
> +
> +    qemu_register_reset(ahci_reset, &s->ahci);
> +    return 0;
> +}
> +
> +static SysBusDeviceInfo sysbus_ahci_info = {
> +    .qdev.name    = "sysbus-ahci",
> +    .qdev.size    = sizeof(sysbus_ahci_state),
> +    .qdev.vmsd    = &vmstate_sysbus_ahci,
> +    .qdev.props = (Property[]) {
> +        DEFINE_PROP_UINT32("num-ports", sysbus_ahci_state, num_ports, 1),
> +        DEFINE_PROP_END_OF_LIST(),
> +    },
> +    .init         = sysbus_ahci_init,
> +
> +
> +};
> +
> +static void sysbus_ahci_register(void)
> +{
> +    sysbus_register_withprop(&sysbus_ahci_info);
> +}
> +
> +device_init(sysbus_ahci_register);

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-10 17:47     ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 17:47 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
>
> Set the maximum theoretically number of GIC interrupts to 1020 and

"theoretical"

> update the save/restore code to only use the appropriate number for
> each SoC.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

> @@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
>     .qdev.reset = a9mp_priv_reset,
>     .qdev.props = (Property[]) {
>         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
> +        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
> +         * IRQ lines (with another 32 internal). We default to 64+32, which
> +         * is the number provided by the Cortex-A9MP test chip in the

Patch has trailing space at the end of this line (my mailer has eaten
it but it's in the original patch).

> +         * Realview PBX-A9 and Versatile Express A9 development boards.
> +         * Other boards may differ and should set this property appropriately.
> +         */
> +        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
>         DEFINE_PROP_END_OF_LIST(),
>     }
>  };

> @@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
>     .qdev.size  = sizeof(mpcore_priv_state),
>     .qdev.props = (Property[]) {
>         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
> +        /* The ARM11 MPCORE TRM says the on-chip controller may have
> +         * anything from 0 to 224 external interrupt IRQ lines (with another
> +         * 32 internal). We default to 32+32, which is the number provided by
> +         * the ARM11 MPCore test chip in the Realview Versatile Express
> +         * coretile. Other boards may differ and should set this property
> +         * appropriately. Some Linux kernels may not boot if the hardware
> +         * has more IRQ lines than the kernel expects.

Trailing space again.

> +        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
>         DEFINE_PROP_END_OF_LIST(),
>     }
>  };

> @@ -384,16 +382,34 @@ static int armv7m_nvic_init(SysBusDevice *dev)
>  {
>     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
>
> -    gic_init(&s->gic);
> +   /* 32 internal lines (16 used for system exceptions) plus 64 external
> +    * interrupt lines.  */
> +    gic_init(&s->gic, 96);

s->num_irq, not hardcoded 96.

Also the comment needs rephrasing now:
/* Note that for M profile gic_init() takes the number of external
 * interrupt lines only.
 */

>     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
>     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
>     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
>     return 0;
>  }
>
> +static SysBusDeviceInfo armv7m_nvic_priv_info = {
> +    .init = armv7m_nvic_init,
> +    .qdev.name  = "armv7m_nvic",
> +    .qdev.size  = sizeof(nvic_state),
> +    .qdev.vmsd = &vmstate_nvic,
> +    .qdev.props = (Property[]) {
> +        /* The ARM v7m may have anything from 0 to 496 external interrupt
> +         * IRQ lines (with another 32 hidden internal exception lines). We
> +         * default to 64+32
> +         * Other boards may differ and should set this property appropriately.
> +         */

This comment shouldn't talk about the 32 internal lines, as they are an
implementation detail of arm_gic.c, not architectural (unlike the A
profile GIC internal interrupt lines).

        /* The ARM v7m may have anything from 0 to 496 external interrupt
         * IRQ lines. We default to 64. Other boards may differ and should
         * set this property appropriately.
         */

> +        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
> +        DEFINE_PROP_END_OF_LIST(),

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model
  2012-01-09 16:59   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-10 17:52     ` Edgar E. Iglesias
  0 siblings, 0 replies; 147+ messages in thread
From: Edgar E. Iglesias @ 2012-01-10 17:52 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, peter.maydell, qemu-devel, Rob Herring, afaerber

On Mon, Jan 09, 2012 at 10:59:04AM -0600, Mark Langsdorf wrote:
> This adds very basic support for XG-mac ethernet core from Synopsis and
> others. Missing things include:
> 
> - statistics counters
> - WoL support
> - rx checksum offload
> - chained descriptors (only linear descriptor ring)
> - broadcast and multicast handling
> 
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
> Changes from v4
>         None
> Changes from v3
>         Added debug macro and cleaned up some debug code
>         Refitted all lines to fit within 80 columns
> Changes from v2
>         None
> Changes from v1
>         Reformated most lines to fit within 80 columns
>         Removed a bunch of unused variables in the state structures
>         Got rid of some camelcase structure names


Hi, this looks good to me, just one question. Do you really need
the c_phyaddr member?

Cheers

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
@ 2012-01-10 17:52     ` Peter Maydell
  2012-01-10 18:03     ` Andreas Färber
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 17:52 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> The current comment says that the arm_timers are restricted to between
> 32 KHz and 1 MHz, but sp804 TRM does not specify those limits.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-10 16:45   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-10 17:55     ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 17:55 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, Rob Herring, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer
  2012-01-10 15:35       ` Peter Maydell
@ 2012-01-10 18:00         ` Andreas Färber
  0 siblings, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-10 18:00 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

Am 10.01.2012 16:35, schrieb Peter Maydell:
> On 10 January 2012 12:45, Andreas Färber <afaerber@suse.de> wrote:
>> Am 09.01.2012 17:59, schrieb Mark Langsdorf:
>>> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
>>> ---
>>>  hw/arm_timer.c |    3 ---
>>>  1 files changed, 0 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/hw/arm_timer.c b/hw/arm_timer.c
>>> index 60e1c63..15d493f 100644
>>> --- a/hw/arm_timer.c
>>> +++ b/hw/arm_timer.c
>>> @@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
>>>
>>>      qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
>>>      sysbus_init_irq(dev, &s->irq);
>>> -    /* The timers are configurable between 32kHz and 1MHz
>>> -     * defaulting to 1MHz but overrideable as individual properties */
>>
>> Wasn't this comment added by your "arm: Set frequencies for arm_timer"?
>>
>> I didn't see a message indicating that series has been applied yet, so
>> you should probably fix the comment in the original patch instead of in
>> a follow-up patch. The point of adding the highbank emulation was to see
>> if the patches are sufficient, no?
> 
> It has been applied: commit 104a26a236.

The v5 various ARM fixes series doesn't say so, only 3/7 v9 has such a
notice. (Just like unthreaded patches a PULL and the original series do
drift apart.)

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  2012-01-10 17:52     ` Peter Maydell
@ 2012-01-10 18:03     ` Andreas Färber
  1 sibling, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-10 18:03 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, peter.maydell, qemu-devel

Am 10.01.2012 17:45, schrieb Mark Langsdorf:
> The current comment says that the arm_timers are restricted to between
> 32 KHz and 1 MHz, but sp804 TRM does not specify those limits.
> 
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Andreas Färber <afaerber@suse.de>

Thanks,
Andreas

> ---
> Changes from v1
> 	Clarified the commit message
> 
>  hw/arm_timer.c |    3 ---
>  1 files changed, 0 insertions(+), 3 deletions(-)
> 
> diff --git a/hw/arm_timer.c b/hw/arm_timer.c
> index 60e1c63..15d493f 100644
> --- a/hw/arm_timer.c
> +++ b/hw/arm_timer.c
> @@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
>  
>      qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
>      sysbus_init_irq(dev, &s->irq);
> -    /* The timers are configurable between 32kHz and 1MHz
> -     * defaulting to 1MHz but overrideable as individual properties */
>      s->timer[0] = arm_timer_init(s->freq0);
>      s->timer[1] = arm_timer_init(s->freq1);
> -
>      s->timer[0]->irq = qi[0];
>      s->timer[1]->irq = qi[1];
>      memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-10 18:04     ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 18:04 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, Rob Herring, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Adds support for Calxeda's Highbank SoC.
> +static int highbank_regs_init(SysBusDevice *dev)
> +{
> +    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
> +
> +    s->iomem = g_new(MemoryRegion, 1);
> +    s->regs[0x40] = 0x05F20121;
> +    s->regs[0x41] = 0x2;
> +    s->regs[0x42] = 0x05F30121;
> +    s->regs[0x43] = 0x05F40121;

Do these reset to these values as well? (ie should they be in a reset function?)

> +    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
> +                          0x1000);

You also need
  sysbus_init_mmio(dev, &s->iomem);
to expose the memory region.

> +    dev = qdev_create(NULL, "highbank-regs");
> +    qdev_init_nofail(dev);
> +    busdev = sysbus_from_qdev(dev);
> +    s = FROM_SYSBUS(highbank_regs_state, busdev);
> +    memory_region_add_subregion(sysmem, 0xfff3c000, s->iomem);

...then you can just use sysbus_mmio_map() rather than fishing
around in the internal state struct.

> +    highbank_binfo.ram_size = ram_size;
> +    highbank_binfo.kernel_filename = kernel_filename;
> +    highbank_binfo.kernel_cmdline = kernel_cmdline;
> +    highbank_binfo.initrd_filename = initrd_filename;
> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
> +    arm_load_kernel(env, &highbank_binfo);

Does your kernel really have the code at the start to cope with
the secondary CPUs so it doesn't need the code in arm_boot.c?
Most kernels don't (and so the board has to set .nb_cpus,
.loader_start (and once the Samsung series lands, the field
for where the secondary boot loader's "release cores now"
flag is).

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (5 preceding siblings ...)
  2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
@ 2012-01-10 18:18   ` Peter Maydell
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
                     ` (5 subsequent siblings)
  12 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-10 18:18 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, qemu-devel, afaerber

On 10 January 2012 16:45, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This patch series adds support for the Calxeda Highbank SoC.
> It depends on my previous patch series "various ARM fixes for
> Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
> Some of the patches are carried voer from "Various ARM fixes
> for Calxeda Highbank" and were reviewed but not accepted in
> that series.

PS: can you make sure all the patches in a series and the
cover letter have the same vN prefix? I think these ones
have got out of sync and it's a bit confusing.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (6 preceding siblings ...)
  2012-01-10 18:18   ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Peter Maydell
@ 2012-01-10 20:33   ` Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 1/6] Add xgmac ethernet model Mark Langsdorf
                       ` (5 more replies)
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (4 subsequent siblings)
  12 siblings, 6 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried voer from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in
that series.

The series patch number jumped from v3 to v7 to synchronize the
revision numbers of the individual patches.

 Makefile.target      |    2 +
 hw/a9mpcore.c        |   13 ++-
 hw/arm11mpcore.c     |   17 ++-
 hw/arm_gic.c         |   68 +++++----
 hw/arm_timer.c       |    3 -
 hw/armv7m_nvic.c     |   30 +++-
 hw/highbank.c        |  277 +++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   44 ++++++
 hw/realview_gic.c    |    7 +-
 hw/xgmac.c           |  421 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 +
 target-arm/machine.c |    2 +
 13 files changed, 844 insertions(+), 52 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 1/6] Add xgmac ethernet model
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v6
	Skipped
Changes from v5
	removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 18be624..5780a5f 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -340,6 +340,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..31594b5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  2012-01-11  4:12       ` Andreas Färber
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (3 subsequent siblings)
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf, edgar.iglesias

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretical number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v6
	Removed trailing whitespace
	armv7m_nvic uses num_irq properly
	Some comments changed
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   30 ++++++++++++++++++-----
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 48 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..befdc16 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,34 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
     vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64 external and 32 internal
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 3/6] ahci: add support for non-PCI based controllers
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v5, v6
	Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..a3bd4b8 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct sysbus_ahci_state {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} sysbus_ahci_state;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    sysbus_ahci_state *s = FROM_SYSBUS(sysbus_ahci_state, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(sysbus_ahci_state),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", sysbus_ahci_state, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v1, v2, v3, v4, v5, v6
	Skipped

 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..00458fc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1440,6 +1440,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1908,6 +1913,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 5/6] arm: SoC model for Calxeda Highbank
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
                       ` (3 preceding siblings ...)
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v3, v4, v5, v6
	Skipped
Changes from v2
	Created a reset function for highbank_regs
	Handled creation of regs i/o memory region in a sensible manner
	Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 5780a5f..56ca94d 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -339,6 +339,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..0e1fe66
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,277 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} highbank_regs_state;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, highbank_regs_state, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(highbank_regs_state),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v7 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
                       ` (4 preceding siblings ...)
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-10 20:33     ` Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-10 20:33 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf, edgar.iglesias

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v2, v3, v4, v5, v6
	Skipped
Changes from v1
        Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 60e1c63..15d493f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable
  2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-11  4:12       ` Andreas Färber
  2012-01-11 10:56         ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Andreas Färber @ 2012-01-11  4:12 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, peter.maydell, qemu-devel, edgar.iglesias

Am 10.01.2012 21:33, schrieb Mark Langsdorf:
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
> 
> Set the maximum theoretical number of GIC interrupts to 1020 and
> update the save/restore code to only use the appropriate number for
> each SoC.
> 
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
> Changes from v6
> 	Removed trailing whitespace
> 	armv7m_nvic uses num_irq properly
> 	Some comments changed
> Changes from v5
>         Clarify the commit message
>         Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
>         Makes num-irq to uint32_t in all cases
>         Clarify the error message
>         Clarify documentation on the num-irq qdev property use in all files
> Changes from v4
>         None
> Changes from v3
>         Increase maximum number of GIC interrupts to 1020
>         Remove SoC/implementation specific GIC_NIRQ #defs
>         Added properties code to arm11mp
>         Changed error handling for too many interrupts
>         Redid save/load handling
> Changes from v2
>         Skipped
> Changes from v1
>         Increase the number of a9mp interrupts to 192
>         Add a property defaulting to 96
>         Add a num_irq member in the gic state structure
>         Use the num_irq value as appropriate
>         Add num_irq argument to gic_init()
>         Add num_irq to various CPU calls to gic_init
> 
>  hw/a9mpcore.c     |   13 +++++++--
>  hw/arm11mpcore.c  |   17 ++++++++----
>  hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
>  hw/armv7m_nvic.c  |   30 ++++++++++++++++++-----
>  hw/realview_gic.c |    7 ++++-
>  5 files changed, 87 insertions(+), 48 deletions(-)

> diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
> index bf8c3c5..befdc16 100644
> --- a/hw/armv7m_nvic.c
> +++ b/hw/armv7m_nvic.c

> @@ -384,16 +382,34 @@ static int armv7m_nvic_init(SysBusDevice *dev)
>  {
>      nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
>  
> -    gic_init(&s->gic);
> +   /* note that for the M profile gic_init() takes the number of external
> +    * interrupt lines only.
> +    */
> +    gic_init(&s->gic, s->num_irq);
>      memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
>      s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);

>      vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);

This should probably be removed now that you register it through
sysbus_register_withprop() below.

>      return 0;
>  }
>  
> +static SysBusDeviceInfo armv7m_nvic_priv_info = {
> +    .init = armv7m_nvic_init,
> +    .qdev.name  = "armv7m_nvic",
> +    .qdev.size  = sizeof(nvic_state),
> +    .qdev.vmsd = &vmstate_nvic,

Minor nit: Assignment is inconsistent - add a space here?

> +    .qdev.props = (Property[]) {
> +        /* The ARM v7m may have anything from 0 to 496 external interrupt
> +         * IRQ lines. We default to 64 external and 32 internal
> +         * Other boards may differ and should set this property appropriately.
> +         */
> +        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
> +        DEFINE_PROP_END_OF_LIST(),
> +    }
> +};
> +
>  static void armv7m_nvic_register_devices(void)
>  {
> -    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
> +    sysbus_register_withprop(&armv7m_nvic_priv_info);
>  }
>  
>  device_init(armv7m_nvic_register_devices)

I'm still wondering whether the num-irq property calls for a version
bump somewhere. My thinking is no, since the SysBus device will not be
user-created from the command line and therefore effectively has the
same values as hardcoded before; but in that case we should assert this
by setting .qdev.no_user = 1.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11  4:12       ` Andreas Färber
@ 2012-01-11 10:56         ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 10:56 UTC (permalink / raw)
  To: Andreas Färber
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Mark Langsdorf

On 11 January 2012 04:12, Andreas Färber <afaerber@suse.de> wrote:
> Am 10.01.2012 21:33, schrieb Mark Langsdorf:
>>      vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
>
> This should probably be removed now that you register it through
> sysbus_register_withprop() below.

Oops, yes, missed that bit.

> I'm still wondering whether the num-irq property calls for a version
> bump somewhere. My thinking is no, since the SysBus device will not be
> user-created from the command line and therefore effectively has the
> same values as hardcoded before; but in that case we should assert this
> by setting .qdev.no_user = 1.

I agree that we should probably set no_user=1 on more of the ARM
internal devices than we currently do, but I think that's probably
a separate issue rather than one we should deal with in this patch.

Re version-bump: my thinking was that one isn't required because
the onus is on the user not to migrate between systems where
the devices have had different qdev property values set. So as long
as "no properties set to non default values" doesn't change then we're
ok whether the user put the device on the command line or not.
(In practice (a) any config with a user-created NVIC device is always
broken because there's no way for the user to wire it up properly,
and (b) another patch in this series is bumping the CPU state
version number so migration is going to fail anyhow.)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (7 preceding siblings ...)
  2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
@ 2012-01-11 15:26   ` Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
                       ` (5 more replies)
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (3 subsequent siblings)
  12 siblings, 6 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel; +Cc: i.mitsyanko, peter.maydell, afaerber, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried voer from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in 
that series.

 Makefile.target      |    1 +
 hw/a9mpcore.c        |   13 ++-
 hw/arm11mpcore.c     |   17 ++-
 hw/arm_gic.c         |   68 +++++++------
 hw/arm_timer.c       |    3 -
 hw/armv7m_nvic.c     |   31 ++++--
 hw/highbank.c        |  277 ++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   44 ++++++++
 hw/realview_gic.c    |    7 +-
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 ++
 target-arm/machine.c |    2 +
 12 files changed, 422 insertions(+), 53 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  2012-01-11 15:50       ` Peter Maydell
  2012-01-13 23:27       ` Peter Maydell
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                       ` (4 subsequent siblings)
  5 siblings, 2 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

This adds very basic support for XG-mac ethernet core from Synopsis and
others. Missing things include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v7
	None
Changes from v6
        Skipped
Changes from v5
        removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..9bc0248 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -343,6 +343,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..31594b5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  2012-01-11 15:40       ` Andreas Färber
  2012-01-11 15:54       ` Peter Maydell
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (3 subsequent siblings)
  5 siblings, 2 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf, edgar.iglesias

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretically number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v7
	Removed unnecessary vmstate_register
Changes from v6
        Removed trailing whitespace
        armv7m_nvic uses num_irq properly
        Some comments changed
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   31 ++++++++++++++++++------
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..4e5eafc 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,33 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd  = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64 external and 32 internal
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 3/6] ahci: add support for non-PCI based controllers
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7
	None
Changes from v5, v6
        Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..a3bd4b8 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct sysbus_ahci_state {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} sysbus_ahci_state;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    sysbus_ahci_state *s = FROM_SYSBUS(sysbus_ahci_state, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(sysbus_ahci_state),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", sysbus_ahci_state, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v7
	None
Changes from v1, v2, v3, v4, v5, v6
        Skipped

 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..00458fc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1440,6 +1440,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1908,6 +1913,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (3 preceding siblings ...)
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  2012-01-11 15:56       ` Peter Maydell
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Mark Langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v7
	None
Changes from v3, v4, v5, v6
        Skipped
Changes from v2
        Created a reset function for highbank_regs
        Handled creation of regs i/o memory region in a sensible manner
        Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 9bc0248..1c86522 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..0e1fe66
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,277 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} highbank_regs_state;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, highbank_regs_state, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(highbank_regs_state),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v8 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (4 preceding siblings ...)
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-11 15:26     ` Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 15:26 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, Mark Langsdorf, edgar.iglesias

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7
	None
Changes from v2, v3, v4, v5, v6
        Skipped
Changes from v1
        Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 60e1c63..15d493f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-11 15:40       ` Andreas Färber
  2012-01-11 15:54       ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: Andreas Färber @ 2012-01-11 15:40 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, peter.maydell, qemu-devel, edgar.iglesias

Am 11.01.2012 16:26, schrieb Mark Langsdorf:
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
> 
> Set the maximum theoretically number of GIC interrupts to 1020 and
> update the save/restore code to only use the appropriate number for
> each SoC.
> 
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Andreas Färber <afaerber@suse.de>

Andreas

> ---
> Changes from v7
> 	Removed unnecessary vmstate_register
> Changes from v6
>         Removed trailing whitespace
>         armv7m_nvic uses num_irq properly
>         Some comments changed
> Changes from v5
>         Clarify the commit message
>         Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
>         Makes num-irq to uint32_t in all cases
>         Clarify the error message
>         Clarify documentation on the num-irq qdev property use in all files
> Changes from v4
>         None
> Changes from v3
>         Increase maximum number of GIC interrupts to 1020
>         Remove SoC/implementation specific GIC_NIRQ #defs
>         Added properties code to arm11mp
>         Changed error handling for too many interrupts
>         Redid save/load handling
> Changes from v2
>         Skipped
> Changes from v1
>         Increase the number of a9mp interrupts to 192
>         Add a property defaulting to 96
>         Add a num_irq member in the gic state structure
>         Use the num_irq value as appropriate
>         Add num_irq argument to gic_init()
>         Add num_irq to various CPU calls to gic_init

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-11 15:50       ` Peter Maydell
  2012-01-13 23:27       ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 15:50 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 11 January 2012 15:26, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This adds very basic support for XG-mac ethernet core from Synopsis and
> others. Missing things include:
>
> - statistics counters
> - WoL support
> - rx checksum offload
> - chained descriptors (only linear descriptor ring)
> - broadcast and multicast handling
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
  2012-01-11 15:40       ` Andreas Färber
@ 2012-01-11 15:54       ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 15:54 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, edgar.iglesias, qemu-devel, afaerber

On 11 January 2012 15:26, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
> and create a configurable property for each defaulting to 96 and 64
> (respectively) so that device modelers can set the value appropriately
> for their SoC. Other ARM processors also set their maximum number of
> used IRQs appropriately.
>
> Set the maximum theoretically number of GIC interrupts to 1020 and

This patch has lost the typo fix ("theoretical") that was in the
last version. I wouldn't bother mentioning this if not for:

> +static SysBusDeviceInfo armv7m_nvic_priv_info = {
> +    .init = armv7m_nvic_init,
> +    .qdev.name  = "armv7m_nvic",
> +    .qdev.size  = sizeof(nvic_state),
> +    .qdev.vmsd  = &vmstate_nvic,
> +    .qdev.props = (Property[]) {
> +        /* The ARM v7m may have anything from 0 to 496 external interrupt
> +         * IRQ lines. We default to 64 external and 32 internal
> +         * Other boards may differ and should set this property appropriately.
> +         */

This is still wrong: from my comments on v5 of this patch:

This comment shouldn't talk about the 32 internal lines, as they are an
implementation detail of arm_gic.c, not architectural (unlike the A
profile GIC internal interrupt lines).

       /* The ARM v7m may have anything from 0 to 496 external interrupt
        * IRQ lines. We default to 64. Other boards may differ and should
        * set this property appropriately.
        */

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-11 15:56       ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 15:56 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 11 January 2012 15:26, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> From: Rob Herring <rob.herring@calxeda.com>
>
> Adds support for Calxeda's Highbank SoC.
>
> Signed-off-by: Rob Herring <rob.herring@calxeda.com>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>

Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (8 preceding siblings ...)
  2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-11 16:31   ` Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 1/6] Add xgmac ethernet model Mark Langsdorf
                       ` (6 more replies)
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                     ` (2 subsequent siblings)
  12 siblings, 7 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.
It depends on my previous patch series "various ARM fixes for
Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
Some of the patches are carried over from "Various ARM fixes
for Calxeda Highbank" and were reviewed but not accepted in 
that series.

 Makefile.target      |    2 +
 hw/a9mpcore.c        |   13 ++-
 hw/arm11mpcore.c     |   17 ++-
 hw/arm_gic.c         |   68 +++++----
 hw/arm_timer.c       |    3 -
 hw/armv7m_nvic.c     |   31 +++-
 hw/highbank.c        |  277 +++++++++++++++++++++++++++++++++
 hw/ide/ahci.c        |   44 ++++++
 hw/realview_gic.c    |    7 +-
 hw/xgmac.c           |  421 ++++++++++++++++++++++++++++++++++++++++++++++++++
 target-arm/cpu.h     |    3 +-
 target-arm/helper.c  |    9 +
 target-arm/machine.c |    2 +
 13 files changed, 844 insertions(+), 53 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 1/6] Add xgmac ethernet model
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                       ` (5 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

This adds very basic support for the xgmac ethernet core. Missing things
include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v7, v8
        None
Changes from v6
        Skipped
Changes from v5
        removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..9bc0248 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -343,6 +343,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..31594b5
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct rxtx_stats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} rxtx_stats;
+
+typedef struct xgmac_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct rxtx_stats stats;
+    uint32_t regs[R_MAX];
+} xgmac_state;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, rxtx_stats),
+        VMSTATE_UINT64(tx_bytes, rxtx_stats),
+        VMSTATE_UINT64(rx, rxtx_stats),
+        VMSTATE_UINT64(rx_bcast, rxtx_stats),
+        VMSTATE_UINT64(rx_mcast, rxtx_stats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, xgmac_state, 0, vmstate_rxtx_stats, rxtx_stats),
+        VMSTATE_UINT32_ARRAY(regs, xgmac_state, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct xgmac_state *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct xgmac_state *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct xgmac_state *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct xgmac_state *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct xgmac_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct xgmac_state *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct xgmac_state),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct xgmac_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-11 22:47       ` Peter Maydell
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (4 subsequent siblings)
  6 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretical number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v8
	Removed comments about armv7m_nvic's external IRQ lines
Changes from v7
        Removed unnecessary vmstate_register
Changes from v6
        Removed trailing whitespace
        armv7m_nvic uses num_irq properly
        Some comments changed
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   31 ++++++++++++++++++------
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..e5cf5bd 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,33 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64. Other boards may differ and should
+         * set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 3/6] ahci: add support for non-PCI based controllers
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
                       ` (3 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7, v8
        None
Changes from v5, v6
        Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 135d0ee..a3bd4b8 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(s, i);
     }
 }
+
+typedef struct sysbus_ahci_state {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} sysbus_ahci_state;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    sysbus_ahci_state *s = FROM_SYSBUS(sysbus_ahci_state, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(sysbus_ahci_state),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", sysbus_ahci_state, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 4/6] arm: Add dummy support for co-processor 15's secure config register
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
                       ` (2 subsequent siblings)
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v7, v8
        None
Changes from v1, v2, v3, v4, v5, v6
        Skipped

 target-arm/cpu.h     |    3 ++-
 target-arm/helper.c  |    9 +++++++++
 target-arm/machine.c |    2 ++
 3 files changed, 13 insertions(+), 1 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index 26b4981..42c53a7 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -116,6 +116,7 @@ typedef struct CPUARMState {
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c1_xscaleauxcr; /* XScale auxiliary control register.  */
+        uint32_t c1_scr; /* secure config register.  */
         uint32_t c2_base0; /* MMU translation table base 0.  */
         uint32_t c2_base1; /* MMU translation table base 1.  */
         uint32_t c2_control; /* MMU translation table base control.  */
@@ -452,7 +453,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define cpu_signal_handler cpu_arm_signal_handler
 #define cpu_list arm_cpu_list
 
-#define CPU_SAVE_VERSION 5
+#define CPU_SAVE_VERSION 6
 
 /* MMU modes definitions */
 #define MMU_MODE0_SUFFIX _kernel
diff --git a/target-arm/helper.c b/target-arm/helper.c
index fa42c64..00458fc 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -1440,6 +1440,11 @@ void HELPER(set_cp15)(CPUState *env, uint32_t insn, uint32_t val)
         }
         goto bad_reg;
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+                && op1 == 0 && crm == 1 && op2 == 0) {
+            env->cp15.c1_scr = val;
+            break;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
@@ -1908,6 +1913,10 @@ uint32_t HELPER(get_cp15)(CPUState *env, uint32_t insn)
             goto bad_reg;
         }
     case 1: /* System configuration.  */
+        if (arm_feature(env, ARM_FEATURE_V7)
+            && op1 == 0 && crm == 1 && op2 == 0) {
+            return env->cp15.c1_scr;
+        }
         if (arm_feature(env, ARM_FEATURE_OMAPCP))
             op2 = 0;
         switch (op2) {
diff --git a/target-arm/machine.c b/target-arm/machine.c
index 8984775..f66b8df 100644
--- a/target-arm/machine.c
+++ b/target-arm/machine.c
@@ -26,6 +26,7 @@ void cpu_save(QEMUFile *f, void *opaque)
     qemu_put_be32(f, env->cp15.c1_sys);
     qemu_put_be32(f, env->cp15.c1_coproc);
     qemu_put_be32(f, env->cp15.c1_xscaleauxcr);
+    qemu_put_be32(f, env->cp15.c1_scr);
     qemu_put_be32(f, env->cp15.c2_base0);
     qemu_put_be32(f, env->cp15.c2_base1);
     qemu_put_be32(f, env->cp15.c2_control);
@@ -143,6 +144,7 @@ int cpu_load(QEMUFile *f, void *opaque, int version_id)
     env->cp15.c1_sys = qemu_get_be32(f);
     env->cp15.c1_coproc = qemu_get_be32(f);
     env->cp15.c1_xscaleauxcr = qemu_get_be32(f);
+    env->cp15.c1_scr = qemu_get_be32(f);
     env->cp15.c2_base0 = qemu_get_be32(f);
     env->cp15.c2_base1 = qemu_get_be32(f);
     env->cp15.c2_control = qemu_get_be32(f);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (3 preceding siblings ...)
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-12 12:47       ` Mitsyanko Igor
                         ` (2 more replies)
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  2012-01-11 22:41     ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Peter Maydell
  6 siblings, 3 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v7, v8
        None
Changes from v3, v4, v5, v6
        Skipped
Changes from v2
        Created a reset function for highbank_regs
        Handled creation of regs i/o memory region in a sensible manner
        Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 9bc0248..1c86522 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..0e1fe66
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,277 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} highbank_regs_state;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, highbank_regs_state, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    highbank_regs_state *s = FROM_SYSBUS(highbank_regs_state, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(highbank_regs_state),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v9 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (4 preceding siblings ...)
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-11 16:31     ` Mark Langsdorf
  2012-01-11 22:41     ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Peter Maydell
  6 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-11 16:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7, v8
        None
Changes from v2, v3, v4, v5, v6
        Skipped
Changes from v1
        Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 60e1c63..15d493f 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -272,11 +272,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                       ` (5 preceding siblings ...)
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
@ 2012-01-11 22:41     ` Peter Maydell
  2012-01-13 12:14       ` Peter Maydell
  6 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 22:41 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Kevin Wolf, afaerber

On 11 January 2012 16:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This patch series adds support for the Calxeda Highbank SoC.
> It depends on my previous patch series "various ARM fixes for
> Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
> Some of the patches are carried over from "Various ARM fixes
> for Calxeda Highbank" and were reviewed but not accepted in
> that series.

So, are there in fact any patches from the "various ARM fixes for
Calxeda Highbank" series which this series depends on and which
haven't been committed to master? It looks to me as if all the
patches from that series either (a) were put into this one or
(b) were committed, but did I miss anything?

Does anybody object to my taking the AHCI patches along with this
series via arm-devs.next ? (other than patch v4 which goes via
target-arm.next)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-11 22:47       ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-11 22:47 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, edgar.iglesias, qemu-devel, afaerber

On 11 January 2012 16:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +static SysBusDeviceInfo armv7m_nvic_priv_info = {
> +    .init = armv7m_nvic_init,
> +    .qdev.name  = "armv7m_nvic",
> +    .qdev.size  = sizeof(nvic_state),
> +    .qdev.vmsd = &vmstate_nvic,

So Andreas pointed out the inconsistent spacing here and you
fixed it in v8 of this patch but it's back again in v9.

I mention this mostly because it indicates that you have
some problem with your workflow which is causing you to
lose fixes you make. In fact this is the second time that
I've seen a fix you've made in one round of the patch
series vanish again in a subsequent round. You need to
find out what is causing this and fix it :-)

You needn't bother resending this patch -- I'll just fix
the space when I apply it to the arm-devs.next queue.

On that basis:
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-12 12:47       ` Mitsyanko Igor
  2012-01-12 13:09         ` Andreas Färber
  2012-01-12 13:58       ` Mitsyanko Igor
  2012-01-12 17:51       ` Peter Maydell
  2 siblings, 1 reply; 147+ messages in thread
From: Mitsyanko Igor @ 2012-01-12 12:47 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: peter.maydell, afaerber, qemu-devel, Rob Herring, edgar.iglesias

On 01/11/2012 08:31 PM, Mark Langsdorf wrote:

>          Removed the automatic detection and resetting of ram_size. Image MUST
> be loaded with -m 4089 or it will crash

I don't know what is maintainer's politics on this, but as a user of 
your board I don't really like that I will have to remember this strange 
number when I launch Highbank emulation. Have you considered adding an 
automatic upper limitation to user-defined ram_size?


> +    sysram = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
> +    if (bios_name != NULL) {
> +        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> +        if (sysboot_filename != NULL) {
> +            uint32_t filesize = get_image_size(sysboot_filename);
> +            if (load_image_targphys("sysram.bin", 0xfff88000, filesize)<  0) {
> +                hw_error("Unable to load %s\n", bios_name);
> +            }

Probably should be
if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000)<  0) {
and then you don't need "uint32_t filesize" at all.

> +    dev = qdev_create(NULL, "l2x0");
> +    qdev_init_nofail(dev);
> +    busdev = sysbus_from_qdev(dev);
> +    sysbus_mmio_map(busdev, 0, 0xfff12000);

 > +    dev = qdev_create(NULL, "highbank-regs");
 > +    qdev_init_nofail(dev);
 > +    busdev = sysbus_from_qdev(dev);
 > +    sysbus_mmio_map(busdev, 0, 0xfff3c000);
 > +

You can use sysbus_create_simple() here (of course, if you didn't avoid 
it intentionally for some reason).



-- 
Mitsyanko Igor
ASWG, Moscow R&D center, Samsung Electronics
email: i.mitsyanko@samsung.com

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-12 12:47       ` Mitsyanko Igor
@ 2012-01-12 13:09         ` Andreas Färber
  2012-01-12 13:42           ` Mitsyanko Igor
  0 siblings, 1 reply; 147+ messages in thread
From: Andreas Färber @ 2012-01-12 13:09 UTC (permalink / raw)
  To: i.mitsyanko
  Cc: peter.maydell, Mark Langsdorf, qemu-devel, Rob Herring,
	Paul Brook, edgar.iglesias

Am 12.01.2012 13:47, schrieb Mitsyanko Igor:
> On 01/11/2012 08:31 PM, Mark Langsdorf wrote:
>> +    sysram = g_new(MemoryRegion, 1);
>> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
>> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
>> +    if (bios_name != NULL) {
>> +        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
>> bios_name);
>> +        if (sysboot_filename != NULL) {
>> +            uint32_t filesize = get_image_size(sysboot_filename);
>> +            if (load_image_targphys("sysram.bin", 0xfff88000,
>> filesize)<  0) {
>> +                hw_error("Unable to load %s\n", bios_name);
>> +            }
> 
> Probably should be
> if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000)<  0) {
> and then you don't need "uint32_t filesize" at all.

You need it either way; if you use 0x8000 there, you need to check if
filesize is actually 0x8000. Doing it this way allows to load smaller
files; a check for larger files should be added though. Thanks for
making me aware.

>> +    dev = qdev_create(NULL, "l2x0");
>> +    qdev_init_nofail(dev);
>> +    busdev = sysbus_from_qdev(dev);
>> +    sysbus_mmio_map(busdev, 0, 0xfff12000);
> 
>> +    dev = qdev_create(NULL, "highbank-regs");
>> +    qdev_init_nofail(dev);
>> +    busdev = sysbus_from_qdev(dev);
>> +    sysbus_mmio_map(busdev, 0, 0xfff3c000);
>> +
> 
> You can use sysbus_create_simple() here (of course, if you didn't avoid
> it intentionally for some reason).

Depends on how you read this:

/* Legacy helper function for creating devices.  */
DeviceState *sysbus_create_varargs(const char *name,
                                 target_phys_addr_t addr, ...);
DeviceState *sysbus_try_create_varargs(const char *name,
                                       target_phys_addr_t addr, ...);
static inline DeviceState *sysbus_create_simple(const char *name,
                                              target_phys_addr_t addr,
                                              qemu_irq irq)
{
    return sysbus_create_varargs(name, addr, irq, NULL);
}

I interpret it as sysbus_create_simple() using deprecated
sysbus_create_varargs() and therefore being deprecated, too.

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-12 13:09         ` Andreas Färber
@ 2012-01-12 13:42           ` Mitsyanko Igor
  2012-01-12 13:46             ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mitsyanko Igor @ 2012-01-12 13:42 UTC (permalink / raw)
  To: Andreas Färber
  Cc: peter.maydell, Mark Langsdorf, qemu-devel, Rob Herring,
	Paul Brook, edgar.iglesias

On 01/12/2012 05:09 PM, Andreas Färber wrote:
> Am 12.01.2012 13:47, schrieb Mitsyanko Igor:
>> On 01/11/2012 08:31 PM, Mark Langsdorf wrote:
>>> +    sysram = g_new(MemoryRegion, 1);
>>> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
>>> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
>>> +    if (bios_name != NULL) {
>>> +        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS,
>>> bios_name);
>>> +        if (sysboot_filename != NULL) {
>>> +            uint32_t filesize = get_image_size(sysboot_filename);
>>> +            if (load_image_targphys("sysram.bin", 0xfff88000,
>>> filesize)<   0) {
>>> +                hw_error("Unable to load %s\n", bios_name);
>>> +            }
>>
>> Probably should be
>> if (load_image_targphys(sysboot_filename, 0xfff88000, 0x8000)<   0) {
>> and then you don't need "uint32_t filesize" at all.
>
> You need it either way; if you use 0x8000 there, you need to check if
> filesize is actually 0x8000. Doing it this way allows to load smaller
> files; a check for larger files should be added though. Thanks for
> making me aware.
>

Why do we need to check if filesize is 0x8000? load_image_targphys() 
will call get_image_size() and check that size is not more then 0x8000 
automatically, so it would operate on any file with size<=0x8000 and 
return error if size>0x8000, just like we need it to. Well, OK, I know 
load_image_targphys() is currently broken and doesn't use max_sz 
argument, but recently I saw a patch in mailing list which fixes this.

>>> +    dev = qdev_create(NULL, "l2x0");
>>> +    qdev_init_nofail(dev);
>>> +    busdev = sysbus_from_qdev(dev);
>>> +    sysbus_mmio_map(busdev, 0, 0xfff12000);
>>
>>> +    dev = qdev_create(NULL, "highbank-regs");
>>> +    qdev_init_nofail(dev);
>>> +    busdev = sysbus_from_qdev(dev);
>>> +    sysbus_mmio_map(busdev, 0, 0xfff3c000);
>>> +
>>
>> You can use sysbus_create_simple() here (of course, if you didn't avoid
>> it intentionally for some reason).
>
> Depends on how you read this:
>
> /* Legacy helper function for creating devices.  */
> DeviceState *sysbus_create_varargs(const char *name,
>                                   target_phys_addr_t addr, ...);
> DeviceState *sysbus_try_create_varargs(const char *name,
>                                         target_phys_addr_t addr, ...);
> static inline DeviceState *sysbus_create_simple(const char *name,
>                                                target_phys_addr_t addr,
>                                                qemu_irq irq)
> {
>      return sysbus_create_varargs(name, addr, irq, NULL);
> }
>
> I interpret it as sysbus_create_simple() using deprecated
> sysbus_create_varargs() and therefore being deprecated, too.
>
> Andreas
>

Sorry, never paid attention that these functions are deprecated.
-- 
Mitsyanko Igor
ASWG, Moscow R&D center, Samsung Electronics
email: i.mitsyanko@samsung.com

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-12 13:42           ` Mitsyanko Igor
@ 2012-01-12 13:46             ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-12 13:46 UTC (permalink / raw)
  To: i.mitsyanko
  Cc: Mark Langsdorf, qemu-devel, Rob Herring, Paul Brook,
	edgar.iglesias, Andreas Färber

On 12 January 2012 13:42, Mitsyanko Igor <i.mitsyanko@samsung.com> wrote:
> On 01/12/2012 05:09 PM, Andreas Färber wrote:
>> Depends on how you read this:
>>
>> /* Legacy helper function for creating devices.  */
>> DeviceState *sysbus_create_varargs(const char *name,
>>                                  target_phys_addr_t addr, ...);
>> DeviceState *sysbus_try_create_varargs(const char *name,
>>                                        target_phys_addr_t addr, ...);
>> static inline DeviceState *sysbus_create_simple(const char *name,
>>                                               target_phys_addr_t addr,
>>                                               qemu_irq irq)
>> {
>>     return sysbus_create_varargs(name, addr, irq, NULL);
>> }
>>
>> I interpret it as sysbus_create_simple() using deprecated
>> sysbus_create_varargs() and therefore being deprecated, too.

> Sorry, never paid attention that these functions are deprecated.

Personally I don't think we should deprecate either
sysbus_create_simple() or sysbus_create_varargs() until QOM has
advanced to the point where we can throw out sysbus devices altogether.
These functions are a straightforward way of instantiating simple
sysbus devices, they're widely used, and I don't see anything
particularly wrong with them.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-12 12:47       ` Mitsyanko Igor
@ 2012-01-12 13:58       ` Mitsyanko Igor
  2012-01-12 17:51       ` Peter Maydell
  2 siblings, 0 replies; 147+ messages in thread
From: Mitsyanko Igor @ 2012-01-12 13:58 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: peter.maydell, afaerber, qemu-devel, Rob Herring, edgar.iglesias

On 01/11/2012 08:31 PM, Mark Langsdorf wrote:
> +    sysram = g_new(MemoryRegion, 1);
> +    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
> +    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
> +    if (bios_name != NULL) {
> +        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
> +        if (sysboot_filename != NULL) {
> +            uint32_t filesize = get_image_size(sysboot_filename);
> +            if (load_image_targphys("sysram.bin", 0xfff88000, filesize)<  0) {
> +                hw_error("Unable to load %s\n", bios_name);
> +            }
> +        } else {
> +           hw_error("Unable to find %s\n", bios_name);
> +        }
> +    }

I'm sorry, I forgot to ask in my previous message, how does control is 
passed to uboot image at 0xfff88000 address? Shouldn't highbank_binfo be 
modified somehow if bios_name supplied?


-- 
Mitsyanko Igor
ASWG, Moscow R&D center, Samsung Electronics
email: i.mitsyanko@samsung.com

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank
  2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-12 12:47       ` Mitsyanko Igor
  2012-01-12 13:58       ` Mitsyanko Igor
@ 2012-01-12 17:51       ` Peter Maydell
  2 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-12 17:51 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 11 January 2012 16:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +    highbank_binfo.ram_size = ram_size;
> +    highbank_binfo.kernel_filename = kernel_filename;
> +    highbank_binfo.kernel_cmdline = kernel_cmdline;
> +    highbank_binfo.initrd_filename = initrd_filename;
> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
> +    highbank_binfo.nb_cpus = smp_cpus;
> +    highbank_binfo.loader_start = 0;
> +    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
> +    arm_load_kernel(env, &highbank_binfo);

So at the moment this will use address 0x10000030 as the location
that the bootloader for secondary CPUs polls to find out whether
it can release the secondary CPUs. This is right for realview
and vexpress, because it's the sysreg SYS_FLAGS (implemented in
arm_sysctl.c). Is this really the right location to poll for
Highbank?

(There's a patch in the Samsung Exynos4 patch series which
addresses this by allowing boards to specify a polling location.
So I'm wondering what that location ought to be for Highbank...)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-11 22:41     ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Peter Maydell
@ 2012-01-13 12:14       ` Peter Maydell
  2012-01-13 14:15         ` Andreas Färber
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-13 12:14 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Kevin Wolf, afaerber

On 11 January 2012 22:41, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 11 January 2012 16:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> This patch series adds support for the Calxeda Highbank SoC.
>> It depends on my previous patch series "various ARM fixes for
>> Calxeda Highbank" and "ahci: convert ahci_reset to use AHCIState".
>> Some of the patches are carried over from "Various ARM fixes
>> for Calxeda Highbank" and were reviewed but not accepted in
>> that series.
>
> So, are there in fact any patches from the "various ARM fixes for
> Calxeda Highbank" series which this series depends on and which
> haven't been committed to master? It looks to me as if all the
> patches from that series either (a) were put into this one or
> (b) were committed, but did I miss anything?

Mark: ping? I'm just waiting for an answer to this and also to
the question about the secondary boot protocol (see my email
replying to patch 5/5) before I take these into arm-devs.next...

> Does anybody object to my taking the AHCI patches along with this
> series via arm-devs.next ? (other than patch v4 which goes via
> target-arm.next)

[I got an Acked-by: from Kevin over irc regarding these and will do this.]

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-13 12:14       ` Peter Maydell
@ 2012-01-13 14:15         ` Andreas Färber
  2012-01-13 14:18           ` Alexander Graf
  0 siblings, 1 reply; 147+ messages in thread
From: Andreas Färber @ 2012-01-13 14:15 UTC (permalink / raw)
  To: Peter Maydell, Kevin Wolf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Mark Langsdorf, Alexander Graf

Am 13.01.2012 13:14, schrieb Peter Maydell:
> On 11 January 2012 22:41, Peter Maydell <peter.maydell@linaro.org> wrote:
>> Does anybody object to my taking the AHCI patches along with this
>> series via arm-devs.next ? (other than patch v4 which goes via
>> target-arm.next)
> 
> [I got an Acked-by: from Kevin over irc regarding these and will do this.]

FWIW I don't object. Either the maintainership of AHCI doesn't fall
under "IDE" or Kevin is busy - possibly both?

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-13 14:15         ` Andreas Färber
@ 2012-01-13 14:18           ` Alexander Graf
  2012-01-13 14:31             ` Andreas Färber
  0 siblings, 1 reply; 147+ messages in thread
From: Alexander Graf @ 2012-01-13 14:18 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Kevin Wolf, Peter Maydell, Mark Langsdorf, i.mitsyanko,
	qemu-devel, edgar.iglesias


On 13.01.2012, at 15:15, Andreas Färber wrote:

> Am 13.01.2012 13:14, schrieb Peter Maydell:
>> On 11 January 2012 22:41, Peter Maydell <peter.maydell@linaro.org> wrote:
>>> Does anybody object to my taking the AHCI patches along with this
>>> series via arm-devs.next ? (other than patch v4 which goes via
>>> target-arm.next)
>> 
>> [I got an Acked-by: from Kevin over irc regarding these and will do this.]
> 
> FWIW I don't object. Either the maintainership of AHCI doesn't fall
> under "IDE" or Kevin is busy - possibly both?

It falls under IDE and Kevin acked them :)


Alex

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-13 14:18           ` Alexander Graf
@ 2012-01-13 14:31             ` Andreas Färber
  2012-01-13 14:35               ` Alexander Graf
  0 siblings, 1 reply; 147+ messages in thread
From: Andreas Färber @ 2012-01-13 14:31 UTC (permalink / raw)
  To: Alexander Graf
  Cc: Kevin Wolf, Peter Maydell, Mark Langsdorf, Juan Quintela,
	i.mitsyanko, qemu-devel, edgar.iglesias

Am 13.01.2012 15:18, schrieb Alexander Graf:
> 
> On 13.01.2012, at 15:15, Andreas Färber wrote:
> 
>> Am 13.01.2012 13:14, schrieb Peter Maydell:
>>> On 11 January 2012 22:41, Peter Maydell <peter.maydell@linaro.org> wrote:
>>>> Does anybody object to my taking the AHCI patches along with this
>>>> series via arm-devs.next ? (other than patch v4 which goes via
>>>> target-arm.next)
>>>
>>> [I got an Acked-by: from Kevin over irc regarding these and will do this.]
>>
>> FWIW I don't object. Either the maintainership of AHCI doesn't fall
>> under "IDE" or Kevin is busy - possibly both?
> 
> It falls under IDE and Kevin acked them :)

My RFC didn't get any review or testing yet, not from you either. ;(

(But that is foremost waiting for Juan to comment on the VMState size
issue the Samsung guys and me ran into. And it's in no way urgent for me
currently or I would've ping'ed it already.)

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC
  2012-01-13 14:31             ` Andreas Färber
@ 2012-01-13 14:35               ` Alexander Graf
  0 siblings, 0 replies; 147+ messages in thread
From: Alexander Graf @ 2012-01-13 14:35 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Kevin Wolf, Peter Maydell, Mark Langsdorf, Juan Quintela,
	i.mitsyanko, qemu-devel, edgar.iglesias


On 13.01.2012, at 15:31, Andreas Färber wrote:

> Am 13.01.2012 15:18, schrieb Alexander Graf:
>> 
>> On 13.01.2012, at 15:15, Andreas Färber wrote:
>> 
>>> Am 13.01.2012 13:14, schrieb Peter Maydell:
>>>> On 11 January 2012 22:41, Peter Maydell <peter.maydell@linaro.org> wrote:
>>>>> Does anybody object to my taking the AHCI patches along with this
>>>>> series via arm-devs.next ? (other than patch v4 which goes via
>>>>> target-arm.next)
>>>> 
>>>> [I got an Acked-by: from Kevin over irc regarding these and will do this.]
>>> 
>>> FWIW I don't object. Either the maintainership of AHCI doesn't fall
>>> under "IDE" or Kevin is busy - possibly both?
>> 
>> It falls under IDE and Kevin acked them :)
> 
> My RFC didn't get any review or testing yet, not from you either. ;(

I'm sure he's still busy catching up on his email. He only got back this week :)

> (But that is foremost waiting for Juan to comment on the VMState size
> issue the Samsung guys and me ran into. And it's in no way urgent for me
> currently or I would've ping'ed it already.)

Yup, that's the one big thing I would like to see addressed first too.


Alex

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model
  2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-11 15:50       ` Peter Maydell
@ 2012-01-13 23:27       ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-13 23:27 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: Anthony Liguori, i.mitsyanko, qemu-devel, Rob Herring,
	edgar.iglesias, afaerber

On 11 January 2012 15:26, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> This adds very basic support for XG-mac ethernet core from Synopsis and
> others.

> +typedef struct rxtx_stats {
> +    uint64_t rx_bytes;
> +    uint64_t tx_bytes;
> +
> +    uint64_t rx;
> +    uint64_t rx_bcast;
> +    uint64_t rx_mcast;
> +} rxtx_stats;

Anthony pointed out to me on IRC today the bit of CODING_STYLE that
mandates CamelCase for struct typedef names.

Sorry to bring up coding style issues at this point in the review
process, but can I get you to go through and camelcase the struct
typenames in this patch series?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (9 preceding siblings ...)
  2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
@ 2012-01-17 13:50   ` Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 1/5] Add xgmac ethernet model Mark Langsdorf
                       ` (4 more replies)
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  12 siblings, 5 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 1/5] Add xgmac ethernet model
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
@ 2012-01-17 13:50     ` Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

This adds very basic support for the xgmac ethernet core. Missing things
include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v10
	Make typedef struct names into CamelCase
Changes from v7, v8
        None
Changes from v6
        Skipped
Changes from v5
        removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..9bc0248 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -343,6 +343,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..be63a7d
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct RxTxStats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} RxTxStats;
+
+typedef struct XgmacState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct RxTxStats stats;
+    uint32_t regs[R_MAX];
+} XgmacState;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, RxTxStats),
+        VMSTATE_UINT64(tx_bytes, RxTxStats),
+        VMSTATE_UINT64(rx, RxTxStats),
+        VMSTATE_UINT64(rx_bcast, RxTxStats),
+        VMSTATE_UINT64(rx_mcast, RxTxStats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, XgmacState, 0, vmstate_rxtx_stats, RxTxStats),
+        VMSTATE_UINT32_ARRAY(regs, XgmacState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct XgmacState *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct XgmacState *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct XgmacState *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct XgmacState *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct XgmacState),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct XgmacState, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.7.5

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 2/5] arm: make the number of GIC interrupts configurable
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 1/5] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-17 13:50     ` Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretical number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v9
        None
Changes from v8
        Removed comments about armv7m_nvic's external IRQ lines
Changes from v7
        Removed unnecessary vmstate_register
Changes from v6
        Removed trailing whitespace
        armv7m_nvic uses num_irq properly
        Some comments changed
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   31 ++++++++++++++++++------
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..28f36ba 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,33 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd  = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64. Other boards may differ and should
+         * set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.7.5

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 3/5] ahci: add support for non-PCI based controllers
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 1/5] Add xgmac ethernet model Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-17 13:50     ` Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 5/5] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  4 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v9
	Changed typedef struct names to CamelCase
Changes from v7, v8
        None
Changes from v5, v6
        Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0af201d..0309dd6 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(&d->ahci, i);
     }
 }
+
+typedef struct SysbusAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} SysbusAHCIState;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(SysbusAHCIState),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.7.5

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-17 13:50     ` Mark Langsdorf
  2012-01-17 15:13       ` Peter Maydell
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 5/5] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  4 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v9
	Made typedef struct names in CamelCase
Changes from v7, v8
        None
Changes from v3, v4, v5, v6
        Skipped
Changes from v2
        Created a reset function for highbank_regs
        Handled creation of regs i/o memory region in a sensible manner
        Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  277 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 278 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 9bc0248..1c86522 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..d13e5c3
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,277 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(HighbankRegsState),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff10000);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
+    arm_load_kernel(env, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.7.5

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v10 5/5] arm: Remove incorrect comment in arm_timer
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (3 preceding siblings ...)
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-17 13:50     ` Mark Langsdorf
  4 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-17 13:50 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7, v8, v9
        None
Changes from v2, v3, v4, v5, v6
        Skipped
Changes from v1
        Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 1902f1a..ead2535 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -273,11 +273,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.7.5

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-17 15:13       ` Peter Maydell
  2012-01-18 14:35         ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-17 15:13 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 17 January 2012 13:50, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +    highbank_binfo.ram_size = ram_size;
> +    highbank_binfo.kernel_filename = kernel_filename;
> +    highbank_binfo.kernel_cmdline = kernel_cmdline;
> +    highbank_binfo.initrd_filename = initrd_filename;
> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
> +    highbank_binfo.nb_cpus = smp_cpus;
> +    highbank_binfo.loader_start = 0;
> +    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
> +    arm_load_kernel(env, &highbank_binfo);

Unfortunately for you Evgeny's patch to arm_boot.c has been
committed to master (commit 078758d0) which means you need
to update this to specify a value for highbank_binfo.smp_bootreg_addr.

The bad news is that if I'm reading this right:
http://lxr.linux.no/#linux+v3.2.1/arch/arm/mach-highbank/highbank.c#L71

that value differs depending on which CPU is to be brought out
of the pen, which implies that you probably need to implement
your own secondary smp boot code.

Incidentally I'm surprised this worked for you at all -- before
Evgeny's patch the secondary bootloader code in arm_boot.c would
have been polling 0x10000030, which the highbank kernel code
doesn't ever change, so I don't see how you got the secondary
cores into the kernel when using -kernel...

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-17 15:13       ` Peter Maydell
@ 2012-01-18 14:35         ` Mark Langsdorf
  2012-01-18 14:53           ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-18 14:35 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/17/2012 09:13 AM, Peter Maydell wrote:
> On 17 January 2012 13:50, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> +    highbank_binfo.ram_size = ram_size;
>> +    highbank_binfo.kernel_filename = kernel_filename;
>> +    highbank_binfo.kernel_cmdline = kernel_cmdline;
>> +    highbank_binfo.initrd_filename = initrd_filename;
>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>> +    highbank_binfo.nb_cpus = smp_cpus;
>> +    highbank_binfo.loader_start = 0;
>> +    highbank_binfo.smp_loader_start = SMP_BOOT_ADDR;
>> +    arm_load_kernel(env, &highbank_binfo);
> 
> Unfortunately for you Evgeny's patch to arm_boot.c has been
> committed to master (commit 078758d0) which means you need
> to update this to specify a value for highbank_binfo.smp_bootreg_addr.
> 
> Incidentally I'm surprised this worked for you at all -- before
> Evgeny's patch the secondary bootloader code in arm_boot.c would
> have been polling 0x10000030, which the highbank kernel code
> doesn't ever change, so I don't see how you got the secondary
> cores into the kernel when using -kernel...

I think I was undertesting.

I can set the smp_loader code so that I can boot 2 cpus
and verify their existence in /proc/cpuinfo, but I can't
get 3 cpus to boot at all, no matter how I hack the existing
arm_boot code.

Is there a good example of how to write secondary smp boot
code other than arm_boot.c? Should I just expect to pull
most of arm_boot.c into highbank and adjust from there? I
don't want to duplicate code like that, but I need more
flexibility than I can easily add to arm_boot.c.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 14:35         ` Mark Langsdorf
@ 2012-01-18 14:53           ` Peter Maydell
  2012-01-18 15:04             ` Mark Langsdorf
  2012-01-18 19:06             ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
  0 siblings, 2 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-18 14:53 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 18 January 2012 14:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> I can set the smp_loader code so that I can boot 2 cpus
> and verify their existence in /proc/cpuinfo, but I can't
> get 3 cpus to boot at all, no matter how I hack the existing
> arm_boot code.

Right, multiple secondary cores requires multiple addresses
to be polled which we don't support in arm_boot.c at the moment.

> Is there a good example of how to write secondary smp boot
> code other than arm_boot.c? Should I just expect to pull
> most of arm_boot.c into highbank and adjust from there? I
> don't want to duplicate code like that, but I need more
> flexibility than I can easily add to arm_boot.c.

Nope, I'm afraid you're the first one to run into this.
arm_boot.c started off as just implementing the realview
secondary boot protocol, and exynos4 and vexpress have
been close enough to piggyback on it. So highbank is the
first board that's different enough to need its own code.

A big chunk of arm_boot.c is the primary CPU boot code,
which should be standard for all arm platforms, so that
shouldn't need to change. So we just need a reasonably
clean solution for a platform to provide its own secondary
boot code. I'm vaguely thinking about providing a hook
function for 'write secondary boot code' and one for
'post-cpu-reset hook for secondary cpus', which would go
in the "if (info->nb_cpus > 1) {...}" condition in
arm_load_kernel() and in the else-clause of "if (env ==
first_cpu) in do_cpu_reset().

Can you try something along those lines?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 14:53           ` Peter Maydell
@ 2012-01-18 15:04             ` Mark Langsdorf
  2012-01-18 15:11               ` Peter Maydell
  2012-01-18 15:50               ` [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
  2012-01-18 19:06             ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
  1 sibling, 2 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-18 15:04 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/18/2012 08:53 AM, Peter Maydell wrote:
> On 18 January 2012 14:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:

>> Is there a good example of how to write secondary smp boot
>> code other than arm_boot.c? Should I just expect to pull
>> most of arm_boot.c into highbank and adjust from there? I
>> don't want to duplicate code like that, but I need more
>> flexibility than I can easily add to arm_boot.c.
> 
> Nope, I'm afraid you're the first one to run into this.
> arm_boot.c started off as just implementing the realview
> secondary boot protocol, and exynos4 and vexpress have
> been close enough to piggyback on it. So highbank is the
> first board that's different enough to need its own code.
> 
> A big chunk of arm_boot.c is the primary CPU boot code,
> which should be standard for all arm platforms, so that
> shouldn't need to change. So we just need a reasonably
> clean solution for a platform to provide its own secondary
> boot code. I'm vaguely thinking about providing a hook
> function for 'write secondary boot code' and one for
> 'post-cpu-reset hook for secondary cpus', which would go
> in the "if (info->nb_cpus > 1) {...}" condition in
> arm_load_kernel() and in the else-clause of "if (env ==
> first_cpu) in do_cpu_reset().
> 
> Can you try something along those lines?

I think so. I was worried about accessing some of the
arm_boot static variables but it doesn't look like
I'll need to do that.

I'll do a quick refactor RFC of arm_boot.c and then
get into the gory bits of getting something to work
for Highbank.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 15:04             ` Mark Langsdorf
@ 2012-01-18 15:11               ` Peter Maydell
  2012-01-18 15:50               ` [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-18 15:11 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 18 January 2012 15:04, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/18/2012 08:53 AM, Peter Maydell wrote:
>> Can you try something along those lines?
>
> I think so. I was worried about accessing some of the
> arm_boot static variables but it doesn't look like
> I'll need to do that.
>
> I'll do a quick refactor RFC of arm_boot.c and then
> get into the gory bits of getting something to work
> for Highbank.

Cool, thanks. NB that I have this patch
http://patchwork.ozlabs.org/patch/135991/
in the vexpress-a15 series which also touches arm_boot.c,
but it's not particularly invasive so it should not
be too hard to reconcile with your changes.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c
  2012-01-18 15:04             ` Mark Langsdorf
  2012-01-18 15:11               ` Peter Maydell
@ 2012-01-18 15:50               ` Mark Langsdorf
  2012-01-18 16:23                 ` Peter Maydell
  1 sibling, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-18 15:50 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, afaerber, Mark Langsdorf

Create two functions, write_secondary_boot() and secondary_cpu_reset_hook(),
to allow platforms more control of how secondary CPUs are brought up. The
new functions default to NULL and aren't called unless they are populated
so there are no changes to existing platform models.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
I'll add this to the Highbank patch series but I wanted to throw it out
now to make sure the general structure was good.

 hw/arm-misc.h |    4 ++++
 hw/arm_boot.c |    6 +++++-
 2 files changed, 9 insertions(+), 1 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b..866f848 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -36,6 +36,10 @@ struct arm_boot_info {
     int nb_cpus;
     int board_id;
     int (*atag_board)(const struct arm_boot_info *info, void *p);
+    void (*write_secondary_boot)(CPUState *env,
+                                 const struct arm_boot_info *info);
+    void (*secondary_cpu_reset_hook)(CPUState *env,
+                                     const struct arm_boot_info *info);
     /* Used internally by arm_boot.c */
     int is_linux;
     target_phys_addr_t initrd_size;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8..78626bb 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -196,6 +196,8 @@ static void do_cpu_reset(void *opaque)
                     set_kernel_args(info, info->initrd_size,
                                     info->loader_start);
                 }
+            } else if (info->secondary_cpu_reset_hook) {
+                info->secondary_cpu_reset_hook(env, info);
             } else {
                 stl_phys_notdirty(info->smp_bootreg_addr, 0);
                 env->regs[15] = info->smp_loader_start;
@@ -272,7 +274,9 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         }
         rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
                            info->loader_start);
-        if (info->nb_cpus > 1) {
+        if ((info->nb_cpus > 1) && (info->write_secondary_boot)) {
+            info->write_secondary_boot(env, info);
+        } else if (info->nb_cpus > 1) {
             smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
             smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
             for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c
  2012-01-18 15:50               ` [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
@ 2012-01-18 16:23                 ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-18 16:23 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel, afaerber

On 18 January 2012 15:50, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Create two functions, write_secondary_boot() and secondary_cpu_reset_hook(),
> to allow platforms more control of how secondary CPUs are brought up. The
> new functions default to NULL and aren't called unless they are populated
> so there are no changes to existing platform models.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
> I'll add this to the Highbank patch series but I wanted to throw it out
> now to make sure the general structure was good.

Looks OK. I'm tempted to suggest that we should pull the default
code out into separate functions and then at the top of arm_load_kernel()
do
  if (!info->write_secondary_boot) {
      info->write_secondary_boot = default_write_secondary_boot;
  }
  if (!info->secondary_cpu_reset_hook) {
      info->secondary_cpu_reset_hook = default_secondary_cpu_reset_hook;
  }

Then we can put all the secondary-cpu-related code that is in arm_boot.c
in one place in the file.

Probably also nice to add a comment about which fields in arm_boot_info
are only required if you're using the default write_secondary_boot.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 14:53           ` Peter Maydell
  2012-01-18 15:04             ` Mark Langsdorf
@ 2012-01-18 19:06             ` Mark Langsdorf
  2012-01-18 19:26               ` Peter Maydell
  1 sibling, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-18 19:06 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/18/2012 08:53 AM, Peter Maydell wrote:
> On 18 January 2012 14:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> I can set the smp_loader code so that I can boot 2 cpus
>> and verify their existence in /proc/cpuinfo, but I can't
>> get 3 cpus to boot at all, no matter how I hack the existing
>> arm_boot code.
> 
> Right, multiple secondary cores requires multiple addresses
> to be polled which we don't support in arm_boot.c at the moment.

How would multiple polling supposed to work? I've tried changing
http://lxr.linux.no/#linux+v3.2.1/arch/arm/mach-highbank/highbank.c#L71
to point to a fixed address (0x50), and the boot loader still fails
if there are 2 or more secondary CPUs.

I've figured out that do_cpu_reset() is only called once, even
though that seems a bit strange to me. I've tried the following
in my local secondary_hook call:

    switch (info->nb_cpus) {
    case 4:
        stl_phys_notdirty(0x70, 0);
    case 3:
        stl_phys_notdirty(0x60, 0);
    case 2:
        stl_phys_notdirty(0x50, 0);
        env->regs[15] = 0x100;
        break;
    }

which works fine with 2 cpus, but fails to boot both
secondary cpus if there are 3 total cpus.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 19:06             ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-18 19:26               ` Peter Maydell
  2012-01-18 19:33                 ` Peter Maydell
  2012-01-18 21:32                 ` Mark Langsdorf
  0 siblings, 2 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-18 19:26 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 18 January 2012 19:06, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/18/2012 08:53 AM, Peter Maydell wrote:
>> On 18 January 2012 14:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>> I can set the smp_loader code so that I can boot 2 cpus
>>> and verify their existence in /proc/cpuinfo, but I can't
>>> get 3 cpus to boot at all, no matter how I hack the existing
>>> arm_boot code.
>>
>> Right, multiple secondary cores requires multiple addresses
>> to be polled which we don't support in arm_boot.c at the moment.
>
> How would multiple polling supposed to work?

You need several separate bits of code, to put each secondary
core in a different loop polling a different address.
(If you have access to your own bootloader sources you should
be able to see how it does it :-))

> I've tried changing
> http://lxr.linux.no/#linux+v3.2.1/arch/arm/mach-highbank/highbank.c#L71
> to point to a fixed address (0x50), and the boot loader still fails
> if there are 2 or more secondary CPUs.

Yeah, that's insufficient, because the highbank kernel doesn't
have an equivalent of this bit of code for versatile et al:
http://lxr.linux.no/#linux+v3.2.1/arch/arm/plat-versatile/headsmp.S
...which puts all the cores back into yet another pen so they
can be released to the main kernel secondary_startup entry
point singly as they are required. On versatile when the flags
register is written, every secondary CPU comes out of the bootloader
pen simultaneously, so we have to catch them all again like this.
Highbank, as far as I can tell, has the boot loader provide a
mechanism for letting the kernel release just one core, so the
highbank kernel can simply ask for the cores one at a time and
direct them straight from the bootloader to secondary_startup.

This is essentially pushing some of this logic from the kernel into
the bootloader, which is arguably cleaner but does make this
boot code more complicated.

> I've figured out that do_cpu_reset() is only called once, even
> though that seems a bit strange to me.

It should be called once per core -- we register it with
qemu_register_reset() for each core at the bottom of arm_load_kernel().
The reason it isn't in your case is a bug in highbank.c -- you should
be passing first_cpu as the first parameter to arm_load_kernel().
In fact you're passing in env, which happens to be the last cpu,
so the loop in arm_load_kernel() registers the reset handler for
the last CPU only. (I think the only reason this bug didn't cause
complete failure to boot is that you have a info->loader_start of 0
which happens to be where the core will come out of reset anyway.)

> I've tried the following
> in my local secondary_hook call:
>
>    switch (info->nb_cpus) {
>    case 4:
>        stl_phys_notdirty(0x70, 0);
>    case 3:
>        stl_phys_notdirty(0x60, 0);
>    case 2:
>        stl_phys_notdirty(0x50, 0);
>        env->regs[15] = 0x100;
>        break;
>    }
>
> which works fine with 2 cpus, but fails to boot both
> secondary cpus if there are 3 total cpus.

This is necessary but not sufficient, I think.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 19:26               ` Peter Maydell
@ 2012-01-18 19:33                 ` Peter Maydell
  2012-01-18 21:32                 ` Mark Langsdorf
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-18 19:33 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 18 January 2012 19:26, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 18 January 2012 19:06, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> How would multiple polling supposed to work?
>
> You need several separate bits of code, to put each secondary
> core in a different loop polling a different address.

Er, or more sensibly, just one bit of code that does something like:
 /* find out which core we are by reading cp15 MPIDR */
 core = cp15_MPIDR & 0x3;
 do {
    /* now we can check the right flag for this core */
    wfi
    poll [0x40+0x10 * core]
 } while (it's zero);
 jump to it;

(translation into assembly left as exercise for the reader)

> (If you have access to your own bootloader sources you should
> be able to see how it does it :-))

This advice is still good :-)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank
  2012-01-18 19:26               ` Peter Maydell
  2012-01-18 19:33                 ` Peter Maydell
@ 2012-01-18 21:32                 ` Mark Langsdorf
  1 sibling, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-18 21:32 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/18/2012 01:26 PM, Peter Maydell wrote:
> On 18 January 2012 19:06, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/18/2012 08:53 AM, Peter Maydell wrote:
>>> On 18 January 2012 14:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>> I can set the smp_loader code so that I can boot 2 cpus
>>>> and verify their existence in /proc/cpuinfo, but I can't
>>>> get 3 cpus to boot at all, no matter how I hack the existing
>>>> arm_boot code.
>>>
>>> Right, multiple secondary cores requires multiple addresses
>>> to be polled which we don't support in arm_boot.c at the moment.
>>
>> How would multiple polling supposed to work?
> 
> You need several separate bits of code, to put each secondary
> core in a different loop polling a different address.
> (If you have access to your own bootloader sources you should
> be able to see how it does it :-))

I wasn't sure if polling was done on the QEMU side. I can
pull code from the bootloader.

>> I've tried changing
>> http://lxr.linux.no/#linux+v3.2.1/arch/arm/mach-highbank/highbank.c#L71
>> to point to a fixed address (0x50), and the boot loader still fails
>> if there are 2 or more secondary CPUs.
> 
> Yeah, that's insufficient, because the highbank kernel doesn't
>
>> I've figured out that do_cpu_reset() is only called once, even
>> though that seems a bit strange to me.
> 
> It should be called once per core -- we register it with
> qemu_register_reset() for each core at the bottom of arm_load_kernel().
> The reason it isn't in your case is a bug in highbank.c -- you should
> be passing first_cpu as the first parameter to arm_load_kernel().

As it turns out, the highbank simulation will boot all 4 cores
if I make the change to pass first_cpu and change the Linux code
to use 0x40 for all 4 CPUs. Which is gratifying if a little
surprising.

With that straightened out, I can go work on translating
the polling code to opcodes. Thanks for the pointers.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (10 preceding siblings ...)
  2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 15:43   ` Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 1/6] Add xgmac ethernet model Mark Langsdorf
                       ` (5 more replies)
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  12 siblings, 6 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 1/6] Add xgmac ethernet model
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
                       ` (4 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

This adds very basic support for the xgmac ethernet core. Missing things
include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v10
	None
Changes from v9
        Make typedef struct names into CamelCase
Changes from v7, v8
        None
Changes from v6
        Skipped
Changes from v5
        removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..9bc0248 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -343,6 +343,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..be63a7d
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct RxTxStats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} RxTxStats;
+
+typedef struct XgmacState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct RxTxStats stats;
+    uint32_t regs[R_MAX];
+} XgmacState;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, RxTxStats),
+        VMSTATE_UINT64(tx_bytes, RxTxStats),
+        VMSTATE_UINT64(rx, RxTxStats),
+        VMSTATE_UINT64(rx_bcast, RxTxStats),
+        VMSTATE_UINT64(rx_mcast, RxTxStats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, XgmacState, 0, vmstate_rxtx_stats, RxTxStats),
+        VMSTATE_UINT32_ARRAY(regs, XgmacState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct XgmacState *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct XgmacState *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct XgmacState *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct XgmacState *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct XgmacState),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct XgmacState, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 2/6] arm: make the number of GIC interrupts configurable
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 1/6] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (3 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

Increase the maximum number of GIC interrupts for a9mp and a11mp to 1020,
and create a configurable property for each defaulting to 96 and 64
(respectively) so that device modelers can set the value appropriately
for their SoC. Other ARM processors also set their maximum number of
used IRQs appropriately.

Set the maximum theoretical number of GIC interrupts to 1020 and
update the save/restore code to only use the appropriate number for
each SoC.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v9, v10
        None
Changes from v8
        Removed comments about armv7m_nvic's external IRQ lines
Changes from v7
        Removed unnecessary vmstate_register
Changes from v6
        Removed trailing whitespace
        armv7m_nvic uses num_irq properly
        Some comments changed
Changes from v5
        Clarify the commit message
        Rename GIC_NIRQ to GIC_MAXIRQ and change usage slightly
        Makes num-irq to uint32_t in all cases
        Clarify the error message
        Clarify documentation on the num-irq qdev property use in all files
Changes from v4
        None
Changes from v3
        Increase maximum number of GIC interrupts to 1020
        Remove SoC/implementation specific GIC_NIRQ #defs
        Added properties code to arm11mp
        Changed error handling for too many interrupts
        Redid save/load handling
Changes from v2
        Skipped
Changes from v1
        Increase the number of a9mp interrupts to 192
        Add a property defaulting to 96
        Add a num_irq member in the gic state structure
        Use the num_irq value as appropriate
        Add num_irq argument to gic_init()
        Add num_irq to various CPU calls to gic_init

 hw/a9mpcore.c     |   13 +++++++--
 hw/arm11mpcore.c  |   17 ++++++++----
 hw/arm_gic.c      |   68 +++++++++++++++++++++++++++++-----------------------
 hw/armv7m_nvic.c  |   31 ++++++++++++++++++------
 hw/realview_gic.c |    7 ++++-
 5 files changed, 87 insertions(+), 49 deletions(-)

diff --git a/hw/a9mpcore.c b/hw/a9mpcore.c
index 3ef0e13..521b8cc 100644
--- a/hw/a9mpcore.c
+++ b/hw/a9mpcore.c
@@ -11,9 +11,8 @@
 #include "sysbus.h"
 
 /* Configuration for arm_gic.c:
- * number of external IRQ lines, max number of CPUs, how to ID current CPU
+ * max number of CPUs, how to ID current CPU
  */
-#define GIC_NIRQ 96
 #define NCPU 4
 
 static inline int
@@ -37,6 +36,7 @@ typedef struct a9mp_priv_state {
     MemoryRegion ptimer_iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } a9mp_priv_state;
 
 static uint64_t a9_scu_read(void *opaque, target_phys_addr_t offset,
@@ -153,7 +153,7 @@ static int a9mp_priv_init(SysBusDevice *dev)
         hw_error("a9mp_priv_init: num-cpu may not be more than %d\n", NCPU);
     }
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
 
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
@@ -216,6 +216,13 @@ static SysBusDeviceInfo a9mp_priv_info = {
     .qdev.reset = a9mp_priv_reset,
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", a9mp_priv_state, num_cpu, 1),
+        /* The Cortex-A9MP may have anything from 0 to 224 external interrupt
+         * IRQ lines (with another 32 internal). We default to 64+32, which
+         * is the number provided by the Cortex-A9MP test chip in the
+         * Realview PBX-A9 and Versatile Express A9 development boards.
+         * Other boards may differ and should set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", a9mp_priv_state, num_irq, 96),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm11mpcore.c b/hw/arm11mpcore.c
index bc0457e..f4d88dc 100644
--- a/hw/arm11mpcore.c
+++ b/hw/arm11mpcore.c
@@ -10,11 +10,6 @@
 #include "sysbus.h"
 #include "qemu-timer.h"
 
-/* ??? The MPCore TRM says the on-chip controller has 224 external IRQ lines
-   (+ 32 internal).  However my test chip only exposes/reports 32.
-   More importantly Linux falls over if more than 32 are present!  */
-#define GIC_NIRQ 64
-
 #define NCPU 4
 
 static inline int
@@ -37,6 +32,7 @@ typedef struct mpcore_priv_state {
     MemoryRegion iomem;
     MemoryRegion container;
     DeviceState *mptimer;
+    uint32_t num_irq;
 } mpcore_priv_state;
 
 /* Per-CPU private memory mapped IO.  */
@@ -132,7 +128,7 @@ static int mpcore_priv_init(SysBusDevice *dev)
 {
     mpcore_priv_state *s = FROM_SYSBUSGIC(mpcore_priv_state, dev);
 
-    gic_init(&s->gic, s->num_cpu);
+    gic_init(&s->gic, s->num_cpu, s->num_irq);
     s->mptimer = qdev_create(NULL, "arm_mptimer");
     qdev_prop_set_uint32(s->mptimer, "num-cpu", s->num_cpu);
     qdev_init_nofail(s->mptimer);
@@ -221,6 +217,15 @@ static SysBusDeviceInfo mpcore_priv_info = {
     .qdev.size  = sizeof(mpcore_priv_state),
     .qdev.props = (Property[]) {
         DEFINE_PROP_UINT32("num-cpu", mpcore_priv_state, num_cpu, 1),
+        /* The ARM11 MPCORE TRM says the on-chip controller may have
+         * anything from 0 to 224 external interrupt IRQ lines (with another
+         * 32 internal). We default to 32+32, which is the number provided by
+         * the ARM11 MPCore test chip in the Realview Versatile Express
+         * coretile. Other boards may differ and should set this property
+         * appropriately. Some Linux kernels may not boot if the hardware
+         * has more IRQ lines than the kernel expects.
+         */
+        DEFINE_PROP_UINT32("num-irq", mpcore_priv_state, num_irq, 64),
         DEFINE_PROP_END_OF_LIST(),
     }
 };
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index 0339cf5..cf582a5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -11,6 +11,8 @@
    controller, MPCore distributed interrupt controller and ARMv7-M
    Nested Vectored Interrupt Controller.  */
 
+/* Maximum number of possible interrupts, determined by the GIC architecture */
+#define GIC_MAXIRQ 1020
 //#define DEBUG_GIC
 
 #ifdef DEBUG_GIC
@@ -86,13 +88,13 @@ typedef struct gic_state
     int enabled;
     int cpu_enabled[NCPU];
 
-    gic_irq_state irq_state[GIC_NIRQ];
+    gic_irq_state irq_state[GIC_MAXIRQ];
 #ifndef NVIC
-    int irq_target[GIC_NIRQ];
+    int irq_target[GIC_MAXIRQ];
 #endif
     int priority1[32][NCPU];
-    int priority2[GIC_NIRQ - 32];
-    int last_active[GIC_NIRQ][NCPU];
+    int priority2[GIC_MAXIRQ - 32];
+    int last_active[GIC_MAXIRQ][NCPU];
 
     int priority_mask[NCPU];
     int running_irq[NCPU];
@@ -111,6 +113,7 @@ typedef struct gic_state
     struct gic_state *backref[NCPU];
     MemoryRegion cpuiomem[NCPU+1]; /* CPU interfaces */
 #endif
+    uint32_t num_irq;
 } gic_state;
 
 /* TODO: Many places that call this routine could be optimized.  */
@@ -133,7 +136,7 @@ static void gic_update(gic_state *s)
         }
         best_prio = 0x100;
         best_irq = 1023;
-        for (irq = 0; irq < GIC_NIRQ; irq++) {
+        for (irq = 0; irq < s->num_irq; irq++) {
             if (GIC_TEST_ENABLED(irq, cm) && GIC_TEST_PENDING(irq, cm)) {
                 if (GIC_GET_PRIORITY(irq, cpu) < best_prio) {
                     best_prio = GIC_GET_PRIORITY(irq, cpu);
@@ -222,7 +225,7 @@ static void gic_complete_irq(gic_state * s, int cpu, int irq)
     int update = 0;
     int cm = 1 << cpu;
     DPRINTF("EOI %d\n", irq);
-    if (irq >= GIC_NIRQ) {
+    if (irq >= s->num_irq) {
         /* This handles two cases:
          * 1. If software writes the ID of a spurious interrupt [ie 1023]
          * to the GICC_EOIR, the GIC ignores that write.
@@ -279,7 +282,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         if (offset == 0)
             return s->enabled;
         if (offset == 4)
-            return ((GIC_NIRQ / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
+            return ((s->num_irq / 32) - 1) | ((NUM_CPU(s) - 1) << 5);
         if (offset < 0x08)
             return 0;
         if (offset >= 0x80) {
@@ -295,7 +298,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x180) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 8; i++) {
@@ -310,7 +313,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
         else
             irq = (offset - 0x280) * 8;
         irq += GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -322,7 +325,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x400) {
         /* Interrupt Active.  */
         irq = (offset - 0x300) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         mask = (irq < 32) ?  cm : ALL_CPU_MASK;
@@ -334,14 +337,14 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = GIC_GET_PRIORITY(irq, cpu);
 #ifndef NVIC
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq >= 29 && irq <= 31) {
             res = cm;
@@ -351,7 +354,7 @@ static uint32_t gic_dist_readb(void *opaque, target_phys_addr_t offset)
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 2 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         res = 0;
         for (i = 0; i < 4; i++) {
@@ -426,7 +429,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x180) {
         /* Interrupt Set Enable.  */
         irq = (offset - 0x100) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0xff;
@@ -451,7 +454,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x200) {
         /* Interrupt Clear Enable.  */
         irq = (offset - 0x180) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           value = 0;
@@ -468,7 +471,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x280) {
         /* Interrupt Set Pending.  */
         irq = (offset - 0x200) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 16)
           irq = 0;
@@ -481,7 +484,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x300) {
         /* Interrupt Clear Pending.  */
         irq = (offset - 0x280) * 8 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         for (i = 0; i < 8; i++) {
             /* ??? This currently clears the pending bit for all CPUs, even
@@ -497,7 +500,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0x800) {
         /* Interrupt Priority.  */
         irq = (offset - 0x400) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32) {
             s->priority1[irq][cpu] = value;
@@ -508,7 +511,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xc00) {
         /* Interrupt CPU Target.  */
         irq = (offset - 0x800) + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 29)
             value = 0;
@@ -518,7 +521,7 @@ static void gic_dist_writeb(void *opaque, target_phys_addr_t offset,
     } else if (offset < 0xf00) {
         /* Interrupt Configuration.  */
         irq = (offset - 0xc00) * 4 + GIC_BASE_IRQ;
-        if (irq >= GIC_NIRQ)
+        if (irq >= s->num_irq)
             goto bad_reg;
         if (irq < 32)
             value |= 0xaa;
@@ -699,7 +702,7 @@ static const MemoryRegionOps gic_cpu_ops = {
 static void gic_reset(gic_state *s)
 {
     int i;
-    memset(s->irq_state, 0, GIC_NIRQ * sizeof(gic_irq_state));
+    memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
     for (i = 0 ; i < NUM_CPU(s); i++) {
         s->priority_mask[i] = 0xf0;
         s->current_pending[i] = 1023;
@@ -735,17 +738,17 @@ static void gic_save(QEMUFile *f, void *opaque)
         qemu_put_be32(f, s->cpu_enabled[i]);
         for (j = 0; j < 32; j++)
             qemu_put_be32(f, s->priority1[j][i]);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             qemu_put_be32(f, s->last_active[j][i]);
         qemu_put_be32(f, s->priority_mask[i]);
         qemu_put_be32(f, s->running_irq[i]);
         qemu_put_be32(f, s->running_priority[i]);
         qemu_put_be32(f, s->current_pending[i]);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         qemu_put_be32(f, s->priority2[i]);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         qemu_put_be32(f, s->irq_target[i]);
 #endif
@@ -772,17 +775,17 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
         s->cpu_enabled[i] = qemu_get_be32(f);
         for (j = 0; j < 32; j++)
             s->priority1[j][i] = qemu_get_be32(f);
-        for (j = 0; j < GIC_NIRQ; j++)
+        for (j = 0; j < s->num_irq; j++)
             s->last_active[j][i] = qemu_get_be32(f);
         s->priority_mask[i] = qemu_get_be32(f);
         s->running_irq[i] = qemu_get_be32(f);
         s->running_priority[i] = qemu_get_be32(f);
         s->current_pending[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ - 32; i++) {
+    for (i = 0; i < s->num_irq - 32; i++) {
         s->priority2[i] = qemu_get_be32(f);
     }
-    for (i = 0; i < GIC_NIRQ; i++) {
+    for (i = 0; i < s->num_irq; i++) {
 #ifndef NVIC
         s->irq_target[i] = qemu_get_be32(f);
 #endif
@@ -798,9 +801,9 @@ static int gic_load(QEMUFile *f, void *opaque, int version_id)
 }
 
 #if NCPU > 1
-static void gic_init(gic_state *s, int num_cpu)
+static void gic_init(gic_state *s, int num_cpu, int num_irq)
 #else
-static void gic_init(gic_state *s)
+static void gic_init(gic_state *s, int num_irq)
 #endif
 {
     int i;
@@ -808,7 +811,12 @@ static void gic_init(gic_state *s)
 #if NCPU > 1
     s->num_cpu = num_cpu;
 #endif
-    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, GIC_NIRQ - 32);
+    s->num_irq = num_irq + GIC_BASE_IRQ;
+    if (s->num_irq > GIC_MAXIRQ) {
+        hw_error("requested %u interrupt lines exceeds GIC maximum %d\n",
+                 num_irq, GIC_MAXIRQ);
+    }
+    qdev_init_gpio_in(&s->busdev.qdev, gic_set_irq, s->num_irq - 32);
     for (i = 0; i < NUM_CPU(s); i++) {
         sysbus_init_irq(&s->busdev, &s->parent_irq[i]);
     }
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index bf8c3c5..28f36ba 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -15,9 +15,6 @@
 #include "arm-misc.h"
 #include "exec-memory.h"
 
-/* 32 internal lines (16 used for system exceptions) plus 64 external
-   interrupt lines.  */
-#define GIC_NIRQ 96
 #define NCPU 1
 #define NVIC 1
 
@@ -41,6 +38,7 @@ typedef struct {
         int64_t tick;
         QEMUTimer *timer;
     } systick;
+    uint32_t num_irq;
 } nvic_state;
 
 /* qemu timers run at 1GHz.   We want something closer to 1MHz.  */
@@ -125,7 +123,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
 
     switch (offset) {
     case 4: /* Interrupt Control Type.  */
-        return (GIC_NIRQ / 32) - 1;
+        return (s->num_irq / 32) - 1;
     case 0x10: /* SysTick Control and Status.  */
         val = s->systick.control;
         s->systick.control &= ~SYSTICK_COUNTFLAG;
@@ -169,7 +167,7 @@ static uint32_t nvic_readl(void *opaque, uint32_t offset)
         if (s->gic.current_pending[0] != 1023)
             val |= (s->gic.current_pending[0] << 12);
         /* ISRPENDING */
-        for (irq = 32; irq < GIC_NIRQ; irq++) {
+        for (irq = 32; irq < s->num_irq; irq++) {
             if (s->gic.irq_state[irq].pending) {
                 val |= (1 << 22);
                 break;
@@ -384,16 +382,33 @@ static int armv7m_nvic_init(SysBusDevice *dev)
 {
     nvic_state *s= FROM_SYSBUSGIC(nvic_state, dev);
 
-    gic_init(&s->gic);
+   /* note that for the M profile gic_init() takes the number of external
+    * interrupt lines only.
+    */
+    gic_init(&s->gic, s->num_irq);
     memory_region_add_subregion(get_system_memory(), 0xe000e000, &s->gic.iomem);
     s->systick.timer = qemu_new_timer_ns(vm_clock, systick_timer_tick, s);
-    vmstate_register(&dev->qdev, -1, &vmstate_nvic, s);
     return 0;
 }
 
+static SysBusDeviceInfo armv7m_nvic_priv_info = {
+    .init = armv7m_nvic_init,
+    .qdev.name  = "armv7m_nvic",
+    .qdev.size  = sizeof(nvic_state),
+    .qdev.vmsd  = &vmstate_nvic,
+    .qdev.props = (Property[]) {
+        /* The ARM v7m may have anything from 0 to 496 external interrupt
+         * IRQ lines. We default to 64. Other boards may differ and should
+         * set this property appropriately.
+         */
+        DEFINE_PROP_UINT32("num-irq", nvic_state, num_irq, 64),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
 static void armv7m_nvic_register_devices(void)
 {
-    sysbus_register_dev("armv7m_nvic", sizeof(nvic_state), armv7m_nvic_init);
+    sysbus_register_withprop(&armv7m_nvic_priv_info);
 }
 
 device_init(armv7m_nvic_register_devices)
diff --git a/hw/realview_gic.c b/hw/realview_gic.c
index 8c4d509..7342ede 100644
--- a/hw/realview_gic.c
+++ b/hw/realview_gic.c
@@ -9,7 +9,6 @@
 
 #include "sysbus.h"
 
-#define GIC_NIRQ 96
 #define NCPU 1
 
 /* Only a single "CPU" interface is present.  */
@@ -37,7 +36,11 @@ static int realview_gic_init(SysBusDevice *dev)
 {
     RealViewGICState *s = FROM_SYSBUSGIC(RealViewGICState, dev);
 
-    gic_init(&s->gic);
+    /* The GICs on the RealView boards have a fixed nonconfigurable
+     * number of interrupt lines, so we don't need to expose this as
+     * a qdev property.
+     */
+    gic_init(&s->gic, 96);
     realview_gic_map_setup(s);
     sysbus_init_mmio(dev, &s->container);
     return 0;
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 3/6] ahci: add support for non-PCI based controllers
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 1/6] Add xgmac ethernet model Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
                       ` (2 subsequent siblings)
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v10
	None
Changes from v9
        Changed typedef struct names to CamelCase
Changes from v7, v8
        None
Changes from v5, v6
        Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0af201d..0309dd6 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(&d->ahci, i);
     }
 }
+
+typedef struct SysbusAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} SysbusAHCIState;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(SysbusAHCIState),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  2012-01-19 17:19       ` Peter Maydell
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

Create two functions, write_secondary_boot() and secondary_cpu_reset_hook(),
to allow platforms more control of how secondary CPUs are brought up. The
new functions default to NULL and aren't called unless they are populated
so there are no changes to existing platform models.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v2-v10
        Skipped
Changes from v1
        Added default versions of the functions
        Created checks so that NULL function entries became default versions
        Simplified calls to the secondary boot functions
	Added comments on the use of these functions

 hw/arm-misc.h |   15 +++++++++++++++
 hw/arm_boot.c |   38 +++++++++++++++++++++++++++++---------
 2 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b..9138eab 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -30,12 +30,27 @@ struct arm_boot_info {
     const char *kernel_cmdline;
     const char *initrd_filename;
     target_phys_addr_t loader_start;
+    /* multicore boards that use the default secondary core boot functions
+     * need to put the address of the secondary boot code, the boot reg,
+     * and the GIC address in the next 3 values, respectively. boards that
+     * have their own boot functions can use these values as they want.
+     */
     target_phys_addr_t smp_loader_start;
     target_phys_addr_t smp_bootreg_addr;
     target_phys_addr_t smp_priv_base;
     int nb_cpus;
     int board_id;
     int (*atag_board)(const struct arm_boot_info *info, void *p);
+    /* multicore boards that use the default secondary core boot functions
+     * can ignore these two function calls. If the default functions won't
+     * work, then write_secondary_boot() should mimic the board's boot
+     * loader code, and secondary_cpu_reset_hook() should operate handle any
+     * polling response and reset functions.
+     */
+    void (*write_secondary_boot)(CPUState *env,
+                                 const struct arm_boot_info *info);
+    void (*secondary_cpu_reset_hook)(CPUState *env,
+                                     const struct arm_boot_info *info);
     /* Used internally by arm_boot.c */
     int is_linux;
     target_phys_addr_t initrd_size;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8..8f73a29 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -197,13 +197,32 @@ static void do_cpu_reset(void *opaque)
                                     info->loader_start);
                 }
             } else {
-                stl_phys_notdirty(info->smp_bootreg_addr, 0);
-                env->regs[15] = info->smp_loader_start;
+                info->secondary_cpu_reset_hook(env, info);
             }
         }
     }
 }
 
+static void default_write_secondary(CPUState *env,
+                                    const struct arm_boot_info *info)
+{
+    int n;
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+static void default_reset_secondary(CPUState *env,
+                                    const struct arm_boot_info *info)
+{
+    stl_phys_notdirty(info->smp_bootreg_addr, 0);
+    env->regs[15] = info->smp_loader_start;
+}
+
 void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
 {
     int kernel_size;
@@ -220,6 +239,13 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         exit(1);
     }
 
+    if (!info->secondary_cpu_reset_hook) {
+        info->secondary_cpu_reset_hook = default_reset_secondary;
+    }
+    if (!info->write_secondary_boot) {
+        info->write_secondary_boot = default_write_secondary;
+    }
+
     if (info->nb_cpus == 0)
         info->nb_cpus = 1;
 
@@ -273,13 +299,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
                            info->loader_start);
         if (info->nb_cpus > 1) {
-            smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-            smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
-            for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-                smpboot[n] = tswap32(smpboot[n]);
-            }
-            rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
-                               info->smp_loader_start);
+            info->write_secondary_boot(env, info);
         }
         info->initrd_size = initrd_size;
     }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (3 preceding siblings ...)
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  2012-01-19 19:15       ` Peter Maydell
  2012-01-19 20:00       ` Peter Maydell
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
  5 siblings, 2 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v10
	Added secondary core boot functions
Changes from v9
        Made typedef struct names in CamelCase
Changes from v7, v8
        None
Changes from v3, v4, v5, v6
        Skipped
Changes from v2
        Created a reset function for highbank_regs
        Handled creation of regs i/o memory region in a sensible manner
        Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  321 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 322 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 9bc0248..1c86522 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..a9a3cb6
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,321 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define SMP_BOOT_REG  0x40       /* should be 0x40 + 0x10 * cpu */
+#define GIC_BASE_ADDR 0xfff10000
+
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
+        0xe210000f, /* ands r0, r0, #0x0f */
+        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
+        0xe0830200, /* add r0, r3, r0, lsl #4 */
+        0xe59f2018, /* ldr r2, privbase */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821100, /* str r1, [r2, #256] */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        GIC_BASE_ADDR      /* privbase: gic address.  */
+    };
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+}
+
+static void hb_reset_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+    switch (info->nb_cpus) {
+    case 4:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
+    case 3:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
+    case 2:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
+        env->regs[15] = SMP_BOOT_ADDR;
+        break;
+    default:
+        break;
+    }
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(HighbankRegsState),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = -1; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.write_secondary_boot = hb_write_secondary;
+    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+    arm_load_kernel(first_cpu, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v11 6/6] arm: Remove incorrect comment in arm_timer
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (4 preceding siblings ...)
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 15:43     ` Mark Langsdorf
  5 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 15:43 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

The current comment says that the arm_timers are restricted to between
32 KHz and 1 MHz, but sp804 TRM does not specify those limits.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v7-v10
        None
Changes from v2-v6
        Skipped
Changes from v1
        Clarified the commit message

 hw/arm_timer.c |    3 ---
 1 files changed, 0 insertions(+), 3 deletions(-)

diff --git a/hw/arm_timer.c b/hw/arm_timer.c
index 1902f1a..ead2535 100644
--- a/hw/arm_timer.c
+++ b/hw/arm_timer.c
@@ -273,11 +273,8 @@ static int sp804_init(SysBusDevice *dev)
 
     qi = qemu_allocate_irqs(sp804_set_irq, s, 2);
     sysbus_init_irq(dev, &s->irq);
-    /* The timers are configurable between 32kHz and 1MHz
-     * defaulting to 1MHz but overrideable as individual properties */
     s->timer[0] = arm_timer_init(s->freq0);
     s->timer[1] = arm_timer_init(s->freq1);
-
     s->timer[0]->irq = qi[0];
     s->timer[1]->irq = qi[1];
     memory_region_init_io(&s->iomem, &sp804_ops, s, "sp804", 0x1000);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
@ 2012-01-19 17:19       ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 17:19 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: i.mitsyanko, edgar.iglesias, qemu-devel, afaerber

On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> Re: [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c

Subject should say 'boot', not 'book'...

> Create two functions, write_secondary_boot() and secondary_cpu_reset_hook(),
> to allow platforms more control of how secondary CPUs are brought up. The
> new functions default to NULL and aren't called unless they are populated
> so there are no changes to existing platform models.
>
> Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
> ---
> Changes from v2-v10
>        Skipped
> Changes from v1
>        Added default versions of the functions
>        Created checks so that NULL function entries became default versions
>        Simplified calls to the secondary boot functions
>        Added comments on the use of these functions
>
>  hw/arm-misc.h |   15 +++++++++++++++
>  hw/arm_boot.c |   38 +++++++++++++++++++++++++++++---------
>  2 files changed, 44 insertions(+), 9 deletions(-)
>
> diff --git a/hw/arm-misc.h b/hw/arm-misc.h
> index 6e8ae6b..9138eab 100644
> --- a/hw/arm-misc.h
> +++ b/hw/arm-misc.h
> @@ -30,12 +30,27 @@ struct arm_boot_info {
>     const char *kernel_cmdline;
>     const char *initrd_filename;
>     target_phys_addr_t loader_start;
> +    /* multicore boards that use the default secondary core boot functions
> +     * need to put the address of the secondary boot code, the boot reg,
> +     * and the GIC address in the next 3 values, respectively. boards that
> +     * have their own boot functions can use these values as they want.
> +     */
>     target_phys_addr_t smp_loader_start;
>     target_phys_addr_t smp_bootreg_addr;
>     target_phys_addr_t smp_priv_base;
>     int nb_cpus;
>     int board_id;
>     int (*atag_board)(const struct arm_boot_info *info, void *p);
> +    /* multicore boards that use the default secondary core boot functions
> +     * can ignore these two function calls. If the default functions won't
> +     * work, then write_secondary_boot() should mimic the board's boot
> +     * loader code, and secondary_cpu_reset_hook() should operate handle any
> +     * polling response and reset functions.
> +     */

"then write_secondary_boot() should write a suitable blob of code mimicing
the secondary CPU startup process used by the board's boot loader/boot ROM
code, and secondary_cpu_reset_hook() should perform any necessary CPU reset
handling and set the PC for the secondary CPUs to point at this boot blob."

> +static void default_write_secondary(CPUState *env,
> +                                    const struct arm_boot_info *info)
> +{
> +    int n;
> +    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
> +    smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
> +    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
> +        smpboot[n] = tswap32(smpboot[n]);
> +    }
> +    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
> +                       info->smp_loader_start);
> +}
> +
> +static void default_reset_secondary(CPUState *env,
> +                                    const struct arm_boot_info *info)
> +{
> +    stl_phys_notdirty(info->smp_bootreg_addr, 0);
> +    env->regs[15] = info->smp_loader_start;
> +}
> +

Can you put these two functions immediately below the smpboot[] array,
and replace the comment just above smpboot[] with this one:

/* Handling for secondary CPU boot in a multicore system.
 * Unlike the uniprocessor/primary CPU boot, this is platform
 * dependent. The default code here is based on the secondary
 * CPU boot protocol used on realview/vexpress boards, with
 * some parameterisation to increase its flexibility.
 * QEMU platform models for which this code is not appropriate
 * should override write_secondary_boot and secondary_cpu_reset_hook
 * instead.
 *
 * This code enables the interrupt controllers for the secondary
 * CPUs and then puts all the secondary CPUs into a loop waiting
 * for an interprocessor interrupt and polling a configurable
 * location for the kernel secondary CPU entry point.
 */

Otherwise looks good.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 19:15       ` Peter Maydell
  2012-01-19 19:25         ` Mark Langsdorf
  2012-01-19 20:00       ` Peter Maydell
  1 sibling, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 19:15 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +    highbank_binfo.board_id = -1; /* provided by deviceTree */

This doesn't work, because arm_boot.c does:
        bootloader[1] |= info->board_id & 0xff;
        bootloader[2] |= (info->board_id >> 8) & 0xff;

and so when you try to boot the kernel it does this:

===begin===
cam-vm-266:maverick:qemu-jeos$
~/linaro/qemu-from-laptop/qemu/arm-softmmu/qemu-system-arm -kernel
build-arm/linux/arch/arm/boot/zImage -initrd build-arm/initramfs.img
-M highbank -serial stdio

Error: unrecognized/unsupported machine ID (r1 = 0x0000ffff).

Available machine support:

ID (hex)        NAME
ffffffff        Highbank

Please check your kernel config and/or bootloader.
===endit===

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:15       ` Peter Maydell
@ 2012-01-19 19:25         ` Mark Langsdorf
  2012-01-19 19:32           ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 19:25 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/19/2012 01:15 PM, Peter Maydell wrote:
> On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
> 
> This doesn't work, because arm_boot.c does:
>         bootloader[1] |= info->board_id & 0xff;
>         bootloader[2] |= (info->board_id >> 8) & 0xff;
> 
> and so when you try to boot the kernel it does this:
> 
> ===begin===
> cam-vm-266:maverick:qemu-jeos$
> ~/linaro/qemu-from-laptop/qemu/arm-softmmu/qemu-system-arm -kernel
> build-arm/linux/arch/arm/boot/zImage -initrd build-arm/initramfs.img
> -M highbank -serial stdio
> 
> Error: unrecognized/unsupported machine ID (r1 = 0x0000ffff).
> 
> Available machine support:
> 
> ID (hex)        NAME
> ffffffff        Highbank
> 
> Please check your kernel config and/or bootloader.
> ===endit===

Works for me, but it requires a kernel build with the device tree
dtb appended to it.

===begin===
mlangsdorf@mjl-dell:~/work/qemu$
./mainline_qemu/arm-softmmu/qemu-system-arm -nographic -M highbank
-kernel linux-2.6/kernel_with_dtb.img -drive
id=disk,if=ide,file=sataDisk -device ide-drive,drive=disk,bus=ide.0
-append "root=/dev/sda2 console=ttyAMA0,38400 debug earlyprintk" -m 4089
-smp 3
[    0.000000] Booting Linux on physical CPU 0
[    0.000000] Initializing cgroup subsys cpuset
[    0.000000] Initializing cgroup subsys cpu
[    0.000000] Linux version 3.2.0+ (mlangsdorf@mjl-dell) (gcc version
4.6.1 (Ubuntu/Linaro 4.6.1-9ubuntu3) ) #72 SMP Wed Jan 18 15:10:31 CST 2012
[    0.000000] CPU: ARMv7 Processor [410fc090] revision 0 (ARMv7),
cr=10c5387d
[    0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT aliasing
instruction cache
[    0.000000] Machine: Highbank, model: Calxeda Highbank
[    0.000000] Memory policy: ECC disabled, Data cache writealloc
[    0.000000] On node 0 totalpages: 1046784
===endit===

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:25         ` Mark Langsdorf
@ 2012-01-19 19:32           ` Peter Maydell
  2012-01-19 19:35             ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 19:32 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 19:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/19/2012 01:15 PM, Peter Maydell wrote:
>> On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>
> Works for me, but it requires a kernel build with the device tree
> dtb appended to it.

How do I get hold of a valid dtb for this platform?

thanks
-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:32           ` Peter Maydell
@ 2012-01-19 19:35             ` Mark Langsdorf
  2012-01-19 19:44               ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 19:35 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/19/2012 01:32 PM, Peter Maydell wrote:
> On 19 January 2012 19:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/19/2012 01:15 PM, Peter Maydell wrote:
>>> On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>>
>> Works for me, but it requires a kernel build with the device tree
>> dtb appended to it.
> 
> How do I get hold of a valid dtb for this platform?

The dts is at:
http://lxr.linux.no/#linux+v3.2.1/arch/arm/boot/dts/highbank.dts

I usually cross compile with:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- highbank.dtb

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:35             ` Mark Langsdorf
@ 2012-01-19 19:44               ` Peter Maydell
  2012-01-19 19:58                 ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 19:44 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 19:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/19/2012 01:32 PM, Peter Maydell wrote:
>> On 19 January 2012 19:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>> On 01/19/2012 01:15 PM, Peter Maydell wrote:
>>>> On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>>>
>>> Works for me, but it requires a kernel build with the device tree
>>> dtb appended to it.
>>
>> How do I get hold of a valid dtb for this platform?
>
> The dts is at:
> http://lxr.linux.no/#linux+v3.2.1/arch/arm/boot/dts/highbank.dts
>
> I usually cross compile with:
> make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- highbank.dtb

Right, thanks.

I have a kernel now that seems to boot but then
barfs with:
Freeing init memory: 124K
Kernel panic - not syncing: Attempted to kill init!

but that's probably a misconfiguration in my kernel.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:44               ` Peter Maydell
@ 2012-01-19 19:58                 ` Mark Langsdorf
  2012-01-19 19:59                   ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 19:58 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/19/2012 01:44 PM, Peter Maydell wrote:
> On 19 January 2012 19:35, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/19/2012 01:32 PM, Peter Maydell wrote:
>>> On 19 January 2012 19:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>> On 01/19/2012 01:15 PM, Peter Maydell wrote:
>>>>> On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>>>>
>>>> Works for me, but it requires a kernel build with the device tree
>>>> dtb appended to it.
>>>
>>> How do I get hold of a valid dtb for this platform?
>>
>> The dts is at:
>> http://lxr.linux.no/#linux+v3.2.1/arch/arm/boot/dts/highbank.dts
>>
>> I usually cross compile with:
>> make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- highbank.dtb
> 
> Right, thanks.
> 
> I have a kernel now that seems to boot but then
> barfs with:
> Freeing init memory: 124K
> Kernel panic - not syncing: Attempted to kill init!
> 
> but that's probably a misconfiguration in my kernel.

You need to be passing -m 4089.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:58                 ` Mark Langsdorf
@ 2012-01-19 19:59                   ` Peter Maydell
  2012-01-19 20:48                     ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 19:59 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 19:58, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/19/2012 01:44 PM, Peter Maydell wrote:
>> I have a kernel now that seems to boot but then
>> barfs with:
>> Freeing init memory: 124K
>> Kernel panic - not syncing: Attempted to kill init!
>>
>> but that's probably a misconfiguration in my kernel.
>
> You need to be passing -m 4089.

cam-vm-266:maverick:qemu-jeos$
~/linaro/qemu-from-laptop/qemu/arm-softmmu/qemu-system-arm -kernel
zImage-with-dtb  -initrd build-arm/initramfs.img -M highbank -serial
stdio -m 4089
qemu: at most 2047 MB RAM can be simulated

I'd rather not have a model that doesn't work on 32 bit hosts
if we can avoid it...

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-19 19:15       ` Peter Maydell
@ 2012-01-19 20:00       ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 20:00 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 15:43, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +    highbank_binfo.board_id = -1; /* provided by deviceTree */

I'm still not sure about this.

The linux Documentation/devicetree/booting-without-of.txt says
there are two calling conventions for booting here, ATAGS and
with-device-tree-blob, and that even with the device tree blob
method it is still considered "good practise" to pass a valid
machine number in r1. Can you point me to some documentation
that says that -1 is OK now?

(We probably ought to get round to actually implementing
a -dtb option to go with -kernel and -initrd.)

thanks
-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank
  2012-01-19 19:59                   ` Peter Maydell
@ 2012-01-19 20:48                     ` Mark Langsdorf
  0 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 20:48 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 01/19/2012 01:59 PM, Peter Maydell wrote:
> On 19 January 2012 19:58, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/19/2012 01:44 PM, Peter Maydell wrote:
>>> I have a kernel now that seems to boot but then
>>> barfs with:
>>> Freeing init memory: 124K
>>> Kernel panic - not syncing: Attempted to kill init!
>>>
>>> but that's probably a misconfiguration in my kernel.
>>
>> You need to be passing -m 4089.
> 
> cam-vm-266:maverick:qemu-jeos$
> ~/linaro/qemu-from-laptop/qemu/arm-softmmu/qemu-system-arm -kernel
> zImage-with-dtb  -initrd build-arm/initramfs.img -M highbank -serial
> stdio -m 4089
> qemu: at most 2047 MB RAM can be simulated
> 
> I'd rather not have a model that doesn't work on 32 bit hosts
> if we can avoid it...

The memory size is determined by the dts:
http://lxr.linux.no/#linux+v3.2.1/arch/arm/boot/dts/highbank.dts#L60

So you should be able to set it to whatever you want as long as the
values match. I've tested a boot with -m 2047 and the memory range
going from 0 to 0x7ff00000. That required regenerating the dtb and
re-appending it to the kernel image, though. I don't know of an
easy to handle that on the command line.

Is that sufficient for me to resend the patch with the changes
covered below?

>> +    highbank_binfo.board_id = -1; /* provided by deviceTree */
>
> I'm still not sure about this.
>
> The linux Documentation/devicetree/booting-without-of.txt says
> there are two calling conventions for booting here, ATAGS and
> with-device-tree-blob, and that even with the device tree blob
> method it is still considered "good practise" to pass a valid
> machine number in r1. Can you point me to some documentation
> that says that -1 is OK now?

I can't, so I'll change the value. We only intend to support
device tree booting.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank
  2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
                     ` (11 preceding siblings ...)
  2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 21:30   ` Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 1/4] Add xgmac ethernet model Mark Langsdorf
                       ` (3 more replies)
  12 siblings, 4 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 21:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

This patch series adds support for the Calxeda Highbank SoC.

 Makefile.target |    2 +
 hw/arm-misc.h   |   17 +++
 hw/arm_boot.c   |   54 ++++++--
 hw/highbank.c   |  327 ++++++++++++++++++++++++++++++++++++++++++
 hw/ide/ahci.c   |   44 ++++++
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 854 insertions(+), 11 deletions(-)

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v12 1/4] Add xgmac ethernet model
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 21:30     ` Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 2/4] ahci: add support for non-PCI based controllers Mark Langsdorf
                       ` (2 subsequent siblings)
  3 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 21:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

This adds very basic support for the xgmac ethernet core. Missing things
include:

- statistics counters
- WoL support
- rx checksum offload
- chained descriptors (only linear descriptor ring)
- broadcast and multicast handling

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Peter Maydell <peter.maydell@linaro.org>
---
Changes from v10, v11
        None
Changes from v9
        Make typedef struct names into CamelCase
Changes from v7, v8
        None
Changes from v6
        Skipped
Changes from v5
        removed c_phyaddr
Changes from v4
        None
Changes from v3
        Added debug macro and cleaned up some debug code
        Refitted all lines to fit within 80 columns
Changes from v2
        None
Changes from v1
        Reformated most lines to fit within 80 columns
        Removed a bunch of unused variables in the state structures
        Got rid of some camelcase structure names

 Makefile.target |    1 +
 hw/xgmac.c      |  421 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 422 insertions(+), 0 deletions(-)
 create mode 100644 hw/xgmac.c

diff --git a/Makefile.target b/Makefile.target
index 06d79b8..9bc0248 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -343,6 +343,7 @@ obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
 obj-arm-y += pl061.o
+obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
 obj-arm-y += pxa2xx.o pxa2xx_pic.o pxa2xx_gpio.o pxa2xx_timer.o pxa2xx_dma.o
 obj-arm-y += pxa2xx_lcd.o pxa2xx_mmci.o pxa2xx_pcmcia.o pxa2xx_keypad.o
diff --git a/hw/xgmac.c b/hw/xgmac.c
new file mode 100644
index 0000000..be63a7d
--- /dev/null
+++ b/hw/xgmac.c
@@ -0,0 +1,421 @@
+/*
+ * QEMU model of XGMAC Ethernet.
+ *
+ * derived from the Xilinx AXI-Ethernet by Edgar E. Iglesias.
+ *
+ * Copyright (c) 2011 Calxeda, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-log.h"
+#include "net.h"
+#include "net/checksum.h"
+
+#ifdef DEBUG_XGMAC
+#define DEBUGF_BRK(message, args...) do { \
+                                         fprintf(stderr, (message), ## args); \
+                                     } while (0)
+#else
+#define DEBUGF_BRK(message, args...) do { } while (0)
+#endif
+
+#define XGMAC_CONTROL           0x00000000   /* MAC Configuration */
+#define XGMAC_FRAME_FILTER      0x00000001   /* MAC Frame Filter */
+#define XGMAC_FLOW_CTRL         0x00000006   /* MAC Flow Control */
+#define XGMAC_VLAN_TAG          0x00000007   /* VLAN Tags */
+#define XGMAC_VERSION           0x00000008   /* Version */
+/* VLAN tag for insertion or replacement into tx frames */
+#define XGMAC_VLAN_INCL         0x00000009
+#define XGMAC_LPI_CTRL          0x0000000a   /* LPI Control and Status */
+#define XGMAC_LPI_TIMER         0x0000000b   /* LPI Timers Control */
+#define XGMAC_TX_PACE           0x0000000c   /* Transmit Pace and Stretch */
+#define XGMAC_VLAN_HASH         0x0000000d   /* VLAN Hash Table */
+#define XGMAC_DEBUG             0x0000000e   /* Debug */
+#define XGMAC_INT_STATUS        0x0000000f   /* Interrupt and Control */
+/* HASH table registers */
+#define XGMAC_HASH(n)           ((0x00000300/4) + (n))
+#define XGMAC_NUM_HASH          16
+/* Operation Mode */
+#define XGMAC_OPMODE            (0x00000400/4)
+/* Remote Wake-Up Frame Filter */
+#define XGMAC_REMOTE_WAKE       (0x00000700/4)
+/* PMT Control and Status */
+#define XGMAC_PMT               (0x00000704/4)
+
+#define XGMAC_ADDR_HIGH(reg)    (0x00000010+((reg) * 2))
+#define XGMAC_ADDR_LOW(reg)     (0x00000011+((reg) * 2))
+
+#define DMA_BUS_MODE            0x000003c0   /* Bus Mode */
+#define DMA_XMT_POLL_DEMAND     0x000003c1   /* Transmit Poll Demand */
+#define DMA_RCV_POLL_DEMAND     0x000003c2   /* Received Poll Demand */
+#define DMA_RCV_BASE_ADDR       0x000003c3   /* Receive List Base */
+#define DMA_TX_BASE_ADDR        0x000003c4   /* Transmit List Base */
+#define DMA_STATUS              0x000003c5   /* Status Register */
+#define DMA_CONTROL             0x000003c6   /* Ctrl (Operational Mode) */
+#define DMA_INTR_ENA            0x000003c7   /* Interrupt Enable */
+#define DMA_MISSED_FRAME_CTR    0x000003c8   /* Missed Frame Counter */
+/* Receive Interrupt Watchdog Timer */
+#define DMA_RI_WATCHDOG_TIMER   0x000003c9
+#define DMA_AXI_BUS             0x000003ca   /* AXI Bus Mode */
+#define DMA_AXI_STATUS          0x000003cb   /* AXI Status */
+#define DMA_CUR_TX_DESC_ADDR    0x000003d2   /* Current Host Tx Descriptor */
+#define DMA_CUR_RX_DESC_ADDR    0x000003d3   /* Current Host Rx Descriptor */
+#define DMA_CUR_TX_BUF_ADDR     0x000003d4   /* Current Host Tx Buffer */
+#define DMA_CUR_RX_BUF_ADDR     0x000003d5   /* Current Host Rx Buffer */
+#define DMA_HW_FEATURE          0x000003d6   /* Enabled Hardware Features */
+
+/* DMA Status register defines */
+#define DMA_STATUS_GMI          0x08000000   /* MMC interrupt */
+#define DMA_STATUS_GLI          0x04000000   /* GMAC Line interface int */
+#define DMA_STATUS_EB_MASK      0x00380000   /* Error Bits Mask */
+#define DMA_STATUS_EB_TX_ABORT  0x00080000   /* Error Bits - TX Abort */
+#define DMA_STATUS_EB_RX_ABORT  0x00100000   /* Error Bits - RX Abort */
+#define DMA_STATUS_TS_MASK      0x00700000   /* Transmit Process State */
+#define DMA_STATUS_TS_SHIFT     20
+#define DMA_STATUS_RS_MASK      0x000e0000   /* Receive Process State */
+#define DMA_STATUS_RS_SHIFT     17
+#define DMA_STATUS_NIS          0x00010000   /* Normal Interrupt Summary */
+#define DMA_STATUS_AIS          0x00008000   /* Abnormal Interrupt Summary */
+#define DMA_STATUS_ERI          0x00004000   /* Early Receive Interrupt */
+#define DMA_STATUS_FBI          0x00002000   /* Fatal Bus Error Interrupt */
+#define DMA_STATUS_ETI          0x00000400   /* Early Transmit Interrupt */
+#define DMA_STATUS_RWT          0x00000200   /* Receive Watchdog Timeout */
+#define DMA_STATUS_RPS          0x00000100   /* Receive Process Stopped */
+#define DMA_STATUS_RU           0x00000080   /* Receive Buffer Unavailable */
+#define DMA_STATUS_RI           0x00000040   /* Receive Interrupt */
+#define DMA_STATUS_UNF          0x00000020   /* Transmit Underflow */
+#define DMA_STATUS_OVF          0x00000010   /* Receive Overflow */
+#define DMA_STATUS_TJT          0x00000008   /* Transmit Jabber Timeout */
+#define DMA_STATUS_TU           0x00000004   /* Transmit Buffer Unavailable */
+#define DMA_STATUS_TPS          0x00000002   /* Transmit Process Stopped */
+#define DMA_STATUS_TI           0x00000001   /* Transmit Interrupt */
+
+/* DMA Control register defines */
+#define DMA_CONTROL_ST          0x00002000   /* Start/Stop Transmission */
+#define DMA_CONTROL_SR          0x00000002   /* Start/Stop Receive */
+#define DMA_CONTROL_DFF         0x01000000   /* Disable flush of rx frames */
+
+struct desc {
+    uint32_t ctl_stat;
+    uint16_t buffer1_size;
+    uint16_t buffer2_size;
+    uint32_t buffer1_addr;
+    uint32_t buffer2_addr;
+    uint32_t ext_stat;
+    uint32_t res[3];
+};
+
+#define R_MAX 0x400
+
+typedef struct RxTxStats {
+    uint64_t rx_bytes;
+    uint64_t tx_bytes;
+
+    uint64_t rx;
+    uint64_t rx_bcast;
+    uint64_t rx_mcast;
+} RxTxStats;
+
+typedef struct XgmacState {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    qemu_irq sbd_irq;
+    qemu_irq pmt_irq;
+    qemu_irq mci_irq;
+    NICState *nic;
+    NICConf conf;
+
+    struct RxTxStats stats;
+    uint32_t regs[R_MAX];
+} XgmacState;
+
+const VMStateDescription vmstate_rxtx_stats = {
+    .name = "xgmac_stats",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields      = (VMStateField[]) {
+        VMSTATE_UINT64(rx_bytes, RxTxStats),
+        VMSTATE_UINT64(tx_bytes, RxTxStats),
+        VMSTATE_UINT64(rx, RxTxStats),
+        VMSTATE_UINT64(rx_bcast, RxTxStats),
+        VMSTATE_UINT64(rx_mcast, RxTxStats),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static const VMStateDescription vmstate_xgmac = {
+    .name = "xgmac",
+    .version_id = 1,
+    .minimum_version_id = 1,
+    .fields = (VMStateField[]) {
+        VMSTATE_STRUCT(stats, XgmacState, 0, vmstate_rxtx_stats, RxTxStats),
+        VMSTATE_UINT32_ARRAY(regs, XgmacState, R_MAX),
+        VMSTATE_END_OF_LIST()
+    }
+};
+
+static void xgmac_read_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] :
+        s->regs[DMA_CUR_TX_DESC_ADDR];
+    cpu_physical_memory_read(addr, d, sizeof(*d));
+}
+
+static void xgmac_write_desc(struct XgmacState *s, struct desc *d, int rx)
+{
+    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
+    uint32_t addr = s->regs[reg];
+
+    if (!rx && (d->ctl_stat & 0x00200000)) {
+        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
+    } else if (rx && (d->buffer1_size & 0x8000)) {
+        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
+    } else {
+        s->regs[reg] += sizeof(*d);
+    }
+    cpu_physical_memory_write(addr, d, sizeof(*d));
+}
+
+static void xgmac_enet_send(struct XgmacState *s)
+{
+    struct desc bd;
+    int frame_size;
+    int len;
+    uint8_t frame[8192];
+    uint8_t *ptr;
+
+    ptr = frame;
+    frame_size = 0;
+    while (1) {
+        xgmac_read_desc(s, &bd, 0);
+        if ((bd.ctl_stat & 0x80000000) == 0) {
+            /* Run out of descriptors to transmit.  */
+            break;
+        }
+        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
+
+        if ((bd.buffer1_size & 0xfff) > 2048) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
+                         __func__, bd.buffer1_size & 0xfff);
+        }
+        if ((bd.buffer2_size & 0xfff) != 0) {
+            DEBUGF_BRK("qemu:%s:ERROR...ERROR...ERROR... -- "
+                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
+                        __func__, bd.buffer2_size & 0xfff);
+        }
+        if (len >= sizeof(frame)) {
+            DEBUGF_BRK("qemu:%s: buffer overflow %d read into %zu "
+                        "buffer\n" , __func__, len, sizeof(frame));
+            DEBUGF_BRK("qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
+                        __func__, bd.buffer1_size, bd.buffer2_size);
+        }
+
+        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
+        ptr += len;
+        frame_size += len;
+        if (bd.ctl_stat & 0x20000000) {
+            /* Last buffer in frame.  */
+            qemu_send_packet(&s->nic->nc, frame, len);
+            ptr = frame;
+            frame_size = 0;
+            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
+        }
+        bd.ctl_stat &= ~0x80000000;
+        /* Write back the modified descriptor.  */
+        xgmac_write_desc(s, &bd, 0);
+    }
+}
+
+static void enet_update_irq(struct XgmacState *s)
+{
+    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
+    qemu_set_irq(s->sbd_irq, !!stat);
+}
+
+static uint64_t enet_read(void *opaque, target_phys_addr_t addr, unsigned size)
+{
+    struct XgmacState *s = opaque;
+    uint64_t r = 0;
+    addr >>= 2;
+
+    switch (addr) {
+    case XGMAC_VERSION:
+        r = 0x1012;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            r = s->regs[addr];
+        }
+        break;
+    }
+    return r;
+}
+
+static void enet_write(void *opaque, target_phys_addr_t addr,
+                       uint64_t value, unsigned size)
+{
+    struct XgmacState *s = opaque;
+
+    addr >>= 2;
+    switch (addr) {
+    case DMA_BUS_MODE:
+        s->regs[DMA_BUS_MODE] = value & ~0x1;
+        break;
+    case DMA_XMT_POLL_DEMAND:
+        xgmac_enet_send(s);
+        break;
+    case DMA_STATUS:
+        s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
+        break;
+    case DMA_RCV_BASE_ADDR:
+        s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
+        break;
+    case DMA_TX_BASE_ADDR:
+        s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
+        break;
+    default:
+        if (addr < ARRAY_SIZE(s->regs)) {
+            s->regs[addr] = value;
+        }
+        break;
+    }
+    enet_update_irq(s);
+}
+
+static const MemoryRegionOps enet_mem_ops = {
+    .read = enet_read,
+    .write = enet_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static int eth_can_rx(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* RX enabled?  */
+    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
+}
+
+static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
+                                              0xff, 0xff, 0xff};
+    int unicast, broadcast, multicast;
+    struct desc bd;
+    ssize_t ret;
+
+    unicast = ~buf[0] & 0x1;
+    broadcast = memcmp(buf, sa_bcast, 6) == 0;
+    multicast = !unicast && !broadcast;
+    if (size < 12) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+        ret = -1;
+        goto out;
+    }
+
+    xgmac_read_desc(s, &bd, 1);
+    if ((bd.ctl_stat & 0x80000000) == 0) {
+        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
+        ret = size;
+        goto out;
+    }
+
+    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
+
+    /* Add in the 4 bytes for crc (the real hw returns length incl crc) */
+    size += 4;
+    bd.ctl_stat = (size << 16) | 0x300;
+    xgmac_write_desc(s, &bd, 1);
+
+    s->stats.rx_bytes += size;
+    s->stats.rx++;
+    if (multicast) {
+        s->stats.rx_mcast++;
+    } else if (broadcast) {
+        s->stats.rx_bcast++;
+    }
+
+    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
+    ret = size;
+
+out:
+    enet_update_irq(s);
+    return ret;
+}
+
+static void eth_cleanup(VLANClientState *nc)
+{
+    struct XgmacState *s = DO_UPCAST(NICState, nc, nc)->opaque;
+    s->nic = NULL;
+}
+
+static NetClientInfo net_xgmac_enet_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = eth_can_rx,
+    .receive = eth_rx,
+    .cleanup = eth_cleanup,
+};
+
+static int xgmac_enet_init(SysBusDevice *dev)
+{
+    struct XgmacState *s = FROM_SYSBUS(typeof(*s), dev);
+
+    memory_region_init_io(&s->iomem, &enet_mem_ops, s, "xgmac", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->sbd_irq);
+    sysbus_init_irq(dev, &s->pmt_irq);
+    sysbus_init_irq(dev, &s->mci_irq);
+
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
+
+    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) |
+                                   s->conf.macaddr.a[4];
+    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
+                                 (s->conf.macaddr.a[2] << 16) |
+                                 (s->conf.macaddr.a[1] << 8) |
+                                  s->conf.macaddr.a[0];
+
+    return 0;
+}
+
+static SysBusDeviceInfo xgmac_enet_info = {
+    .init = xgmac_enet_init,
+    .qdev.name  = "xgmac",
+    .qdev.size  = sizeof(struct XgmacState),
+    .qdev.vmsd = &vmstate_xgmac,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(struct XgmacState, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+static void xgmac_enet_register(void)
+{
+    sysbus_register_withprop(&xgmac_enet_info);
+}
+
+device_init(xgmac_enet_register)
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v12 2/4] ahci: add support for non-PCI based controllers
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 1/4] Add xgmac ethernet model Mark Langsdorf
@ 2012-01-19 21:30     ` Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 3/4] arm: add secondary cpu boot callbacks to arm_boot.c Mark Langsdorf
  2012-01-19 21:31     ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
  3 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 21:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Add support for ahci on sysbus.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
Reviewed-by: Andreas Färber <afaerber@suse.de>
---
Changes from v10
        None
Changes from v9
        Changed typedef struct names to CamelCase
Changes from v7, v8
        None
Changes from v5, v6
        Skipped
Changes from v4
        replaced all references to Plat|plat_ with sysbus_
        made the number of ports into a qdev property
        added dummy migration support
Changes from v3
        Renamed plat-ahci to sysbus-ahci
Changes from v1, v2
        Corrected indentation of PlatAHCIState members
        Made plat_ahci_info into a single structure, not a list

 hw/ide/ahci.c |   44 ++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 44 insertions(+), 0 deletions(-)

diff --git a/hw/ide/ahci.c b/hw/ide/ahci.c
index 0af201d..0309dd6 100644
--- a/hw/ide/ahci.c
+++ b/hw/ide/ahci.c
@@ -25,6 +25,7 @@
 #include <hw/msi.h>
 #include <hw/pc.h>
 #include <hw/pci.h>
+#include <hw/sysbus.h>
 
 #include "monitor.h"
 #include "dma.h"
@@ -1214,3 +1215,46 @@ void ahci_reset(void *opaque)
         ahci_reset_port(&d->ahci, i);
     }
 }
+
+typedef struct SysbusAHCIState {
+    SysBusDevice busdev;
+    AHCIState ahci;
+    uint32_t num_ports;
+} SysbusAHCIState;
+
+static const VMStateDescription vmstate_sysbus_ahci = {
+    .name = "sysbus-ahci",
+    .unmigratable = 1,
+};
+
+static int sysbus_ahci_init(SysBusDevice *dev)
+{
+    SysbusAHCIState *s = FROM_SYSBUS(SysbusAHCIState, dev);
+    ahci_init(&s->ahci, &dev->qdev, s->num_ports);
+
+    sysbus_init_mmio(dev, &s->ahci.mem);
+    sysbus_init_irq(dev, &s->ahci.irq);
+
+    qemu_register_reset(ahci_reset, &s->ahci);
+    return 0;
+}
+
+static SysBusDeviceInfo sysbus_ahci_info = {
+    .qdev.name    = "sysbus-ahci",
+    .qdev.size    = sizeof(SysbusAHCIState),
+    .qdev.vmsd    = &vmstate_sysbus_ahci,
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_UINT32("num-ports", SysbusAHCIState, num_ports, 1),
+        DEFINE_PROP_END_OF_LIST(),
+    },
+    .init         = sysbus_ahci_init,
+
+
+};
+
+static void sysbus_ahci_register(void)
+{
+    sysbus_register_withprop(&sysbus_ahci_info);
+}
+
+device_init(sysbus_ahci_register);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v12 3/4] arm: add secondary cpu boot callbacks to arm_boot.c
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 1/4] Add xgmac ethernet model Mark Langsdorf
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 2/4] ahci: add support for non-PCI based controllers Mark Langsdorf
@ 2012-01-19 21:30     ` Mark Langsdorf
  2012-01-19 21:31     ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
  3 siblings, 0 replies; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 21:30 UTC (permalink / raw)
  To: qemu-devel
  Cc: i.mitsyanko, peter.maydell, afaerber, mark.langsdorf, edgar.iglesias

Create two functions, write_secondary_boot() and secondary_cpu_reset_hook(),
to allow platforms more control of how secondary CPUs are brought up. The
new functions default to NULL and aren't called unless they are populated
so there are no changes to existing platform models.

Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v11
	Corrected typo in subject
	expanded and corrected some documentation
	moved the default_ functions nearer to smpboot array
Changes from v2-v10
        Skipped
Changes from v1
        Added default versions of the functions
        Created checks so that NULL function entries became default versions
        Simplified calls to the secondary boot functions
        Added comments on the use of these functions

 hw/arm-misc.h |   17 +++++++++++++++++
 hw/arm_boot.c |   54 +++++++++++++++++++++++++++++++++++++++++++-----------
 2 files changed, 60 insertions(+), 11 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b..5e5204b 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -30,12 +30,29 @@ struct arm_boot_info {
     const char *kernel_cmdline;
     const char *initrd_filename;
     target_phys_addr_t loader_start;
+    /* multicore boards that use the default secondary core boot functions
+     * need to put the address of the secondary boot code, the boot reg,
+     * and the GIC address in the next 3 values, respectively. boards that
+     * have their own boot functions can use these values as they want.
+     */
     target_phys_addr_t smp_loader_start;
     target_phys_addr_t smp_bootreg_addr;
     target_phys_addr_t smp_priv_base;
     int nb_cpus;
     int board_id;
     int (*atag_board)(const struct arm_boot_info *info, void *p);
+    /* multicore boards that use the default secondary core boot functions
+     * can ignore these two function calls. If the default functions won't
+     * work, then write_secondary_boot() should write a suitable blob of
+     * code mimicing the secondary CPU startup process used by the board's
+     * boot loader/boot ROM code, and secondary_cpu_reset_hook() should
+     * perform any necessary CPU reset handling and set the PC for thei
+     * secondary CPUs to point at this boot blob.
+     */
+    void (*write_secondary_boot)(CPUState *env,
+                                 const struct arm_boot_info *info);
+    void (*secondary_cpu_reset_hook)(CPUState *env,
+                                     const struct arm_boot_info *info);
     /* Used internally by arm_boot.c */
     int is_linux;
     target_phys_addr_t initrd_size;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8..35ca22f 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -28,8 +28,20 @@ static uint32_t bootloader[] = {
   0  /* Kernel entry point.  Set by integratorcp_init.  */
 };
 
-/* Entry point for secondary CPUs.  Enable interrupt controller and
-   Issue WFI until start address is written to system controller.  */
+/* Handling for secondary CPU boot in a multicore system.
+ * Unlike the uniprocessor/primary CPU boot, this is platform
+ * dependent. The default code here is based on the secondary
+ * CPU boot protocol used on realview/vexpress boards, with
+ * some parameterisation to increase its flexibility.
+ * QEMU platform models for which this code is not appropriate
+ * should override write_secondary_boot and secondary_cpu_reset_hook
+ * instead.
+ *
+ * This code enables the interrupt controllers for the secondary
+ * CPUs and then puts all the secondary CPUs into a loop waiting
+ * for an interprocessor interrupt and polling a configurable
+ * location for the kernel secondary CPU entry point.
+ */
 static uint32_t smpboot[] = {
   0xe59f201c, /* ldr r2, privbase */
   0xe59f001c, /* ldr r0, startaddr */
@@ -44,6 +56,26 @@ static uint32_t smpboot[] = {
   0           /* bootreg: Boot register address is held here */
 };
 
+static void default_write_secondary(CPUState *env,
+                                    const struct arm_boot_info *info)
+{
+    int n;
+    smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
+    smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
+                       info->smp_loader_start);
+}
+
+static void default_reset_secondary(CPUState *env,
+                                    const struct arm_boot_info *info)
+{
+    stl_phys_notdirty(info->smp_bootreg_addr, 0);
+    env->regs[15] = info->smp_loader_start;
+}
+
 #define WRITE_WORD(p, value) do { \
     stl_phys_notdirty(p, value);  \
     p += 4;                       \
@@ -197,8 +229,7 @@ static void do_cpu_reset(void *opaque)
                                     info->loader_start);
                 }
             } else {
-                stl_phys_notdirty(info->smp_bootreg_addr, 0);
-                env->regs[15] = info->smp_loader_start;
+                info->secondary_cpu_reset_hook(env, info);
             }
         }
     }
@@ -220,6 +251,13 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         exit(1);
     }
 
+    if (!info->secondary_cpu_reset_hook) {
+        info->secondary_cpu_reset_hook = default_reset_secondary;
+    }
+    if (!info->write_secondary_boot) {
+        info->write_secondary_boot = default_write_secondary;
+    }
+
     if (info->nb_cpus == 0)
         info->nb_cpus = 1;
 
@@ -273,13 +311,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
         rom_add_blob_fixed("bootloader", bootloader, sizeof(bootloader),
                            info->loader_start);
         if (info->nb_cpus > 1) {
-            smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
-            smpboot[ARRAY_SIZE(smpboot) - 2] = info->smp_priv_base;
-            for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
-                smpboot[n] = tswap32(smpboot[n]);
-            }
-            rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
-                               info->smp_loader_start);
+            info->write_secondary_boot(env, info);
         }
         info->initrd_size = initrd_size;
     }
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
                       ` (2 preceding siblings ...)
  2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 3/4] arm: add secondary cpu boot callbacks to arm_boot.c Mark Langsdorf
@ 2012-01-19 21:31     ` Mark Langsdorf
  2012-01-19 21:44       ` Peter Maydell
  3 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-19 21:31 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, mark.langsdorf, i.mitsyanko, Rob Herring,
	edgar.iglesias, afaerber

From: Rob Herring <rob.herring@calxeda.com>

Adds support for Calxeda's Highbank SoC.

Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Signed-off-by: Mark Langsdorf <mark.langsdorf@calxeda.com>
---
Changes from v11
 	Provided a meaningful board ID
	Added comments on the way the device tree memory values interact with
qemu command line arguments for memory
Changes from v10
        Added secondary core boot functions
Changes from v9
        Made typedef struct names in CamelCase
Changes from v7, v8
        None
Changes from v3, v4, v5, v6
        Skipped
Changes from v2
        Created a reset function for highbank_regs
        Handled creation of regs i/o memory region in a sensible manner
        Added code to boot secondary CPUs properly
Changes from v1
        Restructed the loading of sysram.bin and made it more clearly optional
        Made the regs structure into a proper qdev/sysbus object
        Removed some unnecessary include files
        Clarified the GPL version
        Simplified the reset function
        Removed the automatic detection and resetting of ram_size. Image MUST
be loaded with -m 4089 or it will crash
        Added a guard for xgmac creation
        Added a fuller description in the QEMUMachine .desc field

 Makefile.target |    1 +
 hw/highbank.c   |  327 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 328 insertions(+), 0 deletions(-)
 create mode 100644 hw/highbank.c

diff --git a/Makefile.target b/Makefile.target
index 9bc0248..1c86522 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -342,6 +342,7 @@ obj-arm-y += realview_gic.o realview.o arm_sysctl.o arm11mpcore.o a9mpcore.o
 obj-arm-y += arm_l2x0.o
 obj-arm-y += arm_mptimer.o
 obj-arm-y += armv7m.o armv7m_nvic.o stellaris.o pl022.o stellaris_enet.o
+obj-arm-y += highbank.o
 obj-arm-y += pl061.o
 obj-arm-y += xgmac.o
 obj-arm-y += arm-semi.o
diff --git a/hw/highbank.c b/hw/highbank.c
new file mode 100644
index 0000000..a79d0e8
--- /dev/null
+++ b/hw/highbank.c
@@ -0,0 +1,327 @@
+/*
+ * Calxeda Highbank SoC emulation
+ *
+ * Copyright (c) 2010-2012 Calxeda
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "sysbus.h"
+#include "arm-misc.h"
+#include "primecell.h"
+#include "devices.h"
+#include "loader.h"
+#include "net.h"
+#include "sysemu.h"
+#include "boards.h"
+#include "sysbus.h"
+#include "blockdev.h"
+#include "exec-memory.h"
+
+#define SMP_BOOT_ADDR 0x100
+#define SMP_BOOT_REG  0x40
+#define GIC_BASE_ADDR 0xfff10000
+
+#define NIRQ_GIC      160
+
+/* Board init.  */
+static void highbank_cpu_reset(void *opaque)
+{
+    CPUState *env = opaque;
+
+    env->cp15.c15_config_base_address = 0xfff10000;
+}
+
+static void hb_write_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+    int n;
+    uint32_t smpboot[] = {
+        0xee100fb0, /* mrc p15, 0, r0, c0, c0, 5 - read current core id */
+        0xe210000f, /* ands r0, r0, #0x0f */
+        0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
+        0xe0830200, /* add r0, r3, r0, lsl #4 */
+        0xe59f2018, /* ldr r2, privbase */
+        0xe3a01001, /* mov r1, #1 */
+        0xe5821100, /* str r1, [r2, #256] */
+        0xe320f003, /* wfi */
+        0xe5901000, /* ldr     r1, [r0] */
+        0xe1110001, /* tst     r1, r1 */
+        0x0afffffb, /* beq     <wfi> */
+        0xe12fff11, /* bx      r1 */
+        GIC_BASE_ADDR      /* privbase: gic address.  */
+    };
+    for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+        smpboot[n] = tswap32(smpboot[n]);
+    }
+    rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot), SMP_BOOT_ADDR);
+}
+
+static void hb_reset_secondary(CPUState *env, const struct arm_boot_info *info)
+{
+    switch (info->nb_cpus) {
+    case 4:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x30, 0);
+    case 3:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x20, 0);
+    case 2:
+        stl_phys_notdirty(SMP_BOOT_REG + 0x10, 0);
+        env->regs[15] = SMP_BOOT_ADDR;
+        break;
+    default:
+        break;
+    }
+}
+
+#define NUM_REGS      0x200
+static void hb_regs_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uint32_t *regs = opaque;
+
+    if (offset == 0xf00) {
+        if (value == 1 || value == 2) {
+            qemu_system_reset_request();
+        } else if (value == 3) {
+            qemu_system_shutdown_request();
+        }
+    }
+
+    regs[offset/4] = value;
+}
+
+static uint64_t hb_regs_read(void *opaque, target_phys_addr_t offset,
+                             unsigned size)
+{
+    uint32_t *regs = opaque;
+    uint32_t value = regs[offset/4];
+
+    if ((offset == 0x100) || (offset == 0x108) || (offset == 0x10C)) {
+        value |= 0x30000000;
+    }
+
+    return value;
+}
+
+static const MemoryRegionOps hb_mem_ops = {
+    .read = hb_regs_read,
+    .write = hb_regs_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion *iomem;
+    uint32_t regs[NUM_REGS];
+} HighbankRegsState;
+
+static VMStateDescription vmstate_highbank_regs = {
+    .name = "highbank-regs",
+    .version_id = 0,
+    .minimum_version_id = 0,
+    .minimum_version_id_old = 0,
+    .fields = (VMStateField[]) {
+        VMSTATE_UINT32_ARRAY(regs, HighbankRegsState, NUM_REGS),
+        VMSTATE_END_OF_LIST(),
+    },
+};
+
+static void highbank_regs_reset(DeviceState *dev)
+{
+    SysBusDevice *sys_dev = sysbus_from_qdev(dev);
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, sys_dev);
+
+    s->regs[0x40] = 0x05F20121;
+    s->regs[0x41] = 0x2;
+    s->regs[0x42] = 0x05F30121;
+    s->regs[0x43] = 0x05F40121;
+}
+
+static int highbank_regs_init(SysBusDevice *dev)
+{
+    HighbankRegsState *s = FROM_SYSBUS(HighbankRegsState, dev);
+
+    s->iomem = g_new(MemoryRegion, 1);
+    memory_region_init_io(s->iomem, &hb_mem_ops, s->regs, "highbank_regs",
+                          0x1000);
+    sysbus_init_mmio(dev, s->iomem);
+
+    return 0;
+}
+
+static SysBusDeviceInfo highbank_regs_info = {
+    .init       = highbank_regs_init,
+    .qdev.name  = "highbank-regs",
+    .qdev.desc  = "Calxeda Highbank registers",
+    .qdev.size  = sizeof(HighbankRegsState),
+    .qdev.vmsd  = &vmstate_highbank_regs,
+    .qdev.reset = highbank_regs_reset,
+};
+
+static void highbank_regs_register_device(void)
+{
+    sysbus_register_withprop(&highbank_regs_info);
+}
+
+device_init(highbank_regs_register_device)
+
+static struct arm_boot_info highbank_binfo;
+
+/* ram_size must be set to match the upper bound of memory in the
+ * device tree (linux/arch/arm/boot/dts/highbank.dts), which is
+ * normally 0xff900000 or -m 4089. When running this board on a
+ * 32-bit host, set the reg value of memory to 0xf7ff00000 in the
+ * device tree and pass -m 2047
+ */
+static void highbank_init(ram_addr_t ram_size,
+                     const char *boot_device,
+                     const char *kernel_filename, const char *kernel_cmdline,
+                     const char *initrd_filename, const char *cpu_model)
+{
+    CPUState *env = NULL;
+    DeviceState *dev;
+    SysBusDevice *busdev;
+    qemu_irq *irqp;
+    qemu_irq pic[128];
+    int n;
+    qemu_irq cpu_irq[4];
+    MemoryRegion *sysram;
+    MemoryRegion *dram;
+    MemoryRegion *sysmem;
+    char *sysboot_filename;
+
+    if (!cpu_model) {
+        cpu_model = "cortex-a9";
+    }
+
+    for (n = 0; n < smp_cpus; n++) {
+        env = cpu_init(cpu_model);
+        if (!env) {
+            fprintf(stderr, "Unable to find CPU definition\n");
+            exit(1);
+        }
+        irqp = arm_pic_init_cpu(env);
+        cpu_irq[n] = irqp[ARM_PIC_CPU_IRQ];
+        qemu_register_reset(highbank_cpu_reset, env);
+    }
+
+    sysmem = get_system_memory();
+    dram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(dram, "highbank.dram", ram_size);
+    /* SDRAM at address zero.  */
+    memory_region_add_subregion(sysmem, 0, dram);
+
+    sysram = g_new(MemoryRegion, 1);
+    memory_region_init_ram(sysram, "highbank.sysram", 0x8000);
+    memory_region_add_subregion(sysmem, 0xfff88000, sysram);
+    if (bios_name != NULL) {
+        sysboot_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
+        if (sysboot_filename != NULL) {
+            uint32_t filesize = get_image_size(sysboot_filename);
+            if (load_image_targphys("sysram.bin", 0xfff88000, filesize) < 0) {
+                hw_error("Unable to load %s\n", bios_name);
+            }
+        } else {
+           hw_error("Unable to find %s\n", bios_name);
+        }
+    }
+
+    dev = qdev_create(NULL, "a9mpcore_priv");
+    qdev_prop_set_uint32(dev, "num-cpu", smp_cpus);
+    qdev_prop_set_uint32(dev, "num-irq", NIRQ_GIC);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, GIC_BASE_ADDR);
+    for (n = 0; n < smp_cpus; n++) {
+        sysbus_connect_irq(busdev, n, cpu_irq[n]);
+    }
+
+    for (n = 0; n < 128; n++) {
+        pic[n] = qdev_get_gpio_in(dev, n);
+    }
+
+    dev = qdev_create(NULL, "l2x0");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff12000);
+
+    dev = qdev_create(NULL, "sp804");
+    qdev_prop_set_uint32(dev, "freq0", 150000000);
+    qdev_prop_set_uint32(dev, "freq1", 150000000);
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff34000);
+    sysbus_connect_irq(busdev, 0, pic[18]);
+    sysbus_create_simple("pl011", 0xfff36000, pic[20]);
+
+    dev = qdev_create(NULL, "highbank-regs");
+    qdev_init_nofail(dev);
+    busdev = sysbus_from_qdev(dev);
+    sysbus_mmio_map(busdev, 0, 0xfff3c000);
+
+    sysbus_create_simple("pl061", 0xfff30000, pic[14]);
+    sysbus_create_simple("pl061", 0xfff31000, pic[15]);
+    sysbus_create_simple("pl061", 0xfff32000, pic[16]);
+    sysbus_create_simple("pl061", 0xfff33000, pic[17]);
+    sysbus_create_simple("pl031", 0xfff35000, pic[19]);
+    sysbus_create_simple("pl022", 0xfff39000, pic[23]);
+
+    sysbus_create_simple("sysbus-ahci", 0xffe08000, pic[83]);
+
+    if (nd_table[0].vlan) {
+        qemu_check_nic_model(&nd_table[0], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[0]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff50000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[77]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[78]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[79]);
+
+        qemu_check_nic_model(&nd_table[1], "xgmac");
+        dev = qdev_create(NULL, "xgmac");
+        qdev_set_nic_properties(dev, &nd_table[1]);
+        qdev_init_nofail(dev);
+        sysbus_mmio_map(sysbus_from_qdev(dev), 0, 0xfff51000);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 0, pic[80]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 1, pic[81]);
+        sysbus_connect_irq(sysbus_from_qdev(dev), 2, pic[82]);
+    }
+
+    highbank_binfo.ram_size = ram_size;
+    highbank_binfo.kernel_filename = kernel_filename;
+    highbank_binfo.kernel_cmdline = kernel_cmdline;
+    highbank_binfo.initrd_filename = initrd_filename;
+    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
+    highbank_binfo.nb_cpus = smp_cpus;
+    highbank_binfo.loader_start = 0;
+    highbank_binfo.write_secondary_boot = hb_write_secondary;
+    highbank_binfo.secondary_cpu_reset_hook = hb_reset_secondary;
+    arm_load_kernel(first_cpu, &highbank_binfo);
+}
+
+static QEMUMachine highbank_machine = {
+    .name = "highbank",
+    .desc = "Calxeda Highbank (ECX-1000)",
+    .init = highbank_init,
+    .use_scsi = 1,
+    .max_cpus = 4,
+    .no_vga = 1,
+};
+
+static void highbank_machine_init(void)
+{
+    qemu_register_machine(&highbank_machine);
+}
+
+machine_init(highbank_machine_init);
-- 
1.7.5.4

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-19 21:31     ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-19 21:44       ` Peter Maydell
  2012-01-19 23:17         ` Rob Herring
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-19 21:44 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Rob Herring, afaerber

On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */

Where does this number come from? It's not in
http://www.arm.linux.org.uk/developer/machines/

Is 3027 (==0xbd3) you?
http://www.arm.linux.org.uk/developer/machines/list.php?id=3027

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-19 21:44       ` Peter Maydell
@ 2012-01-19 23:17         ` Rob Herring
  2012-01-19 23:41           ` John Williams
  2012-01-20  8:47           ` Peter Maydell
  0 siblings, 2 replies; 147+ messages in thread
From: Rob Herring @ 2012-01-19 23:17 UTC (permalink / raw)
  To: Peter Maydell
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Mark Langsdorf, afaerber

On 01/19/2012 03:44 PM, Peter Maydell wrote:
> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
> 
> Where does this number come from? It's not in
> http://www.arm.linux.org.uk/developer/machines/
> 
> Is 3027 (==0xbd3) you?
> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>

Much of the data there is wrong as none of it is used. 0 or -1 is the
right value as those are obviously meaningless. A highbank kernel will
never be booted without devicetree and in that case this number is
irrelevant. This is the legacy boot interface and qemu really needs to
learn to boot with a separate dtb.

Rob

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-19 23:17         ` Rob Herring
@ 2012-01-19 23:41           ` John Williams
  2012-01-20  8:47           ` Peter Maydell
  1 sibling, 0 replies; 147+ messages in thread
From: John Williams @ 2012-01-19 23:41 UTC (permalink / raw)
  To: Rob Herring
  Cc: Peter Maydell, Mark Langsdorf, i.mitsyanko, qemu-devel,
	Peter Crosthwaite, edgar.iglesias, afaerber

[-- Attachment #1: Type: text/plain, Size: 1501 bytes --]

On Fri, Jan 20, 2012 at 9:17 AM, Rob Herring <rob.herring@calxeda.com>wrote:

> On 01/19/2012 03:44 PM, Peter Maydell wrote:
> > On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com>
> wrote:
> >> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
> >
> > Where does this number come from? It's not in
> > http://www.arm.linux.org.uk/developer/machines/
> >
> > Is 3027 (==0xbd3) you?
> > http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
> >
>
> Much of the data there is wrong as none of it is used. 0 or -1 is the
> right value as those are obviously meaningless. A highbank kernel will
> never be booted without devicetree and in that case this number is
> irrelevant. This is the legacy boot interface and qemu really needs to
> learn to boot with a separate dtb.
>

We partially addressed this issue in our rejected device tree machine model
patch series from last year.  We added two new DTB-related arguments to the
qemu cmdline:

--kernel-dtb which is the DTB that gets passed through to the kernel, and
--hw-dtb which is the DTB describing the actual hardware (we were making
QDEV system models by scanning and parsing the device tree)

If only a HW DTB is provided, then that same DTB is used for the kernel.
 There are situations when you might want them to be different.

Rgds,

John

-- 
John Williams, PhD, B. Eng, B. IT
PetaLogix - Linux Solutions for a Reconfigurable World
w: www.petalogix.com  p: +61-7-30090663  f: +61-7-30090663

[-- Attachment #2: Type: text/html, Size: 2323 bytes --]

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-19 23:17         ` Rob Herring
  2012-01-19 23:41           ` John Williams
@ 2012-01-20  8:47           ` Peter Maydell
  2012-01-20 13:48             ` Rob Herring
  1 sibling, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-20  8:47 UTC (permalink / raw)
  To: Rob Herring
  Cc: i.mitsyanko, edgar.iglesias, qemu-devel, Mark Langsdorf, afaerber

On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
> On 01/19/2012 03:44 PM, Peter Maydell wrote:
>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
>>
>> Where does this number come from? It's not in
>> http://www.arm.linux.org.uk/developer/machines/
>>
>> Is 3027 (==0xbd3) you?
>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>>
>
> Much of the data there is wrong as none of it is used. 0 or -1 is the
> right value as those are obviously meaningless. A highbank kernel will
> never be booted without devicetree and in that case this number is
> irrelevant. This is the legacy boot interface and qemu really needs to
> learn to boot with a separate dtb.

Yeah, but the documentation even for DTB boot says we should pass
in a machine number. If 0 or -1 are right then there should be
some documentation that says so. I'll accept "mailing list post
from some authoritative person [eg Grant Likely]" if necessary.
But this is an ABI between boot loaders and the kernel so I don't
want to just have something random that happens to work. (And in
particular if -1 is the officially sanctioned number then we need
to fix arm_boot to be able to pass values >16 bits wide.)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20  8:47           ` Peter Maydell
@ 2012-01-20 13:48             ` Rob Herring
  2012-01-20 13:57               ` Peter Maydell
                                 ` (2 more replies)
  0 siblings, 3 replies; 147+ messages in thread
From: Rob Herring @ 2012-01-20 13:48 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Mark Langsdorf, i.mitsyanko, qemu-devel, Grant Likely,
	edgar.iglesias, afaerber

On 01/20/2012 02:47 AM, Peter Maydell wrote:
> On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
>> On 01/19/2012 03:44 PM, Peter Maydell wrote:
>>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
>>>
>>> Where does this number come from? It's not in
>>> http://www.arm.linux.org.uk/developer/machines/
>>>
>>> Is 3027 (==0xbd3) you?
>>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>>>
>>
>> Much of the data there is wrong as none of it is used. 0 or -1 is the
>> right value as those are obviously meaningless. A highbank kernel will
>> never be booted without devicetree and in that case this number is
>> irrelevant. This is the legacy boot interface and qemu really needs to
>> learn to boot with a separate dtb.
> 
> Yeah, but the documentation even for DTB boot says we should pass
> in a machine number. If 0 or -1 are right then there should be
> some documentation that says so. I'll accept "mailing list post
> from some authoritative person [eg Grant Likely]" if necessary.

Kernel DT co-maintainer is not authoritative enough for you?

The documentation needs some clarification.

> But this is an ABI between boot loaders and the kernel so I don't
> want to just have something random that happens to work. (And in
> particular if -1 is the officially sanctioned number then we need
> to fix arm_boot to be able to pass values >16 bits wide.)
> 

Here's were the kernel sets the mach #. nr is from the database for
non-DT and ~0 for DT machines.

#define MACHINE_START(_type,_name)                      \
static const struct machine_desc __mach_desc_##_type    \
 __used                                                 \
 __attribute__((__section__(".arch.info.init"))) = {    \
        .nr             = MACH_TYPE_##_type,            \
        .name           = _name,

#define MACHINE_END                             \
};

#define DT_MACHINE_START(_name, _namestr)               \
static const struct machine_desc __mach_desc_##_name    \
 __used                                                 \
 __attribute__((__section__(".arch.info.init"))) = {    \
        .nr             = ~0,                           \
        .name           = _namestr,

In any case, the kernel ignores the value passed in if a valid dtb is
passed in.

Rob

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 13:48             ` Rob Herring
@ 2012-01-20 13:57               ` Peter Maydell
  2012-01-20 18:27                 ` Grant Likely
  2012-01-20 16:25               ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
  2012-01-20 18:25               ` Grant Likely
  2 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-20 13:57 UTC (permalink / raw)
  To: Rob Herring
  Cc: Mark Langsdorf, i.mitsyanko, qemu-devel, Grant Likely,
	edgar.iglesias, afaerber

On 20 January 2012 13:48, Rob Herring <rob.herring@calxeda.com> wrote:
> Kernel DT co-maintainer is not authoritative enough for you?

Only if I recognise their name :-) [ie, sorry.]

> The documentation needs some clarification.
>
>> But this is an ABI between boot loaders and the kernel so I don't
>> want to just have something random that happens to work. (And in
>> particular if -1 is the officially sanctioned number then we need
>> to fix arm_boot to be able to pass values >16 bits wide.)
>>
>
> Here's were the kernel sets the mach #. nr is from the database for
> non-DT and ~0 for DT machines.
>
> #define MACHINE_START(_type,_name)                      \
> static const struct machine_desc __mach_desc_##_type    \
>  __used                                                 \
>  __attribute__((__section__(".arch.info.init"))) = {    \
>        .nr             = MACH_TYPE_##_type,            \
>        .name           = _name,
>
> #define MACHINE_END                             \
> };
>
> #define DT_MACHINE_START(_name, _namestr)               \
> static const struct machine_desc __mach_desc_##_name    \
>  __used                                                 \
>  __attribute__((__section__(".arch.info.init"))) = {    \
>        .nr             = ~0,                           \
>        .name           = _namestr,
>
> In any case, the kernel ignores the value passed in if a valid dtb is
> passed in.

I wonder if we should be passing in anything-except-minus-1,
since if you pass -1 and no DT then the kernel will fail
silently, whereas if you pass something else and no DT the
kernel will complain about the mismatch.

Even when we add a --dtb foo option to qemu, there's bound
to be a pile of user error where users pass in --kernel but
not --dtb.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 13:48             ` Rob Herring
  2012-01-20 13:57               ` Peter Maydell
@ 2012-01-20 16:25               ` Mark Langsdorf
  2012-01-20 16:27                 ` Peter Maydell
  2012-01-20 18:25               ` Grant Likely
  2 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-20 16:25 UTC (permalink / raw)
  To: Rob Herring
  Cc: Peter Maydell, i.mitsyanko, qemu-devel, Grant Likely,
	edgar.iglesias, afaerber

On 01/20/2012 07:48 AM, Rob Herring wrote:
> On 01/20/2012 02:47 AM, Peter Maydell wrote:
>> On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
>>> On 01/19/2012 03:44 PM, Peter Maydell wrote:
>>>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
>>>>
>>>> Where does this number come from? It's not in
>>>> http://www.arm.linux.org.uk/developer/machines/
>>>>
>>>> Is 3027 (==0xbd3) you?
>>>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>>>>
>>>
>>> Much of the data there is wrong as none of it is used. 0 or -1 is the
>>> right value as those are obviously meaningless. A highbank kernel will
>>> never be booted without devicetree and in that case this number is
>>> irrelevant. This is the legacy boot interface and qemu really needs to
>>> learn to boot with a separate dtb.
>>
>> Yeah, but the documentation even for DTB boot says we should pass
>> in a machine number. If 0 or -1 are right then there should be
>> some documentation that says so. I'll accept "mailing list post
>> from some authoritative person [eg Grant Likely]" if necessary.
> 
> Kernel DT co-maintainer is not authoritative enough for you?

Peter, is that sufficient for me to send in the patch with a
board_id of -1? Thanks.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 16:25               ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-20 16:27                 ` Peter Maydell
  2012-01-20 16:57                   ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-20 16:27 UTC (permalink / raw)
  To: Mark Langsdorf
  Cc: i.mitsyanko, qemu-devel, Rob Herring, Grant Likely,
	edgar.iglesias, afaerber

On 20 January 2012 16:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/20/2012 07:48 AM, Rob Herring wrote:
>> On 01/20/2012 02:47 AM, Peter Maydell wrote:
>>> On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
>>>> On 01/19/2012 03:44 PM, Peter Maydell wrote:
>>>>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
>>>>>
>>>>> Where does this number come from? It's not in
>>>>> http://www.arm.linux.org.uk/developer/machines/
>>>>>
>>>>> Is 3027 (==0xbd3) you?
>>>>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>>>>>
>>>>
>>>> Much of the data there is wrong as none of it is used. 0 or -1 is the
>>>> right value as those are obviously meaningless. A highbank kernel will
>>>> never be booted without devicetree and in that case this number is
>>>> irrelevant. This is the legacy boot interface and qemu really needs to
>>>> learn to boot with a separate dtb.
>>>
>>> Yeah, but the documentation even for DTB boot says we should pass
>>> in a machine number. If 0 or -1 are right then there should be
>>> some documentation that says so. I'll accept "mailing list post
>>> from some authoritative person [eg Grant Likely]" if necessary.
>>
>> Kernel DT co-maintainer is not authoritative enough for you?
>
> Peter, is that sufficient for me to send in the patch with a
> board_id of -1? Thanks.

It's still not clear to me from this conversation if the right
answer is "0", "-1" or "anything that's not a valid board ID
and not -1 either"...

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 16:27                 ` Peter Maydell
@ 2012-01-20 16:57                   ` Mark Langsdorf
  2012-01-20 16:58                     ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-20 16:57 UTC (permalink / raw)
  To: qemu-devel

On 01/20/2012 10:27 AM, Peter Maydell wrote:
> On 20 January 2012 16:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/20/2012 07:48 AM, Rob Herring wrote:
>>> On 01/20/2012 02:47 AM, Peter Maydell wrote:
>>>> On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
>>>>> On 01/19/2012 03:44 PM, Peter Maydell wrote:
>>>>>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>>>>>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
>>>>>>
>>>>>> Where does this number come from? It's not in
>>>>>> http://www.arm.linux.org.uk/developer/machines/
>>>>>>
>>>>>> Is 3027 (==0xbd3) you?
>>>>>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
>>>>>>
>>>>>
>>>>> Much of the data there is wrong as none of it is used. 0 or -1 is the
>>>>> right value as those are obviously meaningless. A highbank kernel will
>>>>> never be booted without devicetree and in that case this number is
>>>>> irrelevant. This is the legacy boot interface and qemu really needs to
>>>>> learn to boot with a separate dtb.
>>>>
>>>> Yeah, but the documentation even for DTB boot says we should pass
>>>> in a machine number. If 0 or -1 are right then there should be
>>>> some documentation that says so. I'll accept "mailing list post
>>>> from some authoritative person [eg Grant Likely]" if necessary.
>>>
>>> Kernel DT co-maintainer is not authoritative enough for you?
>>
>> Peter, is that sufficient for me to send in the patch with a
>> board_id of -1? Thanks.
> 
> It's still not clear to me from this conversation if the right
> answer is "0", "-1" or "anything that's not a valid board ID
> and not -1 either"...

Quoting Rob from upthread:
"0 or -1 is the right value as those are obviously meaningless."

The original code that Rob wrote had a board_id of -1. That's
the right answer.

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 16:57                   ` Mark Langsdorf
@ 2012-01-20 16:58                     ` Peter Maydell
  2012-01-20 19:25                       ` Mark Langsdorf
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-20 16:58 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel

On 20 January 2012 16:57, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> On 01/20/2012 10:27 AM, Peter Maydell wrote:
>> It's still not clear to me from this conversation if the right
>> answer is "0", "-1" or "anything that's not a valid board ID
>> and not -1 either"...
>
> Quoting Rob from upthread:
> "0 or -1 is the right value as those are obviously meaningless."
>
> The original code that Rob wrote had a board_id of -1. That's
> the right answer.

In that case you need a patch that causes arm_boot to actually
pass -1, not 0xffff.

(Also it would be nice if the kernel barfed if (id == -1 and
there's no appended device tree), but that's not a qemu thing.)

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 13:48             ` Rob Herring
  2012-01-20 13:57               ` Peter Maydell
  2012-01-20 16:25               ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
@ 2012-01-20 18:25               ` Grant Likely
  2 siblings, 0 replies; 147+ messages in thread
From: Grant Likely @ 2012-01-20 18:25 UTC (permalink / raw)
  To: Rob Herring
  Cc: Peter Maydell, Mark Langsdorf, i.mitsyanko, qemu-devel,
	edgar.iglesias, afaerber

On Fri, Jan 20, 2012 at 07:48:09AM -0600, Rob Herring wrote:
> On 01/20/2012 02:47 AM, Peter Maydell wrote:
> > On 19 January 2012 23:17, Rob Herring <rob.herring@calxeda.com> wrote:
> >> On 01/19/2012 03:44 PM, Peter Maydell wrote:
> >>> On 19 January 2012 21:31, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> >>>> +    highbank_binfo.board_id = 0xEC10100f; /* provided by deviceTree */
> >>>
> >>> Where does this number come from? It's not in
> >>> http://www.arm.linux.org.uk/developer/machines/
> >>>
> >>> Is 3027 (==0xbd3) you?
> >>> http://www.arm.linux.org.uk/developer/machines/list.php?id=3027
> >>>
> >>
> >> Much of the data there is wrong as none of it is used. 0 or -1 is the
> >> right value as those are obviously meaningless. A highbank kernel will
> >> never be booted without devicetree and in that case this number is
> >> irrelevant. This is the legacy boot interface and qemu really needs to
> >> learn to boot with a separate dtb.
> > 
> > Yeah, but the documentation even for DTB boot says we should pass
> > in a machine number. If 0 or -1 are right then there should be
> > some documentation that says so. I'll accept "mailing list post
> > from some authoritative person [eg Grant Likely]" if necessary.
> 
> Kernel DT co-maintainer is not authoritative enough for you?
> 
> The documentation needs some clarification.
> 
> > But this is an ABI between boot loaders and the kernel so I don't
> > want to just have something random that happens to work. (And in
> > particular if -1 is the officially sanctioned number then we need
> > to fix arm_boot to be able to pass values >16 bits wide.)
> > 

I've got a patch that fixes arm_boot.  I'll send it separately.

How about this patch for the kernel:

g.

---

diff --git a/Documentation/arm/Booting b/Documentation/arm/Booting
index a341d87..72b064d 100644
--- a/Documentation/arm/Booting
+++ b/Documentation/arm/Booting
@@ -148,7 +148,9 @@ In either case, the following conditions must be met:
 
 - CPU register settings
   r0 = 0,
-  r1 = machine type number discovered in (3) above.
+  r1 = machine type number discovered in (3) above, or if booting with
+       a dtb then this may be set to ~0 if a valid MACH_TYPE_xxx value
+       does not exist for the machine.
   r2 = physical address of tagged list in system RAM, or
        physical address of device tree block (dtb) in system RAM
 
diff --git a/Documentation/devicetree/booting-without-of.txt b/Documentation/devicetree/booting-without-of.txt
index 7c1329d..33e2b51 100644
--- a/Documentation/devicetree/booting-without-of.txt
+++ b/Documentation/devicetree/booting-without-of.txt
@@ -176,7 +176,8 @@ it with special cases.
 
                 r1 : Valid machine type number.  When using a device tree,
                 a single machine type number will often be assigned to
-                represent a class or family of SoCs.
+                represent a class or family of SoCs.  If a valid machine
+                type number is not assigned, then use ~0.
 
                 r2 : physical pointer to the device-tree block
                 (defined in chapter II) in RAM.  Device tree can be located

^ permalink raw reply related	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 13:57               ` Peter Maydell
@ 2012-01-20 18:27                 ` Grant Likely
  2012-01-21  2:39                   ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Grant Likely @ 2012-01-20 18:27 UTC (permalink / raw)
  To: Peter Maydell
  Cc: Mark Langsdorf, i.mitsyanko, qemu-devel, Rob Herring,
	edgar.iglesias, afaerber

On Fri, Jan 20, 2012 at 01:57:29PM +0000, Peter Maydell wrote:
> On 20 January 2012 13:48, Rob Herring <rob.herring@calxeda.com> wrote:
> > Kernel DT co-maintainer is not authoritative enough for you?
> 
> Only if I recognise their name :-) [ie, sorry.]
> 
> > The documentation needs some clarification.
> >
> >> But this is an ABI between boot loaders and the kernel so I don't
> >> want to just have something random that happens to work. (And in
> >> particular if -1 is the officially sanctioned number then we need
> >> to fix arm_boot to be able to pass values >16 bits wide.)
> >>
> >
> > Here's were the kernel sets the mach #. nr is from the database for
> > non-DT and ~0 for DT machines.
> >
> > #define MACHINE_START(_type,_name)                      \
> > static const struct machine_desc __mach_desc_##_type    \
> >  __used                                                 \
> >  __attribute__((__section__(".arch.info.init"))) = {    \
> >        .nr             = MACH_TYPE_##_type,            \
> >        .name           = _name,
> >
> > #define MACHINE_END                             \
> > };
> >
> > #define DT_MACHINE_START(_name, _namestr)               \
> > static const struct machine_desc __mach_desc_##_name    \
> >  __used                                                 \
> >  __attribute__((__section__(".arch.info.init"))) = {    \
> >        .nr             = ~0,                           \
> >        .name           = _namestr,
> >
> > In any case, the kernel ignores the value passed in if a valid dtb is
> > passed in.
> 
> I wonder if we should be passing in anything-except-minus-1,
> since if you pass -1 and no DT then the kernel will fail
> silently, whereas if you pass something else and no DT the
> kernel will complain about the mismatch.

Alternately, we can make the kernel always complain about machine type
~0, which is probably safer anyway.

g.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 16:58                     ` Peter Maydell
@ 2012-01-20 19:25                       ` Mark Langsdorf
  2012-01-21  2:35                         ` Peter Maydell
  0 siblings, 1 reply; 147+ messages in thread
From: Mark Langsdorf @ 2012-01-20 19:25 UTC (permalink / raw)
  To: Peter Maydell; +Cc: qemu-devel

On 01/20/2012 10:58 AM, Peter Maydell wrote:
> On 20 January 2012 16:57, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
>> On 01/20/2012 10:27 AM, Peter Maydell wrote:
>>> It's still not clear to me from this conversation if the right
>>> answer is "0", "-1" or "anything that's not a valid board ID
>>> and not -1 either"...
>>
>> Quoting Rob from upthread:
>> "0 or -1 is the right value as those are obviously meaningless."
>>
>> The original code that Rob wrote had a board_id of -1. That's
>> the right answer.
> 
> In that case you need a patch that causes arm_boot to actually
> pass -1, not 0xffff.
> 
> (Also it would be nice if the kernel barfed if (id == -1 and
> there's no appended device tree), but that's not a qemu thing.)

It looks like there's an issue with commit 2be276242135eac6,
in that target-arm/helper.c:cpu_reset() is called after
hw/highbank.c:highbank_cpu_reset() and keeps clobbering
our c15_config_base_address. So when the kernel attempts to
read that address, it gets a 0, and it never accesses the
GIC code but instead reads the value of the hw/arm_boot.c:
bootloader[] array (loaded into ROM at address 0).

Is there a way to prioritize the callbacks or something
so that arm's cpu_reset() doesn't clobber highbank's
cpu_reset()? Alternately, is there some other way to
set c15 values outside of cpu_reset()?

--Mark Langsdorf
Calxeda, Inc.

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 19:25                       ` Mark Langsdorf
@ 2012-01-21  2:35                         ` Peter Maydell
  0 siblings, 0 replies; 147+ messages in thread
From: Peter Maydell @ 2012-01-21  2:35 UTC (permalink / raw)
  To: Mark Langsdorf; +Cc: qemu-devel

On 20 January 2012 19:25, Mark Langsdorf <mark.langsdorf@calxeda.com> wrote:
> It looks like there's an issue with commit 2be276242135eac6,
> in that target-arm/helper.c:cpu_reset() is called after
> hw/highbank.c:highbank_cpu_reset() and keeps clobbering
> our c15_config_base_address.

You may recall that when you first sent the patch with
highbank_cpu_reset I said it looked like the resets would be
in the wrong order, and you assured me they weren't :-)
(Commit 2be276242 is the SCU register change, incidentally,
and doesn't seem relevant; did you mean some other commit?)

> Is there a way to prioritize the callbacks or something
> so that arm's cpu_reset() doesn't clobber highbank's
> cpu_reset()? Alternately, is there some other way to
> set c15 values outside of cpu_reset()?

Reset callbacks aren't supposed to do things such that they
care about what order they're called in. This one does because
we're uncleanly reaching into the CPUState from the highbank
reset callback rather than doing CPU reset in the CPU proper.
I was willing to let that pass since it happened to work
OK and we didn't have a clean mechanism to hand, but if it
doesn't work anyhow I guess we need to rethink.

I can't think of anything nicer (since we don't have a proper
qdev object to set properties on) than adding code to cpu_reset()
which saves the value of env->cp15_config_base_address across
the memset(). That's quite ugly but will work. [And in fact
we'd need that even with a hypothetical qdev property because
the property would only set the state field once at init, and
we'd need to avoid the memset() on reset trashing it. There's
an argument that it's the block memset() that's ugly...]

OTOH it's 2.30am here so I may be missing a nicer approach.
Suggestions welcome.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* Re: [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank
  2012-01-20 18:27                 ` Grant Likely
@ 2012-01-21  2:39                   ` Peter Maydell
  2012-01-23 16:32                     ` [Qemu-devel] Adding -dtb option to qemu Grant Likely
  0 siblings, 1 reply; 147+ messages in thread
From: Peter Maydell @ 2012-01-21  2:39 UTC (permalink / raw)
  To: Grant Likely
  Cc: Mark Langsdorf, i.mitsyanko, qemu-devel, Rob Herring,
	edgar.iglesias, afaerber

On 20 January 2012 18:27, Grant Likely <grant.likely@secretlab.ca> wrote:
> On Fri, Jan 20, 2012 at 01:57:29PM +0000, Peter Maydell wrote:
>> I wonder if we should be passing in anything-except-minus-1,
>> since if you pass -1 and no DT then the kernel will fail
>> silently, whereas if you pass something else and no DT the
>> kernel will complain about the mismatch.
>
> Alternately, we can make the kernel always complain about machine type
> ~0, which is probably safer anyway.

That sounds like a good idea to me.

-- PMM

^ permalink raw reply	[flat|nested] 147+ messages in thread

* [Qemu-devel] Adding -dtb option to qemu
  2012-01-21  2:39                   ` Peter Maydell
@ 2012-01-23 16:32                     ` Grant Likely
  0 siblings, 0 replies; 147+ messages in thread
From: Grant Likely @ 2012-01-23 16:32 UTC (permalink / raw)
  To: Peter Maydell; +Cc: edgar.iglesias, qemu-devel, Rob Herring

Hey Peter,

I need some advice.  I'm adding a -dtb option to qemu for specifying a
dtb filename to be passed on to the kernel, similar to how the -initrd
flag works.  The dtb filename needs to then be passed on to the
selected machine, and it looks like the machine->init() callback is
the best way to do that.

However, the current init callback prototype looks like this:

typedef void QEMUMachineInitFunc(ram_addr_t ram_size,
				 const char *boot_device,
				 const char *kernel_filename,
				 const char *kernel_cmdline,
				 const char *initrd_filename,
				 const char *cpu_model);

Now, I could simply add an new "dtb_filename" to the argument list and
fix up all of the users (looks to be about 90 machines), but that
seems like a lot of churn that will need to be repeated the next time
a new argument needs to be passed to the init func.

Alternately, I could do something like this:

struct machine_args {
	ram_addr_t ram_size;
	const char *boot_device;
	const char *kernel_filename,
	const char *kernel_cmdline,
	const char *initrd_filename,
	const char *dtb_filename,
	const char *cpu_model,
};

typedef void QEMUMachineInitFunc(const struct machine_args *args);

And then I'd fix up all the users, which would be about the same
amount of churn, but subsequent additions would be a lot easier.

A third option would be to add a new ".dt_init()" that is executed
instead of .init() if populated, but that seems like an ugly band-aid
to me.

How should I approach this?  Or is there a better way to pass data to
so that it is available at machine->init() time?

g.

^ permalink raw reply	[flat|nested] 147+ messages in thread

end of thread, other threads:[~2012-01-23 16:32 UTC | newest]

Thread overview: 147+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-05 20:02 [Qemu-devel] [PATCH 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 1/5] Add xgmac ethernet model Mark Langsdorf
2012-01-05 20:02 ` [Qemu-devel] [PATCH v5 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-06 15:37   ` Peter Maydell
2012-01-05 20:02 ` [Qemu-devel] [PATCH 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-05 20:02 ` [Qemu-devel] [PATCH 4/5] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-05 20:02 ` [Qemu-devel] [PATCH 5/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-06 16:29   ` Peter Maydell
2012-01-06 16:58     ` Mark Langsdorf
2012-01-06 17:04       ` Peter Maydell
2012-01-06 17:34         ` Mark Langsdorf
2012-01-06 17:46           ` Peter Maydell
2012-01-06 21:16     ` Mark Langsdorf
2012-01-07  3:20       ` Peter Maydell
2012-01-06 18:09   ` Andreas Färber
2012-01-06 18:37   ` Igor Mitsyanko
2012-01-06 18:45     ` Peter Maydell
2012-01-06 19:10       ` Igor Mitsyanko
2012-01-06 20:11         ` Andreas Färber
2012-01-07  3:14           ` Peter Maydell
2012-01-07  4:18             ` Andreas Färber
2012-01-07  9:55           ` Igor Mitsyanko
2012-01-07  9:40             ` Andreas Färber
2012-01-06 18:48     ` Rob Herring
2012-01-09 16:59 ` [Qemu-devel] [PATCH v2 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
2012-01-09 16:59   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-10 17:52     ` Edgar E. Iglesias
2012-01-09 16:59   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-09 16:59   ` [Qemu-devel] [PATCH v4 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-10 11:22     ` Andreas Färber
2012-01-09 16:59   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-09 16:59   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-09 16:59   ` [Qemu-devel] [PATCH 6/6] arm: Remove incorrect and misleading comment in arm_timer Mark Langsdorf
2012-01-10 12:45     ` Andreas Färber
2012-01-10 15:35       ` Peter Maydell
2012-01-10 18:00         ` Andreas Färber
2012-01-10 16:45 ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Mark Langsdorf
2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-10 17:34     ` Peter Maydell
2012-01-10 16:45   ` [Qemu-devel] [PATCH v6 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-10 17:47     ` Peter Maydell
2012-01-10 16:45   ` [Qemu-devel] [PATCH v5 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-10 17:44     ` Andreas Färber
2012-01-10 16:45   ` [Qemu-devel] [PATCH 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-10 17:55     ` Peter Maydell
2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-10 18:04     ` Peter Maydell
2012-01-10 16:45   ` [Qemu-devel] [PATCH v2 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-10 17:52     ` Peter Maydell
2012-01-10 18:03     ` Andreas Färber
2012-01-10 18:18   ` [Qemu-devel] [PATCH v3 0/5] arm: add support for Calxeda Highbank SoC Peter Maydell
2012-01-10 20:33   ` [Qemu-devel] [PATCH v7 0/6] " Mark Langsdorf
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-11  4:12       ` Andreas Färber
2012-01-11 10:56         ` Peter Maydell
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-10 20:33     ` [Qemu-devel] [PATCH v7 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-11 15:26   ` [Qemu-devel] [PATCH v8 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-11 15:50       ` Peter Maydell
2012-01-13 23:27       ` Peter Maydell
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-11 15:40       ` Andreas Färber
2012-01-11 15:54       ` Peter Maydell
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-11 15:56       ` Peter Maydell
2012-01-11 15:26     ` [Qemu-devel] [PATCH v8 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-11 16:31   ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Mark Langsdorf
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-11 22:47       ` Peter Maydell
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 4/6] arm: Add dummy support for co-processor 15's secure config register Mark Langsdorf
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-12 12:47       ` Mitsyanko Igor
2012-01-12 13:09         ` Andreas Färber
2012-01-12 13:42           ` Mitsyanko Igor
2012-01-12 13:46             ` Peter Maydell
2012-01-12 13:58       ` Mitsyanko Igor
2012-01-12 17:51       ` Peter Maydell
2012-01-11 16:31     ` [Qemu-devel] [PATCH v9 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-11 22:41     ` [Qemu-devel] [PATCH v9 0/6] arm: add support for Calxeda Highbank SoC Peter Maydell
2012-01-13 12:14       ` Peter Maydell
2012-01-13 14:15         ` Andreas Färber
2012-01-13 14:18           ` Alexander Graf
2012-01-13 14:31             ` Andreas Färber
2012-01-13 14:35               ` Alexander Graf
2012-01-17 13:50   ` [Qemu-devel] [PATCH v10 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 1/5] Add xgmac ethernet model Mark Langsdorf
2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 2/5] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 3/5] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-17 15:13       ` Peter Maydell
2012-01-18 14:35         ` Mark Langsdorf
2012-01-18 14:53           ` Peter Maydell
2012-01-18 15:04             ` Mark Langsdorf
2012-01-18 15:11               ` Peter Maydell
2012-01-18 15:50               ` [Qemu-devel] [PATCH][RFC] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
2012-01-18 16:23                 ` Peter Maydell
2012-01-18 19:06             ` [Qemu-devel] [PATCH v10 4/5] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-18 19:26               ` Peter Maydell
2012-01-18 19:33                 ` Peter Maydell
2012-01-18 21:32                 ` Mark Langsdorf
2012-01-17 13:50     ` [Qemu-devel] [PATCH v10 5/5] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-19 15:43   ` [Qemu-devel] [PATCH v11 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 1/6] Add xgmac ethernet model Mark Langsdorf
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 2/6] arm: make the number of GIC interrupts configurable Mark Langsdorf
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 3/6] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 4/6] arm: add secondary cpu book callbacks to arm_boot.c Mark Langsdorf
2012-01-19 17:19       ` Peter Maydell
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 5/6] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-19 19:15       ` Peter Maydell
2012-01-19 19:25         ` Mark Langsdorf
2012-01-19 19:32           ` Peter Maydell
2012-01-19 19:35             ` Mark Langsdorf
2012-01-19 19:44               ` Peter Maydell
2012-01-19 19:58                 ` Mark Langsdorf
2012-01-19 19:59                   ` Peter Maydell
2012-01-19 20:48                     ` Mark Langsdorf
2012-01-19 20:00       ` Peter Maydell
2012-01-19 15:43     ` [Qemu-devel] [PATCH v11 6/6] arm: Remove incorrect comment in arm_timer Mark Langsdorf
2012-01-19 21:30   ` [Qemu-devel] [PATCH v12 0/5] arm: add support for Calxeda Highbank Mark Langsdorf
2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 1/4] Add xgmac ethernet model Mark Langsdorf
2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 2/4] ahci: add support for non-PCI based controllers Mark Langsdorf
2012-01-19 21:30     ` [Qemu-devel] [PATCH v12 3/4] arm: add secondary cpu boot callbacks to arm_boot.c Mark Langsdorf
2012-01-19 21:31     ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-19 21:44       ` Peter Maydell
2012-01-19 23:17         ` Rob Herring
2012-01-19 23:41           ` John Williams
2012-01-20  8:47           ` Peter Maydell
2012-01-20 13:48             ` Rob Herring
2012-01-20 13:57               ` Peter Maydell
2012-01-20 18:27                 ` Grant Likely
2012-01-21  2:39                   ` Peter Maydell
2012-01-23 16:32                     ` [Qemu-devel] Adding -dtb option to qemu Grant Likely
2012-01-20 16:25               ` [Qemu-devel] [PATCH v12 4/4] arm: SoC model for Calxeda Highbank Mark Langsdorf
2012-01-20 16:27                 ` Peter Maydell
2012-01-20 16:57                   ` Mark Langsdorf
2012-01-20 16:58                     ` Peter Maydell
2012-01-20 19:25                       ` Mark Langsdorf
2012-01-21  2:35                         ` Peter Maydell
2012-01-20 18:25               ` Grant Likely

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.