mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.12-20180306' into staging
ppc patch queue 2018-03-06
This pull request supersedes ppc-for-2.12-20180302 which had compile
problems with some gcc versions. It also contains a few additional
patches.
Highlights are:
* New Sam460ex machine type
* Yet more fixes related to vcpu id allocation for spapr
* Numerous macio cleanupsr
* Some enhancements to the Spectre/Meltdown fixes for pseries,
allowing use of a better mitigation for indirect branch based
exploits
* New pseries machine types with Spectre/Meltdown mitigations
enabled (stop gap until libvirt and management understands the
machine options)
* A handful of other fixes
# gpg: Signature made Tue 06 Mar 2018 04:01:00 GMT
# gpg: using RSA key 6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>"
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392
* remotes/dgibson/tags/ppc-for-2.12-20180306: (30 commits)
PowerPC: Add TS bits into msr_mask
adb: add trace-events for monitoring keyboard/mouse during bus enumeration
PPC: e500: Fix duplicate kernel load and device tree overlap
hw/ppc/spapr,e500: Use new property "stdout-path" for boot console
ppc/spapr-caps: Define the pseries-2.12-sxxm machine type
ppc/spapr-caps: Convert cap-ibs to custom spapr-cap
ppc/spapr-caps: Convert cap-sbbc to custom spapr-cap
ppc/spapr-caps: Convert cap-cfpc to custom spapr-cap
ppc/spapr-caps: Add support for custom spapr_capabilities
target/ppc: Check mask when setting cap_ppc_safe_indirect_branch
macio: remove macio_init() function
macio: move setting of CUDA timebase frequency to macio_common_realize()
mac_newworld: use object link to pass OpenPIC object to macio
openpic: move OpenPIC state and related definitions to openpic.h
openpic: move KVM-specific declarations into separate openpic_kvm.h file
mac_oldworld: use object link to pass heathrow PIC object to macio
macio: move macio related structures and defines into separate macio.h file
heathrow: change heathrow_pic_init() to return the heathrow device
heathrow: convert to trace-events
heathrow: QOMify heathrow PIC
...
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
@@ -43,3 +43,6 @@
|
||||
[submodule "roms/seabios-hppa"]
|
||||
path = roms/seabios-hppa
|
||||
url = git://github.com/hdeller/seabios-hppa.git
|
||||
[submodule "roms/u-boot-sam460ex"]
|
||||
path = roms/u-boot-sam460ex
|
||||
url = git://github.com/zbalaton/u-boot-sam460ex
|
||||
|
||||
@@ -779,12 +779,12 @@ efi-e1000.rom efi-eepro100.rom efi-ne2k_pci.rom \
|
||||
efi-pcnet.rom efi-rtl8139.rom efi-virtio.rom \
|
||||
efi-e1000e.rom efi-vmxnet3.rom \
|
||||
qemu-icon.bmp qemu_logo_no_text.svg \
|
||||
bamboo.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
bamboo.dtb canyonlands.dtb petalogix-s3adsp1800.dtb petalogix-ml605.dtb \
|
||||
multiboot.bin linuxboot.bin linuxboot_dma.bin kvmvapic.bin \
|
||||
s390-ccw.img s390-netboot.img \
|
||||
spapr-rtas.bin slof.bin skiboot.lid \
|
||||
palcode-clipper \
|
||||
u-boot.e500 \
|
||||
u-boot.e500 u-boot-sam460-20100605.bin \
|
||||
qemu_vga.ndrv \
|
||||
hppa-firmware.img
|
||||
else
|
||||
|
||||
@@ -21,6 +21,8 @@ CONFIG_E500=y
|
||||
CONFIG_OPENPIC_KVM=$(call land,$(CONFIG_E500),$(CONFIG_KVM))
|
||||
CONFIG_PLATFORM_BUS=y
|
||||
CONFIG_ETSEC=y
|
||||
# For Sam460ex
|
||||
CONFIG_USB_EHCI_SYSBUS=y
|
||||
CONFIG_SM501=y
|
||||
CONFIG_IDE_SII3112=y
|
||||
CONFIG_I2C=y
|
||||
|
||||
@@ -15,6 +15,7 @@ CONFIG_PTIMER=y
|
||||
CONFIG_I8259=y
|
||||
CONFIG_XILINX=y
|
||||
CONFIG_XILINX_ETHLITE=y
|
||||
CONFIG_USB_EHCI_SYSBUS=y
|
||||
CONFIG_SM501=y
|
||||
CONFIG_IDE_SII3112=y
|
||||
CONFIG_I2C=y
|
||||
|
||||
@@ -258,6 +258,7 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
|
||||
case ADB_CMD_CHANGE_ID_AND_ACT:
|
||||
case ADB_CMD_CHANGE_ID_AND_ENABLE:
|
||||
d->devaddr = buf[1] & 0xf;
|
||||
trace_adb_kbd_request_change_addr(d->devaddr);
|
||||
break;
|
||||
default:
|
||||
d->devaddr = buf[1] & 0xf;
|
||||
@@ -269,6 +270,9 @@ static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
|
||||
if (buf[2] == 1 || buf[2] == 2 || buf[2] == 3) {
|
||||
d->handler = buf[2];
|
||||
}
|
||||
|
||||
trace_adb_kbd_request_change_addr_and_handler(d->devaddr,
|
||||
d->handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,6 +118,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
|
||||
s->dx = 0;
|
||||
s->dy = 0;
|
||||
s->dz = 0;
|
||||
trace_adb_mouse_flush();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -138,6 +139,7 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
|
||||
case ADB_CMD_CHANGE_ID_AND_ACT:
|
||||
case ADB_CMD_CHANGE_ID_AND_ENABLE:
|
||||
d->devaddr = buf[1] & 0xf;
|
||||
trace_adb_mouse_request_change_addr(d->devaddr);
|
||||
break;
|
||||
default:
|
||||
d->devaddr = buf[1] & 0xf;
|
||||
@@ -155,6 +157,9 @@ static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
|
||||
if (buf[2] == 1 || buf[2] == 2) {
|
||||
d->handler = buf[2];
|
||||
}
|
||||
|
||||
trace_adb_mouse_request_change_addr_and_handler(d->devaddr,
|
||||
d->handler);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,15 @@
|
||||
adb_kbd_no_key(void) "Ignoring NO_KEY"
|
||||
adb_kbd_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
|
||||
adb_kbd_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
|
||||
adb_kbd_request_change_addr(int devaddr) "change addr to 0x%x"
|
||||
adb_kbd_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"
|
||||
|
||||
# hw/input/adb-mouse.c
|
||||
adb_mouse_flush(void) "flush"
|
||||
adb_mouse_writereg(int reg, uint8_t val) "reg %d val 0x%2.2x"
|
||||
adb_mouse_readreg(int reg, uint8_t val0, uint8_t val1) "reg %d obuf[0] 0x%2.2x obuf[1] 0x%2.2x"
|
||||
adb_mouse_request_change_addr(int devaddr) "change addr to 0x%x"
|
||||
adb_mouse_request_change_addr_and_handler(int devaddr, int handler) "change addr and handler to 0x%x, 0x%x"
|
||||
|
||||
# hw/input/ps2.c
|
||||
ps2_put_keycode(void *opaque, int keycode) "%p keycode 0x%02x"
|
||||
|
||||
+87
-81
@@ -25,78 +25,58 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/ppc/mac.h"
|
||||
#include "hw/intc/heathrow_pic.h"
|
||||
#include "trace.h"
|
||||
|
||||
/* debug PIC */
|
||||
//#define DEBUG_PIC
|
||||
|
||||
#ifdef DEBUG_PIC
|
||||
#define PIC_DPRINTF(fmt, ...) \
|
||||
do { printf("PIC: " fmt , ## __VA_ARGS__); } while (0)
|
||||
#else
|
||||
#define PIC_DPRINTF(fmt, ...)
|
||||
#endif
|
||||
|
||||
typedef struct HeathrowPIC {
|
||||
uint32_t events;
|
||||
uint32_t mask;
|
||||
uint32_t levels;
|
||||
uint32_t level_triggered;
|
||||
} HeathrowPIC;
|
||||
|
||||
typedef struct HeathrowPICS {
|
||||
MemoryRegion mem;
|
||||
HeathrowPIC pics[2];
|
||||
qemu_irq *irqs;
|
||||
} HeathrowPICS;
|
||||
|
||||
static inline int check_irq(HeathrowPIC *pic)
|
||||
static inline int heathrow_check_irq(HeathrowPICState *pic)
|
||||
{
|
||||
return (pic->events | (pic->levels & pic->level_triggered)) & pic->mask;
|
||||
}
|
||||
|
||||
/* update the CPU irq state */
|
||||
static void heathrow_pic_update(HeathrowPICS *s)
|
||||
static void heathrow_update_irq(HeathrowState *s)
|
||||
{
|
||||
if (check_irq(&s->pics[0]) || check_irq(&s->pics[1])) {
|
||||
if (heathrow_check_irq(&s->pics[0]) ||
|
||||
heathrow_check_irq(&s->pics[1])) {
|
||||
qemu_irq_raise(s->irqs[0]);
|
||||
} else {
|
||||
qemu_irq_lower(s->irqs[0]);
|
||||
}
|
||||
}
|
||||
|
||||
static void pic_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
static void heathrow_write(void *opaque, hwaddr addr,
|
||||
uint64_t value, unsigned size)
|
||||
{
|
||||
HeathrowPICS *s = opaque;
|
||||
HeathrowPIC *pic;
|
||||
HeathrowState *s = opaque;
|
||||
HeathrowPICState *pic;
|
||||
unsigned int n;
|
||||
|
||||
n = ((addr & 0xfff) - 0x10) >> 4;
|
||||
PIC_DPRINTF("writel: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
|
||||
trace_heathrow_write(addr, n, value);
|
||||
if (n >= 2)
|
||||
return;
|
||||
pic = &s->pics[n];
|
||||
switch(addr & 0xf) {
|
||||
case 0x04:
|
||||
pic->mask = value;
|
||||
heathrow_pic_update(s);
|
||||
heathrow_update_irq(s);
|
||||
break;
|
||||
case 0x08:
|
||||
/* do not reset level triggered IRQs */
|
||||
value &= ~pic->level_triggered;
|
||||
pic->events &= ~value;
|
||||
heathrow_pic_update(s);
|
||||
heathrow_update_irq(s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static uint64_t pic_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
static uint64_t heathrow_read(void *opaque, hwaddr addr,
|
||||
unsigned size)
|
||||
{
|
||||
HeathrowPICS *s = opaque;
|
||||
HeathrowPIC *pic;
|
||||
HeathrowState *s = opaque;
|
||||
HeathrowPICState *pic;
|
||||
unsigned int n;
|
||||
uint32_t value;
|
||||
|
||||
@@ -120,40 +100,39 @@ static uint64_t pic_read(void *opaque, hwaddr addr,
|
||||
break;
|
||||
}
|
||||
}
|
||||
PIC_DPRINTF("readl: " TARGET_FMT_plx " %u: %08x\n", addr, n, value);
|
||||
trace_heathrow_read(addr, n, value);
|
||||
return value;
|
||||
}
|
||||
|
||||
static const MemoryRegionOps heathrow_pic_ops = {
|
||||
.read = pic_read,
|
||||
.write = pic_write,
|
||||
static const MemoryRegionOps heathrow_ops = {
|
||||
.read = heathrow_read,
|
||||
.write = heathrow_write,
|
||||
.endianness = DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
static void heathrow_pic_set_irq(void *opaque, int num, int level)
|
||||
static void heathrow_set_irq(void *opaque, int num, int level)
|
||||
{
|
||||
HeathrowPICS *s = opaque;
|
||||
HeathrowPIC *pic;
|
||||
HeathrowState *s = opaque;
|
||||
HeathrowPICState *pic;
|
||||
unsigned int irq_bit;
|
||||
int last_level;
|
||||
|
||||
#if defined(DEBUG)
|
||||
{
|
||||
static int last_level[64];
|
||||
if (last_level[num] != level) {
|
||||
PIC_DPRINTF("set_irq: num=0x%02x level=%d\n", num, level);
|
||||
last_level[num] = level;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
pic = &s->pics[1 - (num >> 5)];
|
||||
irq_bit = 1 << (num & 0x1f);
|
||||
last_level = (pic->levels & irq_bit) ? 1 : 0;
|
||||
|
||||
if (level) {
|
||||
pic->events |= irq_bit & ~pic->level_triggered;
|
||||
pic->levels |= irq_bit;
|
||||
} else {
|
||||
pic->levels &= ~irq_bit;
|
||||
}
|
||||
heathrow_pic_update(s);
|
||||
|
||||
if (last_level != level) {
|
||||
trace_heathrow_set_irq(num, level);
|
||||
}
|
||||
|
||||
heathrow_update_irq(s);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_heathrow_pic_one = {
|
||||
@@ -161,54 +140,81 @@ static const VMStateDescription vmstate_heathrow_pic_one = {
|
||||
.version_id = 0,
|
||||
.minimum_version_id = 0,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINT32(events, HeathrowPIC),
|
||||
VMSTATE_UINT32(mask, HeathrowPIC),
|
||||
VMSTATE_UINT32(levels, HeathrowPIC),
|
||||
VMSTATE_UINT32(level_triggered, HeathrowPIC),
|
||||
VMSTATE_UINT32(events, HeathrowPICState),
|
||||
VMSTATE_UINT32(mask, HeathrowPICState),
|
||||
VMSTATE_UINT32(levels, HeathrowPICState),
|
||||
VMSTATE_UINT32(level_triggered, HeathrowPICState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static const VMStateDescription vmstate_heathrow_pic = {
|
||||
static const VMStateDescription vmstate_heathrow = {
|
||||
.name = "heathrow_pic",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_STRUCT_ARRAY(pics, HeathrowPICS, 2, 1,
|
||||
vmstate_heathrow_pic_one, HeathrowPIC),
|
||||
VMSTATE_STRUCT_ARRAY(pics, HeathrowState, 2, 1,
|
||||
vmstate_heathrow_pic_one, HeathrowPICState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static void heathrow_pic_reset_one(HeathrowPIC *s)
|
||||
static void heathrow_reset(DeviceState *d)
|
||||
{
|
||||
memset(s, '\0', sizeof(HeathrowPIC));
|
||||
}
|
||||
|
||||
static void heathrow_pic_reset(void *opaque)
|
||||
{
|
||||
HeathrowPICS *s = opaque;
|
||||
|
||||
heathrow_pic_reset_one(&s->pics[0]);
|
||||
heathrow_pic_reset_one(&s->pics[1]);
|
||||
HeathrowState *s = HEATHROW(d);
|
||||
|
||||
s->pics[0].level_triggered = 0;
|
||||
s->pics[1].level_triggered = 0x1ff00000;
|
||||
}
|
||||
|
||||
qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
|
||||
int nb_cpus, qemu_irq **irqs)
|
||||
static void heathrow_init(Object *obj)
|
||||
{
|
||||
HeathrowPICS *s;
|
||||
HeathrowState *s = HEATHROW(obj);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
|
||||
|
||||
s = g_malloc0(sizeof(HeathrowPICS));
|
||||
memory_region_init_io(&s->mem, OBJECT(s), &heathrow_ops, s,
|
||||
"heathrow-pic", 0x1000);
|
||||
sysbus_init_mmio(sbd, &s->mem);
|
||||
}
|
||||
|
||||
DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs,
|
||||
qemu_irq **pic_irqs)
|
||||
{
|
||||
DeviceState *d;
|
||||
HeathrowState *s;
|
||||
|
||||
d = qdev_create(NULL, TYPE_HEATHROW);
|
||||
qdev_init_nofail(d);
|
||||
|
||||
s = HEATHROW(d);
|
||||
/* only 1 CPU */
|
||||
s->irqs = irqs[0];
|
||||
memory_region_init_io(&s->mem, NULL, &heathrow_pic_ops, s,
|
||||
"heathrow-pic", 0x1000);
|
||||
*pmem = &s->mem;
|
||||
|
||||
vmstate_register(NULL, -1, &vmstate_heathrow_pic, s);
|
||||
qemu_register_reset(heathrow_pic_reset, s);
|
||||
return qemu_allocate_irqs(heathrow_pic_set_irq, s, 64);
|
||||
*pic_irqs = qemu_allocate_irqs(heathrow_set_irq, s, HEATHROW_NUM_IRQS);
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
static void heathrow_class_init(ObjectClass *oc, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(oc);
|
||||
|
||||
dc->reset = heathrow_reset;
|
||||
dc->vmsd = &vmstate_heathrow;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
}
|
||||
|
||||
static const TypeInfo heathrow_type_info = {
|
||||
.name = TYPE_HEATHROW,
|
||||
.parent = TYPE_SYS_BUS_DEVICE,
|
||||
.instance_size = sizeof(HeathrowState),
|
||||
.instance_init = heathrow_init,
|
||||
.class_init = heathrow_class_init,
|
||||
};
|
||||
|
||||
static void heathrow_register_types(void)
|
||||
{
|
||||
type_register_static(&heathrow_type_info);
|
||||
}
|
||||
|
||||
type_init(heathrow_register_types)
|
||||
|
||||
@@ -63,10 +63,6 @@ static int get_current_cpu(void);
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MAX_CPU 32
|
||||
#define MAX_MSI 8
|
||||
#define VID 0x03 /* MPIC version ID */
|
||||
|
||||
/* OpenPIC capability flags */
|
||||
#define OPENPIC_FLAG_IDR_CRIT (1 << 0)
|
||||
#define OPENPIC_FLAG_ILR (2 << 0)
|
||||
@@ -85,35 +81,6 @@ static int get_current_cpu(void);
|
||||
#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 OPENPIC_MAX_TMR
|
||||
#define RAVEN_MAX_IPI OPENPIC_MAX_IPI
|
||||
|
||||
/* KeyLargo */
|
||||
#define KEYLARGO_MAX_CPU 4
|
||||
#define KEYLARGO_MAX_EXT 64
|
||||
#define KEYLARGO_MAX_IPI 4
|
||||
#define KEYLARGO_MAX_IRQ (64 + KEYLARGO_MAX_IPI)
|
||||
#define KEYLARGO_MAX_TMR 0
|
||||
#define KEYLARGO_IPI_IRQ (KEYLARGO_MAX_EXT) /* First IPI IRQ */
|
||||
/* Timers don't exist but this makes the code happy... */
|
||||
#define KEYLARGO_TMR_IRQ (KEYLARGO_IPI_IRQ + KEYLARGO_MAX_IPI)
|
||||
|
||||
/* Interrupt definitions */
|
||||
#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))
|
||||
|
||||
typedef struct FslMpicInfo {
|
||||
int max_ext;
|
||||
} FslMpicInfo;
|
||||
|
||||
static FslMpicInfo fsl_mpic_20 = {
|
||||
.max_ext = 12,
|
||||
};
|
||||
@@ -211,55 +178,6 @@ static void openpic_cpu_write_internal(void *opaque, hwaddr addr,
|
||||
uint32_t val, int idx);
|
||||
static void openpic_reset(DeviceState *d);
|
||||
|
||||
typedef enum IRQType {
|
||||
IRQ_TYPE_NORMAL = 0,
|
||||
IRQ_TYPE_FSLINT, /* FSL internal interrupt -- level only */
|
||||
IRQ_TYPE_FSLSPECIAL, /* FSL timer/IPI interrupt, edge, no polarity */
|
||||
} IRQType;
|
||||
|
||||
/* Round up to the nearest 64 IRQs so that the queue length
|
||||
* won't change when moving between 32 and 64 bit hosts.
|
||||
*/
|
||||
#define IRQQUEUE_SIZE_BITS ((OPENPIC_MAX_IRQ + 63) & ~63)
|
||||
|
||||
typedef struct IRQQueue {
|
||||
unsigned long *queue;
|
||||
int32_t queue_size; /* Only used for VMSTATE_BITMAP */
|
||||
int next;
|
||||
int priority;
|
||||
} IRQQueue;
|
||||
|
||||
typedef struct IRQSource {
|
||||
uint32_t ivpr; /* IRQ vector/priority register */
|
||||
uint32_t idr; /* IRQ destination register */
|
||||
uint32_t destmask; /* bitmap of CPU destinations */
|
||||
int last_cpu;
|
||||
int output; /* IRQ level, e.g. OPENPIC_OUTPUT_INT */
|
||||
int pending; /* TRUE if IRQ is pending */
|
||||
IRQType type;
|
||||
bool level:1; /* level-triggered */
|
||||
bool nomask:1; /* critical interrupts ignore mask on some FSL MPICs */
|
||||
} IRQSource;
|
||||
|
||||
#define IVPR_MASK_SHIFT 31
|
||||
#define IVPR_MASK_MASK (1U << IVPR_MASK_SHIFT)
|
||||
#define IVPR_ACTIVITY_SHIFT 30
|
||||
#define IVPR_ACTIVITY_MASK (1U << IVPR_ACTIVITY_SHIFT)
|
||||
#define IVPR_MODE_SHIFT 29
|
||||
#define IVPR_MODE_MASK (1U << IVPR_MODE_SHIFT)
|
||||
#define IVPR_POLARITY_SHIFT 23
|
||||
#define IVPR_POLARITY_MASK (1U << IVPR_POLARITY_SHIFT)
|
||||
#define IVPR_SENSE_SHIFT 22
|
||||
#define IVPR_SENSE_MASK (1U << IVPR_SENSE_SHIFT)
|
||||
|
||||
#define IVPR_PRIORITY_MASK (0xFU << 16)
|
||||
#define IVPR_PRIORITY(_ivprr_) ((int)(((_ivprr_) & IVPR_PRIORITY_MASK) >> 16))
|
||||
#define IVPR_VECTOR(opp, _ivprr_) ((_ivprr_) & (opp)->vector_mask)
|
||||
|
||||
/* IDR[EP/CI] are only for FSL MPIC prior to v4.0 */
|
||||
#define IDR_EP 0x80000000 /* external pin */
|
||||
#define IDR_CI 0x40000000 /* critical interrupt */
|
||||
|
||||
/* Convert between openpic clock ticks and nanosecs. In the hardware the clock
|
||||
frequency is driven by board inputs to the PIC which the PIC would then
|
||||
divide by 4 or 8. For now hard code to 25MZ.
|
||||
@@ -275,81 +193,6 @@ static inline uint64_t ticks_to_ns(uint64_t ticks)
|
||||
return ticks * OPENPIC_TIMER_NS_PER_TICK;
|
||||
}
|
||||
|
||||
typedef struct OpenPICTimer {
|
||||
uint32_t tccr; /* Global timer current count register */
|
||||
uint32_t tbcr; /* Global timer base count register */
|
||||
int n_IRQ;
|
||||
bool qemu_timer_active; /* Is the qemu_timer is running? */
|
||||
struct QEMUTimer *qemu_timer;
|
||||
struct OpenPICState *opp; /* Device timer is part of. */
|
||||
/* The QEMU_CLOCK_VIRTUAL time (in ns) corresponding to the last
|
||||
current_count written or read, only defined if qemu_timer_active. */
|
||||
uint64_t origin_time;
|
||||
} OpenPICTimer;
|
||||
|
||||
typedef struct OpenPICMSI {
|
||||
uint32_t msir; /* Shared Message Signaled Interrupt Register */
|
||||
} OpenPICMSI;
|
||||
|
||||
typedef struct IRQDest {
|
||||
int32_t ctpr; /* CPU current task priority */
|
||||
IRQQueue raised;
|
||||
IRQQueue servicing;
|
||||
qemu_irq *irqs;
|
||||
|
||||
/* Count of IRQ sources asserting on non-INT outputs */
|
||||
uint32_t outputs_active[OPENPIC_OUTPUT_NB];
|
||||
} IRQDest;
|
||||
|
||||
#define OPENPIC(obj) OBJECT_CHECK(OpenPICState, (obj), TYPE_OPENPIC)
|
||||
|
||||
typedef struct OpenPICState {
|
||||
/*< private >*/
|
||||
SysBusDevice parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion mem;
|
||||
|
||||
/* Behavior control */
|
||||
FslMpicInfo *fsl;
|
||||
uint32_t model;
|
||||
uint32_t flags;
|
||||
uint32_t nb_irqs;
|
||||
uint32_t vid;
|
||||
uint32_t vir; /* Vendor identification register */
|
||||
uint32_t vector_mask;
|
||||
uint32_t tfrr_reset;
|
||||
uint32_t ivpr_reset;
|
||||
uint32_t idr_reset;
|
||||
uint32_t brr1;
|
||||
uint32_t mpic_mode_mask;
|
||||
|
||||
/* Sub-regions */
|
||||
MemoryRegion sub_io_mem[6];
|
||||
|
||||
/* Global registers */
|
||||
uint32_t frr; /* Feature reporting register */
|
||||
uint32_t gcr; /* Global configuration register */
|
||||
uint32_t pir; /* Processor initialization register */
|
||||
uint32_t spve; /* Spurious vector register */
|
||||
uint32_t tfrr; /* Timer frequency reporting register */
|
||||
/* Source registers */
|
||||
IRQSource src[OPENPIC_MAX_IRQ];
|
||||
/* Local registers per output pin */
|
||||
IRQDest dst[MAX_CPU];
|
||||
uint32_t nb_cpus;
|
||||
/* Timer registers */
|
||||
OpenPICTimer timers[OPENPIC_MAX_TMR];
|
||||
uint32_t max_tmr;
|
||||
|
||||
/* Shared MSI registers */
|
||||
OpenPICMSI msi[MAX_MSI];
|
||||
uint32_t max_irq;
|
||||
uint32_t irq_ipi0;
|
||||
uint32_t irq_tim0;
|
||||
uint32_t irq_msi;
|
||||
} OpenPICState;
|
||||
|
||||
static inline void IRQ_setbit(IRQQueue *q, int n_IRQ)
|
||||
{
|
||||
set_bit(n_IRQ, q->queue);
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "exec/address-spaces.h"
|
||||
#include "hw/hw.h"
|
||||
#include "hw/ppc/openpic.h"
|
||||
#include "hw/ppc/openpic_kvm.h"
|
||||
#include "hw/pci/msi.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
@@ -186,3 +186,8 @@ nvic_complete_irq(int irq, bool secure) "NVIC complete IRQ %d (secure %d)"
|
||||
nvic_set_irq_level(int irq, int level) "NVIC external irq %d level set to %d"
|
||||
nvic_sysreg_read(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg read addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
|
||||
nvic_sysreg_write(uint64_t addr, uint32_t value, unsigned size) "NVIC sysreg write addr 0x%" PRIx64 " data 0x%" PRIx32 " size %u"
|
||||
|
||||
# hw/intc/heathrow_pic.c
|
||||
heathrow_write(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
|
||||
heathrow_read(uint64_t addr, unsigned int n, uint64_t value) "0x%"PRIx64" %u: 0x%"PRIx64
|
||||
heathrow_set_irq(int num, int level) "set_irq: num=0x%02x level=%d"
|
||||
|
||||
+69
-81
@@ -30,48 +30,11 @@
|
||||
#include "hw/pci/pci.h"
|
||||
#include "hw/ppc/mac_dbdma.h"
|
||||
#include "hw/char/escc.h"
|
||||
#include "hw/misc/macio/macio.h"
|
||||
#include "hw/intc/heathrow_pic.h"
|
||||
|
||||
#define TYPE_MACIO "macio"
|
||||
#define MACIO(obj) OBJECT_CHECK(MacIOState, (obj), TYPE_MACIO)
|
||||
|
||||
typedef struct MacIOState
|
||||
{
|
||||
/*< private >*/
|
||||
PCIDevice parent;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion bar;
|
||||
CUDAState cuda;
|
||||
DBDMAState *dbdma;
|
||||
MemoryRegion *pic_mem;
|
||||
MemoryRegion *escc_mem;
|
||||
uint64_t frequency;
|
||||
} MacIOState;
|
||||
|
||||
#define OLDWORLD_MACIO(obj) \
|
||||
OBJECT_CHECK(OldWorldMacIOState, (obj), TYPE_OLDWORLD_MACIO)
|
||||
|
||||
typedef struct OldWorldMacIOState {
|
||||
/*< private >*/
|
||||
MacIOState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
qemu_irq irqs[5];
|
||||
|
||||
MacIONVRAMState nvram;
|
||||
MACIOIDEState ide[2];
|
||||
} OldWorldMacIOState;
|
||||
|
||||
#define NEWWORLD_MACIO(obj) \
|
||||
OBJECT_CHECK(NewWorldMacIOState, (obj), TYPE_NEWWORLD_MACIO)
|
||||
|
||||
typedef struct NewWorldMacIOState {
|
||||
/*< private >*/
|
||||
MacIOState parent_obj;
|
||||
/*< public >*/
|
||||
qemu_irq irqs[5];
|
||||
MACIOIDEState ide[2];
|
||||
} NewWorldMacIOState;
|
||||
/* Note: this code is strongly inspirated from the corresponding code
|
||||
* in PearPC */
|
||||
|
||||
/*
|
||||
* The mac-io has two interfaces to the ESCC. One is called "escc-legacy",
|
||||
@@ -84,10 +47,12 @@ typedef struct NewWorldMacIOState {
|
||||
*
|
||||
* Reference: ftp://ftp.software.ibm.com/rs6000/technology/spec/chrp/inwork/CHRP_IORef_1.0.pdf
|
||||
*/
|
||||
static void macio_escc_legacy_setup(MacIOState *macio_state)
|
||||
static void macio_escc_legacy_setup(MacIOState *s)
|
||||
{
|
||||
ESCCState *escc = ESCC(&s->escc);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(escc);
|
||||
MemoryRegion *escc_legacy = g_new(MemoryRegion, 1);
|
||||
MemoryRegion *bar = &macio_state->bar;
|
||||
MemoryRegion *bar = &s->bar;
|
||||
int i;
|
||||
static const int maps[] = {
|
||||
0x00, 0x00, /* Command B */
|
||||
@@ -102,25 +67,26 @@ static void macio_escc_legacy_setup(MacIOState *macio_state)
|
||||
0xb0, 0xb0, /* Detect AB */
|
||||
};
|
||||
|
||||
memory_region_init(escc_legacy, OBJECT(macio_state), "escc-legacy", 256);
|
||||
memory_region_init(escc_legacy, OBJECT(s), "escc-legacy", 256);
|
||||
for (i = 0; i < ARRAY_SIZE(maps); i += 2) {
|
||||
MemoryRegion *port = g_new(MemoryRegion, 1);
|
||||
memory_region_init_alias(port, OBJECT(macio_state), "escc-legacy-port",
|
||||
macio_state->escc_mem, maps[i+1], 0x2);
|
||||
memory_region_init_alias(port, OBJECT(s), "escc-legacy-port",
|
||||
sysbus_mmio_get_region(sbd, 0),
|
||||
maps[i + 1], 0x2);
|
||||
memory_region_add_subregion(escc_legacy, maps[i], port);
|
||||
}
|
||||
|
||||
memory_region_add_subregion(bar, 0x12000, escc_legacy);
|
||||
}
|
||||
|
||||
static void macio_bar_setup(MacIOState *macio_state)
|
||||
static void macio_bar_setup(MacIOState *s)
|
||||
{
|
||||
MemoryRegion *bar = &macio_state->bar;
|
||||
ESCCState *escc = ESCC(&s->escc);
|
||||
SysBusDevice *sbd = SYS_BUS_DEVICE(escc);
|
||||
MemoryRegion *bar = &s->bar;
|
||||
|
||||
if (macio_state->escc_mem) {
|
||||
memory_region_add_subregion(bar, 0x13000, macio_state->escc_mem);
|
||||
macio_escc_legacy_setup(macio_state);
|
||||
}
|
||||
memory_region_add_subregion(bar, 0x13000, sysbus_mmio_get_region(sbd, 0));
|
||||
macio_escc_legacy_setup(s);
|
||||
}
|
||||
|
||||
static void macio_common_realize(PCIDevice *d, Error **errp)
|
||||
@@ -129,15 +95,17 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
|
||||
SysBusDevice *sysbus_dev;
|
||||
Error *err = NULL;
|
||||
|
||||
object_property_set_bool(OBJECT(s->dbdma), true, "realized", &err);
|
||||
object_property_set_bool(OBJECT(&s->dbdma), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
sysbus_dev = SYS_BUS_DEVICE(s->dbdma);
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->dbdma);
|
||||
memory_region_add_subregion(&s->bar, 0x08000,
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
qdev_prop_set_uint64(DEVICE(&s->cuda), "timebase-frequency",
|
||||
s->frequency);
|
||||
object_property_set_bool(OBJECT(&s->cuda), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
@@ -147,6 +115,12 @@ static void macio_common_realize(PCIDevice *d, Error **errp)
|
||||
memory_region_add_subregion(&s->bar, 0x16000,
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
object_property_set_bool(OBJECT(&s->escc), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
return;
|
||||
}
|
||||
|
||||
macio_bar_setup(s);
|
||||
pci_register_bar(d, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar);
|
||||
}
|
||||
@@ -161,7 +135,7 @@ static void macio_realize_ide(MacIOState *s, MACIOIDEState *ide,
|
||||
sysbus_connect_irq(sysbus_dev, 0, irq0);
|
||||
sysbus_connect_irq(sysbus_dev, 1, irq1);
|
||||
qdev_prop_set_uint32(DEVICE(ide), "channel", dmaid);
|
||||
object_property_set_link(OBJECT(ide), OBJECT(s->dbdma), "dbdma", errp);
|
||||
object_property_set_link(OBJECT(ide), OBJECT(&s->dbdma), "dbdma", errp);
|
||||
macio_ide_register_dma(ide);
|
||||
|
||||
object_property_set_bool(OBJECT(ide), true, "realized", errp);
|
||||
@@ -185,6 +159,10 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp)
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
|
||||
sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
|
||||
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->escc);
|
||||
sysbus_connect_irq(sysbus_dev, 0, os->irqs[cur_irq++]);
|
||||
sysbus_connect_irq(sysbus_dev, 1, os->irqs[cur_irq++]);
|
||||
|
||||
object_property_set_bool(OBJECT(&os->nvram), true, "realized", &err);
|
||||
if (err) {
|
||||
error_propagate(errp, err);
|
||||
@@ -195,10 +173,10 @@ static void macio_oldworld_realize(PCIDevice *d, Error **errp)
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
pmac_format_nvram_partition(&os->nvram, os->nvram.size);
|
||||
|
||||
if (s->pic_mem) {
|
||||
/* Heathrow PIC */
|
||||
memory_region_add_subregion(&s->bar, 0x00000, s->pic_mem);
|
||||
}
|
||||
/* Heathrow PIC */
|
||||
sysbus_dev = SYS_BUS_DEVICE(os->pic);
|
||||
memory_region_add_subregion(&s->bar, 0x0,
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
/* IDE buses */
|
||||
for (i = 0; i < ARRAY_SIZE(os->ide); i++) {
|
||||
@@ -236,6 +214,11 @@ static void macio_oldworld_init(Object *obj)
|
||||
|
||||
qdev_init_gpio_out(DEVICE(obj), os->irqs, ARRAY_SIZE(os->irqs));
|
||||
|
||||
object_property_add_link(obj, "pic", TYPE_HEATHROW,
|
||||
(Object **) &os->pic,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
0, NULL);
|
||||
|
||||
object_initialize(&os->nvram, sizeof(os->nvram), TYPE_MACIO_NVRAM);
|
||||
dev = DEVICE(&os->nvram);
|
||||
qdev_prop_set_uint32(dev, "size", 0x2000);
|
||||
@@ -297,10 +280,14 @@ static void macio_newworld_realize(PCIDevice *d, Error **errp)
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->cuda);
|
||||
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
|
||||
|
||||
if (s->pic_mem) {
|
||||
/* OpenPIC */
|
||||
memory_region_add_subregion(&s->bar, 0x40000, s->pic_mem);
|
||||
}
|
||||
sysbus_dev = SYS_BUS_DEVICE(&s->escc);
|
||||
sysbus_connect_irq(sysbus_dev, 0, ns->irqs[cur_irq++]);
|
||||
sysbus_connect_irq(sysbus_dev, 1, ns->irqs[cur_irq++]);
|
||||
|
||||
/* OpenPIC */
|
||||
sysbus_dev = SYS_BUS_DEVICE(ns->pic);
|
||||
memory_region_add_subregion(&s->bar, 0x40000,
|
||||
sysbus_mmio_get_region(sysbus_dev, 0));
|
||||
|
||||
/* IDE buses */
|
||||
for (i = 0; i < ARRAY_SIZE(ns->ide); i++) {
|
||||
@@ -329,6 +316,11 @@ static void macio_newworld_init(Object *obj)
|
||||
|
||||
qdev_init_gpio_out(DEVICE(obj), ns->irqs, ARRAY_SIZE(ns->irqs));
|
||||
|
||||
object_property_add_link(obj, "pic", TYPE_OPENPIC,
|
||||
(Object **) &ns->pic,
|
||||
qdev_prop_allow_set_link_before_realize,
|
||||
0, NULL);
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
macio_init_ide(s, &ns->ide[i], sizeof(ns->ide[i]), i);
|
||||
}
|
||||
@@ -344,8 +336,20 @@ static void macio_instance_init(Object *obj)
|
||||
qdev_set_parent_bus(DEVICE(&s->cuda), sysbus_get_default());
|
||||
object_property_add_child(obj, "cuda", OBJECT(&s->cuda), NULL);
|
||||
|
||||
s->dbdma = MAC_DBDMA(object_new(TYPE_MAC_DBDMA));
|
||||
object_property_add_child(obj, "dbdma", OBJECT(s->dbdma), NULL);
|
||||
object_initialize(&s->dbdma, sizeof(s->dbdma), TYPE_MAC_DBDMA);
|
||||
qdev_set_parent_bus(DEVICE(&s->dbdma), sysbus_get_default());
|
||||
object_property_add_child(obj, "dbdma", OBJECT(&s->dbdma), NULL);
|
||||
|
||||
object_initialize(&s->escc, sizeof(s->escc), TYPE_ESCC);
|
||||
qdev_prop_set_uint32(DEVICE(&s->escc), "disabled", 0);
|
||||
qdev_prop_set_uint32(DEVICE(&s->escc), "frequency", ESCC_CLOCK);
|
||||
qdev_prop_set_uint32(DEVICE(&s->escc), "it_shift", 4);
|
||||
qdev_prop_set_chr(DEVICE(&s->escc), "chrA", serial_hds[0]);
|
||||
qdev_prop_set_chr(DEVICE(&s->escc), "chrB", serial_hds[1]);
|
||||
qdev_prop_set_uint32(DEVICE(&s->escc), "chnBtype", escc_serial);
|
||||
qdev_prop_set_uint32(DEVICE(&s->escc), "chnAtype", escc_serial);
|
||||
qdev_set_parent_bus(DEVICE(&s->escc), sysbus_get_default());
|
||||
object_property_add_child(obj, "escc", OBJECT(&s->escc), NULL);
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_macio_oldworld = {
|
||||
@@ -441,19 +445,3 @@ static void macio_register_types(void)
|
||||
}
|
||||
|
||||
type_init(macio_register_types)
|
||||
|
||||
void macio_init(PCIDevice *d,
|
||||
MemoryRegion *pic_mem,
|
||||
MemoryRegion *escc_mem)
|
||||
{
|
||||
MacIOState *macio_state = MACIO(d);
|
||||
|
||||
macio_state->pic_mem = pic_mem;
|
||||
macio_state->escc_mem = escc_mem;
|
||||
/* Note: this code is strongly inspirated from the corresponding code
|
||||
in PearPC */
|
||||
qdev_prop_set_uint64(DEVICE(&macio_state->cuda), "timebase-frequency",
|
||||
macio_state->frequency);
|
||||
|
||||
qdev_init_nofail(DEVICE(d));
|
||||
}
|
||||
|
||||
@@ -13,7 +13,8 @@ endif
|
||||
obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
|
||||
# PowerPC 4xx boards
|
||||
obj-y += ppc4xx_devs.o ppc405_uc.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o ppc440_bamboo.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o
|
||||
obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o sam460ex.o
|
||||
# PReP
|
||||
obj-$(CONFIG_PREP) += prep.o
|
||||
obj-$(CONFIG_PREP) += prep_systemio.o
|
||||
|
||||
+78
-46
@@ -29,6 +29,7 @@
|
||||
#include "kvm_ppc.h"
|
||||
#include "sysemu/device_tree.h"
|
||||
#include "hw/ppc/openpic.h"
|
||||
#include "hw/ppc/openpic_kvm.h"
|
||||
#include "hw/ppc/ppc.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
@@ -119,7 +120,14 @@ static void dt_serial_create(void *fdt, unsigned long long offset,
|
||||
qemu_fdt_setprop_string(fdt, "/aliases", alias, ser);
|
||||
|
||||
if (defcon) {
|
||||
/*
|
||||
* "linux,stdout-path" and "stdout" properties are deprecated by linux
|
||||
* kernel. New platforms should only use the "stdout-path" property. Set
|
||||
* the new property and continue using older property to remain
|
||||
* compatible with the existing firmware.
|
||||
*/
|
||||
qemu_fdt_setprop_string(fdt, "/chosen", "linux,stdout-path", ser);
|
||||
qemu_fdt_setprop_string(fdt, "/chosen", "stdout-path", ser);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -784,8 +792,10 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
|
||||
int initrd_size = 0;
|
||||
hwaddr cur_base = 0;
|
||||
char *filename;
|
||||
const char *payload_name;
|
||||
bool kernel_as_payload;
|
||||
hwaddr bios_entry = 0;
|
||||
target_long bios_size;
|
||||
target_long payload_size;
|
||||
struct boot_info *boot_info;
|
||||
int dt_size;
|
||||
int i;
|
||||
@@ -913,11 +923,6 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
|
||||
/* Register spinning region */
|
||||
sysbus_create_simple("e500-spin", params->spin_base, NULL);
|
||||
|
||||
if (cur_base < (32 * 1024 * 1024)) {
|
||||
/* u-boot occupies memory up to 32MB, so load blobs above */
|
||||
cur_base = (32 * 1024 * 1024);
|
||||
}
|
||||
|
||||
if (params->has_mpc8xxx_gpio) {
|
||||
qemu_irq poweroff_irq;
|
||||
|
||||
@@ -952,8 +957,61 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
|
||||
sysbus_mmio_get_region(s, 0));
|
||||
}
|
||||
|
||||
/* Load kernel. */
|
||||
if (machine->kernel_filename) {
|
||||
/*
|
||||
* Smart firmware defaults ahead!
|
||||
*
|
||||
* We follow the following table to select which payload we execute.
|
||||
*
|
||||
* -kernel | -bios | payload
|
||||
* ---------+-------+---------
|
||||
* N | Y | u-boot
|
||||
* N | N | u-boot
|
||||
* Y | Y | u-boot
|
||||
* Y | N | kernel
|
||||
*
|
||||
* This ensures backwards compatibility with how we used to expose
|
||||
* -kernel to users but allows them to run through u-boot as well.
|
||||
*/
|
||||
kernel_as_payload = false;
|
||||
if (bios_name == NULL) {
|
||||
if (machine->kernel_filename) {
|
||||
payload_name = machine->kernel_filename;
|
||||
kernel_as_payload = true;
|
||||
} else {
|
||||
payload_name = "u-boot.e500";
|
||||
}
|
||||
} else {
|
||||
payload_name = bios_name;
|
||||
}
|
||||
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, payload_name);
|
||||
|
||||
payload_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
|
||||
1, PPC_ELF_MACHINE, 0, 0);
|
||||
if (payload_size < 0) {
|
||||
/*
|
||||
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
|
||||
* ePAPR compliant kernel
|
||||
*/
|
||||
payload_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
|
||||
NULL, NULL);
|
||||
if (payload_size < 0) {
|
||||
error_report("qemu: could not load firmware '%s'", filename);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
g_free(filename);
|
||||
|
||||
if (kernel_as_payload) {
|
||||
kernel_base = loadaddr;
|
||||
kernel_size = payload_size;
|
||||
}
|
||||
|
||||
cur_base = loadaddr + payload_size;
|
||||
|
||||
/* Load bare kernel only if no bios/u-boot has been provided */
|
||||
if (machine->kernel_filename && !kernel_as_payload) {
|
||||
kernel_base = cur_base;
|
||||
kernel_size = load_image_targphys(machine->kernel_filename,
|
||||
cur_base,
|
||||
@@ -967,6 +1025,11 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
|
||||
cur_base += kernel_size;
|
||||
}
|
||||
|
||||
if (cur_base < (32 * 1024 * 1024)) {
|
||||
/* u-boot occupies memory up to 32MB, so load blobs above */
|
||||
cur_base = (32 * 1024 * 1024);
|
||||
}
|
||||
|
||||
/* Load initrd. */
|
||||
if (machine->initrd_filename) {
|
||||
initrd_base = (cur_base + INITRD_LOAD_PAD) & ~INITRD_PAD_MASK;
|
||||
@@ -983,47 +1046,16 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
|
||||
}
|
||||
|
||||
/*
|
||||
* Smart firmware defaults ahead!
|
||||
*
|
||||
* We follow the following table to select which payload we execute.
|
||||
*
|
||||
* -kernel | -bios | payload
|
||||
* ---------+-------+---------
|
||||
* N | Y | u-boot
|
||||
* N | N | u-boot
|
||||
* Y | Y | u-boot
|
||||
* Y | N | kernel
|
||||
*
|
||||
* This ensures backwards compatibility with how we used to expose
|
||||
* -kernel to users but allows them to run through u-boot as well.
|
||||
* Reserve space for dtb behind the kernel image because Linux has a bug
|
||||
* where it can only handle the dtb if it's within the first 64MB of where
|
||||
* <kernel> starts. dtb cannot not reach initrd_base because INITRD_LOAD_PAD
|
||||
* ensures enough space between kernel and initrd.
|
||||
*/
|
||||
if (bios_name == NULL) {
|
||||
if (machine->kernel_filename) {
|
||||
bios_name = machine->kernel_filename;
|
||||
} else {
|
||||
bios_name = "u-boot.e500";
|
||||
}
|
||||
}
|
||||
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
|
||||
|
||||
bios_size = load_elf(filename, NULL, NULL, &bios_entry, &loadaddr, NULL,
|
||||
1, PPC_ELF_MACHINE, 0, 0);
|
||||
if (bios_size < 0) {
|
||||
/*
|
||||
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
|
||||
* ePAPR compliant kernel
|
||||
*/
|
||||
kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
|
||||
NULL, NULL);
|
||||
if (kernel_size < 0) {
|
||||
error_report("could not load firmware '%s'", filename);
|
||||
dt_base = (loadaddr + payload_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
|
||||
if (dt_base + DTB_MAX_SIZE > ram_size) {
|
||||
error_report("qemu: not enough memory for device tree");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
g_free(filename);
|
||||
|
||||
/* Reserve space for dtb */
|
||||
dt_base = (loadaddr + bios_size + DTC_LOAD_PAD) & ~DTC_PAD_MASK;
|
||||
|
||||
dt_size = ppce500_prep_device_tree(machine, params, dt_base,
|
||||
initrd_base, initrd_size,
|
||||
|
||||
+3
-7
@@ -47,9 +47,6 @@
|
||||
|
||||
|
||||
/* MacIO */
|
||||
#define TYPE_OLDWORLD_MACIO "macio-oldworld"
|
||||
#define TYPE_NEWWORLD_MACIO "macio-newworld"
|
||||
|
||||
#define TYPE_MACIO_IDE "macio-ide"
|
||||
#define MACIO_IDE(obj) OBJECT_CHECK(MACIOIDEState, (obj), TYPE_MACIO_IDE)
|
||||
|
||||
@@ -76,12 +73,11 @@ void macio_ide_init_drives(MACIOIDEState *ide, DriveInfo **hd_table);
|
||||
void macio_ide_register_dma(MACIOIDEState *ide);
|
||||
|
||||
void macio_init(PCIDevice *dev,
|
||||
MemoryRegion *pic_mem,
|
||||
MemoryRegion *escc_mem);
|
||||
MemoryRegion *pic_mem);
|
||||
|
||||
/* Heathrow PIC */
|
||||
qemu_irq *heathrow_pic_init(MemoryRegion **pmem,
|
||||
int nb_cpus, qemu_irq **irqs);
|
||||
DeviceState *heathrow_pic_init(int nb_cpus, qemu_irq **irqs,
|
||||
qemu_irq **pic_irqs);
|
||||
|
||||
/* Grackle PCI */
|
||||
#define TYPE_GRACKLE_PCI_HOST_BRIDGE "grackle-pcihost"
|
||||
|
||||
+19
-37
@@ -60,6 +60,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "hw/char/escc.h"
|
||||
#include "hw/misc/macio/macio.h"
|
||||
#include "hw/ppc/openpic.h"
|
||||
#include "hw/ide.h"
|
||||
#include "hw/loader.h"
|
||||
@@ -153,20 +154,18 @@ static void ppc_core99_init(MachineState *machine)
|
||||
hwaddr kernel_base, initrd_base, cmdline_base = 0;
|
||||
long kernel_size, initrd_size;
|
||||
PCIBus *pci_bus;
|
||||
PCIDevice *macio;
|
||||
NewWorldMacIOState *macio;
|
||||
MACIOIDEState *macio_ide;
|
||||
BusState *adb_bus;
|
||||
MacIONVRAMState *nvr;
|
||||
int bios_size, ndrv_size;
|
||||
uint8_t *ndrv_file;
|
||||
MemoryRegion *pic_mem, *escc_mem;
|
||||
MemoryRegion *escc_bar = g_new(MemoryRegion, 1);
|
||||
int ppc_boot_device;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
void *fw_cfg;
|
||||
int machine_arch;
|
||||
SysBusDevice *s;
|
||||
DeviceState *dev;
|
||||
DeviceState *dev, *pic_dev;
|
||||
int *token = g_new(int, 1);
|
||||
hwaddr nvram_addr = 0xFFF04000;
|
||||
uint64_t tbfreq;
|
||||
@@ -333,11 +332,10 @@ static void ppc_core99_init(MachineState *machine)
|
||||
|
||||
pic = g_new0(qemu_irq, 64);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_OPENPIC);
|
||||
qdev_prop_set_uint32(dev, "model", OPENPIC_MODEL_KEYLARGO);
|
||||
qdev_init_nofail(dev);
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
pic_mem = s->mmio[0].memory;
|
||||
pic_dev = qdev_create(NULL, TYPE_OPENPIC);
|
||||
qdev_prop_set_uint32(pic_dev, "model", OPENPIC_MODEL_KEYLARGO);
|
||||
qdev_init_nofail(pic_dev);
|
||||
s = SYS_BUS_DEVICE(pic_dev);
|
||||
k = 0;
|
||||
for (i = 0; i < smp_cpus; i++) {
|
||||
for (j = 0; j < OPENPIC_OUTPUT_NB; j++) {
|
||||
@@ -346,7 +344,7 @@ static void ppc_core99_init(MachineState *machine)
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
pic[i] = qdev_get_gpio_in(dev, i);
|
||||
pic[i] = qdev_get_gpio_in(pic_dev, i);
|
||||
}
|
||||
|
||||
if (PPC_INPUT(env) == PPC_FLAGS_INPUT_970) {
|
||||
@@ -368,36 +366,20 @@ static void ppc_core99_init(MachineState *machine)
|
||||
tbfreq = TBFREQ;
|
||||
}
|
||||
|
||||
/* init basic PC hardware */
|
||||
|
||||
dev = qdev_create(NULL, TYPE_ESCC);
|
||||
qdev_prop_set_uint32(dev, "disabled", 0);
|
||||
qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK);
|
||||
qdev_prop_set_uint32(dev, "it_shift", 4);
|
||||
qdev_prop_set_chr(dev, "chrA", serial_hds[0]);
|
||||
qdev_prop_set_chr(dev, "chrB", serial_hds[1]);
|
||||
qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
|
||||
qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_connect_irq(s, 0, pic[0x24]);
|
||||
sysbus_connect_irq(s, 1, pic[0x25]);
|
||||
|
||||
escc_mem = &ESCC(s)->mmio;
|
||||
|
||||
memory_region_init_alias(escc_bar, NULL, "escc-bar",
|
||||
escc_mem, 0, memory_region_size(escc_mem));
|
||||
|
||||
macio = pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO);
|
||||
/* MacIO */
|
||||
macio = NEWWORLD_MACIO(pci_create(pci_bus, -1, TYPE_NEWWORLD_MACIO));
|
||||
dev = DEVICE(macio);
|
||||
qdev_connect_gpio_out(dev, 0, pic[0x19]); /* CUDA */
|
||||
qdev_connect_gpio_out(dev, 1, pic[0x0d]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE DMA */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0e]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE DMA */
|
||||
qdev_connect_gpio_out(dev, 1, pic[0x24]); /* ESCC-B */
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x25]); /* ESCC-A */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0d]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE DMA */
|
||||
qdev_connect_gpio_out(dev, 5, pic[0x0e]); /* IDE */
|
||||
qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE DMA */
|
||||
qdev_prop_set_uint64(dev, "frequency", tbfreq);
|
||||
macio_init(macio, pic_mem, escc_bar);
|
||||
object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
|
||||
&error_abort);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
/* We only emulate 2 out of 3 IDE controllers for now */
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
+17
-33
@@ -37,6 +37,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "hw/nvram/fw_cfg.h"
|
||||
#include "hw/char/escc.h"
|
||||
#include "hw/misc/macio/macio.h"
|
||||
#include "hw/ide.h"
|
||||
#include "hw/loader.h"
|
||||
#include "elf.h"
|
||||
@@ -92,19 +93,16 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
uint32_t kernel_base, initrd_base, cmdline_base = 0;
|
||||
int32_t kernel_size, initrd_size;
|
||||
PCIBus *pci_bus;
|
||||
PCIDevice *macio;
|
||||
OldWorldMacIOState *macio;
|
||||
MACIOIDEState *macio_ide;
|
||||
DeviceState *dev;
|
||||
DeviceState *dev, *pic_dev;
|
||||
BusState *adb_bus;
|
||||
int bios_size, ndrv_size;
|
||||
uint8_t *ndrv_file;
|
||||
MemoryRegion *pic_mem;
|
||||
MemoryRegion *escc_mem, *escc_bar = g_new(MemoryRegion, 1);
|
||||
uint16_t ppc_boot_device;
|
||||
DriveInfo *hd[MAX_IDE_BUS * MAX_IDE_DEVS];
|
||||
void *fw_cfg;
|
||||
uint64_t tbfreq;
|
||||
SysBusDevice *s;
|
||||
|
||||
linux_boot = (kernel_filename != NULL);
|
||||
|
||||
@@ -259,46 +257,32 @@ static void ppc_heathrow_init(MachineState *machine)
|
||||
error_report("Only 6xx bus is supported on heathrow machine");
|
||||
exit(1);
|
||||
}
|
||||
pic = heathrow_pic_init(&pic_mem, 1, heathrow_irqs);
|
||||
pic_dev = heathrow_pic_init(1, heathrow_irqs, &pic);
|
||||
pci_bus = pci_grackle_init(0xfec00000, pic,
|
||||
get_system_memory(),
|
||||
get_system_io());
|
||||
pci_vga_init(pci_bus);
|
||||
|
||||
dev = qdev_create(NULL, TYPE_ESCC);
|
||||
qdev_prop_set_uint32(dev, "disabled", 0);
|
||||
qdev_prop_set_uint32(dev, "frequency", ESCC_CLOCK);
|
||||
qdev_prop_set_uint32(dev, "it_shift", 4);
|
||||
qdev_prop_set_chr(dev, "chrA", serial_hds[0]);
|
||||
qdev_prop_set_chr(dev, "chrB", serial_hds[1]);
|
||||
qdev_prop_set_uint32(dev, "chnBtype", escc_serial);
|
||||
qdev_prop_set_uint32(dev, "chnAtype", escc_serial);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
s = SYS_BUS_DEVICE(dev);
|
||||
sysbus_connect_irq(s, 0, pic[0x10]);
|
||||
sysbus_connect_irq(s, 1, pic[0x0f]);
|
||||
|
||||
escc_mem = &ESCC(s)->mmio;
|
||||
|
||||
memory_region_init_alias(escc_bar, NULL, "escc-bar",
|
||||
escc_mem, 0, memory_region_size(escc_mem));
|
||||
|
||||
for(i = 0; i < nb_nics; i++)
|
||||
for (i = 0; i < nb_nics; i++) {
|
||||
pci_nic_init_nofail(&nd_table[i], pci_bus, "ne2k_pci", NULL);
|
||||
|
||||
}
|
||||
|
||||
ide_drive_get(hd, ARRAY_SIZE(hd));
|
||||
|
||||
macio = pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO);
|
||||
/* MacIO */
|
||||
macio = OLDWORLD_MACIO(pci_create(pci_bus, -1, TYPE_OLDWORLD_MACIO));
|
||||
dev = DEVICE(macio);
|
||||
qdev_connect_gpio_out(dev, 0, pic[0x12]); /* CUDA */
|
||||
qdev_connect_gpio_out(dev, 1, pic[0x0D]); /* IDE-0 */
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x02]); /* IDE-0 DMA */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0E]); /* IDE-1 */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x03]); /* IDE-1 DMA */
|
||||
qdev_connect_gpio_out(dev, 1, pic[0x10]); /* ESCC-B */
|
||||
qdev_connect_gpio_out(dev, 2, pic[0x0F]); /* ESCC-A */
|
||||
qdev_connect_gpio_out(dev, 3, pic[0x0D]); /* IDE-0 */
|
||||
qdev_connect_gpio_out(dev, 4, pic[0x02]); /* IDE-0 DMA */
|
||||
qdev_connect_gpio_out(dev, 5, pic[0x0E]); /* IDE-1 */
|
||||
qdev_connect_gpio_out(dev, 6, pic[0x03]); /* IDE-1 DMA */
|
||||
qdev_prop_set_uint64(dev, "frequency", tbfreq);
|
||||
macio_init(macio, pic_mem, escc_bar);
|
||||
object_property_set_link(OBJECT(macio), OBJECT(pic_dev), "pic",
|
||||
&error_abort);
|
||||
qdev_init_nofail(dev);
|
||||
|
||||
macio_ide = MACIO_IDE(object_resolve_path_component(OBJECT(macio),
|
||||
"ide[0]"));
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1050,6 +1050,9 @@ static void ppc460ex_pcie_realize(DeviceState *dev, Error **errp)
|
||||
case DCRN_PCIE1_BASE:
|
||||
id = 1;
|
||||
break;
|
||||
default:
|
||||
error_setg(errp, "invalid PCIe DCRN base");
|
||||
return;
|
||||
}
|
||||
snprintf(buf, sizeof(buf), "pcie%d-io", id);
|
||||
memory_region_init(&s->iomem, OBJECT(s), buf, UINT64_MAX);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user