From: Oliver Upton <oliver.upton@linux.dev>
To: Marc Zyngier <maz@kernel.org>, James Morse <james.morse@arm.com>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Shuah Khan <shuah@kernel.org>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, kvmarm@lists.linux.dev,
kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org
Subject: [PATCH v2 4/7] KVM: selftests: Correctly initialize the VA space for TTBR0_EL1
Date: Fri, 9 Dec 2022 01:53:03 +0000 [thread overview]
Message-ID: <20221209015307.1781352-5-oliver.upton@linux.dev> (raw)
In-Reply-To: <20221209015307.1781352-1-oliver.upton@linux.dev>
An interesting feature of the Arm architecture is that the stage-1 MMU
supports two distinct VA regions, controlled by TTBR{0,1}_EL1. As KVM
selftests on arm64 only uses TTBR0_EL1, the VA space is constrained to
[0, 2^(va_bits)). This is different from other architectures that
allow for addressing low and high regions of the VA space from a single
page table.
KVM selftests' VA space allocator presumes the valid address range is
split between low and high memory based the MSB, which of course is a
poor match for arm64's TTBR0 region.
Add a helper that correctly handles both addressing schemes with a
comment describing each.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
.../selftests/kvm/include/kvm_util_base.h | 1 +
tools/testing/selftests/kvm/lib/kvm_util.c | 49 ++++++++++++++++---
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 6cd86da698b3..b193863d754f 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -103,6 +103,7 @@ struct kvm_vm {
struct sparsebit *vpages_mapped;
bool has_irqchip;
bool pgd_created;
+ bool has_split_va_space;
vm_paddr_t ucall_mmio_addr;
vm_paddr_t pgd;
vm_vaddr_t gdt;
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index a256ec67aff6..53d15f32f220 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -186,6 +186,43 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
"Missing new mode params?");
+/*
+ * Initializes vm->vpages_valid to match the canonical VA space of the
+ * architecture.
+ *
+ * Most architectures split the range addressed by a single page table into a
+ * low and high region based on the MSB of the VA. On architectures with this
+ * behavior the VA region spans [0, 2^(va_bits - 1)), [-(2^(va_bits - 1), -1].
+ *
+ * arm64 is a bit different from the rest of the crowd, as the low and high
+ * regions of the VA space are addressed by distinct paging structures
+ * (TTBR{0,1}_EL1). KVM selftests on arm64 only uses TTBR0_EL1, meaning that we
+ * only have a low VA region. As there is no VA split based on the MSB, the VA
+ * region spans [0, 2^va_bits).
+ */
+static void vm_vaddr_populate_bitmap(struct kvm_vm *vm)
+{
+ sparsebit_num_t contig_va_bits = vm->va_bits;
+ sparsebit_num_t nr_contig_pages;
+
+ /*
+ * Depending on the architecture, the MSB of the VA could split between
+ * low and high regions. When that is the case each region has
+ * va_bits - 1 of address.
+ */
+ if (vm->has_split_va_space)
+ contig_va_bits--;
+
+ nr_contig_pages = (1ULL << contig_va_bits) >> vm->page_shift;
+
+ sparsebit_set_num(vm->vpages_valid, 0, nr_contig_pages);
+
+ if (vm->has_split_va_space)
+ sparsebit_set_num(vm->vpages_valid,
+ -(1ULL << contig_va_bits),
+ nr_contig_pages);
+}
+
struct kvm_vm *____vm_create(enum vm_guest_mode mode)
{
struct kvm_vm *vm;
@@ -268,17 +305,17 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
#ifdef __aarch64__
if (vm->pa_bits != 40)
vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
+
+ /* selftests use TTBR0 only, meaning there is a single VA region. */
+ vm->has_split_va_space = false;
+#else
+ vm->has_split_va_space = true;
#endif
vm_open(vm);
- /* Limit to VA-bit canonical virtual addresses. */
vm->vpages_valid = sparsebit_alloc();
- sparsebit_set_num(vm->vpages_valid,
- 0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
- sparsebit_set_num(vm->vpages_valid,
- (~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
- (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
+ vm_vaddr_populate_bitmap(vm);
/* Limit physical addresses to PA-bits. */
vm->max_gfn = vm_compute_max_gfn(vm);
--
2.39.0.rc1.256.g54fd8350bd-goog
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Oliver Upton <oliver.upton@linux.dev>
To: Marc Zyngier <maz@kernel.org>, James Morse <james.morse@arm.com>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Shuah Khan <shuah@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org,
kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org,
kvmarm@lists.linux.dev, Ricardo Koller <ricarkol@google.com>,
Sean Christopherson <seanjc@google.com>,
Oliver Upton <oliver.upton@linux.dev>,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/7] KVM: selftests: Correctly initialize the VA space for TTBR0_EL1
Date: Fri, 9 Dec 2022 01:53:03 +0000 [thread overview]
Message-ID: <20221209015307.1781352-5-oliver.upton@linux.dev> (raw)
Message-ID: <20221209015303.rVOHC4g7mSErwTSc5_vqhal6BDGNH5FI45NTLhvdb2Y@z> (raw)
In-Reply-To: <20221209015307.1781352-1-oliver.upton@linux.dev>
An interesting feature of the Arm architecture is that the stage-1 MMU
supports two distinct VA regions, controlled by TTBR{0,1}_EL1. As KVM
selftests on arm64 only uses TTBR0_EL1, the VA space is constrained to
[0, 2^(va_bits)). This is different from other architectures that
allow for addressing low and high regions of the VA space from a single
page table.
KVM selftests' VA space allocator presumes the valid address range is
split between low and high memory based the MSB, which of course is a
poor match for arm64's TTBR0 region.
Add a helper that correctly handles both addressing schemes with a
comment describing each.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
.../selftests/kvm/include/kvm_util_base.h | 1 +
tools/testing/selftests/kvm/lib/kvm_util.c | 49 ++++++++++++++++---
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 6cd86da698b3..b193863d754f 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -103,6 +103,7 @@ struct kvm_vm {
struct sparsebit *vpages_mapped;
bool has_irqchip;
bool pgd_created;
+ bool has_split_va_space;
vm_paddr_t ucall_mmio_addr;
vm_paddr_t pgd;
vm_vaddr_t gdt;
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index a256ec67aff6..53d15f32f220 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -186,6 +186,43 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
"Missing new mode params?");
+/*
+ * Initializes vm->vpages_valid to match the canonical VA space of the
+ * architecture.
+ *
+ * Most architectures split the range addressed by a single page table into a
+ * low and high region based on the MSB of the VA. On architectures with this
+ * behavior the VA region spans [0, 2^(va_bits - 1)), [-(2^(va_bits - 1), -1].
+ *
+ * arm64 is a bit different from the rest of the crowd, as the low and high
+ * regions of the VA space are addressed by distinct paging structures
+ * (TTBR{0,1}_EL1). KVM selftests on arm64 only uses TTBR0_EL1, meaning that we
+ * only have a low VA region. As there is no VA split based on the MSB, the VA
+ * region spans [0, 2^va_bits).
+ */
+static void vm_vaddr_populate_bitmap(struct kvm_vm *vm)
+{
+ sparsebit_num_t contig_va_bits = vm->va_bits;
+ sparsebit_num_t nr_contig_pages;
+
+ /*
+ * Depending on the architecture, the MSB of the VA could split between
+ * low and high regions. When that is the case each region has
+ * va_bits - 1 of address.
+ */
+ if (vm->has_split_va_space)
+ contig_va_bits--;
+
+ nr_contig_pages = (1ULL << contig_va_bits) >> vm->page_shift;
+
+ sparsebit_set_num(vm->vpages_valid, 0, nr_contig_pages);
+
+ if (vm->has_split_va_space)
+ sparsebit_set_num(vm->vpages_valid,
+ -(1ULL << contig_va_bits),
+ nr_contig_pages);
+}
+
struct kvm_vm *____vm_create(enum vm_guest_mode mode)
{
struct kvm_vm *vm;
@@ -268,17 +305,17 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
#ifdef __aarch64__
if (vm->pa_bits != 40)
vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
+
+ /* selftests use TTBR0 only, meaning there is a single VA region. */
+ vm->has_split_va_space = false;
+#else
+ vm->has_split_va_space = true;
#endif
vm_open(vm);
- /* Limit to VA-bit canonical virtual addresses. */
vm->vpages_valid = sparsebit_alloc();
- sparsebit_set_num(vm->vpages_valid,
- 0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
- sparsebit_set_num(vm->vpages_valid,
- (~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
- (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
+ vm_vaddr_populate_bitmap(vm);
/* Limit physical addresses to PA-bits. */
vm->max_gfn = vm_compute_max_gfn(vm);
--
2.39.0.rc1.256.g54fd8350bd-goog
WARNING: multiple messages have this Message-ID (diff)
From: Oliver Upton <oliver.upton@linux.dev>
To: Marc Zyngier <maz@kernel.org>, James Morse <james.morse@arm.com>,
Alexandru Elisei <alexandru.elisei@arm.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Shuah Khan <shuah@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org,
kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org,
kvmarm@lists.linux.dev, Ricardo Koller <ricarkol@google.com>,
Sean Christopherson <seanjc@google.com>,
Oliver Upton <oliver.upton@linux.dev>,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH v2 4/7] KVM: selftests: Correctly initialize the VA space for TTBR0_EL1
Date: Fri, 9 Dec 2022 01:53:03 +0000 [thread overview]
Message-ID: <20221209015307.1781352-5-oliver.upton@linux.dev> (raw)
In-Reply-To: <20221209015307.1781352-1-oliver.upton@linux.dev>
An interesting feature of the Arm architecture is that the stage-1 MMU
supports two distinct VA regions, controlled by TTBR{0,1}_EL1. As KVM
selftests on arm64 only uses TTBR0_EL1, the VA space is constrained to
[0, 2^(va_bits)). This is different from other architectures that
allow for addressing low and high regions of the VA space from a single
page table.
KVM selftests' VA space allocator presumes the valid address range is
split between low and high memory based the MSB, which of course is a
poor match for arm64's TTBR0 region.
Add a helper that correctly handles both addressing schemes with a
comment describing each.
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
---
.../selftests/kvm/include/kvm_util_base.h | 1 +
tools/testing/selftests/kvm/lib/kvm_util.c | 49 ++++++++++++++++---
2 files changed, 44 insertions(+), 6 deletions(-)
diff --git a/tools/testing/selftests/kvm/include/kvm_util_base.h b/tools/testing/selftests/kvm/include/kvm_util_base.h
index 6cd86da698b3..b193863d754f 100644
--- a/tools/testing/selftests/kvm/include/kvm_util_base.h
+++ b/tools/testing/selftests/kvm/include/kvm_util_base.h
@@ -103,6 +103,7 @@ struct kvm_vm {
struct sparsebit *vpages_mapped;
bool has_irqchip;
bool pgd_created;
+ bool has_split_va_space;
vm_paddr_t ucall_mmio_addr;
vm_paddr_t pgd;
vm_vaddr_t gdt;
diff --git a/tools/testing/selftests/kvm/lib/kvm_util.c b/tools/testing/selftests/kvm/lib/kvm_util.c
index a256ec67aff6..53d15f32f220 100644
--- a/tools/testing/selftests/kvm/lib/kvm_util.c
+++ b/tools/testing/selftests/kvm/lib/kvm_util.c
@@ -186,6 +186,43 @@ const struct vm_guest_mode_params vm_guest_mode_params[] = {
_Static_assert(sizeof(vm_guest_mode_params)/sizeof(struct vm_guest_mode_params) == NUM_VM_MODES,
"Missing new mode params?");
+/*
+ * Initializes vm->vpages_valid to match the canonical VA space of the
+ * architecture.
+ *
+ * Most architectures split the range addressed by a single page table into a
+ * low and high region based on the MSB of the VA. On architectures with this
+ * behavior the VA region spans [0, 2^(va_bits - 1)), [-(2^(va_bits - 1), -1].
+ *
+ * arm64 is a bit different from the rest of the crowd, as the low and high
+ * regions of the VA space are addressed by distinct paging structures
+ * (TTBR{0,1}_EL1). KVM selftests on arm64 only uses TTBR0_EL1, meaning that we
+ * only have a low VA region. As there is no VA split based on the MSB, the VA
+ * region spans [0, 2^va_bits).
+ */
+static void vm_vaddr_populate_bitmap(struct kvm_vm *vm)
+{
+ sparsebit_num_t contig_va_bits = vm->va_bits;
+ sparsebit_num_t nr_contig_pages;
+
+ /*
+ * Depending on the architecture, the MSB of the VA could split between
+ * low and high regions. When that is the case each region has
+ * va_bits - 1 of address.
+ */
+ if (vm->has_split_va_space)
+ contig_va_bits--;
+
+ nr_contig_pages = (1ULL << contig_va_bits) >> vm->page_shift;
+
+ sparsebit_set_num(vm->vpages_valid, 0, nr_contig_pages);
+
+ if (vm->has_split_va_space)
+ sparsebit_set_num(vm->vpages_valid,
+ -(1ULL << contig_va_bits),
+ nr_contig_pages);
+}
+
struct kvm_vm *____vm_create(enum vm_guest_mode mode)
{
struct kvm_vm *vm;
@@ -268,17 +305,17 @@ struct kvm_vm *____vm_create(enum vm_guest_mode mode)
#ifdef __aarch64__
if (vm->pa_bits != 40)
vm->type = KVM_VM_TYPE_ARM_IPA_SIZE(vm->pa_bits);
+
+ /* selftests use TTBR0 only, meaning there is a single VA region. */
+ vm->has_split_va_space = false;
+#else
+ vm->has_split_va_space = true;
#endif
vm_open(vm);
- /* Limit to VA-bit canonical virtual addresses. */
vm->vpages_valid = sparsebit_alloc();
- sparsebit_set_num(vm->vpages_valid,
- 0, (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
- sparsebit_set_num(vm->vpages_valid,
- (~((1ULL << (vm->va_bits - 1)) - 1)) >> vm->page_shift,
- (1ULL << (vm->va_bits - 1)) >> vm->page_shift);
+ vm_vaddr_populate_bitmap(vm);
/* Limit physical addresses to PA-bits. */
vm->max_gfn = vm_compute_max_gfn(vm);
--
2.39.0.rc1.256.g54fd8350bd-goog
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2022-12-09 1:53 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-12-09 1:52 [PATCH v2 0/7] KVM: selftests: Fixes for ucall pool + page_fault_test Oliver Upton
2022-12-09 1:52 ` Oliver Upton
2022-12-09 1:52 ` Oliver Upton
2022-12-09 1:53 ` [PATCH v2 1/7] KVM: selftests: Fix build due to ucall_uninit() removal Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` [PATCH v2 2/7] KVM: selftests: Setup ucall after loading program into guest memory Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` [PATCH v2 3/7] KVM: selftests: Mark correct page as mapped in virt_map() Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton [this message]
2022-12-09 1:53 ` [PATCH v2 4/7] KVM: selftests: Correctly initialize the VA space for TTBR0_EL1 Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 20:45 ` Sean Christopherson
2022-12-09 20:45 ` Sean Christopherson
2022-12-09 20:45 ` Sean Christopherson
2022-12-09 21:22 ` Oliver Upton
2022-12-09 21:22 ` Oliver Upton
2022-12-09 21:22 ` Oliver Upton
2022-12-12 10:34 ` Paolo Bonzini
2022-12-12 10:34 ` Paolo Bonzini
2022-12-12 10:34 ` Paolo Bonzini
2022-12-09 1:53 ` [PATCH v2 5/7] KVM: arm64: selftests: Don't identity map the ucall MMIO hole Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` [PATCH v2 6/7] KVM: selftests: Allocate ucall pool from MEM_REGION_DATA Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` [PATCH v2 7/7] KVM: selftests: Avoid infinite loop if ucall_alloc() fails Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 1:53 ` Oliver Upton
2022-12-09 21:03 ` Sean Christopherson
2022-12-09 21:03 ` Sean Christopherson
2022-12-09 21:03 ` Sean Christopherson
2022-12-09 21:35 ` Oliver Upton
2022-12-09 21:35 ` Oliver Upton
2022-12-09 21:35 ` Oliver Upton
2022-12-12 10:38 ` Paolo Bonzini
2022-12-12 10:38 ` Paolo Bonzini
2022-12-12 10:38 ` Paolo Bonzini
2022-12-09 8:24 ` [PATCH v2 0/7] KVM: selftests: Fixes for ucall pool + page_fault_test Andrew Jones
2022-12-09 8:24 ` Andrew Jones
2022-12-09 8:24 ` Andrew Jones
2022-12-09 8:29 ` Oliver Upton
2022-12-09 8:29 ` Oliver Upton
2022-12-09 8:29 ` Oliver Upton
2022-12-12 10:36 ` Paolo Bonzini
2022-12-12 10:36 ` Paolo Bonzini
2022-12-12 10:36 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20221209015307.1781352-5-oliver.upton@linux.dev \
--to=oliver.upton@linux.dev \
--cc=alexandru.elisei@arm.com \
--cc=james.morse@arm.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=maz@kernel.org \
--cc=pbonzini@redhat.com \
--cc=shuah@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.