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
29 changed files with 917 additions and 907 deletions
+7
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
-----------------------
+2 -2
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,
+1 -1
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);
+495 -457
View File
File diff suppressed because it is too large Load Diff
+8 -11
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)
{
+6 -10
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 */
+23 -28
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;
+7 -8
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)) {
+5 -2
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)) {
+2 -2
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;
+34 -11
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);
}
+42 -30
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);
+1
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 ..."
+2 -1
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 {
+22 -12
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);
+3 -1
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;
+2 -2
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;
+1 -1
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
BIN
View File
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More