ppc patch queue 2020-03-17

Here's my final pull request for the qemu-5.0 soft freeze.  Sorry this
 is just under the wire - I hit some last minute problems that took a
 while to fix up and retest.
 
 Highlights are:
  * Numerous fixes for the FWNMI feature
  * A handful of cleanups to the device tree construction code
  * Numerous fixes for the spapr-vscsi device
  * A number of fixes and cleanups for real mode (MMU off) softmmu
    handling
  * Fixes for handling of the PAPR RMA
  * Better handling of hotplug/unplug events during boot
  * Assorted other fixes
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCAAdFiEEdfRlhq5hpmzETofcbDjKyiDZs5IFAl5wnnsACgkQbDjKyiDZ
 s5JdpQ//eY/AOTs09UhvKxt8DN7lC2WyHGxYSncb2Tj2zaJyPPX9p296IDBMw+KX
 Cafr6LzwLjpcpOyf/EWzg7qYGbNYoYgRWoOkHI/9pHsrIH3ZvhmnyTVQI5CffeEb
 EDDXJUQo/2sFpAGeODr5zz+zAQUGzt6ZZUxAiQAF9RYc9ohUGD2x5c86Asx6ZTZo
 /14bd3qnrcy1x+TxDetb1idFxFr2DsdYqpHAi88zHm+UaWzxYrb7kakd+YbqI24N
 tYryf5SdtGrWAAdF/7nq2PQJFzskx+t0QearU+ruovRydxYbUtBpkr5HauoVuQXR
 LiV270sDYDS/D1vvQQKzLxkUuvWmbZ0rB+2BAtS1rwq2sOKqYyQEAkTWfGtSXcf8
 7fuZm2i1G78MuYGTOLCrF1u0owUB3QYHvt1NUW09GyWS8X3mahtj2fRe1RtPV/5d
 NL217bcd32fkMoGCg/lFvK9sCQzR6zJGKkJvOGMVW4ahHCLixpjIWabWtdXjfguT
 UahRPvlX7fzeVT+DISfjqyxwL+THnTvB3CTMWG2cktf0K1ke4SXcQ0mPyksN1NuC
 QocfPCr1TN2ri8g9dAPwQmOkojnNs9izpIWRYSl3avTJFNseNPxuHQALXj2Y3Y/O
 EoYxLN+cqPukQ1O3GxEj5QMKe8V/0986mxWnuS/dMohQOoy+zV4=
 =BPnR
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-5.0-20200317' into staging

ppc patch queue 2020-03-17

Here's my final pull request for the qemu-5.0 soft freeze.  Sorry this
is just under the wire - I hit some last minute problems that took a
while to fix up and retest.

Highlights are:
 * Numerous fixes for the FWNMI feature
 * A handful of cleanups to the device tree construction code
 * Numerous fixes for the spapr-vscsi device
 * A number of fixes and cleanups for real mode (MMU off) softmmu
   handling
 * Fixes for handling of the PAPR RMA
 * Better handling of hotplug/unplug events during boot
 * Assorted other fixes

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

* remotes/dgibson/tags/ppc-for-5.0-20200317: (45 commits)
  pseries: Update SLOF firmware image
  ppc/spapr: Ignore common "ibm,nmi-interlock" Linux bug
  ppc/spapr: Implement FWNMI System Reset delivery
  target/ppc: allow ppc_cpu_do_system_reset to take an alternate vector
  ppc/spapr: Allow FWNMI on TCG
  ppc/spapr: Fix FWNMI machine check interrupt delivery
  ppc/spapr: Add FWNMI System Reset state
  ppc/spapr: Change FWNMI names
  ppc/spapr: Fix FWNMI machine check failure handling
  spapr: Rename DT functions to newer naming convention
  spapr: Move creation of ibm,architecture-vec-5 property
  spapr: Move creation of ibm,dynamic-reconfiguration-memory dt node
  spapr/rtas: Reserve space for RTAS blob and log
  pseries: Update SLOF firmware image
  ppc/spapr: Move GPRs setup to one place
  target/ppc: Fix rlwinm on ppc64
  spapr/xive: use SPAPR_IRQ_IPI to define IPI ranges exposed to the guest
  hw/scsi/spapr_vscsi: Convert debug fprintf() to trace event
  hw/scsi/spapr_vscsi: Prevent buffer overflow
  hw/scsi/spapr_vscsi: Do not mix SRP IU size with DMA buffer size
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2020-03-18 15:07:57 +00:00
commit b319df5537
29 changed files with 917 additions and 907 deletions

View File

@ -289,6 +289,13 @@ The RISC-V no MMU cpus have been depcreated. The two CPUs: ``rv32imacu-nommu`` a
``rv64imacu-nommu`` should no longer be used. Instead the MMU status can be specified
via the CPU ``mmu`` option when using the ``rv32`` or ``rv64`` CPUs.
``compat`` property of server class POWER CPUs (since 5.0)
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
The ``compat`` property used to set backwards compatibility modes for
the processor has been deprecated. The ``max-cpu-compat`` property of
the ``pseries`` machine type should be used instead.
System emulator devices
-----------------------

View File

