ppc patch queue 2019-02-04

Here's the next batch of ppc target and spapr related changes.
 Highlights are:
  * A number of endianness handling cleanups from Mark Cave-Ayland
  * Updated Mac VGA driver
  * Updated SLOF image
  * Some XIVE cleanups and small fixes
  * ppc4xx cleanups and fixes from BALATON Zoltan
 
 There are a few chances not technically in the ppc target code:
  * Several MAINTAINERS updates
  * Fixes for unmapping of hugepages on power hosts
 
 The latter is included because it's primarily of interest for ppc KVM setups.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAlxX7zoACgkQbDjKyiDZ
 s5KA6g/+NgvY8keFJDoKwEohaE2hhKyd5S4Qo8Rg6SMfoT+NOup/qWPvdGw2srEN
 gUlUp+Cgxh45hfHK6GqVg8AbIF3JXcuvf6B8zCYYhY1doB8kBoBbkt6m1gl4NFSE
 mDApMXGaS0QqjVO2OakZHMfNmDIsZt1afv7RLrMaIeShKJkzyQPD+vepYJtuxTht
 vad+RZEKB4rra65QeFWzAATmqFc0c006wUeqaVYuEuZ8+dpSiDARFlFHEtDOgzMR
 bx4IUglOKTSbqiuqbbFVKYtIS4TRUqlz1UEkPchxNQjSWojFnIKbKR7CW+M1fjGv
 pbTHwvWBliILXFuD1D0spaD2SZwgX28qsSiG1AXDbll94+rW4PStPEN2XuVBOB8F
 7uKBlKVC4v2wGcS0NAp65OGS6c8jyCAA/mEJuUNyeOWlOM0PxJnh0LEDIw2BsjGx
 Eu4ruC3AiNNmYnDaRLmtM2NVZPoO+7JpZi2OjYMV61vpkUcCJWLE8kmfoM3XsyXg
 7j8V4s0sujxf3DMnL0WWoBFzVArp6ri3nGmXRHNnCcbDe3DD48Zht9gdO+Aa+47q
 E+crsrRf7cP2Fz+xnuOQwLQNMfYuZ+zQVCGOlbrBW7s5XOBnKXHtZi2HsTBXeowD
 zjQxOJde5YuPPejQa9FN8qGSURBHvZB9Xtm2XThuS5TDgjUwoXM=
 =grqW
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-4.0-20190204' into staging

ppc patch queue 2019-02-04

Here's the next batch of ppc target and spapr related changes.
Highlights are:
 * A number of endianness handling cleanups from Mark Cave-Ayland
 * Updated Mac VGA driver
 * Updated SLOF image
 * Some XIVE cleanups and small fixes
 * ppc4xx cleanups and fixes from BALATON Zoltan

There are a few chances not technically in the ppc target code:
 * Several MAINTAINERS updates
 * Fixes for unmapping of hugepages on power hosts

The latter is included because it's primarily of interest for ppc KVM setups.

# gpg: Signature made Mon 04 Feb 2019 07:52:26 GMT
# gpg:                using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full]
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full]
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full]
# gpg:                 aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown]
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-4.0-20190204: (37 commits)
  mmap-alloc: fix hugetlbfs misaligned length in ppc64
  mmap-alloc: unfold qemu_ram_mmap()
  hw/ppc: Don't include m48t59.h if it is not necessary
  spapr_pci: Fix endianness in assigned-addresses property
  target/ppc: remove various HOST_WORDS_BIGENDIAN hacks in int_helper.c
  target/ppc: remove ROTRu32 and ROTRu64 macros from int_helper.c
  target/ppc: simplify VEXT_SIGNED macro in int_helper.c
  target/ppc: eliminate use of EL_IDX macros from int_helper.c
  target/ppc: eliminate use of HI_IDX and LO_IDX macros from int_helper.c
  target/ppc: rework vmul{e,o}{s,u}{b,h,w} instructions to use Vsr* macros
  target/ppc: rework vmrg{l,h}{b,h,w} instructions to use Vsr* macros
  hw/ppc/spapr: Add support for "-vga cirrus"
  QemuMacDrivers: update qemu_vga.ndrv to 90c488d built from submodule
  MAINTAINERS: add myself as maintainer for Mac Old World and New World machines
  spapr: Drop unused parameters from fdt building helper
  MAINTAINERS: Merge the two e500 sections
  MAINTAINERS: XIVE is an interrupt controller, not a machine
  hw/ppc: Move ppc40x_*reset() functions from ppc405_uc.c to ppc.c
  ppc: remove the interrupt presenters from under PowerPCCPU
  target/ppc: implement complete set of Vsr* macros
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2019-02-04 10:33:40 +00:00
commit a61faa3d02
41 changed files with 682 additions and 776 deletions

View File

@ -960,9 +960,10 @@ e500
M: David Gibson <david@gibson.dropbear.id.au> M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org L: qemu-ppc@nongnu.org
S: Odd Fixes S: Odd Fixes
F: hw/ppc/e500.[hc] F: hw/ppc/e500*
F: hw/ppc/e500plat.c
F: hw/gpio/mpc8xxx.c F: hw/gpio/mpc8xxx.c
F: hw/net/fsl_etsec/
F: hw/pci-host/ppce500.c
F: include/hw/ppc/ppc_e500.h F: include/hw/ppc/ppc_e500.h
F: include/hw/pci-host/ppce500.h F: include/hw/pci-host/ppce500.h
F: pc-bios/u-boot.e500 F: pc-bios/u-boot.e500
@ -975,7 +976,8 @@ F: hw/ppc/mpc8544ds.c
F: hw/ppc/mpc8544_guts.c F: hw/ppc/mpc8544_guts.c
New World (mac99) New World (mac99)
M: David Gibson <david@gibson.dropbear.id.au> M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
R: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org L: qemu-ppc@nongnu.org
S: Odd Fixes S: Odd Fixes
F: hw/ppc/mac_newworld.c F: hw/ppc/mac_newworld.c
@ -993,7 +995,8 @@ F: include/hw/input/adb*
F: pc-bios/qemu_vga.ndrv F: pc-bios/qemu_vga.ndrv
Old World (g3beige) Old World (g3beige)
M: David Gibson <david@gibson.dropbear.id.au> M: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
R: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org L: qemu-ppc@nongnu.org
S: Odd Fixes S: Odd Fixes
F: hw/ppc/mac_oldworld.c F: hw/ppc/mac_oldworld.c
@ -1041,14 +1044,6 @@ F: tests/libqos/*spapr*
F: tests/rtas* F: tests/rtas*
F: tests/libqos/rtas* F: tests/libqos/rtas*
XIVE
M: David Gibson <david@gibson.dropbear.id.au>
M: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/*/*xive*
F: include/hw/*/*xive*
virtex_ml507 virtex_ml507
M: Edgar E. Iglesias <edgar.iglesias@gmail.com> M: Edgar E. Iglesias <edgar.iglesias@gmail.com>
L: qemu-ppc@nongnu.org L: qemu-ppc@nongnu.org
@ -1327,14 +1322,6 @@ F: hw/i2c/ppc4xx_i2c.c
F: include/hw/ppc/ppc4xx.h F: include/hw/ppc/ppc4xx.h
F: include/hw/i2c/ppc4xx_i2c.h F: include/hw/i2c/ppc4xx_i2c.h
ppce500
M: David Gibson <david@gibson.dropbear.id.au>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/ppc/e500*
F: hw/pci-host/ppce500.c
F: hw/net/fsl_etsec/
Character devices Character devices
M: Marc-André Lureau <marcandre.lureau@redhat.com> M: Marc-André Lureau <marcandre.lureau@redhat.com>
R: Paolo Bonzini <pbonzini@redhat.com> R: Paolo Bonzini <pbonzini@redhat.com>
@ -1648,6 +1635,14 @@ F: tests/libqos/fw_cfg.c
F: tests/fw_cfg-test.c F: tests/fw_cfg-test.c
T: git https://github.com/philmd/qemu.git fw_cfg-next T: git https://github.com/philmd/qemu.git fw_cfg-next
XIVE
M: David Gibson <david@gibson.dropbear.id.au>
M: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Supported
F: hw/*/*xive*
F: include/hw/*/*xive*
Subsystems Subsystems
---------- ----------
Audio Audio

4
exec.c
View File

@ -1873,7 +1873,7 @@ static void *file_ram_alloc(RAMBlock *block,
if (mem_prealloc) { if (mem_prealloc) {
os_mem_prealloc(fd, area, memory, smp_cpus, errp); os_mem_prealloc(fd, area, memory, smp_cpus, errp);
if (errp && *errp) { if (errp && *errp) {
qemu_ram_munmap(area, memory); qemu_ram_munmap(fd, area, memory);
return NULL; return NULL;
} }
} }
@ -2394,7 +2394,7 @@ static void reclaim_ramblock(RAMBlock *block)
xen_invalidate_map_cache_entry(block->host); xen_invalidate_map_cache_entry(block->host);
#ifndef _WIN32 #ifndef _WIN32
} else if (block->fd >= 0) { } else if (block->fd >= 0) {
qemu_ram_munmap(block->host, block->max_length); qemu_ram_munmap(block->fd, block->host, block->max_length);
close(block->fd); close(block->fd);
#endif #endif
} else { } else {

View File

@ -23,6 +23,8 @@
*/ */
#include "qemu/osdep.h" #include "qemu/osdep.h"
#include "qemu/units.h"
#include "qapi/error.h"
#include "hw/hw.h" #include "hw/hw.h"
#include "hw/i2c/i2c.h" #include "hw/i2c/i2c.h"
#include "hw/i2c/smbus.h" #include "hw/i2c/smbus.h"
@ -162,3 +164,130 @@ void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256)); smbus_eeprom_init_one(smbus, 0x50 + i, eeprom_buf + (i * 256));
} }
} }
/* Generate SDRAM SPD EEPROM data describing a module of type and size */
uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t ram_size,
Error **errp)
{
uint8_t *spd;
uint8_t nbanks;
uint16_t density;
uint32_t size;
int min_log2, max_log2, sz_log2;
int i;
switch (type) {
case SDR:
min_log2 = 2;
max_log2 = 9;
break;
case DDR:
min_log2 = 5;
max_log2 = 12;
break;
case DDR2:
min_log2 = 7;
max_log2 = 14;
break;
default:
g_assert_not_reached();
}
size = ram_size >> 20; /* work in terms of megabytes */
if (size < 4) {
error_setg(errp, "SDRAM size is too small");
return NULL;
}
sz_log2 = 31 - clz32(size);
size = 1U << sz_log2;
if (ram_size > size * MiB) {
error_setg(errp, "SDRAM size 0x"RAM_ADDR_FMT" is not a power of 2, "
"truncating to %u MB", ram_size, size);
}
if (sz_log2 < min_log2) {
error_setg(errp,
"Memory size is too small for SDRAM type, adjusting type");
if (size >= 32) {
type = DDR;
min_log2 = 5;
max_log2 = 12;
} else {
type = SDR;
min_log2 = 2;
max_log2 = 9;
}
}
nbanks = 1;
while (sz_log2 > max_log2 && nbanks < 8) {
sz_log2--;
nbanks++;
}
if (size > (1ULL << sz_log2) * nbanks) {
error_setg(errp, "Memory size is too big for SDRAM, truncating");
}
/* split to 2 banks if possible to avoid a bug in MIPS Malta firmware */
if (nbanks == 1 && sz_log2 > min_log2) {
sz_log2--;
nbanks++;
}
density = 1ULL << (sz_log2 - 2);
switch (type) {
case DDR2:
density = (density & 0xe0) | (density >> 8 & 0x1f);
break;
case DDR:
density = (density & 0xf8) | (density >> 8 & 0x07);
break;
case SDR:
default:
density &= 0xff;
break;
}
spd = g_malloc0(256);
spd[0] = 128; /* data bytes in EEPROM */
spd[1] = 8; /* log2 size of EEPROM */
spd[2] = type;
spd[3] = 13; /* row address bits */
spd[4] = 10; /* column address bits */
spd[5] = (type == DDR2 ? nbanks - 1 : nbanks);
spd[6] = 64; /* module data width */
/* reserved / data width high */
spd[8] = 4; /* interface voltage level */
spd[9] = 0x25; /* highest CAS latency */
spd[10] = 1; /* access time */
/* DIMM configuration 0 = non-ECC */
spd[12] = 0x82; /* refresh requirements */
spd[13] = 8; /* primary SDRAM width */
/* ECC SDRAM width */
spd[15] = (type == DDR2 ? 0 : 1); /* reserved / delay for random col rd */
spd[16] = 12; /* burst lengths supported */
spd[17] = 4; /* banks per SDRAM device */
spd[18] = 12; /* ~CAS latencies supported */
spd[19] = (type == DDR2 ? 0 : 1); /* reserved / ~CS latencies supported */
spd[20] = 2; /* DIMM type / ~WE latencies */
/* module features */
/* memory chip features */
spd[23] = 0x12; /* clock cycle time @ medium CAS latency */
/* data access time */
/* clock cycle time @ short CAS latency */
/* data access time */
spd[27] = 20; /* min. row precharge time */
spd[28] = 15; /* min. row active row delay */
spd[29] = 20; /* min. ~RAS to ~CAS delay */
spd[30] = 45; /* min. active to precharge time */
spd[31] = density;
spd[32] = 20; /* addr/cmd setup time */
spd[33] = 8; /* addr/cmd hold time */
spd[34] = 20; /* data input setup time */
spd[35] = 8; /* data input hold time */
/* checksum */
for (i = 0; i < 63; i++) {
spd[63] += spd[i];
}
return spd;
}

View File

