2 * (C) Copyright 2007-2012 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
14 static void __do_psw_swap(struct virt_cpu
*cpu
, u8
*gpsa
, u64 old
, u64
new,
17 memcpy(gpsa
+ old
, &cpu
->sie_cb
.gpsw
, len
);
18 memcpy(&cpu
->sie_cb
.gpsw
, gpsa
+ new, len
);
21 static int __mch_int(struct virt_sys
*sys
)
23 struct virt_cpu
*cpu
= sys
->cpu
;
24 struct mch_int_code
*mch
;
29 if (!cpu
->sie_cb
.gpsw
.m
)
32 /* Channel-Report Pending? */
33 if (pending_circbuf(&sys
->crws
)) {
34 cr14
= cpu
->sie_cb
.gcr
[14];
36 if (cr14
& BIT64(35)) {
37 con_printf(sys
->con
, "Time for MCH int...\n");
39 /* get the guest's first page (PSA) */
40 ret
= virt2phy_current(0, &phy
);
42 con_printf(sys
->con
, "Failed to queue up MCH "
43 "interruption: %d (%s)\n", ret
,
45 cpu
->state
= GUEST_STOPPED
;
52 __do_psw_swap(cpu
, (void*) phy
, 0x160, 0x1e0, 16);
54 __do_psw_swap(cpu
, (void*) phy
, 48, 112, 8);
56 mch
= (struct mch_int_code
*) (phy
+ 0xe8);
59 * The following bits seem to work for Hercules
62 memset(mch
, 0, sizeof(struct mch_int_code
));
63 mch
->cp
= 1; /* channel report pending */
86 static int __io_int(struct virt_sys
*sys
)
88 struct virt_cpu
*cpu
= sys
->cpu
;
89 struct vio_int
*ioint
;
95 /* are I/O interrupts enabled? */
96 if (!cpu
->sie_cb
.gpsw
.io
)
99 cr6
= cpu
->sie_cb
.gcr
[6];
101 mutex_lock(&cpu
->int_lock
);
102 /* for each subclass, check that... */
104 /* ...the subclass is enabled */
105 if (!(cr6
& (0x80000000 >> i
)))
108 /* ...there are interrupts of that subclass */
109 if (list_empty(&cpu
->int_io
[i
]))
112 /* there is an interruption that we can perform */
113 ioint
= list_first_entry(&cpu
->int_io
[i
], struct vio_int
, list
);
114 list_del(&ioint
->list
);
116 mutex_unlock(&cpu
->int_lock
);
118 con_printf(sys
->con
, "Time for I/O int... isc:%d "
119 "%08x.%08x.%08x\n", i
, ioint
->ssid
,
120 ioint
->param
, ioint
->intid
);
122 /* get the guest's first page (PSA) */
123 ret
= virt2phy_current(0, &phy
);
125 con_printf(sys
->con
, "Failed to queue up I/O "
126 "interruption: %d (%s)\n", ret
,
128 cpu
->state
= GUEST_STOPPED
;
133 /* do the PSW swap */
135 __do_psw_swap(cpu
, (void*) phy
, 0x170, 0x1f0, 16);
137 __do_psw_swap(cpu
, (void*) phy
, 56, 120, 8);
139 *((u32
*) (phy
+ 184)) = ioint
->ssid
;
140 *((u32
*) (phy
+ 188)) = ioint
->param
;
141 *((u32
*) (phy
+ 192)) = ioint
->intid
;
148 mutex_unlock(&cpu
->int_lock
);
152 void run_guest(struct virt_sys
*sys
)
154 struct psw
*psw
= &sys
->cpu
->sie_cb
.gpsw
;
164 if (!psw
->io
&& !psw
->ex
&& !psw
->m
) {
165 con_printf(sys
->con
, "ENTERED CP DUE TO DISABLED WAIT\n");
166 sys
->cpu
->state
= GUEST_STOPPED
;
176 FIXME("need to ->icptcode = 0;");
177 FIXME("load FPRs & FPCR");
180 * IMPORTANT: We MUST keep a valid stack address in R15. This way,
181 * if SIE gets interrupted via an interrupt in the host, the
182 * scheduler can still get to the struct task pointer on the stack
185 /* save current regs */
187 /* load the address of the guest state save area */
189 /* load the address of the reg save area */
191 /* load guest's R0-R13 */
195 /* save guest's R0-R13 */
196 " stmg 0,13,%2(14)\n"
197 /* restore all regs */
204 "J" (offsetof(struct virt_cpu
, regs
.gpr
)),
205 "J" (offsetof(struct virt_cpu
, sie_cb
))
210 FIXME("store FPRs & FPCR");
212 handle_interception(sys
);