mbox series

[v2,0/2] Dirtying, failing memop: don't indicate suppression

Message ID 20220425100147.1755340-1-scgl@linux.ibm.com (mailing list archive)
Headers show
Series Dirtying, failing memop: don't indicate suppression | expand

Message

Janis Schoetterl-Glausch April 25, 2022, 10:01 a.m. UTC
If a memop fails due to key checked protection, after already having
written to the guest, don't indicate suppression to the guest, as that
would imply that memory wasn't modified.

This could be considered a fix to the code introducing storage key
support, however this is a bug in KVM only if we emulate an
instructions writing to an operand spanning multiple pages, which I
don't believe we do.

v1 -> v2
 * Reword commit message of patch 1

Janis Schoetterl-Glausch (2):
  KVM: s390: Don't indicate suppression on dirtying, failing memop
  KVM: s390: selftest: Test suppression indication on key prot exception

 arch/s390/kvm/gaccess.c                   | 47 ++++++++++++++---------
 tools/testing/selftests/kvm/s390x/memop.c | 43 ++++++++++++++++++++-
 2 files changed, 70 insertions(+), 20 deletions(-)


base-commit: af2d861d4cd2a4da5137f795ee3509e6f944a25b

Comments

Christian Borntraeger April 25, 2022, 4:30 p.m. UTC | #1
Am 25.04.22 um 12:01 schrieb Janis Schoetterl-Glausch:
> If a memop fails due to key checked protection, after already having
> written to the guest, don't indicate suppression to the guest, as that
> would imply that memory wasn't modified.
> 
> This could be considered a fix to the code introducing storage key
> support, however this is a bug in KVM only if we emulate an
> instructions writing to an operand spanning multiple pages, which I
> don't believe we do.
> 

Thanks applied. I think it makes sense for 5.18 nevertheless.

> v1 -> v2
>   * Reword commit message of patch 1
> 
> Janis Schoetterl-Glausch (2):
>    KVM: s390: Don't indicate suppression on dirtying, failing memop
>    KVM: s390: selftest: Test suppression indication on key prot exception
> 
>   arch/s390/kvm/gaccess.c                   | 47 ++++++++++++++---------
>   tools/testing/selftests/kvm/s390x/memop.c | 43 ++++++++++++++++++++-
>   2 files changed, 70 insertions(+), 20 deletions(-)
> 
> 
> base-commit: af2d861d4cd2a4da5137f795ee3509e6f944a25b
Janis Schoetterl-Glausch April 25, 2022, 5:29 p.m. UTC | #2
On 4/25/22 18:30, Christian Borntraeger wrote:
> Am 25.04.22 um 12:01 schrieb Janis Schoetterl-Glausch:
>> If a memop fails due to key checked protection, after already having
>> written to the guest, don't indicate suppression to the guest, as that
>> would imply that memory wasn't modified.
>>
>> This could be considered a fix to the code introducing storage key
>> support, however this is a bug in KVM only if we emulate an
>> instructions writing to an operand spanning multiple pages, which I
>> don't believe we do.
>>
> 
> Thanks applied. I think it makes sense for 5.18 nevertheless.

Janosch had some concerns because the protection code being 000 implies
that the effective address in the TEID is unpredictable.
Let's see if he chimes in.

> 
>> v1 -> v2
>>   * Reword commit message of patch 1
>>
>> Janis Schoetterl-Glausch (2):
>>    KVM: s390: Don't indicate suppression on dirtying, failing memop
>>    KVM: s390: selftest: Test suppression indication on key prot exception
>>
>>   arch/s390/kvm/gaccess.c                   | 47 ++++++++++++++---------
>>   tools/testing/selftests/kvm/s390x/memop.c | 43 ++++++++++++++++++++-
>>   2 files changed, 70 insertions(+), 20 deletions(-)
>>
>>
>> base-commit: af2d861d4cd2a4da5137f795ee3509e6f944a25b
>
Christian Borntraeger April 26, 2022, 6:19 a.m. UTC | #3
Am 25.04.22 um 19:29 schrieb Janis Schoetterl-Glausch:
> On 4/25/22 18:30, Christian Borntraeger wrote:
>> Am 25.04.22 um 12:01 schrieb Janis Schoetterl-Glausch:
>>> If a memop fails due to key checked protection, after already having
>>> written to the guest, don't indicate suppression to the guest, as that
>>> would imply that memory wasn't modified.
>>>
>>> This could be considered a fix to the code introducing storage key
>>> support, however this is a bug in KVM only if we emulate an
>>> instructions writing to an operand spanning multiple pages, which I
>>> don't believe we do.
>>>
>>
>> Thanks applied. I think it makes sense for 5.18 nevertheless.
> 
> Janosch had some concerns because the protection code being 000 implies
> that the effective address in the TEID is unpredictable.
> Let's see if he chimes in.

