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.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>
This commit is contained in:
@@ -5702,20 +5702,20 @@ case "$target_name" in
|
||||
ppc64)
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
;;
|
||||
ppc64le)
|
||||
TARGET_ARCH=ppc64
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
;;
|
||||
ppc64abi32)
|
||||
TARGET_ARCH=ppc64
|
||||
TARGET_BASE_ARCH=ppc
|
||||
TARGET_ABI_DIR=ppc
|
||||
echo "TARGET_ABI32=y" >> $config_target_mak
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml"
|
||||
gdb_xml_files="power64-core.xml power-fpu.xml power-altivec.xml power-spe.xml power-vsx.xml"
|
||||
;;
|
||||
sh4|sh4eb)
|
||||
TARGET_ARCH=sh4
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Copyright (C) 2008-2015 Free Software Foundation, Inc.
|
||||
|
||||
Copying and distribution of this file, with or without modification,
|
||||
are permitted in any medium without royalty provided the copyright
|
||||
notice and this notice are preserved. -->
|
||||
|
||||
<!-- POWER7 VSX registers that do not overlap existing FP and VMX
|
||||
registers. -->
|
||||
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
|
||||
<feature name="org.gnu.gdb.power.vsx">
|
||||
<reg name="vs0h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs1h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs2h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs3h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs4h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs5h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs6h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs7h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs8h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs9h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs10h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs11h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs12h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs13h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs14h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs15h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs16h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs17h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs18h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs19h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs20h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs21h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs22h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs23h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs24h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs25h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs26h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs27h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs28h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs29h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs30h" bitsize="64" type="uint64"/>
|
||||
<reg name="vs31h" bitsize="64" type="uint64"/>
|
||||
</feature>
|
||||
+14
-9
@@ -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()
|
||||
}
|
||||
};
|
||||
|
||||
+10
-2
@@ -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()
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -134,7 +134,6 @@ typedef struct MACIOIDEState {
|
||||
|
||||
MemoryRegion mem;
|
||||
IDEBus bus;
|
||||
BlockAIOCB *aiocb;
|
||||
IDEDMA dma;
|
||||
void *dbdma;
|
||||
bool dma_active;
|
||||
|
||||
+66
-46
@@ -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;
|
||||
@@ -763,6 +763,13 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
|
||||
uint32_t *int_buf, *cur_index, buf_len;
|
||||
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 {
|
||||
|
||||
+54
-91
@@ -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;
|
||||
}
|
||||
|
||||
+30
-20
@@ -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, ¶m_val, sizeof(param_val));
|
||||
ret = sysparm_st(buffer, length, ¶m_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;
|
||||
|
||||
+9
-27
@@ -408,14 +408,15 @@ int spapr_allocate_irq_block(int num, bool lsi, bool msi);
|
||||
#define RTAS_SLOT_PERM_ERR_LOG 2
|
||||
|
||||
/* RTAS return codes */
|
||||
#define RTAS_OUT_SUCCESS 0
|
||||
#define RTAS_OUT_NO_ERRORS_FOUND 1
|
||||
#define RTAS_OUT_HW_ERROR -1
|
||||
#define RTAS_OUT_BUSY -2
|
||||
#define RTAS_OUT_PARAM_ERROR -3
|
||||
#define RTAS_OUT_NOT_SUPPORTED -3
|
||||
#define RTAS_OUT_NO_SUCH_INDICATOR -3
|
||||
#define RTAS_OUT_NOT_AUTHORIZED -9002
|
||||
#define RTAS_OUT_SUCCESS 0
|
||||
#define RTAS_OUT_NO_ERRORS_FOUND 1
|
||||
#define RTAS_OUT_HW_ERROR -1
|
||||
#define RTAS_OUT_BUSY -2
|
||||
#define RTAS_OUT_PARAM_ERROR -3
|
||||
#define RTAS_OUT_NOT_SUPPORTED -3
|
||||
#define RTAS_OUT_NO_SUCH_INDICATOR -3
|
||||
#define RTAS_OUT_NOT_AUTHORIZED -9002
|
||||
#define RTAS_OUT_SYSPARM_PARAM_ERROR -9999
|
||||
|
||||
/* RTAS tokens */
|
||||
#define RTAS_TOKEN_BASE 0x2000
|
||||
@@ -505,25 +506,6 @@ static inline void rtas_st(target_ulong phys, int n, uint32_t val)
|
||||
stl_be_phys(&address_space_memory, ppc64_phys_to_real(phys + 4*n), val);
|
||||
}
|
||||
|
||||
static inline void rtas_st_buffer_direct(target_ulong phys,
|
||||
target_ulong phys_len,
|
||||
uint8_t *buffer, uint16_t buffer_len)
|
||||
{
|
||||
cpu_physical_memory_write(ppc64_phys_to_real(phys), buffer,
|
||||
MIN(buffer_len, phys_len));
|
||||
}
|
||||
|
||||
static inline void rtas_st_buffer(target_ulong phys, target_ulong phys_len,
|
||||
uint8_t *buffer, uint16_t buffer_len)
|
||||
{
|
||||
if (phys_len < 2) {
|
||||
return;
|
||||
}
|
||||
stw_be_phys(&address_space_memory,
|
||||
ppc64_phys_to_real(phys), buffer_len);
|
||||
rtas_st_buffer_direct(phys + 2, phys_len - 2, buffer, buffer_len);
|
||||
}
|
||||
|
||||
typedef void (*spapr_rtas_fn)(PowerPCCPU *cpu, sPAPRMachineState *sm,
|
||||
uint32_t token,
|
||||
uint32_t nargs, target_ulong args,
|
||||
|
||||
@@ -1139,10 +1139,10 @@
|
||||
"POWER7 v2.3")
|
||||
POWERPC_DEF("POWER7+_v2.1", CPU_POWERPC_POWER7P_v21, POWER7,
|
||||
"POWER7+ v2.1")
|
||||
POWERPC_DEF("POWER8E_v1.0", CPU_POWERPC_POWER8E_v10, POWER8,
|
||||
"POWER8E v1.0")
|
||||
POWERPC_DEF("POWER8_v1.0", CPU_POWERPC_POWER8_v10, POWER8,
|
||||
"POWER8 v1.0")
|
||||
POWERPC_DEF("POWER8E_v2.1", CPU_POWERPC_POWER8E_v21, POWER8,
|
||||
"POWER8E v2.1")
|
||||
POWERPC_DEF("POWER8_v2.0", CPU_POWERPC_POWER8_v20, POWER8,
|
||||
"POWER8 v2.0")
|
||||
POWERPC_DEF("970_v2.2", CPU_POWERPC_970_v22, 970,
|
||||
"PowerPC 970 v2.2")
|
||||
POWERPC_DEF("970fx_v1.0", CPU_POWERPC_970FX_v10, 970,
|
||||
@@ -1390,8 +1390,8 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
|
||||
{ "POWER5gs", "POWER5+_v2.1" },
|
||||
{ "POWER7", "POWER7_v2.3" },
|
||||
{ "POWER7+", "POWER7+_v2.1" },
|
||||
{ "POWER8E", "POWER8E_v1.0" },
|
||||
{ "POWER8", "POWER8_v1.0" },
|
||||
{ "POWER8E", "POWER8E_v2.1" },
|
||||
{ "POWER8", "POWER8_v2.0" },
|
||||
{ "970", "970_v2.2" },
|
||||
{ "970fx", "970fx_v3.1" },
|
||||
{ "970mp", "970mp_v1.1" },
|
||||
|
||||
@@ -557,9 +557,9 @@ enum {
|
||||
CPU_POWERPC_POWER7P_BASE = 0x004A0000,
|
||||
CPU_POWERPC_POWER7P_v21 = 0x004A0201,
|
||||
CPU_POWERPC_POWER8E_BASE = 0x004B0000,
|
||||
CPU_POWERPC_POWER8E_v10 = 0x004B0100,
|
||||
CPU_POWERPC_POWER8E_v21 = 0x004B0201,
|
||||
CPU_POWERPC_POWER8_BASE = 0x004D0000,
|
||||
CPU_POWERPC_POWER8_v10 = 0x004D0100,
|
||||
CPU_POWERPC_POWER8_v20 = 0x004D0200,
|
||||
CPU_POWERPC_970_v22 = 0x00390202,
|
||||
CPU_POWERPC_970FX_v10 = 0x00391100,
|
||||
CPU_POWERPC_970FX_v20 = 0x003C0200,
|
||||
|
||||
+33
-12
@@ -419,6 +419,7 @@ typedef struct ppc_slb_t ppc_slb_t;
|
||||
struct ppc_slb_t {
|
||||
uint64_t esid;
|
||||
uint64_t vsid;
|
||||
const struct ppc_one_seg_page_size *sps;
|
||||
};
|
||||
|
||||
#define MAX_SLB_ENTRIES 64
|
||||
@@ -686,24 +687,43 @@ enum {
|
||||
|
||||
#define FP_FX (1ull << FPSCR_FX)
|
||||
#define FP_FEX (1ull << FPSCR_FEX)
|
||||
#define FP_OX (1ull << FPSCR_OX)
|
||||
#define FP_OE (1ull << FPSCR_OE)
|
||||
#define FP_UX (1ull << FPSCR_UX)
|
||||
#define FP_UE (1ull << FPSCR_UE)
|
||||
#define FP_XX (1ull << FPSCR_XX)
|
||||
#define FP_XE (1ull << FPSCR_XE)
|
||||
#define FP_ZX (1ull << FPSCR_ZX)
|
||||
#define FP_ZE (1ull << FPSCR_ZE)
|
||||
#define FP_VX (1ull << FPSCR_VX)
|
||||
#define FP_OX (1ull << FPSCR_OX)
|
||||
#define FP_UX (1ull << FPSCR_UX)
|
||||
#define FP_ZX (1ull << FPSCR_ZX)
|
||||
#define FP_XX (1ull << FPSCR_XX)
|
||||
#define FP_VXSNAN (1ull << FPSCR_VXSNAN)
|
||||
#define FP_VXISI (1ull << FPSCR_VXISI)
|
||||
#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
|
||||
#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
|
||||
#define FP_VXIDI (1ull << FPSCR_VXIDI)
|
||||
#define FP_VXZDZ (1ull << FPSCR_VXZDZ)
|
||||
#define FP_VXIMZ (1ull << FPSCR_VXIMZ)
|
||||
#define FP_VXVC (1ull << FPSCR_VXVC)
|
||||
#define FP_FR (1ull << FSPCR_FR)
|
||||
#define FP_FI (1ull << FPSCR_FI)
|
||||
#define FP_C (1ull << FPSCR_C)
|
||||
#define FP_FL (1ull << FPSCR_FL)
|
||||
#define FP_FG (1ull << FPSCR_FG)
|
||||
#define FP_FE (1ull << FPSCR_FE)
|
||||
#define FP_FU (1ull << FPSCR_FU)
|
||||
#define FP_FPCC (FP_FL | FP_FG | FP_FE | FP_FU)
|
||||
#define FP_FPRF (FP_C | FP_FL | FP_FG | FP_FE | FP_FU)
|
||||
#define FP_VXSOFT (1ull << FPSCR_VXSOFT)
|
||||
#define FP_VXSQRT (1ull << FPSCR_VXSQRT)
|
||||
#define FP_VXCVI (1ull << FPSCR_VXCVI)
|
||||
#define FP_VE (1ull << FPSCR_VE)
|
||||
#define FP_FI (1ull << FPSCR_FI)
|
||||
#define FP_OE (1ull << FPSCR_OE)
|
||||
#define FP_UE (1ull << FPSCR_UE)
|
||||
#define FP_ZE (1ull << FPSCR_ZE)
|
||||
#define FP_XE (1ull << FPSCR_XE)
|
||||
#define FP_NI (1ull << FPSCR_NI)
|
||||
#define FP_RN1 (1ull << FPSCR_RN1)
|
||||
#define FP_RN (1ull << FPSCR_RN)
|
||||
|
||||
/* the exception bits which can be cleared by mcrfs - includes FX */
|
||||
#define FP_EX_CLEAR_BITS (FP_FX | FP_OX | FP_UX | FP_ZX | \
|
||||
FP_XX | FP_VXSNAN | FP_VXISI | FP_VXIDI | \
|
||||
FP_VXZDZ | FP_VXIMZ | FP_VXVC | FP_VXSOFT | \
|
||||
FP_VXSQRT | FP_VXCVI)
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Vector status and control register */
|
||||
@@ -1210,7 +1230,7 @@ void ppc_store_msr (CPUPPCState *env, target_ulong value);
|
||||
|
||||
void ppc_cpu_list (FILE *f, fprintf_function cpu_fprintf);
|
||||
int ppc_get_compat_smt_threads(PowerPCCPU *cpu);
|
||||
int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version);
|
||||
void ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version, Error **errp);
|
||||
|
||||
/* Time-base and decrementer management */
|
||||
#ifndef NO_CPU_IO_DEFS
|
||||
@@ -2355,4 +2375,5 @@ int ppc_get_vcpu_dt_id(PowerPCCPU *cpu);
|
||||
*/
|
||||
PowerPCCPU *ppc_get_vcpu_by_dt_id(int cpu_dt_id);
|
||||
|
||||
void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len);
|
||||
#endif /* !defined (__CPU_PPC_H__) */
|
||||
|
||||
@@ -88,7 +88,7 @@ static int ppc_gdb_register_len(int n)
|
||||
the proper ordering for the binary, and cannot be changed.
|
||||
For system mode, TARGET_WORDS_BIGENDIAN is always set, and we must check
|
||||
the current mode of the chip to see if we're running in little-endian. */
|
||||
static void maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
|
||||
void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (!msr_le) {
|
||||
@@ -158,7 +158,7 @@ int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
break;
|
||||
}
|
||||
}
|
||||
maybe_bswap_register(env, mem_buf, r);
|
||||
ppc_maybe_bswap_register(env, mem_buf, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
break;
|
||||
}
|
||||
}
|
||||
maybe_bswap_register(env, mem_buf, r);
|
||||
ppc_maybe_bswap_register(env, mem_buf, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
if (!r) {
|
||||
return r;
|
||||
}
|
||||
maybe_bswap_register(env, mem_buf, r);
|
||||
ppc_maybe_bswap_register(env, mem_buf, r);
|
||||
if (n < 32) {
|
||||
/* gprs */
|
||||
env->gpr[n] = ldtul_p(mem_buf);
|
||||
@@ -277,7 +277,7 @@ int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n)
|
||||
if (!r) {
|
||||
return r;
|
||||
}
|
||||
maybe_bswap_register(env, mem_buf, r);
|
||||
ppc_maybe_bswap_register(env, mem_buf, r);
|
||||
if (n < 32) {
|
||||
/* gprs */
|
||||
env->gpr[n] = ldq_p(mem_buf);
|
||||
|
||||
@@ -544,6 +544,7 @@ DEF_HELPER_2(74xx_tlbd, void, env, tl)
|
||||
DEF_HELPER_2(74xx_tlbi, void, env, tl)
|
||||
DEF_HELPER_FLAGS_1(tlbia, TCG_CALL_NO_RWG, void, env)
|
||||
DEF_HELPER_FLAGS_2(tlbie, TCG_CALL_NO_RWG, void, env, tl)
|
||||
DEF_HELPER_FLAGS_2(tlbiva, TCG_CALL_NO_RWG, void, env, tl)
|
||||
#if defined(TARGET_PPC64)
|
||||
DEF_HELPER_FLAGS_3(store_slb, TCG_CALL_NO_RWG, void, env, tl, tl)
|
||||
DEF_HELPER_2(load_slb_esid, tl, env, tl)
|
||||
|
||||
+13
-1
@@ -650,8 +650,13 @@ static int kvm_put_fp(CPUState *cs)
|
||||
for (i = 0; i < 32; i++) {
|
||||
uint64_t vsr[2];
|
||||
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
vsr[0] = float64_val(env->fpr[i]);
|
||||
vsr[1] = env->vsr[i];
|
||||
#else
|
||||
vsr[0] = env->vsr[i];
|
||||
vsr[1] = float64_val(env->fpr[i]);
|
||||
#endif
|
||||
reg.addr = (uintptr_t) &vsr;
|
||||
reg.id = vsx ? KVM_REG_PPC_VSR(i) : KVM_REG_PPC_FPR(i);
|
||||
|
||||
@@ -721,10 +726,17 @@ static int kvm_get_fp(CPUState *cs)
|
||||
vsx ? "VSR" : "FPR", i, strerror(errno));
|
||||
return ret;
|
||||
} else {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
env->fpr[i] = vsr[0];
|
||||
if (vsx) {
|
||||
env->vsr[i] = vsr[1];
|
||||
}
|
||||
#else
|
||||
env->fpr[i] = vsr[1];
|
||||
if (vsx) {
|
||||
env->vsr[i] = vsr[0];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1193,7 +1205,7 @@ int kvm_arch_get_registers(CPUState *cs)
|
||||
* Only restore valid entries
|
||||
*/
|
||||
if (rb & SLB_ESID_V) {
|
||||
ppc_store_slb(env, rb, rs);
|
||||
ppc_store_slb(cpu, rb & 0xfff, rb & ~0xfffULL, rs);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -98,11 +98,6 @@ static inline int kvmppc_get_hypercall(CPUPPCState *env, uint8_t *buf, int buf_l
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int kvmppc_read_segment_page_sizes(uint32_t *prop, int maxcells)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline int kvmppc_set_interrupt(PowerPCCPU *cpu, int irq, int level)
|
||||
{
|
||||
return -1;
|
||||
|
||||
+21
-1
@@ -3,6 +3,7 @@
|
||||
#include "hw/boards.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "helper_regs.h"
|
||||
#include "mmu-hash64.h"
|
||||
|
||||
static int cpu_load_old(QEMUFile *f, void *opaque, int version_id)
|
||||
{
|
||||
@@ -169,7 +170,7 @@ static int cpu_post_load(void *opaque, int version_id)
|
||||
env->spr[SPR_PVR] = env->spr_cb[SPR_PVR].default_value;
|
||||
env->lr = env->spr[SPR_LR];
|
||||
env->ctr = env->spr[SPR_CTR];
|
||||
env->xer = env->spr[SPR_XER];
|
||||
cpu_write_xer(env, env->spr[SPR_XER]);
|
||||
#if defined(TARGET_PPC64)
|
||||
env->cfar = env->spr[SPR_CFAR];
|
||||
#endif
|
||||
@@ -353,11 +354,30 @@ static bool slb_needed(void *opaque)
|
||||
return (cpu->env.mmu_model & POWERPC_MMU_64);
|
||||
}
|
||||
|
||||
static int slb_post_load(void *opaque, int version_id)
|
||||
{
|
||||
PowerPCCPU *cpu = opaque;
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int i;
|
||||
|
||||
/* We've pulled in the raw esid and vsid values from the migration
|
||||
* stream, but we need to recompute the page size pointers */
|
||||
for (i = 0; i < env->slb_nr; i++) {
|
||||
if (ppc_store_slb(cpu, i, env->slb[i].esid, env->slb[i].vsid) < 0) {
|
||||
/* Migration source had bad values in its SLB */
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_slb = {
|
||||
.name = "cpu/slb",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = slb_needed,
|
||||
.post_load = slb_post_load,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_INT32_EQUAL(env.slb_nr, PowerPCCPU),
|
||||
VMSTATE_SLB_ARRAY(env.slb, PowerPCCPU, MAX_SLB_ENTRIES),
|
||||
|
||||
+39
-29
@@ -84,9 +84,10 @@ static int ppc_hash32_pp_prot(int key, int pp, int nx)
|
||||
return prot;
|
||||
}
|
||||
|
||||
static int ppc_hash32_pte_prot(CPUPPCState *env,
|
||||
static int ppc_hash32_pte_prot(PowerPCCPU *cpu,
|
||||
target_ulong sr, ppc_hash_pte32_t pte)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
unsigned pp, key;
|
||||
|
||||
key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
|
||||
@@ -95,9 +96,11 @@ static int ppc_hash32_pte_prot(CPUPPCState *env,
|
||||
return ppc_hash32_pp_prot(key, pp, !!(sr & SR32_NX));
|
||||
}
|
||||
|
||||
static target_ulong hash32_bat_size(CPUPPCState *env,
|
||||
static target_ulong hash32_bat_size(PowerPCCPU *cpu,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
if ((msr_pr && !(batu & BATU32_VP))
|
||||
|| (!msr_pr && !(batu & BATU32_VS))) {
|
||||
return 0;
|
||||
@@ -106,7 +109,7 @@ static target_ulong hash32_bat_size(CPUPPCState *env,
|
||||
return BATU32_BEPI & ~((batu & BATU32_BL) << 15);
|
||||
}
|
||||
|
||||
static int hash32_bat_prot(CPUPPCState *env,
|
||||
static int hash32_bat_prot(PowerPCCPU *cpu,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
int pp, prot;
|
||||
@@ -122,7 +125,7 @@ static int hash32_bat_prot(CPUPPCState *env,
|
||||
return prot;
|
||||
}
|
||||
|
||||
static target_ulong hash32_bat_601_size(CPUPPCState *env,
|
||||
static target_ulong hash32_bat_601_size(PowerPCCPU *cpu,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
if (!(batl & BATL32_601_V)) {
|
||||
@@ -132,9 +135,10 @@ static target_ulong hash32_bat_601_size(CPUPPCState *env,
|
||||
return BATU32_BEPI & ~((batl & BATL32_601_BL) << 17);
|
||||
}
|
||||
|
||||
static int hash32_bat_601_prot(CPUPPCState *env,
|
||||
static int hash32_bat_601_prot(PowerPCCPU *cpu,
|
||||
target_ulong batu, target_ulong batl)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int key, pp;
|
||||
|
||||
pp = batu & BATU32_601_PP;
|
||||
@@ -146,9 +150,10 @@ static int hash32_bat_601_prot(CPUPPCState *env,
|
||||
return ppc_hash32_pp_prot(key, pp, 0);
|
||||
}
|
||||
|
||||
static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
|
||||
static hwaddr ppc_hash32_bat_lookup(PowerPCCPU *cpu, target_ulong ea, int rwx,
|
||||
int *prot)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong *BATlt, *BATut;
|
||||
int i;
|
||||
|
||||
@@ -167,9 +172,9 @@ static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
|
||||
target_ulong mask;
|
||||
|
||||
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
||||
mask = hash32_bat_601_size(env, batu, batl);
|
||||
mask = hash32_bat_601_size(cpu, batu, batl);
|
||||
} else {
|
||||
mask = hash32_bat_size(env, batu, batl);
|
||||
mask = hash32_bat_size(cpu, batu, batl);
|
||||
}
|
||||
LOG_BATS("%s: %cBAT%d v " TARGET_FMT_lx " BATu " TARGET_FMT_lx
|
||||
" BATl " TARGET_FMT_lx "\n", __func__,
|
||||
@@ -179,9 +184,9 @@ static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
|
||||
hwaddr raddr = (batl & mask) | (ea & ~mask);
|
||||
|
||||
if (unlikely(env->mmu_model == POWERPC_MMU_601)) {
|
||||
*prot = hash32_bat_601_prot(env, batu, batl);
|
||||
*prot = hash32_bat_601_prot(cpu, batu, batl);
|
||||
} else {
|
||||
*prot = hash32_bat_prot(env, batu, batl);
|
||||
*prot = hash32_bat_prot(cpu, batu, batl);
|
||||
}
|
||||
|
||||
return raddr & TARGET_PAGE_MASK;
|
||||
@@ -210,11 +215,12 @@ static hwaddr ppc_hash32_bat_lookup(CPUPPCState *env, target_ulong ea, int rwx,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
|
||||
static int ppc_hash32_direct_store(PowerPCCPU *cpu, target_ulong sr,
|
||||
target_ulong eaddr, int rwx,
|
||||
hwaddr *raddr, int *prot)
|
||||
{
|
||||
CPUState *cs = CPU(ppc_env_get_cpu(env));
|
||||
CPUState *cs = CPU(cpu);
|
||||
CPUPPCState *env = &cpu->env;
|
||||
int key = !!(msr_pr ? (sr & SR32_KP) : (sr & SR32_KS));
|
||||
|
||||
qemu_log_mask(CPU_LOG_MMU, "direct store...\n");
|
||||
@@ -294,12 +300,14 @@ static int ppc_hash32_direct_store(CPUPPCState *env, target_ulong sr,
|
||||
}
|
||||
}
|
||||
|
||||
hwaddr get_pteg_offset32(CPUPPCState *env, hwaddr hash)
|
||||
hwaddr get_pteg_offset32(PowerPCCPU *cpu, hwaddr hash)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
|
||||
return (hash * HASH_PTEG_SIZE_32) & env->htab_mask;
|
||||
}
|
||||
|
||||
static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
|
||||
static hwaddr ppc_hash32_pteg_search(PowerPCCPU *cpu, hwaddr pteg_off,
|
||||
bool secondary, target_ulong ptem,
|
||||
ppc_hash_pte32_t *pte)
|
||||
{
|
||||
@@ -308,8 +316,8 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
|
||||
int i;
|
||||
|
||||
for (i = 0; i < HPTES_PER_GROUP; i++) {
|
||||
pte0 = ppc_hash32_load_hpte0(env, pte_offset);
|
||||
pte1 = ppc_hash32_load_hpte1(env, pte_offset);
|
||||
pte0 = ppc_hash32_load_hpte0(cpu, pte_offset);
|
||||
pte1 = ppc_hash32_load_hpte1(cpu, pte_offset);
|
||||
|
||||
if ((pte0 & HPTE32_V_VALID)
|
||||
&& (secondary == !!(pte0 & HPTE32_V_SECONDARY))
|
||||
@@ -325,10 +333,11 @@ static hwaddr ppc_hash32_pteg_search(CPUPPCState *env, hwaddr pteg_off,
|
||||
return -1;
|
||||
}
|
||||
|
||||
static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
|
||||
static hwaddr ppc_hash32_htab_lookup(PowerPCCPU *cpu,
|
||||
target_ulong sr, target_ulong eaddr,
|
||||
ppc_hash_pte32_t *pte)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
hwaddr pteg_off, pte_offset;
|
||||
hwaddr hash;
|
||||
uint32_t vsid, pgidx, ptem;
|
||||
@@ -349,16 +358,16 @@ static hwaddr ppc_hash32_htab_lookup(CPUPPCState *env,
|
||||
" vsid=%" PRIx32 " ptem=%" PRIx32
|
||||
" hash=" TARGET_FMT_plx "\n",
|
||||
env->htab_base, env->htab_mask, vsid, ptem, hash);
|
||||
pteg_off = get_pteg_offset32(env, hash);
|
||||
pte_offset = ppc_hash32_pteg_search(env, pteg_off, 0, ptem, pte);
|
||||
pteg_off = get_pteg_offset32(cpu, hash);
|
||||
pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 0, ptem, pte);
|
||||
if (pte_offset == -1) {
|
||||
/* Secondary PTEG lookup */
|
||||
qemu_log_mask(CPU_LOG_MMU, "1 htab=" TARGET_FMT_plx "/" TARGET_FMT_plx
|
||||
" vsid=%" PRIx32 " api=%" PRIx32
|
||||
" hash=" TARGET_FMT_plx "\n", env->htab_base,
|
||||
env->htab_mask, vsid, ptem, ~hash);
|
||||
pteg_off = get_pteg_offset32(env, ~hash);
|
||||
pte_offset = ppc_hash32_pteg_search(env, pteg_off, 1, ptem, pte);
|
||||
pteg_off = get_pteg_offset32(cpu, ~hash);
|
||||
pte_offset = ppc_hash32_pteg_search(cpu, pteg_off, 1, ptem, pte);
|
||||
}
|
||||
|
||||
return pte_offset;
|
||||
@@ -400,7 +409,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
|
||||
/* 2. Check Block Address Translation entries (BATs) */
|
||||
if (env->nb_BATs != 0) {
|
||||
raddr = ppc_hash32_bat_lookup(env, eaddr, rwx, &prot);
|
||||
raddr = ppc_hash32_bat_lookup(cpu, eaddr, rwx, &prot);
|
||||
if (raddr != -1) {
|
||||
if (need_prot[rwx] & ~prot) {
|
||||
if (rwx == 2) {
|
||||
@@ -431,7 +440,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
|
||||
/* 4. Handle direct store segments */
|
||||
if (sr & SR32_T) {
|
||||
if (ppc_hash32_direct_store(env, sr, eaddr, rwx,
|
||||
if (ppc_hash32_direct_store(cpu, sr, eaddr, rwx,
|
||||
&raddr, &prot) == 0) {
|
||||
tlb_set_page(cs, eaddr & TARGET_PAGE_MASK,
|
||||
raddr & TARGET_PAGE_MASK, prot, mmu_idx,
|
||||
@@ -450,7 +459,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
}
|
||||
|
||||
/* 6. Locate the PTE in the hash table */
|
||||
pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte);
|
||||
pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
|
||||
if (pte_offset == -1) {
|
||||
if (rwx == 2) {
|
||||
cs->exception_index = POWERPC_EXCP_ISI;
|
||||
@@ -473,7 +482,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
|
||||
/* 7. Check access permissions */
|
||||
|
||||
prot = ppc_hash32_pte_prot(env, sr, pte);
|
||||
prot = ppc_hash32_pte_prot(cpu, sr, pte);
|
||||
|
||||
if (need_prot[rwx] & ~prot) {
|
||||
/* Access right violation */
|
||||
@@ -508,7 +517,7 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
}
|
||||
|
||||
if (new_pte1 != pte.pte1) {
|
||||
ppc_hash32_store_hpte1(env, pte_offset, new_pte1);
|
||||
ppc_hash32_store_hpte1(cpu, pte_offset, new_pte1);
|
||||
}
|
||||
|
||||
/* 9. Determine the real address from the PTE */
|
||||
@@ -521,8 +530,9 @@ int ppc_hash32_handle_mmu_fault(PowerPCCPU *cpu, target_ulong eaddr, int rwx,
|
||||
return 0;
|
||||
}
|
||||
|
||||
hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong eaddr)
|
||||
hwaddr ppc_hash32_get_phys_page_debug(PowerPCCPU *cpu, target_ulong eaddr)
|
||||
{
|
||||
CPUPPCState *env = &cpu->env;
|
||||
target_ulong sr;
|
||||
hwaddr pte_offset;
|
||||
ppc_hash_pte32_t pte;
|
||||
@@ -534,7 +544,7 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong eaddr)
|
||||
}
|
||||
|
||||
if (env->nb_BATs != 0) {
|
||||
hwaddr raddr = ppc_hash32_bat_lookup(env, eaddr, 0, &prot);
|
||||
hwaddr raddr = ppc_hash32_bat_lookup(cpu, eaddr, 0, &prot);
|
||||
if (raddr != -1) {
|
||||
return raddr;
|
||||
}
|
||||
@@ -547,7 +557,7 @@ hwaddr ppc_hash32_get_phys_page_debug(CPUPPCState *env, target_ulong eaddr)
|
||||
return -1;
|
||||
}
|
||||
|
||||
pte_offset = ppc_hash32_htab_lookup(env, sr, eaddr, &pte);
|
||||
pte_offset = ppc_hash32_htab_lookup(cpu, sr, eaddr, &pte);
|
||||
if (pte_offset == -1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user