aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
authorCornelia Huck <cornelia.huck@de.ibm.com>2012-12-20 09:32:07 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2013-01-07 16:53:38 -0500
commitb1c571a50dfacf25a24c23271e9b8bf18ff6b102 (patch)
treeca6408076537bab63fd2b7e9df890f1a524c14a3 /arch/s390
parent77975357956c6450dd7ac3dfe572c1a8f0014c54 (diff)
KVM: s390: Decoding helper functions.
Introduce helper functions for decoding the various base/displacement instruction formats. Reviewed-by: Alexander Graf <agraf@suse.de> Signed-off-by: Cornelia Huck <cornelia.huck@de.ibm.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/kvm/intercept.c21
-rw-r--r--arch/s390/kvm/kvm-s390.h37
-rw-r--r--arch/s390/kvm/priv.c42
-rw-r--r--arch/s390/kvm/sigp.c6
4 files changed, 55 insertions, 51 deletions
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 0c08b3f1c1c5..df6c0ad085aa 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -26,9 +26,6 @@ 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
@@ -36,17 +33,15 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
36 if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f) 33 if ((vcpu->arch.sie_block->ipb & 0xff) != 0x2f)
37 return -EOPNOTSUPP; 34 return -EOPNOTSUPP;
38 35
39 useraddr = disp2; 36 useraddr = kvm_s390_get_base_disp_rsy(vcpu);
40 if (base2)
41 useraddr += vcpu->run->s.regs.gprs[base2];
42 37
43 if (useraddr & 7) 38 if (useraddr & 7)
44 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 39 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
45 40
46 reg = reg1; 41 reg = reg1;
47 42
48 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, 43 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3,
49 disp2); 44 useraddr);
50 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr); 45 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, useraddr);
51 46
52 do { 47 do {
@@ -68,23 +63,19 @@ static int handle_lctl(struct kvm_vcpu *vcpu)
68{ 63{
69 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 64 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
70 int reg3 = vcpu->arch.sie_block->ipa & 0x000f; 65 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; 66 u64 useraddr;
74 u32 val = 0; 67 u32 val = 0;
75 int reg, rc; 68 int reg, rc;
76 69
77 vcpu->stat.instruction_lctl++; 70 vcpu->stat.instruction_lctl++;
78 71
79 useraddr = disp2; 72 useraddr = kvm_s390_get_base_disp_rs(vcpu);
80 if (base2)
81 useraddr += vcpu->run->s.regs.gprs[base2];
82 73
83 if (useraddr & 3) 74 if (useraddr & 3)
84 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 75 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
85 76
86 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x,b2:%x,d2:%x", reg1, reg3, base2, 77 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3,
87 disp2); 78 useraddr);
88 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr); 79 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, useraddr);
89 80
90 reg = reg1; 81 reg = reg1;
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index d75bc5e92c5b..dccc0242b7ca 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -65,6 +65,43 @@ 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
68static inline u64 kvm_s390_get_base_disp_s(struct kvm_vcpu *vcpu)
69{
70 int base2 = vcpu->arch.sie_block->ipb >> 28;
71 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
72
73 return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
74}
75
76static inline void kvm_s390_get_base_disp_sse(struct kvm_vcpu *vcpu,
77 u64 *address1, u64 *address2)
78{
79 int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28;
80 int disp1 = (vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16;
81 int base2 = (vcpu->arch.sie_block->ipb & 0xf000) >> 12;
82 int 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
88static inline u64 kvm_s390_get_base_disp_rsy(struct kvm_vcpu *vcpu)
89{
90 int base2 = vcpu->arch.sie_block->ipb >> 28;
91 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16) +
92 ((vcpu->arch.sie_block->ipb & 0xff00) << 4);
93
94 return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
95}
96
97static inline u64 kvm_s390_get_base_disp_rs(struct kvm_vcpu *vcpu)
98{
99 int base2 = vcpu->arch.sie_block->ipb >> 28;
100 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
101
102 return (base2 ? vcpu->run->s.regs.gprs[base2] : 0) + disp2;
103}
104
68int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); 105int kvm_s390_handle_wait(struct kvm_vcpu *vcpu);
69enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); 106enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer);
70void kvm_s390_tasklet(unsigned long parm); 107void kvm_s390_tasklet(unsigned long parm);
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 1aeb9335f9e2..d715842f56ca 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -24,17 +24,13 @@
24 24
25static int handle_set_prefix(struct kvm_vcpu *vcpu) 25static int handle_set_prefix(struct kvm_vcpu *vcpu)
26{ 26{
27 int base2 = vcpu->arch.sie_block->ipb >> 28;
28 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
29 u64 operand2; 27 u64 operand2;
30 u32 address = 0; 28 u32 address = 0;
31 u8 tmp; 29 u8 tmp;
32 30
33 vcpu->stat.instruction_spx++; 31 vcpu->stat.instruction_spx++;
34 32
35 operand2 = disp2; 33 operand2 = kvm_s390_get_base_disp_s(vcpu);
36 if (base2)
37 operand2 += vcpu->run->s.regs.gprs[base2];
38 34
39 /* must be word boundary */ 35 /* must be word boundary */
40 if (operand2 & 3) { 36 if (operand2 & 3) {
@@ -67,15 +63,12 @@ out:
67 63
68static int handle_store_prefix(struct kvm_vcpu *vcpu) 64static int handle_store_prefix(struct kvm_vcpu *vcpu)
69{ 65{
70 int base2 = vcpu->arch.sie_block->ipb >> 28;
71 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
72 u64 operand2; 66 u64 operand2;
73 u32 address; 67 u32 address;
74 68
75 vcpu->stat.instruction_stpx++; 69 vcpu->stat.instruction_stpx++;
76 operand2 = disp2; 70
77 if (base2) 71 operand2 = kvm_s390_get_base_disp_s(vcpu);
78 operand2 += vcpu->run->s.regs.gprs[base2];
79 72
80 /* must be word boundary */ 73 /* must be word boundary */
81 if (operand2 & 3) { 74 if (operand2 & 3) {
@@ -100,15 +93,12 @@ out:
100 93
101static int handle_store_cpu_address(struct kvm_vcpu *vcpu) 94static int handle_store_cpu_address(struct kvm_vcpu *vcpu)
102{ 95{
103 int base2 = vcpu->arch.sie_block->ipb >> 28;
104 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
105 u64 useraddr; 96 u64 useraddr;
106 int rc; 97 int rc;
107 98
108 vcpu->stat.instruction_stap++; 99 vcpu->stat.instruction_stap++;
109 useraddr = disp2; 100
110 if (base2) 101 useraddr = kvm_s390_get_base_disp_s(vcpu);
111 useraddr += vcpu->run->s.regs.gprs[base2];
112 102
113 if (useraddr & 1) { 103 if (useraddr & 1) {
114 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 104 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -178,15 +168,12 @@ static int handle_stfl(struct kvm_vcpu *vcpu)
178 168
179static int handle_stidp(struct kvm_vcpu *vcpu) 169static int handle_stidp(struct kvm_vcpu *vcpu)
180{ 170{
181 int base2 = vcpu->arch.sie_block->ipb >> 28;
182 int disp2 = ((vcpu->arch.sie_block->ipb & 0x0fff0000) >> 16);
183 u64 operand2; 171 u64 operand2;
184 int rc; 172 int rc;
185 173
186 vcpu->stat.instruction_stidp++; 174 vcpu->stat.instruction_stidp++;
187 operand2 = disp2; 175
188 if (base2) 176 operand2 = kvm_s390_get_base_disp_s(vcpu);
189 operand2 += vcpu->run->s.regs.gprs[base2];
190 177
191 if (operand2 & 7) { 178 if (operand2 & 7) {
192 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 179 kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -240,17 +227,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
240 int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28; 227 int fc = (vcpu->run->s.regs.gprs[0] & 0xf0000000) >> 28;
241 int sel1 = vcpu->run->s.regs.gprs[0] & 0xff; 228 int sel1 = vcpu->run->s.regs.gprs[0] & 0xff;
242 int sel2 = vcpu->run->s.regs.gprs[1] & 0xffff; 229 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; 230 u64 operand2;
246 unsigned long mem; 231 unsigned long mem;
247 232
248 vcpu->stat.instruction_stsi++; 233 vcpu->stat.instruction_stsi++;
249 VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2); 234 VCPU_EVENT(vcpu, 4, "stsi: fc: %x sel1: %x sel2: %x", fc, sel1, sel2);
250 235
251 operand2 = disp2; 236 operand2 = kvm_s390_get_base_disp_s(vcpu);
252 if (base2)
253 operand2 += vcpu->run->s.regs.gprs[base2];
254 237
255 if (operand2 & 0xfff && fc > 0) 238 if (operand2 & 0xfff && fc > 0)
256 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 239 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
@@ -335,17 +318,14 @@ int kvm_s390_handle_b2(struct kvm_vcpu *vcpu)
335 318
336static int handle_tprot(struct kvm_vcpu *vcpu) 319static int handle_tprot(struct kvm_vcpu *vcpu)
337{ 320{
338 int base1 = (vcpu->arch.sie_block->ipb & 0xf0000000) >> 28; 321 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; 322 struct vm_area_struct *vma;
345 unsigned long user_address; 323 unsigned long user_address;
346 324
347 vcpu->stat.instruction_tprot++; 325 vcpu->stat.instruction_tprot++;
348 326
327 kvm_s390_get_base_disp_sse(vcpu, &address1, &address2);
328
349 /* we only handle the Linux memory detection case: 329 /* we only handle the Linux memory detection case:
350 * access key == 0 330 * access key == 0
351 * guest DAT == off 331 * guest DAT == off
diff --git a/arch/s390/kvm/sigp.c b/arch/s390/kvm/sigp.c
index 566ddf6e8dfb..461e84179db1 100644
--- a/arch/s390/kvm/sigp.c
+++ b/arch/s390/kvm/sigp.c
@@ -324,8 +324,6 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
324{ 324{
325 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 325 int r1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
326 int r3 = vcpu->arch.sie_block->ipa & 0x000f; 326 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; 327 u32 parameter;
330 u16 cpu_addr = vcpu->run->s.regs.gprs[r3]; 328 u16 cpu_addr = vcpu->run->s.regs.gprs[r3];
331 u8 order_code; 329 u8 order_code;
@@ -336,9 +334,7 @@ int kvm_s390_handle_sigp(struct kvm_vcpu *vcpu)
336 return kvm_s390_inject_program_int(vcpu, 334 return kvm_s390_inject_program_int(vcpu,
337 PGM_PRIVILEGED_OPERATION); 335 PGM_PRIVILEGED_OPERATION);
338 336
339 order_code = disp2; 337 order_code = kvm_s390_get_base_disp_rs(vcpu);
340 if (base2)
341 order_code += vcpu->run->s.regs.gprs[base2];
342 338
343 if (r1 % 2) 339 if (r1 % 2)
344 parameter = vcpu->run->s.regs.gprs[r1]; 340 parameter = vcpu->run->s.regs.gprs[r1];