z/VM does exactly the same on key protection crossing a page boundary. The
architecture was written in a way to allow all zeros exactly for this case.
(hypervisor emulation of key protection crossing pages).
This is even true for ESOP-2. See Figure 3-5 or figure 3-8 (the first line)
which allows to NOT have a valid address in the TEID for key controlled
protection.

The only question is, do we need to change the suppression parameter in
access_guest_with_key

  (mode != GACC_STORE) || (idx == 0)

to also check for prot != PROT_TYPE_KEYC
? I think we do not need this as we have checked other reasons before.
Janosch Frank April 26, 2022, 7:25 a.m. UTC | #4
On 4/26/22 08:19, Christian Borntraeger wrote:
> 
> 
> Am 25.04.22 um 19:29 schrieb Janis Schoetterl-Glausch:
>> On 4/25/22 18:30, Christian Borntraeger wrote:
>>> Am 25.04.22 um 12:01 schrieb Janis Schoetterl-Glausch:
>>>> If a memop fails due to key checked protection, after already having
>>>> written to the guest, don't indicate suppression to the guest, as that
>>>> would imply that memory wasn't modified.
>>>>
>>>> This could be considered a fix to the code introducing storage key
>>>> support, however this is a bug in KVM only if we emulate an
>>>> instructions writing to an operand spanning multiple pages, which I
>>>> don't believe we do.
>>>>
>>>
>>> Thanks applied. I think it makes sense for 5.18 nevertheless.
>>
>> Janosch had some concerns because the protection code being 000 implies
>> that the effective address in the TEID is unpredictable.
>> Let's see if he chimes in.
> 
> z/VM does exactly the same on key protection crossing a page boundary. The
> architecture was written in a way to allow all zeros exactly for this case.
> (hypervisor emulation of key protection crossing pages).
> This is even true for ESOP-2. See Figure 3-5 or figure 3-8 (the first line)
> which allows to NOT have a valid address in the TEID for key controlled
> protection.
> 
> The only question is, do we need to change the suppression parameter in
> access_guest_with_key
> 
>    (mode != GACC_STORE) || (idx == 0)
> 
> to also check for prot != PROT_TYPE_KEYC
> ? I think we do not need this as we have checked other reasons before.

To me this measure looks like a last resort option and the POP doesn't 
state a 100% what is to be done. Some instructions can mandate 
suppression instead of termination according to the architects.

My intuition tells me that if we are in a situation where this would 
happen then we would be much better off just doing it by hand (i.e. in 
the instruction emulation code) and not letting this function decide.

So I'm not entirely sure if we're replacing something that is not 
correct with something that also won't be correct for all cases.

But to summarize this: I'm not entirely sure even after reading the POP 
for more than an hour and consulting an architect
Janis Schoetterl-Glausch April 26, 2022, 11:56 a.m. UTC | #5
On 4/26/22 09:25, Janosch Frank wrote:
> On 4/26/22 08:19, Christian Borntraeger wrote:
>>
>>
>> Am 25.04.22 um 19:29 schrieb Janis Schoetterl-Glausch:
>>> On 4/25/22 18:30, Christian Borntraeger wrote:
>>>> Am 25.04.22 um 12:01 schrieb Janis Schoetterl-Glausch:
>>>>> If a memop fails due to key checked protection, after already having
>>>>> written to the guest, don't indicate suppression to the guest, as that
>>>>> would imply that memory wasn't modified.
>>>>>
>>>>> This could be considered a fix to the code introducing storage key
>>>>> support, however this is a bug in KVM only if we emulate an
>>>>> instructions writing to an operand spanning multiple pages, which I
>>>>> don't believe we do.
>>>>>
>>>>
>>>> Thanks applied. I think it makes sense for 5.18 nevertheless.
>>>
>>> Janosch had some concerns because the protection code being 000 implies
>>> that the effective address in the TEID is unpredictable.
>>> Let's see if he chimes in.
>>
>> z/VM does exactly the same on key protection crossing a page boundary. The
>> architecture was written in a way to allow all zeros exactly for this case.
>> (hypervisor emulation of key protection crossing pages).
>> This is even true for ESOP-2. See Figure 3-5 or figure 3-8 (the first line)
>> which allows to NOT have a valid address in the TEID for key controlled
>> protection.

