From e9a789c1858a9b63449c1c8ee2410dd4c1acf46f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 29 Mar 2024 13:27:14 +0100 Subject: [PATCH] 5.15-stable patches added patches: kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch kvm-arm64-work-out-supported-block-level-at-compile-time.patch tty-serial-imx-fix-broken-rs485.patch --- ...ly_range-batch-size-to-largest-block.patch | 142 ++++++++++++++++++ ...upported-block-level-at-compile-time.patch | 57 +++++++ queue-5.15/series | 3 + .../tty-serial-imx-fix-broken-rs485.patch | 85 +++++++++++ 4 files changed, 287 insertions(+) create mode 100644 queue-5.15/kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch create mode 100644 queue-5.15/kvm-arm64-work-out-supported-block-level-at-compile-time.patch create mode 100644 queue-5.15/tty-serial-imx-fix-broken-rs485.patch diff --git a/queue-5.15/kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch b/queue-5.15/kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch new file mode 100644 index 00000000000..a473ecbcf69 --- /dev/null +++ b/queue-5.15/kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch @@ -0,0 +1,142 @@ +From 5994bc9e05c2f8811f233aa434e391cd2783f0f5 Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Fri, 7 Oct 2022 23:41:51 +0000 +Subject: KVM: arm64: Limit stage2_apply_range() batch size to largest block + +From: Oliver Upton + +commit 5994bc9e05c2f8811f233aa434e391cd2783f0f5 upstream. + +Presently stage2_apply_range() works on a batch of memory addressed by a +stage 2 root table entry for the VM. Depending on the IPA limit of the +VM and PAGE_SIZE of the host, this could address a massive range of +memory. Some examples: + + 4 level, 4K paging -> 512 GB batch size + + 3 level, 64K paging -> 4TB batch size + +Unsurprisingly, working on such a large range of memory can lead to soft +lockups. When running dirty_log_perf_test: + + ./dirty_log_perf_test -m -2 -s anonymous_thp -b 4G -v 48 + + watchdog: BUG: soft lockup - CPU#0 stuck for 45s! [dirty_log_perf_:16703] + Modules linked in: vfat fat cdc_ether usbnet mii xhci_pci xhci_hcd sha3_generic gq(O) + CPU: 0 PID: 16703 Comm: dirty_log_perf_ Tainted: G O 6.0.0-smp-DEV #1 + pstate: 80400009 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) + pc : dcache_clean_inval_poc+0x24/0x38 + lr : clean_dcache_guest_page+0x28/0x4c + sp : ffff800021763990 + pmr_save: 000000e0 + x29: ffff800021763990 x28: 0000000000000005 x27: 0000000000000de0 + x26: 0000000000000001 x25: 00400830b13bc77f x24: ffffad4f91ead9c0 + x23: 0000000000000000 x22: ffff8000082ad9c8 x21: 0000fffafa7bc000 + x20: ffffad4f9066ce50 x19: 0000000000000003 x18: ffffad4f92402000 + x17: 000000000000011b x16: 000000000000011b x15: 0000000000000124 + x14: ffff07ff8301d280 x13: 0000000000000000 x12: 00000000ffffffff + x11: 0000000000010001 x10: fffffc0000000000 x9 : ffffad4f9069e580 + x8 : 000000000000000c x7 : 0000000000000000 x6 : 000000000000003f + x5 : ffff07ffa2076980 x4 : 0000000000000001 x3 : 000000000000003f + x2 : 0000000000000040 x1 : ffff0830313bd000 x0 : ffff0830313bcc40 + Call trace: + dcache_clean_inval_poc+0x24/0x38 + stage2_unmap_walker+0x138/0x1ec + __kvm_pgtable_walk+0x130/0x1d4 + __kvm_pgtable_walk+0x170/0x1d4 + __kvm_pgtable_walk+0x170/0x1d4 + __kvm_pgtable_walk+0x170/0x1d4 + kvm_pgtable_stage2_unmap+0xc4/0xf8 + kvm_arch_flush_shadow_memslot+0xa4/0x10c + kvm_set_memslot+0xb8/0x454 + __kvm_set_memory_region+0x194/0x244 + kvm_vm_ioctl_set_memory_region+0x58/0x7c + kvm_vm_ioctl+0x49c/0x560 + __arm64_sys_ioctl+0x9c/0xd4 + invoke_syscall+0x4c/0x124 + el0_svc_common+0xc8/0x194 + do_el0_svc+0x38/0xc0 + el0_svc+0x2c/0xa4 + el0t_64_sync_handler+0x84/0xf0 + el0t_64_sync+0x1a0/0x1a4 + +Use the largest supported block mapping for the configured page size as +the batch granularity. In so doing the walker is guaranteed to visit a +leaf only once. + +Signed-off-by: Oliver Upton +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221007234151.461779-3-oliver.upton@linux.dev +Signed-off-by: Krister Johansen +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/stage2_pgtable.h | 20 -------------------- + arch/arm64/kvm/mmu.c | 9 ++++++++- + 2 files changed, 8 insertions(+), 21 deletions(-) + +--- a/arch/arm64/include/asm/stage2_pgtable.h ++++ b/arch/arm64/include/asm/stage2_pgtable.h +@@ -11,13 +11,6 @@ + #include + + /* +- * PGDIR_SHIFT determines the size a top-level page table entry can map +- * and depends on the number of levels in the page table. Compute the +- * PGDIR_SHIFT for a given number of levels. +- */ +-#define pt_levels_pgdir_shift(lvls) ARM64_HW_PGTABLE_LEVEL_SHIFT(4 - (lvls)) +- +-/* + * The hardware supports concatenation of up to 16 tables at stage2 entry + * level and we use the feature whenever possible, which means we resolve 4 + * additional bits of address at the entry level. +@@ -30,11 +23,6 @@ + #define stage2_pgtable_levels(ipa) ARM64_HW_PGTABLE_LEVELS((ipa) - 4) + #define kvm_stage2_levels(kvm) VTCR_EL2_LVLS(kvm->arch.vtcr) + +-/* stage2_pgdir_shift() is the size mapped by top-level stage2 entry for the VM */ +-#define stage2_pgdir_shift(kvm) pt_levels_pgdir_shift(kvm_stage2_levels(kvm)) +-#define stage2_pgdir_size(kvm) (1ULL << stage2_pgdir_shift(kvm)) +-#define stage2_pgdir_mask(kvm) ~(stage2_pgdir_size(kvm) - 1) +- + /* + * kvm_mmmu_cache_min_pages() is the number of pages required to install + * a stage-2 translation. We pre-allocate the entry level page table at +@@ -42,12 +30,4 @@ + */ + #define kvm_mmu_cache_min_pages(kvm) (kvm_stage2_levels(kvm) - 1) + +-static inline phys_addr_t +-stage2_pgd_addr_end(struct kvm *kvm, phys_addr_t addr, phys_addr_t end) +-{ +- phys_addr_t boundary = (addr + stage2_pgdir_size(kvm)) & stage2_pgdir_mask(kvm); +- +- return (boundary - 1 < end - 1) ? boundary : end; +-} +- + #endif /* __ARM64_S2_PGTABLE_H_ */ +--- a/arch/arm64/kvm/mmu.c ++++ b/arch/arm64/kvm/mmu.c +@@ -31,6 +31,13 @@ static phys_addr_t hyp_idmap_vector; + + static unsigned long io_map_base; + ++static phys_addr_t stage2_range_addr_end(phys_addr_t addr, phys_addr_t end) ++{ ++ phys_addr_t size = kvm_granule_size(KVM_PGTABLE_MIN_BLOCK_LEVEL); ++ phys_addr_t boundary = ALIGN_DOWN(addr + size, size); ++ ++ return (boundary - 1 < end - 1) ? boundary : end; ++} + + /* + * Release kvm_mmu_lock periodically if the memory region is large. Otherwise, +@@ -52,7 +59,7 @@ static int stage2_apply_range(struct kvm + if (!pgt) + return -EINVAL; + +- next = stage2_pgd_addr_end(kvm, addr, end); ++ next = stage2_range_addr_end(addr, end); + ret = fn(pgt, addr, next - addr); + if (ret) + break; diff --git a/queue-5.15/kvm-arm64-work-out-supported-block-level-at-compile-time.patch b/queue-5.15/kvm-arm64-work-out-supported-block-level-at-compile-time.patch new file mode 100644 index 00000000000..6b627df03f7 --- /dev/null +++ b/queue-5.15/kvm-arm64-work-out-supported-block-level-at-compile-time.patch @@ -0,0 +1,57 @@ +From 3b5c082bbfa20d9a57924edd655bbe63fe98ab06 Mon Sep 17 00:00:00 2001 +From: Oliver Upton +Date: Fri, 7 Oct 2022 23:41:50 +0000 +Subject: KVM: arm64: Work out supported block level at compile time + +From: Oliver Upton + +commit 3b5c082bbfa20d9a57924edd655bbe63fe98ab06 upstream. + +Work out the minimum page table level where KVM supports block mappings +at compile time. While at it, rewrite the comment around supported block +mappings to directly describe what KVM supports instead of phrasing in +terms of what it does not. + +Signed-off-by: Oliver Upton +Signed-off-by: Marc Zyngier +Link: https://lore.kernel.org/r/20221007234151.461779-2-oliver.upton@linux.dev +Signed-off-by: Krister Johansen +Signed-off-by: Greg Kroah-Hartman +--- + arch/arm64/include/asm/kvm_pgtable.h | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +--- a/arch/arm64/include/asm/kvm_pgtable.h ++++ b/arch/arm64/include/asm/kvm_pgtable.h +@@ -13,6 +13,18 @@ + + #define KVM_PGTABLE_MAX_LEVELS 4U + ++/* ++ * The largest supported block sizes for KVM (no 52-bit PA support): ++ * - 4K (level 1): 1GB ++ * - 16K (level 2): 32MB ++ * - 64K (level 2): 512MB ++ */ ++#ifdef CONFIG_ARM64_4K_PAGES ++#define KVM_PGTABLE_MIN_BLOCK_LEVEL 1U ++#else ++#define KVM_PGTABLE_MIN_BLOCK_LEVEL 2U ++#endif ++ + static inline u64 kvm_get_parange(u64 mmfr0) + { + u64 parange = cpuid_feature_extract_unsigned_field(mmfr0, +@@ -58,11 +70,7 @@ static inline u64 kvm_granule_size(u32 l + + static inline bool kvm_level_supports_block_mapping(u32 level) + { +- /* +- * Reject invalid block mappings and don't bother with 4TB mappings for +- * 52-bit PAs. +- */ +- return !(level == 0 || (PAGE_SIZE != SZ_4K && level == 1)); ++ return level >= KVM_PGTABLE_MIN_BLOCK_LEVEL; + } + + /** diff --git a/queue-5.15/series b/queue-5.15/series index d958bfa30e7..4990e9ddbea 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -146,3 +146,6 @@ dma-mapping-add-dma_opt_mapping_size.patch dma-iommu-add-iommu_dma_opt_mapping_size.patch iommu-dma-force-swiotlb_max_mapping_size-on-an-untru.patch printk-update-console_may_schedule-in-console_tryloc.patch +tty-serial-imx-fix-broken-rs485.patch +kvm-arm64-work-out-supported-block-level-at-compile-time.patch +kvm-arm64-limit-stage2_apply_range-batch-size-to-largest-block.patch diff --git a/queue-5.15/tty-serial-imx-fix-broken-rs485.patch b/queue-5.15/tty-serial-imx-fix-broken-rs485.patch new file mode 100644 index 00000000000..e6131a1b72d --- /dev/null +++ b/queue-5.15/tty-serial-imx-fix-broken-rs485.patch @@ -0,0 +1,85 @@ +From 672448ccf9b6a676f96f9352cbf91f4d35f4084a Mon Sep 17 00:00:00 2001 +From: Rickard x Andersson +Date: Wed, 21 Feb 2024 12:53:04 +0100 +Subject: tty: serial: imx: Fix broken RS485 + +From: Rickard x Andersson + +commit 672448ccf9b6a676f96f9352cbf91f4d35f4084a upstream. + +When about to transmit the function imx_uart_start_tx is called and in +some RS485 configurations this function will call imx_uart_stop_rx. The +problem is that imx_uart_stop_rx will enable loopback in order to +release the RS485 bus, but when loopback is enabled transmitted data +will just be looped to RX. + +This patch fixes the above problem by not enabling loopback when about +to transmit. + +This driver now works well when used for RS485 half duplex master +configurations. + +Fixes: 79d0224f6bf2 ("tty: serial: imx: Handle RS485 DE signal active high") +Cc: stable +Signed-off-by: Rickard x Andersson +Tested-by: Christoph Niedermaier +Link: https://lore.kernel.org/r/20240221115304.509811-1-rickaran@axis.com +Signed-off-by: Christoph Niedermaier +Signed-off-by: Greg Kroah-Hartman +--- + drivers/tty/serial/imx.c | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +--- a/drivers/tty/serial/imx.c ++++ b/drivers/tty/serial/imx.c +@@ -491,8 +491,7 @@ static void imx_uart_stop_tx(struct uart + } + } + +-/* called with port.lock taken and irqs off */ +-static void imx_uart_stop_rx(struct uart_port *port) ++static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback) + { + struct imx_port *sport = (struct imx_port *)port; + u32 ucr1, ucr2, ucr4, uts; +@@ -514,7 +513,7 @@ static void imx_uart_stop_rx(struct uart + /* See SER_RS485_ENABLED/UTS_LOOP comment in imx_uart_probe() */ + if (port->rs485.flags & SER_RS485_ENABLED && + port->rs485.flags & SER_RS485_RTS_ON_SEND && +- sport->have_rtscts && !sport->have_rtsgpio) { ++ sport->have_rtscts && !sport->have_rtsgpio && loopback) { + uts = imx_uart_readl(sport, imx_uart_uts_reg(sport)); + uts |= UTS_LOOP; + imx_uart_writel(sport, uts, imx_uart_uts_reg(sport)); +@@ -527,6 +526,16 @@ static void imx_uart_stop_rx(struct uart + } + + /* called with port.lock taken and irqs off */ ++static void imx_uart_stop_rx(struct uart_port *port) ++{ ++ /* ++ * Stop RX and enable loopback in order to make sure RS485 bus ++ * is not blocked. Se comment in imx_uart_probe(). ++ */ ++ imx_uart_stop_rx_with_loopback_ctrl(port, true); ++} ++ ++/* called with port.lock taken and irqs off */ + static void imx_uart_enable_ms(struct uart_port *port) + { + struct imx_port *sport = (struct imx_port *)port; +@@ -714,8 +723,13 @@ static void imx_uart_start_tx(struct uar + imx_uart_rts_inactive(sport, &ucr2); + imx_uart_writel(sport, ucr2, UCR2); + ++ /* ++ * Since we are about to transmit we can not stop RX ++ * with loopback enabled because that will make our ++ * transmitted data being just looped to RX. ++ */ + if (!(port->rs485.flags & SER_RS485_RX_DURING_TX)) +- imx_uart_stop_rx(port); ++ imx_uart_stop_rx_with_loopback_ctrl(port, false); + + sport->tx_state = WAIT_AFTER_RTS; + start_hrtimer_ms(&sport->trigger_start_tx, -- 2.47.2