Re: [PATCH 2/2] KVM: s390: gaccess: Refactor access address range check
From: Janis Schoetterl-Glausch <hidden>
Date: 2021-08-19 12:39:58
Also in:
kvm, lkml
On 8/18/21 12:08 PM, Claudio Imbrenda wrote:
On Mon, 16 Aug 2021 17:07:17 +0200 Janis Schoetterl-Glausch [off-list ref] wrote:quoted
Do not round down the first address to the page boundary, just translate it normally, which gives the value we care about in the first place. Given this, translating a single address is just the special case of translating a range spanning a single page. Make the output optional, so the function can be used to just check a range.I like the idea, but see a few nits belowquoted
Signed-off-by: Janis Schoetterl-Glausch <redacted> --- arch/s390/kvm/gaccess.c | 91 ++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 52 deletions(-)diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c index df83de0843de..e5a19d8b30e2 100644 --- a/arch/s390/kvm/gaccess.c +++ b/arch/s390/kvm/gaccess.c@@ -794,35 +794,45 @@ static int low_address_protection_enabled(struct kvm_vcpu *vcpu, return 1; } -static int guest_page_range(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, - unsigned long *pages, unsigned long nr_pages, - const union asce asce, enum gacc_mode mode) +/* Stores the gpas for each page in a real/virtual range into @gpas + * Modifies the 'struct kvm_s390_pgm_info pgm' member of @vcpu in the same + * way read_guest/write_guest do, the meaning of the return value is likewisethis comment is a bit confusing; why telling us to look what a different function is doing? either don't mention this at all (since it's more or less the expected behaviour), or explain in full what's going on
Yeah, it's not ideal. I haven't decided yet what I'll do. I think a comment would be helpful, and it may be expected behavior only if one has looked at the code for long enough :).
quoted
+ * the same. + * If @gpas is NULL only the checks are performed. + */ +static int guest_range_to_gpas(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, + unsigned long *gpas, unsigned long len, + const union asce asce, enum gacc_mode mode) { psw_t *psw = &vcpu->arch.sie_block->gpsw; + unsigned long gpa; + unsigned int seg; + unsigned int offset = offset_in_page(ga); int lap_enabled, rc = 0; enum prot_type prot; lap_enabled = low_address_protection_enabled(vcpu, asce); - while (nr_pages) { + while ((seg = min(PAGE_SIZE - offset, len)) != 0) {I'm not terribly fond of assignments-as-values; moreover offset is used only once. why not something like: seg = min(PAGE_SIZE - offset, len); while (seg) { ... seg = min(PAGE_SIZE, len); } or maybe even: seg = min(PAGE_SIZE - offset, len); for (; seg; seg = min(PAGE_SIZE, len)) { (although the one with the while is perhaps more readable)
That code pattern is not entirely uncommon, but I'll change it to:
while(min(PAGE_SIZE - offset, len) > 0) {
seg = min(PAGE_SIZE - offset, len);
...
}
which I think reads better than having the assignment at the end.
I assume the compiler gets rid of the redundancy.[...]
quoted
@@ -845,10 +855,10 @@ int access_guest(struct kvm_vcpu *vcpu, unsigned long ga, u8 ar, void *data, unsigned long len, enum gacc_mode mode) { psw_t *psw = &vcpu->arch.sie_block->gpsw; - unsigned long nr_pages, gpa, idx; + unsigned long nr_pages, idx; unsigned int seg; - unsigned long pages_array[2]; - unsigned long *pages; + unsigned long gpa_array[2]; + unsigned long *gpas;reverse Christmas tree? also, since you're touching this: have you checked if a different size for the array would bring any benefit? 2 seems a little too small, but I have no idea if anything bigger would bring any advantages.
I have not checked it, no. When emulating instructions, you would only need >2 entries if an operand is >8k or >4k and weirdly aligned, hardly seems like a common occurrence. On the other hand, bumping it up should not have any negative consequences. I'll leave it as is. [...]