aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/kvm
diff options
context:
space:
mode:
authorThomas Huth <thuth@linux.vnet.ibm.com>2013-06-20 11:22:04 -0400
committerPaolo Bonzini <pbonzini@redhat.com>2013-06-20 17:32:39 -0400
commit953ed88d10444c0e139a2333b6cd96ce01aa94dc (patch)
tree89579d65e96ce247b41ae2b2fe788250bb80a94c /arch/s390/kvm
parent133608f392ce2e11481317e3d0b02044710a5956 (diff)
KVM: s390: Reworked LCTL and LCTLG instructions
LCTL and LCTLG are also privileged instructions, thus there is no need for treating them separately from the other instructions in priv.c. So this patch moves these two instructions to priv.c, adds a check for supervisor state and simplifies the "handle_eb" instruction decoding by merging the two eb_handlers jump tables from intercept.c and priv.c into one table only. Signed-off-by: Thomas Huth <thuth@linux.vnet.ibm.com> Acked-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'arch/s390/kvm')
-rw-r--r--arch/s390/kvm/intercept.c85
-rw-r--r--arch/s390/kvm/kvm-s390.h3
-rw-r--r--arch/s390/kvm/priv.c78
3 files changed, 81 insertions, 85 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index f0b8be0cc08d..5ee56e5acc23 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -22,87 +22,6 @@
22#include "trace.h" 22#include "trace.h"
23#include "trace-s390.h" 23#include "trace-s390.h"
24 24
25static int handle_lctlg(struct kvm_vcpu *vcpu)
26{
27 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
28 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
29 u64 useraddr;
30 int reg, rc;
31
32 vcpu->stat.instruction_lctlg++;
33
34 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
35
36 if (useraddr & 7)
37 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
38
39 reg = reg1;
40
41 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
42 useraddr);
43 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
44
45 do {
46 rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg],
47 (u64 __user *) useraddr);
48 if (rc)
49 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
50 useraddr += 8;
51 if (reg == reg3)
52 break;
53 reg = (reg + 1) % 16;
54 } while (1);
55 return 0;
56}
57
58static int handle_lctl(struct kvm_vcpu *vcpu)
59{
60 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
61 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
62 u64 useraddr;
63 u32 val = 0;
64 int reg, rc;
65
66 vcpu->stat.instruction_lctl++;
67
68 useraddr = kvm_s390_get_base_disp_rs(vcpu);
69
70 if (useraddr & 3)
71 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
72
73 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
74 useraddr);
75 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
76
77 reg = reg1;
78 do {
79 rc = get_guest(vcpu, val, (u32 __user *) useraddr);
80 if (rc)
81 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
82 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
83 vcpu->arch.sie_block->gcr[reg] |= val;
84 useraddr += 4;
85 if (reg == reg3)
86 break;
87 reg = (reg + 1) % 16;
88 } while (1);
89 return 0;
90}
91
92static const intercept_handler_t eb_handlers[256] = {
93 [0x2f] = handle_lctlg,
94 [0x8a] = kvm_s390_handle_priv_eb,
95};
96
97static int handle_eb(struct kvm_vcpu *vcpu)
98{
99 intercept_handler_t handler;
100
101 handler = eb_handlers[vcpu->arch.sie_block->ipb & 0xff];
102 if (handler)
103 return handler(vcpu);
104 return -EOPNOTSUPP;
105}
106 25
107static const intercept_handler_t instruction_handlers[256] = { 26static const intercept_handler_t instruction_handlers[256] = {
108 [0x01] = kvm_s390_handle_01, 27 [0x01] = kvm_s390_handle_01,
@@ -110,10 +29,10 @@ static const intercept_handler_t instruction_handlers[256] = {
110 [0x83] = kvm_s390_handle_diag, 29 [0x83] = kvm_s390_handle_diag,
111 [0xae] = kvm_s390_handle_sigp, 30 [0xae] = kvm_s390_handle_sigp,
112 [0xb2] = kvm_s390_handle_b2, 31 [0xb2] = kvm_s390_handle_b2,
113 [0xb7] = handle_lctl, 32 [0xb7] = kvm_s390_handle_lctl,
114 [0xb9] = kvm_s390_handle_b9, 33 [0xb9] = kvm_s390_handle_b9,
115 [0xe5] = kvm_s390_handle_e5, 34 [0xe5] = kvm_s390_handle_e5,
116 [0xeb] = handle_eb, 35 [0xeb] = kvm_s390_handle_eb,
117}; 36};
118 37
119static int handle_noop(struct kvm_vcpu *vcpu) 38static int handle_noop(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 15795b8f8ff5..028ca9fd2158 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -132,7 +132,8 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
132int kvm_s390_handle_01(struct kvm_vcpu *vcpu); 132int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
133int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); 133int kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
134int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); 134int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
135int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu); 135int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu);
136int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
136 137
137/* implemented in sigp.c */ 138/* implemented in sigp.c */
138int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu); 139int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 4b8fb6cc3c45..c7603f5b4c28 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -590,11 +590,87 @@ int kvm_s390_handle_b9(struct kvm_vcpu *vcpu)
590 return -EOPNOTSUPP; 590 return -EOPNOTSUPP;
591} 591}
592 592
593int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
594{
595 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
596 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
597 u64 useraddr;
598 u32 val = 0;
599 int reg, rc;
600
601 vcpu->stat.instruction_lctl++;
602
603 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
604 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
605
606 useraddr = kvm_s390_get_base_disp_rs(vcpu);
607
608 if (useraddr & 3)
609 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
610
611 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
612 useraddr);
613 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
614
615 reg = reg1;
616 do {
617 rc = get_guest(vcpu, val, (u32 __user *) useraddr);
618 if (rc)
619 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
620 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
621 vcpu->arch.sie_block->gcr[reg] |= val;
622 useraddr += 4;
623 if (reg == reg3)
624 break;
625 reg = (reg + 1) % 16;
626 } while (1);
627
628 return 0;
629}
630
631static int handle_lctlg(struct kvm_vcpu *vcpu)
632{
633 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
634 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
635 u64 useraddr;
636 int reg, rc;
637
638 vcpu->stat.instruction_lctlg++;
639
640 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
641 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
642
643 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
644
645 if (useraddr & 7)
646 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
647
648 reg = reg1;
649
650 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
651 useraddr);
652 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
653
654 do {
655 rc = get_guest(vcpu, vcpu->arch.sie_block->gcr[reg],
656 (u64 __user *) useraddr);
657 if (rc)
658 return kvm_s390_inject_program_int(vcpu, PGM_ADDRESSING);
659 useraddr += 8;
660 if (reg == reg3)
661 break;
662 reg = (reg + 1) % 16;
663 } while (1);
664
665 return 0;
666}
667
593static const intercept_handler_t eb_handlers[256] = { 668static const intercept_handler_t eb_handlers[256] = {
669 [0x2f] = handle_lctlg,
594 [0x8a] = handle_io_inst, 670 [0x8a] = handle_io_inst,
595}; 671};
596 672
597int kvm_s390_handle_priv_eb(struct kvm_vcpu *vcpu) 673int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
598{ 674{
599 intercept_handler_t handler; 675 intercept_handler_t handler;
600 676