| From e9696d259d0fb5d239e8c28ca41089838ea76d13 Mon Sep 17 00:00:00 2001 |
| From: Stefano Stabellini <stefano.stabellini@xilinx.com> |
| Date: Mon, 26 Oct 2020 17:02:14 -0700 |
| Subject: swiotlb: fix "x86: Don't panic if can not alloc buffer for swiotlb" |
| |
| From: Stefano Stabellini <stefano.stabellini@xilinx.com> |
| |
| commit e9696d259d0fb5d239e8c28ca41089838ea76d13 upstream. |
| |
| kernel/dma/swiotlb.c:swiotlb_init gets called first and tries to |
| allocate a buffer for the swiotlb. It does so by calling |
| |
| memblock_alloc_low(PAGE_ALIGN(bytes), PAGE_SIZE); |
| |
| If the allocation must fail, no_iotlb_memory is set. |
| |
| Later during initialization swiotlb-xen comes in |
| (drivers/xen/swiotlb-xen.c:xen_swiotlb_init) and given that io_tlb_start |
| is != 0, it thinks the memory is ready to use when actually it is not. |
| |
| When the swiotlb is actually needed, swiotlb_tbl_map_single gets called |
| and since no_iotlb_memory is set the kernel panics. |
| |
| Instead, if swiotlb-xen.c:xen_swiotlb_init knew the swiotlb hadn't been |
| initialized, it would do the initialization itself, which might still |
| succeed. |
| |
| Fix the panic by setting io_tlb_start to 0 on swiotlb initialization |
| failure, and also by setting no_iotlb_memory to false on swiotlb |
| initialization success. |
| |
| Fixes: ac2cbab21f31 ("x86: Don't panic if can not alloc buffer for swiotlb") |
| |
| Reported-by: Elliott Mitchell <ehem+xen@m5p.com> |
| Tested-by: Elliott Mitchell <ehem+xen@m5p.com> |
| Signed-off-by: Stefano Stabellini <stefano.stabellini@xilinx.com> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| Cc: stable@vger.kernel.org |
| Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| lib/swiotlb.c | 6 +++++- |
| 1 file changed, 5 insertions(+), 1 deletion(-) |
| |
| --- a/lib/swiotlb.c |
| +++ b/lib/swiotlb.c |
| @@ -199,6 +199,7 @@ int __init swiotlb_init_with_tbl(char *t |
| io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; |
| } |
| io_tlb_index = 0; |
| + no_iotlb_memory = false; |
| |
| if (verbose) |
| swiotlb_print_info(); |
| @@ -229,9 +230,11 @@ swiotlb_init(int verbose) |
| if (vstart && !swiotlb_init_with_tbl(vstart, io_tlb_nslabs, verbose)) |
| return; |
| |
| - if (io_tlb_start) |
| + if (io_tlb_start) { |
| memblock_free_early(io_tlb_start, |
| PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT)); |
| + io_tlb_start = 0; |
| + } |
| pr_warn("Cannot allocate buffer"); |
| no_iotlb_memory = true; |
| } |
| @@ -330,6 +333,7 @@ swiotlb_late_init_with_tbl(char *tlb, un |
| io_tlb_orig_addr[i] = INVALID_PHYS_ADDR; |
| } |
| io_tlb_index = 0; |
| + no_iotlb_memory = false; |
| |
| swiotlb_print_info(); |
| |