diff mbox series

[v3,12/12] KVM: s390: allow to change the IAM clear strategy dynamically

Message ID 20181128101943.155542-13-mimu@linux.ibm.com (mailing list archive)
State New, archived
Headers show
Series KVM: s390: make use of the GIB | expand

Commit Message

Michael Mueller Nov. 28, 2018, 10:19 a.m. UTC
The sysctl file /proc/sys/s390/iam_clear_strategy defines under which
condition the GISA IAM is cleared before entering the SIE in routine
vcpu_pre_run().

The following IAM clear strategies are available:

  0 : the mask is never cleared
  1 : the mask is cleared if I/O interruptions are not
      disabled by the PSW of the vcpu entering the SIE
  2 : the mask is unconditionally cleared

The default IAM clear strategy after system boot is 0.

Set the new strategy by means of the sysctl command or write to the file.

  sysctl s390.iam_clear_strategy=1
  echo 2 >/proc/sys/s390/iam_clear_strategy

Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
---
 arch/s390/kvm/interrupt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/s390/kvm/kvm-s390.c  |  1 +
 arch/s390/kvm/kvm-s390.h  |  1 +
 3 files changed, 71 insertions(+)

Comments

Michael Mueller Nov. 29, 2018, 9:42 a.m. UTC | #1
On 28.11.18 11:19, Michael Mueller wrote:
> The sysctl file /proc/sys/s390/iam_clear_strategy defines under which
> condition the GISA IAM is cleared before entering the SIE in routine
> vcpu_pre_run().
> 
> The following IAM clear strategies are available:
> 
>    0 : the mask is never cleared
>    1 : the mask is cleared if I/O interruptions are not
>        disabled by the PSW of the vcpu entering the SIE
>    2 : the mask is unconditionally cleared
> 
> The default IAM clear strategy after system boot is 0.
> 
> Set the new strategy by means of the sysctl command or write to the file.
> 
>    sysctl s390.iam_clear_strategy=1
>    echo 2 >/proc/sys/s390/iam_clear_strategy
> 
> Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
> ---
>   arch/s390/kvm/interrupt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
>   arch/s390/kvm/kvm-s390.c  |  1 +
>   arch/s390/kvm/kvm-s390.h  |  1 +
>   3 files changed, 71 insertions(+)
> 
> diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
> index dae78d91fa53..76fb37ed98f8 100644
> --- a/arch/s390/kvm/interrupt.c
> +++ b/arch/s390/kvm/interrupt.c
> @@ -33,6 +33,7 @@
>   #define VIRTIO_PARAM 0x0d00
>   
>   static struct kvm_s390_gib *gib;
> +static unsigned int iam_clear_strategy;
>   
>   /* handle external calls via sigp interpretation facility */
>   static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
> @@ -2895,6 +2896,73 @@ int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, __u8 __user *buf, int len)
>   	return n;
>   }
>   
> +static int iam_clear_strategy_ctl_handler(struct ctl_table *ctl, int write,
> +					  void __user *buffer, size_t *lenp,
> +					  loff_t *ppos)
> +{
> +	unsigned int strategy = iam_clear_strategy;
> +	unsigned int min = 0;
> +	unsigned int max = 2;
> +	int rc;
> +	struct ctl_table ctl_entry = {
> +		.procname	= ctl->procname,
> +		.data		= &strategy,
> +		.maxlen		= sizeof(int),
> +		.extra1		= &min,
> +		.extra2		= &max,
> +	};
> +
> +	rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
> +	if (rc < 0 || !write)
> +		return rc;
> +
> +	if (iam_clear_strategy != strategy)
> +		iam_clear_strategy = strategy;
> +
> +	return rc;
> +}
> +
> +static struct ctl_table iam_clear_strategy_ctl_table[] = {
> +	{
> +		.procname	= "iam_clear_strategy",
> +		.mode		= 0644,
> +		.proc_handler	= iam_clear_strategy_ctl_handler,
> +	},
> +	{ },
> +};
> +
> +static struct ctl_table s390_dir_table[] = {
> +	{
> +		.procname	= "s390",
> +		.maxlen		= 0,
> +		.mode		= 0555,
> +		.child		= iam_clear_strategy_ctl_table,
> +	},
> +	{ },
> +};
> +
> +void kvm_s390_try_clear_iam(struct kvm_vcpu *vcpu)
> +{
> +	if (!vcpu->kvm->arch.gib_in_use)
> +		return;
> +
> +	switch (iam_clear_strategy) {
> +	case 0: /* never clear IAM on SIE entry */
> +		return;
> +	case 1: /*
> +		 * clear IAM on SIE entry when I/O interruptions
> +		 * are not disabled by the vcpu PSW
> +		 */
> +		if (psw_ioint_disabled(vcpu))
> +			return;
> +	case 2: /* always clear IAM on SIE entry */
> +		vcpu->kvm->arch.gisa->iam = 0;
> +		return;
> +	default:
> +		break;
> +	}
> +}
> +
>   static void nullify_gisa(struct kvm_s390_gisa *gisa)
>   {
>   	memset(gisa, 0, sizeof(struct kvm_s390_gisa));
> @@ -3078,6 +3146,7 @@ int kvm_s390_gib_init(u8 nisc)
>   		goto out_unreg;
>   	}
>   
> +	register_sysctl_table(s390_dir_table);
>   	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
>   	return rc;

Unregistering should be done is well...

@@ -3044,6 +3112,7 @@ void kvm_s390_gib_destroy(void)
                 return;
         chsc_sgib(0);
         unregister_adapter_interrupt(&gib_alert_irq);
+       unregister_sysctl_table(s390_dir_table);
         free_page((unsigned long)gib);
         gib = NULL;

>   
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 9b20017dda29..0b34be612172 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -3474,6 +3474,7 @@ static int vcpu_pre_run(struct kvm_vcpu *vcpu)
>   	}
>   
>   	atomic_inc(&vcpu->kvm->arch.vcpus_in_sie);
> +	kvm_s390_try_clear_iam(vcpu);
>   
>   	vcpu->arch.sie_block->icptcode = 0;
>   	cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
> diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
> index 1c93ceaeb9e4..09fa5a559858 100644
> --- a/arch/s390/kvm/kvm-s390.h
> +++ b/arch/s390/kvm/kvm-s390.h
> @@ -388,6 +388,7 @@ void kvm_s390_gisa_clear(struct kvm *kvm);
>   void kvm_s390_gisa_destroy(struct kvm *kvm);
>   int kvm_s390_gib_init(u8 nisc);
>   void kvm_s390_gib_destroy(void);
> +void kvm_s390_try_clear_iam(struct kvm_vcpu *vcpu);
>   
>   /* implemented in guestdbg.c */
>   void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);
>
Cornelia Huck Nov. 29, 2018, 12:38 p.m. UTC | #2
On Wed, 28 Nov 2018 11:19:43 +0100
Michael Mueller <mimu@linux.ibm.com> wrote:

> The sysctl file /proc/sys/s390/iam_clear_strategy defines under which
> condition the GISA IAM is cleared before entering the SIE in routine
> vcpu_pre_run().
> 
> The following IAM clear strategies are available:
> 
>   0 : the mask is never cleared
>   1 : the mask is cleared if I/O interruptions are not
>       disabled by the PSW of the vcpu entering the SIE
>   2 : the mask is unconditionally cleared
> 
> The default IAM clear strategy after system boot is 0.
> 
> Set the new strategy by means of the sysctl command or write to the file.
> 
>   sysctl s390.iam_clear_strategy=1
>   echo 2 >/proc/sys/s390/iam_clear_strategy

This wants some documentation, I think. How is the admin supposed to
know which strategy to choose?

> 
> Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
> ---
>  arch/s390/kvm/interrupt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
>  arch/s390/kvm/kvm-s390.c  |  1 +
>  arch/s390/kvm/kvm-s390.h  |  1 +
>  3 files changed, 71 insertions(+)
Michael Mueller Nov. 30, 2018, 1:17 p.m. UTC | #3
On 29.11.18 13:38, Cornelia Huck wrote:
> On Wed, 28 Nov 2018 11:19:43 +0100
> Michael Mueller <mimu@linux.ibm.com> wrote:
> 
>> The sysctl file /proc/sys/s390/iam_clear_strategy defines under which
>> condition the GISA IAM is cleared before entering the SIE in routine
>> vcpu_pre_run().
>>
>> The following IAM clear strategies are available:
>>
>>    0 : the mask is never cleared
>>    1 : the mask is cleared if I/O interruptions are not
>>        disabled by the PSW of the vcpu entering the SIE
>>    2 : the mask is unconditionally cleared
>>
>> The default IAM clear strategy after system boot is 0.
>>
>> Set the new strategy by means of the sysctl command or write to the file.
>>
>>    sysctl s390.iam_clear_strategy=1
>>    echo 2 >/proc/sys/s390/iam_clear_strategy
> 
> This wants some documentation, I think. How is the admin supposed to
> know which strategy to choose?

The patch will be dropped. The strategy will not be changeable by
an admin. The IAM will never be cleared by the host program during
normal operation except for the GISA clear and GISA drop cases.

