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

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); s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return; 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return; 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); s390_program_interrupt(env, PGM_SPECIFICATION, ra);
return; 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return; return;
} }
@ -231,6 +235,10 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
cc = css_do_stcrw(&crw); cc = css_do_stcrw(&crw);
/* 0 - crw stored, 1 - zeroes stored */ /* 0 - crw stored, 1 - zeroes stored */
if (s390_is_pv()) {
s390_cpu_pv_mem_write(cpu, addr, &crw, sizeof(crw));
setcc(cpu, cc);
} else {
if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) { if (s390_cpu_virt_mem_write(cpu, addr, ar, &crw, sizeof(crw)) == 0) {
setcc(cpu, cc); setcc(cpu, cc);
} else { } else {
@ -241,6 +249,7 @@ void ioinst_handle_stcrw(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
s390_cpu_virt_mem_handle_exc(cpu, ra); s390_cpu_virt_mem_handle_exc(cpu, ra);
} }
} }
}
void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, void ioinst_handle_stsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb,
uintptr_t ra) uintptr_t 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)) { 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, * As operand exceptions have a lower priority than access exceptions,
* we check whether the memory area is writeable (injecting the * 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 (cc != 3) {
if (s390_cpu_virt_mem_write(cpu, addr, ar, &schib, 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) { sizeof(schib)) != 0) {
s390_cpu_virt_mem_handle_exc(cpu, ra); s390_cpu_virt_mem_handle_exc(cpu, ra);
return; return;
} }
} else { } else {
/* Access exceptions have a higher priority than cc3 */ /* 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return; 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 */ /* 0 - status pending, 1 - not status pending, 3 - not operational */
if (cc != 3) { 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return -EFAULT; return -EFAULT;
} }
@ -344,7 +365,8 @@ int ioinst_handle_tsch(S390CPU *cpu, uint64_t reg1, uint32_t ipb, uintptr_t ra)
} else { } else {
irb_len = sizeof(irb) - sizeof(irb.emw); irb_len = sizeof(irb) - sizeof(irb.emw);
/* Access exceptions have a higher priority than cc3 */ /* 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return -EFAULT; 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 * present CHSC sub-handlers ... if we ever need more, we should take
* care of req->len here first. * 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); s390_cpu_virt_mem_handle_exc(cpu, ra);
return; return;
} }
@ -675,6 +699,10 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
break; break;
} }
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 {
if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res, if (!s390_cpu_virt_mem_write(cpu, addr + len, reg, res,
be16_to_cpu(res->len))) { be16_to_cpu(res->len))) {
setcc(cpu, 0); /* Command execution complete */ setcc(cpu, 0); /* Command execution complete */
@ -682,6 +710,7 @@ void ioinst_handle_chsc(S390CPU *cpu, uint32_t ipb, uintptr_t ra)
s390_cpu_virt_mem_handle_exc(cpu, ra); s390_cpu_virt_mem_handle_exc(cpu, ra);
} }
} }
}
#define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc) #define SCHM_REG1_RES(_reg) (_reg & 0x000000000ffffffc)
#define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28) #define SCHM_REG1_MBK(_reg) ((_reg & 0x00000000f0000000) >> 28)