ppc patch queue 2021-08-27

First ppc pull request for qemu-6.2.  As usual, there's a fair bit
 here, since it's been queued during the 6.1 freeze.  Highlights are:
 
  * Some fixes for 128 bit arithmetic and some vector opcodes that use
    them
  * Significant improvements to the powernv to support POWER10 cpus
    (more to come though)
  * Several cleanups to the ppc softmmu code
  * A few other assorted fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAmEoj5gACgkQbDjKyiDZ
 s5JFPw/+JOmi1G6eY3u/kYJ8TJhe65s6TJDQhGQiQSBoBShRBJ1+bro3fPGA8pkT
 48NAb9RnTnLqys+vhScF7qt2wIxXJFVoVyMhAj2Xv11VQzDPpbLGg6+2Qt7WFraQ
 zyeEKBQQTV29RtV7UBUEmx4ZGmnoc0cmzl3QGO3Jq17ucOHNTSW19QpxU60wClU1
 PZIUDoWdt7FBS8lvj/55736H3z6ZRnBqZtW9m64ln+CBQuuKo5UkAkaooaJhEFJx
 OUZYeo+zky8YaYSWwTFGIxBYhwptnAWCsqkzeJUxPw1ICAzwj/kQX7ckVhbgTpbE
 CADpgkATXTbQzLFipzxJ45UMP0yMsk5IOPZ6FS9G+JfsP2T92RMwy7XhqPfWCoov
 WKqX/xpmGTnJONuQ7SO/bWUyPH4K7hYgSPPlLAcwDYCg4szWRIbTCs9Yr9rzAPhk
 KqKUGLb7D7Rbi1ulSC2ieqsTqVmp6plfnjxR2gPcbp0FltqGln6tVZEHEyPjTEv0
 5b7w+3AHDwh9a4NyzULaxxBKktNU1KXKe74/U86qhJtx4kXFSkAhoeztcR30zmUX
 W1xjb5eoRgFbHnoDTCtDYAUwuz2w1/I2OLA5kfnSQnRQS0YiqUeicbBkW6iIE61z
 oM86ZwEQX1lyf7agECRgpfdcPa6uyAQ72QUR5wgvXDW59PSNNxk=
 =C5XY
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dg-gitlab/tags/ppc-for-6.2-20210827' into staging

ppc patch queue 2021-08-27

First ppc pull request for qemu-6.2.  As usual, there's a fair bit
here, since it's been queued during the 6.1 freeze.  Highlights are:

 * Some fixes for 128 bit arithmetic and some vector opcodes that use
   them
 * Significant improvements to the powernv to support POWER10 cpus
   (more to come though)
 * Several cleanups to the ppc softmmu code
 * A few other assorted fixes

# gpg: Signature made Fri 27 Aug 2021 08:09:12 BST
# 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/dg-gitlab/tags/ppc-for-6.2-20210827:
  target/ppc: fix vector registers access in gdbstub for little-endian
  include/qemu/int128.h: introduce bswap128s
  target/ppc: fix vextu[bhw][lr]x helpers
  include/qemu/int128.h: define struct Int128 according to the host endianness
  ppc/xive: Export xive_presenter_notify()
  ppc/xive: Export PQ get/set routines
  ppc/pnv: add a chip topology index for POWER10
  ppc/pnv: Distribute RAM among the chips
  ppc/pnv: Use a simple incrementing index for the chip-id
  ppc/pnv: powerpc_excp: Do not discard HDECR exception when entering power-saving mode
  ppc/pnv: Change the POWER10 machine to support DD2 only
  ppc: Add a POWER10 DD2 CPU
  ppc/pnv: update skiboot to commit 820d43c0a775.
  target/ppc: moved store_40x_sler to helper_regs.c
  target/ppc: moved ppc_store_sdr1 to mmu_common.c
  target/ppc: divided mmu_helper.c in 2 files
  spapr_pci: Fix leak in spapr_phb_vfio_get_loc_code() with g_autofree
  xive: Remove extra '0x' prefix in trace events

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2021-08-27 11:34:12 +01:00
commit ad22d05833
25 changed files with 1824 additions and 1761 deletions

View File

