Merge tag 'kvm-s390-next-5.9-1' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorPaolo Bonzini <pbonzini@redhat.com>
Mon, 3 Aug 2020 18:19:13 +0000 (14:19 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Mon, 3 Aug 2020 18:19:13 +0000 (14:19 -0400)
KVM: s390: Enhancement for 5.9
- implement diagnose 318

1  2 
arch/s390/include/asm/kvm_host.h
arch/s390/kvm/kvm-s390.c
include/uapi/linux/kvm.h

  #define KVM_USER_MEM_SLOTS 32
  
  /*
 - * These seem to be used for allocating ->chip in the routing table,
 - * which we don't use. 4096 is an out-of-thin-air value. If we need
 - * to look at ->chip later on, we'll need to revisit this.
 + * These seem to be used for allocating ->chip in the routing table, which we
 + * don't use. 1 is as small as we can get to reduce the needed memory. If we
 + * need to look at ->chip later on, we'll need to revisit this.
   */
  #define KVM_NR_IRQCHIPS 1
 -#define KVM_IRQCHIP_NUM_PINS 4096
 +#define KVM_IRQCHIP_NUM_PINS 1
  #define KVM_HALT_POLL_NS_DEFAULT 50000
  
  /* s390-specific vcpu->requests bit members */
@@@ -260,7 -260,8 +260,8 @@@ struct kvm_s390_sie_block 
        __u32   scaol;                  /* 0x0064 */
        __u8    sdf;                    /* 0x0068 */
        __u8    epdx;                   /* 0x0069 */
-       __u8    reserved6a[2];          /* 0x006a */
+       __u8    cpnc;                   /* 0x006a */
+       __u8    reserved6b;             /* 0x006b */
        __u32   todpr;                  /* 0x006c */
  #define GISA_FORMAT1 0x00000001
        __u32   gd;                     /* 0x0070 */
@@@ -745,6 -746,7 +746,7 @@@ struct kvm_vcpu_arch 
        bool gs_enabled;
        bool skey_enabled;
        struct kvm_s390_pv_vcpu pv;
+       union diag318_info diag318_info;
  };
  
  struct kvm_vm_stat {
diff --combined arch/s390/kvm/kvm-s390.c
@@@ -545,6 -545,7 +545,7 @@@ int kvm_vm_ioctl_check_extension(struc
        case KVM_CAP_S390_AIS_MIGRATION:
        case KVM_CAP_S390_VCPU_RESETS:
        case KVM_CAP_SET_GUEST_DEBUG:
+       case KVM_CAP_S390_DIAG318:
                r = 1;
                break;
        case KVM_CAP_S390_HPAGE_1M:
@@@ -3267,7 -3268,8 +3268,8 @@@ int kvm_arch_vcpu_create(struct kvm_vcp
                                    KVM_SYNC_ACRS |
                                    KVM_SYNC_CRS |
                                    KVM_SYNC_ARCH0 |
-                                   KVM_SYNC_PFAULT;
+                                   KVM_SYNC_PFAULT |
+                                   KVM_SYNC_DIAG318;
        kvm_s390_set_prefix(vcpu, 0);
        if (test_kvm_facility(vcpu->kvm, 64))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
@@@ -3562,6 -3564,7 +3564,7 @@@ static void kvm_arch_vcpu_ioctl_initial
                vcpu->arch.sie_block->pp = 0;
                vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
                vcpu->arch.sie_block->todpr = 0;
+               vcpu->arch.sie_block->cpnc = 0;
        }
  }
  
@@@ -3579,6 -3582,7 +3582,7 @@@ static void kvm_arch_vcpu_ioctl_clear_r
  
        regs->etoken = 0;
        regs->etoken_extension = 0;
+       regs->diag318 = 0;
  }
  
  int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs)
@@@ -3954,31 -3958,33 +3958,31 @@@ bool kvm_arch_can_dequeue_async_page_pr
        return true;
  }
  
 -static int kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
 +static bool kvm_arch_setup_async_pf(struct kvm_vcpu *vcpu)
  {
        hva_t hva;
        struct kvm_arch_async_pf arch;
 -      int rc;
  
        if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
 -              return 0;
 +              return false;
        if ((vcpu->arch.sie_block->gpsw.mask & vcpu->arch.pfault_select) !=
            vcpu->arch.pfault_compare)
 -              return 0;
 +              return false;
        if (psw_extint_disabled(vcpu))
 -              return 0;
 +              return false;
        if (kvm_s390_vcpu_has_irq(vcpu, 0))
 -              return 0;
 +              return false;
        if (!(vcpu->arch.sie_block->gcr[0] & CR0_SERVICE_SIGNAL_SUBMASK))
 -              return 0;
 +              return false;
        if (!vcpu->arch.gmap->pfault_enabled)
 -              return 0;
 +              return false;
  
        hva = gfn_to_hva(vcpu->kvm, gpa_to_gfn(current->thread.gmap_addr));
        hva += current->thread.gmap_addr & ~PAGE_MASK;
        if (read_guest_real(vcpu, vcpu->arch.pfault_token, &arch.pfault_token, 8))
 -              return 0;
 +              return false;
  
 -      rc = kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch);
 -      return rc;
 +      return kvm_setup_async_pf(vcpu, current->thread.gmap_addr, hva, &arch);
  }
  
  static int vcpu_pre_run(struct kvm_vcpu *vcpu)
