* PAPR nested hypervisor host implementation for spapr TCG

* excp_helper.c code cleanups and improvements
 * Move more ops to decodetree
 * Deprecate pseries-2.12 machines and P9 and P10 DD1.0 CPUs
 * Document running Linux on AmigaNG
 * Update dt feature advertising POWER CPUs.
 * Add P10 PMU SPRs
 * Improve pnv topology calculation for SMT8 CPUs.
 * Various bug fixes.
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmXwiT8ACgkQZ7MCdqhi
 HK7C/w//XxEO2bQTFPLFDTrP/voq7pcX8XeQNVyXCkXYjvsbu05oQow50k+Y5UAE
 US4MFjt8jFz0vuIKuKyoA3kG41zDSOzoX4TQXMM+tyTWbuFF3KAyfizb1xE6SYAN
 xJEGvmiXv/EgoSBD7BTKQp1tMPdIGZLwSdYiA0lmOo7YaMCgYAXaujW5hnNjQecT
 873sN+10pHtQY++mINtD9Nfb6AcDGMWw0b+bykqIXhNRkI8IGOS4WF4vAuMBrwfe
 UM00wDnNRb86Dk14bv2XVNDr6/i0VRtUMwM4yiptrQ1TQx18LZaPSQFYjQfPaan7
 LwN4QkMFnBX54yJ7Npvjvu8BCBF47kwOVu4CIAFJ4sIm0WfTmozDpPttwcZ5w7Ve
 iXDOB9ECAB4pQ2rCgbSNG8MYUZgoHHOuThqolOP0Vh9NHRRJxpdw6CyAbmCGftc0
 lvRDPFiKp8xmCNJ/j3XzoUdHoG7NMwpUmHv9ruGU18SdQ8hyJN9AcQGWYrB4v0RV
 /hs2RAbwntG7ahkcwd8uy5aFw88Wph/uGXPXc49EWj7i49vHeIV2y5+gtthMywje
 qqjFXkistXuF+JHVnyoYmqqCyXaHX5CEwtawMv4EQeaJs76bLhMeMTKKl9rRp8qB
 DtbIZphO8iMsocrBnje48sA5HR0PM+H4HTjw10i8R0fLlWitaIY=
 =XnY5
 -----END PGP SIGNATURE-----

Merge tag 'pull-ppc-for-9.0-2-20240313' of https://gitlab.com/npiggin/qemu into staging

* PAPR nested hypervisor host implementation for spapr TCG
* excp_helper.c code cleanups and improvements
* Move more ops to decodetree
* Deprecate pseries-2.12 machines and P9 and P10 DD1.0 CPUs
* Document running Linux on AmigaNG
* Update dt feature advertising POWER CPUs.
* Add P10 PMU SPRs
* Improve pnv topology calculation for SMT8 CPUs.
* Various bug fixes.

# -----BEGIN PGP SIGNATURE-----
#
# iQIzBAABCgAdFiEETkN92lZhb0MpsKeVZ7MCdqhiHK4FAmXwiT8ACgkQZ7MCdqhi
# HK7C/w//XxEO2bQTFPLFDTrP/voq7pcX8XeQNVyXCkXYjvsbu05oQow50k+Y5UAE
# US4MFjt8jFz0vuIKuKyoA3kG41zDSOzoX4TQXMM+tyTWbuFF3KAyfizb1xE6SYAN
# xJEGvmiXv/EgoSBD7BTKQp1tMPdIGZLwSdYiA0lmOo7YaMCgYAXaujW5hnNjQecT
# 873sN+10pHtQY++mINtD9Nfb6AcDGMWw0b+bykqIXhNRkI8IGOS4WF4vAuMBrwfe
# UM00wDnNRb86Dk14bv2XVNDr6/i0VRtUMwM4yiptrQ1TQx18LZaPSQFYjQfPaan7
# LwN4QkMFnBX54yJ7Npvjvu8BCBF47kwOVu4CIAFJ4sIm0WfTmozDpPttwcZ5w7Ve
# iXDOB9ECAB4pQ2rCgbSNG8MYUZgoHHOuThqolOP0Vh9NHRRJxpdw6CyAbmCGftc0
# lvRDPFiKp8xmCNJ/j3XzoUdHoG7NMwpUmHv9ruGU18SdQ8hyJN9AcQGWYrB4v0RV
# /hs2RAbwntG7ahkcwd8uy5aFw88Wph/uGXPXc49EWj7i49vHeIV2y5+gtthMywje
# qqjFXkistXuF+JHVnyoYmqqCyXaHX5CEwtawMv4EQeaJs76bLhMeMTKKl9rRp8qB
# DtbIZphO8iMsocrBnje48sA5HR0PM+H4HTjw10i8R0fLlWitaIY=
# =XnY5
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 12 Mar 2024 16:56:31 GMT
# gpg:                using RSA key 4E437DDA56616F4329B0A79567B30276A8621CAE
# gpg: Good signature from "Nicholas Piggin <npiggin@gmail.com>" [unknown]
# gpg: WARNING: This key is not certified with a trusted signature!
# gpg:          There is no indication that the signature belongs to the owner.
# Primary key fingerprint: 4E43 7DDA 5661 6F43 29B0  A795 67B3 0276 A862 1CAE

* tag 'pull-ppc-for-9.0-2-20240313' of https://gitlab.com/npiggin/qemu: (38 commits)
  spapr: nested: Introduce cap-nested-papr for Nested PAPR API
  spapr: nested: Introduce H_GUEST_RUN_VCPU hcall.
  spapr: nested: Use correct source for parttbl info for nested PAPR API.
  spapr: nested: Introduce H_GUEST_[GET|SET]_STATE hcalls.
  spapr: nested: Initialize the GSB elements lookup table.
  spapr: nested: Extend nested_ppc_state for nested PAPR API
  spapr: nested: Introduce H_GUEST_CREATE_VCPU hcall.
  spapr: nested: Introduce H_GUEST_[CREATE|DELETE] hcalls.
  spapr: nested: Introduce H_GUEST_[GET|SET]_CAPABILITIES hcalls.
  spapr: nested: Document Nested PAPR API
  spapr: nested: keep nested-hv related code restricted to its API.
  spapr: nested: Introduce SpaprMachineStateNested to store related info.
  spapr: nested: move nested part of spapr_get_pate into spapr_nested.c
  spapr: nested: register nested-hv api hcalls only for cap-nested-hv
  target/ppc: Remove interrupt handler wrapper functions
  target/ppc: Clean up ifdefs in excp_helper.c, part 3
  target/ppc: Clean up ifdefs in excp_helper.c, part 2
  target/ppc: Clean up ifdefs in excp_helper.c, part 1
  target/ppc: Add gen_exception_err_nip() function
  target/ppc: Readability improvements in exception handlers
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
master
Peter Maydell 2024-03-13 12:37:27 +00:00
commit 51e31f2140
28 changed files with 2883 additions and 563 deletions

View File

@ -316,7 +316,6 @@ F: tests/tcg/openrisc/
PowerPC TCG CPUs
M: Nicholas Piggin <npiggin@gmail.com>
M: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: target/ppc/
@ -468,7 +467,6 @@ F: target/mips/sysemu/
PPC KVM CPUs
M: Nicholas Piggin <npiggin@gmail.com>
R: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
S: Odd Fixes
F: target/ppc/kvm.c
@ -1508,7 +1506,6 @@ F: tests/avocado/ppc_prep_40p.py
sPAPR (pseries)
M: Nicholas Piggin <npiggin@gmail.com>
R: Daniel Henrique Barboza <danielhb413@gmail.com>
R: Cédric Le Goater <clg@kaod.org>
R: David Gibson <david@gibson.dropbear.id.au>
R: Harsh Prateek Bora <harshpb@linux.ibm.com>
L: qemu-ppc@nongnu.org
@ -1575,6 +1572,7 @@ F: hw/rtc/m41t80.c
F: pc-bios/canyonlands.dt[sb]
F: pc-bios/u-boot-sam460ex-20100605.bin
F: roms/u-boot-sam460ex
F: docs/system/ppc/amigang.rst
pegasos2
M: BALATON Zoltan <balaton@eik.bme.hu>

View File

@ -237,13 +237,13 @@ The Nios II architecture is orphan.
The machine is no longer in existence and has been long unmaintained
in QEMU. This also holds for the TC51828 16MiB flash that it uses.
``pseries-2.1`` up to ``pseries-2.11`` (since 9.0)
``pseries-2.1`` up to ``pseries-2.12`` (since 9.0)
''''''''''''''''''''''''''''''''''''''''''''''''''
Older pseries machines before version 2.12 have undergone many changes
Older pseries machines before version 3.0 have undergone many changes
to correct issues, mostly regarding migration compatibility. These are
no longer maintained and removing them will make the code easier to
read and maintain. Use versions 2.12 and above as a replacement.
read and maintain. Use versions 3.0 and above as a replacement.
Arm machines ``akita``, ``borzoi``, ``cheetah``, ``connex``, ``mainstone``, ``n800``, ``n810``, ``spitz``, ``terrier``, ``tosa``, ``verdex``, ``z2`` (since 9.0)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

119
docs/devel/nested-papr.txt Normal file
View File

@ -0,0 +1,119 @@
Nested PAPR API (aka KVM on PowerVM)
====================================
This API aims at providing support to enable nested virtualization with
KVM on PowerVM. While the existing support for nested KVM on PowerNV was
introduced with cap-nested-hv option, however, with a slight design change,
to enable this on papr/pseries, a new cap-nested-papr option is added. eg:
qemu-system-ppc64 -cpu POWER10 -machine pseries,cap-nested-papr=true ...
Work by:
Michael Neuling <mikey@neuling.org>
Vaibhav Jain <vaibhav@linux.ibm.com>
Jordan Niethe <jniethe5@gmail.com>
Harsh Prateek Bora <harshpb@linux.ibm.com>
Shivaprasad G Bhat <sbhat@linux.ibm.com>
Kautuk Consul <kconsul@linux.vnet.ibm.com>
Below taken from the kernel documentation:
Introduction
============
This document explains how a guest operating system can act as a
hypervisor and run nested guests through the use of hypercalls, if the
hypervisor has implemented them. The terms L0, L1, and L2 are used to
refer to different software entities. L0 is the hypervisor mode entity
that would normally be called the "host" or "hypervisor". L1 is a
guest virtual machine that is directly run under L0 and is initiated
and controlled by L0. L2 is a guest virtual machine that is initiated
and controlled by L1 acting as a hypervisor. A significant design change
wrt existing API is that now the entire L2 state is maintained within L0.
Existing Nested-HV API
======================
Linux/KVM has had support for Nesting as an L0 or L1 since 2018
The L0 code was added::
commit 8e3f5fc1045dc49fd175b978c5457f5f51e7a2ce
Author: Paul Mackerras <paulus@ozlabs.org>
Date: Mon Oct 8 16:31:03 2018 +1100
KVM: PPC: Book3S HV: Framework and hcall stubs for nested virtualization
The L1 code was added::
commit 360cae313702cdd0b90f82c261a8302fecef030a
Author: Paul Mackerras <paulus@ozlabs.org>
Date: Mon Oct 8 16:31:04 2018 +1100
KVM: PPC: Book3S HV: Nested guest entry via hypercall
This API works primarily using a signal hcall h_enter_nested(). This
call made by the L1 to tell the L0 to start an L2 vCPU with the given
state. The L0 then starts this L2 and runs until an L2 exit condition
is reached. Once the L2 exits, the state of the L2 is given back to
the L1 by the L0. The full L2 vCPU state is always transferred from
and to L1 when the L2 is run. The L0 doesn't keep any state on the L2
vCPU (except in the short sequence in the L0 on L1 -> L2 entry and L2
-> L1 exit).
The only state kept by the L0 is the partition table. The L1 registers
it's partition table using the h_set_partition_table() hcall. All
other state held by the L0 about the L2s is cached state (such as
shadow page tables).
The L1 may run any L2 or vCPU without first informing the L0. It
simply starts the vCPU using h_enter_nested(). The creation of L2s and
vCPUs is done implicitly whenever h_enter_nested() is called.
In this document, we call this existing API the v1 API.
New PAPR API
===============
The new PAPR API changes from the v1 API such that the creating L2 and
associated vCPUs is explicit. In this document, we call this the v2
API.
h_enter_nested() is replaced with H_GUEST_VCPU_RUN(). Before this can
be called the L1 must explicitly create the L2 using h_guest_create()
and any associated vCPUs() created with h_guest_create_vCPU(). Getting
and setting vCPU state can also be performed using h_guest_{g|s}et
hcall.
The basic execution flow is for an L1 to create an L2, run it, and
delete it is:
- L1 and L0 negotiate capabilities with H_GUEST_{G,S}ET_CAPABILITIES()
(normally at L1 boot time).
- L1 requests the L0 to create an L2 with H_GUEST_CREATE() and receives a token
- L1 requests the L0 to create an L2 vCPU with H_GUEST_CREATE_VCPU()
- L1 and L0 communicate the vCPU state using the H_GUEST_{G,S}ET() hcall
- L1 requests the L0 to run the vCPU using H_GUEST_RUN_VCPU() hcall
- L1 deletes L2 with H_GUEST_DELETE()
For more details, please refer:
[1] Linux Kernel documentation (upstream documentation commit):
commit 476652297f94a2e5e5ef29e734b0da37ade94110
Author: Michael Neuling <mikey@neuling.org>
Date: Thu Sep 14 13:06:00 2023 +1000
docs: powerpc: Document nested KVM on POWER
Document support for nested KVM on POWER using the existing API as well
as the new PAPR API. This includes the new HCALL interface and how it
used by KVM.
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Link: https://msgid.link/20230914030600.16993-12-jniethe5@gmail.com

