diff mbox series

[v2,24/42] KVM: s390: protvirt: STSI handling

Message ID 20200214222658.12946-25-borntraeger@de.ibm.com (mailing list archive)
State New, archived
Headers show
Series KVM: s390: Add support for protected VMs | expand

Commit Message

Christian Borntraeger Feb. 14, 2020, 10:26 p.m. UTC
From: Janosch Frank <frankja@linux.ibm.com>

Save response to sidad and disable address checking for protected
guests.

Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
Reviewed-by: Thomas Huth <thuth@redhat.com>
Reviewed-by: Cornelia Huck <cohuck@redhat.com>
[borntraeger@de.ibm.com: patch merging, splitting, fixing]
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
---
 arch/s390/kvm/priv.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

Comments

David Hildenbrand Feb. 18, 2020, 8:35 a.m. UTC | #1
On 14.02.20 23:26, Christian Borntraeger wrote:
> From: Janosch Frank <frankja@linux.ibm.com>
> 
> Save response to sidad and disable address checking for protected
> guests.
> 
> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
> Reviewed-by: Thomas Huth <thuth@redhat.com>
> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
> [borntraeger@de.ibm.com: patch merging, splitting, fixing]
> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
> ---
>  arch/s390/kvm/priv.c | 11 ++++++++---
>  1 file changed, 8 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
> index ed52ffa8d5d4..b2de7dc5f58d 100644
> --- a/arch/s390/kvm/priv.c
> +++ b/arch/s390/kvm/priv.c
> @@ -872,7 +872,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>  
>  	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
>  
> -	if (operand2 & 0xfff)
> +	if (!kvm_s390_pv_is_protected(vcpu->kvm) && (operand2 & 0xfff))
>  		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);

Why is that needed? I'd assume the hardware handles this for us and this
case can never happen for PV? (IOW, change is not necessary)

