blob: 80b12bac6a5be841abdc78fb6c3911b54749125a [file] [log] [blame]
Heiko Carstensb0c632d2008-03-25 18:47:20 +01001/*
2 * s390host.c -- hosting zSeries kernel virtual machines
3 *
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +02004 * Copyright IBM Corp. 2008,2009
Heiko Carstensb0c632d2008-03-25 18:47:20 +01005 *
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>
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +020013 * Christian Ehrhardt <ehrhardt@de.ibm.com>
Heiko Carstensb0c632d2008-03-25 18:47:20 +010014 */
15
16#include <linux/compiler.h>
17#include <linux/err.h>
18#include <linux/fs.h>
Christian Borntraegerca872302009-05-12 17:21:49 +020019#include <linux/hrtimer.h>
Heiko Carstensb0c632d2008-03-25 18:47:20 +010020#include <linux/init.h>
21#include <linux/kvm.h>
22#include <linux/kvm_host.h>
23#include <linux/module.h>
24#include <linux/slab.h>
Carsten Otteba5c1e92008-03-25 18:47:26 +010025#include <linux/timer.h>
Heiko Carstenscbb870c2010-02-26 22:37:43 +010026#include <asm/asm-offsets.h>
Heiko Carstensb0c632d2008-03-25 18:47:20 +010027#include <asm/lowcore.h>
28#include <asm/pgtable.h>
Heiko Carstensf5daba12009-03-26 15:24:01 +010029#include <asm/nmi.h>
Christian Borntraegeref50f7a2009-06-23 17:24:07 +020030#include <asm/system.h>
Christian Borntraeger8f2abe62008-03-25 18:47:23 +010031#include "kvm-s390.h"
Heiko Carstensb0c632d2008-03-25 18:47:20 +010032#include "gaccess.h"
33
34#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU
35
36struct kvm_stats_debugfs_item debugfs_entries[] = {
37 { "userspace_handled", VCPU_STAT(exit_userspace) },
Christian Borntraeger0eaeafa2008-05-07 09:22:53 +020038 { "exit_null", VCPU_STAT(exit_null) },
Christian Borntraeger8f2abe62008-03-25 18:47:23 +010039 { "exit_validity", VCPU_STAT(exit_validity) },
40 { "exit_stop_request", VCPU_STAT(exit_stop_request) },
41 { "exit_external_request", VCPU_STAT(exit_external_request) },
42 { "exit_external_interrupt", VCPU_STAT(exit_external_interrupt) },
Carsten Otteba5c1e92008-03-25 18:47:26 +010043 { "exit_instruction", VCPU_STAT(exit_instruction) },
44 { "exit_program_interruption", VCPU_STAT(exit_program_interruption) },
45 { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
Christian Borntraegerf5e10b02008-07-25 15:52:44 +020046 { "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
Carsten Otteba5c1e92008-03-25 18:47:26 +010047 { "instruction_lctl", VCPU_STAT(instruction_lctl) },
48 { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
Christian Ehrhardt7697e71f2011-10-18 12:27:15 +020049 { "deliver_external_call", VCPU_STAT(deliver_external_call) },
Carsten Otteba5c1e92008-03-25 18:47:26 +010050 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
51 { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
52 { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
53 { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
54 { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
55 { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
56 { "exit_wait_state", VCPU_STAT(exit_wait_state) },
Christian Borntraeger453423d2008-03-25 18:47:29 +010057 { "instruction_stidp", VCPU_STAT(instruction_stidp) },
58 { "instruction_spx", VCPU_STAT(instruction_spx) },
59 { "instruction_stpx", VCPU_STAT(instruction_stpx) },
60 { "instruction_stap", VCPU_STAT(instruction_stap) },
61 { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
62 { "instruction_stsch", VCPU_STAT(instruction_stsch) },
63 { "instruction_chsc", VCPU_STAT(instruction_chsc) },
64 { "instruction_stsi", VCPU_STAT(instruction_stsi) },
65 { "instruction_stfl", VCPU_STAT(instruction_stfl) },
Christian Borntraegerbb25b9b2011-07-24 10:48:17 +020066 { "instruction_tprot", VCPU_STAT(instruction_tprot) },
Christian Borntraeger5288fbf2008-03-25 18:47:31 +010067 { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
Cornelia Huckbd59d3a2011-11-17 11:00:42 +010068 { "instruction_sigp_sense_running", VCPU_STAT(instruction_sigp_sense_running) },
Christian Ehrhardt7697e71f2011-10-18 12:27:15 +020069 { "instruction_sigp_external_call", VCPU_STAT(instruction_sigp_external_call) },
Christian Borntraeger5288fbf2008-03-25 18:47:31 +010070 { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
71 { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
72 { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
73 { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
74 { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
Christian Borntraeger388186b2011-10-30 15:17:03 +010075 { "diagnose_10", VCPU_STAT(diagnose_10) },
Christian Borntraegere28acfe2008-03-25 18:47:34 +010076 { "diagnose_44", VCPU_STAT(diagnose_44) },
Heiko Carstensb0c632d2008-03-25 18:47:20 +010077 { NULL }
78};
79
Christian Borntraegeref50f7a2009-06-23 17:24:07 +020080static unsigned long long *facilities;
Heiko Carstensb0c632d2008-03-25 18:47:20 +010081
82/* Section: not file related */
Alexander Graf10474ae2009-09-15 11:37:46 +020083int kvm_arch_hardware_enable(void *garbage)
Heiko Carstensb0c632d2008-03-25 18:47:20 +010084{
85 /* every s390 is virtualization enabled ;-) */
Alexander Graf10474ae2009-09-15 11:37:46 +020086 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +010087}
88
89void kvm_arch_hardware_disable(void *garbage)
90{
91}
92
Heiko Carstensb0c632d2008-03-25 18:47:20 +010093int kvm_arch_hardware_setup(void)
94{
95 return 0;
96}
97
98void kvm_arch_hardware_unsetup(void)
99{
100}
101
102void kvm_arch_check_processor_compat(void *rtn)
103{
104}
105
106int kvm_arch_init(void *opaque)
107{
108 return 0;
109}
110
111void kvm_arch_exit(void)
112{
113}
114
115/* Section: device related */
116long kvm_arch_dev_ioctl(struct file *filp,
117 unsigned int ioctl, unsigned long arg)
118{
119 if (ioctl == KVM_S390_ENABLE_SIE)
120 return s390_enable_sie();
121 return -EINVAL;
122}
123
124int kvm_dev_ioctl_check_extension(long ext)
125{
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100126 int r;
127
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200128 switch (ext) {
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100129 case KVM_CAP_S390_PSW:
Christian Borntraegerb6cf8782011-09-20 17:07:29 +0200130 case KVM_CAP_S390_GMAP:
Christian Borntraeger52e16b12011-11-17 11:00:44 +0100131 case KVM_CAP_SYNC_MMU:
Carsten Otte1efd0f52012-01-04 10:25:29 +0100132#ifdef CONFIG_KVM_S390_UCONTROL
133 case KVM_CAP_S390_UCONTROL:
134#endif
Christian Borntraeger60b413c2012-01-11 11:20:31 +0100135 case KVM_CAP_SYNC_REGS:
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100136 r = 1;
137 break;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200138 default:
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100139 r = 0;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200140 }
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100141 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100142}
143
144/* Section: vm related */
145/*
146 * Get (and clear) the dirty memory log for a memory slot.
147 */
148int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
149 struct kvm_dirty_log *log)
150{
151 return 0;
152}
153
154long kvm_arch_vm_ioctl(struct file *filp,
155 unsigned int ioctl, unsigned long arg)
156{
157 struct kvm *kvm = filp->private_data;
158 void __user *argp = (void __user *)arg;
159 int r;
160
161 switch (ioctl) {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100162 case KVM_S390_INTERRUPT: {
163 struct kvm_s390_interrupt s390int;
164
165 r = -EFAULT;
166 if (copy_from_user(&s390int, argp, sizeof(s390int)))
167 break;
168 r = kvm_s390_inject_vm(kvm, &s390int);
169 break;
170 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100171 default:
Avi Kivity367e1312009-08-26 14:57:07 +0300172 r = -ENOTTY;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100173 }
174
175 return r;
176}
177
Carsten Ottee08b9632012-01-04 10:25:20 +0100178int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100179{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100180 int rc;
181 char debug_name[16];
182
Carsten Ottee08b9632012-01-04 10:25:20 +0100183 rc = -EINVAL;
184#ifdef CONFIG_KVM_S390_UCONTROL
185 if (type & ~KVM_VM_S390_UCONTROL)
186 goto out_err;
187 if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
188 goto out_err;
189#else
190 if (type)
191 goto out_err;
192#endif
193
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100194 rc = s390_enable_sie();
195 if (rc)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100196 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100197
Carsten Otteb2904112011-10-18 12:27:13 +0200198 rc = -ENOMEM;
199
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100200 kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
201 if (!kvm->arch.sca)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100202 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100203
204 sprintf(debug_name, "kvm-%u", current->pid);
205
206 kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
207 if (!kvm->arch.dbf)
208 goto out_nodbf;
209
Carsten Otteba5c1e92008-03-25 18:47:26 +0100210 spin_lock_init(&kvm->arch.float_int.lock);
211 INIT_LIST_HEAD(&kvm->arch.float_int.list);
212
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100213 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
214 VM_EVENT(kvm, 3, "%s", "vm created");
215
Carsten Ottee08b9632012-01-04 10:25:20 +0100216 if (type & KVM_VM_S390_UCONTROL) {
217 kvm->arch.gmap = NULL;
218 } else {
219 kvm->arch.gmap = gmap_alloc(current->mm);
220 if (!kvm->arch.gmap)
221 goto out_nogmap;
222 }
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100223 return 0;
Carsten Otte598841c2011-07-24 10:48:21 +0200224out_nogmap:
225 debug_unregister(kvm->arch.dbf);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100226out_nodbf:
227 free_page((unsigned long)(kvm->arch.sca));
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100228out_err:
229 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100230}
231
Christian Borntraegerd329c032008-11-26 14:50:27 +0100232void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
233{
234 VCPU_EVENT(vcpu, 3, "%s", "free cpu");
Carsten Otte58f94602012-01-04 10:25:27 +0100235 if (!kvm_is_ucontrol(vcpu->kvm)) {
236 clear_bit(63 - vcpu->vcpu_id,
237 (unsigned long *) &vcpu->kvm->arch.sca->mcn);
238 if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
239 (__u64) vcpu->arch.sie_block)
240 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
241 }
Carsten Otteabf4a712009-05-12 17:21:51 +0200242 smp_mb();
Carsten Otte27e03932012-01-04 10:25:21 +0100243
244 if (kvm_is_ucontrol(vcpu->kvm))
245 gmap_free(vcpu->arch.gmap);
246
Christian Borntraegerd329c032008-11-26 14:50:27 +0100247 free_page((unsigned long)(vcpu->arch.sie_block));
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100248 kvm_vcpu_uninit(vcpu);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100249 kfree(vcpu);
250}
251
252static void kvm_free_vcpus(struct kvm *kvm)
253{
254 unsigned int i;
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300255 struct kvm_vcpu *vcpu;
Christian Borntraegerd329c032008-11-26 14:50:27 +0100256
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300257 kvm_for_each_vcpu(i, vcpu, kvm)
258 kvm_arch_vcpu_destroy(vcpu);
259
260 mutex_lock(&kvm->lock);
261 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
262 kvm->vcpus[i] = NULL;
263
264 atomic_set(&kvm->online_vcpus, 0);
265 mutex_unlock(&kvm->lock);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100266}
267
Sheng Yangad8ba2c2009-01-06 10:03:02 +0800268void kvm_arch_sync_events(struct kvm *kvm)
269{
270}
271
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100272void kvm_arch_destroy_vm(struct kvm *kvm)
273{
Christian Borntraegerd329c032008-11-26 14:50:27 +0100274 kvm_free_vcpus(kvm);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100275 free_page((unsigned long)(kvm->arch.sca));
Christian Borntraegerd329c032008-11-26 14:50:27 +0100276 debug_unregister(kvm->arch.dbf);
Carsten Otte27e03932012-01-04 10:25:21 +0100277 if (!kvm_is_ucontrol(kvm))
278 gmap_free(kvm->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100279}
280
281/* Section: vcpu related */
282int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
283{
Carsten Otte27e03932012-01-04 10:25:21 +0100284 if (kvm_is_ucontrol(vcpu->kvm)) {
285 vcpu->arch.gmap = gmap_alloc(current->mm);
286 if (!vcpu->arch.gmap)
287 return -ENOMEM;
288 return 0;
289 }
290
Carsten Otte598841c2011-07-24 10:48:21 +0200291 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100292 vcpu->run->kvm_valid_regs = KVM_SYNC_PREFIX | KVM_SYNC_GPRS;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100293 return 0;
294}
295
296void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
297{
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100298 /* Nothing todo */
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100299}
300
301void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
302{
303 save_fp_regs(&vcpu->arch.host_fpregs);
304 save_access_regs(vcpu->arch.host_acrs);
305 vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
306 restore_fp_regs(&vcpu->arch.guest_fpregs);
307 restore_access_regs(vcpu->arch.guest_acrs);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200308 gmap_enable(vcpu->arch.gmap);
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100309 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100310}
311
312void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
313{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100314 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200315 gmap_disable(vcpu->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100316 save_fp_regs(&vcpu->arch.guest_fpregs);
317 save_access_regs(vcpu->arch.guest_acrs);
318 restore_fp_regs(&vcpu->arch.host_fpregs);
319 restore_access_regs(vcpu->arch.host_acrs);
320}
321
322static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
323{
324 /* this equals initial cpu reset in pop, but we don't switch to ESA */
325 vcpu->arch.sie_block->gpsw.mask = 0UL;
326 vcpu->arch.sie_block->gpsw.addr = 0UL;
Christian Borntraeger8d26cf72012-01-11 11:19:32 +0100327 kvm_s390_set_prefix(vcpu, 0);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100328 vcpu->arch.sie_block->cputm = 0UL;
329 vcpu->arch.sie_block->ckc = 0UL;
330 vcpu->arch.sie_block->todpr = 0;
331 memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
332 vcpu->arch.sie_block->gcr[0] = 0xE0UL;
333 vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
334 vcpu->arch.guest_fpregs.fpc = 0;
335 asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
336 vcpu->arch.sie_block->gbea = 1;
337}
338
339int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
340{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100341 atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
342 CPUSTAT_SM |
343 CPUSTAT_STOPPED);
Christian Borntraegerfc345312010-06-17 23:16:20 +0200344 vcpu->arch.sie_block->ecb = 6;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100345 vcpu->arch.sie_block->eca = 0xC1002001U;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200346 vcpu->arch.sie_block->fac = (int) (long) facilities;
Christian Borntraegerca872302009-05-12 17:21:49 +0200347 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
348 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
349 (unsigned long) vcpu);
350 vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
Christian Borntraeger453423d2008-03-25 18:47:29 +0100351 get_cpu_id(&vcpu->arch.cpu_id);
Christian Borntraeger92e6ecf2009-03-26 15:23:58 +0100352 vcpu->arch.cpu_id.version = 0xff;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100353 return 0;
354}
355
356struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
357 unsigned int id)
358{
Carsten Otte4d475552011-10-18 12:27:12 +0200359 struct kvm_vcpu *vcpu;
360 int rc = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100361
Carsten Otte4d475552011-10-18 12:27:12 +0200362 if (id >= KVM_MAX_VCPUS)
363 goto out;
364
365 rc = -ENOMEM;
366
367 vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100368 if (!vcpu)
Carsten Otte4d475552011-10-18 12:27:12 +0200369 goto out;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100370
Christian Borntraeger180c12f2008-06-27 15:05:40 +0200371 vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
372 get_zeroed_page(GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100373
374 if (!vcpu->arch.sie_block)
375 goto out_free_cpu;
376
377 vcpu->arch.sie_block->icpua = id;
Carsten Otte58f94602012-01-04 10:25:27 +0100378 if (!kvm_is_ucontrol(kvm)) {
379 if (!kvm->arch.sca) {
380 WARN_ON_ONCE(1);
381 goto out_free_cpu;
382 }
383 if (!kvm->arch.sca->cpu[id].sda)
384 kvm->arch.sca->cpu[id].sda =
385 (__u64) vcpu->arch.sie_block;
386 vcpu->arch.sie_block->scaoh =
387 (__u32)(((__u64)kvm->arch.sca) >> 32);
388 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
389 set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
390 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100391
Carsten Otteba5c1e92008-03-25 18:47:26 +0100392 spin_lock_init(&vcpu->arch.local_int.lock);
393 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
394 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200395 spin_lock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100396 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
397 init_waitqueue_head(&vcpu->arch.local_int.wq);
Christian Borntraeger5288fbf2008-03-25 18:47:31 +0100398 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200399 spin_unlock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100400
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100401 rc = kvm_vcpu_init(vcpu, kvm, id);
402 if (rc)
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800403 goto out_free_sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100404 VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
405 vcpu->arch.sie_block);
406
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100407 return vcpu;
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800408out_free_sie_block:
409 free_page((unsigned long)(vcpu->arch.sie_block));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100410out_free_cpu:
411 kfree(vcpu);
Carsten Otte4d475552011-10-18 12:27:12 +0200412out:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100413 return ERR_PTR(rc);
414}
415
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100416int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
417{
418 /* kvm common code refers to this, but never calls it */
419 BUG();
420 return 0;
421}
422
423static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
424{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100425 kvm_s390_vcpu_initial_reset(vcpu);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100426 return 0;
427}
428
429int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
430{
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100431 memcpy(&vcpu->run->s.regs.gprs, &regs->gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100432 return 0;
433}
434
435int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
436{
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100437 memcpy(&regs->gprs, &vcpu->run->s.regs.gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100438 return 0;
439}
440
441int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
442 struct kvm_sregs *sregs)
443{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100444 memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
445 memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
Carsten Otte7eef87d2011-10-18 12:27:14 +0200446 restore_access_regs(vcpu->arch.guest_acrs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100447 return 0;
448}
449
450int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
451 struct kvm_sregs *sregs)
452{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100453 memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
454 memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100455 return 0;
456}
457
458int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
459{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100460 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
461 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
Carsten Otte7eef87d2011-10-18 12:27:14 +0200462 restore_fp_regs(&vcpu->arch.guest_fpregs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100463 return 0;
464}
465
466int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
467{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100468 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
469 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100470 return 0;
471}
472
473static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
474{
475 int rc = 0;
476
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100477 if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100478 rc = -EBUSY;
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100479 else {
480 vcpu->run->psw_mask = psw.mask;
481 vcpu->run->psw_addr = psw.addr;
482 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100483 return rc;
484}
485
486int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
487 struct kvm_translation *tr)
488{
489 return -EINVAL; /* not implemented yet */
490}
491
Jan Kiszkad0bfb942008-12-15 13:52:10 +0100492int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
493 struct kvm_guest_debug *dbg)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100494{
495 return -EINVAL; /* not implemented yet */
496}
497
Marcelo Tosatti62d9f0d2008-04-11 13:24:45 -0300498int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
499 struct kvm_mp_state *mp_state)
500{
501 return -EINVAL; /* not implemented yet */
502}
503
504int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
505 struct kvm_mp_state *mp_state)
506{
507 return -EINVAL; /* not implemented yet */
508}
509
Carsten Ottee168bf82012-01-04 10:25:22 +0100510static int __vcpu_run(struct kvm_vcpu *vcpu)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100511{
Carsten Ottee168bf82012-01-04 10:25:22 +0100512 int rc;
513
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100514 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->run->s.regs.gprs[14], 16);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100515
516 if (need_resched())
517 schedule();
518
Christian Borntraeger71cde582008-05-21 13:37:34 +0200519 if (test_thread_flag(TIF_MCCK_PENDING))
520 s390_handle_mcck();
521
Carsten Otted6b6d162012-01-04 10:25:25 +0100522 if (!kvm_is_ucontrol(vcpu->kvm))
523 kvm_s390_deliver_pending_interrupts(vcpu);
Carsten Otte0ff31862008-05-21 13:37:37 +0200524
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100525 vcpu->arch.sie_block->icptcode = 0;
526 local_irq_disable();
527 kvm_guest_enter();
528 local_irq_enable();
529 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
530 atomic_read(&vcpu->arch.sie_block->cpuflags));
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100531 rc = sie64a(vcpu->arch.sie_block, vcpu->run->s.regs.gprs);
Carsten Ottee168bf82012-01-04 10:25:22 +0100532 if (rc) {
533 if (kvm_is_ucontrol(vcpu->kvm)) {
534 rc = SIE_INTERCEPT_UCONTROL;
535 } else {
536 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
537 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
538 rc = 0;
539 }
Carsten Otte1f0d0f02008-05-21 13:37:40 +0200540 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100541 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
542 vcpu->arch.sie_block->icptcode);
543 local_irq_disable();
544 kvm_guest_exit();
545 local_irq_enable();
546
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100547 memcpy(&vcpu->run->s.regs.gprs[14], &vcpu->arch.sie_block->gg14, 16);
Carsten Ottee168bf82012-01-04 10:25:22 +0100548 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100549}
550
551int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
552{
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100553 int rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100554 sigset_t sigsaved;
555
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200556rerun_vcpu:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100557 if (vcpu->sigset_active)
558 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
559
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100560 atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100561
Carsten Otteba5c1e92008-03-25 18:47:26 +0100562 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
563
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100564 switch (kvm_run->exit_reason) {
565 case KVM_EXIT_S390_SIEIC:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100566 case KVM_EXIT_UNKNOWN:
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200567 case KVM_EXIT_INTR:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100568 case KVM_EXIT_S390_RESET:
Carsten Ottee168bf82012-01-04 10:25:22 +0100569 case KVM_EXIT_S390_UCONTROL:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100570 break;
571 default:
572 BUG();
573 }
574
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100575 vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
576 vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
Christian Borntraeger60b413c2012-01-11 11:20:31 +0100577 if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX) {
578 kvm_run->kvm_dirty_regs &= ~KVM_SYNC_PREFIX;
579 kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
580 }
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100581
Heiko Carstensdab4079d2009-06-12 10:26:32 +0200582 might_fault();
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100583
584 do {
Carsten Ottee168bf82012-01-04 10:25:22 +0100585 rc = __vcpu_run(vcpu);
586 if (rc)
587 break;
Carsten Ottec0d744a2012-01-04 10:25:24 +0100588 if (kvm_is_ucontrol(vcpu->kvm))
589 rc = -EOPNOTSUPP;
590 else
591 rc = kvm_handle_sie_intercept(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100592 } while (!signal_pending(current) && !rc);
593
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200594 if (rc == SIE_INTERCEPT_RERUNVCPU)
595 goto rerun_vcpu;
596
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200597 if (signal_pending(current) && !rc) {
598 kvm_run->exit_reason = KVM_EXIT_INTR;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100599 rc = -EINTR;
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200600 }
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100601
Carsten Ottee168bf82012-01-04 10:25:22 +0100602#ifdef CONFIG_KVM_S390_UCONTROL
603 if (rc == SIE_INTERCEPT_UCONTROL) {
604 kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL;
605 kvm_run->s390_ucontrol.trans_exc_code =
606 current->thread.gmap_addr;
607 kvm_run->s390_ucontrol.pgm_code = 0x10;
608 rc = 0;
609 }
610#endif
611
Heiko Carstensb8e660b2010-02-26 22:37:41 +0100612 if (rc == -EOPNOTSUPP) {
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100613 /* intercept cannot be handled in-kernel, prepare kvm-run */
614 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
615 kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100616 kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
617 kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
618 rc = 0;
619 }
620
621 if (rc == -EREMOTE) {
622 /* intercept was handled, but userspace support is needed
623 * kvm_run has been prepared by the handler */
624 rc = 0;
625 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100626
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100627 kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
628 kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
Christian Borntraeger60b413c2012-01-11 11:20:31 +0100629 kvm_run->s.regs.prefix = vcpu->arch.sie_block->prefix;
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100630
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100631 if (vcpu->sigset_active)
632 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
633
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100634 vcpu->stat.exit_userspace++;
Heiko Carstens7e8e6ab2008-04-04 15:12:35 +0200635 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100636}
637
Carsten Otte092670c2011-07-24 10:48:22 +0200638static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100639 unsigned long n, int prefix)
640{
641 if (prefix)
642 return copy_to_guest(vcpu, guestdest, from, n);
643 else
644 return copy_to_guest_absolute(vcpu, guestdest, from, n);
645}
646
647/*
648 * store status at address
649 * we use have two special cases:
650 * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
651 * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
652 */
Christian Borntraeger971eb772010-06-12 08:54:13 +0200653int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100654{
Carsten Otte092670c2011-07-24 10:48:22 +0200655 unsigned char archmode = 1;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100656 int prefix;
657
658 if (addr == KVM_S390_STORE_STATUS_NOADDR) {
659 if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
660 return -EFAULT;
661 addr = SAVE_AREA_BASE;
662 prefix = 0;
663 } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
664 if (copy_to_guest(vcpu, 163ul, &archmode, 1))
665 return -EFAULT;
666 addr = SAVE_AREA_BASE;
667 prefix = 1;
668 } else
669 prefix = 0;
670
Heiko Carstensf64ca212010-02-26 22:37:32 +0100671 if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100672 vcpu->arch.guest_fpregs.fprs, 128, prefix))
673 return -EFAULT;
674
Heiko Carstensf64ca212010-02-26 22:37:32 +0100675 if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
Christian Borntraeger5a32c1a2012-01-11 11:20:32 +0100676 vcpu->run->s.regs.gprs, 128, prefix))
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100677 return -EFAULT;
678
Heiko Carstensf64ca212010-02-26 22:37:32 +0100679 if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100680 &vcpu->arch.sie_block->gpsw, 16, prefix))
681 return -EFAULT;
682
Heiko Carstensf64ca212010-02-26 22:37:32 +0100683 if (__guestcopy(vcpu, addr + offsetof(struct save_area, pref_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100684 &vcpu->arch.sie_block->prefix, 4, prefix))
685 return -EFAULT;
686
687 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100688 addr + offsetof(struct save_area, fp_ctrl_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100689 &vcpu->arch.guest_fpregs.fpc, 4, prefix))
690 return -EFAULT;
691
Heiko Carstensf64ca212010-02-26 22:37:32 +0100692 if (__guestcopy(vcpu, addr + offsetof(struct save_area, tod_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100693 &vcpu->arch.sie_block->todpr, 4, prefix))
694 return -EFAULT;
695
Heiko Carstensf64ca212010-02-26 22:37:32 +0100696 if (__guestcopy(vcpu, addr + offsetof(struct save_area, timer),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100697 &vcpu->arch.sie_block->cputm, 8, prefix))
698 return -EFAULT;
699
Heiko Carstensf64ca212010-02-26 22:37:32 +0100700 if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100701 &vcpu->arch.sie_block->ckc, 8, prefix))
702 return -EFAULT;
703
Heiko Carstensf64ca212010-02-26 22:37:32 +0100704 if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100705 &vcpu->arch.guest_acrs, 64, prefix))
706 return -EFAULT;
707
708 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100709 addr + offsetof(struct save_area, ctrl_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100710 &vcpu->arch.sie_block->gcr, 128, prefix))
711 return -EFAULT;
712 return 0;
713}
714
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100715long kvm_arch_vcpu_ioctl(struct file *filp,
716 unsigned int ioctl, unsigned long arg)
717{
718 struct kvm_vcpu *vcpu = filp->private_data;
719 void __user *argp = (void __user *)arg;
Avi Kivitybc923cc2010-05-13 12:21:46 +0300720 long r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100721
Avi Kivity937366242010-05-13 12:35:17 +0300722 switch (ioctl) {
723 case KVM_S390_INTERRUPT: {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100724 struct kvm_s390_interrupt s390int;
725
Avi Kivity937366242010-05-13 12:35:17 +0300726 r = -EFAULT;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100727 if (copy_from_user(&s390int, argp, sizeof(s390int)))
Avi Kivity937366242010-05-13 12:35:17 +0300728 break;
729 r = kvm_s390_inject_vcpu(vcpu, &s390int);
730 break;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100731 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100732 case KVM_S390_STORE_STATUS:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300733 r = kvm_s390_vcpu_store_status(vcpu, arg);
734 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100735 case KVM_S390_SET_INITIAL_PSW: {
736 psw_t psw;
737
Avi Kivitybc923cc2010-05-13 12:21:46 +0300738 r = -EFAULT;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100739 if (copy_from_user(&psw, argp, sizeof(psw)))
Avi Kivitybc923cc2010-05-13 12:21:46 +0300740 break;
741 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
742 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100743 }
744 case KVM_S390_INITIAL_RESET:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300745 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
746 break;
Carsten Otte27e03932012-01-04 10:25:21 +0100747#ifdef CONFIG_KVM_S390_UCONTROL
748 case KVM_S390_UCAS_MAP: {
749 struct kvm_s390_ucas_mapping ucasmap;
750
751 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
752 r = -EFAULT;
753 break;
754 }
755
756 if (!kvm_is_ucontrol(vcpu->kvm)) {
757 r = -EINVAL;
758 break;
759 }
760
761 r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
762 ucasmap.vcpu_addr, ucasmap.length);
763 break;
764 }
765 case KVM_S390_UCAS_UNMAP: {
766 struct kvm_s390_ucas_mapping ucasmap;
767
768 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
769 r = -EFAULT;
770 break;
771 }
772
773 if (!kvm_is_ucontrol(vcpu->kvm)) {
774 r = -EINVAL;
775 break;
776 }
777
778 r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
779 ucasmap.length);
780 break;
781 }
782#endif
Carsten Otteccc79102012-01-04 10:25:26 +0100783 case KVM_S390_VCPU_FAULT: {
784 r = gmap_fault(arg, vcpu->arch.gmap);
785 if (!IS_ERR_VALUE(r))
786 r = 0;
787 break;
788 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100789 default:
Carsten Otte3e6afcf2012-01-04 10:25:30 +0100790 r = -ENOTTY;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100791 }
Avi Kivitybc923cc2010-05-13 12:21:46 +0300792 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100793}
794
Carsten Otte5b1c1492012-01-04 10:25:23 +0100795int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
796{
797#ifdef CONFIG_KVM_S390_UCONTROL
798 if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
799 && (kvm_is_ucontrol(vcpu->kvm))) {
800 vmf->page = virt_to_page(vcpu->arch.sie_block);
801 get_page(vmf->page);
802 return 0;
803 }
804#endif
805 return VM_FAULT_SIGBUS;
806}
807
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100808/* Section: memory related */
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200809int kvm_arch_prepare_memory_region(struct kvm *kvm,
810 struct kvm_memory_slot *memslot,
811 struct kvm_memory_slot old,
812 struct kvm_userspace_memory_region *mem,
813 int user_alloc)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100814{
815 /* A few sanity checks. We can have exactly one memory slot which has
816 to start at guest virtual zero and which has to be located at a
817 page boundary in userland and which has to end at a page boundary.
818 The memory in userland is ok to be fragmented into various different
819 vmas. It is okay to mmap() and munmap() stuff in this slot after
820 doing this call at any time */
821
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +0200822 if (mem->slot)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100823 return -EINVAL;
824
825 if (mem->guest_phys_addr)
826 return -EINVAL;
827
Carsten Otte598841c2011-07-24 10:48:21 +0200828 if (mem->userspace_addr & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100829 return -EINVAL;
830
Carsten Otte598841c2011-07-24 10:48:21 +0200831 if (mem->memory_size & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100832 return -EINVAL;
833
Carsten Otte2668dab2009-05-12 17:21:48 +0200834 if (!user_alloc)
835 return -EINVAL;
836
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200837 return 0;
838}
839
840void kvm_arch_commit_memory_region(struct kvm *kvm,
841 struct kvm_userspace_memory_region *mem,
842 struct kvm_memory_slot old,
843 int user_alloc)
844{
Carsten Ottef7850c92011-07-24 10:48:23 +0200845 int rc;
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200846
Carsten Otte598841c2011-07-24 10:48:21 +0200847
848 rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
849 mem->guest_phys_addr, mem->memory_size);
850 if (rc)
Carsten Ottef7850c92011-07-24 10:48:23 +0200851 printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
Carsten Otte598841c2011-07-24 10:48:21 +0200852 return;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100853}
854
Marcelo Tosatti34d4cb82008-07-10 20:49:31 -0300855void kvm_arch_flush_shadow(struct kvm *kvm)
856{
857}
858
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100859static int __init kvm_s390_init(void)
860{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200861 int ret;
Avi Kivity0ee75be2010-04-28 15:39:01 +0300862 ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200863 if (ret)
864 return ret;
865
866 /*
867 * guests can ask for up to 255+1 double words, we need a full page
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300868 * to hold the maximum amount of facilities. On the other hand, we
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200869 * only set facilities that are known to work in KVM.
870 */
Heiko Carstensc2f0e8c2010-06-08 18:58:09 +0200871 facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200872 if (!facilities) {
873 kvm_exit();
874 return -ENOMEM;
875 }
Martin Schwidefsky14375bc2010-10-25 16:10:51 +0200876 memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
Christian Borntraeger6d00d002010-10-25 16:10:48 +0200877 facilities[0] &= 0xff00fff3f47c0000ULL;
Christian Borntraeger9950f8b2011-06-06 14:14:39 +0200878 facilities[1] &= 0x201c000000000000ULL;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200879 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100880}
881
882static void __exit kvm_s390_exit(void)
883{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200884 free_page((unsigned long) facilities);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100885 kvm_exit();
886}
887
888module_init(kvm_s390_init);
889module_exit(kvm_s390_exit);