aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2012-03-17 12:59:23 +0000
committerBlue Swirl <blauwirbel@gmail.com>2012-03-17 12:59:23 +0000
commitcb76e9c7b7e9fe8786be2ef729636b264fe1d63a (patch)
treec5e38019a45fc629cbd8101e739b01b4d1cc16f3
parent1329d1896cc627cf71e3833525152ff59dd5113b (diff)
parent38ae51a804a6ad2baec3e45ecb1571583b312441 (diff)
Merge branch 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf
* 'ppc-for-upstream' of git://repo.or.cz/qemu/agraf: PPC: Fix openpic with relative memregions pseries: Configure PCI bridge using properties PPC: KVM: Synchronize regs on CPU dump kvm: Comparison with ioctl number macros needs to be unsigned ppc: Correctly define POWERPC_INSNS2_DEFAULT pseries: Add support for level interrupts to XICS PPC: Fix large page support in TCG PPC: Add PIR register to POWER7 CPU pseries: Remove PCI device from PCI host bridge code pseries: Remove unused constant from PCI code pseries: Update SLOF firmware image PPC64: Add support for ldbrx and stdbrx instructions pseries: Don't try to munmap() a malloc()ed TCE table ppc: Add missing 'static' to spin_rw_ops PPC: 405: Fix ppc405ep initialization Bad zero comparison for sas_ss_flags on powerpc
-rw-r--r--hw/openpic.c12
-rw-r--r--hw/ppc405_uc.c2
-rw-r--r--hw/ppce500_spin.c2
-rw-r--r--hw/spapr.c5
-rw-r--r--hw/spapr.h13
-rw-r--r--hw/spapr_pci.c193
-rw-r--r--hw/spapr_pci.h4
-rw-r--r--hw/spapr_vio.c2
-rw-r--r--hw/xics.c125
-rw-r--r--hw/xics.h8
-rw-r--r--kvm-all.c5
-rw-r--r--linux-user/signal.c2
-rw-r--r--pc-bios/README2
-rw-r--r--pc-bios/slof.binbin869584 -> 880496 bytes
m---------roms/SLOF0
-rw-r--r--target-ppc/cpu.h4
-rw-r--r--target-ppc/helper.c12
-rw-r--r--target-ppc/kvm.c12
-rw-r--r--target-ppc/translate.c54
-rw-r--r--target-ppc/translate_init.c11
20 files changed, 293 insertions, 175 deletions
diff --git a/hw/openpic.c b/hw/openpic.c
index 280b7a9bb..58ef871f6 100644
--- a/hw/openpic.c
+++ b/hw/openpic.c
@@ -713,7 +713,7 @@ static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
if (addr & 0xF)
return;
- addr -= 0x1100;
+ addr -= 0x10;
addr &= 0xFFFF;
idx = (addr & 0xFFF0) >> 6;
addr = addr & 0x30;
@@ -746,7 +746,7 @@ static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
retval = 0xFFFFFFFF;
if (addr & 0xF)
return retval;
- addr -= 0x1100;
+ addr -= 0x10;
addr &= 0xFFFF;
idx = (addr & 0xFFF0) >> 6;
addr = addr & 0x30;
@@ -1361,7 +1361,6 @@ static void mpic_src_ext_write (void *opaque, target_phys_addr_t addr,
if (addr & 0xF)
return;
- addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_EXT_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1385,7 +1384,6 @@ static uint32_t mpic_src_ext_read (void *opaque, target_phys_addr_t addr)
if (addr & 0xF)
return retval;
- addr -= MPIC_EXT_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_EXT_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1411,7 +1409,6 @@ static void mpic_src_int_write (void *opaque, target_phys_addr_t addr,
if (addr & 0xF)
return;
- addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_INT_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1435,7 +1432,6 @@ static uint32_t mpic_src_int_read (void *opaque, target_phys_addr_t addr)
if (addr & 0xF)
return retval;
- addr -= MPIC_INT_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_INT_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1461,7 +1457,6 @@ static void mpic_src_msg_write (void *opaque, target_phys_addr_t addr,
if (addr & 0xF)
return;
- addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_MSG_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1485,7 +1480,6 @@ static uint32_t mpic_src_msg_read (void *opaque, target_phys_addr_t addr)
if (addr & 0xF)
return retval;
- addr -= MPIC_MSG_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_MSG_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1511,7 +1505,6 @@ static void mpic_src_msi_write (void *opaque, target_phys_addr_t addr,
if (addr & 0xF)
return;
- addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_MSI_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
@@ -1534,7 +1527,6 @@ static uint32_t mpic_src_msi_read (void *opaque, target_phys_addr_t addr)
if (addr & 0xF)
return retval;
- addr -= MPIC_MSI_REG_START & (OPENPIC_PAGE_SIZE - 1);
if (addr < MPIC_MSI_REG_SIZE) {
idx += (addr & 0xFFF0) >> 5;
if (addr & 0x10) {
diff --git a/hw/ppc405_uc.c b/hw/ppc405_uc.c
index 6f8342e0e..89e5013b5 100644
--- a/hw/ppc405_uc.c
+++ b/hw/ppc405_uc.c
@@ -2471,6 +2471,8 @@ CPUPPCState *ppc405ep_init(MemoryRegion *address_space_mem,
ppc4xx_pob_init(env);
/* OBP arbitrer */
ppc4xx_opba_init(0xef600600);
+ /* Initialize timers */
+ ppc_booke_timers_init(env, sysclk, 0);
/* Universal interrupt controller */
irqs = g_malloc0(sizeof(qemu_irq) * PPCUIC_OUTPUT_NB);
irqs[PPCUIC_OUTPUT_INT] =
diff --git a/hw/ppce500_spin.c b/hw/ppce500_spin.c
index 268f5fdb9..960b7b0c3 100644
--- a/hw/ppce500_spin.c
+++ b/hw/ppce500_spin.c
@@ -182,7 +182,7 @@ static uint64_t spin_read(void *opaque, target_phys_addr_t addr, unsigned len)
}
}
-const MemoryRegionOps spin_rw_ops = {
+static const MemoryRegionOps spin_rw_ops = {
.read = spin_read,
.write = spin_write,
.endianness = DEVICE_BIG_ENDIAN,
diff --git a/hw/spapr.c b/hw/spapr.c
index 3719e0e4a..bfaf260d5 100644
--- a/hw/spapr.c
+++ b/hw/spapr.c
@@ -83,7 +83,8 @@
sPAPREnvironment *spapr;
-qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
+ enum xics_irq_type type)
{
uint32_t irq;
qemu_irq qirq;
@@ -95,7 +96,7 @@ qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num)
irq = spapr->next_irq++;
}
- qirq = xics_find_qirq(spapr->icp, irq);
+ qirq = xics_assign_irq(spapr->icp, irq, type);
if (!qirq) {
return NULL;
}
diff --git a/hw/spapr.h b/hw/spapr.h
index a41641fdd..11160b02d 100644
--- a/hw/spapr.h
+++ b/hw/spapr.h
@@ -286,7 +286,18 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
target_ulong spapr_hypercall(CPUPPCState *env, target_ulong opcode,
target_ulong *args);
-qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num);
+qemu_irq spapr_allocate_irq(uint32_t hint, uint32_t *irq_num,
+ enum xics_irq_type type);
+
+static inline qemu_irq spapr_allocate_msi(uint32_t hint, uint32_t *irq_num)
+{
+ return spapr_allocate_irq(hint, irq_num, XICS_MSI);
+}
+
+static inline qemu_irq spapr_allocate_lsi(uint32_t hint, uint32_t *irq_num)
+{
+ return spapr_allocate_irq(hint, irq_num, XICS_LSI);
+}
static inline uint32_t rtas_ld(target_ulong phys, int n)
{
diff --git a/hw/spapr_pci.c b/hw/spapr_pci.c
index 374dcf8be..e7ef551c1 100644
--- a/hw/spapr_pci.c
+++ b/hw/spapr_pci.c
@@ -32,13 +32,6 @@
#include "hw/pci_internals.h"
-static const uint32_t bars[] = {
- PCI_BASE_ADDRESS_0, PCI_BASE_ADDRESS_1,
- PCI_BASE_ADDRESS_2, PCI_BASE_ADDRESS_3,
- PCI_BASE_ADDRESS_4, PCI_BASE_ADDRESS_5
- /*, PCI_ROM_ADDRESS*/
-};
-
static PCIDevice *find_dev(sPAPREnvironment *spapr,
uint64_t buid, uint32_t config_addr)
{
@@ -187,69 +180,6 @@ static void pci_spapr_set_irq(void *opaque, int irq_num, int level)
qemu_set_irq(phb->lsi_table[irq_num].qirq, level);
}
-static int spapr_phb_init(SysBusDevice *s)
-{
- sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
- int i;
-
- /* Initialize the LSI table */
- for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
- qemu_irq qirq;
- uint32_t num;
-
- qirq = spapr_allocate_irq(0, &num);
- if (!qirq) {
- return -1;
- }
-
- phb->lsi_table[i].dt_irq = num;
- phb->lsi_table[i].qirq = qirq;
- }
-
- return 0;
-}
-
-static int spapr_main_pci_host_init(PCIDevice *d)
-{
- return 0;
-}
-
-static void spapr_main_pci_host_class_init(ObjectClass *klass, void *data)
-{
- PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
-
- k->init = spapr_main_pci_host_init;
-}
-
-static TypeInfo spapr_main_pci_host_info = {
- .name = "spapr-pci-host-bridge-pci",
- .parent = TYPE_PCI_DEVICE,
- .instance_size = sizeof(PCIDevice),
- .class_init = spapr_main_pci_host_class_init,
-};
-
-static void spapr_phb_class_init(ObjectClass *klass, void *data)
-{
- SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
-
- sdc->init = spapr_phb_init;
-}
-
-static TypeInfo spapr_phb_info = {
- .name = "spapr-pci-host-bridge",
- .parent = TYPE_SYS_BUS_DEVICE,
- .instance_size = sizeof(sPAPRPHBState),
- .class_init = spapr_phb_class_init,
-};
-
-static void spapr_register_types(void)
-{
- type_register_static(&spapr_phb_info);
- type_register_static(&spapr_main_pci_host_info);
-}
-
-type_init(spapr_register_types)
-
static uint64_t spapr_io_read(void *opaque, target_phys_addr_t addr,
unsigned size)
{
@@ -287,35 +217,29 @@ static const MemoryRegionOps spapr_io_ops = {
.write = spapr_io_write
};
-void spapr_create_phb(sPAPREnvironment *spapr,
- const char *busname, uint64_t buid,
- uint64_t mem_win_addr, uint64_t mem_win_size,
- uint64_t io_win_addr)
+/*
+ * PHB PCI device
+ */
+static int spapr_phb_init(SysBusDevice *s)
{
- DeviceState *dev;
- SysBusDevice *s;
- sPAPRPHBState *phb;
+ sPAPRPHBState *phb = FROM_SYSBUS(sPAPRPHBState, s);
+ char *namebuf;
+ int i;
PCIBus *bus;
- char namebuf[strlen(busname)+11];
-
- dev = qdev_create(NULL, "spapr-pci-host-bridge");
- qdev_init_nofail(dev);
- s = sysbus_from_qdev(dev);
- phb = FROM_SYSBUS(sPAPRPHBState, s);
- phb->mem_win_addr = mem_win_addr;
+ phb->dtbusname = g_strdup_printf("pci@%" PRIx64, phb->buid);
+ namebuf = alloca(strlen(phb->dtbusname) + 32);
- sprintf(namebuf, "%s-mem", busname);
+ /* Initialize memory regions */
+ sprintf(namebuf, "%s.mmio", phb->dtbusname);
memory_region_init(&phb->memspace, namebuf, INT64_MAX);
- sprintf(namebuf, "%s-memwindow", busname);
+ sprintf(namebuf, "%s.mmio-alias", phb->dtbusname);
memory_region_init_alias(&phb->memwindow, namebuf, &phb->memspace,
- SPAPR_PCI_MEM_WIN_BUS_OFFSET, mem_win_size);
- memory_region_add_subregion(get_system_memory(), mem_win_addr,
+ SPAPR_PCI_MEM_WIN_BUS_OFFSET, phb->mem_win_size);
+ memory_region_add_subregion(get_system_memory(), phb->mem_win_addr,
&phb->memwindow);
- phb->io_win_addr = io_win_addr;
-
/* On ppc, we only have MMIO no specific IO space from the CPU
* perspective. In theory we ought to be able to embed the PCI IO
* memory region direction in the system memory space. However,
@@ -324,33 +248,92 @@ void spapr_create_phb(sPAPREnvironment *spapr,
* system io address space. This hack to bounce things via
* system_io works around the problem until all the users of
* old_portion are updated */
- sprintf(namebuf, "%s-io", busname);
+ sprintf(namebuf, "%s.io", phb->dtbusname);
memory_region_init(&phb->iospace, namebuf, SPAPR_PCI_IO_WIN_SIZE);
/* FIXME: fix to support multiple PHBs */
memory_region_add_subregion(get_system_io(), 0, &phb->iospace);
- sprintf(namebuf, "%s-iowindow", busname);
+ sprintf(namebuf, "%s.io-alias", phb->dtbusname);
memory_region_init_io(&phb->iowindow, &spapr_io_ops, phb,
namebuf, SPAPR_PCI_IO_WIN_SIZE);
- memory_region_add_subregion(get_system_memory(), io_win_addr,
+ memory_region_add_subregion(get_system_memory(), phb->io_win_addr,
&phb->iowindow);
- phb->host_state.bus = bus = pci_register_bus(&phb->busdev.qdev, busname,
- pci_spapr_set_irq,
- pci_spapr_map_irq,
- phb,
- &phb->memspace, &phb->iospace,
- PCI_DEVFN(0, 0),
- SPAPR_PCI_NUM_LSI);
+ bus = pci_register_bus(&phb->busdev.qdev,
+ phb->busname ? phb->busname : phb->dtbusname,
+ pci_spapr_set_irq, pci_spapr_map_irq, phb,
+ &phb->memspace, &phb->iospace,
+ PCI_DEVFN(0, 0), SPAPR_PCI_NUM_LSI);
+ phb->host_state.bus = bus;
+
+ QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+
+ /* Initialize the LSI table */
+ for (i = 0; i < SPAPR_PCI_NUM_LSI; i++) {
+ qemu_irq qirq;
+ uint32_t num;
+
+ qirq = spapr_allocate_lsi(0, &num);
+ if (!qirq) {
+ return -1;
+ }
+
+ phb->lsi_table[i].dt_irq = num;
+ phb->lsi_table[i].qirq = qirq;
+ }
+
+ return 0;
+}
+
+static Property spapr_phb_properties[] = {
+ DEFINE_PROP_HEX64("buid", sPAPRPHBState, buid, 0),
+ DEFINE_PROP_STRING("busname", sPAPRPHBState, busname),
+ DEFINE_PROP_HEX64("mem_win_addr", sPAPRPHBState, mem_win_addr, 0),
+ DEFINE_PROP_HEX64("mem_win_size", sPAPRPHBState, mem_win_size, 0x20000000),
+ DEFINE_PROP_HEX64("io_win_addr", sPAPRPHBState, io_win_addr, 0),
+ DEFINE_PROP_HEX64("io_win_size", sPAPRPHBState, io_win_size, 0x10000),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void spapr_phb_class_init(ObjectClass *klass, void *data)
+{
+ SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
+ DeviceClass *dc = DEVICE_CLASS(klass);
+
+ sdc->init = spapr_phb_init;
+ dc->props = spapr_phb_properties;
spapr_rtas_register("read-pci-config", rtas_read_pci_config);
spapr_rtas_register("write-pci-config", rtas_write_pci_config);
spapr_rtas_register("ibm,read-pci-config", rtas_ibm_read_pci_config);
spapr_rtas_register("ibm,write-pci-config", rtas_ibm_write_pci_config);
+}
- QLIST_INSERT_HEAD(&spapr->phbs, phb, list);
+static TypeInfo spapr_phb_info = {
+ .name = "spapr-pci-host-bridge",
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(sPAPRPHBState),
+ .class_init = spapr_phb_class_init,
+};
+
+void spapr_create_phb(sPAPREnvironment *spapr,
+ const char *busname, uint64_t buid,
+ uint64_t mem_win_addr, uint64_t mem_win_size,
+ uint64_t io_win_addr)
+{
+ DeviceState *dev;
+
+ dev = qdev_create(NULL, spapr_phb_info.name);
- /* pci_bus_set_mem_base(bus, mem_va_start - SPAPR_PCI_MEM_BAR_START); */
+ if (busname) {
+ qdev_prop_set_string(dev, "busname", g_strdup(busname));
+ }
+ qdev_prop_set_uint64(dev, "buid", buid);
+ qdev_prop_set_uint64(dev, "mem_win_addr", mem_win_addr);
+ qdev_prop_set_uint64(dev, "mem_win_size", mem_win_size);
+ qdev_prop_set_uint64(dev, "io_win_addr", io_win_addr);
+
+ qdev_init_nofail(dev);
}
/* Macros to operate with address in OF binding to PCI */
@@ -442,3 +425,9 @@ int spapr_populate_pci_devices(sPAPRPHBState *phb,
return 0;
}
+
+static void register_types(void)
+{
+ type_register_static(&spapr_phb_info);
+}
+type_init(register_types)
diff --git a/hw/spapr_pci.h b/hw/spapr_pci.h
index 213340c91..039f85bd4 100644
--- a/hw/spapr_pci.h
+++ b/hw/spapr_pci.h
@@ -33,9 +33,11 @@ typedef struct sPAPRPHBState {
PCIHostState host_state;
uint64_t buid;
+ char *busname;
+ char *dtbusname;
MemoryRegion memspace, iospace;
- target_phys_addr_t mem_win_addr, io_win_addr;
+ target_phys_addr_t mem_win_addr, mem_win_size, io_win_addr, io_win_size;
MemoryRegion memwindow, iowindow;
struct {
diff --git a/hw/spapr_vio.c b/hw/spapr_vio.c
index 2fb3cee26..dbf5a9017 100644
--- a/hw/spapr_vio.c
+++ b/hw/spapr_vio.c
@@ -670,7 +670,7 @@ static int spapr_vio_busdev_init(DeviceState *qdev)
dev->qdev.id = id;
}
- dev->qirq = spapr_allocate_irq(dev->vio_irq_num, &dev->vio_irq_num);
+ dev->qirq = spapr_allocate_msi(dev->vio_irq_num, &dev->vio_irq_num);
if (!dev->qirq) {
return -1;
}
diff --git a/hw/xics.c b/hw/xics.c
index f7963f309..668a0d648 100644
--- a/hw/xics.c
+++ b/hw/xics.c
@@ -132,9 +132,9 @@ static void icp_eoi(struct icp_state *icp, int server, uint32_t xirr)
{
struct icp_server_state *ss = icp->ss + server;
- ics_eoi(icp->ics, xirr & XISR_MASK);
/* Send EOI -> ICS */
ss->xirr = (ss->xirr & ~CPPR_MASK) | (xirr & CPPR_MASK);
+ ics_eoi(icp->ics, xirr & XISR_MASK);
if (!XISR(ss)) {
icp_resend(icp, server);
}
@@ -165,8 +165,9 @@ struct ics_irq_state {
int server;
uint8_t priority;
uint8_t saved_priority;
- /* int pending:1; */
- /* int presented:1; */
+ enum xics_irq_type type;
+ int asserted:1;
+ int sent:1;
int rejected:1;
int masked_pending:1;
};
@@ -185,9 +186,32 @@ static int ics_valid_irq(struct ics_state *ics, uint32_t nr)
&& (nr < (ics->offset + ics->nr_irqs));
}
-static void ics_set_irq_msi(void *opaque, int srcno, int val)
+static void resend_msi(struct ics_state *ics, int srcno)
+{
+ struct ics_irq_state *irq = ics->irqs + srcno;
+
+ /* FIXME: filter by server#? */
+ if (irq->rejected) {
+ irq->rejected = 0;
+ if (irq->priority != 0xff) {
+ icp_irq(ics->icp, irq->server, srcno + ics->offset,
+ irq->priority);
+ }
+ }
+}
+
+static void resend_lsi(struct ics_state *ics, int srcno)
+{
+ struct ics_irq_state *irq = ics->irqs + srcno;
+
+ if ((irq->priority != 0xff) && irq->asserted && !irq->sent) {
+ irq->sent = 1;
+ icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
+ }
+}
+
+static void set_irq_msi(struct ics_state *ics, int srcno, int val)
{
- struct ics_state *ics = (struct ics_state *)opaque;
struct ics_irq_state *irq = ics->irqs + srcno;
if (val) {
@@ -200,71 +224,108 @@ static void ics_set_irq_msi(void *opaque, int srcno, int val)
}
}
-static void ics_reject_msi(struct ics_state *ics, int nr)
+static void set_irq_lsi(struct ics_state *ics, int srcno, int val)
{
- struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+ struct ics_irq_state *irq = ics->irqs + srcno;
- irq->rejected = 1;
+ irq->asserted = val;
+ resend_lsi(ics, srcno);
}
-static void ics_resend_msi(struct ics_state *ics)
+static void ics_set_irq(void *opaque, int srcno, int val)
{
- int i;
+ struct ics_state *ics = (struct ics_state *)opaque;
+ struct ics_irq_state *irq = ics->irqs + srcno;
- for (i = 0; i < ics->nr_irqs; i++) {
- struct ics_irq_state *irq = ics->irqs + i;
+ if (irq->type == XICS_LSI) {
+ set_irq_lsi(ics, srcno, val);
+ } else {
+ set_irq_msi(ics, srcno, val);
+ }
+}
- /* FIXME: filter by server#? */
- if (irq->rejected) {
- irq->rejected = 0;
- if (irq->priority != 0xff) {
- icp_irq(ics->icp, irq->server, i + ics->offset, irq->priority);
- }
- }
+static void write_xive_msi(struct ics_state *ics, int srcno)
+{
+ struct ics_irq_state *irq = ics->irqs + srcno;
+
+ if (!irq->masked_pending || (irq->priority == 0xff)) {
+ return;
}
+
+ irq->masked_pending = 0;
+ icp_irq(ics->icp, irq->server, srcno + ics->offset, irq->priority);
}
-static void ics_write_xive_msi(struct ics_state *ics, int nr, int server,
- uint8_t priority)
+static void write_xive_lsi(struct ics_state *ics, int srcno)
{
- struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+ resend_lsi(ics, srcno);
+}
+
+static void ics_write_xive(struct ics_state *ics, int nr, int server,
+ uint8_t priority)
+{
+ int srcno = nr - ics->offset;
+ struct ics_irq_state *irq = ics->irqs + srcno;
irq->server = server;
irq->priority = priority;
- if (!irq->masked_pending || (priority == 0xff)) {
- return;
+ if (irq->type == XICS_LSI) {
+ write_xive_lsi(ics, srcno);
+ } else {
+ write_xive_msi(ics, srcno);
}
-
- irq->masked_pending = 0;
- icp_irq(ics->icp, server, nr, priority);
}
static void ics_reject(struct ics_state *ics, int nr)
{
- ics_reject_msi(ics, nr);
+ struct ics_irq_state *irq = ics->irqs + nr - ics->offset;
+
+ irq->rejected = 1; /* Irrelevant but harmless for LSI */
+ irq->sent = 0; /* Irrelevant but harmless for MSI */
}
static void ics_resend(struct ics_state *ics)
{
- ics_resend_msi(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->type == XICS_LSI) {
+ resend_lsi(ics, i);
+ } else {
+ resend_msi(ics, i);
+ }
+ }
}
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->type == XICS_LSI) {
+ irq->sent = 0;
+ }
}
/*
* Exported functions
*/
-qemu_irq xics_find_qirq(struct icp_state *icp, int irq)
+qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
+ enum xics_irq_type type)
{
if ((irq < icp->ics->offset)
|| (irq >= (icp->ics->offset + icp->ics->nr_irqs))) {
return NULL;
}
+ assert((type == XICS_MSI) || (type == XICS_LSI));
+
+ icp->ics->irqs[irq - icp->ics->offset].type = type;
return icp->ics->qirqs[irq - icp->ics->offset];
}
@@ -332,7 +393,7 @@ static void rtas_set_xive(sPAPREnvironment *spapr, uint32_t token,
return;
}
- ics_write_xive_msi(ics, nr, server, priority);
+ ics_write_xive(ics, nr, server, priority);
rtas_st(rets, 0, 0); /* Success */
}
@@ -477,7 +538,7 @@ struct icp_state *xics_system_init(int nr_irqs)
ics->irqs[i].saved_priority = 0xff;
}
- ics->qirqs = qemu_allocate_irqs(ics_set_irq_msi, ics, nr_irqs);
+ ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, nr_irqs);
spapr_register_hypercall(H_CPPR, h_cppr);
spapr_register_hypercall(H_IPI, h_ipi);
diff --git a/hw/xics.h b/hw/xics.h
index 83c118259..208015939 100644
--- a/hw/xics.h
+++ b/hw/xics.h
@@ -31,7 +31,13 @@
struct icp_state;
-qemu_irq xics_find_qirq(struct icp_state *icp, int irq);
+enum xics_irq_type {
+ XICS_MSI, /* Message-signalled (edge) interrupt */
+ XICS_LSI, /* Level-signalled interrupt */
+};
+
+qemu_irq xics_assign_irq(struct icp_state *icp, int irq,
+ enum xics_irq_type type);
struct icp_state *xics_system_init(int nr_irqs);
diff --git a/kvm-all.c b/kvm-all.c
index 42e5e23d5..ba2cee10f 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -79,7 +79,10 @@ struct KVMState
int pit_state2;
int xsave, xcrs;
int many_ioeventfds;
- int irqchip_inject_ioctl;
+ /* The man page (and posix) say ioctl numbers are signed int, but
+ * they're not. Linux, glibc and *BSD all treat ioctl numbers as
+ * unsigned, and treating them as signed here can break things */
+ unsigned irqchip_inject_ioctl;
#ifdef KVM_CAP_IRQ_ROUTING
struct kvm_irq_routing *irq_routes;
int nr_allocated_irq_routes;
diff --git a/linux-user/signal.c b/linux-user/signal.c
index fca51e2b1..b1e139d6f 100644
--- a/linux-user/signal.c
+++ b/linux-user/signal.c
@@ -4118,7 +4118,7 @@ static target_ulong get_sigframe(struct target_sigaction *ka,
oldsp = env->gpr[1];
if ((ka->sa_flags & TARGET_SA_ONSTACK) &&
- (sas_ss_flags(oldsp))) {
+ (sas_ss_flags(oldsp) == 0)) {
oldsp = (target_sigaltstack_used.ss_sp
+ target_sigaltstack_used.ss_size);
}
diff --git a/pc-bios/README b/pc-bios/README
index 5dce355f5..71f48711b 100644
--- a/pc-bios/README
+++ b/pc-bios/README
@@ -17,7 +17,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at
https://github.com/dgibson/SLOF, and the image currently in qemu is
- built from git tag qemu-slof-20120111.1.
+ built from git tag qemu-slof-20120217.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as
diff --git a/pc-bios/slof.bin b/pc-bios/slof.bin
index 8554f54b5..449a7bb2a 100644
--- a/pc-bios/slof.bin
+++ b/pc-bios/slof.bin
Binary files differ
diff --git a/roms/SLOF b/roms/SLOF
-Subproject ab062ff3b37c39649f2b0d94ed607adc6f6b3c7
+Subproject d153364253548d6cd91403711f84996e6a7dab3
diff --git a/target-ppc/cpu.h b/target-ppc/cpu.h
index ad09cbe06..ca6f1cb58 100644
--- a/target-ppc/cpu.h
+++ b/target-ppc/cpu.h
@@ -1918,8 +1918,10 @@ enum {
PPC2_DFP = 0x0000000000000004ULL,
/* Embedded.Processor Control */
PPC2_PRCNTL = 0x0000000000000008ULL,
+ /* Byte-reversed, indexed, double-word load and store */
+ PPC2_DBRX = 0x0000000000000010ULL,
-#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL)
+#define PPC_TCG_INSNS2 (PPC2_BOOKE206 | PPC2_PRCNTL | PPC2_DBRX)
};
/*****************************************************************************/
diff --git a/target-ppc/helper.c b/target-ppc/helper.c
index bd711b6e2..39dcc273e 100644
--- a/target-ppc/helper.c
+++ b/target-ppc/helper.c
@@ -591,12 +591,6 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
pte1 = ldq_phys(env->htab_base + pteg_off + (i * 16) + 8);
}
- /* We have a TLB that saves 4K pages, so let's
- * split a huge page to 4k chunks */
- if (target_page_bits != TARGET_PAGE_BITS)
- pte1 |= (ctx->eaddr & (( 1 << target_page_bits ) - 1))
- & TARGET_PAGE_MASK;
-
r = pte64_check(ctx, pte0, pte1, h, rw, type);
LOG_MMU("Load pte from " TARGET_FMT_lx " => " TARGET_FMT_lx " "
TARGET_FMT_lx " %d %d %d " TARGET_FMT_lx "\n",
@@ -672,6 +666,12 @@ static inline int _find_pte(CPUPPCState *env, mmu_ctx_t *ctx, int is_64b, int h,
}
}
+ /* We have a TLB that saves 4K pages, so let's
+ * split a huge page to 4k chunks */
+ if (target_page_bits != TARGET_PAGE_BITS) {
+ ctx->raddr |= (ctx->eaddr & ((1 << target_page_bits) - 1))
+ & TARGET_PAGE_MASK;
+ }
return ret;
}
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index aeb3de9ae..724f4c781 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -843,12 +843,18 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
int fd;
void *table;
+ /* Must set fd to -1 so we don't try to munmap when called for
+ * destroying the table, which the upper layers -will- do
+ */
+ *pfd = -1;
if (!cap_spapr_tce) {
return NULL;
}
fd = kvm_vm_ioctl(kvm_state, KVM_CREATE_SPAPR_TCE, &args);
if (fd < 0) {
+ fprintf(stderr, "KVM: Failed to create TCE table for liobn 0x%x\n",
+ liobn);
return NULL;
}
@@ -857,6 +863,8 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd)
table = mmap(NULL, len, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
if (table == MAP_FAILED) {
+ fprintf(stderr, "KVM: Failed to map TCE table for liobn 0x%x\n",
+ liobn);
close(fd);
return NULL;
}
@@ -876,8 +884,8 @@ int kvmppc_remove_spapr_tce(void *table, int fd, uint32_t window_size)
len = (window_size / SPAPR_VIO_TCE_PAGE_SIZE)*sizeof(VIOsPAPR_RTCE);
if ((munmap(table, len) < 0) ||
(close(fd) < 0)) {
- fprintf(stderr, "KVM: Unexpected error removing KVM SPAPR TCE "
- "table: %s", strerror(errno));
+ fprintf(stderr, "KVM: Unexpected error removing TCE table: %s",
+ strerror(errno));
/* Leak the table */
}
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 3ec59a7ee..c9a503a1d 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -2650,7 +2650,7 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
tcg_temp_free(EA); \
}
-#define GEN_LDX(name, ldop, opc2, opc3, type) \
+#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
@@ -2660,6 +2660,8 @@ static void glue(gen_, name##x)(DisasContext *ctx) \
gen_qemu_##ldop(ctx, cpu_gpr[rD(ctx->opcode)], EA); \
tcg_temp_free(EA); \
}
+#define GEN_LDX(name, ldop, opc2, opc3, type) \
+ GEN_LDX_E(name, ldop, opc2, opc3, type, PPC_NONE)
#define GEN_LDS(name, ldop, op, type) \
GEN_LD(name, ldop, op | 0x20, type); \
@@ -2793,8 +2795,8 @@ static void glue(gen_, name##ux)(DisasContext *ctx)
tcg_temp_free(EA); \
}
-#define GEN_STX(name, stop, opc2, opc3, type) \
-static void glue(gen_, name##x)(DisasContext *ctx) \
+#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
+static void glue(gen_, name##x)(DisasContext *ctx) \
{ \
TCGv EA; \
gen_set_access_type(ctx, ACCESS_INT); \
@@ -2803,6 +2805,8 @@ static void glue(gen_, name##x)(DisasContext *ctx)
gen_qemu_##stop(ctx, cpu_gpr[rS(ctx->opcode)], EA); \
tcg_temp_free(EA); \
}
+#define GEN_STX(name, stop, opc2, opc3, type) \
+ GEN_STX_E(name, stop, opc2, opc3, type, PPC_NONE)
#define GEN_STS(name, stop, op, type) \
GEN_ST(name, stop, op | 0x20, type); \
@@ -2891,6 +2895,18 @@ static inline void gen_qemu_ld32ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
}
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER);
+#if defined(TARGET_PPC64)
+/* ldbrx */
+static inline void gen_qemu_ld64ur(DisasContext *ctx, TCGv arg1, TCGv arg2)
+{
+ tcg_gen_qemu_ld64(arg1, arg2, ctx->mem_idx);
+ if (likely(!ctx->le_mode)) {
+ tcg_gen_bswap64_tl(arg1, arg1);
+ }
+}
+GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX);
+#endif /* TARGET_PPC64 */
+
/* sthbrx */
static inline void gen_qemu_st16r(DisasContext *ctx, TCGv arg1, TCGv arg2)
{
@@ -2921,6 +2937,22 @@ static inline void gen_qemu_st32r(DisasContext *ctx, TCGv arg1, TCGv arg2)
}
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER);
+#if defined(TARGET_PPC64)
+/* stdbrx */
+static inline void gen_qemu_st64r(DisasContext *ctx, TCGv arg1, TCGv arg2)
+{
+ if (likely(!ctx->le_mode)) {
+ TCGv t0 = tcg_temp_new();
+ tcg_gen_bswap64_tl(t0, arg1);
+ tcg_gen_qemu_st64(t0, arg2, ctx->mem_idx);
+ tcg_temp_free(t0);
+ } else {
+ tcg_gen_qemu_st64(arg1, arg2, ctx->mem_idx);
+ }
+}
+GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX);
+#endif /* TARGET_PPC64 */
+
/*** Integer load and store multiple ***/
/* lmw */
@@ -8818,7 +8850,7 @@ GEN_FLOAT_B(neg, 0x08, 0x01, 0, PPC_FLOAT),
#undef GEN_LD
#undef GEN_LDU
#undef GEN_LDUX
-#undef GEN_LDX
+#undef GEN_LDX_E
#undef GEN_LDS
#define GEN_LD(name, ldop, opc, type) \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
@@ -8826,8 +8858,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
GEN_HANDLER(name##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_LDUX(name, ldop, opc2, opc3, type) \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_LDX(name, ldop, opc2, opc3, type) \
-GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
+#define GEN_LDX_E(name, ldop, opc2, opc3, type, type2) \
+GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
#define GEN_LDS(name, ldop, op, type) \
GEN_LD(name, ldop, op | 0x20, type) \
GEN_LDU(name, ldop, op | 0x21, type) \
@@ -8843,6 +8875,7 @@ GEN_LDUX(lwa, ld32s, 0x15, 0x0B, PPC_64B)
GEN_LDX(lwa, ld32s, 0x15, 0x0A, PPC_64B)
GEN_LDUX(ld, ld64, 0x15, 0x01, PPC_64B)
GEN_LDX(ld, ld64, 0x15, 0x00, PPC_64B)
+GEN_LDX_E(ldbr, ld64ur, 0x14, 0x10, PPC_NONE, PPC2_DBRX)
#endif
GEN_LDX(lhbr, ld16ur, 0x16, 0x18, PPC_INTEGER)
GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
@@ -8850,7 +8883,7 @@ GEN_LDX(lwbr, ld32ur, 0x16, 0x10, PPC_INTEGER)
#undef GEN_ST
#undef GEN_STU
#undef GEN_STUX
-#undef GEN_STX
+#undef GEN_STX_E
#undef GEN_STS
#define GEN_ST(name, stop, opc, type) \
GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
@@ -8858,8 +8891,8 @@ GEN_HANDLER(name, opc, 0xFF, 0xFF, 0x00000000, type),
GEN_HANDLER(stop##u, opc, 0xFF, 0xFF, 0x00000000, type),
#define GEN_STUX(name, stop, opc2, opc3, type) \
GEN_HANDLER(name##ux, 0x1F, opc2, opc3, 0x00000001, type),
-#define GEN_STX(name, stop, opc2, opc3, type) \
-GEN_HANDLER(name##x, 0x1F, opc2, opc3, 0x00000001, type),
+#define GEN_STX_E(name, stop, opc2, opc3, type, type2) \
+GEN_HANDLER_E(name##x, 0x1F, opc2, opc3, 0x00000001, type, type2),
#define GEN_STS(name, stop, op, type) \
GEN_ST(name, stop, op | 0x20, type) \
GEN_STU(name, stop, op | 0x21, type) \
@@ -8872,6 +8905,7 @@ GEN_STS(stw, st32, 0x04, PPC_INTEGER)
#if defined(TARGET_PPC64)
GEN_STUX(std, st64, 0x15, 0x05, PPC_64B)
GEN_STX(std, st64, 0x15, 0x04, PPC_64B)
+GEN_STX_E(stdbr, st64r, 0x14, 0x14, PPC_NONE, PPC2_DBRX)
#endif
GEN_STX(sthbr, st16r, 0x16, 0x1C, PPC_INTEGER)
GEN_STX(stwbr, st32r, 0x16, 0x14, PPC_INTEGER)
@@ -9285,6 +9319,8 @@ void cpu_dump_state (CPUPPCState *env, FILE *f, fprintf_function cpu_fprintf,
int i;
+ cpu_synchronize_state(env);
+
cpu_fprintf(f, "NIP " TARGET_FMT_lx " LR " TARGET_FMT_lx " CTR "
TARGET_FMT_lx " XER " TARGET_FMT_lx "\n",
env->nip, env->lr, env->ctr, env->xer);
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 1ec6f4248..367eefaf9 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -6571,7 +6571,7 @@ static void init_proc_970MP (CPUPPCState *env)
PPC_64B | PPC_ALTIVEC | \
PPC_SEGMENT_64B | PPC_SLBI | \
PPC_POPCNTB | PPC_POPCNTWD)
-#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP)
+#define POWERPC_INSNS2_POWER7 (PPC2_VSX | PPC2_DFP | PPC2_DBRX)
#define POWERPC_MSRM_POWER7 (0x800000000204FF36ULL)
#define POWERPC_MMU_POWER7 (POWERPC_MMU_2_06)
#define POWERPC_EXCP_POWER7 (POWERPC_EXCP_POWER7)
@@ -6588,6 +6588,11 @@ static void init_proc_POWER7 (CPUPPCState *env)
gen_spr_7xx(env);
/* Time base */
gen_tbl(env);
+ /* Processor identification */
+ spr_register(env, SPR_PIR, "PIR",
+ SPR_NOACCESS, SPR_NOACCESS,
+ &spr_read_generic, &spr_write_pir,
+ 0x00000000);
#if !defined(CONFIG_USER_ONLY)
/* PURR & SPURR: Hack - treat these as aliases for the TB for now */
spr_register(env, SPR_PURR, "PURR",
@@ -6713,7 +6718,7 @@ static void init_proc_620 (CPUPPCState *env)
#if defined (TARGET_PPC64) && 0 // XXX: TODO
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC64
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC64
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC64
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC64
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC64
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC64
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC64
@@ -6725,7 +6730,7 @@ static void init_proc_620 (CPUPPCState *env)
#else
#define CPU_POWERPC_DEFAULT CPU_POWERPC_PPC32
#define POWERPC_INSNS_DEFAULT POWERPC_INSNS_PPC32
-#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS_PPC32
+#define POWERPC_INSNS2_DEFAULT POWERPC_INSNS2_PPC32
#define POWERPC_MSRM_DEFAULT POWERPC_MSRM_PPC32
#define POWERPC_MMU_DEFAULT POWERPC_MMU_PPC32
#define POWERPC_EXCP_DEFAULT POWERPC_EXCP_PPC32