>  
>  	switch (fc) {
> @@ -893,8 +893,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>  		handle_stsi_3_2_2(vcpu, (void *) mem);
>  		break;
>  	}
> -
> -	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
> +	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
> +		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
> +		       PAGE_SIZE);
> +		rc = 0;
> +	} else {
> +		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
> +	}
>  	if (rc) {
>  		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>  		goto out;
> 

I'd pull the interrupt injection into the else case, makes things clearer.

What about user_stsi? Will that still work? (I assume user space will
write to the sida and it should work just fine)

(I assume races regarding kvm_s390_pv_is_protected() will be dealt with
in your next series)

In general, looks good to me.
Christian Borntraeger Feb. 18, 2020, 8:44 a.m. UTC | #2
On 18.02.20 09:35, David Hildenbrand wrote:
> On 14.02.20 23:26, Christian Borntraeger wrote:
>> From: Janosch Frank <frankja@linux.ibm.com>
>>
>> Save response to sidad and disable address checking for protected
>> guests.
>>
>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
>> [borntraeger@de.ibm.com: patch merging, splitting, fixing]
>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>> ---
>>  arch/s390/kvm/priv.c | 11 ++++++++---
>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
>> index ed52ffa8d5d4..b2de7dc5f58d 100644
>> --- a/arch/s390/kvm/priv.c
>> +++ b/arch/s390/kvm/priv.c
>> @@ -872,7 +872,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>  
>>  	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
>>  
>> -	if (operand2 & 0xfff)
>> +	if (!kvm_s390_pv_is_protected(vcpu->kvm) && (operand2 & 0xfff))
>>  		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
> 
> Why is that needed? I'd assume the hardware handles this for us and this
> case can never happen for PV? (IOW, change is not necessary)

Hardware is handling this for us AND we are not allowed to inject a specification
exception. The ultravisor guards the program checks that we are allowed to inject.

> 
>>  
>>  	switch (fc) {
>> @@ -893,8 +893,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>  		handle_stsi_3_2_2(vcpu, (void *) mem);
>>  		break;
>>  	}
>> -
>> -	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>> +	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
>> +		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
>> +		       PAGE_SIZE);
>> +		rc = 0;
>> +	} else {
>> +		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>> +	}
>>  	if (rc) {
>>  		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>>  		goto out;
>>
> 
> I'd pull the interrupt injection into the else case, makes things clearer.

Well, no. Thhe else case could set rc to 0.

> 
> What about user_stsi? Will that still work? (I assume user space will
> write to the sida and it should work just fine)

will still work. 
> 
> (I assume races regarding kvm_s390_pv_is_protected() will be dealt with
> in your next series)
> 
> In general, looks good to me.
>
David Hildenbrand Feb. 18, 2020, 9:08 a.m. UTC | #3
On 18.02.20 09:44, Christian Borntraeger wrote:
> 
> 
> On 18.02.20 09:35, David Hildenbrand wrote:
>> On 14.02.20 23:26, Christian Borntraeger wrote:
>>> From: Janosch Frank <frankja@linux.ibm.com>
>>>
>>> Save response to sidad and disable address checking for protected
>>> guests.
>>>
>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>>> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
>>> [borntraeger@de.ibm.com: patch merging, splitting, fixing]
>>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>> ---
>>>  arch/s390/kvm/priv.c | 11 ++++++++---
>>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>>
>>> diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
>>> index ed52ffa8d5d4..b2de7dc5f58d 100644
>>> --- a/arch/s390/kvm/priv.c
>>> +++ b/arch/s390/kvm/priv.c
>>> @@ -872,7 +872,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>>  
>>>  	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
>>>  
>>> -	if (operand2 & 0xfff)
>>> +	if (!kvm_s390_pv_is_protected(vcpu->kvm) && (operand2 & 0xfff))
>>>  		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
>>
>> Why is that needed? I'd assume the hardware handles this for us and this
>> case can never happen for PV? (IOW, change is not necessary)
> 
> Hardware is handling this for us AND we are not allowed to inject a specification
> exception. The ultravisor guards the program checks that we are allowed to inject.
> 

Yeah, but can this ever trigger without the check? AFAIKs, no. So why
add it?

(rather add a BUG_ON in kvm_s390_inject_program_int() in case we are in
PV mode)

>>
>>>  
>>>  	switch (fc) {
>>> @@ -893,8 +893,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>>  		handle_stsi_3_2_2(vcpu, (void *) mem);
>>>  		break;
>>>  	}
>>> -
>>> -	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>> +	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
>>> +		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
>>> +		       PAGE_SIZE);
>>> +		rc = 0;
>>> +	} else {
>>> +		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>> +	}
>>>  	if (rc) {
>>>  		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>>>  		goto out;
>>>
>>
>> I'd pull the interrupt injection into the else case, makes things clearer.
> 
> Well, no. Thhe else case could set rc to 0.

Huh?!

if (kvm_s390_pv_is_protected(vcpu->kvm)) {
	memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
	rc = 0;
} else {
	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
	if (rc) {
		rc = kvm_s390_inject_prog_cond(vcpu, rc);
		goto out;
	}
}

What am I missing?
Christian Borntraeger Feb. 18, 2020, 9:11 a.m. UTC | #4
On 18.02.20 10:08, David Hildenbrand wrote:
> On 18.02.20 09:44, Christian Borntraeger wrote:
>>
>>
>> On 18.02.20 09:35, David Hildenbrand wrote:
>>> On 14.02.20 23:26, Christian Borntraeger wrote:
>>>> From: Janosch Frank <frankja@linux.ibm.com>
>>>>
>>>> Save response to sidad and disable address checking for protected
>>>> guests.
>>>>
>>>> Signed-off-by: Janosch Frank <frankja@linux.ibm.com>
>>>> Reviewed-by: Thomas Huth <thuth@redhat.com>
>>>> Reviewed-by: Cornelia Huck <cohuck@redhat.com>
>>>> [borntraeger@de.ibm.com: patch merging, splitting, fixing]
>>>> Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
>>>> ---
>>>>  arch/s390/kvm/priv.c | 11 ++++++++---
>>>>  1 file changed, 8 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
>>>> index ed52ffa8d5d4..b2de7dc5f58d 100644
>>>> --- a/arch/s390/kvm/priv.c
>>>> +++ b/arch/s390/kvm/priv.c
>>>> @@ -872,7 +872,7 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>>>  
>>>>  	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
>>>>  
>>>> -	if (operand2 & 0xfff)
>>>> +	if (!kvm_s390_pv_is_protected(vcpu->kvm) && (operand2 & 0xfff))
>>>>  		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
>>>
>>> Why is that needed? I'd assume the hardware handles this for us and this
>>> case can never happen for PV? (IOW, change is not necessary)
>>
>> Hardware is handling this for us AND we are not allowed to inject a specification
>> exception. The ultravisor guards the program checks that we are allowed to inject.
>>
> 
> Yeah, but can this ever trigger without the check? AFAIKs, no. So why
> add it?

It can. the GPRS can contain stale data and so can operand2.

> 
> (rather add a BUG_ON in kvm_s390_inject_program_int() in case we are in
> PV mode)
> 
>>>
>>>>  
>>>>  	switch (fc) {
>>>> @@ -893,8 +893,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>>>  		handle_stsi_3_2_2(vcpu, (void *) mem);
>>>>  		break;
>>>>  	}
>>>> -
>>>> -	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>>> +	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
>>>> +		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
>>>> +		       PAGE_SIZE);
>>>> +		rc = 0;
>>>> +	} else {
>>>> +		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>>> +	}
>>>>  	if (rc) {
>>>>  		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>>>>  		goto out;
>>>>
>>>
>>> I'd pull the interrupt injection into the else case, makes things clearer.
>>
>> Well, no. Thhe else case could set rc to 0.
> 
> Huh?!
> 
> if (kvm_s390_pv_is_protected(vcpu->kvm)) {
> 	memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
> 	rc = 0;
> } else {
> 	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
> 	if (rc) {
> 		rc = kvm_s390_inject_prog_cond(vcpu, rc);
> 		goto out;
> 	}
> }
> 

Hmm, I find that one harder to read.
David Hildenbrand Feb. 18, 2020, 9:13 a.m. UTC | #5
>> Yeah, but can this ever trigger without the check? AFAIKs, no. So why
>> add it?
> 
> It can. the GPRS can contain stale data and so can operand2.
> 

Oh, ok. Makes sense.

>>
>> (rather add a BUG_ON in kvm_s390_inject_program_int() in case we are in
>> PV mode)
>>
>>>>
>>>>>  
>>>>>  	switch (fc) {
>>>>> @@ -893,8 +893,13 @@ static int handle_stsi(struct kvm_vcpu *vcpu)
>>>>>  		handle_stsi_3_2_2(vcpu, (void *) mem);
>>>>>  		break;
>>>>>  	}
>>>>> -
>>>>> -	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>>>> +	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
>>>>> +		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
>>>>> +		       PAGE_SIZE);
>>>>> +		rc = 0;
>>>>> +	} else {
>>>>> +		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>>>>> +	}
>>>>>  	if (rc) {
>>>>>  		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>>>>>  		goto out;
>>>>>
>>>>
>>>> I'd pull the interrupt injection into the else case, makes things clearer.
>>>
>>> Well, no. Thhe else case could set rc to 0.
>>
>> Huh?!
>>
>> if (kvm_s390_pv_is_protected(vcpu->kvm)) {
>> 	memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
>> 	rc = 0;
>> } else {
>> 	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
>> 	if (rc) {
>> 		rc = kvm_s390_inject_prog_cond(vcpu, rc);
>> 		goto out;
>> 	}
>> }
>>
> 
> Hmm, I find that one harder to read.

It's clearer that you only inject a program check when not in pv mode
... ;) No strong feelings.
diff mbox series