@ -16,6 +16,7 @@
#include "monitor/monitor.h" #include "monitor/monitor.h"
#include "hw/ppc/fdt.h" #include "hw/ppc/fdt.h"
#include "hw/ppc/spapr.h" #include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/spapr_xive.h" #include "hw/ppc/spapr_xive.h"
#include "hw/ppc/xive.h" #include "hw/ppc/xive.h"
#include "hw/ppc/xive_regs.h" #include "hw/ppc/xive_regs.h"
@ -390,6 +391,13 @@ static int spapr_xive_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk,
g_assert_not_reached(); g_assert_not_reached();
} }
static XiveTCTX *spapr_xive_get_tctx(XiveRouter *xrtr, CPUState *cs)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
return spapr_cpu_state(cpu)->tctx;
}
static const VMStateDescription vmstate_spapr_xive_end = { static const VMStateDescription vmstate_spapr_xive_end = {
.name = TYPE_SPAPR_XIVE "/end", .name = TYPE_SPAPR_XIVE "/end",
.version_id = 1, .version_id = 1,
@ -454,6 +462,7 @@ static void spapr_xive_class_init(ObjectClass *klass, void *data)
xrc->write_end = spapr_xive_write_end; xrc->write_end = spapr_xive_write_end;
xrc->get_nvt = spapr_xive_get_nvt; xrc->get_nvt = spapr_xive_get_nvt;
xrc->write_nvt = spapr_xive_write_nvt; xrc->write_nvt = spapr_xive_write_nvt;
xrc->get_tctx = spapr_xive_get_tctx;
} }
static const TypeInfo spapr_xive_info = { static const TypeInfo spapr_xive_info = {

View File

@ -31,6 +31,7 @@
#include "trace.h" #include "trace.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "hw/ppc/spapr.h" #include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/xics.h" #include "hw/ppc/xics.h"
#include "hw/ppc/xics_spapr.h" #include "hw/ppc/xics_spapr.h"
#include "hw/ppc/fdt.h" #include "hw/ppc/fdt.h"
@ -45,7 +46,7 @@ static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{ {
target_ulong cppr = args[0]; target_ulong cppr = args[0];
icp_set_cppr(cpu->icp, cppr); icp_set_cppr(spapr_cpu_state(cpu)->icp, cppr);
return H_SUCCESS; return H_SUCCESS;
} }
@ -66,7 +67,7 @@ static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr, static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args) target_ulong opcode, target_ulong *args)
{ {
uint32_t xirr = icp_accept(cpu->icp); uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
args[0] = xirr; args[0] = xirr;
return H_SUCCESS; return H_SUCCESS;
@ -75,7 +76,7 @@ static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr, static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args) target_ulong opcode, target_ulong *args)
{ {
uint32_t xirr = icp_accept(cpu->icp); uint32_t xirr = icp_accept(spapr_cpu_state(cpu)->icp);
args[0] = xirr; args[0] = xirr;
args[1] = cpu_get_host_ticks(); args[1] = cpu_get_host_ticks();
@ -87,7 +88,7 @@ static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
{ {
target_ulong xirr = args[0]; target_ulong xirr = args[0];
icp_eoi(cpu->icp, xirr); icp_eoi(spapr_cpu_state(cpu)->icp, xirr);
return H_SUCCESS; return H_SUCCESS;
} }
@ -95,7 +96,7 @@ static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
target_ulong opcode, target_ulong *args) target_ulong opcode, target_ulong *args)
{ {
uint32_t mfrr; uint32_t mfrr;
uint32_t xirr = icp_ipoll(cpu->icp, &mfrr); uint32_t xirr = icp_ipoll(spapr_cpu_state(cpu)->icp, &mfrr);
args[0] = xirr; args[0] = xirr;
args[1] = mfrr; args[1] = mfrr;

View File

@ -320,8 +320,7 @@ static const XiveTmOp *xive_tm_find_op(hwaddr offset, unsigned size, bool write)
static void xive_tm_write(void *opaque, hwaddr offset, static void xive_tm_write(void *opaque, hwaddr offset,
uint64_t value, unsigned size) uint64_t value, unsigned size)
{ {
PowerPCCPU *cpu = POWERPC_CPU(current_cpu); XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
XiveTCTX *tctx = cpu->tctx;
const XiveTmOp *xto; const XiveTmOp *xto;
/* /*
@ -359,8 +358,7 @@ static void xive_tm_write(void *opaque, hwaddr offset,
static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size) static uint64_t xive_tm_read(void *opaque, hwaddr offset, unsigned size)
{ {
PowerPCCPU *cpu = POWERPC_CPU(current_cpu); XiveTCTX *tctx = xive_router_get_tctx(XIVE_ROUTER(opaque), current_cpu);
XiveTCTX *tctx = cpu->tctx;
const XiveTmOp *xto; const XiveTmOp *xto;
/* /*
@ -1107,6 +1105,13 @@ int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number); return xrc->write_nvt(xrtr, nvt_blk, nvt_idx, nvt, word_number);
} }
XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs)
{
XiveRouterClass *xrc = XIVE_ROUTER_GET_CLASS(xrtr);
return xrc->get_tctx(xrtr, cs);
}
/* /*
* The thread context register words are in big-endian format. * The thread context register words are in big-endian format.
*/ */
@ -1182,8 +1187,7 @@ static bool xive_presenter_match(XiveRouter *xrtr, uint8_t format,
*/ */
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs); XiveTCTX *tctx = xive_router_get_tctx(xrtr, cs);
XiveTCTX *tctx = cpu->tctx;
int ring; int ring;
/* /*
@ -1576,9 +1580,9 @@ static const TypeInfo xive_end_source_info = {
}; };
/* /*
* XIVE Fabric * XIVE Notifier
*/ */
static const TypeInfo xive_fabric_info = { static const TypeInfo xive_notifier_info = {
.name = TYPE_XIVE_NOTIFIER, .name = TYPE_XIVE_NOTIFIER,
.parent = TYPE_INTERFACE, .parent = TYPE_INTERFACE,
.class_size = sizeof(XiveNotifierClass), .class_size = sizeof(XiveNotifierClass),
@ -1587,7 +1591,7 @@ static const TypeInfo xive_fabric_info = {
static void xive_register_types(void) static void xive_register_types(void)
{ {
type_register_static(&xive_source_info); type_register_static(&xive_source_info);
type_register_static(&xive_fabric_info); type_register_static(&xive_notifier_info);
type_register_static(&xive_router_info); type_register_static(&xive_router_info);
type_register_static(&xive_end_source_info); type_register_static(&xive_end_source_info);
type_register_static(&xive_tctx_info); type_register_static(&xive_tctx_info);

View File

@ -13,8 +13,7 @@ obj-y += spapr_pci_vfio.o
endif endif
obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o obj-$(CONFIG_PSERIES) += spapr_rtas_ddw.o
# PowerPC 4xx boards # PowerPC 4xx boards
obj-y += ppc4xx_devs.o ppc405_uc.o obj-$(CONFIG_PPC4XX) += ppc4xx_devs.o ppc4xx_pci.o ppc405_uc.o ppc405_boards.o
obj-$(CONFIG_PPC4XX) += ppc4xx_pci.o ppc405_boards.o
obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o obj-$(CONFIG_PPC4XX) += ppc440_bamboo.o ppc440_pcix.o ppc440_uc.o
obj-$(CONFIG_SAM460EX) += sam460ex.o obj-$(CONFIG_SAM460EX) += sam460ex.o
# PReP # PReP

View File

@ -53,7 +53,6 @@
#include "hw/ppc/mac.h" #include "hw/ppc/mac.h"
#include "hw/input/adb.h" #include "hw/input/adb.h"
#include "hw/ppc/mac_dbdma.h" #include "hw/ppc/mac_dbdma.h"
#include "hw/timer/m48t59.h"
#include "hw/pci/pci.h" #include "hw/pci/pci.h"
#include "net/net.h" #include "net/net.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"

View File

@ -30,7 +30,6 @@
#include "hw/ppc/ppc.h" #include "hw/ppc/ppc.h"
#include "mac.h" #include "mac.h"
#include "hw/input/adb.h" #include "hw/input/adb.h"
#include "hw/timer/m48t59.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "net/net.h" #include "net/net.h"
#include "hw/isa/isa.h" #include "hw/isa/isa.h"

View File

@ -673,6 +673,7 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
{ {
Error *local_err = NULL; Error *local_err = NULL;
Object *obj; Object *obj;
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()), obj = icp_create(OBJECT(cpu), TYPE_PNV_ICP, XICS_FABRIC(qdev_get_machine()),
&local_err); &local_err);
@ -681,7 +682,7 @@ static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
return; return;
} }
cpu->icp = ICP(obj); pnv_cpu->icp = ICP(obj);
} }
/* /*
@ -1099,7 +1100,7 @@ static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
{ {
PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir); PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
return cpu ? cpu->icp : NULL; return cpu ? pnv_cpu_state(cpu)->icp : NULL;
} }
static void pnv_pic_print_info(InterruptStatsProvider *obj, static void pnv_pic_print_info(InterruptStatsProvider *obj,
@ -1112,7 +1113,7 @@ static void pnv_pic_print_info(InterruptStatsProvider *obj,
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_pic_print_info(cpu->icp, mon); icp_pic_print_info(pnv_cpu_state(cpu)->icp, mon);
} }
for (i = 0; i < pnv->num_chips; i++) { for (i = 0; i < pnv->num_chips; i++) {

View File

@ -155,7 +155,10 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
pc->threads = g_new(PowerPCCPU *, cc->nr_threads); pc->threads = g_new(PowerPCCPU *, cc->nr_threads);
for (i = 0; i < cc->nr_threads; i++) { for (i = 0; i < cc->nr_threads; i++) {
PowerPCCPU *cpu;
obj = object_new(typename); obj = object_new(typename);
cpu = POWERPC_CPU(obj);
pc->threads[i] = POWERPC_CPU(obj); pc->threads[i] = POWERPC_CPU(obj);
@ -163,6 +166,9 @@ static void pnv_core_realize(DeviceState *dev, Error **errp)
object_property_add_child(OBJECT(pc), name, obj, &error_abort); object_property_add_child(OBJECT(pc), name, obj, &error_abort);
object_property_add_alias(obj, "core-pir", OBJECT(pc), object_property_add_alias(obj, "core-pir", OBJECT(pc),
"pir", &error_abort); "pir", &error_abort);
cpu->machine_data = g_new0(PnvCPUState, 1);
object_unref(obj); object_unref(obj);
} }
@ -189,9 +195,13 @@ err:
static void pnv_unrealize_vcpu(PowerPCCPU *cpu) static void pnv_unrealize_vcpu(PowerPCCPU *cpu)
{ {
PnvCPUState *pnv_cpu = pnv_cpu_state(cpu);
qemu_unregister_reset(pnv_cpu_reset, cpu); qemu_unregister_reset(pnv_cpu_reset, cpu);
object_unparent(OBJECT(cpu->icp)); object_unparent(OBJECT(pnv_cpu_state(cpu)->icp));
cpu_remove_sync(CPU(cpu)); cpu_remove_sync(CPU(cpu));
cpu->machine_data = NULL;
g_free(pnv_cpu);
object_unparent(OBJECT(cpu)); object_unparent(OBJECT(cpu));
} }

View File

@ -30,10 +30,8 @@
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "sysemu/cpus.h" #include "sysemu/cpus.h"
#include "hw/timer/m48t59.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "hw/loader.h"
#include "sysemu/kvm.h" #include "sysemu/kvm.h"
#include "kvm_ppc.h" #include "kvm_ppc.h"
#include "trace.h" #include "trace.h"
@ -310,6 +308,62 @@ void ppcPOWER7_irq_init(PowerPCCPU *cpu)
} }
#endif /* defined(TARGET_PPC64) */ #endif /* defined(TARGET_PPC64) */
void ppc40x_core_reset(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
target_ulong dbsr;
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC core\n");
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000100;
env->spr[SPR_40x_DBSR] = dbsr;
}
void ppc40x_chip_reset(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
target_ulong dbsr;
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC chip\n");
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
/* XXX: TODO reset all internal peripherals */
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000200;
env->spr[SPR_40x_DBSR] = dbsr;
}
void ppc40x_system_reset(PowerPCCPU *cpu)
{
qemu_log_mask(CPU_LOG_RESET, "Reset PowerPC system\n");
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
void store_40x_dbcr0(CPUPPCState *env, uint32_t val)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
switch ((val >> 28) & 0x3) {
case 0x0:
/* No action */
break;
case 0x1:
/* Core reset */
ppc40x_core_reset(cpu);
break;
case 0x2:
/* Chip reset */
ppc40x_chip_reset(cpu);
break;
case 0x3:
/* System reset */
ppc40x_system_reset(cpu);
break;
}
}
/* PowerPC 40x internal IRQ controller */ /* PowerPC 40x internal IRQ controller */
static void ppc40x_set_irq(void *opaque, int pin, int level) static void ppc40x_set_irq(void *opaque, int pin, int level)
{ {

View File

@ -1155,64 +1155,6 @@ static void ppc4xx_gpt_init(hwaddr base, qemu_irq irqs[5])
qemu_register_reset(ppc4xx_gpt_reset, gpt); qemu_register_reset(ppc4xx_gpt_reset, gpt);
} }
/*****************************************************************************/
/* SPR */
void ppc40x_core_reset(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
target_ulong dbsr;
printf("Reset PowerPC core\n");
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000100;
env->spr[SPR_40x_DBSR] = dbsr;
}
void ppc40x_chip_reset(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
target_ulong dbsr;
printf("Reset PowerPC chip\n");
cpu_interrupt(CPU(cpu), CPU_INTERRUPT_RESET);
/* XXX: TODO reset all internal peripherals */
dbsr = env->spr[SPR_40x_DBSR];
dbsr &= ~0x00000300;
dbsr |= 0x00000200;
env->spr[SPR_40x_DBSR] = dbsr;
}
void ppc40x_system_reset(PowerPCCPU *cpu)
{
printf("Reset PowerPC system\n");
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
}
void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
{
PowerPCCPU *cpu = ppc_env_get_cpu(env);
switch ((val >> 28) & 0x3) {
case 0x0:
/* No action */
break;
case 0x1:
/* Core reset */
ppc40x_core_reset(cpu);
break;
case 0x2:
/* Chip reset */
ppc40x_chip_reset(cpu);
break;
case 0x3:
/* System reset */
ppc40x_system_reset(cpu);
break;
}
}
/*****************************************************************************/ /*****************************************************************************/
/* PowerPC 405CR */ /* PowerPC 405CR */
enum { enum {

View File

@ -49,7 +49,7 @@
#define PPC440EP_SDRAM_NR_BANKS 4 #define PPC440EP_SDRAM_NR_BANKS 4
static const unsigned int ppc440ep_sdram_bank_sizes[] = { static const ram_addr_t ppc440ep_sdram_bank_sizes[] = {
256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0 256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 16 * MiB, 8 * MiB, 0
}; };

View File

@ -2,7 +2,7 @@
* QEMU PowerPC 440 embedded processors emulation * QEMU PowerPC 440 embedded processors emulation
* *
* Copyright (c) 2012 François Revol * Copyright (c) 2012 François Revol
* Copyright (c) 2016-2018 BALATON Zoltan * Copyright (c) 2016-2019 BALATON Zoltan
* *
* This work is licensed under the GNU GPL license version 2 or later. * This work is licensed under the GNU GPL license version 2 or later.
* *
@ -481,7 +481,7 @@ void ppc4xx_sdr_init(CPUPPCState *env)
/*****************************************************************************/ /*****************************************************************************/
/* SDRAM controller */ /* SDRAM controller */
typedef struct ppc4xx_sdram_t { typedef struct ppc440_sdram_t {
uint32_t addr; uint32_t addr;
int nbanks; int nbanks;
MemoryRegion containers[4]; /* used for clipping */ MemoryRegion containers[4]; /* used for clipping */
@ -489,7 +489,7 @@ typedef struct ppc4xx_sdram_t {
hwaddr ram_bases[4]; hwaddr ram_bases[4];
hwaddr ram_sizes[4]; hwaddr ram_sizes[4];
uint32_t bcr[4]; uint32_t bcr[4];
} ppc4xx_sdram_t; } ppc440_sdram_t;
enum { enum {
SDRAM0_CFGADDR = 0x10, SDRAM0_CFGADDR = 0x10,
@ -505,10 +505,6 @@ enum {
SDRAM_PLBADDUHB = 0x50, SDRAM_PLBADDUHB = 0x50,
}; };
/* XXX: TOFIX: some patches have made this code become inconsistent:
* there are type inconsistencies, mixing hwaddr, target_ulong
* and uint32_t
*/
static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size) static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
{ {
uint32_t bcr; uint32_t bcr;
@ -538,11 +534,17 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
case (1 * GiB): case (1 * GiB):
bcr = 0xe000; bcr = 0xe000;
break; break;
case (2 * GiB):
bcr = 0xc000;
break;
case (4 * GiB):
bcr = 0x8000;
break;
default: default:
error_report("invalid RAM size " TARGET_FMT_plx, ram_size); error_report("invalid RAM size " TARGET_FMT_plx, ram_size);
return 0; return 0;
} }
bcr |= ram_base & 0xFF800000; bcr |= ram_base >> 2 & 0xffe00000;
bcr |= 1; bcr |= 1;
return bcr; return bcr;
@ -550,12 +552,12 @@ static uint32_t sdram_bcr(hwaddr ram_base, hwaddr ram_size)
static inline hwaddr sdram_base(uint32_t bcr) static inline hwaddr sdram_base(uint32_t bcr)
{ {
return bcr & 0xFF800000; return (bcr & 0xffe00000) << 2;
} }
static target_ulong sdram_size(uint32_t bcr) static uint64_t sdram_size(uint32_t bcr)
{ {
target_ulong size; uint64_t size;
int sh; int sh;
sh = 1024 - ((bcr >> 6) & 0x3ff); sh = 1024 - ((bcr >> 6) & 0x3ff);
@ -564,50 +566,46 @@ static target_ulong sdram_size(uint32_t bcr)
return size; return size;
} }
static void sdram_set_bcr(ppc4xx_sdram_t *sdram, static void sdram_set_bcr(ppc440_sdram_t *sdram, int i,
uint32_t *bcrp, uint32_t bcr, int enabled) uint32_t bcr, int enabled)
{ {
unsigned n = bcrp - sdram->bcr; if (sdram->bcr[i] & 1) {
/* First unmap RAM if enabled */
if (*bcrp & 1) {
/* Unmap RAM */
memory_region_del_subregion(get_system_memory(), memory_region_del_subregion(get_system_memory(),
&sdram->containers[n]); &sdram->containers[i]);
memory_region_del_subregion(&sdram->containers[n], memory_region_del_subregion(&sdram->containers[i],
&sdram->ram_memories[n]); &sdram->ram_memories[i]);
object_unparent(OBJECT(&sdram->containers[n])); object_unparent(OBJECT(&sdram->containers[i]));
} }
*bcrp = bcr & 0xFFDEE001; sdram->bcr[i] = bcr & 0xffe0ffc1;
if (enabled && (bcr & 1)) { if (enabled && (bcr & 1)) {
memory_region_init(&sdram->containers[n], NULL, "sdram-containers", memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
sdram_size(bcr)); sdram_size(bcr));
memory_region_add_subregion(&sdram->containers[n], 0, memory_region_add_subregion(&sdram->containers[i], 0,
&sdram->ram_memories[n]); &sdram->ram_memories[i]);
memory_region_add_subregion(get_system_memory(), memory_region_add_subregion(get_system_memory(),
sdram_base(bcr), sdram_base(bcr),
&sdram->containers[n]); &sdram->containers[i]);
} }
} }
static void sdram_map_bcr(ppc4xx_sdram_t *sdram) static void sdram_map_bcr(ppc440_sdram_t *sdram)
{ {
int i; int i;
for (i = 0; i < sdram->nbanks; i++) { for (i = 0; i < sdram->nbanks; i++) {
if (sdram->ram_sizes[i] != 0) { if (sdram->ram_sizes[i] != 0) {
sdram_set_bcr(sdram, sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
&sdram->bcr[i], sdram->ram_sizes[i]), 1);
sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
1);
} else { } else {
sdram_set_bcr(sdram, &sdram->bcr[i], 0, 0); sdram_set_bcr(sdram, i, 0, 0);
} }
} }
} }
static uint32_t dcr_read_sdram(void *opaque, int dcrn) static uint32_t dcr_read_sdram(void *opaque, int dcrn)
{ {
ppc4xx_sdram_t *sdram = opaque; ppc440_sdram_t *sdram = opaque;
uint32_t ret = 0; uint32_t ret = 0;
switch (dcrn) { switch (dcrn) {
@ -615,8 +613,10 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
case SDRAM_R1BAS: case SDRAM_R1BAS:
case SDRAM_R2BAS: case SDRAM_R2BAS:
case SDRAM_R3BAS: case SDRAM_R3BAS:
if (sdram->ram_sizes[dcrn - SDRAM_R0BAS]) {
ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS], ret = sdram_bcr(sdram->ram_bases[dcrn - SDRAM_R0BAS],
sdram->ram_sizes[dcrn - SDRAM_R0BAS]); sdram->ram_sizes[dcrn - SDRAM_R0BAS]);
}
break; break;
case SDRAM_CONF1HB: case SDRAM_CONF1HB:
case SDRAM_CONF1LL: case SDRAM_CONF1LL:
@ -658,7 +658,7 @@ static uint32_t dcr_read_sdram(void *opaque, int dcrn)
static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val) static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
{ {
ppc4xx_sdram_t *sdram = opaque; ppc440_sdram_t *sdram = opaque;
switch (dcrn) { switch (dcrn) {
case SDRAM_R0BAS: case SDRAM_R0BAS:
@ -689,7 +689,7 @@ static void dcr_write_sdram(void *opaque, int dcrn, uint32_t val)
static void sdram_reset(void *opaque) static void sdram_reset(void *opaque)
{ {
ppc4xx_sdram_t *sdram = opaque; ppc440_sdram_t *sdram = opaque;
sdram->addr = 0; sdram->addr = 0;
} }
@ -699,7 +699,7 @@ void ppc440_sdram_init(CPUPPCState *env, int nbanks,
hwaddr *ram_bases, hwaddr *ram_sizes, hwaddr *ram_bases, hwaddr *ram_sizes,
int do_init) int do_init)
{ {
ppc4xx_sdram_t *sdram; ppc440_sdram_t *sdram;
sdram = g_malloc0(sizeof(*sdram)); sdram = g_malloc0(sizeof(*sdram));
sdram->nbanks = nbanks; sdram->nbanks = nbanks;

View File

@ -405,36 +405,34 @@ static target_ulong sdram_size (uint32_t bcr)
return size; return size;
} }
static void sdram_set_bcr(ppc4xx_sdram_t *sdram, static void sdram_set_bcr(ppc4xx_sdram_t *sdram, int i,
uint32_t *bcrp, uint32_t bcr, int enabled) uint32_t bcr, int enabled)
{ {
unsigned n = bcrp - sdram->bcr; if (sdram->bcr[i] & 0x00000001) {
if (*bcrp & 0x00000001) {
/* Unmap RAM */ /* Unmap RAM */
#ifdef DEBUG_SDRAM #ifdef DEBUG_SDRAM
printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", printf("%s: unmap RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
__func__, sdram_base(*bcrp), sdram_size(*bcrp)); __func__, sdram_base(sdram->bcr[i]), sdram_size(sdram->bcr[i]));
#endif #endif
memory_region_del_subregion(get_system_memory(), memory_region_del_subregion(get_system_memory(),
&sdram->containers[n]); &sdram->containers[i]);
memory_region_del_subregion(&sdram->containers[n], memory_region_del_subregion(&sdram->containers[i],
&sdram->ram_memories[n]); &sdram->ram_memories[i]);
object_unparent(OBJECT(&sdram->containers[n])); object_unparent(OBJECT(&sdram->containers[i]));
} }
*bcrp = bcr & 0xFFDEE001; sdram->bcr[i] = bcr & 0xFFDEE001;
if (enabled && (bcr & 0x00000001)) { if (enabled && (bcr & 0x00000001)) {
#ifdef DEBUG_SDRAM #ifdef DEBUG_SDRAM
printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n", printf("%s: Map RAM area " TARGET_FMT_plx " " TARGET_FMT_lx "\n",
__func__, sdram_base(bcr), sdram_size(bcr)); __func__, sdram_base(bcr), sdram_size(bcr));
#endif #endif
memory_region_init(&sdram->containers[n], NULL, "sdram-containers", memory_region_init(&sdram->containers[i], NULL, "sdram-containers",
sdram_size(bcr)); sdram_size(bcr));
memory_region_add_subregion(&sdram->containers[n], 0, memory_region_add_subregion(&sdram->containers[i], 0,
&sdram->ram_memories[n]); &sdram->ram_memories[i]);
memory_region_add_subregion(get_system_memory(), memory_region_add_subregion(get_system_memory(),
sdram_base(bcr), sdram_base(bcr),
&sdram->containers[n]); &sdram->containers[i]);
} }
} }
@ -444,12 +442,10 @@ static void sdram_map_bcr (ppc4xx_sdram_t *sdram)
for (i = 0; i < sdram->nbanks; i++) { for (i = 0; i < sdram->nbanks; i++) {
if (sdram->ram_sizes[i] != 0) { if (sdram->ram_sizes[i] != 0) {
sdram_set_bcr(sdram, sdram_set_bcr(sdram, i, sdram_bcr(sdram->ram_bases[i],
&sdram->bcr[i], sdram->ram_sizes[i]), 1);
sdram_bcr(sdram->ram_bases[i], sdram->ram_sizes[i]),
1);
} else { } else {
sdram_set_bcr(sdram, &sdram->bcr[i], 0x00000000, 0); sdram_set_bcr(sdram, i, 0x00000000, 0);
} }
} }
} }
@ -589,16 +585,16 @@ static void dcr_write_sdram (void *opaque, int dcrn, uint32_t val)
sdram->pmit = (val & 0xF8000000) | 0x07C00000; sdram->pmit = (val & 0xF8000000) | 0x07C00000;
break; break;
case 0x40: /* SDRAM_B0CR */ case 0x40: /* SDRAM_B0CR */
sdram_set_bcr(sdram, &sdram->bcr[0], val, sdram->cfg & 0x80000000); sdram_set_bcr(sdram, 0, val, sdram->cfg & 0x80000000);
break; break;
case 0x44: /* SDRAM_B1CR */ case 0x44: /* SDRAM_B1CR */
sdram_set_bcr(sdram, &sdram->bcr[1], val, sdram->cfg & 0x80000000); sdram_set_bcr(sdram, 1, val, sdram->cfg & 0x80000000);
break; break;
case 0x48: /* SDRAM_B2CR */ case 0x48: /* SDRAM_B2CR */
sdram_set_bcr(sdram, &sdram->bcr[2], val, sdram->cfg & 0x80000000); sdram_set_bcr(sdram, 2, val, sdram->cfg & 0x80000000);
break; break;
case 0x4C: /* SDRAM_B3CR */ case 0x4C: /* SDRAM_B3CR */
sdram_set_bcr(sdram, &sdram->bcr[3], val, sdram->cfg & 0x80000000); sdram_set_bcr(sdram, 3, val, sdram->cfg & 0x80000000);
break; break;
case 0x80: /* SDRAM_TR */ case 0x80: /* SDRAM_TR */
sdram->tr = val & 0x018FC01F; sdram->tr = val & 0x018FC01F;
@ -679,12 +675,12 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
MemoryRegion ram_memories[], MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_bases[],
hwaddr ram_sizes[], hwaddr ram_sizes[],
const unsigned int sdram_bank_sizes[]) const ram_addr_t sdram_bank_sizes[])
{ {
MemoryRegion *ram = g_malloc0(sizeof(*ram)); MemoryRegion *ram = g_malloc0(sizeof(*ram));
ram_addr_t size_left = ram_size; ram_addr_t size_left = ram_size;
ram_addr_t base = 0; ram_addr_t base = 0;
unsigned int bank_size; ram_addr_t bank_size;
int i; int i;
int j; int j;

View File

@ -28,7 +28,6 @@
#include "hw/ppc/ppc.h" #include "hw/ppc/ppc.h"
#include "qemu/timer.h" #include "qemu/timer.h"
#include "sysemu/sysemu.h" #include "sysemu/sysemu.h"
#include "hw/timer/m48t59.h"
#include "qemu/log.h" #include "qemu/log.h"
#include "hw/loader.h" #include "hw/loader.h"
#include "kvm_ppc.h" #include "kvm_ppc.h"

View File

@ -2,7 +2,7 @@
* QEMU aCube Sam460ex board emulation * QEMU aCube Sam460ex board emulation
* *
* Copyright (c) 2012 François Revol * Copyright (c) 2012 François Revol
* Copyright (c) 2016-2018 BALATON Zoltan * Copyright (c) 2016-2019 BALATON Zoltan
* *
* This file is derived from hw/ppc440_bamboo.c, * This file is derived from hw/ppc440_bamboo.c,
* the copyright for that material belongs to the original owners. * the copyright for that material belongs to the original owners.
@ -76,9 +76,11 @@
#define UART_FREQ 11059200 #define UART_FREQ 11059200
#define SDRAM_NR_BANKS 4 #define SDRAM_NR_BANKS 4
/* FIXME: See u-boot.git 8ac41e, also fix in ppc440_uc.c */ /* The SoC could also handle 4 GiB but firmware does not work with that. */
static const unsigned int ppc460ex_sdram_bank_sizes[] = { /* Maybe it overflows a signed 32 bit number somewhere? */
1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB, 32 * MiB, 0 static const ram_addr_t ppc460ex_sdram_bank_sizes[] = {
2 * GiB, 1 * GiB, 512 * MiB, 256 * MiB, 128 * MiB, 64 * MiB,
32 * MiB, 0
}; };
struct boot_info { struct boot_info {
@ -87,135 +89,6 @@ struct boot_info {
uint32_t entry; uint32_t entry;
}; };
/*****************************************************************************/
/* SPD eeprom content from mips_malta.c */
struct _eeprom24c0x_t {
uint8_t tick;
uint8_t address;
uint8_t command;
uint8_t ack;
uint8_t scl;
uint8_t sda;
uint8_t data;
uint8_t contents[256];
};
typedef struct _eeprom24c0x_t eeprom24c0x_t;
static eeprom24c0x_t spd_eeprom = {
.contents = {
/* 00000000: */ 0x80, 0x08, 0xFF, 0x0D, 0x0A, 0xFF, 0x40, 0x00,
/* 00000008: */ 0x04, 0x75, 0x54, 0x00, 0x82, 0x08, 0x00, 0x01,
/* 00000010: */ 0x8F, 0x04, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00,
/* 00000018: */ 0x00, 0x00, 0x00, 0x14, 0x0F, 0x14, 0x2D, 0xFF,
/* 00000020: */ 0x15, 0x08, 0x15, 0x08, 0x00, 0x00, 0x00, 0x00,
/* 00000028: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000030: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000038: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0xD0,
/* 00000040: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000048: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000050: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000058: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000060: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000068: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000070: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
/* 00000078: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x64, 0xF4,
},
};
static void generate_eeprom_spd(uint8_t *eeprom, ram_addr_t ram_size)
{
enum { SDR = 0x4, DDR1 = 0x7, DDR2 = 0x8 } type;
uint8_t *spd = spd_eeprom.contents;
uint8_t nbanks = 0;
uint16_t density = 0;
int i;
/* work in terms of MB */
ram_size /= MiB;
while ((ram_size >= 4) && (nbanks <= 2)) {
int sz_log2 = MIN(31 - clz32(ram_size), 14);
nbanks++;
density |= 1 << (sz_log2 - 2);
ram_size -= 1 << sz_log2;
}
/* split to 2 banks if possible */
if ((nbanks == 1) && (density > 1)) {
nbanks++;
density >>= 1;
}
if (density & 0xff00) {
density = (density & 0xe0) | ((density >> 8) & 0x1f);
type = DDR2;
} else if (!(density & 0x1f)) {
type = DDR2;
} else {
type = SDR;
}
if (ram_size) {
warn_report("SPD cannot represent final " RAM_ADDR_FMT "MB"
" of SDRAM", ram_size);
}
/* fill in SPD memory information */
spd[2] = type;
spd[5] = nbanks;
spd[31] = density;
/* XXX: this is totally random */
spd[9] = 0x10; /* CAS tcyc */
spd[18] = 0x20; /* CAS bit */
spd[23] = 0x10; /* CAS tcyc */
spd[25] = 0x10; /* CAS tcyc */
/* checksum */
spd[63] = 0;
for (i = 0; i < 63; i++) {
spd[63] += spd[i];
}
/* copy for SMBUS */
memcpy(eeprom, spd, sizeof(spd_eeprom.contents));
}
static void generate_eeprom_serial(uint8_t *eeprom)
{
int i, pos = 0;
uint8_t mac[6] = { 0x00 };
uint8_t sn[5] = { 0x01, 0x23, 0x45, 0x67, 0x89 };
/* version */
eeprom[pos++] = 0x01;
/* count */
eeprom[pos++] = 0x02;
/* MAC address */
eeprom[pos++] = 0x01; /* MAC */
eeprom[pos++] = 0x06; /* length */
memcpy(&eeprom[pos], mac, sizeof(mac));
pos += sizeof(mac);
/* serial number */
eeprom[pos++] = 0x02; /* serial */
eeprom[pos++] = 0x05; /* length */
memcpy(&eeprom[pos], sn, sizeof(sn));
pos += sizeof(sn);
/* checksum */
eeprom[pos] = 0;
for (i = 0; i < pos; i++) {
eeprom[pos] += eeprom[i];
}
}
/*****************************************************************************/
static int sam460ex_load_uboot(void) static int sam460ex_load_uboot(void)
{ {
DriveInfo *dinfo; DriveInfo *dinfo;
@ -393,24 +266,23 @@ static void sam460ex_init(MachineState *machine)
MemoryRegion *address_space_mem = get_system_memory(); MemoryRegion *address_space_mem = get_system_memory();
MemoryRegion *isa = g_new(MemoryRegion, 1); MemoryRegion *isa = g_new(MemoryRegion, 1);
MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS); MemoryRegion *ram_memories = g_new(MemoryRegion, SDRAM_NR_BANKS);
hwaddr ram_bases[SDRAM_NR_BANKS]; hwaddr ram_bases[SDRAM_NR_BANKS] = {0};
hwaddr ram_sizes[SDRAM_NR_BANKS]; hwaddr ram_sizes[SDRAM_NR_BANKS] = {0};
MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1); MemoryRegion *l2cache_ram = g_new(MemoryRegion, 1);
qemu_irq *irqs, *uic[4]; qemu_irq *irqs, *uic[4];
PCIBus *pci_bus; PCIBus *pci_bus;
PowerPCCPU *cpu; PowerPCCPU *cpu;
CPUPPCState *env; CPUPPCState *env;
PPC4xxI2CState *i2c[2]; I2CBus *i2c;
hwaddr entry = UBOOT_ENTRY; hwaddr entry = UBOOT_ENTRY;
hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID; hwaddr loadaddr = LOAD_UIMAGE_LOADADDR_INVALID;
target_long initrd_size = 0; target_long initrd_size = 0;
DeviceState *dev; DeviceState *dev;
SysBusDevice *sbdev; SysBusDevice *sbdev;
int success;
int i;
struct boot_info *boot_info; struct boot_info *boot_info;
const size_t smbus_eeprom_size = 8 * 256; uint8_t *spd_data;
uint8_t *smbus_eeprom_buf = g_malloc0(smbus_eeprom_size); Error *err = NULL;
int success;
cpu = POWERPC_CPU(cpu_create(machine->cpu_type)); cpu = POWERPC_CPU(cpu_create(machine->cpu_type));
env = &cpu->env; env = &cpu->env;
@ -439,8 +311,6 @@ static void sam460ex_init(MachineState *machine)
uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1); uic[3] = ppcuic_init(env, &uic[0][16], 0xf0, 0, 1);
/* SDRAM controller */ /* SDRAM controller */
memset(ram_bases, 0, sizeof(ram_bases));
memset(ram_sizes, 0, sizeof(ram_sizes));
/* put all RAM on first bank because board has one slot /* put all RAM on first bank because board has one slot
* and firmware only checks that */ * and firmware only checks that */
machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1, machine->ram_size = ppc4xx_sdram_adjust(machine->ram_size, 1,
@ -451,23 +321,22 @@ static void sam460ex_init(MachineState *machine)
ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories, ppc440_sdram_init(env, SDRAM_NR_BANKS, ram_memories,
ram_bases, ram_sizes, 1); ram_bases, ram_sizes, 1);
/* generate SPD EEPROM data */ /* IIC controllers and devices */
for (i = 0; i < SDRAM_NR_BANKS; i++) {
generate_eeprom_spd(&smbus_eeprom_buf[i * 256], ram_sizes[i]);
}
generate_eeprom_serial(&smbus_eeprom_buf[4 * 256]);
generate_eeprom_serial(&smbus_eeprom_buf[6 * 256]);
/* IIC controllers */
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]); dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600700, uic[0][2]);
i2c[0] = PPC4xx_I2C(dev); i2c = PPC4xx_I2C(dev)->bus;
object_property_set_bool(OBJECT(dev), true, "realized", NULL); /* SPD EEPROM on RAM module */
smbus_eeprom_init(i2c[0]->bus, 8, smbus_eeprom_buf, smbus_eeprom_size); spd_data = spd_data_generate(DDR2, ram_sizes[0], &err);
g_free(smbus_eeprom_buf); if (err) {
i2c_create_slave(i2c[0]->bus, "m41t80", 0x68); warn_report_err(err);
}
if (spd_data) {
spd_data[20] = 4; /* SO-DIMM module */
smbus_eeprom_init_one(i2c, 0x50, spd_data);
}
/* RTC */
i2c_create_slave(i2c, "m41t80", 0x68);
dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]); dev = sysbus_create_simple(TYPE_PPC4xx_I2C, 0x4ef600800, uic[0][3]);
i2c[1] = PPC4xx_I2C(dev);
/* External bus controller */ /* External bus controller */
ppc405_ebc_init(env); ppc405_ebc_init(env);

View File

@ -1225,9 +1225,7 @@ static void spapr_dt_hypervisor(sPAPRMachineState *spapr, void *fdt)
} }
} }
static void *spapr_build_fdt(sPAPRMachineState *spapr, static void *spapr_build_fdt(sPAPRMachineState *spapr)
hwaddr rtas_addr,
hwaddr rtas_size)
{ {
MachineState *machine = MACHINE(spapr); MachineState *machine = MACHINE(spapr);
MachineClass *mc = MACHINE_GET_CLASS(machine); MachineClass *mc = MACHINE_GET_CLASS(machine);
@ -1644,14 +1642,14 @@ static void spapr_machine_reset(void)
/* /*
* We place the device tree and RTAS just below either the top of the RMA, * We place the device tree and RTAS just below either the top of the RMA,
* or just below 2GB, whichever is lowere, so that it can be * or just below 2GB, whichever is lower, so that it can be
* processed with 32-bit real mode code if necessary * processed with 32-bit real mode code if necessary
*/ */
rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR); rtas_limit = MIN(spapr->rma_size, RTAS_MAX_ADDR);
rtas_addr = rtas_limit - RTAS_MAX_SIZE; rtas_addr = rtas_limit - RTAS_MAX_SIZE;
fdt_addr = rtas_addr - FDT_MAX_SIZE; fdt_addr = rtas_addr - FDT_MAX_SIZE;
fdt = spapr_build_fdt(spapr, rtas_addr, spapr->rtas_size); fdt = spapr_build_fdt(spapr);
spapr_load_rtas(spapr, fdt, rtas_addr); spapr_load_rtas(spapr, fdt, rtas_addr);
@ -1717,6 +1715,7 @@ static bool spapr_vga_init(PCIBus *pci_bus, Error **errp)
return true; return true;
case VGA_STD: case VGA_STD:
case VGA_VIRTIO: case VGA_VIRTIO:
case VGA_CIRRUS:
return pci_vga_init(pci_bus) != NULL; return pci_vga_init(pci_bus) != NULL;
default: default:
error_setg(errp, error_setg(errp,
@ -2959,10 +2958,11 @@ static char *spapr_get_fw_dev_path(FWPathProvider *p, BusState *bus,
if (spapr) { if (spapr) {
/* /*
* Replace "channel@0/disk@0,0" with "disk@8000000000000000": * Replace "channel@0/disk@0,0" with "disk@8000000000000000":
* We use SRP luns of the form 8000 | (bus << 8) | (id << 5) | lun * In the top 16 bits of the 64-bit LUN, we use SRP luns of the form
* in the top 16 bits of the 64-bit LUN * 0x8000 | (target << 8) | (bus << 5) | lun
* (see the "Logical unit addressing format" table in SAM5)
*/ */
unsigned id = 0x8000 | (d->id << 8) | d->lun; unsigned id = 0x8000 | (d->id << 8) | (d->channel << 5) | d->lun;
return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev), return g_strdup_printf("%s@%"PRIX64, qdev_fw_name(dev),
(uint64_t)id << 48); (uint64_t)id << 48);
} else if (virtio) { } else if (virtio) {
@ -3126,6 +3126,11 @@ static void spapr_set_ic_mode(Object *obj, const char *value, Error **errp)
{ {
sPAPRMachineState *spapr = SPAPR_MACHINE(obj); sPAPRMachineState *spapr = SPAPR_MACHINE(obj);
if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
error_setg(errp, "This machine only uses the legacy XICS backend, don't pass ic-mode");
return;
}
/* The legacy IRQ backend can not be set */ /* The legacy IRQ backend can not be set */
if (strcmp(value, "xics") == 0) { if (strcmp(value, "xics") == 0) {
spapr->irq = &spapr_irq_xics; spapr->irq = &spapr_irq_xics;
@ -3896,7 +3901,7 @@ static ICPState *spapr_icp_get(XICSFabric *xi, int vcpu_id)
{ {
PowerPCCPU *cpu = spapr_find_cpu(vcpu_id); PowerPCCPU *cpu = spapr_find_cpu(vcpu_id);
return cpu ? cpu->icp : NULL; return cpu ? spapr_cpu_state(cpu)->icp : NULL;
} }
static void spapr_pic_print_info(InterruptStatsProvider *obj, static void spapr_pic_print_info(InterruptStatsProvider *obj,

View File

@ -194,11 +194,11 @@ static void spapr_unrealize_vcpu(PowerPCCPU *cpu, sPAPRCPUCore *sc)
vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data); vmstate_unregister(NULL, &vmstate_spapr_cpu_state, cpu->machine_data);
} }
qemu_unregister_reset(spapr_cpu_reset, cpu); qemu_unregister_reset(spapr_cpu_reset, cpu);
if (cpu->icp) { if (spapr_cpu_state(cpu)->icp) {
object_unparent(OBJECT(cpu->icp)); object_unparent(OBJECT(spapr_cpu_state(cpu)->icp));
} }
if (cpu->tctx) { if (spapr_cpu_state(cpu)->tctx) {
object_unparent(OBJECT(cpu->tctx)); object_unparent(OBJECT(spapr_cpu_state(cpu)->tctx));
} }
cpu_remove_sync(CPU(cpu)); cpu_remove_sync(CPU(cpu));
object_unparent(OBJECT(cpu)); object_unparent(OBJECT(cpu));

View File

@ -12,6 +12,7 @@
#include "qemu/error-report.h" #include "qemu/error-report.h"
#include "qapi/error.h" #include "qapi/error.h"
#include "hw/ppc/spapr.h" #include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/spapr_xive.h" #include "hw/ppc/spapr_xive.h"
#include "hw/ppc/xics.h" #include "hw/ppc/xics.h"
#include "hw/ppc/xics_spapr.h" #include "hw/ppc/xics_spapr.h"
@ -185,7 +186,7 @@ static void spapr_irq_print_info_xics(sPAPRMachineState *spapr, Monitor *mon)
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_pic_print_info(cpu->icp, mon); icp_pic_print_info(spapr_cpu_state(cpu)->icp, mon);
} }
ics_pic_print_info(spapr->ics, mon); ics_pic_print_info(spapr->ics, mon);
@ -196,6 +197,7 @@ static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
{ {
Error *local_err = NULL; Error *local_err = NULL;
Object *obj; Object *obj;
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
obj = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr), obj = icp_create(OBJECT(cpu), spapr->icp_type, XICS_FABRIC(spapr),
&local_err); &local_err);
@ -204,7 +206,7 @@ static void spapr_irq_cpu_intc_create_xics(sPAPRMachineState *spapr,
return; return;
} }
cpu->icp = ICP(obj); spapr_cpu->icp = ICP(obj);
} }
static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id) static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
@ -213,7 +215,7 @@ static int spapr_irq_post_load_xics(sPAPRMachineState *spapr, int version_id)
CPUState *cs; CPUState *cs;
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPU *cpu = POWERPC_CPU(cs);
icp_resend(cpu->icp); icp_resend(spapr_cpu_state(cpu)->icp);
} }
} }
return 0; return 0;
@ -334,7 +336,7 @@ static void spapr_irq_print_info_xive(sPAPRMachineState *spapr,
CPU_FOREACH(cs) { CPU_FOREACH(cs) {
PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPU *cpu = POWERPC_CPU(cs);
xive_tctx_pic_print_info(cpu->tctx, mon); xive_tctx_pic_print_info(spapr_cpu_state(cpu)->tctx, mon);
} }
spapr_xive_pic_print_info(spapr->xive, mon); spapr_xive_pic_print_info(spapr->xive, mon);
@ -345,6 +347,7 @@ static void spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
{ {
Error *local_err = NULL; Error *local_err = NULL;
Object *obj; Object *obj;
sPAPRCPUState *spapr_cpu = spapr_cpu_state(cpu);
obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err); obj = xive_tctx_create(OBJECT(cpu), XIVE_ROUTER(spapr->xive), &local_err);
if (local_err) { if (local_err) {
@ -352,13 +355,13 @@ static void spapr_irq_cpu_intc_create_xive(sPAPRMachineState *spapr,
return; return;
} }
cpu->tctx = XIVE_TCTX(obj); spapr_cpu->tctx = XIVE_TCTX(obj);
/* /*
* (TCG) Early setting the OS CAM line for hotplugged CPUs as they * (TCG) Early setting the OS CAM line for hotplugged CPUs as they
* don't beneficiate from the reset of the XIVE IRQ backend * don't beneficiate from the reset of the XIVE IRQ backend
*/ */
spapr_xive_set_tctx_os_cam(cpu->tctx); spapr_xive_set_tctx_os_cam(spapr_cpu->tctx);
} }
static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id) static int spapr_irq_post_load_xive(sPAPRMachineState *spapr, int version_id)
@ -374,7 +377,7 @@ static void spapr_irq_reset_xive(sPAPRMachineState *spapr, Error **errp)
PowerPCCPU *cpu = POWERPC_CPU(cs); PowerPCCPU *cpu = POWERPC_CPU(cs);
/* (TCG) Set the OS CAM line of the thread interrupt context. */ /* (TCG) Set the OS CAM line of the thread interrupt context. */
spapr_xive_set_tctx_os_cam(cpu->tctx); spapr_xive_set_tctx_os_cam(spapr_cpu_state(cpu)->tctx);
} }
/* Activate the XIVE MMIOs */ /* Activate the XIVE MMIOs */

View File

@ -964,7 +964,7 @@ static void populate_resource_props(PCIDevice *d, ResourceProps *rp)
} }
assigned = &rp->assigned[assigned_idx++]; assigned = &rp->assigned[assigned_idx++];
assigned->phys_hi = cpu_to_be32(reg->phys_hi | b_n(1)); assigned->phys_hi = cpu_to_be32(be32_to_cpu(reg->phys_hi) | b_n(1));
assigned->phys_mid = cpu_to_be32(d->io_regions[i].addr >> 32); assigned->phys_mid = cpu_to_be32(d->io_regions[i].addr >> 32);
assigned->phys_lo = cpu_to_be32(d->io_regions[i].addr); assigned->phys_lo = cpu_to_be32(d->io_regions[i].addr);
assigned->size_hi = reg->size_hi; assigned->size_hi = reg->size_hi;
@ -2030,8 +2030,6 @@ static void spapr_phb_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
void *opaque) void *opaque)
{ {
unsigned int *bus_no = opaque; unsigned int *bus_no = opaque;
unsigned int primary = *bus_no;
unsigned int subordinate = 0xff;
PCIBus *sec_bus = NULL; PCIBus *sec_bus = NULL;
if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) != if ((pci_default_read_config(pdev, PCI_HEADER_TYPE, 1) !=
@ -2040,7 +2038,7 @@ static void spapr_phb_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
} }
(*bus_no)++; (*bus_no)++;
pci_default_write_config(pdev, PCI_PRIMARY_BUS, primary, 1); pci_default_write_config(pdev, PCI_PRIMARY_BUS, pci_dev_bus_num(pdev), 1);
pci_default_write_config(pdev, PCI_SECONDARY_BUS, *bus_no, 1); pci_default_write_config(pdev, PCI_SECONDARY_BUS, *bus_no, 1);
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1); pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1);
@ -2049,7 +2047,6 @@ static void spapr_phb_pci_enumerate_bridge(PCIBus *bus, PCIDevice *pdev,
return; return;
} }
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, subordinate, 1);
pci_for_each_device(sec_bus, pci_bus_num(sec_bus), pci_for_each_device(sec_bus, pci_bus_num(sec_bus),
spapr_phb_pci_enumerate_bridge, bus_no); spapr_phb_pci_enumerate_bridge, bus_no);
pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1); pci_default_write_config(pdev, PCI_SUBORDINATE_BUS, *bus_no, 1);

