qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC PATCH 0/7] Zynq-7000 EPP platform model
@ 2012-01-23  7:20 Peter A. G. Crosthwaite
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
  0 siblings, 1 reply; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Hi,

This is an RFC for a suite of Device models and a machine model for the Xilinx Zynq-7000 Extensible Processing Platform:

http://www.xilinx.com/products/silicon-devices/epp/zynq-7000/index.htm

This is an ARM based platform featuring embedded SoC peripherals. This patch series includes a minimal set of device models and a a machine model capable of emulating zynq platforms booting linux.

A suitable test linux image is available from:

http://www.origin.xilinx.com/member/zynq_linux/zynq_linux.tar.gz

This first 4 patches in this series are device models for IP provided by cadence for the Zynq platform. The next two are changes/additions to the qemu boot process to faciliate booting of zynq-linux. The final patch is the initial revision of the zynq machine model.

Most of this work was originally authored by Xilinx, as indicated by (c) notices in added files.

Peter A. G. Crosthwaite (7):
  cadence_uart: first revision
  cadence ttc: first revision
  cadence_wdt: first reivison
  cadence_gem: first revision
  vl.c: added -kerndtb option
  arm_boot: added initrd address override
  xilinx_zynq: machine model first revision

 Makefile.target   |    5 +
 hw/arm-misc.h     |    2 +
 hw/arm_boot.c     |   12 +-
 hw/cadence_gem.c  | 1442 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/cadence_ttc.c  |  545 ++++++++++++++++++++
 hw/cadence_uart.c |  620 +++++++++++++++++++++++
 hw/cadence_wdt.c  |  254 ++++++++++
 qemu-options.hx   |    3 +
 vl.c              |    4 +
 9 files changed, 2883 insertions(+), 4 deletions(-)
 create mode 100644 hw/cadence_gem.c
 create mode 100644 hw/cadence_ttc.c
 create mode 100644 hw/cadence_uart.c
 create mode 100644 hw/cadence_wdt.c