> 
>>
>> Signed-off-by: Michael Mueller <mimu@linux.ibm.com>
>> ---
>>   arch/s390/kvm/interrupt.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++
>>   arch/s390/kvm/kvm-s390.c  |  1 +
>>   arch/s390/kvm/kvm-s390.h  |  1 +
>>   3 files changed, 71 insertions(+)
>
diff mbox series

Patch

diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index dae78d91fa53..76fb37ed98f8 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -33,6 +33,7 @@ 
 #define VIRTIO_PARAM 0x0d00
 
 static struct kvm_s390_gib *gib;
+static unsigned int iam_clear_strategy;
 
 /* handle external calls via sigp interpretation facility */
 static int sca_ext_call_pending(struct kvm_vcpu *vcpu, int *src_id)
@@ -2895,6 +2896,73 @@  int kvm_s390_get_irq_state(struct kvm_vcpu *vcpu, __u8 __user *buf, int len)
 	return n;
 }
 
+static int iam_clear_strategy_ctl_handler(struct ctl_table *ctl, int write,
+					  void __user *buffer, size_t *lenp,
+					  loff_t *ppos)
+{
+	unsigned int strategy = iam_clear_strategy;
+	unsigned int min = 0;
+	unsigned int max = 2;
+	int rc;
+	struct ctl_table ctl_entry = {
+		.procname	= ctl->procname,
+		.data		= &strategy,
+		.maxlen		= sizeof(int),
+		.extra1		= &min,
+		.extra2		= &max,
+	};
+
+	rc = proc_douintvec_minmax(&ctl_entry, write, buffer, lenp, ppos);
+	if (rc < 0 || !write)
+		return rc;
+
+	if (iam_clear_strategy != strategy)
+		iam_clear_strategy = strategy;
+
+	return rc;
+}
+
+static struct ctl_table iam_clear_strategy_ctl_table[] = {
+	{
+		.procname	= "iam_clear_strategy",
+		.mode		= 0644,
+		.proc_handler	= iam_clear_strategy_ctl_handler,
+	},
+	{ },
+};
+
+static struct ctl_table s390_dir_table[] = {
+	{
+		.procname	= "s390",
+		.maxlen		= 0,
+		.mode		= 0555,
+		.child		= iam_clear_strategy_ctl_table,
+	},
+	{ },
+};
+
+void kvm_s390_try_clear_iam(struct kvm_vcpu *vcpu)
+{
+	if (!vcpu->kvm->arch.gib_in_use)
+		return;
+
+	switch (iam_clear_strategy) {
+	case 0: /* never clear IAM on SIE entry */
+		return;
+	case 1: /*
+		 * clear IAM on SIE entry when I/O interruptions
+		 * are not disabled by the vcpu PSW
+		 */
+		if (psw_ioint_disabled(vcpu))
+			return;
+	case 2: /* always clear IAM on SIE entry */
+		vcpu->kvm->arch.gisa->iam = 0;
+		return;
+	default:
+		break;
+	}
+}
+
 static void nullify_gisa(struct kvm_s390_gisa *gisa)
 {
 	memset(gisa, 0, sizeof(struct kvm_s390_gisa));
@@ -3078,6 +3146,7 @@  int kvm_s390_gib_init(u8 nisc)
 		goto out_unreg;
 	}
 
+	register_sysctl_table(s390_dir_table);
 	KVM_EVENT(3, "gib 0x%pK (nisc=%d) initialized", gib, gib->nisc);
 	return rc;
 
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 9b20017dda29..0b34be612172 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -3474,6 +3474,7 @@  static int vcpu_pre_run(struct kvm_vcpu *vcpu)
 	}
 
 	atomic_inc(&vcpu->kvm->arch.vcpus_in_sie);
+	kvm_s390_try_clear_iam(vcpu);
 
 	vcpu->arch.sie_block->icptcode = 0;
 	cpuflags = atomic_read(&vcpu->arch.sie_block->cpuflags);
diff --git a/arch/s390/kvm/kvm-s390.h b/arch/s390/kvm/kvm-s390.h
index 1c93ceaeb9e4..09fa5a559858 100644
--- a/arch/s390/kvm/kvm-s390.h
+++ b/arch/s390/kvm/kvm-s390.h
@@ -388,6 +388,7 @@  void kvm_s390_gisa_clear(struct kvm *kvm);
 void kvm_s390_gisa_destroy(struct kvm *kvm);
 int kvm_s390_gib_init(u8 nisc);
 void kvm_s390_gib_destroy(void);
+void kvm_s390_try_clear_iam(struct kvm_vcpu *vcpu);
 
 /* implemented in guestdbg.c */
 void kvm_s390_backup_guest_per_regs(struct kvm_vcpu *vcpu);