161
docs/system/ppc/amigang.rst Normal file
View File

@ -0,0 +1,161 @@
=========================================================
AmigaNG boards (``amigaone``, ``pegasos2``, ``sam460ex``)
=========================================================
These PowerPC machines emulate boards that are primarily used for
running Amiga like OSes (AmigaOS 4, MorphOS and AROS) but these can
also run Linux which is what this section documents.
Eyetech AmigaOne/Mai Logic Teron (``amigaone``)
===============================================
The ``amigaone`` machine emulates an AmigaOne XE mainboard by Eyetech
which is a rebranded Mai Logic Teron board with modified U-Boot
firmware to support AmigaOS 4.
Emulated devices
----------------
* PowerPC 7457 CPU (can also use``-cpu g3, 750cxe, 750fx`` or ``750gx``)
* Articia S north bridge
* VIA VT82C686B south bridge
* PCI VGA compatible card (guests may need other card instead)
* PS/2 keyboard and mouse
Firmware
--------
A firmware binary is necessary for the boot process. It is a modified
U-Boot under GPL but its source is lost so it cannot be included in
QEMU. A binary is available at
https://www.hyperion-entertainment.com/index.php/downloads?view=files&parent=28.
The ROM image is in the last 512kB which can be extracted with the
following command:
.. code-block:: bash
$ tail -c 524288 updater.image > u-boot-amigaone.bin
The BIOS emulator in the firmware is unable to run QEMUs standard
vgabios so ``VGABIOS-lgpl-latest.bin`` is needed instead which can be
downloaded from http://www.nongnu.org/vgabios.
Running Linux
-------------
There are some Linux images under the following link that work on the
``amigaone`` machine:
https://sourceforge.net/projects/amigaone-linux/files/debian-installer/.
To boot the system run:
.. code-block:: bash
$ qemu-system-ppc -machine amigaone -bios u-boot-amigaone.bin \
-cdrom "A1 Linux Net Installer.iso" \
-device ati-vga,model=rv100,romfile=VGABIOS-lgpl-latest.bin
From the firmware menu that appears select ``Boot sequence``
``Amiga Multiboot Options`` and set ``Boot device 1`` to
``Onboard VIA IDE CDROM``. Then hit escape until the main screen appears again,
hit escape once more and from the exit menu that appears select either
``Save settings and exit`` or ``Use settings for this session only``. It may
take a long time loading the kernel into memory but eventually it boots and the
installer becomes visible. The ``ati-vga`` RV100 emulation is not
complete yet so only frame buffer works, DRM and 3D is not available.
Genesi/bPlan Pegasos II (``pegasos2``)
======================================
The ``pegasos2`` machine emulates the Pegasos II sold by Genesi and
designed by bPlan. Its schematics are available at
https://www.powerdeveloper.org/platforms/pegasos/schematics.
Emulated devices
----------------
* PowerPC 7457 CPU (can also use``-cpu g3`` or ``750cxe``)
* Marvell MV64361 Discovery II north bridge
* VIA VT8231 south bridge
* PCI VGA compatible card (guests may need other card instead)
* PS/2 keyboard and mouse
Firmware
--------
The Pegasos II board has an Open Firmware compliant ROM based on
SmartFirmware with some changes that are not open-sourced therefore
the ROM binary cannot be included in QEMU. An updater was available
from bPlan, it can be found in the `Internet Archive
<http://web.archive.org/web/20071021223056/http://www.bplan-gmbh.de/up050404/up050404>`_.
The ROM image can be extracted from it with the following command:
.. code-block:: bash
$ tail -c +85581 up050404 | head -c 524288 > pegasos2.rom
Running Linux
-------------
The PowerPC version of Debian 8.11 supported Pegasos II. The BIOS
emulator in the firmware binary is unable to run QEMUs standard
vgabios so it needs to be disabled. To boot the system run:
.. code-block:: bash
$ qemu-system-ppc -machine pegasos2 -bios pegasos2.rom \
-cdrom debian-8.11.0-powerpc-netinst.iso \
-device VGA,romfile="" -serial stdio
At the firmware ``ok`` prompt enter ``boot cd install/pegasos``.
Alternatively, it is possible to boot the kernel directly without
firmware ROM using the QEMU built-in minimal Virtual Open Firmware
(VOF) emulation which is also supported on ``pegasos2``. For this,
extract the kernel ``install/powerpc/vmlinuz-chrp.initrd`` from the CD
image, then run:
.. code-block:: bash
$ qemu-system-ppc -machine pegasos2 -serial stdio \
-kernel vmlinuz-chrp.initrd -append "---" \
-cdrom debian-8.11.0-powerpc-netinst.iso
aCube Sam460ex (``sam460ex``)
=============================
The ``sam460ex`` machine emulates the Sam460ex board by aCube which is
based on the AMCC PowerPC 460EX SoC (that despite its name has a
PPC440 CPU core).
Firmware
--------
The board has a firmware based on an older U-Boot version with
modifications to support booting AmigaOS 4. The firmware ROM is
included with QEMU.
Emulated devices
----------------
* PowerPC 460EX SoC
* M41T80 serial RTC chip
* Silicon Motion SM501 display parts (identical to SM502 on real board)
* Silicon Image SiI3112 2 port SATA controller
* USB keyboard and mouse
Running Linux
-------------
The only Linux distro that supported Sam460ex out of box was CruxPPC
2.x. It can be booted by running:
.. code-block:: bash
$ qemu-system-ppc -machine sam460ex -serial stdio \
-drive if=none,id=cd,format=raw,file=crux-ppc-2.7a.iso \
-device ide-cd,drive=cd,bus=ide.1
There are some other kernels and instructions for booting other
distros on aCube's product page at
https://www.acube-systems.biz/index.php?page=hardware&pid=5
but those are untested.

View File

@ -17,6 +17,7 @@ help``.
.. toctree::
:maxdepth: 1
ppc/amigang
ppc/embedded
ppc/powermac
ppc/powernv

View File

