cp: guest layer revamp, part 1
[hvf.git] / cp / guest / run.c
blobccf8888d846e61a348a03ae7a9886b1457383539
1 /*
2 * (C) Copyright 2007-2011 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
5 * details.
6 */
8 #include <directory.h>
9 #include <sched.h>
10 #include <dat.h>
11 #include <vcpu.h>
12 #include <slab.h>
14 static void __do_psw_swap(struct virt_cpu *cpu, u8 *gpsa, u64 old, u64 new,
15 int len)
17 memcpy(gpsa + old, &cpu->sie_cb.gpsw, len);
18 memcpy(&cpu->sie_cb.gpsw, gpsa + new, len);
21 static int __io_int(struct virt_sys *sys)
23 struct virt_cpu *cpu = sys->task->cpu;
24 struct vio_int *ioint;
25 u64 cr6;
26 u64 phy;
27 int ret;
28 int i;
30 /* are I/O interrupts enabled? */
31 if (!cpu->sie_cb.gpsw.io)
32 return 0;
34 cr6 = cpu->sie_cb.gcr[6];
36 mutex_lock(&cpu->int_lock);
37 /* for each subclass, check that... */
38 for(i=0; i<8; i++) {
39 /* ...the subclass is enabled */
40 if (!(cr6 & (0x80000000 >> i)))
41 continue;
43 /* ...there are interrupts of that subclass */
44 if (list_empty(&cpu->int_io[i]))
45 continue;
47 /* there is an interruption that we can perform */
48 ioint = list_first_entry(&cpu->int_io[i], struct vio_int, list);
49 list_del(&ioint->list);
51 mutex_unlock(&cpu->int_lock);
53 con_printf(sys->con, "Time for I/O int... isc:%d "
54 "%08x.%08x.%08x\n", i, ioint->ssid,
55 ioint->param, ioint->intid);
57 /* get the guest's first page (PSA) */
58 ret = virt2phy_current(0, &phy);
59 if (ret) {
60 con_printf(sys->con, "Failed to queue up I/O "
61 "interruption: %d (%s)\n", ret,
62 errstrings[-ret]);
63 cpu->state = GUEST_STOPPED;
65 return 0;
68 /* do the PSW swap */
69 if (VCPU_ZARCH(cpu))
70 __do_psw_swap(cpu, (void*) phy, 0x170, 0x1f0, 16);
71 else
72 __do_psw_swap(cpu, (void*) phy, 56, 120, 8);
74 *((u32*) (phy + 184)) = ioint->ssid;
75 *((u32*) (phy + 188)) = ioint->param;
76 *((u32*) (phy + 192)) = ioint->intid;
78 free(ioint);
80 return 1;
83 mutex_unlock(&cpu->int_lock);
84 return 0;
88 * FIXME:
89 * - issue any pending interruptions
91 void run_guest(struct virt_sys *sys)
93 struct psw *psw = &sys->task->cpu->sie_cb.gpsw;
94 u64 save_gpr[16];
96 if (__io_int(sys))
97 goto go;
99 if (psw->w) {
100 if (!psw->io && !psw->ex && !psw->m) {
101 con_printf(sys->con, "ENTERED CP DUE TO DISABLED WAIT\n");
102 sys->task->cpu->state = GUEST_STOPPED;
103 return;
106 /* wait state */
107 schedule();
108 return;
113 * FIXME: need to ->icptcode = 0;
117 * FIXME: load FPRs & FPCR
121 * IMPORTANT: We MUST keep a valid stack address in R15. This way,
122 * if SIE gets interrupted via an interrupt in the host, the
123 * scheduler can still get to the struct task pointer on the stack
125 asm volatile(
126 /* save current regs */
127 " stmg 0,15,%0\n"
128 /* load the address of the guest state save area */
129 " lr 14,%1\n"
130 /* load the address of the reg save area */
131 " la 15,%0\n"
132 /* load guest's R0-R13 */
133 " lmg 0,13,%2(14)\n"
134 /* SIE */
135 " sie %3(14)\n"
136 /* save guest's R0-R13 */
137 " stmg 0,13,%2(14)\n"
138 /* restore all regs */
139 " lmg 0,15,0(15)\n"
141 : /* output */
142 "+m" (save_gpr)
143 : /* input */
144 "a" (sys->task->cpu),
145 "J" (offsetof(struct virt_cpu, regs.gpr)),
146 "J" (offsetof(struct virt_cpu, sie_cb))
147 : /* clobbered */
148 "memory"
152 * FIXME: store FPRs & FPCR
155 handle_interception(sys);