-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-24  2:02     ` John Linn
  2012-01-24  8:07     ` Andreas Färber
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 2/7] cadence ttc: " Peter A. G. Crosthwaite
                     ` (5 subsequent siblings)
  6 siblings, 2 replies; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Device model for Cadence UART

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.target   |    1 +
 hw/cadence_uart.c |  619 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 620 insertions(+), 0 deletions(-)
 create mode 100644 hw/cadence_uart.c

diff --git a/Makefile.target b/Makefile.target
index bb18d72..824f6eb 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -334,6 +334,7 @@ endif
 obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
+obj-arm-y += cadence_uart.o
 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
diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
new file mode 100644
index 0000000..931ff2c
--- /dev/null
+++ b/hw/cadence_uart.c
@@ -0,0 +1,619 @@
+/*
+ * Device model for Cadence UART
+ *
+ * Copyright (c) 2010 Xilinx Inc.
+ * Written by Haibing Ma
+ *            M.Habib
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include "sysbus.h"
+#include "qemu-char.h"
+#include "qemu-timer.h"
+
+#define UART_INTR_RTRIG     0x00000001
+#define UART_INTR_REMPTY    0x00000002
+#define UART_INTR_RFUL      0x00000004
+#define UART_INTR_TEMPTY    0x00000008
+#define UART_INTR_TFUL      0x00000010
+#define UART_INTR_ROVR      0x00000020
+#define UART_INTR_FRAME     0x00000040
+#define UART_INTR_PARE      0x00000080
+#define UART_INTR_TIMEOUT   0x00000100
+#define UART_INTR_DMSI      0x00000200
+#define UART_INTR_TTRIG     0x00000400
+#define UART_INTR_TNFUL     0x00000800
+#define UART_INTR_TOVR      0x00001000
+
+#define UART_CSR_RTRIG      0x00000001
+#define UART_CSR_REMPTY     0x00000002
+#define UART_CSR_RFUL       0x00000004
+#define UART_CSR_TEMPTY     0x00000008
+#define UART_CSR_TFUL       0x00000010
+#define UART_CSR_ROVR       0x00000020
+#define UART_CSR_FRAME      0x00000040
+#define UART_CSR_PARE       0x00000080
+#define UART_CSR_TIMEOUT    0x00000100
+#define UART_CSR_DMSI       0x00000200
+#define UART_CSR_RACTIVE    0x00000400
+#define UART_CSR_TACTIVE    0x00000800
+#define UART_CSR_FDELT      0x00001000
+#define UART_CSR_TTRIG      0x00002000
+#define UART_CSR_TNFUL      0x00004000
+
+#define UART_CR_STOPBRK     0x00000100
+#define UART_CR_STARTBRK    0x00000080
+#define UART_CR_TX_DIS      0x00000020
+#define UART_CR_TX_EN       0x00000010
+#define UART_CR_RX_DIS      0x00000008
+#define UART_CR_RX_EN       0x00000004
+#define UART_CR_TXRST       0x00000002
+#define UART_CR_RXRST       0x00000001
+#define UART_CR_RST_TO      0x00000040
+
+#define UART_MR_CLKSEL          0x00000001
+#define UART_MR_CHMODE_L_LOOP   0x00000200
+#define UART_MR_CHMODE_NORM     0x00000000
+#define UART_MR_STOPMODE_2_BIT  0x00000080
+#define UART_MR_STOPMODE_1_BIT  0x00000000
+#define UART_MR_PARITY_NONE     0x00000020
+#define UART_MR_PARITY_MARK     0x00000018
+#define UART_MR_PARITY_SPACE    0x00000010
+#define UART_MR_PARITY_ODD      0x00000008
+#define UART_MR_PARITY_EVEN     0x00000000
+#define UART_MR_CHARLEN_6_BIT   0x00000006
+#define UART_MR_CHARLEN_7_BIT   0x00000004
+#define UART_MR_CHARLEN_8_BIT   0x00000000
+
+#define UART_MR_CLKS            0x00000001
+#define UART_CHRL_SHFT          1
+#define UART_MR_CHRL            0x00000006
+#define UART_PAR_SHFT           3
+#define UART_MR_PAR             0x00000038
+#define UART_NBSTOP_SHFT        6
+#define UART_MR_NBSTOP          0x000000C0
+#define UART_CHMODE_SHFT        8
+#define UART_MR_CHMODE          0x00000300
+#define UART_UCLKEN_SHFT        10
+#define UART_MR_UCLKEN          0x00000400
+#define UART_IRMODE_SHFT        11
+#define UART_MR_IRMODE          0x00000800
+
+#define UART_PARITY_ODD        0x001
+#define UART_PARITY_EVEN       0x000
+#define UART_DATA_BITS_6       0x003
+#define UART_DATA_BITS_7       0x002
+#define UART_STOP_BITS_1       0x003
+#define UART_STOP_BITS_2       0x002
+#define RX_FIFO_SIZE           16
+#define TX_FIFO_SIZE           16
+#define RESET_TX_RX            0xFFFFFFFC
+#define UARK_INPUT_CLK         50000000
+
+#define NORMAL_MODE            0
+#define ECHO_MODE              1
+#define LOCAL_LOOPBACK         2
+#define REMOTE_LOOPBACK        3
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    uint32_t cr;
+    uint32_t mr;
+    uint32_t ier;
+    uint32_t idr;
+    uint32_t imr;
+    uint32_t cisr;
+    uint32_t brgr;
+    uint32_t rtor;
+    uint32_t rtrig;
+    uint32_t mcr;
+    uint32_t msr;
+    uint32_t csr;
+    uint8_t r_fifo[RX_FIFO_SIZE];
+    uint8_t t_fifo[TX_FIFO_SIZE];
+    uint32_t bdiv;
+    uint32_t fdel;
+    uint32_t pmin;
+    uint32_t pwid;
+    uint32_t ttrig;
+    int rx_rpos;
+    int rx_wpos;
+    int rx_count;
+    int tx_trigger;
+    int rx_trigger;
+    int tx_enabled;
+    int rx_enabled;
+    int parity;
+    int data_bits;
+    int stop_bits;
+    int sel_clk;
+    int ch_mode;
+    int ur_mode;
+    int ir_mode;
+    uint64_t char_tx_time;
+    CharDriverState *chr;
+    qemu_irq irq;
+    struct QEMUTimer *fifo_trigger_handle;
+    struct QEMUTimer *tx_time_handle;
+} uart_state;
+
+static void uart_update_status(uart_state *s)
+{
+    uint32_t flags;
+
+    flags = s->imr & s->cisr;
+
+    qemu_set_irq(s->irq, flags != 0);
+}
+
+static void fifo_trigger_update (void *opaque)
+{
+    uart_state *s = (uart_state *)opaque;
+
+    s->csr |= UART_CSR_TIMEOUT;
+    s->cisr |= UART_INTR_TIMEOUT;
+
+    uart_update_status(s);
+}
+
+static void uart_tx_redo (uart_state *s)
+{
+    uint64_t new_tx_time = qemu_get_clock_ns(vm_clock);
+
+    qemu_mod_timer(s->tx_time_handle, new_tx_time + s->char_tx_time);
+
+    s->csr |= UART_CSR_TEMPTY;
+    s->cisr |= UART_INTR_TEMPTY;
+
+    uart_update_status(s);
+}
+
+static void uart_tx_write (void *opaque)
+{
+    uart_state *s = (uart_state *)opaque;
+
+    uart_tx_redo (s);
+}
+
+static void uart_rx_reset(uart_state *s)
+{
+    s->rx_count = 0;
+    s->rx_rpos = 0;
+    s->rx_wpos = 0;
+
+    s->csr |= UART_CSR_REMPTY;
+    s->csr &= ~UART_CSR_RFUL;
+    s->csr &= ~UART_CSR_ROVR;
+    s->csr &= ~UART_CSR_TIMEOUT;
+
+    s->cisr &= ~UART_INTR_REMPTY;
+    s->cisr &= ~UART_INTR_RFUL;
+    s->cisr &= ~UART_INTR_ROVR;
+    s->cisr &= ~UART_INTR_TIMEOUT;
+}
+
+static void uart_tx_reset(uart_state *s)
+{
+    s->csr |= UART_CSR_TEMPTY;
+    s->csr &= ~UART_CSR_TFUL;
+
+    s->cisr &= ~UART_INTR_TEMPTY;
+    s->cisr &= ~UART_INTR_TFUL;
+}
+
+static void uart_send_breaks(uart_state *s)
+{
+    int break_enabled = 1;
+    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+                               &break_enabled);
+
+}
+
+static void uart_parameters_setup(uart_state *s)
+{
+    QEMUSerialSetParams ssp;
+    unsigned int baud_rate , packet_size;
+
+    if (s->sel_clk) {
+        baud_rate = UARK_INPUT_CLK /8;
+    } else
+        baud_rate = UARK_INPUT_CLK ;
+
+    ssp.speed = baud_rate/(s->brgr * (s->bdiv + 1));
+    packet_size = 1;
+
+    switch (s->parity) {
+        case UART_PARITY_EVEN:
+            ssp.parity = 'E';
+            packet_size++;
+            break;
+        case UART_PARITY_ODD:
+            ssp.parity = 'O';
+            packet_size++;
+            break;
+        default:
+            ssp.parity = 'N';
+        break;
+    }
+
+    switch (s->data_bits) {
+        case UART_DATA_BITS_6:
+            ssp.data_bits = 6;
+            break;
+        case UART_DATA_BITS_7:
+            ssp.data_bits = 7;
+            break;
+        default:
+            ssp.data_bits = 8;
+            break;
+    }
+
+    if (s->stop_bits == UART_STOP_BITS_1) {
+        ssp.stop_bits = 1;
+    } else {
+        ssp.stop_bits = 2;
+    }
+
+    packet_size += ssp.data_bits + ssp.stop_bits;
+    s->char_tx_time =  (get_ticks_per_sec() / ssp.speed) * packet_size;
+    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+}
+
+static void uart_mode_update(uart_state *s, uint32_t value)
+{
+    s->mr = value;
+
+    s->sel_clk = value & UART_MR_CLKS;
+
+    s->data_bits = (value >> UART_CHRL_SHFT) & UART_MR_CHRL;
+    s->parity = (value >> UART_PAR_SHFT) & UART_MR_PAR;
+    s->stop_bits = (value >> UART_NBSTOP_SHFT) & UART_MR_NBSTOP;
+
+    s->ch_mode = (value >> UART_CHMODE_SHFT) & UART_MR_CHMODE;
+    s->ur_mode = (value >> UART_UCLKEN_SHFT) & UART_MR_UCLKEN;
+    s->ir_mode = (value >> UART_IRMODE_SHFT) & UART_MR_IRMODE;
+
+    uart_parameters_setup(s);
+}
+
+static void uart_stop_breaks(uart_state *s)
+{
+    int break_enabled = 0;
+    qemu_chr_fe_ioctl(s->chr, CHR_IOCTL_SERIAL_SET_BREAK,
+                               &break_enabled);
+
+}
+
+static int uart_can_receive(void *opaque)
+{
+    uart_state *s = (uart_state *)opaque;
+
+    return (RX_FIFO_SIZE - s->rx_count);
+}
+
+static void uart_ctrl_update(uart_state *s, uint32_t value)
+{
+    s->cr = value;
+
+    if (value & UART_CR_TXRST) {
+        uart_tx_reset(s);
+    }
+
+    if (value & UART_CR_RXRST) {
+        uart_rx_reset(s);
+    }
+
+    s->cr &= RESET_TX_RX;
+
+    if (value & UART_CR_TX_EN) {
+        if (!(s->cr & UART_CR_TX_DIS)) {
+            s->tx_enabled = 1;
+            uart_tx_redo (s);
+        }
+    }
+    if (value & UART_CR_TX_DIS) {
+        s->tx_enabled = 0;
+    }
+
+    if (value & UART_CR_RX_EN) {
+        if (!(s->cr & UART_CR_RX_DIS)) {
+            s->rx_enabled = 1;
+        }
+    }
+    if (value & UART_CR_RX_DIS) {
+        s->rx_enabled = 0;
+    }
+
+    if (value & UART_CR_STARTBRK) {
+        if (!(s->cr & UART_CR_STOPBRK)) {
+            uart_send_breaks(s);
+        }
+    }
+    if (value & UART_CR_STARTBRK) {
+        uart_stop_breaks(s);
+    }
+}
+
+static void uart_write_rx_fifo(void *opaque, const uint8_t *buf, int size)
+{
+    uart_state *s = (uart_state *)opaque;
+    uint64_t new_rx_time = qemu_get_clock_ns(vm_clock);
+    int i;
+
+    if (!s->rx_enabled)
+        return;
+
+    s->csr &= ~UART_CSR_REMPTY;
+    s->cisr &= ~UART_INTR_REMPTY;
+
+    if (s->rx_count == RX_FIFO_SIZE) {
+        s->cisr |= UART_INTR_ROVR;
+        s->csr |= UART_CSR_ROVR;
+    } else {
+        if (s->rx_wpos == RX_FIFO_SIZE)
+        s->rx_wpos = 0;
+
+        for (i = 0; i < size; i++) {
+            s->r_fifo[s->rx_wpos++] = buf[i];
+            s->rx_count++;
+
+            if (s->rx_count == RX_FIFO_SIZE) {
+                s->csr |= UART_CSR_RFUL;
+                s->cisr |= UART_INTR_RFUL;
+                break;
+            }
+
+            if (s->rx_count >= s->rtrig) {
+                s->cisr |= UART_INTR_RTRIG;
+                s->csr |= UART_CSR_RTRIG;
+            }
+        }
+        qemu_mod_timer(s->fifo_trigger_handle, new_rx_time +
+                                                (s->char_tx_time * 4));
+    }
+    uart_update_status(s);
+}
+
+static void uart_write_tx_fifo(uart_state *s, unsigned  char *c)
+{
+    unsigned  char ch = *c;
+
+    if (!s->tx_enabled)
+       return;
+
+    while (!(qemu_chr_fe_write(s->chr, &ch, 1)));
+}
+
+static void uart_receive(void *opaque, const uint8_t *buf, int size)
+{
+    uart_state *s = (uart_state *)opaque;
+    if (s->ch_mode == NORMAL_MODE || s->ch_mode == ECHO_MODE) {
+        uart_write_rx_fifo(opaque, buf, size);
+    }
+    if (s->ch_mode == REMOTE_LOOPBACK || s->ch_mode == ECHO_MODE) {
+        uart_write_tx_fifo(s, (unsigned  char *)buf);
+    }
+}
+
+static void uart_event(void *opaque, int event)
+{
+    uart_state *s = (uart_state *)opaque;
+    uint8_t buf= '\0';
+
+    if (event == CHR_EVENT_BREAK) {
+        uart_write_rx_fifo(opaque, &buf, 1);
+    }
+
+    uart_update_status(s);
+}
+
+static void uart_read_rx_fifo(uart_state *s, uint32_t *c)
+{
+
+    if (!s->rx_enabled)
+       return;
+
+    s->csr &= ~UART_CSR_RFUL;
+    s->csr &= ~UART_CSR_ROVR;
+    s->cisr &= ~UART_INTR_ROVR;
+    s->cisr &= ~UART_INTR_RFUL;
+
+    if (s->rx_count > 0) {
+        s->rx_count--;
+
+        *c = s->r_fifo[s->rx_rpos];
+        ++s->rx_rpos;
+
+        if (s->rx_rpos == RX_FIFO_SIZE)
+            s->rx_rpos = 0;
+
+        if (s->rx_count == 0) {
+            s->cisr |= UART_INTR_REMPTY;
+            s->csr |= UART_CSR_REMPTY;
+        }
+
+    } else {
+        *c = 0;
+        s->cisr |= UART_INTR_REMPTY;
+        s->csr |= UART_CSR_REMPTY;
+    }
+
+    if (s->rx_count < s->rtrig) {
+        s->csr &= ~UART_CSR_RTRIG;
+        s->cisr &= ~UART_INTR_RTRIG;
+
+    }
+    uart_update_status(s);
+}
+
+static void uart_write(void *opaque, target_phys_addr_t offset,
+                          uint64_t value, unsigned size)
+{
+    uart_state *s = (uart_state *)opaque;
+    switch (offset) {
+        case 0x00:
+            uart_ctrl_update(s, value);
+            break;
+        case 0x04:
+            uart_mode_update(s, value);
+            break;
+        case 0x08: /* ier */
+            s->imr |= value;
+            break;
+        case 0x0c: /* idr */
+            s->imr &= ~value;
+            break;
+        case 0x14: /* cisr */
+            s->cisr &= ~value;
+            break;
+        case 0x18: /* brgr */
+            s->brgr = value;
+            break;
+        case 0x1c: /* rtor */
+            s->rtor = value;
+            break;
+        case 0x20: /* rtrig */
+            s->rtrig = value;
+            break;
+        case 0x24: /* mcr */
+            s->mcr = value;
+            break;
+        case 0x30: /* UARTDR */
+            if (s->ch_mode == NORMAL_MODE) {
+                uart_write_tx_fifo(s, (unsigned  char *) &value);
+            }
+            if (s->ch_mode == LOCAL_LOOPBACK) {
+                uart_write_rx_fifo(opaque, (unsigned  char *) &value, 1);
+            }
+            break;
+        case 0x34: /* bdiv */
+            s->bdiv = value;
+            break;
+        case 0x38: /* fdel */
+            s->fdel = value;
+            break;
+        case 0x3c: /* pmin */
+            s->pmin = value;
+            break;
+        case 0x40: /* pwid */
+            s->pwid = value;
+            break;
+        case 0x44: /* ttrig */
+            s->ttrig = value;
+            break;
+        default:
+            return;
+    }
+}
+
+static uint64_t uart_read(void *opaque, target_phys_addr_t offset,
+        unsigned size)
+{
+    uart_state *s = (uart_state *)opaque;
+    uint32_t c = 0;
+    uint32_t value;
+
+    switch (offset) {
+        case 0x00:
+            return s->cr;
+        case 0x04:
+            return s->mr;
+        case 0x10:
+            return s->imr;
+        case 0x14:
+            value = s->cisr;
+            s->cisr = 0;
+            uart_update_status(s);
+            return value;
+        case 0x18:
+            return s->brgr;
+        case 0x1c:
+            return s->rtor;
+        case 0x20:
+            return s->rtrig;
+        case 0x24:
+            return s->mcr;
+        case 0x28:
+            return s->msr;
+        case 0x2c:
+            return s->csr;
+        case 0x30: /* Receive FIFO */
+            uart_read_rx_fifo (s, &c);
+            return c;
+        case 0x34:
+            return s->bdiv;
+        case 0x38:
+            return s->fdel;
+        case 0x3c:
+            return s->pmin;
+        case 0x40:
+            return s->pwid;
+        case 0x44:
+            return s->ttrig;
+        default:
+            return 0;
+    }
+}
+
+static const MemoryRegionOps uart_ops = {
+    .read = uart_read,
+    .write = uart_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int uart_init(SysBusDevice *dev)
+{
+    uart_state *s = FROM_SYSBUS(uart_state, dev);
+
+    memory_region_init_io(&s->iomem, &uart_ops, s, "uart", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+
+    s->fifo_trigger_handle = qemu_new_timer_ns(vm_clock,
+            (QEMUTimerCB *)fifo_trigger_update, s);
+
+    s->tx_time_handle = qemu_new_timer_ns(vm_clock,
+            (QEMUTimerCB *)uart_tx_write, s);
+
+    s->char_tx_time = (get_ticks_per_sec() / 9600) * 10;
+
+    s->chr = qdev_init_chardev(&dev->qdev);
+
+    s->cr = 0x00000128;
+    s->imr = 0;
+    s->cisr = 0;
+    s->rtrig = 0x00000020;
+    s->brgr = 0x0000000F;
+    s->ttrig = 0x00000020;
+
+    s->rx_rpos = 0;
+    s->rx_wpos = 0;
+    s->rx_count = 0;
+    s->tx_enabled = 1;
+    s->rx_enabled = 1;
+
+    if (s->chr) {
+        qemu_chr_add_handlers(s->chr, uart_can_receive, uart_receive,
+                              uart_event, s);
+    }
+
+    return 0;
+}
+
+static void uart_register_devices(void)
+{
+    sysbus_register_dev("cadence_uart", sizeof(uart_state),
+                        uart_init);
+}
+
+device_init(uart_register_devices)
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 2/7] cadence ttc: first revision
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-24  2:03     ` John Linn
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: " Peter A. G. Crosthwaite
                     ` (4 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Device model for cadence triple timer counter (TTC)

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.target  |    1 +
 hw/cadence_ttc.c |  545 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 546 insertions(+), 0 deletions(-)
 create mode 100644 hw/cadence_ttc.c

diff --git a/Makefile.target b/Makefile.target
index 824f6eb..44ba41b 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -335,6 +335,7 @@ obj-arm-y = integratorcp.o versatilepb.o arm_pic.o arm_timer.o
 obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
 obj-arm-y += cadence_uart.o
+obj-arm-y += cadence_ttc.o
 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
diff --git a/hw/cadence_ttc.c b/hw/cadence_ttc.c
new file mode 100644
index 0000000..2fe1696
--- /dev/null
+++ b/hw/cadence_ttc.c
@@ -0,0 +1,545 @@
+/*
+ * Xilinx Zynq cadence TTC model
+ *
+ * Copyright (c) 2011 Xilinx Inc.
+ * Written By Haibing Ma
+ *            M. Habib
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include "sysbus.h"
+#include "qemu-timer.h"
+#include "ptimer.h"
+
+#ifdef CADENCE_TTC_ERR_DEBUG
+#define qemu_debug(...) \
+    fprintf(stderr,  ": %s: ", __func__); \
+    fprintf(stderr, ## __VA_ARGS__); \
+    fflush(stderr);
+#else
+    #define qemu_debug(...)
+#endif
+
+#define COUNTER_INTR_IV     0x00000001
+#define COUNTER_INTR_M1     0x00000002
+#define COUNTER_INTR_M2     0x00000004
+#define COUNTER_INTR_M3     0x00000008
+#define COUNTER_INTR_OV     0x00000010
+#define COUNTER_INTR_EV     0x00000020
+
+#define COUNTER_CTRL_DIS    0x00000001
+#define COUNTER_CTRL_INT    0x00000002
+#define COUNTER_CTRL_DEC    0x00000004
+#define COUNTER_CTRL_MATCH  0x00000008
+#define COUNTER_CTRL_RST    0x00000010
+
+#define CLOCK_CTRL_PS_EN    0x00000001
+#define CLOCK_CTRL_PS_V     0x0000001e
+
+typedef struct {
+    ptimer_state *timer;
+    uint32_t reg_clock;
+    uint32_t reg_count;
+    uint16_t reg_interval;
+    uint16_t reg_match[3];
+    uint32_t reg_intr;
+    uint32_t reg_intr_en;
+    uint32_t reg_event_ctrl;
+    uint32_t reg_event;
+    uint32_t control;
+    uint32_t limit;
+    uint32_t next_event[5];
+    uint16_t event_seq;
+    uint16_t event_total;
+
+    int freq;
+    qemu_irq irq;
+
+} cadence_timer_state;
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    cadence_timer_state *timer[3];
+} cadence_ttc_state;
+
+static void cadence_timer_update(cadence_timer_state *s)
+{
+    uint32_t flags;
+
+    flags = s->reg_intr & s->reg_intr_en;
+
+    qemu_set_irq(s->irq, flags != 0);
+}
+
+static cadence_timer_state *cadence_timer_from_addr (void *opaque,
+                                        target_phys_addr_t offset)
+{
+    unsigned int index;
+    cadence_ttc_state *s = (cadence_ttc_state *)opaque;
+
+    index = (offset >> 2) % 3;
+
+    return (s->timer[index]);
+}
+
+static void cadence_timer_recalibrate(cadence_timer_state *s)
+{
+    uint32_t limit;
+
+    if (s->reg_count & COUNTER_CTRL_INT) {
+        /* interval */
+        limit = s->reg_interval;
+    } else {
+        /* Free running.  */
+        limit = 0xffff;
+    }
+    if (limit == 0)
+        limit = 1;
+
+    ptimer_set_limit(s->timer, limit, 1);
+}
+
+static void cadence_timer_fix_events(cadence_timer_state *s)
+{
+    uint16_t tmp = 0;
+
+    if (s->event_total <2)
+        return;
+
+    if (s->event_total <3)
+    {
+        if (s->next_event[0] < s->next_event[1])
+            return;
+        else {
+            tmp = s->next_event[0];
+            s->next_event[0] = s->next_event[1];
+            s->next_event[1] = tmp;
+            return;
+        }
+    }
+
+    if (s->next_event[0] > s->next_event[1]) {
+        tmp = s->next_event[0];
+        s->next_event[0] = s->next_event[1];
+        s->next_event[1] = tmp;
+    }
+
+    if (s->next_event[2] > s->next_event[3]) {
+        tmp = s->next_event[2];
+        s->next_event[2] = s->next_event[3];
+        s->next_event[3] = tmp;
+    }
+
+    if (s->next_event[1] < s->next_event[2]){
+        return;
+    }
+
+    // 0 < 1  2 < 3  but (1 > 2)
+    if (s->next_event[0] < s->next_event[2]) { // 0 < 2
+        if (s->next_event[1] < s->next_event[3]) { // 1 < 3
+            tmp = s->next_event[1];
+            s->next_event[1] = s->next_event[2];
+            s->next_event[2] = tmp;
+        }
+        else // 1 > 3
+        {
+            tmp = s->next_event[1];
+            s->next_event[1] = s->next_event[2];
+            s->next_event[2] = s->next_event[3];
+            s->next_event[3] = tmp;
+        }
+        return;
+    }
+    else { //  0 < 1  2 < 3  but 0 > 2
+        if (s->next_event[1] < s->next_event[3]) { // 1 < 3
+            tmp = s->next_event[0];
+            s->next_event[0] = s->next_event[2];
+            s->next_event[2] = s->next_event[1];
+            s->next_event[1] = tmp;
+        }
+        else
+        {   // 1 > 3
+            if (s->next_event[0] > s->next_event[3]) { // 0 > 3
+                tmp = s->next_event[0];
+                s->next_event[0] = s->next_event[2];
+                s->next_event[2] = tmp;
+                tmp = s->next_event[1];
+                s->next_event[1] = s->next_event[3];
+                s->next_event[3] = tmp;
+            }
+            else
+            {   // 0 < 3
+                tmp = s->next_event[0];
+                s->next_event[0] = s->next_event[2];
+                s->next_event[2] = s->next_event[3];
+                s->next_event[3] = s->next_event[1];
+                s->next_event[1] = tmp;
+            }
+        }
+    }
+}
+
+static void cadence_timer_setup_events(cadence_timer_state *s)
+{
+    uint16_t tmp = 0;
+
+    s->event_total = 4;
+
+    if (s->reg_count & COUNTER_CTRL_INT) {
+        s->next_event[tmp++] = s->reg_interval;
+    }
+    else
+    {
+        s->next_event[tmp++] = 0xffff;
+    }
+
+    if (s->next_event[0] != s->reg_match[0])
+    {
+        s->next_event[tmp++] = s->reg_match[0];
+    }
+    else {
+        s->event_total--;
+    }
+
+    if ((s->reg_match[0] == s->reg_match[1]) ||
+                        (s->next_event[0] == s->reg_match[1]))
+    {
+        s->event_total--;
+    }
+    else {
+        s->next_event[tmp++] = s->reg_match[1];
+    }
+
+    if ((s->reg_match[0] == s->reg_match[2]) ||
+            (s->reg_match[1] == s->reg_match[2]) ||
+            (s->next_event[0] != s->reg_match[2]))
+    {
+        s->event_total--;
+    }
+    else {
+        s->next_event[tmp++] = s->reg_match[1];
+    }
+
+    cadence_timer_fix_events(s);
+}
+
+static uint32_t cadence_counter_value(cadence_timer_state *s)
+{
+    uint32_t r;
+
+    r = ptimer_get_count(s->timer);
+
+    if (s->reg_count & COUNTER_CTRL_DEC) {
+        return r;
+    } else {
+        if (s->reg_count & COUNTER_CTRL_INT)
+            return s->reg_interval - r;
+        else
+            return 0xffff - r;
+    }
+}
+
+static void cadence_counter_clock(cadence_timer_state *s , uint32_t value)
+{
+    int freq;
+
+    s->reg_clock = value & 0x3f;
+    if (s->reg_clock & CLOCK_CTRL_PS_EN) {
+        freq = s->freq;
+        freq >>= ((value & CLOCK_CTRL_PS_V) >> 1) + 1;
+        ptimer_set_freq(s->timer, freq);
+    }
+}
+
+static void cadence_counter_control(cadence_timer_state *s , uint32_t value)
+{
+    s->reg_count = value & 0x3f;
+    if (value & COUNTER_CTRL_RST) {
+        ptimer_stop(s->timer);
+        cadence_timer_recalibrate(s);
+        s->reg_count &= ~COUNTER_CTRL_RST;
+    }
+    if (value & COUNTER_CTRL_DIS) {
+        ptimer_stop(s->timer);
+    } else {
+        cadence_timer_recalibrate(s);
+        ptimer_run(s->timer, 0);
+    }
+    if (value & COUNTER_CTRL_MATCH) {
+        cadence_timer_setup_events(s);
+    }
+}
+
+static void cadence_timer_next_event(cadence_timer_state *s)
+{
+    uint32_t limit = 0;
+
+    if (s->event_seq < s->event_total) {
+        limit = s->next_event[s->event_seq++];
+    } else {
+        s->event_seq = 0;
+    }
+
+    ptimer_set_limit(s->timer, limit, 1);
+}
+
+/*********************************************************
+ * Read Timer registers
+ *
+ *********************************************************/
+
+static uint32_t cadence_ttc_read_imp(void *opaque, target_phys_addr_t offset)
+{
+    cadence_timer_state *s = cadence_timer_from_addr(opaque, offset);
+    uint32_t value;
+
+    switch (offset) {
+    case 0x00: /* clock control */
+    case 0x04:
+    case 0x08:
+        return s->reg_clock;
+
+    case 0x0c: /* counter control */
+    case 0x10:
+    case 0x14:
+        return s->reg_count;
+
+    case 0x18: /* counter value */
+    case 0x1c:
+    case 0x20:
+        return cadence_counter_value(s);
+
+    case 0x24: /* reg_interval counter */
+    case 0x28:
+    case 0x2c:
+        return s->reg_interval;
+
+    case 0x30: /* match 1 counter */
+    case 0x34:
+    case 0x38:
+        return s->reg_match[0];
+
+    case 0x3c: /* match 2 counter */
+    case 0x40:
+    case 0x44:
+        return s->reg_match[1];
+
+    case 0x48: /* match 3 counter */
+    case 0x4c:
+    case 0x50:
+        return s->reg_match[2];
+
+    case 0x54: /* interrupt register */
+    case 0x58:
+    case 0x5c:
+        /* cleared after read */
+        value = s->reg_intr;
+        s->reg_intr = 0;
+        return value;
+
+    case 0x60: /* interrupt enable */
+    case 0x64:
+    case 0x68:
+        return s->reg_intr_en;
+
+    case 0x6c:
+    case 0x70:
+    case 0x74:
+        return s->reg_event_ctrl;
+
+    case 0x78:
+    case 0x7c:
+    case 0x80:
+        return s->reg_event;
+
+    default:
+        return 0;
+    }
+}
+
+static uint64_t cadence_ttc_read(void *opaque, target_phys_addr_t offset,
+    unsigned size)
+{
+    uint32_t ret = cadence_ttc_read_imp(opaque, offset);
+    qemu_debug("addr: %08x data: %08x\n", offset, ret);
+    return ret;
+}
+
+/*********************************************************
+ * Write Timer registers
+ *
+ *********************************************************/
+
+static void cadence_ttc_write(void *opaque, target_phys_addr_t offset,
+        uint64_t value, unsigned size)
+{
+    cadence_timer_state *s = cadence_timer_from_addr(opaque, offset);
+
+    qemu_debug("addr: %08x data %08x\n", offset, (unsigned)value);
+
+    switch (offset) {
+    case 0x00: /* clock control */
+    case 0x04:
+    case 0x08:
+        cadence_counter_clock (s, value);
+        break;
+
+    case 0x0c: /* conter control */
+    case 0x10:
+    case 0x14:
+        cadence_counter_control (s, value);
+        break;
+
+    case 0x24: /* interval register */
+    case 0x28:
+    case 0x2c:
+        s->reg_interval = value & 0xffff;
+        break;
+
+    case 0x30: /* match register */
+    case 0x34:
+    case 0x38:
+        s->reg_match[0] = value & 0xffff;
+
+    case 0x3c: /* match register */
+    case 0x40:
+    case 0x44:
+        s->reg_match[1] = value & 0xffff;
+
+    case 0x48: /* match register */
+    case 0x4c:
+    case 0x50:
+        s->reg_match[2] = value & 0xffff;
+        break;
+
+    case 0x54: /* interrupt register */
+    case 0x58:
+    case 0x5c:
+        s->reg_intr &= (~value & 0xfff);
+        break;
+
+    case 0x60: /* interrupt enable */
+    case 0x64:
+    case 0x68:
+        s->reg_intr_en = value & 0x3f;
+        break;
+
+    case 0x6c: /* event control */
+    case 0x70:
+    case 0x74:
+        s->reg_event_ctrl = value & 0x07;
+        break;
+
+    default:
+        return;
+    }
+
+    cadence_timer_update(s);
+}
+
+static const MemoryRegionOps cadence_ttc_ops = {
+    .read = cadence_ttc_read,
+    .write = cadence_ttc_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+/*********************************************************
+ * update time counter
+ *
+ *********************************************************/
+static void cadence_timer_tick(void *opaque)
+{
+    cadence_timer_state *s = (cadence_timer_state *)opaque;
+
+    if (s->reg_count & COUNTER_CTRL_MATCH) {
+        cadence_timer_next_event(s);
+    }
+
+    else
+    {
+        if (s->reg_count & COUNTER_CTRL_INT)
+        {
+            s->reg_intr |= COUNTER_INTR_IV;
+        }
+        else
+        {
+            s->reg_intr |= COUNTER_INTR_OV;
+        }
+    }
+
+    cadence_timer_update(s);
+}
+
+/*********************************************************
+ * Initialiaze each cadence TTC counter with its features
+ *
+ *********************************************************/
+
+static cadence_timer_state *cadence_timer_init(uint32_t freq)
+{
+    cadence_timer_state *s;
+    QEMUBH *bh;
+
+    s = (cadence_timer_state *)g_malloc0(sizeof(cadence_timer_state));
+    s->freq = freq;
+    s->reg_count = 0x21;
+
+    bh = qemu_bh_new(cadence_timer_tick, s);
+    s->timer = ptimer_init(bh);
+    ptimer_set_freq(s->timer, freq);
+
+    return s;
+}
+
+/*************************************************
+ * Initialiaze cadence TTC device on reset state
+ *
+ *************************************************/
+
+static int cadence_ttc_init(SysBusDevice *dev)
+{
+    cadence_ttc_state *s = FROM_SYSBUS(cadence_ttc_state, dev);
+
+    s->timer[0] = cadence_timer_init(2500000);
+    s->timer[1] = cadence_timer_init(2500000);
+    s->timer[2] = cadence_timer_init(2500000);
+
+    sysbus_init_irq(dev, &s->timer[0]->irq);
+    sysbus_init_irq(dev, &s->timer[1]->irq);
+    sysbus_init_irq(dev, &s->timer[2]->irq);
+
+    memory_region_init_io(&s->iomem, &cadence_ttc_ops, s, "timer", 0x1000);
+    sysbus_init_mmio(dev, &s->iomem);
+
+    return 0;
+}
+
+/********************************************
+ * Register cadence TTC device
+ *
+ *******************************************/
+static SysBusDeviceInfo ttc_info = {
+    .init = cadence_ttc_init,
+    .qdev.name  = "cadence_ttc",
+    .qdev.size  = sizeof(cadence_ttc_state),
+    .qdev.props = (Property[]) {
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void cadence_ttc_register_devices(void)
+{
+    sysbus_register_withprop(&ttc_info);
+}
+
+device_init(cadence_ttc_register_devices)
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: first revision
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision Peter A. G. Crosthwaite
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 2/7] cadence ttc: " Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-24  2:03     ` John Linn
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 4/7] cadence_gem: " Peter A. G. Crosthwaite
                     ` (3 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Device model for cadence watchdog timer (WDT)

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.target  |    1 +
 hw/cadence_wdt.c |  260 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 261 insertions(+), 0 deletions(-)
 create mode 100644 hw/cadence_wdt.c

diff --git a/Makefile.target b/Makefile.target
index 44ba41b..c7abcde 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -336,6 +336,7 @@ obj-arm-y += arm_boot.o pl011.o pl031.o pl050.o pl080.o pl110.o pl181.o pl190.o
 obj-arm-y += versatile_pci.o
 obj-arm-y += cadence_uart.o
 obj-arm-y += cadence_ttc.o
+obj-arm-y += cadence_wdt.o
 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
diff --git a/hw/cadence_wdt.c b/hw/cadence_wdt.c
new file mode 100644
index 0000000..c153d62
--- /dev/null
+++ b/hw/cadence_wdt.c
@@ -0,0 +1,260 @@
+/*
+ * Cadence System Watchdog Timer module.
+ *
+ * Copyright (c) 2010 Xilinx Inc.
+ * Written by M. Habib
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
+ * 02139, USA.
+ */
+
+#include <inttypes.h>
+#include "qemu-common.h"
+#include "qemu-timer.h"
+#include "watchdog.h"
+#include "hw.h"
+#include "sysbus.h"
+
+#define CADENCE_WDT_ZKEY 0x00000ABC
+#define CADENCE_WDT_CKEY 0x00000248
+#define CADENCE_WDT_RKEY 0x00001999
+#define CADENCE_WDT_ZVAL 0x00000FFF
+#define CADENCE_WDT_CVAL 0x0000003F
+
+#define CADENCE_WDT_ZKEY_SHT 12
+#define CADENCE_WDT_CKEY_SHT 6
+
+#define CADENCE_WDT_ENABLE_TIMER 0x00000001
+#define CADENCE_WDT_ENABLE_RESET 0x00000002
+#define CADENCE_WDT_ENABLE_INTR  0x00000004
+#define CADENCE_WDT_ENABLE_EXTNL 0x00000008
+
+#define CADENCE_WDT_RST_LEN 0x00000070
+#define CADENCE_WDT_INT_LEN 0x00000180
+#define CADENCE_WDT_SIG_LEN 0x00000E00
+
+#define CADENCE_WDT_RST_LEN 0x00000070
+#define CADENCE_WDT_INT_LEN 0x00000180
+#define CADENCE_WDT_SIG_LEN 0x00000E00
+
+#define CADENCE_WDT_RST_SHT 4
+#define CADENCE_WDT_INT_SHT 7
+#define CADENCE_WDT_SIG_SHT 9
+
+#define CADENCE_WDT_CCLOCK_LEN 0x00000003
+#define CADENCE_WDT_RSTART_VAL 0x0000003C
+#define CADENCE_WDT_RSTART_CNS 0x00000FFF
+
+#define CADENCE_WDT_RSTART_SHT 10
+
+typedef struct {
+    uint32_t zero_mode;
+    uint32_t counter_ctrl;
+    uint32_t status;
+    int      enabled;
+    int      reset;
+    int      intr;
+    int      extr;
+    uint32_t timer_preload;
+    uint32_t clock_prescale;
+    uint32_t reset_len;
+    uint32_t intr_len;
+    uint32_t signal_len;
+    QEMUTimer *timer;
+} cadence_watchdog_timer;
+
+typedef struct cadence_wdt_state {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    cadence_watchdog_timer *timer;
+} cadence_wdt_state;
+
+static void cadence_wdt_restart_timer(cadence_watchdog_timer *s)
+{
+    int64_t timeout = 0;
+    int64_t clock_scale = 0x00000008;
+
+    if (!s->enabled)
+        return;
+
+    timeout = s->timer_preload << (clock_scale << s->clock_prescale);
+
+    timeout = (int64_t) (get_ticks_per_sec() * (timeout / 2500000));
+
+    qemu_mod_timer(s->timer, qemu_get_clock_ns(vm_clock) + timeout);
+}
+
+static void cadence_wdt_disable_timer(cadence_watchdog_timer *s)
+{
+    qemu_del_timer(s->timer);
+}
+
+static void cadence_wdt_reset(cadence_watchdog_timer *s)
+{
+    cadence_wdt_disable_timer(s);
+}
+
+static void cadence_wdt_timer_expired(void *opaque)
+{
+    cadence_watchdog_timer *s = (cadence_watchdog_timer *) opaque;
+
+    s->status = 0;
+
+    if ((s->enabled) && (s->reset)) {
+        watchdog_perform_action();
+        cadence_wdt_reset(s);
+    }
+}
+
+static void cadence_wdt_cctrl_update(cadence_watchdog_timer *s , uint32_t value)
+{
+    /* get counter clock prescalar */
+    s->clock_prescale = (value & CADENCE_WDT_CCLOCK_LEN);
+
+    /* get restart value */
+    s->timer_preload = (((value & CADENCE_WDT_RSTART_VAL) <<
+                        CADENCE_WDT_RSTART_SHT) | CADENCE_WDT_RSTART_CNS);
+}
+
+static void cadence_wdt_zmode_update(cadence_watchdog_timer *s , uint32_t value)
+{
+
+    if (value & CADENCE_WDT_ENABLE_TIMER) {
+        s->enabled = 1;
+    }
+    else {
+        s->enabled = 0;
+    }
+
+    if (value & CADENCE_WDT_ENABLE_RESET) {
+        s->reset = 1;
+    }
+    else
+        s->reset = 0;
+
+    if (value & CADENCE_WDT_ENABLE_INTR) {
+        s->intr = 1;
+    }
+    else
+        s->intr = 0;
+
+    if (value & CADENCE_WDT_ENABLE_EXTNL) {
+        s->extr = 1;
+    }
+    else
+        s->extr = 0;
+
+    /* get output time lengths */
+    s->reset_len = ((value & CADENCE_WDT_RST_LEN) >> CADENCE_WDT_RST_SHT);
+    s->intr_len = ((value & CADENCE_WDT_INT_LEN) >> CADENCE_WDT_INT_SHT);
+    s->signal_len = ((value & CADENCE_WDT_SIG_LEN) >> CADENCE_WDT_SIG_SHT);
+}
+
+static uint64_t cadence_wdt_read(void *opaque, target_phys_addr_t offset,
+        unsigned size)
+{
+    cadence_watchdog_timer *s = (cadence_watchdog_timer *) opaque;
+
+    switch (offset) {
+        case 0x00:
+            return s->zero_mode;
+        case 0x04:
+            return s->counter_ctrl;
+        case 0x0c:
+            return s->status;
+        default:
+            return 0;
+    }
+}
+
+static void cadence_wdt_write(void *opaque, target_phys_addr_t offset,
+                                            uint64_t value, unsigned size)
+{
+    cadence_watchdog_timer *s = (cadence_watchdog_timer *) opaque;
+    uint32_t tmp = value;
+
+    switch (offset) {
+        case 0x0:
+            tmp = value >> CADENCE_WDT_ZKEY_SHT;
+            if (tmp == CADENCE_WDT_ZKEY) {
+                value &= CADENCE_WDT_ZVAL;
+                s->zero_mode = value;
+                cadence_wdt_zmode_update(s , value);
+            }
+        break;
+        case 0x04:
+            tmp = value >> CADENCE_WDT_CKEY_SHT;
+            if (tmp == CADENCE_WDT_CKEY) {
+                value &= CADENCE_WDT_CVAL;
+                s->counter_ctrl = value;
+                cadence_wdt_cctrl_update(s , value);
+            }
+        break;
+        case 0x08:
+            if (tmp == CADENCE_WDT_RKEY) {
+                cadence_wdt_restart_timer (s);
+            }
+
+        break;
+        default:
+        break;
+    }
+    return;
+}
+
+static const MemoryRegionOps cadence_wdt_ops = {
+    .read = cadence_wdt_read,
+    .write = cadence_wdt_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int cadence_wdt_init(SysBusDevice *dev)
+{
+    cadence_wdt_state *d = FROM_SYSBUS(cadence_wdt_state, dev);
+    cadence_watchdog_timer *s;
+
+    s = (cadence_watchdog_timer *)g_malloc0(sizeof(cadence_watchdog_timer));
+
+    s->zero_mode = 0x000001c3;
+
+    s->counter_ctrl = 0x0000003c;
+    s->status = 0x00000000;
+
+    s->enabled = 1;
+    s->reset = 1;
+    s->intr = 0;
+    s->extr = 0;
+    s->timer_preload = 0xffff;
+    s->clock_prescale = 0x0000;
+    s->reset_len = 0x0004;
+    s->intr_len = 0x0003;
+    s->signal_len = 0x0000;
+
+    s->timer = qemu_new_timer_ns(vm_clock, cadence_wdt_timer_expired, s);
+    d->timer = s;
+    memory_region_init_io(&d->iomem, &cadence_wdt_ops, s, "wdt", 0x1000);
+    sysbus_init_mmio(dev, &d->iomem);
+
+    return 0;
+}
+
+static WatchdogTimerModel model = {
+    .wdt_name = "cadence_wdt",
+    .wdt_description = "cadence SWDT for Pele",
+};
+
+static void cadence_wdt_register_devices(void)
+{
+    watchdog_add_model(&model);
+    sysbus_register_dev("cadence_wdt", sizeof(struct cadence_wdt_state),
+            cadence_wdt_init);
+}
+
+device_init(cadence_wdt_register_devices);
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 4/7] cadence_gem: first revision
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
                     ` (2 preceding siblings ...)
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: " Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-24  2:05     ` John Linn
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option Peter A. G. Crosthwaite
                     ` (2 subsequent siblings)
  6 siblings, 1 reply; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Device mode for cadence gem ethernet controller.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.target  |    1 +
 hw/cadence_gem.c | 1441 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1442 insertions(+), 0 deletions(-)
 create mode 100644 hw/cadence_gem.c

diff --git a/Makefile.target b/Makefile.target
index c7abcde..e62ff59 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -337,6 +337,7 @@ obj-arm-y += versatile_pci.o
 obj-arm-y += cadence_uart.o
 obj-arm-y += cadence_ttc.o
 obj-arm-y += cadence_wdt.o
+obj-arm-y += cadence_gem.o
 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
diff --git a/hw/cadence_gem.c b/hw/cadence_gem.c
new file mode 100644
index 0000000..76bcb70
--- /dev/null
+++ b/hw/cadence_gem.c
@@ -0,0 +1,1441 @@
+/*
+ * QEMU Xilinx GEM emulation
+ *
+ * Copyright (c) 2011 Xilinx, 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 "net.h"
+#include "devices.h"
+#include "sysemu.h"
+#include "net/checksum.h"
+
+/* For crc32 */
+#include <zlib.h>
+
+#include <strings.h>
+
+#define GEM_NWCTRL      0x00000000 /* Network Control reg */
+#define GEM_NWCFG       0x00000004 /* Network Config reg */
+#define GEM_NWSTATUS    0x00000008 /* Network Status reg */
+#define GEM_USERIO      0x0000000C /* User IO reg */
+#define GEM_DMACFG      0x00000010 /* DMA Control reg */
+#define GEM_TXSTATUS    0x00000014 /* TX Status reg */
+#define GEM_RXQBASE     0x00000018 /* RX Q Base address reg */
+#define GEM_TXQBASE     0x0000001C /* TX Q Base address reg */
+#define GEM_RXSTATUS    0x00000020 /* RX Status reg */
+#define GEM_ISR         0x00000024 /* Interrupt Status reg */
+#define GEM_IER         0x00000028 /* Interrupt Enable reg */
+#define GEM_IDR         0x0000002C /* Interrupt Disable reg */
+#define GEM_IMR         0x00000030 /* Interrupt Mask reg */
+#define GEM_PHYMNTNC    0x00000034 /* Phy Maintaince reg */
+#define GEM_RXPAUSE     0x00000038 /* RX Pause Time reg */
+#define GEM_TXPAUSE     0x0000003C /* TX Pause Time reg */
+#define GEM_TXPARTIALSF 0x00000040 /* TX Partial Store and Forward */
+#define GEM_RXPARTIALSF 0x00000044 /* RX Partial Store and Forward */
+#define GEM_HASHLO      0x00000080 /* Hash Low address reg */
+#define GEM_HASHHI      0x00000084 /* Hash High address reg */
+#define GEM_SPADDR1LO   0x00000088 /* Specific addr 1 low reg */
+#define GEM_SPADDR1HI   0x0000008C /* Specific addr 1 high reg */
+#define GEM_SPADDR2LO   0x00000090 /* Specific addr 2 low reg */
+#define GEM_SPADDR2HI   0x00000094 /* Specific addr 2 high reg */
+#define GEM_SPADDR3LO   0x00000098 /* Specific addr 3 low reg */
+#define GEM_SPADDR3HI   0x0000009C /* Specific addr 3 high reg */
+#define GEM_SPADDR4LO   0x000000A0 /* Specific addr 4 low reg */
+#define GEM_SPADDR4HI   0x000000A4 /* Specific addr 4 high reg */
+#define GEM_TIDMATCH1   0x000000A8 /* Type ID1 Match reg */
+#define GEM_TIDMATCH2   0x000000AC /* Type ID2 Match reg */
+#define GEM_TIDMATCH3   0x000000B0 /* Type ID3 Match reg */
+#define GEM_TIDMATCH4   0x000000B4 /* Type ID4 Match reg */
+#define GEM_WOLAN       0x000000B8 /* Wake on LAN reg */
+#define GEM_IPGSTRETCH  0x000000BC /* IPG Stretch reg */
+#define GEM_SVLAN       0x000000C0 /* Stacked VLAN reg */
+#define GEM_MODID       0x000000FC /* Module ID reg */
+#define GEM_OCTTXLO     0x00000100 /* Octects transmitted Low reg */
+#define GEM_OCTTXHI     0x00000104 /* Octects transmitted High reg */
+#define GEM_TXCNT       0x00000108 /* Error-free Frmaes transmitted counter */
+#define GEM_TXBCNT      0x0000010C /* Error-free Broadcast Frames counter*/
+#define GEM_TXMCNT      0x00000110 /* Error-free Multicast Frame counter */
+#define GEM_TXPAUSECNT  0x00000114 /* Pause Frames Transmitted Counter */
+#define GEM_TX64CNT     0x00000118 /* Error-free 64 TX */
+#define GEM_TX65CNT     0x0000011C /* Error-free 65-127 TX */
+#define GEM_TX128CNT    0x00000120 /* Error-free 128-255 TX */
+#define GEM_TX256CNT    0x00000124 /* Error-free 256-511 */
+#define GEM_TX512CNT    0x00000128 /* Error-free 512-1023 TX */
+#define GEM_TX1024CNT   0x0000012C /* Error-free 1024-1518 TX */
+#define GEM_TX1519CNT   0x00000130 /* Error-free larger than 1519 TX */
+#define GEM_TXURUNCNT   0x00000134 /* TX under run error counter */
+#define GEM_SINGLECOLLCNT   0x00000138 /* Single Collision Frame Counter */
+#define GEM_MULTCOLLCNT     0x0000013C /* Multiple Collision Frame Counter */
+#define GEM_EXCESSCOLLCNT   0x00000140 /* Excessive Collision Frame Counter */
+#define GEM_LATECOLLCNT     0x00000144 /* Late Collision Frame Counter */
+#define GEM_DEFERTXCNT  0x00000148 /* Deferred Transmission Frame Counter */
+#define GEM_CSENSECNT   0x0000014C /* Carrier Sense Error Counter */
+#define GEM_OCTRXLO     0x00000150 /* Octects Received register Low */
+#define GEM_OCTRXHI     0x00000154 /* Octects Received register High */
+#define GEM_RXCNT       0x00000158 /* Error-free Frames Received Counter */
+#define GEM_RXBROADCNT  0x0000015C /* Error-free Broadcast Frames RX */
+#define GEM_RXMULTICNT  0x00000160 /* Error-free Multicast Frames RX */
+#define GEM_RXPAUSECNT  0x00000164 /* Pause Frames Received Counter */
+#define GEM_RX64CNT     0x00000168 /* Error-free 64 byte Frames RX */
+#define GEM_RX65CNT     0x0000016C /* Error-free 65-127 byte Frames RX */
+#define GEM_RX128CNT    0x00000170 /* Error-free 128-255 byte Frames RX */
+#define GEM_RX256CNT    0x00000174 /* Error-free 256-512 byte Frames RX */
+#define GEM_RX512CNT    0x00000178 /* Error-free 512-1023 byte Frames RX */
+#define GEM_RX1024CNT   0x0000017C /* Error-free 1024-1518 byte Frames RX */
+#define GEM_RX1519CNT   0x00000180 /* Error-free 1519-max byte Frames RX */
+#define GEM_RXUNDERCNT  0x00000184 /* Undersize Frames Received Counter */
+#define GEM_RXOVERCNT   0x00000188 /* Oversize Frames Received Counter */
+#define GEM_RXJABCNT    0x0000018C /* Jabbers Received Counter */
+#define GEM_RXFCSCNT    0x00000190 /* Frame Check Sequence Error Counter */
+#define GEM_RXLENERRCNT 0x00000194 /* Length Field Error Counter */
+#define GEM_RXSYMERRCNT 0x00000198 /* Symbol Error Counter */
+#define GEM_RXALIGNERRCNT   0x0000019C /* Alignment Error Counter */
+#define GEM_RXRSCERRCNT 0x000001A0 /* Receive Resource Error Counter */
+#define GEM_RXORUNCNT   0x000001A4 /* Receive Overrun Counter */
+#define GEM_RXIPCSERRCNT    0x000001A8 /* IP header Checksum Error Counter */
+#define GEM_RXTCPCCNT   0x000001AC /* TCP Checksum Error Counter */
+#define GEM_RXUDPCCNT   0x000001B0 /* UDP Checksum Error Counter */
+
+#define GEM_1588S       0x000001D0 /* 1588 Timer Seconds */
+#define GEM_1588NS      0x000001D4 /* 1588 Timer Nanoseconds */
+#define GEM_1588ADJ     0x000001D8 /* 1588 Timer Adjust */
+#define GEM_1588INC     0x000001DC /* 1588 Timer Increment */
+#define GEM_PTPETXS     0x000001E0 /* PTP Event Frame Transmitted Seconds */
+#define GEM_PTPETXNS    0x000001E4 /* PTP Event Frame Transmitted Nanoseconds */
+#define GEM_PTPERXS     0x000001E8 /* PTP Event Frame Received Seconds */
+#define GEM_PTPERXNS    0x000001EC /* PTP Event Frame Received Nanoseconds */
+#define GEM_PTPPTXS     0x000001E0 /* PTP Peer Frame Transmitted Seconds */
+#define GEM_PTPPTXNS    0x000001E4 /* PTP Peer Frame Transmitted Nanoseconds */
+#define GEM_PTPPRXS     0x000001E8 /* PTP Peer Frame Received Seconds */
+#define GEM_PTPPRXNS    0x000001EC /* PTP Peer Frame Received Nanoseconds */
+
+#define GEM_DESCONF     0x00000280 /* Design Configuration Register */
+#define GEM_DESCONF2    0x00000284 /* Design Configuration Register */
+#define GEM_DESCONF3    0x00000288 /* Design Configuration Register */
+#define GEM_DESCONF4    0x0000028C /* Design Configuration Register */
+#define GEM_DESCONF5    0x00000290 /* Design Configuration Register */
+#define GEM_DESCONF6    0x00000294 /* Design Configuration Register */
+#define GEM_DESCONF7    0x00000298 /* Design Configuration Register */
+
+#define GEM_MAXREG      0x00000640  /* Last valid GEM address */
+
+/*****************************************/
+#define GEM_NWCTRL_TXSTART     0x00000200 /* Transmit Enable */
+#define GEM_NWCTRL_TXENA       0x00000008 /* Transmit Enable */
+#define GEM_NWCTRL_RXENA       0x00000004 /* Receive Enable */
+#define GEM_NWCTRL_LOCALLOOP   0x00000002 /* Local Loopback */
+
+#define GEM_NWCFG_STRIP_FCS    0x00020000 /* Strip FCS field */
+#define GEM_NWCFG_LERR_DISC    0x00010000 /* Discard RX frames with lenth err */
+#define GEM_NWCFG_BUFF_OFST_M  0x0000C000 /* Receive buffer offset mask */
+#define GEM_NWCFG_BUFF_OFST_S  14         /* Receive buffer offset shift */
+#define GEM_NWCFG_UCAST_HASH   0x00000080 /* accept unicast if hash match */
+#define GEM_NWCFG_MCAST_HASH   0x00000040 /* accept multicast if hash match */
+#define GEM_NWCFG_BCAST_REJ    0x00000020 /* Reject broadcast packets */
+#define GEM_NWCFG_PERMISC      0x00000010 /* Accept all packets */
+
+#define GEM_DMACFG_TXCSUM_OFFL 0x00000800 /* Transmit checksum offload */
+#define GEM_DMACFG_RBUFSZ_M    0x007F0000 /* DMA RX Buffer Size mask */
+#define GEM_DMACFG_RBUFSZ_S    16         /* DMA RX Buffer Size shift */
+#define GEM_DMACFG_RBUFSZ_MUL  64         /* DMA RX Buffer Size multiplier */
+
+#define GEM_TXSTATUS_TXCMPL    0x00000020 /* Transmit Complete */
+#define GEM_TXSTATUS_USED      0x00000001 /* sw owned descriptor encountered */
+
+#define GEM_RXSTATUS_FRMRCVD   0x00000002 /* Frame received */
+#define GEM_RXSTATUS_NOBUF     0x00000001 /* Buffer unavailable */
+
+/* GEM_ISR GEM_IER GEM_IDR GEM_IMR */
+#define GEM_INT_TXCOMPL        0x00000080 /* Transmit Complete */
+#define GEM_INT_TXUSED         0x00000008
+#define GEM_INT_RXUSED         0x00000004
+#define GEM_INT_RXCOMPL        0x00000002
+
+#define GEM_PHYMNTNC_OP_R      0x20000000 /* read operation */
+#define GEM_PHYMNTNC_OP_W      0x10000000 /* write operation */
+#define GEM_PHYMNTNC_ADDR      0x0F800000 /* Address bits */
+#define GEM_PHYMNTNC_ADDR_SHFT 23
+#define GEM_PHYMNTNC_REG       0x007C0000 /* register bits */
+#define GEM_PHYMNTNC_REG_SHIFT 18
+
+/* Marvell PHY definitions */
+#define BOARD_PHY_ADDRESS    23 /* PHY address we will emulate a device at */
+
+#define PHY_REG_CONTROL      0
+#define PHY_REG_STATUS       1
+#define PHY_REG_PHYID1       2
+#define PHY_REG_PHYID2       3
+#define PHY_REG_ANEGADV      4
+#define PHY_REG_LINKPABIL    5
+#define PHY_REG_ANEGEXP      6
+#define PHY_REG_NEXTP        7
+#define PHY_REG_LINKPNEXTP   8
+#define PHY_REG_100BTCTRL    9
+#define PHY_REG_1000BTSTAT   10
+#define PHY_REG_EXTSTAT      15
+#define PHY_REG_PHYSPCFC_CTL 16
+#define PHY_REG_PHYSPCFC_ST  17
+#define PHY_REG_INT_EN       18
+#define PHY_REG_INT_ST       19
+#define PHY_REG_EXT_PHYSPCFC_CTL  20
+#define PHY_REG_RXERR        21
+#define PHY_REG_EACD         22
+#define PHY_REG_LED          24
+#define PHY_REG_LED_OVRD     25
+#define PHY_REG_EXT_PHYSPCFC_CTL2 26
+#define PHY_REG_EXT_PHYSPCFC_ST   27
+#define PHY_REG_CABLE_DIAG   28
+
+#define PHY_REG_CONTROL_RST  0x8000
+#define PHY_REG_CONTROL_LOOP 0x4000
+#define PHY_REG_CONTROL_ANEG 0x1000
+
+#define PHY_REG_STATUS_LINK     0x0004
+#define PHY_REG_STATUS_ANEGCMPL 0x0020
+
+#define PHY_REG_INT_ST_ANEGCMPL 0x0800
+#define PHY_REG_INT_ST_LINKC    0x0400
+#define PHY_REG_INT_ST_ENERGY   0x0010
+
+/***********************************************************************/
+#define GEM_RX_REJECT  1
+#define GEM_RX_ACCEPT  0
+
+/***********************************************************************/
+
+static inline unsigned tx_desc_get_buffer(unsigned *desc)
+{
+    return desc[0];
+}
+static inline unsigned tx_desc_get_used(unsigned *desc)
+{
+    return (desc[1] & 0x80000000) ? 1 : 0;
+}
+static inline void tx_desc_set_used(unsigned *desc)
+{
+    desc[1] |= 0x80000000;
+}
+static inline unsigned tx_desc_get_wrap(unsigned *desc)
+{
+    return (desc[1] & 0x40000000) ? 1 : 0;
+}
+static inline unsigned tx_desc_get_last(unsigned *desc)
+{
+    return (desc[1] & 0x00008000) ? 1 : 0;
+}
+static inline unsigned tx_desc_get_length(unsigned *desc)
+{
+    return desc[1] & 0x1FFF;
+}
+
+static inline void print_gem_tx_desc (unsigned *desc)
+{
+    printf("TXDESC: \n");
+    printf(" bufaddr: 0x%08x\n", *desc);
+    printf(" used_hw: %d\n", tx_desc_get_used(desc));
+    printf(" wrap:    %d\n", tx_desc_get_wrap(desc));
+    printf(" last:    %d\n", tx_desc_get_last(desc));
+    printf(" length:  %d\n", tx_desc_get_length(desc));
+}
+
+static inline unsigned rx_desc_get_buffer(unsigned *desc)
+{
+    return (desc[0] & 0xFFFFFFFC);
+}
+static inline unsigned rx_desc_get_wrap(unsigned *desc)
+{
+    return (desc[0] & 0x00000002) ? 1 : 0;
+}
+static inline unsigned rx_desc_get_ownership(unsigned *desc)
+{
+    return (desc[0] & 0x00000001) ? 1 : 0;
+}
+static inline void rx_desc_set_ownership(unsigned *desc)
+{
+    desc[0] |= 0x00000001;
+}
+static inline void rx_desc_set_sof(unsigned *desc)
+{
+    desc[1] |= 0x00004000;
+}
+static inline void rx_desc_set_eof(unsigned *desc)
+{
+    desc[1] |= 0x00008000;
+}
+static inline void rx_desc_set_length(unsigned *desc, unsigned len)
+{
+    desc[1] &= 0xFFFFE000;
+    desc[1] |= len;
+}
+
+typedef struct {
+    SysBusDevice busdev;
+    MemoryRegion iomem;
+    NICState *nic;
+    NICConf conf;
+    qemu_irq irq;
+
+    /* GEM registers backing store */
+    uint32_t regs[GEM_MAXREG/4];
+    /* Mask of register bits which are write only */
+    uint32_t regs_wo[GEM_MAXREG/4];
+    /* Mask of register bits which are read only */
+    uint32_t regs_ro[GEM_MAXREG/4];
+    /* Mask of register bits which are clear on read */
+    uint32_t regs_rtc[GEM_MAXREG/4];
+    /* Mask of register bits which are write 1 to clear */
+    uint32_t regs_w1c[GEM_MAXREG/4];
+
+    /* PHY registers backing store */
+    uint16_t phy_regs[32];
+
+    int phy_loop; /* Are we in phy loopback? */
+
+    /* The current DMA descriptor pointers */
+    target_phys_addr_t rx_desc_addr;
+    target_phys_addr_t tx_desc_addr;
+
+} gem_state;
+
+/* The broadcast MAC address: 0xFFFFFFFFFFFF */
+const uint8_t Broadcast_Addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+
+/*
+ * gem_init_register_masks:
+ * One time initialization.
+ * Set masks to identify which register bits have magical clear properties
+ */
+static void gem_init_register_masks(gem_state *s)
+{
+    /* Mask of register bits which are read only*/
+    bzero(&s->regs_ro[0], GEM_MAXREG);
+    s->regs_ro[GEM_NWCTRL/4]   = 0xFFF80000;
+    s->regs_ro[GEM_NWSTATUS/4] = 0xFFFFFFFF;
+    s->regs_ro[GEM_DMACFG/4]   = 0xFE00F000;
+    s->regs_ro[GEM_TXSTATUS/4] = 0xFFFFFE08;
+    s->regs_ro[GEM_RXQBASE/4]  = 0x00000003;
+    s->regs_ro[GEM_TXQBASE/4]  = 0x00000003;
+    s->regs_ro[GEM_RXSTATUS/4] = 0xFFFFFFF0;
+    s->regs_ro[GEM_ISR/4]      = 0xFFFFFFFF;
+    s->regs_ro[GEM_IMR/4]      = 0xFFFFFFFF;
+    s->regs_ro[GEM_MODID/4]    = 0xFFFFFFFF;
+
+    /* Mask of register bits which are clear on read */
+    bzero(&s->regs_rtc[0], GEM_MAXREG);
+    s->regs_rtc[GEM_ISR/4]      = 0xFFFFFFFF;
+
+    /* Mask of register bits which are write 1 to clear */
+    bzero(&s->regs_w1c[0], GEM_MAXREG);
+    s->regs_w1c[GEM_TXSTATUS/4] = 0x000001F7;
+    s->regs_w1c[GEM_RXSTATUS/4]  = 0x0000000F;
+
+    /* Mask of register bits which are write only */
+    bzero(&s->regs_wo[0], GEM_MAXREG);
+    s->regs_wo[GEM_NWCTRL/4]   = 0x00073E60;
+    s->regs_wo[GEM_IER/4]      = 0x07FFFFFF;
+    s->regs_wo[GEM_IDR/4]      = 0x07FFFFFF;
+}
+
+/*
+ * phy_update_link:
+ * Make the emulated PHY link state match the QEMU "interface" state.
+ */
+static void phy_update_link(gem_state *s)
+{
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("QEMU: %s: down %d\n", __FUNCTION__, s->nic->nc.link_down);
+#endif
+
+    /* Autonegotiation status mirrors link status.  */
+    if (s->nic->nc.link_down) {
+        s->phy_regs[PHY_REG_STATUS] &= ~(PHY_REG_STATUS_ANEGCMPL |
+                                         PHY_REG_STATUS_LINK);
+        s->phy_regs[PHY_REG_INT_ST] |= PHY_REG_INT_ST_LINKC;
+    } else {
+        s->phy_regs[PHY_REG_STATUS] |= (PHY_REG_STATUS_ANEGCMPL |
+                                         PHY_REG_STATUS_LINK);
+        s->phy_regs[PHY_REG_INT_ST] |= (PHY_REG_INT_ST_LINKC |
+                                        PHY_REG_INT_ST_ANEGCMPL |
+                                        PHY_REG_INT_ST_ENERGY);
+    }
+}
+
+static int gem_can_receive(VLANClientState *nc)
+{
+    gem_state *s;
+
+    s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("QEMU: %s:\n", __FUNCTION__);
+#endif
+
+    /* Do nothing if receive is not enabled. */
+    if (!(s->regs[GEM_NWCTRL/4] & GEM_NWCTRL_RXENA)) {
+        return 0;
+    }
+
+    return 1;
+}
+
+/*
+ * gem_update_int_status:
+ * Raise or lower interrupt based on current status.
+ */
+static void gem_update_int_status(gem_state *s)
+{
+    /* Packet transmitted ? */
+    if (s->regs[GEM_TXSTATUS/4] & GEM_TXSTATUS_TXCMPL) {
+        /* TX Completion ints enabled ? */
+        if ((s->regs[GEM_IMR/4] & GEM_INT_TXCOMPL) == 0) {
+            s->regs[GEM_ISR/4] |= GEM_INT_TXCOMPL;
+        }
+    }
+    /* End of TX ring ? */
+    if (s->regs[GEM_TXSTATUS/4] & GEM_TXSTATUS_USED) {
+        /* int enabled ? */
+        if ((s->regs[GEM_IMR/4] & GEM_INT_TXUSED) == 0) {
+            s->regs[GEM_ISR/4] |= GEM_INT_TXUSED;
+        }
+    }
+
+    /* Frame received ? */
+    if (s->regs[GEM_RXSTATUS/4] & GEM_RXSTATUS_FRMRCVD) {
+        /* int enabled ? */
+        if ((s->regs[GEM_IMR/4] & GEM_INT_RXCOMPL) == 0) {
+            s->regs[GEM_ISR/4] |= GEM_INT_RXCOMPL;
+        }
+    }
+    /* RX ring full ? */
+    if (s->regs[GEM_RXSTATUS/4] & GEM_RXSTATUS_NOBUF) {
+        /* int enabled ? */
+        if ((s->regs[GEM_IMR/4] & GEM_INT_RXUSED) == 0) {
+            s->regs[GEM_ISR/4] |= GEM_INT_RXUSED;
+        }
+    }
+
+    if (s->regs[GEM_ISR/4]) {
+#ifdef GEM_DEBUG_INT
+        printf("QEMU: %s: asserting int. (0x%08x)\n",
+            __FUNCTION__, s->regs[GEM_ISR/4]);
+#endif
+        qemu_set_irq(s->irq, 1);
+    } else {
+        qemu_set_irq(s->irq, 0);
+    }
+}
+
+#ifdef GEM_DEBUG_PACKET
+/*
+ * print_packet:
+ * Decode provided packet.
+ */
+static void print_packet (const uint8_t *packet, unsigned len, int rx_tx)
+{
+    int i;
+    unsigned ethtype;
+
+    printf("PACKET: %s length: %d\n",
+     (rx_tx ? "RX" : "TX"), len);
+
+    printf("DST:     ");
+    for (i=0; i<6; i++) {
+        printf("%02x", *packet);
+        packet++;
+    }
+    printf("\n");
+    len -= 6;
+
+    printf("SRC:     ");
+    for (i=0; i<6; i++) {
+        printf("%02x", *packet);
+        packet++;
+    }
+    len -= 6;
+    printf("\n");
+
+    printf("ETHTYPE: ");
+    ethtype = 0;
+    for (i=0; i<2; i++) {
+        ethtype <<= 8;
+        ethtype |= *packet;
+        packet++;
+    }
+    len -= 2;
+    printf("%02x\n", ethtype);
+
+    if (ethtype == 0x800) {
+        unsigned ip_proto;
+
+        packet += 9;
+        len -= 9;
+        ip_proto = *packet;
+        printf("IPPROTO:  %d ", ip_proto);
+        switch(ip_proto) {
+        case 1:
+            printf("ICMP ");
+            break;
+        case 6:
+            printf("TCP ");
+            break;
+        case 17:
+            printf("UDP ");
+            break;
+        }
+        printf("\n");
+
+        printf("IPSRC: ");
+        packet += 3;
+        len -= 3;
+        for (i=0; i<4; i++) {
+            printf("%d", *packet);
+            if (i != 3) printf(".");
+            packet++;
+        }
+        len -= 4;
+        printf("\n");
+
+        printf("IPDST: ");
+        for (i=0; i<4; i++) {
+            printf("%d", *packet);
+            if (i != 3) printf(".");
+            packet++;
+        }
+        len -= 4;
+        printf("\n");
+
+        switch(ip_proto) {
+        case 1:
+            printf("ICMP ");
+            break;
+        case 6:
+            printf("TCP SOURCE PORT: 0x%02x%02x\n",
+                packet[0], packet[1]);
+            packet += 2;
+            len -= 2;
+
+            printf("TCP DEST PORT:   0x%02x%02x\n",
+                packet[0], packet[1]);
+            packet += 2;
+            len -= 2;
+
+            printf("TCP SEQ:         0x%02x%02x%02x%02x\n",
+                packet[0], packet[1], packet[2], packet[3]);
+            packet += 4;
+            len -= 4;
+
+            printf("TCP ACK:         0x%02x%02x%02x%02x\n",
+                packet[0], packet[1], packet[2], packet[3]);
+            packet += 4;
+            len -= 4;
+
+            packet++;
+            len--;
+            printf("TCP FLAGS: ");
+            if (*packet & 0x80) {
+                printf("CWR ");
+            }
+            if (*packet & 0x40) {
+                printf("ECE ");
+            }
+            if (*packet & 0x20) {
+                printf("URG ");
+            }
+            if (*packet & 0x10) {
+                printf("ACK ");
+            }
+            if (*packet & 0x08) {
+                printf("PSH ");
+            }
+            if (*packet & 0x04) {
+                printf("RST ");
+            }
+            if (*packet & 0x02) {
+                printf("SYN ");
+            }
+            if (*packet & 0x01) {
+                printf("FIN ");
+            }
+            printf("\n");
+
+            packet += 3;
+            len -= 3;
+            printf("TCP CHECKSUM:    0x%02x%02x\n",
+                packet[0], packet[1]);
+            packet += 2;
+            len -= 2;
+
+            break;
+        case 17:
+            printf("UDP ");
+            break;
+        }
+    }
+    if (ethtype == 0x806) {
+        unsigned op;
+
+        packet += 7;
+        len -= 7;
+        op = *packet;
+
+        if (op == 1) {
+            printf("WHOHAS: ");
+            packet += 17;
+            len -= 17;
+        } else {
+            printf("IHAVE:  ");
+            packet += 7;
+            len -= 7;
+        }
+        for (i=0; i<4; i++) {
+            printf("%d", *packet);
+            if (i != 3) printf(".");
+            packet++;
+        }
+        len -= 4;
+        printf("\n");
+    }
+
+    printf("DATA:  ");
+    for (i=0; i<MIN(len,16); i++) {
+        printf("%02x", *packet);
+        packet++;
+    }
+    printf("\n\n");
+}
+#endif
+
+/*
+ * gem_receive_updatestats:
+ * Increment receive statistics.
+ */
+static void gem_receive_updatestats(gem_state *s, const uint8_t *packet,
+                                    unsigned bytes)
+{
+    uint64_t octets;
+
+    /* Total octets (bytes) received */
+    octets = ((uint64_t)(s->regs[GEM_OCTRXLO/4]) << 32) |
+             s->regs[GEM_OCTRXHI/4];
+    octets += bytes;
+    s->regs[GEM_OCTRXLO/4] = octets >> 32;
+    s->regs[GEM_OCTRXHI/4] = octets;
+
+    /* Error-free Frames reveived */
+    s->regs[GEM_RXCNT/4]++;
+
+    /* Error-free Broadcast Frames counter */
+    if (memcmp(packet, Broadcast_Addr, 6) == 0) {
+        s->regs[GEM_RXBROADCNT/4]++;
+    }
+
+    /* Error-free Multicast Frames counter */
+    if (packet[0] == 0x01) {
+        s->regs[GEM_RXMULTICNT/4]++;
+    }
+
+    if (bytes <= 64) {
+        s->regs[GEM_RX64CNT/4]++;
+    } else if (bytes <= 127) {
+        s->regs[GEM_RX65CNT/4]++;
+    } else if (bytes <= 255) {
+        s->regs[GEM_RX128CNT/4]++;
+    } else if (bytes <= 511) {
+        s->regs[GEM_RX256CNT/4]++;
+    } else if (bytes <= 1023) {
+        s->regs[GEM_RX512CNT/4]++;
+    } else if (bytes <= 1518) {
+        s->regs[GEM_RX1024CNT/4]++;
+    } else {
+        s->regs[GEM_RX1519CNT/4]++;
+    }
+}
+
+/*
+ * Get the MAC Address bit from the specified position
+ */
+static unsigned get_bit(const uint8_t *mac, unsigned bit)
+{
+    unsigned byte;
+
+    byte = mac[bit / 8];
+    byte >>= (bit & 0x7);
+    byte &= 1;
+
+    return byte;
+}
+
+/*
+ * Calculate a GEM MAC Address hash index
+ */
+static unsigned calc_mac_hash(const uint8_t *mac)
+{
+    int index_bit, mac_bit;
+    unsigned hash_index;
+
+    hash_index = 0;
+    mac_bit = 5;
+    for (index_bit = 5; index_bit >= 0; index_bit--) {
+        hash_index |= (get_bit(mac,  mac_bit) ^
+                               get_bit(mac, mac_bit + 6) ^
+                               get_bit(mac, mac_bit + 12) ^
+                               get_bit(mac, mac_bit + 18) ^
+                               get_bit(mac, mac_bit + 24) ^
+                               get_bit(mac, mac_bit + 30) ^
+                               get_bit(mac, mac_bit + 36) ^
+                               get_bit(mac, mac_bit + 42)) << index_bit;
+        mac_bit--;
+    }
+
+    return hash_index;
+}
+
+/*
+ * gem_mac_address_filter:
+ * Accept or reject this destination address?
+ * Returns:
+ * GEM_RX_REJECT: reject
+ * GEM_RX_ACCEPT: accept
+ */
+static int gem_mac_address_filter(gem_state *s, const uint8_t *packet)
+{
+    uint8_t *gem_spaddr;
+    int i;
+
+    /* Permiscuous mode? */
+    if (s->regs[GEM_NWCFG/4] & GEM_NWCFG_PERMISC) {
+        return GEM_RX_ACCEPT;
+    }
+
+    if (memcmp(packet, Broadcast_Addr, 6) == 0) {
+        /* Recject broadcast packets? */
+        if (s->regs[GEM_NWCFG/4] & GEM_NWCFG_BCAST_REJ) {
+            return GEM_RX_REJECT;
+        } else {
+            return GEM_RX_ACCEPT;
+        }
+    }
+
+    /* Accept packets -w- hash match? */
+    if ((packet[0] == 0x01 && (s->regs[GEM_NWCFG/4] & GEM_NWCFG_MCAST_HASH)) ||
+        (packet[0] != 0x01 && (s->regs[GEM_NWCFG/4] & GEM_NWCFG_UCAST_HASH))) {
+        unsigned hash_index;
+
+        hash_index = calc_mac_hash(packet);
+        if (hash_index < 32) {
+            if (s->regs[GEM_HASHLO/4] & (1<<hash_index)) {
+                return GEM_RX_ACCEPT;
+            }
+        } else {
+            hash_index -= 32;
+            if (s->regs[GEM_HASHHI/4] & (1<<hash_index)) {
+                return GEM_RX_ACCEPT;
+            }
+        }
+    }
+
+    /* Check all 4 specific addresses */
+    gem_spaddr = (uint8_t*)&(s->regs[GEM_SPADDR1LO/4]);
+    for (i=0; i<4; i++) {
+        if (memcmp(packet, gem_spaddr, 6) == 0) {
+            return GEM_RX_ACCEPT;
+        }
+
+        gem_spaddr += 8;
+    }
+
+    /* No address match; reject the packet */
+    return GEM_RX_REJECT;
+}
+
+/*
+ * gem_receive:
+ * Fit a packet handed to us by QEMU into the receive descriptor ring.
+ */
+static ssize_t gem_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
+{
+    unsigned    desc[2];
+    target_phys_addr_t packet_desc_addr, last_desc_addr;
+    gem_state *s;
+    unsigned   rxbufsize, bytes_to_copy;
+    unsigned   rxbuf_offset;
+    uint8_t    rxbuf[2048];
+    uint8_t   *rxbuf_ptr;
+
+    s = DO_UPCAST(NICState, nc, nc)->opaque;
+
+    /* Do nothing if receive is not enabled. */
+    if (!(s->regs[GEM_NWCTRL/4] & GEM_NWCTRL_RXENA)) {
+        return -1;
+    }
+
+    /* Is this destination MAC address "for us" ? */
+    if (gem_mac_address_filter(s, buf) == GEM_RX_REJECT) {
+        return -1;
+    }
+
+    /* Discard packets with receive length error enabled ? */
+    if (s->regs[GEM_NWCFG/4] & GEM_NWCFG_LERR_DISC) {
+        unsigned type_len;
+
+        /* Fish the ethertype / length field out of the RX packet */
+        type_len = buf[12] << 8 | buf[13];
+        /* It is a length field, not an ethertype */
+        if (type_len < 0x600) {
+            if (size < type_len) {
+                /* discard */
+                return -1;
+            }
+        }
+    }
+
+    /*
+     * Determine configured receive buffer offset (probably 0)
+     */
+    rxbuf_offset = (s->regs[GEM_NWCFG/4] & GEM_NWCFG_BUFF_OFST_M) >>
+                   GEM_NWCFG_BUFF_OFST_S;
+
+    /* The configure size of each receive buffer.  Determines how many
+     * buffers needed to hold this packet.
+     */
+    rxbufsize = ((s->regs[GEM_DMACFG/4] & GEM_DMACFG_RBUFSZ_M) >>
+                 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
+    bytes_to_copy = size;
+
+    /* Strip of FCS field ? (usually yes) */
+    if (s->regs[GEM_NWCFG/4] & GEM_NWCFG_STRIP_FCS) {
+        rxbuf_ptr = (void*)buf;
+    } else {
+        unsigned crc_val;
+        int      crc_offset;
+
+        /* The application wants the FCS field, which QEMU does not provide.
+         * We must try and caclculate one.
+         */
+
+        memcpy(rxbuf, buf, size);
+        bzero(rxbuf + size, sizeof(rxbuf - size));
+        rxbuf_ptr = rxbuf;
+        crc_val = cpu_to_le32(crc32(0, rxbuf, MAX(size, 60)));
+        if (size < 60) {
+            crc_offset = 60;
+        } else {
+            crc_offset = size;
+        }
+        memcpy(rxbuf + crc_offset, &crc_val, sizeof(crc_val));
+
+        bytes_to_copy += 4;
+        size += 4;
+    }
+
+    /* Pad to minimum length */
+    if (size < 64) {
+        size = 64;
+    }
+
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("QEMU: %s: config bufsize: %d packet size: %ld\n",
+        __FUNCTION__, rxbufsize, size);
+#endif
+
+    packet_desc_addr = s->rx_desc_addr;
+    while (1) {
+#ifdef GEM_DEBUG_RX
+        printf("QEMU: %s: read descriptor 0x%x \n",
+            __FUNCTION__, packet_desc_addr);
+#endif
+        /* read current descriptor */
+        cpu_physical_memory_read(packet_desc_addr,
+                                 (uint8_t *)&desc[0], sizeof(desc));
+
+        /* Descriptor owned by software ? */
+        if (rx_desc_get_ownership(desc) == 1) {
+#ifdef GEM_DEBUG_RX
+            printf("QEMU: %s: descriptor 0x%x owned by sw.\n",
+                __FUNCTION__, packet_desc_addr);
+#endif
+            s->regs[GEM_RXSTATUS/4] |= GEM_RXSTATUS_NOBUF;
+            /* Handle interrupt consequences */
+            gem_update_int_status(s);
+            return -1;
+        }
+
+#ifdef GEM_DEBUG_RX
+        printf("QEMU: %s: copy %d bytes to 0x%x\n", __FUNCTION__,
+                MIN(bytes_to_copy, rxbufsize),
+                rx_desc_get_buffer(desc));
+#endif
+
+        /*
+         * Let's have QEMU lend a helping hand.
+         */
+        if (rx_desc_get_buffer(desc) == 0) {
+            printf("QEMU: GEM: Invalid RX buffer (NULL) for descriptor 0x%x\n",
+                packet_desc_addr);
+            break;
+        }
+
+        /* Copy packet data to emulated DMA buffer */
+        cpu_physical_memory_write(rx_desc_get_buffer(desc) + rxbuf_offset,
+                                  rxbuf_ptr, MIN(bytes_to_copy, rxbufsize));
+        bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
+        rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
+        if (bytes_to_copy == 0) {
+            break;
+        }
+
+        /* Next descriptor */
+        if (rx_desc_get_wrap(desc)) {
+            packet_desc_addr = s->regs[GEM_RXQBASE/4];
+        } else {
+            packet_desc_addr += 8;
+        }
+    }
+
+#ifdef GEM_DEBUG_PACKET
+    print_packet(buf, size, 1);
+#endif
+
+#ifdef GEM_DEBUG_RX
+    printf("QEMU: %s: set length: %ld, EOF on descriptor 0x%x\n", __FUNCTION__,
+         size, (unsigned)packet_desc_addr);
+#endif
+
+    /* Update last descriptor with EOF and total length */
+    rx_desc_set_eof(desc);
+    rx_desc_set_length(desc, size);
+    cpu_physical_memory_write(packet_desc_addr,
+                              (uint8_t *)&desc[0], sizeof(desc));
+
+    /* Advance RX packet descriptor Q */
+    last_desc_addr = packet_desc_addr;
+    packet_desc_addr = s->rx_desc_addr;
+    s->rx_desc_addr = last_desc_addr;
+    if (rx_desc_get_wrap(desc)) {
+        s->rx_desc_addr = s->regs[GEM_RXQBASE/4];
+    } else {
+        s->rx_desc_addr += 8;
+    }
+
+#ifdef GEM_DEBUG_RX
+    printf("QEMU: %s: set SOF, OWN on descriptor 0x%08x\n", __FUNCTION__,
+        packet_desc_addr);
+#endif
+
+    /* Count it */
+    gem_receive_updatestats(s, buf, size);
+
+    /* Update first descriptor (which could also be the last) */
+    /* read descriptor */
+    cpu_physical_memory_read(packet_desc_addr,
+                             (uint8_t *)&desc[0], sizeof(desc));
+    rx_desc_set_sof(desc);
+    rx_desc_set_ownership(desc);
+    cpu_physical_memory_write(packet_desc_addr,
+                              (uint8_t *)&desc[0], sizeof(desc));
+
+    s->regs[GEM_RXSTATUS/4] |= GEM_RXSTATUS_FRMRCVD;
+
+    /* Handle interrupt consequences */
+    gem_update_int_status(s);
+
+    return size;
+}
+
+/*
+ * gem_transmit_updatestats:
+ * Increment transmit statistics.
+ */
+static void gem_transmit_updatestats(gem_state *s, const uint8_t *packet,
+                                     unsigned bytes)
+{
+    uint64_t octets;
+
+    /* Total octets (bytes) transmitted */
+    octets = ((uint64_t)(s->regs[GEM_OCTTXLO/4]) << 32) |
+             s->regs[GEM_OCTTXHI/4];
+    octets += bytes;
+    s->regs[GEM_OCTTXLO/4] = octets >> 32;
+    s->regs[GEM_OCTTXHI/4] = octets;
+
+    /* Error-free Frmaes transmitted */
+    s->regs[GEM_TXCNT/4]++;
+
+    /* Error-free Broadcast Frames counter */
+    if (memcmp(packet, Broadcast_Addr, 6) == 0) {
+        s->regs[GEM_TXBCNT/4]++;
+    }
+
+    /* Error-free Multicast Frames counter */
+    if (packet[0] == 0x01) {
+        s->regs[GEM_TXMCNT/4]++;
+    }
+
+    if (bytes <= 64) {
+        s->regs[GEM_TX64CNT/4]++;
+    } else if (bytes <= 127) {
+        s->regs[GEM_TX65CNT/4]++;
+    } else if (bytes <= 255) {
+        s->regs[GEM_TX128CNT/4]++;
+    } else if (bytes <= 511) {
+        s->regs[GEM_TX256CNT/4]++;
+    } else if (bytes <= 1023) {
+        s->regs[GEM_TX512CNT/4]++;
+    } else if (bytes <= 1518) {
+        s->regs[GEM_TX1024CNT/4]++;
+    } else {
+        s->regs[GEM_TX1519CNT/4]++;
+    }
+}
+
+/*
+ * gem_transmit:
+ * Fish packets out of the descriptor ring and feed them to QEMU
+ */
+static void gem_transmit(gem_state *s)
+{
+    unsigned    desc[2];
+    target_phys_addr_t packet_desc_addr;
+    uint8_t     tx_packet[2048];
+    uint8_t     *p;
+    unsigned    total_bytes;
+
+    /* Do nothing if transmit is not enabled. */
+    if (!(s->regs[GEM_NWCTRL/4] & GEM_NWCTRL_TXENA)) {
+        return;
+    }
+
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("QEMU: %s:\n", __FUNCTION__);
+#endif
+
+    /* The packet we will hand off to qemu.
+     * Packets scattered across multiple descriptors are gathered to this
+     * one contiguous buffer first.
+     */
+    p = tx_packet;
+    total_bytes = 0;
+
+    /* read current descriptor */
+    packet_desc_addr = s->tx_desc_addr;
+    cpu_physical_memory_read(packet_desc_addr,
+                             (uint8_t *)&desc[0], sizeof(desc));
+    /* Handle all decriptors owned by hardware */
+    while (tx_desc_get_used(desc) == 0) {
+
+        /* Do nothing if transmit is not enabled. */
+        if (!(s->regs[GEM_NWCTRL/4] & GEM_NWCTRL_TXENA)) {
+            return;
+        }
+#ifdef GEM_DEBUG_TX
+        print_gem_tx_desc(desc);
+#endif
+
+        /* The real hardware would eat this (and possibly crash).
+         * For QEMU let's lend a helping hand.
+         */
+        if ((tx_desc_get_buffer(desc) == 0) ||
+            (tx_desc_get_length(desc) == 0)) {
+            printf("QEMU: GEM: Invalid TX descriptor @ 0x%x\n",
+                packet_desc_addr);
+            break;
+        }
+
+        /* Gather this fragment of the packet from "dma memory" to our contig.
+         * buffer.
+         */
+        cpu_physical_memory_read(tx_desc_get_buffer(desc), p,
+                                 tx_desc_get_length(desc));
+        p += tx_desc_get_length(desc);
+        total_bytes += tx_desc_get_length(desc);
+
+        /* Last descriptor for this packet; hand the whole thing off */
+        if (tx_desc_get_last(desc)) {
+            /* Modifiy the 1st descriptor of this packet to be owned by
+             * the processor.
+             */
+            cpu_physical_memory_read(s->tx_desc_addr,
+                                     (uint8_t *)&desc[0], sizeof(desc));
+            tx_desc_set_used(desc);
+            cpu_physical_memory_write(s->tx_desc_addr,
+                                      (uint8_t *)&desc[0], sizeof(desc));
+            /* Advance the hardare current descriptor past this packet */
+            if (tx_desc_get_wrap(desc)) {
+                s->tx_desc_addr = s->regs[GEM_TXQBASE/4];
+            } else {
+                s->tx_desc_addr = packet_desc_addr + 8;
+            }
+#ifdef GEM_DEBUG_TX
+            printf("QEMU: GEM: TX descriptor next: 0x%08x\n", s->tx_desc_addr);
+#endif
+
+            s->regs[GEM_TXSTATUS/4] |= GEM_TXSTATUS_TXCMPL;
+
+            /* Handle interrupt consequences */
+            gem_update_int_status(s);
+
+#ifdef GEM_DEBUG_PACKET
+            print_packet(tx_packet, total_bytes, 0);
+#endif
+
+            /* Is checksum offload enabled? */
+            if (s->regs[GEM_DMACFG/4] & GEM_DMACFG_TXCSUM_OFFL) {
+                net_checksum_calculate(tx_packet, total_bytes);
+            }
+
+            /* Update MAC statistics */
+            gem_transmit_updatestats(s, tx_packet, total_bytes);
+
+            /* Send the packet somewhere */
+            if (s->phy_loop) {
+                gem_receive(&s->nic->nc, tx_packet, total_bytes);
+            } else {
+                qemu_send_packet(&s->nic->nc, tx_packet, total_bytes);
+            }
+
+            /* Prepare for next packet */
+            p = tx_packet;
+            total_bytes = 0;
+        }
+
+        /* read next descriptor */
+        if (tx_desc_get_wrap(desc)) {
+            packet_desc_addr = s->regs[GEM_TXQBASE/4];
+        } else {
+            packet_desc_addr += 8;
+        }
+        cpu_physical_memory_read(packet_desc_addr,
+                                 (uint8_t *)&desc[0], sizeof(desc));
+    }
+
+    if (tx_desc_get_used(desc)) {
+        s->regs[GEM_TXSTATUS/4] |= GEM_TXSTATUS_USED;
+        gem_update_int_status(s);
+    }
+}
+
+static void gem_reset(DeviceState *d)
+{
+    gem_state *s = FROM_SYSBUS(gem_state, sysbus_from_qdev(d));
+
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s:\n", __FUNCTION__);
+#endif
+    /* Set post reset register values */
+    bzero(&s->regs[0], GEM_MAXREG);
+    s->regs[GEM_NWCFG/4] = 0x00080000;
+    s->regs[GEM_NWSTATUS/4] = 0x00000006;
+    s->regs[GEM_DMACFG/4] = 0x00020784;
+    s->regs[GEM_IMR/4] = 0x07ffffff;
+    s->regs[GEM_TXPAUSE/4] = 0x0000ffff;
+    s->regs[GEM_TXPARTIALSF/4] = 0x000003ff;
+    s->regs[GEM_RXPARTIALSF/4] = 0x000003ff;
+    s->regs[GEM_MODID/4] = 0x00020118;
+    s->regs[GEM_DESCONF/4] = 0x02500111;
+    s->regs[GEM_DESCONF2/4] = 0x2ab13fff;
+    s->regs[GEM_DESCONF5/4] = 0x002f2145;
+    s->regs[GEM_DESCONF6/4] = 0x00000200;
+
+    bzero(&s->phy_regs[0], sizeof(s->phy_regs));
+    s->phy_regs[PHY_REG_CONTROL] = 0x1140;
+    s->phy_regs[PHY_REG_STATUS] = 0x7969;
+    s->phy_regs[PHY_REG_PHYID1] = 0x0141;
+    s->phy_regs[PHY_REG_PHYID2] = 0x0CC2;
+    s->phy_regs[PHY_REG_ANEGADV] = 0x01E1;
+    s->phy_regs[PHY_REG_LINKPABIL] = 0xCDE1;
+    s->phy_regs[PHY_REG_ANEGEXP] = 0x000F;
+    s->phy_regs[PHY_REG_NEXTP] = 0x2001;
+    s->phy_regs[PHY_REG_LINKPNEXTP] = 0x40E6;
+    s->phy_regs[PHY_REG_100BTCTRL] = 0x0300;
+    s->phy_regs[PHY_REG_1000BTSTAT] = 0x7C00;
+    s->phy_regs[PHY_REG_EXTSTAT] = 0x3000;
+    s->phy_regs[PHY_REG_PHYSPCFC_CTL] = 0x0078;
+    s->phy_regs[PHY_REG_PHYSPCFC_ST] = 0xBC00;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL] = 0x0C60;
+    s->phy_regs[PHY_REG_LED] = 0x4100;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL2] = 0x000A;
+    s->phy_regs[PHY_REG_EXT_PHYSPCFC_ST] = 0x848B;
+
+    phy_update_link(s);
+    gem_update_int_status(s);
+}
+
+static uint16_t gem_phy_read(gem_state *s, unsigned reg_num)
+{
+#ifdef GEM_DEBUG_PHY
+    printf("gem_phy_read:  reg: %d value: 0x%04x\n",
+           reg_num, s->phy_regs[reg_num]);
+#endif
+    return s->phy_regs[reg_num];
+}
+
+static void gem_phy_write(gem_state *s, unsigned reg_num, uint16_t val)
+{
+#ifdef GEM_DEBUG_PHY
+    printf("gem_phy_write: reg: %d value: 0x%04x\n",
+           reg_num, val);
+#endif
+
+    switch(reg_num) {
+    case PHY_REG_CONTROL:
+        if (val & PHY_REG_CONTROL_RST) {
+            /* Anything to do for phy reset? */
+            val &= ~(PHY_REG_CONTROL_RST | PHY_REG_CONTROL_LOOP);
+            s->phy_loop = 0;
+        }
+        if (val & PHY_REG_CONTROL_ANEG) {
+            /* Complete autonegotiation imediately */
+            val &= ~PHY_REG_CONTROL_ANEG;
+            s->phy_regs[PHY_REG_STATUS] |= PHY_REG_STATUS_ANEGCMPL;
+        }
+        if (val & PHY_REG_CONTROL_LOOP) {
+#ifdef GEM_DEBUG_PHY
+            printf("gem_phy_write: PHY placed in loopback\n");
+#endif
+            s->phy_loop = 1;
+        } else {
+            s->phy_loop = 0;
+        }
+        break;
+    }
+    s->phy_regs[reg_num] = val;
+}
+
+/*
+ * gem_read32:
+ * Read a GEM register.
+ */
+static uint64_t gem_read(void *opaque, target_phys_addr_t offset, unsigned size)
+{
+    gem_state *s;
+    uint32_t retval;
+
+    s = (gem_state *)opaque;
+
+    retval = s->regs[offset/4];
+
+#ifdef GEM_DEBUG_REG
+    printf("gem_read32:  offset: 0x%04x read: 0x%08x ", offset, retval);
+#endif
+    switch (offset) {
+    case GEM_ISR:
+        qemu_set_irq(s->irq, 0);
+        break;
+    case GEM_PHYMNTNC:
+        if (retval & GEM_PHYMNTNC_OP_R) {
+            uint32_t phy_addr, reg_num;
+
+            phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
+            if (phy_addr == BOARD_PHY_ADDRESS) {
+                reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
+                retval &= 0xFFFF0000;
+                retval |= gem_phy_read(s, reg_num);
+            } else {
+                retval |= 0xFFFF; /* No device at this address */
+            }
+        }
+        break;
+    }
+
+    /* Squash read to clear bits */
+    s->regs[offset/4] &= ~(s->regs_rtc[offset/4]);
+
+    /* Do not provide write only bits */
+    retval &= ~(s->regs_wo[offset/4]);
+
+#ifdef GEM_DEBUG_REG
+    printf("0x%08x\n", retval);
+#endif
+    return retval;
+}
+
+/*
+ * gem_write32:
+ * Write a GEM register.
+ */
+static void gem_write(void *opaque, target_phys_addr_t offset, uint64_t val,
+        unsigned size)
+{
+    gem_state *s = (gem_state *)opaque;
+    uint32_t readonly;
+
+#ifdef GEM_DEBUG_REG
+    printf("gem_writel: offset: 0x%04x write: 0x%08x ", offset, (unsigned)val);
+#endif
+
+    /* Squash bits which are read only in write value */
+    val &= ~(s->regs_ro[offset/4]);
+    /* Preserve (only) bits which are read only in register */
+    readonly = s->regs[offset/4];
+    readonly &= s->regs_ro[offset/4];
+
+    /* Squash bits which are write 1 to clear */
+    val &= ~(s->regs_w1c[offset/4] & val);
+
+    /* Copy register write to backing store */
+    s->regs[offset/4] = val | readonly;
+
+    /* Handle register write side effects */
+    switch (offset) {
+    case GEM_NWCTRL:
+        if (val & GEM_NWCTRL_TXSTART) {
+            gem_transmit(s);
+        }
+        if (!(val & GEM_NWCTRL_TXENA)) {
+            /* Reset to start of Q when transmit disabled. */
+            s->tx_desc_addr = s->regs[GEM_TXQBASE/4];
+        }
+        if (!(val & GEM_NWCTRL_RXENA)) {
+            /* Reset to start of Q when receive disabled. */
+            s->rx_desc_addr = s->regs[GEM_RXQBASE/4];
+        }
+        break;
+
+    case GEM_TXSTATUS:
+        gem_update_int_status(s);
+        break;
+    case GEM_RXQBASE:
+        s->rx_desc_addr = val;
+        break;
+    case GEM_TXQBASE:
+        s->tx_desc_addr = val;
+        break;
+    case GEM_RXSTATUS:
+        gem_update_int_status(s);
+        break;
+    case GEM_IER:
+        s->regs[GEM_IMR/4] &= ~val;
+        gem_update_int_status(s);
+        break;
+    case GEM_IDR:
+        s->regs[GEM_IMR/4] |= val;
+        gem_update_int_status(s);
+        break;
+    case GEM_PHYMNTNC:
+        if (val & GEM_PHYMNTNC_OP_W) {
+            uint32_t phy_addr, reg_num;
+
+            phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
+            if (phy_addr == BOARD_PHY_ADDRESS) {
+                reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
+                gem_phy_write(s, reg_num, val);
+            }
+        }
+        break;
+    }
+
+#ifdef GEM_DEBUG_REG
+    printf("newval: 0x%08x\n", s->regs[offset/4]);
+#endif
+}
+
+static const MemoryRegionOps gem_ops = {
+    .read = gem_read,
+    .write = gem_write,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
+
+static void gem_cleanup(VLANClientState *nc)
+{
+    gem_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s:\n", __FUNCTION__);
+#endif
+
+    s->nic = NULL;
+}
+
+static void gem_set_link(VLANClientState *nc)
+{
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s:\n", __FUNCTION__);
+#endif
+    phy_update_link(DO_UPCAST(NICState, nc, nc)->opaque);
+}
+
+static NetClientInfo net_gem_info = {
+    .type = NET_CLIENT_TYPE_NIC,
+    .size = sizeof(NICState),
+    .can_receive = gem_can_receive,
+    .receive = gem_receive,
+    .cleanup = gem_cleanup,
+    .link_status_changed = gem_set_link,
+};
+
+static int gem_init(SysBusDevice *dev)
+{
+    gem_state *s;
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s:\n", __FUNCTION__);
+#endif
+
+    s = FROM_SYSBUS(gem_state, dev);
+    gem_init_register_masks(s);
+    memory_region_init_io(&s->iomem, &gem_ops, s, "enet", GEM_MAXREG);
+    sysbus_init_mmio(dev, &s->iomem);
+    sysbus_init_irq(dev, &s->irq);
+    qemu_macaddr_default_if_unset(&s->conf.macaddr);
+
+    s->nic = qemu_new_nic(&net_gem_info, &s->conf,
+                          dev->qdev.info->name, dev->qdev.id, s);
+
+    return 0;
+}
+
+static SysBusDeviceInfo gem_info = {
+    .init = gem_init,
+    .qdev.name  = "cadence_gem",
+    .qdev.size  = sizeof(gem_state),
+    .qdev.reset = gem_reset,
+    .qdev.props = (Property[]) {
+        DEFINE_NIC_PROPERTIES(gem_state, conf),
+        DEFINE_PROP_END_OF_LIST(),
+    }
+};
+
+static void gem_register_devices(void)
+{
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s:\n", __FUNCTION__);
+#endif
+    sysbus_register_withprop(&gem_info);
+}
+
+void gem_init2(NICInfo *nd, uint32_t base, qemu_irq irq);
+void gem_init2(NICInfo *nd, uint32_t base, qemu_irq irq)
+{
+    DeviceState *dev;
+    SysBusDevice *s;
+
+#ifdef GEM_DEBUG_FUNCTIONS
+    printf("%s: base: 0x%08x irq: %p\n", __FUNCTION__, base, irq);
+#endif
+    qemu_check_nic_model(nd, "cadence_gem");
+    dev = qdev_create(NULL, "cadence_gem");
+    qdev_set_nic_properties(dev, nd);
+    qdev_init_nofail(dev);
+    s = sysbus_from_qdev(dev);
+    sysbus_mmio_map(s, 0, base);
+    sysbus_connect_irq(s, 0, irq);
+}
+
+device_init(gem_register_devices)
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
                     ` (3 preceding siblings ...)
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 4/7] cadence_gem: " Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-24  7:22     ` Andreas Färber
  2012-01-26 19:40     ` Peter Maydell
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 6/7] arm_boot: added initrd address override Peter A. G. Crosthwaite
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision Peter A. G. Crosthwaite
  6 siblings, 2 replies; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Added linux specific kernel dtb option. This option can be specified to inject
an argument device tree blob (dtb) into linux.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 qemu-options.hx |    3 +++
 vl.c            |    4 ++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/qemu-options.hx b/qemu-options.hx
index 6295cde..43cddff 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1931,6 +1931,9 @@ ETEXI
 
 DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
     "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
+DEF("kern-dtb", HAS_ARG, QEMU_OPTION_kerndtb, \
+    "-kern-dtb dtb device tree blob passed to kernel boot\n", QEMU_ARCH_ALL)
+
 STEXI
 @item -kernel @var{bzImage}
 @findex -kernel
diff --git a/vl.c b/vl.c
index d5868b1..75246f8 100644
--- a/vl.c
+++ b/vl.c
@@ -233,6 +233,7 @@ int boot_menu;
 uint8_t *boot_splash_filedata;
 int boot_splash_filedata_size;
 uint8_t qemu_extra_params_fw[2];
+const char *qemu_kerndtb = NULL;
 
 typedef struct FWBootEntry FWBootEntry;
 
@@ -2437,6 +2438,9 @@ int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_kernel:
                 kernel_filename = optarg;
                 break;
+            case QEMU_OPTION_kerndtb:
+                qemu_kerndtb = optarg;
+                break;
             case QEMU_OPTION_append:
                 kernel_cmdline = optarg;
                 break;
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 6/7] arm_boot: added initrd address override
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
                     ` (4 preceding siblings ...)
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision Peter A. G. Crosthwaite
  6 siblings, 0 replies; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