@ -133,7 +133,7 @@ static int get_cpus_node(void *fdt)
* device tree, used in XSCOM to address cores and in interrupt
* servers.
*/
static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
static int pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
{
PowerPCCPU *cpu = pc->threads[0];
CPUState *cs = CPU(cpu);
@ -141,32 +141,31 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
int smt_threads = CPU_CORE(pc)->nr_threads;
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
PnvChipClass *pnv_cc = PNV_CHIP_GET_CLASS(chip);
g_autofree uint32_t *servers_prop = g_new(uint32_t, smt_threads);
int i;
uint32_t pir;
uint32_t segs[] = {cpu_to_be32(28), cpu_to_be32(40),
0xffffffff, 0xffffffff};
uint32_t tbfreq = PNV_TIMEBASE_FREQ;
uint32_t cpufreq = 1000000000;
uint32_t page_sizes_prop[64];
size_t page_sizes_prop_size;
const uint8_t pa_features[] = { 24, 0,
0xf6, 0x3f, 0xc7, 0xc0, 0x80, 0xf0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
int offset;
char *nodename;
int cpus_offset = get_cpus_node(fdt);
nodename = g_strdup_printf("%s@%x", dc->fw_name, pc->pir);
pir = pnv_cc->chip_pir(chip, pc->hwid, 0);
nodename = g_strdup_printf("%s@%x", dc->fw_name, pir);
offset = fdt_add_subnode(fdt, cpus_offset, nodename);
_FDT(offset);
g_free(nodename);
_FDT((fdt_setprop_cell(fdt, offset, "ibm,chip-id", chip->chip_id)));
_FDT((fdt_setprop_cell(fdt, offset, "reg", pc->pir)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pc->pir)));
_FDT((fdt_setprop_cell(fdt, offset, "reg", pir)));
_FDT((fdt_setprop_cell(fdt, offset, "ibm,pir", pir)));
_FDT((fdt_setprop_string(fdt, offset, "device_type", "cpu")));
_FDT((fdt_setprop_cell(fdt, offset, "cpu-version", env->spr[SPR_PVR])));
@ -236,20 +235,21 @@ static void pnv_dt_core(PnvChip *chip, PnvCore *pc, void *fdt)
page_sizes_prop, page_sizes_prop_size)));
}
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
pa_features, sizeof(pa_features))));
/* Build interrupt servers properties */
for (i = 0; i < smt_threads; i++) {
servers_prop[i] = cpu_to_be32(pc->pir + i);
servers_prop[i] = cpu_to_be32(pnv_cc->chip_pir(chip, pc->hwid, i));
}
_FDT((fdt_setprop(fdt, offset, "ibm,ppc-interrupt-server#s",
servers_prop, sizeof(*servers_prop) * smt_threads)));
return offset;
}
static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t hwid,
uint32_t nr_threads)
{
PnvChipClass *pcc = PNV_CHIP_GET_CLASS(chip);
uint32_t pir = pcc->chip_pir(chip, hwid, 0);
uint64_t addr = PNV_ICP_BASE(chip) | (pir << 12);
char *name;
const char compat[] = "IBM,power8-icp\0IBM,ppc-xicp";
@ -263,6 +263,7 @@ static void pnv_dt_icp(PnvChip *chip, void *fdt, uint32_t pir,
rsize = sizeof(uint64_t) * 2 * nr_threads;
reg = g_malloc(rsize);
for (i = 0; i < nr_threads; i++) {
/* We know P8 PIR is linear with thread id */
reg[i * 2] = cpu_to_be64(addr | ((pir + i) * 0x1000));
reg[i * 2 + 1] = cpu_to_be64(0x1000);
}
@ -299,6 +300,17 @@ PnvChip *pnv_chip_add_phb(PnvChip *chip, PnvPHB *phb)
return chip;
}
/*
* Same as spapr pa_features_207 except pnv always enables CI largepages bit.
* HTM is always enabled because TCG does implement HTM, it's just a
* degenerate implementation.
*/
static const uint8_t pa_features_207[] = { 24, 0,
0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x80, 0x00 };
static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
{
static const char compat[] = "ibm,power8-xscom\0ibm,xscom";
@ -311,11 +323,15 @@ static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
for (i = 0; i < chip->nr_cores; i++) {
PnvCore *pnv_core = chip->cores[i];
int offset;
pnv_dt_core(chip, pnv_core, fdt);
offset = pnv_dt_core(chip, pnv_core, fdt);
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
pa_features_207, sizeof(pa_features_207))));
/* Interrupt Control Presenters (ICP). One per core. */
pnv_dt_icp(chip, fdt, pnv_core->pir, CPU_CORE(pnv_core)->nr_threads);
pnv_dt_icp(chip, fdt, pnv_core->hwid, CPU_CORE(pnv_core)->nr_threads);
}
if (chip->ram_size) {
@ -323,6 +339,35 @@ static void pnv_chip_power8_dt_populate(PnvChip *chip, void *fdt)
}
}
/*
* Same as spapr pa_features_300 except pnv always enables CI largepages bit.
*/
static const uint8_t pa_features_300[] = { 66, 0,
/* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
/* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
/* 6: DS207 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
/* 16: Vector */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
/* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 18 - 23 */
/* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
/* 32: LE atomic, 34: EBB + ext EBB */
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
/* 40: Radix MMU */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
/* 42: PM, 44: PC RA, 46: SC vec'd */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
/* 48: SIMD, 50: QP BFP, 52: String */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
/* 54: DecFP, 56: DecI, 58: SHA */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
/* 60: NM atomic, 62: RNG */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
};
static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
{
static const char compat[] = "ibm,power9-xscom\0ibm,xscom";
@ -335,8 +380,12 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
for (i = 0; i < chip->nr_cores; i++) {
PnvCore *pnv_core = chip->cores[i];
int offset;
pnv_dt_core(chip, pnv_core, fdt);
offset = pnv_dt_core(chip, pnv_core, fdt);
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
pa_features_300, sizeof(pa_features_300))));
}
if (chip->ram_size) {
@ -346,6 +395,40 @@ static void pnv_chip_power9_dt_populate(PnvChip *chip, void *fdt)
pnv_dt_lpc(chip, fdt, 0, PNV9_LPCM_BASE(chip), PNV9_LPCM_SIZE);
}
/*
* Same as spapr pa_features_31 except pnv always enables CI largepages bit,
* always disables copy/paste.
*/
static const uint8_t pa_features_31[] = { 74, 0,
/* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: CILRG|fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
/* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
0xf6, 0x3f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
/* 6: DS207 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
/* 16: Vector */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
/* 18: Vec. Scalar, 20: Vec. XOR */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
/* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
/* 32: LE atomic, 34: EBB + ext EBB */
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
/* 40: Radix MMU */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
/* 42: PM, 44: PC RA, 46: SC vec'd */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
/* 48: SIMD, 50: QP BFP, 52: String */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
/* 54: DecFP, 56: DecI, 58: SHA */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
/* 60: NM atomic, 62: RNG */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
/* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
/* 72: [P]HASHST/[P]HASHCHK */
0x80, 0x00, /* 72 - 73 */
};
static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
{
static const char compat[] = "ibm,power10-xscom\0ibm,xscom";
@ -358,8 +441,12 @@ static void pnv_chip_power10_dt_populate(PnvChip *chip, void *fdt)
for (i = 0; i < chip->nr_cores; i++) {
PnvCore *pnv_core = chip->cores[i];
int offset;
pnv_dt_core(chip, pnv_core, fdt);
offset = pnv_dt_core(chip, pnv_core, fdt);
_FDT((fdt_setprop(fdt, offset, "ibm,pa-features",
pa_features_31, sizeof(pa_features_31))));
}
if (chip->ram_size) {
@ -995,9 +1082,10 @@ static void pnv_init(MachineState *machine)
* 25:28 Core number
* 29:31 Thread ID
*/
static uint32_t pnv_chip_core_pir_p8(PnvChip *chip, uint32_t core_id)
static uint32_t pnv_chip_pir_p8(PnvChip *chip, uint32_t core_id,
uint32_t thread_id)
{
return (chip->chip_id << 7) | (core_id << 3);
return (chip->chip_id << 7) | (core_id << 3) | thread_id;
}
static void pnv_chip_power8_intc_create(PnvChip *chip, PowerPCCPU *cpu,
@ -1049,14 +1137,37 @@ static void pnv_chip_power8_intc_print_info(PnvChip *chip, PowerPCCPU *cpu,
*
* We only care about the lower bits. uint32_t is fine for the moment.
*/
static uint32_t pnv_chip_core_pir_p9(PnvChip *chip, uint32_t core_id)
static uint32_t pnv_chip_pir_p9(PnvChip *chip, uint32_t core_id,
uint32_t thread_id)
{
return (chip->chip_id << 8) | (core_id << 2);
if (chip->nr_threads == 8) {
return (chip->chip_id << 8) | ((thread_id & 1) << 2) | (core_id << 3) |
(thread_id >> 1);
} else {
return (chip->chip_id << 8) | (core_id << 2) | thread_id;
}
}
static uint32_t pnv_chip_core_pir_p10(PnvChip *chip, uint32_t core_id)
/*
* 0:48 Reserved - Read as zeroes
* 49:52 Node ID
* 53:55 Chip ID
* 56 Reserved - Read as zero
* 57:59 Quad ID
* 60 Core Chiplet Pair ID
* 61:63 Thread/Core Chiplet ID t0-t2
*
* We only care about the lower bits. uint32_t is fine for the moment.
*/
static uint32_t pnv_chip_pir_p10(PnvChip *chip, uint32_t core_id,
uint32_t thread_id)
{
return (chip->chip_id << 8) | (core_id << 2);
if (chip->nr_threads == 8) {
return (chip->chip_id << 8) | ((core_id / 4) << 4) |
((core_id % 2) << 3) | thread_id;
} else {
return (chip->chip_id << 8) | (core_id << 2) | thread_id;
}
}
static void pnv_chip_power9_intc_create(PnvChip *chip, PowerPCCPU *cpu,
@ -1235,7 +1346,7 @@ static void pnv_chip_icp_realize(Pnv8Chip *chip8, Error **errp)
int core_hwid = CPU_CORE(pnv_core)->core_id;
for (j = 0; j < CPU_CORE(pnv_core)->nr_threads; j++) {
uint32_t pir = pcc->core_pir(chip, core_hwid) + j;
uint32_t pir = pcc->chip_pir(chip, core_hwid, j);
PnvICPState *icp = PNV_ICP(xics_icp_get(chip8->xics, pir));
memory_region_add_subregion(&chip8->icp_mmio, pir << 12,
@ -1348,7 +1459,7 @@ static void pnv_chip_power8e_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x221ef04980000000ull; /* P8 Murano DD2.1 */
k->cores_mask = POWER8E_CORE_MASK;
k->num_phbs = 3;
k->core_pir = pnv_chip_core_pir_p8;
k->chip_pir = pnv_chip_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->intc_destroy = pnv_chip_power8_intc_destroy;
@ -1372,7 +1483,7 @@ static void pnv_chip_power8_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x220ea04980000000ull; /* P8 Venice DD2.0 */
k->cores_mask = POWER8_CORE_MASK;
k->num_phbs = 3;
k->core_pir = pnv_chip_core_pir_p8;
k->chip_pir = pnv_chip_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->intc_destroy = pnv_chip_power8_intc_destroy;
@ -1396,7 +1507,7 @@ static void pnv_chip_power8nvl_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x120d304980000000ull; /* P8 Naples DD1.0 */
k->cores_mask = POWER8_CORE_MASK;
k->num_phbs = 4;
k->core_pir = pnv_chip_core_pir_p8;
k->chip_pir = pnv_chip_pir_p8;
k->intc_create = pnv_chip_power8_intc_create;
k->intc_reset = pnv_chip_power8_intc_reset;
k->intc_destroy = pnv_chip_power8_intc_destroy;
@ -1669,7 +1780,7 @@ static void pnv_chip_power9_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x220d104900008000ull; /* P9 Nimbus DD2.0 */
k->cores_mask = POWER9_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p9;
k->chip_pir = pnv_chip_pir_p9;
k->intc_create = pnv_chip_power9_intc_create;
k->intc_reset = pnv_chip_power9_intc_reset;
k->intc_destroy = pnv_chip_power9_intc_destroy;
@ -1981,7 +2092,7 @@ static void pnv_chip_power10_class_init(ObjectClass *klass, void *data)
k->chip_cfam_id = 0x120da04900008000ull; /* P10 DD1.0 (with NX) */
k->cores_mask = POWER10_CORE_MASK;
k->core_pir = pnv_chip_core_pir_p10;
k->chip_pir = pnv_chip_pir_p10;
k->intc_create = pnv_chip_power10_intc_create;
k->intc_reset = pnv_chip_power10_intc_reset;
k->intc_destroy = pnv_chip_power10_intc_destroy;
@ -2071,8 +2182,8 @@ static void pnv_chip_core_realize(PnvChip *chip, Error **errp)
chip->nr_threads, &error_fatal);
object_property_set_int(OBJECT(pnv_core), CPU_CORE_PROP_CORE_ID,
core_hwid, &error_fatal);
object_property_set_int(OBJECT(pnv_core), "pir",
pcc->core_pir(chip, core_hwid), &error_fatal);
object_property_set_int(OBJECT(pnv_core), "hwid", core_hwid,
&error_fatal);
object_property_set_int(OBJECT(pnv_core), "hrmor", pnv->fw_load_addr,
&error_fatal);
object_property_set_link(OBJECT(pnv_core), "chip", OBJECT(chip),

View File

@ -226,7 +226,7 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
int thread_index)
{
CPUPPCState *env = &cpu->env;
int core_pir;
int core_hwid;
ppc_spr_t *pir = &env->spr_cb[SPR_PIR];
ppc_spr_t *tir = &env->spr_cb[SPR_TIR];
Error *local_err = NULL;
@ -242,10 +242,10 @@ static void pnv_core_cpu_realize(PnvCore *pc, PowerPCCPU *cpu, Error **errp,
return;
}
core_pir = object_property_get_uint(OBJECT(pc), "pir", &error_abort);
core_hwid = object_property_get_uint(OBJECT(pc), "hwid", &error_abort);
tir->default_value = thread_index;
pir->default_value = core_pir + thread_index;
pir->default_value = pcc->chip_pir(pc->chip, core_hwid, thread_index);
/* Set time-base frequency to 512 MHz */
cpu_ppc_tb_init(env, PNV_TIMEBASE_FREQ);
@ -342,7 +342,7 @@ static void pnv_core_unrealize(DeviceState *dev)
}
static Property pnv_core_properties[] = {
DEFINE_PROP_UINT32("pir", PnvCore, pir, 0),
DEFINE_PROP_UINT32("hwid", PnvCore, hwid, 0),
DEFINE_PROP_UINT64("hrmor", PnvCore, hrmor, 0),
DEFINE_PROP_LINK("chip", PnvCore, chip, TYPE_PNV_CHIP, PnvChip *),
DEFINE_PROP_END_OF_LIST(),

View File

@ -633,6 +633,16 @@ void cpu_ppc_store_atbu (CPUPPCState *env, uint32_t value)
((uint64_t)value << 32) | tb);
}
void cpu_ppc_increase_tb_by_offset(CPUPPCState *env, int64_t offset)
{
env->tb_env->tb_offset += offset;
}
void cpu_ppc_decrease_tb_by_offset(CPUPPCState *env, int64_t offset)
{
env->tb_env->tb_offset -= offset;
}
uint64_t cpu_ppc_load_vtb(CPUPPCState *env)
{
ppc_tb_t *tb_env = env->tb_env;

View File

@ -233,29 +233,40 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr,
PowerPCCPU *cpu,
void *fdt, int offset)
{
/*
* SSO (SAO) ordering is supported on KVM and thread=single hosts,
* but not MTTCG, so disable it. To advertise it, a cap would have
* to be added, or support implemented for MTTCG.
*
* Copy/paste is not supported by TCG, so it is not advertised. KVM
* can execute them but it has no accelerator drivers which are usable,
* so there isn't much need for it anyway.
*/
/* These should be kept in sync with pnv */
uint8_t pa_features_206[] = { 6, 0,
0xf6, 0x1f, 0xc7, 0x00, 0x80, 0xc0 };
0xf6, 0x1f, 0xc7, 0x00, 0x00, 0xc0 };
uint8_t pa_features_207[] = { 24, 0,
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0,
0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0,
0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
0x80, 0x00, 0x80, 0x00, 0x00, 0x00 };
uint8_t pa_features_300[] = { 66, 0,
/* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
/* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, SSO, 5: LE|CFAR|EB|LSQ */
0xf6, 0x1f, 0xc7, 0xc0, 0x80, 0xf0, /* 0 - 5 */
/* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
/* 6: DS207 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
/* 16: Vector */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
/* 18: Vec. Scalar, 20: Vec. XOR, 22: HTM */
/* 18: Vec. Scalar, 20: Vec. XOR */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
/* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
/* 30: MMR, 32: LE atomic, 34: EBB + ext EBB */
0x80, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
/* 36: SPR SO, 38: Copy/Paste, 40: Radix MMU */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 36 - 41 */
/* 32: LE atomic, 34: EBB + ext EBB */
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
/* 40: Radix MMU */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
/* 42: PM, 44: PC RA, 46: SC vec'd */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
/* 48: SIMD, 50: QP BFP, 52: String */
@ -265,6 +276,36 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr,
/* 60: NM atomic, 62: RNG */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
};
/* 3.1 removes SAO, HTM support */
uint8_t pa_features_31[] = { 74, 0,
/* 0: MMU|FPU|SLB|RUN|DABR|NX, 1: fri[nzpm]|DABRX|SPRG3|SLB0|PP110 */
/* 2: VPM|DS205|PPR|DS202|DS206, 3: LSD|URG, 5: LE|CFAR|EB|LSQ */
0xf6, 0x1f, 0xc7, 0xc0, 0x00, 0xf0, /* 0 - 5 */
/* 6: DS207 */
0x80, 0x00, 0x00, 0x00, 0x00, 0x00, /* 6 - 11 */
/* 16: Vector */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 12 - 17 */
/* 18: Vec. Scalar, 20: Vec. XOR */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 18 - 23 */
/* 24: Ext. Dec, 26: 64 bit ftrs, 28: PM ftrs */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 24 - 29 */
/* 32: LE atomic, 34: EBB + ext EBB */
0x00, 0x00, 0x80, 0x00, 0xC0, 0x00, /* 30 - 35 */
/* 40: Radix MMU */
0x00, 0x00, 0x00, 0x00, 0x80, 0x00, /* 36 - 41 */
/* 42: PM, 44: PC RA, 46: SC vec'd */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 42 - 47 */
/* 48: SIMD, 50: QP BFP, 52: String */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 48 - 53 */
/* 54: DecFP, 56: DecI, 58: SHA */
0x80, 0x00, 0x80, 0x00, 0x80, 0x00, /* 54 - 59 */
/* 60: NM atomic, 62: RNG */
0x80, 0x00, 0x80, 0x00, 0x00, 0x00, /* 60 - 65 */
/* 68: DEXCR[SBHE|IBRTPDUS|SRAPD|NPHIE|PHIE] */
0x00, 0x00, 0xce, 0x00, 0x00, 0x00, /* 66 - 71 */
/* 72: [P]HASHST/[P]HASHCHK */
0x80, 0x00, /* 72 - 73 */
};
uint8_t *pa_features = NULL;
size_t pa_size;
@ -280,6 +321,10 @@ static void spapr_dt_pa_features(SpaprMachineState *spapr,
pa_features = pa_features_300;
pa_size = sizeof(pa_features_300);
}
if (ppc_check_compat(cpu, CPU_POWERPC_LOGICAL_3_10, 0, cpu->compat_pvr)) {
pa_features = pa_features_31;
pa_size = sizeof(pa_features_31);
}
if (!pa_features) {
return;
}
@ -1362,7 +1407,6 @@ void spapr_init_all_lpcrs(target_ulong value, target_ulong mask)
}
}
static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu,
target_ulong lpid, ppc_v3_pate_t *entry)
{
@ -1375,33 +1419,16 @@ static bool spapr_get_pate(PPCVirtualHypervisor *vhyp, PowerPCCPU *cpu,
/* Copy PATE1:GR into PATE0:HR */
entry->dw0 = spapr->patb_entry & PATE0_HR;
entry->dw1 = spapr->patb_entry;
return true;
} else {
uint64_t patb, pats;
assert(lpid != 0);
patb = spapr->nested_ptcr & PTCR_PATB;
pats = spapr->nested_ptcr & PTCR_PATS;
/* Check if partition table is properly aligned */
if (patb & MAKE_64BIT_MASK(0, pats + 12)) {
return false;
if (spapr_nested_api(spapr) == NESTED_API_KVM_HV) {
return spapr_get_pate_nested_hv(spapr, cpu, lpid, entry);
} else if (spapr_nested_api(spapr) == NESTED_API_PAPR) {
return spapr_get_pate_nested_papr(spapr, cpu, lpid, entry);
} else {
g_assert_not_reached();
}
/* Calculate number of entries */
pats = 1ull << (pats + 12 - 4);
if (pats <= lpid) {
return false;
}
/* Grab entry */
patb += 16 * lpid;
entry->dw0 = ldq_phys(CPU(cpu)->as, patb);
entry->dw1 = ldq_phys(CPU(cpu)->as, patb + 8);
}
return true;
}
#define HPTE(_table, _i) (void *)(((uint64_t *)(_table)) + ((_i) * 2))
@ -1689,6 +1716,7 @@ static void spapr_machine_reset(MachineState *machine, ShutdownCause reason)
pef_kvm_reset(machine->cgs, &error_fatal);
spapr_caps_apply(spapr);
spapr_nested_reset(spapr);
first_ppc_cpu = POWERPC_CPU(first_cpu);
if (kvm_enabled() && kvmppc_has_cap_mmu_radix() &&
@ -2138,6 +2166,7 @@ static const VMStateDescription vmstate_spapr = {
&vmstate_spapr_cap_fwnmi,
&vmstate_spapr_fwnmi,
&vmstate_spapr_cap_rpt_invalidate,
&vmstate_spapr_cap_nested_papr,
NULL
}
};
@ -4702,6 +4731,7 @@ static void spapr_machine_class_init(ObjectClass *oc, void *data)
smc->default_caps.caps[SPAPR_CAP_IBS] = SPAPR_CAP_WORKAROUND;
smc->default_caps.caps[SPAPR_CAP_HPT_MAXPAGESIZE] = 16; /* 64kiB */
smc->default_caps.caps[SPAPR_CAP_NESTED_KVM_HV] = SPAPR_CAP_OFF;
smc->default_caps.caps[SPAPR_CAP_NESTED_PAPR] = SPAPR_CAP_OFF;
smc->default_caps.caps[SPAPR_CAP_LARGE_DECREMENTER] = SPAPR_CAP_ON;
smc->default_caps.caps[SPAPR_CAP_CCF_ASSIST] = SPAPR_CAP_ON;
smc->default_caps.caps[SPAPR_CAP_FWNMI] = SPAPR_CAP_ON;

View File

@ -484,6 +484,50 @@ static void cap_nested_kvm_hv_apply(SpaprMachineState *spapr,
error_append_hint(errp, "Try appending -machine cap-nested-hv=off "
"or use threads=1 with -smp\n");
}
if (spapr_nested_api(spapr) &&
spapr_nested_api(spapr) != NESTED_API_KVM_HV) {
error_setg(errp, "Nested-HV APIs are mutually exclusive");
error_append_hint(errp, "Please use either cap-nested-hv or "
"cap-nested-papr to proceed.\n");
return;
} else {
spapr->nested.api = NESTED_API_KVM_HV;
}
}
}
static void cap_nested_papr_apply(SpaprMachineState *spapr,
uint8_t val, Error **errp)
{
ERRP_GUARD();
PowerPCCPU *cpu = POWERPC_CPU(first_cpu);
CPUPPCState *env = &cpu->env;
if (!val) {
/* capability disabled by default */
return;
}
if (tcg_enabled()) {
if (!(env->insns_flags2 & PPC2_ISA300)) {
error_setg(errp, "Nested-PAPR only supported on POWER9 and later");
error_append_hint(errp,
"Try appending -machine cap-nested-papr=off\n");
return;
}
if (spapr_nested_api(spapr) &&
spapr_nested_api(spapr) != NESTED_API_PAPR) {
error_setg(errp, "Nested-HV APIs are mutually exclusive");
error_append_hint(errp, "Please use either cap-nested-hv or "
"cap-nested-papr to proceed.\n");
return;
} else {
spapr->nested.api = NESTED_API_PAPR;
}
} else if (kvm_enabled()) {
error_setg(errp, "KVM implementation does not support Nested-PAPR");
error_append_hint(errp,
"Try appending -machine cap-nested-papr=off\n");
}
}
@ -732,6 +776,15 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.type = "bool",
.apply = cap_nested_kvm_hv_apply,
},
[SPAPR_CAP_NESTED_PAPR] = {
.name = "nested-papr",
.description = "Allow Nested HV (PAPR API)",
.index = SPAPR_CAP_NESTED_PAPR,
.get = spapr_cap_get_bool,
.set = spapr_cap_set_bool,
.type = "bool",
.apply = cap_nested_papr_apply,
},
[SPAPR_CAP_LARGE_DECREMENTER] = {
.name = "large-decr",
.description = "Allow Large Decrementer",
@ -916,6 +969,7 @@ SPAPR_CAP_MIG_STATE(sbbc, SPAPR_CAP_SBBC);
SPAPR_CAP_MIG_STATE(ibs, SPAPR_CAP_IBS);
SPAPR_CAP_MIG_STATE(hpt_maxpagesize, SPAPR_CAP_HPT_MAXPAGESIZE);
SPAPR_CAP_MIG_STATE(nested_kvm_hv, SPAPR_CAP_NESTED_KVM_HV);
SPAPR_CAP_MIG_STATE(nested_papr, SPAPR_CAP_NESTED_PAPR);
SPAPR_CAP_MIG_STATE(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI);

View File

@ -39,9 +39,13 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
/*
* "PowerPC Processor binding to IEEE 1275" defines the initial MSR state
* as 32bit (MSR_SF=0) in "8.2.1. Initial Register Values".
* as 32bit (MSR_SF=0) with MSR_ME=1 and MSR_FP=1 in "8.2.1. Initial
* Register Values". This can also be found in "LoPAPR 1.1" "C.9.2.1
* Initial Register Values".
*/
env->msr &= ~(1ULL << MSR_SF);
env->msr |= (1ULL << MSR_ME) | (1ULL << MSR_FP);
env->spr[SPR_HIOR] = 0;
lpcr = env->spr[SPR_LPCR];
@ -394,10 +398,8 @@ static const TypeInfo spapr_cpu_core_type_infos[] = {
DEFINE_SPAPR_CPU_CORE_TYPE("power8_v2.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power8e_v2.1"),
DEFINE_SPAPR_CPU_CORE_TYPE("power8nvl_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power9_v2.2"),
DEFINE_SPAPR_CPU_CORE_TYPE("power10_v1.0"),
DEFINE_SPAPR_CPU_CORE_TYPE("power10_v2.0"),
#ifdef CONFIG_KVM
DEFINE_SPAPR_CPU_CORE_TYPE("host"),

View File

@ -1525,6 +1525,28 @@ void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn)
*slot = fn;
}
void spapr_unregister_hypercall(target_ulong opcode)
{
spapr_hcall_fn *slot;
if (opcode <= MAX_HCALL_OPCODE) {
assert((opcode & 0x3) == 0);
slot = &papr_hypercall_table[opcode / 4];
} else if (opcode >= SVM_HCALL_BASE && opcode <= SVM_HCALL_MAX) {
/* we only have SVM-related hcall numbers assigned in multiples of 4 */
assert((opcode & 0x3) == 0);
slot = &svm_hypercall_table[(opcode - SVM_HCALL_BASE) / 4];
} else {
assert((opcode >= KVMPPC_HCALL_BASE) && (opcode <= KVMPPC_HCALL_MAX));
slot = &kvmppc_hypercall_table[opcode - KVMPPC_HCALL_BASE];
}
*slot = NULL;
}
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args)
{
@ -1638,8 +1660,6 @@ static void hypercall_register_types(void)
spapr_register_hypercall(KVMPPC_H_CAS, h_client_architecture_support);
spapr_register_hypercall(KVMPPC_H_UPDATE_DT, h_update_dt);
spapr_register_nested();
}
type_init(hypercall_register_types)

