[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: v5.4.289 failed to boot with error megasas_build_io_fusion 3219 sge_count (-12) is out of range
On Thu, 30 Jan 2025, Jürgen Groß wrote: > Can you try the attached patch, please? I don't have a system at hand > showing the problem. > > From cff43e997f79a95dc44e02debaeafe5f127f40bb Mon Sep 17 00:00:00 2001 > From: Juergen Gross <jgross@xxxxxxxx> > Date: Thu, 30 Jan 2025 09:56:57 +0100 > Subject: [PATCH] x86/xen: allow larger contiguous memory regions in PV guests > > Today a PV guest (including dom0) can create 2MB contiguous memory > regions for DMA buffers at max. This has led to problems at least > with the megaraid_sas driver, which wants to allocate a 2.3MB DMA > buffer. > > The limiting factor is the frame array used to do the hypercall for > making the memory contiguous, which has 512 entries and is just a > static array in mmu_pv.c. > > In case a contiguous memory area larger than the initially supported > 2MB is requested, allocate a larger buffer for the frame list. Note > that such an allocation is tried only after memory management has been > initialized properly, which is tested via the early_boot_irqs_disabled > flag. > > Fixes: 9f40ec84a797 ("xen/swiotlb: add alignment check for dma buffers") > Signed-off-by: Juergen Gross <jgross@xxxxxxxx> > --- > Note that the "Fixes:" tag is not really correct, as that patch didn't > introduce the problem, but rather made it visible. OTOH it is the best > indicator we have to identify kernel versions this patch should be > backported to. > --- > arch/x86/xen/mmu_pv.c | 44 ++++++++++++++++++++++++++++++++++++------- > 1 file changed, 37 insertions(+), 7 deletions(-) > > diff --git a/arch/x86/xen/mmu_pv.c b/arch/x86/xen/mmu_pv.c > index 55a4996d0c04..62aec29b8174 100644 > --- a/arch/x86/xen/mmu_pv.c > +++ b/arch/x86/xen/mmu_pv.c > @@ -2200,8 +2200,10 @@ void __init xen_init_mmu_ops(void) > } > > /* Protected by xen_reservation_lock. */ > -#define MAX_CONTIG_ORDER 9 /* 2MB */ > -static unsigned long discontig_frames[1<<MAX_CONTIG_ORDER]; > +#define MIN_CONTIG_ORDER 9 /* 2MB */ > +static unsigned int discontig_frames_order = MIN_CONTIG_ORDER; > +static unsigned long discontig_frames_early[1UL << MIN_CONTIG_ORDER]; > +static unsigned long *discontig_frames = discontig_frames_early; > > #define VOID_PTE (mfn_pte(0, __pgprot(0))) > static void xen_zap_pfn_range(unsigned long vaddr, unsigned int order, > @@ -2319,18 +2321,44 @@ int xen_create_contiguous_region(phys_addr_t pstart, > unsigned int order, > unsigned int address_bits, > dma_addr_t *dma_handle) > { > - unsigned long *in_frames = discontig_frames, out_frame; > + unsigned long *in_frames, out_frame; > + unsigned long *new_array, *old_array; > unsigned long flags; > int success; > unsigned long vstart = (unsigned long)phys_to_virt(pstart); > > - if (unlikely(order > MAX_CONTIG_ORDER)) > - return -ENOMEM; > + if (unlikely(order > discontig_frames_order)) { > + if (early_boot_irqs_disabled) > + return -ENOMEM; > + > + new_array = vmalloc(sizeof(unsigned long) * (1UL << order)); > + > + if (!new_array) > + return -ENOMEM; > + > + spin_lock_irqsave(&xen_reservation_lock, flags); > + > + if (order > discontig_frames_order) { This second if check should not be needed because it is the same as the outer if check. > + if (discontig_frames == discontig_frames_early) > + old_array = NULL; > + else > + old_array = discontig_frames; > + discontig_frames = new_array; > + discontig_frames_order = order; > + } else > + old_array = new_array; > + > + spin_unlock_irqrestore(&xen_reservation_lock, flags); > + > + vfree(old_array); > + } > > memset((void *) vstart, 0, PAGE_SIZE << order); > > spin_lock_irqsave(&xen_reservation_lock, flags); > > + in_frames = discontig_frames; > + > /* 1. Zap current PTEs, remembering MFNs. */ > xen_zap_pfn_range(vstart, order, in_frames, NULL); > > @@ -2354,12 +2382,12 @@ int xen_create_contiguous_region(phys_addr_t pstart, > unsigned int order, > > void xen_destroy_contiguous_region(phys_addr_t pstart, unsigned int order) > { > - unsigned long *out_frames = discontig_frames, in_frame; > + unsigned long *out_frames, in_frame; > unsigned long flags; > int success; > unsigned long vstart; > > - if (unlikely(order > MAX_CONTIG_ORDER)) > + if (unlikely(order > discontig_frames_order)) > return; > > vstart = (unsigned long)phys_to_virt(pstart); > @@ -2367,6 +2395,8 @@ void xen_destroy_contiguous_region(phys_addr_t pstart, > unsigned int order) > > spin_lock_irqsave(&xen_reservation_lock, flags); > > + out_frames = discontig_frames; > + > /* 1. Find start MFN of contiguous extent. */ > in_frame = virt_to_mfn((void *)vstart); > > -- > 2.43.0 >
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |