s390x: protvirt: Move IO control structures over SIDA

For protected guests, we need to put the IO emulation results into the
SIDA, so SIE will write them into the guest at the next entry.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
Message-Id: <20200319131921.2367-14-frankja@linux.ibm.com>
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
This commit is contained in:
Janosch Frank 2020-03-19 09:19:18 -04:00 committed by Cornelia Huck
parent c10b708752
commit fcc10c1470
1 changed files with 45 additions and 16 deletions

View File

@ -138,7 +138,9 @@ void ioinst_handle_msch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return;
}
if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
if (s390_is_pv()) {
s390_cpu_pv_mem_read(cpu, addr, &schib, sizeof(schib));
} else if (s390_cpu_virt_mem_read(cpu, addr, ar, &schib, sizeof(schib))) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return;
}
@ -195,7 +197,9 @@ void ioinst_handle_ssch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return;
}
if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
if (s390_is_pv()) {
s390_cpu_pv_mem_read(cpu, addr, &orig_orb, sizeof(orb));
} else if (s390_cpu_virt_mem_read(cpu, addr, ar, &orig_orb, sizeof(orb))) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return;
}
@ -231,14 +235,19 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
cc = css_do_stcrw(&crw);
/* 0 - crw stored, 1 - zeroes stored */
if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
if (s390_is_pv()) {
s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw));
setcc(cpu, cc);
} else {
if (cc == 0) {
/* Write failed: requeue CRW since STCRW is suppressing */
css_undo_stcrw(&crw);
if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
setcc(cpu, cc);
} else {
if (cc == 0) {
/* Write failed: requeue CRW since STCRW is suppressing */
css_undo_stcrw(&crw);
}
s390_cpu_virt_mem_handle_exc(cpu, ra);
}
s390_cpu_virt_mem_handle_exc(cpu, ra);
}
}
@ -260,6 +269,13 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
}
if (ioinst_disassemble_sch_ident(reg1, &m, &cssid, &ssid, &schid)) {
/*
* The Ultravisor checks schid bit 16 to be one and bits 0-12
* to be 0 and injects a operand exception itself.
*
* Hence we should never end up here.
*/
g_assert(!s390_is_pv());
/*
* As operand exceptions have a lower priority than access exceptions,
* we check whether the memory area is writeable (injecting the
@ -292,14 +308,17 @@ void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
}
}
if (cc != 3) {
if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
sizeof(schib)) != 0) {
if (s390_is_pv()) {
s390_cpu_pv_mem_write(cpu, addr, &schib, sizeof(schib));
} else if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib,
sizeof(schib)) != 0) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return;
}
} else {
/* Access exceptions have a higher priority than cc3 */
if (s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
if (!s390_is_pv() &&
s390_cpu_virt_mem_check_write(cpu, addr, ar, sizeof(schib)) != 0) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return;
}
@ -336,7 +355,9 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
}
/* 0 - status pending, 1 - not status pending, 3 - not operational */
if (cc != 3) {
if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
if (s390_is_pv()) {
s390_cpu_pv_mem_write(cpu, addr, &irb, irb_len);
} else if (s390_cpu_virt_mem_write(cpu, addr, ar, &irb, irb_len) != 0) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return -EFAULT;
}
@ -344,7 +365,8 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
} else {
irb_len = sizeof(irb) - sizeof(irb.emw);
/* Access exceptions have a higher priority than cc3 */
if (s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
if (!s390_is_pv() &&
s390_cpu_virt_mem_check_write(cpu, addr, ar, irb_len) != 0) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return -EFAULT;
}
@ -642,7 +664,9 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
* present CHSC sub-handlers ... if we ever need more, we should take
* care of req->len here first.
*/
if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
if (s390_is_pv()) {
s390_cpu_pv_mem_read(cpu, addr, buf, sizeof(ChscReq));
} else if (s390_cpu_virt_mem_read(cpu, addr, reg, buf, sizeof(ChscReq))) {
s390_cpu_virt_mem_handle_exc(cpu, ra);
return;
}
@ -675,11 +699,16 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
break;
}
if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
be16_to_cpu(res->len))) {
if (s390_is_pv()) {
s390_cpu_pv_mem_write(cpu, addr + len, res, be16_to_cpu(res->len));
setcc(cpu, 0); /* Command execution complete */
} else {
s390_cpu_virt_mem_handle_exc(cpu, ra);
if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
be16_to_cpu(res->len))) {
setcc(cpu, 0); /* Command execution complete */
} else {
s390_cpu_virt_mem_handle_exc(cpu, ra);
}
}
}