File diff suppressed because it is too large Load Diff

View File

@ -147,7 +147,7 @@ struct PnvChipClass {
DeviceRealize parent_realize;
uint32_t (*core_pir)(PnvChip *chip, uint32_t core_id);
uint32_t (*chip_pir)(PnvChip *chip, uint32_t core_id, uint32_t thread_id);
void (*intc_create)(PnvChip *chip, PowerPCCPU *cpu, Error **errp);
void (*intc_reset)(PnvChip *chip, PowerPCCPU *cpu);
void (*intc_destroy)(PnvChip *chip, PowerPCCPU *cpu);

View File

@ -36,6 +36,7 @@ struct PnvCore {
/*< public >*/
PowerPCCPU **threads;
uint32_t pir;
uint32_t hwid;
uint64_t hrmor;
PnvChip *chip;

View File

@ -12,6 +12,7 @@
#include "hw/ppc/spapr_xive.h" /* For SpaprXive */
#include "hw/ppc/xics.h" /* For ICSState */
#include "hw/ppc/spapr_tpm_proxy.h"
#include "hw/ppc/spapr_nested.h" /* For SpaprMachineStateNested */
struct SpaprVioBus;
struct SpaprPhbState;
@ -80,8 +81,10 @@ typedef enum {
#define SPAPR_CAP_RPT_INVALIDATE 0x0B
/* Support for AIL modes */
#define SPAPR_CAP_AIL_MODE_3 0x0C
/* Nested PAPR */
#define SPAPR_CAP_NESTED_PAPR 0x0D
/* Num Caps */
#define SPAPR_CAP_NUM (SPAPR_CAP_AIL_MODE_3 + 1)
#define SPAPR_CAP_NUM (SPAPR_CAP_NESTED_PAPR + 1)
/*
* Capability Values
@ -213,7 +216,7 @@ struct SpaprMachineState {
uint32_t vsmt; /* Virtual SMT mode (KVM's "core stride") */
/* Nested HV support (TCG only) */
uint64_t nested_ptcr;
SpaprMachineStateNested nested;
Notifier epow_notifier;
QTAILQ_HEAD(, SpaprEventLogEntry) pending_events;
@ -363,6 +366,9 @@ struct SpaprMachineState {
#define H_NOOP -63
#define H_UNSUPPORTED -67
#define H_OVERLAP -68
#define H_STATE -75
#define H_IN_USE -77
#define H_INVALID_ELEMENT_VALUE -81
#define H_UNSUPPORTED_FLAG -256
#define H_MULTI_THREADS_ACTIVE -9005
@ -582,8 +588,16 @@ struct SpaprMachineState {
#define H_RPT_INVALIDATE 0x448
#define H_SCM_FLUSH 0x44C
#define H_WATCHDOG 0x45C
#define H_GUEST_GET_CAPABILITIES 0x460
#define H_GUEST_SET_CAPABILITIES 0x464
#define H_GUEST_CREATE 0x470
#define H_GUEST_CREATE_VCPU 0x474
#define H_GUEST_GET_STATE 0x478
#define H_GUEST_SET_STATE 0x47C
#define H_GUEST_RUN_VCPU 0x480
#define H_GUEST_DELETE 0x488
#define MAX_HCALL_OPCODE H_WATCHDOG
#define MAX_HCALL_OPCODE H_GUEST_DELETE
/* The hcalls above are standardized in PAPR and implemented by pHyp
* as well.
@ -631,6 +645,7 @@ typedef target_ulong (*spapr_hcall_fn)(PowerPCCPU *cpu, SpaprMachineState *sm,
target_ulong *args);
void spapr_register_hypercall(target_ulong opcode, spapr_hcall_fn fn);
void spapr_unregister_hypercall(target_ulong opcode);
target_ulong spapr_hypercall(PowerPCCPU *cpu, target_ulong opcode,
target_ulong *args);
@ -984,6 +999,7 @@ extern const VMStateDescription vmstate_spapr_cap_sbbc;
extern const VMStateDescription vmstate_spapr_cap_ibs;
extern const VMStateDescription vmstate_spapr_cap_hpt_maxpagesize;
extern const VMStateDescription vmstate_spapr_cap_nested_kvm_hv;
extern const VMStateDescription vmstate_spapr_cap_nested_papr;
extern const VMStateDescription vmstate_spapr_cap_large_decr;
extern const VMStateDescription vmstate_spapr_cap_ccf_assist;
extern const VMStateDescription vmstate_spapr_cap_fwnmi;
@ -1028,5 +1044,10 @@ void spapr_vof_client_dt_finalize(SpaprMachineState *spapr, void *fdt);
/* H_WATCHDOG */
void spapr_watchdog_init(SpaprMachineState *spapr);
void spapr_register_nested_hv(void);
void spapr_unregister_nested_hv(void);
void spapr_nested_reset(SpaprMachineState *spapr);
void spapr_register_nested_papr(void);
void spapr_unregister_nested_papr(void);
#endif /* HW_SPAPR_H */

View File

@ -3,6 +3,348 @@
#include "target/ppc/cpu.h"
/* Guest State Buffer Element IDs */
#define GSB_HV_VCPU_IGNORED_ID 0x0000 /* An element whose value is ignored */
#define GSB_HV_VCPU_STATE_SIZE 0x0001 /* HV internal format VCPU state size */
#define GSB_VCPU_OUT_BUF_MIN_SZ 0x0002 /* Min size of the Run VCPU o/p buffer */
#define GSB_VCPU_LPVR 0x0003 /* Logical PVR */
#define GSB_TB_OFFSET 0x0004 /* Timebase Offset */
#define GSB_PART_SCOPED_PAGETBL 0x0005 /* Partition Scoped Page Table */
#define GSB_PROCESS_TBL 0x0006 /* Process Table */
/* RESERVED 0x0007 - 0x0BFF */
#define GSB_VCPU_IN_BUFFER 0x0C00 /* Run VCPU Input Buffer */
#define GSB_VCPU_OUT_BUFFER 0x0C01 /* Run VCPU Out Buffer */
#define GSB_VCPU_VPA 0x0C02 /* HRA to Guest VCPU VPA */
/* RESERVED 0x0C03 - 0x0FFF */
#define GSB_VCPU_GPR0 0x1000
#define GSB_VCPU_GPR1 0x1001
#define GSB_VCPU_GPR2 0x1002
#define GSB_VCPU_GPR3 0x1003
#define GSB_VCPU_GPR4 0x1004
#define GSB_VCPU_GPR5 0x1005
#define GSB_VCPU_GPR6 0x1006
#define GSB_VCPU_GPR7 0x1007
#define GSB_VCPU_GPR8 0x1008
#define GSB_VCPU_GPR9 0x1009
#define GSB_VCPU_GPR10 0x100A
#define GSB_VCPU_GPR11 0x100B
#define GSB_VCPU_GPR12 0x100C
#define GSB_VCPU_GPR13 0x100D
#define GSB_VCPU_GPR14 0x100E
#define GSB_VCPU_GPR15 0x100F
#define GSB_VCPU_GPR16 0x1010
#define GSB_VCPU_GPR17 0x1011
#define GSB_VCPU_GPR18 0x1012
#define GSB_VCPU_GPR19 0x1013
#define GSB_VCPU_GPR20 0x1014
#define GSB_VCPU_GPR21 0x1015
#define GSB_VCPU_GPR22 0x1016
#define GSB_VCPU_GPR23 0x1017
#define GSB_VCPU_GPR24 0x1018
#define GSB_VCPU_GPR25 0x1019
#define GSB_VCPU_GPR26 0x101A
#define GSB_VCPU_GPR27 0x101B
#define GSB_VCPU_GPR28 0x101C
#define GSB_VCPU_GPR29 0x101D
#define GSB_VCPU_GPR30 0x101E
#define GSB_VCPU_GPR31 0x101F
#define GSB_VCPU_HDEC_EXPIRY_TB 0x1020
#define GSB_VCPU_SPR_NIA 0x1021
#define GSB_VCPU_SPR_MSR 0x1022
#define GSB_VCPU_SPR_LR 0x1023
#define GSB_VCPU_SPR_XER 0x1024
#define GSB_VCPU_SPR_CTR 0x1025
#define GSB_VCPU_SPR_CFAR 0x1026
#define GSB_VCPU_SPR_SRR0 0x1027
#define GSB_VCPU_SPR_SRR1 0x1028
#define GSB_VCPU_SPR_DAR 0x1029
#define GSB_VCPU_DEC_EXPIRE_TB 0x102A
#define GSB_VCPU_SPR_VTB 0x102B
#define GSB_VCPU_SPR_LPCR 0x102C
#define GSB_VCPU_SPR_HFSCR 0x102D
#define GSB_VCPU_SPR_FSCR 0x102E
#define GSB_VCPU_SPR_FPSCR 0x102F
#define GSB_VCPU_SPR_DAWR0 0x1030
#define GSB_VCPU_SPR_DAWR1 0x1031
#define GSB_VCPU_SPR_CIABR 0x1032
#define GSB_VCPU_SPR_PURR 0x1033
#define GSB_VCPU_SPR_SPURR 0x1034
#define GSB_VCPU_SPR_IC 0x1035
#define GSB_VCPU_SPR_SPRG0 0x1036
#define GSB_VCPU_SPR_SPRG1 0x1037
#define GSB_VCPU_SPR_SPRG2 0x1038
#define GSB_VCPU_SPR_SPRG3 0x1039
#define GSB_VCPU_SPR_PPR 0x103A
#define GSB_VCPU_SPR_MMCR0 0x103B
#define GSB_VCPU_SPR_MMCR1 0x103C
#define GSB_VCPU_SPR_MMCR2 0x103D
#define GSB_VCPU_SPR_MMCR3 0x103E
#define GSB_VCPU_SPR_MMCRA 0x103F
#define GSB_VCPU_SPR_SIER 0x1040
#define GSB_VCPU_SPR_SIER2 0x1041
#define GSB_VCPU_SPR_SIER3 0x1042
#define GSB_VCPU_SPR_BESCR 0x1043
#define GSB_VCPU_SPR_EBBHR 0x1044
#define GSB_VCPU_SPR_EBBRR 0x1045
#define GSB_VCPU_SPR_AMR 0x1046
#define GSB_VCPU_SPR_IAMR 0x1047
#define GSB_VCPU_SPR_AMOR 0x1048
#define GSB_VCPU_SPR_UAMOR 0x1049
#define GSB_VCPU_SPR_SDAR 0x104A
#define GSB_VCPU_SPR_SIAR 0x104B
#define GSB_VCPU_SPR_DSCR 0x104C
#define GSB_VCPU_SPR_TAR 0x104D
#define GSB_VCPU_SPR_DEXCR 0x104E
#define GSB_VCPU_SPR_HDEXCR 0x104F
#define GSB_VCPU_SPR_HASHKEYR 0x1050
#define GSB_VCPU_SPR_HASHPKEYR 0x1051
#define GSB_VCPU_SPR_CTRL 0x1052
/* RESERVED 0x1053 - 0x1FFF */
#define GSB_VCPU_SPR_CR 0x2000
#define GSB_VCPU_SPR_PIDR 0x2001
#define GSB_VCPU_SPR_DSISR 0x2002
#define GSB_VCPU_SPR_VSCR 0x2003
#define GSB_VCPU_SPR_VRSAVE 0x2004
#define GSB_VCPU_SPR_DAWRX0 0x2005
#define GSB_VCPU_SPR_DAWRX1 0x2006
#define GSB_VCPU_SPR_PMC1 0x2007
#define GSB_VCPU_SPR_PMC2 0x2008
#define GSB_VCPU_SPR_PMC3 0x2009
#define GSB_VCPU_SPR_PMC4 0x200A
#define GSB_VCPU_SPR_PMC5 0x200B
#define GSB_VCPU_SPR_PMC6 0x200C
#define GSB_VCPU_SPR_WORT 0x200D
#define GSB_VCPU_SPR_PSPB 0x200E
/* RESERVED 0x200F - 0x2FFF */
#define GSB_VCPU_SPR_VSR0 0x3000
#define GSB_VCPU_SPR_VSR1 0x3001
#define GSB_VCPU_SPR_VSR2 0x3002
#define GSB_VCPU_SPR_VSR3 0x3003
#define GSB_VCPU_SPR_VSR4 0x3004
#define GSB_VCPU_SPR_VSR5 0x3005
#define GSB_VCPU_SPR_VSR6 0x3006
#define GSB_VCPU_SPR_VSR7 0x3007
#define GSB_VCPU_SPR_VSR8 0x3008
#define GSB_VCPU_SPR_VSR9 0x3009
#define GSB_VCPU_SPR_VSR10 0x300A
#define GSB_VCPU_SPR_VSR11 0x300B
#define GSB_VCPU_SPR_VSR12 0x300C
#define GSB_VCPU_SPR_VSR13 0x300D
#define GSB_VCPU_SPR_VSR14 0x300E
#define GSB_VCPU_SPR_VSR15 0x300F
#define GSB_VCPU_SPR_VSR16 0x3010
#define GSB_VCPU_SPR_VSR17 0x3011
#define GSB_VCPU_SPR_VSR18 0x3012
#define GSB_VCPU_SPR_VSR19 0x3013
#define GSB_VCPU_SPR_VSR20 0x3014
#define GSB_VCPU_SPR_VSR21 0x3015
#define GSB_VCPU_SPR_VSR22 0x3016
#define GSB_VCPU_SPR_VSR23 0x3017
#define GSB_VCPU_SPR_VSR24 0x3018
#define GSB_VCPU_SPR_VSR25 0x3019
#define GSB_VCPU_SPR_VSR26 0x301A
#define GSB_VCPU_SPR_VSR27 0x301B
#define GSB_VCPU_SPR_VSR28 0x301C
#define GSB_VCPU_SPR_VSR29 0x301D
#define GSB_VCPU_SPR_VSR30 0x301E
#define GSB_VCPU_SPR_VSR31 0x301F
#define GSB_VCPU_SPR_VSR32 0x3020
#define GSB_VCPU_SPR_VSR33 0x3021
#define GSB_VCPU_SPR_VSR34 0x3022
#define GSB_VCPU_SPR_VSR35 0x3023
#define GSB_VCPU_SPR_VSR36 0x3024
#define GSB_VCPU_SPR_VSR37 0x3025
#define GSB_VCPU_SPR_VSR38 0x3026
#define GSB_VCPU_SPR_VSR39 0x3027
#define GSB_VCPU_SPR_VSR40 0x3028
#define GSB_VCPU_SPR_VSR41 0x3029
#define GSB_VCPU_SPR_VSR42 0x302A
#define GSB_VCPU_SPR_VSR43 0x302B
#define GSB_VCPU_SPR_VSR44 0x302C
#define GSB_VCPU_SPR_VSR45 0x302D
#define GSB_VCPU_SPR_VSR46 0x302E
#define GSB_VCPU_SPR_VSR47 0x302F
#define GSB_VCPU_SPR_VSR48 0x3030
#define GSB_VCPU_SPR_VSR49 0x3031
#define GSB_VCPU_SPR_VSR50 0x3032
#define GSB_VCPU_SPR_VSR51 0x3033
#define GSB_VCPU_SPR_VSR52 0x3034
#define GSB_VCPU_SPR_VSR53 0x3035
#define GSB_VCPU_SPR_VSR54 0x3036
#define GSB_VCPU_SPR_VSR55 0x3037
#define GSB_VCPU_SPR_VSR56 0x3038
#define GSB_VCPU_SPR_VSR57 0x3039
#define GSB_VCPU_SPR_VSR58 0x303A
#define GSB_VCPU_SPR_VSR59 0x303B
#define GSB_VCPU_SPR_VSR60 0x303C
#define GSB_VCPU_SPR_VSR61 0x303D
#define GSB_VCPU_SPR_VSR62 0x303E
#define GSB_VCPU_SPR_VSR63 0x303F
/* RESERVED 0x3040 - 0xEFFF */
#define GSB_VCPU_SPR_HDAR 0xF000
#define GSB_VCPU_SPR_HDSISR 0xF001
#define GSB_VCPU_SPR_HEIR 0xF002
#define GSB_VCPU_SPR_ASDR 0xF003
/* End of list of Guest State Buffer Element IDs */
#define GSB_LAST GSB_VCPU_SPR_ASDR
typedef struct SpaprMachineStateNested {
uint64_t ptcr;
uint8_t api;
#define NESTED_API_KVM_HV 1
#define NESTED_API_PAPR 2
bool capabilities_set;
uint32_t pvr_base;
GHashTable *guests;
} SpaprMachineStateNested;
typedef struct SpaprMachineStateNestedGuest {
uint32_t pvr_logical;
unsigned long nr_vcpus;
uint64_t parttbl[2];
uint64_t tb_offset;
struct SpaprMachineStateNestedGuestVcpu *vcpus;
} SpaprMachineStateNestedGuest;
/* Nested PAPR API related macros */
#define H_GUEST_CAPABILITIES_COPY_MEM 0x8000000000000000
#define H_GUEST_CAPABILITIES_P9_MODE 0x4000000000000000
#define H_GUEST_CAPABILITIES_P10_MODE 0x2000000000000000
#define H_GUEST_CAP_VALID_MASK (H_GUEST_CAPABILITIES_P10_MODE | \
H_GUEST_CAPABILITIES_P9_MODE)
#define H_GUEST_CAP_COPY_MEM_BMAP 0
#define H_GUEST_CAP_P9_MODE_BMAP 1
#define H_GUEST_CAP_P10_MODE_BMAP 2
#define PAPR_NESTED_GUEST_MAX 4096
#define H_GUEST_DELETE_ALL_FLAG 0x8000000000000000ULL
#define PAPR_NESTED_GUEST_VCPU_MAX 2048
#define VCPU_OUT_BUF_MIN_SZ 0x80ULL
#define HVMASK_DEFAULT 0xffffffffffffffff
#define HVMASK_LPCR 0x0070000003820800
#define HVMASK_MSR 0xEBFFFFFFFFBFEFFF
#define HVMASK_HDEXCR 0x00000000FFFFFFFF
#define HVMASK_TB_OFFSET 0x000000FFFFFFFFFF
#define GSB_MAX_BUF_SIZE (1024 * 1024)
#define H_GUEST_GETSET_STATE_FLAG_GUEST_WIDE 0x8000000000000000
#define GUEST_STATE_REQUEST_GUEST_WIDE 0x1
#define GUEST_STATE_REQUEST_SET 0x2
/*
* As per ISA v3.1B, following bits are reserved:
* 0:2
* 4:57 (ISA mentions bit 58 as well but it should be used for P10)
* 61:63 (hence, haven't included PCR bits for v2.06 and v2.05
* in LOW BITS)
*/
#define PCR_LOW_BITS (PCR_COMPAT_3_10 | PCR_COMPAT_3_00)
#define HVMASK_PCR (~PCR_LOW_BITS)
#define GUEST_STATE_ELEMENT(i, sz, s, f, ptr, c) { \
.id = (i), \
.size = (sz), \
.location = ptr, \
.offset = offsetof(struct s, f), \
.copy = (c) \
}
#define GSBE_NESTED(i, sz, f, c) { \
.id = (i), \
.size = (sz), \
.location = get_guest_ptr, \
.offset = offsetof(struct SpaprMachineStateNestedGuest, f),\
.copy = (c), \
.mask = HVMASK_DEFAULT \
}
#define GSBE_NESTED_MSK(i, sz, f, c, m) { \
.id = (i), \
.size = (sz), \
.location = get_guest_ptr, \
.offset = offsetof(struct SpaprMachineStateNestedGuest, f),\
.copy = (c), \
.mask = (m) \
}
#define GSBE_NESTED_VCPU(i, sz, f, c) { \
.id = (i), \
.size = (sz), \
.location = get_vcpu_ptr, \
.offset = offsetof(struct SpaprMachineStateNestedGuestVcpu, f),\
.copy = (c), \
.mask = HVMASK_DEFAULT \
}
#define GUEST_STATE_ELEMENT_NOP(i, sz) { \
.id = (i), \
.size = (sz), \
.location = NULL, \
.offset = 0, \
.copy = NULL, \
.mask = HVMASK_DEFAULT \
}
#define GUEST_STATE_ELEMENT_NOP_DW(i) \
GUEST_STATE_ELEMENT_NOP(i, 8)
#define GUEST_STATE_ELEMENT_NOP_W(i) \
GUEST_STATE_ELEMENT_NOP(i, 4)
#define GUEST_STATE_ELEMENT_BASE(i, s, c) { \
.id = (i), \
.size = (s), \
.location = get_vcpu_state_ptr, \
.offset = 0, \
.copy = (c), \
.mask = HVMASK_DEFAULT \
}
#define GUEST_STATE_ELEMENT_OFF(i, s, f, c) { \
.id = (i), \
.size = (s), \
.location = get_vcpu_state_ptr, \
.offset = offsetof(struct nested_ppc_state, f), \
.copy = (c), \
.mask = HVMASK_DEFAULT \
}
#define GUEST_STATE_ELEMENT_MSK(i, s, f, c, m) { \
.id = (i), \
.size = (s), \
.location = get_vcpu_state_ptr, \
.offset = offsetof(struct nested_ppc_state, f), \
.copy = (c), \
.mask = (m) \
}
#define GUEST_STATE_ELEMENT_ENV_QW(i, f) \
GUEST_STATE_ELEMENT_OFF(i, 16, f, copy_state_16to16)
#define GUEST_STATE_ELEMENT_ENV_DW(i, f) \
GUEST_STATE_ELEMENT_OFF(i, 8, f, copy_state_8to8)
#define GUEST_STATE_ELEMENT_ENV_W(i, f) \
GUEST_STATE_ELEMENT_OFF(i, 4, f, copy_state_4to8)
#define GUEST_STATE_ELEMENT_ENV_WW(i, f) \
GUEST_STATE_ELEMENT_OFF(i, 4, f, copy_state_4to4)
#define GSE_ENV_DWM(i, f, m) \
GUEST_STATE_ELEMENT_MSK(i, 8, f, copy_state_8to8, m)
struct guest_state_element {
uint16_t id;
uint16_t size;
uint8_t value[];
} QEMU_PACKED;
struct guest_state_buffer {
uint32_t num_elements;
struct guest_state_element elements[];
} QEMU_PACKED;
/* Actual buffer plus some metadata about the request */
struct guest_state_request {
struct guest_state_buffer *gsb;
int64_t buf;
int64_t len;
uint16_t flags;
};
/*
* Register state for entering a nested guest with H_ENTER_NESTED.
* New member must be added at the end.
@ -93,9 +435,90 @@ struct nested_ppc_state {
uint64_t ppr;
int64_t tb_offset;
/* Nested PAPR API */
uint64_t amor;
uint64_t dawr0;
uint64_t dawrx0;
uint64_t ciabr;
uint64_t purr;
uint64_t spurr;
uint64_t ic;
uint64_t vtb;
uint64_t hdar;
uint64_t hdsisr;
uint64_t heir;
uint64_t asdr;
uint64_t dawr1;
uint64_t dawrx1;
uint64_t dexcr;
uint64_t hdexcr;
uint64_t hashkeyr;
uint64_t hashpkeyr;
ppc_vsr_t vsr[64] QEMU_ALIGNED(16);
uint64_t ebbhr;
uint64_t tar;
uint64_t ebbrr;
uint64_t bescr;
uint64_t iamr;
uint64_t amr;
uint64_t uamor;
uint64_t dscr;
uint64_t fscr;
uint64_t pspb;
uint64_t ctrl;
uint64_t vrsave;
uint64_t dar;
uint64_t dsisr;
uint64_t pmc1;
uint64_t pmc2;
uint64_t pmc3;
uint64_t pmc4;
uint64_t pmc5;
uint64_t pmc6;
uint64_t mmcr0;
uint64_t mmcr1;
uint64_t mmcr2;
uint64_t mmcra;
uint64_t sdar;
uint64_t siar;
uint64_t sier;
uint32_t vscr;
uint64_t fpscr;
int64_t dec_expiry_tb;
};
void spapr_register_nested(void);
void spapr_exit_nested(PowerPCCPU *cpu, int excp);
struct SpaprMachineStateNestedGuestVcpuRunBuf {
uint64_t addr;
uint64_t size;
};
typedef struct SpaprMachineStateNestedGuestVcpu {
bool enabled;
struct nested_ppc_state state;
struct SpaprMachineStateNestedGuestVcpuRunBuf runbufin;
struct SpaprMachineStateNestedGuestVcpuRunBuf runbufout;
int64_t tb_offset;
uint64_t hdecr_expiry_tb;
} SpaprMachineStateNestedGuestVcpu;
struct guest_state_element_type {
uint16_t id;
int size;
#define GUEST_STATE_ELEMENT_TYPE_FLAG_GUEST_WIDE 0x1
#define GUEST_STATE_ELEMENT_TYPE_FLAG_READ_ONLY 0x2
uint16_t flags;
void *(*location)(SpaprMachineStateNestedGuest *, target_ulong);
size_t offset;
void (*copy)(void *, void *, bool);
uint64_t mask;
};
void spapr_exit_nested(PowerPCCPU *cpu, int excp);
typedef struct SpaprMachineState SpaprMachineState;
bool spapr_get_pate_nested_hv(SpaprMachineState *spapr, PowerPCCPU *cpu,
target_ulong lpid, ppc_v3_pate_t *entry);
uint8_t spapr_nested_api(SpaprMachineState *spapr);
void spapr_nested_gsb_init(void);
bool spapr_get_pate_nested_papr(SpaprMachineState *spapr, PowerPCCPU *cpu,
target_ulong lpid, ppc_v3_pate_t *entry);
#endif /* HW_SPAPR_NESTED_H */

