diff options
Diffstat (limited to 'arch/s390')
-rw-r--r-- | arch/s390/Kconfig | 1 | ||||
-rw-r--r-- | arch/s390/hypfs/hypfs_dbfs.c | 2 | ||||
-rw-r--r-- | arch/s390/hypfs/inode.c | 2 | ||||
-rw-r--r-- | arch/s390/include/asm/elf.h | 5 | ||||
-rw-r--r-- | arch/s390/include/asm/irq.h | 1 | ||||
-rw-r--r-- | arch/s390/include/asm/kvm_host.h | 15 | ||||
-rw-r--r-- | arch/s390/kernel/debug.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/irq.c | 1 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 8 | ||||
-rw-r--r-- | arch/s390/kernel/traps.c | 2 | ||||
-rw-r--r-- | arch/s390/kvm/intercept.c | 45 | ||||
-rw-r--r-- | arch/s390/kvm/interrupt.c | 264 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.c | 50 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 46 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 316 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 10 | ||||
-rw-r--r-- | arch/s390/kvm/trace-s390.h | 26 | ||||
-rw-r--r-- | arch/s390/pci/pci_debug.c | 4 | ||||
-rw-r--r-- | arch/s390/pci/pci_msi.c | 3 |
19 files changed, 704 insertions, 99 deletions
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig index f09ae7b0b4c5..4b505370a1d5 100644 --- a/arch/s390/Kconfig +++ b/arch/s390/Kconfig | |||
@@ -134,6 +134,7 @@ config S390 | |||
134 | select HAVE_SYSCALL_WRAPPERS | 134 | select HAVE_SYSCALL_WRAPPERS |
135 | select HAVE_UID16 if 32BIT | 135 | select HAVE_UID16 if 32BIT |
136 | select HAVE_VIRT_CPU_ACCOUNTING | 136 | select HAVE_VIRT_CPU_ACCOUNTING |
137 | select HAVE_VIRT_TO_BUS | ||
137 | select INIT_ALL_POSSIBLE | 138 | select INIT_ALL_POSSIBLE |
138 | select KTIME_SCALAR if 32BIT | 139 | select KTIME_SCALAR if 32BIT |
139 | select MODULES_USE_ELF_RELA | 140 | select MODULES_USE_ELF_RELA |
diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c index 13e76dabbe8b..9fd4a40c6752 100644 --- a/arch/s390/hypfs/hypfs_dbfs.c +++ b/arch/s390/hypfs/hypfs_dbfs.c | |||
@@ -54,7 +54,7 @@ static ssize_t dbfs_read(struct file *file, char __user *buf, | |||
54 | if (*ppos != 0) | 54 | if (*ppos != 0) |
55 | return 0; | 55 | return 0; |
56 | 56 | ||
57 | df = file->f_path.dentry->d_inode->i_private; | 57 | df = file_inode(file)->i_private; |
58 | mutex_lock(&df->lock); | 58 | mutex_lock(&df->lock); |
59 | if (!df->data) { | 59 | if (!df->data) { |
60 | data = hypfs_dbfs_data_alloc(df); | 60 | data = hypfs_dbfs_data_alloc(df); |
diff --git a/arch/s390/hypfs/inode.c b/arch/s390/hypfs/inode.c index 06ea69bd387a..280ded8b79ba 100644 --- a/arch/s390/hypfs/inode.c +++ b/arch/s390/hypfs/inode.c | |||
@@ -119,7 +119,7 @@ static void hypfs_evict_inode(struct inode *inode) | |||
119 | 119 | ||
120 | static int hypfs_open(struct inode *inode, struct file *filp) | 120 | static int hypfs_open(struct inode *inode, struct file *filp) |
121 | { | 121 | { |
122 | char *data = filp->f_path.dentry->d_inode->i_private; | 122 | char *data = file_inode(filp)->i_private; |
123 | struct hypfs_sb_info *fs_info; | 123 | struct hypfs_sb_info *fs_info; |
124 | 124 | ||
125 | if (filp->f_mode & FMODE_WRITE) { | 125 | if (filp->f_mode & FMODE_WRITE) { |
diff --git a/arch/s390/include/asm/elf.h b/arch/s390/include/asm/elf.h index 178ff966a8ba..1bfdf24b85a2 100644 --- a/arch/s390/include/asm/elf.h +++ b/arch/s390/include/asm/elf.h | |||
@@ -180,10 +180,7 @@ extern unsigned long elf_hwcap; | |||
180 | extern char elf_platform[]; | 180 | extern char elf_platform[]; |
181 | #define ELF_PLATFORM (elf_platform) | 181 | #define ELF_PLATFORM (elf_platform) |
182 | 182 | ||
183 | #ifndef CONFIG_64BIT | 183 | #ifdef CONFIG_64BIT |
184 | #define SET_PERSONALITY(ex) \ | ||
185 | set_personality(PER_LINUX | (current->personality & (~PER_MASK))) | ||
186 | #else /* CONFIG_64BIT */ | ||
187 | #define SET_PERSONALITY(ex) \ | 184 | #define SET_PERSONALITY(ex) \ |
188 | do { \ | 185 | do { \ |
189 | if (personality(current->personality) != PER_LINUX32) \ | 186 | if (personality(current->personality) != PER_LINUX32) \ |
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h index 7def77302d63..87c17bfb2968 100644 --- a/arch/s390/include/asm/irq.h +++ b/arch/s390/include/asm/irq.h | |||
@@ -41,6 +41,7 @@ enum interruption_class { | |||
41 | IRQIO_CSC, | 41 | IRQIO_CSC, |
42 | IRQIO_PCI, | 42 | IRQIO_PCI, |
43 | IRQIO_MSI, | 43 | IRQIO_MSI, |
44 | IRQIO_VIR, | ||
44 | NMI_NMI, | 45 | NMI_NMI, |
45 | CPU_RST, | 46 | CPU_RST, |
46 | NR_ARCH_IRQS | 47 | NR_ARCH_IRQS |
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h index b7841546991f..16bd5d169cdb 100644 --- a/arch/s390/include/asm/kvm_host.h +++ b/arch/s390/include/asm/kvm_host.h | |||
@@ -20,9 +20,7 @@ | |||
20 | #include <asm/cpu.h> | 20 | #include <asm/cpu.h> |
21 | 21 | ||
22 | #define KVM_MAX_VCPUS 64 | 22 | #define KVM_MAX_VCPUS 64 |
23 | #define KVM_MEMORY_SLOTS 32 | 23 | #define KVM_USER_MEM_SLOTS 32 |
24 | /* memory slots that does not exposed to userspace */ | ||
25 | #define KVM_PRIVATE_MEM_SLOTS 4 | ||
26 | 24 | ||
27 | struct sca_entry { | 25 | struct sca_entry { |
28 | atomic_t scn; | 26 | atomic_t scn; |
@@ -76,8 +74,11 @@ struct kvm_s390_sie_block { | |||
76 | __u64 epoch; /* 0x0038 */ | 74 | __u64 epoch; /* 0x0038 */ |
77 | __u8 reserved40[4]; /* 0x0040 */ | 75 | __u8 reserved40[4]; /* 0x0040 */ |
78 | #define LCTL_CR0 0x8000 | 76 | #define LCTL_CR0 0x8000 |
77 | #define LCTL_CR6 0x0200 | ||
78 | #define LCTL_CR14 0x0002 | ||
79 | __u16 lctl; /* 0x0044 */ | 79 | __u16 lctl; /* 0x0044 */ |
80 | __s16 icpua; /* 0x0046 */ | 80 | __s16 icpua; /* 0x0046 */ |
81 | #define ICTL_LPSW 0x00400000 | ||
81 | __u32 ictl; /* 0x0048 */ | 82 | __u32 ictl; /* 0x0048 */ |
82 | __u32 eca; /* 0x004c */ | 83 | __u32 eca; /* 0x004c */ |
83 | __u8 icptcode; /* 0x0050 */ | 84 | __u8 icptcode; /* 0x0050 */ |
@@ -127,6 +128,7 @@ struct kvm_vcpu_stat { | |||
127 | u32 deliver_prefix_signal; | 128 | u32 deliver_prefix_signal; |
128 | u32 deliver_restart_signal; | 129 | u32 deliver_restart_signal; |
129 | u32 deliver_program_int; | 130 | u32 deliver_program_int; |
131 | u32 deliver_io_int; | ||
130 | u32 exit_wait_state; | 132 | u32 exit_wait_state; |
131 | u32 instruction_stidp; | 133 | u32 instruction_stidp; |
132 | u32 instruction_spx; | 134 | u32 instruction_spx; |
@@ -187,6 +189,11 @@ struct kvm_s390_emerg_info { | |||
187 | __u16 code; | 189 | __u16 code; |
188 | }; | 190 | }; |
189 | 191 | ||
192 | struct kvm_s390_mchk_info { | ||
193 | __u64 cr14; | ||
194 | __u64 mcic; | ||
195 | }; | ||
196 | |||
190 | struct kvm_s390_interrupt_info { | 197 | struct kvm_s390_interrupt_info { |
191 | struct list_head list; | 198 | struct list_head list; |
192 | u64 type; | 199 | u64 type; |
@@ -197,6 +204,7 @@ struct kvm_s390_interrupt_info { | |||
197 | struct kvm_s390_emerg_info emerg; | 204 | struct kvm_s390_emerg_info emerg; |
198 | struct kvm_s390_extcall_info extcall; | 205 | struct kvm_s390_extcall_info extcall; |
199 | struct kvm_s390_prefix_info prefix; | 206 | struct kvm_s390_prefix_info prefix; |
207 | struct kvm_s390_mchk_info mchk; | ||
200 | }; | 208 | }; |
201 | }; | 209 | }; |
202 | 210 | ||
@@ -254,6 +262,7 @@ struct kvm_arch{ | |||
254 | debug_info_t *dbf; | 262 | debug_info_t *dbf; |
255 | struct kvm_s390_float_interrupt float_int; | 263 | struct kvm_s390_float_interrupt float_int; |
256 | struct gmap *gmap; | 264 | struct gmap *gmap; |
265 | int css_support; | ||
257 | }; | 266 | }; |
258 | 267 | ||
259 | extern int sie64a(struct kvm_s390_sie_block *, u64 *); | 268 | extern int sie64a(struct kvm_s390_sie_block *, u64 *); |
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 09a94cd9debc..f1279dc2e1bc 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c | |||
@@ -611,7 +611,7 @@ debug_open(struct inode *inode, struct file *file) | |||
611 | debug_info_t *debug_info, *debug_info_snapshot; | 611 | debug_info_t *debug_info, *debug_info_snapshot; |
612 | 612 | ||
613 | mutex_lock(&debug_mutex); | 613 | mutex_lock(&debug_mutex); |
614 | debug_info = file->f_path.dentry->d_inode->i_private; | 614 | debug_info = file_inode(file)->i_private; |
615 | /* find debug view */ | 615 | /* find debug view */ |
616 | for (i = 0; i < DEBUG_MAX_VIEWS; i++) { | 616 | for (i = 0; i < DEBUG_MAX_VIEWS; i++) { |
617 | if (!debug_info->views[i]) | 617 | if (!debug_info->views[i]) |
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 9df824ea1667..1630f439cd2a 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c | |||
@@ -81,6 +81,7 @@ static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = { | |||
81 | [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, | 81 | [IRQIO_CSC] = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"}, |
82 | [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, | 82 | [IRQIO_PCI] = {.name = "PCI", .desc = "[I/O] PCI Interrupt" }, |
83 | [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, | 83 | [IRQIO_MSI] = {.name = "MSI", .desc = "[I/O] MSI Interrupt" }, |
84 | [IRQIO_VIR] = {.name = "VIR", .desc = "[I/O] Virtual I/O Devices"}, | ||
84 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, | 85 | [NMI_NMI] = {.name = "NMI", .desc = "[NMI] Machine Check"}, |
85 | [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, | 86 | [CPU_RST] = {.name = "RST", .desc = "[CPU] CPU Restart"}, |
86 | }; | 87 | }; |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index d1c7214e157c..3388b2b2a07d 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -354,7 +354,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
354 | { | 354 | { |
355 | struct kretprobe_instance *ri; | 355 | struct kretprobe_instance *ri; |
356 | struct hlist_head *head, empty_rp; | 356 | struct hlist_head *head, empty_rp; |
357 | struct hlist_node *node, *tmp; | 357 | struct hlist_node *tmp; |
358 | unsigned long flags, orig_ret_address; | 358 | unsigned long flags, orig_ret_address; |
359 | unsigned long trampoline_address; | 359 | unsigned long trampoline_address; |
360 | kprobe_opcode_t *correct_ret_addr; | 360 | kprobe_opcode_t *correct_ret_addr; |
@@ -379,7 +379,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
379 | orig_ret_address = 0; | 379 | orig_ret_address = 0; |
380 | correct_ret_addr = NULL; | 380 | correct_ret_addr = NULL; |
381 | trampoline_address = (unsigned long) &kretprobe_trampoline; | 381 | trampoline_address = (unsigned long) &kretprobe_trampoline; |
382 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 382 | hlist_for_each_entry_safe(ri, tmp, head, hlist) { |
383 | if (ri->task != current) | 383 | if (ri->task != current) |
384 | /* another task is sharing our hash bucket */ | 384 | /* another task is sharing our hash bucket */ |
385 | continue; | 385 | continue; |
@@ -398,7 +398,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
398 | kretprobe_assert(ri, orig_ret_address, trampoline_address); | 398 | kretprobe_assert(ri, orig_ret_address, trampoline_address); |
399 | 399 | ||
400 | correct_ret_addr = ri->ret_addr; | 400 | correct_ret_addr = ri->ret_addr; |
401 | hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { | 401 | hlist_for_each_entry_safe(ri, tmp, head, hlist) { |
402 | if (ri->task != current) | 402 | if (ri->task != current) |
403 | /* another task is sharing our hash bucket */ | 403 | /* another task is sharing our hash bucket */ |
404 | continue; | 404 | continue; |
@@ -427,7 +427,7 @@ static int __kprobes trampoline_probe_handler(struct kprobe *p, | |||
427 | kretprobe_hash_unlock(current, &flags); | 427 | kretprobe_hash_unlock(current, &flags); |
428 | preempt_enable_no_resched(); | 428 | preempt_enable_no_resched(); |
429 | 429 | ||
430 | hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) { | 430 | hlist_for_each_entry_safe(ri, tmp, &empty_rp, hlist) { |
431 | hlist_del(&ri->hlist); | 431 | hlist_del(&ri->hlist); |
432 | kfree(ri); | 432 | kfree(ri); |
433 | } | 433 | } |
diff --git a/arch/s390/kernel/traps.c b/arch/s390/kernel/traps.c index 70ecfc5fe8f0..13dd63fba367 100644 --- a/arch/s390/kernel/traps.c +++ b/arch/s390/kernel/traps.c | |||
@@ -271,7 +271,7 @@ void die(struct pt_regs *regs, const char *str) | |||
271 | print_modules(); | 271 | print_modules(); |
272 | show_regs(regs); | 272 | show_regs(regs); |
273 | bust_spinlocks(0); | 273 | bust_spinlocks(0); |
274 | add_taint(TAINT_DIE); | 274 | add_taint(TAINT_DIE, LOCKDEP_NOW_UNRELIABLE); |
275 | spin_unlock_irq(&die_lock); | 275 | spin_unlock_irq(&die_lock); |
276 | if (in_interrupt()) | 276 | if (in_interrupt()) |
277 | panic("Fatal exception in interrupt"); | 277 | panic("Fatal exception in interrupt"); |
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c index 22798ec33fd1..f26ff1e31bdb 100644 --- a/arch/s390/kvm/intercept.c +++ b/arch/s390/kvm/intercept.c | |||
@@ -26,27 +26,20 @@ static int handle_lctlg(struct kvm_vcpu *vcpu) | |||
26 | { | 26 | { |
27 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | 27 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; |
28 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | 28 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; |
29 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
30 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) + | ||
31 | ((vcpu->arch.sie_block->ipb & 0xff00) << 4); | ||
32 | u64 useraddr; | 29 | u64 useraddr; |
33 | int reg, rc; | 30 | int reg, rc; |
34 | 31 | ||
35 | vcpu->stat.instruction_lctlg++; | 32 | vcpu->stat.instruction_lctlg++; |
36 | if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f) | ||
37 | return -EOPNOTSUPP; | ||
38 | 33 | ||
39 | useraddr = disp2; | 34 | useraddr = kvm_s390_get_base_disp_rsy(vcpu); |
40 | if (base2) | ||
41 | useraddr += vcpu->run->s.regs.gprs[base2]; | ||
42 | 35 | ||
43 | if (useraddr & 7) | 36 | if (useraddr & 7) |
44 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 37 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
45 | 38 | ||
46 | reg = reg1; | 39 | reg = reg1; |
47 | 40 | ||
48 | VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, | 41 | VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, |
49 | disp2); | 42 | useraddr); |
50 | trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr); | 43 | trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr); |
51 | 44 | ||
52 | do { | 45 | do { |
@@ -68,23 +61,19 @@ static int handle_lctl(struct kvm_vcpu *vcpu) | |||
68 | { | 61 | { |
69 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | 62 | int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; |
70 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; | 63 | int reg3 = vcpu->arch.sie_block->ipa & 0x000f; |
71 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
72 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
73 | u64 useraddr; | 64 | u64 useraddr; |
74 | u32 val = 0; | 65 | u32 val = 0; |
75 | int reg, rc; | 66 | int reg, rc; |
76 | 67 | ||
77 | vcpu->stat.instruction_lctl++; | 68 | vcpu->stat.instruction_lctl++; |
78 | 69 | ||
79 | useraddr = disp2; | 70 | useraddr = kvm_s390_get_base_disp_rs(vcpu); |
80 | if (base2) | ||
81 | useraddr += vcpu->run->s.regs.gprs[base2]; | ||
82 | 71 | ||
83 | if (useraddr & 3) | 72 | if (useraddr & 3) |
84 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 73 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
85 | 74 | ||
86 | VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, | 75 | VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, |
87 | disp2); | 76 | useraddr); |
88 | trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr); | 77 | trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr); |
89 | 78 | ||
90 | reg = reg1; | 79 | reg = reg1; |
@@ -104,14 +93,31 @@ static int handle_lctl(struct kvm_vcpu *vcpu) | |||
104 | return 0; | 93 | return 0; |
105 | } | 94 | } |
106 | 95 | ||
107 | static intercept_handler_t instruction_handlers[256] = { | 96 | static const intercept_handler_t eb_handlers[256] = { |
97 | [0x2f] = handle_lctlg, | ||
98 | [0x8a] = kvm_s390_handle_priv_eb, | ||
99 | }; | ||
100 | |||
101 | static int handle_eb(struct kvm_vcpu *vcpu) | ||
102 | { | ||
103 | intercept_handler_t handler; | ||
104 | |||
105 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; | ||
106 | if (handler) | ||
107 | return handler(vcpu); | ||
108 | return -EOPNOTSUPP; | ||
109 | } | ||
110 | |||
111 | static const intercept_handler_t instruction_handlers[256] = { | ||
108 | [0x01] = kvm_s390_handle_01, | 112 | [0x01] = kvm_s390_handle_01, |
113 | [0x82] = kvm_s390_handle_lpsw, | ||
109 | [0x83] = kvm_s390_handle_diag, | 114 | [0x83] = kvm_s390_handle_diag, |
110 | [0xae] = kvm_s390_handle_sigp, | 115 | [0xae] = kvm_s390_handle_sigp, |
111 | [0xb2] = kvm_s390_handle_b2, | 116 | [0xb2] = kvm_s390_handle_b2, |
112 | [0xb7] = handle_lctl, | 117 | [0xb7] = handle_lctl, |
118 | [0xb9] = kvm_s390_handle_b9, | ||
113 | [0xe5] = kvm_s390_handle_e5, | 119 | [0xe5] = kvm_s390_handle_e5, |
114 | [0xeb] = handle_lctlg, | 120 | [0xeb] = handle_eb, |
115 | }; | 121 | }; |
116 | 122 | ||
117 | static int handle_noop(struct kvm_vcpu *vcpu) | 123 | static int handle_noop(struct kvm_vcpu *vcpu) |
@@ -258,6 +264,7 @@ static const intercept_handler_t intercept_funcs[] = { | |||
258 | [0x0C >> 2] = handle_instruction_and_prog, | 264 | [0x0C >> 2] = handle_instruction_and_prog, |
259 | [0x10 >> 2] = handle_noop, | 265 | [0x10 >> 2] = handle_noop, |
260 | [0x14 >> 2] = handle_noop, | 266 | [0x14 >> 2] = handle_noop, |
267 | [0x18 >> 2] = handle_noop, | ||
261 | [0x1C >> 2] = kvm_s390_handle_wait, | 268 | [0x1C >> 2] = kvm_s390_handle_wait, |
262 | [0x20 >> 2] = handle_validity, | 269 | [0x20 >> 2] = handle_validity, |
263 | [0x28 >> 2] = handle_stop, | 270 | [0x28 >> 2] = handle_stop, |
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c index 87418b50f21c..37116a77cb4b 100644 --- a/arch/s390/kvm/interrupt.c +++ b/arch/s390/kvm/interrupt.c | |||
@@ -21,11 +21,31 @@ | |||
21 | #include "gaccess.h" | 21 | #include "gaccess.h" |
22 | #include "trace-s390.h" | 22 | #include "trace-s390.h" |
23 | 23 | ||
24 | #define IOINT_SCHID_MASK 0x0000ffff | ||
25 | #define IOINT_SSID_MASK 0x00030000 | ||
26 | #define IOINT_CSSID_MASK 0x03fc0000 | ||
27 | #define IOINT_AI_MASK 0x04000000 | ||
28 | |||
29 | static int is_ioint(u64 type) | ||
30 | { | ||
31 | return ((type & 0xfffe0000u) != 0xfffe0000u); | ||
32 | } | ||
33 | |||
24 | static int psw_extint_disabled(struct kvm_vcpu *vcpu) | 34 | static int psw_extint_disabled(struct kvm_vcpu *vcpu) |
25 | { | 35 | { |
26 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT); | 36 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_EXT); |
27 | } | 37 | } |
28 | 38 | ||
39 | static int psw_ioint_disabled(struct kvm_vcpu *vcpu) | ||
40 | { | ||
41 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_IO); | ||
42 | } | ||
43 | |||
44 | static int psw_mchk_disabled(struct kvm_vcpu *vcpu) | ||
45 | { | ||
46 | return !(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_MCHECK); | ||
47 | } | ||
48 | |||
29 | static int psw_interrupts_disabled(struct kvm_vcpu *vcpu) | 49 | static int psw_interrupts_disabled(struct kvm_vcpu *vcpu) |
30 | { | 50 | { |
31 | if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) || | 51 | if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PER) || |
@@ -35,6 +55,13 @@ static int psw_interrupts_disabled(struct kvm_vcpu *vcpu) | |||
35 | return 1; | 55 | return 1; |
36 | } | 56 | } |
37 | 57 | ||
58 | static u64 int_word_to_isc_bits(u32 int_word) | ||
59 | { | ||
60 | u8 isc = (int_word & 0x38000000) >> 27; | ||
61 | |||
62 | return (0x80 >> isc) << 24; | ||
63 | } | ||
64 | |||
38 | static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | 65 | static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, |
39 | struct kvm_s390_interrupt_info *inti) | 66 | struct kvm_s390_interrupt_info *inti) |
40 | { | 67 | { |
@@ -67,7 +94,22 @@ static int __interrupt_is_deliverable(struct kvm_vcpu *vcpu, | |||
67 | case KVM_S390_SIGP_SET_PREFIX: | 94 | case KVM_S390_SIGP_SET_PREFIX: |
68 | case KVM_S390_RESTART: | 95 | case KVM_S390_RESTART: |
69 | return 1; | 96 | return 1; |
97 | case KVM_S390_MCHK: | ||
98 | if (psw_mchk_disabled(vcpu)) | ||
99 | return 0; | ||
100 | if (vcpu->arch.sie_block->gcr[14] & inti->mchk.cr14) | ||
101 | return 1; | ||
102 | return 0; | ||
103 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
104 | if (psw_ioint_disabled(vcpu)) | ||
105 | return 0; | ||
106 | if (vcpu->arch.sie_block->gcr[6] & | ||
107 | int_word_to_isc_bits(inti->io.io_int_word)) | ||
108 | return 1; | ||
109 | return 0; | ||
70 | default: | 110 | default: |
111 | printk(KERN_WARNING "illegal interrupt type %llx\n", | ||
112 | inti->type); | ||
71 | BUG(); | 113 | BUG(); |
72 | } | 114 | } |
73 | return 0; | 115 | return 0; |
@@ -93,6 +135,7 @@ static void __reset_intercept_indicators(struct kvm_vcpu *vcpu) | |||
93 | CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT, | 135 | CPUSTAT_IO_INT | CPUSTAT_EXT_INT | CPUSTAT_STOP_INT, |
94 | &vcpu->arch.sie_block->cpuflags); | 136 | &vcpu->arch.sie_block->cpuflags); |
95 | vcpu->arch.sie_block->lctl = 0x0000; | 137 | vcpu->arch.sie_block->lctl = 0x0000; |
138 | vcpu->arch.sie_block->ictl &= ~ICTL_LPSW; | ||
96 | } | 139 | } |
97 | 140 | ||
98 | static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) | 141 | static void __set_cpuflag(struct kvm_vcpu *vcpu, u32 flag) |
@@ -116,6 +159,18 @@ static void __set_intercept_indicator(struct kvm_vcpu *vcpu, | |||
116 | case KVM_S390_SIGP_STOP: | 159 | case KVM_S390_SIGP_STOP: |
117 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); | 160 | __set_cpuflag(vcpu, CPUSTAT_STOP_INT); |
118 | break; | 161 | break; |
162 | case KVM_S390_MCHK: | ||
163 | if (psw_mchk_disabled(vcpu)) | ||
164 | vcpu->arch.sie_block->ictl |= ICTL_LPSW; | ||
165 | else | ||
166 | vcpu->arch.sie_block->lctl |= LCTL_CR14; | ||
167 | break; | ||
168 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
169 | if (psw_ioint_disabled(vcpu)) | ||
170 | __set_cpuflag(vcpu, CPUSTAT_IO_INT); | ||
171 | else | ||
172 | vcpu->arch.sie_block->lctl |= LCTL_CR6; | ||
173 | break; | ||
119 | default: | 174 | default: |
120 | BUG(); | 175 | BUG(); |
121 | } | 176 | } |
@@ -297,6 +352,73 @@ static void __do_deliver_interrupt(struct kvm_vcpu *vcpu, | |||
297 | exception = 1; | 352 | exception = 1; |
298 | break; | 353 | break; |
299 | 354 | ||
355 | case KVM_S390_MCHK: | ||
356 | VCPU_EVENT(vcpu, 4, "interrupt: machine check mcic=%llx", | ||
357 | inti->mchk.mcic); | ||
358 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
359 | inti->mchk.cr14, | ||
360 | inti->mchk.mcic); | ||
361 | rc = kvm_s390_vcpu_store_status(vcpu, | ||
362 | KVM_S390_STORE_STATUS_PREFIXED); | ||
363 | if (rc == -EFAULT) | ||
364 | exception = 1; | ||
365 | |||
366 | rc = put_guest_u64(vcpu, __LC_MCCK_CODE, inti->mchk.mcic); | ||
367 | if (rc == -EFAULT) | ||
368 | exception = 1; | ||
369 | |||
370 | rc = copy_to_guest(vcpu, __LC_MCK_OLD_PSW, | ||
371 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
372 | if (rc == -EFAULT) | ||
373 | exception = 1; | ||
374 | |||
375 | rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, | ||
376 | __LC_MCK_NEW_PSW, sizeof(psw_t)); | ||
377 | if (rc == -EFAULT) | ||
378 | exception = 1; | ||
379 | break; | ||
380 | |||
381 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
382 | { | ||
383 | __u32 param0 = ((__u32)inti->io.subchannel_id << 16) | | ||
384 | inti->io.subchannel_nr; | ||
385 | __u64 param1 = ((__u64)inti->io.io_int_parm << 32) | | ||
386 | inti->io.io_int_word; | ||
387 | VCPU_EVENT(vcpu, 4, "interrupt: I/O %llx", inti->type); | ||
388 | vcpu->stat.deliver_io_int++; | ||
389 | trace_kvm_s390_deliver_interrupt(vcpu->vcpu_id, inti->type, | ||
390 | param0, param1); | ||
391 | rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_ID, | ||
392 | inti->io.subchannel_id); | ||
393 | if (rc == -EFAULT) | ||
394 | exception = 1; | ||
395 | |||
396 | rc = put_guest_u16(vcpu, __LC_SUBCHANNEL_NR, | ||
397 | inti->io.subchannel_nr); | ||
398 | if (rc == -EFAULT) | ||
399 | exception = 1; | ||
400 | |||
401 | rc = put_guest_u32(vcpu, __LC_IO_INT_PARM, | ||
402 | inti->io.io_int_parm); | ||
403 | if (rc == -EFAULT) | ||
404 | exception = 1; | ||
405 | |||
406 | rc = put_guest_u32(vcpu, __LC_IO_INT_WORD, | ||
407 | inti->io.io_int_word); | ||
408 | if (rc == -EFAULT) | ||
409 | exception = 1; | ||
410 | |||
411 | rc = copy_to_guest(vcpu, __LC_IO_OLD_PSW, | ||
412 | &vcpu->arch.sie_block->gpsw, sizeof(psw_t)); | ||
413 | if (rc == -EFAULT) | ||
414 | exception = 1; | ||
415 | |||
416 | rc = copy_from_guest(vcpu, &vcpu->arch.sie_block->gpsw, | ||
417 | __LC_IO_NEW_PSW, sizeof(psw_t)); | ||
418 | if (rc == -EFAULT) | ||
419 | exception = 1; | ||
420 | break; | ||
421 | } | ||
300 | default: | 422 | default: |
301 | BUG(); | 423 | BUG(); |
302 | } | 424 | } |
@@ -518,6 +640,61 @@ void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu) | |||
518 | } | 640 | } |
519 | } | 641 | } |
520 | 642 | ||
643 | void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu) | ||
644 | { | ||
645 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | ||
646 | struct kvm_s390_float_interrupt *fi = vcpu->arch.local_int.float_int; | ||
647 | struct kvm_s390_interrupt_info *n, *inti = NULL; | ||
648 | int deliver; | ||
649 | |||
650 | __reset_intercept_indicators(vcpu); | ||
651 | if (atomic_read(&li->active)) { | ||
652 | do { | ||
653 | deliver = 0; | ||
654 | spin_lock_bh(&li->lock); | ||
655 | list_for_each_entry_safe(inti, n, &li->list, list) { | ||
656 | if ((inti->type == KVM_S390_MCHK) && | ||
657 | __interrupt_is_deliverable(vcpu, inti)) { | ||
658 | list_del(&inti->list); | ||
659 | deliver = 1; | ||
660 | break; | ||
661 | } | ||
662 | __set_intercept_indicator(vcpu, inti); | ||
663 | } | ||
664 | if (list_empty(&li->list)) | ||
665 | atomic_set(&li->active, 0); | ||
666 | spin_unlock_bh(&li->lock); | ||
667 | if (deliver) { | ||
668 | __do_deliver_interrupt(vcpu, inti); | ||
669 | kfree(inti); | ||
670 | } | ||
671 | } while (deliver); | ||
672 | } | ||
673 | |||
674 | if (atomic_read(&fi->active)) { | ||
675 | do { | ||
676 | deliver = 0; | ||
677 | spin_lock(&fi->lock); | ||
678 | list_for_each_entry_safe(inti, n, &fi->list, list) { | ||
679 | if ((inti->type == KVM_S390_MCHK) && | ||
680 | __interrupt_is_deliverable(vcpu, inti)) { | ||
681 | list_del(&inti->list); | ||
682 | deliver = 1; | ||
683 | break; | ||
684 | } | ||
685 | __set_intercept_indicator(vcpu, inti); | ||
686 | } | ||
687 | if (list_empty(&fi->list)) | ||
688 | atomic_set(&fi->active, 0); | ||
689 | spin_unlock(&fi->lock); | ||
690 | if (deliver) { | ||
691 | __do_deliver_interrupt(vcpu, inti); | ||
692 | kfree(inti); | ||
693 | } | ||
694 | } while (deliver); | ||
695 | } | ||
696 | } | ||
697 | |||
521 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) | 698 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) |
522 | { | 699 | { |
523 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; | 700 | struct kvm_s390_local_interrupt *li = &vcpu->arch.local_int; |
@@ -540,12 +717,50 @@ int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code) | |||
540 | return 0; | 717 | return 0; |
541 | } | 718 | } |
542 | 719 | ||
720 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | ||
721 | u64 cr6, u64 schid) | ||
722 | { | ||
723 | struct kvm_s390_float_interrupt *fi; | ||
724 | struct kvm_s390_interrupt_info *inti, *iter; | ||
725 | |||
726 | if ((!schid && !cr6) || (schid && cr6)) | ||
727 | return NULL; | ||
728 | mutex_lock(&kvm->lock); | ||
729 | fi = &kvm->arch.float_int; | ||
730 | spin_lock(&fi->lock); | ||
731 | inti = NULL; | ||
732 | list_for_each_entry(iter, &fi->list, list) { | ||
733 | if (!is_ioint(iter->type)) | ||
734 | continue; | ||
735 | if (cr6 && | ||
736 | ((cr6 & int_word_to_isc_bits(iter->io.io_int_word)) == 0)) | ||
737 | continue; | ||
738 | if (schid) { | ||
739 | if (((schid & 0x00000000ffff0000) >> 16) != | ||
740 | iter->io.subchannel_id) | ||
741 | continue; | ||
742 | if ((schid & 0x000000000000ffff) != | ||
743 | iter->io.subchannel_nr) | ||
744 | continue; | ||
745 | } | ||
746 | inti = iter; | ||
747 | break; | ||
748 | } | ||
749 | if (inti) | ||
750 | list_del_init(&inti->list); | ||
751 | if (list_empty(&fi->list)) | ||
752 | atomic_set(&fi->active, 0); | ||
753 | spin_unlock(&fi->lock); | ||
754 | mutex_unlock(&kvm->lock); | ||
755 | return inti; | ||
756 | } | ||
757 | |||
543 | int kvm_s390_inject_vm(struct kvm *kvm, | 758 | int kvm_s390_inject_vm(struct kvm *kvm, |
544 | struct kvm_s390_interrupt *s390int) | 759 | struct kvm_s390_interrupt *s390int) |
545 | { | 760 | { |
546 | struct kvm_s390_local_interrupt *li; | 761 | struct kvm_s390_local_interrupt *li; |
547 | struct kvm_s390_float_interrupt *fi; | 762 | struct kvm_s390_float_interrupt *fi; |
548 | struct kvm_s390_interrupt_info *inti; | 763 | struct kvm_s390_interrupt_info *inti, *iter; |
549 | int sigcpu; | 764 | int sigcpu; |
550 | 765 | ||
551 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); | 766 | inti = kzalloc(sizeof(*inti), GFP_KERNEL); |
@@ -569,6 +784,29 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
569 | case KVM_S390_SIGP_STOP: | 784 | case KVM_S390_SIGP_STOP: |
570 | case KVM_S390_INT_EXTERNAL_CALL: | 785 | case KVM_S390_INT_EXTERNAL_CALL: |
571 | case KVM_S390_INT_EMERGENCY: | 786 | case KVM_S390_INT_EMERGENCY: |
787 | kfree(inti); | ||
788 | return -EINVAL; | ||
789 | case KVM_S390_MCHK: | ||
790 | VM_EVENT(kvm, 5, "inject: machine check parm64:%llx", | ||
791 | s390int->parm64); | ||
792 | inti->type = s390int->type; | ||
793 | inti->mchk.cr14 = s390int->parm; /* upper bits are not used */ | ||
794 | inti->mchk.mcic = s390int->parm64; | ||
795 | break; | ||
796 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
797 | if (s390int->type & IOINT_AI_MASK) | ||
798 | VM_EVENT(kvm, 5, "%s", "inject: I/O (AI)"); | ||
799 | else | ||
800 | VM_EVENT(kvm, 5, "inject: I/O css %x ss %x schid %04x", | ||
801 | s390int->type & IOINT_CSSID_MASK, | ||
802 | s390int->type & IOINT_SSID_MASK, | ||
803 | s390int->type & IOINT_SCHID_MASK); | ||
804 | inti->type = s390int->type; | ||
805 | inti->io.subchannel_id = s390int->parm >> 16; | ||
806 | inti->io.subchannel_nr = s390int->parm & 0x0000ffffu; | ||
807 | inti->io.io_int_parm = s390int->parm64 >> 32; | ||
808 | inti->io.io_int_word = s390int->parm64 & 0x00000000ffffffffull; | ||
809 | break; | ||
572 | default: | 810 | default: |
573 | kfree(inti); | 811 | kfree(inti); |
574 | return -EINVAL; | 812 | return -EINVAL; |
@@ -579,7 +817,22 @@ int kvm_s390_inject_vm(struct kvm *kvm, | |||
579 | mutex_lock(&kvm->lock); | 817 | mutex_lock(&kvm->lock); |
580 | fi = &kvm->arch.float_int; | 818 | fi = &kvm->arch.float_int; |
581 | spin_lock(&fi->lock); | 819 | spin_lock(&fi->lock); |
582 | list_add_tail(&inti->list, &fi->list); | 820 | if (!is_ioint(inti->type)) |
821 | list_add_tail(&inti->list, &fi->list); | ||
822 | else { | ||
823 | u64 isc_bits = int_word_to_isc_bits(inti->io.io_int_word); | ||
824 | |||
825 | /* Keep I/O interrupts sorted in isc order. */ | ||
826 | list_for_each_entry(iter, &fi->list, list) { | ||
827 | if (!is_ioint(iter->type)) | ||
828 | continue; | ||
829 | if (int_word_to_isc_bits(iter->io.io_int_word) | ||
830 | <= isc_bits) | ||
831 | continue; | ||
832 | break; | ||
833 | } | ||
834 | list_add_tail(&inti->list, &iter->list); | ||
835 | } | ||
583 | atomic_set(&fi->active, 1); | 836 | atomic_set(&fi->active, 1); |
584 | sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); | 837 | sigcpu = find_first_bit(fi->idle_mask, KVM_MAX_VCPUS); |
585 | if (sigcpu == KVM_MAX_VCPUS) { | 838 | if (sigcpu == KVM_MAX_VCPUS) { |
@@ -651,8 +904,15 @@ int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | |||
651 | inti->type = s390int->type; | 904 | inti->type = s390int->type; |
652 | inti->emerg.code = s390int->parm; | 905 | inti->emerg.code = s390int->parm; |
653 | break; | 906 | break; |
907 | case KVM_S390_MCHK: | ||
908 | VCPU_EVENT(vcpu, 5, "inject: machine check parm64:%llx", | ||
909 | s390int->parm64); | ||
910 | inti->type = s390int->type; | ||
911 | inti->mchk.mcic = s390int->parm64; | ||
912 | break; | ||
654 | case KVM_S390_INT_VIRTIO: | 913 | case KVM_S390_INT_VIRTIO: |
655 | case KVM_S390_INT_SERVICE: | 914 | case KVM_S390_INT_SERVICE: |
915 | case KVM_S390_INT_IO_MIN...KVM_S390_INT_IO_MAX: | ||
656 | default: | 916 | default: |
657 | kfree(inti); | 917 | kfree(inti); |
658 | return -EINVAL; | 918 | return -EINVAL; |
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index 2923781590a6..4cf35a0a79e7 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c | |||
@@ -140,6 +140,8 @@ int kvm_dev_ioctl_check_extension(long ext) | |||
140 | #endif | 140 | #endif |
141 | case KVM_CAP_SYNC_REGS: | 141 | case KVM_CAP_SYNC_REGS: |
142 | case KVM_CAP_ONE_REG: | 142 | case KVM_CAP_ONE_REG: |
143 | case KVM_CAP_ENABLE_CAP: | ||
144 | case KVM_CAP_S390_CSS_SUPPORT: | ||
143 | r = 1; | 145 | r = 1; |
144 | break; | 146 | break; |
145 | case KVM_CAP_NR_VCPUS: | 147 | case KVM_CAP_NR_VCPUS: |
@@ -234,6 +236,9 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type) | |||
234 | if (!kvm->arch.gmap) | 236 | if (!kvm->arch.gmap) |
235 | goto out_nogmap; | 237 | goto out_nogmap; |
236 | } | 238 | } |
239 | |||
240 | kvm->arch.css_support = 0; | ||
241 | |||
237 | return 0; | 242 | return 0; |
238 | out_nogmap: | 243 | out_nogmap: |
239 | debug_unregister(kvm->arch.dbf); | 244 | debug_unregister(kvm->arch.dbf); |
@@ -659,6 +664,7 @@ rerun_vcpu: | |||
659 | case KVM_EXIT_INTR: | 664 | case KVM_EXIT_INTR: |
660 | case KVM_EXIT_S390_RESET: | 665 | case KVM_EXIT_S390_RESET: |
661 | case KVM_EXIT_S390_UCONTROL: | 666 | case KVM_EXIT_S390_UCONTROL: |
667 | case KVM_EXIT_S390_TSCH: | ||
662 | break; | 668 | break; |
663 | default: | 669 | default: |
664 | BUG(); | 670 | BUG(); |
@@ -766,6 +772,14 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | |||
766 | } else | 772 | } else |
767 | prefix = 0; | 773 | prefix = 0; |
768 | 774 | ||
775 | /* | ||
776 | * The guest FPRS and ACRS are in the host FPRS/ACRS due to the lazy | ||
777 | * copying in vcpu load/put. Lets update our copies before we save | ||
778 | * it into the save area | ||
779 | */ | ||
780 | save_fp_regs(&vcpu->arch.guest_fpregs); | ||
781 | save_access_regs(vcpu->run->s.regs.acrs); | ||
782 | |||
769 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), | 783 | if (__guestcopy(vcpu, addr + offsetof(struct save_area, fp_regs), |
770 | vcpu->arch.guest_fpregs.fprs, 128, prefix)) | 784 | vcpu->arch.guest_fpregs.fprs, 128, prefix)) |
771 | return -EFAULT; | 785 | return -EFAULT; |
@@ -810,6 +824,29 @@ int kvm_s390_vcpu_store_status(struct kvm_vcpu *vcpu, unsigned long addr) | |||
810 | return 0; | 824 | return 0; |
811 | } | 825 | } |
812 | 826 | ||
827 | static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu, | ||
828 | struct kvm_enable_cap *cap) | ||
829 | { | ||
830 | int r; | ||
831 | |||
832 | if (cap->flags) | ||
833 | return -EINVAL; | ||
834 | |||
835 | switch (cap->cap) { | ||
836 | case KVM_CAP_S390_CSS_SUPPORT: | ||
837 | if (!vcpu->kvm->arch.css_support) { | ||
838 | vcpu->kvm->arch.css_support = 1; | ||
839 | trace_kvm_s390_enable_css(vcpu->kvm); | ||
840 | } | ||
841 | r = 0; | ||
842 | break; | ||
843 | default: | ||
844 | r = -EINVAL; | ||
845 | break; | ||
846 | } | ||
847 | return r; | ||
848 | } | ||
849 | |||
813 | long kvm_arch_vcpu_ioctl(struct file *filp, | 850 | long kvm_arch_vcpu_ioctl(struct file *filp, |
814 | unsigned int ioctl, unsigned long arg) | 851 | unsigned int ioctl, unsigned long arg) |
815 | { | 852 | { |
@@ -896,6 +933,15 @@ long kvm_arch_vcpu_ioctl(struct file *filp, | |||
896 | r = 0; | 933 | r = 0; |
897 | break; | 934 | break; |
898 | } | 935 | } |
936 | case KVM_ENABLE_CAP: | ||
937 | { | ||
938 | struct kvm_enable_cap cap; | ||
939 | r = -EFAULT; | ||
940 | if (copy_from_user(&cap, argp, sizeof(cap))) | ||
941 | break; | ||
942 | r = kvm_vcpu_ioctl_enable_cap(vcpu, &cap); | ||
943 | break; | ||
944 | } | ||
899 | default: | 945 | default: |
900 | r = -ENOTTY; | 946 | r = -ENOTTY; |
901 | } | 947 | } |
@@ -930,7 +976,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, | |||
930 | struct kvm_memory_slot *memslot, | 976 | struct kvm_memory_slot *memslot, |
931 | struct kvm_memory_slot old, | 977 | struct kvm_memory_slot old, |
932 | struct kvm_userspace_memory_region *mem, | 978 | struct kvm_userspace_memory_region *mem, |
933 | int user_alloc) | 979 | bool user_alloc) |
934 | { | 980 | { |
935 | /* A few sanity checks. We can have exactly one memory slot which has | 981 | /* A few sanity checks. We can have exactly one memory slot which has |
936 | to start at guest virtual zero and which has to be located at a | 982 | to start at guest virtual zero and which has to be located at a |
@@ -960,7 +1006,7 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm, | |||
960 | void kvm_arch_commit_memory_region(struct kvm *kvm, | 1006 | void kvm_arch_commit_memory_region(struct kvm *kvm, |
961 | struct kvm_userspace_memory_region *mem, | 1007 | struct kvm_userspace_memory_region *mem, |
962 | struct kvm_memory_slot old, | 1008 | struct kvm_memory_slot old, |
963 | int user_alloc) | 1009 | bool user_alloc) |
964 | { | 1010 | { |
965 | int rc; | 1011 | int rc; |
966 | 1012 | ||
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h index d75bc5e92c5b..4d89d64a8161 100644 --- a/arch/s390/kvm/kvm-s390.h +++ b/arch/s390/kvm/kvm-s390.h | |||
@@ -65,21 +65,67 @@ static inline void kvm_s390_set_prefix(struct kvm_vcpu *vcpu, u32 prefix) | |||
65 | vcpu->arch.sie_block->ihcpu = 0xffff; | 65 | vcpu->arch.sie_block->ihcpu = 0xffff; |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu) | ||
69 | { | ||
70 | u32 base2 = vcpu->arch.sie_block->ipb >> 28; | ||
71 | u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
72 | |||
73 | return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; | ||
74 | } | ||
75 | |||
76 | static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu, | ||
77 | u64 *address1, u64 *address2) | ||
78 | { | ||
79 | u32 base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28; | ||
80 | u32 disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16; | ||
81 | u32 base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12; | ||
82 | u32 disp2 = vcpu->arch.sie_block->ipb & 0x0fff; | ||
83 | |||
84 | *address1 = (base1 ? vcpu->run->s.regs.gprs[base1] : 0) + disp1; | ||
85 | *address2 = (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; | ||
86 | } | ||
87 | |||
88 | static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu) | ||
89 | { | ||
90 | u32 base2 = vcpu->arch.sie_block->ipb >> 28; | ||
91 | u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) + | ||
92 | ((vcpu->arch.sie_block->ipb & 0xff00) << 4); | ||
93 | /* The displacement is a 20bit _SIGNED_ value */ | ||
94 | if (disp2 & 0x80000) | ||
95 | disp2+=0xfff00000; | ||
96 | |||
97 | return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + (long)(int)disp2; | ||
98 | } | ||
99 | |||
100 | static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu) | ||
101 | { | ||
102 | u32 base2 = vcpu->arch.sie_block->ipb >> 28; | ||
103 | u32 disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
104 | |||
105 | return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2; | ||
106 | } | ||
107 | |||
68 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); | 108 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); |
69 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); | 109 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); |
70 | void kvm_s390_tasklet(unsigned long parm); | 110 | void kvm_s390_tasklet(unsigned long parm); |
71 | void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); | 111 | void kvm_s390_deliver_pending_interrupts(struct kvm_vcpu *vcpu); |
112 | void kvm_s390_deliver_pending_machine_checks(struct kvm_vcpu *vcpu); | ||
72 | int kvm_s390_inject_vm(struct kvm *kvm, | 113 | int kvm_s390_inject_vm(struct kvm *kvm, |
73 | struct kvm_s390_interrupt *s390int); | 114 | struct kvm_s390_interrupt *s390int); |
74 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, | 115 | int kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, |
75 | struct kvm_s390_interrupt *s390int); | 116 | struct kvm_s390_interrupt *s390int); |
76 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); | 117 | int kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code); |
77 | int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); | 118 | int kvm_s390_inject_sigp_stop(struct kvm_vcpu *vcpu, int action); |
119 | struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm, | ||
120 | u64 cr6, u64 schid); | ||
78 | 121 | ||
79 | /* implemented in priv.c */ | 122 | /* implemented in priv.c */ |
80 | int kvm_s390_handle_b2(struct kvm_vcpu *vcpu); | 123 | int kvm_s390_handle_b2(struct kvm_vcpu *vcpu); |
81 | int kvm_s390_handle_e5(struct kvm_vcpu *vcpu); | 124 | int kvm_s390_handle_e5(struct kvm_vcpu *vcpu); |
82 | int kvm_s390_handle_01(struct kvm_vcpu *vcpu); | 125 | int kvm_s390_handle_01(struct kvm_vcpu *vcpu); |
126 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); | ||
127 | int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); | ||
128 | int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu); | ||
83 | 129 | ||
84 | /* implemented in sigp.c */ | 130 | /* implemented in sigp.c */ |
85 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); | 131 | int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); |
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c index d768906f15c8..0ef9894606e5 100644 --- a/arch/s390/kvm/priv.c +++ b/arch/s390/kvm/priv.c | |||
@@ -18,23 +18,21 @@ | |||
18 | #include <asm/debug.h> | 18 | #include <asm/debug.h> |
19 | #include <asm/ebcdic.h> | 19 | #include <asm/ebcdic.h> |
20 | #include <asm/sysinfo.h> | 20 | #include <asm/sysinfo.h> |
21 | #include <asm/ptrace.h> | ||
22 | #include <asm/compat.h> | ||
21 | #include "gaccess.h" | 23 | #include "gaccess.h" |
22 | #include "kvm-s390.h" | 24 | #include "kvm-s390.h" |
23 | #include "trace.h" | 25 | #include "trace.h" |
24 | 26 | ||
25 | static int handle_set_prefix(struct kvm_vcpu *vcpu) | 27 | static int handle_set_prefix(struct kvm_vcpu *vcpu) |
26 | { | 28 | { |
27 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
28 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
29 | u64 operand2; | 29 | u64 operand2; |
30 | u32 address = 0; | 30 | u32 address = 0; |
31 | u8 tmp; | 31 | u8 tmp; |
32 | 32 | ||
33 | vcpu->stat.instruction_spx++; | 33 | vcpu->stat.instruction_spx++; |
34 | 34 | ||
35 | operand2 = disp2; | 35 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
36 | if (base2) | ||
37 | operand2 += vcpu->run->s.regs.gprs[base2]; | ||
38 | 36 | ||
39 | /* must be word boundary */ | 37 | /* must be word boundary */ |
40 | if (operand2 & 3) { | 38 | if (operand2 & 3) { |
@@ -67,15 +65,12 @@ out: | |||
67 | 65 | ||
68 | static int handle_store_prefix(struct kvm_vcpu *vcpu) | 66 | static int handle_store_prefix(struct kvm_vcpu *vcpu) |
69 | { | 67 | { |
70 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
71 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
72 | u64 operand2; | 68 | u64 operand2; |
73 | u32 address; | 69 | u32 address; |
74 | 70 | ||
75 | vcpu->stat.instruction_stpx++; | 71 | vcpu->stat.instruction_stpx++; |
76 | operand2 = disp2; | 72 | |
77 | if (base2) | 73 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
78 | operand2 += vcpu->run->s.regs.gprs[base2]; | ||
79 | 74 | ||
80 | /* must be word boundary */ | 75 | /* must be word boundary */ |
81 | if (operand2 & 3) { | 76 | if (operand2 & 3) { |
@@ -100,15 +95,12 @@ out: | |||
100 | 95 | ||
101 | static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | 96 | static int handle_store_cpu_address(struct kvm_vcpu *vcpu) |
102 | { | 97 | { |
103 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
104 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
105 | u64 useraddr; | 98 | u64 useraddr; |
106 | int rc; | 99 | int rc; |
107 | 100 | ||
108 | vcpu->stat.instruction_stap++; | 101 | vcpu->stat.instruction_stap++; |
109 | useraddr = disp2; | 102 | |
110 | if (base2) | 103 | useraddr = kvm_s390_get_base_disp_s(vcpu); |
111 | useraddr += vcpu->run->s.regs.gprs[base2]; | ||
112 | 104 | ||
113 | if (useraddr & 1) { | 105 | if (useraddr & 1) { |
114 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 106 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
@@ -135,24 +127,96 @@ static int handle_skey(struct kvm_vcpu *vcpu) | |||
135 | return 0; | 127 | return 0; |
136 | } | 128 | } |
137 | 129 | ||
138 | static int handle_stsch(struct kvm_vcpu *vcpu) | 130 | static int handle_tpi(struct kvm_vcpu *vcpu) |
139 | { | 131 | { |
140 | vcpu->stat.instruction_stsch++; | 132 | u64 addr; |
141 | VCPU_EVENT(vcpu, 4, "%s", "store subchannel - CC3"); | 133 | struct kvm_s390_interrupt_info *inti; |
142 | /* condition code 3 */ | 134 | int cc; |
135 | |||
136 | addr = kvm_s390_get_base_disp_s(vcpu); | ||
137 | |||
138 | inti = kvm_s390_get_io_int(vcpu->kvm, vcpu->run->s.regs.crs[6], 0); | ||
139 | if (inti) { | ||
140 | if (addr) { | ||
141 | /* | ||
142 | * Store the two-word I/O interruption code into the | ||
143 | * provided area. | ||
144 | */ | ||
145 | put_guest_u16(vcpu, addr, inti->io.subchannel_id); | ||
146 | put_guest_u16(vcpu, addr + 2, inti->io.subchannel_nr); | ||
147 | put_guest_u32(vcpu, addr + 4, inti->io.io_int_parm); | ||
148 | } else { | ||
149 | /* | ||
150 | * Store the three-word I/O interruption code into | ||
151 | * the appropriate lowcore area. | ||
152 | */ | ||
153 | put_guest_u16(vcpu, 184, inti->io.subchannel_id); | ||
154 | put_guest_u16(vcpu, 186, inti->io.subchannel_nr); | ||
155 | put_guest_u32(vcpu, 188, inti->io.io_int_parm); | ||
156 | put_guest_u32(vcpu, 192, inti->io.io_int_word); | ||
157 | } | ||
158 | cc = 1; | ||
159 | } else | ||
160 | cc = 0; | ||
161 | kfree(inti); | ||
162 | /* Set condition code and we're done. */ | ||
143 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 163 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); |
144 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; | 164 | vcpu->arch.sie_block->gpsw.mask |= (cc & 3ul) << 44; |
145 | return 0; | 165 | return 0; |
146 | } | 166 | } |
147 | 167 | ||
148 | static int handle_chsc(struct kvm_vcpu *vcpu) | 168 | static int handle_tsch(struct kvm_vcpu *vcpu) |
149 | { | 169 | { |
150 | vcpu->stat.instruction_chsc++; | 170 | struct kvm_s390_interrupt_info *inti; |
151 | VCPU_EVENT(vcpu, 4, "%s", "channel subsystem call - CC3"); | 171 | |
152 | /* condition code 3 */ | 172 | inti = kvm_s390_get_io_int(vcpu->kvm, 0, |
153 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | 173 | vcpu->run->s.regs.gprs[1]); |
154 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; | 174 | |
155 | return 0; | 175 | /* |
176 | * Prepare exit to userspace. | ||
177 | * We indicate whether we dequeued a pending I/O interrupt | ||
178 | * so that userspace can re-inject it if the instruction gets | ||
179 | * a program check. While this may re-order the pending I/O | ||
180 | * interrupts, this is no problem since the priority is kept | ||
181 | * intact. | ||
182 | */ | ||
183 | vcpu->run->exit_reason = KVM_EXIT_S390_TSCH; | ||
184 | vcpu->run->s390_tsch.dequeued = !!inti; | ||
185 | if (inti) { | ||
186 | vcpu->run->s390_tsch.subchannel_id = inti->io.subchannel_id; | ||
187 | vcpu->run->s390_tsch.subchannel_nr = inti->io.subchannel_nr; | ||
188 | vcpu->run->s390_tsch.io_int_parm = inti->io.io_int_parm; | ||
189 | vcpu->run->s390_tsch.io_int_word = inti->io.io_int_word; | ||
190 | } | ||
191 | vcpu->run->s390_tsch.ipb = vcpu->arch.sie_block->ipb; | ||
192 | kfree(inti); | ||
193 | return -EREMOTE; | ||
194 | } | ||
195 | |||
196 | static int handle_io_inst(struct kvm_vcpu *vcpu) | ||
197 | { | ||
198 | VCPU_EVENT(vcpu, 4, "%s", "I/O instruction"); | ||
199 | |||
200 | if (vcpu->kvm->arch.css_support) { | ||
201 | /* | ||
202 | * Most I/O instructions will be handled by userspace. | ||
203 | * Exceptions are tpi and the interrupt portion of tsch. | ||
204 | */ | ||
205 | if (vcpu->arch.sie_block->ipa == 0xb236) | ||
206 | return handle_tpi(vcpu); | ||
207 | if (vcpu->arch.sie_block->ipa == 0xb235) | ||
208 | return handle_tsch(vcpu); | ||
209 | /* Handle in userspace. */ | ||
210 | return -EOPNOTSUPP; | ||
211 | } else { | ||
212 | /* | ||
213 | * Set condition code 3 to stop the guest from issueing channel | ||
214 | * I/O instructions. | ||
215 | */ | ||
216 | vcpu->arch.sie_block->gpsw.mask &= ~(3ul << 44); | ||
217 | vcpu->arch.sie_block->gpsw.mask |= (3 & 3ul) << 44; | ||
218 | return 0; | ||
219 | } | ||
156 | } | 220 | } |
157 | 221 | ||
158 | static int handle_stfl(struct kvm_vcpu *vcpu) | 222 | static int handle_stfl(struct kvm_vcpu *vcpu) |
@@ -176,17 +240,107 @@ static int handle_stfl(struct kvm_vcpu *vcpu) | |||
176 | return 0; | 240 | return 0; |
177 | } | 241 | } |
178 | 242 | ||
243 | static void handle_new_psw(struct kvm_vcpu *vcpu) | ||
244 | { | ||
245 | /* Check whether the new psw is enabled for machine checks. */ | ||
246 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_MCHECK) | ||
247 | kvm_s390_deliver_pending_machine_checks(vcpu); | ||
248 | } | ||
249 | |||
250 | #define PSW_MASK_ADDR_MODE (PSW_MASK_EA | PSW_MASK_BA) | ||
251 | #define PSW_MASK_UNASSIGNED 0xb80800fe7fffffffUL | ||
252 | #define PSW_ADDR_24 0x00000000000fffffUL | ||
253 | #define PSW_ADDR_31 0x000000007fffffffUL | ||
254 | |||
255 | int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu) | ||
256 | { | ||
257 | u64 addr; | ||
258 | psw_compat_t new_psw; | ||
259 | |||
260 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
261 | return kvm_s390_inject_program_int(vcpu, | ||
262 | PGM_PRIVILEGED_OPERATION); | ||
263 | |||
264 | addr = kvm_s390_get_base_disp_s(vcpu); | ||
265 | |||
266 | if (addr & 7) { | ||
267 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
268 | goto out; | ||
269 | } | ||
270 | |||
271 | if (copy_from_guest(vcpu, &new_psw, addr, sizeof(new_psw))) { | ||
272 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
273 | goto out; | ||
274 | } | ||
275 | |||
276 | if (!(new_psw.mask & PSW32_MASK_BASE)) { | ||
277 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
278 | goto out; | ||
279 | } | ||
280 | |||
281 | vcpu->arch.sie_block->gpsw.mask = | ||
282 | (new_psw.mask & ~PSW32_MASK_BASE) << 32; | ||
283 | vcpu->arch.sie_block->gpsw.addr = new_psw.addr; | ||
284 | |||
285 | if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_UNASSIGNED) || | ||
286 | (!(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_ADDR_MODE) && | ||
287 | (vcpu->arch.sie_block->gpsw.addr & ~PSW_ADDR_24)) || | ||
288 | ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_ADDR_MODE) == | ||
289 | PSW_MASK_EA)) { | ||
290 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
291 | goto out; | ||
292 | } | ||
293 | |||
294 | handle_new_psw(vcpu); | ||
295 | out: | ||
296 | return 0; | ||
297 | } | ||
298 | |||
299 | static int handle_lpswe(struct kvm_vcpu *vcpu) | ||
300 | { | ||
301 | u64 addr; | ||
302 | psw_t new_psw; | ||
303 | |||
304 | addr = kvm_s390_get_base_disp_s(vcpu); | ||
305 | |||
306 | if (addr & 7) { | ||
307 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
308 | goto out; | ||
309 | } | ||
310 | |||
311 | if (copy_from_guest(vcpu, &new_psw, addr, sizeof(new_psw))) { | ||
312 | kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING); | ||
313 | goto out; | ||
314 | } | ||
315 | |||
316 | vcpu->arch.sie_block->gpsw.mask = new_psw.mask; | ||
317 | vcpu->arch.sie_block->gpsw.addr = new_psw.addr; | ||
318 | |||
319 | if ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_UNASSIGNED) || | ||
320 | (((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_ADDR_MODE) == | ||
321 | PSW_MASK_BA) && | ||
322 | (vcpu->arch.sie_block->gpsw.addr & ~PSW_ADDR_31)) || | ||
323 | (!(vcpu->arch.sie_block->gpsw.mask & PSW_MASK_ADDR_MODE) && | ||
324 | (vcpu->arch.sie_block->gpsw.addr & ~PSW_ADDR_24)) || | ||
325 | ((vcpu->arch.sie_block->gpsw.mask & PSW_MASK_ADDR_MODE) == | ||
326 | PSW_MASK_EA)) { | ||
327 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | ||
328 | goto out; | ||
329 | } | ||
330 | |||
331 | handle_new_psw(vcpu); | ||
332 | out: | ||
333 | return 0; | ||
334 | } | ||
335 | |||
179 | static int handle_stidp(struct kvm_vcpu *vcpu) | 336 | static int handle_stidp(struct kvm_vcpu *vcpu) |
180 | { | 337 | { |
181 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
182 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
183 | u64 operand2; | 338 | u64 operand2; |
184 | int rc; | 339 | int rc; |
185 | 340 | ||
186 | vcpu->stat.instruction_stidp++; | 341 | vcpu->stat.instruction_stidp++; |
187 | operand2 = disp2; | 342 | |
188 | if (base2) | 343 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
189 | operand2 += vcpu->run->s.regs.gprs[base2]; | ||
190 | 344 | ||
191 | if (operand2 & 7) { | 345 | if (operand2 & 7) { |
192 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 346 | kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
@@ -240,17 +394,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu) | |||
240 | int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28; | 394 | int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28; |
241 | int sel1 = vcpu->run->s.regs.gprs[0] & 0xff; | 395 | int sel1 = vcpu->run->s.regs.gprs[0] & 0xff; |
242 | int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff; | 396 | int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff; |
243 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
244 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
245 | u64 operand2; | 397 | u64 operand2; |
246 | unsigned long mem; | 398 | unsigned long mem; |
247 | 399 | ||
248 | vcpu->stat.instruction_stsi++; | 400 | vcpu->stat.instruction_stsi++; |
249 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); | 401 | VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); |
250 | 402 | ||
251 | operand2 = disp2; | 403 | operand2 = kvm_s390_get_base_disp_s(vcpu); |
252 | if (base2) | ||
253 | operand2 += vcpu->run->s.regs.gprs[base2]; | ||
254 | 404 | ||
255 | if (operand2 & 0xfff && fc > 0) | 405 | if (operand2 & 0xfff && fc > 0) |
256 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); | 406 | return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); |
@@ -297,7 +447,7 @@ out_fail: | |||
297 | return 0; | 447 | return 0; |
298 | } | 448 | } |
299 | 449 | ||
300 | static intercept_handler_t priv_handlers[256] = { | 450 | static const intercept_handler_t b2_handlers[256] = { |
301 | [0x02] = handle_stidp, | 451 | [0x02] = handle_stidp, |
302 | [0x10] = handle_set_prefix, | 452 | [0x10] = handle_set_prefix, |
303 | [0x11] = handle_store_prefix, | 453 | [0x11] = handle_store_prefix, |
@@ -305,10 +455,25 @@ static intercept_handler_t priv_handlers[256] = { | |||
305 | [0x29] = handle_skey, | 455 | [0x29] = handle_skey, |
306 | [0x2a] = handle_skey, | 456 | [0x2a] = handle_skey, |
307 | [0x2b] = handle_skey, | 457 | [0x2b] = handle_skey, |
308 | [0x34] = handle_stsch, | 458 | [0x30] = handle_io_inst, |
309 | [0x5f] = handle_chsc, | 459 | [0x31] = handle_io_inst, |
460 | [0x32] = handle_io_inst, | ||
461 | [0x33] = handle_io_inst, | ||
462 | [0x34] = handle_io_inst, | ||
463 | [0x35] = handle_io_inst, | ||
464 | [0x36] = handle_io_inst, | ||
465 | [0x37] = handle_io_inst, | ||
466 | [0x38] = handle_io_inst, | ||
467 | [0x39] = handle_io_inst, | ||
468 | [0x3a] = handle_io_inst, | ||
469 | [0x3b] = handle_io_inst, | ||
470 | [0x3c] = handle_io_inst, | ||
471 | [0x5f] = handle_io_inst, | ||
472 | [0x74] = handle_io_inst, | ||
473 | [0x76] = handle_io_inst, | ||
310 | [0x7d] = handle_stsi, | 474 | [0x7d] = handle_stsi, |
311 | [0xb1] = handle_stfl, | 475 | [0xb1] = handle_stfl, |
476 | [0xb2] = handle_lpswe, | ||
312 | }; | 477 | }; |
313 | 478 | ||
314 | int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | 479 | int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) |
@@ -322,7 +487,7 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | |||
322 | * state bit and (a) handle the instruction or (b) send a code 2 | 487 | * state bit and (a) handle the instruction or (b) send a code 2 |
323 | * program check. | 488 | * program check. |
324 | * Anything else goes to userspace.*/ | 489 | * Anything else goes to userspace.*/ |
325 | handler = priv_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; | 490 | handler = b2_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; |
326 | if (handler) { | 491 | if (handler) { |
327 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | 492 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) |
328 | return kvm_s390_inject_program_int(vcpu, | 493 | return kvm_s390_inject_program_int(vcpu, |
@@ -333,19 +498,74 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu) | |||
333 | return -EOPNOTSUPP; | 498 | return -EOPNOTSUPP; |
334 | } | 499 | } |
335 | 500 | ||
501 | static int handle_epsw(struct kvm_vcpu *vcpu) | ||
502 | { | ||
503 | int reg1, reg2; | ||
504 | |||
505 | reg1 = (vcpu->arch.sie_block->ipb & 0x00f00000) >> 24; | ||
506 | reg2 = (vcpu->arch.sie_block->ipb & 0x000f0000) >> 16; | ||
507 | |||
508 | /* This basically extracts the mask half of the psw. */ | ||
509 | vcpu->run->s.regs.gprs[reg1] &= 0xffffffff00000000; | ||
510 | vcpu->run->s.regs.gprs[reg1] |= vcpu->arch.sie_block->gpsw.mask >> 32; | ||
511 | if (reg2) { | ||
512 | vcpu->run->s.regs.gprs[reg2] &= 0xffffffff00000000; | ||
513 | vcpu->run->s.regs.gprs[reg2] |= | ||
514 | vcpu->arch.sie_block->gpsw.mask & 0x00000000ffffffff; | ||
515 | } | ||
516 | return 0; | ||
517 | } | ||
518 | |||
519 | static const intercept_handler_t b9_handlers[256] = { | ||
520 | [0x8d] = handle_epsw, | ||
521 | [0x9c] = handle_io_inst, | ||
522 | }; | ||
523 | |||
524 | int kvm_s390_handle_b9(struct kvm_vcpu *vcpu) | ||
525 | { | ||
526 | intercept_handler_t handler; | ||
527 | |||
528 | /* This is handled just as for the B2 instructions. */ | ||
529 | handler = b9_handlers[vcpu->arch.sie_block->ipa & 0x00ff]; | ||
530 | if (handler) { | ||
531 | if ((handler != handle_epsw) && | ||
532 | (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)) | ||
533 | return kvm_s390_inject_program_int(vcpu, | ||
534 | PGM_PRIVILEGED_OPERATION); | ||
535 | else | ||
536 | return handler(vcpu); | ||
537 | } | ||
538 | return -EOPNOTSUPP; | ||
539 | } | ||
540 | |||
541 | static const intercept_handler_t eb_handlers[256] = { | ||
542 | [0x8a] = handle_io_inst, | ||
543 | }; | ||
544 | |||
545 | int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu) | ||
546 | { | ||
547 | intercept_handler_t handler; | ||
548 | |||
549 | /* All eb instructions that end up here are privileged. */ | ||
550 | if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE) | ||
551 | return kvm_s390_inject_program_int(vcpu, | ||
552 | PGM_PRIVILEGED_OPERATION); | ||
553 | handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff]; | ||
554 | if (handler) | ||
555 | return handler(vcpu); | ||
556 | return -EOPNOTSUPP; | ||
557 | } | ||
558 | |||
336 | static int handle_tprot(struct kvm_vcpu *vcpu) | 559 | static int handle_tprot(struct kvm_vcpu *vcpu) |
337 | { | 560 | { |
338 | int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28; | 561 | u64 address1, address2; |
339 | int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16; | ||
340 | int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12; | ||
341 | int disp2 = vcpu->arch.sie_block->ipb & 0x0fff; | ||
342 | u64 address1 = disp1 + base1 ? vcpu->run->s.regs.gprs[base1] : 0; | ||
343 | u64 address2 = disp2 + base2 ? vcpu->run->s.regs.gprs[base2] : 0; | ||
344 | struct vm_area_struct *vma; | 562 | struct vm_area_struct *vma; |
345 | unsigned long user_address; | 563 | unsigned long user_address; |
346 | 564 | ||
347 | vcpu->stat.instruction_tprot++; | 565 | vcpu->stat.instruction_tprot++; |
348 | 566 | ||
567 | kvm_s390_get_base_disp_sse(vcpu, &address1, &address2); | ||
568 | |||
349 | /* we only handle the Linux memory detection case: | 569 | /* we only handle the Linux memory detection case: |
350 | * access key == 0 | 570 | * access key == 0 |
351 | * guest DAT == off | 571 | * guest DAT == off |
@@ -405,7 +625,7 @@ static int handle_sckpf(struct kvm_vcpu *vcpu) | |||
405 | return 0; | 625 | return 0; |
406 | } | 626 | } |
407 | 627 | ||
408 | static intercept_handler_t x01_handlers[256] = { | 628 | static const intercept_handler_t x01_handlers[256] = { |
409 | [0x07] = handle_sckpf, | 629 | [0x07] = handle_sckpf, |
410 | }; | 630 | }; |
411 | 631 | ||
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c index 566ddf6e8dfb..1c48ab2845e0 100644 --- a/arch/s390/kvm/sigp.c +++ b/arch/s390/kvm/sigp.c | |||
@@ -137,8 +137,10 @@ static int __inject_sigp_stop(struct kvm_s390_local_interrupt *li, int action) | |||
137 | inti->type = KVM_S390_SIGP_STOP; | 137 | inti->type = KVM_S390_SIGP_STOP; |
138 | 138 | ||
139 | spin_lock_bh(&li->lock); | 139 | spin_lock_bh(&li->lock); |
140 | if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) | 140 | if ((atomic_read(li->cpuflags) & CPUSTAT_STOPPED)) { |
141 | kfree(inti); | ||
141 | goto out; | 142 | goto out; |
143 | } | ||
142 | list_add_tail(&inti->list, &li->list); | 144 | list_add_tail(&inti->list, &li->list); |
143 | atomic_set(&li->active, 1); | 145 | atomic_set(&li->active, 1); |
144 | atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); | 146 | atomic_set_mask(CPUSTAT_STOP_INT, li->cpuflags); |
@@ -324,8 +326,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
324 | { | 326 | { |
325 | int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; | 327 | int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; |
326 | int r3 = vcpu->arch.sie_block->ipa & 0x000f; | 328 | int r3 = vcpu->arch.sie_block->ipa & 0x000f; |
327 | int base2 = vcpu->arch.sie_block->ipb >> 28; | ||
328 | int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16); | ||
329 | u32 parameter; | 329 | u32 parameter; |
330 | u16 cpu_addr = vcpu->run->s.regs.gprs[r3]; | 330 | u16 cpu_addr = vcpu->run->s.regs.gprs[r3]; |
331 | u8 order_code; | 331 | u8 order_code; |
@@ -336,9 +336,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu) | |||
336 | return kvm_s390_inject_program_int(vcpu, | 336 | return kvm_s390_inject_program_int(vcpu, |
337 | PGM_PRIVILEGED_OPERATION); | 337 | PGM_PRIVILEGED_OPERATION); |
338 | 338 | ||
339 | order_code = disp2; | 339 | order_code = kvm_s390_get_base_disp_rs(vcpu); |
340 | if (base2) | ||
341 | order_code += vcpu->run->s.regs.gprs[base2]; | ||
342 | 340 | ||
343 | if (r1 % 2) | 341 | if (r1 % 2) |
344 | parameter = vcpu->run->s.regs.gprs[r1]; | 342 | parameter = vcpu->run->s.regs.gprs[r1]; |
diff --git a/arch/s390/kvm/trace-s390.h b/arch/s390/kvm/trace-s390.h index 90fdf85b5ff7..13f30f58a2df 100644 --- a/arch/s390/kvm/trace-s390.h +++ b/arch/s390/kvm/trace-s390.h | |||
@@ -141,13 +141,13 @@ TRACE_EVENT(kvm_s390_inject_vcpu, | |||
141 | * Trace point for the actual delivery of interrupts. | 141 | * Trace point for the actual delivery of interrupts. |
142 | */ | 142 | */ |
143 | TRACE_EVENT(kvm_s390_deliver_interrupt, | 143 | TRACE_EVENT(kvm_s390_deliver_interrupt, |
144 | TP_PROTO(unsigned int id, __u64 type, __u32 data0, __u64 data1), | 144 | TP_PROTO(unsigned int id, __u64 type, __u64 data0, __u64 data1), |
145 | TP_ARGS(id, type, data0, data1), | 145 | TP_ARGS(id, type, data0, data1), |
146 | 146 | ||
147 | TP_STRUCT__entry( | 147 | TP_STRUCT__entry( |
148 | __field(int, id) | 148 | __field(int, id) |
149 | __field(__u32, inttype) | 149 | __field(__u32, inttype) |
150 | __field(__u32, data0) | 150 | __field(__u64, data0) |
151 | __field(__u64, data1) | 151 | __field(__u64, data1) |
152 | ), | 152 | ), |
153 | 153 | ||
@@ -159,7 +159,7 @@ TRACE_EVENT(kvm_s390_deliver_interrupt, | |||
159 | ), | 159 | ), |
160 | 160 | ||
161 | TP_printk("deliver interrupt (vcpu %d): type:%x (%s) " \ | 161 | TP_printk("deliver interrupt (vcpu %d): type:%x (%s) " \ |
162 | "data:%08x %016llx", | 162 | "data:%08llx %016llx", |
163 | __entry->id, __entry->inttype, | 163 | __entry->id, __entry->inttype, |
164 | __print_symbolic(__entry->inttype, kvm_s390_int_type), | 164 | __print_symbolic(__entry->inttype, kvm_s390_int_type), |
165 | __entry->data0, __entry->data1) | 165 | __entry->data0, __entry->data1) |
@@ -204,6 +204,26 @@ TRACE_EVENT(kvm_s390_stop_request, | |||
204 | ); | 204 | ); |
205 | 205 | ||
206 | 206 | ||
207 | /* | ||
208 | * Trace point for enabling channel I/O instruction support. | ||
209 | */ | ||
210 | TRACE_EVENT(kvm_s390_enable_css, | ||
211 | TP_PROTO(void *kvm), | ||
212 | TP_ARGS(kvm), | ||
213 | |||
214 | TP_STRUCT__entry( | ||
215 | __field(void *, kvm) | ||
216 | ), | ||
217 | |||
218 | TP_fast_assign( | ||
219 | __entry->kvm = kvm; | ||
220 | ), | ||
221 | |||
222 | TP_printk("enabling channel I/O support (kvm @ %p)\n", | ||
223 | __entry->kvm) | ||
224 | ); | ||
225 | |||
226 | |||
207 | #endif /* _TRACE_KVMS390_H */ | 227 | #endif /* _TRACE_KVMS390_H */ |
208 | 228 | ||
209 | /* This part must be outside protection */ | 229 | /* This part must be outside protection */ |
diff --git a/arch/s390/pci/pci_debug.c b/arch/s390/pci/pci_debug.c index a303c95346cb..a5d07bc2a547 100644 --- a/arch/s390/pci/pci_debug.c +++ b/arch/s390/pci/pci_debug.c | |||
@@ -99,7 +99,7 @@ static ssize_t pci_perf_seq_write(struct file *file, const char __user *ubuf, | |||
99 | static int pci_perf_seq_open(struct inode *inode, struct file *filp) | 99 | static int pci_perf_seq_open(struct inode *inode, struct file *filp) |
100 | { | 100 | { |
101 | return single_open(filp, pci_perf_show, | 101 | return single_open(filp, pci_perf_show, |
102 | filp->f_path.dentry->d_inode->i_private); | 102 | file_inode(filp)->i_private); |
103 | } | 103 | } |
104 | 104 | ||
105 | static const struct file_operations debugfs_pci_perf_fops = { | 105 | static const struct file_operations debugfs_pci_perf_fops = { |
@@ -121,7 +121,7 @@ static int pci_debug_show(struct seq_file *m, void *v) | |||
121 | static int pci_debug_seq_open(struct inode *inode, struct file *filp) | 121 | static int pci_debug_seq_open(struct inode *inode, struct file *filp) |
122 | { | 122 | { |
123 | return single_open(filp, pci_debug_show, | 123 | return single_open(filp, pci_debug_show, |
124 | filp->f_path.dentry->d_inode->i_private); | 124 | file_inode(filp)->i_private); |
125 | } | 125 | } |
126 | 126 | ||
127 | static const struct file_operations debugfs_pci_debug_fops = { | 127 | static const struct file_operations debugfs_pci_debug_fops = { |
diff --git a/arch/s390/pci/pci_msi.c b/arch/s390/pci/pci_msi.c index 90fd3482b9e2..0297931335e1 100644 --- a/arch/s390/pci/pci_msi.c +++ b/arch/s390/pci/pci_msi.c | |||
@@ -25,10 +25,9 @@ static DEFINE_SPINLOCK(msi_map_lock); | |||
25 | 25 | ||
26 | struct msi_desc *__irq_get_msi_desc(unsigned int irq) | 26 | struct msi_desc *__irq_get_msi_desc(unsigned int irq) |
27 | { | 27 | { |
28 | struct hlist_node *entry; | ||
29 | struct msi_map *map; | 28 | struct msi_map *map; |
30 | 29 | ||
31 | hlist_for_each_entry_rcu(map, entry, | 30 | hlist_for_each_entry_rcu(map, |
32 | &msi_hash[msi_hashfn(irq)], msi_chain) | 31 | &msi_hash[msi_hashfn(irq)], msi_chain) |
33 | if (map->irq == irq) | 32 | if (map->irq == irq) |
34 | return map->msi; | 33 | return map->msi; |