diff options
author | Cornelia Huck <cornelia.huck@de.ibm.com> | 2012-12-20 09:32:07 -0500 |
---|---|---|
committer | Marcelo Tosatti <mtosatti@redhat.com> | 2013-01-07 16:53:38 -0500 |
commit | b1c571a50dfacf25a24c23271e9b8bf18ff6b102 (patch) | |
tree | ca6408076537bab63fd2b7e9df890f1a524c14a3 /arch/s390 | |
parent | 77975357956c6450dd7ac3dfe572c1a8f0014c54 (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.c | 21 | ||||
-rw-r--r-- | arch/s390/kvm/kvm-s390.h | 37 | ||||
-rw-r--r-- | arch/s390/kvm/priv.c | 42 | ||||
-rw-r--r-- | arch/s390/kvm/sigp.c | 6 |
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 | ||
68 | static 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 | |||
76 | static 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 | |||
88 | static 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 | |||
97 | static 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 | |||
68 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); | 105 | int kvm_s390_handle_wait(struct kvm_vcpu *vcpu); |
69 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); | 106 | enum hrtimer_restart kvm_s390_idle_wakeup(struct hrtimer *timer); |
70 | void kvm_s390_tasklet(unsigned long parm); | 107 | void 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 | ||
25 | static int handle_set_prefix(struct kvm_vcpu *vcpu) | 25 | static 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 | ||
68 | static int handle_store_prefix(struct kvm_vcpu *vcpu) | 64 | static 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 | ||
101 | static int handle_store_cpu_address(struct kvm_vcpu *vcpu) | 94 | static 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 | ||
179 | static int handle_stidp(struct kvm_vcpu *vcpu) | 169 | static 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 | ||
336 | static int handle_tprot(struct kvm_vcpu *vcpu) | 319 | static 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]; |