* [PATCH v1 0/2] KVM: s390: Fix AR parameter in MEM_OP ioctl
@ 2024-02-09 20:45 Eric Farman
2024-02-09 20:45 ` [PATCH v1 1/2] KVM: s390: load guest access registers " Eric Farman
2024-02-09 20:45 ` [PATCH v1 2/2] KVM: s390: selftests: memop: add a simple AR test Eric Farman
0 siblings, 2 replies; 6+ messages in thread
From: Eric Farman @ 2024-02-09 20:45 UTC (permalink / raw)
To: Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
David Hildenbrand
Cc: Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle,
Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest,
Eric Farman
Hi Christian, Janosch, Heiko,
Here is a pair of patches to replace the RFC I recently sent [1].
Patch 1 performs the host/guest access register swap that Christian
suggested (instead of a full sync_reg/store_reg process).
Patch 2 provides a selftest patch that exercises this scenario.
Applying patch 2 without patch 1 fails in the following way:
[eric@host linux]# ./tools/testing/selftests/kvm/s390x/memop
TAP version 13
1..16
ok 1 simple copy
ok 2 generic error checks
ok 3 copy with storage keys
ok 4 cmpxchg with storage keys
ok 5 concurrently cmpxchg with storage keys
ok 6 copy with key storage protection override
ok 7 copy with key fetch protection
ok 8 copy with key fetch protection override
==== Test Assertion Failure ====
s390x/memop.c:186: !r
pid=5720 tid=5720 errno=4 - Interrupted system call
1 0x00000000010042af: memop_ioctl at memop.c:186 (discriminator 3)
2 0x0000000001006697: test_copy_access_register at memop.c:400 (discriminator 2)
3 0x0000000001002aaf: main at memop.c:1181
4 0x000003ffaec33a5b: ?? ??:0
5 0x000003ffaec33b5d: ?? ??:0
6 0x0000000001002ba9: _start at ??:?
KVM_S390_MEM_OP failed, rc: 40 errno: 4 (Interrupted system call)
Thoughts on this approach?
Thanks,
Eric
[1] https://lore.kernel.org/r/20240131205832.2179029-1-farman@linux.ibm.com/
Eric Farman (2):
KVM: s390: load guest access registers in MEM_OP ioctl
KVM: s390: selftests: memop: add a simple AR test
arch/s390/kvm/kvm-s390.c | 6 +++++
tools/testing/selftests/kvm/s390x/memop.c | 28 +++++++++++++++++++++++
2 files changed, 34 insertions(+)
--
2.40.1
^ permalink raw reply [flat|nested] 6+ messages in thread* [PATCH v1 1/2] KVM: s390: load guest access registers in MEM_OP ioctl 2024-02-09 20:45 [PATCH v1 0/2] KVM: s390: Fix AR parameter in MEM_OP ioctl Eric Farman @ 2024-02-09 20:45 ` Eric Farman 2024-02-12 10:21 ` Heiko Carstens 2024-02-09 20:45 ` [PATCH v1 2/2] KVM: s390: selftests: memop: add a simple AR test Eric Farman 1 sibling, 1 reply; 6+ messages in thread From: Eric Farman @ 2024-02-09 20:45 UTC (permalink / raw) To: Christian Borntraeger, Janosch Frank, Claudio Imbrenda, David Hildenbrand Cc: Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest, Eric Farman The routine ar_translation() is called by get_vcpu_asce(), which is called by both the instruction intercept path (where the access registers had been loaded with the guest's values), and the MEM_OP ioctl (which hadn't). This means that any ALET the guest expects to be used would be ignored. Furthermore, the logic in ar_translation() will store the contents of the access registers back to the KVM_RUN struct. This unexpected change of AR values can lead to problems after invoking the MEM_OP, for example an ALET Specification Exception. Fix this by swapping the host/guest access registers around the MEM_OP ioctl, in the same way that the KVM_RUN ioctl does with sync_regs()/store_regs(). The full register swap isn't needed here, since only the access registers are used in this interface. Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com> Signed-off-by: Eric Farman <farman@linux.ibm.com> --- arch/s390/kvm/kvm-s390.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ea63ac769889..c2dfeea55dcf 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -5391,6 +5391,10 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu, return -ENOMEM; } + /* Swap host/guest access registers in the event of a MEM_OP with AR specified */ + save_access_regs(vcpu->arch.host_acrs); + restore_access_regs(vcpu->run->s.regs.acrs); + acc_mode = mop->op == KVM_S390_MEMOP_LOGICAL_READ ? GACC_FETCH : GACC_STORE; if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, @@ -5420,6 +5424,8 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu, kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm); out_free: + save_access_regs(vcpu->run->s.regs.acrs); + restore_access_regs(vcpu->arch.host_acrs); vfree(tmpbuf); return r; } -- 2.40.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v1 1/2] KVM: s390: load guest access registers in MEM_OP ioctl 2024-02-09 20:45 ` [PATCH v1 1/2] KVM: s390: load guest access registers " Eric Farman @ 2024-02-12 10:21 ` Heiko Carstens 2024-02-12 11:52 ` Heiko Carstens 0 siblings, 1 reply; 6+ messages in thread From: Heiko Carstens @ 2024-02-12 10:21 UTC (permalink / raw) To: Eric Farman Cc: Christian Borntraeger, Janosch Frank, Claudio Imbrenda, David Hildenbrand, Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest On Fri, Feb 09, 2024 at 09:45:38PM +0100, Eric Farman wrote: > The routine ar_translation() is called by get_vcpu_asce(), which is > called by both the instruction intercept path (where the access > registers had been loaded with the guest's values), and the MEM_OP > ioctl (which hadn't). This means that any ALET the guest expects to > be used would be ignored. > > Furthermore, the logic in ar_translation() will store the contents > of the access registers back to the KVM_RUN struct. This unexpected > change of AR values can lead to problems after invoking the MEM_OP, > for example an ALET Specification Exception. > > Fix this by swapping the host/guest access registers around the > MEM_OP ioctl, in the same way that the KVM_RUN ioctl does with > sync_regs()/store_regs(). The full register swap isn't needed here, > since only the access registers are used in this interface. > > Suggested-by: Christian Borntraeger <borntraeger@linux.ibm.com> > Signed-off-by: Eric Farman <farman@linux.ibm.com> > --- > arch/s390/kvm/kvm-s390.c | 6 ++++++ > 1 file changed, 6 insertions(+) > > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c > index ea63ac769889..c2dfeea55dcf 100644 > --- a/arch/s390/kvm/kvm-s390.c > +++ b/arch/s390/kvm/kvm-s390.c > @@ -5391,6 +5391,10 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu, > return -ENOMEM; > } > > + /* Swap host/guest access registers in the event of a MEM_OP with AR specified */ > + save_access_regs(vcpu->arch.host_acrs); > + restore_access_regs(vcpu->run->s.regs.acrs); > + > acc_mode = mop->op == KVM_S390_MEMOP_LOGICAL_READ ? GACC_FETCH : GACC_STORE; > if (mop->flags & KVM_S390_MEMOP_F_CHECK_ONLY) { > r = check_gva_range(vcpu, mop->gaddr, mop->ar, mop->size, > @@ -5420,6 +5424,8 @@ static long kvm_s390_vcpu_mem_op(struct kvm_vcpu *vcpu, > kvm_s390_inject_prog_irq(vcpu, &vcpu->arch.pgm); > > out_free: > + save_access_regs(vcpu->run->s.regs.acrs); > + restore_access_regs(vcpu->arch.host_acrs); I guess we will end up with more and more of such constructs until nobody knows when which register contents are loaded. I would higly prefer a TIF flag which indicates if the access registers contain the host or guest register contents, and actual users grab the required content from the correct location - or better: always take it from guest save area, and write to the guest save area if the to be invented TIF flag indicates that access registers contain guest registers... Or maybe a TIF flag with different semantics: "guest save area does not reflect current state - which is within registers". ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH v1 1/2] KVM: s390: load guest access registers in MEM_OP ioctl 2024-02-12 10:21 ` Heiko Carstens @ 2024-02-12 11:52 ` Heiko Carstens 2024-02-13 17:31 ` Eric Farman 0 siblings, 1 reply; 6+ messages in thread From: Heiko Carstens @ 2024-02-12 11:52 UTC (permalink / raw) To: Heiko Carstens Cc: Eric Farman, Christian Borntraeger, Janosch Frank, Claudio Imbrenda, David Hildenbrand, Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest On Mon, Feb 12, 2024 at 11:21:30AM +0100, Heiko Carstens wrote: > Or maybe a TIF flag with different semantics: "guest save area does not > reflect current state - which is within registers". Something like the below; untested of course. But I guess there must be some arch specific vcpu flags, which can be used to achieve the same? diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h index a674c7d25da5..b9ff8b125fb8 100644 --- a/arch/s390/include/asm/thread_info.h +++ b/arch/s390/include/asm/thread_info.h @@ -69,6 +69,7 @@ void arch_setup_new_exec(void); #define TIF_PATCH_PENDING 5 /* pending live patching update */ #define TIF_PGSTE 6 /* New mm's will use 4K page tables */ #define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */ +#define TIF_KVM_ACRS 8 /* access registers contain guest content */ #define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */ #define TIF_PER_TRAP 10 /* Need to handle PER trap on exit to usermode */ diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index 5bfcc50c1a68..b0ef242d2371 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c @@ -391,7 +391,8 @@ static int ar_translation(struct kvm_vcpu *vcpu, union asce *asce, u8 ar, if (ar >= NUM_ACRS) return -EINVAL; - save_access_regs(vcpu->run->s.regs.acrs); + if (test_thread_flag(TIF_KVM_ACRS)) + save_access_regs(vcpu->run->s.regs.acrs); alet.val = vcpu->run->s.regs.acrs[ar]; if (ar == 0 || alet.val == 0) { diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c index ea63ac769889..3ee0913639d5 100644 --- a/arch/s390/kvm/kvm-s390.c +++ b/arch/s390/kvm/kvm-s390.c @@ -4951,6 +4951,7 @@ static void sync_regs(struct kvm_vcpu *vcpu) } save_access_regs(vcpu->arch.host_acrs); restore_access_regs(vcpu->run->s.regs.acrs); + set_thread_flag(TIF_KVM_ACRS); /* save host (userspace) fprs/vrs */ save_fpu_regs(); vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc; @@ -5020,6 +5021,7 @@ static void store_regs(struct kvm_vcpu *vcpu) kvm_run->s.regs.pfs = vcpu->arch.pfault_select; kvm_run->s.regs.pfc = vcpu->arch.pfault_compare; save_access_regs(vcpu->run->s.regs.acrs); + clear_thread_flag(TIF_KVM_ACRS); restore_access_regs(vcpu->arch.host_acrs); /* Save guest register state */ save_fpu_regs(); ^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v1 1/2] KVM: s390: load guest access registers in MEM_OP ioctl 2024-02-12 11:52 ` Heiko Carstens @ 2024-02-13 17:31 ` Eric Farman 0 siblings, 0 replies; 6+ messages in thread From: Eric Farman @ 2024-02-13 17:31 UTC (permalink / raw) To: Heiko Carstens Cc: Christian Borntraeger, Janosch Frank, Claudio Imbrenda, David Hildenbrand, Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest On Mon, 2024-02-12 at 12:52 +0100, Heiko Carstens wrote: > > On Mon, Feb 12, 2024 at 11:21:30AM +0100, Heiko Carstens wrote: > > > > Or maybe a TIF flag with different semantics: "guest save area > > > > does > > > > not > > > > reflect current state - which is within registers". > > > > Something like the below; untested of course. Ooops, yeah. Christian suggested something similar in his first response to the RFC which I'd overlooked. > > But I guess there must be > > some arch specific vcpu flags, which can be used to achieve the > > same? Agreed. Putting something there probably makes sense to keep it in the KVM sphere > > > > diff --git a/arch/s390/include/asm/thread_info.h > > b/arch/s390/include/asm/thread_info.h > > index a674c7d25da5..b9ff8b125fb8 100644 > > --- a/arch/s390/include/asm/thread_info.h > > +++ b/arch/s390/include/asm/thread_info.h > > @@ -69,6 +69,7 @@ void arch_setup_new_exec(void); > > #define TIF_PATCH_PENDING 5 /* pending live patching update */ > > #define TIF_PGSTE 6 /* New mm's will use 4K page tables */ > > #define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */ > > +#define TIF_KVM_ACRS 8 /* access registers contain guest content > > */ > > #define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP > > */ > > #define TIF_PER_TRAP 10 /* Need to handle PER trap on exit to > > usermode */ > > > > diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c > > index 5bfcc50c1a68..b0ef242d2371 100644 > > --- a/arch/s390/kvm/gaccess.c > > +++ b/arch/s390/kvm/gaccess.c > > @@ -391,7 +391,8 @@ static int ar_translation(struct kvm_vcpu > > *vcpu, > > union asce *asce, u8 ar, > > if (ar >= NUM_ACRS) > > return -EINVAL; > > > > - save_access_regs(vcpu->run->s.regs.acrs); > > + if (test_thread_flag(TIF_KVM_ACRS)) > > + save_access_regs(vcpu->run->s.regs.acrs); ...or WARN if not set, so that we know of the missing path. Will send this all as a v2. Thanks. > > alet.val = vcpu->run->s.regs.acrs[ar]; > > > > if (ar == 0 || alet.val == 0) { > > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c > > index ea63ac769889..3ee0913639d5 100644 > > --- a/arch/s390/kvm/kvm-s390.c > > +++ b/arch/s390/kvm/kvm-s390.c > > @@ -4951,6 +4951,7 @@ static void sync_regs(struct kvm_vcpu *vcpu) > > } > > save_access_regs(vcpu->arch.host_acrs); > > restore_access_regs(vcpu->run->s.regs.acrs); > > + set_thread_flag(TIF_KVM_ACRS); > > /* save host (userspace) fprs/vrs */ > > save_fpu_regs(); > > vcpu->arch.host_fpregs.fpc = current->thread.fpu.fpc; > > @@ -5020,6 +5021,7 @@ static void store_regs(struct kvm_vcpu *vcpu) > > kvm_run->s.regs.pfs = vcpu->arch.pfault_select; > > kvm_run->s.regs.pfc = vcpu->arch.pfault_compare; > > save_access_regs(vcpu->run->s.regs.acrs); > > + clear_thread_flag(TIF_KVM_ACRS); > > restore_access_regs(vcpu->arch.host_acrs); > > /* Save guest register state */ > > save_fpu_regs(); ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v1 2/2] KVM: s390: selftests: memop: add a simple AR test 2024-02-09 20:45 [PATCH v1 0/2] KVM: s390: Fix AR parameter in MEM_OP ioctl Eric Farman 2024-02-09 20:45 ` [PATCH v1 1/2] KVM: s390: load guest access registers " Eric Farman @ 2024-02-09 20:45 ` Eric Farman 1 sibling, 0 replies; 6+ messages in thread From: Eric Farman @ 2024-02-09 20:45 UTC (permalink / raw) To: Christian Borntraeger, Janosch Frank, Claudio Imbrenda, David Hildenbrand Cc: Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle, Paolo Bonzini, Shuah Khan, kvm, linux-s390, linux-kselftest, Eric Farman There is a selftest that checks for an (expected) error when an invalid AR is specified, but not one that exercises the AR path. Add a simple test that mirrors the vanilla write/read test while providing an AR. An AR that contains zero will direct the CPU to use the primary address space normally used anyway. AR[1] is selected for this test because the host AR[1] is usually non-zero, and KVM needs to correctly swap those values. Signed-off-by: Eric Farman <farman@linux.ibm.com> --- tools/testing/selftests/kvm/s390x/memop.c | 28 +++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tools/testing/selftests/kvm/s390x/memop.c b/tools/testing/selftests/kvm/s390x/memop.c index bb3ca9a5d731..be20c26ee545 100644 --- a/tools/testing/selftests/kvm/s390x/memop.c +++ b/tools/testing/selftests/kvm/s390x/memop.c @@ -375,6 +375,29 @@ static void test_copy(void) kvm_vm_free(t.kvm_vm); } +static void test_copy_access_register(void) +{ + struct test_default t = test_default_init(guest_copy); + + HOST_SYNC(t.vcpu, STAGE_INITED); + + prepare_mem12(); + t.run->psw_mask &= ~(3UL << (63 - 17)); + t.run->psw_mask |= 1UL << (63 - 17); /* Enable AR mode */ + + CHECK_N_DO(MOP, t.vcpu, LOGICAL, WRITE, mem1, t.size, + GADDR_V(mem1), AR(1)); + HOST_SYNC(t.vcpu, STAGE_COPIED); + + CHECK_N_DO(MOP, t.vcpu, LOGICAL, READ, mem2, t.size, + GADDR_V(mem2), AR(1)); + ASSERT_MEM_EQ(mem1, mem2, t.size); + + t.run->psw_mask &= ~(3UL << (63 - 17)); /* Disable AR mode */ + + kvm_vm_free(t.kvm_vm); +} + static void set_storage_key_range(void *addr, size_t len, uint8_t key) { uintptr_t _addr, abs, i; @@ -1101,6 +1124,11 @@ int main(int argc, char *argv[]) .test = test_copy_key_fetch_prot_override, .requirements_met = extension_cap > 0, }, + { + .name = "copy with access register mode", + .test = test_copy_access_register, + .requirements_met = true, + }, { .name = "error checks with key", .test = test_errors_key, -- 2.40.1 ^ permalink raw reply related [flat|nested] 6+ messages in thread
end of thread, other threads:[~2024-02-13 17:31 UTC | newest] Thread overview: 6+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2024-02-09 20:45 [PATCH v1 0/2] KVM: s390: Fix AR parameter in MEM_OP ioctl Eric Farman 2024-02-09 20:45 ` [PATCH v1 1/2] KVM: s390: load guest access registers " Eric Farman 2024-02-12 10:21 ` Heiko Carstens 2024-02-12 11:52 ` Heiko Carstens 2024-02-13 17:31 ` Eric Farman 2024-02-09 20:45 ` [PATCH v1 2/2] KVM: s390: selftests: memop: add a simple AR test Eric Farman
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox