]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/s390/kvm/gaccess.c
Merge branch 'fsnotify' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
[karo-tx-linux.git] / arch / s390 / kvm / gaccess.c
index 4aa8a7e2a1da479c8e33162814d1e9f1a4908952..ddbffb715b40fd27a705396ffcd2221af74bab26 100644 (file)
@@ -6,7 +6,9 @@
  */
 
 #include <linux/vmalloc.h>
+#include <linux/mm_types.h>
 #include <linux/err.h>
+
 #include <asm/pgtable.h>
 #include <asm/gmap.h>
 #include "kvm-s390.h"
@@ -166,8 +168,7 @@ union page_table_entry {
                unsigned long z  : 1; /* Zero Bit */
                unsigned long i  : 1; /* Page-Invalid Bit */
                unsigned long p  : 1; /* DAT-Protection Bit */
-               unsigned long co : 1; /* Change-Recording Override */
-               unsigned long    : 8;
+               unsigned long    : 9;
        };
 };
 
@@ -373,7 +374,7 @@ void ipte_unlock(struct kvm_vcpu *vcpu)
                ipte_unlock_simple(vcpu);
 }
 
-static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, ar_t ar,
+static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar,
                          enum gacc_mode mode)
 {
        union alet alet;
@@ -465,7 +466,9 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, ar_t ar,
 struct trans_exc_code_bits {
        unsigned long addr : 52; /* Translation-exception Address */
        unsigned long fsi  : 2;  /* Access Exception Fetch/Store Indication */
-       unsigned long      : 6;
+       unsigned long      : 2;
+       unsigned long b56  : 1;
+       unsigned long      : 3;
        unsigned long b60  : 1;
        unsigned long b61  : 1;
        unsigned long as   : 2;  /* ASCE Identifier */
@@ -485,7 +488,7 @@ enum prot_type {
 };
 
 static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
-                    ar_t ar, enum gacc_mode mode, enum prot_type prot)
+                    u8 ar, enum gacc_mode mode, enum prot_type prot)
 {
        struct kvm_s390_pgm_info *pgm = &vcpu->arch.pgm;
        struct trans_exc_code_bits *tec;
@@ -497,14 +500,18 @@ static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
        switch (code) {
        case PGM_PROTECTION:
                switch (prot) {
+               case PROT_TYPE_LA:
+                       tec->b56 = 1;
+                       break;
+               case PROT_TYPE_KEYC:
+                       tec->b60 = 1;
+                       break;
                case PROT_TYPE_ALC:
                        tec->b60 = 1;
                        /* FALL THROUGH */
                case PROT_TYPE_DAT:
                        tec->b61 = 1;
                        break;
-               default: /* LA and KEYC set b61 to 0, other params undefined */
-                       return code;
                }
                /* FALL THROUGH */
        case PGM_ASCE_TYPE:
@@ -539,7 +546,7 @@ static int trans_exc(struct kvm_vcpu *vcpu, int code, unsigned long gva,
 }
 
 static int get_vcpu_asce(struct kvm_vcpu *vcpu, union asce *asce,
-                        unsigned long ga, ar_t ar, enum gacc_mode mode)
+                        unsigned long ga, u8 ar, enum gacc_mode mode)
 {
        int rc;
        struct psw_bits psw = psw_bits(vcpu->arch.sie_block->gpsw);
@@ -737,8 +744,6 @@ static unsigned long guest_translate(struct kvm_vcpu *vcpu, unsigned long gva,
                return PGM_PAGE_TRANSLATION;
        if (pte.z)
                return PGM_TRANSLATION_SPEC;
-       if (pte.co && !edat1)
-               return PGM_TRANSLATION_SPEC;
        dat_protection |= pte.p;
        raddr.pfra = pte.pfra;
 real_address:
@@ -771,7 +776,7 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu,
        return 1;
 }
 
-static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar,
+static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar,
                            unsigned long *pages, unsigned long nr_pages,
                            const union asce asce, enum gacc_mode mode)
 {
@@ -803,7 +808,7 @@ static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar,
        return 0;
 }
 
-int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, ar_t ar, void *data,
+int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data,
                 unsigned long len, enum gacc_mode mode)
 {
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
@@ -877,7 +882,7 @@ int access_guest_real(struct kvm_vcpu *vcpu, unsigned long gra,
  * Note: The IPTE lock is not taken during this function, so the caller
  * has to take care of this.
  */
-int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
+int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
                            unsigned long *gpa, enum gacc_mode mode)
 {
        psw_t *psw = &vcpu->arch.sie_block->gpsw;
@@ -910,7 +915,7 @@ int guest_translate_address(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
 /**
  * check_gva_range - test a range of guest virtual addresses for accessibility
  */
-int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, ar_t ar,
+int check_gva_range(struct kvm_vcpu *vcpu, unsigned long gva, u8 ar,
                    unsigned long length, enum gacc_mode mode)
 {
        unsigned long gpa;
@@ -1174,7 +1179,7 @@ int kvm_s390_shadow_fault(struct kvm_vcpu *vcpu, struct gmap *sg,
                rc = gmap_read_table(sg->parent, pgt + vaddr.px * 8, &pte.val);
        if (!rc && pte.i)
                rc = PGM_PAGE_TRANSLATION;
-       if (!rc && (pte.z || (pte.co && sg->edat_level < 1)))
+       if (!rc && pte.z)
                rc = PGM_TRANSLATION_SPEC;
 shadow_page:
        pte.p |= dat_protection;