View File

@ -44,38 +44,6 @@
#define SPAPR_VIO_REG_BASE 0x71000000 #define SPAPR_VIO_REG_BASE 0x71000000
static void spapr_vio_get_irq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
visit_type_uint32(v, name, ptr, errp);
}
static void spapr_vio_set_irq(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
Property *prop = opaque;
uint32_t *ptr = qdev_get_prop_ptr(DEVICE(obj), prop);
if (!qtest_enabled()) {
warn_report(TYPE_VIO_SPAPR_DEVICE " '%s' property is deprecated", name);
}
visit_type_uint32(v, name, ptr, errp);
}
static const PropertyInfo spapr_vio_irq_propinfo = {
.name = "irq",
.get = spapr_vio_get_irq,
.set = spapr_vio_set_irq,
};
static Property spapr_vio_props[] = {
DEFINE_PROP("irq", VIOsPAPRDevice, irq, spapr_vio_irq_propinfo, uint32_t),
DEFINE_PROP_END_OF_LIST(),
};
static char *spapr_vio_get_dev_name(DeviceState *qdev) static char *spapr_vio_get_dev_name(DeviceState *qdev)
{ {
VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev); VIOsPAPRDevice *dev = VIO_SPAPR_DEVICE(qdev);
@ -534,7 +502,6 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
dev->qdev.id = id; dev->qdev.id = id;
} }
if (!dev->irq) {
dev->irq = spapr_vio_reg_to_irq(dev->reg); dev->irq = spapr_vio_reg_to_irq(dev->reg);
if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) { if (SPAPR_MACHINE_GET_CLASS(spapr)->legacy_irq_allocation) {
@ -544,7 +511,6 @@ static void spapr_vio_busdev_realize(DeviceState *qdev, Error **errp)
return; return;
} }
} }
}
spapr_irq_claim(spapr, dev->irq, false, &local_err); spapr_irq_claim(spapr, dev->irq, false, &local_err);
if (local_err) { if (local_err) {
@ -668,7 +634,6 @@ static void vio_spapr_device_class_init(ObjectClass *klass, void *data)
k->realize = spapr_vio_busdev_realize; k->realize = spapr_vio_busdev_realize;
k->reset = spapr_vio_busdev_reset; k->reset = spapr_vio_busdev_reset;
k->bus_type = TYPE_SPAPR_VIO_BUS; k->bus_type = TYPE_SPAPR_VIO_BUS;
k->props = spapr_vio_props;
} }
static const TypeInfo spapr_vio_type_info = { static const TypeInfo spapr_vio_type_info = {

View File

@ -95,4 +95,7 @@ void smbus_eeprom_init_one(I2CBus *smbus, uint8_t address, uint8_t *eeprom_buf);
void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom, void smbus_eeprom_init(I2CBus *smbus, int nb_eeprom,
const uint8_t *eeprom_spd, int size); const uint8_t *eeprom_spd, int size);
enum sdram_type { SDR = 0x4, DDR = 0x7, DDR2 = 0x8 };
uint8_t *spd_data_generate(enum sdram_type type, ram_addr_t size, Error **errp);
#endif #endif

View File

@ -47,4 +47,13 @@ typedef struct PnvCoreClass {
#define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE #define PNV_CORE_TYPE_SUFFIX "-" TYPE_PNV_CORE
#define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX #define PNV_CORE_TYPE_NAME(cpu_model) cpu_model PNV_CORE_TYPE_SUFFIX
typedef struct PnvCPUState {
struct ICPState *icp;
} PnvCPUState;
static inline PnvCPUState *pnv_cpu_state(PowerPCCPU *cpu)
{
return (PnvCPUState *)cpu->machine_data;
}
#endif /* _PPC_PNV_CORE_H */ #endif /* _PPC_PNV_CORE_H */

View File

@ -43,7 +43,7 @@ ram_addr_t ppc4xx_sdram_adjust(ram_addr_t ram_size, int nr_banks,
MemoryRegion ram_memories[], MemoryRegion ram_memories[],
hwaddr ram_bases[], hwaddr ram_bases[],
hwaddr ram_sizes[], hwaddr ram_sizes[],
const unsigned int sdram_bank_sizes[]); const ram_addr_t sdram_bank_sizes[]);
void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks, void ppc4xx_sdram_init (CPUPPCState *env, qemu_irq irq, int nbanks,
MemoryRegion ram_memories[], MemoryRegion ram_memories[],

View File

@ -46,6 +46,8 @@ typedef struct sPAPRCPUState {
uint64_t vpa_addr; uint64_t vpa_addr;
uint64_t slb_shadow_addr, slb_shadow_size; uint64_t slb_shadow_addr, slb_shadow_size;
uint64_t dtl_addr, dtl_size; uint64_t dtl_addr, dtl_size;
struct ICPState *icp;
struct XiveTCTX *tctx;
} sPAPRCPUState; } sPAPRCPUState;
static inline sPAPRCPUState *spapr_cpu_state(PowerPCCPU *cpu) static inline sPAPRCPUState *spapr_cpu_state(PowerPCCPU *cpu)

View File

@ -145,7 +145,7 @@
#include "hw/ppc/xive_regs.h" #include "hw/ppc/xive_regs.h"
/* /*
* XIVE Fabric (Interface between Source and Router) * XIVE Notifier (Interface between Source and Router)
*/ */
typedef struct XiveNotifier { typedef struct XiveNotifier {
@ -294,6 +294,33 @@ static inline void xive_source_irq_set(XiveSource *xsrc, uint32_t srcno,
void xive_source_set_irq(void *opaque, int srcno, int val); void xive_source_set_irq(void *opaque, int srcno, int val);
/*
* XIVE Thread interrupt Management (TM) context
*/
#define TYPE_XIVE_TCTX "xive-tctx"
#define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
/*
* XIVE Thread interrupt Management register rings :
*
* QW-0 User event-based exception state
* QW-1 O/S OS context for priority management, interrupt acks
* QW-2 Pool hypervisor pool context for virtual processors dispatched
* QW-3 Physical physical thread context and security context
*/
#define XIVE_TM_RING_COUNT 4
#define XIVE_TM_RING_SIZE 0x10
typedef struct XiveTCTX {
DeviceState parent_obj;
CPUState *cs;
qemu_irq output;
uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE];
} XiveTCTX;
/* /*
* XIVE Router * XIVE Router
*/ */
@ -324,6 +351,7 @@ typedef struct XiveRouterClass {
XiveNVT *nvt); XiveNVT *nvt);
int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, int (*write_nvt)(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt, uint8_t word_number); XiveNVT *nvt, uint8_t word_number);
XiveTCTX *(*get_tctx)(XiveRouter *xrtr, CPUState *cs);
} XiveRouterClass; } XiveRouterClass;
void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon); void xive_eas_pic_print_info(XiveEAS *eas, uint32_t lisn, Monitor *mon);
@ -338,7 +366,7 @@ int xive_router_get_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt); XiveNVT *nvt);
int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx, int xive_router_write_nvt(XiveRouter *xrtr, uint8_t nvt_blk, uint32_t nvt_idx,
XiveNVT *nvt, uint8_t word_number); XiveNVT *nvt, uint8_t word_number);
XiveTCTX *xive_router_get_tctx(XiveRouter *xrtr, CPUState *cs);
/* /*
* XIVE END ESBs * XIVE END ESBs
@ -371,33 +399,6 @@ typedef struct XiveENDSource {
void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon); void xive_end_pic_print_info(XiveEND *end, uint32_t end_idx, Monitor *mon);
void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon); void xive_end_queue_pic_print_info(XiveEND *end, uint32_t width, Monitor *mon);
/*
* XIVE Thread interrupt Management (TM) context
*/
#define TYPE_XIVE_TCTX "xive-tctx"
#define XIVE_TCTX(obj) OBJECT_CHECK(XiveTCTX, (obj), TYPE_XIVE_TCTX)
/*
* XIVE Thread interrupt Management register rings :
*
* QW-0 User event-based exception state
* QW-1 O/S OS context for priority management, interrupt acks
* QW-2 Pool hypervisor pool context for virtual processors dispatched
* QW-3 Physical physical thread context and security context
*/
#define XIVE_TM_RING_COUNT 4
#define XIVE_TM_RING_SIZE 0x10
typedef struct XiveTCTX {
DeviceState parent_obj;
CPUState *cs;
qemu_irq output;
uint8_t regs[XIVE_TM_RING_COUNT * XIVE_TM_RING_SIZE];
} XiveTCTX;
/* /*
* XIVE Thread Interrupt Management Aera (TIMA) * XIVE Thread Interrupt Management Aera (TIMA)
* *

View File

@ -9,6 +9,6 @@ size_t qemu_mempath_getpagesize(const char *mem_path);
void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared); void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared);
void qemu_ram_munmap(void *ptr, size_t size); void qemu_ram_munmap(int fd, void *ptr, size_t size);
#endif #endif

View File

@ -17,7 +17,7 @@
- SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware - SLOF (Slimline Open Firmware) is a free IEEE 1275 Open Firmware
implementation for certain IBM POWER hardware. The sources are at implementation for certain IBM POWER hardware. The sources are at
https://github.com/aik/SLOF, and the image currently in qemu is https://github.com/aik/SLOF, and the image currently in qemu is
built from git tag qemu-slof-20180702. built from git tag qemu-slof-20190114.
- sgabios (the Serial Graphics Adapter option ROM) provides a means for - sgabios (the Serial Graphics Adapter option ROM) provides a means for
legacy x86 software to communicate with an attached serial console as legacy x86 software to communicate with an attached serial console as

Binary file not shown.

Binary file not shown.

View File

@ -160,9 +160,3 @@ Example of legacy encoding:
The above, converted to the current supported format: The above, converted to the current supported format:
@code{json:@{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"@}} @code{json:@{"file.driver":"rbd", "file.pool":"rbd", "file.image":"name"@}}
@subsection vio-spapr-device device options
@subsubsection "irq": "" (since 3.0.0)
The ``irq'' property is obsoleted.

@ -1 +1 @@
Subproject commit d4e7d7ac663fcb55f1b93575445fcbca372f17a7 Subproject commit 90c488d5f4a407342247b9ea869df1c2d9c8e266

@ -1 +1 @@
Subproject commit 9b7ab2fa020341dee8bf9df6c9cf40003e0136df Subproject commit a5b428e1c1eae703bdd62a3f527223c291ee3fdc

View File

@ -1178,9 +1178,6 @@ do { \
typedef struct PPCVirtualHypervisor PPCVirtualHypervisor; typedef struct PPCVirtualHypervisor PPCVirtualHypervisor;
typedef struct PPCVirtualHypervisorClass PPCVirtualHypervisorClass; typedef struct PPCVirtualHypervisorClass PPCVirtualHypervisorClass;
struct XiveTCTX;
struct ICPState;
/** /**
* PowerPCCPU: * PowerPCCPU:
* @env: #CPUPPCState * @env: #CPUPPCState
@ -1198,8 +1195,6 @@ struct PowerPCCPU {
int vcpu_id; int vcpu_id;
uint32_t compat_pvr; uint32_t compat_pvr;
PPCVirtualHypervisor *vhyp; PPCVirtualHypervisor *vhyp;
struct ICPState *icp;
struct XiveTCTX *tctx;
void *machine_data; void *machine_data;
int32_t node_id; /* NUMA node this CPU belongs to */ int32_t node_id; /* NUMA node this CPU belongs to */
PPCHash64Options *hash64_opts; PPCHash64Options *hash64_opts;

View File

