On Wed, 1 Feb 2023 08:48:33 +0000 Janosch Frank <frankja@xxxxxxxxxxxxx> wrote: > The diag308 requires extensive cooperation between the hypervisor and > the Ultravisor so the Ultravisor can make sure all necessary reset > steps have been done. > > Let's check if we get the correct validity errors. > > Signed-off-by: Janosch Frank <frankja@xxxxxxxxxxxxx> > --- [...] > + > + /* > + * We need to perform several UV calls to emulate the subcode > + * 1. Failing to do that should result in a validity > + * > + * - Mark all cpus as stopped > + * - Reset the cpus, calling one gets an initial reset > + * - Load the reset PSW > + * - Unshare all > + * - Load the reset PSW you forgot to mention prepare the reset, and the list does not reflect the order things are done in the code > + */ > + sie_expect_validity(&vm); > + sie(&vm); > + report((sie_get_validity(&vm) & 0xff00) == 0x2000, "validity no UVCs"); > + > + /* Mark the CPU as stopped so we can unshare and reset */ > + cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_STP); > + report(!cc, "Set cpu stopped"); > + > + sie_expect_validity(&vm); > + sie(&vm); > + report((sie_get_validity(&vm) & 0xff00) == 0x2000, "validity stopped"); > + > + /* Unshare all memory */ > + cc = uv_cmd_nodata(vm.sblk->pv_handle_config, > + UVC_CMD_SET_UNSHARED_ALL, &rc, &rrc); > + report(cc == 0 && rc == 1, "Unshare all"); > + > + sie_expect_validity(&vm); > + sie(&vm); > + report((sie_get_validity(&vm) & 0xff00) == 0x2000, > + "validity stopped, unshared"); > + > + /* Prepare the CPU reset */ > + cc = uv_cmd_nodata(vm.sblk->pv_handle_config, > + UVC_CMD_PREPARE_RESET, &rc, &rrc); > + report(cc == 0 && rc == 1, "Prepare reset call"); > + > + sie_expect_validity(&vm); > + sie(&vm); > + report((sie_get_validity(&vm) & 0xff00) == 0x2000, > + "validity stopped, unshared, prepare"); > + > + /* Do the reset */ > + cc = uv_cmd_nodata(vm.sblk->pv_handle_cpu, > + UVC_CMD_CPU_RESET_INITIAL, &rc, &rrc); > + report(cc == 0 && rc == 1, "Clear reset cpu"); > + > + sie_expect_validity(&vm); > + sie(&vm); > + report((sie_get_validity(&vm) & 0xff00) == 0x2000, > + "validity stopped, unshared, prepare, reset"); > + > + /* Load the PSW from 0x0 */ > + cc = uv_set_cpu_state(vm.sblk->pv_handle_cpu, PV_CPU_STATE_OPR_LOAD); > + report(!cc, "Set cpu load"); > + > + /* > + * Check if we executed the iaddr of the reset PSW, we should > + * see a diagnose 0x9c PV instruction notification. > + */ > + sie(&vm); > + report(vm.sblk->icptcode == ICPT_PV_NOTIFY && vm.sblk->ipa == 0x8302 && > + vm.sblk->ipb == 0x50000000 && vm.save_area.guest.grs[5] == 0x9c && > + vm.save_area.guest.grs[0] == 42, > + "intercept values after diag 0x308"); > + > + > + uv_destroy_guest(&vm); > + report_prefix_pop(); > +} > + [...] > diff --git a/s390x/snippets/asm/snippet-pv-diag-308.S b/s390x/snippets/asm/snippet-pv-diag-308.S > new file mode 100644 > index 00000000..58c96173 > --- /dev/null > +++ b/s390x/snippets/asm/snippet-pv-diag-308.S > @@ -0,0 +1,67 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Diagnose 0x308 snippet used for PV IPL and reset testing > + * > + * Copyright (c) 2023 IBM Corp > + * > + * Authors: > + * Janosch Frank <frankja@xxxxxxxxxxxxx> > + */ > +#include <asm/asm-offsets.h> > +.section .text > + > +/* Sets a reset PSW with the given PSW address */ > +.macro SET_RESET_PSW_ADDR label > +lgrl %r5, reset_psw > +larl %r6, \label > +ogr %r5, %r6 > +stg %r5, 0 > +.endm > + > +/* Does a diagnose 308 with the given subcode */ > +.macro DIAG308 subcode > +xgr %r3, %r3 > +lghi %r3, \subcode > +diag 1, 3, 0x308 > +.endm > + > +sam64 > + > +/* Execute the diag500 which will set the subcode we execute in gr2 */ > +diag 0, 0, 0x500 > + > +/* > + * A valid PGM new PSW can be a real problem since we never fall out > + * of SIE and therefore effectively loop forever. 0 is a valid PSW > + * therefore we re-use the reset_psw as this has the short PSW > + * bit set which is invalid for a long PSW like the exception new > + * PSWs. > + * > + * For subcode 0/1 there are no PGMs to consider. > + */ > +lgrl %r5, reset_psw > +stg %r5, GEN_LC_PGM_NEW_PSW > + > +/* Clean registers that are used */ > +xgr %r0, %r0 > +xgr %r1, %r1 > +xgr %r3, %r3 > +xgr %r4, %r4 > +xgr %r5, %r5 > +xgr %r6, %r6 > + > +/* Subcode 0 - Modified Clear */ what about subcode 1? > +SET_RESET_PSW_ADDR done > +diag %r0, %r2, 0x308 > + > +/* Should never be executed because of the reset PSW */ > +diag 0, 0, 0x44 > + > +done: > +lghi %r1, 42 > +diag %r1, 0, 0x9c > + > + > + .align 8 > +reset_psw: > + .quad 0x0008000180000000