The question is if this is the best way to do it. Janosch brought up
interruptible instructions, for those you would want to just consider
the current unit of operation to be suppressed. Now this is not actually
relevant, I guess PFMF is the only interruptible instruction we'd emulate
and that ignores keys when clearing memory.
But maybe there are other edge cases.

>>
>> The only question is, do we need to change the suppression parameter in
>> access_guest_with_key
>>
>>    (mode != GACC_STORE) || (idx == 0)
>>
>> to also check for prot != PROT_TYPE_KEYC
>> ? I think we do not need this as we have checked other reasons before.

Yes, it is not necessary, the control flow is such that a protection exception
implies that is due to keys.
> 
> To me this measure looks like a last resort option and the POP doesn't state a 100% what is to be done. Some instructions can mandate suppression instead of termination according to the architects.
> 
> My intuition tells me that if we are in a situation where this would happen then we would be much better off just doing it by hand (i.e. in the instruction emulation code) and not letting this function decide.

For the instructions we currently need to emulate in KVM we should be fine.
So the question is what's best for the future and for instructions emulated by user space.
Upward in the call stack (including user space), we don't know the failing address,
which complicates handling it in the emulation code.
You could chop up the memop in page chunks to find out, but that might have other issues.

Since this behavior is very implicit and easy to overlook maybe we should document it
in the description of the memop ioctl?
> 
> So I'm not entirely sure if we're replacing something that is not correct with something that also won't be correct for all cases.

That may be the case, which option is more correct/less incorrect tho?
It's hard to say because one would have to consider all instructions/possibilities,
but indicating not suppression when we've already written to memory, seems to make
sense more often than not doing so.
> 
> But to summarize this: I'm not entirely sure even after reading the POP for more than an hour and consulting an architect
Janosch Frank April 26, 2022, 12:34 p.m. UTC | #6
[...]
>>>
>>> The only question is, do we need to change the suppression parameter in
>>> access_guest_with_key
>>>
>>>     (mode != GACC_STORE) || (idx == 0)
>>>
>>> to also check for prot != PROT_TYPE_KEYC
>>> ? I think we do not need this as we have checked other reasons before.
> 
> Yes, it is not necessary, the control flow is such that a protection exception
> implies that is due to keys.
>>
>> To me this measure looks like a last resort option and the POP doesn't state a 100% what is to be done. Some instructions can mandate suppression instead of termination according to the architects.
>>
>> My intuition tells me that if we are in a situation where this would happen then we would be much better off just doing it by hand (i.e. in the instruction emulation code) and not letting this function decide.
> 
> For the instructions we currently need to emulate in KVM we should be fine.
> So the question is what's best for the future and for instructions emulated by user space.
> Upward in the call stack (including user space), we don't know the failing address,
> which complicates handling it in the emulation code.
> You could chop up the memop in page chunks to find out, but that might have other issues.
> 
> Since this behavior is very implicit and easy to overlook maybe we should document it
> in the description of the memop ioctl?

Yeah, properly documenting this is the least we can do.
Christian Borntraeger May 2, 2022, 7:58 a.m. UTC | #7
Am 26.04.22 um 09:25 schrieb Janosch Frank:
> 
> To me this measure looks like a last resort option and the POP doesn't state a 100% what is to be done. Some instructions can mandate suppression instead of termination according to the architects.
> 
> My intuition tells me that if we are in a situation where this would happen then we would be much better off just doing it by hand (i.e. in the instruction emulation code) and not letting this function decide.
> 
> So I'm not entirely sure if we're replacing something that is not correct with something that also won't be correct for all cases.
> 
> But to summarize this: I'm not entirely sure even after reading the POP for more than an hour and consulting an architect

According to Damian, the definition in the POP is exactly the way it is to cover for z/VMs way of handling key protection for long operatings in a terminating fashion since the 70ies or 80ies.
As it is fine for z/VM (and then also for z/OS and zVSE under z/VM) I guess we can (and should) mimic that behaviour.