@ -677,8 +677,8 @@ static void spapr_xive_dt(SpaprInterruptController *intc, uint32_t nr_servers,
uint64_t timas[2 * 2];
/* Interrupt number ranges for the IPIs */
uint32_t lisn_ranges[] = {
cpu_to_be32(0),
cpu_to_be32(nr_servers),
cpu_to_be32(SPAPR_IRQ_IPI),
cpu_to_be32(SPAPR_IRQ_IPI + nr_servers),
};
/*
* EQ size - the sizes of pages supported by the system 4K, 64K,

View File

@ -829,7 +829,7 @@ ISABus *pnv_lpc_isa_create(PnvLpcController *lpc, bool use_cpld, Error **errp)
bool hostboot_mode = !!pnv->fw_load_addr;
/* let isa_bus_new() create its own bridge on SysBus otherwise
* devices speficied on the command line won't find the bus and
* devices specified on the command line won't find the bus and
* will fail to create.
*/
isa_bus = isa_bus_new(NULL, &lpc->isa_mem, &lpc->isa_io, &local_err);

File diff suppressed because it is too large Load Diff

View File

@ -509,17 +509,14 @@ static void cap_ccf_assist_apply(SpaprMachineState *spapr, uint8_t val,
}
}
static void cap_fwnmi_mce_apply(SpaprMachineState *spapr, uint8_t val,
static void cap_fwnmi_apply(SpaprMachineState *spapr, uint8_t val,
Error **errp)
{
if (!val) {
return; /* Disabled by default */
}
if (tcg_enabled()) {
warn_report("Firmware Assisted Non-Maskable Interrupts(FWNMI) not "
"supported in TCG");
} else if (kvm_enabled()) {
if (kvm_enabled()) {
if (kvmppc_set_fwnmi() < 0) {
error_setg(errp, "Firmware Assisted Non-Maskable Interrupts(FWNMI) "
"not supported by KVM");
@ -626,14 +623,14 @@ SpaprCapabilityInfo capability_table[SPAPR_CAP_NUM] = {
.type = "bool",
.apply = cap_ccf_assist_apply,
},
[SPAPR_CAP_FWNMI_MCE] = {
.name = "fwnmi-mce",
.description = "Handle fwnmi machine check exceptions",
.index = SPAPR_CAP_FWNMI_MCE,
[SPAPR_CAP_FWNMI] = {
.name = "fwnmi",
.description = "Implements PAPR FWNMI option",
.index = SPAPR_CAP_FWNMI,
.get = spapr_cap_get_bool,
.set = spapr_cap_set_bool,
.type = "bool",
.apply = cap_fwnmi_mce_apply,
.apply = cap_fwnmi_apply,
},
};
@ -774,7 +771,7 @@ 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(large_decr, SPAPR_CAP_LARGE_DECREMENTER);
SPAPR_CAP_MIG_STATE(ccf_assist, SPAPR_CAP_CCF_ASSIST);
SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI_MCE);
SPAPR_CAP_MIG_STATE(fwnmi, SPAPR_CAP_FWNMI);
void spapr_caps_init(SpaprMachineState *spapr)
{

View File

@ -50,22 +50,14 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
* the settings below ensure proper operations with TCG in absence of
* a real hypervisor.
*
* Clearing VPM0 will also cause us to use RMOR in mmu-hash64.c for
* real mode accesses, which thankfully defaults to 0 and isn't
* accessible in guest mode.
*
* Disable Power-saving mode Exit Cause exceptions for the CPU, so
* we don't get spurious wakups before an RTAS start-cpu call.
* For the same reason, set PSSCR_EC.
*/
lpcr &= ~(LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
lpcr &= ~(LPCR_VPM1 | LPCR_ISL | LPCR_KBV | pcc->lpcr_pm);
lpcr |= LPCR_LPES0 | LPCR_LPES1;
env->spr[SPR_PSSCR] |= PSSCR_EC;
/* Set RMLS to the max (ie, 16G) */
lpcr &= ~LPCR_RMLS;
lpcr |= 1ull << LPCR_RMLS_SHIFT;
ppc_store_lpcr(cpu, lpcr);
/* Set a full AMOR so guest can use the AMR as it sees fit */
@ -84,13 +76,17 @@ static void spapr_reset_vcpu(PowerPCCPU *cpu)
spapr_irq_cpu_intc_reset(spapr, cpu);
}
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3)
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
target_ulong r1, target_ulong r3,
target_ulong r4)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
env->nip = nip;
env->gpr[1] = r1;
env->gpr[3] = r3;
env->gpr[4] = r4;
kvmppc_set_reg_ppc_online(cpu, 1);
CPU(cpu)->halted = 0;
/* Enable Power-saving mode Exit Cause exceptions */

View File

@ -786,28 +786,12 @@ static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered)
{
SpaprMachineState *spapr = SPAPR_MACHINE(qdev_get_machine());
CPUState *cs = CPU(cpu);
uint64_t rtas_addr;
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
target_ulong msr = 0;
uint64_t rtas_addr;
struct rtas_error_log log;
struct mc_extended_log *ext_elog;
uint32_t summary;
/*
* Properly set bits in MSR before we invoke the handler.
* SRR0/1, DAR and DSISR are properly set by KVM
*/
if (!(*pcc->interrupts_big_endian)(cpu)) {
msr |= (1ULL << MSR_LE);
}
if (env->msr & (1ULL << MSR_SF)) {
msr |= (1ULL << MSR_SF);
}
msr |= (1ULL << MSR_ME);
ext_elog = g_malloc0(sizeof(*ext_elog));
summary = spapr_mce_get_elog_type(cpu, recovered, ext_elog);
@ -823,8 +807,7 @@ static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered)
/* get rtas addr from fdt */
rtas_addr = spapr_get_rtas_addr();
if (!rtas_addr) {
/* Unable to fetch rtas_addr. Hence reset the guest */
ppc_cpu_do_system_reset(cs);
qemu_system_guest_panicked(NULL);
g_free(ext_elog);
return;
}
@ -836,12 +819,11 @@ static void spapr_mce_dispatch_elog(PowerPCCPU *cpu, bool recovered)
cpu_physical_memory_write(rtas_addr + RTAS_ERROR_LOG_OFFSET +
sizeof(env->gpr[3]) + sizeof(log), ext_elog,
sizeof(*ext_elog));
g_free(ext_elog);
env->gpr[3] = rtas_addr + RTAS_ERROR_LOG_OFFSET;
env->msr = msr;
env->nip = spapr->guest_machine_check_addr;
g_free(ext_elog);
ppc_cpu_do_fwnmi_machine_check(cs, spapr->fwnmi_machine_check_addr);
}
void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
@ -851,7 +833,7 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
int ret;
Error *local_err = NULL;
if (spapr->guest_machine_check_addr == -1) {
if (spapr->fwnmi_machine_check_addr == -1) {
/*
* This implies that we have hit a machine check either when the
* guest has not registered FWNMI (i.e., "ibm,nmi-register" not
@ -863,19 +845,19 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
return;
}
while (spapr->mc_status != -1) {
while (spapr->fwnmi_machine_check_interlock != -1) {
/*
* Check whether the same CPU got machine check error
* while still handling the mc error (i.e., before
* that CPU called "ibm,nmi-interlock")
*/
if (spapr->mc_status == cpu->vcpu_id) {
if (spapr->fwnmi_machine_check_interlock == cpu->vcpu_id) {
qemu_system_guest_panicked(NULL);
return;
}
qemu_cond_wait_iothread(&spapr->mc_delivery_cond);
qemu_cond_wait_iothread(&spapr->fwnmi_machine_check_interlock_cond);
/* Meanwhile if the system is reset, then just return */
if (spapr->guest_machine_check_addr == -1) {
if (spapr->fwnmi_machine_check_addr == -1) {
return;
}
}
@ -891,7 +873,7 @@ void spapr_mce_req_event(PowerPCCPU *cpu, bool recovered)
warn_report("Received a fwnmi while migration was in progress");
}
spapr->mc_status = cpu->vcpu_id;
spapr->fwnmi_machine_check_interlock = cpu->vcpu_id;
spapr_mce_dispatch_elog(cpu, recovered);
}
@ -983,6 +965,19 @@ void spapr_clear_pending_events(SpaprMachineState *spapr)
}
}
void spapr_clear_pending_hotplug_events(SpaprMachineState *spapr)
{
SpaprEventLogEntry *entry = NULL, *next_entry;
QTAILQ_FOREACH_SAFE(entry, &spapr->pending_events, next, next_entry) {
if (spapr_event_log_entry_type(entry) == RTAS_LOG_TYPE_HOTPLUG) {
QTAILQ_REMOVE(&spapr->pending_events, entry, next);
g_free(entry->extended_log);
g_free(entry);
}
}
}
void spapr_events_init(SpaprMachineState *spapr)
{
int epow_irq = SPAPR_IRQ_EPOW;

View File

@ -1458,7 +1458,7 @@ static void spapr_check_setup_free_hpt(SpaprMachineState *spapr,
spapr_free_hpt(spapr);
} else if (!(patbe_new & PATE1_GR)) {
/* RADIX->HASH || NOTHING->HASH : Allocate HPT */
spapr_setup_hpt_and_vrma(spapr);
spapr_setup_hpt(spapr);
}
return;
}
@ -1640,7 +1640,7 @@ static uint32_t cas_check_pvr(SpaprMachineState *spapr, PowerPCCPU *cpu,
return best_compat;
}
static bool spapr_transient_dev_before_cas(void)
static void spapr_handle_transient_dev_before_cas(SpaprMachineState *spapr)
{
Object *drc_container;
ObjectProperty *prop;
@ -1658,10 +1658,11 @@ static bool spapr_transient_dev_before_cas(void)
prop->name, NULL));
if (spapr_drc_transient(drc)) {
return true;
spapr_drc_reset(drc);
}
}
return false;
spapr_clear_pending_hotplug_events(spapr);
}
static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
@ -1834,9 +1835,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
spapr_irq_update_active_intc(spapr);
if (spapr_transient_dev_before_cas()) {
spapr->cas_reboot = true;
}
spapr_handle_transient_dev_before_cas(spapr);
if (!spapr->cas_reboot) {
void *fdt;
@ -1846,7 +1845,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
* (because the guest isn't going to use radix) then set it up here. */
if ((spapr->patb_entry & PATE1_GR) && !guest_radix) {
/* legacy hash or new hash: */
spapr_setup_hpt_and_vrma(spapr);
spapr_setup_hpt(spapr);
}
if (fdt_bufsize < sizeof(hdr)) {

View File

@ -35,6 +35,7 @@ void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size,
{
char *uuidstr = NULL;
QemuUUID uuid;
int ret;
if (size % SPAPR_MINIMUM_SCM_BLOCK_SIZE) {
error_setg(errp, "NVDIMM memory size excluding the label area"
@ -43,8 +44,10 @@ void spapr_nvdimm_validate_opts(NVDIMMDevice *nvdimm, uint64_t size,
return;
}
uuidstr = object_property_get_str(OBJECT(nvdimm), NVDIMM_UUID_PROP, NULL);
qemu_uuid_parse(uuidstr, &uuid);
uuidstr = object_property_get_str(OBJECT(nvdimm), NVDIMM_UUID_PROP,
&error_abort);
ret = qemu_uuid_parse(uuidstr, &uuid);
g_assert(!ret);
g_free(uuidstr);
if (qemu_uuid_is_null(&uuid)) {

View File

@ -200,8 +200,8 @@ SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector)
return ov;
}
int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name)
int spapr_dt_ovec(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name)
{
uint8_t vec[OV_MAXBYTES + 1];
uint16_t vec_len;

View File

@ -190,7 +190,7 @@ static void rtas_start_cpu(PowerPCCPU *callcpu, SpaprMachineState *spapr,
*/
newcpu->env.tb_env->tb_offset = callcpu->env.tb_env->tb_offset;
spapr_cpu_set_entry_state(newcpu, start, r3);
spapr_cpu_set_entry_state(newcpu, start, 0, r3, 0);
qemu_cpu_kick(CPU(newcpu));
@ -414,8 +414,9 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
uint32_t nret, target_ulong rets)
{
hwaddr rtas_addr;
target_ulong sreset_addr, mce_addr;
if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI_MCE) == SPAPR_CAP_OFF) {
if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
return;
}
@ -426,7 +427,19 @@ static void rtas_ibm_nmi_register(PowerPCCPU *cpu,
return;
}
spapr->guest_machine_check_addr = rtas_ld(args, 1);
sreset_addr = rtas_ld(args, 0);
mce_addr = rtas_ld(args, 1);
/* PAPR requires these are in the first 32M of memory and within RMA */
if (sreset_addr >= 32 * MiB || sreset_addr >= spapr->rma_size ||
mce_addr >= 32 * MiB || mce_addr >= spapr->rma_size) {
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
spapr->fwnmi_system_reset_addr = sreset_addr;
spapr->fwnmi_machine_check_addr = mce_addr;
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
}
@ -436,29 +449,39 @@ static void rtas_ibm_nmi_interlock(PowerPCCPU *cpu,
target_ulong args,
uint32_t nret, target_ulong rets)
{
if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI_MCE) == SPAPR_CAP_OFF) {
if (spapr_get_cap(spapr, SPAPR_CAP_FWNMI) == SPAPR_CAP_OFF) {
rtas_st(rets, 0, RTAS_OUT_NOT_SUPPORTED);
return;
}
if (spapr->guest_machine_check_addr == -1) {
if (spapr->fwnmi_machine_check_addr == -1) {
/* NMI register not called */
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
return;
}
if (spapr->mc_status != cpu->vcpu_id) {
/* The vCPU that hit the NMI should invoke "ibm,nmi-interlock" */
rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
if (spapr->fwnmi_machine_check_interlock != cpu->vcpu_id) {
/*
* The vCPU that hit the NMI should invoke "ibm,nmi-interlock"
* This should be PARAM_ERROR, but Linux calls "ibm,nmi-interlock"
* for system reset interrupts, despite them not being interlocked.
* PowerVM silently ignores this and returns success here. Returning
* failure causes Linux to print the error "FWNMI: nmi-interlock
* failed: -3", although no other apparent ill effects, this is a
* regression for the user when enabling FWNMI. So for now, match
* PowerVM. When most Linux clients are fixed, this could be
* changed.
*/
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
return;
}
/*
* vCPU issuing "ibm,nmi-interlock" is done with NMI handling,
* hence unset mc_status.
* hence unset fwnmi_machine_check_interlock.
*/
spapr->mc_status = -1;
qemu_cond_signal(&spapr->mc_delivery_cond);
spapr->fwnmi_machine_check_interlock = -1;
qemu_cond_signal(&spapr->fwnmi_machine_check_interlock_cond);
rtas_st(rets, 0, RTAS_OUT_SUCCESS);
migrate_del_blocker(spapr->fwnmi_migration_blocker);
}

View File

@ -55,6 +55,8 @@
#define VSCSI_MAX_SECTORS 4096
#define VSCSI_REQ_LIMIT 24
/* Maximum size of a IU payload */
#define SRP_MAX_IU_DATA_LEN (SRP_MAX_IU_LEN - sizeof(union srp_iu))
#define SRP_RSP_SENSE_DATA_LEN 18
#define SRP_REPORT_LUNS_WLUN 0xc10100000000000ULL
@ -66,7 +68,7 @@ typedef union vscsi_crq {
typedef struct vscsi_req {
vscsi_crq crq;
union viosrp_iu iu;
uint8_t viosrp_iu_buf[SRP_MAX_IU_LEN];
/* SCSI request tracking */
SCSIRequest *sreq;
@ -97,6 +99,11 @@ typedef struct {
vscsi_req reqs[VSCSI_REQ_LIMIT];
} VSCSIState;
static union viosrp_iu *req_iu(vscsi_req *req)
{
return (union viosrp_iu *)req->viosrp_iu_buf;
}
static struct vscsi_req *vscsi_get_req(VSCSIState *s)
{
vscsi_req *req;
@ -121,7 +128,7 @@ static struct vscsi_req *vscsi_find_req(VSCSIState *s, uint64_t srp_tag)
for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
req = &s->reqs[i];
if (req->iu.srp.cmd.tag == srp_tag) {
if (req_iu(req)->srp.cmd.tag == srp_tag) {
return req;
}
}
@ -176,9 +183,11 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
{
long rc, rc1;
assert(length <= SRP_MAX_IU_LEN);
/* First copy the SRP */
rc = spapr_vio_dma_write(&s->vdev, req->crq.s.IU_data_ptr,
&req->iu, length);
&req->viosrp_iu_buf, length);
if (rc) {
fprintf(stderr, "vscsi_send_iu: DMA write failure !\n");
}
@ -188,7 +197,7 @@ static int vscsi_send_iu(VSCSIState *s, vscsi_req *req,
req->crq.s.reserved = 0x00;
req->crq.s.timeout = cpu_to_be16(0x0000);
req->crq.s.IU_length = cpu_to_be16(length);
req->crq.s.IU_data_ptr = req->iu.srp.rsp.tag; /* right byte order */
req->crq.s.IU_data_ptr = req_iu(req)->srp.rsp.tag; /* right byte order */
if (rc == 0) {
req->crq.s.status = VIOSRP_OK;
@ -224,7 +233,7 @@ static void vscsi_makeup_sense(VSCSIState *s, vscsi_req *req,
static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
uint8_t status, int32_t res_in, int32_t res_out)
{
union viosrp_iu *iu = &req->iu;
union viosrp_iu *iu = req_iu(req);
uint64_t tag = iu->srp.rsp.tag;
int total_len = sizeof(iu->srp.rsp);
uint8_t sol_not = iu->srp.cmd.sol_not;
@ -261,10 +270,12 @@ static int vscsi_send_rsp(VSCSIState *s, vscsi_req *req,
if (status) {
iu->srp.rsp.sol_not = (sol_not & 0x04) >> 2;
if (req->senselen) {
req->iu.srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
req->iu.srp.rsp.sense_data_len = cpu_to_be32(req->senselen);
memcpy(req->iu.srp.rsp.data, req->sense, req->senselen);
total_len += req->senselen;
int sense_data_len = MIN(req->senselen, SRP_MAX_IU_DATA_LEN);
iu->srp.rsp.flags |= SRP_RSP_FLAG_SNSVALID;
iu->srp.rsp.sense_data_len = cpu_to_be32(sense_data_len);
memcpy(iu->srp.rsp.data, req->sense, sense_data_len);
total_len += sense_data_len;
}
} else {
iu->srp.rsp.sol_not = (sol_not & 0x02) >> 1;
@ -285,7 +296,7 @@ static int vscsi_fetch_desc(VSCSIState *s, struct vscsi_req *req,
unsigned n, unsigned buf_offset,
struct srp_direct_buf *ret)
{
struct srp_cmd *cmd = &req->iu.srp.cmd;
struct srp_cmd *cmd = &req_iu(req)->srp.cmd;
switch (req->dma_fmt) {
case SRP_NO_DATA_DESC: {
@ -473,7 +484,7 @@ static int data_out_desc_size(struct srp_cmd *cmd)
static int vscsi_preprocess_desc(vscsi_req *req)
{
struct srp_cmd *cmd = &req->iu.srp.cmd;
struct srp_cmd *cmd = &req_iu(req)->srp.cmd;
req->cdb_offset = cmd->add_cdb_len & ~3;
@ -597,7 +608,7 @@ static const VMStateDescription vmstate_spapr_vscsi_req = {
.minimum_version_id = 1,
.fields = (VMStateField[]) {
VMSTATE_BUFFER(crq.raw, vscsi_req),
VMSTATE_BUFFER(iu.srp.reserved, vscsi_req),
VMSTATE_BUFFER(viosrp_iu_buf, vscsi_req),
VMSTATE_UINT32(qtag, vscsi_req),
VMSTATE_BOOL(active, vscsi_req),
VMSTATE_UINT32(data_len, vscsi_req),
@ -655,7 +666,7 @@ static void *vscsi_load_request(QEMUFile *f, SCSIRequest *sreq)
static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
{
union viosrp_iu *iu = &req->iu;
union viosrp_iu *iu = req_iu(req);
struct srp_login_rsp *rsp = &iu->srp.login_rsp;
uint64_t tag = iu->srp.rsp.tag;
@ -671,8 +682,8 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
*/
rsp->req_lim_delta = cpu_to_be32(VSCSI_REQ_LIMIT-2);
rsp->tag = tag;
rsp->max_it_iu_len = cpu_to_be32(sizeof(union srp_iu));
rsp->max_ti_iu_len = cpu_to_be32(sizeof(union srp_iu));
rsp->max_it_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
rsp->max_ti_iu_len = cpu_to_be32(SRP_MAX_IU_LEN);
/* direct and indirect */
rsp->buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT | SRP_BUF_FORMAT_INDIRECT);
@ -681,7 +692,7 @@ static void vscsi_process_login(VSCSIState *s, vscsi_req *req)
static void vscsi_inquiry_no_target(VSCSIState *s, vscsi_req *req)
{
uint8_t *cdb = req->iu.srp.cmd.cdb;
uint8_t *cdb = req_iu(req)->srp.cmd.cdb;
uint8_t resp_data[36];
int rc, len, alen;
@ -770,7 +781,7 @@ static void vscsi_report_luns(VSCSIState *s, vscsi_req *req)
static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
{
union srp_iu *srp = &req->iu.srp;
union srp_iu *srp = &req_iu(req)->srp;
SCSIDevice *sdev;
int n, lun;
@ -821,17 +832,16 @@ static int vscsi_queue_cmd(VSCSIState *s, vscsi_req *req)
static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
{
union viosrp_iu *iu = &req->iu;
union viosrp_iu *iu = req_iu(req);
vscsi_req *tmpreq;
int i, lun = 0, resp = SRP_TSK_MGMT_COMPLETE;
SCSIDevice *d;
uint64_t tag = iu->srp.rsp.tag;
uint8_t sol_not = iu->srp.cmd.sol_not;
fprintf(stderr, "vscsi_process_tsk_mgmt %02x\n",
iu->srp.tsk_mgmt.tsk_mgmt_func);
d = vscsi_device_find(&s->bus, be64_to_cpu(req->iu.srp.tsk_mgmt.lun), &lun);
trace_spapr_vscsi_process_tsk_mgmt(iu->srp.tsk_mgmt.tsk_mgmt_func);
d = vscsi_device_find(&s->bus,
be64_to_cpu(req_iu(req)->srp.tsk_mgmt.lun), &lun);
if (!d) {
resp = SRP_TSK_MGMT_FIELDS_INVALID;
} else {
@ -842,7 +852,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
break;
}
tmpreq = vscsi_find_req(s, req->iu.srp.tsk_mgmt.task_tag);
tmpreq = vscsi_find_req(s, req_iu(req)->srp.tsk_mgmt.task_tag);
if (tmpreq && tmpreq->sreq) {
assert(tmpreq->sreq->hba_private);
scsi_req_cancel(tmpreq->sreq);
@ -867,7 +877,8 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
for (i = 0; i < VSCSI_REQ_LIMIT; i++) {
tmpreq = &s->reqs[i];
if (tmpreq->iu.srp.cmd.lun != req->iu.srp.tsk_mgmt.lun) {
if (req_iu(tmpreq)->srp.cmd.lun
!= req_iu(req)->srp.tsk_mgmt.lun) {
continue;
}
if (!tmpreq->active || !tmpreq->sreq) {
@ -889,6 +900,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
}
/* Compose the response here as */
QEMU_BUILD_BUG_ON(SRP_MAX_IU_DATA_LEN < 4);
memset(iu, 0, sizeof(struct srp_rsp) + 4);
iu->srp.rsp.opcode = SRP_RSP;
iu->srp.rsp.req_lim_delta = cpu_to_be32(1);
@ -911,7 +923,7 @@ static int vscsi_process_tsk_mgmt(VSCSIState *s, vscsi_req *req)
static int vscsi_handle_srp_req(VSCSIState *s, vscsi_req *req)
{
union srp_iu *srp = &req->iu.srp;
union srp_iu *srp = &req_iu(req)->srp;
int done = 1;
uint8_t opcode = srp->rsp.opcode;
@ -948,7 +960,7 @@ static int vscsi_send_adapter_info(VSCSIState *s, vscsi_req *req)
struct mad_adapter_info_data info;
int rc;
sinfo = &req->iu.mad.adapter_info;
sinfo = &req_iu(req)->mad.adapter_info;
#if 0 /* What for ? */
rc = spapr_vio_dma_read(&s->vdev, be64_to_cpu(sinfo->buffer),
@ -984,7 +996,7 @@ static int vscsi_send_capabilities(VSCSIState *s, vscsi_req *req)
uint64_t buffer;
int rc;
vcap = &req->iu.mad.capabilities;
vcap = &req_iu(req)->mad.capabilities;
req_len = len = be16_to_cpu(vcap->common.length);
buffer = be64_to_cpu(vcap->buffer);
if (len > sizeof(cap)) {
@ -1029,7 +1041,7 @@ static int vscsi_send_capabilities(VSCSIState *s, vscsi_req *req)
static int vscsi_handle_mad_req(VSCSIState *s, vscsi_req *req)
{
union mad_iu *mad = &req->iu.mad;
union mad_iu *mad = &req_iu(req)->mad;
bool request_handled = false;
uint64_t retlen = 0;
@ -1088,7 +1100,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
* in our 256 bytes IUs. If not we'll have to increase the size
* of the structure.
*/
if (crq->s.IU_length > sizeof(union viosrp_iu)) {
if (crq->s.IU_length > SRP_MAX_IU_LEN) {
fprintf(stderr, "VSCSI: SRP IU too long (%d bytes) !\n",
crq->s.IU_length);
vscsi_put_req(req);
@ -1096,7 +1108,7 @@ static void vscsi_got_payload(VSCSIState *s, vscsi_crq *crq)
}
/* XXX Handle failure differently ? */
if (spapr_vio_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->iu,
if (spapr_vio_dma_read(&s->vdev, crq->s.IU_data_ptr, &req->viosrp_iu_buf,
crq->s.IU_length)) {
fprintf(stderr, "vscsi_got_payload: DMA read failure !\n");
vscsi_put_req(req);

View File

@ -227,6 +227,7 @@ spapr_vscsi_command_complete_status(uint32_t status) "Command complete err=%"PRI
spapr_vscsi_save_request(uint32_t qtag, unsigned desc, unsigned offset) "saving tag=%"PRIu32", current desc#%u, offset=0x%x"
spapr_vscsi_load_request(uint32_t qtag, unsigned desc, unsigned offset) "restoring tag=%"PRIu32", current desc#%u, offset=0x%x"
spapr_vscsi_process_login(void) "Got login, sending response !"
spapr_vscsi_process_tsk_mgmt(uint8_t func) "tsk_mgmt_func 0x%02x"
spapr_vscsi_queue_cmd_no_drive(uint64_t lun) "Command for lun 0x%08" PRIx64 " with no drive"
spapr_vscsi_queue_cmd(uint32_t qtag, unsigned cdb, const char *cmd, int lun, int ret) "Queued command tag 0x%"PRIx32" CMD 0x%x=%s LUN %d ret: %d"
spapr_vscsi_do_crq(unsigned c0, unsigned c1) "crq: %02x %02x ..."

View File

@ -34,6 +34,8 @@
#ifndef PPC_VIOSRP_H
#define PPC_VIOSRP_H
#include "hw/scsi/srp.h"
#define SRP_VERSION "16.a"
#define SRP_MAX_IU_LEN 256
#define SRP_MAX_LOC_LEN 32
@ -47,7 +49,6 @@ union srp_iu {
struct srp_tsk_mgmt tsk_mgmt;
struct srp_cmd cmd;
struct srp_rsp rsp;
uint8_t reserved[SRP_MAX_IU_LEN];
};
enum viosrp_crq_formats {

View File

@ -79,10 +79,10 @@ typedef enum {
#define SPAPR_CAP_LARGE_DECREMENTER 0x08
/* Count Cache Flush Assist HW Instruction */
#define SPAPR_CAP_CCF_ASSIST 0x09
/* FWNMI machine check handling */
#define SPAPR_CAP_FWNMI_MCE 0x0A
/* Implements PAPR FWNMI option */
#define SPAPR_CAP_FWNMI 0x0A
/* Num Caps */
#define SPAPR_CAP_NUM (SPAPR_CAP_FWNMI_MCE + 1)
#define SPAPR_CAP_NUM (SPAPR_CAP_FWNMI + 1)
/*
* Capability Values
@ -126,6 +126,7 @@ struct SpaprMachineClass {
bool pre_4_1_migration; /* don't migrate hpt-max-page-size */
bool linux_pci_probe;
bool smp_threads_vsmt; /* set VSMT to smp_threads by default */
hwaddr rma_limit; /* clamp the RMA to this size */
void (*phb_placement)(SpaprMachineState *spapr, uint32_t index,
uint64_t *buid, hwaddr *pio,
@ -156,7 +157,6 @@ struct SpaprMachineState {
SpaprPendingHpt *pending_hpt; /* in-progress resize */
hwaddr rma_size;
int vrma_adjust;
uint32_t fdt_size;
uint32_t fdt_initial_size;
void *fdt_blob;
@ -192,14 +192,22 @@ struct SpaprMachineState {
* occurs during the unplug process. */
QTAILQ_HEAD(, SpaprDimmState) pending_dimm_unplugs;
/* State related to "ibm,nmi-register" and "ibm,nmi-interlock" calls */
target_ulong guest_machine_check_addr;
/*
* mc_status is set to -1 if mc is not in progress, else is set to the CPU
* handling the mc.
/* State related to FWNMI option */
/* System Reset and Machine Check Notification Routine addresses
* registered by "ibm,nmi-register" RTAS call.
*/
int mc_status;
QemuCond mc_delivery_cond;
target_ulong fwnmi_system_reset_addr;
target_ulong fwnmi_machine_check_addr;
/* Machine Check FWNMI synchronization, fwnmi_machine_check_interlock is
* set to -1 if a FWNMI machine check is not in progress, else is set to
* the CPU that was delivered the machine check, and is set back to -1
* when that CPU makes an "ibm,nmi-interlock" RTAS call. The cond is used
* to synchronize other CPUs.
*/
int fwnmi_machine_check_interlock;
QemuCond fwnmi_machine_check_interlock_cond;
/*< public >*/
char *kvm_type;
@ -736,6 +744,7 @@ void spapr_load_rtas(SpaprMachineState *spapr, void *fdt, hwaddr addr);
#define SPAPR_IS_PCI_LIOBN(liobn) (!!((liobn) & 0x80000000))
#define SPAPR_PCI_DMA_WINDOW_NUM(liobn) ((liobn) & 0xff)
#define RTAS_SIZE 2048
#define RTAS_ERROR_LOG_MAX 2048
/* Offset from rtas-base where error log is placed */
@ -795,7 +804,7 @@ void *spapr_build_fdt(SpaprMachineState *spapr, bool reset, size_t space);
void spapr_events_init(SpaprMachineState *sm);
void spapr_dt_events(SpaprMachineState *sm, void *fdt);
void close_htab_fd(SpaprMachineState *spapr);
void spapr_setup_hpt_and_vrma(SpaprMachineState *spapr);
void spapr_setup_hpt(SpaprMachineState *spapr);
void spapr_free_hpt(SpaprMachineState *spapr);
SpaprTceTable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn);
void spapr_tce_table_enable(SpaprTceTable *tcet,
@ -824,6 +833,7 @@ int spapr_hpt_shift_for_ramsize(uint64_t ramsize);
void spapr_reallocate_hpt(SpaprMachineState *spapr, int shift,
Error **errp);
void spapr_clear_pending_events(SpaprMachineState *spapr);
void spapr_clear_pending_hotplug_events(SpaprMachineState *spapr);
int spapr_max_server_number(SpaprMachineState *spapr);
void spapr_store_hpte(PowerPCCPU *cpu, hwaddr ptex,
uint64_t pte0, uint64_t pte1);

View File

@ -40,7 +40,9 @@ typedef struct SpaprCpuCoreClass {
} SpaprCpuCoreClass;
const char *spapr_get_cpu_core_type(const char *cpu_type);
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip, target_ulong r3);
void spapr_cpu_set_entry_state(PowerPCCPU *cpu, target_ulong nip,
target_ulong r1, target_ulong r3,
target_ulong r4);
typedef struct SpaprCpuState {
uint64_t vpa_addr;

View File

@ -72,8 +72,8 @@ void spapr_ovec_set(SpaprOptionVector *ov, long bitnr);
void spapr_ovec_clear(SpaprOptionVector *ov, long bitnr);
bool spapr_ovec_test(SpaprOptionVector *ov, long bitnr);
SpaprOptionVector *spapr_ovec_parse_vector(target_ulong table_addr, int vector);
int spapr_ovec_populate_dt(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name);
int spapr_dt_ovec(void *fdt, int fdt_offset,
SpaprOptionVector *ov, const char *name);
/* migration */
extern const VMStateDescription vmstate_spapr_ovec;

View File

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

Binary file not shown.

@ -1 +1 @@
Subproject commit 9546892a80d5a4c73deea6719de46372f007f4a6
Subproject commit ab6984f5a6d054e1f634dda855b32e5357111974

View File

@ -177,6 +177,7 @@ typedef struct PowerPCCPUClass {
uint64_t insns_flags;
uint64_t insns_flags2;
uint64_t msr_mask;
uint64_t lpcr_mask; /* Available bits in the LPCR */
uint64_t lpcr_pm; /* Power-saving mode Exit Cause Enable bits */
powerpc_mmu_t mmu_model;
powerpc_excp_t excp_model;

View File

@ -24,8 +24,6 @@
#include "exec/cpu-defs.h"
#include "cpu-qom.h"
/* #define PPC_EMULATE_32BITS_HYPV */
#define TCG_GUEST_DEFAULT_MO 0
#define TARGET_PAGE_BITS_64K 16
@ -300,13 +298,12 @@ typedef struct ppc_v3_pate_t {
#define MSR_SF 63 /* Sixty-four-bit mode hflags */
#define MSR_TAG 62 /* Tag-active mode (POWERx ?) */
#define MSR_ISF 61 /* Sixty-four-bit interrupt mode on 630 */
#define MSR_SHV 60 /* hypervisor state hflags */
#define MSR_HV 60 /* hypervisor state hflags */
#define MSR_TS0 34 /* Transactional state, 2 bits (Book3s) */
#define MSR_TS1 33
#define MSR_TM 32 /* Transactional Memory Available (Book3s) */
#define MSR_CM 31 /* Computation mode for BookE hflags */
#define MSR_ICM 30 /* Interrupt computation mode for BookE */
#define MSR_THV 29 /* hypervisor state for 32 bits PowerPC hflags */
#define MSR_GS 28 /* guest state for BookE */
#define MSR_UCLE 26 /* User-mode cache lock enable for BookE */
#define MSR_VR 25 /* altivec available x hflags */
@ -401,10 +398,13 @@ typedef struct ppc_v3_pate_t {
#define msr_sf ((env->msr >> MSR_SF) & 1)
#define msr_isf ((env->msr >> MSR_ISF) & 1)
#define msr_shv ((env->msr >> MSR_SHV) & 1)
#if defined(TARGET_PPC64)
#define msr_hv ((env->msr >> MSR_HV) & 1)
#else
#define msr_hv (0)
#endif
#define msr_cm ((env->msr >> MSR_CM) & 1)
#define msr_icm ((env->msr >> MSR_ICM) & 1)
#define msr_thv ((env->msr >> MSR_THV) & 1)
#define msr_gs ((env->msr >> MSR_GS) & 1)
#define msr_ucle ((env->msr >> MSR_UCLE) & 1)
#define msr_vr ((env->msr >> MSR_VR) & 1)
@ -449,16 +449,9 @@ typedef struct ppc_v3_pate_t {
/* Hypervisor bit is more specific */
#if defined(TARGET_PPC64)
#define MSR_HVB (1ULL << MSR_SHV)
#define msr_hv msr_shv
#else
#if defined(PPC_EMULATE_32BITS_HYPV)
#define MSR_HVB (1ULL << MSR_THV)
#define msr_hv msr_thv
#define MSR_HVB (1ULL << MSR_HV)
#else
#define MSR_HVB (0ULL)
#define msr_hv (0)
#endif
#endif
/* DSISR */
@ -1051,10 +1044,6 @@ struct CPUPPCState {
uint32_t flags;
uint64_t insns_flags;
uint64_t insns_flags2;
#if defined(TARGET_PPC64)
ppc_slb_t vrma_slb;
target_ulong rmls;
#endif
int error_code;
uint32_t pending_interrupts;
@ -1231,7 +1220,8 @@ int ppc64_cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cs,
int ppc32_cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cs,
int cpuid, void *opaque);
#ifndef CONFIG_USER_ONLY
void ppc_cpu_do_system_reset(CPUState *cs);
void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector);
void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector);
extern const VMStateDescription vmstate_ppc_cpu;
#endif

View File

@ -128,6 +128,37 @@ static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
return offset;
}
static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
target_ulong vector, target_ulong msr)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
/*
* We don't use hreg_store_msr here as already have treated any
* special case that could occur. Just store MSR and update hflags
*
* Note: We *MUST* not use hreg_store_msr() as-is anyway because it
* will prevent setting of the HV bit which some exceptions might need
* to do.
*/
env->msr = msr & env->msr_mask;
hreg_compute_hflags(env);
env->nip = vector;
/* Reset exception state */
cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
/* Reset the reservation */
env->reserve_addr = -1;
/*
* Any interrupt is context synchronizing, check if TCG TLB needs
* a delayed flush on ppc64
*/
check_tlb_flush(env, false);
}
/*
* Note that this function should be greatly optimized when called
* with a constant excp, from ppc_hw_interrupt
@ -768,29 +799,8 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
}
}
#endif
/*
* We don't use hreg_store_msr here as already have treated any
* special case that could occur. Just store MSR and update hflags
*
* Note: We *MUST* not use hreg_store_msr() as-is anyway because it
* will prevent setting of the HV bit which some exceptions might need
* to do.
*/
env->msr = new_msr & env->msr_mask;
hreg_compute_hflags(env);
env->nip = vector;
/* Reset exception state */
cs->exception_index = POWERPC_EXCP_NONE;
env->error_code = 0;
/* Reset the reservation */
env->reserve_addr = -1;
/*
* Any interrupt is context synchronizing, check if TCG TLB needs
* a delayed flush on ppc64
*/
check_tlb_flush(env, false);
powerpc_set_excp_state(cpu, vector, new_msr);
}
void ppc_cpu_do_interrupt(CPUState *cs)
@ -951,12 +961,35 @@ static void ppc_hw_interrupt(CPUPPCState *env)
}
}
void ppc_cpu_do_system_reset(CPUState *cs)
void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
if (vector != -1) {
env->nip = vector;
}
}
void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
{
PowerPCCPU *cpu = POWERPC_CPU(cs);
CPUPPCState *env = &cpu->env;
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
target_ulong msr = 0;
/*
* Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
* been set by KVM.
*/
msr = (1ULL << MSR_ME);
msr |= env->msr & (1ULL << MSR_SF);
if (!(*pcc->interrupts_big_endian)(cpu)) {
msr |= (1ULL << MSR_LE);
}
powerpc_set_excp_state(cpu, vector, msr);
}
#endif /* !CONFIG_USER_ONLY */

View File

@ -2113,7 +2113,7 @@ void kvmppc_error_append_smt_possible_hint(Error *const *errp)
#ifdef TARGET_PPC64
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
uint64_t kvmppc_vrma_limit(unsigned int hash_shift)
{
struct kvm_ppc_smmu_info info;
long rampagesize, best_page_shift;
@ -2140,8 +2140,7 @@ uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift)
}
}
return MIN(current_size,
1ULL << (best_page_shift + hash_shift - 7));
return 1ULL << (best_page_shift + hash_shift - 7);
}
#endif

View File

@ -47,7 +47,7 @@ void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t page_shift,
int *pfd, bool need_vfio);
int kvmppc_remove_spapr_tce(void *table, int pfd, uint32_t window_size);
int kvmppc_reset_htab(int shift_hint);
uint64_t kvmppc_rma_size(uint64_t current_size, unsigned int hash_shift);
uint64_t kvmppc_vrma_limit(unsigned int hash_shift);
bool kvmppc_has_cap_spapr_vfio(void);
#endif /* !CONFIG_USER_ONLY */
bool kvmppc_has_cap_epr(void);
@ -255,10 +255,9 @@ static inline int kvmppc_reset_htab(int shift_hint)
return 0;
}
static inline uint64_t kvmppc_rma_size(uint64_t current_size,
unsigned int hash_shift)
static inline uint64_t kvmppc_vrma_limit(unsigned int hash_shift)
{
return ram_size;
g_assert_not_reached();
}
static inline bool kvmppc_hpt_needs_host_contiguous_pages(void)

View File

@ -18,6 +18,7 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/units.h"
#include "cpu.h"
#include "exec/exec-all.h"
#include "exec/helper-proto.h"
@ -668,6 +669,21 @@ unsigned ppc_hash64_hpte_page_shift_noslb(PowerPCCPU *cpu,
return 0;
}
static bool ppc_hash64_use_vrma(CPUPPCState *env)
{
switch (env->mmu_model) {
case POWERPC_MMU_3_00:
/*
* ISAv3.0 (POWER9) always uses VRMA, the VPM0 field and RMOR
* register no longer exist
*/
return true;
default:
return !!(env->spr[SPR_LPCR] & LPCR_VPM0);
}
}
static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
{
CPUPPCState *env = &POWERPC_CPU(cs)->env;
@ -676,15 +692,7 @@ static void ppc_hash64_set_isi(CPUState *cs, uint64_t error_code)
if (msr_ir) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
switch (env->mmu_model) {
case POWERPC_MMU_3_00:
/* Field deprecated in ISAv3.00 - interrupts always go to hyperv */
vpm = true;
break;
default:
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0);
break;
}
vpm = ppc_hash64_use_vrma(env);
}
if (vpm && !msr_hv) {
cs->exception_index = POWERPC_EXCP_HISI;
@ -702,15 +710,7 @@ static void ppc_hash64_set_dsi(CPUState *cs, uint64_t dar, uint64_t dsisr)
if (msr_dr) {
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM1);
} else {
switch (env->mmu_model) {
case POWERPC_MMU_3_00:
/* Field deprecated in ISAv3.00 - interrupts always go to hyperv */
vpm = true;
break;
default:
vpm = !!(env->spr[SPR_LPCR] & LPCR_VPM0);
break;
}
vpm = ppc_hash64_use_vrma(env);
}
if (vpm && !msr_hv) {
cs->exception_index = POWERPC_EXCP_HDSI;
@ -758,11 +758,67 @@ static void ppc_hash64_set_c(PowerPCCPU *cpu, hwaddr ptex, uint64_t pte1)
stb_phys(CPU(cpu)->as, base + offset, (pte1 & 0xff) | 0x80);
}
static target_ulong rmls_limit(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
/*
* In theory the meanings of RMLS values are implementation
* dependent. In practice, this seems to have been the set from
* POWER4+..POWER8, and RMLS is no longer supported in POWER9.
*
* Unsupported values mean the OS has shot itself in the
* foot. Return a 0-sized RMA in this case, which we expect
* to trigger an immediate DSI or ISI
*/
static const target_ulong rma_sizes[16] = {
[0] = 256 * GiB,
[1] = 16 * GiB,
[2] = 1 * GiB,
[3] = 64 * MiB,
[4] = 256 * MiB,
[7] = 128 * MiB,
[8] = 32 * MiB,
};
target_ulong rmls = (env->spr[SPR_LPCR] & LPCR_RMLS) >> LPCR_RMLS_SHIFT;
return rma_sizes[rmls];
}
static int build_vrma_slbe(PowerPCCPU *cpu, ppc_slb_t *slb)
{
CPUPPCState *env = &cpu->env;
target_ulong lpcr = env->spr[SPR_LPCR];
uint32_t vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
target_ulong vsid = SLB_VSID_VRMA | ((vrmasd << 4) & SLB_VSID_LLP_MASK);
int i;
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const PPCHash64SegmentPageSizes *sps = &cpu->hash64_opts->sps[i];
if (!sps->page_shift) {
break;
}
if ((vsid & SLB_VSID_LLP_MASK) == sps->slb_enc) {
slb->esid = SLB_ESID_V;
slb->vsid = vsid;
slb->sps = sps;
return 0;
}
}
error_report("Bad page size encoding in LPCR[VRMASD]; LPCR=0x"
TARGET_FMT_lx"\n", lpcr);
return -1;
}
int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
int rwx, int mmu_idx)
{
CPUState *cs = CPU(cpu);
CPUPPCState *env = &cpu->env;
ppc_slb_t vrma_slbe;
ppc_slb_t *slb;
unsigned apshift;
hwaddr ptex;
@ -789,27 +845,32 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
*/
raddr = eaddr & 0x0FFFFFFFFFFFFFFFULL;
/* In HV mode, add HRMOR if top EA bit is clear */
if (msr_hv || !env->has_hv_mode) {
if (cpu->vhyp) {
/*
* In virtual hypervisor mode, there's nothing to do:
* EA == GPA == qemu guest address
*/
} else if (msr_hv || !env->has_hv_mode) {
/* In HV mode, add HRMOR if top EA bit is clear */
if (!(eaddr >> 63)) {
raddr |= env->spr[SPR_HRMOR];
}
} else {
/* Otherwise, check VPM for RMA vs VRMA */
if (env->spr[SPR_LPCR] & LPCR_VPM0) {
slb = &env->vrma_slb;
if (slb->sps) {
goto skip_slb_search;
}
/* Not much else to do here */
} else if (ppc_hash64_use_vrma(env)) {
/* Emulated VRMA mode */
slb = &vrma_slbe;
if (build_vrma_slbe(cpu, slb) != 0) {
/* Invalid VRMA setup, machine check */
cs->exception_index = POWERPC_EXCP_MCHECK;
env->error_code = 0;
return 1;
} else if (raddr < env->rmls) {
/* RMA. Check bounds in RMLS */
raddr |= env->spr[SPR_RMOR];
} else {
/* The access failed, generate the approriate interrupt */
}
goto skip_slb_search;
} else {
target_ulong limit = rmls_limit(cpu);
/* Emulated old-style RMO mode, bounds check against RMLS */
if (raddr >= limit) {
if (rwx == 2) {
ppc_hash64_set_isi(cs, SRR1_PROTFAULT);
} else {
@ -821,6 +882,8 @@ int ppc_hash64_handle_mmu_fault(PowerPCCPU *cpu, vaddr eaddr,
}
return 1;
}
raddr |= env->spr[SPR_RMOR];
}
tlb_set_page(cs, eaddr & TARGET_PAGE_MASK, raddr & TARGET_PAGE_MASK,
PAGE_READ | PAGE_WRITE | PAGE_EXEC, mmu_idx,
@ -943,6 +1006,7 @@ skip_slb_search:
hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
{
CPUPPCState *env = &cpu->env;
ppc_slb_t vrma_slbe;
ppc_slb_t *slb;
hwaddr ptex, raddr;
ppc_hash_pte64_t pte;
@ -953,22 +1017,29 @@ hwaddr ppc_hash64_get_phys_page_debug(PowerPCCPU *cpu, target_ulong addr)
/* In real mode the top 4 effective address bits are ignored */
raddr = addr & 0x0FFFFFFFFFFFFFFFULL;
/* In HV mode, add HRMOR if top EA bit is clear */
if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) {
if (cpu->vhyp) {
/*
* In virtual hypervisor mode, there's nothing to do:
* EA == GPA == qemu guest address
*/
return raddr;
} else if ((msr_hv || !env->has_hv_mode) && !(addr >> 63)) {
/* In HV mode, add HRMOR if top EA bit is clear */
return raddr | env->spr[SPR_HRMOR];
}
/* Otherwise, check VPM for RMA vs VRMA */
if (env->spr[SPR_LPCR] & LPCR_VPM0) {
slb = &env->vrma_slb;
if (!slb->sps) {
} else if (ppc_hash64_use_vrma(env)) {
/* Emulated VRMA mode */
slb = &vrma_slbe;
if (build_vrma_slbe(cpu, slb) != 0) {
return -1;
}
} else if (raddr < env->rmls) {
/* RMA. Check bounds in RMLS */
return raddr | env->spr[SPR_RMOR];
} else {
return -1;
target_ulong limit = rmls_limit(cpu);
/* Emulated old-style RMO mode, bounds check against RMLS */
if (raddr >= limit) {
return -1;
}
return raddr | env->spr[SPR_RMOR];
}
} else {
slb = slb_lookup(cpu, addr);
@ -997,168 +1068,12 @@ void ppc_hash64_tlb_flush_hpte(PowerPCCPU *cpu, target_ulong ptex,
cpu->env.tlb_need_flush = TLB_NEED_GLOBAL_FLUSH | TLB_NEED_LOCAL_FLUSH;
}
static void ppc_hash64_update_rmls(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
uint64_t lpcr = env->spr[SPR_LPCR];
/*
* This is the full 4 bits encoding of POWER8. Previous
* CPUs only support a subset of these but the filtering
* is done when writing LPCR
*/
switch ((lpcr & LPCR_RMLS) >> LPCR_RMLS_SHIFT) {
case 0x8: /* 32MB */
env->rmls = 0x2000000ull;
break;
case 0x3: /* 64MB */
env->rmls = 0x4000000ull;
break;
case 0x7: /* 128MB */
env->rmls = 0x8000000ull;
break;
case 0x4: /* 256MB */
env->rmls = 0x10000000ull;
break;
case 0x2: /* 1GB */
env->rmls = 0x40000000ull;
break;
case 0x1: /* 16GB */
env->rmls = 0x400000000ull;
break;
default:
/* What to do here ??? */
env->rmls = 0;
}
}
static void ppc_hash64_update_vrma(PowerPCCPU *cpu)
{
CPUPPCState *env = &cpu->env;
const PPCHash64SegmentPageSizes *sps = NULL;
target_ulong esid, vsid, lpcr;
ppc_slb_t *slb = &env->vrma_slb;
uint32_t vrmasd;
int i;
/* First clear it */
slb->esid = slb->vsid = 0;
slb->sps = NULL;
/* Is VRMA enabled ? */
lpcr = env->spr[SPR_LPCR];
if (!(lpcr & LPCR_VPM0)) {
return;
}
/*
* Make one up. Mostly ignore the ESID which will not be needed
* for translation
*/
vsid = SLB_VSID_VRMA;
vrmasd = (lpcr & LPCR_VRMASD) >> LPCR_VRMASD_SHIFT;
vsid |= (vrmasd << 4) & (SLB_VSID_L | SLB_VSID_LP);
esid = SLB_ESID_V;
for (i = 0; i < PPC_PAGE_SIZES_MAX_SZ; i++) {
const PPCHash64SegmentPageSizes *sps1 = &cpu->hash64_opts->sps[i];
if (!sps1->page_shift) {
break;
}
if ((vsid & SLB_VSID_LLP_MASK) == sps1->slb_enc) {
sps = sps1;
break;
}
}
if (!sps) {
error_report("Bad page size encoding esid 0x"TARGET_FMT_lx
" vsid 0x"TARGET_FMT_lx, esid, vsid);
return;
}
slb->vsid = vsid;
slb->esid = esid;
slb->sps = sps;
}
void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
{
PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
CPUPPCState *env = &cpu->env;
uint64_t lpcr = 0;
/* Filter out bits */
switch (env->mmu_model) {
case POWERPC_MMU_64B: /* 970 */
if (val & 0x40) {
lpcr |= LPCR_LPES0;
}
if (val & 0x8000000000000000ull) {
lpcr |= LPCR_LPES1;
}
if (val & 0x20) {
lpcr |= (0x4ull << LPCR_RMLS_SHIFT);
}
if (val & 0x4000000000000000ull) {
lpcr |= (0x2ull << LPCR_RMLS_SHIFT);
}
if (val & 0x2000000000000000ull) {
lpcr |= (0x1ull << LPCR_RMLS_SHIFT);
}
env->spr[SPR_RMOR] = ((lpcr >> 41) & 0xffffull) << 26;
/*
* XXX We could also write LPID from HID4 here
* but since we don't tag any translation on it
* it doesn't actually matter
*
* XXX For proper emulation of 970 we also need
* to dig HRMOR out of HID5
*/
break;
case POWERPC_MMU_2_03: /* P5p */
lpcr = val & (LPCR_RMLS | LPCR_ILE |
LPCR_LPES0 | LPCR_LPES1 |
LPCR_RMI | LPCR_HDICE);
break;
case POWERPC_MMU_2_06: /* P7 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
LPCR_MER | LPCR_TC |
LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE);
break;
case POWERPC_MMU_2_07: /* P8 */
lpcr = val & (LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE);
break;
case POWERPC_MMU_3_00: /* P9 */
lpcr = val & (LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
(LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
LPCR_DEE | LPCR_OEE)) | LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE);
/*
* If we have a virtual hypervisor, we need to bring back RMLS. It
* doesn't exist on an actual P9 but that's all we know how to
* configure with softmmu at the moment
*/
if (cpu->vhyp) {
lpcr |= (val & LPCR_RMLS);
}
break;
default:
;
}
env->spr[SPR_LPCR] = lpcr;
ppc_hash64_update_rmls(cpu);
ppc_hash64_update_vrma(cpu);
env->spr[SPR_LPCR] = val & pcc->lpcr_mask;
}
void helper_store_lpcr(CPUPPCState *env, target_ulong val)

View File

@ -1938,15 +1938,17 @@ static void gen_rlwinm(DisasContext *ctx)
me += 32;
#endif
mask = MASK(mb, me);
if (sh == 0) {
tcg_gen_andi_tl(t_ra, t_rs, mask);
} else if (mask <= 0xffffffffu) {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, t_rs);
tcg_gen_rotli_i32(t0, t0, sh);
tcg_gen_andi_i32(t0, t0, mask);
tcg_gen_extu_i32_tl(t_ra, t0);
tcg_temp_free_i32(t0);
if (mask <= 0xffffffffu) {
if (sh == 0) {
tcg_gen_andi_tl(t_ra, t_rs, mask);
} else {
TCGv_i32 t0 = tcg_temp_new_i32();
tcg_gen_trunc_tl_i32(t0, t_rs);
tcg_gen_rotli_i32(t0, t0, sh);
tcg_gen_andi_i32(t0, t0, mask);
tcg_gen_extu_i32_tl(t_ra, t0);
tcg_temp_free_i32(t0);
}
} else {
#if defined(TARGET_PPC64)
tcg_gen_deposit_i64(t_ra, t_rs, t_rs, 32, 32);

View File

@ -7895,25 +7895,21 @@ static void spr_write_lpcr(DisasContext *ctx, int sprn, int gprn)
{
gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
}
static void spr_write_970_hid4(DisasContext *ctx, int sprn, int gprn)
{
#if defined(TARGET_PPC64)
spr_write_generic(ctx, sprn, gprn);
gen_helper_store_lpcr(cpu_env, cpu_gpr[gprn]);
#endif
}
#endif /* !defined(CONFIG_USER_ONLY) */
static void gen_spr_970_lpar(CPUPPCState *env)
{
#if !defined(CONFIG_USER_ONLY)
/* Logical partitionning */
/* PPC970: HID4 is effectively the LPCR */
/*
* PPC970: HID4 covers things later controlled by the LPCR and
* RMOR in later CPUs, but with a different encoding. We only
* support the 970 in "Apple mode" which has all hypervisor
* facilities disabled by strapping, so we can basically just
* ignore it
*/
spr_register(env, SPR_970_HID4, "HID4",
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_970_hid4,
&spr_read_generic, &spr_write_generic,
0x00000000);
#endif
}
@ -8019,12 +8015,16 @@ static void gen_spr_book3s_ids(CPUPPCState *env)
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register_hv(env, SPR_RMOR, "RMOR",
spr_register_hv(env, SPR_HRMOR, "HRMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
0x00000000);
spr_register_hv(env, SPR_HRMOR, "HRMOR",
}
static void gen_spr_rmor(CPUPPCState *env)
{
spr_register_hv(env, SPR_RMOR, "RMOR",
SPR_NOACCESS, SPR_NOACCESS,
SPR_NOACCESS, SPR_NOACCESS,
&spr_read_generic, &spr_write_generic,
@ -8476,6 +8476,8 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
(1ull << MSR_DR) |
(1ull << MSR_PMM) |
(1ull << MSR_RI);
pcc->lpcr_mask = LPCR_RMLS | LPCR_ILE | LPCR_LPES0 | LPCR_LPES1 |
LPCR_RMI | LPCR_HDICE;
pcc->mmu_model = POWERPC_MMU_2_03;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@ -8492,44 +8494,6 @@ POWERPC_FAMILY(POWER5P)(ObjectClass *oc, void *data)
pcc->l1_icache_size = 0x10000;
}
/*
* The CPU used to have a "compat" property which set the
* compatibility mode PVR. However, this was conceptually broken - it
* only makes sense on the pseries machine type (otherwise the guest
* owns the PCR and can control the compatibility mode itself). It's
* been replaced with the 'max-cpu-compat' property on the pseries
* machine type. For backwards compatibility, pseries specially
* parses the -cpu parameter and converts old compat= parameters into
* the appropriate machine parameters. This stub implementation of
* the parameter catches any uses on explicitly created CPUs.
*/
static void getset_compat_deprecated(Object *obj, Visitor *v, const char *name,
void *opaque, Error **errp)
{
QNull *null = NULL;
if (!qtest_enabled()) {
warn_report("CPU 'compat' property is deprecated and has no effect; "
"use max-cpu-compat machine property instead");
}
visit_type_null(v, name, &null, NULL);
qobject_unref(null);
}
static const PropertyInfo ppc_compat_deprecated_propinfo = {
.name = "str",
.description = "compatibility mode (deprecated)",
.get = getset_compat_deprecated,
.set = getset_compat_deprecated,
};
static Property powerpc_servercpu_properties[] = {
{
.name = "compat",
.info = &ppc_compat_deprecated_propinfo,
},
DEFINE_PROP_END_OF_LIST(),
};
static void init_proc_POWER7(CPUPPCState *env)
{
/* Common Registers */
@ -8539,6 +8503,7 @@ static void init_proc_POWER7(CPUPPCState *env)
/* POWER7 Specific Registers */
gen_spr_book3s_ids(env);
gen_spr_rmor(env);
gen_spr_amr(env);
gen_spr_book3s_purr(env);
gen_spr_power5p_common(env);
@ -8611,7 +8576,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER7";
dc->desc = "POWER7";
device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power7;
pcc->pcr_mask = PCR_VEC_DIS | PCR_VSX_DIS | PCR_COMPAT_2_05;
pcc->pcr_supported = PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@ -8652,6 +8616,12 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->lpcr_mask = LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_DPFD |
LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2 |
LPCR_MER | LPCR_TC |
LPCR_LPES0 | LPCR_LPES1 | LPCR_HDICE;
pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
pcc->mmu_model = POWERPC_MMU_2_06;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@ -8668,7 +8638,6 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
pcc->lpcr_pm = LPCR_P7_PECE0 | LPCR_P7_PECE1 | LPCR_P7_PECE2;
}
static void init_proc_POWER8(CPUPPCState *env)
@ -8680,6 +8649,7 @@ static void init_proc_POWER8(CPUPPCState *env)
/* POWER8 Specific Registers */
gen_spr_book3s_ids(env);
gen_spr_rmor(env);
gen_spr_amr(env);
gen_spr_iamr(env);
gen_spr_book3s_purr(env);
@ -8776,7 +8746,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER8";
dc->desc = "POWER8";
device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power8;
pcc->pcr_mask = PCR_TM_DIS | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
pcc->pcr_supported = PCR_COMPAT_2_07 | PCR_COMPAT_2_06 | PCR_COMPAT_2_05;
@ -8804,7 +8773,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_PM_ISA206;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_SHV) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@ -8823,6 +8792,13 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
(1ull << MSR_TS0) |
(1ull << MSR_TS1) |
(1ull << MSR_LE);
pcc->lpcr_mask = LPCR_VPM0 | LPCR_VPM1 | LPCR_ISL | LPCR_KBV |
LPCR_DPFD | LPCR_VRMASD | LPCR_RMLS | LPCR_ILE |
LPCR_AIL | LPCR_ONL | LPCR_P8_PECE0 | LPCR_P8_PECE1 |
LPCR_P8_PECE2 | LPCR_P8_PECE3 | LPCR_P8_PECE4 |
LPCR_MER | LPCR_TC | LPCR_LPES0 | LPCR_HDICE;
pcc->lpcr_pm = LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
LPCR_P8_PECE3 | LPCR_P8_PECE4;
pcc->mmu_model = POWERPC_MMU_2_07;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc_hash64_handle_mmu_fault;
@ -8840,8 +8816,6 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
pcc->lpcr_pm = LPCR_P8_PECE0 | LPCR_P8_PECE1 | LPCR_P8_PECE2 |
LPCR_P8_PECE3 | LPCR_P8_PECE4;
}
#ifdef CONFIG_SOFTMMU
@ -8988,7 +8962,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER9";
dc->desc = "POWER9";
device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power9;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07;
pcc->pcr_supported = PCR_COMPAT_3_00 | PCR_COMPAT_2_07 | PCR_COMPAT_2_06 |
@ -9017,7 +8990,7 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_SHV) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@ -9034,6 +9007,14 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
(LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
LPCR_DEE | LPCR_OEE))
| LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE;
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
pcc->mmu_model = POWERPC_MMU_3_00;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
@ -9053,7 +9034,6 @@ POWERPC_FAMILY(POWER9)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
}
#ifdef CONFIG_SOFTMMU
@ -9198,7 +9178,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
dc->fw_name = "PowerPC,POWER10";
dc->desc = "POWER10";
device_class_set_props(dc, powerpc_servercpu_properties);
pcc->pvr_match = ppc_pvr_match_power10;
pcc->pcr_mask = PCR_COMPAT_2_05 | PCR_COMPAT_2_06 | PCR_COMPAT_2_07 |
PCR_COMPAT_3_00;
@ -9228,7 +9207,7 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
PPC2_ISA205 | PPC2_ISA207S | PPC2_FP_CVT_S64 |
PPC2_TM | PPC2_ISA300 | PPC2_PRCNTL;
pcc->msr_mask = (1ull << MSR_SF) |
(1ull << MSR_SHV) |
(1ull << MSR_HV) |
(1ull << MSR_TM) |
(1ull << MSR_VR) |
(1ull << MSR_VSX) |
@ -9245,6 +9224,14 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
(1ull << MSR_PMM) |
(1ull << MSR_RI) |
(1ull << MSR_LE);
pcc->lpcr_mask = LPCR_VPM1 | LPCR_ISL | LPCR_KBV | LPCR_DPFD |
(LPCR_PECE_U_MASK & LPCR_HVEE) | LPCR_ILE | LPCR_AIL |
LPCR_UPRT | LPCR_EVIRT | LPCR_ONL | LPCR_HR | LPCR_LD |
(LPCR_PECE_L_MASK & (LPCR_PDEE | LPCR_HDEE | LPCR_EEE |
LPCR_DEE | LPCR_OEE))
| LPCR_MER | LPCR_GTSE | LPCR_TC |
LPCR_HEIC | LPCR_LPES0 | LPCR_HVICE | LPCR_HDICE;
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
pcc->mmu_model = POWERPC_MMU_3_00;
#if defined(CONFIG_SOFTMMU)
pcc->handle_mmu_fault = ppc64_v3_handle_mmu_fault;
@ -9263,7 +9250,6 @@ POWERPC_FAMILY(POWER10)(ObjectClass *oc, void *data)
pcc->l1_dcache_size = 0x8000;
pcc->l1_icache_size = 0x8000;
pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr;
pcc->lpcr_pm = LPCR_PDEE | LPCR_HDEE | LPCR_EEE | LPCR_DEE | LPCR_OEE;
}
#if !defined(CONFIG_USER_ONLY)
@ -10486,6 +10472,8 @@ static void ppc_cpu_parse_featurestr(const char *type, char *features,
*s = '\0';
for (i = 0; inpieces[i]; i++) {
if (g_str_has_prefix(inpieces[i], "compat=")) {
warn_report_once("CPU 'compat' property is deprecated; "
"use max-cpu-compat machine property instead");
compat_str = inpieces[i];
continue;
}

View File

@ -12,7 +12,6 @@ void qtest_spapr_shutdown(QOSState *qs);
"cap-cfpc=broken," \
"cap-sbbc=broken," \
"cap-ibs=broken," \
"cap-ccf-assist=off," \
"cap-fwnmi-mce=off"
"cap-ccf-assist=off,"
#endif