aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
Diffstat (limited to 'hw')
-rw-r--r--hw/Makefile.objs2
-rw-r--r--hw/arm_boot.c17
-rw-r--r--hw/arm_gic.c7
-rw-r--r--hw/arm_gic_common.c6
-rw-r--r--hw/armv7m_nvic.c4
-rw-r--r--hw/boards.h3
-rw-r--r--hw/device-hotplug.c2
-rw-r--r--hw/ds1338.c81
-rw-r--r--hw/exynos4210.c10
-rw-r--r--hw/exynos4210_mct.c2
-rw-r--r--hw/highbank.c9
-rw-r--r--hw/ide/core.c2
-rw-r--r--hw/kvmvapic.c4
-rw-r--r--hw/leon3.c1
-rw-r--r--hw/mips_jazz.c4
-rw-r--r--hw/openpic.c1397
-rw-r--r--hw/openpic.h7
-rw-r--r--hw/pc_sysfw.c2
-rw-r--r--hw/pci/Makefile.objs2
-rw-r--r--hw/pci/msix.c6
-rw-r--r--hw/ppc/Makefile.objs2
-rw-r--r--hw/ppc/e500-ccsr.h17
-rw-r--r--hw/ppc/e500.c205
-rw-r--r--hw/ppc/e500.h2
-rw-r--r--hw/ppc/e500plat.c3
-rw-r--r--hw/ppc/mpc8544ds.c2
-rw-r--r--hw/ppc_newworld.c25
-rw-r--r--hw/ppce500_pci.c58
-rw-r--r--hw/ppce500_pci.h9
-rw-r--r--hw/puv3.c1
-rw-r--r--hw/realview.c6
-rw-r--r--hw/s390-virtio.c17
-rw-r--r--hw/spapr.c37
-rw-r--r--hw/spapr.h4
-rw-r--r--hw/spapr_iommu.c6
-rw-r--r--hw/spapr_nvram.c196
-rw-r--r--hw/spapr_rtas.c6
-rw-r--r--hw/sun4m.c24
-rw-r--r--hw/versatilepb.c4
-rw-r--r--hw/vexpress.c4
-rw-r--r--hw/vfio_pci.c5
-rw-r--r--hw/vga.c2
-rw-r--r--hw/virtio-blk.h1
-rw-r--r--hw/virtio-pci.c1
-rw-r--r--hw/watchdog.c2
-rw-r--r--hw/xics.c47
-rw-r--r--hw/xics.h1
-rw-r--r--hw/xilinx_zynq.c11
48 files changed, 1171 insertions, 1095 deletions
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 9d33b189e6..bcf278d4ec 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -37,6 +37,8 @@ common-obj-$(CONFIG_I8259) += i8259_common.o i8259.o
common-obj-y += fifo.o
common-obj-y += pam.o
+extra-obj-y += pci/
+
# PPC devices
common-obj-$(CONFIG_PREP_PCI) += prep_pci.o
common-obj-$(CONFIG_I82378) += i82378.o
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 92e2cab476..ec3b8d5d12 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -44,11 +44,17 @@ static uint32_t bootloader[] = {
* for an interprocessor interrupt and polling a configurable
* location for the kernel secondary CPU entry point.
*/
+#define DSB_INSN 0xf57ff04f
+#define CP15_DSB_INSN 0xee070f9a /* mcr cp15, 0, r0, c7, c10, 4 */
+
static uint32_t smpboot[] = {
- 0xe59f201c, /* ldr r2, gic_cpu_if */
- 0xe59f001c, /* ldr r0, startaddr */
+ 0xe59f2028, /* ldr r2, gic_cpu_if */
+ 0xe59f0028, /* ldr r0, startaddr */
0xe3a01001, /* mov r1, #1 */
- 0xe5821000, /* str r1, [r2] */
+ 0xe5821000, /* str r1, [r2] - set GICC_CTLR.Enable */
+ 0xe3a010ff, /* mov r1, #0xff */
+ 0xe5821004, /* str r1, [r2, 4] - set GIC_PMR.Priority to 0xff */
+ DSB_INSN, /* dsb */
0xe320f003, /* wfi */
0xe5901000, /* ldr r1, [r0] */
0xe1110001, /* tst r1, r1 */
@@ -65,6 +71,11 @@ static void default_write_secondary(ARMCPU *cpu,
smpboot[ARRAY_SIZE(smpboot) - 1] = info->smp_bootreg_addr;
smpboot[ARRAY_SIZE(smpboot) - 2] = info->gic_cpu_if_addr;
for (n = 0; n < ARRAY_SIZE(smpboot); n++) {
+ /* Replace DSB with the pre-v7 DSB if necessary. */
+ if (!arm_feature(&cpu->env, ARM_FEATURE_V7) &&
+ smpboot[n] == DSB_INSN) {
+ smpboot[n] = CP15_DSB_INSN;
+ }
smpboot[n] = tswap32(smpboot[n]);
}
rom_add_blob_fixed("smpboot", smpboot, sizeof(smpboot),
diff --git a/hw/arm_gic.c b/hw/arm_gic.c
index f9e423f152..8d769de4f5 100644
--- a/hw/arm_gic.c
+++ b/hw/arm_gic.c
@@ -73,7 +73,7 @@ void gic_update(GICState *s)
}
}
level = 0;
- if (best_prio <= s->priority_mask[cpu]) {
+ if (best_prio < s->priority_mask[cpu]) {
s->current_pending[cpu] = best_irq;
if (best_prio < s->running_priority[cpu]) {
DPRINTF("Raised pending IRQ %d\n", best_irq);
@@ -374,7 +374,8 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
value = 0xff;
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
- int mask = (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq);
+ int mask =
+ (irq < GIC_INTERNAL) ? (1 << cpu) : GIC_TARGET(irq + i);
int cm = (irq < GIC_INTERNAL) ? (1 << cpu) : ALL_CPU_MASK;
if (!GIC_TEST_ENABLED(irq + i, cm)) {
@@ -417,7 +418,7 @@ static void gic_dist_writeb(void *opaque, hwaddr offset,
for (i = 0; i < 8; i++) {
if (value & (1 << i)) {
- GIC_SET_PENDING(irq + i, GIC_TARGET(irq));
+ GIC_SET_PENDING(irq + i, GIC_TARGET(irq + i));
}
}
} else if (offset < 0x300) {
diff --git a/hw/arm_gic_common.c b/hw/arm_gic_common.c
index 8369309d21..73ae331807 100644
--- a/hw/arm_gic_common.c
+++ b/hw/arm_gic_common.c
@@ -127,7 +127,11 @@ static void arm_gic_common_reset(DeviceState *dev)
int i;
memset(s->irq_state, 0, GIC_MAXIRQ * sizeof(gic_irq_state));
for (i = 0 ; i < s->num_cpu; i++) {
- s->priority_mask[i] = 0xf0;
+ if (s->revision == REV_11MPCORE) {
+ s->priority_mask[i] = 0xf0;
+ } else {
+ s->priority_mask[i] = 0;
+ }
s->current_pending[i] = 1023;
s->running_irq[i] = 1023;
s->running_priority[i] = 0x100;
diff --git a/hw/armv7m_nvic.c b/hw/armv7m_nvic.c
index f0a2e7b5d2..4963678bf1 100644
--- a/hw/armv7m_nvic.c
+++ b/hw/armv7m_nvic.c
@@ -455,9 +455,11 @@ static void armv7m_nvic_reset(DeviceState *dev)
nc->parent_reset(dev);
/* Common GIC reset resets to disabled; the NVIC doesn't have
* per-CPU interfaces so mark our non-existent CPU interface
- * as enabled by default.
+ * as enabled by default, and with a priority mask which allows
+ * all interrupts through.
*/
s->gic.cpu_enabled[0] = 1;
+ s->gic.priority_mask[0] = 0x100;
/* The NVIC as a whole is always enabled. */
s->gic.enabled = 1;
systick_reset(s);
diff --git a/hw/boards.h b/hw/boards.h
index 813d0e5109..c66fa16a9d 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -3,6 +3,7 @@
#ifndef HW_BOARDS_H
#define HW_BOARDS_H
+#include "blockdev.h"
#include "qdev.h"
typedef struct QEMUMachineInitArgs {
@@ -24,7 +25,7 @@ typedef struct QEMUMachine {
const char *desc;
QEMUMachineInitFunc *init;
QEMUMachineResetFunc *reset;
- int use_scsi;
+ BlockInterfaceType block_default_type;
int max_cpus;
unsigned int no_serial:1,
no_parallel:1,
diff --git a/hw/device-hotplug.c b/hw/device-hotplug.c
index 6d9c080381..839b9ea1d4 100644
--- a/hw/device-hotplug.c
+++ b/hw/device-hotplug.c
@@ -39,7 +39,7 @@ DriveInfo *add_init_drive(const char *optstr)
if (!opts)
return NULL;
- dinfo = drive_init(opts, current_machine->use_scsi);
+ dinfo = drive_init(opts, current_machine->block_default_type);
if (!dinfo) {
qemu_opts_del(opts);
return NULL;
diff --git a/hw/ds1338.c b/hw/ds1338.c
index b576d56438..1aefa3ba04 100644
--- a/hw/ds1338.c
+++ b/hw/ds1338.c
@@ -17,9 +17,16 @@
*/
#define NVRAM_SIZE 64
+/* Flags definitions */
+#define SECONDS_CH 0x80
+#define HOURS_12 0x40
+#define HOURS_PM 0x20
+#define CTRL_OSF 0x20
+
typedef struct {
I2CSlave i2c;
int64_t offset;
+ uint8_t wday_offset;
uint8_t nvram[NVRAM_SIZE];
int32_t ptr;
bool addr_byte;
@@ -27,12 +34,13 @@ typedef struct {
static const VMStateDescription vmstate_ds1338 = {
.name = "ds1338",
- .version_id = 1,
+ .version_id = 2,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField[]) {
VMSTATE_I2C_SLAVE(i2c, DS1338State),
VMSTATE_INT64(offset, DS1338State),
+ VMSTATE_UINT8_V(wday_offset, DS1338State, 2),
VMSTATE_UINT8_ARRAY(nvram, DS1338State, NVRAM_SIZE),
VMSTATE_INT32(ptr, DS1338State),
VMSTATE_BOOL(addr_byte, DS1338State),
@@ -49,17 +57,22 @@ static void capture_current_time(DS1338State *s)
qemu_get_timedate(&now, s->offset);
s->nvram[0] = to_bcd(now.tm_sec);
s->nvram[1] = to_bcd(now.tm_min);
- if (s->nvram[2] & 0x40) {
- s->nvram[2] = (to_bcd((now.tm_hour % 12)) + 1) | 0x40;
- if (now.tm_hour >= 12) {
- s->nvram[2] |= 0x20;
+ if (s->nvram[2] & HOURS_12) {
+ int tmp = now.tm_hour;
+ if (tmp == 0) {
+ tmp = 24;
+ }
+ if (tmp <= 12) {
+ s->nvram[2] = HOURS_12 | to_bcd(tmp);
+ } else {
+ s->nvram[2] = HOURS_12 | HOURS_PM | to_bcd(tmp - 12);
}
} else {
s->nvram[2] = to_bcd(now.tm_hour);
}
- s->nvram[3] = to_bcd(now.tm_wday) + 1;
+ s->nvram[3] = (now.tm_wday + s->wday_offset) % 7 + 1;
s->nvram[4] = to_bcd(now.tm_mday);
- s->nvram[5] = to_bcd(now.tm_mon) + 1;
+ s->nvram[5] = to_bcd(now.tm_mon + 1);
s->nvram[6] = to_bcd(now.tm_year - 100);
}
@@ -114,7 +127,8 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
s->addr_byte = false;
return 0;
}
- if (s->ptr < 8) {
+ if (s->ptr < 7) {
+ /* Time register. */
struct tm now;
qemu_get_timedate(&now, s->offset);
switch(s->ptr) {
@@ -126,19 +140,27 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
now.tm_min = from_bcd(data & 0x7f);
break;
case 2:
- if (data & 0x40) {
- if (data & 0x20) {
- data = from_bcd(data & 0x4f) + 11;
- } else {
- data = from_bcd(data & 0x1f) - 1;
+ if (data & HOURS_12) {
+ int tmp = from_bcd(data & (HOURS_PM - 1));
+ if (data & HOURS_PM) {
+ tmp += 12;
+ }
+ if (tmp == 24) {
+ tmp = 0;
}
+ now.tm_hour = tmp;
} else {
- data = from_bcd(data);
+ now.tm_hour = from_bcd(data & (HOURS_12 - 1));
}
- now.tm_hour = data;
break;
case 3:
- now.tm_wday = from_bcd(data & 7) - 1;
+ {
+ /* The day field is supposed to contain a value in
+ the range 1-7. Otherwise behavior is undefined.
+ */
+ int user_wday = (data & 7) - 1;
+ s->wday_offset = (user_wday - now.tm_wday + 7) % 7;
+ }
break;
case 4:
now.tm_mday = from_bcd(data & 0x3f);
@@ -149,11 +171,19 @@ static int ds1338_send(I2CSlave *i2c, uint8_t data)
case 6:
now.tm_year = from_bcd(data) + 100;
break;
- case 7:
- /* Control register. Currently ignored. */
- break;
}
s->offset = qemu_timedate_diff(&now);
+ } else if (s->ptr == 7) {
+ /* Control register. */
+
+ /* Ensure bits 2, 3 and 6 will read back as zero. */
+ data &= 0xB3;
+
+ /* Attempting to write the OSF flag to logic 1 leaves the
+ value unchanged. */
+ data = (data & ~CTRL_OSF) | (data & s->nvram[s->ptr] & CTRL_OSF);
+
+ s->nvram[s->ptr] = data;
} else {
s->nvram[s->ptr] = data;
}
@@ -166,6 +196,18 @@ static int ds1338_init(I2CSlave *i2c)
return 0;
}
+static void ds1338_reset(DeviceState *dev)
+{
+ DS1338State *s = FROM_I2C_SLAVE(DS1338State, I2C_SLAVE_FROM_QDEV(dev));
+
+ /* The clock is running and synchronized with the host */
+ s->offset = 0;
+ s->wday_offset = 0;
+ memset(s->nvram, 0, NVRAM_SIZE);
+ s->ptr = 0;
+ s->addr_byte = false;
+}
+
static void ds1338_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -175,6 +217,7 @@ static void ds1338_class_init(ObjectClass *klass, void *data)
k->event = ds1338_event;
k->recv = ds1338_recv;
k->send = ds1338_send;
+ dc->reset = ds1338_reset;
dc->vmsd = &vmstate_ds1338;
}
diff --git a/hw/exynos4210.c b/hw/exynos4210.c
index 00d4db8871..22148cd946 100644
--- a/hw/exynos4210.c
+++ b/hw/exynos4210.c
@@ -80,12 +80,16 @@ void exynos4210_write_secondary(ARMCPU *cpu,
{
int n;
uint32_t smpboot[] = {
- 0xe59f3024, /* ldr r3, External gic_cpu_if */
- 0xe59f2024, /* ldr r2, Internal gic_cpu_if */
- 0xe59f0024, /* ldr r0, startaddr */
+ 0xe59f3034, /* ldr r3, External gic_cpu_if */
+ 0xe59f2034, /* ldr r2, Internal gic_cpu_if */
+ 0xe59f0034, /* ldr r0, startaddr */
0xe3a01001, /* mov r1, #1 */
0xe5821000, /* str r1, [r2] */
0xe5831000, /* str r1, [r3] */
+ 0xe3a010ff, /* mov r1, #0xff */
+ 0xe5821004, /* str r1, [r2, #4] */
+ 0xe5831004, /* str r1, [r3, #4] */
+ 0xf57ff04f, /* dsb */
0xe320f003, /* wfi */
0xe5901000, /* ldr r1, [r0] */
0xe1110001, /* tst r1, r1 */
diff --git a/hw/exynos4210_mct.c b/hw/exynos4210_mct.c
index e79cd6ac01..37dbda92df 100644
--- a/hw/exynos4210_mct.c
+++ b/hw/exynos4210_mct.c
@@ -568,7 +568,7 @@ static void exynos4210_gfrc_event(void *opaque)
/* Reload FRC to reach nearest comparator */
s->g_timer.curr_comp = exynos4210_gcomp_find(s);
distance = exynos4210_gcomp_get_distance(s, s->g_timer.curr_comp);
- if (distance > MCT_GT_COUNTER_STEP) {
+ if (distance > MCT_GT_COUNTER_STEP || !distance) {
distance = MCT_GT_COUNTER_STEP;
}
exynos4210_gfrc_set_count(&s->g_timer, distance);
diff --git a/hw/highbank.c b/hw/highbank.c
index afbb005422..8e35127c8a 100644
--- a/hw/highbank.c
+++ b/hw/highbank.c
@@ -44,9 +44,12 @@ static void hb_write_secondary(ARMCPU *cpu, const struct arm_boot_info *info)
0xe210000f, /* ands r0, r0, #0x0f */
0xe3a03040, /* mov r3, #0x40 - jump address is 0x40 + 0x10 * core id */
0xe0830200, /* add r0, r3, r0, lsl #4 */
- 0xe59f2018, /* ldr r2, privbase */
+ 0xe59f2024, /* ldr r2, privbase */
0xe3a01001, /* mov r1, #1 */
- 0xe5821100, /* str r1, [r2, #256] */
+ 0xe5821100, /* str r1, [r2, #256] - set GICC_CTLR.Enable */
+ 0xe3a010ff, /* mov r1, #0xff */
+ 0xe5821104, /* str r1, [r2, #260] - set GICC_PMR.Priority to 0xff */
+ 0xf57ff04f, /* dsb */
0xe320f003, /* wfi */
0xe5901000, /* ldr r1, [r0] */
0xe1110001, /* tst r1, r1 */
@@ -326,7 +329,7 @@ static QEMUMachine highbank_machine = {
.name = "highbank",
.desc = "Calxeda Highbank (ECX-1000)",
.init = highbank_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
diff --git a/hw/ide/core.c b/hw/ide/core.c
index adc4aa41b9..0e5bc7fe3b 100644
--- a/hw/ide/core.c
+++ b/hw/ide/core.c
@@ -1869,6 +1869,8 @@ static void ide_reset(IDEState *s)
s->io_buffer_index = 0;
s->cd_sector_size = 0;
s->atapi_dma = 0;
+ s->tray_locked = 0;
+ s->tray_open = 0;
/* ATA DMA state */
s->io_buffer_size = 0;
s->req_nb_sectors = 0;
diff --git a/hw/kvmvapic.c b/hw/kvmvapic.c
index e04c4011d7..60c8fc46aa 100644
--- a/hw/kvmvapic.c
+++ b/hw/kvmvapic.c
@@ -387,7 +387,6 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
VAPICHandlers *handlers;
uint8_t opcode[2];
uint32_t imm32;
- TranslationBlock *current_tb;
target_ulong current_pc = 0;
target_ulong current_cs_base = 0;
int current_flags = 0;
@@ -399,8 +398,7 @@ static void patch_instruction(VAPICROMState *s, CPUX86State *env, target_ulong i
}
if (!kvm_enabled()) {
- current_tb = tb_find_pc(env->mem_io_pc);
- cpu_restore_state(current_tb, env, env->mem_io_pc);
+ cpu_restore_state(env, env->mem_io_pc);
cpu_get_tb_cpu_state(env, &current_pc, &current_cs_base,
&current_flags);
}
diff --git a/hw/leon3.c b/hw/leon3.c
index 774273828f..ef83dffd85 100644
--- a/hw/leon3.c
+++ b/hw/leon3.c
@@ -212,7 +212,6 @@ static QEMUMachine leon3_generic_machine = {
.name = "leon3_generic",
.desc = "Leon-3 generic",
.init = leon3_generic_hw_init,
- .use_scsi = 0,
};
static void leon3_machine_init(void)
diff --git a/hw/mips_jazz.c b/hw/mips_jazz.c
index 0847427241..ea1416ae2f 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -324,14 +324,14 @@ static QEMUMachine mips_magnum_machine = {
.name = "magnum",
.desc = "MIPS Magnum",
.init = mips_magnum_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine mips_pica61_machine = {
.name = "pica61",
.desc = "Acer Pica 61",
.init = mips_pica61_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static void mips_jazz_machine_init(void)
diff --git a/hw/openpic.c b/hw/openpic.c
index 4791dc6eaf..9c956b9dcc 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -37,6 +37,8 @@
#include "ppc_mac.h"
#include "pci/pci.h"
#include "openpic.h"
+#include "sysbus.h"
+#include "pci/msi.h"
//#define DEBUG_OPENPIC
@@ -46,89 +48,61 @@
#define DPRINTF(fmt, ...) do { } while (0)
#endif
-#define USE_MPCxxx /* Intel model is broken, for now */
-
-#if defined (USE_INTEL_GW80314)
-/* Intel GW80314 I/O Companion chip */
-
-#define MAX_CPU 4
-#define MAX_IRQ 32
-#define MAX_DBL 4
-#define MAX_MBX 4
-#define MAX_TMR 4
-#define VECTOR_BITS 8
-#define MAX_IPI 4
-
-#define VID (0x00000000)
-
-#elif defined(USE_MPCxxx)
-
-#define MAX_CPU 15
-#define MAX_IRQ 128
-#define MAX_DBL 0
-#define MAX_MBX 0
+#define MAX_CPU 15
+#define MAX_SRC 256
#define MAX_TMR 4
#define VECTOR_BITS 8
#define MAX_IPI 4
+#define MAX_MSI 8
+#define MAX_IRQ (MAX_SRC + MAX_IPI + MAX_TMR)
#define VID 0x03 /* MPIC version ID */
-#define VENI 0x00000000 /* Vendor ID */
-
-enum {
- IRQ_IPVP = 0,
- IRQ_IDE,
-};
-/* OpenPIC */
-#define OPENPIC_MAX_CPU 2
-#define OPENPIC_MAX_IRQ 64
-#define OPENPIC_EXT_IRQ 48
-#define OPENPIC_MAX_TMR MAX_TMR
-#define OPENPIC_MAX_IPI MAX_IPI
+/* OpenPIC capability flags */
+#define OPENPIC_FLAG_IDE_CRIT (1 << 0)
+
+/* OpenPIC address map */
+#define OPENPIC_GLB_REG_START 0x0
+#define OPENPIC_GLB_REG_SIZE 0x10F0
+#define OPENPIC_TMR_REG_START 0x10F0
+#define OPENPIC_TMR_REG_SIZE 0x220
+#define OPENPIC_MSI_REG_START 0x1600
+#define OPENPIC_MSI_REG_SIZE 0x200
+#define OPENPIC_SRC_REG_START 0x10000
+#define OPENPIC_SRC_REG_SIZE (MAX_SRC * 0x20)
+#define OPENPIC_CPU_REG_START 0x20000
+#define OPENPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
+
+/* Raven */
+#define RAVEN_MAX_CPU 2
+#define RAVEN_MAX_EXT 48
+#define RAVEN_MAX_IRQ 64
+#define RAVEN_MAX_TMR MAX_TMR
+#define RAVEN_MAX_IPI MAX_IPI
/* Interrupt definitions */
-#define OPENPIC_IRQ_FE (OPENPIC_EXT_IRQ) /* Internal functional IRQ */
-#define OPENPIC_IRQ_ERR (OPENPIC_EXT_IRQ + 1) /* Error IRQ */
-#define OPENPIC_IRQ_TIM0 (OPENPIC_EXT_IRQ + 2) /* First timer IRQ */
-#if OPENPIC_MAX_IPI > 0
-#define OPENPIC_IRQ_IPI0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First IPI IRQ */
-#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_IPI0 + (OPENPIC_MAX_CPU * OPENPIC_MAX_IPI)) /* First doorbell IRQ */
-#else
-#define OPENPIC_IRQ_DBL0 (OPENPIC_IRQ_TIM0 + OPENPIC_MAX_TMR) /* First doorbell IRQ */
-#define OPENPIC_IRQ_MBX0 (OPENPIC_IRQ_DBL0 + OPENPIC_MAX_DBL) /* First mailbox IRQ */
-#endif
-
-/* MPIC */
-#define MPIC_MAX_CPU 1
-#define MPIC_MAX_EXT 12
-#define MPIC_MAX_INT 64
-#define MPIC_MAX_MSG 4
-#define MPIC_MAX_MSI 8
-#define MPIC_MAX_TMR MAX_TMR
-#define MPIC_MAX_IPI MAX_IPI
-#define MPIC_MAX_IRQ (MPIC_MAX_EXT + MPIC_MAX_INT + MPIC_MAX_TMR + MPIC_MAX_MSG + MPIC_MAX_MSI + (MPIC_MAX_IPI * MPIC_MAX_CPU))
+#define RAVEN_FE_IRQ (RAVEN_MAX_EXT) /* Internal functional IRQ */
+#define RAVEN_ERR_IRQ (RAVEN_MAX_EXT + 1) /* Error IRQ */
+#define RAVEN_TMR_IRQ (RAVEN_MAX_EXT + 2) /* First timer IRQ */
+#define RAVEN_IPI_IRQ (RAVEN_TMR_IRQ + RAVEN_MAX_TMR) /* First IPI IRQ */
+/* First doorbell IRQ */
+#define RAVEN_DBL_IRQ (RAVEN_IPI_IRQ + (RAVEN_MAX_CPU * RAVEN_MAX_IPI))
+
+/* FSL_MPIC_20 */
+#define FSL_MPIC_20_MAX_CPU 1
+#define FSL_MPIC_20_MAX_EXT 12
+#define FSL_MPIC_20_MAX_INT 64
+#define FSL_MPIC_20_MAX_IRQ MAX_IRQ
/* Interrupt definitions */
-#define MPIC_EXT_IRQ 0
-#define MPIC_INT_IRQ (MPIC_EXT_IRQ + MPIC_MAX_EXT)
-#define MPIC_TMR_IRQ (MPIC_INT_IRQ + MPIC_MAX_INT)
-#define MPIC_MSG_IRQ (MPIC_TMR_IRQ + MPIC_MAX_TMR)
-#define MPIC_MSI_IRQ (MPIC_MSG_IRQ + MPIC_MAX_MSG)
-#define MPIC_IPI_IRQ (MPIC_MSI_IRQ + MPIC_MAX_MSI)
-
-#define MPIC_GLB_REG_START 0x0
-#define MPIC_GLB_REG_SIZE 0x10F0
-#define MPIC_TMR_REG_START 0x10F0
-#define MPIC_TMR_REG_SIZE 0x220
-#define MPIC_EXT_REG_START 0x10000
-#define MPIC_EXT_REG_SIZE 0x180
-#define MPIC_INT_REG_START 0x10200
-#define MPIC_INT_REG_SIZE 0x800
-#define MPIC_MSG_REG_START 0x11600
-#define MPIC_MSG_REG_SIZE 0x100
-#define MPIC_MSI_REG_START 0x11C00
-#define MPIC_MSI_REG_SIZE 0x100
-#define MPIC_CPU_REG_START 0x20000
-#define MPIC_CPU_REG_SIZE 0x100 + ((MAX_CPU - 1) * 0x1000)
+/* IRQs, accessible through the IRQ region */
+#define FSL_MPIC_20_EXT_IRQ 0x00
+#define FSL_MPIC_20_INT_IRQ 0x10
+#define FSL_MPIC_20_MSG_IRQ 0xb0
+#define FSL_MPIC_20_MSI_IRQ 0xe0
+/* These are available through separate regions, but
+ for simplicity's sake mapped into the same number space */
+#define FSL_MPIC_20_TMR_IRQ 0x100
+#define FSL_MPIC_20_IPI_IRQ 0x104
/*
* Block Revision Register1 (BRR1): QEMU does not fully emulate
@@ -141,34 +115,42 @@ enum {
#define FSL_BRR1_IPMJ (0x00 << 8) /* 8 bit IP major number */
#define FSL_BRR1_IPMN 0x00 /* 8 bit IP minor number */
-enum mpic_ide_bits {
- IDR_EP = 31,
- IDR_CI0 = 30,
- IDR_CI1 = 29,
- IDR_P1 = 1,
- IDR_P0 = 0,
-};
+#define FREP_NIRQ_SHIFT 16
+#define FREP_NCPU_SHIFT 8
+#define FREP_VID_SHIFT 0
-#else
-#error "Please select which OpenPic implementation is to be emulated"
-#endif
+#define VID_REVISION_1_2 2
+#define VID_REVISION_1_3 3
-#define OPENPIC_PAGE_SIZE 4096
+#define VENI_GENERIC 0x00000000 /* Generic Vendor ID */
+
+#define IDR_EP_SHIFT 31
+#define IDR_EP_MASK (1 << IDR_EP_SHIFT)
+#define IDR_CI0_SHIFT 30
+#define IDR_CI1_SHIFT 29
+#define IDR_P1_SHIFT 1
+#define IDR_P0_SHIFT 0
+
+#define MSIIR_OFFSET 0x140
+#define MSIIR_SRS_SHIFT 29
+#define MSIIR_SRS_MASK (0x7 << MSIIR_SRS_SHIFT)
+#define MSIIR_IBS_SHIFT 24
+#define MSIIR_IBS_MASK (0x1f << MSIIR_IBS_SHIFT)
#define BF_WIDTH(_bits_) \
(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
-static inline void set_bit (uint32_t *field, int bit)
+static inline void set_bit(uint32_t *field, int bit)
{
field[bit >> 5] |= 1 << (bit & 0x1F);
}
-static inline void reset_bit (uint32_t *field, int bit)
+static inline void reset_bit(uint32_t *field, int bit)
{
field[bit >> 5] &= ~(1 << (bit & 0x1F));
}
-static inline int test_bit (uint32_t *field, int bit)
+static inline int test_bit(uint32_t *field, int bit)
{
return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
}
@@ -183,41 +165,37 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
uint32_t val, int idx);
-enum {
- IRQ_EXTERNAL = 0x01,
- IRQ_INTERNAL = 0x02,
- IRQ_TIMER = 0x04,
- IRQ_SPECIAL = 0x08,
-};
-
typedef struct IRQ_queue_t {
uint32_t queue[BF_WIDTH(MAX_IRQ)];
int next;
int priority;
+ int pending; /* nr of pending bits in queue */
} IRQ_queue_t;
typedef struct IRQ_src_t {
uint32_t ipvp; /* IRQ vector/priority register */
uint32_t ide; /* IRQ destination register */
- int type;
int last_cpu;
int pending; /* TRUE if IRQ is pending */
} IRQ_src_t;
-enum IPVP_bits {
- IPVP_MASK = 31,
- IPVP_ACTIVITY = 30,
- IPVP_MODE = 29,
- IPVP_POLARITY = 23,
- IPVP_SENSE = 22,
-};
+#define IPVP_MASK_SHIFT 31
+#define IPVP_MASK_MASK (1 << IPVP_MASK_SHIFT)
+#define IPVP_ACTIVITY_SHIFT 30
+#define IPVP_ACTIVITY_MASK (1 << IPVP_ACTIVITY_SHIFT)
+#define IPVP_MODE_SHIFT 29
+#define IPVP_MODE_MASK (1 << IPVP_MODE_SHIFT)
+#define IPVP_POLARITY_SHIFT 23
+#define IPVP_POLARITY_MASK (1 << IPVP_POLARITY_SHIFT)
+#define IPVP_SENSE_SHIFT 22
+#define IPVP_SENSE_MASK (1 << IPVP_SENSE_SHIFT)
+
#define IPVP_PRIORITY_MASK (0x1F << 16)
#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
#define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
#define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
typedef struct IRQ_dst_t {
- uint32_t tfrr;
uint32_t pctp; /* CPU current task priority */
uint32_t pcsr; /* CPU sensitivity register */
IRQ_queue_t raised;
@@ -225,18 +203,28 @@ typedef struct IRQ_dst_t {
qemu_irq *irqs;
} IRQ_dst_t;
-typedef struct openpic_t {
- PCIDevice pci_dev;
+typedef struct OpenPICState {
+ SysBusDevice busdev;
MemoryRegion mem;
+ /* Behavior control */
+ uint32_t model;
+ uint32_t flags;
+ uint32_t nb_irqs;
+ uint32_t vid;
+ uint32_t veni; /* Vendor identification register */
+ uint32_t spve_mask;
+ uint32_t tifr_reset;
+ uint32_t ipvp_reset;
+ uint32_t ide_reset;
+ uint32_t brr1;
+
/* Sub-regions */
- MemoryRegion sub_io_mem[7];
+ MemoryRegion sub_io_mem[5];
/* Global registers */
uint32_t frep; /* Feature reporting register */
uint32_t glbc; /* Global configuration register */
- uint32_t micr; /* MPIC interrupt configuration register */
- uint32_t veni; /* Vendor identification register */
uint32_t pint; /* Processor initialization register */
uint32_t spve; /* Spurious vector register */
uint32_t tifr; /* Timer frequency reporting register */
@@ -244,56 +232,54 @@ typedef struct openpic_t {
IRQ_src_t src[MAX_IRQ];
/* Local registers per output pin */
IRQ_dst_t dst[MAX_CPU];
- int nb_cpus;
+ uint32_t nb_cpus;
/* Timer registers */
struct {
uint32_t ticc; /* Global timer current count register */
uint32_t tibc; /* Global timer base count register */
} timers[MAX_TMR];
-#if MAX_DBL > 0
- /* Doorbell registers */
- uint32_t dar; /* Doorbell activate register */
+ /* Shared MSI registers */
struct {
- uint32_t dmr; /* Doorbell messaging register */
- } doorbells[MAX_DBL];
-#endif
-#if MAX_MBX > 0
- /* Mailbox registers */
- struct {
- uint32_t mbr; /* Mailbox register */
- } mailboxes[MAX_MAILBOXES];
-#endif
- /* IRQ out is used when in bypass mode (not implemented) */
- qemu_irq irq_out;
- int max_irq;
- int irq_ipi0;
- int irq_tim0;
- void (*reset) (void *);
- void (*irq_raise) (struct openpic_t *, int, IRQ_src_t *);
-} openpic_t;
-
-static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
+ uint32_t msir; /* Shared Message Signaled Interrupt Register */
+ } msi[MAX_MSI];
+ uint32_t max_irq;
+ uint32_t irq_ipi0;
+ uint32_t irq_tim0;
+ uint32_t irq_msi;
+} OpenPICState;
+
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src);
+
+static inline void IRQ_setbit(IRQ_queue_t *q, int n_IRQ)
{
+ q->pending++;
set_bit(q->queue, n_IRQ);
}
-static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
+static inline void IRQ_resetbit(IRQ_queue_t *q, int n_IRQ)
{
+ q->pending--;
reset_bit(q->queue, n_IRQ);
}
-static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
+static inline int IRQ_testbit(IRQ_queue_t *q, int n_IRQ)
{
return test_bit(q->queue, n_IRQ);
}
-static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
+static void IRQ_check(OpenPICState *opp, IRQ_queue_t *q)
{
int next, i;
int priority;
next = -1;
priority = -1;
+
+ if (!q->pending) {
+ /* IRQ bitmap is empty */
+ goto out;
+ }
+
for (i = 0; i < opp->max_irq; i++) {
if (IRQ_testbit(q, i)) {
DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
@@ -304,11 +290,13 @@ static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
}
}
}
+
+out:
q->next = next;
q->priority = priority;
}
-static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
+static int IRQ_get_next(OpenPICState *opp, IRQ_queue_t *q)
{
if (q->next == -1) {
/* XXX: optimize */
@@ -318,7 +306,7 @@ static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
return q->next;
}
-static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
+static void IRQ_local_pipe(OpenPICState *opp, int n_CPU, int n_IRQ)
{
IRQ_dst_t *dst;
IRQ_src_t *src;
@@ -339,7 +327,7 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
__func__, n_IRQ, n_CPU);
return;
}
- set_bit(&src->ipvp, IPVP_ACTIVITY);
+ src->ipvp |= IPVP_ACTIVITY_MASK;
IRQ_setbit(&dst->raised, n_IRQ);
if (priority < dst->raised.priority) {
/* An higher priority IRQ is already raised */
@@ -356,11 +344,11 @@ static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
return;
}
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n", n_CPU, n_IRQ);
- opp->irq_raise(opp, n_CPU, src);
+ openpic_irq_raise(opp, n_CPU, src);
}
/* update pic state because registers for n_IRQ have changed value */
-static void openpic_update_irq(openpic_t *opp, int n_IRQ)
+static void openpic_update_irq(OpenPICState *opp, int n_IRQ)
{
IRQ_src_t *src;
int i;
@@ -372,7 +360,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
DPRINTF("%s: IRQ %d is not pending\n", __func__, n_IRQ);
return;
}
- if (test_bit(&src->ipvp, IPVP_MASK)) {
+ if (src->ipvp & IPVP_MASK_MASK) {
/* Interrupt source is disabled */
DPRINTF("%s: IRQ %d is disabled\n", __func__, n_IRQ);
return;
@@ -382,7 +370,7 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
DPRINTF("%s: IRQ %d has 0 priority\n", __func__, n_IRQ);
return;
}
- if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
+ if (src->ipvp & IPVP_ACTIVITY_MASK) {
/* IRQ already active */
DPRINTF("%s: IRQ %d is already active\n", __func__, n_IRQ);
return;
@@ -396,18 +384,19 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
if (src->ide == (1 << src->last_cpu)) {
/* Only one CPU is allowed to receive this IRQ */
IRQ_local_pipe(opp, src->last_cpu, n_IRQ);
- } else if (!test_bit(&src->ipvp, IPVP_MODE)) {
+ } else if (!(src->ipvp & IPVP_MODE_MASK)) {
/* Directed delivery mode */
for (i = 0; i < opp->nb_cpus; i++) {
- if (test_bit(&src->ide, i))
+ if (src->ide & (1 << i)) {
IRQ_local_pipe(opp, i, n_IRQ);
+ }
}
} else {
/* Distributed delivery mode */
for (i = src->last_cpu + 1; i != src->last_cpu; i++) {
if (i == opp->nb_cpus)
i = 0;
- if (test_bit(&src->ide, i)) {
+ if (src->ide & (1 << i)) {
IRQ_local_pipe(opp, i, n_IRQ);
src->last_cpu = i;
break;
@@ -418,17 +407,18 @@ static void openpic_update_irq(openpic_t *opp, int n_IRQ)
static void openpic_set_irq(void *opaque, int n_IRQ, int level)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
IRQ_src_t *src;
src = &opp->src[n_IRQ];
DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
n_IRQ, level, src->ipvp);
- if (test_bit(&src->ipvp, IPVP_SENSE)) {
+ if (src->ipvp & IPVP_SENSE_MASK) {
/* level-sensitive irq */
src->pending = level;
- if (!level)
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ if (!level) {
+ src->ipvp &= ~IPVP_ACTIVITY_MASK;
+ }
} else {
/* edge-sensitive irq */
if (level)
@@ -437,24 +427,24 @@ static void openpic_set_irq(void *opaque, int n_IRQ, int level)
openpic_update_irq(opp, n_IRQ);
}
-static void openpic_reset (void *opaque)
+static void openpic_reset(DeviceState *d)
{
- openpic_t *opp = (openpic_t *)opaque;
+ OpenPICState *opp = FROM_SYSBUS(typeof (*opp), sysbus_from_qdev(d));
int i;
opp->glbc = 0x80000000;
/* Initialise controller registers */
- opp->frep = ((OPENPIC_EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
- opp->veni = VENI;
+ opp->frep = ((opp->nb_irqs -1) << FREP_NIRQ_SHIFT) |
+ ((opp->nb_cpus -1) << FREP_NCPU_SHIFT) |
+ (opp->vid << FREP_VID_SHIFT);
+
opp->pint = 0x00000000;
- opp->spve = 0x000000FF;
- opp->tifr = 0x003F7A00;
- /* ? */
- opp->micr = 0x00000000;
+ opp->spve = -1 & opp->spve_mask;
+ opp->tifr = opp->tifr_reset;
/* Initialise IRQ sources */
for (i = 0; i < opp->max_irq; i++) {
- opp->src[i].ipvp = 0xA0000000;
- opp->src[i].ide = 0x00000000;
+ opp->src[i].ipvp = opp->ipvp_reset;
+ opp->src[i].ide = opp->ide_reset;
}
/* Initialise IRQ destinations */
for (i = 0; i < MAX_CPU; i++) {
@@ -470,34 +460,21 @@ static void openpic_reset (void *opaque)
opp->timers[i].ticc = 0x00000000;
opp->timers[i].tibc = 0x80000000;
}
- /* Initialise doorbells */
-#if MAX_DBL > 0
- opp->dar = 0x00000000;
- for (i = 0; i < MAX_DBL; i++) {
- opp->doorbells[i].dmr = 0x00000000;
- }
-#endif
- /* Initialise mailboxes */
-#if MAX_MBX > 0
- for (i = 0; i < MAX_MBX; i++) { /* ? */
- opp->mailboxes[i].mbr = 0x00000000;
- }
-#endif
/* Go out of RESET state */
opp->glbc = 0x00000000;
}
-static inline uint32_t read_IRQreg_ide(openpic_t *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_ide(OpenPICState *opp, int n_IRQ)
{
return opp->src[n_IRQ].ide;
}
-static inline uint32_t read_IRQreg_ipvp(openpic_t *opp, int n_IRQ)
+static inline uint32_t read_IRQreg_ipvp(OpenPICState *opp, int n_IRQ)
{
return opp->src[n_IRQ].ipvp;
}
-static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_ide(OpenPICState *opp, int n_IRQ, uint32_t val)
{
uint32_t tmp;
@@ -507,7 +484,7 @@ static inline void write_IRQreg_ide(openpic_t *opp, int n_IRQ, uint32_t val)
DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
}
-static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
+static inline void write_IRQreg_ipvp(OpenPICState *opp, int n_IRQ, uint32_t val)
{
/* NOTE: not fully accurate for special IRQs, but simple and sufficient */
/* ACTIVITY bit is read-only */
@@ -518,87 +495,10 @@ static inline void write_IRQreg_ipvp(openpic_t *opp, int n_IRQ, uint32_t val)
opp->src[n_IRQ].ipvp);
}
-#if 0 // Code provision for Intel model
-#if MAX_DBL > 0
-static uint32_t read_doorbell_register (openpic_t *opp,
- int n_dbl, uint32_t offset)
-{
- uint32_t retval;
-
- switch (offset) {
- case DBL_IPVP_OFFSET:
- retval = read_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl);
- break;
- case DBL_IDE_OFFSET:
- retval = read_IRQreg_ide(opp, IRQ_DBL0 + n_dbl);
- break;
- case DBL_DMR_OFFSET:
- retval = opp->doorbells[n_dbl].dmr;
- break;
- }
-
- return retval;
-}
-
-static void write_doorbell_register (penpic_t *opp, int n_dbl,
- uint32_t offset, uint32_t value)
-{
- switch (offset) {
- case DBL_IVPR_OFFSET:
- write_IRQreg_ipvp(opp, IRQ_DBL0 + n_dbl, value);
- break;
- case DBL_IDE_OFFSET:
- write_IRQreg_ide(opp, IRQ_DBL0 + n_dbl, value);
- break;
- case DBL_DMR_OFFSET:
- opp->doorbells[n_dbl].dmr = value;
- break;
- }
-}
-#endif
-
-#if MAX_MBX > 0
-static uint32_t read_mailbox_register (openpic_t *opp,
- int n_mbx, uint32_t offset)
-{
- uint32_t retval;
-
- switch (offset) {
- case MBX_MBR_OFFSET:
- retval = opp->mailboxes[n_mbx].mbr;
- break;
- case MBX_IVPR_OFFSET:
- retval = read_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx);
- break;
- case MBX_DMR_OFFSET:
- retval = read_IRQreg_ide(opp, IRQ_MBX0 + n_mbx);
- break;
- }
-
- return retval;
-}
-
-static void write_mailbox_register (openpic_t *opp, int n_mbx,
- uint32_t address, uint32_t value)
-{
- switch (offset) {
- case MBX_MBR_OFFSET:
- opp->mailboxes[n_mbx].mbr = value;
- break;
- case MBX_IVPR_OFFSET:
- write_IRQreg_ipvp(opp, IRQ_MBX0 + n_mbx, value);
- break;
- case MBX_DMR_OFFSET:
- write_IRQreg_ide(opp, IRQ_MBX0 + n_mbx, value);
- break;
- }
-}
-#endif
-#endif /* 0 : Code provision for Intel model */
-
-static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val)
+static void openpic_gbl_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned len)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
IRQ_dst_t *dst;
int idx;
@@ -621,9 +521,9 @@ static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val)
case 0x1000: /* FREP */
break;
case 0x1020: /* GLBC */
- if (val & 0x80000000 && opp->reset)
- opp->reset(opp);
- opp->glbc = val & ~0x80000000;
+ if (val & 0x80000000) {
+ openpic_reset(&opp->busdev.qdev);
+ }
break;
case 0x1080: /* VENI */
break;
@@ -652,19 +552,16 @@ static void openpic_gbl_write (void *opaque, hwaddr addr, uint32_t val)
}
break;
case 0x10E0: /* SPVE */
- opp->spve = val & 0x000000FF;
- break;
- case 0x10F0: /* TIFR */
- opp->tifr = val;
+ opp->spve = val & opp->spve_mask;
break;
default:
break;
}
}
-static uint32_t openpic_gbl_read (void *opaque, hwaddr addr)
+static uint64_t openpic_gbl_read(void *opaque, hwaddr addr, unsigned len)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
uint32_t retval;
DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
@@ -708,9 +605,6 @@ static uint32_t openpic_gbl_read (void *opaque, hwaddr addr)
case 0x10E0: /* SPVE */
retval = opp->spve;
break;
- case 0x10F0: /* TIFR */
- retval = opp->tifr;
- break;
default:
break;
}
@@ -719,73 +613,83 @@ static uint32_t openpic_gbl_read (void *opaque, hwaddr addr)
return retval;
}
-static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
+static void openpic_tmr_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned len)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
int idx;
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
- addr -= 0x10;
- addr &= 0xFFFF;
- idx = (addr & 0xFFF0) >> 6;
+ idx = (addr >> 6) & 0x3;
addr = addr & 0x30;
- switch (addr) {
- case 0x00: /* TICC */
+
+ if (addr == 0x0) {
+ /* TIFR (TFRR) */
+ opp->tifr = val;
+ return;
+ }
+ switch (addr & 0x30) {
+ case 0x00: /* TICC (GTCCR) */
break;
- case 0x10: /* TIBC */
+ case 0x10: /* TIBC (GTBCR) */
if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
(val & 0x80000000) == 0 &&
(opp->timers[idx].tibc & 0x80000000) != 0)
opp->timers[idx].ticc &= ~0x80000000;
opp->timers[idx].tibc = val;
break;
- case 0x20: /* TIVP */
+ case 0x20: /* TIVP (GTIVPR) */
write_IRQreg_ipvp(opp, opp->irq_tim0 + idx, val);
break;
- case 0x30: /* TIDE */
+ case 0x30: /* TIDE (GTIDR) */
write_IRQreg_ide(opp, opp->irq_tim0 + idx, val);
break;
}
}
-static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
+static uint64_t openpic_tmr_read(void *opaque, hwaddr addr, unsigned len)
{
- openpic_t *opp = opaque;
- uint32_t retval;
+ OpenPICState *opp = opaque;
+ uint32_t retval = -1;
int idx;
DPRINTF("%s: addr %08x\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr -= 0x10;
- addr &= 0xFFFF;
- idx = (addr & 0xFFF0) >> 6;
- addr = addr & 0x30;
- switch (addr) {
- case 0x00: /* TICC */
+ if (addr & 0xF) {
+ goto out;
+ }
+ idx = (addr >> 6) & 0x3;
+ if (addr == 0x0) {
+ /* TIFR (TFRR) */
+ retval = opp->tifr;
+ goto out;
+ }
+ switch (addr & 0x30) {
+ case 0x00: /* TICC (GTCCR) */
retval = opp->timers[idx].ticc;
break;
- case 0x10: /* TIBC */
+ case 0x10: /* TIBC (GTBCR) */
retval = opp->timers[idx].tibc;
break;
- case 0x20: /* TIPV */
+ case 0x20: /* TIPV (TIPV) */
retval = read_IRQreg_ipvp(opp, opp->irq_tim0 + idx);
break;
- case 0x30: /* TIDE */
+ case 0x30: /* TIDE (TIDR) */
retval = read_IRQreg_ide(opp, opp->irq_tim0 + idx);
break;
}
+
+out:
DPRINTF("%s: => %08x\n", __func__, retval);
return retval;
}
-static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
+static void openpic_src_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned len)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
int idx;
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
@@ -802,9 +706,9 @@ static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
}
}
-static uint32_t openpic_src_read (void *opaque, uint32_t addr)
+static uint64_t openpic_src_read(void *opaque, uint64_t addr, unsigned len)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
uint32_t retval;
int idx;
@@ -826,10 +730,72 @@ static uint32_t openpic_src_read (void *opaque, uint32_t addr)
return retval;
}
+static void openpic_msi_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+ OpenPICState *opp = opaque;
+ int idx = opp->irq_msi;
+ int srs, ibs;
+
+ DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
+ if (addr & 0xF) {
+ return;
+ }
+
+ switch (addr) {
+ case MSIIR_OFFSET:
+ srs = val >> MSIIR_SRS_SHIFT;
+ idx += srs;
+ ibs = (val & MSIIR_IBS_MASK) >> MSIIR_IBS_SHIFT;
+ opp->msi[srs].msir |= 1 << ibs;
+ openpic_set_irq(opp, idx, 1);
+ break;
+ default:
+ /* most registers are read-only, thus ignored */
+ break;
+ }
+}
+
+static uint64_t openpic_msi_read(void *opaque, hwaddr addr, unsigned size)
+{
+ OpenPICState *opp = opaque;
+ uint64_t r = 0;
+ int i, srs;
+
+ DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
+ if (addr & 0xF) {
+ return -1;
+ }
+
+ srs = addr >> 4;
+
+ switch (addr) {
+ case 0x00:
+ case 0x10:
+ case 0x20:
+ case 0x30:
+ case 0x40:
+ case 0x50:
+ case 0x60:
+ case 0x70: /* MSIRs */
+ r = opp->msi[srs].msir;
+ /* Clear on read */
+ opp->msi[srs].msir = 0;
+ break;
+ case 0x120: /* MSISR */
+ for (i = 0; i < MAX_MSI; i++) {
+ r |= (opp->msi[i].msir ? 1 : 0) << i;
+ }
+ break;
+ }
+
+ return r;
+}
+
static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
uint32_t val, int idx)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
IRQ_src_t *src;
IRQ_dst_t *dst;
int s_IRQ, n_IRQ;
@@ -841,7 +807,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
dst = &opp->dst[idx];
addr &= 0xFF0;
switch (addr) {
-#if MAX_IPI > 0
case 0x40: /* IPIDR */
case 0x50:
case 0x60:
@@ -853,7 +818,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
openpic_set_irq(opp, opp->irq_ipi0 + idx, 1);
openpic_set_irq(opp, opp->irq_ipi0 + idx, 0);
break;
-#endif
case 0x80: /* PCTP */
dst->pctp = val & 0x0000000F;
break;
@@ -878,7 +842,7 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
IPVP_PRIORITY(src->ipvp) > dst->servicing.priority)) {
DPRINTF("Raise OpenPIC INT output cpu %d irq %d\n",
idx, n_IRQ);
- opp->irq_raise(opp, idx, src);
+ openpic_irq_raise(opp, idx, src);
}
break;
default:
@@ -886,7 +850,8 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
}
}
-static void openpic_cpu_write(void *opaque, hwaddr addr, uint32_t val)
+static void openpic_cpu_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned len)
{
openpic_cpu_write_internal(opaque, addr, val, (addr & 0x1f000) >> 12);
}
@@ -894,7 +859,7 @@ static void openpic_cpu_write(void *opaque, hwaddr addr, uint32_t val)
static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
int idx)
{
- openpic_t *opp = opaque;
+ OpenPICState *opp = opaque;
IRQ_src_t *src;
IRQ_dst_t *dst;
uint32_t retval;
@@ -908,7 +873,7 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
addr &= 0xFF0;
switch (addr) {
case 0x00: /* Block Revision Register1 (BRR1) */
- retval = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
+ retval = opp->brr1;
break;
case 0x80: /* PCTP */
retval = dst->pctp;
@@ -926,13 +891,13 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
retval = IPVP_VECTOR(opp->spve);
} else {
src = &opp->src[n_IRQ];
- if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
+ if (!(src->ipvp & IPVP_ACTIVITY_MASK) ||
!(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
/* - Spurious level-sensitive IRQ
* - Priorities has been changed
* and the pending IRQ isn't allowed anymore
*/
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ src->ipvp &= ~IPVP_ACTIVITY_MASK;
retval = IPVP_VECTOR(opp->spve);
} else {
/* IRQ enter servicing state */
@@ -941,20 +906,20 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
}
IRQ_resetbit(&dst->raised, n_IRQ);
dst->raised.next = -1;
- if (!test_bit(&src->ipvp, IPVP_SENSE)) {
+ if (!(src->ipvp & IPVP_SENSE_MASK)) {
/* edge-sensitive IRQ */
- reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ src->ipvp &= ~IPVP_ACTIVITY_MASK;
src->pending = 0;
}
if ((n_IRQ >= opp->irq_ipi0) && (n_IRQ < (opp->irq_ipi0 + MAX_IPI))) {
src->ide &= ~(1 << idx);
- if (src->ide && !test_bit(&src->ipvp, IPVP_SENSE)) {
+ if (src->ide && !(src->ipvp & IPVP_SENSE_MASK)) {
/* trigger on CPUs that didn't know about it yet */
openpic_set_irq(opp, n_IRQ, 1);
openpic_set_irq(opp, n_IRQ, 0);
/* if all CPUs knew about it, set active bit again */
- set_bit(&src->ipvp, IPVP_ACTIVITY);
+ src->ipvp |= IPVP_ACTIVITY_MASK;
}
}
}
@@ -970,96 +935,109 @@ static uint32_t openpic_cpu_read_internal(void *opaque, hwaddr addr,
return retval;
}
-static uint32_t openpic_cpu_read(void *opaque, hwaddr addr)
+static uint64_t openpic_cpu_read(void *opaque, hwaddr addr, unsigned len)
{
return openpic_cpu_read_internal(opaque, addr, (addr & 0x1f000) >> 12);
}
-static void openpic_buggy_write (void *opaque,
- hwaddr addr, uint32_t val)
-{
- printf("Invalid OPENPIC write access !\n");
-}
-
-static uint32_t openpic_buggy_read (void *opaque, hwaddr addr)
-{
- printf("Invalid OPENPIC read access !\n");
-
- return -1;
-}
-
-static void openpic_writel (void *opaque,
- hwaddr addr, uint32_t val)
-{
- openpic_t *opp = opaque;
-
- addr &= 0x3FFFF;
- DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
- if (addr < 0x1100) {
- /* Global registers */
- openpic_gbl_write(opp, addr, val);
- } else if (addr < 0x10000) {
- /* Timers registers */
- openpic_timer_write(opp, addr, val);
- } else if (addr < 0x20000) {
- /* Source registers */
- openpic_src_write(opp, addr, val);
- } else {
- /* CPU registers */
- openpic_cpu_write(opp, addr, val);
- }
-}
+static const MemoryRegionOps openpic_glb_ops_le = {
+ .write = openpic_gbl_write,
+ .read = openpic_gbl_read,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
-static uint32_t openpic_readl (void *opaque,hwaddr addr)
-{
- openpic_t *opp = opaque;
- uint32_t retval;
+static const MemoryRegionOps openpic_glb_ops_be = {
+ .write = openpic_gbl_write,
+ .read = openpic_gbl_read,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
- addr &= 0x3FFFF;
- DPRINTF("%s: offset %08x\n", __func__, (int)addr);
- if (addr < 0x1100) {
- /* Global registers */
- retval = openpic_gbl_read(opp, addr);
- } else if (addr < 0x10000) {
- /* Timers registers */
- retval = openpic_timer_read(opp, addr);
- } else if (addr < 0x20000) {
- /* Source registers */
- retval = openpic_src_read(opp, addr);
- } else {
- /* CPU registers */
- retval = openpic_cpu_read(opp, addr);
- }
+static const MemoryRegionOps openpic_tmr_ops_le = {
+ .write = openpic_tmr_write,
+ .read = openpic_tmr_read,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
- return retval;
-}
+static const MemoryRegionOps openpic_tmr_ops_be = {
+ .write = openpic_tmr_write,
+ .read = openpic_tmr_read,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
-static uint64_t openpic_read(void *opaque, hwaddr addr,
- unsigned size)
-{
- openpic_t *opp = opaque;
+static const MemoryRegionOps openpic_cpu_ops_le = {
+ .write = openpic_cpu_write,
+ .read = openpic_cpu_read,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
- switch (size) {
- case 4: return openpic_readl(opp, addr);
- default: return openpic_buggy_read(opp, addr);
- }
-}
+static const MemoryRegionOps openpic_cpu_ops_be = {
+ .write = openpic_cpu_write,
+ .read = openpic_cpu_read,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
-static void openpic_write(void *opaque, hwaddr addr,
- uint64_t data, unsigned size)
-{
- openpic_t *opp = opaque;
+static const MemoryRegionOps openpic_src_ops_le = {
+ .write = openpic_src_write,
+ .read = openpic_src_read,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
- switch (size) {
- case 4: return openpic_writel(opp, addr, data);
- default: return openpic_buggy_write(opp, addr, data);
- }
-}
+static const MemoryRegionOps openpic_src_ops_be = {
+ .write = openpic_src_write,
+ .read = openpic_src_read,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
-static const MemoryRegionOps openpic_ops = {
- .read = openpic_read,
- .write = openpic_write,
+static const MemoryRegionOps openpic_msi_ops_le = {
+ .read = openpic_msi_read,
+ .write = openpic_msi_write,
.endianness = DEVICE_LITTLE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+};
+
+static const MemoryRegionOps openpic_msi_ops_be = {
+ .read = openpic_msi_read,
+ .write = openpic_msi_write,
+ .endianness = DEVICE_BIG_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
};
static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
@@ -1075,12 +1053,10 @@ static void openpic_save_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
static void openpic_save(QEMUFile* f, void *opaque)
{
- openpic_t *opp = (openpic_t *)opaque;
+ OpenPICState *opp = (OpenPICState *)opaque;
unsigned int i;
- qemu_put_be32s(f, &opp->frep);
qemu_put_be32s(f, &opp->glbc);
- qemu_put_be32s(f, &opp->micr);
qemu_put_be32s(f, &opp->veni);
qemu_put_be32s(f, &opp->pint);
qemu_put_be32s(f, &opp->spve);
@@ -1089,15 +1065,13 @@ static void openpic_save(QEMUFile* f, void *opaque)
for (i = 0; i < opp->max_irq; i++) {
qemu_put_be32s(f, &opp->src[i].ipvp);
qemu_put_be32s(f, &opp->src[i].ide);
- qemu_put_sbe32s(f, &opp->src[i].type);
qemu_put_sbe32s(f, &opp->src[i].last_cpu);
qemu_put_sbe32s(f, &opp->src[i].pending);
}
- qemu_put_sbe32s(f, &opp->nb_cpus);
+ qemu_put_be32s(f, &opp->nb_cpus);
for (i = 0; i < opp->nb_cpus; i++) {
- qemu_put_be32s(f, &opp->dst[i].tfrr);
qemu_put_be32s(f, &opp->dst[i].pctp);
qemu_put_be32s(f, &opp->dst[i].pcsr);
openpic_save_IRQ_queue(f, &opp->dst[i].raised);
@@ -1108,22 +1082,6 @@ static void openpic_save(QEMUFile* f, void *opaque)
qemu_put_be32s(f, &opp->timers[i].ticc);
qemu_put_be32s(f, &opp->timers[i].tibc);
}
-
-#if MAX_DBL > 0
- qemu_put_be32s(f, &opp->dar);
-
- for (i = 0; i < MAX_DBL; i++) {
- qemu_put_be32s(f, &opp->doorbells[i].dmr);
- }
-#endif
-
-#if MAX_MBX > 0
- for (i = 0; i < MAX_MAILBOXES; i++) {
- qemu_put_be32s(f, &opp->mailboxes[i].mbr);
- }
-#endif
-
- pci_device_save(&opp->pci_dev, f);
}
static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
@@ -1139,15 +1097,13 @@ static void openpic_load_IRQ_queue(QEMUFile* f, IRQ_queue_t *q)
static int openpic_load(QEMUFile* f, void *opaque, int version_id)
{
- openpic_t *opp = (openpic_t *)opaque;
+ OpenPICState *opp = (OpenPICState *)opaque;
unsigned int i;
if (version_id != 1)
return -EINVAL;
- qemu_get_be32s(f, &opp->frep);
qemu_get_be32s(f, &opp->glbc);
- qemu_get_be32s(f, &opp->micr);
qemu_get_be32s(f, &opp->veni);
qemu_get_be32s(f, &opp->pint);
qemu_get_be32s(f, &opp->spve);
@@ -1156,15 +1112,13 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
for (i = 0; i < opp->max_irq; i++) {
qemu_get_be32s(f, &opp->src[i].ipvp);
qemu_get_be32s(f, &opp->src[i].ide);
- qemu_get_sbe32s(f, &opp->src[i].type);
qemu_get_sbe32s(f, &opp->src[i].last_cpu);
qemu_get_sbe32s(f, &opp->src[i].pending);
}
- qemu_get_sbe32s(f, &opp->nb_cpus);
+ qemu_get_be32s(f, &opp->nb_cpus);
for (i = 0; i < opp->nb_cpus; i++) {
- qemu_get_be32s(f, &opp->dst[i].tfrr);
qemu_get_be32s(f, &opp->dst[i].pctp);
qemu_get_be32s(f, &opp->dst[i].pcsr);
openpic_load_IRQ_queue(f, &opp->dst[i].raised);
@@ -1176,535 +1130,156 @@ static int openpic_load(QEMUFile* f, void *opaque, int version_id)
qemu_get_be32s(f, &opp->timers[i].tibc);
}
-#if MAX_DBL > 0
- qemu_get_be32s(f, &opp->dar);
-
- for (i = 0; i < MAX_DBL; i++) {
- qemu_get_be32s(f, &opp->doorbells[i].dmr);
- }
-#endif
-
-#if MAX_MBX > 0
- for (i = 0; i < MAX_MAILBOXES; i++) {
- qemu_get_be32s(f, &opp->mailboxes[i].mbr);
- }
-#endif
-
- return pci_device_load(&opp->pci_dev, f);
-}
-
-static void openpic_irq_raise(openpic_t *opp, int n_CPU, IRQ_src_t *src)
-{
- qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
-}
-
-qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
- qemu_irq **irqs, qemu_irq irq_out)
-{
- openpic_t *opp;
- int i, m;
-
- /* XXX: for now, only one CPU is supported */
- if (nb_cpus != 1)
- return NULL;
- opp = g_malloc0(sizeof(openpic_t));
- memory_region_init_io(&opp->mem, &openpic_ops, opp, "openpic", 0x40000);
-
- // isu_base &= 0xFFFC0000;
- opp->nb_cpus = nb_cpus;
- opp->max_irq = OPENPIC_MAX_IRQ;
- opp->irq_ipi0 = OPENPIC_IRQ_IPI0;
- opp->irq_tim0 = OPENPIC_IRQ_TIM0;
- /* Set IRQ types */
- for (i = 0; i < OPENPIC_EXT_IRQ; i++) {
- opp->src[i].type = IRQ_EXTERNAL;
- }
- for (; i < OPENPIC_IRQ_TIM0; i++) {
- opp->src[i].type = IRQ_SPECIAL;
- }
-#if MAX_IPI > 0
- m = OPENPIC_IRQ_IPI0;
-#else
- m = OPENPIC_IRQ_DBL0;
-#endif
- for (; i < m; i++) {
- opp->src[i].type = IRQ_TIMER;
- }
- for (; i < OPENPIC_MAX_IRQ; i++) {
- opp->src[i].type = IRQ_INTERNAL;
- }
- for (i = 0; i < nb_cpus; i++)
- opp->dst[i].irqs = irqs[i];
- opp->irq_out = irq_out;
-
- register_savevm(&opp->pci_dev.qdev, "openpic", 0, 2,
- openpic_save, openpic_load, opp);
- qemu_register_reset(openpic_reset, opp);
-
- opp->irq_raise = openpic_irq_raise;
- opp->reset = openpic_reset;
-
- if (pmem)
- *pmem = &opp->mem;
-
- return qemu_allocate_irqs(openpic_set_irq, opp, opp->max_irq);
-}
-
-static void mpic_irq_raise(openpic_t *mpp, int n_CPU, IRQ_src_t *src)
-{
- int n_ci = IDR_CI0 - n_CPU;
-
- if(test_bit(&src->ide, n_ci)) {
- qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
- }
- else {
- qemu_irq_raise(mpp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
- }
+ return 0;
}
-static void mpic_reset (void *opaque)
+static void openpic_irq_raise(OpenPICState *opp, int n_CPU, IRQ_src_t *src)
{
- openpic_t *mpp = (openpic_t *)opaque;
- int i;
+ int n_ci = IDR_CI0_SHIFT - n_CPU;
- mpp->glbc = 0x80000000;
- /* Initialise controller registers */
- mpp->frep = 0x004f0002 | ((mpp->nb_cpus - 1) << 8);
- mpp->veni = VENI;
- mpp->pint = 0x00000000;
- mpp->spve = 0x0000FFFF;
- /* Initialise IRQ sources */
- for (i = 0; i < mpp->max_irq; i++) {
- mpp->src[i].ipvp = 0x80800000;
- mpp->src[i].ide = 0x00000001;
- }
- /* Set IDE for IPIs to 0 so we don't get spurious interrupts */
- for (i = mpp->irq_ipi0; i < (mpp->irq_ipi0 + MAX_IPI); i++) {
- mpp->src[i].ide = 0;
- }
- /* Initialise IRQ destinations */
- for (i = 0; i < MAX_CPU; i++) {
- mpp->dst[i].pctp = 0x0000000F;
- mpp->dst[i].tfrr = 0x00000000;
- memset(&mpp->dst[i].raised, 0, sizeof(IRQ_queue_t));
- mpp->dst[i].raised.next = -1;
- memset(&mpp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
- mpp->dst[i].servicing.next = -1;
- }
- /* Initialise timers */
- for (i = 0; i < MAX_TMR; i++) {
- mpp->timers[i].ticc = 0x00000000;
- mpp->timers[i].tibc = 0x80000000;
+ if ((opp->flags & OPENPIC_FLAG_IDE_CRIT) && (src->ide & (1 << n_ci))) {
+ qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_CINT]);
+ } else {
+ qemu_irq_raise(opp->dst[n_CPU].irqs[OPENPIC_OUTPUT_INT]);
}
- /* Go out of RESET state */
- mpp->glbc = 0x00000000;
}
-static void mpic_timer_write (void *opaque, hwaddr addr, uint32_t val)
-{
- openpic_t *mpp = opaque;
- int idx, cpu;
-
- DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
- addr &= 0xFFFF;
- cpu = addr >> 12;
- idx = (addr >> 6) & 0x3;
- switch (addr & 0x30) {
- case 0x00: /* gtccr */
- break;
- case 0x10: /* gtbcr */
- if ((mpp->timers[idx].ticc & 0x80000000) != 0 &&
- (val & 0x80000000) == 0 &&
- (mpp->timers[idx].tibc & 0x80000000) != 0)
- mpp->timers[idx].ticc &= ~0x80000000;
- mpp->timers[idx].tibc = val;
- break;
- case 0x20: /* GTIVPR */
- write_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx, val);
- break;
- case 0x30: /* GTIDR & TFRR */
- if ((addr & 0xF0) == 0xF0)
- mpp->dst[cpu].tfrr = val;
- else
- write_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx, val);
- break;
- }
-}
+struct memreg {
+ const char *name;
+ MemoryRegionOps const *ops;
+ bool map;
+ hwaddr start_addr;
+ ram_addr_t size;
+};
-static uint32_t mpic_timer_read (void *opaque, hwaddr addr)
+static int openpic_init(SysBusDevice *dev)
{
- openpic_t *mpp = opaque;
- uint32_t retval;
- int idx, cpu;
+ OpenPICState *opp = FROM_SYSBUS(typeof (*opp), dev);
+ int i, j;
+ struct memreg list_le[] = {
+ {"glb", &openpic_glb_ops_le, true,
+ OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
+ {"tmr", &openpic_tmr_ops_le, true,
+ OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
+ {"msi", &openpic_msi_ops_le, true,
+ OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
+ {"src", &openpic_src_ops_le, true,
+ OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
+ {"cpu", &openpic_cpu_ops_le, true,
+ OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
+ };
+ struct memreg list_be[] = {
+ {"glb", &openpic_glb_ops_be, true,
+ OPENPIC_GLB_REG_START, OPENPIC_GLB_REG_SIZE},
+ {"tmr", &openpic_tmr_ops_be, true,
+ OPENPIC_TMR_REG_START, OPENPIC_TMR_REG_SIZE},
+ {"msi", &openpic_msi_ops_be, true,
+ OPENPIC_MSI_REG_START, OPENPIC_MSI_REG_SIZE},
+ {"src", &openpic_src_ops_be, true,
+ OPENPIC_SRC_REG_START, OPENPIC_SRC_REG_SIZE},
+ {"cpu", &openpic_cpu_ops_be, true,
+ OPENPIC_CPU_REG_START, OPENPIC_CPU_REG_SIZE},
+ };
+ struct memreg *list;
- DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
- addr &= 0xFFFF;
- cpu = addr >> 12;
- idx = (addr >> 6) & 0x3;
- switch (addr & 0x30) {
- case 0x00: /* gtccr */
- retval = mpp->timers[idx].ticc;
- break;
- case 0x10: /* gtbcr */
- retval = mpp->timers[idx].tibc;
- break;
- case 0x20: /* TIPV */
- retval = read_IRQreg_ipvp(mpp, MPIC_TMR_IRQ + idx);
- break;
- case 0x30: /* TIDR */
- if ((addr &0xF0) == 0XF0)
- retval = mpp->dst[cpu].tfrr;
- else
- retval = read_IRQreg_ide(mpp, MPIC_TMR_IRQ + idx);
+ switch (opp->model) {
+ case OPENPIC_MODEL_FSL_MPIC_20:
+ default:
+ opp->flags |= OPENPIC_FLAG_IDE_CRIT;
+ opp->nb_irqs = 80;
+ opp->vid = VID_REVISION_1_2;
+ opp->veni = VENI_GENERIC;
+ opp->spve_mask = 0xFFFF;
+ opp->tifr_reset = 0x00000000;
+ opp->ipvp_reset = 0x80000000;
+ opp->ide_reset = 0x00000001;
+ opp->max_irq = FSL_MPIC_20_MAX_IRQ;
+ opp->irq_ipi0 = FSL_MPIC_20_IPI_IRQ;
+ opp->irq_tim0 = FSL_MPIC_20_TMR_IRQ;
+ opp->irq_msi = FSL_MPIC_20_MSI_IRQ;
+ opp->brr1 = FSL_BRR1_IPID | FSL_BRR1_IPMJ | FSL_BRR1_IPMN;
+ msi_supported = true;
+ list = list_be;
break;
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
-
- return retval;
-}
-
-static void mpic_src_ext_write (void *opaque, hwaddr addr,
- uint32_t val)
-{
- openpic_t *mpp = opaque;
- int idx = MPIC_EXT_IRQ;
-
- DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-
- if (addr < MPIC_EXT_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- write_IRQreg_ide(mpp, idx, val);
- } else {
- /* EXVP / IFEVP / IEEVP */
- write_IRQreg_ipvp(mpp, idx, val);
+ case OPENPIC_MODEL_RAVEN:
+ opp->nb_irqs = RAVEN_MAX_EXT;
+ opp->vid = VID_REVISION_1_3;
+ opp->veni = VENI_GENERIC;
+ opp->spve_mask = 0xFF;
+ opp->tifr_reset = 0x003F7A00;
+ opp->ipvp_reset = 0xA0000000;
+ opp->ide_reset = 0x00000000;
+ opp->max_irq = RAVEN_MAX_IRQ;
+ opp->irq_ipi0 = RAVEN_IPI_IRQ;
+ opp->irq_tim0 = RAVEN_TMR_IRQ;
+ opp->brr1 = -1;
+ list = list_le;
+ /* Don't map MSI region */
+ list[2].map = false;
+
+ /* Only UP supported today */
+ if (opp->nb_cpus != 1) {
+ return -EINVAL;
}
+ break;
}
-}
-static uint32_t mpic_src_ext_read (void *opaque, hwaddr addr)
-{
- openpic_t *mpp = opaque;
- uint32_t retval;
- int idx = MPIC_EXT_IRQ;
+ memory_region_init(&opp->mem, "openpic", 0x40000);
- DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
-
- if (addr < MPIC_EXT_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- retval = read_IRQreg_ide(mpp, idx);
- } else {
- /* EXVP / IFEVP / IEEVP */
- retval = read_IRQreg_ipvp(mpp, idx);
+ for (i = 0; i < ARRAY_SIZE(list_le); i++) {
+ if (!list[i].map) {
+ continue;
}
- DPRINTF("%s: => %08x\n", __func__, retval);
- }
-
- return retval;
-}
-
-static void mpic_src_int_write (void *opaque, hwaddr addr,
- uint32_t val)
-{
- openpic_t *mpp = opaque;
- int idx = MPIC_INT_IRQ;
- DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-
- if (addr < MPIC_INT_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- write_IRQreg_ide(mpp, idx, val);
- } else {
- /* EXVP / IFEVP / IEEVP */
- write_IRQreg_ipvp(mpp, idx, val);
- }
- }
-}
-
-static uint32_t mpic_src_int_read (void *opaque, hwaddr addr)
-{
- openpic_t *mpp = opaque;
- uint32_t retval;
- int idx = MPIC_INT_IRQ;
-
- DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
+ memory_region_init_io(&opp->sub_io_mem[i], list[i].ops, opp,
+ list[i].name, list[i].size);
- if (addr < MPIC_INT_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- retval = read_IRQreg_ide(mpp, idx);
- } else {
- /* EXVP / IFEVP / IEEVP */
- retval = read_IRQreg_ipvp(mpp, idx);
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
+ memory_region_add_subregion(&opp->mem, list[i].start_addr,
+ &opp->sub_io_mem[i]);
}
- return retval;
-}
-
-static void mpic_src_msg_write (void *opaque, hwaddr addr,
- uint32_t val)
-{
- openpic_t *mpp = opaque;
- int idx = MPIC_MSG_IRQ;
-
- DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
-
- if (addr < MPIC_MSG_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- write_IRQreg_ide(mpp, idx, val);
- } else {
- /* EXVP / IFEVP / IEEVP */
- write_IRQreg_ipvp(mpp, idx, val);
+ for (i = 0; i < opp->nb_cpus; i++) {
+ opp->dst[i].irqs = g_new(qemu_irq, OPENPIC_OUTPUT_NB);
+ for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+ sysbus_init_irq(dev, &opp->dst[i].irqs[j]);
}
}
-}
-static uint32_t mpic_src_msg_read (void *opaque, hwaddr addr)
-{
- openpic_t *mpp = opaque;
- uint32_t retval;
- int idx = MPIC_MSG_IRQ;
-
- DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
+ register_savevm(&opp->busdev.qdev, "openpic", 0, 2,
+ openpic_save, openpic_load, opp);
- if (addr < MPIC_MSG_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- retval = read_IRQreg_ide(mpp, idx);
- } else {
- /* EXVP / IFEVP / IEEVP */
- retval = read_IRQreg_ipvp(mpp, idx);
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
- }
+ sysbus_init_mmio(dev, &opp->mem);
+ qdev_init_gpio_in(&dev->qdev, openpic_set_irq, opp->max_irq);
- return retval;
+ return 0;
}
-static void mpic_src_msi_write (void *opaque, hwaddr addr,
- uint32_t val)
-{
- openpic_t *mpp = opaque;
- int idx = MPIC_MSI_IRQ;
-
- DPRINTF("%s: addr " TARGET_FMT_plx " <= %08x\n", __func__, addr, val);
- if (addr & 0xF)
- return;
+static Property openpic_properties[] = {
+ DEFINE_PROP_UINT32("model", OpenPICState, model, OPENPIC_MODEL_FSL_MPIC_20),
+ DEFINE_PROP_UINT32("nb_cpus", OpenPICState, nb_cpus, 1),
+ DEFINE_PROP_END_OF_LIST(),
+};
- if (addr < MPIC_MSI_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- write_IRQreg_ide(mpp, idx, val);
- } else {
- /* EXVP / IFEVP / IEEVP */
- write_IRQreg_ipvp(mpp, idx, val);
- }
- }
-}
-static uint32_t mpic_src_msi_read (void *opaque, hwaddr addr)
+static void openpic_class_init(ObjectClass *klass, void *data)
{
- openpic_t *mpp = opaque;
- uint32_t retval;
- int idx = MPIC_MSI_IRQ;
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
- DPRINTF("%s: addr " TARGET_FMT_plx "\n", __func__, addr);
- retval = 0xFFFFFFFF;
- if (addr & 0xF)
- return retval;
-
- if (addr < MPIC_MSI_REG_SIZE) {
- idx += (addr & 0xFFF0) >> 5;
- if (addr & 0x10) {
- /* EXDE / IFEDE / IEEDE */
- retval = read_IRQreg_ide(mpp, idx);
- } else {
- /* EXVP / IFEVP / IEEVP */
- retval = read_IRQreg_ipvp(mpp, idx);
- }
- DPRINTF("%s: => %08x\n", __func__, retval);
- }
-
- return retval;
+ k->init = openpic_init;
+ dc->props = openpic_properties;
+ dc->reset = openpic_reset;
}
-static const MemoryRegionOps mpic_glb_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- openpic_gbl_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- openpic_gbl_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
+static TypeInfo openpic_info = {
+ .name = "openpic",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(OpenPICState),
+ .class_init = openpic_class_init,
};
-static const MemoryRegionOps mpic_tmr_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- mpic_timer_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- mpic_timer_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const MemoryRegionOps mpic_cpu_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- openpic_cpu_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- openpic_cpu_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const MemoryRegionOps mpic_ext_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- mpic_src_ext_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- mpic_src_ext_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const MemoryRegionOps mpic_int_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- mpic_src_int_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- mpic_src_int_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const MemoryRegionOps mpic_msg_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- mpic_src_msg_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- mpic_src_msg_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-static const MemoryRegionOps mpic_msi_ops = {
- .old_mmio = {
- .write = { openpic_buggy_write,
- openpic_buggy_write,
- mpic_src_msi_write,
- },
- .read = { openpic_buggy_read,
- openpic_buggy_read,
- mpic_src_msi_read,
- },
- },
- .endianness = DEVICE_BIG_ENDIAN,
-};
-
-qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
- int nb_cpus, qemu_irq **irqs, qemu_irq irq_out)
+static void openpic_register_types(void)
{
- openpic_t *mpp;
- int i;
- struct {
- const char *name;
- MemoryRegionOps const *ops;
- hwaddr start_addr;
- ram_addr_t size;
- } const list[] = {
- {"glb", &mpic_glb_ops, MPIC_GLB_REG_START, MPIC_GLB_REG_SIZE},
- {"tmr", &mpic_tmr_ops, MPIC_TMR_REG_START, MPIC_TMR_REG_SIZE},
- {"ext", &mpic_ext_ops, MPIC_EXT_REG_START, MPIC_EXT_REG_SIZE},
- {"int", &mpic_int_ops, MPIC_INT_REG_START, MPIC_INT_REG_SIZE},
- {"msg", &mpic_msg_ops, MPIC_MSG_REG_START, MPIC_MSG_REG_SIZE},
- {"msi", &mpic_msi_ops, MPIC_MSI_REG_START, MPIC_MSI_REG_SIZE},
- {"cpu", &mpic_cpu_ops, MPIC_CPU_REG_START, MPIC_CPU_REG_SIZE},
- };
-
- mpp = g_malloc0(sizeof(openpic_t));
-
- memory_region_init(&mpp->mem, "mpic", 0x40000);
- memory_region_add_subregion(address_space, base, &mpp->mem);
-
- for (i = 0; i < sizeof(list)/sizeof(list[0]); i++) {
-
- memory_region_init_io(&mpp->sub_io_mem[i], list[i].ops, mpp,
- list[i].name, list[i].size);
-
- memory_region_add_subregion(&mpp->mem, list[i].start_addr,
- &mpp->sub_io_mem[i]);
- }
-
- mpp->nb_cpus = nb_cpus;
- mpp->max_irq = MPIC_MAX_IRQ;
- mpp->irq_ipi0 = MPIC_IPI_IRQ;
- mpp->irq_tim0 = MPIC_TMR_IRQ;
-
- for (i = 0; i < nb_cpus; i++)
- mpp->dst[i].irqs = irqs[i];
- mpp->irq_out = irq_out;
-
- mpp->irq_raise = mpic_irq_raise;
- mpp->reset = mpic_reset;
-
- register_savevm(NULL, "mpic", 0, 2, openpic_save, openpic_load, mpp);
- qemu_register_reset(mpic_reset, mpp);
-
- return qemu_allocate_irqs(openpic_set_irq, mpp, mpp->max_irq);
+ type_register_static(&openpic_info);
}
+
+type_init(openpic_register_types)
diff --git a/hw/openpic.h b/hw/openpic.h
index f50a1e42bd..e226d7b563 100644
--- a/hw/openpic.h
+++ b/hw/openpic.h
@@ -11,8 +11,7 @@ enum {
OPENPIC_OUTPUT_NB,
};
-qemu_irq *openpic_init (MemoryRegion **pmem, int nb_cpus,
- qemu_irq **irqs, qemu_irq irq_out);
-qemu_irq *mpic_init (MemoryRegion *address_space, hwaddr base,
- int nb_cpus, qemu_irq **irqs, qemu_irq irq_out);
+#define OPENPIC_MODEL_RAVEN 0
+#define OPENPIC_MODEL_FSL_MPIC_20 1
+
#endif /* __OPENPIC_H__ */
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index 40bced2322..d7ea3a5595 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -98,7 +98,7 @@ static void pc_fw_add_pflash_drv(void)
return;
}
- if (!drive_init(opts, machine->use_scsi)) {
+ if (!drive_init(opts, machine->block_default_type)) {
qemu_opts_del(opts);
}
}
diff --git a/hw/pci/Makefile.objs b/hw/pci/Makefile.objs
index aa7a0e84b5..fe965fe2f6 100644
--- a/hw/pci/Makefile.objs
+++ b/hw/pci/Makefile.objs
@@ -5,3 +5,5 @@ common-obj-$(CONFIG_PCI) += slotid_cap.o
common-obj-$(CONFIG_PCI) += pci_host.o pcie_host.o
common-obj-$(CONFIG_PCI) += pcie.o pcie_aer.o pcie_port.o
common-obj-$(CONFIG_NO_PCI) += pci-stub.o
+
+extra-obj-y += pci-stub.o
diff --git a/hw/pci/msix.c b/hw/pci/msix.c
index 917327bfe6..a6a401e286 100644
--- a/hw/pci/msix.c
+++ b/hw/pci/msix.c
@@ -180,8 +180,7 @@ static void msix_table_mmio_write(void *opaque, hwaddr addr,
static const MemoryRegionOps msix_table_mmio_ops = {
.read = msix_table_mmio_read,
.write = msix_table_mmio_write,
- /* TODO: MSIX should be LITTLE_ENDIAN. */
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
@@ -198,8 +197,7 @@ static uint64_t msix_pba_mmio_read(void *opaque, hwaddr addr,
static const MemoryRegionOps msix_pba_mmio_ops = {
.read = msix_pba_mmio_read,
- /* TODO: MSIX should be LITTLE_ENDIAN. */
- .endianness = DEVICE_NATIVE_ENDIAN,
+ .endianness = DEVICE_LITTLE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4,
diff --git a/hw/ppc/Makefile.objs b/hw/ppc/Makefile.objs
index cb7cf8fba5..afdcc0e531 100644
--- a/hw/ppc/Makefile.objs
+++ b/hw/ppc/Makefile.objs
@@ -11,7 +11,7 @@ obj-y += ppc_newworld.o
obj-$(CONFIG_PSERIES) += spapr.o spapr_hcall.o spapr_rtas.o spapr_vio.o
obj-$(CONFIG_PSERIES) += xics.o spapr_vty.o spapr_llan.o spapr_vscsi.o
obj-$(CONFIG_PSERIES) += spapr_pci.o pci/pci-hotplug.o spapr_iommu.o
-obj-$(CONFIG_PSERIES) += spapr_events.o
+obj-$(CONFIG_PSERIES) += spapr_events.o spapr_nvram.o
# PowerPC 4xx boards
obj-y += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-y += ppc440_bamboo.o
diff --git a/hw/ppc/e500-ccsr.h b/hw/ppc/e500-ccsr.h
new file mode 100644
index 0000000000..f20f51bcd2
--- /dev/null
+++ b/hw/ppc/e500-ccsr.h
@@ -0,0 +1,17 @@
+#ifndef E500_CCSR_H
+#define E500_CCSR_H
+
+#include "../sysbus.h"
+
+typedef struct PPCE500CCSRState {
+ /*< private >*/
+ SysBusDevice parent;
+ /*< public >*/
+
+ MemoryRegion ccsr_space;
+} PPCE500CCSRState;
+
+#define TYPE_CCSR "e500-ccsr"
+#define CCSR(obj) OBJECT_CHECK(PPCE500CCSRState, (obj), TYPE_CCSR)
+
+#endif /* E500_CCSR_H */
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index f77c488af7..8fab508c07 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -17,6 +17,7 @@
#include "config.h"
#include "qemu-common.h"
#include "e500.h"
+#include "e500-ccsr.h"
#include "net.h"
#include "hw/hw.h"
#include "hw/serial.h"
@@ -33,6 +34,7 @@
#include "hw/sysbus.h"
#include "exec-memory.h"
#include "host-utils.h"
+#include "hw/ppce500_pci.h"
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define UIMAGE_LOAD_BASE 0
@@ -46,13 +48,16 @@
/* TODO: parameterize */
#define MPC8544_CCSRBAR_BASE 0xE0000000ULL
#define MPC8544_CCSRBAR_SIZE 0x00100000ULL
-#define MPC8544_MPIC_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x40000ULL)
-#define MPC8544_SERIAL0_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4500ULL)
-#define MPC8544_SERIAL1_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x4600ULL)
-#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + 0x8000ULL)
+#define MPC8544_MPIC_REGS_OFFSET 0x40000ULL
+#define MPC8544_MSI_REGS_OFFSET 0x41600ULL
+#define MPC8544_SERIAL0_REGS_OFFSET 0x4500ULL
+#define MPC8544_SERIAL1_REGS_OFFSET 0x4600ULL
+#define MPC8544_PCI_REGS_OFFSET 0x8000ULL
+#define MPC8544_PCI_REGS_BASE (MPC8544_CCSRBAR_BASE + \
+ MPC8544_PCI_REGS_OFFSET)
#define MPC8544_PCI_REGS_SIZE 0x1000ULL
#define MPC8544_PCI_IO 0xE1000000ULL
-#define MPC8544_UTIL_BASE (MPC8544_CCSRBAR_BASE + 0xe0000ULL)
+#define MPC8544_UTIL_OFFSET 0xe0000ULL
#define MPC8544_SPIN_BASE 0xEF000000ULL
struct boot_info
@@ -62,25 +67,35 @@ struct boot_info
uint32_t entry;
};
-static void pci_map_create(void *fdt, uint32_t *pci_map, uint32_t mpic)
+static uint32_t *pci_map_create(void *fdt, uint32_t mpic, int first_slot,
+ int nr_slots, int *len)
{
- int i;
- const uint32_t tmp[] = {
- /* IDSEL 0x11 J17 Slot 1 */
- 0x8800, 0x0, 0x0, 0x1, mpic, 0x2, 0x1,
- 0x8800, 0x0, 0x0, 0x2, mpic, 0x3, 0x1,
- 0x8800, 0x0, 0x0, 0x3, mpic, 0x4, 0x1,
- 0x8800, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
-
- /* IDSEL 0x12 J16 Slot 2 */
- 0x9000, 0x0, 0x0, 0x1, mpic, 0x3, 0x1,
- 0x9000, 0x0, 0x0, 0x2, mpic, 0x4, 0x1,
- 0x9000, 0x0, 0x0, 0x3, mpic, 0x2, 0x1,
- 0x9000, 0x0, 0x0, 0x4, mpic, 0x1, 0x1,
- };
- for (i = 0; i < (7 * 8); i++) {
- pci_map[i] = cpu_to_be32(tmp[i]);
+ int i = 0;
+ int slot;
+ int pci_irq;
+ int host_irq;
+ int last_slot = first_slot + nr_slots;
+ uint32_t *pci_map;
+
+ *len = nr_slots * 4 * 7 * sizeof(uint32_t);
+ pci_map = g_malloc(*len);
+
+ for (slot = first_slot; slot < last_slot; slot++) {
+ for (pci_irq = 0; pci_irq < 4; pci_irq++) {
+ pci_map[i++] = cpu_to_be32(slot << 11);
+ pci_map[i++] = cpu_to_be32(0x0);
+ pci_map[i++] = cpu_to_be32(0x0);
+ pci_map[i++] = cpu_to_be32(pci_irq + 1);
+ pci_map[i++] = cpu_to_be32(mpic);
+ host_irq = ppce500_pci_map_irq_slot(slot, pci_irq);
+ pci_map[i++] = cpu_to_be32(host_irq + 1);
+ pci_map[i++] = cpu_to_be32(0x1);
+ }
}
+
+ assert((i * sizeof(uint32_t)) == *len);
+
+ return pci_map;
}
static void dt_serial_create(void *fdt, unsigned long long offset,
@@ -124,9 +139,12 @@ static int ppce500_load_device_tree(CPUPPCState *env,
char soc[128];
char mpic[128];
uint32_t mpic_ph;
+ uint32_t msi_ph;
char gutil[128];
char pci[128];
- uint32_t pci_map[7 * 8];
+ char msi[128];
+ uint32_t *pci_map = NULL;
+ int len;
uint32_t pci_ranges[14] =
{
0x2000000, 0x0, 0xc0000000,
@@ -267,13 +285,12 @@ static int ppce500_load_device_tree(CPUPPCState *env,
/* XXX should contain a reasonable value */
qemu_devtree_setprop_cell(fdt, soc, "bus-frequency", 0);
- snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc,
- MPC8544_MPIC_REGS_BASE - MPC8544_CCSRBAR_BASE);
+ snprintf(mpic, sizeof(mpic), "%s/pic@%llx", soc, MPC8544_MPIC_REGS_OFFSET);
qemu_devtree_add_subnode(fdt, mpic);
qemu_devtree_setprop_string(fdt, mpic, "device_type", "open-pic");
qemu_devtree_setprop_string(fdt, mpic, "compatible", "chrp,open-pic");
- qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_BASE -
- MPC8544_CCSRBAR_BASE, 0x40000);
+ qemu_devtree_setprop_cells(fdt, mpic, "reg", MPC8544_MPIC_REGS_OFFSET,
+ 0x40000);
qemu_devtree_setprop_cell(fdt, mpic, "#address-cells", 0);
qemu_devtree_setprop_cell(fdt, mpic, "#interrupt-cells", 2);
mpic_ph = qemu_devtree_alloc_phandle(fdt);
@@ -286,19 +303,37 @@ static int ppce500_load_device_tree(CPUPPCState *env,
* device it finds in the dt as serial output device. And we generate
* devices in reverse order to the dt.
*/
- dt_serial_create(fdt, MPC8544_SERIAL1_REGS_BASE - MPC8544_CCSRBAR_BASE,
+ dt_serial_create(fdt, MPC8544_SERIAL1_REGS_OFFSET,
soc, mpic, "serial1", 1, false);
- dt_serial_create(fdt, MPC8544_SERIAL0_REGS_BASE - MPC8544_CCSRBAR_BASE,
+ dt_serial_create(fdt, MPC8544_SERIAL0_REGS_OFFSET,
soc, mpic, "serial0", 0, true);
snprintf(gutil, sizeof(gutil), "%s/global-utilities@%llx", soc,
- MPC8544_UTIL_BASE - MPC8544_CCSRBAR_BASE);
+ MPC8544_UTIL_OFFSET);
qemu_devtree_add_subnode(fdt, gutil);
qemu_devtree_setprop_string(fdt, gutil, "compatible", "fsl,mpc8544-guts");
- qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_BASE -
- MPC8544_CCSRBAR_BASE, 0x1000);
+ qemu_devtree_setprop_cells(fdt, gutil, "reg", MPC8544_UTIL_OFFSET, 0x1000);
qemu_devtree_setprop(fdt, gutil, "fsl,has-rstcr", NULL, 0);
+ snprintf(msi, sizeof(msi), "/%s/msi@%llx", soc, MPC8544_MSI_REGS_OFFSET);
+ qemu_devtree_add_subnode(fdt, msi);
+ qemu_devtree_setprop_string(fdt, msi, "compatible", "fsl,mpic-msi");
+ qemu_devtree_setprop_cells(fdt, msi, "reg", MPC8544_MSI_REGS_OFFSET, 0x200);
+ msi_ph = qemu_devtree_alloc_phandle(fdt);
+ qemu_devtree_setprop_cells(fdt, msi, "msi-available-ranges", 0x0, 0x100);
+ qemu_devtree_setprop_phandle(fdt, msi, "interrupt-parent", mpic);
+ qemu_devtree_setprop_cells(fdt, msi, "interrupts",
+ 0xe0, 0x0,
+ 0xe1, 0x0,
+ 0xe2, 0x0,
+ 0xe3, 0x0,
+ 0xe4, 0x0,
+ 0xe5, 0x0,
+ 0xe6, 0x0,
+ 0xe7, 0x0);
+ qemu_devtree_setprop_cell(fdt, msi, "phandle", msi_ph);
+ qemu_devtree_setprop_cell(fdt, msi, "linux,phandle", msi_ph);
+
snprintf(pci, sizeof(pci), "/pci@%llx", MPC8544_PCI_REGS_BASE);
qemu_devtree_add_subnode(fdt, pci);
qemu_devtree_setprop_cell(fdt, pci, "cell-index", 0);
@@ -306,14 +341,17 @@ static int ppce500_load_device_tree(CPUPPCState *env,
qemu_devtree_setprop_string(fdt, pci, "device_type", "pci");
qemu_devtree_setprop_cells(fdt, pci, "interrupt-map-mask", 0xf800, 0x0,
0x0, 0x7);
- pci_map_create(fdt, pci_map, qemu_devtree_get_phandle(fdt, mpic));
- qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, sizeof(pci_map));
+ pci_map = pci_map_create(fdt, qemu_devtree_get_phandle(fdt, mpic),
+ params->pci_first_slot, params->pci_nr_slots,
+ &len);
+ qemu_devtree_setprop(fdt, pci, "interrupt-map", pci_map, len);
qemu_devtree_setprop_phandle(fdt, pci, "interrupt-parent", mpic);
qemu_devtree_setprop_cells(fdt, pci, "interrupts", 24, 2);
qemu_devtree_setprop_cells(fdt, pci, "bus-range", 0, 255);
for (i = 0; i < 14; i++) {
pci_ranges[i] = cpu_to_be32(pci_ranges[i]);
}
+ qemu_devtree_setprop_cell(fdt, pci, "fsl,msi", msi_ph);
qemu_devtree_setprop(fdt, pci, "ranges", pci_ranges, sizeof(pci_ranges));
qemu_devtree_setprop_cells(fdt, pci, "reg", MPC8544_PCI_REGS_BASE >> 32,
MPC8544_PCI_REGS_BASE, 0, 0x1000);
@@ -340,6 +378,7 @@ done:
ret = fdt_size;
out:
+ g_free(pci_map);
return ret;
}
@@ -417,11 +456,14 @@ void ppce500_init(PPCE500Params *params)
target_ulong dt_base = 0;
target_ulong initrd_base = 0;
target_long initrd_size=0;
- int i=0;
+ int i = 0, j, k;
unsigned int pci_irq_nrs[4] = {1, 2, 3, 4};
qemu_irq **irqs, *mpic;
DeviceState *dev;
CPUPPCState *firstenv = NULL;
+ MemoryRegion *ccsr_addr_space;
+ SysBusDevice *s;
+ PPCE500CCSRState *ccsr;
/* Setup CPUs */
if (params->cpu_model == NULL) {
@@ -450,7 +492,8 @@ void ppce500_init(PPCE500Params *params)
irqs[i][OPENPIC_OUTPUT_INT] = input[PPCE500_INPUT_INT];
irqs[i][OPENPIC_OUTPUT_CINT] = input[PPCE500_INPUT_CINT];
env->spr[SPR_BOOKE_PIR] = env->cpu_index = i;
- env->mpic_cpu_base = MPC8544_MPIC_REGS_BASE + 0x20000;
+ env->mpic_cpu_base = MPC8544_CCSRBAR_BASE +
+ MPC8544_MPIC_REGS_OFFSET + 0x20000;
ppc_booke_timers_init(env, 400000000, PPC_TIMER_E500);
@@ -477,35 +520,69 @@ void ppce500_init(PPCE500Params *params)
vmstate_register_ram_global(ram);
memory_region_add_subregion(address_space_mem, 0, ram);
+ dev = qdev_create(NULL, "e500-ccsr");
+ object_property_add_child(qdev_get_machine(), "e500-ccsr",
+ OBJECT(dev), NULL);
+ qdev_init_nofail(dev);
+ ccsr = CCSR(dev);
+ ccsr_addr_space = &ccsr->ccsr_space;
+ memory_region_add_subregion(address_space_mem, MPC8544_CCSRBAR_BASE,
+ ccsr_addr_space);
+
/* MPIC */
- mpic = mpic_init(address_space_mem, MPC8544_MPIC_REGS_BASE,
- smp_cpus, irqs, NULL);
+ mpic = g_new(qemu_irq, 256);
+ dev = qdev_create(NULL, "openpic");
+ qdev_prop_set_uint32(dev, "nb_cpus", smp_cpus);
+ qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_FSL_MPIC_20);
+ qdev_init_nofail(dev);
+ s = sysbus_from_qdev(dev);
+
+ k = 0;
+ for (i = 0; i < smp_cpus; i++) {
+ for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+ sysbus_connect_irq(s, k++, irqs[i][j]);
+ }
+ }
- if (!mpic) {
- cpu_abort(env, "MPIC failed to initialize\n");
+ for (i = 0; i < 256; i++) {
+ mpic[i] = qdev_get_gpio_in(dev, i);
}
+ memory_region_add_subregion(ccsr_addr_space, MPC8544_MPIC_REGS_OFFSET,
+ s->mmio[0].memory);
+
/* Serial */
if (serial_hds[0]) {
- serial_mm_init(address_space_mem, MPC8544_SERIAL0_REGS_BASE,
- 0, mpic[12+26], 399193,
+ serial_mm_init(ccsr_addr_space, MPC8544_SERIAL0_REGS_OFFSET,
+ 0, mpic[42], 399193,
serial_hds[0], DEVICE_BIG_ENDIAN);
}
if (serial_hds[1]) {
- serial_mm_init(address_space_mem, MPC8544_SERIAL1_REGS_BASE,
- 0, mpic[12+26], 399193,
+ serial_mm_init(ccsr_addr_space, MPC8544_SERIAL1_REGS_OFFSET,
+ 0, mpic[42], 399193,
serial_hds[1], DEVICE_BIG_ENDIAN);
}
/* General Utility device */
- sysbus_create_simple("mpc8544-guts", MPC8544_UTIL_BASE, NULL);
+ dev = qdev_create(NULL, "mpc8544-guts");
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ memory_region_add_subregion(ccsr_addr_space, MPC8544_UTIL_OFFSET,
+ sysbus_mmio_get_region(s, 0));
/* PCI */
- dev = sysbus_create_varargs("e500-pcihost", MPC8544_PCI_REGS_BASE,
- mpic[pci_irq_nrs[0]], mpic[pci_irq_nrs[1]],
- mpic[pci_irq_nrs[2]], mpic[pci_irq_nrs[3]],
- NULL);
+ dev = qdev_create(NULL, "e500-pcihost");
+ qdev_prop_set_uint32(dev, "first_slot", params->pci_first_slot);
+ qdev_init_nofail(dev);
+ s = SYS_BUS_DEVICE(dev);
+ sysbus_connect_irq(s, 0, mpic[pci_irq_nrs[0]]);
+ sysbus_connect_irq(s, 1, mpic[pci_irq_nrs[1]]);
+ sysbus_connect_irq(s, 2, mpic[pci_irq_nrs[2]]);
+ sysbus_connect_irq(s, 3, mpic[pci_irq_nrs[3]]);
+ memory_region_add_subregion(ccsr_addr_space, MPC8544_PCI_REGS_OFFSET,
+ sysbus_mmio_get_region(s, 0));
+
pci_bus = (PCIBus *)qdev_get_child_bus(dev, "pci.0");
if (!pci_bus)
printf("couldn't create PCI controller!\n");
@@ -578,3 +655,33 @@ void ppce500_init(PPCE500Params *params)
kvmppc_init();
}
}
+
+static int e500_ccsr_initfn(SysBusDevice *dev)
+{
+ PPCE500CCSRState *ccsr;
+
+ ccsr = CCSR(dev);
+ memory_region_init(&ccsr->ccsr_space, "e500-ccsr",
+ MPC8544_CCSRBAR_SIZE);
+ return 0;
+}
+
+static void e500_ccsr_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
+ k->init = e500_ccsr_initfn;
+}
+
+static const TypeInfo e500_ccsr_info = {
+ .name = TYPE_CCSR,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(PPCE500CCSRState),
+ .class_init = e500_ccsr_class_init,
+};
+
+static void e500_register_types(void)
+{
+ type_register_static(&e500_ccsr_info);
+}
+
+type_init(e500_register_types)
diff --git a/hw/ppc/e500.h b/hw/ppc/e500.h
index 7ae87f4e21..f5ff27385b 100644
--- a/hw/ppc/e500.h
+++ b/hw/ppc/e500.h
@@ -9,6 +9,8 @@ typedef struct PPCE500Params {
const char *kernel_cmdline;
const char *initrd_filename;
const char *cpu_model;
+ int pci_first_slot;
+ int pci_nr_slots;
/* e500-specific params */
diff --git a/hw/ppc/e500plat.c b/hw/ppc/e500plat.c
index 4cfb94061a..2992bd9794 100644
--- a/hw/ppc/e500plat.c
+++ b/hw/ppc/e500plat.c
@@ -14,6 +14,7 @@
#include "e500.h"
#include "../boards.h"
#include "device_tree.h"
+#include "hw/pci.h"
static void e500plat_fixup_devtree(PPCE500Params *params, void *fdt)
{
@@ -40,6 +41,8 @@ static void e500plat_init(QEMUMachineInitArgs *args)
.kernel_cmdline = kernel_cmdline,
.initrd_filename = initrd_filename,
.cpu_model = cpu_model,
+ .pci_first_slot = 0x1,
+ .pci_nr_slots = PCI_SLOT_MAX - 1,
.fixup_devtree = e500plat_fixup_devtree,
};
diff --git a/hw/ppc/mpc8544ds.c b/hw/ppc/mpc8544ds.c
index e651661941..7e1761d20c 100644
--- a/hw/ppc/mpc8544ds.c
+++ b/hw/ppc/mpc8544ds.c
@@ -40,6 +40,8 @@ static void mpc8544ds_init(QEMUMachineInitArgs *args)
.kernel_cmdline = kernel_cmdline,
.initrd_filename = initrd_filename,
.cpu_model = cpu_model,
+ .pci_first_slot = 0x11,
+ .pci_nr_slots = 2,
.fixup_devtree = mpc8544ds_fixup_devtree,
};
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index c1ff9d7c31..2bf3094e9f 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -67,6 +67,7 @@
#include "hw/usb.h"
#include "blockdev.h"
#include "exec-memory.h"
+#include "sysbus.h"
#define MAX_IDE_BUS 2
#define CFG_ADDR 0xf0000510
@@ -141,7 +142,7 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
char *filename;
qemu_irq *pic, **openpic_irqs;
MemoryRegion *unin_memory = g_new(MemoryRegion, 1);
- int linux_boot, i;
+ int linux_boot, i, j, k;
MemoryRegion *ram = g_new(MemoryRegion, 1), *bios = g_new(MemoryRegion, 1);
hwaddr kernel_base, initrd_base, cmdline_base = 0;
long kernel_size, initrd_size;
@@ -156,6 +157,8 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
void *fw_cfg;
void *dbdma;
int machine_arch;
+ SysBusDevice *s;
+ DeviceState *dev;
linux_boot = (kernel_filename != NULL);
@@ -320,7 +323,25 @@ static void ppc_core99_init(QEMUMachineInitArgs *args)
exit(1);
}
}
- pic = openpic_init(&pic_mem, smp_cpus, openpic_irqs, NULL);
+
+ pic = g_new(qemu_irq, 64);
+
+ dev = qdev_create(NULL, "openpic");
+ qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_RAVEN);
+ qdev_init_nofail(dev);
+ s = sysbus_from_qdev(dev);
+ pic_mem = s->mmio[0].memory;
+ k = 0;
+ for (i = 0; i < smp_cpus; i++) {
+ for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
+ sysbus_connect_irq(s, k++, openpic_irqs[i][j]);
+ }
+ }
+
+ for (i = 0; i < 64; i++) {
+ pic[i] = qdev_get_gpio_in(dev, i);
+ }
+
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
/* 970 gets a U3 bus */
pci_bus = pci_pmac_u3_init(pic, get_system_memory(), get_system_io());
diff --git a/hw/ppce500_pci.c b/hw/ppce500_pci.c
index 39022aada0..9bffbb9f87 100644
--- a/hw/ppce500_pci.c
+++ b/hw/ppce500_pci.c
@@ -15,9 +15,11 @@
*/
#include "hw.h"
+#include "hw/ppc/e500-ccsr.h"
#include "pci/pci.h"
#include "pci/pci_host.h"
#include "bswap.h"
+#include "ppce500_pci.h"
#ifdef DEBUG_PCI
#define pci_debug(fmt, ...) fprintf(stderr, fmt, ## __VA_ARGS__)
@@ -86,12 +88,26 @@ struct PPCE500PCIState {
struct pci_inbound pib[PPCE500_PCI_NR_PIBS];
uint32_t gasket_time;
qemu_irq irq[4];
+ uint32_t first_slot;
/* mmio maps */
MemoryRegion container;
MemoryRegion iomem;
MemoryRegion pio;
};
+#define TYPE_PPC_E500_PCI_BRIDGE "e500-host-bridge"
+#define PPC_E500_PCI_BRIDGE(obj) \
+ OBJECT_CHECK(PPCE500PCIBridgeState, (obj), TYPE_PPC_E500_PCI_BRIDGE)
+
+struct PPCE500PCIBridgeState {
+ /*< private >*/
+ PCIDevice parent;
+ /*< public >*/
+
+ MemoryRegion bar0;
+};
+
+typedef struct PPCE500PCIBridgeState PPCE500PCIBridgeState;
typedef struct PPCE500PCIState PPCE500PCIState;
static uint64_t pci_reg_read4(void *opaque, hwaddr addr,
@@ -238,17 +254,10 @@ static const MemoryRegionOps e500_pci_reg_ops = {
static int mpc85xx_pci_map_irq(PCIDevice *pci_dev, int irq_num)
{
- int devno = pci_dev->devfn >> 3, ret = 0;
+ int devno = pci_dev->devfn >> 3;
+ int ret;
- switch (devno) {
- /* Two PCI slot */
- case 0x11:
- case 0x12:
- ret = (irq_num + devno - 0x10) % 4;
- break;
- default:
- printf("Error:%s:unknown dev number\n", __func__);
- }
+ ret = ppce500_pci_map_irq_slot(devno, irq_num);
pci_debug("%s: devfn %x irq %d -> %d devno:%x\n", __func__,
pci_dev->devfn, irq_num, ret, devno);
@@ -310,6 +319,24 @@ static const VMStateDescription vmstate_ppce500_pci = {
#include "exec-memory.h"
+static int e500_pcihost_bridge_initfn(PCIDevice *d)
+{
+ PPCE500PCIBridgeState *b = PPC_E500_PCI_BRIDGE(d);
+ PPCE500CCSRState *ccsr = CCSR(container_get(qdev_get_machine(),
+ "/e500-ccsr"));
+
+ pci_config_set_class(d->config, PCI_CLASS_BRIDGE_PCI);
+ d->config[PCI_HEADER_TYPE] =
+ (d->config[PCI_HEADER_TYPE] & PCI_HEADER_TYPE_MULTI_FUNCTION) |
+ PCI_HEADER_TYPE_BRIDGE;
+
+ memory_region_init_alias(&b->bar0, "e500-pci-bar0", &ccsr->ccsr_space,
+ 0, int128_get64(ccsr->ccsr_space.size));
+ pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &b->bar0);
+
+ return 0;
+}
+
static int e500_pcihost_initfn(SysBusDevice *dev)
{
PCIHostState *h;
@@ -329,7 +356,7 @@ static int e500_pcihost_initfn(SysBusDevice *dev)
b = pci_register_bus(DEVICE(dev), NULL, mpc85xx_pci_set_irq,
mpc85xx_pci_map_irq, s->irq, address_space_mem,
- &s->pio, PCI_DEVFN(0x11, 0), 4);
+ &s->pio, PCI_DEVFN(s->first_slot, 0), 4);
h->bus = b;
pci_create_simple(b, 0, "e500-host-bridge");
@@ -355,6 +382,7 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
DeviceClass *dc = DEVICE_CLASS(klass);
PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+ k->init = e500_pcihost_bridge_initfn;
k->vendor_id = PCI_VENDOR_ID_FREESCALE;
k->device_id = PCI_DEVICE_ID_MPC8533E;
k->class_id = PCI_CLASS_PROCESSOR_POWERPC;
@@ -364,16 +392,22 @@ static void e500_host_bridge_class_init(ObjectClass *klass, void *data)
static const TypeInfo e500_host_bridge_info = {
.name = "e500-host-bridge",
.parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIDevice),
+ .instance_size = sizeof(PPCE500PCIBridgeState),
.class_init = e500_host_bridge_class_init,
};
+static Property pcihost_properties[] = {
+ DEFINE_PROP_UINT32("first_slot", PPCE500PCIState, first_slot, 0x11),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
static void e500_pcihost_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
k->init = e500_pcihost_initfn;
+ dc->props = pcihost_properties;
dc->vmsd = &vmstate_ppce500_pci;
}
diff --git a/hw/ppce500_pci.h b/hw/ppce500_pci.h
new file mode 100644
index 0000000000..61f773ef30
--- /dev/null
+++ b/hw/ppce500_pci.h
@@ -0,0 +1,9 @@
+#ifndef PPCE500_PCI_H
+#define PPCE500_PCI_H
+
+static inline int ppce500_pci_map_irq_slot(int devno, int irq_num)
+{
+ return (devno + irq_num) % 4;
+}
+
+#endif
diff --git a/hw/puv3.c b/hw/puv3.c
index 764799cff4..3d7734936b 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -122,7 +122,6 @@ static QEMUMachine puv3_machine = {
.desc = "PKUnity Version-3 based on UniCore32",
.init = puv3_init,
.is_default = 1,
- .use_scsi = 0,
};
static void puv3_machine_init(void)
diff --git a/hw/realview.c b/hw/realview.c
index 149bb562af..5fbdcbf2b0 100644
--- a/hw/realview.c
+++ b/hw/realview.c
@@ -364,14 +364,14 @@ static QEMUMachine realview_eb_machine = {
.name = "realview-eb",
.desc = "ARM RealView Emulation Baseboard (ARM926EJ-S)",
.init = realview_eb_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine realview_eb_mpcore_machine = {
.name = "realview-eb-mpcore",
.desc = "ARM RealView Emulation Baseboard (ARM11MPCore)",
.init = realview_eb_mpcore_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
@@ -385,7 +385,7 @@ static QEMUMachine realview_pbx_a9_machine = {
.name = "realview-pbx-a9",
.desc = "ARM RealView Platform Baseboard Explore for Cortex-A9",
.init = realview_pbx_a9_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index ca1bb09816..7aca0c4aad 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -314,21 +314,6 @@ static void s390_init(QEMUMachineInitArgs *args)
qdev_set_nic_properties(dev, nd);
qdev_init_nofail(dev);
}
-
- /* Create VirtIO disk drives */
- for(i = 0; i < MAX_BLK_DEVS; i++) {
- DriveInfo *dinfo;
- DeviceState *dev;
-
- dinfo = drive_get(IF_IDE, 0, i);
- if (!dinfo) {
- continue;
- }
-
- dev = qdev_create((BusState *)s390_bus, "virtio-blk-s390");
- qdev_prop_set_drive_nofail(dev, "drive", dinfo->bdrv);
- qdev_init_nofail(dev);
- }
}
static QEMUMachine s390_machine = {
@@ -336,6 +321,7 @@ static QEMUMachine s390_machine = {
.alias = "s390",
.desc = "VirtIO based S390 machine",
.init = s390_init,
+ .block_default_type = IF_VIRTIO,
.no_cdrom = 1,
.no_floppy = 1,
.no_serial = 1,
@@ -352,3 +338,4 @@ static void s390_machine_init(void)
}
machine_init(s390_machine_init);
+
diff --git a/hw/spapr.c b/hw/spapr.c
index b0125a892c..9bd2fd5c8c 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -657,6 +657,36 @@ static void spapr_cpu_reset(void *opaque)
(spapr->htab_shift - 18);
}
+static void spapr_create_nvram(sPAPREnvironment *spapr)
+{
+ QemuOpts *machine_opts;
+ DeviceState *dev;
+
+ dev = qdev_create(&spapr->vio_bus->bus, "spapr-nvram");
+
+ machine_opts = qemu_opts_find(qemu_find_opts("machine"), 0);
+ if (machine_opts) {
+ const char *drivename;
+
+ drivename = qemu_opt_get(machine_opts, "nvram");
+ if (drivename) {
+ BlockDriverState *bs;
+
+ bs = bdrv_find(drivename);
+ if (!bs) {
+ fprintf(stderr, "No such block device \"%s\" for nvram\n",
+ drivename);
+ exit(1);
+ }
+ qdev_prop_set_drive_nofail(dev, "drive", bs);
+ }
+ }
+
+ qdev_init_nofail(dev);
+
+ spapr->nvram = (struct sPAPRNVRAM *)dev;
+}
+
/* Returns whether we want to use VGA or not */
static int spapr_vga_init(PCIBus *pci_bus)
{
@@ -801,7 +831,7 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
/* Set up Interrupt Controller */
spapr->icp = xics_system_init(XICS_IRQS);
- spapr->next_irq = 16;
+ spapr->next_irq = XICS_IRQ_BASE;
/* Set up EPOW events infrastructure */
spapr_events_init(spapr);
@@ -818,6 +848,9 @@ static void ppc_spapr_init(QEMUMachineInitArgs *args)
}
}
+ /* We always have at least the nvram device on VIO */
+ spapr_create_nvram(spapr);
+
/* Set up PCI */
spapr_pci_rtas_init();
@@ -924,9 +957,9 @@ static QEMUMachine spapr_machine = {
.desc = "pSeries Logical Partition (PAPR compliant)",
.init = ppc_spapr_init,
.reset = ppc_spapr_reset,
+ .block_default_type = IF_SCSI,
.max_cpus = MAX_CPUS,
.no_parallel = 1,
- .use_scsi = 1,
};
static void spapr_machine_init(void)
diff --git a/hw/spapr.h b/hw/spapr.h
index efe7f5758f..600722f132 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -6,11 +6,13 @@
struct VIOsPAPRBus;
struct sPAPRPHBState;
+struct sPAPRNVRAM;
struct icp_state;
typedef struct sPAPREnvironment {
struct VIOsPAPRBus *vio_bus;
QLIST_HEAD(, sPAPRPHBState) phbs;
+ struct sPAPRNVRAM *nvram;
struct icp_state *icp;
hwaddr ram_limit;
@@ -320,7 +322,7 @@ static inline void rtas_st(target_ulong phys, int n, uint32_t val)
typedef void (*spapr_rtas_fn)(sPAPREnvironment *spapr, uint32_t token,
uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
-void spapr_rtas_register(const char *name, spapr_rtas_fn fn);
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn);
target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
uint32_t token, uint32_t nargs, target_ulong args,
uint32_t nret, target_ulong rets);
diff --git a/hw/spapr_iommu.c b/hw/spapr_iommu.c
index 02d78ccf28..3011b251d3 100644
--- a/hw/spapr_iommu.c
+++ b/hw/spapr_iommu.c
@@ -120,6 +120,12 @@ DMAContext *spapr_tce_new_dma_context(uint32_t liobn, size_t window_size)
{
sPAPRTCETable *tcet;
+ if (spapr_tce_find_by_liobn(liobn)) {
+ fprintf(stderr, "Attempted to create TCE table with duplicate"
+ " LIOBN 0x%x\n", liobn);
+ return NULL;
+ }
+
if (!window_size) {
return NULL;
}
diff --git a/hw/spapr_nvram.c b/hw/spapr_nvram.c
new file mode 100644
index 0000000000..512bb8d5d1
--- /dev/null
+++ b/hw/spapr_nvram.c
@@ -0,0 +1,196 @@
+/*
+ * QEMU sPAPR NVRAM emulation
+ *
+ * Copyright (C) 2012 David Gibson, IBM Corporation.
+ *
+ * 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 <sys/mman.h>
+#include <libfdt.h>
+
+#include "device_tree.h"
+#include "hw/sysbus.h"
+#include "hw/spapr.h"
+#include "hw/spapr_vio.h"
+
+typedef struct sPAPRNVRAM {
+ VIOsPAPRDevice sdev;
+ uint32_t size;
+ uint8_t *buf;
+ BlockDriverState *drive;
+} sPAPRNVRAM;
+
+#define MIN_NVRAM_SIZE 8192
+#define DEFAULT_NVRAM_SIZE 65536
+#define MAX_NVRAM_SIZE (UINT16_MAX * 16)
+
+static void rtas_nvram_fetch(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ sPAPRNVRAM *nvram = spapr->nvram;
+ hwaddr offset, buffer, len;
+ int alen;
+ void *membuf;
+
+ if ((nargs != 3) || (nret != 2)) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ if (!nvram) {
+ rtas_st(rets, 0, -1);
+ rtas_st(rets, 1, 0);
+ return;
+ }
+
+ offset = rtas_ld(args, 0);
+ buffer = rtas_ld(args, 1);
+ len = rtas_ld(args, 2);
+
+ if (((offset + len) < offset)
+ || ((offset + len) > nvram->size)) {
+ rtas_st(rets, 0, -3);
+ rtas_st(rets, 1, 0);
+ return;
+ }
+
+ membuf = cpu_physical_memory_map(buffer, &len, 1);
+ if (nvram->drive) {
+ alen = bdrv_pread(nvram->drive, offset, membuf, len);
+ } else {
+ assert(nvram->buf);
+
+ memcpy(membuf, nvram->buf + offset, len);
+ alen = len;
+ }
+ cpu_physical_memory_unmap(membuf, len, 1, len);
+
+ rtas_st(rets, 0, (alen < len) ? -1 : 0);
+ rtas_st(rets, 1, (alen < 0) ? 0 : alen);
+}
+
+static void rtas_nvram_store(sPAPREnvironment *spapr,
+ uint32_t token, uint32_t nargs,
+ target_ulong args,
+ uint32_t nret, target_ulong rets)
+{
+ sPAPRNVRAM *nvram = spapr->nvram;
+ hwaddr offset, buffer, len;
+ int alen;
+ void *membuf;
+
+ if ((nargs != 3) || (nret != 2)) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ if (!nvram) {
+ rtas_st(rets, 0, -1);
+ return;
+ }
+
+ offset = rtas_ld(args, 0);
+ buffer = rtas_ld(args, 1);
+ len = rtas_ld(args, 2);
+
+ if (((offset + len) < offset)
+ || ((offset + len) > nvram->size)) {
+ rtas_st(rets, 0, -3);
+ return;
+ }
+
+ membuf = cpu_physical_memory_map(buffer, &len, 0);
+ if (nvram->drive) {
+ alen = bdrv_pwrite(nvram->drive, offset, membuf, len);
+ } else {
+ assert(nvram->buf);
+
+ memcpy(nvram->buf + offset, membuf, len);
+ alen = len;
+ }
+ cpu_physical_memory_unmap(membuf, len, 0, len);
+
+ rtas_st(rets, 0, (alen < len) ? -1 : 0);
+ rtas_st(rets, 1, (alen < 0) ? 0 : alen);
+}
+
+static int spapr_nvram_init(VIOsPAPRDevice *dev)
+{
+ sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+
+ if (nvram->drive) {
+ nvram->size = bdrv_getlength(nvram->drive);
+ } else {
+ nvram->size = DEFAULT_NVRAM_SIZE;
+ nvram->buf = g_malloc0(nvram->size);
+ }
+
+ if ((nvram->size < MIN_NVRAM_SIZE) || (nvram->size > MAX_NVRAM_SIZE)) {
+ fprintf(stderr, "spapr-nvram must be between %d and %d bytes in size\n",
+ MIN_NVRAM_SIZE, MAX_NVRAM_SIZE);
+ return -1;
+ }
+
+ spapr_rtas_register("nvram-fetch", rtas_nvram_fetch);
+ spapr_rtas_register("nvram-store", rtas_nvram_store);
+
+ return 0;
+}
+
+static int spapr_nvram_devnode(VIOsPAPRDevice *dev, void *fdt, int node_off)
+{
+ sPAPRNVRAM *nvram = (sPAPRNVRAM *)dev;
+
+ return fdt_setprop_cell(fdt, node_off, "#bytes", nvram->size);
+}
+
+static Property spapr_nvram_properties[] = {
+ DEFINE_SPAPR_PROPERTIES(sPAPRNVRAM, sdev),
+ DEFINE_PROP_DRIVE("drive", sPAPRNVRAM, drive),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_nvram_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ VIOsPAPRDeviceClass *k = VIO_SPAPR_DEVICE_CLASS(klass);
+
+ k->init = spapr_nvram_init;
+ k->devnode = spapr_nvram_devnode;
+ k->dt_name = "nvram";
+ k->dt_type = "nvram";
+ k->dt_compatible = "qemu,spapr-nvram";
+ dc->props = spapr_nvram_properties;
+}
+
+static const TypeInfo spapr_nvram_type_info = {
+ .name = "spapr-nvram",
+ .parent = TYPE_VIO_SPAPR_DEVICE,
+ .instance_size = sizeof(sPAPRNVRAM),
+ .class_init = spapr_nvram_class_init,
+};
+
+static void spapr_nvram_register_types(void)
+{
+ type_register_static(&spapr_nvram_type_info);
+}
+
+type_init(spapr_nvram_register_types)
diff --git a/hw/spapr_rtas.c b/hw/spapr_rtas.c
index 6d5c48a740..e618c2db53 100644
--- a/hw/spapr_rtas.c
+++ b/hw/spapr_rtas.c
@@ -242,7 +242,7 @@ target_ulong spapr_rtas_call(sPAPREnvironment *spapr,
return H_PARAMETER;
}
-void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
+int spapr_rtas_register(const char *name, spapr_rtas_fn fn)
{
int i;
@@ -258,7 +258,7 @@ void spapr_rtas_register(const char *name, spapr_rtas_fn fn)
rtas_next->name = name;
rtas_next->fn = fn;
- rtas_next++;
+ return (rtas_next++ - rtas_table) + TOKEN_BASE;
}
int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
@@ -301,7 +301,7 @@ int spapr_rtas_device_tree_setup(void *fdt, hwaddr rtas_addr,
for (i = 0; i < TOKEN_MAX; i++) {
struct rtas_call *call = &rtas_table[i];
- if (!call->fn) {
+ if (!call->name) {
continue;
}
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 1a786762aa..52cf82b681 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -1426,7 +1426,7 @@ static QEMUMachine ss5_machine = {
.name = "SS-5",
.desc = "Sun4m platform, SPARCstation 5",
.init = ss5_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.is_default = 1,
};
@@ -1434,7 +1434,7 @@ static QEMUMachine ss10_machine = {
.name = "SS-10",
.desc = "Sun4m platform, SPARCstation 10",
.init = ss10_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
@@ -1442,7 +1442,7 @@ static QEMUMachine ss600mp_machine = {
.name = "SS-600MP",
.desc = "Sun4m platform, SPARCserver 600MP",
.init = ss600mp_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
@@ -1450,7 +1450,7 @@ static QEMUMachine ss20_machine = {
.name = "SS-20",
.desc = "Sun4m platform, SPARCstation 20",
.init = ss20_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
@@ -1458,35 +1458,35 @@ static QEMUMachine voyager_machine = {
.name = "Voyager",
.desc = "Sun4m platform, SPARCstation Voyager",
.init = vger_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine ss_lx_machine = {
.name = "LX",
.desc = "Sun4m platform, SPARCstation LX",
.init = ss_lx_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine ss4_machine = {
.name = "SS-4",
.desc = "Sun4m platform, SPARCstation 4",
.init = ss4_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine scls_machine = {
.name = "SPARCClassic",
.desc = "Sun4m platform, SPARCClassic",
.init = scls_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine sbook_machine = {
.name = "SPARCbook",
.desc = "Sun4m platform, SPARCbook",
.init = sbook_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static const struct sun4d_hwdef sun4d_hwdefs[] = {
@@ -1709,7 +1709,7 @@ static QEMUMachine ss1000_machine = {
.name = "SS-1000",
.desc = "Sun4d platform, SPARCserver 1000",
.init = ss1000_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 8,
};
@@ -1717,7 +1717,7 @@ static QEMUMachine ss2000_machine = {
.name = "SS-2000",
.desc = "Sun4d platform, SPARCcenter 2000",
.init = ss2000_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 20,
};
@@ -1896,7 +1896,7 @@ static QEMUMachine ss2_machine = {
.name = "SS-2",
.desc = "Sun4c platform, SPARCstation 2",
.init = ss2_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static void sun4m_register_types(void)
diff --git a/hw/versatilepb.c b/hw/versatilepb.c
index 41e39d8fb9..f5a742b37f 100644
--- a/hw/versatilepb.c
+++ b/hw/versatilepb.c
@@ -358,14 +358,14 @@ static QEMUMachine versatilepb_machine = {
.name = "versatilepb",
.desc = "ARM Versatile/PB (ARM926EJ-S)",
.init = vpb_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static QEMUMachine versatileab_machine = {
.name = "versatileab",
.desc = "ARM Versatile/AB (ARM926EJ-S)",
.init = vab_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
};
static void versatile_machine_init(void)
diff --git a/hw/vexpress.c b/hw/vexpress.c
index d93f057bff..e89694c86e 100644
--- a/hw/vexpress.c
+++ b/hw/vexpress.c
@@ -477,7 +477,7 @@ static QEMUMachine vexpress_a9_machine = {
.name = "vexpress-a9",
.desc = "ARM Versatile Express for Cortex-A9",
.init = vexpress_a9_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
@@ -485,7 +485,7 @@ static QEMUMachine vexpress_a15_machine = {
.name = "vexpress-a15",
.desc = "ARM Versatile Express for Cortex-A15",
.init = vexpress_a15_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 4,
};
diff --git a/hw/vfio_pci.c b/hw/vfio_pci.c
index 45d90ab490..264e58a68b 100644
--- a/hw/vfio_pci.c
+++ b/hw/vfio_pci.c
@@ -275,7 +275,7 @@ static void vfio_enable_intx_kvm(VFIODevice *vdev)
int ret, argsz;
int32_t *pfd;
- if (!kvm_irqchip_in_kernel() ||
+ if (!kvm_irqfds_enabled() ||
vdev->intx.route.mode != PCI_INTX_ENABLED ||
!kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
return;
@@ -438,7 +438,8 @@ static int vfio_enable_intx(VFIODevice *vdev)
* Only conditional to avoid generating error messages on platforms
* where we won't actually use the result anyway.
*/
- if (kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
+ if (kvm_irqfds_enabled() &&
+ kvm_check_extension(kvm_state, KVM_CAP_IRQFD_RESAMPLE)) {
vdev->intx.route = pci_device_route_intx_to_irq(&vdev->pdev,
vdev->intx.pin);
}
diff --git a/hw/vga.c b/hw/vga.c
index 6d56f8a5d9..ab40d73100 100644
--- a/hw/vga.c
+++ b/hw/vga.c
@@ -2413,7 +2413,7 @@ void ppm_save(const char *filename, struct DisplaySurface *ds, Error **errp)
}
linebuf = qemu_pixman_linebuf_create(PIXMAN_BE_r8g8b8, width);
for (y = 0; y < height; y++) {
- qemu_pixman_linebuf_fill(linebuf, ds->image, width, y);
+ qemu_pixman_linebuf_fill(linebuf, ds->image, width, 0, y);
clearerr(f);
ret = fwrite(pixman_image_get_data(linebuf), 1,
pixman_image_get_stride(linebuf), f);
diff --git a/hw/virtio-blk.h b/hw/virtio-blk.h
index f0740d01af..651a000b9f 100644
--- a/hw/virtio-blk.h
+++ b/hw/virtio-blk.h
@@ -104,7 +104,6 @@ struct VirtIOBlkConf
BlockConf conf;
char *serial;
uint32_t scsi;
- uint32_t config_wce;
};
#define DEFINE_VIRTIO_BLK_FEATURES(_state, _field) \
diff --git a/hw/virtio-pci.c b/hw/virtio-pci.c
index e9b722dd96..d0d6a5e816 100644
--- a/hw/virtio-pci.c
+++ b/hw/virtio-pci.c
@@ -895,7 +895,6 @@ static Property virtio_blk_properties[] = {
#ifdef __linux__
DEFINE_PROP_BIT("scsi", VirtIOPCIProxy, blk.scsi, 0, true),
#endif
- DEFINE_PROP_BIT("config-wce", VirtIOPCIProxy, blk.config_wce, 0, true),
DEFINE_PROP_BIT("ioeventfd", VirtIOPCIProxy, flags, VIRTIO_PCI_FLAG_USE_IOEVENTFD_BIT, true),
DEFINE_PROP_UINT32("vectors", VirtIOPCIProxy, nvectors, 2),
DEFINE_VIRTIO_BLK_FEATURES(VirtIOPCIProxy, host_features),
diff --git a/hw/watchdog.c b/hw/watchdog.c
index b52acedd98..5c82c17d09 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -66,7 +66,7 @@ int select_watchdog(const char *p)
QLIST_FOREACH(model, &watchdog_list, entry) {
if (strcasecmp(model->wdt_name, p) == 0) {
/* add the device */
- opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
+ opts = qemu_opts_create_nofail(qemu_find_opts("device"));
qemu_opt_set(opts, "driver", p);
return 0;
}
diff --git a/hw/xics.c b/hw/xics.c
index 1da310653b..55899ce77d 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -26,6 +26,7 @@
*/
#include "hw.h"
+#include "trace.h"
#include "hw/spapr.h"
#include "hw/xics.h"
@@ -66,6 +67,8 @@ static void icp_check_ipi(struct icp_state *icp, int server)
return;
}
+ trace_xics_icp_check_ipi(server, ss->mfrr);
+
if (XISR(ss)) {
ics_reject(icp->ics, XISR(ss));
}
@@ -120,11 +123,13 @@ static void icp_set_mfrr(struct icp_state *icp, int server, uint8_t mfrr)
static uint32_t icp_accept(struct icp_server_state *ss)
{
- uint32_t xirr;
+ uint32_t xirr = ss->xirr;
qemu_irq_lower(ss->output);
- xirr = ss->xirr;
ss->xirr = ss->pending_priority << 24;
+
+ trace_xics_icp_accept(xirr, ss->xirr);
+
return xirr;
}
@@ -134,6 +139,7 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
/* Send EOI -> ICS */
ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+ trace_xics_icp_eoi(server, xirr, ss->xirr);
ics_eoi(icp->ics, xirr & XISR_MASK);
if (!XISR(ss)) {
icp_resend(icp, server);
@@ -144,6 +150,8 @@ static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
{
struct icp_server_state *ss = icp->ss + server;
+ trace_xics_icp_irq(server, nr, priority);
+
if ((priority >= CPPR(ss))
|| (XISR(ss) && (ss->pending_priority <= priority))) {
ics_reject(icp->ics, nr);
@@ -153,6 +161,7 @@ static void icp_irq(struct icp_state *icp, int server, int nr, uint8_t priority)
}
ss->xirr = (ss->xirr & ~XISR_MASK) | (nr & XISR_MASK);
ss->pending_priority = priority;
+ trace_xics_icp_raise(ss->xirr, ss->pending_priority);
qemu_irq_raise(ss->output);
}
}
@@ -170,13 +179,13 @@ struct ics_irq_state {
#define XICS_STATUS_REJECTED 0x4
#define XICS_STATUS_MASKED_PENDING 0x8
uint8_t status;
- bool lsi;
};
struct ics_state {
int nr_irqs;
int offset;
qemu_irq *qirqs;
+ bool *islsi;
struct ics_irq_state *irqs;
struct icp_state *icp;
};
@@ -217,10 +226,12 @@ static void set_irq_msi(struct ics_state *ics, int srcno, int val)
{
struct ics_irq_state *irq = ics->irqs + srcno;
+ trace_xics_set_irq_msi(srcno, srcno + ics->offset);
+
if (val) {
if (irq->priority == 0xff) {
irq->status |= XICS_STATUS_MASKED_PENDING;
- /* masked pending */ ;
+ trace_xics_masked_pending();
} else {
icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
@@ -231,6 +242,7 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
{
struct ics_irq_state *irq = ics->irqs + srcno;
+ trace_xics_set_irq_lsi(srcno, srcno + ics->offset);
if (val) {
irq->status |= XICS_STATUS_ASSERTED;
} else {
@@ -242,9 +254,8 @@ static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
static void ics_set_irq(void *opaque, int srcno, int val)
{
struct ics_state *ics = (struct ics_state *)opaque;
- struct ics_irq_state *irq = ics->irqs + srcno;
- if (irq->lsi) {
+ if (ics->islsi[srcno]) {
set_irq_lsi(ics, srcno, val);
} else {
set_irq_msi(ics, srcno, val);
@@ -279,7 +290,9 @@ static void ics_write_xive(struct ics_state *ics, int nr, int server,
irq->priority = priority;
irq->saved_priority = saved_priority;
- if (irq->lsi) {
+ trace_xics_ics_write_xive(nr, srcno, server, priority);
+
+ if (ics->islsi[srcno]) {
write_xive_lsi(ics, srcno);
} else {
write_xive_msi(ics, srcno);
@@ -290,6 +303,7 @@ static void ics_reject(struct ics_state *ics, int nr)
{
struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+ trace_xics_ics_reject(nr, nr - ics->offset);
irq->status |= XICS_STATUS_REJECTED; /* Irrelevant but harmless for LSI */
irq->status &= ~XICS_STATUS_SENT; /* Irrelevant but harmless for MSI */
}
@@ -299,10 +313,8 @@ static void ics_resend(struct ics_state *ics)
int i;
for (i = 0; i < ics->nr_irqs; i++) {
- struct ics_irq_state *irq = ics->irqs + i;
-
/* FIXME: filter by server#? */
- if (irq->lsi) {
+ if (ics->islsi[i]) {
resend_lsi(ics, i);
} else {
resend_msi(ics, i);
@@ -315,7 +327,9 @@ static void ics_eoi(struct ics_state *ics, int nr)
int srcno = nr - ics->offset;
struct ics_irq_state *irq = ics->irqs + srcno;
- if (irq->lsi) {
+ trace_xics_ics_eoi(nr);
+
+ if (ics->islsi[srcno]) {
irq->status &= ~XICS_STATUS_SENT;
}
}
@@ -337,7 +351,7 @@ void xics_set_irq_type(struct icp_state *icp, int irq, bool lsi)
{
assert(ics_valid_irq(icp->ics, irq));
- icp->ics->irqs[irq - icp->ics->offset].lsi = lsi;
+ icp->ics->islsi[irq - icp->ics->offset] = lsi;
}
static target_ulong h_cppr(PowerPCCPU *cpu, sPAPREnvironment *spapr,
@@ -495,16 +509,14 @@ static void xics_reset(void *opaque)
for (i = 0; i < icp->nr_servers; i++) {
icp->ss[i].xirr = 0;
- icp->ss[i].pending_priority = 0;
+ icp->ss[i].pending_priority = 0xff;
icp->ss[i].mfrr = 0xff;
/* Make all outputs are deasserted */
qemu_set_irq(icp->ss[i].output, 0);
}
+ memset(ics->irqs, 0, sizeof(struct ics_irq_state) * ics->nr_irqs);
for (i = 0; i < ics->nr_irqs; i++) {
- /* Reset everything *except* the type */
- ics->irqs[i].server = 0;
- ics->irqs[i].status = 0;
ics->irqs[i].priority = 0xff;
ics->irqs[i].saved_priority = 0xff;
}
@@ -549,8 +561,9 @@ struct icp_state *xics_system_init(int nr_irqs)
ics = g_malloc0(sizeof(*ics));
ics->nr_irqs = nr_irqs;
- ics->offset = 16;
+ ics->offset = XICS_IRQ_BASE;
ics->irqs = g_malloc0(nr_irqs * sizeof(struct ics_irq_state));
+ ics->islsi = g_malloc0(nr_irqs * sizeof(bool));
icp->ics = ics;
ics->icp = icp;
diff --git a/hw/xics.h b/hw/xics.h
index 6817268697..c3bf0083e2 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -28,6 +28,7 @@
#define __XICS_H__
#define XICS_IPI 0x2
+#define XICS_IRQ_BASE 0x10
struct icp_state;
diff --git a/hw/xilinx_zynq.c b/hw/xilinx_zynq.c
index 1f12a3d1ad..9ca22a4e7d 100644
--- a/hw/xilinx_zynq.c
+++ b/hw/xilinx_zynq.c
@@ -57,6 +57,7 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
DeviceState *dev;
SysBusDevice *busdev;
SSIBus *spi;
+ DeviceState *flash_dev;
int i, j;
int num_busses = is_qspi ? NUM_QSPI_BUSSES : 1;
int num_ss = is_qspi ? NUM_QSPI_FLASHES : NUM_SPI_FLASHES;
@@ -81,11 +82,11 @@ static inline void zynq_init_spi_flashes(uint32_t base_addr, qemu_irq irq,
spi = (SSIBus *)qdev_get_child_bus(dev, bus_name);
for (j = 0; j < num_ss; ++j) {
- dev = ssi_create_slave_no_init(spi, "m25p80");
- qdev_prop_set_string(dev, "partname", "n25q128");
- qdev_init_nofail(dev);
+ flash_dev = ssi_create_slave_no_init(spi, "m25p80");
+ qdev_prop_set_string(flash_dev, "partname", "n25q128");
+ qdev_init_nofail(flash_dev);
- cs_line = qdev_get_gpio_in(dev, 0);
+ cs_line = qdev_get_gpio_in(flash_dev, 0);
sysbus_connect_irq(busdev, i * num_ss + j + 1, cs_line);
}
}
@@ -200,7 +201,7 @@ static QEMUMachine zynq_machine = {
.name = "xilinx-zynq-a9",
.desc = "Xilinx Zynq Platform Baseboard for Cortex-A9",
.init = zynq_init,
- .use_scsi = 1,
+ .block_default_type = IF_SCSI,
.max_cpus = 1,
.no_sdcard = 1
};