View File

@ -728,14 +728,10 @@
"POWER8 v2.0")
POWERPC_DEF("power8nvl_v1.0", CPU_POWERPC_POWER8NVL_v10, POWER8,
"POWER8NVL v1.0")
POWERPC_DEF("power9_v1.0", CPU_POWERPC_POWER9_DD1, POWER9,
"POWER9 v1.0")
POWERPC_DEF("power9_v2.0", CPU_POWERPC_POWER9_DD20, POWER9,
"POWER9 v2.0")
POWERPC_DEF("power9_v2.2", CPU_POWERPC_POWER9_DD22, POWER9,
"POWER9 v2.2")
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) */

View File

@ -1584,6 +1584,8 @@ uint64_t cpu_ppc_load_atbl(CPUPPCState *env);
uint32_t cpu_ppc_load_atbu(CPUPPCState *env);
void cpu_ppc_store_atbl(CPUPPCState *env, uint32_t value);
void cpu_ppc_store_atbu(CPUPPCState *env, uint32_t value);
void cpu_ppc_increase_tb_by_offset(CPUPPCState *env, int64_t offset);
void cpu_ppc_decrease_tb_by_offset(CPUPPCState *env, int64_t offset);
uint64_t cpu_ppc_load_vtb(CPUPPCState *env);
void cpu_ppc_store_vtb(CPUPPCState *env, uint64_t value);
bool ppc_decr_clear_on_delivery(CPUPPCState *env);
@ -1755,9 +1757,11 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_PSPB (0x09F)
#define SPR_DPDES (0x0B0)
#define SPR_DAWR0 (0x0B4)
#define SPR_DAWR1 (0x0B5)
#define SPR_RPR (0x0BA)
#define SPR_CIABR (0x0BB)
#define SPR_DAWRX0 (0x0BC)
#define SPR_DAWRX1 (0x0BD)
#define SPR_HFSCR (0x0BE)
#define SPR_VRSAVE (0x100)
#define SPR_USPRG0 (0x100)
@ -1951,6 +1955,12 @@ void ppc_compat_add_property(Object *obj, const char *name,
#define SPR_BOOKE_TLB2CFG (0x2B2)
#define SPR_BOOKE_TLB3CFG (0x2B3)
#define SPR_BOOKE_EPR (0x2BE)
#define SPR_POWER_USIER2 (0x2E0)
#define SPR_POWER_USIER3 (0x2E1)
#define SPR_POWER_UMMCR3 (0x2E2)
#define SPR_POWER_SIER2 (0x2F0)
#define SPR_POWER_SIER3 (0x2F1)
#define SPR_POWER_MMCR3 (0x2F2)
#define SPR_PERF0 (0x300)
#define SPR_RCPU_MI_RBA0 (0x300)
#define SPR_MPC_MI_CTR (0x300)
@ -2948,6 +2958,7 @@ static inline bool ppc_has_spr(PowerPCCPU *cpu, int spr)
}
#if !defined(CONFIG_USER_ONLY)
/* Sort out endianness of interrupt. Depends on the CPU, HV mode, etc. */
static inline bool ppc_interrupts_little_endian(PowerPCCPU *cpu, bool hv)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);

