numa.c

来自「底层驱动开发」· C语言 代码 · 共 780 行 · 第 1/2 页

C
780
字号
		numa_domain = of_node_numa_domain(memory);		if (numa_domain >= MAX_NUMNODES) {			if (numa_domain != 0xffff)				printk(KERN_ERR "WARNING: memory at %lx maps "				       "to invalid NUMA node %d\n", start,				       numa_domain);			numa_domain = 0;		}		if (max_domain < numa_domain)			max_domain = numa_domain;		if (! (size = numa_enforce_memory_limit(start, size))) {			if (--ranges)				goto new_range;			else				continue;		}		/*		 * Initialize new node struct, or add to an existing one.		 */		if (init_node_data[numa_domain].node_end_pfn) {			if ((start / PAGE_SIZE) <			    init_node_data[numa_domain].node_start_pfn)				init_node_data[numa_domain].node_start_pfn =					start / PAGE_SIZE;			if (((start / PAGE_SIZE) + (size / PAGE_SIZE)) >			    init_node_data[numa_domain].node_end_pfn)				init_node_data[numa_domain].node_end_pfn =					(start / PAGE_SIZE) +					(size / PAGE_SIZE);			init_node_data[numa_domain].node_present_pages +=				size / PAGE_SIZE;		} else {			node_set_online(numa_domain);			init_node_data[numa_domain].node_start_pfn =				start / PAGE_SIZE;			init_node_data[numa_domain].node_end_pfn =				init_node_data[numa_domain].node_start_pfn +				size / PAGE_SIZE;			init_node_data[numa_domain].node_present_pages =				size / PAGE_SIZE;		}		for (i = start ; i < (start+size); i += MEMORY_INCREMENT)			numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] =				numa_domain;		if (--ranges)			goto new_range;	}	for (i = 0; i <= max_domain; i++)		node_set_online(i);	return 0;}static void __init setup_nonnuma(void){	unsigned long top_of_ram = lmb_end_of_DRAM();	unsigned long total_ram = lmb_phys_mem_size();	unsigned long i;	printk(KERN_INFO "Top of RAM: 0x%lx, Total RAM: 0x%lx\n",	       top_of_ram, total_ram);	printk(KERN_INFO "Memory hole size: %ldMB\n",	       (top_of_ram - total_ram) >> 20);	if (!numa_memory_lookup_table) {		long entries = top_of_ram >> MEMORY_INCREMENT_SHIFT;		numa_memory_lookup_table =			(char *)abs_to_virt(lmb_alloc(entries * sizeof(char), 1));		memset(numa_memory_lookup_table, 0, entries * sizeof(char));		for (i = 0; i < entries ; i++)			numa_memory_lookup_table[i] = ARRAY_INITIALISER;	}	map_cpu_to_node(boot_cpuid, 0);	node_set_online(0);	init_node_data[0].node_start_pfn = 0;	init_node_data[0].node_end_pfn = lmb_end_of_DRAM() / PAGE_SIZE;	init_node_data[0].node_present_pages = total_ram / PAGE_SIZE;	for (i = 0 ; i < top_of_ram; i += MEMORY_INCREMENT)		numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] = 0;}static void __init dump_numa_topology(void){	unsigned int node;	unsigned int count;	if (min_common_depth == -1 || !numa_enabled)		return;	for_each_online_node(node) {		unsigned long i;		printk(KERN_INFO "Node %d Memory:", node);		count = 0;		for (i = 0; i < lmb_end_of_DRAM(); i += MEMORY_INCREMENT) {			if (numa_memory_lookup_table[i >> MEMORY_INCREMENT_SHIFT] == node) {				if (count == 0)					printk(" 0x%lx", i);				++count;			} else {				if (count > 0)					printk("-0x%lx", i);				count = 0;			}		}		if (count > 0)			printk("-0x%lx", i);		printk("\n");	}	return;}/* * Allocate some memory, satisfying the lmb or bootmem allocator where * required. nid is the preferred node and end is the physical address of * the highest address in the node. * * Returns the physical address of the memory. */static unsigned long careful_allocation(int nid, unsigned long size,					unsigned long align, unsigned long end){	unsigned long ret = lmb_alloc_base(size, align, end);	/* retry over all memory */	if (!ret)		ret = lmb_alloc_base(size, align, lmb_end_of_DRAM());	if (!ret)		panic("numa.c: cannot allocate %lu bytes on node %d",		      size, nid);	/*	 * If the memory came from a previously allocated node, we must	 * retry with the bootmem allocator.	 */	if (pa_to_nid(ret) < nid) {		nid = pa_to_nid(ret);		ret = (unsigned long)__alloc_bootmem_node(NODE_DATA(nid),				size, align, 0);		if (!ret)			panic("numa.c: cannot allocate %lu bytes on node %d",			      size, nid);		ret = virt_to_abs(ret);		dbg("alloc_bootmem %lx %lx\n", ret, size);	}	return ret;}void __init do_init_bootmem(void){	int nid;	int addr_cells, size_cells;	struct device_node *memory = NULL;	static struct notifier_block ppc64_numa_nb = {		.notifier_call = cpu_numa_callback,		.priority = 1 /* Must run before sched domains notifier. */	};	min_low_pfn = 0;	max_low_pfn = lmb_end_of_DRAM() >> PAGE_SHIFT;	max_pfn = max_low_pfn;	if (parse_numa_properties())		setup_nonnuma();	else		dump_numa_topology();	register_cpu_notifier(&ppc64_numa_nb);	for_each_online_node(nid) {		unsigned long start_paddr, end_paddr;		int i;		unsigned long bootmem_paddr;		unsigned long bootmap_pages;		start_paddr = init_node_data[nid].node_start_pfn * PAGE_SIZE;		end_paddr = init_node_data[nid].node_end_pfn * PAGE_SIZE;		/* Allocate the node structure node local if possible */		NODE_DATA(nid) = (struct pglist_data *)careful_allocation(nid,					sizeof(struct pglist_data),					SMP_CACHE_BYTES, end_paddr);		NODE_DATA(nid) = abs_to_virt(NODE_DATA(nid));		memset(NODE_DATA(nid), 0, sizeof(struct pglist_data));  		dbg("node %d\n", nid);		dbg("NODE_DATA() = %p\n", NODE_DATA(nid));		NODE_DATA(nid)->bdata = &plat_node_bdata[nid];		NODE_DATA(nid)->node_start_pfn =			init_node_data[nid].node_start_pfn;		NODE_DATA(nid)->node_spanned_pages =			end_paddr - start_paddr;		if (NODE_DATA(nid)->node_spanned_pages == 0)  			continue;  		dbg("start_paddr = %lx\n", start_paddr);  		dbg("end_paddr = %lx\n", end_paddr);		bootmap_pages = bootmem_bootmap_pages((end_paddr - start_paddr) >> PAGE_SHIFT);		bootmem_paddr = careful_allocation(nid,				bootmap_pages << PAGE_SHIFT,				PAGE_SIZE, end_paddr);		memset(abs_to_virt(bootmem_paddr), 0,		       bootmap_pages << PAGE_SHIFT);		dbg("bootmap_paddr = %lx\n", bootmem_paddr);		init_bootmem_node(NODE_DATA(nid), bootmem_paddr >> PAGE_SHIFT,				  start_paddr >> PAGE_SHIFT,				  end_paddr >> PAGE_SHIFT);		/*		 * We need to do another scan of all memory sections to		 * associate memory with the correct node.		 */		addr_cells = get_mem_addr_cells();		size_cells = get_mem_size_cells();		memory = NULL;		while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {			unsigned long mem_start, mem_size;			int numa_domain, ranges;			unsigned int *memcell_buf;			unsigned int len;			memcell_buf = (unsigned int *)get_property(memory, "reg", &len);			if (!memcell_buf || len <= 0)				continue;			ranges = memory->n_addrs;	/* ranges in cell */new_range:			mem_start = read_n_cells(addr_cells, &memcell_buf);			mem_size = read_n_cells(size_cells, &memcell_buf);			if (numa_enabled) {				numa_domain = of_node_numa_domain(memory);				if (numa_domain  >= MAX_NUMNODES)					numa_domain = 0;			} else				numa_domain =  0;			if (numa_domain != nid)				continue;			mem_size = numa_enforce_memory_limit(mem_start, mem_size);  			if (mem_size) {  				dbg("free_bootmem %lx %lx\n", mem_start, mem_size);  				free_bootmem_node(NODE_DATA(nid), mem_start, mem_size);			}			if (--ranges)		/* process all ranges in cell */				goto new_range;		}		/*		 * Mark reserved regions on this node		 */		for (i = 0; i < lmb.reserved.cnt; i++) {			unsigned long physbase = lmb.reserved.region[i].base;			unsigned long size = lmb.reserved.region[i].size;			if (pa_to_nid(physbase) != nid &&			    pa_to_nid(physbase+size-1) != nid)				continue;			if (physbase < end_paddr &&			    (physbase+size) > start_paddr) {				/* overlaps */				if (physbase < start_paddr) {					size -= start_paddr - physbase;					physbase = start_paddr;				}				if (size > end_paddr - physbase)					size = end_paddr - physbase;				dbg("reserve_bootmem %lx %lx\n", physbase,				    size);				reserve_bootmem_node(NODE_DATA(nid), physbase,						     size);			}		}		/*		 * This loop may look famaliar, but we have to do it again		 * after marking our reserved memory to mark memory present		 * for sparsemem.		 */		addr_cells = get_mem_addr_cells();		size_cells = get_mem_size_cells();		memory = NULL;		while ((memory = of_find_node_by_type(memory, "memory")) != NULL) {			unsigned long mem_start, mem_size;			int numa_domain, ranges;			unsigned int *memcell_buf;			unsigned int len;			memcell_buf = (unsigned int *)get_property(memory, "reg", &len);			if (!memcell_buf || len <= 0)				continue;			ranges = memory->n_addrs;	/* ranges in cell */new_range2:			mem_start = read_n_cells(addr_cells, &memcell_buf);			mem_size = read_n_cells(size_cells, &memcell_buf);			if (numa_enabled) {				numa_domain = of_node_numa_domain(memory);				if (numa_domain  >= MAX_NUMNODES)					numa_domain = 0;			} else				numa_domain =  0;			if (numa_domain != nid)				continue;			mem_size = numa_enforce_memory_limit(mem_start, mem_size);			memory_present(numa_domain, mem_start >> PAGE_SHIFT,				       (mem_start + mem_size) >> PAGE_SHIFT);			if (--ranges)		/* process all ranges in cell */				goto new_range2;		}	}}void __init paging_init(void){	unsigned long zones_size[MAX_NR_ZONES];	unsigned long zholes_size[MAX_NR_ZONES];	int nid;	memset(zones_size, 0, sizeof(zones_size));	memset(zholes_size, 0, sizeof(zholes_size));	for_each_online_node(nid) {		unsigned long start_pfn;		unsigned long end_pfn;		start_pfn = init_node_data[nid].node_start_pfn;		end_pfn = init_node_data[nid].node_end_pfn;		zones_size[ZONE_DMA] = end_pfn - start_pfn;		zholes_size[ZONE_DMA] = zones_size[ZONE_DMA] -			init_node_data[nid].node_present_pages;		dbg("free_area_init node %d %lx %lx (hole: %lx)\n", nid,		    zones_size[ZONE_DMA], start_pfn, zholes_size[ZONE_DMA]);		free_area_init_node(nid, NODE_DATA(nid), zones_size,							start_pfn, zholes_size);	}}static int __init early_numa(char *p){	if (!p)		return 0;	if (strstr(p, "off"))		numa_enabled = 0;	if (strstr(p, "debug"))		numa_debug = 1;	return 0;}early_param("numa", early_numa);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?