@ -388,14 +388,6 @@ target_ulong helper_602_mfrom(target_ulong arg)
/*****************************************************************************/ /*****************************************************************************/
/* Altivec extension helpers */ /* Altivec extension helpers */
#if defined(HOST_WORDS_BIGENDIAN)
#define HI_IDX 0
#define LO_IDX 1
#else
#define HI_IDX 1
#define LO_IDX 0
#endif
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)
#define VECTOR_FOR_INORDER_I(index, element) \ #define VECTOR_FOR_INORDER_I(index, element) \
for (index = 0; index < ARRAY_SIZE(r->element); index++) for (index = 0; index < ARRAY_SIZE(r->element); index++)
@ -451,8 +443,8 @@ void helper_lvsl(ppc_avr_t *r, target_ulong sh)
{ {
int i, j = (sh & 0xf); int i, j = (sh & 0xf);
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
r->u8[i] = j++; r->VsrB(i) = j++;
} }
} }
@ -460,18 +452,14 @@ void helper_lvsr(ppc_avr_t *r, target_ulong sh)
{ {
int i, j = 0x10 - (sh & 0xf); int i, j = 0x10 - (sh & 0xf);
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
r->u8[i] = j++; r->VsrB(i) = j++;
} }
} }
void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r) void helper_mtvscr(CPUPPCState *env, ppc_avr_t *r)
{ {
#if defined(HOST_WORDS_BIGENDIAN) env->vscr = r->VsrW(3);
env->vscr = r->u32[3];
#else
env->vscr = r->u32[0];
#endif
set_flush_to_zero(vscr_nj, &env->vec_status); set_flush_to_zero(vscr_nj, &env->vec_status);
} }
@ -514,8 +502,8 @@ void helper_vprtybq(ppc_avr_t *r, ppc_avr_t *b)
res ^= res >> 32; res ^= res >> 32;
res ^= res >> 16; res ^= res >> 16;
res ^= res >> 8; res ^= res >> 8;
r->u64[LO_IDX] = res & 1; r->VsrD(1) = res & 1;
r->u64[HI_IDX] = 0; r->VsrD(0) = 0;
} }
#define VARITH_DO(name, op, element) \ #define VARITH_DO(name, op, element) \
@ -878,8 +866,8 @@ target_ulong helper_vclzlsbb(ppc_avr_t *r)
{ {
target_ulong count = 0; target_ulong count = 0;
int i; int i;
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
if (r->u8[i] & 0x01) { if (r->VsrB(i) & 0x01) {
break; break;
} }
count++; count++;
@ -891,12 +879,8 @@ target_ulong helper_vctzlsbb(ppc_avr_t *r)
{ {
target_ulong count = 0; target_ulong count = 0;
int i; int i;
#if defined(HOST_WORDS_BIGENDIAN)
for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) { for (i = ARRAY_SIZE(r->u8) - 1; i >= 0; i--) {
#else if (r->VsrB(i) & 0x01) {
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
#endif
if (r->u8[i] & 0x01) {
break; break;
} }
count++; count++;
@ -976,43 +960,27 @@ void helper_vmladduhm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
} }
} }
#define VMRG_DO(name, element, highp) \ #define VMRG_DO(name, element, access, ofs) \
void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \ { \
ppc_avr_t result; \ ppc_avr_t result; \
int i; \ int i, half = ARRAY_SIZE(r->element) / 2; \
size_t n_elems = ARRAY_SIZE(r->element); \
\ \
for (i = 0; i < n_elems / 2; i++) { \ for (i = 0; i < half; i++) { \
if (highp) { \ result.access(i * 2 + 0) = a->access(i + ofs); \
result.element[i*2+HI_IDX] = a->element[i]; \ result.access(i * 2 + 1) = b->access(i + ofs); \
result.element[i*2+LO_IDX] = b->element[i]; \
} else { \
result.element[n_elems - i * 2 - (1 + HI_IDX)] = \
b->element[n_elems - i - 1]; \
result.element[n_elems - i * 2 - (1 + LO_IDX)] = \
a->element[n_elems - i - 1]; \
} \
} \ } \
*r = result; \ *r = result; \
} }
#if defined(HOST_WORDS_BIGENDIAN)
#define MRGHI 0 #define VMRG(suffix, element, access) \
#define MRGLO 1 VMRG_DO(mrgl##suffix, element, access, half) \
#else VMRG_DO(mrgh##suffix, element, access, 0)
#define MRGHI 1 VMRG(b, u8, VsrB)
#define MRGLO 0 VMRG(h, u16, VsrH)
#endif VMRG(w, u32, VsrW)
#define VMRG(suffix, element) \
VMRG_DO(mrgl##suffix, element, MRGHI) \
VMRG_DO(mrgh##suffix, element, MRGLO)
VMRG(b, u8)
VMRG(h, u16)
VMRG(w, u32)
#undef VMRG_DO #undef VMRG_DO
#undef VMRG #undef VMRG
#undef MRGHI
#undef MRGLO
void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, void helper_vmsummbm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
ppc_avr_t *b, ppc_avr_t *c) ppc_avr_t *b, ppc_avr_t *c)
@ -1120,33 +1088,39 @@ void helper_vmsumuhs(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a,
} }
} }
#define VMUL_DO(name, mul_element, prod_element, cast, evenp) \ #define VMUL_DO_EVN(name, mul_element, mul_access, prod_access, cast) \
void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \ { \
int i; \ int i; \
\ \
VECTOR_FOR_INORDER_I(i, prod_element) { \ for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \
if (evenp) { \ r->prod_access(i >> 1) = (cast)a->mul_access(i) * \
r->prod_element[i] = \ (cast)b->mul_access(i); \
(cast)a->mul_element[i * 2 + HI_IDX] * \
(cast)b->mul_element[i * 2 + HI_IDX]; \
} else { \
r->prod_element[i] = \
(cast)a->mul_element[i * 2 + LO_IDX] * \
(cast)b->mul_element[i * 2 + LO_IDX]; \
} \
} \ } \
} }
#define VMUL(suffix, mul_element, prod_element, cast) \
VMUL_DO(mule##suffix, mul_element, prod_element, cast, 1) \ #define VMUL_DO_ODD(name, mul_element, mul_access, prod_access, cast) \
VMUL_DO(mulo##suffix, mul_element, prod_element, cast, 0) void helper_v##name(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
VMUL(sb, s8, s16, int16_t) { \
VMUL(sh, s16, s32, int32_t) int i; \
VMUL(sw, s32, s64, int64_t) \
VMUL(ub, u8, u16, uint16_t) for (i = 0; i < ARRAY_SIZE(r->mul_element); i += 2) { \
VMUL(uh, u16, u32, uint32_t) r->prod_access(i >> 1) = (cast)a->mul_access(i + 1) * \
VMUL(uw, u32, u64, uint64_t) (cast)b->mul_access(i + 1); \
#undef VMUL_DO } \
}
#define VMUL(suffix, mul_element, mul_access, prod_access, cast) \
VMUL_DO_EVN(mule##suffix, mul_element, mul_access, prod_access, cast) \
VMUL_DO_ODD(mulo##suffix, mul_element, mul_access, prod_access, cast)
VMUL(sb, s8, VsrSB, VsrSH, int16_t)
VMUL(sh, s16, VsrSH, VsrSW, int32_t)
VMUL(sw, s32, VsrSW, VsrSD, int64_t)
VMUL(ub, u8, VsrB, VsrH, uint16_t)
VMUL(uh, u16, VsrH, VsrW, uint32_t)
VMUL(uw, u32, VsrW, VsrD, uint64_t)
#undef VMUL_DO_EVN
#undef VMUL_DO_ODD
#undef VMUL #undef VMUL
void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
@ -1155,18 +1129,14 @@ void helper_vperm(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
ppc_avr_t result; ppc_avr_t result;
int i; int i;
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
int s = c->u8[i] & 0x1f; int s = c->VsrB(i) & 0x1f;
#if defined(HOST_WORDS_BIGENDIAN)
int index = s & 0xf; int index = s & 0xf;
#else
int index = 15 - (s & 0xf);
#endif
if (s & 0x10) { if (s & 0x10) {
result.u8[i] = b->u8[index]; result.VsrB(i) = b->VsrB(index);
} else { } else {
result.u8[i] = a->u8[index]; result.VsrB(i) = a->VsrB(index);
} }
} }
*r = result; *r = result;
@ -1178,18 +1148,14 @@ void helper_vpermr(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b,
ppc_avr_t result; ppc_avr_t result;
int i; int i;
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
int s = c->u8[i] & 0x1f; int s = c->VsrB(i) & 0x1f;
#if defined(HOST_WORDS_BIGENDIAN)
int index = 15 - (s & 0xf); int index = 15 - (s & 0xf);
#else
int index = s & 0xf;
#endif
if (s & 0x10) { if (s & 0x10) {
result.u8[i] = a->u8[index]; result.VsrB(i) = a->VsrB(index);
} else { } else {
result.u8[i] = b->u8[index]; result.VsrB(i) = b->VsrB(index);
} }
} }
*r = result; *r = result;
@ -1239,8 +1205,8 @@ void helper_vbpermq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
} }
} }
r->u64[HI_IDX] = perm; r->VsrD(0) = perm;
r->u64[LO_IDX] = 0; r->VsrD(1) = 0;
} }
#undef VBPERMQ_INDEX #undef VBPERMQ_INDEX
@ -1569,25 +1535,25 @@ void helper_vpmsumd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t prod[2]; ppc_avr_t prod[2];
VECTOR_FOR_INORDER_I(i, u64) { VECTOR_FOR_INORDER_I(i, u64) {
prod[i].u64[LO_IDX] = prod[i].u64[HI_IDX] = 0; prod[i].VsrD(1) = prod[i].VsrD(0) = 0;
for (j = 0; j < 64; j++) { for (j = 0; j < 64; j++) {
if (a->u64[i] & (1ull<<j)) { if (a->u64[i] & (1ull<<j)) {
ppc_avr_t bshift; ppc_avr_t bshift;
if (j == 0) { if (j == 0) {
bshift.u64[HI_IDX] = 0; bshift.VsrD(0) = 0;
bshift.u64[LO_IDX] = b->u64[i]; bshift.VsrD(1) = b->u64[i];
} else { } else {
bshift.u64[HI_IDX] = b->u64[i] >> (64-j); bshift.VsrD(0) = b->u64[i] >> (64 - j);
bshift.u64[LO_IDX] = b->u64[i] << j; bshift.VsrD(1) = b->u64[i] << j;
} }
prod[i].u64[LO_IDX] ^= bshift.u64[LO_IDX]; prod[i].VsrD(1) ^= bshift.VsrD(1);
prod[i].u64[HI_IDX] ^= bshift.u64[HI_IDX]; prod[i].VsrD(0) ^= bshift.VsrD(0);
} }
} }
} }
r->u64[LO_IDX] = prod[0].u64[LO_IDX] ^ prod[1].u64[LO_IDX]; r->VsrD(1) = prod[0].VsrD(1) ^ prod[1].VsrD(1);
r->u64[HI_IDX] = prod[0].u64[HI_IDX] ^ prod[1].u64[HI_IDX]; r->VsrD(0) = prod[0].VsrD(0) ^ prod[1].VsrD(0);
#endif #endif
} }
@ -1805,7 +1771,7 @@ VEXTU_X_DO(vextuwrx, 32, 0)
#define VSHIFT(suffix, leftp) \ #define VSHIFT(suffix, leftp) \
void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \ void helper_vs##suffix(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) \
{ \ { \
int shift = b->u8[LO_IDX*15] & 0x7; \ int shift = b->VsrB(15) & 0x7; \
int doit = 1; \ int doit = 1; \
int i; \ int i; \
\ \
@ -1816,15 +1782,15 @@ VEXTU_X_DO(vextuwrx, 32, 0)
if (shift == 0) { \ if (shift == 0) { \
*r = *a; \ *r = *a; \
} else if (leftp) { \ } else if (leftp) { \
uint64_t carry = a->u64[LO_IDX] >> (64 - shift); \ uint64_t carry = a->VsrD(1) >> (64 - shift); \
\ \
r->u64[HI_IDX] = (a->u64[HI_IDX] << shift) | carry; \ r->VsrD(0) = (a->VsrD(0) << shift) | carry; \
r->u64[LO_IDX] = a->u64[LO_IDX] << shift; \ r->VsrD(1) = a->VsrD(1) << shift; \
} else { \ } else { \
uint64_t carry = a->u64[HI_IDX] << (64 - shift); \ uint64_t carry = a->VsrD(0) << (64 - shift); \
\ \
r->u64[LO_IDX] = (a->u64[LO_IDX] >> shift) | carry; \ r->VsrD(1) = (a->VsrD(1) >> shift) | carry; \
r->u64[HI_IDX] = a->u64[HI_IDX] >> shift; \ r->VsrD(0) = a->VsrD(0) >> shift; \
} \ } \
} \ } \
} }
@ -1886,31 +1852,20 @@ void helper_vsldoi(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t shift)
int i; int i;
ppc_avr_t result; ppc_avr_t result;
#if defined(HOST_WORDS_BIGENDIAN)
for (i = 0; i < ARRAY_SIZE(r->u8); i++) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
int index = sh + i; int index = sh + i;
if (index > 0xf) { if (index > 0xf) {
result.u8[i] = b->u8[index - 0x10]; result.VsrB(i) = b->VsrB(index - 0x10);
} else { } else {
result.u8[i] = a->u8[index]; result.VsrB(i) = a->VsrB(index);
} }
} }
#else
for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
int index = (16 - sh) + i;
if (index > 0xf) {
result.u8[i] = a->u8[index - 0x10];
} else {
result.u8[i] = b->u8[index];
}
}
#endif
*r = result; *r = result;
} }
void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{ {
int sh = (b->u8[LO_IDX*0xf] >> 3) & 0xf; int sh = (b->VsrB(0xf) >> 3) & 0xf;
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)
memmove(&r->u8[0], &a->u8[sh], 16 - sh); memmove(&r->u8[0], &a->u8[sh], 16 - sh);
@ -1923,25 +1878,20 @@ void helper_vslo(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
/* Experimental testing shows that hardware masks the immediate. */ /* Experimental testing shows that hardware masks the immediate. */
#define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1)) #define _SPLAT_MASKED(element) (splat & (ARRAY_SIZE(r->element) - 1))
#if defined(HOST_WORDS_BIGENDIAN)
#define SPLAT_ELEMENT(element) _SPLAT_MASKED(element) #define SPLAT_ELEMENT(element) _SPLAT_MASKED(element)
#else #define VSPLT(suffix, element, access) \
#define SPLAT_ELEMENT(element) \
(ARRAY_SIZE(r->element) - 1 - _SPLAT_MASKED(element))
#endif
#define VSPLT(suffix, element) \
void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \ void helper_vsplt##suffix(ppc_avr_t *r, ppc_avr_t *b, uint32_t splat) \
{ \ { \
uint32_t s = b->element[SPLAT_ELEMENT(element)]; \ uint32_t s = b->access(SPLAT_ELEMENT(element)); \
int i; \ int i; \
\ \
for (i = 0; i < ARRAY_SIZE(r->element); i++) { \ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
r->element[i] = s; \ r->access(i) = s; \
} \ } \
} }
VSPLT(b, u8) VSPLT(b, u8, VsrB)
VSPLT(h, u16) VSPLT(h, u16, VsrH)
VSPLT(w, u32) VSPLT(w, u32, VsrW)
#undef VSPLT #undef VSPLT
#undef SPLAT_ELEMENT #undef SPLAT_ELEMENT
#undef _SPLAT_MASKED #undef _SPLAT_MASKED
@ -2002,17 +1952,10 @@ void helper_xxextractuw(CPUPPCState *env, target_ulong xtn,
getVSR(xbn, &xb, env); getVSR(xbn, &xb, env);
memset(&xt, 0, sizeof(xt)); memset(&xt, 0, sizeof(xt));
#if defined(HOST_WORDS_BIGENDIAN)
ext_index = index; ext_index = index;
for (i = 0; i < es; i++, ext_index++) { for (i = 0; i < es; i++, ext_index++) {
xt.u8[8 - es + i] = xb.u8[ext_index % 16]; xt.VsrB(8 - es + i) = xb.VsrB(ext_index % 16);
} }
#else
ext_index = 15 - index;
for (i = es - 1; i >= 0; i--, ext_index--) {
xt.u8[8 + i] = xb.u8[ext_index % 16];
}
#endif
putVSR(xtn, &xt, env); putVSR(xtn, &xt, env);
} }
@ -2027,41 +1970,34 @@ void helper_xxinsertw(CPUPPCState *env, target_ulong xtn,
getVSR(xbn, &xb, env); getVSR(xbn, &xb, env);
getVSR(xtn, &xt, env); getVSR(xtn, &xt, env);
#if defined(HOST_WORDS_BIGENDIAN)
ins_index = index; ins_index = index;
for (i = 0; i < es && ins_index < 16; i++, ins_index++) { for (i = 0; i < es && ins_index < 16; i++, ins_index++) {
xt.u8[ins_index] = xb.u8[8 - es + i]; xt.VsrB(ins_index) = xb.VsrB(8 - es + i);
} }
#else
ins_index = 15 - index;
for (i = es - 1; i >= 0 && ins_index >= 0; i--, ins_index--) {
xt.u8[ins_index] = xb.u8[8 + i];
}
#endif
putVSR(xtn, &xt, env); putVSR(xtn, &xt, env);
} }
#define VEXT_SIGNED(name, element, mask, cast, recast) \ #define VEXT_SIGNED(name, element, cast) \
void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \
{ \ { \
int i; \ int i; \
VECTOR_FOR_INORDER_I(i, element) { \ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
r->element[i] = (recast)((cast)(b->element[i] & mask)); \ r->element[i] = (cast)b->element[i]; \
} \ } \
} }
VEXT_SIGNED(vextsb2w, s32, UINT8_MAX, int8_t, int32_t) VEXT_SIGNED(vextsb2w, s32, int8_t)
VEXT_SIGNED(vextsb2d, s64, UINT8_MAX, int8_t, int64_t) VEXT_SIGNED(vextsb2d, s64, int8_t)
VEXT_SIGNED(vextsh2w, s32, UINT16_MAX, int16_t, int32_t) VEXT_SIGNED(vextsh2w, s32, int16_t)
VEXT_SIGNED(vextsh2d, s64, UINT16_MAX, int16_t, int64_t) VEXT_SIGNED(vextsh2d, s64, int16_t)
VEXT_SIGNED(vextsw2d, s64, UINT32_MAX, int32_t, int64_t) VEXT_SIGNED(vextsw2d, s64, int32_t)
#undef VEXT_SIGNED #undef VEXT_SIGNED
#define VNEG(name, element) \ #define VNEG(name, element) \
void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \ void helper_##name(ppc_avr_t *r, ppc_avr_t *b) \
{ \ { \
int i; \ int i; \
VECTOR_FOR_INORDER_I(i, element) { \ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
r->element[i] = -b->element[i]; \ r->element[i] = -b->element[i]; \
} \ } \
} }
@ -2106,7 +2042,7 @@ VSR(d, u64, 0x3F)
void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b) void helper_vsro(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
{ {
int sh = (b->u8[LO_IDX * 0xf] >> 3) & 0xf; int sh = (b->VsrB(0xf) >> 3) & 0xf;
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)
memmove(&r->u8[sh], &a->u8[0], 16 - sh); memmove(&r->u8[sh], &a->u8[0], 16 - sh);
@ -2133,17 +2069,13 @@ void helper_vsumsws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t result; ppc_avr_t result;
int sat = 0; int sat = 0;
#if defined(HOST_WORDS_BIGENDIAN) upper = ARRAY_SIZE(r->s32) - 1;
upper = ARRAY_SIZE(r->s32)-1; t = (int64_t)b->VsrSW(upper);
#else
upper = 0;
#endif
t = (int64_t)b->s32[upper];
for (i = 0; i < ARRAY_SIZE(r->s32); i++) { for (i = 0; i < ARRAY_SIZE(r->s32); i++) {
t += a->s32[i]; t += a->VsrSW(i);
result.s32[i] = 0; result.VsrSW(i) = 0;
} }
result.s32[upper] = cvtsdsw(t, &sat); result.VsrSW(upper) = cvtsdsw(t, &sat);
*r = result; *r = result;
if (sat) { if (sat) {
@ -2157,19 +2089,15 @@ void helper_vsum2sws(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t result; ppc_avr_t result;
int sat = 0; int sat = 0;
#if defined(HOST_WORDS_BIGENDIAN)
upper = 1; upper = 1;
#else
upper = 0;
#endif
for (i = 0; i < ARRAY_SIZE(r->u64); i++) { for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
int64_t t = (int64_t)b->s32[upper + i * 2]; int64_t t = (int64_t)b->VsrSW(upper + i * 2);
result.u64[i] = 0; result.VsrW(i) = 0;
for (j = 0; j < ARRAY_SIZE(r->u64); j++) { for (j = 0; j < ARRAY_SIZE(r->u64); j++) {
t += a->s32[2 * i + j]; t += a->VsrSW(2 * i + j);
} }
result.s32[upper + i * 2] = cvtsdsw(t, &sat); result.VsrSW(upper + i * 2) = cvtsdsw(t, &sat);
} }
*r = result; *r = result;
@ -2294,7 +2222,7 @@ VUPK(lsw, s64, s32, UPKLO)
{ \ { \
int i; \ int i; \
\ \
VECTOR_FOR_INORDER_I(i, element) { \ for (i = 0; i < ARRAY_SIZE(r->element); i++) { \
r->element[i] = name(b->element[i]); \ r->element[i] = name(b->element[i]); \
} \ } \
} }
@ -2362,13 +2290,13 @@ static inline void avr_qw_not(ppc_avr_t *t, ppc_avr_t a)
static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b) static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b)
{ {
if (a.u64[HI_IDX] < b.u64[HI_IDX]) { if (a.VsrD(0) < b.VsrD(0)) {
return -1; return -1;
} else if (a.u64[HI_IDX] > b.u64[HI_IDX]) { } else if (a.VsrD(0) > b.VsrD(0)) {
return 1; return 1;
} else if (a.u64[LO_IDX] < b.u64[LO_IDX]) { } else if (a.VsrD(1) < b.VsrD(1)) {
return -1; return -1;
} else if (a.u64[LO_IDX] > b.u64[LO_IDX]) { } else if (a.VsrD(1) > b.VsrD(1)) {
return 1; return 1;
} else { } else {
return 0; return 0;
@ -2377,17 +2305,17 @@ static int avr_qw_cmpu(ppc_avr_t a, ppc_avr_t b)
static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) static void avr_qw_add(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
{ {
t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
(~a.u64[LO_IDX] < b.u64[LO_IDX]); (~a.VsrD(1) < b.VsrD(1));
} }
static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b) static int avr_qw_addc(ppc_avr_t *t, ppc_avr_t a, ppc_avr_t b)
{ {
ppc_avr_t not_a; ppc_avr_t not_a;
t->u64[LO_IDX] = a.u64[LO_IDX] + b.u64[LO_IDX]; t->VsrD(1) = a.VsrD(1) + b.VsrD(1);
t->u64[HI_IDX] = a.u64[HI_IDX] + b.u64[HI_IDX] + t->VsrD(0) = a.VsrD(0) + b.VsrD(0) +
(~a.u64[LO_IDX] < b.u64[LO_IDX]); (~a.VsrD(1) < b.VsrD(1));
avr_qw_not(&not_a, a); avr_qw_not(&not_a, a);
return avr_qw_cmpu(not_a, b) < 0; return avr_qw_cmpu(not_a, b) < 0;
} }
@ -2409,11 +2337,11 @@ void helper_vaddeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
r->u128 = a->u128 + b->u128 + (c->u128 & 1); r->u128 = a->u128 + b->u128 + (c->u128 & 1);
#else #else
if (c->u64[LO_IDX] & 1) { if (c->VsrD(1) & 1) {
ppc_avr_t tmp; ppc_avr_t tmp;
tmp.u64[HI_IDX] = 0; tmp.VsrD(0) = 0;
tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; tmp.VsrD(1) = c->VsrD(1) & 1;
avr_qw_add(&tmp, *a, tmp); avr_qw_add(&tmp, *a, tmp);
avr_qw_add(r, tmp, *b); avr_qw_add(r, tmp, *b);
} else { } else {
@ -2431,8 +2359,8 @@ void helper_vaddcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
avr_qw_not(&not_a, *a); avr_qw_not(&not_a, *a);
r->u64[HI_IDX] = 0; r->VsrD(0) = 0;
r->u64[LO_IDX] = (avr_qw_cmpu(not_a, *b) < 0); r->VsrD(1) = (avr_qw_cmpu(not_a, *b) < 0);
#endif #endif
} }
@ -2447,7 +2375,7 @@ void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
r->u128 = carry_out; r->u128 = carry_out;
#else #else
int carry_in = c->u64[LO_IDX] & 1; int carry_in = c->VsrD(1) & 1;
int carry_out = 0; int carry_out = 0;
ppc_avr_t tmp; ppc_avr_t tmp;
@ -2457,8 +2385,8 @@ void helper_vaddecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
ppc_avr_t one = QW_ONE; ppc_avr_t one = QW_ONE;
carry_out = avr_qw_addc(&tmp, tmp, one); carry_out = avr_qw_addc(&tmp, tmp, one);
} }
r->u64[HI_IDX] = 0; r->VsrD(0) = 0;
r->u64[LO_IDX] = carry_out; r->VsrD(1) = carry_out;
#endif #endif
} }
@ -2486,8 +2414,8 @@ void helper_vsubeuqm(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
avr_qw_not(&tmp, *b); avr_qw_not(&tmp, *b);
avr_qw_add(&sum, *a, tmp); avr_qw_add(&sum, *a, tmp);
tmp.u64[HI_IDX] = 0; tmp.VsrD(0) = 0;
tmp.u64[LO_IDX] = c->u64[LO_IDX] & 1; tmp.VsrD(1) = c->VsrD(1) & 1;
avr_qw_add(r, sum, tmp); avr_qw_add(r, sum, tmp);
#endif #endif
} }
@ -2503,10 +2431,10 @@ void helper_vsubcuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
ppc_avr_t tmp; ppc_avr_t tmp;
avr_qw_not(&tmp, *b); avr_qw_not(&tmp, *b);
avr_qw_add(&tmp, *a, tmp); avr_qw_add(&tmp, *a, tmp);
carry = ((tmp.s64[HI_IDX] == -1ull) && (tmp.s64[LO_IDX] == -1ull)); carry = ((tmp.VsrSD(0) == -1ull) && (tmp.VsrSD(1) == -1ull));
} }
r->u64[HI_IDX] = 0; r->VsrD(0) = 0;
r->u64[LO_IDX] = carry; r->VsrD(1) = carry;
#endif #endif
} }
@ -2517,17 +2445,17 @@ void helper_vsubecuq(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
(~a->u128 < ~b->u128) || (~a->u128 < ~b->u128) ||
((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1)); ((c->u128 & 1) && (a->u128 + ~b->u128 == (__uint128_t)-1));
#else #else
int carry_in = c->u64[LO_IDX] & 1; int carry_in = c->VsrD(1) & 1;
int carry_out = (avr_qw_cmpu(*a, *b) > 0); int carry_out = (avr_qw_cmpu(*a, *b) > 0);
if (!carry_out && carry_in) { if (!carry_out && carry_in) {
ppc_avr_t tmp; ppc_avr_t tmp;
avr_qw_not(&tmp, *b); avr_qw_not(&tmp, *b);
avr_qw_add(&tmp, *a, tmp); avr_qw_add(&tmp, *a, tmp);
carry_out = ((tmp.u64[HI_IDX] == -1ull) && (tmp.u64[LO_IDX] == -1ull)); carry_out = ((tmp.VsrD(0) == -1ull) && (tmp.VsrD(1) == -1ull));
} }
r->u64[HI_IDX] = 0; r->VsrD(0) = 0;
r->u64[LO_IDX] = carry_out; r->VsrD(1) = carry_out;
#endif #endif
} }
@ -2625,7 +2553,7 @@ static bool bcd_is_valid(ppc_avr_t *bcd)
static int bcd_cmp_zero(ppc_avr_t *bcd) static int bcd_cmp_zero(ppc_avr_t *bcd)
{ {
if (bcd->u64[HI_IDX] == 0 && (bcd->u64[LO_IDX] >> 4) == 0) { if (bcd->VsrD(0) == 0 && (bcd->VsrD(1) >> 4) == 0) {
return CRF_EQ; return CRF_EQ;
} else { } else {
return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT; return (bcd_get_sgn(bcd) == 1) ? CRF_GT : CRF_LT;
@ -2634,20 +2562,12 @@ static int bcd_cmp_zero(ppc_avr_t *bcd)
static uint16_t get_national_digit(ppc_avr_t *reg, int n) static uint16_t get_national_digit(ppc_avr_t *reg, int n)
{ {
#if defined(HOST_WORDS_BIGENDIAN) return reg->VsrH(7 - n);
return reg->u16[7 - n];
#else
return reg->u16[n];
#endif
} }
static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n) static void set_national_digit(ppc_avr_t *reg, uint8_t val, int n)
{ {
#if defined(HOST_WORDS_BIGENDIAN) reg->VsrH(7 - n) = val;
reg->u16[7 - n] = val;
#else
reg->u16[n] = val;
#endif
} }
static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b) static int bcd_cmp_mag(ppc_avr_t *a, ppc_avr_t *b)
@ -2745,7 +2665,7 @@ uint32_t helper_bcdadd(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
} }
if (unlikely(invalid)) { if (unlikely(invalid)) {
result.u64[HI_IDX] = result.u64[LO_IDX] = -1; result.VsrD(0) = result.VsrD(1) = -1;
cr = CRF_SO; cr = CRF_SO;
} else if (overflow) { } else if (overflow) {
cr |= CRF_SO; cr |= CRF_SO;
@ -2814,7 +2734,7 @@ uint32_t helper_bcdctn(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
int invalid = (sgnb == 0); int invalid = (sgnb == 0);
ppc_avr_t ret = { .u64 = { 0, 0 } }; ppc_avr_t ret = { .u64 = { 0, 0 } };
int ox_flag = (b->u64[HI_IDX] != 0) || ((b->u64[LO_IDX] >> 32) != 0); int ox_flag = (b->VsrD(0) != 0) || ((b->VsrD(1) >> 32) != 0);
for (i = 1; i < 8; i++) { for (i = 1; i < 8; i++) {
set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i); set_national_digit(&ret, 0x30 + bcd_get_digit(b, i, &invalid), i);
@ -2894,7 +2814,7 @@ uint32_t helper_bcdctz(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
int invalid = (sgnb == 0); int invalid = (sgnb == 0);
ppc_avr_t ret = { .u64 = { 0, 0 } }; ppc_avr_t ret = { .u64 = { 0, 0 } };
int ox_flag = ((b->u64[HI_IDX] >> 4) != 0); int ox_flag = ((b->VsrD(0) >> 4) != 0);
for (i = 0; i < 16; i++) { for (i = 0; i < 16; i++) {
digit = bcd_get_digit(b, i + 1, &invalid); digit = bcd_get_digit(b, i + 1, &invalid);
@ -2935,13 +2855,13 @@ uint32_t helper_bcdcfsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
uint64_t hi_value; uint64_t hi_value;
ppc_avr_t ret = { .u64 = { 0, 0 } }; ppc_avr_t ret = { .u64 = { 0, 0 } };
if (b->s64[HI_IDX] < 0) { if (b->VsrSD(0) < 0) {
lo_value = -b->s64[LO_IDX]; lo_value = -b->VsrSD(1);
hi_value = ~b->u64[HI_IDX] + !lo_value; hi_value = ~b->VsrD(0) + !lo_value;
bcd_put_digit(&ret, 0xD, 0); bcd_put_digit(&ret, 0xD, 0);
} else { } else {
lo_value = b->u64[LO_IDX]; lo_value = b->VsrD(1);
hi_value = b->u64[HI_IDX]; hi_value = b->VsrD(0);
bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0); bcd_put_digit(&ret, bcd_preferred_sgn(0, ps), 0);
} }
@ -2989,11 +2909,11 @@ uint32_t helper_bcdctsq(ppc_avr_t *r, ppc_avr_t *b, uint32_t ps)
} }
if (sgnb == -1) { if (sgnb == -1) {
r->s64[LO_IDX] = -lo_value; r->VsrSD(1) = -lo_value;
r->s64[HI_IDX] = ~hi_value + !r->s64[LO_IDX]; r->VsrSD(0) = ~hi_value + !r->VsrSD(1);
} else { } else {
r->s64[LO_IDX] = lo_value; r->VsrSD(1) = lo_value;
r->s64[HI_IDX] = hi_value; r->VsrSD(0) = hi_value;
} }
cr = bcd_cmp_zero(b); cr = bcd_cmp_zero(b);
@ -3053,7 +2973,7 @@ uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
bool ox_flag = false; bool ox_flag = false;
int sgnb = bcd_get_sgn(b); int sgnb = bcd_get_sgn(b);
ppc_avr_t ret = *b; ppc_avr_t ret = *b;
ret.u64[LO_IDX] &= ~0xf; ret.VsrD(1) &= ~0xf;
if (bcd_is_valid(b) == false) { if (bcd_is_valid(b) == false) {
return CRF_SO; return CRF_SO;
@ -3066,9 +2986,9 @@ uint32_t helper_bcds(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
} }
if (i > 0) { if (i > 0) {
ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
} else { } else {
urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
} }
bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0); bcd_put_digit(&ret, bcd_preferred_sgn(sgnb, ps), 0);
@ -3105,13 +3025,13 @@ uint32_t helper_bcdus(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
#endif #endif
if (i >= 32) { if (i >= 32) {
ox_flag = true; ox_flag = true;
ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0; ret.VsrD(1) = ret.VsrD(0) = 0;
} else if (i <= -32) { } else if (i <= -32) {
ret.u64[LO_IDX] = ret.u64[HI_IDX] = 0; ret.VsrD(1) = ret.VsrD(0) = 0;
} else if (i > 0) { } else if (i > 0) {
ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
} else { } else {
urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
} }
*r = ret; *r = ret;
@ -3131,7 +3051,7 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
bool ox_flag = false; bool ox_flag = false;
int sgnb = bcd_get_sgn(b); int sgnb = bcd_get_sgn(b);
ppc_avr_t ret = *b; ppc_avr_t ret = *b;
ret.u64[LO_IDX] &= ~0xf; ret.VsrD(1) &= ~0xf;
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)
int i = a->s8[7]; int i = a->s8[7];
@ -3152,9 +3072,9 @@ uint32_t helper_bcdsr(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
} }
if (i > 0) { if (i > 0) {
ulshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], i * 4, &ox_flag); ulshift(&ret.VsrD(1), &ret.VsrD(0), i * 4, &ox_flag);
} else { } else {
urshift(&ret.u64[LO_IDX], &ret.u64[HI_IDX], -i * 4); urshift(&ret.VsrD(1), &ret.VsrD(0), -i * 4);
if (bcd_get_digit(&ret, 0, &invalid) >= 5) { if (bcd_get_digit(&ret, 0, &invalid) >= 5) {
bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused); bcd_add_mag(&ret, &ret, &bcd_one, &invalid, &unused);
@ -3188,19 +3108,19 @@ uint32_t helper_bcdtrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
if (i > 16 && i < 32) { if (i > 16 && i < 32) {
mask = (uint64_t)-1 >> (128 - i * 4); mask = (uint64_t)-1 >> (128 - i * 4);
if (ret.u64[HI_IDX] & ~mask) { if (ret.VsrD(0) & ~mask) {
ox_flag = CRF_SO; ox_flag = CRF_SO;
} }
ret.u64[HI_IDX] &= mask; ret.VsrD(0) &= mask;
} else if (i >= 0 && i <= 16) { } else if (i >= 0 && i <= 16) {
mask = (uint64_t)-1 >> (64 - i * 4); mask = (uint64_t)-1 >> (64 - i * 4);
if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] & ~mask)) { if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
ox_flag = CRF_SO; ox_flag = CRF_SO;
} }
ret.u64[LO_IDX] &= mask; ret.VsrD(1) &= mask;
ret.u64[HI_IDX] = 0; ret.VsrD(0) = 0;
} }
bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0); bcd_put_digit(&ret, bcd_preferred_sgn(bcd_get_sgn(b), ps), 0);
*r = ret; *r = ret;
@ -3231,28 +3151,28 @@ uint32_t helper_bcdutrunc(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, uint32_t ps)
#endif #endif
if (i > 16 && i < 33) { if (i > 16 && i < 33) {
mask = (uint64_t)-1 >> (128 - i * 4); mask = (uint64_t)-1 >> (128 - i * 4);
if (ret.u64[HI_IDX] & ~mask) { if (ret.VsrD(0) & ~mask) {
ox_flag = CRF_SO; ox_flag = CRF_SO;
} }
ret.u64[HI_IDX] &= mask; ret.VsrD(0) &= mask;
} else if (i > 0 && i <= 16) { } else if (i > 0 && i <= 16) {
mask = (uint64_t)-1 >> (64 - i * 4); mask = (uint64_t)-1 >> (64 - i * 4);
if (ret.u64[HI_IDX] || (ret.u64[LO_IDX] & ~mask)) { if (ret.VsrD(0) || (ret.VsrD(1) & ~mask)) {
ox_flag = CRF_SO; ox_flag = CRF_SO;
} }
ret.u64[LO_IDX] &= mask; ret.VsrD(1) &= mask;
ret.u64[HI_IDX] = 0; ret.VsrD(0) = 0;
} else if (i == 0) { } else if (i == 0) {
if (ret.u64[HI_IDX] || ret.u64[LO_IDX]) { if (ret.VsrD(0) || ret.VsrD(1)) {
ox_flag = CRF_SO; ox_flag = CRF_SO;
} }
ret.u64[HI_IDX] = ret.u64[LO_IDX] = 0; ret.VsrD(0) = ret.VsrD(1) = 0;
} }
*r = ret; *r = ret;
if (r->u64[HI_IDX] == 0 && r->u64[LO_IDX] == 0) { if (r->VsrD(0) == 0 && r->VsrD(1) == 0) {
return ox_flag | CRF_EQ; return ox_flag | CRF_EQ;
} }
@ -3324,108 +3244,83 @@ void helper_vncipherlast(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
*r = result; *r = result;
} }
#define ROTRu32(v, n) (((v) >> (n)) | ((v) << (32-n)))
#if defined(HOST_WORDS_BIGENDIAN)
#define EL_IDX(i) (i)
#else
#define EL_IDX(i) (3 - (i))
#endif
void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) void helper_vshasigmaw(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six)
{ {
int st = (st_six & 0x10) != 0; int st = (st_six & 0x10) != 0;
int six = st_six & 0xF; int six = st_six & 0xF;
int i; int i;
VECTOR_FOR_INORDER_I(i, u32) { for (i = 0; i < ARRAY_SIZE(r->u32); i++) {
if (st == 0) { if (st == 0) {
if ((six & (0x8 >> i)) == 0) { if ((six & (0x8 >> i)) == 0) {
r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 7) ^ r->VsrW(i) = ror32(a->VsrW(i), 7) ^
ROTRu32(a->u32[EL_IDX(i)], 18) ^ ror32(a->VsrW(i), 18) ^
(a->u32[EL_IDX(i)] >> 3); (a->VsrW(i) >> 3);
} else { /* six.bit[i] == 1 */ } else { /* six.bit[i] == 1 */
r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 17) ^ r->VsrW(i) = ror32(a->VsrW(i), 17) ^
ROTRu32(a->u32[EL_IDX(i)], 19) ^ ror32(a->VsrW(i), 19) ^
(a->u32[EL_IDX(i)] >> 10); (a->VsrW(i) >> 10);
} }
} else { /* st == 1 */ } else { /* st == 1 */
if ((six & (0x8 >> i)) == 0) { if ((six & (0x8 >> i)) == 0) {
r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 2) ^ r->VsrW(i) = ror32(a->VsrW(i), 2) ^
ROTRu32(a->u32[EL_IDX(i)], 13) ^ ror32(a->VsrW(i), 13) ^
ROTRu32(a->u32[EL_IDX(i)], 22); ror32(a->VsrW(i), 22);
} else { /* six.bit[i] == 1 */ } else { /* six.bit[i] == 1 */
r->u32[EL_IDX(i)] = ROTRu32(a->u32[EL_IDX(i)], 6) ^ r->VsrW(i) = ror32(a->VsrW(i), 6) ^
ROTRu32(a->u32[EL_IDX(i)], 11) ^ ror32(a->VsrW(i), 11) ^
ROTRu32(a->u32[EL_IDX(i)], 25); ror32(a->VsrW(i), 25);
} }
} }
} }
} }
#undef ROTRu32
#undef EL_IDX
#define ROTRu64(v, n) (((v) >> (n)) | ((v) << (64-n)))
#if defined(HOST_WORDS_BIGENDIAN)
#define EL_IDX(i) (i)
#else
#define EL_IDX(i) (1 - (i))
#endif
void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six) void helper_vshasigmad(ppc_avr_t *r, ppc_avr_t *a, uint32_t st_six)
{ {
int st = (st_six & 0x10) != 0; int st = (st_six & 0x10) != 0;
int six = st_six & 0xF; int six = st_six & 0xF;
int i; int i;
VECTOR_FOR_INORDER_I(i, u64) { for (i = 0; i < ARRAY_SIZE(r->u64); i++) {
if (st == 0) { if (st == 0) {
if ((six & (0x8 >> (2*i))) == 0) { if ((six & (0x8 >> (2*i))) == 0) {
r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 1) ^ r->VsrD(i) = ror64(a->VsrD(i), 1) ^
ROTRu64(a->u64[EL_IDX(i)], 8) ^ ror64(a->VsrD(i), 8) ^
(a->u64[EL_IDX(i)] >> 7); (a->VsrD(i) >> 7);
} else { /* six.bit[2*i] == 1 */ } else { /* six.bit[2*i] == 1 */
r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 19) ^ r->VsrD(i) = ror64(a->VsrD(i), 19) ^
ROTRu64(a->u64[EL_IDX(i)], 61) ^ ror64(a->VsrD(i), 61) ^
(a->u64[EL_IDX(i)] >> 6); (a->VsrD(i) >> 6);
} }
} else { /* st == 1 */ } else { /* st == 1 */
if ((six & (0x8 >> (2*i))) == 0) { if ((six & (0x8 >> (2*i))) == 0) {
r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 28) ^ r->VsrD(i) = ror64(a->VsrD(i), 28) ^
ROTRu64(a->u64[EL_IDX(i)], 34) ^ ror64(a->VsrD(i), 34) ^
ROTRu64(a->u64[EL_IDX(i)], 39); ror64(a->VsrD(i), 39);
} else { /* six.bit[2*i] == 1 */ } else { /* six.bit[2*i] == 1 */
r->u64[EL_IDX(i)] = ROTRu64(a->u64[EL_IDX(i)], 14) ^ r->VsrD(i) = ror64(a->VsrD(i), 14) ^
ROTRu64(a->u64[EL_IDX(i)], 18) ^ ror64(a->VsrD(i), 18) ^
ROTRu64(a->u64[EL_IDX(i)], 41); ror64(a->VsrD(i), 41);
} }
} }
} }
} }
#undef ROTRu64
#undef EL_IDX
void helper_vpermxor(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c) void helper_vpermxor(ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b, ppc_avr_t *c)
{ {
ppc_avr_t result; ppc_avr_t result;
int i; int i;
VECTOR_FOR_INORDER_I(i, u8) { for (i = 0; i < ARRAY_SIZE(r->u8); i++) {
int indexA = c->u8[i] >> 4; int indexA = c->VsrB(i) >> 4;
int indexB = c->u8[i] & 0xF; int indexB = c->VsrB(i) & 0xF;
#if defined(HOST_WORDS_BIGENDIAN)
result.u8[i] = a->u8[indexA] ^ b->u8[indexB]; result.VsrB(i) = a->VsrB(indexA) ^ b->VsrB(indexB);
#else
result.u8[i] = a->u8[15-indexA] ^ b->u8[15-indexB];
#endif
} }
*r = result; *r = result;
} }
#undef VECTOR_FOR_INORDER_I #undef VECTOR_FOR_INORDER_I
#undef HI_IDX
#undef LO_IDX
/*****************************************************************************/ /*****************************************************************************/
/* SPE extension helpers */ /* SPE extension helpers */

View File

@ -206,16 +206,23 @@ EXTRACT_HELPER_SPLIT_3(DCMX_XV, 5, 16, 0, 1, 2, 5, 1, 6, 6);
#if defined(HOST_WORDS_BIGENDIAN) #if defined(HOST_WORDS_BIGENDIAN)
#define VsrB(i) u8[i] #define VsrB(i) u8[i]
#define VsrSB(i) s8[i]
#define VsrH(i) u16[i] #define VsrH(i) u16[i]
#define VsrSH(i) s16[i]
#define VsrW(i) u32[i] #define VsrW(i) u32[i]
#define VsrSW(i) s32[i]
#define VsrD(i) u64[i] #define VsrD(i) u64[i]
#define VsrSD(i) s64[i]
#else #else
#define VsrB(i) u8[15 - (i)] #define VsrB(i) u8[15 - (i)]
#define VsrSB(i) s8[15 - (i)]
#define VsrH(i) u16[7 - (i)] #define VsrH(i) u16[7 - (i)]
#define VsrSH(i) s16[7 - (i)]
#define VsrW(i) u32[3 - (i)] #define VsrW(i) u32[3 - (i)]
#define VsrSW(i) s32[3 - (i)]
#define VsrD(i) u64[1 - (i)] #define VsrD(i) u64[1 - (i)]
#define VsrSD(i) s64[1 - (i)]
#endif #endif
static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env) static inline void getVSR(int n, ppc_vsr_t *vsr, CPUPPCState *env)
{ {
vsr->VsrD(0) = env->vsr[n].u64[0]; vsr->VsrD(0) = env->vsr[n].u64[0];

View File

@ -36,7 +36,6 @@
#include "hw/sysbus.h" #include "hw/sysbus.h"
#include "hw/ppc/spapr.h" #include "hw/ppc/spapr.h"
#include "hw/ppc/spapr_vio.h"
#include "hw/ppc/spapr_cpu_core.h" #include "hw/ppc/spapr_cpu_core.h"
#include "hw/ppc/ppc.h" #include "hw/ppc/ppc.h"
#include "sysemu/watchdog.h" #include "sysemu/watchdog.h"

View File

@ -77,11 +77,20 @@ size_t qemu_mempath_getpagesize(const char *mem_path)
void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared) void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
{ {
int flags;
int guardfd;
size_t offset;
size_t pagesize;
size_t total;
void *guardptr;
void *ptr;
/* /*
* Note: this always allocates at least one extra page of virtual address * Note: this always allocates at least one extra page of virtual address
* space, even if size is already aligned. * space, even if size is already aligned.
*/ */
size_t total = size + align; total = size + align;
#if defined(__powerpc64__) && defined(__linux__) #if defined(__powerpc64__) && defined(__linux__)
/* On ppc64 mappings in the same segment (aka slice) must share the same /* On ppc64 mappings in the same segment (aka slice) must share the same
* page size. Since we will be re-allocating part of this segment * page size. Since we will be re-allocating part of this segment
@ -91,36 +100,45 @@ void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
* We do this unless we are using the system page size, in which case * We do this unless we are using the system page size, in which case
* anonymous memory is OK. * anonymous memory is OK.
*/ */
int anonfd = fd == -1 || qemu_fd_getpagesize(fd) == getpagesize() ? -1 : fd; flags = MAP_PRIVATE;
int flags = anonfd == -1 ? MAP_ANONYMOUS : MAP_NORESERVE; pagesize = qemu_fd_getpagesize(fd);
void *ptr = mmap(0, total, PROT_NONE, flags | MAP_PRIVATE, anonfd, 0); if (fd == -1 || pagesize == getpagesize()) {
guardfd = -1;
flags |= MAP_ANONYMOUS;
} else {
guardfd = fd;
flags |= MAP_NORESERVE;
}
#else #else
void *ptr = mmap(0, total, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); guardfd = -1;
pagesize = getpagesize();
flags = MAP_PRIVATE | MAP_ANONYMOUS;
#endif #endif
size_t offset;
void *ptr1;
if (ptr == MAP_FAILED) { guardptr = mmap(0, total, PROT_NONE, flags, guardfd, 0);
if (guardptr == MAP_FAILED) {
return MAP_FAILED; return MAP_FAILED;
} }
assert(is_power_of_2(align)); assert(is_power_of_2(align));
/* Always align to host page size */ /* Always align to host page size */
assert(align >= getpagesize()); assert(align >= pagesize);
offset = QEMU_ALIGN_UP((uintptr_t)ptr, align) - (uintptr_t)ptr; flags = MAP_FIXED;
ptr1 = mmap(ptr + offset, size, PROT_READ | PROT_WRITE, flags |= fd == -1 ? MAP_ANONYMOUS : 0;
MAP_FIXED | flags |= shared ? MAP_SHARED : MAP_PRIVATE;
(fd == -1 ? MAP_ANONYMOUS : 0) | offset = QEMU_ALIGN_UP((uintptr_t)guardptr, align) - (uintptr_t)guardptr;
(shared ? MAP_SHARED : MAP_PRIVATE),
fd, 0); ptr = mmap(guardptr + offset, size, PROT_READ | PROT_WRITE, flags, fd, 0);
if (ptr1 == MAP_FAILED) {
munmap(ptr, total); if (ptr == MAP_FAILED) {
munmap(guardptr, total);
return MAP_FAILED; return MAP_FAILED;
} }
if (offset > 0) { if (offset > 0) {
munmap(ptr, offset); munmap(guardptr, offset);
} }
/* /*
@ -128,17 +146,24 @@ void *qemu_ram_mmap(int fd, size_t size, size_t align, bool shared)
* a guard page guarding against potential buffer overflows. * a guard page guarding against potential buffer overflows.
*/ */
total -= offset; total -= offset;
if (total > size + getpagesize()) { if (total > size + pagesize) {
munmap(ptr1 + size + getpagesize(), total - size - getpagesize()); munmap(ptr + size + pagesize, total - size - pagesize);
} }
return ptr1; return ptr;
} }
void qemu_ram_munmap(void *ptr, size_t size) void qemu_ram_munmap(int fd, void *ptr, size_t size)
{ {
size_t pagesize;
if (ptr) { if (ptr) {
/* Unmap both the RAM block and the guard page */ /* Unmap both the RAM block and the guard page */
munmap(ptr, size + getpagesize()); #if defined(__powerpc64__) && defined(__linux__)
pagesize = qemu_fd_getpagesize(fd);
#else
pagesize = getpagesize();
#endif
munmap(ptr, size + pagesize);
} }
} }

View File

@ -226,7 +226,7 @@ void qemu_vfree(void *ptr)
void qemu_anon_ram_free(void *ptr, size_t size) void qemu_anon_ram_free(void *ptr, size_t size)
{ {
trace_qemu_anon_ram_free(ptr, size); trace_qemu_anon_ram_free(ptr, size);
qemu_ram_munmap(ptr, size); qemu_ram_munmap(-1, ptr, size);
} }
void qemu_set_block(int fd) void qemu_set_block(int fd)