2 * (C) Copyright 2007-2010 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
4 * This file is released under the GPLv2. See the COPYING file for more
14 #define RESET_CPU 0x000001
15 #define SET_ESA390 0x000002
16 #define RESET_PSW 0x000004
17 #define RESET_PREFIX 0x000008
18 #define RESET_CPU_TIMER 0x000010
19 #define RESET_CLK_COMP 0x000020
20 #define RESET_TOD_PROG_REG 0x000040
21 #define RESET_CR 0x000080
22 #define RESET_BREAK_EV_ADDR 0x000100
23 #define RESET_FPCR 0x000200
24 #define RESET_AR 0x000400
25 #define RESET_GPR 0x000800
26 #define RESET_FPR 0x001000
27 #define RESET_STORAGE_KEYS 0x002000
28 #define RESET_STORAGE 0x004000
29 #define RESET_NONVOL_STORAGE 0x008000
30 #define RESET_EXPANDED_STORAGE 0x010000
31 #define RESET_TOD 0x020000
32 #define RESET_TOD_STEER 0x040000
33 #define RESET_FLOATING_INTERRUPTIONS 0x080000
34 #define RESET_IO 0x100000
35 #define RESET_PLO_LOCKS 0x200000
36 #define __RESET_PLO_LOCKS_PRESERVE 0x400000
37 #define RESET_PLO_LOCKS_PRESERVE (RESET_PLO_LOCKS | \
38 __RESET_PLO_LOCKS_PRESERVE)
41 * These define all the different ways of reseting the system...to save us
44 #define SUBSYSTEM_RESET_FLAGS (RESET_FLOATING_INTERRUPTIONS | RESET_IO)
45 #define CPU_RESET_FLAGS (RESET_CPU)
46 #define INIT_CPU_RESET_FLAGS (RESET_CPU | SET_ESA390 | RESET_PSW | \
47 RESET_PREFIX | RESET_CPU_TIMER | \
48 RESET_CLK_COMP | RESET_TOD_PROG_REG | \
49 RESET_CR | RESET_BREAK_EV_ADDR | \
51 #define CLEAR_RESET_FLAGS (RESET_CPU | SET_ESA390 | RESET_PSW | \
52 RESET_PREFIX | RESET_CPU_TIMER | \
53 RESET_CLK_COMP | RESET_TOD_PROG_REG | \
54 RESET_CR | RESET_BREAK_EV_ADDR | RESET_FPCR | \
55 RESET_AR | RESET_GPR | RESET_FPR | \
56 RESET_STORAGE_KEYS | RESET_STORAGE | \
57 RESET_NONVOL_STORAGE | RESET_PLO_LOCKS | \
58 RESET_FLOATING_INTERRUPTIONS | RESET_IO)
59 #define POWER_ON_RESET_FLAGS (RESET_CPU | SET_ESA390 | RESET_PSW | \
60 RESET_PREFIX | RESET_CPU_TIMER | \
61 RESET_CLK_COMP | RESET_TOD_PROG_REG | \
62 RESET_CR | RESET_BREAK_EV_ADDR | RESET_FPCR | \
63 RESET_AR | RESET_GPR | RESET_FPR | \
64 RESET_STORAGE_KEYS | RESET_STORAGE | \
65 RESET_EXPANDED_STORAGE | RESET_TOD | \
66 RESET_TOD_STEER | RESET_PLO_LOCKS_PRESERVE | \
67 RESET_FLOATING_INTERRUPTIONS | RESET_IO)
71 * - handle Captured-z/Architecture-PSW register
73 static void __perform_cpu_reset(struct virt_sys
*sys
, int flags
)
75 struct virt_cpu
*cpu
= sys
->cpu
;
77 if (flags
& RESET_CPU
) {
78 if (flags
& SET_ESA390
) {
79 FIXME("set the arch mode to ESA/390");
82 FIXME("clear interruptions (PROG, SVC, local EXT, MCHECK)");
84 * FIXME: clear interruptions:
87 * - local EXT (floating EXT are NOT cleared)
88 * - MCHECK (floating are NOT cleared)
91 cpu
->state
= GUEST_STOPPED
;
94 if (flags
& RESET_PSW
)
95 memset(&cpu
->sie_cb
.gpsw
, 0, sizeof(struct psw
));
97 if (flags
& RESET_PREFIX
)
98 cpu
->sie_cb
.prefix
= 0;
100 if (flags
& RESET_CPU_TIMER
) {
104 if (flags
& RESET_CLK_COMP
) {
108 if (flags
& RESET_TOD_PROG_REG
) {
112 if (flags
& RESET_CR
) {
113 memset(cpu
->sie_cb
.gcr
, 0, 16*sizeof(u64
));
114 cpu
->sie_cb
.gcr
[0] = 0xE0UL
;
115 cpu
->sie_cb
.gcr
[14] = 0xC2000000UL
;
118 if (flags
& RESET_BREAK_EV_ADDR
) {
119 FIXME("initialize to 0x1");
122 if (flags
& RESET_FPCR
)
125 if (flags
& RESET_AR
)
126 memset(cpu
->regs
.ar
, 0, 16*sizeof(u32
));
128 if (flags
& RESET_GPR
)
129 memset(cpu
->regs
.gpr
, 0, 16*sizeof(u64
));
131 if (flags
& RESET_FPR
)
132 memset(cpu
->regs
.fpr
, 0, 16*sizeof(u64
));
134 if (flags
& RESET_STORAGE_KEYS
) {
137 if (flags
& RESET_STORAGE
) {
140 list_for_each_entry(p
, &sys
->guest_pages
, guest
)
141 memset(page_to_addr(p
), 0, PAGE_SIZE
);
144 if (flags
& RESET_NONVOL_STORAGE
) {
147 if (flags
& RESET_EXPANDED_STORAGE
) {
150 if (flags
& RESET_TOD
) {
153 if (flags
& RESET_TOD_STEER
) {
156 if (flags
& RESET_PLO_LOCKS
) {
157 FIXME("if RESET_PLO_LOCKS_PRESERVE is set, don't reset locks...");
159 * TODO: if RESET_PLO_LOCKS_PRESERVE is set, don't reset
160 * locks held by powered on CPUS
165 static void __perform_noncpu_reset(struct virt_sys
*sys
, int flags
)
167 struct virt_device
*vdev
;
170 if (flags
& RESET_FLOATING_INTERRUPTIONS
) {
173 if (flags
& RESET_IO
) {
174 for_each_vdev(sys
, vdev
) {
175 FIXME("wait for I/O to complete?");
176 mutex_lock(&vdev
->lock
);
179 vdev
->pmcw
.interrupt_param
= 0;
193 vdev
->pmcw
.pom
= 0xff;
195 /* defined by the install - HVF hardcoded */
197 vdev
->pmcw
.lpm
= 0x80;
198 vdev
->pmcw
.pim
= 0x80;
199 vdev
->pmcw
.pam
= 0x80;
201 vdev
->pmcw
.chpid
[i
] = 0;
203 memset(&vdev
->scsw
, 0, sizeof(struct scsw
));
204 mutex_unlock(&vdev
->lock
);
211 void guest_power_on_reset(struct virt_sys
*sys
)
213 __perform_cpu_reset(sys
, POWER_ON_RESET_FLAGS
);
214 __perform_noncpu_reset(sys
, POWER_ON_RESET_FLAGS
);
217 void guest_system_reset_normal(struct virt_sys
*sys
)
219 __perform_cpu_reset(sys
, CPU_RESET_FLAGS
);
222 * TODO: once we have SMP guests, all other cpus should get a
223 * CPU_RESET_FLAGS as well.
226 __perform_noncpu_reset(sys
, SUBSYSTEM_RESET_FLAGS
);
229 void guest_system_reset_clear(struct virt_sys
*sys
)
231 __perform_cpu_reset(sys
, CLEAR_RESET_FLAGS
);
234 * TODO: once we have SMP guests, all other cpus should get a
235 * CLEAR_RESET_FLAGS as well.
238 __perform_noncpu_reset(sys
, CLEAR_RESET_FLAGS
);
241 void guest_load_normal(struct virt_sys
*sys
)
243 __perform_cpu_reset(sys
, INIT_CPU_RESET_FLAGS
);
246 * TODO: once we have SMP guests, all other cpus should get a
250 __perform_noncpu_reset(sys
, SUBSYSTEM_RESET_FLAGS
);
253 void guest_load_clear(struct virt_sys
*sys
)
255 __perform_cpu_reset(sys
, CLEAR_RESET_FLAGS
);
258 * TODO: once we have SMP guests, all other cpus should get a
259 * CLEAR_RESET_FLAGS as well.
262 __perform_noncpu_reset(sys
, CLEAR_RESET_FLAGS
);