blob: 40e4f2de73208d290dad4a14b6bfdbdbf759381e [file] [log] [blame]
Heiko Carstensb0c632d2008-03-25 18:47:20 +01001/*
2 * s390host.c -- hosting zSeries kernel virtual machines
3 *
4 * Copyright IBM Corp. 2008
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License (version 2 only)
8 * as published by the Free Software Foundation.
9 *
10 * Author(s): Carsten Otte <cotte@de.ibm.com>
11 * Christian Borntraeger <borntraeger@de.ibm.com>
12 * Heiko Carstens <heiko.carstens@de.ibm.com>
13 */
14
15#include <linux/compiler.h>
16#include <linux/err.h>
17#include <linux/fs.h>
18#include <linux/init.h>
19#include <linux/kvm.h>
20#include <linux/kvm_host.h>
21#include <linux/module.h>
22#include <linux/slab.h>
Carsten Otteba5c1e92008-03-25 18:47:26 +010023#include <linux/timer.h>
Heiko Carstensb0c632d2008-03-25 18:47:20 +010024#include <asm/lowcore.h>
25#include <asm/pgtable.h>
26
Christian Borntraeger8f2abe62008-03-25 18:47:23 +010027#include "kvm-s390.h"
Heiko Carstensb0c632d2008-03-25 18:47:20 +010028#include "gaccess.h"
29
30#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
31
32struct kvm_stats_debugfs_item debugfs_entries[] = {
33 { "userspace_handled", VCPU_STAT(exit_userspace) },
Christian Borntraeger0eaeafa2008-05-07 09:22:53 +020034 { "exit_null", VCPU_STAT(exit_null) },
Christian Borntraeger8f2abe62008-03-25 18:47:23 +010035 { "exit_validity", VCPU_STAT(exit_validity) },
36 { "exit_stop_request", VCPU_STAT(exit_stop_request) },
37 { "exit_external_request", VCPU_STAT(exit_external_request) },
38 { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
Carsten Otteba5c1e92008-03-25 18:47:26 +010039 { "exit_instruction", VCPU_STAT(exit_instruction) },
40 { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
41 { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
42 { "instruction_lctg", VCPU_STAT(instruction_lctg) },
43 { "instruction_lctl", VCPU_STAT(instruction_lctl) },
44 { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
45 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
46 { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
47 { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
48 { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
49 { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
50 { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
51 { "exit_wait_state", VCPU_STAT(exit_wait_state) },
Christian Borntraeger453423d2008-03-25 18:47:29 +010052 { "instruction_stidp", VCPU_STAT(instruction_stidp) },
53 { "instruction_spx", VCPU_STAT(instruction_spx) },
54 { "instruction_stpx", VCPU_STAT(instruction_stpx) },
55 { "instruction_stap", VCPU_STAT(instruction_stap) },
56 { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
57 { "instruction_stsch", VCPU_STAT(instruction_stsch) },
58 { "instruction_chsc", VCPU_STAT(instruction_chsc) },
59 { "instruction_stsi", VCPU_STAT(instruction_stsi) },
60 { "instruction_stfl", VCPU_STAT(instruction_stfl) },
Christian Borntraeger5288fbf2008-03-25 18:47:31 +010061 { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
62 { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
63 { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
64 { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
65 { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
66 { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
Christian Borntraegere28acfe2008-03-25 18:47:34 +010067 { "diagnose_44", VCPU_STAT(diagnose_44) },
Heiko Carstensb0c632d2008-03-25 18:47:20 +010068 { NULL }
69};
70
71
72/* Section: not file related */
73void kvm_arch_hardware_enable(void *garbage)
74{
75 /* every s390 is virtualization enabled ;-) */
76}
77
78void kvm_arch_hardware_disable(void *garbage)
79{
80}
81
82void decache_vcpus_on_cpu(int cpu)
83{
84}
85
86int kvm_arch_hardware_setup(void)
87{
88 return 0;
89}
90
91void kvm_arch_hardware_unsetup(void)
92{
93}
94
95void kvm_arch_check_processor_compat(void *rtn)
96{
97}
98
99int kvm_arch_init(void *opaque)
100{
101 return 0;
102}
103
104void kvm_arch_exit(void)
105{
106}
107
108/* Section: device related */
109long kvm_arch_dev_ioctl(struct file *filp,
110 unsigned int ioctl, unsigned long arg)
111{
112 if (ioctl == KVM_S390_ENABLE_SIE)
113 return s390_enable_sie();
114 return -EINVAL;
115}
116
117int kvm_dev_ioctl_check_extension(long ext)
118{
119 return 0;
120}
121
122/* Section: vm related */
123/*
124 * Get (and clear) the dirty memory log for a memory slot.
125 */
126int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
127 struct kvm_dirty_log *log)
128{
129 return 0;
130}
131
132long kvm_arch_vm_ioctl(struct file *filp,
133 unsigned int ioctl, unsigned long arg)
134{
135 struct kvm *kvm = filp->private_data;
136 void __user *argp = (void __user *)arg;
137 int r;
138
139 switch (ioctl) {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100140 case KVM_S390_INTERRUPT: {
141 struct kvm_s390_interrupt s390int;
142
143 r = -EFAULT;
144 if (copy_from_user(&s390int, argp, sizeof(s390int)))
145 break;
146 r = kvm_s390_inject_vm(kvm, &s390int);
147 break;
148 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100149 default:
150 r = -EINVAL;
151 }
152
153 return r;
154}
155
156struct kvm *kvm_arch_create_vm(void)
157{
158 struct kvm *kvm;
159 int rc;
160 char debug_name[16];
161
162 rc = s390_enable_sie();
163 if (rc)
164 goto out_nokvm;
165
166 rc = -ENOMEM;
167 kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL);
168 if (!kvm)
169 goto out_nokvm;
170
171 kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
172 if (!kvm->arch.sca)
173 goto out_nosca;
174
175 sprintf(debug_name, "kvm-%u", current->pid);
176
177 kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
178 if (!kvm->arch.dbf)
179 goto out_nodbf;
180
Carsten Otteba5c1e92008-03-25 18:47:26 +0100181 spin_lock_init(&kvm->arch.float_int.lock);
182 INIT_LIST_HEAD(&kvm->arch.float_int.list);
183
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100184 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
185 VM_EVENT(kvm, 3, "%s", "vm created");
186
187 try_module_get(THIS_MODULE);
188
189 return kvm;
190out_nodbf:
191 free_page((unsigned long)(kvm->arch.sca));
192out_nosca:
193 kfree(kvm);
194out_nokvm:
195 return ERR_PTR(rc);
196}
197
198void kvm_arch_destroy_vm(struct kvm *kvm)
199{
200 debug_unregister(kvm->arch.dbf);
201 free_page((unsigned long)(kvm->arch.sca));
202 kfree(kvm);
203 module_put(THIS_MODULE);
204}
205
206/* Section: vcpu related */
207int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
208{
209 return 0;
210}
211
212void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
213{
214 /* kvm common code refers to this, but does'nt call it */
215 BUG();
216}
217
218void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
219{
220 save_fp_regs(&vcpu->arch.host_fpregs);
221 save_access_regs(vcpu->arch.host_acrs);
222 vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
223 restore_fp_regs(&vcpu->arch.guest_fpregs);
224 restore_access_regs(vcpu->arch.guest_acrs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100225}
226
227void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
228{
229 save_fp_regs(&vcpu->arch.guest_fpregs);
230 save_access_regs(vcpu->arch.guest_acrs);
231 restore_fp_regs(&vcpu->arch.host_fpregs);
232 restore_access_regs(vcpu->arch.host_acrs);
233}
234
235static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
236{
237 /* this equals initial cpu reset in pop, but we don't switch to ESA */
238 vcpu->arch.sie_block->gpsw.mask = 0UL;
239 vcpu->arch.sie_block->gpsw.addr = 0UL;
240 vcpu->arch.sie_block->prefix = 0UL;
241 vcpu->arch.sie_block->ihcpu = 0xffff;
242 vcpu->arch.sie_block->cputm = 0UL;
243 vcpu->arch.sie_block->ckc = 0UL;
244 vcpu->arch.sie_block->todpr = 0;
245 memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
246 vcpu->arch.sie_block->gcr[0] = 0xE0UL;
247 vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
248 vcpu->arch.guest_fpregs.fpc = 0;
249 asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
250 vcpu->arch.sie_block->gbea = 1;
251}
252
253int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
254{
255 atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH);
256 vcpu->arch.sie_block->gmslm = 0xffffffffffUL;
257 vcpu->arch.sie_block->gmsor = 0x000000000000;
258 vcpu->arch.sie_block->ecb = 2;
259 vcpu->arch.sie_block->eca = 0xC1002001U;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100260 setup_timer(&vcpu->arch.ckc_timer, kvm_s390_idle_wakeup,
261 (unsigned long) vcpu);
Christian Borntraeger453423d2008-03-25 18:47:29 +0100262 get_cpu_id(&vcpu->arch.cpu_id);
263 vcpu->arch.cpu_id.version = 0xfe;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100264 return 0;
265}
266
267struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
268 unsigned int id)
269{
270 struct kvm_vcpu *vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
271 int rc = -ENOMEM;
272
273 if (!vcpu)
274 goto out_nomem;
275
276 vcpu->arch.sie_block = (struct sie_block *) get_zeroed_page(GFP_KERNEL);
277
278 if (!vcpu->arch.sie_block)
279 goto out_free_cpu;
280
281 vcpu->arch.sie_block->icpua = id;
282 BUG_ON(!kvm->arch.sca);
283 BUG_ON(kvm->arch.sca->cpu[id].sda);
284 kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
285 vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
286 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
287
Carsten Otteba5c1e92008-03-25 18:47:26 +0100288 spin_lock_init(&vcpu->arch.local_int.lock);
289 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
290 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
291 spin_lock_bh(&kvm->arch.float_int.lock);
292 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
293 init_waitqueue_head(&vcpu->arch.local_int.wq);
Christian Borntraeger5288fbf2008-03-25 18:47:31 +0100294 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100295 spin_unlock_bh(&kvm->arch.float_int.lock);
296
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100297 rc = kvm_vcpu_init(vcpu, kvm, id);
298 if (rc)
299 goto out_free_cpu;
300 VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
301 vcpu->arch.sie_block);
302
303 try_module_get(THIS_MODULE);
304
305 return vcpu;
306out_free_cpu:
307 kfree(vcpu);
308out_nomem:
309 return ERR_PTR(rc);
310}
311
312void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
313{
314 VCPU_EVENT(vcpu, 3, "%s", "destroy cpu");
315 free_page((unsigned long)(vcpu->arch.sie_block));
316 kfree(vcpu);
317 module_put(THIS_MODULE);
318}
319
320int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
321{
322 /* kvm common code refers to this, but never calls it */
323 BUG();
324 return 0;
325}
326
327static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
328{
329 vcpu_load(vcpu);
330 kvm_s390_vcpu_initial_reset(vcpu);
331 vcpu_put(vcpu);
332 return 0;
333}
334
335int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
336{
337 vcpu_load(vcpu);
338 memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
339 vcpu_put(vcpu);
340 return 0;
341}
342
343int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
344{
345 vcpu_load(vcpu);
346 memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
347 vcpu_put(vcpu);
348 return 0;
349}
350
351int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
352 struct kvm_sregs *sregs)
353{
354 vcpu_load(vcpu);
355 memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
356 memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
357 vcpu_put(vcpu);
358 return 0;
359}
360
361int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
362 struct kvm_sregs *sregs)
363{
364 vcpu_load(vcpu);
365 memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
366 memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
367 vcpu_put(vcpu);
368 return 0;
369}
370
371int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
372{
373 vcpu_load(vcpu);
374 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
375 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
376 vcpu_put(vcpu);
377 return 0;
378}
379
380int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
381{
382 vcpu_load(vcpu);
383 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
384 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
385 vcpu_put(vcpu);
386 return 0;
387}
388
389static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
390{
391 int rc = 0;
392
393 vcpu_load(vcpu);
394 if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
395 rc = -EBUSY;
396 else
397 vcpu->arch.sie_block->gpsw = psw;
398 vcpu_put(vcpu);
399 return rc;
400}
401
402int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
403 struct kvm_translation *tr)
404{
405 return -EINVAL; /* not implemented yet */
406}
407
408int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu,
409 struct kvm_debug_guest *dbg)
410{
411 return -EINVAL; /* not implemented yet */
412}
413
Marcelo Tosatti62d9f0d2008-04-11 13:24:45 -0300414int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
415 struct kvm_mp_state *mp_state)
416{
417 return -EINVAL; /* not implemented yet */
418}
419
420int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
421 struct kvm_mp_state *mp_state)
422{
423 return -EINVAL; /* not implemented yet */
424}
425
Christian Borntraeger71cde582008-05-21 13:37:34 +0200426extern void s390_handle_mcck(void);
427
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100428static void __vcpu_run(struct kvm_vcpu *vcpu)
429{
430 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
431
432 if (need_resched())
433 schedule();
434
Christian Borntraeger71cde582008-05-21 13:37:34 +0200435 if (test_thread_flag(TIF_MCCK_PENDING))
436 s390_handle_mcck();
437
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100438 vcpu->arch.sie_block->icptcode = 0;
439 local_irq_disable();
440 kvm_guest_enter();
441 local_irq_enable();
442 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
443 atomic_read(&vcpu->arch.sie_block->cpuflags));
444 sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
445 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
446 vcpu->arch.sie_block->icptcode);
447 local_irq_disable();
448 kvm_guest_exit();
449 local_irq_enable();
450
451 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
452}
453
454int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
455{
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100456 int rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100457 sigset_t sigsaved;
458
459 vcpu_load(vcpu);
460
461 if (vcpu->sigset_active)
462 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
463
464 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
465
Carsten Otteba5c1e92008-03-25 18:47:26 +0100466 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
467
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100468 switch (kvm_run->exit_reason) {
469 case KVM_EXIT_S390_SIEIC:
470 vcpu->arch.sie_block->gpsw.mask = kvm_run->s390_sieic.mask;
471 vcpu->arch.sie_block->gpsw.addr = kvm_run->s390_sieic.addr;
472 break;
473 case KVM_EXIT_UNKNOWN:
474 case KVM_EXIT_S390_RESET:
475 break;
476 default:
477 BUG();
478 }
479
480 might_sleep();
481
482 do {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100483 kvm_s390_deliver_pending_interrupts(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100484 __vcpu_run(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100485 rc = kvm_handle_sie_intercept(vcpu);
486 } while (!signal_pending(current) && !rc);
487
488 if (signal_pending(current) && !rc)
489 rc = -EINTR;
490
491 if (rc == -ENOTSUPP) {
492 /* intercept cannot be handled in-kernel, prepare kvm-run */
493 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
494 kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
495 kvm_run->s390_sieic.mask = vcpu->arch.sie_block->gpsw.mask;
496 kvm_run->s390_sieic.addr = vcpu->arch.sie_block->gpsw.addr;
497 kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
498 kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
499 rc = 0;
500 }
501
502 if (rc == -EREMOTE) {
503 /* intercept was handled, but userspace support is needed
504 * kvm_run has been prepared by the handler */
505 rc = 0;
506 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100507
508 if (vcpu->sigset_active)
509 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
510
511 vcpu_put(vcpu);
512
513 vcpu->stat.exit_userspace++;
Heiko Carstens7e8e6ab2008-04-04 15:12:35 +0200514 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100515}
516
517static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, const void *from,
518 unsigned long n, int prefix)
519{
520 if (prefix)
521 return copy_to_guest(vcpu, guestdest, from, n);
522 else
523 return copy_to_guest_absolute(vcpu, guestdest, from, n);
524}
525
526/*
527 * store status at address
528 * we use have two special cases:
529 * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
530 * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
531 */
532int __kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
533{
534 const unsigned char archmode = 1;
535 int prefix;
536
537 if (addr == KVM_S390_STORE_STATUS_NOADDR) {
538 if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
539 return -EFAULT;
540 addr = SAVE_AREA_BASE;
541 prefix = 0;
542 } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
543 if (copy_to_guest(vcpu, 163ul, &archmode, 1))
544 return -EFAULT;
545 addr = SAVE_AREA_BASE;
546 prefix = 1;
547 } else
548 prefix = 0;
549
550 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, fp_regs),
551 vcpu->arch.guest_fpregs.fprs, 128, prefix))
552 return -EFAULT;
553
554 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, gp_regs),
555 vcpu->arch.guest_gprs, 128, prefix))
556 return -EFAULT;
557
558 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, psw),
559 &vcpu->arch.sie_block->gpsw, 16, prefix))
560 return -EFAULT;
561
562 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, pref_reg),
563 &vcpu->arch.sie_block->prefix, 4, prefix))
564 return -EFAULT;
565
566 if (__guestcopy(vcpu,
567 addr + offsetof(struct save_area_s390x, fp_ctrl_reg),
568 &vcpu->arch.guest_fpregs.fpc, 4, prefix))
569 return -EFAULT;
570
571 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, tod_reg),
572 &vcpu->arch.sie_block->todpr, 4, prefix))
573 return -EFAULT;
574
575 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, timer),
576 &vcpu->arch.sie_block->cputm, 8, prefix))
577 return -EFAULT;
578
579 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, clk_cmp),
580 &vcpu->arch.sie_block->ckc, 8, prefix))
581 return -EFAULT;
582
583 if (__guestcopy(vcpu, addr + offsetof(struct save_area_s390x, acc_regs),
584 &vcpu->arch.guest_acrs, 64, prefix))
585 return -EFAULT;
586
587 if (__guestcopy(vcpu,
588 addr + offsetof(struct save_area_s390x, ctrl_regs),
589 &vcpu->arch.sie_block->gcr, 128, prefix))
590 return -EFAULT;
591 return 0;
592}
593
594static int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
595{
596 int rc;
597
598 vcpu_load(vcpu);
599 rc = __kvm_s390_vcpu_store_status(vcpu, addr);
600 vcpu_put(vcpu);
601 return rc;
602}
603
604long kvm_arch_vcpu_ioctl(struct file *filp,
605 unsigned int ioctl, unsigned long arg)
606{
607 struct kvm_vcpu *vcpu = filp->private_data;
608 void __user *argp = (void __user *)arg;
609
610 switch (ioctl) {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100611 case KVM_S390_INTERRUPT: {
612 struct kvm_s390_interrupt s390int;
613
614 if (copy_from_user(&s390int, argp, sizeof(s390int)))
615 return -EFAULT;
616 return kvm_s390_inject_vcpu(vcpu, &s390int);
617 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100618 case KVM_S390_STORE_STATUS:
619 return kvm_s390_vcpu_store_status(vcpu, arg);
620 case KVM_S390_SET_INITIAL_PSW: {
621 psw_t psw;
622
623 if (copy_from_user(&psw, argp, sizeof(psw)))
624 return -EFAULT;
625 return kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
626 }
627 case KVM_S390_INITIAL_RESET:
628 return kvm_arch_vcpu_ioctl_initial_reset(vcpu);
629 default:
630 ;
631 }
632 return -EINVAL;
633}
634
635/* Section: memory related */
636int kvm_arch_set_memory_region(struct kvm *kvm,
637 struct kvm_userspace_memory_region *mem,
638 struct kvm_memory_slot old,
639 int user_alloc)
640{
641 /* A few sanity checks. We can have exactly one memory slot which has
642 to start at guest virtual zero and which has to be located at a
643 page boundary in userland and which has to end at a page boundary.
644 The memory in userland is ok to be fragmented into various different
645 vmas. It is okay to mmap() and munmap() stuff in this slot after
646 doing this call at any time */
647
648 if (mem->slot)
649 return -EINVAL;
650
651 if (mem->guest_phys_addr)
652 return -EINVAL;
653
654 if (mem->userspace_addr & (PAGE_SIZE - 1))
655 return -EINVAL;
656
657 if (mem->memory_size & (PAGE_SIZE - 1))
658 return -EINVAL;
659
660 kvm->arch.guest_origin = mem->userspace_addr;
661 kvm->arch.guest_memsize = mem->memory_size;
662
663 /* FIXME: we do want to interrupt running CPUs and update their memory
664 configuration now to avoid race conditions. But hey, changing the
665 memory layout while virtual CPUs are running is usually bad
666 programming practice. */
667
668 return 0;
669}
670
671gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn)
672{
673 return gfn;
674}
675
676static int __init kvm_s390_init(void)
677{
678 return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE);
679}
680
681static void __exit kvm_s390_exit(void)
682{
683 kvm_exit();
684}
685
686module_init(kvm_s390_init);
687module_exit(kvm_s390_exit);