@ -297,7 +297,7 @@ static uint8_t xive_esb_read(XiveSource *xsrc, int srcno, uint32_t offset)
return xive_esb_rw(xsrc, srcno, offset, 0, 0) & 0x3;
}
static void xive_esb_trigger(XiveSource *xsrc, int srcno)
static void kvmppc_xive_esb_trigger(XiveSource *xsrc, int srcno)
{
uint64_t *addr = xsrc->esb_mmap + xive_source_esb_page(xsrc, srcno);
@ -322,7 +322,7 @@ uint64_t kvmppc_xive_esb_rw(XiveSource *xsrc, int srcno, uint32_t offset,
offset == XIVE_ESB_LOAD_EOI) {
xive_esb_read(xsrc, srcno, XIVE_ESB_SET_PQ_00);
if (xsrc->status[srcno] & XIVE_STATUS_ASSERTED) {
xive_esb_trigger(xsrc, srcno);
kvmppc_xive_esb_trigger(xsrc, srcno);
}
return 0;
} else {
@ -366,7 +366,7 @@ void kvmppc_xive_source_set_irq(void *opaque, int srcno, int val)
}
}
xive_esb_trigger(xsrc, srcno);
kvmppc_xive_esb_trigger(xsrc, srcno);
}
/*
@ -533,7 +533,7 @@ static void kvmppc_xive_change_state_handler(void *opaque, bool running,
* generate a trigger.
*/
if (pq == XIVE_ESB_RESET && old_pq == XIVE_ESB_QUEUED) {
xive_esb_trigger(xsrc, i);
kvmppc_xive_esb_trigger(xsrc, i);
}
}

View File