View File

@ -5308,6 +5308,38 @@ static void register_power8_pmu_user_sprs(CPUPPCState *env)
0x00000000);
}
static void register_power10_pmu_sup_sprs(CPUPPCState *env)
{
spr_register_kvm(env, SPR_POWER_MMCR3, "MMCR3",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_MMCR3, 0x00000000);
spr_register_kvm(env, SPR_POWER_SIER2, "SIER2",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_SIER2, 0x00000000);
spr_register_kvm(env, SPR_POWER_SIER3, "SIER3",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
KVM_REG_PPC_SIER3, 0x00000000);
}
static void register_power10_pmu_user_sprs(CPUPPCState *env)
{
spr_register(env, SPR_POWER_UMMCR3, "UMMCR3",
&spr_read_generic, &spr_write_generic,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_POWER_USIER2, "USIER2",
&spr_read_generic, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register(env, SPR_POWER_USIER3, "USIER3",
&spr_read_generic, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
}
static void register_power5p_ear_sprs(CPUPPCState *env)
{
/* External access control */
@ -6350,10 +6382,7 @@ static bool ppc_pvr_match_power9(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
return false;
}
if ((pvr & 0x0f00) == 0x100) {
/* DD1.x always matches power9_v1.0 */
return true;
} else if ((pvr & 0x0f00) == 0x200) {
if ((pvr & 0x0f00) == 0x200) {
if ((pvr & 0xf) < 2) {
/* DD2.0, DD2.1 match power9_v2.0 */
if ((pcc->pvr & 0xf) == 0) {
@ -6505,6 +6534,8 @@ static void init_proc_POWER10(CPUPPCState *env)
register_power9_mmu_sprs(env);
register_power10_hash_sprs(env);
register_power10_dexcr_sprs(env);
register_power10_pmu_sup_sprs(env);
register_power10_pmu_user_sprs(env);
/* FIXME: Filter fields properly based on privilege level */
spr_register_kvm_hv(env, SPR_PSSCR, "PSSCR", NULL, NULL, NULL, NULL,
@ -6536,7 +6567,7 @@ static bool ppc_pvr_match_power10(PowerPCCPUClass *pcc, uint32_t pvr, bool best)
}
if ((pvr & 0x0f00) == (pcc->pvr & 0x0f00)) {
/* Major DD version matches to power10_v1.0 and power10_v2.0 */
/* Major DD version matches power10_v2.0 */
return true;
}
@ -6576,11 +6607,10 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PPC2_FP_TST_ISA206 | PPC2_BCTAR_ISA207 |
PPC2_LSQ_ISA207 | PPC2_ALTIVEC_207 |
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
PPC2_ISA300 | PPC2_PRCNTL | PPC2_ISA310 |
PPC2_MEM_LWSYNC | PPC2_BCDA_ISA206;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
(1ull << MSR_EE) |
@ -6620,7 +6650,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->flags = POWERPC_FLAG_VRE | POWERPC_FLAG_SE |
POWERPC_FLAG_BE | POWERPC_FLAG_PMM |
POWERPC_FLAG_BUS_CLK | POWERPC_FLAG_CFAR |
POWERPC_FLAG_VSX | POWERPC_FLAG_TM | POWERPC_FLAG_SCV;
POWERPC_FLAG_VSX | POWERPC_FLAG_SCV;
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
}

File diff suppressed because it is too large Load Diff

View File

@ -320,6 +320,9 @@ static void gdb_gen_spr_feature(CPUState *cs)
continue;
}
gdb_feature_builder_append_reg(&builder, g_ascii_strdown(spr->name, -1),
TARGET_LONG_BITS, num_regs,
"int", "spr");
/*
* GDB identifies registers based on the order they are
* presented in the XML. These ids will not match QEMU's
@ -330,10 +333,6 @@ static void gdb_gen_spr_feature(CPUState *cs)
*/
spr->gdb_id = num_regs;
num_regs++;
gdb_feature_builder_append_reg(&builder, g_ascii_strdown(spr->name, -1),
TARGET_LONG_BITS, num_regs,
"int", "spr");
}
gdb_feature_builder_end(&builder);

View File

@ -264,6 +264,11 @@ int hreg_store_msr(CPUPPCState *env, target_ulong value, int alter_hv)
value &= ~MSR_HVB;
value |= env->msr & MSR_HVB;
}
/* Attempt to modify MSR[ME] in guest state is ignored */
if (is_book3s_arch2x(env) && !(env->msr & MSR_HVB)) {
value &= ~(1 << MSR_ME);
value |= env->msr & (1 << MSR_ME);
}
if ((value ^ env->msr) & (R_MSR_IR_MASK | R_MSR_DR_MASK)) {
cpu_interrupt_exittb(cs);
}

View File

@ -187,6 +187,12 @@
&X_a ra
@X_a ...... ra:3 .. ..... ..... .......... . &X_a
&XO rt ra rb oe:bool rc:bool
@XO ...... rt:5 ra:5 rb:5 oe:1 ......... rc:1 &XO
&XO_ta rt ra oe:bool rc:bool
@XO_ta ...... rt:5 ra:5 ..... oe:1 ......... rc:1 &XO_ta
%xx_xt 0:1 21:5
%xx_xb 1:1 11:5
%xx_xa 2:1 16:5
@ -322,10 +328,30 @@ CMPLI 001010 ... - . ..... ................ @D_bfu
### Fixed-Point Arithmetic Instructions
ADD 011111 ..... ..... ..... . 100001010 . @XO
ADDC 011111 ..... ..... ..... . 000001010 . @XO
ADDE 011111 ..... ..... ..... . 010001010 . @XO
# ADDEX is Z23-form, with CY=0; all other values for CY are reserved.
# This works out the same as X-form.
ADDEX 011111 ..... ..... ..... 00 10101010 - @X
ADDI 001110 ..... ..... ................ @D
ADDIS 001111 ..... ..... ................ @D
ADDIC 001100 ..... ..... ................ @D
ADDIC_ 001101 ..... ..... ................ @D
ADDPCIS 010011 ..... ..... .......... 00010 . @DX
ADDME 011111 ..... ..... ----- . 011101010 . @XO_ta
ADDZE 011111 ..... ..... ----- . 011001010 . @XO_ta
SUBF 011111 ..... ..... ..... . 000101000 . @XO
SUBFIC 001000 ..... ..... ................ @D
SUBFC 011111 ..... ..... ..... . 000001000 . @XO
SUBFE 011111 ..... ..... ..... . 010001000 . @XO
SUBFME 011111 ..... ..... ----- . 011101000 . @XO_ta
SUBFZE 011111 ..... ..... ----- . 011001000 . @XO_ta
## Fixed-Point Logical Instructions

View File

@ -2365,17 +2365,6 @@ static void kvmppc_host_cpu_class_init(ObjectClass *oc, void *data)
#if defined(TARGET_PPC64)
pcc->radix_page_info = kvmppc_get_radix_page_info();
if ((pcc->pvr & 0xffffff00) == CPU_POWERPC_POWER9_DD1) {
/*
* POWER9 DD1 has some bugs which make it not really ISA 3.00
* compliant. More importantly, advertising ISA 3.00
* architected mode may prevent guests from activating
* necessary DD1 workarounds.
*/
pcc->pcr_supported &= ~(PCR_COMPAT_3_00 | PCR_COMPAT_2_07
| PCR_COMPAT_2_06 | PCR_COMPAT_2_05);
}
#endif /* defined(TARGET_PPC64) */
}

View File

@ -49,9 +49,6 @@ void helper_spr_core_write_generic(CPUPPCState *env, uint32_t sprn,
CPUState *cs = env_cpu(env);
CPUState *ccs;
uint32_t nr_threads = cs->nr_threads;
uint32_t core_id = env->spr[SPR_PIR] & ~(nr_threads - 1);
assert(core_id == env->spr[SPR_PIR] - env->spr[SPR_TIR]);
if (nr_threads == 1) {
env->spr[sprn] = val;

View File

@ -296,33 +296,26 @@ static inline void gen_update_nip(DisasContext *ctx, target_ulong nip)
tcg_gen_movi_tl(cpu_nip, nip);
}
static void gen_exception_err(DisasContext *ctx, uint32_t excp, uint32_t error)
static void gen_exception_err_nip(DisasContext *ctx, uint32_t excp,
uint32_t error, target_ulong nip)
{
TCGv_i32 t0, t1;
/*
* These are all synchronous exceptions, we set the PC back to the
* faulting instruction
*/
gen_update_nip(ctx, ctx->cia);
gen_update_nip(ctx, nip);
t0 = tcg_constant_i32(excp);
t1 = tcg_constant_i32(error);
gen_helper_raise_exception_err(tcg_env, t0, t1);
ctx->base.is_jmp = DISAS_NORETURN;
}
static void gen_exception(DisasContext *ctx, uint32_t excp)
static inline void gen_exception_err(DisasContext *ctx, uint32_t excp,
uint32_t error)
{
TCGv_i32 t0;
/*
* These are all synchronous exceptions, we set the PC back to the
* faulting instruction
*/
gen_update_nip(ctx, ctx->cia);
t0 = tcg_constant_i32(excp);
gen_helper_raise_exception(tcg_env, t0);
ctx->base.is_jmp = DISAS_NORETURN;
gen_exception_err_nip(ctx, excp, error, ctx->cia);
}
static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
@ -336,6 +329,15 @@ static void gen_exception_nip(DisasContext *ctx, uint32_t excp,
ctx->base.is_jmp = DISAS_NORETURN;
}
static inline void gen_exception(DisasContext *ctx, uint32_t excp)
{
/*
* These are all synchronous exceptions, we set the PC back to the
* faulting instruction
*/
gen_exception_nip(ctx, excp, ctx->cia);
}
#if !defined(CONFIG_USER_ONLY)
static void gen_ppc_maybe_interrupt(DisasContext *ctx)
{
@ -1735,61 +1737,6 @@ static inline void gen_op_arith_add(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
/* Add functions with two operands */
#define GEN_INT_ARITH_ADD(name, opc3, ca, add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
ca, glue(ca, 32), \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* Add functions with one operand and one immediate */
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, ca, \
add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv t0 = tcg_constant_tl(const_val); \
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], t0, \
ca, glue(ca, 32), \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* add add. addo addo. */
GEN_INT_ARITH_ADD(add, 0x08, cpu_ca, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, cpu_ca, 0, 0, 1)
/* addc addc. addco addco. */
GEN_INT_ARITH_ADD(addc, 0x00, cpu_ca, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, cpu_ca, 0, 1, 1)
/* adde adde. addeo addeo. */
GEN_INT_ARITH_ADD(adde, 0x04, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, cpu_ca, 1, 1, 1)
/* addme addme. addmeo addmeo. */
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, cpu_ca, 1, 1, 1)
/* addex */
GEN_INT_ARITH_ADD(addex, 0x05, cpu_ov, 1, 1, 0);
/* addze addze. addzeo addzeo.*/
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, cpu_ca, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, cpu_ca, 1, 1, 1)
/* addic addic.*/
static inline void gen_op_addic(DisasContext *ctx, bool compute_rc0)
{
TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
gen_op_arith_add(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
c, cpu_ca, cpu_ca32, 0, 1, 0, compute_rc0);
}
static void gen_addic(DisasContext *ctx)
{
gen_op_addic(ctx, 0);
}
static void gen_addic_(DisasContext *ctx)
{
gen_op_addic(ctx, 1);
}
static inline void gen_op_arith_divw(DisasContext *ctx, TCGv ret, TCGv arg1,
TCGv arg2, int sign, int compute_ov)
@ -2210,47 +2157,6 @@ static inline void gen_op_arith_subf(DisasContext *ctx, TCGv ret, TCGv arg1,
tcg_gen_mov_tl(ret, t0);
}
}
/* Sub functions with Two operands functions */
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], cpu_gpr[rB(ctx->opcode)], \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* Sub functions with one operand and one immediate */
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
static void glue(gen_, name)(DisasContext *ctx) \
{ \
TCGv t0 = tcg_constant_tl(const_val); \
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], \
cpu_gpr[rA(ctx->opcode)], t0, \
add_ca, compute_ca, compute_ov, Rc(ctx->opcode)); \
}
/* subf subf. subfo subfo. */
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
/* subfc subfc. subfco subfco. */
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
/* subfe subfe. subfeo subfo. */
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
/* subfme subfme. subfmeo subfmeo. */
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
/* subfze subfze. subfzeo subfzeo.*/
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
/* subfic */
static void gen_subfic(DisasContext *ctx)
{
TCGv c = tcg_constant_tl(SIMM(ctx->opcode));
gen_op_arith_subf(ctx, cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)],
c, 0, 1, 0, 0);
}
/* neg neg. nego nego. */
static inline void gen_op_arith_neg(DisasContext *ctx, bool compute_ov)
@ -6524,8 +6430,6 @@ GEN_HANDLER_E(cmpeqb, 0x1F, 0x00, 0x07, 0x00600000, PPC_NONE, PPC2_ISA300),
GEN_HANDLER_E(cmpb, 0x1F, 0x1C, 0x0F, 0x00000001, PPC_NONE, PPC2_ISA205),
GEN_HANDLER_E(cmprb, 0x1F, 0x00, 0x06, 0x00400001, PPC_NONE, PPC2_ISA300),
GEN_HANDLER(isel, 0x1F, 0x0F, 0xFF, 0x00000001, PPC_ISEL),
GEN_HANDLER(addic, 0x0C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(addic_, "addic.", 0x0D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(mulhw, 0x1F, 0x0B, 0x02, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mulhwu, 0x1F, 0x0B, 0x00, 0x00000400, PPC_INTEGER),
GEN_HANDLER(mullw, 0x1F, 0x0B, 0x07, 0x00000000, PPC_INTEGER),
@ -6536,7 +6440,6 @@ GEN_HANDLER(mulld, 0x1F, 0x09, 0x07, 0x00000000, PPC_64B),
#endif
GEN_HANDLER(neg, 0x1F, 0x08, 0x03, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(nego, 0x1F, 0x08, 0x13, 0x0000F800, PPC_INTEGER),
GEN_HANDLER(subfic, 0x08, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andi_, "andi.", 0x1C, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER2(andis_, "andis.", 0x1D, 0xFF, 0xFF, 0x00000000, PPC_INTEGER),
GEN_HANDLER(cntlzw, 0x1F, 0x1A, 0x00, 0x00000000, PPC_INTEGER),
@ -6747,25 +6650,6 @@ GEN_HANDLER_E(maddhd_maddhdu, 0x04, 0x18, 0xFF, 0x00000000, PPC_NONE,
GEN_HANDLER_E(maddld, 0x04, 0x19, 0xFF, 0x00000000, PPC_NONE, PPC2_ISA300),
#endif
#undef GEN_INT_ARITH_ADD
#undef GEN_INT_ARITH_ADD_CONST
#define GEN_INT_ARITH_ADD(name, opc3, add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x00000000, PPC_INTEGER),
#define GEN_INT_ARITH_ADD_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0A, opc3, 0x0000F800, PPC_INTEGER),
GEN_INT_ARITH_ADD(add, 0x08, 0, 0, 0)
GEN_INT_ARITH_ADD(addo, 0x18, 0, 0, 1)
GEN_INT_ARITH_ADD(addc, 0x00, 0, 1, 0)
GEN_INT_ARITH_ADD(addco, 0x10, 0, 1, 1)
GEN_INT_ARITH_ADD(adde, 0x04, 1, 1, 0)
GEN_INT_ARITH_ADD(addeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_ADD_CONST(addme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addmeo, 0x17, -1LL, 1, 1, 1)
GEN_HANDLER_E(addex, 0x1F, 0x0A, 0x05, 0x00000000, PPC_NONE, PPC2_ISA300),
GEN_INT_ARITH_ADD_CONST(addze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_ADD_CONST(addzeo, 0x16, 0, 1, 1, 1)
#undef GEN_INT_ARITH_DIVW
#define GEN_INT_ARITH_DIVW(name, opc3, sign, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x0B, opc3, 0x00000000, PPC_INTEGER)
@ -6804,24 +6688,6 @@ GEN_INT_ARITH_MUL_HELPER(mulhd, 0x02),
GEN_INT_ARITH_MUL_HELPER(mulldo, 0x17),
#endif
#undef GEN_INT_ARITH_SUBF
#undef GEN_INT_ARITH_SUBF_CONST
#define GEN_INT_ARITH_SUBF(name, opc3, add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x00000000, PPC_INTEGER),
#define GEN_INT_ARITH_SUBF_CONST(name, opc3, const_val, \
add_ca, compute_ca, compute_ov) \
GEN_HANDLER(name, 0x1F, 0x08, opc3, 0x0000F800, PPC_INTEGER),
GEN_INT_ARITH_SUBF(subf, 0x01, 0, 0, 0)
GEN_INT_ARITH_SUBF(subfo, 0x11, 0, 0, 1)
GEN_INT_ARITH_SUBF(subfc, 0x00, 0, 1, 0)
GEN_INT_ARITH_SUBF(subfco, 0x10, 0, 1, 1)
GEN_INT_ARITH_SUBF(subfe, 0x04, 1, 1, 0)
GEN_INT_ARITH_SUBF(subfeo, 0x14, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfme, 0x07, -1LL, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfmeo, 0x17, -1LL, 1, 1, 1)
GEN_INT_ARITH_SUBF_CONST(subfze, 0x06, 0, 1, 1, 0)
GEN_INT_ARITH_SUBF_CONST(subfzeo, 0x16, 0, 1, 1, 1)
#undef GEN_LOGICAL1
#undef GEN_LOGICAL2
#define GEN_LOGICAL2(name, tcg_op, opc, type) \

View File

@ -325,6 +325,76 @@ static bool trans_ADDPCIS(DisasContext *ctx, arg_DX *a)
return true;
}
static bool trans_ADDEX(DisasContext *ctx, arg_X *a)
{
REQUIRE_INSNS_FLAGS2(ctx, ISA300);
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
cpu_ov, cpu_ov32, true, true, false, false);
return true;
}
static bool do_add_D(DisasContext *ctx, arg_D *a, bool add_ca, bool compute_ca,
bool compute_ov, bool compute_rc0)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
tcg_constant_tl(a->si), cpu_ca, cpu_ca32,
add_ca, compute_ca, compute_ov, compute_rc0);
return true;
}
static bool do_add_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
bool compute_ca)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
return true;
}
static bool do_add_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
bool add_ca, bool compute_ca)
{
gen_op_arith_add(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
cpu_ca, cpu_ca32, add_ca, compute_ca, a->oe, a->rc);
return true;
}
TRANS(ADD, do_add_XO, false, false);
TRANS(ADDC, do_add_XO, false, true);
TRANS(ADDE, do_add_XO, true, true);
TRANS(ADDME, do_add_const_XO, tcg_constant_tl(-1LL), true, true);
TRANS(ADDZE, do_add_const_XO, tcg_constant_tl(0), true, true);
TRANS(ADDIC, do_add_D, false, true, false, false);
TRANS(ADDIC_, do_add_D, false, true, false, true);
static bool trans_SUBFIC(DisasContext *ctx, arg_D *a)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra],
tcg_constant_tl(a->si), false, true, false, false);
return true;
}
static bool do_subf_XO(DisasContext *ctx, arg_XO *a, bool add_ca,
bool compute_ca)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], cpu_gpr[a->rb],
add_ca, compute_ca, a->oe, a->rc);
return true;
}
static bool do_subf_const_XO(DisasContext *ctx, arg_XO_ta *a, TCGv const_val,
bool add_ca, bool compute_ca)
{
gen_op_arith_subf(ctx, cpu_gpr[a->rt], cpu_gpr[a->ra], const_val,
add_ca, compute_ca, a->oe, a->rc);
return true;
}
TRANS(SUBF, do_subf_XO, false, false)
TRANS(SUBFC, do_subf_XO, false, true)
TRANS(SUBFE, do_subf_XO, true, true)
TRANS(SUBFME, do_subf_const_XO, tcg_constant_tl(-1LL), true, true)
TRANS(SUBFZE, do_subf_const_XO, tcg_constant_tl(0), true, true)
static bool trans_INVALID(DisasContext *ctx, arg_INVALID *a)
{
gen_invalid(ctx);