page-alloc/x86: don't restrict DMA heap to node 0 When node zero has no memory, the DMA bit width will end up getting set to 9, which is obviously not helpful to hold back a reasonable amount of low enough memory for Dom0 to use for DMA purposes. Find the lowest node with memory below 4Gb instead. Introduce arch_get_dma_bitsize() to keep this arch-specific logic out of common code. Signed-off-by: Jan Beulich --- a/xen/arch/x86/numa.c +++ b/xen/arch/x86/numa.c @@ -355,11 +355,21 @@ void __init init_cpu_to_node(void) } } -EXPORT_SYMBOL(cpu_to_node); -EXPORT_SYMBOL(node_to_cpumask); -EXPORT_SYMBOL(memnode_shift); -EXPORT_SYMBOL(memnodemap); -EXPORT_SYMBOL(node_data); +unsigned int __init arch_get_dma_bitsize(void) +{ + unsigned int node; + + for_each_online_node(node) + if ( node_spanned_pages(node) && + !(node_start_pfn(node) >> (32 - PAGE_SHIFT)) ) + break; + if ( node >= MAX_NUMNODES ) + panic("No node with memory below 4Gb"); + + return min_t(unsigned int, + flsl(node_start_pfn(node) + node_spanned_pages(node) / 4 - 1) + + PAGE_SHIFT, 32); +} static void dump_numa(unsigned char key) { --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -1368,16 +1368,7 @@ void __init end_boot_allocator(void) init_heap_pages(virt_to_page(bootmem_region_list), 1); if ( !dma_bitsize && (num_online_nodes() > 1) ) - { -#ifdef CONFIG_X86 - dma_bitsize = min_t(unsigned int, - flsl(NODE_DATA(0)->node_spanned_pages) - 1 - + PAGE_SHIFT - 2, - 32); -#else - dma_bitsize = 32; -#endif - } + dma_bitsize = arch_get_dma_bitsize(); printk("Domain heap initialised"); if ( dma_bitsize ) --- a/xen/include/asm-arm/numa.h +++ b/xen/include/asm-arm/numa.h @@ -17,6 +17,11 @@ static inline __attribute__((pure)) node #define node_start_pfn(nid) (pdx_to_pfn(frametable_base_pdx)) #define __node_distance(a, b) (20) +static inline unsigned int arch_get_dma_bitsize(void) +{ + return 32; +} + #endif /* __ARCH_ARM_NUMA_H */ /* * Local variables: --- a/xen/include/asm-x86/numa.h +++ b/xen/include/asm-x86/numa.h @@ -86,5 +86,6 @@ extern int valid_numa_range(u64 start, u void srat_parse_regions(u64 addr); extern u8 __node_distance(nodeid_t a, nodeid_t b); +unsigned int arch_get_dma_bitsize(void); #endif