@@ -92,6 +92,7 @@ enum address_space {
};
#define PSW_MASK_DAT 0x0400000000000000UL
+#define PSW_MASK_HOME 0x0000C00000000000UL
#define PSW_MASK_IO 0x0200000000000000UL
#define PSW_MASK_EXT 0x0100000000000000UL
#define PSW_MASK_KEY 0x00F0000000000000UL
@@ -54,6 +54,8 @@ void sie_handle_validity(struct vm *vm)
void sie(struct vm *vm)
{
+ uint64_t old_cr13;
+
if (vm->sblk->sdf == 2)
memcpy(vm->sblk->pv_grregs, vm->save_area.guest.grs,
sizeof(vm->save_area.guest.grs));
@@ -61,6 +63,24 @@ void sie(struct vm *vm)
/* Reset icptcode so we don't trip over it below */
vm->sblk->icptcode = 0;
+ /*
+ * Set up home address space to match primary space. Instead of running
+ * in home space all the time, we switch every time in sie() because:
+ * - tests that depend on running in primary space mode don't need to be
+ * touched
+ * - it avoids regressions in tests
+ * - switching every time makes it easier to extend this in the future,
+ * for example to allow tests to run in whatever space they want
+ */
+ old_cr13 = stctg(13);
+ lctlg(13, stctg(1));
+
+ /* switch to home space so guest tables can be different from host */
+ psw_mask_set_bits(PSW_MASK_HOME);
+
+ /* also handle all interruptions in home space while in SIE */
+ irq_set_dat_mode(true, AS_HOME);
+
while (vm->sblk->icptcode == 0) {
sie64a(vm->sblk, &vm->save_area);
sie_handle_validity(vm);
@@ -68,6 +88,12 @@ void sie(struct vm *vm)
vm->save_area.guest.grs[14] = vm->sblk->gg14;
vm->save_area.guest.grs[15] = vm->sblk->gg15;
+ irq_set_dat_mode(true, AS_PRIM);
+ psw_mask_clear_bits(PSW_MASK_HOME);
+
+ /* restore the old CR 13 */
+ lctlg(13, old_cr13);
+
if (vm->sblk->sdf == 2)
memcpy(vm->save_area.guest.grs, vm->sblk->pv_grregs,
sizeof(vm->save_area.guest.grs));