@@@ -4173,9 -4179,8 +4177,9 @@@ static int __vcpu_run(struct kvm_vcpu *
        return rc;
  }
  
 -static void sync_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 +static void sync_regs_fmt2(struct kvm_vcpu *vcpu)
  {
 +      struct kvm_run *kvm_run = vcpu->run;
        struct runtime_instr_cb *riccb;
        struct gs_cb *gscb;
  
                if (vcpu->arch.pfault_token == KVM_S390_PFAULT_TOKEN_INVALID)
                        kvm_clear_async_pf_completion_queue(vcpu);
        }
+       if (kvm_run->kvm_dirty_regs & KVM_SYNC_DIAG318) {
+               vcpu->arch.diag318_info.val = kvm_run->s.regs.diag318;
+               vcpu->arch.sie_block->cpnc = vcpu->arch.diag318_info.cpnc;
+       }
        /*
         * If userspace sets the riccb (e.g. after migration) to a valid state,
         * we should enable RI here instead of doing the lazy enablement.
        /* SIE will load etoken directly from SDNX and therefore kvm_run */
  }
  
 -static void sync_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 +static void sync_regs(struct kvm_vcpu *vcpu)
  {
 +      struct kvm_run *kvm_run = vcpu->run;
 +
        if (kvm_run->kvm_dirty_regs & KVM_SYNC_PREFIX)
                kvm_s390_set_prefix(vcpu, kvm_run->s.regs.prefix);
        if (kvm_run->kvm_dirty_regs & KVM_SYNC_CRS) {
  
        /* Sync fmt2 only data */
        if (likely(!kvm_s390_pv_cpu_is_protected(vcpu))) {
 -              sync_regs_fmt2(vcpu, kvm_run);
 +              sync_regs_fmt2(vcpu);
        } else {
                /*
                 * In several places we have to modify our internal view to
        kvm_run->kvm_dirty_regs = 0;
  }
  
 -static void store_regs_fmt2(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 +static void store_regs_fmt2(struct kvm_vcpu *vcpu)
  {
 +      struct kvm_run *kvm_run = vcpu->run;
 +
        kvm_run->s.regs.todpr = vcpu->arch.sie_block->todpr;
        kvm_run->s.regs.pp = vcpu->arch.sie_block->pp;
        kvm_run->s.regs.gbea = vcpu->arch.sie_block->gbea;
        kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
+       kvm_run->s.regs.diag318 = vcpu->arch.diag318_info.val;
        if (MACHINE_HAS_GS) {
                __ctl_set_bit(2, 4);
                if (vcpu->arch.gs_enabled)
        /* SIE will save etoken directly into SDNX and therefore kvm_run */
  }
  
 -static void store_regs(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 +static void store_regs(struct kvm_vcpu *vcpu)
  {
 +      struct kvm_run *kvm_run = vcpu->run;
 +
        kvm_run->psw_mask = vcpu->arch.sie_block->gpsw.mask;
        kvm_run->psw_addr = vcpu->arch.sie_block->gpsw.addr;
        kvm_run->s.regs.prefix = kvm_s390_get_prefix(vcpu);
        current->thread.fpu.fpc = vcpu->arch.host_fpregs.fpc;
        current->thread.fpu.regs = vcpu->arch.host_fpregs.regs;
        if (likely(!kvm_s390_pv_cpu_is_protected(vcpu)))
 -              store_regs_fmt2(vcpu, kvm_run);
 +              store_regs_fmt2(vcpu);
  }
  
  int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu)
                goto out;
        }
  
 -      sync_regs(vcpu, kvm_run);
 +      sync_regs(vcpu);
        enable_cpu_timer_accounting(vcpu);
  
        might_fault();
        }
  
        disable_cpu_timer_accounting(vcpu);
 -      store_regs(vcpu, kvm_run);
 +      store_regs(vcpu);
  
        kvm_sigset_deactivate(vcpu);
  
diff --combined include/uapi/linux/kvm.h
@@@ -289,7 -289,6 +289,7 @@@ struct kvm_run 
                /* KVM_EXIT_FAIL_ENTRY */
                struct {
                        __u64 hardware_entry_failure_reason;
 +                      __u32 cpu;
                } fail_entry;
                /* KVM_EXIT_EXCEPTION */
                struct {
@@@ -1032,9 -1031,7 +1032,9 @@@ struct kvm_ppc_resize_hpt 
  #define KVM_CAP_PPC_SECURE_GUEST 181
  #define KVM_CAP_HALT_POLL 182
  #define KVM_CAP_ASYNC_PF_INT 183
 -#define KVM_CAP_S390_DIAG318 184
 +#define KVM_CAP_LAST_CPU 184
 +#define KVM_CAP_SMALLER_MAXPHYADDR 185
++#define KVM_CAP_S390_DIAG318 186
  
  #ifdef KVM_CAP_IRQ_ROUTING