aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>2014-01-23 04:47:13 -0500
committerChristian Borntraeger <borntraeger@de.ibm.com>2014-04-22 07:24:50 -0400
commitaba0750889d012f84a719112997abb7be11bba4b (patch)
treeadf0c6d527dfb844ddfd03a0a460a3c8806e5223 /arch
parent8712836b30cef5d49bc3bb8bc3da88a40e11e574 (diff)
KVM: s390: emulate stctl and stctg
Introduce the methods to emulate the stctl and stctg instruction. Added tracing code. Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/s390/include/asm/kvm_host.h2
-rw-r--r--arch/s390/kvm/intercept.c1
-rw-r--r--arch/s390/kvm/kvm-s390.c2
-rw-r--r--arch/s390/kvm/kvm-s390.h1
-rw-r--r--arch/s390/kvm/priv.c73
-rw-r--r--arch/s390/kvm/trace.h25
6 files changed, 104 insertions, 0 deletions
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 5e5a14db8c21..5d9648925a8e 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -175,6 +175,8 @@ struct kvm_vcpu_stat {
175 u32 exit_instruction; 175 u32 exit_instruction;
176 u32 instruction_lctl; 176 u32 instruction_lctl;
177 u32 instruction_lctlg; 177 u32 instruction_lctlg;
178 u32 instruction_stctl;
179 u32 instruction_stctg;
178 u32 exit_program_interruption; 180 u32 exit_program_interruption;
179 u32 exit_instr_and_program; 181 u32 exit_instr_and_program;
180 u32 deliver_external_call; 182 u32 deliver_external_call;
diff --git a/arch/s390/kvm/intercept.c b/arch/s390/kvm/intercept.c
index 4c3311e41727..c0e6b49191ba 100644
--- a/arch/s390/kvm/intercept.c
+++ b/arch/s390/kvm/intercept.c
@@ -29,6 +29,7 @@ static const intercept_handler_t instruction_handlers[256] = {
29 [0x83] = kvm_s390_handle_diag, 29 [0x83] = kvm_s390_handle_diag,
30 [0xae] = kvm_s390_handle_sigp, 30 [0xae] = kvm_s390_handle_sigp,
31 [0xb2] = kvm_s390_handle_b2, 31 [0xb2] = kvm_s390_handle_b2,
32 [0xb6] = kvm_s390_handle_stctl,
32 [0xb7] = kvm_s390_handle_lctl, 33 [0xb7] = kvm_s390_handle_lctl,
33 [0xb9] = kvm_s390_handle_b9, 34 [0xb9] = kvm_s390_handle_b9,
34 [0xe5] = kvm_s390_handle_e5, 35 [0xe5] = kvm_s390_handle_e5,
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index ae7c1265fcc1..7ae8c26065fb 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -52,6 +52,8 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
52 { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) }, 52 { "exit_instr_and_program_int", VCPU_STAT(exit_instr_and_program) },
53 { "instruction_lctlg", VCPU_STAT(instruction_lctlg) }, 53 { "instruction_lctlg", VCPU_STAT(instruction_lctlg) },
54 { "instruction_lctl", VCPU_STAT(instruction_lctl) }, 54 { "instruction_lctl", VCPU_STAT(instruction_lctl) },
55 { "instruction_stctl", VCPU_STAT(instruction_stctl) },
56 { "instruction_stctg", VCPU_STAT(instruction_stctg) },
55 { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) }, 57 { "deliver_emergency_signal", VCPU_STAT(deliver_emergency_signal) },
56 { "deliver_external_call", VCPU_STAT(deliver_external_call) }, 58 { "deliver_external_call", VCPU_STAT(deliver_external_call) },
57 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) }, 59 { "deliver_service_signal", VCPU_STAT(deliver_service_signal) },
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index dc506f3782ea..5f00fc1e9785 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -147,6 +147,7 @@ int kvm_s390_handle_e5(struct kvm_vcpu *vcpu);
147int kvm_s390_handle_01(struct kvm_vcpu *vcpu); 147int kvm_s390_handle_01(struct kvm_vcpu *vcpu);
148int kvm_s390_handle_b9(struct kvm_vcpu *vcpu); 148int kvm_s390_handle_b9(struct kvm_vcpu *vcpu);
149int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu); 149int kvm_s390_handle_lpsw(struct kvm_vcpu *vcpu);
150int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu);
150int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu); 151int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu);
151int kvm_s390_handle_eb(struct kvm_vcpu *vcpu); 152int kvm_s390_handle_eb(struct kvm_vcpu *vcpu);
152 153
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 5fb503a6c443..27f9051a78f8 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -789,6 +789,42 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
789 return 0; 789 return 0;
790} 790}
791 791
792int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
793{
794 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
795 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
796 u64 ga;
797 u32 val;
798 int reg, rc;
799
800 vcpu->stat.instruction_stctl++;
801
802 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
803 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
804
805 ga = kvm_s390_get_base_disp_rs(vcpu);
806
807 if (ga & 3)
808 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
809
810 VCPU_EVENT(vcpu, 5, "stctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
811 trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga);
812
813 reg = reg1;
814 do {
815 val = vcpu->arch.sie_block->gcr[reg] & 0x00000000fffffffful;
816 rc = write_guest(vcpu, ga, &val, sizeof(val));
817 if (rc)
818 return kvm_s390_inject_prog_cond(vcpu, rc);
819 ga += 4;
820 if (reg == reg3)
821 break;
822 reg = (reg + 1) % 16;
823 } while (1);
824
825 return 0;
826}
827
792static int handle_lctlg(struct kvm_vcpu *vcpu) 828static int handle_lctlg(struct kvm_vcpu *vcpu)
793{ 829{
794 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 830 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
@@ -825,8 +861,45 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
825 return 0; 861 return 0;
826} 862}
827 863
864static int handle_stctg(struct kvm_vcpu *vcpu)
865{
866 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
867 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
868 u64 ga, val;
869 int reg, rc;
870
871 vcpu->stat.instruction_stctg++;
872
873 if (vcpu->arch.sie_block->gpsw.mask & PSW_MASK_PSTATE)
874 return kvm_s390_inject_program_int(vcpu, PGM_PRIVILEGED_OP);
875
876 ga = kvm_s390_get_base_disp_rsy(vcpu);
877
878 if (ga & 7)
879 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
880
881 reg = reg1;
882
883 VCPU_EVENT(vcpu, 5, "stctg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
884 trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga);
885
886 do {
887 val = vcpu->arch.sie_block->gcr[reg];
888 rc = write_guest(vcpu, ga, &val, sizeof(val));
889 if (rc)
890 return kvm_s390_inject_prog_cond(vcpu, rc);
891 ga += 8;
892 if (reg == reg3)
893 break;
894 reg = (reg + 1) % 16;
895 } while (1);
896
897 return 0;
898}
899
828static const intercept_handler_t eb_handlers[256] = { 900static const intercept_handler_t eb_handlers[256] = {
829 [0x2f] = handle_lctlg, 901 [0x2f] = handle_lctlg,
902 [0x25] = handle_stctg,
830}; 903};
831 904
832int kvm_s390_handle_eb(struct kvm_vcpu *vcpu) 905int kvm_s390_handle_eb(struct kvm_vcpu *vcpu)
diff --git a/arch/s390/kvm/trace.h b/arch/s390/kvm/trace.h
index a4bf7d78a0db..abf6ba52769e 100644
--- a/arch/s390/kvm/trace.h
+++ b/arch/s390/kvm/trace.h
@@ -315,6 +315,31 @@ TRACE_EVENT(kvm_s390_handle_lctl,
315 __entry->reg1, __entry->reg3, __entry->addr) 315 __entry->reg1, __entry->reg3, __entry->addr)
316 ); 316 );
317 317
318TRACE_EVENT(kvm_s390_handle_stctl,
319 TP_PROTO(VCPU_PROTO_COMMON, int g, int reg1, int reg3, u64 addr),
320 TP_ARGS(VCPU_ARGS_COMMON, g, reg1, reg3, addr),
321
322 TP_STRUCT__entry(
323 VCPU_FIELD_COMMON
324 __field(int, g)
325 __field(int, reg1)
326 __field(int, reg3)
327 __field(u64, addr)
328 ),
329
330 TP_fast_assign(
331 VCPU_ASSIGN_COMMON
332 __entry->g = g;
333 __entry->reg1 = reg1;
334 __entry->reg3 = reg3;
335 __entry->addr = addr;
336 ),
337
338 VCPU_TP_PRINTK("%s: storing cr %x-%x to %016llx",
339 __entry->g ? "stctg" : "stctl",
340 __entry->reg1, __entry->reg3, __entry->addr)
341 );
342
318TRACE_EVENT(kvm_s390_handle_prefix, 343TRACE_EVENT(kvm_s390_handle_prefix,
319 TP_PROTO(VCPU_PROTO_COMMON, int set, u32 address), 344 TP_PROTO(VCPU_PROTO_COMMON, int set, u32 address),
320 TP_ARGS(VCPU_ARGS_COMMON, set, address), 345 TP_ARGS(VCPU_ARGS_COMMON, set, address),