]>
Commit | Line | Data |
---|---|---|
a5c95808 CH |
1 | /* |
2 | * virtio ccw machine | |
3 | * | |
4 | * Copyright 2012 IBM Corp. | |
5 | * Author(s): Cornelia Huck <[email protected]> | |
6 | * | |
7 | * This work is licensed under the terms of the GNU GPL, version 2 or (at | |
8 | * your option) any later version. See the COPYING file in the top-level | |
9 | * directory. | |
10 | */ | |
11 | ||
12 | #include "hw/boards.h" | |
13 | #include "exec/address-spaces.h" | |
14 | #include "s390-virtio.h" | |
83c9f4ca | 15 | #include "hw/s390x/sclp.h" |
3a553fc6 | 16 | #include "hw/s390x/s390_flic.h" |
a5c95808 CH |
17 | #include "ioinst.h" |
18 | #include "css.h" | |
19 | #include "virtio-ccw.h" | |
b6fe0124 | 20 | #include "qemu/config-file.h" |
8cba80c3 | 21 | #include "s390-pci-bus.h" |
0f5f6691 | 22 | #include "hw/s390x/storage-keys.h" |
a5c95808 | 23 | |
d07aa7c7 AK |
24 | #define TYPE_S390_CCW_MACHINE "s390-ccw-machine" |
25 | ||
2eb1cd07 TK |
26 | #define S390_CCW_MACHINE(obj) \ |
27 | OBJECT_CHECK(S390CcwMachineState, (obj), TYPE_S390_CCW_MACHINE) | |
28 | ||
29 | typedef struct S390CcwMachineState { | |
30 | /*< private >*/ | |
31 | MachineState parent_obj; | |
32 | ||
33 | /*< public >*/ | |
34 | bool aes_key_wrap; | |
35 | bool dea_key_wrap; | |
36 | } S390CcwMachineState; | |
37 | ||
09c7f58c DH |
38 | static const char *const reset_dev_types[] = { |
39 | "virtual-css-bridge", | |
40 | "s390-sclp-event-facility", | |
41 | "s390-flic", | |
42 | "diag288", | |
43 | }; | |
44 | ||
d9f090ec | 45 | void subsystem_reset(void) |
4e872a3f | 46 | { |
09c7f58c DH |
47 | DeviceState *dev; |
48 | int i; | |
4e872a3f | 49 | |
09c7f58c DH |
50 | for (i = 0; i < ARRAY_SIZE(reset_dev_types); i++) { |
51 | dev = DEVICE(object_resolve_path_type("", reset_dev_types[i], NULL)); | |
52 | if (dev) { | |
53 | qdev_reset_all(dev); | |
54 | } | |
0c7322cf | 55 | } |
4e872a3f CB |
56 | } |
57 | ||
a5c95808 CH |
58 | static int virtio_ccw_hcall_notify(const uint64_t *args) |
59 | { | |
60 | uint64_t subch_id = args[0]; | |
61 | uint64_t queue = args[1]; | |
62 | SubchDev *sch; | |
63 | int cssid, ssid, schid, m; | |
64 | ||
65 | if (ioinst_disassemble_sch_ident(subch_id, &m, &cssid, &ssid, &schid)) { | |
66 | return -EINVAL; | |
67 | } | |
68 | sch = css_find_subch(m, cssid, ssid, schid); | |
69 | if (!sch || !css_subch_visible(sch)) { | |
70 | return -EINVAL; | |
71 | } | |
8dfbaa6a | 72 | if (queue >= VIRTIO_CCW_QUEUE_MAX) { |
b57ed9bf CH |
73 | return -EINVAL; |
74 | } | |
a5c95808 CH |
75 | virtio_queue_notify(virtio_ccw_get_vdev(sch), queue); |
76 | return 0; | |
77 | ||
78 | } | |
79 | ||
80 | static int virtio_ccw_hcall_early_printk(const uint64_t *args) | |
81 | { | |
82 | uint64_t mem = args[0]; | |
83 | ||
84 | if (mem < ram_size) { | |
85 | /* Early printk */ | |
86 | return 0; | |
87 | } | |
88 | return -EINVAL; | |
89 | } | |
90 | ||
91 | static void virtio_ccw_register_hcalls(void) | |
92 | { | |
93 | s390_register_virtio_hypercall(KVM_S390_VIRTIO_CCW_NOTIFY, | |
94 | virtio_ccw_hcall_notify); | |
95 | /* Tolerate early printk. */ | |
96 | s390_register_virtio_hypercall(KVM_S390_VIRTIO_NOTIFY, | |
97 | virtio_ccw_hcall_early_printk); | |
98 | } | |
99 | ||
80d23275 | 100 | void s390_memory_init(ram_addr_t mem_size) |
a5c95808 | 101 | { |
a5c95808 CH |
102 | MemoryRegion *sysmem = get_system_memory(); |
103 | MemoryRegion *ram = g_new(MemoryRegion, 1); | |
80d23275 DH |
104 | |
105 | /* allocate RAM for core */ | |
f8ed85ac | 106 | memory_region_init_ram(ram, NULL, "s390.ram", mem_size, &error_fatal); |
80d23275 DH |
107 | vmstate_register_ram_global(ram); |
108 | memory_region_add_subregion(sysmem, 0, ram); | |
109 | ||
110 | /* Initialize storage key device */ | |
111 | s390_skeys_init(); | |
112 | } | |
113 | ||
114 | static void ccw_init(MachineState *machine) | |
115 | { | |
a5c95808 CH |
116 | int ret; |
117 | VirtualCssBus *css_bus; | |
8cba80c3 | 118 | DeviceState *dev; |
b6fe0124 | 119 | |
1cf065fb | 120 | s390_sclp_init(); |
80d23275 | 121 | s390_memory_init(machine->ram_size); |
a5c95808 CH |
122 | |
123 | /* get a BUS */ | |
124 | css_bus = virtual_css_bus_init(); | |
3ef96221 | 125 | s390_init_ipl_dev(machine->kernel_filename, machine->kernel_cmdline, |
f0180f91 | 126 | machine->initrd_filename, "s390-ccw.img", true); |
3a553fc6 | 127 | s390_flic_init(); |
a5c95808 | 128 | |
8cba80c3 FB |
129 | dev = qdev_create(NULL, TYPE_S390_PCI_HOST_BRIDGE); |
130 | object_property_add_child(qdev_get_machine(), TYPE_S390_PCI_HOST_BRIDGE, | |
131 | OBJECT(dev), NULL); | |
132 | qdev_init_nofail(dev); | |
133 | ||
a5c95808 CH |
134 | /* register hypercalls */ |
135 | virtio_ccw_register_hcalls(); | |
136 | ||
a5c95808 | 137 | /* init CPUs */ |
0f5f6691 | 138 | s390_init_cpus(machine->cpu_model); |
a5c95808 CH |
139 | |
140 | if (kvm_enabled()) { | |
141 | kvm_s390_enable_css_support(s390_cpu_addr2state(0)); | |
142 | } | |
143 | /* | |
144 | * Create virtual css and set it as default so that non mcss-e | |
145 | * enabled guests only see virtio devices. | |
146 | */ | |
147 | ret = css_create_css_image(VIRTUAL_CSSID, true); | |
148 | assert(ret == 0); | |
149 | ||
150 | /* Create VirtIO network adapters */ | |
151 | s390_create_virtio_net(BUS(css_bus), "virtio-net-ccw"); | |
3f9e59bb JH |
152 | |
153 | /* Register savevm handler for guest TOD clock */ | |
154 | register_savevm(NULL, "todclock", 0, 1, | |
155 | gtod_save, gtod_load, kvm_state); | |
a5c95808 CH |
156 | } |
157 | ||
d07aa7c7 AK |
158 | static void ccw_machine_class_init(ObjectClass *oc, void *data) |
159 | { | |
160 | MachineClass *mc = MACHINE_CLASS(oc); | |
3dd7852f | 161 | NMIClass *nc = NMI_CLASS(oc); |
d07aa7c7 | 162 | |
d07aa7c7 | 163 | mc->init = ccw_init; |
db3b2566 | 164 | mc->reset = s390_machine_reset; |
d07aa7c7 AK |
165 | mc->block_default_type = IF_VIRTIO; |
166 | mc->no_cdrom = 1; | |
167 | mc->no_floppy = 1; | |
168 | mc->no_serial = 1; | |
169 | mc->no_parallel = 1; | |
170 | mc->no_sdcard = 1; | |
fb85b34d | 171 | mc->use_sclp = 1; |
d07aa7c7 | 172 | mc->max_cpus = 255; |
3dd7852f | 173 | nc->nmi_monitor_handler = s390_nmi; |
d07aa7c7 AK |
174 | } |
175 | ||
2eb1cd07 TK |
176 | static inline bool machine_get_aes_key_wrap(Object *obj, Error **errp) |
177 | { | |
178 | S390CcwMachineState *ms = S390_CCW_MACHINE(obj); | |
179 | ||
180 | return ms->aes_key_wrap; | |
181 | } | |
182 | ||
183 | static inline void machine_set_aes_key_wrap(Object *obj, bool value, | |
184 | Error **errp) | |
185 | { | |
186 | S390CcwMachineState *ms = S390_CCW_MACHINE(obj); | |
187 | ||
188 | ms->aes_key_wrap = value; | |
189 | } | |
190 | ||
191 | static inline bool machine_get_dea_key_wrap(Object *obj, Error **errp) | |
192 | { | |
193 | S390CcwMachineState *ms = S390_CCW_MACHINE(obj); | |
194 | ||
195 | return ms->dea_key_wrap; | |
196 | } | |
197 | ||
198 | static inline void machine_set_dea_key_wrap(Object *obj, bool value, | |
199 | Error **errp) | |
200 | { | |
201 | S390CcwMachineState *ms = S390_CCW_MACHINE(obj); | |
202 | ||
203 | ms->dea_key_wrap = value; | |
204 | } | |
205 | ||
206 | static inline void s390_machine_initfn(Object *obj) | |
207 | { | |
208 | object_property_add_bool(obj, "aes-key-wrap", | |
209 | machine_get_aes_key_wrap, | |
210 | machine_set_aes_key_wrap, NULL); | |
211 | object_property_set_description(obj, "aes-key-wrap", | |
212 | "enable/disable AES key wrapping using the CPACF wrapping key", | |
213 | NULL); | |
214 | object_property_set_bool(obj, true, "aes-key-wrap", NULL); | |
215 | ||
216 | object_property_add_bool(obj, "dea-key-wrap", | |
217 | machine_get_dea_key_wrap, | |
218 | machine_set_dea_key_wrap, NULL); | |
219 | object_property_set_description(obj, "dea-key-wrap", | |
220 | "enable/disable DEA key wrapping using the CPACF wrapping key", | |
221 | NULL); | |
222 | object_property_set_bool(obj, true, "dea-key-wrap", NULL); | |
223 | } | |
224 | ||
d07aa7c7 AK |
225 | static const TypeInfo ccw_machine_info = { |
226 | .name = TYPE_S390_CCW_MACHINE, | |
227 | .parent = TYPE_MACHINE, | |
c4d3c0a2 | 228 | .abstract = true, |
2eb1cd07 TK |
229 | .instance_size = sizeof(S390CcwMachineState), |
230 | .instance_init = s390_machine_initfn, | |
d07aa7c7 | 231 | .class_init = ccw_machine_class_init, |
3dd7852f AK |
232 | .interfaces = (InterfaceInfo[]) { |
233 | { TYPE_NMI }, | |
234 | { } | |
235 | }, | |
a5c95808 CH |
236 | }; |
237 | ||
9ef40173 JH |
238 | #define CCW_COMPAT_2_4 \ |
239 | {\ | |
240 | .driver = TYPE_S390_SKEYS,\ | |
241 | .property = "migration-enabled",\ | |
242 | .value = "off",\ | |
542571d5 CH |
243 | },{\ |
244 | .driver = "virtio-blk-ccw",\ | |
245 | .property = "max_revision",\ | |
246 | .value = "0",\ | |
247 | },{\ | |
248 | .driver = "virtio-balloon-ccw",\ | |
249 | .property = "max_revision",\ | |
250 | .value = "0",\ | |
251 | },{\ | |
252 | .driver = "virtio-serial-ccw",\ | |
253 | .property = "max_revision",\ | |
254 | .value = "0",\ | |
255 | },{\ | |
256 | .driver = "virtio-9p-ccw",\ | |
257 | .property = "max_revision",\ | |
258 | .value = "0",\ | |
259 | },{\ | |
260 | .driver = "virtio-rng-ccw",\ | |
261 | .property = "max_revision",\ | |
262 | .value = "0",\ | |
085b0b05 CH |
263 | },{\ |
264 | .driver = "virtio-net-ccw",\ | |
265 | .property = "max_revision",\ | |
266 | .value = "0",\ | |
267 | },{\ | |
268 | .driver = "virtio-scsi-ccw",\ | |
269 | .property = "max_revision",\ | |
270 | .value = "0",\ | |
271 | },{\ | |
272 | .driver = "vhost-scsi-ccw",\ | |
273 | .property = "max_revision",\ | |
274 | .value = "0",\ | |
9ef40173 JH |
275 | }, |
276 | ||
c4d3c0a2 CB |
277 | static void ccw_machine_2_4_class_init(ObjectClass *oc, void *data) |
278 | { | |
279 | MachineClass *mc = MACHINE_CLASS(oc); | |
9ef40173 JH |
280 | static GlobalProperty compat_props[] = { |
281 | CCW_COMPAT_2_4 | |
282 | { /* end of list */ } | |
283 | }; | |
c4d3c0a2 | 284 | |
c4d3c0a2 | 285 | mc->desc = "VirtIO-ccw based S390 machine v2.4"; |
9ef40173 | 286 | mc->compat_props = compat_props; |
c4d3c0a2 CB |
287 | } |
288 | ||
289 | static const TypeInfo ccw_machine_2_4_info = { | |
af62e639 | 290 | .name = MACHINE_TYPE_NAME("s390-ccw-virtio-2.4"), |
c4d3c0a2 CB |
291 | .parent = TYPE_S390_CCW_MACHINE, |
292 | .class_init = ccw_machine_2_4_class_init, | |
293 | }; | |
294 | ||
84b48ad6 CH |
295 | static void ccw_machine_2_5_class_init(ObjectClass *oc, void *data) |
296 | { | |
297 | MachineClass *mc = MACHINE_CLASS(oc); | |
298 | ||
84b48ad6 CH |
299 | mc->alias = "s390-ccw-virtio"; |
300 | mc->desc = "VirtIO-ccw based S390 machine v2.5"; | |
301 | mc->is_default = 1; | |
302 | } | |
303 | ||
304 | static const TypeInfo ccw_machine_2_5_info = { | |
af62e639 | 305 | .name = MACHINE_TYPE_NAME("s390-ccw-virtio-2.5"), |
84b48ad6 CH |
306 | .parent = TYPE_S390_CCW_MACHINE, |
307 | .class_init = ccw_machine_2_5_class_init, | |
308 | }; | |
309 | ||
d07aa7c7 | 310 | static void ccw_machine_register_types(void) |
a5c95808 | 311 | { |
d07aa7c7 | 312 | type_register_static(&ccw_machine_info); |
c4d3c0a2 | 313 | type_register_static(&ccw_machine_2_4_info); |
84b48ad6 | 314 | type_register_static(&ccw_machine_2_5_info); |
a5c95808 CH |
315 | } |
316 | ||
d07aa7c7 | 317 | type_init(ccw_machine_register_types) |