aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-02-02 09:13:10 +0000
committerPeter Maydell <peter.maydell@linaro.org>2016-02-02 09:13:10 +0000
commit10ae9d76388e3f4a31f6a1475b5e2d1f28404a10 (patch)
tree46287b1f210d363a995dbab357e7c28c8c5ad14b /hw
parent0430891ce162b986c6e02a7729a942ecd2a32ca4 (diff)
parentd1277156b5d3df6d75d138a7eec6ff80934cdcec (diff)
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.6-20160201' into staging
ppc patch queue for 2016-02-01 Currently accumulated patches for target-ppc, pseries machine type and related devices. * Cleanup of error handling code in spapr * A number of fixes for Macintosh devices for the benefit of MacOS 9 and X * Remove some abuses of the RTAS memory access functions in spapr * Fixes for the gdbstub (and monitor debug) for VMX and VSX extensions. * Fix pseries machine hotplug memory under TCG * Clean up and extend handling of multiple page sizes with 64-bit hash MMUs * Fix to the TCG implementation of mcrfs # gpg: Signature made Mon 01 Feb 2016 02:28:34 GMT using RSA key ID 20D9B392 # 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: WARNING: This key is not certified with sufficiently trusted signatures! # gpg: It is not certain that the signature belongs to the owner. # Primary key fingerprint: 75F4 6586 AE61 A66C C44E 87DC 6C38 CACA 20D9 B392 * remotes/dgibson/tags/ppc-for-2.6-20160201: (40 commits) target-ppc: mcrfs should always update FEX/VX and only clear exception bits target-ppc: Make every FPSCR_ macro have a corresponding FP_ macro target-ppc: Allow more page sizes for POWER7 & POWER8 in TCG target-ppc: Helper to determine page size information from hpte alone target-ppc: Add new TLB invalidate by HPTE call for hash64 MMUs target-ppc: Split 44x tlbiva from ppc_tlb_invalidate_one() target-ppc: Remove unused mmu models from ppc_tlb_invalidate_one target-ppc: Use actual page size encodings from HPTE target-ppc: Rework SLB page size lookup target-ppc: Rework ppc_store_slb target-ppc: Convert mmu-hash{32,64}.[ch] from CPUPPCState to PowerPCCPU target-ppc: Remove unused kvmppc_read_segment_page_sizes() stub uninorth.c: add support for UniNorth kMacRISCPCIAddressSelect (0x48) register cuda.c: return error for unknown commands pseries: Allow TCG h_enter to work with hotplugged memory target-ppc: gdbstub: Add VSX support target-ppc: gdbstub: fix spe registers for little-endian guests target-ppc: gdbstub: fix altivec registers for little-endian guests target-ppc: gdbstub: introduce avr_need_swap() target-ppc: gdbstub: fix float registers for little-endian guests ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/ide/macio.c23
-rw-r--r--hw/misc/macio/cuda.c12
-rw-r--r--hw/misc/macio/mac_dbdma.c40
-rw-r--r--hw/pci-host/uninorth.c9
-rw-r--r--hw/ppc/mac.h1
-rw-r--r--hw/ppc/spapr.c112
-rw-r--r--hw/ppc/spapr_hcall.c145
-rw-r--r--hw/ppc/spapr_rtas.c50
8 files changed, 219 insertions, 173 deletions
diff --git a/hw/ide/macio.c b/hw/ide/macio.c
index 336784b076..1725e5b23f 100644
--- a/hw/ide/macio.c
+++ b/hw/ide/macio.c
@@ -120,8 +120,8 @@ static void pmac_dma_read(BlockBackend *blk,
MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", (offset >> 9), (bytes >> 9));
- m->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, (bytes >> 9),
- cb, io);
+ s->bus->dma->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_dma_write(BlockBackend *blk,
@@ -205,8 +205,8 @@ static void pmac_dma_write(BlockBackend *blk,
MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " "
"nsector: %x\n", (offset >> 9), (bytes >> 9));
- m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9),
- cb, io);
+ s->bus->dma->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_dma_trim(BlockBackend *blk,
@@ -232,8 +232,8 @@ static void pmac_dma_trim(BlockBackend *blk,
s->io_buffer_index += io->len;
io->len = 0;
- m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9),
- cb, io);
+ s->bus->dma->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov,
+ (bytes >> 9), cb, io);
}
static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
@@ -292,6 +292,8 @@ done:
} else {
block_acct_done(blk_get_stats(s->blk), &s->acct);
}
+
+ ide_set_inactive(s, false);
io->dma_end(opaque);
}
@@ -306,7 +308,6 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
if (ret < 0) {
MACIO_DPRINTF("DMA error: %d\n", ret);
- m->aiocb = NULL;
ide_dma_error(s);
goto done;
}
@@ -357,6 +358,8 @@ done:
block_acct_done(blk_get_stats(s->blk), &s->acct);
}
}
+
+ ide_set_inactive(s, false);
io->dma_end(opaque);
}
@@ -394,8 +397,9 @@ static void pmac_ide_transfer(DBDMA_io *io)
static void pmac_ide_flush(DBDMA_io *io)
{
MACIOIDEState *m = io->opaque;
+ IDEState *s = idebus_active_if(&m->bus);
- if (m->aiocb) {
+ if (s->bus->dma->aiocb) {
blk_drain_all();
}
}
@@ -513,11 +517,12 @@ static const MemoryRegionOps pmac_ide_ops = {
static const VMStateDescription vmstate_pmac = {
.name = "ide",
- .version_id = 3,
+ .version_id = 4,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
VMSTATE_IDE_BUS(bus, MACIOIDEState),
VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
+ VMSTATE_BOOL(dma_active, MACIOIDEState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 8d450cfce2..316c1ac8da 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -606,6 +606,11 @@ static void cuda_receive_packet(CUDAState *s,
}
break;
default:
+ obuf[0] = ERROR_PACKET;
+ obuf[1] = 0x2;
+ obuf[2] = CUDA_PACKET;
+ obuf[3] = data[0];
+ cuda_send_packet_to_host(s, obuf, 4);
break;
}
}
@@ -705,15 +710,17 @@ static const VMStateDescription vmstate_cuda_timer = {
static const VMStateDescription vmstate_cuda = {
.name = "cuda",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_UINT8(a, CUDAState),
VMSTATE_UINT8(b, CUDAState),
+ VMSTATE_UINT8(last_b, CUDAState),
VMSTATE_UINT8(dira, CUDAState),
VMSTATE_UINT8(dirb, CUDAState),
VMSTATE_UINT8(sr, CUDAState),
VMSTATE_UINT8(acr, CUDAState),
+ VMSTATE_UINT8(last_acr, CUDAState),
VMSTATE_UINT8(pcr, CUDAState),
VMSTATE_UINT8(ifr, CUDAState),
VMSTATE_UINT8(ier, CUDAState),
@@ -728,6 +735,7 @@ static const VMStateDescription vmstate_cuda = {
VMSTATE_STRUCT_ARRAY(timers, CUDAState, 2, 1,
vmstate_cuda_timer, CUDATimer),
VMSTATE_TIMER_PTR(adb_poll_timer, CUDAState),
+ VMSTATE_TIMER_PTR(sr_delay_timer, CUDAState),
VMSTATE_END_OF_LIST()
}
};
diff --git a/hw/misc/macio/mac_dbdma.c b/hw/misc/macio/mac_dbdma.c
index c6d5b966b4..d81dea7b0d 100644
--- a/hw/misc/macio/mac_dbdma.c
+++ b/hw/misc/macio/mac_dbdma.c
@@ -713,20 +713,52 @@ static const MemoryRegionOps dbdma_ops = {
},
};
-static const VMStateDescription vmstate_dbdma_channel = {
- .name = "dbdma_channel",
+static const VMStateDescription vmstate_dbdma_io = {
+ .name = "dbdma_io",
+ .version_id = 0,
+ .minimum_version_id = 0,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT64(addr, struct DBDMA_io),
+ VMSTATE_INT32(len, struct DBDMA_io),
+ VMSTATE_INT32(is_last, struct DBDMA_io),
+ VMSTATE_INT32(is_dma_out, struct DBDMA_io),
+ VMSTATE_BOOL(processing, struct DBDMA_io),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_dbdma_cmd = {
+ .name = "dbdma_cmd",
.version_id = 0,
.minimum_version_id = 0,
.fields = (VMStateField[]) {
+ VMSTATE_UINT16(req_count, dbdma_cmd),
+ VMSTATE_UINT16(command, dbdma_cmd),
+ VMSTATE_UINT32(phy_addr, dbdma_cmd),
+ VMSTATE_UINT32(cmd_dep, dbdma_cmd),
+ VMSTATE_UINT16(res_count, dbdma_cmd),
+ VMSTATE_UINT16(xfer_status, dbdma_cmd),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static const VMStateDescription vmstate_dbdma_channel = {
+ .name = "dbdma_channel",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
VMSTATE_UINT32_ARRAY(regs, struct DBDMA_channel, DBDMA_REGS),
+ VMSTATE_STRUCT(io, struct DBDMA_channel, 0, vmstate_dbdma_io, DBDMA_io),
+ VMSTATE_STRUCT(current, struct DBDMA_channel, 0, vmstate_dbdma_cmd,
+ dbdma_cmd),
VMSTATE_END_OF_LIST()
}
};
static const VMStateDescription vmstate_dbdma = {
.name = "dbdma",
- .version_id = 2,
- .minimum_version_id = 2,
+ .version_id = 3,
+ .minimum_version_id = 3,
.fields = (VMStateField[]) {
VMSTATE_STRUCT_ARRAY(channels, DBDMAState, DBDMA_CHANNELS, 1,
vmstate_dbdma_channel, DBDMA_channel),
diff --git a/hw/pci-host/uninorth.c b/hw/pci-host/uninorth.c
index 778f8e6045..40a2e3e6b4 100644
--- a/hw/pci-host/uninorth.c
+++ b/hw/pci-host/uninorth.c
@@ -331,6 +331,15 @@ static void unin_agp_pci_host_realize(PCIDevice *d, Error **errp)
d->config[0x0C] = 0x08; // cache_line_size
d->config[0x0D] = 0x10; // latency_timer
// d->config[0x34] = 0x80; // capabilities_pointer
+ /*
+ * Set kMacRISCPCIAddressSelect (0x48) register to indicate PCI
+ * memory space with base 0x80000000, size 0x10000000 for Apple's
+ * AppleMacRiscPCI driver
+ */
+ d->config[0x48] = 0x0;
+ d->config[0x49] = 0x0;
+ d->config[0x4a] = 0x0;
+ d->config[0x4b] = 0x1;
}
static void u3_agp_pci_host_realize(PCIDevice *d, Error **errp)
diff --git a/hw/ppc/mac.h b/hw/ppc/mac.h
index e375ed2b2b..ecf7792bc9 100644
--- a/hw/ppc/mac.h
+++ b/hw/ppc/mac.h
@@ -134,7 +134,6 @@ typedef struct MACIOIDEState {
MemoryRegion mem;
IDEBus bus;
- BlockAIOCB *aiocb;
IDEDMA dma;
void *dbdma;
bool dma_active;
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 08da895cba..5bd8fd3ef8 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -112,7 +112,7 @@ static XICSState *try_create_xics(const char *type, int nr_servers,
}
static XICSState *xics_system_init(MachineState *machine,
- int nr_servers, int nr_irqs)
+ int nr_servers, int nr_irqs, Error **errp)
{
XICSState *icp = NULL;
@@ -131,7 +131,7 @@ static XICSState *xics_system_init(MachineState *machine,
}
if (!icp) {
- icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, &error_abort);
+ icp = try_create_xics(TYPE_XICS, nr_servers, nr_irqs, errp);
}
return icp;
@@ -764,6 +764,13 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;
/*
+ * Don't create the node if there are no DR LMBs.
+ */
+ if (!nr_lmbs) {
+ return 0;
+ }
+
+ /*
* Allocate enough buffer size to fit in ibm,dynamic-memory
* or ibm,associativity-lookup-arrays
*/
@@ -869,7 +876,7 @@ int spapr_h_cas_compose_response(sPAPRMachineState *spapr,
_FDT((spapr_fixup_cpu_dt(fdt, spapr)));
}
- /* Generate memory nodes or ibm,dynamic-reconfiguration-memory node */
+ /* Generate ibm,dynamic-reconfiguration-memory node if required */
if (memory_update && smc->dr_lmb_enabled) {
_FDT((spapr_populate_drconf_memory(spapr, fdt)));
}
@@ -1239,7 +1246,7 @@ static void spapr_rtc_create(sPAPRMachineState *spapr)
}
/* Returns whether we want to use VGA or not */
-static int spapr_vga_init(PCIBus *pci_bus)
+static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
{
switch (vga_interface_type) {
case VGA_NONE:
@@ -1250,9 +1257,9 @@ static int spapr_vga_init(PCIBus *pci_bus)
case VGA_VIRTIO:
return pci_vga_init(pci_bus) != NULL;
default:
- fprintf(stderr, "This vga model is not supported,"
- "currently it only supports -vga std\n");
- exit(0);
+ error_setg(errp,
+ "Unsupported VGA mode, only -vga std or -vga virtio is supported");
+ return false;
}
}
@@ -1527,7 +1534,7 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
int fd = -1;
if (version_id < 1 || version_id > 1) {
- fprintf(stderr, "htab_load() bad version\n");
+ error_report("htab_load() bad version");
return -EINVAL;
}
@@ -1548,8 +1555,8 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
fd = kvmppc_get_htab_fd(true);
if (fd < 0) {
- fprintf(stderr, "Unable to open fd to restore KVM hash table: %s\n",
- strerror(errno));
+ error_report("Unable to open fd to restore KVM hash table: %s",
+ strerror(errno));
}
}
@@ -1569,9 +1576,9 @@ static int htab_load(QEMUFile *f, void *opaque, int version_id)
if ((index + n_valid + n_invalid) >
(HTAB_SIZE(spapr) / HASH_PTE_SIZE_64)) {
/* Bad index in stream */
- fprintf(stderr, "htab_load() bad index %d (%hd+%hd entries) "
- "in htab stream (htab_shift=%d)\n", index, n_valid, n_invalid,
- spapr->htab_shift);
+ error_report(
+ "htab_load() bad index %d (%hd+%hd entries) in htab stream (htab_shift=%d)",
+ index, n_valid, n_invalid, spapr->htab_shift);
return -EINVAL;
}
@@ -1618,7 +1625,8 @@ static void spapr_boot_set(void *opaque, const char *boot_device,
machine->boot_order = g_strdup(boot_device);
}
-static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu)
+static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu,
+ Error **errp)
{
CPUPPCState *env = &cpu->env;
@@ -1636,8 +1644,12 @@ static void spapr_cpu_init(sPAPRMachineState *spapr, PowerPCCPU *cpu)
}
if (cpu->max_compat) {
- if (ppc_set_compat(cpu, cpu->max_compat) < 0) {
- exit(1);
+ Error *local_err = NULL;
+
+ ppc_set_compat(cpu, cpu->max_compat, &local_err);
+ if (local_err) {
+ error_propagate(errp, local_err);
+ return;
}
}
@@ -1687,27 +1699,34 @@ static void spapr_create_lmb_dr_connectors(sPAPRMachineState *spapr)
* to SPAPR_MEMORY_BLOCK_SIZE(256MB), then refuse to start the guest
* since we can't support such unaligned sizes with DRCONF_MEMORY.
*/
-static void spapr_validate_node_memory(MachineState *machine)
+static void spapr_validate_node_memory(MachineState *machine, Error **errp)
{
int i;
- if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE ||
- machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) {
- error_report("Can't support memory configuration where RAM size "
- "0x" RAM_ADDR_FMT " or maxmem size "
- "0x" RAM_ADDR_FMT " isn't aligned to %llu MB",
- machine->ram_size, machine->maxram_size,
- SPAPR_MEMORY_BLOCK_SIZE/M_BYTE);
- exit(EXIT_FAILURE);
+ if (machine->ram_size % SPAPR_MEMORY_BLOCK_SIZE) {
+ error_setg(errp, "Memory size 0x" RAM_ADDR_FMT
+ " is not aligned to %llu MiB",
+ machine->ram_size,
+ SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
+ return;
+ }
+
+ if (machine->maxram_size % SPAPR_MEMORY_BLOCK_SIZE) {
+ error_setg(errp, "Maximum memory size 0x" RAM_ADDR_FMT
+ " is not aligned to %llu MiB",
+ machine->ram_size,
+ SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
+ return;
}
for (i = 0; i < nb_numa_nodes; i++) {
if (numa_info[i].node_mem % SPAPR_MEMORY_BLOCK_SIZE) {
- error_report("Can't support memory configuration where memory size"
- " %" PRIx64 " of node %d isn't aligned to %llu MB",
- numa_info[i].node_mem, i,
- SPAPR_MEMORY_BLOCK_SIZE/M_BYTE);
- exit(EXIT_FAILURE);
+ error_setg(errp,
+ "Node %d memory size 0x%" PRIx64
+ " is not aligned to %llu MiB",
+ i, numa_info[i].node_mem,
+ SPAPR_MEMORY_BLOCK_SIZE / M_BYTE);
+ return;
}
}
}
@@ -1770,8 +1789,8 @@ static void ppc_spapr_init(MachineState *machine)
}
if (spapr->rma_size > node0_size) {
- fprintf(stderr, "Error: Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")\n",
- spapr->rma_size);
+ error_report("Numa node 0 has to span the RMA (%#08"HWADDR_PRIx")",
+ spapr->rma_size);
exit(1);
}
@@ -1794,10 +1813,10 @@ static void ppc_spapr_init(MachineState *machine)
spapr->icp = xics_system_init(machine,
DIV_ROUND_UP(max_cpus * kvmppc_smt_threads(),
smp_threads),
- XICS_IRQS);
+ XICS_IRQS, &error_fatal);
if (smc->dr_lmb_enabled) {
- spapr_validate_node_memory(machine);
+ spapr_validate_node_memory(machine, &error_fatal);
}
/* init CPUs */
@@ -1807,10 +1826,10 @@ static void ppc_spapr_init(MachineState *machine)
for (i = 0; i < smp_cpus; i++) {
cpu = cpu_ppc_init(machine->cpu_model);
if (cpu == NULL) {
- fprintf(stderr, "Unable to find PowerPC CPU definition\n");
+ error_report("Unable to find PowerPC CPU definition");
exit(1);
}
- spapr_cpu_init(spapr, cpu);
+ spapr_cpu_init(spapr, cpu, &error_fatal);
}
if (kvm_enabled()) {
@@ -1837,10 +1856,10 @@ static void ppc_spapr_init(MachineState *machine)
ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) {
- error_report("Specified number of memory slots %" PRIu64
- " exceeds max supported %d",
+ error_report("Specified number of memory slots %"
+ PRIu64" exceeds max supported %d",
machine->ram_slots, SPAPR_MAX_RAM_SLOTS);
- exit(EXIT_FAILURE);
+ exit(1);
}
spapr->hotplug_memory.base = ROUND_UP(machine->ram_size,
@@ -1915,7 +1934,7 @@ static void ppc_spapr_init(MachineState *machine)
}
/* Graphics */
- if (spapr_vga_init(phb->bus)) {
+ if (spapr_vga_init(phb->bus, &error_fatal)) {
spapr->has_graphics = true;
machine->usb |= defaults_enabled() && !machine->usb_disabled;
}
@@ -1936,8 +1955,9 @@ static void ppc_spapr_init(MachineState *machine)
}
if (spapr->rma_size < (MIN_RMA_SLOF << 20)) {
- fprintf(stderr, "qemu: pSeries SLOF firmware requires >= "
- "%ldM guest RMA (Real Mode Area memory)\n", MIN_RMA_SLOF);
+ error_report(
+ "pSeries SLOF firmware requires >= %ldM guest RMA (Real Mode Area memory)",
+ MIN_RMA_SLOF);
exit(1);
}
@@ -1953,8 +1973,8 @@ static void ppc_spapr_init(MachineState *machine)
kernel_le = kernel_size > 0;
}
if (kernel_size < 0) {
- fprintf(stderr, "qemu: error loading %s: %s\n",
- kernel_filename, load_elf_strerror(kernel_size));
+ error_report("error loading %s: %s",
+ kernel_filename, load_elf_strerror(kernel_size));
exit(1);
}
@@ -1967,8 +1987,8 @@ static void ppc_spapr_init(MachineState *machine)
initrd_size = load_image_targphys(initrd_filename, initrd_base,
load_limit - initrd_base);
if (initrd_size < 0) {
- fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
- initrd_filename);
+ error_report("could not load initial ram disk '%s'",
+ initrd_filename);
exit(1);
}
} else {
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 51083cd756..12f8c33db7 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -38,42 +38,6 @@ static void set_spr(CPUState *cs, int spr, target_ulong value,
run_on_cpu(cs, do_spr_sync, &s);
}
-static target_ulong compute_tlbie_rb(target_ulong v, target_ulong r,
- target_ulong pte_index)
-{
- target_ulong rb, va_low;
-
- rb = (v & ~0x7fULL) << 16; /* AVA field */
- va_low = pte_index >> 3;
- if (v & HPTE64_V_SECONDARY) {
- va_low = ~va_low;
- }
- /* xor vsid from AVA */
- if (!(v & HPTE64_V_1TB_SEG)) {
- va_low ^= v >> 12;
- } else {
- va_low ^= v >> 24;
- }
- va_low &= 0x7ff;
- if (v & HPTE64_V_LARGE) {
- rb |= 1; /* L field */
-#if 0 /* Disable that P7 specific bit for now */
- if (r & 0xff000) {
- /* non-16MB large page, must be 64k */
- /* (masks depend on page size) */
- rb |= 0x1000; /* page encoding in LP field */
- rb |= (va_low & 0x7f) << 16; /* 7b of VA in AVA/LP field */
- rb |= (va_low & 0xfe); /* AVAL field */
- }
-#endif
- } else {
- /* 4kB page */
- rb |= (va_low & 0x7ff) << 12; /* remaining 11b of AVA */
- }
- rb |= (v >> 54) & 0x300; /* B field */
- return rb;
-}
-
static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
{
/*
@@ -85,42 +49,44 @@ static inline bool valid_pte_index(CPUPPCState *env, target_ulong pte_index)
return true;
}
+static bool is_ram_address(sPAPRMachineState *spapr, hwaddr addr)
+{
+ MachineState *machine = MACHINE(spapr);
+ MemoryHotplugState *hpms = &spapr->hotplug_memory;
+
+ if (addr < machine->ram_size) {
+ return true;
+ }
+ if ((addr >= hpms->base)
+ && ((addr - hpms->base) < memory_region_size(&hpms->mr))) {
+ return true;
+ }
+
+ return false;
+}
+
static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
- MachineState *machine = MACHINE(spapr);
CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong pteh = args[2];
target_ulong ptel = args[3];
- target_ulong page_shift = 12;
+ unsigned apshift, spshift;
target_ulong raddr;
target_ulong index;
uint64_t token;
- /* only handle 4k and 16M pages for now */
- if (pteh & HPTE64_V_LARGE) {
-#if 0 /* We don't support 64k pages yet */
- if ((ptel & 0xf000) == 0x1000) {
- /* 64k page */
- } else
-#endif
- if ((ptel & 0xff000) == 0) {
- /* 16M page */
- page_shift = 24;
- /* lowest AVA bit must be 0 for 16M pages */
- if (pteh & 0x80) {
- return H_PARAMETER;
- }
- } else {
- return H_PARAMETER;
- }
+ apshift = ppc_hash64_hpte_page_shift_noslb(cpu, pteh, ptel, &spshift);
+ if (!apshift) {
+ /* Bad page size encoding */
+ return H_PARAMETER;
}
- raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << page_shift) - 1);
+ raddr = (ptel & HPTE64_R_RPN) & ~((1ULL << apshift) - 1);
- if (raddr < machine->ram_size) {
+ if (is_ram_address(spapr, raddr)) {
/* Regular RAM - should have WIMG=0010 */
if ((ptel & HPTE64_R_WIMG) != HPTE64_R_M) {
return H_PARAMETER;
@@ -146,7 +112,7 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
pte_index &= ~7ULL;
token = ppc_hash64_start_access(cpu, pte_index);
for (; index < 8; index++) {
- if ((ppc_hash64_load_hpte0(env, token, index) & HPTE64_V_VALID) == 0) {
+ if (!(ppc_hash64_load_hpte0(cpu, token, index) & HPTE64_V_VALID)) {
break;
}
}
@@ -156,14 +122,14 @@ static target_ulong h_enter(PowerPCCPU *cpu, sPAPRMachineState *spapr,
}
} else {
token = ppc_hash64_start_access(cpu, pte_index);
- if (ppc_hash64_load_hpte0(env, token, 0) & HPTE64_V_VALID) {
+ if (ppc_hash64_load_hpte0(cpu, token, 0) & HPTE64_V_VALID) {
ppc_hash64_stop_access(token);
return H_PTEG_FULL;
}
ppc_hash64_stop_access(token);
}
- ppc_hash64_store_hpte(env, pte_index + index,
+ ppc_hash64_store_hpte(cpu, pte_index + index,
pteh | HPTE64_V_HPTE_DIRTY, ptel);
args[0] = pte_index + index;
@@ -177,21 +143,22 @@ typedef enum {
REMOVE_HW = 3,
} RemoveResult;
-static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
+static RemoveResult remove_hpte(PowerPCCPU *cpu, target_ulong ptex,
target_ulong avpn,
target_ulong flags,
target_ulong *vp, target_ulong *rp)
{
+ CPUPPCState *env = &cpu->env;
uint64_t token;
- target_ulong v, r, rb;
+ target_ulong v, r;
if (!valid_pte_index(env, ptex)) {
return REMOVE_PARM;
}
- token = ppc_hash64_start_access(ppc_env_get_cpu(env), ptex);
- v = ppc_hash64_load_hpte0(env, token, 0);
- r = ppc_hash64_load_hpte1(env, token, 0);
+ token = ppc_hash64_start_access(cpu, ptex);
+ v = ppc_hash64_load_hpte0(cpu, token, 0);
+ r = ppc_hash64_load_hpte1(cpu, token, 0);
ppc_hash64_stop_access(token);
if ((v & HPTE64_V_VALID) == 0 ||
@@ -201,22 +168,20 @@ static RemoveResult remove_hpte(CPUPPCState *env, target_ulong ptex,
}
*vp = v;
*rp = r;
- ppc_hash64_store_hpte(env, ptex, HPTE64_V_HPTE_DIRTY, 0);
- rb = compute_tlbie_rb(v, r, ptex);
- ppc_tlb_invalidate_one(env, rb);
+ ppc_hash64_store_hpte(cpu, ptex, HPTE64_V_HPTE_DIRTY, 0);
+ ppc_hash64_tlb_flush_hpte(cpu, ptex, v, r);
return REMOVE_SUCCESS;
}
static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
- CPUPPCState *env = &cpu->env;
target_ulong flags = args[0];
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
RemoveResult ret;
- ret = remove_hpte(env, pte_index, avpn, flags,
+ ret = remove_hpte(cpu, pte_index, avpn, flags,
&args[0], &args[1]);
switch (ret) {
@@ -257,7 +222,6 @@ static target_ulong h_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args)
{
- CPUPPCState *env = &cpu->env;
int i;
for (i = 0; i < H_BULK_REMOVE_MAX_BATCH; i++) {
@@ -279,7 +243,7 @@ static target_ulong h_bulk_remove(PowerPCCPU *cpu, sPAPRMachineState *spapr,
return H_PARAMETER;
}
- ret = remove_hpte(env, *tsh & H_BULK_REMOVE_PTEX, tsl,
+ ret = remove_hpte(cpu, *tsh & H_BULK_REMOVE_PTEX, tsl,
(*tsh & H_BULK_REMOVE_FLAGS) >> 26,
&v, &r);
@@ -309,15 +273,15 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong pte_index = args[1];
target_ulong avpn = args[2];
uint64_t token;
- target_ulong v, r, rb;
+ target_ulong v, r;
if (!valid_pte_index(env, pte_index)) {
return H_PARAMETER;
}
token = ppc_hash64_start_access(cpu, pte_index);
- v = ppc_hash64_load_hpte0(env, token, 0);
- r = ppc_hash64_load_hpte1(env, token, 0);
+ v = ppc_hash64_load_hpte0(cpu, token, 0);
+ r = ppc_hash64_load_hpte1(cpu, token, 0);
ppc_hash64_stop_access(token);
if ((v & HPTE64_V_VALID) == 0 ||
@@ -330,12 +294,11 @@ static target_ulong h_protect(PowerPCCPU *cpu, sPAPRMachineState *spapr,
r |= (flags << 55) & HPTE64_R_PP0;
r |= (flags << 48) & HPTE64_R_KEY_HI;
r |= flags & (HPTE64_R_PP | HPTE64_R_N | HPTE64_R_KEY_LO);
- rb = compute_tlbie_rb(v, r, pte_index);
- ppc_hash64_store_hpte(env, pte_index,
+ ppc_hash64_store_hpte(cpu, pte_index,
(v & ~HPTE64_V_VALID) | HPTE64_V_HPTE_DIRTY, 0);
- ppc_tlb_invalidate_one(env, rb);
+ ppc_hash64_tlb_flush_hpte(cpu, pte_index, v, r);
/* Don't need a memory barrier, due to qemu's global lock */
- ppc_hash64_store_hpte(env, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
+ ppc_hash64_store_hpte(cpu, pte_index, v | HPTE64_V_HPTE_DIRTY, r);
return H_SUCCESS;
}
@@ -838,7 +801,7 @@ static target_ulong cas_get_option_vector(int vector, target_ulong table)
typedef struct {
PowerPCCPU *cpu;
uint32_t cpu_version;
- int ret;
+ Error *err;
} SetCompatState;
static void do_set_compat(void *arg)
@@ -846,7 +809,7 @@ static void do_set_compat(void *arg)
SetCompatState *s = arg;
cpu_synchronize_state(CPU(s->cpu));
- s->ret = ppc_set_compat(s->cpu, s->cpu_version);
+ ppc_set_compat(s->cpu, s->cpu_version, &s->err);
}
#define get_compat_level(cpuver) ( \
@@ -862,7 +825,8 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
target_ulong opcode,
target_ulong *args)
{
- target_ulong list = args[0], ov_table;
+ target_ulong list = ppc64_phys_to_real(args[0]);
+ target_ulong ov_table, ov5;
PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
CPUState *cs;
bool cpu_match = false, cpu_update = true, memory_update = false;
@@ -876,9 +840,9 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
for (counter = 0; counter < 512; ++counter) {
uint32_t pvr, pvr_mask;
- pvr_mask = rtas_ld(list, 0);
+ pvr_mask = ldl_be_phys(&address_space_memory, list);
list += 4;
- pvr = rtas_ld(list, 0);
+ pvr = ldl_be_phys(&address_space_memory, list);
list += 4;
trace_spapr_cas_pvr_try(pvr);
@@ -930,13 +894,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
SetCompatState s = {
.cpu = POWERPC_CPU(cs),
.cpu_version = cpu_version,
- .ret = 0
+ .err = NULL,
};
run_on_cpu(cs, do_set_compat, &s);
- if (s.ret < 0) {
- fprintf(stderr, "Unable to set compatibility mode\n");
+ if (s.err) {
+ error_report_err(s.err);
return H_HARDWARE;
}
}
@@ -949,14 +913,13 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
/* For the future use: here @ov_table points to the first option vector */
ov_table = list;
- list = cas_get_option_vector(5, ov_table);
- if (!list) {
+ ov5 = cas_get_option_vector(5, ov_table);
+ if (!ov5) {
return H_SUCCESS;
}
/* @list now points to OV 5 */
- list += 2;
- ov5_byte2 = rtas_ld(list, 0) >> 24;
+ ov5_byte2 = ldub_phys(&address_space_memory, ov5 + 2);
if (ov5_byte2 & OV5_DRCONF_MEMORY) {
memory_update = true;
}
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index f3ead8c1ce..07ad672e5a 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -229,6 +229,19 @@ static void rtas_stop_self(PowerPCCPU *cpu, sPAPRMachineState *spapr,
env->msr = 0;
}
+static inline int sysparm_st(target_ulong addr, target_ulong len,
+ const void *val, uint16_t vallen)
+{
+ hwaddr phys = ppc64_phys_to_real(addr);
+
+ if (len < 2) {
+ return RTAS_OUT_SYSPARM_PARAM_ERROR;
+ }
+ stw_be_phys(&address_space_memory, phys, vallen);
+ cpu_physical_memory_write(phys + 2, val, MIN(len - 2, vallen));
+ return RTAS_OUT_SUCCESS;
+}
+
static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
@@ -238,7 +251,7 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
target_ulong parameter = rtas_ld(args, 0);
target_ulong buffer = rtas_ld(args, 1);
target_ulong length = rtas_ld(args, 2);
- target_ulong ret = RTAS_OUT_SUCCESS;
+ target_ulong ret;
switch (parameter) {
case RTAS_SYSPARM_SPLPAR_CHARACTERISTICS: {
@@ -250,18 +263,18 @@ static void rtas_ibm_get_system_parameter(PowerPCCPU *cpu,
current_machine->ram_size / M_BYTE,
smp_cpus,
max_cpus);
- rtas_st_buffer(buffer, length, (uint8_t *)param_val, strlen(param_val));
+ ret = sysparm_st(buffer, length, param_val, strlen(param_val) + 1);
g_free(param_val);
break;
}
case RTAS_SYSPARM_DIAGNOSTICS_RUN_MODE: {
uint8_t param_val = DIAGNOSTICS_RUN_MODE_DISABLED;
- rtas_st_buffer(buffer, length, &param_val, sizeof(param_val));
+ ret = sysparm_st(buffer, length, &param_val, sizeof(param_val));
break;
}
case RTAS_SYSPARM_UUID:
- rtas_st_buffer(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0));
+ ret = sysparm_st(buffer, length, qemu_uuid, (qemu_uuid_set ? 16 : 0));
break;
default:
ret = RTAS_OUT_NOT_SUPPORTED;
@@ -493,6 +506,13 @@ out:
#define CC_VAL_DATA_OFFSET ((CC_IDX_PROP_DATA_OFFSET + 1) * 4)
#define CC_WA_LEN 4096
+static void configure_connector_st(target_ulong addr, target_ulong offset,
+ const void *buf, size_t len)
+{
+ cpu_physical_memory_write(ppc64_phys_to_real(addr + offset),
+ buf, MIN(len, CC_WA_LEN - offset));
+}
+
static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
sPAPRMachineState *spapr,
uint32_t token, uint32_t nargs,
@@ -558,8 +578,7 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
/* provide the name of the next OF node */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_NODE_NAME_OFFSET, wa_offset);
- rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
- (uint8_t *)name, strlen(name) + 1);
+ configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
resp = SPAPR_DR_CC_RESPONSE_NEXT_CHILD;
break;
case FDT_END_NODE:
@@ -584,8 +603,7 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
/* provide the name of the next OF property */
wa_offset = CC_VAL_DATA_OFFSET;
rtas_st(wa_addr, CC_IDX_PROP_NAME_OFFSET, wa_offset);
- rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
- (uint8_t *)name, strlen(name) + 1);
+ configure_connector_st(wa_addr, wa_offset, name, strlen(name) + 1);
/* provide the length and value of the OF property. data gets
* placed immediately after NULL terminator of the OF property's
@@ -594,9 +612,7 @@ static void rtas_ibm_configure_connector(PowerPCCPU *cpu,
wa_offset += strlen(name) + 1,
rtas_st(wa_addr, CC_IDX_PROP_LEN, prop_len);
rtas_st(wa_addr, CC_IDX_PROP_DATA_OFFSET, wa_offset);
- rtas_st_buffer_direct(wa_addr + wa_offset, CC_WA_LEN - wa_offset,
- (uint8_t *)((struct fdt_property *)prop)->data,
- prop_len);
+ configure_connector_st(wa_addr, wa_offset, prop->data, prop_len);
resp = SPAPR_DR_CC_RESPONSE_NEXT_PROPERTY;
break;
case FDT_END:
@@ -649,17 +665,11 @@ target_ulong spapr_rtas_call(PowerPCCPU *cpu, sPAPRMachineState *spapr,
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
{
- if (!((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX))) {
- fprintf(stderr, "RTAS invalid token 0x%x\n", token);
- exit(1);
- }
+ assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
token -= RTAS_TOKEN_BASE;
- if (rtas_table[token].name) {
- fprintf(stderr, "RTAS call \"%s\" is registered already as 0x%x\n",
- rtas_table[token].name, token);
- exit(1);
- }
+
+ assert(!rtas_table[token].name);
rtas_table[token].name = name;
rtas_table[token].fn = fn;