@ -219,14 +219,14 @@ kvm_xive_source_reset(uint32_t srcno) "IRQ 0x%x"
xive_tctx_accept(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x ACK"
xive_tctx_notify(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x CPPR=0x%02x NSR=0x%02x raise !"
xive_tctx_set_cppr(uint32_t index, uint8_t ring, uint8_t ipb, uint8_t pipr, uint8_t cppr, uint8_t nsr) "target=%d ring=0x%x IBP=0x%02x PIPR=0x%02x new CPPR=0x%02x NSR=0x%02x"
xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x0x%"PRIx64" IRQ 0x%x val=0x0x%"PRIx64
xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x0x%"PRIx64" IRQ 0x%x val=0x0x%"PRIx64
xive_source_esb_read(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64
xive_source_esb_write(uint64_t addr, uint32_t srcno, uint64_t value) "@0x%"PRIx64" IRQ 0x%x val=0x%"PRIx64
xive_router_end_notify(uint8_t end_blk, uint32_t end_idx, uint32_t end_data) "END 0x%02x/0x%04x -> enqueue 0x%08x"
xive_router_end_escalate(uint8_t end_blk, uint32_t end_idx, uint8_t esc_blk, uint32_t esc_idx, uint32_t end_data) "END 0x%02x/0x%04x -> escalate END 0x%02x/0x%04x data 0x%08x"
xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"PRIx64" sz=%d val=0x%" PRIx64
xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x0x%"PRIx64" sz=%d val=0x%" PRIx64
xive_tctx_tm_write(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64
xive_tctx_tm_read(uint64_t offset, unsigned int size, uint64_t value) "@0x%"PRIx64" sz=%d val=0x%" PRIx64
xive_presenter_notify(uint8_t nvt_blk, uint32_t nvt_idx, uint8_t ring) "found NVT 0x%x/0x%x ring=0x%x"
xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x0x%"PRIx64
xive_end_source_read(uint8_t end_blk, uint32_t end_idx, uint64_t addr) "END 0x%x/0x%x @0x%"PRIx64
# pnv_xive.c
pnv_xive_ic_hw_trigger(uint64_t addr, uint64_t val) "@0x%"PRIx64" val=0x%"PRIx64

View File

@ -816,7 +816,7 @@ void xive_tctx_destroy(XiveTCTX *tctx)
* XIVE ESB helpers
*/
static uint8_t xive_esb_set(uint8_t *pq, uint8_t value)
uint8_t xive_esb_set(uint8_t *pq, uint8_t value)
{
uint8_t old_pq = *pq & 0x3;
@ -826,7 +826,7 @@ static uint8_t xive_esb_set(uint8_t *pq, uint8_t value)
return old_pq;
}
static bool xive_esb_trigger(uint8_t *pq)
bool xive_esb_trigger(uint8_t *pq)
{
uint8_t old_pq = *pq & 0x3;
@ -846,7 +846,7 @@ static bool xive_esb_trigger(uint8_t *pq)
}
}
static bool xive_esb_eoi(uint8_t *pq)
bool xive_esb_eoi(uint8_t *pq)
{
uint8_t old_pq = *pq & 0x3;
@ -1514,10 +1514,10 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
*
* The parameters represent what is sent on the PowerBus
*/
static bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint8_t priority,
uint32_t logic_serv)
bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint8_t priority,
uint32_t logic_serv)
{
XiveFabricClass *xfc = XIVE_FABRIC_GET_CLASS(xfb);
XiveTCTXMatch match = { .tctx = NULL, .ring = 0 };

View File

@ -710,6 +710,23 @@ static void pnv_chip_power10_pic_print_info(PnvChip *chip, Monitor *mon)
pnv_psi_pic_print_info(&chip10->psi, mon);
}
/* Always give the first 1GB to chip 0 else we won't boot */
static uint64_t pnv_chip_get_ram_size(PnvMachineState *pnv, int chip_id)
{
MachineState *machine = MACHINE(pnv);
uint64_t ram_per_chip;
assert(machine->ram_size >= 1 * GiB);
ram_per_chip = machine->ram_size / pnv->num_chips;
if (ram_per_chip >= 1 * GiB) {
return QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
}
ram_per_chip = (machine->ram_size - 1 * GiB) / (pnv->num_chips - 1);
return chip_id == 0 ? 1 * GiB : QEMU_ALIGN_DOWN(ram_per_chip, 1 * MiB);
}
static void pnv_init(MachineState *machine)
{
const char *bios_name = machine->firmware ?: FW_FILE_NAME;
@ -717,6 +734,7 @@ static void pnv_init(MachineState *machine)
MachineClass *mc = MACHINE_GET_CLASS(machine);
char *fw_filename;
long fw_size;
uint64_t chip_ram_start = 0;
int i;
char *chip_typename;
DriveInfo *pnor = drive_get(IF_MTD, 0, 0);
@ -809,9 +827,10 @@ static void pnv_init(MachineState *machine)
* TODO: should we decide on how many chips we can create based
* on #cores and Venice vs. Murano vs. Naples chip type etc...,
*/
if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 4) {
if (!is_power_of_2(pnv->num_chips) || pnv->num_chips > 16) {
error_report("invalid number of chips: '%d'", pnv->num_chips);
error_printf("Try '-smp sockets=N'. Valid values are : 1, 2 or 4.\n");
error_printf(
"Try '-smp sockets=N'. Valid values are : 1, 2, 4, 8 and 16.\n");
exit(1);
}
@ -819,22 +838,21 @@ static void pnv_init(MachineState *machine)
for (i = 0; i < pnv->num_chips; i++) {
char chip_name[32];
Object *chip = OBJECT(qdev_new(chip_typename));
int chip_id = i;
uint64_t chip_ram_size = pnv_chip_get_ram_size(pnv, chip_id);
pnv->chips[i] = PNV_CHIP(chip);
/*
* TODO: put all the memory in one node on chip 0 until we find a
* way to specify different ranges for each chip
*/
if (i == 0) {
object_property_set_int(chip, "ram-size", machine->ram_size,
&error_fatal);
}
snprintf(chip_name, sizeof(chip_name), "chip[%d]", PNV_CHIP_HWID(i));
object_property_add_child(OBJECT(pnv), chip_name, chip);
object_property_set_int(chip, "chip-id", PNV_CHIP_HWID(i),
/* Distribute RAM among the chips */
object_property_set_int(chip, "ram-start", chip_ram_start,
&error_fatal);
object_property_set_int(chip, "ram-size", chip_ram_size,
&error_fatal);
chip_ram_start += chip_ram_size;
snprintf(chip_name, sizeof(chip_name), "chip[%d]", chip_id);
object_property_add_child(OBJECT(pnv), chip_name, chip);
object_property_set_int(chip, "chip-id", chip_id, &error_fatal);
object_property_set_int(chip, "nr-cores", machine->smp.cores,
&error_fatal);
object_property_set_int(chip, "nr-threads", machine->smp.threads,
@ -1916,7 +1934,7 @@ static void pnv_machine_power10_class_init(ObjectClass *oc, void *data)
static const char compat[] = "qemu,powernv10\0ibm,powernv";
mc->desc = "IBM PowerNV (Non-Virtualized) POWER10";
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v1.0");
mc->default_cpu_type = POWERPC_CPU_TYPE_NAME("power10_v2.0");
pmc->compat = compat;
pmc->compat_size = sizeof(compat);

View File

@ -347,7 +347,7 @@ static const TypeInfo pnv_core_infos[] = {
DEFINE_PNV_CORE_TYPE(power8, "power8_v2.0"),
DEFINE_PNV_CORE_TYPE(power8, "power8nvl_v1.0"),
DEFINE_PNV_CORE_TYPE(power9, "power9_v2.0"),
DEFINE_PNV_CORE_TYPE(power10, "power10_v1.0"),
DEFINE_PNV_CORE_TYPE(power10, "power10_v2.0"),
};
DEFINE_TYPES(pnv_core_infos)

View File

@ -284,6 +284,8 @@ int pnv_dt_xscom(PnvChip *chip, void *fdt, int root_offset,
_FDT(xscom_offset);
g_free(name);
_FDT((fdt_setprop_cell(fdt, xscom_offset, "ibm,chip-id", chip->chip_id)));
_FDT((fdt_setprop_cell(fdt, xscom_offset, "ibm,primary-topology-index",
chip->chip_id)));
_FDT((fdt_setprop_cell(fdt, xscom_offset, "#address-cells", 1)));
_FDT((fdt_setprop_cell(fdt, xscom_offset, "#size-cells", 1)));
_FDT((fdt_setprop(fdt, xscom_offset, "reg", reg, sizeof(reg))));

View File

@ -782,33 +782,29 @@ static AddressSpace *spapr_pci_dma_iommu(PCIBus *bus, void *opaque, int devfn)
static char *spapr_phb_vfio_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)
{
char *path = NULL, *buf = NULL, *host = NULL;
g_autofree char *path = NULL;
g_autofree char *host = NULL;
g_autofree char *devspec = NULL;
char *buf = NULL;
/* Get the PCI VFIO host id */
host = object_property_get_str(OBJECT(pdev), "host", NULL);
if (!host) {
goto err_out;
return NULL;
}
/* Construct the path of the file that will give us the DT location */
path = g_strdup_printf("/sys/bus/pci/devices/%s/devspec", host);
g_free(host);
if (!g_file_get_contents(path, &buf, NULL, NULL)) {
goto err_out;
if (!g_file_get_contents(path, &devspec, NULL, NULL)) {
return NULL;
}
g_free(path);
/* Construct and read from host device tree the loc-code */
path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", buf);
g_free(buf);
path = g_strdup_printf("/proc/device-tree%s/ibm,loc-code", devspec);
if (!g_file_get_contents(path, &buf, NULL, NULL)) {
goto err_out;
return NULL;
}
return buf;
err_out:
g_free(path);
return NULL;
}
static char *spapr_phb_get_loc_code(SpaprPhbState *sphb, PCIDevice *pdev)

View File

@ -170,29 +170,10 @@ DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER8NVL,
DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER9,
TYPE_PNV_CHIP_POWER9)
#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v1.0")
#define TYPE_PNV_CHIP_POWER10 PNV_CHIP_TYPE_NAME("power10_v2.0")
DECLARE_INSTANCE_CHECKER(PnvChip, PNV_CHIP_POWER10,
TYPE_PNV_CHIP_POWER10)
/*
* This generates a HW chip id depending on an index, as found on a
* two socket system with dual chip modules :
*
* 0x0, 0x1, 0x10, 0x11
*
* 4 chips should be the maximum
*
* TODO: use a machine property to define the chip ids
*/
#define PNV_CHIP_HWID(i) ((((i) & 0x3e) << 3) | ((i) & 0x1))
/*
* Converts back a HW chip id to an index. This is useful to calculate
* the MMIO addresses of some controllers which depend on the chip id.
*/
#define PNV_CHIP_INDEX(chip) \
(((chip)->chip_id >> 2) * 2 + ((chip)->chip_id & 0x3))
PowerPCCPU *pnv_chip_find_cpu(PnvChip *chip, uint32_t pir);
#define TYPE_PNV_MACHINE MACHINE_TYPE_NAME("powernv")
@ -256,11 +237,11 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
#define PNV_OCC_COMMON_AREA_SIZE 0x0000000000800000ull
#define PNV_OCC_COMMON_AREA_BASE 0x7fff800000ull
#define PNV_OCC_SENSOR_BASE(chip) (PNV_OCC_COMMON_AREA_BASE + \
PNV_OCC_SENSOR_DATA_BLOCK_BASE(PNV_CHIP_INDEX(chip)))
PNV_OCC_SENSOR_DATA_BLOCK_BASE((chip)->chip_id))
#define PNV_HOMER_SIZE 0x0000000000400000ull
#define PNV_HOMER_BASE(chip) \
(0x7ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV_HOMER_SIZE)
(0x7ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV_HOMER_SIZE)
/*
@ -279,16 +260,16 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
*/
#define PNV_ICP_SIZE 0x0000000000100000ull
#define PNV_ICP_BASE(chip) \
(0x0003ffff80000000ull + (uint64_t) PNV_CHIP_INDEX(chip) * PNV_ICP_SIZE)
(0x0003ffff80000000ull + (uint64_t) (chip)->chip_id * PNV_ICP_SIZE)
#define PNV_PSIHB_SIZE 0x0000000000100000ull
#define PNV_PSIHB_BASE(chip) \
(0x0003fffe80000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * PNV_PSIHB_SIZE)
(0x0003fffe80000000ull + (uint64_t)(chip)->chip_id * PNV_PSIHB_SIZE)
#define PNV_PSIHB_FSP_SIZE 0x0000000100000000ull
#define PNV_PSIHB_FSP_BASE(chip) \
(0x0003ffe000000000ull + (uint64_t)PNV_CHIP_INDEX(chip) * \
(0x0003ffe000000000ull + (uint64_t)(chip)->chip_id * \
PNV_PSIHB_FSP_SIZE)
/*
@ -324,11 +305,11 @@ void pnv_bmc_set_pnor(IPMIBmc *bmc, PnvPnor *pnor);
#define PNV9_OCC_COMMON_AREA_SIZE 0x0000000000800000ull
#define PNV9_OCC_COMMON_AREA_BASE 0x203fff800000ull
#define PNV9_OCC_SENSOR_BASE(chip) (PNV9_OCC_COMMON_AREA_BASE + \
PNV_OCC_SENSOR_DATA_BLOCK_BASE(PNV_CHIP_INDEX(chip)))
PNV_OCC_SENSOR_DATA_BLOCK_BASE((chip)->chip_id))
#define PNV9_HOMER_SIZE 0x0000000000400000ull
#define PNV9_HOMER_BASE(chip) \
(0x203ffd800000ull + ((uint64_t)PNV_CHIP_INDEX(chip)) * PNV9_HOMER_SIZE)
(0x203ffd800000ull + ((uint64_t)(chip)->chip_id) * PNV9_HOMER_SIZE)
/*
* POWER10 MMIO base addresses - 16TB stride per chip

View File

@ -261,6 +261,10 @@ static inline hwaddr xive_source_esb_mgmt(XiveSource *xsrc, int srcno)
#define XIVE_ESB_QUEUED (XIVE_ESB_VAL_P | XIVE_ESB_VAL_Q)
#define XIVE_ESB_OFF XIVE_ESB_VAL_Q
bool xive_esb_trigger(uint8_t *pq);
bool xive_esb_eoi(uint8_t *pq);
uint8_t xive_esb_set(uint8_t *pq, uint8_t value);
/*
* "magic" Event State Buffer (ESB) MMIO offsets.
*
@ -404,6 +408,10 @@ int xive_presenter_tctx_match(XivePresenter *xptr, XiveTCTX *tctx,
uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint32_t logic_serv);
bool xive_presenter_notify(XiveFabric *xfb, uint8_t format,
uint8_t nvt_blk, uint32_t nvt_idx,
bool cam_ignore, uint8_t priority,
uint32_t logic_serv);
/*
* XIVE Fabric (Interface between Interrupt Controller and Machine)

View File

@ -1,9 +1,9 @@
#ifndef INT128_H
#define INT128_H
#ifdef CONFIG_INT128
#include "qemu/bswap.h"
#ifdef CONFIG_INT128
typedef __int128_t Int128;
static inline Int128 int128_make64(uint64_t a)
@ -155,31 +155,48 @@ static inline void int128_subfrom(Int128 *a, Int128 b)
static inline Int128 bswap128(Int128 a)
{
#if __has_builtin(__builtin_bswap128)
return __builtin_bswap128(a);
#else
return int128_make128(bswap64(int128_gethi(a)), bswap64(int128_getlo(a)));
#endif
}
#else /* !CONFIG_INT128 */
typedef struct Int128 Int128;
/*
* We guarantee that the in-memory byte representation of an
* Int128 is that of a host-endian-order 128-bit integer
* (whether using this struct or the __int128_t version of the type).
* Some code using this type relies on this (eg when copying it into
* guest memory or a gdb protocol buffer, or by using Int128 in
* a union with other integer types).
*/
struct Int128 {
#ifdef HOST_WORDS_BIGENDIAN
int64_t hi;
uint64_t lo;
#else
uint64_t lo;
int64_t hi;
#endif
};
static inline Int128 int128_make64(uint64_t a)
{
return (Int128) { a, 0 };
return (Int128) { .lo = a, .hi = 0 };
}
static inline Int128 int128_makes64(int64_t a)
{
return (Int128) { a, a >> 63 };
return (Int128) { .lo = a, .hi = a >> 63 };
}
static inline Int128 int128_make128(uint64_t lo, uint64_t hi)
{
return (Int128) { lo, hi };
return (Int128) { .lo = lo, .hi = hi };
}
static inline uint64_t int128_get64(Int128 a)
@ -210,22 +227,22 @@ static inline Int128 int128_one(void)
static inline Int128 int128_2_64(void)
{
return (Int128) { 0, 1 };
return int128_make128(0, 1);
}
static inline Int128 int128_exts64(int64_t a)
{
return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
return int128_make128(a, (a < 0) ? -1 : 0);
}
static inline Int128 int128_and(Int128 a, Int128 b)
{
return (Int128) { a.lo & b.lo, a.hi & b.hi };
return int128_make128(a.lo & b.lo, a.hi & b.hi);
}
static inline Int128 int128_or(Int128 a, Int128 b)
{
return (Int128) { a.lo | b.lo, a.hi | b.hi };
return int128_make128(a.lo | b.lo, a.hi | b.hi);
}
static inline Int128 int128_rshift(Int128 a, int n)
@ -337,5 +354,16 @@ static inline void int128_subfrom(Int128 *a, Int128 b)
*a = int128_sub(*a, b);
}
static inline Int128 bswap128(Int128 a)
{
return int128_make128(bswap64(a.hi), bswap64(a.lo));
}
#endif /* CONFIG_INT128 */
static inline void bswap128s(Int128 *s)
{
*s = bswap128(*s);
}
#endif /* INT128_H */

Binary file not shown.

@ -1 +1 @@
Subproject commit 3a6fdede6ce117facec0108afe716cf5d0472c3f
Subproject commit 820d43c0a7751e75a8830561f35535dfffd522bd

View File

@ -776,6 +776,8 @@
"POWER9 v2.0")
POWERPC_DEF("power10_v1.0", CPU_POWERPC_POWER10_DD1, POWER10,
"POWER10 v1.0")
POWERPC_DEF("power10_v2.0", CPU_POWERPC_POWER10_DD20, POWER10,
"POWER10 v2.0")
#endif /* defined (TARGET_PPC64) */
/***************************************************************************/
@ -952,7 +954,7 @@ PowerPCCPUAlias ppc_cpu_aliases[] = {
{ "power8", "power8_v2.0" },
{ "power8nvl", "power8nvl_v1.0" },
{ "power9", "power9_v2.0" },
{ "power10", "power10_v1.0" },
{ "power10", "power10_v2.0" },
#endif
/* Generic PowerPCs */

View File

@ -375,6 +375,7 @@ enum {
CPU_POWERPC_POWER9_DD20 = 0x004E1200,
CPU_POWERPC_POWER10_BASE = 0x00800000,
CPU_POWERPC_POWER10_DD1 = 0x00800100,
CPU_POWERPC_POWER10_DD20 = 0x00800200,
CPU_POWERPC_970_v22 = 0x00390202,
CPU_POWERPC_970FX_v10 = 0x00391100,
CPU_POWERPC_970FX_v20 = 0x003C0200,

View File

@ -67,34 +67,6 @@ uint32_t ppc_get_vscr(CPUPPCState *env)
return env->vscr | (sat << VSCR_SAT);
}
#ifdef CONFIG_SOFTMMU
void ppc_store_sdr1(CPUPPCState *env, target_ulong value)
{
PowerPCCPU *cpu = env_archcpu(env);
qemu_log_mask(CPU_LOG_MMU, "%s: " TARGET_FMT_lx "\n", __func__, value);
assert(!cpu->env.has_hv_mode || !cpu->vhyp);
#if defined(TARGET_PPC64)
if (mmu_is_64bit(env->mmu_model)) {
target_ulong sdr_mask = SDR_64_HTABORG | SDR_64_HTABSIZE;
target_ulong htabsize = value & SDR_64_HTABSIZE;
if (value & ~sdr_mask) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid bits 0x"TARGET_FMT_lx
" set in SDR1", value & ~sdr_mask);
value &= sdr_mask;
}
if (htabsize > 28) {
qemu_log_mask(LOG_GUEST_ERROR, "Invalid HTABSIZE 0x" TARGET_FMT_lx
" stored in SDR1", htabsize);
return;
}
}
#endif /* defined(TARGET_PPC64) */
/* FIXME: Should check for valid HTABMASK values in 32-bit case */
env->spr[SPR_SDR1] = value;
}
#endif /* CONFIG_SOFTMMU */
/* GDBstub can read and write MSR... */
void ppc_store_msr(CPUPPCState *env, target_ulong value)
{

View File

@ -1330,6 +1330,15 @@ void store_booke_tsr(CPUPPCState *env, target_ulong val);
void ppc_tlb_invalidate_all(CPUPPCState *env);
void ppc_tlb_invalidate_one(CPUPPCState *env, target_ulong addr);
void cpu_ppc_set_vhyp(PowerPCCPU *cpu, PPCVirtualHypervisor *vhyp);
int ppcmas_tlb_check(CPUPPCState *env, ppcmas_tlb_t *tlb,
hwaddr *raddrp, target_ulong address,
uint32_t pid);
int ppcemb_tlb_check(CPUPPCState *env, ppcemb_tlb_t *tlb,
hwaddr *raddrp,
target_ulong address, uint32_t pid, int ext,
int i);
hwaddr booke206_tlb_to_page_size(CPUPPCState *env,
ppcmas_tlb_t *tlb);
#endif
#endif

View File

@ -8269,6 +8269,9 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
LPCR_DEE | LPCR_OEE))
| LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE;
/* DD2 adds an extra HAIL bit */
pcc->lpcr_mask |= LPCR_HAIL;
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
pcc->mmu_model = POWERPC_MMU_3_00;
#if defined(CONFIG_SOFTMMU)

View File

@ -1211,12 +1211,6 @@ void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
cs = env_cpu(env);
cs->halted = 1;
/*
* The architecture specifies that HDEC interrupts are discarded
* in PM states
*/
env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
/* Condition for waking up at 0x100 */
env->resume_as_sreset = (insn != PPC_PM_STOP) ||
(env->spr[SPR_PSSCR] & PSSCR_EC);

View File

@ -101,6 +101,8 @@ void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
bswap32s((uint32_t *)mem_buf);
} else if (len == 8) {
bswap64s((uint64_t *)mem_buf);
} else if (len == 16) {
bswap128s((Int128 *)mem_buf);
} else {
g_assert_not_reached();
}
@ -389,15 +391,6 @@ const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name)
}
#endif
static bool avr_need_swap(CPUPPCState *env)
{
#ifdef HOST_WORDS_BIGENDIAN
return msr_le;
#else
return !msr_le;
#endif
}
#if !defined(CONFIG_USER_ONLY)
static int gdb_find_spr_idx(CPUPPCState *env, int n)
{
@ -486,14 +479,9 @@ static int gdb_get_avr_reg(CPUPPCState *env, GByteArray *buf, int n)
if (n < 32) {
ppc_avr_t *avr = cpu_avr_ptr(env, n);
if (!avr_need_swap(env)) {
gdb_get_reg128(buf, avr->u64[0] , avr->u64[1]);
} else {
gdb_get_reg128(buf, avr->u64[1] , avr->u64[0]);
}
gdb_get_reg128(buf, avr->VsrD(0), avr->VsrD(1));
mem_buf = gdb_get_reg_ptr(buf, 16);
ppc_maybe_bswap_register(env, mem_buf, 8);
ppc_maybe_bswap_register(env, mem_buf + 8, 8);
ppc_maybe_bswap_register(env, mem_buf, 16);
return 16;
}
if (n == 32) {
@ -515,15 +503,9 @@ static int gdb_set_avr_reg(CPUPPCState *env, uint8_t *mem_buf, int n)
{
if (n < 32) {
ppc_avr_t *avr = cpu_avr_ptr(env, n);
ppc_maybe_bswap_register(env, mem_buf, 8);
ppc_maybe_bswap_register(env, mem_buf + 8, 8);
if (!avr_need_swap(env)) {
avr->u64[0] = ldq_p(mem_buf);
avr->u64[1] = ldq_p(mem_buf + 8);
} else {
avr->u64[1] = ldq_p(mem_buf);
avr->u64[0] = ldq_p(mem_buf + 8);
}
ppc_maybe_bswap_register(env, mem_buf, 16);
avr->VsrD(0) = ldq_p(mem_buf);
avr->VsrD(1) = ldq_p(mem_buf + 8);
return 16;
}
if (n == 32) {

View File

@ -258,6 +258,18 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
return excp;
}
#ifdef CONFIG_SOFTMMU
void store_40x_sler(CPUPPCState *env, uint32_t val)
{
/* XXX: TO BE FIXED */
if (val != 0x00000000) {
cpu_abort(env_cpu(env),
"Little-endian regions are not supported by now\n");
}
env->spr[SPR_405_SLER] = val;
}
#endif /* CONFIG_SOFTMMU */
#ifndef CONFIG_USER_ONLY
void check_tlb_flush(CPUPPCState *env, bool global)
{

View File

@ -1492,34 +1492,16 @@ void helper_vlogefp(CPUPPCState *env, ppc_avr_t *r, ppc_avr_t *b)
}
}
#if defined(HOST_WORDS_BIGENDIAN)
#define VEXTU_X_DO(name, size, left) \
target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b) \
{ \
int index; \
if (left) { \
index = (a & 0xf) * 8; \
} else { \
index = ((15 - (a & 0xf) + 1) * 8) - size; \
} \
return int128_getlo(int128_rshift(b->s128, index)) & \
MAKE_64BIT_MASK(0, size); \
}
#else
#define VEXTU_X_DO(name, size, left) \
target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b) \
{ \
int index; \
if (left) { \
index = ((15 - (a & 0xf) + 1) * 8) - size; \
} else { \
index = (a & 0xf) * 8; \
} \
return int128_getlo(int128_rshift(b->s128, index)) & \
MAKE_64BIT_MASK(0, size); \
}
#endif
#define VEXTU_X_DO(name, size, left) \
target_ulong glue(helper_, name)(target_ulong a, ppc_avr_t *b) \
{ \
int index = (a & 0xf) * 8; \
if (left) { \
index = 128 - index - size; \
} \
return int128_getlo(int128_rshift(b->s128, index)) & \
MAKE_64BIT_MASK(0, size); \
}
VEXTU_X_DO(vextublx, 8, 1)
VEXTU_X_DO(vextuhlx, 16, 1)
VEXTU_X_DO(vextuwlx, 32, 1)