parameterised the initrd load address for arm boot process. Machine models
can populate the initrd field with a non-zero address to specifiy that the
default value of 0x00d00000 should be overridden.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 hw/arm-misc.h |    2 ++
 hw/arm_boot.c |   12 ++++++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/hw/arm-misc.h b/hw/arm-misc.h
index 6e8ae6b..89e90c9 100644
--- a/hw/arm-misc.h
+++ b/hw/arm-misc.h
@@ -29,6 +29,8 @@ struct arm_boot_info {
     const char *kernel_filename;
     const char *kernel_cmdline;
     const char *initrd_filename;
+    /* FIXME: support initrd load address = 0  somehow */
+    target_phys_addr_t initrd_load_addr;
     target_phys_addr_t loader_start;
     target_phys_addr_t smp_loader_start;
     target_phys_addr_t smp_bootreg_addr;
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index bf509a8..d63ed3f 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -71,7 +71,8 @@ static void set_kernel_args(const struct arm_boot_info *info,
         /* ATAG_INITRD2 */
         WRITE_WORD(p, 4);
         WRITE_WORD(p, 0x54420005);
-        WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
+        WRITE_WORD(p, info->loader_start + info->initrd_load_addr ?
+                info->initrd_load_addr : INITRD_LOAD_ADDR);
         WRITE_WORD(p, initrd_size);
     }
     if (info->kernel_cmdline && *info->kernel_cmdline) {
@@ -148,7 +149,8 @@ static void set_kernel_args_old(const struct arm_boot_info *info,
     WRITE_WORD(p, 0);
     /* initrd_start */
     if (initrd_size)
-        WRITE_WORD(p, info->loader_start + INITRD_LOAD_ADDR);
+        WRITE_WORD(p, info->loader_start + info->initrd_load_addr ?
+                info->initrd_load_addr : INITRD_LOAD_ADDR);
     else
         WRITE_WORD(p, 0);
     /* initrd_size */
@@ -250,11 +252,13 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
     }
     info->entry = entry;
     if (is_linux) {
+        target_phys_addr_t initrd_load_addr = info->initrd_load_addr ?
+                info->initrd_load_addr : INITRD_LOAD_ADDR;
         if (info->initrd_filename) {
             initrd_size = load_image_targphys(info->initrd_filename,
                                               info->loader_start
-                                              + INITRD_LOAD_ADDR,
-                                              ram_size - INITRD_LOAD_ADDR);
+                                              + initrd_load_addr,
+                                              ram_size - initrd_load_addr);
             if (initrd_size < 0) {
                 fprintf(stderr, "qemu: could not load initrd '%s'\n",
                         info->initrd_filename);
-- 
1.7.3.2

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

* [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision
       [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
                     ` (5 preceding siblings ...)
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 6/7] arm_boot: added initrd address override Peter A. G. Crosthwaite
@ 2012-01-23  7:20   ` Peter A. G. Crosthwaite
  2012-01-23  8:00     ` Michal Simek
  6 siblings, 1 reply; 33+ messages in thread
From: Peter A. G. Crosthwaite @ 2012-01-23  7:20 UTC (permalink / raw)
  To: qemu-devel, monstr, john.williams, peter.crosthwaite,
	edgar.iglesias, duyl, linnj

Xilinx zynq-7000 machine model. Also includes device model for the zynq-specific
system level control register (SLCR) module.

Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
---
 Makefile.target |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/Makefile.target b/Makefile.target
index e62ff59..1c89779 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -338,6 +338,7 @@ obj-arm-y += cadence_uart.o
 obj-arm-y += cadence_ttc.o
 obj-arm-y += cadence_wdt.o
 obj-arm-y += cadence_gem.o
+obj-arm-y += xilinx_zynq.o zynq_arm_sysctl.o
 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
-- 
1.7.3.2

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

* Re: [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision Peter A. G. Crosthwaite
@ 2012-01-23  8:00     ` Michal Simek
  2012-01-23  8:22       ` Peter Crosthwaite
  0 siblings, 1 reply; 33+ messages in thread
From: Michal Simek @ 2012-01-23  8:00 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite
  Cc: duyl, linnj, edgar.iglesias, qemu-devel, john.williams

Peter A. G. Crosthwaite wrote:
> Xilinx zynq-7000 machine model. Also includes device model for the zynq-specific
> system level control register (SLCR) module.
> 
> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
> ---
>  Makefile.target |    1 +
>  1 files changed, 1 insertions(+), 0 deletions(-)
> 
> diff --git a/Makefile.target b/Makefile.target
> index e62ff59..1c89779 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -338,6 +338,7 @@ obj-arm-y += cadence_uart.o
>  obj-arm-y += cadence_ttc.o
>  obj-arm-y += cadence_wdt.o
>  obj-arm-y += cadence_gem.o
> +obj-arm-y += xilinx_zynq.o zynq_arm_sysctl.o
>  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

You probably forget to add that two files to this patch.

Michal


-- 
Michal Simek, Ing. (M.Eng)
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel 2.6 Microblaze Linux - http://www.monstr.eu/fdt/
Microblaze U-BOOT custodian

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

* Re: [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision
  2012-01-23  8:00     ` Michal Simek
@ 2012-01-23  8:22       ` Peter Crosthwaite
  0 siblings, 0 replies; 33+ messages in thread
From: Peter Crosthwaite @ 2012-01-23  8:22 UTC (permalink / raw)
  To: monstr; +Cc: duyl, linnj, edgar.iglesias, qemu-devel, john.williams

[-- Attachment #1: Type: text/plain, Size: 1228 bytes --]

Regenerated and resent.

Regards,
Peter

On Mon, Jan 23, 2012 at 6:00 PM, Michal Simek <monstr@monstr.eu> wrote:

> Peter A. G. Crosthwaite wrote:
>
>> Xilinx zynq-7000 machine model. Also includes device model for the
>> zynq-specific
>> system level control register (SLCR) module.
>>
>> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.**com<peter.crosthwaite@petalogix.com>
>> >
>> ---
>>  Makefile.target |    1 +
>>  1 files changed, 1 insertions(+), 0 deletions(-)
>>
>> diff --git a/Makefile.target b/Makefile.target
>> index e62ff59..1c89779 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -338,6 +338,7 @@ obj-arm-y += cadence_uart.o
>>  obj-arm-y += cadence_ttc.o
>>  obj-arm-y += cadence_wdt.o
>>  obj-arm-y += cadence_gem.o
>> +obj-arm-y += xilinx_zynq.o zynq_arm_sysctl.o
>>  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
>>
>
> You probably forget to add that two files to this patch.
>
> Michal
>
>
>
> --
> Michal Simek, Ing. (M.Eng)
> w: www.monstr.eu p: +42-0-721842854
> Maintainer of Linux kernel 2.6 Microblaze Linux -
> http://www.monstr.eu/fdt/
> Microblaze U-BOOT custodian
>

[-- Attachment #2: Type: text/html, Size: 1970 bytes --]

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

* Re: [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision Peter A. G. Crosthwaite
@ 2012-01-24  2:02     ` John Linn
  2012-01-24  8:07     ` Andreas Färber
  1 sibling, 0 replies; 33+ messages in thread
From: John Linn @ 2012-01-24  2:02 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite, qemu-devel, monstr, john.williams,
	edgar.iglesias, Duy Le

> -----Original Message-----
> From: Peter A. G. Crosthwaite [mailto:peter.crosthwaite@petalogix.com]
> Sent: Sunday, January 22, 2012 11:20 PM
> To: qemu-devel@nongnu.org; monstr@monstr.eu;
> john.williams@petalogix.com; peter.crosthwaite@petalogix.com;
> edgar.iglesias@petalogix.com; Duy Le; John Linn
> Subject: [RFC PATCH 1/7] cadence_uart: first revision
> 
> Device model for Cadence UART
> 
> Signed-off-by: Peter A. G. Crosthwaite
> <peter.crosthwaite@petalogix.com>

Signed-off-by: John Linn <john.linn@xilinx.com>

*** My apologies, please ignore the legal footer below which I'm working
on getting removed ***

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

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

* Re: [Qemu-devel] [RFC PATCH 2/7] cadence ttc: first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 2/7] cadence ttc: " Peter A. G. Crosthwaite
@ 2012-01-24  2:03     ` John Linn
  0 siblings, 0 replies; 33+ messages in thread
From: John Linn @ 2012-01-24  2:03 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite, qemu-devel, monstr, john.williams,
	edgar.iglesias, Duy Le

> -----Original Message-----
> From: Peter A. G. Crosthwaite [mailto:peter.crosthwaite@petalogix.com]
> Sent: Sunday, January 22, 2012 11:20 PM
> To: qemu-devel@nongnu.org; monstr@monstr.eu;
> john.williams@petalogix.com; peter.crosthwaite@petalogix.com;
> edgar.iglesias@petalogix.com; Duy Le; John Linn
> Subject: [RFC PATCH 2/7] cadence ttc: first revision
> 
> Device model for cadence triple timer counter (TTC)
> 
> Signed-off-by: Peter A. G. Crosthwaite
> <peter.crosthwaite@petalogix.com>

Signed-off-by: John Linn <john.linn@xilinx.com>

*** My apologies, please ignore the legal footer below which I'm working
on getting removed ***

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

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

* Re: [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: " Peter A. G. Crosthwaite
@ 2012-01-24  2:03     ` John Linn
  0 siblings, 0 replies; 33+ messages in thread
From: John Linn @ 2012-01-24  2:03 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite, qemu-devel, monstr, john.williams,
	edgar.iglesias, Duy Le

> -----Original Message-----
> From: Peter A. G. Crosthwaite [mailto:peter.crosthwaite@petalogix.com]
> Sent: Sunday, January 22, 2012 11:21 PM
> To: qemu-devel@nongnu.org; monstr@monstr.eu;
> john.williams@petalogix.com; peter.crosthwaite@petalogix.com;
> edgar.iglesias@petalogix.com; Duy Le; John Linn
> Subject: [RFC PATCH 3/7] cadence_wdt: first revision
> 
> Device model for cadence watchdog timer (WDT)
> 
> Signed-off-by: Peter A. G. Crosthwaite
> <peter.crosthwaite@petalogix.com>

Signed-off-by: John Linn <john.linn@xilinx.com>

*** My apologies, please ignore the legal footer below which I'm working
on getting removed ***



This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

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

* Re: [Qemu-devel] [RFC PATCH 4/7] cadence_gem: first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 4/7] cadence_gem: " Peter A. G. Crosthwaite
@ 2012-01-24  2:05     ` John Linn
  0 siblings, 0 replies; 33+ messages in thread
From: John Linn @ 2012-01-24  2:05 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite, qemu-devel, monstr, john.williams,
	edgar.iglesias, Duy Le

> -----Original Message-----
> From: Peter A. G. Crosthwaite [mailto:peter.crosthwaite@petalogix.com]
> Sent: Sunday, January 22, 2012 11:21 PM
> To: qemu-devel@nongnu.org; monstr@monstr.eu;
> john.williams@petalogix.com; peter.crosthwaite@petalogix.com;
> edgar.iglesias@petalogix.com; Duy Le; John Linn
> Subject: [RFC PATCH 4/7] cadence_gem: first revision
> 
> Device mode for cadence gem ethernet controller.
> 
> Signed-off-by: Peter A. G. Crosthwaite
> <peter.crosthwaite@petalogix.com>

Signed-off-by: John Linn <john.linn@xilinx.com>

*** My apologies, please ignore the legal footer below which I'm working
on getting removed ***

This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option Peter A. G. Crosthwaite
@ 2012-01-24  7:22     ` Andreas Färber
  2012-01-24  7:35       ` Peter Crosthwaite
  2012-01-24 18:23       ` Stefan Weil
  2012-01-26 19:40     ` Peter Maydell
  1 sibling, 2 replies; 33+ messages in thread
From: Andreas Färber @ 2012-01-24  7:22 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite
  Cc: Peter Maydell, monstr, edgar.iglesias, qemu-devel, duyl, linnj,
	john.williams

Am 23.01.2012 08:20, schrieb Peter A. G. Crosthwaite:
> Added linux specific kernel dtb option. This option can be specified to inject
> an argument device tree blob (dtb) into linux.
> 
> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
> ---
>  qemu-options.hx |    3 +++
>  vl.c            |    4 ++++
>  2 files changed, 7 insertions(+), 0 deletions(-)
> 
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 6295cde..43cddff 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -1931,6 +1931,9 @@ ETEXI
>  
>  DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
>      "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
> +DEF("kern-dtb", HAS_ARG, QEMU_OPTION_kerndtb, \
> +    "-kern-dtb dtb device tree blob passed to kernel boot\n", QEMU_ARCH_ALL)

We should probably call it -kernel-dtb. If there's some strncmp() from
-kernel interfering, we should fix that instead.

I don't see this variable being used anywhere in this series though.
Would it have been in the missing zynq machine of 7/7?

Andreas

> +
>  STEXI
>  @item -kernel @var{bzImage}
>  @findex -kernel
> diff --git a/vl.c b/vl.c
> index d5868b1..75246f8 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -233,6 +233,7 @@ int boot_menu;
>  uint8_t *boot_splash_filedata;
>  int boot_splash_filedata_size;
>  uint8_t qemu_extra_params_fw[2];
> +const char *qemu_kerndtb = NULL;
>  
>  typedef struct FWBootEntry FWBootEntry;
>  
> @@ -2437,6 +2438,9 @@ int main(int argc, char **argv, char **envp)
>              case QEMU_OPTION_kernel:
>                  kernel_filename = optarg;
>                  break;
> +            case QEMU_OPTION_kerndtb:
> +                qemu_kerndtb = optarg;
> +                break;
>              case QEMU_OPTION_append:
>                  kernel_cmdline = optarg;
>                  break;

-- 
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] 33+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-24  7:22     ` Andreas Färber
@ 2012-01-24  7:35       ` Peter Crosthwaite
  2012-01-24  7:50         ` Andreas Färber
  2012-01-24 18:23       ` Stefan Weil
  1 sibling, 1 reply; 33+ messages in thread
From: Peter Crosthwaite @ 2012-01-24  7:35 UTC (permalink / raw)
  To: Andreas Färber
  Cc: Peter Maydell, monstr, edgar.iglesias, qemu-devel, duyl, linnj,
	john.williams

[-- Attachment #1: Type: text/plain, Size: 2490 bytes --]

Hi Andreas,

Thanks for that, I will rename the switch to -kernel-dtb.

You are correct that 7/7 should have the usage in it, that patch was
incorrectly generated, I will regenerate and resend the series tomorrow for
another review cycle.

Regards.
Peter


On Tue, Jan 24, 2012 at 5:22 PM, Andreas Färber <afaerber@suse.de> wrote:

> Am 23.01.2012 08:20, schrieb Peter A. G. Crosthwaite:
> > Added linux specific kernel dtb option. This option can be specified to
> inject
> > an argument device tree blob (dtb) into linux.
> >
> > Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
> > ---
> >  qemu-options.hx |    3 +++
> >  vl.c            |    4 ++++
> >  2 files changed, 7 insertions(+), 0 deletions(-)
> >
> > diff --git a/qemu-options.hx b/qemu-options.hx
> > index 6295cde..43cddff 100644
> > --- a/qemu-options.hx
> > +++ b/qemu-options.hx
> > @@ -1931,6 +1931,9 @@ ETEXI
> >
> >  DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
> >      "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
> > +DEF("kern-dtb", HAS_ARG, QEMU_OPTION_kerndtb, \
> > +    "-kern-dtb dtb device tree blob passed to kernel boot\n",
> QEMU_ARCH_ALL)
>
> We should probably call it -kernel-dtb. If there's some strncmp() from
> -kernel interfering, we should fix that instead.
>
> I don't see this variable being used anywhere in this series though.
> Would it have been in the missing zynq machine of 7/7?
>
> Andreas
>
> > +
> >  STEXI
> >  @item -kernel @var{bzImage}
> >  @findex -kernel
> > diff --git a/vl.c b/vl.c
> > index d5868b1..75246f8 100644
> > --- a/vl.c
> > +++ b/vl.c
> > @@ -233,6 +233,7 @@ int boot_menu;
> >  uint8_t *boot_splash_filedata;
> >  int boot_splash_filedata_size;
> >  uint8_t qemu_extra_params_fw[2];
> > +const char *qemu_kerndtb = NULL;
> >
> >  typedef struct FWBootEntry FWBootEntry;
> >
> > @@ -2437,6 +2438,9 @@ int main(int argc, char **argv, char **envp)
> >              case QEMU_OPTION_kernel:
> >                  kernel_filename = optarg;
> >                  break;
> > +            case QEMU_OPTION_kerndtb:
> > +                qemu_kerndtb = optarg;
> > +                break;
> >              case QEMU_OPTION_append:
> >                  kernel_cmdline = optarg;
> >                  break;
>
> --
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg
>

[-- Attachment #2: Type: text/html, Size: 3300 bytes --]

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-24  7:35       ` Peter Crosthwaite
@ 2012-01-24  7:50         ` Andreas Färber
  0 siblings, 0 replies; 33+ messages in thread
From: Andreas Färber @ 2012-01-24  7:50 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, monstr, edgar.iglesias, qemu-devel, duyl, linnj,
	john.williams

Hi Peter,

Am 24.01.2012 08:35, schrieb Peter Crosthwaite:
> Thanks for that, I will rename the switch to -kernel-dtb.
> 
> You are correct that 7/7 should have the usage in it, that patch was
> incorrectly generated, I will regenerate and resend the series tomorrow
> for another review cycle.

Just found it, sorry. Is it just my mail client or did something go
wrong with sending? 0/7 is not threaded with the rest, and neither is
the fixed-up 7/7. It would facilitate review.

When resending, please also cc our ARM maintainer, even if your Edgar
might be the one to commit it in the end.
Please also don't forget to update MAINTAINERS with an entry for the new
machine and devices.

Regards,
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] 33+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision Peter A. G. Crosthwaite
  2012-01-24  2:02     ` John Linn
@ 2012-01-24  8:07     ` Andreas Färber
  1 sibling, 0 replies; 33+ messages in thread
From: Andreas Färber @ 2012-01-24  8:07 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite
  Cc: Peter Maydell, monstr, edgar.iglesias, qemu-devel,
	Anthony Liguori, duyl, linnj, john.williams

Am 23.01.2012 08:20, schrieb Peter A. G. Crosthwaite:
> Device model for Cadence UART
> 
> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
> ---
>  Makefile.target   |    1 +
>  hw/cadence_uart.c |  619 +++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 620 insertions(+), 0 deletions(-)
>  create mode 100644 hw/cadence_uart.c

> diff --git a/hw/cadence_uart.c b/hw/cadence_uart.c
> new file mode 100644
> index 0000000..931ff2c
> --- /dev/null
> +++ b/hw/cadence_uart.c

> +typedef struct {
[...]
> +} uart_state;

Coding Style mandates CamelCase for structs.

> +static void uart_register_devices(void)
> +{
> +    sysbus_register_dev("cadence_uart", sizeof(uart_state),
> +                        uart_init);

Please use sysbus_register_withprop() instead, for the upcoming QOM
conversion.

Could you also consider adding VMState for the devices, to allow
load/save? If not, they should at least be marked as unmigratable.

> +}

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] 33+ messages in thread

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-24  7:22     ` Andreas Färber
  2012-01-24  7:35       ` Peter Crosthwaite
@ 2012-01-24 18:23       ` Stefan Weil
  2012-01-26 19:34         ` Scott Wood
  2012-01-30  2:10         ` Anthony Liguori
  1 sibling, 2 replies; 33+ messages in thread
From: Stefan Weil @ 2012-01-24 18:23 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite
  Cc: Peter Maydell, monstr, edgar.iglesias, qemu-devel, duyl, linnj,
	Andreas Färber, john.williams

Am 24.01.2012 08:22, schrieb Andreas Färber:
> Am 23.01.2012 08:20, schrieb Peter A. G. Crosthwaite:
>> Added linux specific kernel dtb option. This option can be specified 
>> to inject
>> an argument device tree blob (dtb) into linux.
>>
>> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
>> ---
>> qemu-options.hx | 3 +++
>> vl.c | 4 ++++
>> 2 files changed, 7 insertions(+), 0 deletions(-)
>>
>> diff --git a/qemu-options.hx b/qemu-options.hx
>> index 6295cde..43cddff 100644
>> --- a/qemu-options.hx
>> +++ b/qemu-options.hx
>> @@ -1931,6 +1931,9 @@ ETEXI
>>
>> DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
>> "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
>> +DEF("kern-dtb", HAS_ARG, QEMU_OPTION_kerndtb, \
>> + "-kern-dtb dtb device tree blob passed to kernel boot\n", 
>> QEMU_ARCH_ALL)
>
> We should probably call it -kernel-dtb. If there's some strncmp() from
> -kernel interfering, we should fix that instead.
>
> I don't see this variable being used anywhere in this series though.
> Would it have been in the missing zynq machine of 7/7?
>
> Andreas

I'd prefer a different solution. As far as I have understood,
the dtb is only useful with a kernel, so it could be handled
as an optional attribute to the -kernel parameter:

     -kernel IMAGE[,dtb=DTB]

Of course the same applies to -append, but that's a different issue.

Regards,
Stefan

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-24 18:23       ` Stefan Weil
@ 2012-01-26 19:34         ` Scott Wood
  2012-01-26 21:27           ` Eric Blake
  2012-01-30  2:10         ` Anthony Liguori
  1 sibling, 1 reply; 33+ messages in thread
From: Scott Wood @ 2012-01-26 19:34 UTC (permalink / raw)
  To: Stefan Weil
  Cc: Peter Maydell, monstr, duyl, qemu-devel, Peter A. G. Crosthwaite,
	edgar.iglesias, linnj, Andreas Färber, john.williams

On 01/24/2012 12:23 PM, Stefan Weil wrote:
> I'd prefer a different solution. As far as I have understood,
> the dtb is only useful with a kernel, so it could be handled
> as an optional attribute to the -kernel parameter:
> 
>     -kernel IMAGE[,dtb=DTB]
> 
> Of course the same applies to -append, but that's a different issue.

-initrd as well.

This would mean you couldn't have a comma in a filename (shouldn't come
up often, but still ugly).

-Scott

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option Peter A. G. Crosthwaite
  2012-01-24  7:22     ` Andreas Färber
@ 2012-01-26 19:40     ` Peter Maydell
  1 sibling, 0 replies; 33+ messages in thread
From: Peter Maydell @ 2012-01-26 19:40 UTC (permalink / raw)
  To: Peter A. G. Crosthwaite
  Cc: monstr, edgar.iglesias, qemu-devel, duyl, linnj, john.williams

On 23 January 2012 07:20, Peter A. G. Crosthwaite
<peter.crosthwaite@petalogix.com> wrote:
> --- a/vl.c
> +++ b/vl.c
> @@ -233,6 +233,7 @@ int boot_menu;
>  uint8_t *boot_splash_filedata;
>  int boot_splash_filedata_size;
>  uint8_t qemu_extra_params_fw[2];
> +const char *qemu_kerndtb = NULL;
>
>  typedef struct FWBootEntry FWBootEntry;
>
> @@ -2437,6 +2438,9 @@ int main(int argc, char **argv, char **envp)
>             case QEMU_OPTION_kernel:
>                 kernel_filename = optarg;
>                 break;
> +            case QEMU_OPTION_kerndtb:
> +                qemu_kerndtb = optarg;
> +                break;
>             case QEMU_OPTION_append:
>                 kernel_cmdline = optarg;
>                 break;

This is inconsistent with how we handle kernel_filename
and initrd_filename (throwing things around via random
globals is a pretty nasty interface).

I think I like the approach Grant Likely suggested of
cleaning up the machine->init function signature so we
just pass it a struct instead.

Also missing the mollyguard on attempting to use -kernel-dtb
but not -kernel (cf the check done for -append and -initrd).

-- PMM

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-26 19:34         ` Scott Wood
@ 2012-01-26 21:27           ` Eric Blake
  2012-01-27  8:25             ` Markus Armbruster
  0 siblings, 1 reply; 33+ messages in thread
From: Eric Blake @ 2012-01-26 21:27 UTC (permalink / raw)
  To: Scott Wood
  Cc: Peter Maydell, monstr, edgar.iglesias, Stefan Weil, qemu-devel,
	Peter A. G. Crosthwaite, duyl, linnj, Andreas Färber,
	john.williams

[-- Attachment #1: Type: text/plain, Size: 920 bytes --]

On 01/26/2012 12:34 PM, Scott Wood wrote:
> On 01/24/2012 12:23 PM, Stefan Weil wrote:
>> I'd prefer a different solution. As far as I have understood,
>> the dtb is only useful with a kernel, so it could be handled
>> as an optional attribute to the -kernel parameter:
>>
>>     -kernel IMAGE[,dtb=DTB]
>>
>> Of course the same applies to -append, but that's a different issue.
> 
> -initrd as well.
> 
> This would mean you couldn't have a comma in a filename (shouldn't come
> up often, but still ugly).

In other instances where you use a comma to separate arguments and also
want to accept commas in arbitrary file names, qemu has used the notion
of a double comma as being the escape sequence for a single comma in the
intended file name, rather than a separator for later arguments.

-- 
Eric Blake   eblake@redhat.com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 620 bytes --]

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-26 21:27           ` Eric Blake
@ 2012-01-27  8:25             ` Markus Armbruster
  2012-01-29  6:51               ` Peter Crosthwaite
  0 siblings, 1 reply; 33+ messages in thread
From: Markus Armbruster @ 2012-01-27  8:25 UTC (permalink / raw)
  To: Eric Blake
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel,
	Peter A. G. Crosthwaite, linnj, edgar.iglesias, Scott Wood,
	Andreas Färber, john.williams

Eric Blake <eblake@redhat.com> writes:

> On 01/26/2012 12:34 PM, Scott Wood wrote:
>> On 01/24/2012 12:23 PM, Stefan Weil wrote:
>>> I'd prefer a different solution. As far as I have understood,
>>> the dtb is only useful with a kernel, so it could be handled
>>> as an optional attribute to the -kernel parameter:
>>>
>>>     -kernel IMAGE[,dtb=DTB]
>>>
>>> Of course the same applies to -append, but that's a different issue.
>> 
>> -initrd as well.
>> 
>> This would mean you couldn't have a comma in a filename (shouldn't come
>> up often, but still ugly).
>
> In other instances where you use a comma to separate arguments and also
> want to accept commas in arbitrary file names, qemu has used the notion
> of a double comma as being the escape sequence for a single comma in the
> intended file name, rather than a separator for later arguments.

Use QemuOpts for NAME=VALUE,... arguments.  Common code, common
syntactic conventions.

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-27  8:25             ` Markus Armbruster
@ 2012-01-29  6:51               ` Peter Crosthwaite
  2012-01-30  0:28                 ` John Williams
  0 siblings, 1 reply; 33+ messages in thread
From: Peter Crosthwaite @ 2012-01-29  6:51 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel, linnj,
	edgar.iglesias, Scott Wood, Eric Blake, Andreas Färber,
	john.williams

[-- Attachment #1: Type: text/plain, Size: 2619 bytes --]

Hi All,

So on the topic of these command line arguments for initrd, dtb and
friends, another related issue we have encountered (and have hacked around
in our tree) is not being able to relocate the initrd or kernel. Currently
these memory locations are hardcoded in arm_boot.c:

#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
#define INITRD_LOAD_ADDR 0x00d00000

If you see patch 6/7 in this same series I put in place a hack to override
the initrd location in memory, but I wonder if instead this should go up to
the command line interface as a parameter. Currently the machine model (or
arm_boot.c) defines exactly where kernels/initrds/command-line-args line in
memory, but since these are software properties should perhaps they go up
to the command line as -kernel,foo=bar options? E.G:

qemu-system-arm
-kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000

It strikes me as broken that a machine model specifies where in memory a
kernel has to live. Something similar would apply to the dtb argument, this
patch introduces.

For the next revision of this patch series I am going to put in the
mollyguard and just use -kernel-dtb foo for the moment.

So with the greater issue of linux specific command line arguments, what is
the consensus here on how this is going to be handled with regards to:

-Passing all this command line stuff in a struct
-nesting initrd and friends under the -kernel option.

And do either of these act as a blocker on this patch series?

Regards,
Peter

On Fri, Jan 27, 2012 at 6:25 PM, Markus Armbruster <armbru@redhat.com>wrote:

> Eric Blake <eblake@redhat.com> writes:
>
> > On 01/26/2012 12:34 PM, Scott Wood wrote:
> >> On 01/24/2012 12:23 PM, Stefan Weil wrote:
> >>> I'd prefer a different solution. As far as I have understood,
> >>> the dtb is only useful with a kernel, so it could be handled
> >>> as an optional attribute to the -kernel parameter:
> >>>
> >>>     -kernel IMAGE[,dtb=DTB]
> >>>
> >>> Of course the same applies to -append, but that's a different issue.
> >>
> >> -initrd as well.
> >>
> >> This would mean you couldn't have a comma in a filename (shouldn't come
> >> up often, but still ugly).
> >
> > In other instances where you use a comma to separate arguments and also
> > want to accept commas in arbitrary file names, qemu has used the notion
> > of a double comma as being the escape sequence for a single comma in the
> > intended file name, rather than a separator for later arguments.
>
> Use QemuOpts for NAME=VALUE,... arguments.  Common code, common
> syntactic conventions.
>

[-- Attachment #2: Type: text/html, Size: 3500 bytes --]

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-29  6:51               ` Peter Crosthwaite
@ 2012-01-30  0:28                 ` John Williams
  2012-01-30  0:33                   ` John Williams
  2012-01-30  2:11                   ` Anthony Liguori
  0 siblings, 2 replies; 33+ messages in thread
From: John Williams @ 2012-01-30  0:28 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, Markus Armbruster,
	qemu-devel, linnj, edgar.iglesias, Scott Wood, Eric Blake,
	Andreas Färber

On Sun, Jan 29, 2012 at 4:51 PM, Peter Crosthwaite
<peter.crosthwaite@petalogix.com> wrote:
> Hi All,
>
> So on the topic of these command line arguments for initrd, dtb and friends,
> another related issue we have encountered (and have hacked around in our
> tree) is not being able to relocate the initrd or kernel. Currently these
> memory locations are hardcoded in arm_boot.c:
>
> #define KERNEL_ARGS_ADDR 0x100
> #define KERNEL_LOAD_ADDR 0x00010000
> #define INITRD_LOAD_ADDR 0x00d00000
>
> If you see patch 6/7 in this same series I put in place a hack to override
> the initrd location in memory, but I wonder if instead this should go up to
> the command line interface as a parameter. Currently the machine model (or
> arm_boot.c) defines exactly where kernels/initrds/command-line-args line in
> memory, but since these are software properties should perhaps they go up to
> the command line as -kernel,foo=bar options? E.G:
>
> qemu-system-arm
> -kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000

There's an opportunity here - QEMU needs the cmdline ability to load
random binaries/elfs anyway, such as

--load file@address

e.g. --load image.bin@0xa4000000

-- load file.elf

(no address required)

This option or one like it would make it much easier and less
hard-coded to assemble any sort of initial memory state.

Extending this, kernels, initrds and DTBs all can have
machine-specific preferred addresses but can be overriden in the same
way:

--kernel zImage@0x20000000 --initrd fs.img@0x40000000

and so on

The '@' symbol will need to be escaped by it's a pretty natural syntax.

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

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  0:28                 ` John Williams
@ 2012-01-30  0:33                   ` John Williams
  2012-01-30  2:11                   ` Anthony Liguori
  1 sibling, 0 replies; 33+ messages in thread
From: John Williams @ 2012-01-30  0:33 UTC (permalink / raw)
  To: Peter Crosthwaite
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, Markus Armbruster,
	qemu-devel, linnj, edgar.iglesias, Scott Wood, Eric Blake,
	Andreas Färber

On Mon, Jan 30, 2012 at 10:28 AM, John Williams
<john.williams@petalogix.com> wrote:
> On Sun, Jan 29, 2012 at 4:51 PM, Peter Crosthwaite
> <peter.crosthwaite@petalogix.com> wrote:
>> Hi All,
>>
>> So on the topic of these command line arguments for initrd, dtb and friends,
>> another related issue we have encountered (and have hacked around in our
>> tree) is not being able to relocate the initrd or kernel. Currently these
>> memory locations are hardcoded in arm_boot.c:
>>
>> #define KERNEL_ARGS_ADDR 0x100
>> #define KERNEL_LOAD_ADDR 0x00010000
>> #define INITRD_LOAD_ADDR 0x00d00000
>>
>> If you see patch 6/7 in this same series I put in place a hack to override
>> the initrd location in memory, but I wonder if instead this should go up to
>> the command line interface as a parameter. Currently the machine model (or
>> arm_boot.c) defines exactly where kernels/initrds/command-line-args line in
>> memory, but since these are software properties should perhaps they go up to
>> the command line as -kernel,foo=bar options? E.G:
>>
>> qemu-system-arm
>> -kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000
>
> There's an opportunity here - QEMU needs the cmdline ability to load
> random binaries/elfs anyway, such as
>
> --load file@address
>
> e.g. --load image.bin@0xa4000000

And while we're at it how about overriding arbitrary boot PC addresses as well?

--boot-addr 0xdeadbeef

It should be possible to boot random bootrom code in QEMU without
hacking on the machine model.

qemu-system-arm -M foo --file bootrom.bin@0x000000 --boot-addr 0x00001000

We bumped into this recently - we need a cleaner way of telling QEMU
if it's pretending to be just the machine with some minimal initial
state as above(for running bootloaders, baremetal etc), or it's being
the machine *plus* a bootloader (booting vmlinux/zimage).

Currently it's pretty hacky.

John






>
> -- load file.elf
>
> (no address required)
>
> This option or one like it would make it much easier and less
> hard-coded to assemble any sort of initial memory state.
>
> Extending this, kernels, initrds and DTBs all can have
> machine-specific preferred addresses but can be overriden in the same
> way:
>
> --kernel zImage@0x20000000 --initrd fs.img@0x40000000
>
> and so on
>
> The '@' symbol will need to be escaped by it's a pretty natural syntax.
>
> 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



-- 
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

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-24 18:23       ` Stefan Weil
  2012-01-26 19:34         ` Scott Wood
@ 2012-01-30  2:10         ` Anthony Liguori
  1 sibling, 0 replies; 33+ messages in thread
From: Anthony Liguori @ 2012-01-30  2:10 UTC (permalink / raw)
  To: Stefan Weil
  Cc: Peter Maydell, monstr, duyl, qemu-devel, Peter A. G. Crosthwaite,
	edgar.iglesias, linnj, Andreas Färber, john.williams

On 01/24/2012 12:23 PM, Stefan Weil wrote:
> Am 24.01.2012 08:22, schrieb Andreas Färber:
>> Am 23.01.2012 08:20, schrieb Peter A. G. Crosthwaite:
>>> Added linux specific kernel dtb option. This option can be specified to inject
>>> an argument device tree blob (dtb) into linux.
>>>
>>> Signed-off-by: Peter A. G. Crosthwaite <peter.crosthwaite@petalogix.com>
>>> ---
>>> qemu-options.hx | 3 +++
>>> vl.c | 4 ++++
>>> 2 files changed, 7 insertions(+), 0 deletions(-)
>>>
>>> diff --git a/qemu-options.hx b/qemu-options.hx
>>> index 6295cde..43cddff 100644
>>> --- a/qemu-options.hx
>>> +++ b/qemu-options.hx
>>> @@ -1931,6 +1931,9 @@ ETEXI
>>>
>>> DEF("kernel", HAS_ARG, QEMU_OPTION_kernel, \
>>> "-kernel bzImage use 'bzImage' as kernel image\n", QEMU_ARCH_ALL)
>>> +DEF("kern-dtb", HAS_ARG, QEMU_OPTION_kerndtb, \
>>> + "-kern-dtb dtb device tree blob passed to kernel boot\n", QEMU_ARCH_ALL)
>>
>> We should probably call it -kernel-dtb. If there's some strncmp() from
>> -kernel interfering, we should fix that instead.
>>
>> I don't see this variable being used anywhere in this series though.
>> Would it have been in the missing zynq machine of 7/7?
>>
>> Andreas
>
> I'd prefer a different solution. As far as I have understood,
> the dtb is only useful with a kernel, so it could be handled
> as an optional attribute to the -kernel parameter:
>
> -kernel IMAGE[,dtb=DTB]

If it looks like a device, acts like a device, and smells like a device...

The best thing to do here is to make an arm-kernel-loader device that hangs off 
of sysbus and takes four string properties.

I was going to do this shortly for PC anyway.

BTW, for unknown command line options, we should probably assume they are 
-device and treat accordingly.  So -arm-kernel-loader 
dtb=DTB,kernel=/path/to/vmlinux would Just Work.

Regards,

Anthony Liguori

>
> Of course the same applies to -append, but that's a different issue.
>
> Regards,
> Stefan
>
>

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  0:28                 ` John Williams
  2012-01-30  0:33                   ` John Williams
@ 2012-01-30  2:11                   ` Anthony Liguori
  2012-01-30  2:19                     ` John Williams
  1 sibling, 1 reply; 33+ messages in thread
From: Anthony Liguori @ 2012-01-30  2:11 UTC (permalink / raw)
  To: John Williams
  Cc: Peter Maydell, monstr, edgar.iglesias, Stefan Weil,
	Markus Armbruster, qemu-devel, Peter Crosthwaite, Scott Wood,
	duyl, linnj, Eric Blake, Andreas Färber

On 01/29/2012 06:28 PM, John Williams wrote:
> On Sun, Jan 29, 2012 at 4:51 PM, Peter Crosthwaite
> <peter.crosthwaite@petalogix.com>  wrote:
>> Hi All,
>>
>> So on the topic of these command line arguments for initrd, dtb and friends,
>> another related issue we have encountered (and have hacked around in our
>> tree) is not being able to relocate the initrd or kernel. Currently these
>> memory locations are hardcoded in arm_boot.c:
>>
>> #define KERNEL_ARGS_ADDR 0x100
>> #define KERNEL_LOAD_ADDR 0x00010000
>> #define INITRD_LOAD_ADDR 0x00d00000
>>
>> If you see patch 6/7 in this same series I put in place a hack to override
>> the initrd location in memory, but I wonder if instead this should go up to
>> the command line interface as a parameter. Currently the machine model (or
>> arm_boot.c) defines exactly where kernels/initrds/command-line-args line in
>> memory, but since these are software properties should perhaps they go up to
>> the command line as -kernel,foo=bar options? E.G:
>>
>> qemu-system-arm
>> -kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000
>
> There's an opportunity here - QEMU needs the cmdline ability to load
> random binaries/elfs anyway, such as
>
> --load file@address

Make an elf loader device if you desire this ability but I'm skeptical that it 
really is all that useful.

No special syntax though, we have a way to parameterize options as Markus 
rightly points out.

Regards,

Anthony Liguori

>
> e.g. --load image.bin@0xa4000000
>
> -- load file.elf
>
> (no address required)
>
> This option or one like it would make it much easier and less
> hard-coded to assemble any sort of initial memory state.
>
> Extending this, kernels, initrds and DTBs all can have
> machine-specific preferred addresses but can be overriden in the same
> way:
>
> --kernel zImage@0x20000000 --initrd fs.img@0x40000000
>
> and so on
>
> The '@' symbol will need to be escaped by it's a pretty natural syntax.
>
> John

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  2:11                   ` Anthony Liguori
@ 2012-01-30  2:19                     ` John Williams
  2012-01-30  2:28                       ` Anthony Liguori
  0 siblings, 1 reply; 33+ messages in thread
From: John Williams @ 2012-01-30  2:19 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Peter Maydell, monstr, edgar.iglesias, Stefan Weil,
	Markus Armbruster, qemu-devel, Peter Crosthwaite, Scott Wood,
	duyl, linnj, Eric Blake, Andreas Färber

On Mon, Jan 30, 2012 at 12:11 PM, Anthony Liguori <anthony@codemonkey.ws> wrote:
> On 01/29/2012 06:28 PM, John Williams wrote:
>>
>> On Sun, Jan 29, 2012 at 4:51 PM, Peter Crosthwaite
>> <peter.crosthwaite@petalogix.com>  wrote:
>>>
>>> Hi All,
>>>
>>> So on the topic of these command line arguments for initrd, dtb and
>>> friends,
>>> another related issue we have encountered (and have hacked around in our
>>> tree) is not being able to relocate the initrd or kernel. Currently these
>>> memory locations are hardcoded in arm_boot.c:
>>>
>>> #define KERNEL_ARGS_ADDR 0x100
>>> #define KERNEL_LOAD_ADDR 0x00010000
>>> #define INITRD_LOAD_ADDR 0x00d00000
>>>
>>> If you see patch 6/7 in this same series I put in place a hack to
>>> override
>>> the initrd location in memory, but I wonder if instead this should go up
>>> to
>>> the command line interface as a parameter. Currently the machine model
>>> (or
>>> arm_boot.c) defines exactly where kernels/initrds/command-line-args line
>>> in
>>> memory, but since these are software properties should perhaps they go up
>>> to
>>> the command line as -kernel,foo=bar options? E.G:
>>>
>>> qemu-system-arm
>>>
>>> -kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000
>>
>>
>> There's an opportunity here - QEMU needs the cmdline ability to load
>> random binaries/elfs anyway, such as
>>
>> --load file@address
>
>
> Make an elf loader device if you desire this ability but I'm skeptical that
> it really is all that useful.

It is useful for non-Linux use-cases, of which there are many!

Can you explain how you'd see such a 'loader device' in practice?  How
does it get bound into the machine model?  How do we pass arguments to
it?

Thanks,

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

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  2:19                     ` John Williams
@ 2012-01-30  2:28                       ` Anthony Liguori
  2012-01-30  2:41                         ` John Williams
  0 siblings, 1 reply; 33+ messages in thread
From: Anthony Liguori @ 2012-01-30  2:28 UTC (permalink / raw)
  To: John Williams
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel,
	Markus Armbruster, Peter Crosthwaite, linnj, edgar.iglesias,
	Scott Wood, Eric Blake, Andreas Färber

On 01/29/2012 08:19 PM, John Williams wrote:
> On Mon, Jan 30, 2012 at 12:11 PM, Anthony Liguori<anthony@codemonkey.ws>  wrote:
>> On 01/29/2012 06:28 PM, John Williams wrote:
>>>
>>> On Sun, Jan 29, 2012 at 4:51 PM, Peter Crosthwaite
>>> <peter.crosthwaite@petalogix.com>    wrote:
>>>>
>>>> Hi All,
>>>>
>>>> So on the topic of these command line arguments for initrd, dtb and
>>>> friends,
>>>> another related issue we have encountered (and have hacked around in our
>>>> tree) is not being able to relocate the initrd or kernel. Currently these
>>>> memory locations are hardcoded in arm_boot.c:
>>>>
>>>> #define KERNEL_ARGS_ADDR 0x100
>>>> #define KERNEL_LOAD_ADDR 0x00010000
>>>> #define INITRD_LOAD_ADDR 0x00d00000
>>>>
>>>> If you see patch 6/7 in this same series I put in place a hack to
>>>> override
>>>> the initrd location in memory, but I wonder if instead this should go up
>>>> to
>>>> the command line interface as a parameter. Currently the machine model
>>>> (or
>>>> arm_boot.c) defines exactly where kernels/initrds/command-line-args line
>>>> in
>>>> memory, but since these are software properties should perhaps they go up
>>>> to
>>>> the command line as -kernel,foo=bar options? E.G:
>>>>
>>>> qemu-system-arm
>>>>
>>>> -kernel,kernel-image=/foo/zImage,kernel-addr=0x00010000,initrd=/foo/initrd,initrd_addr=0x00d00000
>>>
>>>
>>> There's an opportunity here - QEMU needs the cmdline ability to load
>>> random binaries/elfs anyway, such as
>>>
>>> --load file@address
>>
>>
>> Make an elf loader device if you desire this ability but I'm skeptical that
>> it really is all that useful.
>
> It is useful for non-Linux use-cases, of which there are many!

It's not just a matter of loading an elf binary in memory.  You probably need to 
have a specific register state set in order to run non-Linux elf binaries which 
means you'll need binary specific logic.

If all of these binaries you want to run have a well known register state, they 
you can just use fw_cfg and a piece of firmware to read the binary (which is 
basically how -kernel works on target-i386).

>
> Can you explain how you'd see such a 'loader device' in practice?  How
> does it get bound into the machine model?  How do we pass arguments to
> it?

You create a device via qdev (now QOM) that takes whatever properties you need. 
  You then do:

-device elf-loader,base=0xa00000,file=my-elf-binary

No different than adding a network card.

As I mentioned in the previous note, we probably should short cut unknown 
options as just assume they're meant for -device such that you could also do:

-elf-loader base=0xa00000,file=my-elf-binary

Regards,

Anthony Liguori

>
> Thanks,
>
> John

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  2:28                       ` Anthony Liguori
@ 2012-01-30  2:41                         ` John Williams
  2012-01-30  2:48                           ` Anthony Liguori
  0 siblings, 1 reply; 33+ messages in thread
From: John Williams @ 2012-01-30  2:41 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel,
	Markus Armbruster, Peter Crosthwaite, linnj, edgar.iglesias,
	Scott Wood, Eric Blake, Andreas Färber

>>>> There's an opportunity here - QEMU needs the cmdline ability to load
>>>> random binaries/elfs anyway, such as
>>>>
>>>> --load file@address
>>>
>>>
>>>
>>> Make an elf loader device if you desire this ability but I'm skeptical
>>> that
>>> it really is all that useful.
>>
>>
>> It is useful for non-Linux use-cases, of which there are many!
>
>
> It's not just a matter of loading an elf binary in memory.  You probably
> need to have a specific register state set in order to run non-Linux elf
> binaries which means you'll need binary specific logic.

The machine state at bootup is very well defined - it's whatever the TRM says!

An example may help.  We are working on the Xilinx Zynq model, dual
core Cortex A-9.  We currently are able to use QEMU for the entire
flow from

cold reset ->
bootrom ->
u-boot ->
Linux

In this flow, we don't want any magic initial state, we want QEMU to
model the CPU just like the real hardware.

Equivalently, we might like to kick directly into the kernel, SMP==2 and so on.

It makes no sense to me that we should somehow use a different machine
model just to model a different boot flow on the same hardware.

Another example, we are working on remoteproc/rpmsg support so that we
can run Linux on one core, and firmware on another.  We have this
working in QEMU today, except we had to hack around the ARM boot
code's assumptions that we always want the 2nd CPU to run an WFE/WIQ
loop.  This is only true if you are running Linux *and* you want QEMU
to fake the actions of a bootloader.

If you are modelling a cold start you want those two CPUs to race
until one of them reads the CPUID register puts itself to sleep, ie
just run the bootrom.

All of these use cases are not about virtualisation, but about system
modeling and emulation, which really is where QEMU is valuable in the
embedded space.

> If all of these binaries you want to run have a well known register state,
> they you can just use fw_cfg and a piece of firmware to read the binary
> (which is basically how -kernel works on target-i386).
>
>
>>
>> Can you explain how you'd see such a 'loader device' in practice?  How
>> does it get bound into the machine model?  How do we pass arguments to
>> it?
>
>
> You create a device via qdev (now QOM) that takes whatever properties you
> need.  You then do:
>
> -device elf-loader,base=0xa00000,file=my-elf-binary
>
> No different than adding a network card.

A network card is a tangible object, it can be present in the system.
The ELF loader is just emulator cruft, a necessary evil to get the
initial state of the machine.  Should it really be on a level footing
with actual devices?

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

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  2:41                         ` John Williams
@ 2012-01-30  2:48                           ` Anthony Liguori
  2012-02-01  2:06                             ` John Williams
  0 siblings, 1 reply; 33+ messages in thread
From: Anthony Liguori @ 2012-01-30  2:48 UTC (permalink / raw)
  To: John Williams
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel,
	Markus Armbruster, Peter Crosthwaite, linnj, edgar.iglesias,
	Scott Wood, Eric Blake, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 3433 bytes --]

On Jan 29, 2012 8:41 PM, "John Williams" <john.williams@petalogix.com>
wrote:
>
> >>>> There's an opportunity here - QEMU needs the cmdline ability to load
> >>>> random binaries/elfs anyway, such as
> >>>>
> >>>> --load file@address
> >>>
> >>>
> >>>
> >>> Make an elf loader device if you desire this ability but I'm skeptical
> >>> that
> >>> it really is all that useful.
> >>
> >>
> >> It is useful for non-Linux use-cases, of which there are many!
> >
> >
> > It's not just a matter of loading an elf binary in memory.  You probably
> > need to have a specific register state set in order to run non-Linux elf
> > binaries which means you'll need binary specific logic.
>
> The machine state at bootup is very well defined - it's whatever the TRM
says!
>
> An example may help.  We are working on the Xilinx Zynq model, dual
> core Cortex A-9.  We currently are able to use QEMU for the entire
> flow from
>
> cold reset ->
> bootrom ->
> u-boot ->
> Linux
>
> In this flow, we don't want any magic initial state, we want QEMU to
> model the CPU just like the real hardware.
>
> Equivalently, we might like to kick directly into the kernel, SMP==2 and
so on.
>
> It makes no sense to me that we should somehow use a different machine
> model just to model a different boot flow on the same hardware.
>
> Another example, we are working on remoteproc/rpmsg support so that we
> can run Linux on one core, and firmware on another.  We have this
> working in QEMU today, except we had to hack around the ARM boot
> code's assumptions that we always want the 2nd CPU to run an WFE/WIQ
> loop.  This is only true if you are running Linux *and* you want QEMU
> to fake the actions of a bootloader.
>
> If you are modelling a cold start you want those two CPUs to race
> until one of them reads the CPUID register puts itself to sleep, ie
> just run the bootrom.
>
> All of these use cases are not about virtualisation, but about system
> modeling and emulation, which really is where QEMU is valuable in the
> embedded space.

I don't see how any of this is relevant.  Presumably, on real hardware, you
have a rom bank wired to a specific physical address with ip fixed to an
address which happens to be in that space?

Why not just use an emulated flash chip?

>
> > If all of these binaries you want to run have a well known register
state,
> > they you can just use fw_cfg and a piece of firmware to read the binary
> > (which is basically how -kernel works on target-i386).
> >
> >
> >>
> >> Can you explain how you'd see such a 'loader device' in practice?  How
> >> does it get bound into the machine model?  How do we pass arguments to
> >> it?
> >
> >
> > You create a device via qdev (now QOM) that takes whatever properties
you
> > need.  You then do:
> >
> > -device elf-loader,base=0xa00000,file=my-elf-binary
> >
> > No different than adding a network card.
>
> A network card is a tangible object, it can be present in the system.
> The ELF loader is just emulator cruft, a necessary evil to get the
> initial state of the machine.  Should it really be on a level footing
> with actual devices?

All systems have to bootstrap software some how.  Some device is reasonable
for this.  This isn't emulated magic :-)

Regards,

Anthony Liguori

>
> 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: 4523 bytes --]

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

* Re: [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option
  2012-01-30  2:48                           ` Anthony Liguori
@ 2012-02-01  2:06                             ` John Williams
  0 siblings, 0 replies; 33+ messages in thread
From: John Williams @ 2012-02-01  2:06 UTC (permalink / raw)
  To: Anthony Liguori
  Cc: Peter Maydell, monstr, duyl, Stefan Weil, qemu-devel,
	Markus Armbruster, Peter Crosthwaite, linnj, edgar.iglesias,
	Scott Wood, Eric Blake, Andreas Färber

On Mon, Jan 30, 2012 at 12:48 PM, Anthony Liguori <anthony@codemonkey.ws> wrote:
>
> On Jan 29, 2012 8:41 PM, "John Williams" <john.williams@petalogix.com>
> wrote:
>>
>> >>>> There's an opportunity here - QEMU needs the cmdline ability to load
>> >>>> random binaries/elfs anyway, such as
>> >>>>
>> >>>> --load file@address
>> >>>
>> >>>
>> >>>
>> >>> Make an elf loader device if you desire this ability but I'm skeptical
>> >>> that
>> >>> it really is all that useful.
>> >>
>> >>
>> >> It is useful for non-Linux use-cases, of which there are many!
>> >
>> >
>> > It's not just a matter of loading an elf binary in memory.  You probably
>> > need to have a specific register state set in order to run non-Linux elf
>> > binaries which means you'll need binary specific logic.
>>
>> The machine state at bootup is very well defined - it's whatever the TRM
>> says!
>>
>> An example may help.  We are working on the Xilinx Zynq model, dual
>> core Cortex A-9.  We currently are able to use QEMU for the entire
>> flow from
>>
>> cold reset ->
>> bootrom ->
>> u-boot ->
>> Linux
>>
>> In this flow, we don't want any magic initial state, we want QEMU to
>> model the CPU just like the real hardware.
>>
>> Equivalently, we might like to kick directly into the kernel, SMP==2 and
>> so on.
>>
>> It makes no sense to me that we should somehow use a different machine
>> model just to model a different boot flow on the same hardware.
>>
>> Another example, we are working on remoteproc/rpmsg support so that we
>> can run Linux on one core, and firmware on another.  We have this
>> working in QEMU today, except we had to hack around the ARM boot
>> code's assumptions that we always want the 2nd CPU to run an WFE/WIQ
>> loop.  This is only true if you are running Linux *and* you want QEMU
>> to fake the actions of a bootloader.
>>
>> If you are modelling a cold start you want those two CPUs to race
>> until one of them reads the CPUID register puts itself to sleep, ie
>> just run the bootrom.
>>
>> All of these use cases are not about virtualisation, but about system
>> modeling and emulation, which really is where QEMU is valuable in the
>> embedded space.
>
> I don't see how any of this is relevant.  Presumably, on real hardware, you
> have a rom bank wired to a specific physical address with ip fixed to an
> address which happens to be in that space?

Certainly a ROM makes sense to model as a device - there is a physical
equivalent.  I'm just not so sure about a virtual device whos job is
to bus master stuffing contents into some other memory.  For example,
with such an 'ELF loader' device - when ecaxtly should it do the load?
 Do you end up with a race at system init time?

> Why not just use an emulated flash chip?

If there is a bus addressable memory with fixed contents then that can
be modelled with a device.  I'm talking about an intermediate mode
where we would like to be able to prepopulate memory with arbitrary
contents.  Half way between 'model a ROM device with the bootrom', and
the hacky 'QEMU is also sometimes a Linux bootloader' approach taken
for booting VMLinux images.

>> > If all of these binaries you want to run have a well known register
>> > state,
>> > they you can just use fw_cfg and a piece of firmware to read the binary
>> > (which is basically how -kernel works on target-i386).
>> >
>> >
>> >>
>> >> Can you explain how you'd see such a 'loader device' in practice?  How
>> >> does it get bound into the machine model?  How do we pass arguments to
>> >> it?
>> >
>> >
>> > You create a device via qdev (now QOM) that takes whatever properties
>> > you
>> > need.  You then do:
>> >
>> > -device elf-loader,base=0xa00000,file=my-elf-binary
>> >
>> > No different than adding a network card.
>>
>> A network card is a tangible object, it can be present in the system.
>> The ELF loader is just emulator cruft, a necessary evil to get the
>> initial state of the machine.  Should it really be on a level footing
>> with actual devices?
>
> All systems have to bootstrap software some how.  Some device is reasonable
> for this.  This isn't emulated magic :-)

Sure.  I just have some questions about the behavioural semantics of
an ELF/binary loader device, vs recognising this loading function as a
role for a 'deus ex machina'

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

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

end of thread, other threads:[~2012-02-01  2:06 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-01-23  7:20 [Qemu-devel] [RFC PATCH 0/7] Zynq-7000 EPP platform model Peter A. G. Crosthwaite
     [not found] ` <cover.1327302677.git.peter.crosthwaite@petalogix.com>
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 1/7] cadence_uart: first revision Peter A. G. Crosthwaite
2012-01-24  2:02     ` John Linn
2012-01-24  8:07     ` Andreas Färber
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 2/7] cadence ttc: " Peter A. G. Crosthwaite
2012-01-24  2:03     ` John Linn
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 3/7] cadence_wdt: " Peter A. G. Crosthwaite
2012-01-24  2:03     ` John Linn
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 4/7] cadence_gem: " Peter A. G. Crosthwaite
2012-01-24  2:05     ` John Linn
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 5/7] vl.c: added -kerndtb option Peter A. G. Crosthwaite
2012-01-24  7:22     ` Andreas Färber
2012-01-24  7:35       ` Peter Crosthwaite
2012-01-24  7:50         ` Andreas Färber
2012-01-24 18:23       ` Stefan Weil
2012-01-26 19:34         ` Scott Wood
2012-01-26 21:27           ` Eric Blake
2012-01-27  8:25             ` Markus Armbruster
2012-01-29  6:51               ` Peter Crosthwaite
2012-01-30  0:28                 ` John Williams
2012-01-30  0:33                   ` John Williams
2012-01-30  2:11                   ` Anthony Liguori
2012-01-30  2:19                     ` John Williams
2012-01-30  2:28                       ` Anthony Liguori
2012-01-30  2:41                         ` John Williams
2012-01-30  2:48                           ` Anthony Liguori
2012-02-01  2:06                             ` John Williams
2012-01-30  2:10         ` Anthony Liguori
2012-01-26 19:40     ` Peter Maydell
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 6/7] arm_boot: added initrd address override Peter A. G. Crosthwaite
2012-01-23  7:20   ` [Qemu-devel] [RFC PATCH 7/7] xilinx_zynq: machine model first revision Peter A. G. Crosthwaite
2012-01-23  8:00     ` Michal Simek
2012-01-23  8:22       ` Peter Crosthwaite

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).