Re: [PATCH 08/10] KVM: s390: add functions to (un)register GISC with GISA

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 25/10/2018 14:37, Michael Mueller wrote:
Add the IAM (Interruption Alert Mask) to the architectue specific
kvm struct. This mask in the GISA is used to define for which ISC
a GIB alert can be issued.

The functions kvm_s390_gisc_register() and kvm_s390_gisc_unregister()
are used to (un)register a GISC (guest ISC) with a virtual machine and
its GISA.

Upon successful completion, kvm_s390_gisc_register() returns the
ISC to be used for GIB alert interruptions. A negative return code
indicates an error during registration.

Signed-off-by: Michael Mueller <mimu@xxxxxxxxxxxxx>
---
  arch/s390/include/asm/kvm_host.h |  3 +++
  arch/s390/kvm/interrupt.c        | 44 ++++++++++++++++++++++++++++++++
  arch/s390/kvm/kvm-s390.h         |  2 ++
  3 files changed, 49 insertions(+)

diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index b5f671d7d167..d17ab17b5943 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -841,6 +841,9 @@ struct kvm_arch{
  	struct kvm_s390_gisa *gisa;
  	int gib_in_use;
  	atomic_t vcpus_in_sie;
+	u8 iam;
+	u32 iam_ref_count[MAX_ISC + 1];
+	spinlock_t iam_ref_lock;
  };

I think registering and unregistering functions should be defined here for external usage.

#define KVM_HVA_ERR_BAD (-1UL)
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 920c065ce1d3..799e232a0cc5 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -2950,6 +2950,8 @@ void kvm_s390_gisa_init(struct kvm *kvm)
  {
  	if (css_general_characteristics.aiv) {
  		kvm->arch.gisa = &kvm->arch.sie_page2->gisa;
+		kvm->arch.iam = 0;
+		spin_lock_init(&kvm->arch.iam_ref_lock);
  		VM_EVENT(kvm, 3, "gisa 0x%pK initialized", kvm->arch.gisa);
  		kvm_s390_gisa_clear(kvm);
  		kvm->arch.gib_in_use = !!gib;
@@ -2961,8 +2963,50 @@ void kvm_s390_gisa_destroy(struct kvm *kvm)
  	if (!kvm->arch.gisa)
  		return;
  	kvm->arch.gisa = NULL;
+	kvm->arch.iam = 0;
  }
+int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc)
+{
+	if (!kvm->arch.gib_in_use)
+		return -ENODEV;
+	if (gisc > MAX_ISC)
+		return -EINVAL;
+
+	spin_lock(&kvm->arch.iam_ref_lock);
+	if (kvm->arch.iam_ref_count[gisc] == 0)
+		kvm->arch.iam |= 0x80 >> gisc;
+	kvm->arch.iam_ref_count[gisc]++;
+	spin_unlock(&kvm->arch.iam_ref_lock);

I am not sure it brings something to handle multiple registrations per VM.
ISC are defined pro adapter types.
If we once will multiplex different types pro ISC we would certainly handle it through other means.

Not having it will simplify the code.

+
+	return gib->nisc;
+}

hum.
Will nisc change ?
It is hard coded in the call to kvm_s390_gib_init(GAL_ISC)

the NISC is a global value, if the only way to retrieve it is to register we need to keep it local in the space of the registering caller. I mean, registering to the GIB alert and registering an interruption are two different things and can be done in different functions.

Shouldn't we just need the GAL_ISC definition?


+EXPORT_SYMBOL_GPL(kvm_s390_gisc_register);
+
+int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc)
+{
+	int rc = 0;
+
+	if (!kvm->arch.gib_in_use)
+		return -ENODEV;
+	if (gisc > MAX_ISC)
+		return -EINVAL;
+
+	spin_lock(&kvm->arch.iam_ref_lock);
+	if (kvm->arch.iam_ref_count[gisc] == 0) {
+		rc = -EFAULT;
+		goto out;
+	}
+	kvm->arch.iam_ref_count[gisc]--;
+	if (kvm->arch.iam_ref_count[gisc] == 0)
+		kvm->arch.iam &= ~(0x80 >> gisc);

Here too the code would be much more simpler without multiple registrations per VM.


+out:
+	spin_unlock(&kvm->arch.iam_ref_lock);
+
+	return rc;
+}
+EXPORT_SYMBOL_GPL(kvm_s390_gisc_unregister);
+
  void kvm_s390_gib_destroy(void)
  {
  	if (!gib)
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 5983800d6433..be0daa1680fa 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -382,6 +382,8 @@ void kvm_s390_gisa_clear(struct kvm *kvm);
  void kvm_s390_gisa_destroy(struct kvm *kvm);
  void kvm_s390_gib_init(u8 nisc);
  void kvm_s390_gib_destroy(void);
+int kvm_s390_gisc_register(struct kvm *kvm, u32 gisc);
+int kvm_s390_gisc_unregister(struct kvm *kvm, u32 gisc);
/* implemented in guestdbg.c */
  void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);



--
Pierre Morel
Linux/KVM/QEMU in Böblingen - Germany




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Kernel Development]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Info]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Linux Media]     [Device Mapper]

  Powered by Linux