aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/virtual/kvm/devices/vm.txt10
-rw-r--r--arch/s390/kvm/gaccess.c20
-rw-r--r--arch/s390/kvm/priv.c72
3 files changed, 53 insertions, 49 deletions
diff --git a/Documentation/virtual/kvm/devices/vm.txt b/Documentation/virtual/kvm/devices/vm.txt
index 0d16f96c0eac..d426fc87fe93 100644
--- a/Documentation/virtual/kvm/devices/vm.txt
+++ b/Documentation/virtual/kvm/devices/vm.txt
@@ -12,14 +12,14 @@ specific.
121. GROUP: KVM_S390_VM_MEM_CTRL 121. GROUP: KVM_S390_VM_MEM_CTRL
13Architectures: s390 13Architectures: s390
14 14
151.1. ATTRIBUTE: KVM_S390_VM_MEM_CTRL 151.1. ATTRIBUTE: KVM_S390_VM_MEM_ENABLE_CMMA
16Parameters: none 16Parameters: none
17Returns: -EBUSY if already a vcpus is defined, otherwise 0 17Returns: -EBUSY if a vcpu is already defined, otherwise 0
18 18
19Enables CMMA for the virtual machine 19Enables Collaborative Memory Management Assist (CMMA) for the virtual machine.
20 20
211.2. ATTRIBUTE: KVM_S390_VM_CLR_CMMA 211.2. ATTRIBUTE: KVM_S390_VM_MEM_CLR_CMMA
22Parameteres: none 22Parameters: none
23Returns: 0 23Returns: 0
24 24
25Clear the CMMA status for all guest pages, so any pages the guest marked 25Clear the CMMA status for all guest pages, so any pages the guest marked
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index c1424e8b7f09..8b9ccf02a2c5 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -227,10 +227,12 @@ static void ipte_lock_simple(struct kvm_vcpu *vcpu)
227 goto out; 227 goto out;
228 ic = &vcpu->kvm->arch.sca->ipte_control; 228 ic = &vcpu->kvm->arch.sca->ipte_control;
229 do { 229 do {
230 old = ACCESS_ONCE(*ic); 230 old = *ic;
231 barrier();
231 while (old.k) { 232 while (old.k) {
232 cond_resched(); 233 cond_resched();
233 old = ACCESS_ONCE(*ic); 234 old = *ic;
235 barrier();
234 } 236 }
235 new = old; 237 new = old;
236 new.k = 1; 238 new.k = 1;
@@ -249,7 +251,9 @@ static void ipte_unlock_simple(struct kvm_vcpu *vcpu)
249 goto out; 251 goto out;
250 ic = &vcpu->kvm->arch.sca->ipte_control; 252 ic = &vcpu->kvm->arch.sca->ipte_control;
251 do { 253 do {
252 new = old = ACCESS_ONCE(*ic); 254 old = *ic;
255 barrier();
256 new = old;
253 new.k = 0; 257 new.k = 0;
254 } while (cmpxchg(&ic->val, old.val, new.val) != old.val); 258 } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
255 wake_up(&vcpu->kvm->arch.ipte_wq); 259 wake_up(&vcpu->kvm->arch.ipte_wq);
@@ -263,10 +267,12 @@ static void ipte_lock_siif(struct kvm_vcpu *vcpu)
263 267
264 ic = &vcpu->kvm->arch.sca->ipte_control; 268 ic = &vcpu->kvm->arch.sca->ipte_control;
265 do { 269 do {
266 old = ACCESS_ONCE(*ic); 270 old = *ic;
271 barrier();
267 while (old.kg) { 272 while (old.kg) {
268 cond_resched(); 273 cond_resched();
269 old = ACCESS_ONCE(*ic); 274 old = *ic;
275 barrier();
270 } 276 }
271 new = old; 277 new = old;
272 new.k = 1; 278 new.k = 1;
@@ -280,7 +286,9 @@ static void ipte_unlock_siif(struct kvm_vcpu *vcpu)
280 286
281 ic = &vcpu->kvm->arch.sca->ipte_control; 287 ic = &vcpu->kvm->arch.sca->ipte_control;
282 do { 288 do {
283 new = old = ACCESS_ONCE(*ic); 289 old = *ic;
290 barrier();
291 new = old;
284 new.kh--; 292 new.kh--;
285 if (!new.kh) 293 if (!new.kh)
286 new.k = 0; 294 new.k = 0;
diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index 72bb2dd8b9cd..9bde32f66eb5 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -762,8 +762,8 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
762{ 762{
763 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 763 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
764 int reg3 = vcpu->arch.sie_block->ipa & 0x000f; 764 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
765 u32 val = 0; 765 int reg, rc, nr_regs;
766 int reg, rc; 766 u32 ctl_array[16];
767 u64 ga; 767 u64 ga;
768 768
769 vcpu->stat.instruction_lctl++; 769 vcpu->stat.instruction_lctl++;
@@ -779,19 +779,20 @@ int kvm_s390_handle_lctl(struct kvm_vcpu *vcpu)
779 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga); 779 VCPU_EVENT(vcpu, 5, "lctl r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
780 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga); 780 trace_kvm_s390_handle_lctl(vcpu, 0, reg1, reg3, ga);
781 781
782 nr_regs = ((reg3 - reg1) & 0xf) + 1;
783 rc = read_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u32));
784 if (rc)
785 return kvm_s390_inject_prog_cond(vcpu, rc);
782 reg = reg1; 786 reg = reg1;
787 nr_regs = 0;
783 do { 788 do {
784 rc = read_guest(vcpu, ga, &val, sizeof(val));
785 if (rc)
786 return kvm_s390_inject_prog_cond(vcpu, rc);
787 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul; 789 vcpu->arch.sie_block->gcr[reg] &= 0xffffffff00000000ul;
788 vcpu->arch.sie_block->gcr[reg] |= val; 790 vcpu->arch.sie_block->gcr[reg] |= ctl_array[nr_regs++];
789 ga += 4;
790 if (reg == reg3) 791 if (reg == reg3)
791 break; 792 break;
792 reg = (reg + 1) % 16; 793 reg = (reg + 1) % 16;
793 } while (1); 794 } while (1);
794 795 kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
795 return 0; 796 return 0;
796} 797}
797 798
@@ -799,9 +800,9 @@ int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
799{ 800{
800 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 801 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
801 int reg3 = vcpu->arch.sie_block->ipa & 0x000f; 802 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
803 int reg, rc, nr_regs;
804 u32 ctl_array[16];
802 u64 ga; 805 u64 ga;
803 u32 val;
804 int reg, rc;
805 806
806 vcpu->stat.instruction_stctl++; 807 vcpu->stat.instruction_stctl++;
807 808
@@ -817,26 +818,24 @@ int kvm_s390_handle_stctl(struct kvm_vcpu *vcpu)
817 trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga); 818 trace_kvm_s390_handle_stctl(vcpu, 0, reg1, reg3, ga);
818 819
819 reg = reg1; 820 reg = reg1;
821 nr_regs = 0;
820 do { 822 do {
821 val = vcpu->arch.sie_block->gcr[reg] & 0x00000000fffffffful; 823 ctl_array[nr_regs++] = vcpu->arch.sie_block->gcr[reg];
822 rc = write_guest(vcpu, ga, &val, sizeof(val));
823 if (rc)
824 return kvm_s390_inject_prog_cond(vcpu, rc);
825 ga += 4;
826 if (reg == reg3) 824 if (reg == reg3)
827 break; 825 break;
828 reg = (reg + 1) % 16; 826 reg = (reg + 1) % 16;
829 } while (1); 827 } while (1);
830 828 rc = write_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u32));
831 return 0; 829 return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
832} 830}
833 831
834static int handle_lctlg(struct kvm_vcpu *vcpu) 832static int handle_lctlg(struct kvm_vcpu *vcpu)
835{ 833{
836 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 834 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
837 int reg3 = vcpu->arch.sie_block->ipa & 0x000f; 835 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
838 u64 ga, val; 836 int reg, rc, nr_regs;
839 int reg, rc; 837 u64 ctl_array[16];
838 u64 ga;
840 839
841 vcpu->stat.instruction_lctlg++; 840 vcpu->stat.instruction_lctlg++;
842 841
@@ -848,22 +847,22 @@ static int handle_lctlg(struct kvm_vcpu *vcpu)
848 if (ga & 7) 847 if (ga & 7)
849 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 848 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
850 849
851 reg = reg1;
852
853 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga); 850 VCPU_EVENT(vcpu, 5, "lctlg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
854 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga); 851 trace_kvm_s390_handle_lctl(vcpu, 1, reg1, reg3, ga);
855 852
853 nr_regs = ((reg3 - reg1) & 0xf) + 1;
854 rc = read_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u64));
855 if (rc)
856 return kvm_s390_inject_prog_cond(vcpu, rc);
857 reg = reg1;
858 nr_regs = 0;
856 do { 859 do {
857 rc = read_guest(vcpu, ga, &val, sizeof(val)); 860 vcpu->arch.sie_block->gcr[reg] = ctl_array[nr_regs++];
858 if (rc)
859 return kvm_s390_inject_prog_cond(vcpu, rc);
860 vcpu->arch.sie_block->gcr[reg] = val;
861 ga += 8;
862 if (reg == reg3) 861 if (reg == reg3)
863 break; 862 break;
864 reg = (reg + 1) % 16; 863 reg = (reg + 1) % 16;
865 } while (1); 864 } while (1);
866 865 kvm_make_request(KVM_REQ_TLB_FLUSH, vcpu);
867 return 0; 866 return 0;
868} 867}
869 868
@@ -871,8 +870,9 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
871{ 870{
872 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4; 871 int reg1 = (vcpu->arch.sie_block->ipa & 0x00f0) >> 4;
873 int reg3 = vcpu->arch.sie_block->ipa & 0x000f; 872 int reg3 = vcpu->arch.sie_block->ipa & 0x000f;
874 u64 ga, val; 873 int reg, rc, nr_regs;
875 int reg, rc; 874 u64 ctl_array[16];
875 u64 ga;
876 876
877 vcpu->stat.instruction_stctg++; 877 vcpu->stat.instruction_stctg++;
878 878
@@ -884,23 +884,19 @@ static int handle_stctg(struct kvm_vcpu *vcpu)
884 if (ga & 7) 884 if (ga & 7)
885 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION); 885 return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
886 886
887 reg = reg1;
888
889 VCPU_EVENT(vcpu, 5, "stctg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga); 887 VCPU_EVENT(vcpu, 5, "stctg r1:%x, r3:%x, addr:%llx", reg1, reg3, ga);
890 trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga); 888 trace_kvm_s390_handle_stctl(vcpu, 1, reg1, reg3, ga);
891 889
890 reg = reg1;
891 nr_regs = 0;
892 do { 892 do {
893 val = vcpu->arch.sie_block->gcr[reg]; 893 ctl_array[nr_regs++] = vcpu->arch.sie_block->gcr[reg];
894 rc = write_guest(vcpu, ga, &val, sizeof(val));
895 if (rc)
896 return kvm_s390_inject_prog_cond(vcpu, rc);
897 ga += 8;
898 if (reg == reg3) 894 if (reg == reg3)
899 break; 895 break;
900 reg = (reg + 1) % 16; 896 reg = (reg + 1) % 16;
901 } while (1); 897 } while (1);
902 898 rc = write_guest(vcpu, ga, ctl_array, nr_regs * sizeof(u64));
903 return 0; 899 return rc ? kvm_s390_inject_prog_cond(vcpu, rc) : 0;
904} 900}
905 901
906static const intercept_handler_t eb_handlers[256] = { 902static const intercept_handler_t eb_handlers[256] = {