blob: abf784d8c68058ab74d3623ccde6a46a75059860 [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 Otted7b0b5e2009-11-19 14:21:16 +0100132 r = 1;
133 break;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200134 default:
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100135 r = 0;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200136 }
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100137 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100138}
139
140/* Section: vm related */
141/*
142 * Get (and clear) the dirty memory log for a memory slot.
143 */
144int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
145 struct kvm_dirty_log *log)
146{
147 return 0;
148}
149
150long kvm_arch_vm_ioctl(struct file *filp,
151 unsigned int ioctl, unsigned long arg)
152{
153 struct kvm *kvm = filp->private_data;
154 void __user *argp = (void __user *)arg;
155 int r;
156
157 switch (ioctl) {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100158 case KVM_S390_INTERRUPT: {
159 struct kvm_s390_interrupt s390int;
160
161 r = -EFAULT;
162 if (copy_from_user(&s390int, argp, sizeof(s390int)))
163 break;
164 r = kvm_s390_inject_vm(kvm, &s390int);
165 break;
166 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100167 default:
Avi Kivity367e1312009-08-26 14:57:07 +0300168 r = -ENOTTY;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100169 }
170
171 return r;
172}
173
Carsten Ottee08b9632012-01-04 10:25:20 +0100174int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100175{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100176 int rc;
177 char debug_name[16];
178
Carsten Ottee08b9632012-01-04 10:25:20 +0100179 rc = -EINVAL;
180#ifdef CONFIG_KVM_S390_UCONTROL
181 if (type & ~KVM_VM_S390_UCONTROL)
182 goto out_err;
183 if ((type & KVM_VM_S390_UCONTROL) && (!capable(CAP_SYS_ADMIN)))
184 goto out_err;
185#else
186 if (type)
187 goto out_err;
188#endif
189
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100190 rc = s390_enable_sie();
191 if (rc)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100192 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100193
Carsten Otteb2904112011-10-18 12:27:13 +0200194 rc = -ENOMEM;
195
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100196 kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
197 if (!kvm->arch.sca)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100198 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100199
200 sprintf(debug_name, "kvm-%u", current->pid);
201
202 kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
203 if (!kvm->arch.dbf)
204 goto out_nodbf;
205
Carsten Otteba5c1e92008-03-25 18:47:26 +0100206 spin_lock_init(&kvm->arch.float_int.lock);
207 INIT_LIST_HEAD(&kvm->arch.float_int.list);
208
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100209 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
210 VM_EVENT(kvm, 3, "%s", "vm created");
211
Carsten Ottee08b9632012-01-04 10:25:20 +0100212 if (type & KVM_VM_S390_UCONTROL) {
213 kvm->arch.gmap = NULL;
214 } else {
215 kvm->arch.gmap = gmap_alloc(current->mm);
216 if (!kvm->arch.gmap)
217 goto out_nogmap;
218 }
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100219 return 0;
Carsten Otte598841c2011-07-24 10:48:21 +0200220out_nogmap:
221 debug_unregister(kvm->arch.dbf);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100222out_nodbf:
223 free_page((unsigned long)(kvm->arch.sca));
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100224out_err:
225 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100226}
227
Christian Borntraegerd329c032008-11-26 14:50:27 +0100228void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
229{
230 VCPU_EVENT(vcpu, 3, "%s", "free cpu");
Carsten Otte58f94602012-01-04 10:25:27 +0100231 if (!kvm_is_ucontrol(vcpu->kvm)) {
232 clear_bit(63 - vcpu->vcpu_id,
233 (unsigned long *) &vcpu->kvm->arch.sca->mcn);
234 if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
235 (__u64) vcpu->arch.sie_block)
236 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
237 }
Carsten Otteabf4a712009-05-12 17:21:51 +0200238 smp_mb();
Carsten Otte27e03932012-01-04 10:25:21 +0100239
240 if (kvm_is_ucontrol(vcpu->kvm))
241 gmap_free(vcpu->arch.gmap);
242
Christian Borntraegerd329c032008-11-26 14:50:27 +0100243 free_page((unsigned long)(vcpu->arch.sie_block));
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100244 kvm_vcpu_uninit(vcpu);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100245 kfree(vcpu);
246}
247
248static void kvm_free_vcpus(struct kvm *kvm)
249{
250 unsigned int i;
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300251 struct kvm_vcpu *vcpu;
Christian Borntraegerd329c032008-11-26 14:50:27 +0100252
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300253 kvm_for_each_vcpu(i, vcpu, kvm)
254 kvm_arch_vcpu_destroy(vcpu);
255
256 mutex_lock(&kvm->lock);
257 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
258 kvm->vcpus[i] = NULL;
259
260 atomic_set(&kvm->online_vcpus, 0);
261 mutex_unlock(&kvm->lock);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100262}
263
Sheng Yangad8ba2c2009-01-06 10:03:02 +0800264void kvm_arch_sync_events(struct kvm *kvm)
265{
266}
267
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100268void kvm_arch_destroy_vm(struct kvm *kvm)
269{
Christian Borntraegerd329c032008-11-26 14:50:27 +0100270 kvm_free_vcpus(kvm);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100271 free_page((unsigned long)(kvm->arch.sca));
Christian Borntraegerd329c032008-11-26 14:50:27 +0100272 debug_unregister(kvm->arch.dbf);
Carsten Otte27e03932012-01-04 10:25:21 +0100273 if (!kvm_is_ucontrol(kvm))
274 gmap_free(kvm->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100275}
276
277/* Section: vcpu related */
278int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
279{
Carsten Otte27e03932012-01-04 10:25:21 +0100280 if (kvm_is_ucontrol(vcpu->kvm)) {
281 vcpu->arch.gmap = gmap_alloc(current->mm);
282 if (!vcpu->arch.gmap)
283 return -ENOMEM;
284 return 0;
285 }
286
Carsten Otte598841c2011-07-24 10:48:21 +0200287 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100288 return 0;
289}
290
291void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
292{
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100293 /* Nothing todo */
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100294}
295
296void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
297{
298 save_fp_regs(&vcpu->arch.host_fpregs);
299 save_access_regs(vcpu->arch.host_acrs);
300 vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
301 restore_fp_regs(&vcpu->arch.guest_fpregs);
302 restore_access_regs(vcpu->arch.guest_acrs);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200303 gmap_enable(vcpu->arch.gmap);
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100304 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100305}
306
307void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
308{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100309 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200310 gmap_disable(vcpu->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100311 save_fp_regs(&vcpu->arch.guest_fpregs);
312 save_access_regs(vcpu->arch.guest_acrs);
313 restore_fp_regs(&vcpu->arch.host_fpregs);
314 restore_access_regs(vcpu->arch.host_acrs);
315}
316
317static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
318{
319 /* this equals initial cpu reset in pop, but we don't switch to ESA */
320 vcpu->arch.sie_block->gpsw.mask = 0UL;
321 vcpu->arch.sie_block->gpsw.addr = 0UL;
322 vcpu->arch.sie_block->prefix = 0UL;
323 vcpu->arch.sie_block->ihcpu = 0xffff;
324 vcpu->arch.sie_block->cputm = 0UL;
325 vcpu->arch.sie_block->ckc = 0UL;
326 vcpu->arch.sie_block->todpr = 0;
327 memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
328 vcpu->arch.sie_block->gcr[0] = 0xE0UL;
329 vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
330 vcpu->arch.guest_fpregs.fpc = 0;
331 asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
332 vcpu->arch.sie_block->gbea = 1;
333}
334
335int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
336{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100337 atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
338 CPUSTAT_SM |
339 CPUSTAT_STOPPED);
Christian Borntraegerfc345312010-06-17 23:16:20 +0200340 vcpu->arch.sie_block->ecb = 6;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100341 vcpu->arch.sie_block->eca = 0xC1002001U;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200342 vcpu->arch.sie_block->fac = (int) (long) facilities;
Christian Borntraegerca872302009-05-12 17:21:49 +0200343 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
344 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
345 (unsigned long) vcpu);
346 vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
Christian Borntraeger453423d2008-03-25 18:47:29 +0100347 get_cpu_id(&vcpu->arch.cpu_id);
Christian Borntraeger92e6ecf2009-03-26 15:23:58 +0100348 vcpu->arch.cpu_id.version = 0xff;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100349 return 0;
350}
351
352struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
353 unsigned int id)
354{
Carsten Otte4d475552011-10-18 12:27:12 +0200355 struct kvm_vcpu *vcpu;
356 int rc = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100357
Carsten Otte4d475552011-10-18 12:27:12 +0200358 if (id >= KVM_MAX_VCPUS)
359 goto out;
360
361 rc = -ENOMEM;
362
363 vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100364 if (!vcpu)
Carsten Otte4d475552011-10-18 12:27:12 +0200365 goto out;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100366
Christian Borntraeger180c12f2008-06-27 15:05:40 +0200367 vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
368 get_zeroed_page(GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100369
370 if (!vcpu->arch.sie_block)
371 goto out_free_cpu;
372
373 vcpu->arch.sie_block->icpua = id;
Carsten Otte58f94602012-01-04 10:25:27 +0100374 if (!kvm_is_ucontrol(kvm)) {
375 if (!kvm->arch.sca) {
376 WARN_ON_ONCE(1);
377 goto out_free_cpu;
378 }
379 if (!kvm->arch.sca->cpu[id].sda)
380 kvm->arch.sca->cpu[id].sda =
381 (__u64) vcpu->arch.sie_block;
382 vcpu->arch.sie_block->scaoh =
383 (__u32)(((__u64)kvm->arch.sca) >> 32);
384 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
385 set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
386 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100387
Carsten Otteba5c1e92008-03-25 18:47:26 +0100388 spin_lock_init(&vcpu->arch.local_int.lock);
389 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
390 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200391 spin_lock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100392 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
393 init_waitqueue_head(&vcpu->arch.local_int.wq);
Christian Borntraeger5288fbf2008-03-25 18:47:31 +0100394 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200395 spin_unlock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100396
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100397 rc = kvm_vcpu_init(vcpu, kvm, id);
398 if (rc)
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800399 goto out_free_sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100400 VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
401 vcpu->arch.sie_block);
402
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100403 return vcpu;
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800404out_free_sie_block:
405 free_page((unsigned long)(vcpu->arch.sie_block));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100406out_free_cpu:
407 kfree(vcpu);
Carsten Otte4d475552011-10-18 12:27:12 +0200408out:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100409 return ERR_PTR(rc);
410}
411
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100412int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
413{
414 /* kvm common code refers to this, but never calls it */
415 BUG();
416 return 0;
417}
418
419static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
420{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100421 kvm_s390_vcpu_initial_reset(vcpu);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100422 return 0;
423}
424
425int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
426{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100427 memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100428 return 0;
429}
430
431int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
432{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100433 memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100434 return 0;
435}
436
437int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
438 struct kvm_sregs *sregs)
439{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100440 memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
441 memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
Carsten Otte7eef87d2011-10-18 12:27:14 +0200442 restore_access_regs(vcpu->arch.guest_acrs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100443 return 0;
444}
445
446int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
447 struct kvm_sregs *sregs)
448{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100449 memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
450 memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100451 return 0;
452}
453
454int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
455{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100456 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
457 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
Carsten Otte7eef87d2011-10-18 12:27:14 +0200458 restore_fp_regs(&vcpu->arch.guest_fpregs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100459 return 0;
460}
461
462int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
463{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100464 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
465 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100466 return 0;
467}
468
469static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
470{
471 int rc = 0;
472
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100473 if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100474 rc = -EBUSY;
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100475 else {
476 vcpu->run->psw_mask = psw.mask;
477 vcpu->run->psw_addr = psw.addr;
478 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100479 return rc;
480}
481
482int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
483 struct kvm_translation *tr)
484{
485 return -EINVAL; /* not implemented yet */
486}
487
Jan Kiszkad0bfb942008-12-15 13:52:10 +0100488int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
489 struct kvm_guest_debug *dbg)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100490{
491 return -EINVAL; /* not implemented yet */
492}
493
Marcelo Tosatti62d9f0d2008-04-11 13:24:45 -0300494int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
495 struct kvm_mp_state *mp_state)
496{
497 return -EINVAL; /* not implemented yet */
498}
499
500int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
501 struct kvm_mp_state *mp_state)
502{
503 return -EINVAL; /* not implemented yet */
504}
505
Carsten Ottee168bf82012-01-04 10:25:22 +0100506static int __vcpu_run(struct kvm_vcpu *vcpu)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100507{
Carsten Ottee168bf82012-01-04 10:25:22 +0100508 int rc;
509
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100510 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
511
512 if (need_resched())
513 schedule();
514
Christian Borntraeger71cde582008-05-21 13:37:34 +0200515 if (test_thread_flag(TIF_MCCK_PENDING))
516 s390_handle_mcck();
517
Carsten Otted6b6d162012-01-04 10:25:25 +0100518 if (!kvm_is_ucontrol(vcpu->kvm))
519 kvm_s390_deliver_pending_interrupts(vcpu);
Carsten Otte0ff31862008-05-21 13:37:37 +0200520
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100521 vcpu->arch.sie_block->icptcode = 0;
522 local_irq_disable();
523 kvm_guest_enter();
524 local_irq_enable();
525 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
526 atomic_read(&vcpu->arch.sie_block->cpuflags));
Carsten Ottee168bf82012-01-04 10:25:22 +0100527 rc = sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs);
528 if (rc) {
529 if (kvm_is_ucontrol(vcpu->kvm)) {
530 rc = SIE_INTERCEPT_UCONTROL;
531 } else {
532 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
533 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
534 rc = 0;
535 }
Carsten Otte1f0d0f02008-05-21 13:37:40 +0200536 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100537 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
538 vcpu->arch.sie_block->icptcode);
539 local_irq_disable();
540 kvm_guest_exit();
541 local_irq_enable();
542
543 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
Carsten Ottee168bf82012-01-04 10:25:22 +0100544 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100545}
546
547int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
548{
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100549 int rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100550 sigset_t sigsaved;
551
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200552rerun_vcpu:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100553 if (vcpu->sigset_active)
554 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
555
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100556 atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100557
Carsten Otteba5c1e92008-03-25 18:47:26 +0100558 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
559
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100560 switch (kvm_run->exit_reason) {
561 case KVM_EXIT_S390_SIEIC:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100562 case KVM_EXIT_UNKNOWN:
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200563 case KVM_EXIT_INTR:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100564 case KVM_EXIT_S390_RESET:
Carsten Ottee168bf82012-01-04 10:25:22 +0100565 case KVM_EXIT_S390_UCONTROL:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100566 break;
567 default:
568 BUG();
569 }
570
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100571 vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
572 vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
573
Heiko Carstensdab4079d2009-06-12 10:26:32 +0200574 might_fault();
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100575
576 do {
Carsten Ottee168bf82012-01-04 10:25:22 +0100577 rc = __vcpu_run(vcpu);
578 if (rc)
579 break;
Carsten Ottec0d744a2012-01-04 10:25:24 +0100580 if (kvm_is_ucontrol(vcpu->kvm))
581 rc = -EOPNOTSUPP;
582 else
583 rc = kvm_handle_sie_intercept(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100584 } while (!signal_pending(current) && !rc);
585
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200586 if (rc == SIE_INTERCEPT_RERUNVCPU)
587 goto rerun_vcpu;
588
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200589 if (signal_pending(current) && !rc) {
590 kvm_run->exit_reason = KVM_EXIT_INTR;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100591 rc = -EINTR;
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200592 }
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100593
Carsten Ottee168bf82012-01-04 10:25:22 +0100594#ifdef CONFIG_KVM_S390_UCONTROL
595 if (rc == SIE_INTERCEPT_UCONTROL) {
596 kvm_run->exit_reason = KVM_EXIT_S390_UCONTROL;
597 kvm_run->s390_ucontrol.trans_exc_code =
598 current->thread.gmap_addr;
599 kvm_run->s390_ucontrol.pgm_code = 0x10;
600 rc = 0;
601 }
602#endif
603
Heiko Carstensb8e660b2010-02-26 22:37:41 +0100604 if (rc == -EOPNOTSUPP) {
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100605 /* intercept cannot be handled in-kernel, prepare kvm-run */
606 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
607 kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100608 kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
609 kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
610 rc = 0;
611 }
612
613 if (rc == -EREMOTE) {
614 /* intercept was handled, but userspace support is needed
615 * kvm_run has been prepared by the handler */
616 rc = 0;
617 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100618
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100619 kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
620 kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
621
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100622 if (vcpu->sigset_active)
623 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
624
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100625 vcpu->stat.exit_userspace++;
Heiko Carstens7e8e6ab2008-04-04 15:12:35 +0200626 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100627}
628
Carsten Otte092670c2011-07-24 10:48:22 +0200629static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100630 unsigned long n, int prefix)
631{
632 if (prefix)
633 return copy_to_guest(vcpu, guestdest, from, n);
634 else
635 return copy_to_guest_absolute(vcpu, guestdest, from, n);
636}
637
638/*
639 * store status at address
640 * we use have two special cases:
641 * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
642 * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
643 */
Christian Borntraeger971eb772010-06-12 08:54:13 +0200644int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100645{
Carsten Otte092670c2011-07-24 10:48:22 +0200646 unsigned char archmode = 1;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100647 int prefix;
648
649 if (addr == KVM_S390_STORE_STATUS_NOADDR) {
650 if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
651 return -EFAULT;
652 addr = SAVE_AREA_BASE;
653 prefix = 0;
654 } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
655 if (copy_to_guest(vcpu, 163ul, &archmode, 1))
656 return -EFAULT;
657 addr = SAVE_AREA_BASE;
658 prefix = 1;
659 } else
660 prefix = 0;
661
Heiko Carstensf64ca212010-02-26 22:37:32 +0100662 if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100663 vcpu->arch.guest_fpregs.fprs, 128, prefix))
664 return -EFAULT;
665
Heiko Carstensf64ca212010-02-26 22:37:32 +0100666 if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100667 vcpu->arch.guest_gprs, 128, prefix))
668 return -EFAULT;
669
Heiko Carstensf64ca212010-02-26 22:37:32 +0100670 if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100671 &vcpu->arch.sie_block->gpsw, 16, prefix))
672 return -EFAULT;
673
Heiko Carstensf64ca212010-02-26 22:37:32 +0100674 if (__guestcopy(vcpu, addr + offsetof(struct save_area, pref_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100675 &vcpu->arch.sie_block->prefix, 4, prefix))
676 return -EFAULT;
677
678 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100679 addr + offsetof(struct save_area, fp_ctrl_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100680 &vcpu->arch.guest_fpregs.fpc, 4, prefix))
681 return -EFAULT;
682
Heiko Carstensf64ca212010-02-26 22:37:32 +0100683 if (__guestcopy(vcpu, addr + offsetof(struct save_area, tod_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100684 &vcpu->arch.sie_block->todpr, 4, prefix))
685 return -EFAULT;
686
Heiko Carstensf64ca212010-02-26 22:37:32 +0100687 if (__guestcopy(vcpu, addr + offsetof(struct save_area, timer),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100688 &vcpu->arch.sie_block->cputm, 8, prefix))
689 return -EFAULT;
690
Heiko Carstensf64ca212010-02-26 22:37:32 +0100691 if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100692 &vcpu->arch.sie_block->ckc, 8, prefix))
693 return -EFAULT;
694
Heiko Carstensf64ca212010-02-26 22:37:32 +0100695 if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100696 &vcpu->arch.guest_acrs, 64, prefix))
697 return -EFAULT;
698
699 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100700 addr + offsetof(struct save_area, ctrl_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100701 &vcpu->arch.sie_block->gcr, 128, prefix))
702 return -EFAULT;
703 return 0;
704}
705
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100706long kvm_arch_vcpu_ioctl(struct file *filp,
707 unsigned int ioctl, unsigned long arg)
708{
709 struct kvm_vcpu *vcpu = filp->private_data;
710 void __user *argp = (void __user *)arg;
Avi Kivitybc923cc2010-05-13 12:21:46 +0300711 long r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100712
Avi Kivity937366242010-05-13 12:35:17 +0300713 switch (ioctl) {
714 case KVM_S390_INTERRUPT: {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100715 struct kvm_s390_interrupt s390int;
716
Avi Kivity937366242010-05-13 12:35:17 +0300717 r = -EFAULT;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100718 if (copy_from_user(&s390int, argp, sizeof(s390int)))
Avi Kivity937366242010-05-13 12:35:17 +0300719 break;
720 r = kvm_s390_inject_vcpu(vcpu, &s390int);
721 break;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100722 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100723 case KVM_S390_STORE_STATUS:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300724 r = kvm_s390_vcpu_store_status(vcpu, arg);
725 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100726 case KVM_S390_SET_INITIAL_PSW: {
727 psw_t psw;
728
Avi Kivitybc923cc2010-05-13 12:21:46 +0300729 r = -EFAULT;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100730 if (copy_from_user(&psw, argp, sizeof(psw)))
Avi Kivitybc923cc2010-05-13 12:21:46 +0300731 break;
732 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
733 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100734 }
735 case KVM_S390_INITIAL_RESET:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300736 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
737 break;
Carsten Otte27e03932012-01-04 10:25:21 +0100738#ifdef CONFIG_KVM_S390_UCONTROL
739 case KVM_S390_UCAS_MAP: {
740 struct kvm_s390_ucas_mapping ucasmap;
741
742 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
743 r = -EFAULT;
744 break;
745 }
746
747 if (!kvm_is_ucontrol(vcpu->kvm)) {
748 r = -EINVAL;
749 break;
750 }
751
752 r = gmap_map_segment(vcpu->arch.gmap, ucasmap.user_addr,
753 ucasmap.vcpu_addr, ucasmap.length);
754 break;
755 }
756 case KVM_S390_UCAS_UNMAP: {
757 struct kvm_s390_ucas_mapping ucasmap;
758
759 if (copy_from_user(&ucasmap, argp, sizeof(ucasmap))) {
760 r = -EFAULT;
761 break;
762 }
763
764 if (!kvm_is_ucontrol(vcpu->kvm)) {
765 r = -EINVAL;
766 break;
767 }
768
769 r = gmap_unmap_segment(vcpu->arch.gmap, ucasmap.vcpu_addr,
770 ucasmap.length);
771 break;
772 }
773#endif
Carsten Otteccc79102012-01-04 10:25:26 +0100774 case KVM_S390_VCPU_FAULT: {
775 r = gmap_fault(arg, vcpu->arch.gmap);
776 if (!IS_ERR_VALUE(r))
777 r = 0;
778 break;
779 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100780 default:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300781 r = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100782 }
Avi Kivitybc923cc2010-05-13 12:21:46 +0300783 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100784}
785
Carsten Otte5b1c1492012-01-04 10:25:23 +0100786int kvm_arch_vcpu_fault(struct kvm_vcpu *vcpu, struct vm_fault *vmf)
787{
788#ifdef CONFIG_KVM_S390_UCONTROL
789 if ((vmf->pgoff == KVM_S390_SIE_PAGE_OFFSET)
790 && (kvm_is_ucontrol(vcpu->kvm))) {
791 vmf->page = virt_to_page(vcpu->arch.sie_block);
792 get_page(vmf->page);
793 return 0;
794 }
795#endif
796 return VM_FAULT_SIGBUS;
797}
798
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100799/* Section: memory related */
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200800int kvm_arch_prepare_memory_region(struct kvm *kvm,
801 struct kvm_memory_slot *memslot,
802 struct kvm_memory_slot old,
803 struct kvm_userspace_memory_region *mem,
804 int user_alloc)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100805{
806 /* A few sanity checks. We can have exactly one memory slot which has
807 to start at guest virtual zero and which has to be located at a
808 page boundary in userland and which has to end at a page boundary.
809 The memory in userland is ok to be fragmented into various different
810 vmas. It is okay to mmap() and munmap() stuff in this slot after
811 doing this call at any time */
812
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +0200813 if (mem->slot)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100814 return -EINVAL;
815
816 if (mem->guest_phys_addr)
817 return -EINVAL;
818
Carsten Otte598841c2011-07-24 10:48:21 +0200819 if (mem->userspace_addr & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100820 return -EINVAL;
821
Carsten Otte598841c2011-07-24 10:48:21 +0200822 if (mem->memory_size & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100823 return -EINVAL;
824
Carsten Otte2668dab2009-05-12 17:21:48 +0200825 if (!user_alloc)
826 return -EINVAL;
827
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200828 return 0;
829}
830
831void kvm_arch_commit_memory_region(struct kvm *kvm,
832 struct kvm_userspace_memory_region *mem,
833 struct kvm_memory_slot old,
834 int user_alloc)
835{
Carsten Ottef7850c92011-07-24 10:48:23 +0200836 int rc;
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200837
Carsten Otte598841c2011-07-24 10:48:21 +0200838
839 rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
840 mem->guest_phys_addr, mem->memory_size);
841 if (rc)
Carsten Ottef7850c92011-07-24 10:48:23 +0200842 printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
Carsten Otte598841c2011-07-24 10:48:21 +0200843 return;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100844}
845
Marcelo Tosatti34d4cb82008-07-10 20:49:31 -0300846void kvm_arch_flush_shadow(struct kvm *kvm)
847{
848}
849
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100850static int __init kvm_s390_init(void)
851{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200852 int ret;
Avi Kivity0ee75be2010-04-28 15:39:01 +0300853 ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200854 if (ret)
855 return ret;
856
857 /*
858 * guests can ask for up to 255+1 double words, we need a full page
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300859 * to hold the maximum amount of facilities. On the other hand, we
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200860 * only set facilities that are known to work in KVM.
861 */
Heiko Carstensc2f0e8c2010-06-08 18:58:09 +0200862 facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200863 if (!facilities) {
864 kvm_exit();
865 return -ENOMEM;
866 }
Martin Schwidefsky14375bc2010-10-25 16:10:51 +0200867 memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
Christian Borntraeger6d00d002010-10-25 16:10:48 +0200868 facilities[0] &= 0xff00fff3f47c0000ULL;
Christian Borntraeger9950f8b2011-06-06 14:14:39 +0200869 facilities[1] &= 0x201c000000000000ULL;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200870 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100871}
872
873static void __exit kvm_s390_exit(void)
874{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200875 free_page((unsigned long) facilities);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100876 kvm_exit();
877}
878
879module_init(kvm_s390_init);
880module_exit(kvm_s390_exit);