View File

@ -245,4 +245,43 @@ static inline int prot_for_access_type(MMUAccessType access_type)
g_assert_not_reached();
}
/* PowerPC MMU emulation */
typedef struct mmu_ctx_t mmu_ctx_t;
bool ppc_xlate(PowerPCCPU *cpu, vaddr eaddr, MMUAccessType access_type,
hwaddr *raddrp, int *psizep, int *protp,
int mmu_idx, bool guest_visible);
int get_physical_address_wtlb(CPUPPCState *env, mmu_ctx_t *ctx,
target_ulong eaddr,
MMUAccessType access_type, int type,
int mmu_idx);
/* Software driven TLB helpers */
int ppc6xx_tlb_getnum(CPUPPCState *env, target_ulong eaddr,
int way, int is_code);
/* Context used internally during MMU translations */
struct mmu_ctx_t {
hwaddr raddr; /* Real address */
hwaddr eaddr; /* Effective address */
int prot; /* Protection bits */
hwaddr hash[2]; /* Pagetable hash values */
target_ulong ptem; /* Virtual segment ID | API */
int key; /* Access key */
int nx; /* Non-execute area */
};
/* Common routines used by software and hardware TLBs emulation */
static inline int pte_is_valid(target_ulong pte0)
{
return pte0 & 0x80000000 ? 1 : 0;
}
static inline void pte_invalidate(target_ulong *pte0)
{
*pte0 &= ~0x80000000;
}
#define PTE_PTEM_MASK 0x7FFFFFBF
#define PTE_CHECK_MASK (TARGET_PAGE_MASK | 0x7B)
#endif /* PPC_INTERNAL_H */

View File

@ -37,11 +37,13 @@ ppc_softmmu_ss.add(files(
'arch_dump.c',
'machine.c',
'mmu-hash32.c',
'mmu_helper.c',
'mmu_common.c',
'monitor.c',
))
ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_false: files(
'tcg-stub.c'
ppc_softmmu_ss.add(when: 'CONFIG_TCG', if_true: files(
'mmu_helper.c',
), if_false: files(
'tcg-stub.c',
))
ppc_softmmu_ss.add(when: 'TARGET_PPC64', if_true: files(

1620
target/ppc/mmu_common.c Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff