blob: 0cba935d1282ed20e09353bf5419d06246330e37 [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) },
49 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
50 { "deliver_virtio_interrupt", VCPU_STAT(deliver_virtio_interrupt) },
51 { "deliver_stop_signal", VCPU_STAT(deliver_stop_signal) },
52 { "deliver_prefix_signal", VCPU_STAT(deliver_prefix_signal) },
53 { "deliver_restart_signal", VCPU_STAT(deliver_restart_signal) },
54 { "deliver_program_interruption", VCPU_STAT(deliver_program_int) },
55 { "exit_wait_state", VCPU_STAT(exit_wait_state) },
Christian Borntraeger453423d2008-03-25 18:47:29 +010056 { "instruction_stidp", VCPU_STAT(instruction_stidp) },
57 { "instruction_spx", VCPU_STAT(instruction_spx) },
58 { "instruction_stpx", VCPU_STAT(instruction_stpx) },
59 { "instruction_stap", VCPU_STAT(instruction_stap) },
60 { "instruction_storage_key", VCPU_STAT(instruction_storage_key) },
61 { "instruction_stsch", VCPU_STAT(instruction_stsch) },
62 { "instruction_chsc", VCPU_STAT(instruction_chsc) },
63 { "instruction_stsi", VCPU_STAT(instruction_stsi) },
64 { "instruction_stfl", VCPU_STAT(instruction_stfl) },
Christian Borntraegerbb25b9b2011-07-24 10:48:17 +020065 { "instruction_tprot", VCPU_STAT(instruction_tprot) },
Christian Borntraeger5288fbf2008-03-25 18:47:31 +010066 { "instruction_sigp_sense", VCPU_STAT(instruction_sigp_sense) },
67 { "instruction_sigp_emergency", VCPU_STAT(instruction_sigp_emergency) },
68 { "instruction_sigp_stop", VCPU_STAT(instruction_sigp_stop) },
69 { "instruction_sigp_set_arch", VCPU_STAT(instruction_sigp_arch) },
70 { "instruction_sigp_set_prefix", VCPU_STAT(instruction_sigp_prefix) },
71 { "instruction_sigp_restart", VCPU_STAT(instruction_sigp_restart) },
Christian Borntraegere28acfe2008-03-25 18:47:34 +010072 { "diagnose_44", VCPU_STAT(diagnose_44) },
Heiko Carstensb0c632d2008-03-25 18:47:20 +010073 { NULL }
74};
75
Christian Borntraegeref50f7a2009-06-23 17:24:07 +020076static unsigned long long *facilities;
Heiko Carstensb0c632d2008-03-25 18:47:20 +010077
78/* Section: not file related */
Alexander Graf10474ae2009-09-15 11:37:46 +020079int kvm_arch_hardware_enable(void *garbage)
Heiko Carstensb0c632d2008-03-25 18:47:20 +010080{
81 /* every s390 is virtualization enabled ;-) */
Alexander Graf10474ae2009-09-15 11:37:46 +020082 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +010083}
84
85void kvm_arch_hardware_disable(void *garbage)
86{
87}
88
Heiko Carstensb0c632d2008-03-25 18:47:20 +010089int kvm_arch_hardware_setup(void)
90{
91 return 0;
92}
93
94void kvm_arch_hardware_unsetup(void)
95{
96}
97
98void kvm_arch_check_processor_compat(void *rtn)
99{
100}
101
102int kvm_arch_init(void *opaque)
103{
104 return 0;
105}
106
107void kvm_arch_exit(void)
108{
109}
110
111/* Section: device related */
112long kvm_arch_dev_ioctl(struct file *filp,
113 unsigned int ioctl, unsigned long arg)
114{
115 if (ioctl == KVM_S390_ENABLE_SIE)
116 return s390_enable_sie();
117 return -EINVAL;
118}
119
120int kvm_dev_ioctl_check_extension(long ext)
121{
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100122 int r;
123
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200124 switch (ext) {
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100125 case KVM_CAP_S390_PSW:
Christian Borntraegerb6cf8782011-09-20 17:07:29 +0200126 case KVM_CAP_S390_GMAP:
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100127 r = 1;
128 break;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200129 default:
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100130 r = 0;
Carsten Otte2bd0ac42008-07-25 15:49:13 +0200131 }
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100132 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100133}
134
135/* Section: vm related */
136/*
137 * Get (and clear) the dirty memory log for a memory slot.
138 */
139int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
140 struct kvm_dirty_log *log)
141{
142 return 0;
143}
144
145long kvm_arch_vm_ioctl(struct file *filp,
146 unsigned int ioctl, unsigned long arg)
147{
148 struct kvm *kvm = filp->private_data;
149 void __user *argp = (void __user *)arg;
150 int r;
151
152 switch (ioctl) {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100153 case KVM_S390_INTERRUPT: {
154 struct kvm_s390_interrupt s390int;
155
156 r = -EFAULT;
157 if (copy_from_user(&s390int, argp, sizeof(s390int)))
158 break;
159 r = kvm_s390_inject_vm(kvm, &s390int);
160 break;
161 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100162 default:
Avi Kivity367e1312009-08-26 14:57:07 +0300163 r = -ENOTTY;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100164 }
165
166 return r;
167}
168
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100169int kvm_arch_init_vm(struct kvm *kvm)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100170{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100171 int rc;
172 char debug_name[16];
173
174 rc = s390_enable_sie();
175 if (rc)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100176 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100177
178 kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
179 if (!kvm->arch.sca)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100180 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100181
182 sprintf(debug_name, "kvm-%u", current->pid);
183
184 kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
185 if (!kvm->arch.dbf)
186 goto out_nodbf;
187
Carsten Otteba5c1e92008-03-25 18:47:26 +0100188 spin_lock_init(&kvm->arch.float_int.lock);
189 INIT_LIST_HEAD(&kvm->arch.float_int.list);
190
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100191 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
192 VM_EVENT(kvm, 3, "%s", "vm created");
193
Carsten Otte598841c2011-07-24 10:48:21 +0200194 kvm->arch.gmap = gmap_alloc(current->mm);
195 if (!kvm->arch.gmap)
196 goto out_nogmap;
197
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100198 return 0;
Carsten Otte598841c2011-07-24 10:48:21 +0200199out_nogmap:
200 debug_unregister(kvm->arch.dbf);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100201out_nodbf:
202 free_page((unsigned long)(kvm->arch.sca));
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100203out_err:
204 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100205}
206
Christian Borntraegerd329c032008-11-26 14:50:27 +0100207void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
208{
209 VCPU_EVENT(vcpu, 3, "%s", "free cpu");
Christian Borntraegerfc345312010-06-17 23:16:20 +0200210 clear_bit(63 - vcpu->vcpu_id, (unsigned long *) &vcpu->kvm->arch.sca->mcn);
Carsten Otteabf4a712009-05-12 17:21:51 +0200211 if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
212 (__u64) vcpu->arch.sie_block)
213 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
214 smp_mb();
Christian Borntraegerd329c032008-11-26 14:50:27 +0100215 free_page((unsigned long)(vcpu->arch.sie_block));
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100216 kvm_vcpu_uninit(vcpu);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100217 kfree(vcpu);
218}
219
220static void kvm_free_vcpus(struct kvm *kvm)
221{
222 unsigned int i;
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300223 struct kvm_vcpu *vcpu;
Christian Borntraegerd329c032008-11-26 14:50:27 +0100224
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300225 kvm_for_each_vcpu(i, vcpu, kvm)
226 kvm_arch_vcpu_destroy(vcpu);
227
228 mutex_lock(&kvm->lock);
229 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
230 kvm->vcpus[i] = NULL;
231
232 atomic_set(&kvm->online_vcpus, 0);
233 mutex_unlock(&kvm->lock);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100234}
235
Sheng Yangad8ba2c2009-01-06 10:03:02 +0800236void kvm_arch_sync_events(struct kvm *kvm)
237{
238}
239
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100240void kvm_arch_destroy_vm(struct kvm *kvm)
241{
Christian Borntraegerd329c032008-11-26 14:50:27 +0100242 kvm_free_vcpus(kvm);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100243 free_page((unsigned long)(kvm->arch.sca));
Christian Borntraegerd329c032008-11-26 14:50:27 +0100244 debug_unregister(kvm->arch.dbf);
Carsten Otte598841c2011-07-24 10:48:21 +0200245 gmap_free(kvm->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100246}
247
248/* Section: vcpu related */
249int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
250{
Carsten Otte598841c2011-07-24 10:48:21 +0200251 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100252 return 0;
253}
254
255void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
256{
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100257 /* Nothing todo */
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100258}
259
260void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
261{
262 save_fp_regs(&vcpu->arch.host_fpregs);
263 save_access_regs(vcpu->arch.host_acrs);
264 vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
265 restore_fp_regs(&vcpu->arch.guest_fpregs);
266 restore_access_regs(vcpu->arch.guest_acrs);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200267 gmap_enable(vcpu->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100268}
269
270void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
271{
Christian Borntraeger480e5922011-09-20 17:07:28 +0200272 gmap_disable(vcpu->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100273 save_fp_regs(&vcpu->arch.guest_fpregs);
274 save_access_regs(vcpu->arch.guest_acrs);
275 restore_fp_regs(&vcpu->arch.host_fpregs);
276 restore_access_regs(vcpu->arch.host_acrs);
277}
278
279static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
280{
281 /* this equals initial cpu reset in pop, but we don't switch to ESA */
282 vcpu->arch.sie_block->gpsw.mask = 0UL;
283 vcpu->arch.sie_block->gpsw.addr = 0UL;
284 vcpu->arch.sie_block->prefix = 0UL;
285 vcpu->arch.sie_block->ihcpu = 0xffff;
286 vcpu->arch.sie_block->cputm = 0UL;
287 vcpu->arch.sie_block->ckc = 0UL;
288 vcpu->arch.sie_block->todpr = 0;
289 memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
290 vcpu->arch.sie_block->gcr[0] = 0xE0UL;
291 vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
292 vcpu->arch.guest_fpregs.fpc = 0;
293 asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
294 vcpu->arch.sie_block->gbea = 1;
295}
296
297int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
298{
Carsten Otte598841c2011-07-24 10:48:21 +0200299 atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH | CPUSTAT_SM);
Christian Borntraegerfc345312010-06-17 23:16:20 +0200300 vcpu->arch.sie_block->ecb = 6;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100301 vcpu->arch.sie_block->eca = 0xC1002001U;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200302 vcpu->arch.sie_block->fac = (int) (long) facilities;
Christian Borntraegerca872302009-05-12 17:21:49 +0200303 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
304 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
305 (unsigned long) vcpu);
306 vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
Christian Borntraeger453423d2008-03-25 18:47:29 +0100307 get_cpu_id(&vcpu->arch.cpu_id);
Christian Borntraeger92e6ecf2009-03-26 15:23:58 +0100308 vcpu->arch.cpu_id.version = 0xff;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100309 return 0;
310}
311
312struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
313 unsigned int id)
314{
Carsten Otte4d475552011-10-18 12:27:12 +0200315 struct kvm_vcpu *vcpu;
316 int rc = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100317
Carsten Otte4d475552011-10-18 12:27:12 +0200318 if (id >= KVM_MAX_VCPUS)
319 goto out;
320
321 rc = -ENOMEM;
322
323 vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100324 if (!vcpu)
Carsten Otte4d475552011-10-18 12:27:12 +0200325 goto out;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100326
Christian Borntraeger180c12f2008-06-27 15:05:40 +0200327 vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
328 get_zeroed_page(GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100329
330 if (!vcpu->arch.sie_block)
331 goto out_free_cpu;
332
333 vcpu->arch.sie_block->icpua = id;
334 BUG_ON(!kvm->arch.sca);
Carsten Otteabf4a712009-05-12 17:21:51 +0200335 if (!kvm->arch.sca->cpu[id].sda)
336 kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100337 vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
338 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
Christian Borntraegerfc345312010-06-17 23:16:20 +0200339 set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100340
Carsten Otteba5c1e92008-03-25 18:47:26 +0100341 spin_lock_init(&vcpu->arch.local_int.lock);
342 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
343 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200344 spin_lock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100345 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
346 init_waitqueue_head(&vcpu->arch.local_int.wq);
Christian Borntraeger5288fbf2008-03-25 18:47:31 +0100347 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200348 spin_unlock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100349
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100350 rc = kvm_vcpu_init(vcpu, kvm, id);
351 if (rc)
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800352 goto out_free_sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100353 VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
354 vcpu->arch.sie_block);
355
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100356 return vcpu;
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800357out_free_sie_block:
358 free_page((unsigned long)(vcpu->arch.sie_block));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100359out_free_cpu:
360 kfree(vcpu);
Carsten Otte4d475552011-10-18 12:27:12 +0200361out:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100362 return ERR_PTR(rc);
363}
364
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100365int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
366{
367 /* kvm common code refers to this, but never calls it */
368 BUG();
369 return 0;
370}
371
372static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
373{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100374 kvm_s390_vcpu_initial_reset(vcpu);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100375 return 0;
376}
377
378int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
379{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100380 memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100381 return 0;
382}
383
384int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
385{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100386 memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100387 return 0;
388}
389
390int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
391 struct kvm_sregs *sregs)
392{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100393 memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
394 memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100395 return 0;
396}
397
398int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
399 struct kvm_sregs *sregs)
400{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100401 memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
402 memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100403 return 0;
404}
405
406int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
407{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100408 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
409 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100410 return 0;
411}
412
413int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
414{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100415 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
416 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100417 return 0;
418}
419
420static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
421{
422 int rc = 0;
423
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100424 if (atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_RUNNING)
425 rc = -EBUSY;
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100426 else {
427 vcpu->run->psw_mask = psw.mask;
428 vcpu->run->psw_addr = psw.addr;
429 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100430 return rc;
431}
432
433int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
434 struct kvm_translation *tr)
435{
436 return -EINVAL; /* not implemented yet */
437}
438
Jan Kiszkad0bfb942008-12-15 13:52:10 +0100439int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
440 struct kvm_guest_debug *dbg)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100441{
442 return -EINVAL; /* not implemented yet */
443}
444
Marcelo Tosatti62d9f0d2008-04-11 13:24:45 -0300445int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
446 struct kvm_mp_state *mp_state)
447{
448 return -EINVAL; /* not implemented yet */
449}
450
451int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
452 struct kvm_mp_state *mp_state)
453{
454 return -EINVAL; /* not implemented yet */
455}
456
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100457static void __vcpu_run(struct kvm_vcpu *vcpu)
458{
459 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
460
461 if (need_resched())
462 schedule();
463
Christian Borntraeger71cde582008-05-21 13:37:34 +0200464 if (test_thread_flag(TIF_MCCK_PENDING))
465 s390_handle_mcck();
466
Carsten Otte0ff31862008-05-21 13:37:37 +0200467 kvm_s390_deliver_pending_interrupts(vcpu);
468
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100469 vcpu->arch.sie_block->icptcode = 0;
470 local_irq_disable();
471 kvm_guest_enter();
472 local_irq_enable();
473 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
474 atomic_read(&vcpu->arch.sie_block->cpuflags));
Carsten Otte1f0d0f02008-05-21 13:37:40 +0200475 if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
476 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
477 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
478 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100479 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
480 vcpu->arch.sie_block->icptcode);
481 local_irq_disable();
482 kvm_guest_exit();
483 local_irq_enable();
484
485 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
486}
487
488int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
489{
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100490 int rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100491 sigset_t sigsaved;
492
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200493rerun_vcpu:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100494 if (vcpu->sigset_active)
495 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
496
497 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
498
Carsten Otteba5c1e92008-03-25 18:47:26 +0100499 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
500
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100501 switch (kvm_run->exit_reason) {
502 case KVM_EXIT_S390_SIEIC:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100503 case KVM_EXIT_UNKNOWN:
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200504 case KVM_EXIT_INTR:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100505 case KVM_EXIT_S390_RESET:
506 break;
507 default:
508 BUG();
509 }
510
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100511 vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
512 vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
513
Heiko Carstensdab4079d2009-06-12 10:26:32 +0200514 might_fault();
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100515
516 do {
517 __vcpu_run(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100518 rc = kvm_handle_sie_intercept(vcpu);
519 } while (!signal_pending(current) && !rc);
520
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200521 if (rc == SIE_INTERCEPT_RERUNVCPU)
522 goto rerun_vcpu;
523
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200524 if (signal_pending(current) && !rc) {
525 kvm_run->exit_reason = KVM_EXIT_INTR;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100526 rc = -EINTR;
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200527 }
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100528
Heiko Carstensb8e660b2010-02-26 22:37:41 +0100529 if (rc == -EOPNOTSUPP) {
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100530 /* intercept cannot be handled in-kernel, prepare kvm-run */
531 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
532 kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100533 kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
534 kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
535 rc = 0;
536 }
537
538 if (rc == -EREMOTE) {
539 /* intercept was handled, but userspace support is needed
540 * kvm_run has been prepared by the handler */
541 rc = 0;
542 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100543
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100544 kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
545 kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
546
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100547 if (vcpu->sigset_active)
548 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
549
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100550 vcpu->stat.exit_userspace++;
Heiko Carstens7e8e6ab2008-04-04 15:12:35 +0200551 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100552}
553
Carsten Otte092670c2011-07-24 10:48:22 +0200554static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100555 unsigned long n, int prefix)
556{
557 if (prefix)
558 return copy_to_guest(vcpu, guestdest, from, n);
559 else
560 return copy_to_guest_absolute(vcpu, guestdest, from, n);
561}
562
563/*
564 * store status at address
565 * we use have two special cases:
566 * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
567 * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
568 */
Christian Borntraeger971eb772010-06-12 08:54:13 +0200569int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100570{
Carsten Otte092670c2011-07-24 10:48:22 +0200571 unsigned char archmode = 1;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100572 int prefix;
573
574 if (addr == KVM_S390_STORE_STATUS_NOADDR) {
575 if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
576 return -EFAULT;
577 addr = SAVE_AREA_BASE;
578 prefix = 0;
579 } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
580 if (copy_to_guest(vcpu, 163ul, &archmode, 1))
581 return -EFAULT;
582 addr = SAVE_AREA_BASE;
583 prefix = 1;
584 } else
585 prefix = 0;
586
Heiko Carstensf64ca212010-02-26 22:37:32 +0100587 if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100588 vcpu->arch.guest_fpregs.fprs, 128, prefix))
589 return -EFAULT;
590
Heiko Carstensf64ca212010-02-26 22:37:32 +0100591 if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100592 vcpu->arch.guest_gprs, 128, prefix))
593 return -EFAULT;
594
Heiko Carstensf64ca212010-02-26 22:37:32 +0100595 if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100596 &vcpu->arch.sie_block->gpsw, 16, prefix))
597 return -EFAULT;
598
Heiko Carstensf64ca212010-02-26 22:37:32 +0100599 if (__guestcopy(vcpu, addr + offsetof(struct save_area, pref_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100600 &vcpu->arch.sie_block->prefix, 4, prefix))
601 return -EFAULT;
602
603 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100604 addr + offsetof(struct save_area, fp_ctrl_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100605 &vcpu->arch.guest_fpregs.fpc, 4, prefix))
606 return -EFAULT;
607
Heiko Carstensf64ca212010-02-26 22:37:32 +0100608 if (__guestcopy(vcpu, addr + offsetof(struct save_area, tod_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100609 &vcpu->arch.sie_block->todpr, 4, prefix))
610 return -EFAULT;
611
Heiko Carstensf64ca212010-02-26 22:37:32 +0100612 if (__guestcopy(vcpu, addr + offsetof(struct save_area, timer),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100613 &vcpu->arch.sie_block->cputm, 8, prefix))
614 return -EFAULT;
615
Heiko Carstensf64ca212010-02-26 22:37:32 +0100616 if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100617 &vcpu->arch.sie_block->ckc, 8, prefix))
618 return -EFAULT;
619
Heiko Carstensf64ca212010-02-26 22:37:32 +0100620 if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100621 &vcpu->arch.guest_acrs, 64, prefix))
622 return -EFAULT;
623
624 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100625 addr + offsetof(struct save_area, ctrl_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100626 &vcpu->arch.sie_block->gcr, 128, prefix))
627 return -EFAULT;
628 return 0;
629}
630
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100631long kvm_arch_vcpu_ioctl(struct file *filp,
632 unsigned int ioctl, unsigned long arg)
633{
634 struct kvm_vcpu *vcpu = filp->private_data;
635 void __user *argp = (void __user *)arg;
Avi Kivitybc923cc2010-05-13 12:21:46 +0300636 long r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100637
Avi Kivity93736622010-05-13 12:35:17 +0300638 switch (ioctl) {
639 case KVM_S390_INTERRUPT: {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100640 struct kvm_s390_interrupt s390int;
641
Avi Kivity93736622010-05-13 12:35:17 +0300642 r = -EFAULT;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100643 if (copy_from_user(&s390int, argp, sizeof(s390int)))
Avi Kivity93736622010-05-13 12:35:17 +0300644 break;
645 r = kvm_s390_inject_vcpu(vcpu, &s390int);
646 break;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100647 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100648 case KVM_S390_STORE_STATUS:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300649 r = kvm_s390_vcpu_store_status(vcpu, arg);
650 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100651 case KVM_S390_SET_INITIAL_PSW: {
652 psw_t psw;
653
Avi Kivitybc923cc2010-05-13 12:21:46 +0300654 r = -EFAULT;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100655 if (copy_from_user(&psw, argp, sizeof(psw)))
Avi Kivitybc923cc2010-05-13 12:21:46 +0300656 break;
657 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
658 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100659 }
660 case KVM_S390_INITIAL_RESET:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300661 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
662 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100663 default:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300664 r = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100665 }
Avi Kivitybc923cc2010-05-13 12:21:46 +0300666 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100667}
668
669/* Section: memory related */
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200670int kvm_arch_prepare_memory_region(struct kvm *kvm,
671 struct kvm_memory_slot *memslot,
672 struct kvm_memory_slot old,
673 struct kvm_userspace_memory_region *mem,
674 int user_alloc)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100675{
676 /* A few sanity checks. We can have exactly one memory slot which has
677 to start at guest virtual zero and which has to be located at a
678 page boundary in userland and which has to end at a page boundary.
679 The memory in userland is ok to be fragmented into various different
680 vmas. It is okay to mmap() and munmap() stuff in this slot after
681 doing this call at any time */
682
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +0200683 if (mem->slot)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100684 return -EINVAL;
685
686 if (mem->guest_phys_addr)
687 return -EINVAL;
688
Carsten Otte598841c2011-07-24 10:48:21 +0200689 if (mem->userspace_addr & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100690 return -EINVAL;
691
Carsten Otte598841c2011-07-24 10:48:21 +0200692 if (mem->memory_size & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100693 return -EINVAL;
694
Carsten Otte2668dab2009-05-12 17:21:48 +0200695 if (!user_alloc)
696 return -EINVAL;
697
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200698 return 0;
699}
700
701void kvm_arch_commit_memory_region(struct kvm *kvm,
702 struct kvm_userspace_memory_region *mem,
703 struct kvm_memory_slot old,
704 int user_alloc)
705{
Carsten Ottef7850c92011-07-24 10:48:23 +0200706 int rc;
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200707
Carsten Otte598841c2011-07-24 10:48:21 +0200708
709 rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
710 mem->guest_phys_addr, mem->memory_size);
711 if (rc)
Carsten Ottef7850c92011-07-24 10:48:23 +0200712 printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
Carsten Otte598841c2011-07-24 10:48:21 +0200713 return;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100714}
715
Marcelo Tosatti34d4cb82008-07-10 20:49:31 -0300716void kvm_arch_flush_shadow(struct kvm *kvm)
717{
718}
719
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100720static int __init kvm_s390_init(void)
721{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200722 int ret;
Avi Kivity0ee75be2010-04-28 15:39:01 +0300723 ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200724 if (ret)
725 return ret;
726
727 /*
728 * guests can ask for up to 255+1 double words, we need a full page
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300729 * to hold the maximum amount of facilities. On the other hand, we
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200730 * only set facilities that are known to work in KVM.
731 */
Heiko Carstensc2f0e8c2010-06-08 18:58:09 +0200732 facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200733 if (!facilities) {
734 kvm_exit();
735 return -ENOMEM;
736 }
Martin Schwidefsky14375bc2010-10-25 16:10:51 +0200737 memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
Christian Borntraeger6d00d002010-10-25 16:10:48 +0200738 facilities[0] &= 0xff00fff3f47c0000ULL;
Christian Borntraeger9950f8b2011-06-06 14:14:39 +0200739 facilities[1] &= 0x201c000000000000ULL;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200740 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100741}
742
743static void __exit kvm_s390_exit(void)
744{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200745 free_page((unsigned long) facilities);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100746 kvm_exit();
747}
748
749module_init(kvm_s390_init);
750module_exit(kvm_s390_exit);