]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - arch/s390/kvm/guestdbg.c
Merge branch 'for-4.9-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[karo-tx-linux.git] / arch / s390 / kvm / guestdbg.c
index 31a05330d11c77fc0c34cd30ea54bc2075a2c3d9..d7c6a7f53cedb3b1694589d6644346570b12ea1b 100644 (file)
@@ -206,7 +206,7 @@ static int __import_wp_info(struct kvm_vcpu *vcpu,
 int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
                            struct kvm_guest_debug *dbg)
 {
-       int ret = 0, nr_wp = 0, nr_bp = 0, i, size;
+       int ret = 0, nr_wp = 0, nr_bp = 0, i;
        struct kvm_hw_breakpoint *bp_data = NULL;
        struct kvm_hw_wp_info_arch *wp_info = NULL;
        struct kvm_hw_bp_info_arch *bp_info = NULL;
@@ -216,17 +216,10 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
        else if (dbg->arch.nr_hw_bp > MAX_BP_COUNT)
                return -EINVAL;
 
-       size = dbg->arch.nr_hw_bp * sizeof(struct kvm_hw_breakpoint);
-       bp_data = kmalloc(size, GFP_KERNEL);
-       if (!bp_data) {
-               ret = -ENOMEM;
-               goto error;
-       }
-
-       if (copy_from_user(bp_data, dbg->arch.hw_bp, size)) {
-               ret = -EFAULT;
-               goto error;
-       }
+       bp_data = memdup_user(dbg->arch.hw_bp,
+                             sizeof(*bp_data) * dbg->arch.nr_hw_bp);
+       if (IS_ERR(bp_data))
+               return PTR_ERR(bp_data);
 
        for (i = 0; i < dbg->arch.nr_hw_bp; i++) {
                switch (bp_data[i].type) {
@@ -241,17 +234,19 @@ int kvm_s390_import_bp_data(struct kvm_vcpu *vcpu,
                }
        }
 
-       size = nr_wp * sizeof(struct kvm_hw_wp_info_arch);
-       if (size > 0) {
-               wp_info = kmalloc(size, GFP_KERNEL);
+       if (nr_wp > 0) {
+               wp_info = kmalloc_array(nr_wp,
+                                       sizeof(*wp_info),
+                                       GFP_KERNEL);
                if (!wp_info) {
                        ret = -ENOMEM;
                        goto error;
                }
        }
-       size = nr_bp * sizeof(struct kvm_hw_bp_info_arch);
-       if (size > 0) {
-               bp_info = kmalloc(size, GFP_KERNEL);
+       if (nr_bp > 0) {
+               bp_info = kmalloc_array(nr_bp,
+                                       sizeof(*bp_info),
+                                       GFP_KERNEL);
                if (!bp_info) {
                        ret = -ENOMEM;
                        goto error;
@@ -382,14 +377,20 @@ void kvm_s390_prepare_debug_exit(struct kvm_vcpu *vcpu)
        vcpu->guest_debug &= ~KVM_GUESTDBG_EXIT_PENDING;
 }
 
+#define PER_CODE_MASK          (PER_EVENT_MASK >> 24)
+#define PER_CODE_BRANCH                (PER_EVENT_BRANCH >> 24)
+#define PER_CODE_IFETCH                (PER_EVENT_IFETCH >> 24)
+#define PER_CODE_STORE         (PER_EVENT_STORE >> 24)
+#define PER_CODE_STORE_REAL    (PER_EVENT_STORE_REAL >> 24)
+
 #define per_bp_event(code) \
-                       (code & (PER_EVENT_IFETCH | PER_EVENT_BRANCH))
+                       (code & (PER_CODE_IFETCH | PER_CODE_BRANCH))
 #define per_write_wp_event(code) \
-                       (code & (PER_EVENT_STORE | PER_EVENT_STORE_REAL))
+                       (code & (PER_CODE_STORE | PER_CODE_STORE_REAL))
 
 static int debug_exit_required(struct kvm_vcpu *vcpu)
 {
-       u32 perc = (vcpu->arch.sie_block->perc << 24);
+       u8 perc = vcpu->arch.sie_block->perc;
        struct kvm_debug_exit_arch *debug_exit = &vcpu->run->debug.arch;
        struct kvm_hw_wp_info_arch *wp_info = NULL;
        struct kvm_hw_bp_info_arch *bp_info = NULL;
@@ -444,7 +445,7 @@ int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu)
        const u8 ilen = kvm_s390_get_ilen(vcpu);
        struct kvm_s390_pgm_info pgm_info = {
                .code = PGM_PER,
-               .per_code = PER_EVENT_IFETCH >> 24,
+               .per_code = PER_CODE_IFETCH,
                .per_address = __rewind_psw(vcpu->arch.sie_block->gpsw, ilen),
        };
 
@@ -458,33 +459,33 @@ int kvm_s390_handle_per_ifetch_icpt(struct kvm_vcpu *vcpu)
 
 static void filter_guest_per_event(struct kvm_vcpu *vcpu)
 {
-       u32 perc = vcpu->arch.sie_block->perc << 24;
+       const u8 perc = vcpu->arch.sie_block->perc;
        u64 peraddr = vcpu->arch.sie_block->peraddr;
        u64 addr = vcpu->arch.sie_block->gpsw.addr;
        u64 cr9 = vcpu->arch.sie_block->gcr[9];
        u64 cr10 = vcpu->arch.sie_block->gcr[10];
        u64 cr11 = vcpu->arch.sie_block->gcr[11];
        /* filter all events, demanded by the guest */
-       u32 guest_perc = perc & cr9 & PER_EVENT_MASK;
+       u8 guest_perc = perc & (cr9 >> 24) & PER_CODE_MASK;
 
        if (!guest_per_enabled(vcpu))
                guest_perc = 0;
 
        /* filter "successful-branching" events */
-       if (guest_perc & PER_EVENT_BRANCH &&
+       if (guest_perc & PER_CODE_BRANCH &&
            cr9 & PER_CONTROL_BRANCH_ADDRESS &&
            !in_addr_range(addr, cr10, cr11))
-               guest_perc &= ~PER_EVENT_BRANCH;
+               guest_perc &= ~PER_CODE_BRANCH;
 
        /* filter "instruction-fetching" events */
-       if (guest_perc & PER_EVENT_IFETCH &&
+       if (guest_perc & PER_CODE_IFETCH &&
            !in_addr_range(peraddr, cr10, cr11))
-               guest_perc &= ~PER_EVENT_IFETCH;
+               guest_perc &= ~PER_CODE_IFETCH;
 
        /* All other PER events will be given to the guest */
        /* TODO: Check altered address/address space */
 
-       vcpu->arch.sie_block->perc = guest_perc >> 24;
+       vcpu->arch.sie_block->perc = guest_perc;
 
        if (!guest_perc)
                vcpu->arch.sie_block->iprcc &= ~PGM_PER;