blob: d1c445732451b6d1bd1c4b95db3d6467ff629c68 [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
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100174int kvm_arch_init_vm(struct kvm *kvm)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100175{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100176 int rc;
177 char debug_name[16];
178
179 rc = s390_enable_sie();
180 if (rc)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100181 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100182
Carsten Otteb2904112011-10-18 12:27:13 +0200183 rc = -ENOMEM;
184
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100185 kvm->arch.sca = (struct sca_block *) get_zeroed_page(GFP_KERNEL);
186 if (!kvm->arch.sca)
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100187 goto out_err;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100188
189 sprintf(debug_name, "kvm-%u", current->pid);
190
191 kvm->arch.dbf = debug_register(debug_name, 8, 2, 8 * sizeof(long));
192 if (!kvm->arch.dbf)
193 goto out_nodbf;
194
Carsten Otteba5c1e92008-03-25 18:47:26 +0100195 spin_lock_init(&kvm->arch.float_int.lock);
196 INIT_LIST_HEAD(&kvm->arch.float_int.list);
197
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100198 debug_register_view(kvm->arch.dbf, &debug_sprintf_view);
199 VM_EVENT(kvm, 3, "%s", "vm created");
200
Carsten Otte598841c2011-07-24 10:48:21 +0200201 kvm->arch.gmap = gmap_alloc(current->mm);
202 if (!kvm->arch.gmap)
203 goto out_nogmap;
204
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100205 return 0;
Carsten Otte598841c2011-07-24 10:48:21 +0200206out_nogmap:
207 debug_unregister(kvm->arch.dbf);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100208out_nodbf:
209 free_page((unsigned long)(kvm->arch.sca));
Jan Kiszkad89f5ef2010-11-09 17:02:49 +0100210out_err:
211 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100212}
213
Christian Borntraegerd329c032008-11-26 14:50:27 +0100214void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu)
215{
216 VCPU_EVENT(vcpu, 3, "%s", "free cpu");
Christian Borntraegerfc345312010-06-17 23:16:20 +0200217 clear_bit(63 - vcpu->vcpu_id, (unsigned long *) &vcpu->kvm->arch.sca->mcn);
Carsten Otteabf4a712009-05-12 17:21:51 +0200218 if (vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda ==
219 (__u64) vcpu->arch.sie_block)
220 vcpu->kvm->arch.sca->cpu[vcpu->vcpu_id].sda = 0;
221 smp_mb();
Christian Borntraegerd329c032008-11-26 14:50:27 +0100222 free_page((unsigned long)(vcpu->arch.sie_block));
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100223 kvm_vcpu_uninit(vcpu);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100224 kfree(vcpu);
225}
226
227static void kvm_free_vcpus(struct kvm *kvm)
228{
229 unsigned int i;
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300230 struct kvm_vcpu *vcpu;
Christian Borntraegerd329c032008-11-26 14:50:27 +0100231
Gleb Natapov988a2ca2009-06-09 15:56:29 +0300232 kvm_for_each_vcpu(i, vcpu, kvm)
233 kvm_arch_vcpu_destroy(vcpu);
234
235 mutex_lock(&kvm->lock);
236 for (i = 0; i < atomic_read(&kvm->online_vcpus); i++)
237 kvm->vcpus[i] = NULL;
238
239 atomic_set(&kvm->online_vcpus, 0);
240 mutex_unlock(&kvm->lock);
Christian Borntraegerd329c032008-11-26 14:50:27 +0100241}
242
Sheng Yangad8ba2c2009-01-06 10:03:02 +0800243void kvm_arch_sync_events(struct kvm *kvm)
244{
245}
246
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100247void kvm_arch_destroy_vm(struct kvm *kvm)
248{
Christian Borntraegerd329c032008-11-26 14:50:27 +0100249 kvm_free_vcpus(kvm);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100250 free_page((unsigned long)(kvm->arch.sca));
Christian Borntraegerd329c032008-11-26 14:50:27 +0100251 debug_unregister(kvm->arch.dbf);
Carsten Otte598841c2011-07-24 10:48:21 +0200252 gmap_free(kvm->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100253}
254
255/* Section: vcpu related */
256int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
257{
Carsten Otte598841c2011-07-24 10:48:21 +0200258 vcpu->arch.gmap = vcpu->kvm->arch.gmap;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100259 return 0;
260}
261
262void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu)
263{
Christian Borntraeger6692cef2008-11-26 14:51:08 +0100264 /* Nothing todo */
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100265}
266
267void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
268{
269 save_fp_regs(&vcpu->arch.host_fpregs);
270 save_access_regs(vcpu->arch.host_acrs);
271 vcpu->arch.guest_fpregs.fpc &= FPC_VALID_MASK;
272 restore_fp_regs(&vcpu->arch.guest_fpregs);
273 restore_access_regs(vcpu->arch.guest_acrs);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200274 gmap_enable(vcpu->arch.gmap);
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100275 atomic_set_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100276}
277
278void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
279{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100280 atomic_clear_mask(CPUSTAT_RUNNING, &vcpu->arch.sie_block->cpuflags);
Christian Borntraeger480e5922011-09-20 17:07:28 +0200281 gmap_disable(vcpu->arch.gmap);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100282 save_fp_regs(&vcpu->arch.guest_fpregs);
283 save_access_regs(vcpu->arch.guest_acrs);
284 restore_fp_regs(&vcpu->arch.host_fpregs);
285 restore_access_regs(vcpu->arch.host_acrs);
286}
287
288static void kvm_s390_vcpu_initial_reset(struct kvm_vcpu *vcpu)
289{
290 /* this equals initial cpu reset in pop, but we don't switch to ESA */
291 vcpu->arch.sie_block->gpsw.mask = 0UL;
292 vcpu->arch.sie_block->gpsw.addr = 0UL;
293 vcpu->arch.sie_block->prefix = 0UL;
294 vcpu->arch.sie_block->ihcpu = 0xffff;
295 vcpu->arch.sie_block->cputm = 0UL;
296 vcpu->arch.sie_block->ckc = 0UL;
297 vcpu->arch.sie_block->todpr = 0;
298 memset(vcpu->arch.sie_block->gcr, 0, 16 * sizeof(__u64));
299 vcpu->arch.sie_block->gcr[0] = 0xE0UL;
300 vcpu->arch.sie_block->gcr[14] = 0xC2000000UL;
301 vcpu->arch.guest_fpregs.fpc = 0;
302 asm volatile("lfpc %0" : : "Q" (vcpu->arch.guest_fpregs.fpc));
303 vcpu->arch.sie_block->gbea = 1;
304}
305
306int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
307{
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100308 atomic_set(&vcpu->arch.sie_block->cpuflags, CPUSTAT_ZARCH |
309 CPUSTAT_SM |
310 CPUSTAT_STOPPED);
Christian Borntraegerfc345312010-06-17 23:16:20 +0200311 vcpu->arch.sie_block->ecb = 6;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100312 vcpu->arch.sie_block->eca = 0xC1002001U;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200313 vcpu->arch.sie_block->fac = (int) (long) facilities;
Christian Borntraegerca872302009-05-12 17:21:49 +0200314 hrtimer_init(&vcpu->arch.ckc_timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
315 tasklet_init(&vcpu->arch.tasklet, kvm_s390_tasklet,
316 (unsigned long) vcpu);
317 vcpu->arch.ckc_timer.function = kvm_s390_idle_wakeup;
Christian Borntraeger453423d2008-03-25 18:47:29 +0100318 get_cpu_id(&vcpu->arch.cpu_id);
Christian Borntraeger92e6ecf2009-03-26 15:23:58 +0100319 vcpu->arch.cpu_id.version = 0xff;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100320 return 0;
321}
322
323struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm,
324 unsigned int id)
325{
Carsten Otte4d475552011-10-18 12:27:12 +0200326 struct kvm_vcpu *vcpu;
327 int rc = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100328
Carsten Otte4d475552011-10-18 12:27:12 +0200329 if (id >= KVM_MAX_VCPUS)
330 goto out;
331
332 rc = -ENOMEM;
333
334 vcpu = kzalloc(sizeof(struct kvm_vcpu), GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100335 if (!vcpu)
Carsten Otte4d475552011-10-18 12:27:12 +0200336 goto out;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100337
Christian Borntraeger180c12f2008-06-27 15:05:40 +0200338 vcpu->arch.sie_block = (struct kvm_s390_sie_block *)
339 get_zeroed_page(GFP_KERNEL);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100340
341 if (!vcpu->arch.sie_block)
342 goto out_free_cpu;
343
344 vcpu->arch.sie_block->icpua = id;
345 BUG_ON(!kvm->arch.sca);
Carsten Otteabf4a712009-05-12 17:21:51 +0200346 if (!kvm->arch.sca->cpu[id].sda)
347 kvm->arch.sca->cpu[id].sda = (__u64) vcpu->arch.sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100348 vcpu->arch.sie_block->scaoh = (__u32)(((__u64)kvm->arch.sca) >> 32);
349 vcpu->arch.sie_block->scaol = (__u32)(__u64)kvm->arch.sca;
Christian Borntraegerfc345312010-06-17 23:16:20 +0200350 set_bit(63 - id, (unsigned long *) &kvm->arch.sca->mcn);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100351
Carsten Otteba5c1e92008-03-25 18:47:26 +0100352 spin_lock_init(&vcpu->arch.local_int.lock);
353 INIT_LIST_HEAD(&vcpu->arch.local_int.list);
354 vcpu->arch.local_int.float_int = &kvm->arch.float_int;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200355 spin_lock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100356 kvm->arch.float_int.local_int[id] = &vcpu->arch.local_int;
357 init_waitqueue_head(&vcpu->arch.local_int.wq);
Christian Borntraeger5288fbf2008-03-25 18:47:31 +0100358 vcpu->arch.local_int.cpuflags = &vcpu->arch.sie_block->cpuflags;
Christian Borntraegerb037a4f2009-05-12 17:21:50 +0200359 spin_unlock(&kvm->arch.float_int.lock);
Carsten Otteba5c1e92008-03-25 18:47:26 +0100360
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100361 rc = kvm_vcpu_init(vcpu, kvm, id);
362 if (rc)
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800363 goto out_free_sie_block;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100364 VM_EVENT(kvm, 3, "create cpu %d at %p, sie block at %p", id, vcpu,
365 vcpu->arch.sie_block);
366
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100367 return vcpu;
Wei Yongjun7b06bf22010-03-09 14:37:53 +0800368out_free_sie_block:
369 free_page((unsigned long)(vcpu->arch.sie_block));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100370out_free_cpu:
371 kfree(vcpu);
Carsten Otte4d475552011-10-18 12:27:12 +0200372out:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100373 return ERR_PTR(rc);
374}
375
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100376int kvm_arch_vcpu_runnable(struct kvm_vcpu *vcpu)
377{
378 /* kvm common code refers to this, but never calls it */
379 BUG();
380 return 0;
381}
382
383static int kvm_arch_vcpu_ioctl_initial_reset(struct kvm_vcpu *vcpu)
384{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100385 kvm_s390_vcpu_initial_reset(vcpu);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100386 return 0;
387}
388
389int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
390{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100391 memcpy(&vcpu->arch.guest_gprs, &regs->gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100392 return 0;
393}
394
395int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
396{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100397 memcpy(&regs->gprs, &vcpu->arch.guest_gprs, sizeof(regs->gprs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100398 return 0;
399}
400
401int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
402 struct kvm_sregs *sregs)
403{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100404 memcpy(&vcpu->arch.guest_acrs, &sregs->acrs, sizeof(sregs->acrs));
405 memcpy(&vcpu->arch.sie_block->gcr, &sregs->crs, sizeof(sregs->crs));
Carsten Otte7eef87d2011-10-18 12:27:14 +0200406 restore_access_regs(vcpu->arch.guest_acrs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100407 return 0;
408}
409
410int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu,
411 struct kvm_sregs *sregs)
412{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100413 memcpy(&sregs->acrs, &vcpu->arch.guest_acrs, sizeof(sregs->acrs));
414 memcpy(&sregs->crs, &vcpu->arch.sie_block->gcr, sizeof(sregs->crs));
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100415 return 0;
416}
417
418int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
419{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100420 memcpy(&vcpu->arch.guest_fpregs.fprs, &fpu->fprs, sizeof(fpu->fprs));
421 vcpu->arch.guest_fpregs.fpc = fpu->fpc;
Carsten Otte7eef87d2011-10-18 12:27:14 +0200422 restore_fp_regs(&vcpu->arch.guest_fpregs);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100423 return 0;
424}
425
426int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu)
427{
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100428 memcpy(&fpu->fprs, &vcpu->arch.guest_fpregs.fprs, sizeof(fpu->fprs));
429 fpu->fpc = vcpu->arch.guest_fpregs.fpc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100430 return 0;
431}
432
433static int kvm_arch_vcpu_ioctl_set_initial_psw(struct kvm_vcpu *vcpu, psw_t psw)
434{
435 int rc = 0;
436
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100437 if (!(atomic_read(&vcpu->arch.sie_block->cpuflags) & CPUSTAT_STOPPED))
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100438 rc = -EBUSY;
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100439 else {
440 vcpu->run->psw_mask = psw.mask;
441 vcpu->run->psw_addr = psw.addr;
442 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100443 return rc;
444}
445
446int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu,
447 struct kvm_translation *tr)
448{
449 return -EINVAL; /* not implemented yet */
450}
451
Jan Kiszkad0bfb942008-12-15 13:52:10 +0100452int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
453 struct kvm_guest_debug *dbg)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100454{
455 return -EINVAL; /* not implemented yet */
456}
457
Marcelo Tosatti62d9f0d2008-04-11 13:24:45 -0300458int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu,
459 struct kvm_mp_state *mp_state)
460{
461 return -EINVAL; /* not implemented yet */
462}
463
464int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu,
465 struct kvm_mp_state *mp_state)
466{
467 return -EINVAL; /* not implemented yet */
468}
469
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100470static void __vcpu_run(struct kvm_vcpu *vcpu)
471{
472 memcpy(&vcpu->arch.sie_block->gg14, &vcpu->arch.guest_gprs[14], 16);
473
474 if (need_resched())
475 schedule();
476
Christian Borntraeger71cde582008-05-21 13:37:34 +0200477 if (test_thread_flag(TIF_MCCK_PENDING))
478 s390_handle_mcck();
479
Carsten Otte0ff31862008-05-21 13:37:37 +0200480 kvm_s390_deliver_pending_interrupts(vcpu);
481
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100482 vcpu->arch.sie_block->icptcode = 0;
483 local_irq_disable();
484 kvm_guest_enter();
485 local_irq_enable();
486 VCPU_EVENT(vcpu, 6, "entering sie flags %x",
487 atomic_read(&vcpu->arch.sie_block->cpuflags));
Carsten Otte1f0d0f02008-05-21 13:37:40 +0200488 if (sie64a(vcpu->arch.sie_block, vcpu->arch.guest_gprs)) {
489 VCPU_EVENT(vcpu, 3, "%s", "fault in sie instruction");
490 kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
491 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100492 VCPU_EVENT(vcpu, 6, "exit sie icptcode %d",
493 vcpu->arch.sie_block->icptcode);
494 local_irq_disable();
495 kvm_guest_exit();
496 local_irq_enable();
497
498 memcpy(&vcpu->arch.guest_gprs[14], &vcpu->arch.sie_block->gg14, 16);
499}
500
501int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
502{
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100503 int rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100504 sigset_t sigsaved;
505
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200506rerun_vcpu:
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100507 if (vcpu->sigset_active)
508 sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
509
Cornelia Huck9e6dabe2011-11-17 11:00:41 +0100510 atomic_clear_mask(CPUSTAT_STOPPED, &vcpu->arch.sie_block->cpuflags);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100511
Carsten Otteba5c1e92008-03-25 18:47:26 +0100512 BUG_ON(vcpu->kvm->arch.float_int.local_int[vcpu->vcpu_id] == NULL);
513
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100514 switch (kvm_run->exit_reason) {
515 case KVM_EXIT_S390_SIEIC:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100516 case KVM_EXIT_UNKNOWN:
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200517 case KVM_EXIT_INTR:
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100518 case KVM_EXIT_S390_RESET:
519 break;
520 default:
521 BUG();
522 }
523
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100524 vcpu->arch.sie_block->gpsw.mask = kvm_run->psw_mask;
525 vcpu->arch.sie_block->gpsw.addr = kvm_run->psw_addr;
526
Heiko Carstensdab4079d2009-06-12 10:26:32 +0200527 might_fault();
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100528
529 do {
530 __vcpu_run(vcpu);
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100531 rc = kvm_handle_sie_intercept(vcpu);
532 } while (!signal_pending(current) && !rc);
533
Christian Ehrhardt9ace9032009-05-20 15:34:55 +0200534 if (rc == SIE_INTERCEPT_RERUNVCPU)
535 goto rerun_vcpu;
536
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200537 if (signal_pending(current) && !rc) {
538 kvm_run->exit_reason = KVM_EXIT_INTR;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100539 rc = -EINTR;
Christian Ehrhardtb1d16c42009-05-20 15:34:56 +0200540 }
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100541
Heiko Carstensb8e660b2010-02-26 22:37:41 +0100542 if (rc == -EOPNOTSUPP) {
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100543 /* intercept cannot be handled in-kernel, prepare kvm-run */
544 kvm_run->exit_reason = KVM_EXIT_S390_SIEIC;
545 kvm_run->s390_sieic.icptcode = vcpu->arch.sie_block->icptcode;
Christian Borntraeger8f2abe62008-03-25 18:47:23 +0100546 kvm_run->s390_sieic.ipa = vcpu->arch.sie_block->ipa;
547 kvm_run->s390_sieic.ipb = vcpu->arch.sie_block->ipb;
548 rc = 0;
549 }
550
551 if (rc == -EREMOTE) {
552 /* intercept was handled, but userspace support is needed
553 * kvm_run has been prepared by the handler */
554 rc = 0;
555 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100556
Carsten Otted7b0b5e2009-11-19 14:21:16 +0100557 kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
558 kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
559
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100560 if (vcpu->sigset_active)
561 sigprocmask(SIG_SETMASK, &sigsaved, NULL);
562
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100563 vcpu->stat.exit_userspace++;
Heiko Carstens7e8e6ab2008-04-04 15:12:35 +0200564 return rc;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100565}
566
Carsten Otte092670c2011-07-24 10:48:22 +0200567static int __guestcopy(struct kvm_vcpu *vcpu, u64 guestdest, void *from,
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100568 unsigned long n, int prefix)
569{
570 if (prefix)
571 return copy_to_guest(vcpu, guestdest, from, n);
572 else
573 return copy_to_guest_absolute(vcpu, guestdest, from, n);
574}
575
576/*
577 * store status at address
578 * we use have two special cases:
579 * KVM_S390_STORE_STATUS_NOADDR: -> 0x1200 on 64 bit
580 * KVM_S390_STORE_STATUS_PREFIXED: -> prefix
581 */
Christian Borntraeger971eb772010-06-12 08:54:13 +0200582int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100583{
Carsten Otte092670c2011-07-24 10:48:22 +0200584 unsigned char archmode = 1;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100585 int prefix;
586
587 if (addr == KVM_S390_STORE_STATUS_NOADDR) {
588 if (copy_to_guest_absolute(vcpu, 163ul, &archmode, 1))
589 return -EFAULT;
590 addr = SAVE_AREA_BASE;
591 prefix = 0;
592 } else if (addr == KVM_S390_STORE_STATUS_PREFIXED) {
593 if (copy_to_guest(vcpu, 163ul, &archmode, 1))
594 return -EFAULT;
595 addr = SAVE_AREA_BASE;
596 prefix = 1;
597 } else
598 prefix = 0;
599
Heiko Carstensf64ca212010-02-26 22:37:32 +0100600 if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100601 vcpu->arch.guest_fpregs.fprs, 128, prefix))
602 return -EFAULT;
603
Heiko Carstensf64ca212010-02-26 22:37:32 +0100604 if (__guestcopy(vcpu, addr + offsetof(struct save_area, gp_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100605 vcpu->arch.guest_gprs, 128, prefix))
606 return -EFAULT;
607
Heiko Carstensf64ca212010-02-26 22:37:32 +0100608 if (__guestcopy(vcpu, addr + offsetof(struct save_area, psw),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100609 &vcpu->arch.sie_block->gpsw, 16, prefix))
610 return -EFAULT;
611
Heiko Carstensf64ca212010-02-26 22:37:32 +0100612 if (__guestcopy(vcpu, addr + offsetof(struct save_area, pref_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100613 &vcpu->arch.sie_block->prefix, 4, prefix))
614 return -EFAULT;
615
616 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100617 addr + offsetof(struct save_area, fp_ctrl_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100618 &vcpu->arch.guest_fpregs.fpc, 4, prefix))
619 return -EFAULT;
620
Heiko Carstensf64ca212010-02-26 22:37:32 +0100621 if (__guestcopy(vcpu, addr + offsetof(struct save_area, tod_reg),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100622 &vcpu->arch.sie_block->todpr, 4, prefix))
623 return -EFAULT;
624
Heiko Carstensf64ca212010-02-26 22:37:32 +0100625 if (__guestcopy(vcpu, addr + offsetof(struct save_area, timer),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100626 &vcpu->arch.sie_block->cputm, 8, prefix))
627 return -EFAULT;
628
Heiko Carstensf64ca212010-02-26 22:37:32 +0100629 if (__guestcopy(vcpu, addr + offsetof(struct save_area, clk_cmp),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100630 &vcpu->arch.sie_block->ckc, 8, prefix))
631 return -EFAULT;
632
Heiko Carstensf64ca212010-02-26 22:37:32 +0100633 if (__guestcopy(vcpu, addr + offsetof(struct save_area, acc_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100634 &vcpu->arch.guest_acrs, 64, prefix))
635 return -EFAULT;
636
637 if (__guestcopy(vcpu,
Heiko Carstensf64ca212010-02-26 22:37:32 +0100638 addr + offsetof(struct save_area, ctrl_regs),
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100639 &vcpu->arch.sie_block->gcr, 128, prefix))
640 return -EFAULT;
641 return 0;
642}
643
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100644long kvm_arch_vcpu_ioctl(struct file *filp,
645 unsigned int ioctl, unsigned long arg)
646{
647 struct kvm_vcpu *vcpu = filp->private_data;
648 void __user *argp = (void __user *)arg;
Avi Kivitybc923cc2010-05-13 12:21:46 +0300649 long r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100650
Avi Kivity93736622010-05-13 12:35:17 +0300651 switch (ioctl) {
652 case KVM_S390_INTERRUPT: {
Carsten Otteba5c1e92008-03-25 18:47:26 +0100653 struct kvm_s390_interrupt s390int;
654
Avi Kivity93736622010-05-13 12:35:17 +0300655 r = -EFAULT;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100656 if (copy_from_user(&s390int, argp, sizeof(s390int)))
Avi Kivity93736622010-05-13 12:35:17 +0300657 break;
658 r = kvm_s390_inject_vcpu(vcpu, &s390int);
659 break;
Carsten Otteba5c1e92008-03-25 18:47:26 +0100660 }
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100661 case KVM_S390_STORE_STATUS:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300662 r = kvm_s390_vcpu_store_status(vcpu, arg);
663 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100664 case KVM_S390_SET_INITIAL_PSW: {
665 psw_t psw;
666
Avi Kivitybc923cc2010-05-13 12:21:46 +0300667 r = -EFAULT;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100668 if (copy_from_user(&psw, argp, sizeof(psw)))
Avi Kivitybc923cc2010-05-13 12:21:46 +0300669 break;
670 r = kvm_arch_vcpu_ioctl_set_initial_psw(vcpu, psw);
671 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100672 }
673 case KVM_S390_INITIAL_RESET:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300674 r = kvm_arch_vcpu_ioctl_initial_reset(vcpu);
675 break;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100676 default:
Avi Kivitybc923cc2010-05-13 12:21:46 +0300677 r = -EINVAL;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100678 }
Avi Kivitybc923cc2010-05-13 12:21:46 +0300679 return r;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100680}
681
682/* Section: memory related */
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200683int kvm_arch_prepare_memory_region(struct kvm *kvm,
684 struct kvm_memory_slot *memslot,
685 struct kvm_memory_slot old,
686 struct kvm_userspace_memory_region *mem,
687 int user_alloc)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100688{
689 /* A few sanity checks. We can have exactly one memory slot which has
690 to start at guest virtual zero and which has to be located at a
691 page boundary in userland and which has to end at a page boundary.
692 The memory in userland is ok to be fragmented into various different
693 vmas. It is okay to mmap() and munmap() stuff in this slot after
694 doing this call at any time */
695
Christian Ehrhardt628eb9b2009-05-25 13:40:51 +0200696 if (mem->slot)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100697 return -EINVAL;
698
699 if (mem->guest_phys_addr)
700 return -EINVAL;
701
Carsten Otte598841c2011-07-24 10:48:21 +0200702 if (mem->userspace_addr & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100703 return -EINVAL;
704
Carsten Otte598841c2011-07-24 10:48:21 +0200705 if (mem->memory_size & 0xffffful)
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100706 return -EINVAL;
707
Carsten Otte2668dab2009-05-12 17:21:48 +0200708 if (!user_alloc)
709 return -EINVAL;
710
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200711 return 0;
712}
713
714void kvm_arch_commit_memory_region(struct kvm *kvm,
715 struct kvm_userspace_memory_region *mem,
716 struct kvm_memory_slot old,
717 int user_alloc)
718{
Carsten Ottef7850c92011-07-24 10:48:23 +0200719 int rc;
Marcelo Tosattif7784b82009-12-23 14:35:18 -0200720
Carsten Otte598841c2011-07-24 10:48:21 +0200721
722 rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
723 mem->guest_phys_addr, mem->memory_size);
724 if (rc)
Carsten Ottef7850c92011-07-24 10:48:23 +0200725 printk(KERN_WARNING "kvm-s390: failed to commit memory region\n");
Carsten Otte598841c2011-07-24 10:48:21 +0200726 return;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100727}
728
Marcelo Tosatti34d4cb82008-07-10 20:49:31 -0300729void kvm_arch_flush_shadow(struct kvm *kvm)
730{
731}
732
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100733static int __init kvm_s390_init(void)
734{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200735 int ret;
Avi Kivity0ee75be2010-04-28 15:39:01 +0300736 ret = kvm_init(NULL, sizeof(struct kvm_vcpu), 0, THIS_MODULE);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200737 if (ret)
738 return ret;
739
740 /*
741 * guests can ask for up to 255+1 double words, we need a full page
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300742 * to hold the maximum amount of facilities. On the other hand, we
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200743 * only set facilities that are known to work in KVM.
744 */
Heiko Carstensc2f0e8c2010-06-08 18:58:09 +0200745 facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200746 if (!facilities) {
747 kvm_exit();
748 return -ENOMEM;
749 }
Martin Schwidefsky14375bc2010-10-25 16:10:51 +0200750 memcpy(facilities, S390_lowcore.stfle_fac_list, 16);
Christian Borntraeger6d00d002010-10-25 16:10:48 +0200751 facilities[0] &= 0xff00fff3f47c0000ULL;
Christian Borntraeger9950f8b2011-06-06 14:14:39 +0200752 facilities[1] &= 0x201c000000000000ULL;
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200753 return 0;
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100754}
755
756static void __exit kvm_s390_exit(void)
757{
Christian Borntraegeref50f7a2009-06-23 17:24:07 +0200758 free_page((unsigned long) facilities);
Heiko Carstensb0c632d2008-03-25 18:47:20 +0100759 kvm_exit();
760}
761
762module_init(kvm_s390_init);
763module_exit(kvm_s390_exit);