* [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series @ 2022-11-16 16:56 Oliver Upton 2022-11-16 16:56 ` Oliver Upton ` (2 more replies) 0 siblings, 3 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei Cc: kvm, kvmarm, Will Deacon, kvmarm, linux-arm-kernel Small set of fixes for the parallel faults series. Most importantly, stop taking the RCU read lock for walking hyp stage-1. For the sake of consistency, take a pointer to kvm_pgtable_walker in kvm_dereference_pteref() as well. Tested on an Ampere Altra system with kvm-arm.mode={nvhe,protected}. Applies to the parallel faults series picked up last week. v2: https://lore.kernel.org/kvmarm/20221115225502.2240227-1-oliver.upton@linux.dev/ v2 -> v3: - Pass a pointer to the walker instead of a bool (Marc) - Apply the aforementioned change to kvm_dereference_pteref() Oliver Upton (2): KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() KVM: arm64: Don't acquire RCU read lock for exclusive table walks arch/arm64/include/asm/kvm_pgtable.h | 154 +++++++++++++++------------ arch/arm64/kvm/hyp/pgtable.c | 10 +- 2 files changed, 88 insertions(+), 76 deletions(-) -- 2.38.1.431.g37b22c650d-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series 2022-11-16 16:56 [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series Oliver Upton @ 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() Oliver Upton 2022-11-16 16:56 ` [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks Oliver Upton 2 siblings, 0 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei Cc: linux-arm-kernel, kvmarm, kvm, kvmarm, Will Deacon, Oliver Upton Small set of fixes for the parallel faults series. Most importantly, stop taking the RCU read lock for walking hyp stage-1. For the sake of consistency, take a pointer to kvm_pgtable_walker in kvm_dereference_pteref() as well. Tested on an Ampere Altra system with kvm-arm.mode={nvhe,protected}. Applies to the parallel faults series picked up last week. v2: https://lore.kernel.org/kvmarm/20221115225502.2240227-1-oliver.upton@linux.dev/ v2 -> v3: - Pass a pointer to the walker instead of a bool (Marc) - Apply the aforementioned change to kvm_dereference_pteref() Oliver Upton (2): KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() KVM: arm64: Don't acquire RCU read lock for exclusive table walks arch/arm64/include/asm/kvm_pgtable.h | 154 +++++++++++++++------------ arch/arm64/kvm/hyp/pgtable.c | 10 +- 2 files changed, 88 insertions(+), 76 deletions(-) -- 2.38.1.431.g37b22c650d-goog ^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() 2022-11-16 16:56 [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series Oliver Upton 2022-11-16 16:56 ` Oliver Upton @ 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks Oliver Upton 2 siblings, 1 reply; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Oliver Upton, Catalin Marinas, Will Deacon Cc: kvmarm, linux-kernel, kvmarm, linux-arm-kernel, kvm Rather than passing through the state of the KVM_PGTABLE_WALK_SHARED flag, just take a pointer to the whole walker structure instead. Move around struct kvm_pgtable and the RCU indirection such that the associated ifdeffery remains in one place while ensuring the walker + flags definitions precede their use. No functional change intended. Signed-off-by: Oliver Upton <oliver.upton@linux.dev> --- arch/arm64/include/asm/kvm_pgtable.h | 144 ++++++++++++++------------- arch/arm64/kvm/hyp/pgtable.c | 6 +- 2 files changed, 76 insertions(+), 74 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index a874ce0ce7b5..f23af693e3c5 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -37,54 +37,6 @@ static inline u64 kvm_get_parange(u64 mmfr0) typedef u64 kvm_pte_t; -/* - * RCU cannot be used in a non-kernel context such as the hyp. As such, page - * table walkers used in hyp do not call into RCU and instead use other - * synchronization mechanisms (such as a spinlock). - */ -#if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) - -typedef kvm_pte_t *kvm_pteref_t; - -static inline kvm_pte_t *kvm_dereference_pteref(kvm_pteref_t pteref, bool shared) -{ - return pteref; -} - -static inline void kvm_pgtable_walk_begin(void) {} -static inline void kvm_pgtable_walk_end(void) {} - -static inline bool kvm_pgtable_walk_lock_held(void) -{ - return true; -} - -#else - -typedef kvm_pte_t __rcu *kvm_pteref_t; - -static inline kvm_pte_t *kvm_dereference_pteref(kvm_pteref_t pteref, bool shared) -{ - return rcu_dereference_check(pteref, !shared); -} - -static inline void kvm_pgtable_walk_begin(void) -{ - rcu_read_lock(); -} - -static inline void kvm_pgtable_walk_end(void) -{ - rcu_read_unlock(); -} - -static inline bool kvm_pgtable_walk_lock_held(void) -{ - return rcu_read_lock_held(); -} - -#endif - #define KVM_PTE_VALID BIT(0) #define KVM_PTE_ADDR_MASK GENMASK(47, PAGE_SHIFT) @@ -212,29 +164,6 @@ enum kvm_pgtable_prot { typedef bool (*kvm_pgtable_force_pte_cb_t)(u64 addr, u64 end, enum kvm_pgtable_prot prot); -/** - * struct kvm_pgtable - KVM page-table. - * @ia_bits: Maximum input address size, in bits. - * @start_level: Level at which the page-table walk starts. - * @pgd: Pointer to the first top-level entry of the page-table. - * @mm_ops: Memory management callbacks. - * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables. - * @flags: Stage-2 page-table flags. - * @force_pte_cb: Function that returns true if page level mappings must - * be used instead of block mappings. - */ -struct kvm_pgtable { - u32 ia_bits; - u32 start_level; - kvm_pteref_t pgd; - struct kvm_pgtable_mm_ops *mm_ops; - - /* Stage-2 only */ - struct kvm_s2_mmu *mmu; - enum kvm_pgtable_stage2_flags flags; - kvm_pgtable_force_pte_cb_t force_pte_cb; -}; - /** * enum kvm_pgtable_walk_flags - Flags to control a depth-first page-table walk. * @KVM_PGTABLE_WALK_LEAF: Visit leaf entries, including invalid @@ -285,6 +214,79 @@ struct kvm_pgtable_walker { const enum kvm_pgtable_walk_flags flags; }; +/* + * RCU cannot be used in a non-kernel context such as the hyp. As such, page + * table walkers used in hyp do not call into RCU and instead use other + * synchronization mechanisms (such as a spinlock). + */ +#if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) + +typedef kvm_pte_t *kvm_pteref_t; + +static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walker, + kvm_pteref_t pteref) +{ + return pteref; +} + +static inline void kvm_pgtable_walk_begin(void) {} +static inline void kvm_pgtable_walk_end(void) {} + +static inline bool kvm_pgtable_walk_lock_held(void) +{ + return true; +} + +#else + +typedef kvm_pte_t __rcu *kvm_pteref_t; + +static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walker, + kvm_pteref_t pteref) +{ + return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); +} + +static inline void kvm_pgtable_walk_begin(void) +{ + rcu_read_lock(); +} + +static inline void kvm_pgtable_walk_end(void) +{ + rcu_read_unlock(); +} + +static inline bool kvm_pgtable_walk_lock_held(void) +{ + return rcu_read_lock_held(); +} + +#endif + +/** + * struct kvm_pgtable - KVM page-table. + * @ia_bits: Maximum input address size, in bits. + * @start_level: Level at which the page-table walk starts. + * @pgd: Pointer to the first top-level entry of the page-table. + * @mm_ops: Memory management callbacks. + * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables. + * @flags: Stage-2 page-table flags. + * @force_pte_cb: Function that returns true if page level mappings must + * be used instead of block mappings. + */ +struct kvm_pgtable { + u32 ia_bits; + u32 start_level; + kvm_pteref_t pgd; + struct kvm_pgtable_mm_ops *mm_ops; + + /* Stage-2 only */ + struct kvm_s2_mmu *mmu; + enum kvm_pgtable_stage2_flags flags; + kvm_pgtable_force_pte_cb_t force_pte_cb; +}; + /** * kvm_pgtable_hyp_init() - Initialise a hypervisor stage-1 page-table. * @pgt: Uninitialised page-table structure to initialise. diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 5bca9610d040..b5b91a882836 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -188,7 +188,7 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data, kvm_pteref_t pteref, u32 level) { enum kvm_pgtable_walk_flags flags = data->walker->flags; - kvm_pte_t *ptep = kvm_dereference_pteref(pteref, flags & KVM_PGTABLE_WALK_SHARED); + kvm_pte_t *ptep = kvm_dereference_pteref(data->walker, pteref); struct kvm_pgtable_visit_ctx ctx = { .ptep = ptep, .old = READ_ONCE(*ptep), @@ -558,7 +558,7 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt) }; WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker)); - pgt->mm_ops->put_page(kvm_dereference_pteref(pgt->pgd, false)); + pgt->mm_ops->put_page(kvm_dereference_pteref(&walker, pgt->pgd)); pgt->pgd = NULL; } @@ -1241,7 +1241,7 @@ void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker)); pgd_sz = kvm_pgd_pages(pgt->ia_bits, pgt->start_level) * PAGE_SIZE; - pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(pgt->pgd, false), pgd_sz); + pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(&walker, pgt->pgd), pgd_sz); pgt->pgd = NULL; } -- 2.38.1.431.g37b22c650d-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() 2022-11-16 16:56 ` [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() Oliver Upton @ 2022-11-16 16:56 ` Oliver Upton 0 siblings, 0 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Oliver Upton, Catalin Marinas, Will Deacon Cc: linux-arm-kernel, kvmarm, kvm, kvmarm, linux-kernel Rather than passing through the state of the KVM_PGTABLE_WALK_SHARED flag, just take a pointer to the whole walker structure instead. Move around struct kvm_pgtable and the RCU indirection such that the associated ifdeffery remains in one place while ensuring the walker + flags definitions precede their use. No functional change intended. Signed-off-by: Oliver Upton <oliver.upton@linux.dev> --- arch/arm64/include/asm/kvm_pgtable.h | 144 ++++++++++++++------------- arch/arm64/kvm/hyp/pgtable.c | 6 +- 2 files changed, 76 insertions(+), 74 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index a874ce0ce7b5..f23af693e3c5 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -37,54 +37,6 @@ static inline u64 kvm_get_parange(u64 mmfr0) typedef u64 kvm_pte_t; -/* - * RCU cannot be used in a non-kernel context such as the hyp. As such, page - * table walkers used in hyp do not call into RCU and instead use other - * synchronization mechanisms (such as a spinlock). - */ -#if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) - -typedef kvm_pte_t *kvm_pteref_t; - -static inline kvm_pte_t *kvm_dereference_pteref(kvm_pteref_t pteref, bool shared) -{ - return pteref; -} - -static inline void kvm_pgtable_walk_begin(void) {} -static inline void kvm_pgtable_walk_end(void) {} - -static inline bool kvm_pgtable_walk_lock_held(void) -{ - return true; -} - -#else - -typedef kvm_pte_t __rcu *kvm_pteref_t; - -static inline kvm_pte_t *kvm_dereference_pteref(kvm_pteref_t pteref, bool shared) -{ - return rcu_dereference_check(pteref, !shared); -} - -static inline void kvm_pgtable_walk_begin(void) -{ - rcu_read_lock(); -} - -static inline void kvm_pgtable_walk_end(void) -{ - rcu_read_unlock(); -} - -static inline bool kvm_pgtable_walk_lock_held(void) -{ - return rcu_read_lock_held(); -} - -#endif - #define KVM_PTE_VALID BIT(0) #define KVM_PTE_ADDR_MASK GENMASK(47, PAGE_SHIFT) @@ -212,29 +164,6 @@ enum kvm_pgtable_prot { typedef bool (*kvm_pgtable_force_pte_cb_t)(u64 addr, u64 end, enum kvm_pgtable_prot prot); -/** - * struct kvm_pgtable - KVM page-table. - * @ia_bits: Maximum input address size, in bits. - * @start_level: Level at which the page-table walk starts. - * @pgd: Pointer to the first top-level entry of the page-table. - * @mm_ops: Memory management callbacks. - * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables. - * @flags: Stage-2 page-table flags. - * @force_pte_cb: Function that returns true if page level mappings must - * be used instead of block mappings. - */ -struct kvm_pgtable { - u32 ia_bits; - u32 start_level; - kvm_pteref_t pgd; - struct kvm_pgtable_mm_ops *mm_ops; - - /* Stage-2 only */ - struct kvm_s2_mmu *mmu; - enum kvm_pgtable_stage2_flags flags; - kvm_pgtable_force_pte_cb_t force_pte_cb; -}; - /** * enum kvm_pgtable_walk_flags - Flags to control a depth-first page-table walk. * @KVM_PGTABLE_WALK_LEAF: Visit leaf entries, including invalid @@ -285,6 +214,79 @@ struct kvm_pgtable_walker { const enum kvm_pgtable_walk_flags flags; }; +/* + * RCU cannot be used in a non-kernel context such as the hyp. As such, page + * table walkers used in hyp do not call into RCU and instead use other + * synchronization mechanisms (such as a spinlock). + */ +#if defined(__KVM_NVHE_HYPERVISOR__) || defined(__KVM_VHE_HYPERVISOR__) + +typedef kvm_pte_t *kvm_pteref_t; + +static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walker, + kvm_pteref_t pteref) +{ + return pteref; +} + +static inline void kvm_pgtable_walk_begin(void) {} +static inline void kvm_pgtable_walk_end(void) {} + +static inline bool kvm_pgtable_walk_lock_held(void) +{ + return true; +} + +#else + +typedef kvm_pte_t __rcu *kvm_pteref_t; + +static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walker, + kvm_pteref_t pteref) +{ + return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); +} + +static inline void kvm_pgtable_walk_begin(void) +{ + rcu_read_lock(); +} + +static inline void kvm_pgtable_walk_end(void) +{ + rcu_read_unlock(); +} + +static inline bool kvm_pgtable_walk_lock_held(void) +{ + return rcu_read_lock_held(); +} + +#endif + +/** + * struct kvm_pgtable - KVM page-table. + * @ia_bits: Maximum input address size, in bits. + * @start_level: Level at which the page-table walk starts. + * @pgd: Pointer to the first top-level entry of the page-table. + * @mm_ops: Memory management callbacks. + * @mmu: Stage-2 KVM MMU struct. Unused for stage-1 page-tables. + * @flags: Stage-2 page-table flags. + * @force_pte_cb: Function that returns true if page level mappings must + * be used instead of block mappings. + */ +struct kvm_pgtable { + u32 ia_bits; + u32 start_level; + kvm_pteref_t pgd; + struct kvm_pgtable_mm_ops *mm_ops; + + /* Stage-2 only */ + struct kvm_s2_mmu *mmu; + enum kvm_pgtable_stage2_flags flags; + kvm_pgtable_force_pte_cb_t force_pte_cb; +}; + /** * kvm_pgtable_hyp_init() - Initialise a hypervisor stage-1 page-table. * @pgt: Uninitialised page-table structure to initialise. diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index 5bca9610d040..b5b91a882836 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -188,7 +188,7 @@ static inline int __kvm_pgtable_visit(struct kvm_pgtable_walk_data *data, kvm_pteref_t pteref, u32 level) { enum kvm_pgtable_walk_flags flags = data->walker->flags; - kvm_pte_t *ptep = kvm_dereference_pteref(pteref, flags & KVM_PGTABLE_WALK_SHARED); + kvm_pte_t *ptep = kvm_dereference_pteref(data->walker, pteref); struct kvm_pgtable_visit_ctx ctx = { .ptep = ptep, .old = READ_ONCE(*ptep), @@ -558,7 +558,7 @@ void kvm_pgtable_hyp_destroy(struct kvm_pgtable *pgt) }; WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker)); - pgt->mm_ops->put_page(kvm_dereference_pteref(pgt->pgd, false)); + pgt->mm_ops->put_page(kvm_dereference_pteref(&walker, pgt->pgd)); pgt->pgd = NULL; } @@ -1241,7 +1241,7 @@ void kvm_pgtable_stage2_destroy(struct kvm_pgtable *pgt) WARN_ON(kvm_pgtable_walk(pgt, 0, BIT(pgt->ia_bits), &walker)); pgd_sz = kvm_pgd_pages(pgt->ia_bits, pgt->start_level) * PAGE_SIZE; - pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(pgt->pgd, false), pgd_sz); + pgt->mm_ops->free_pages_exact(kvm_dereference_pteref(&walker, pgt->pgd), pgd_sz); pgt->pgd = NULL; } -- 2.38.1.431.g37b22c650d-goog ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-16 16:56 [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() Oliver Upton @ 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-17 17:49 ` Will Deacon 2 siblings, 2 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Oliver Upton, Catalin Marinas, Will Deacon Cc: kvm, linux-kernel, kvmarm, kvmarm, linux-arm-kernel, Marek Szyprowski Marek reported a BUG resulting from the recent parallel faults changes, as the hyp stage-1 map walker attempted to allocate table memory while holding the RCU read lock: BUG: sleeping function called from invalid context at include/linux/sched/mm.h:274 in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0 preempt_count: 0, expected: 0 RCU nest depth: 1, expected: 0 2 locks held by swapper/0/1: #0: ffff80000a8a44d0 (kvm_hyp_pgd_mutex){+.+.}-{3:3}, at: __create_hyp_mappings+0x80/0xc4 #1: ffff80000a927720 (rcu_read_lock){....}-{1:2}, at: kvm_pgtable_walk+0x0/0x1f4 CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc3+ #5918 Hardware name: Raspberry Pi 3 Model B (DT) Call trace: dump_backtrace.part.0+0xe4/0xf0 show_stack+0x18/0x40 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 __might_resched+0x178/0x220 __might_sleep+0x48/0xa0 prepare_alloc_pages+0x178/0x1a0 __alloc_pages+0x9c/0x109c alloc_page_interleave+0x1c/0xc4 alloc_pages+0xec/0x160 get_zeroed_page+0x1c/0x44 kvm_hyp_zalloc_page+0x14/0x20 hyp_map_walker+0xd4/0x134 kvm_pgtable_visitor_cb.isra.0+0x38/0x5c __kvm_pgtable_walk+0x1a4/0x220 kvm_pgtable_walk+0x104/0x1f4 kvm_pgtable_hyp_map+0x80/0xc4 __create_hyp_mappings+0x9c/0xc4 kvm_mmu_init+0x144/0x1cc kvm_arch_init+0xe4/0xef4 kvm_init+0x3c/0x3d0 arm_init+0x20/0x30 do_one_initcall+0x74/0x400 kernel_init_freeable+0x2e0/0x350 kernel_init+0x24/0x130 ret_from_fork+0x10/0x20 Since the hyp stage-1 table walkers are serialized by kvm_hyp_pgd_mutex, RCU protection really doesn't add anything. Don't acquire the RCU read lock for an exclusive walk. While at it, add a warning which codifies the lack of support for shared walks in the hypervisor code. Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Oliver Upton <oliver.upton@linux.dev> --- arch/arm64/include/asm/kvm_pgtable.h | 22 ++++++++++++++++------ arch/arm64/kvm/hyp/pgtable.c | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index f23af693e3c5..a07fc5e35a8c 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -229,8 +229,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke return pteref; } -static inline void kvm_pgtable_walk_begin(void) {} -static inline void kvm_pgtable_walk_end(void) {} +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) +{ + /* + * Due to the lack of RCU (or a similar protection scheme), only + * non-shared table walkers are allowed in the hypervisor. + */ + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); +} + +static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker) {} static inline bool kvm_pgtable_walk_lock_held(void) { @@ -247,14 +255,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); } -static inline void kvm_pgtable_walk_begin(void) +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) { - rcu_read_lock(); + if (walker->flags & KVM_PGTABLE_WALK_SHARED) + rcu_read_lock(); } -static inline void kvm_pgtable_walk_end(void) +static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker) { - rcu_read_unlock(); + if (walker->flags & KVM_PGTABLE_WALK_SHARED) + rcu_read_unlock(); } static inline bool kvm_pgtable_walk_lock_held(void) diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index b5b91a882836..d6f3753cb87e 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -289,9 +289,9 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size, }; int r; - kvm_pgtable_walk_begin(); + kvm_pgtable_walk_begin(walker); r = _kvm_pgtable_walk(pgt, &walk_data); - kvm_pgtable_walk_end(); + kvm_pgtable_walk_end(walker); return r; } -- 2.38.1.431.g37b22c650d-goog _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-16 16:56 ` [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks Oliver Upton @ 2022-11-16 16:56 ` Oliver Upton 2022-11-17 17:49 ` Will Deacon 1 sibling, 0 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-16 16:56 UTC (permalink / raw) To: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Oliver Upton, Catalin Marinas, Will Deacon Cc: linux-arm-kernel, kvmarm, kvm, kvmarm, Marek Szyprowski, linux-kernel Marek reported a BUG resulting from the recent parallel faults changes, as the hyp stage-1 map walker attempted to allocate table memory while holding the RCU read lock: BUG: sleeping function called from invalid context at include/linux/sched/mm.h:274 in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0 preempt_count: 0, expected: 0 RCU nest depth: 1, expected: 0 2 locks held by swapper/0/1: #0: ffff80000a8a44d0 (kvm_hyp_pgd_mutex){+.+.}-{3:3}, at: __create_hyp_mappings+0x80/0xc4 #1: ffff80000a927720 (rcu_read_lock){....}-{1:2}, at: kvm_pgtable_walk+0x0/0x1f4 CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc3+ #5918 Hardware name: Raspberry Pi 3 Model B (DT) Call trace: dump_backtrace.part.0+0xe4/0xf0 show_stack+0x18/0x40 dump_stack_lvl+0x8c/0xb8 dump_stack+0x18/0x34 __might_resched+0x178/0x220 __might_sleep+0x48/0xa0 prepare_alloc_pages+0x178/0x1a0 __alloc_pages+0x9c/0x109c alloc_page_interleave+0x1c/0xc4 alloc_pages+0xec/0x160 get_zeroed_page+0x1c/0x44 kvm_hyp_zalloc_page+0x14/0x20 hyp_map_walker+0xd4/0x134 kvm_pgtable_visitor_cb.isra.0+0x38/0x5c __kvm_pgtable_walk+0x1a4/0x220 kvm_pgtable_walk+0x104/0x1f4 kvm_pgtable_hyp_map+0x80/0xc4 __create_hyp_mappings+0x9c/0xc4 kvm_mmu_init+0x144/0x1cc kvm_arch_init+0xe4/0xef4 kvm_init+0x3c/0x3d0 arm_init+0x20/0x30 do_one_initcall+0x74/0x400 kernel_init_freeable+0x2e0/0x350 kernel_init+0x24/0x130 ret_from_fork+0x10/0x20 Since the hyp stage-1 table walkers are serialized by kvm_hyp_pgd_mutex, RCU protection really doesn't add anything. Don't acquire the RCU read lock for an exclusive walk. While at it, add a warning which codifies the lack of support for shared walks in the hypervisor code. Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> Signed-off-by: Oliver Upton <oliver.upton@linux.dev> --- arch/arm64/include/asm/kvm_pgtable.h | 22 ++++++++++++++++------ arch/arm64/kvm/hyp/pgtable.c | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h index f23af693e3c5..a07fc5e35a8c 100644 --- a/arch/arm64/include/asm/kvm_pgtable.h +++ b/arch/arm64/include/asm/kvm_pgtable.h @@ -229,8 +229,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke return pteref; } -static inline void kvm_pgtable_walk_begin(void) {} -static inline void kvm_pgtable_walk_end(void) {} +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) +{ + /* + * Due to the lack of RCU (or a similar protection scheme), only + * non-shared table walkers are allowed in the hypervisor. + */ + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); +} + +static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker) {} static inline bool kvm_pgtable_walk_lock_held(void) { @@ -247,14 +255,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke return rcu_dereference_check(pteref, !(walker->flags & KVM_PGTABLE_WALK_SHARED)); } -static inline void kvm_pgtable_walk_begin(void) +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) { - rcu_read_lock(); + if (walker->flags & KVM_PGTABLE_WALK_SHARED) + rcu_read_lock(); } -static inline void kvm_pgtable_walk_end(void) +static inline void kvm_pgtable_walk_end(struct kvm_pgtable_walker *walker) { - rcu_read_unlock(); + if (walker->flags & KVM_PGTABLE_WALK_SHARED) + rcu_read_unlock(); } static inline bool kvm_pgtable_walk_lock_held(void) diff --git a/arch/arm64/kvm/hyp/pgtable.c b/arch/arm64/kvm/hyp/pgtable.c index b5b91a882836..d6f3753cb87e 100644 --- a/arch/arm64/kvm/hyp/pgtable.c +++ b/arch/arm64/kvm/hyp/pgtable.c @@ -289,9 +289,9 @@ int kvm_pgtable_walk(struct kvm_pgtable *pgt, u64 addr, u64 size, }; int r; - kvm_pgtable_walk_begin(); + kvm_pgtable_walk_begin(walker); r = _kvm_pgtable_walk(pgt, &walk_data); - kvm_pgtable_walk_end(); + kvm_pgtable_walk_end(walker); return r; } -- 2.38.1.431.g37b22c650d-goog ^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-16 16:56 ` [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks Oliver Upton 2022-11-16 16:56 ` Oliver Upton @ 2022-11-17 17:49 ` Will Deacon 2022-11-17 17:49 ` Will Deacon 2022-11-17 18:23 ` Oliver Upton 1 sibling, 2 replies; 14+ messages in thread From: Will Deacon @ 2022-11-17 17:49 UTC (permalink / raw) To: Oliver Upton Cc: kvm, Marc Zyngier, linux-kernel, Catalin Marinas, kvmarm, kvmarm, linux-arm-kernel, Marek Szyprowski On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > Marek reported a BUG resulting from the recent parallel faults changes, > as the hyp stage-1 map walker attempted to allocate table memory while > holding the RCU read lock: > > BUG: sleeping function called from invalid context at > include/linux/sched/mm.h:274 > in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0 > preempt_count: 0, expected: 0 > RCU nest depth: 1, expected: 0 > 2 locks held by swapper/0/1: > #0: ffff80000a8a44d0 (kvm_hyp_pgd_mutex){+.+.}-{3:3}, at: > __create_hyp_mappings+0x80/0xc4 > #1: ffff80000a927720 (rcu_read_lock){....}-{1:2}, at: > kvm_pgtable_walk+0x0/0x1f4 > CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc3+ #5918 > Hardware name: Raspberry Pi 3 Model B (DT) > Call trace: > dump_backtrace.part.0+0xe4/0xf0 > show_stack+0x18/0x40 > dump_stack_lvl+0x8c/0xb8 > dump_stack+0x18/0x34 > __might_resched+0x178/0x220 > __might_sleep+0x48/0xa0 > prepare_alloc_pages+0x178/0x1a0 > __alloc_pages+0x9c/0x109c > alloc_page_interleave+0x1c/0xc4 > alloc_pages+0xec/0x160 > get_zeroed_page+0x1c/0x44 > kvm_hyp_zalloc_page+0x14/0x20 > hyp_map_walker+0xd4/0x134 > kvm_pgtable_visitor_cb.isra.0+0x38/0x5c > __kvm_pgtable_walk+0x1a4/0x220 > kvm_pgtable_walk+0x104/0x1f4 > kvm_pgtable_hyp_map+0x80/0xc4 > __create_hyp_mappings+0x9c/0xc4 > kvm_mmu_init+0x144/0x1cc > kvm_arch_init+0xe4/0xef4 > kvm_init+0x3c/0x3d0 > arm_init+0x20/0x30 > do_one_initcall+0x74/0x400 > kernel_init_freeable+0x2e0/0x350 > kernel_init+0x24/0x130 > ret_from_fork+0x10/0x20 > > Since the hyp stage-1 table walkers are serialized by kvm_hyp_pgd_mutex, > RCU protection really doesn't add anything. Don't acquire the RCU read > lock for an exclusive walk. While at it, add a warning which codifies > the lack of support for shared walks in the hypervisor code. > > Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> > Signed-off-by: Oliver Upton <oliver.upton@linux.dev> > --- > arch/arm64/include/asm/kvm_pgtable.h | 22 ++++++++++++++++------ > arch/arm64/kvm/hyp/pgtable.c | 4 ++-- > 2 files changed, 18 insertions(+), 8 deletions(-) > > diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h > index f23af693e3c5..a07fc5e35a8c 100644 > --- a/arch/arm64/include/asm/kvm_pgtable.h > +++ b/arch/arm64/include/asm/kvm_pgtable.h > @@ -229,8 +229,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke > return pteref; > } > > -static inline void kvm_pgtable_walk_begin(void) {} > -static inline void kvm_pgtable_walk_end(void) {} > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > +{ > + /* > + * Due to the lack of RCU (or a similar protection scheme), only > + * non-shared table walkers are allowed in the hypervisor. > + */ > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > +} I think it would be better to propagate the error to the caller rather than WARN here. Since you're rejigging things anyway, can you have this function return int? Will _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-17 17:49 ` Will Deacon @ 2022-11-17 17:49 ` Will Deacon 2022-11-17 18:23 ` Oliver Upton 1 sibling, 0 replies; 14+ messages in thread From: Will Deacon @ 2022-11-17 17:49 UTC (permalink / raw) To: Oliver Upton Cc: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, linux-arm-kernel, kvmarm, kvm, kvmarm, Marek Szyprowski, linux-kernel On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > Marek reported a BUG resulting from the recent parallel faults changes, > as the hyp stage-1 map walker attempted to allocate table memory while > holding the RCU read lock: > > BUG: sleeping function called from invalid context at > include/linux/sched/mm.h:274 > in_atomic(): 0, irqs_disabled(): 0, non_block: 0, pid: 1, name: swapper/0 > preempt_count: 0, expected: 0 > RCU nest depth: 1, expected: 0 > 2 locks held by swapper/0/1: > #0: ffff80000a8a44d0 (kvm_hyp_pgd_mutex){+.+.}-{3:3}, at: > __create_hyp_mappings+0x80/0xc4 > #1: ffff80000a927720 (rcu_read_lock){....}-{1:2}, at: > kvm_pgtable_walk+0x0/0x1f4 > CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.1.0-rc3+ #5918 > Hardware name: Raspberry Pi 3 Model B (DT) > Call trace: > dump_backtrace.part.0+0xe4/0xf0 > show_stack+0x18/0x40 > dump_stack_lvl+0x8c/0xb8 > dump_stack+0x18/0x34 > __might_resched+0x178/0x220 > __might_sleep+0x48/0xa0 > prepare_alloc_pages+0x178/0x1a0 > __alloc_pages+0x9c/0x109c > alloc_page_interleave+0x1c/0xc4 > alloc_pages+0xec/0x160 > get_zeroed_page+0x1c/0x44 > kvm_hyp_zalloc_page+0x14/0x20 > hyp_map_walker+0xd4/0x134 > kvm_pgtable_visitor_cb.isra.0+0x38/0x5c > __kvm_pgtable_walk+0x1a4/0x220 > kvm_pgtable_walk+0x104/0x1f4 > kvm_pgtable_hyp_map+0x80/0xc4 > __create_hyp_mappings+0x9c/0xc4 > kvm_mmu_init+0x144/0x1cc > kvm_arch_init+0xe4/0xef4 > kvm_init+0x3c/0x3d0 > arm_init+0x20/0x30 > do_one_initcall+0x74/0x400 > kernel_init_freeable+0x2e0/0x350 > kernel_init+0x24/0x130 > ret_from_fork+0x10/0x20 > > Since the hyp stage-1 table walkers are serialized by kvm_hyp_pgd_mutex, > RCU protection really doesn't add anything. Don't acquire the RCU read > lock for an exclusive walk. While at it, add a warning which codifies > the lack of support for shared walks in the hypervisor code. > > Reported-by: Marek Szyprowski <m.szyprowski@samsung.com> > Signed-off-by: Oliver Upton <oliver.upton@linux.dev> > --- > arch/arm64/include/asm/kvm_pgtable.h | 22 ++++++++++++++++------ > arch/arm64/kvm/hyp/pgtable.c | 4 ++-- > 2 files changed, 18 insertions(+), 8 deletions(-) > > diff --git a/arch/arm64/include/asm/kvm_pgtable.h b/arch/arm64/include/asm/kvm_pgtable.h > index f23af693e3c5..a07fc5e35a8c 100644 > --- a/arch/arm64/include/asm/kvm_pgtable.h > +++ b/arch/arm64/include/asm/kvm_pgtable.h > @@ -229,8 +229,16 @@ static inline kvm_pte_t *kvm_dereference_pteref(struct kvm_pgtable_walker *walke > return pteref; > } > > -static inline void kvm_pgtable_walk_begin(void) {} > -static inline void kvm_pgtable_walk_end(void) {} > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > +{ > + /* > + * Due to the lack of RCU (or a similar protection scheme), only > + * non-shared table walkers are allowed in the hypervisor. > + */ > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > +} I think it would be better to propagate the error to the caller rather than WARN here. Since you're rejigging things anyway, can you have this function return int? Will ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-17 17:49 ` Will Deacon 2022-11-17 17:49 ` Will Deacon @ 2022-11-17 18:23 ` Oliver Upton 2022-11-17 18:23 ` Oliver Upton 2022-11-18 12:19 ` Will Deacon 1 sibling, 2 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-17 18:23 UTC (permalink / raw) To: Will Deacon Cc: kvm, Marc Zyngier, linux-kernel, Catalin Marinas, kvmarm, kvmarm, linux-arm-kernel, Marek Szyprowski Hi Will, Thanks for having a look. On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: [...] > > -static inline void kvm_pgtable_walk_begin(void) {} > > -static inline void kvm_pgtable_walk_end(void) {} > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > +{ > > + /* > > + * Due to the lack of RCU (or a similar protection scheme), only > > + * non-shared table walkers are allowed in the hypervisor. > > + */ > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > +} > > I think it would be better to propagate the error to the caller rather > than WARN here. I'd really like to warn somewhere though since we're rather fscked at this point. Keeping that WARN close to the exceptional condition would help w/ debugging. Were you envisioning bubbling the error all the way back up (i.e. early return from kvm_pgtable_walk())? I had really only intended these to indirect lock acquisition/release, so the error handling on the caller side feels weird: static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) { if (WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED)) return -EPERM; return 0; } r = kvm_pgtable_walk_begin() if (r) return r; r = _kvm_pgtable_walk(); kvm_pgtable_walk_end(); > Since you're rejigging things anyway, can you have this > function return int? If having this is a strong motivator I can do a v4. -- Thanks, Oliver _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-17 18:23 ` Oliver Upton @ 2022-11-17 18:23 ` Oliver Upton 2022-11-18 12:19 ` Will Deacon 1 sibling, 0 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-17 18:23 UTC (permalink / raw) To: Will Deacon Cc: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, linux-arm-kernel, kvmarm, kvm, kvmarm, Marek Szyprowski, linux-kernel Hi Will, Thanks for having a look. On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: [...] > > -static inline void kvm_pgtable_walk_begin(void) {} > > -static inline void kvm_pgtable_walk_end(void) {} > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > +{ > > + /* > > + * Due to the lack of RCU (or a similar protection scheme), only > > + * non-shared table walkers are allowed in the hypervisor. > > + */ > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > +} > > I think it would be better to propagate the error to the caller rather > than WARN here. I'd really like to warn somewhere though since we're rather fscked at this point. Keeping that WARN close to the exceptional condition would help w/ debugging. Were you envisioning bubbling the error all the way back up (i.e. early return from kvm_pgtable_walk())? I had really only intended these to indirect lock acquisition/release, so the error handling on the caller side feels weird: static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) { if (WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED)) return -EPERM; return 0; } r = kvm_pgtable_walk_begin() if (r) return r; r = _kvm_pgtable_walk(); kvm_pgtable_walk_end(); > Since you're rejigging things anyway, can you have this > function return int? If having this is a strong motivator I can do a v4. -- Thanks, Oliver ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-17 18:23 ` Oliver Upton 2022-11-17 18:23 ` Oliver Upton @ 2022-11-18 12:19 ` Will Deacon 2022-11-18 12:19 ` Will Deacon 2022-11-18 17:12 ` Oliver Upton 1 sibling, 2 replies; 14+ messages in thread From: Will Deacon @ 2022-11-18 12:19 UTC (permalink / raw) To: Oliver Upton Cc: kvm, Marc Zyngier, linux-kernel, Catalin Marinas, kvmarm, kvmarm, linux-arm-kernel, Marek Szyprowski On Thu, Nov 17, 2022 at 06:23:23PM +0000, Oliver Upton wrote: > On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > > [...] > > > > -static inline void kvm_pgtable_walk_begin(void) {} > > > -static inline void kvm_pgtable_walk_end(void) {} > > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > > +{ > > > + /* > > > + * Due to the lack of RCU (or a similar protection scheme), only > > > + * non-shared table walkers are allowed in the hypervisor. > > > + */ > > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > > +} > > > > I think it would be better to propagate the error to the caller rather > > than WARN here. > > I'd really like to warn somewhere though since we're rather fscked at > this point. Keeping that WARN close to the exceptional condition would > help w/ debugging. > > Were you envisioning bubbling the error all the way back up (i.e. early > return from kvm_pgtable_walk())? Yes, that's what I had in mind. WARN is fatal at EL2, so I think it's better to fail the pgtable operation rather than bring down the entire machine by default. Now, it _might_ be fatal anyway (e.g. if we were handling a host stage-2 fault w/ pKVM), but the caller is in a better position to decide the severity. > I had really only intended these to indirect lock acquisition/release, > so the error handling on the caller side feels weird: > > static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > { > if (WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED)) > return -EPERM; > > return 0; > } > > r = kvm_pgtable_walk_begin() > if (r) > return r; > > r = _kvm_pgtable_walk(); > kvm_pgtable_walk_end(); This doesn't look particularly weird to me (modulo dropping the WARN, or moving it to _end()), but maybe I've lost my sense of taste. > > Since you're rejigging things anyway, can you have this > > function return int? > > If having this is a strong motivator I can do a v4. It's a really minor point, so I'll leave it up to you guys. WIll _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-18 12:19 ` Will Deacon @ 2022-11-18 12:19 ` Will Deacon 2022-11-18 17:12 ` Oliver Upton 1 sibling, 0 replies; 14+ messages in thread From: Will Deacon @ 2022-11-18 12:19 UTC (permalink / raw) To: Oliver Upton Cc: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, linux-arm-kernel, kvmarm, kvm, kvmarm, Marek Szyprowski, linux-kernel On Thu, Nov 17, 2022 at 06:23:23PM +0000, Oliver Upton wrote: > On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > > [...] > > > > -static inline void kvm_pgtable_walk_begin(void) {} > > > -static inline void kvm_pgtable_walk_end(void) {} > > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > > +{ > > > + /* > > > + * Due to the lack of RCU (or a similar protection scheme), only > > > + * non-shared table walkers are allowed in the hypervisor. > > > + */ > > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > > +} > > > > I think it would be better to propagate the error to the caller rather > > than WARN here. > > I'd really like to warn somewhere though since we're rather fscked at > this point. Keeping that WARN close to the exceptional condition would > help w/ debugging. > > Were you envisioning bubbling the error all the way back up (i.e. early > return from kvm_pgtable_walk())? Yes, that's what I had in mind. WARN is fatal at EL2, so I think it's better to fail the pgtable operation rather than bring down the entire machine by default. Now, it _might_ be fatal anyway (e.g. if we were handling a host stage-2 fault w/ pKVM), but the caller is in a better position to decide the severity. > I had really only intended these to indirect lock acquisition/release, > so the error handling on the caller side feels weird: > > static inline int kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > { > if (WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED)) > return -EPERM; > > return 0; > } > > r = kvm_pgtable_walk_begin() > if (r) > return r; > > r = _kvm_pgtable_walk(); > kvm_pgtable_walk_end(); This doesn't look particularly weird to me (modulo dropping the WARN, or moving it to _end()), but maybe I've lost my sense of taste. > > Since you're rejigging things anyway, can you have this > > function return int? > > If having this is a strong motivator I can do a v4. It's a really minor point, so I'll leave it up to you guys. WIll ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-18 12:19 ` Will Deacon 2022-11-18 12:19 ` Will Deacon @ 2022-11-18 17:12 ` Oliver Upton 2022-11-18 17:12 ` Oliver Upton 1 sibling, 1 reply; 14+ messages in thread From: Oliver Upton @ 2022-11-18 17:12 UTC (permalink / raw) To: Will Deacon Cc: kvm, Marc Zyngier, linux-kernel, Catalin Marinas, kvmarm, kvmarm, linux-arm-kernel, Marek Szyprowski On Fri, Nov 18, 2022 at 12:19:50PM +0000, Will Deacon wrote: > On Thu, Nov 17, 2022 at 06:23:23PM +0000, Oliver Upton wrote: > > On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > > > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > > > > [...] > > > > > > -static inline void kvm_pgtable_walk_begin(void) {} > > > > -static inline void kvm_pgtable_walk_end(void) {} > > > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > > > +{ > > > > + /* > > > > + * Due to the lack of RCU (or a similar protection scheme), only > > > > + * non-shared table walkers are allowed in the hypervisor. > > > > + */ > > > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > > > +} > > > > > > I think it would be better to propagate the error to the caller rather > > > than WARN here. > > > > I'd really like to warn somewhere though since we're rather fscked at > > this point. Keeping that WARN close to the exceptional condition would > > help w/ debugging. > > > > Were you envisioning bubbling the error all the way back up (i.e. early > > return from kvm_pgtable_walk())? > > Yes, that's what I had in mind. WARN is fatal at EL2, so I think it's > better to fail the pgtable operation rather than bring down the entire > machine by default. Duh, I forgot WARNs really do go boom at EL2. Yeah, in that case it'd be best to let the caller clean up the mess. > > If having this is a strong motivator I can do a v4. > > It's a really minor point, so I'll leave it up to you guys. Sold (sorry I wasn't following before). v4 on the way. -- Thanks, Oliver _______________________________________________ kvmarm mailing list kvmarm@lists.cs.columbia.edu https://lists.cs.columbia.edu/mailman/listinfo/kvmarm ^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks 2022-11-18 17:12 ` Oliver Upton @ 2022-11-18 17:12 ` Oliver Upton 0 siblings, 0 replies; 14+ messages in thread From: Oliver Upton @ 2022-11-18 17:12 UTC (permalink / raw) To: Will Deacon Cc: Marc Zyngier, James Morse, Alexandru Elisei, Suzuki K Poulose, Catalin Marinas, linux-arm-kernel, kvmarm, kvm, kvmarm, Marek Szyprowski, linux-kernel On Fri, Nov 18, 2022 at 12:19:50PM +0000, Will Deacon wrote: > On Thu, Nov 17, 2022 at 06:23:23PM +0000, Oliver Upton wrote: > > On Thu, Nov 17, 2022 at 05:49:52PM +0000, Will Deacon wrote: > > > On Wed, Nov 16, 2022 at 04:56:55PM +0000, Oliver Upton wrote: > > > > [...] > > > > > > -static inline void kvm_pgtable_walk_begin(void) {} > > > > -static inline void kvm_pgtable_walk_end(void) {} > > > > +static inline void kvm_pgtable_walk_begin(struct kvm_pgtable_walker *walker) > > > > +{ > > > > + /* > > > > + * Due to the lack of RCU (or a similar protection scheme), only > > > > + * non-shared table walkers are allowed in the hypervisor. > > > > + */ > > > > + WARN_ON(walker->flags & KVM_PGTABLE_WALK_SHARED); > > > > +} > > > > > > I think it would be better to propagate the error to the caller rather > > > than WARN here. > > > > I'd really like to warn somewhere though since we're rather fscked at > > this point. Keeping that WARN close to the exceptional condition would > > help w/ debugging. > > > > Were you envisioning bubbling the error all the way back up (i.e. early > > return from kvm_pgtable_walk())? > > Yes, that's what I had in mind. WARN is fatal at EL2, so I think it's > better to fail the pgtable operation rather than bring down the entire > machine by default. Duh, I forgot WARNs really do go boom at EL2. Yeah, in that case it'd be best to let the caller clean up the mess. > > If having this is a strong motivator I can do a v4. > > It's a really minor point, so I'll leave it up to you guys. Sold (sorry I wasn't following before). v4 on the way. -- Thanks, Oliver ^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2022-11-18 17:12 UTC | newest] Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-11-16 16:56 [PATCH v3 0/2] KVM: arm64: Fixes for parallel faults series Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` [PATCH v3 1/2] KVM: arm64: Take a pointer to walker data in kvm_dereference_pteref() Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-16 16:56 ` [PATCH v3 2/2] KVM: arm64: Don't acquire RCU read lock for exclusive table walks Oliver Upton 2022-11-16 16:56 ` Oliver Upton 2022-11-17 17:49 ` Will Deacon 2022-11-17 17:49 ` Will Deacon 2022-11-17 18:23 ` Oliver Upton 2022-11-17 18:23 ` Oliver Upton 2022-11-18 12:19 ` Will Deacon 2022-11-18 12:19 ` Will Deacon 2022-11-18 17:12 ` Oliver Upton 2022-11-18 17:12 ` Oliver Upton
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).