Patch

diff --git a/arch/s390/kvm/priv.c b/arch/s390/kvm/priv.c
index ed52ffa8d5d4..b2de7dc5f58d 100644
--- a/arch/s390/kvm/priv.c
+++ b/arch/s390/kvm/priv.c
@@ -872,7 +872,7 @@  static int handle_stsi(struct kvm_vcpu *vcpu)
 
 	operand2 = kvm_s390_get_base_disp_s(vcpu, &ar);
 
-	if (operand2 & 0xfff)
+	if (!kvm_s390_pv_is_protected(vcpu->kvm) && (operand2 & 0xfff))
 		return kvm_s390_inject_program_int(vcpu, PGM_SPECIFICATION);
 
 	switch (fc) {
@@ -893,8 +893,13 @@  static int handle_stsi(struct kvm_vcpu *vcpu)
 		handle_stsi_3_2_2(vcpu, (void *) mem);
 		break;
 	}
-
-	rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
+	if (kvm_s390_pv_is_protected(vcpu->kvm)) {
+		memcpy((void *)sida_origin(vcpu->arch.sie_block), (void *)mem,
+		       PAGE_SIZE);
+		rc = 0;
+	} else {
+		rc = write_guest(vcpu, operand2, ar, (void *)mem, PAGE_SIZE);
+	}
 	if (rc) {
 		rc = kvm_s390_inject_prog_cond(vcpu, rc);
 		goto out;