Happy shrimp http://blog.csdn.net/lights_joy/lights@hb165.com this article applies to ADI bf561 DSPuclinux-2008r1-rc8 (transplanted to vdsp5) Visual DSP ++ 5.0 welcome reprint, but please keep the author information
1.1 Related global variables
1.1.1 _ ramstart, _ ramend, _ rambaseThe three global variables are defined in head. in the s file:/** set up the usable of Ram stuff. size of Ram is determined then * an initial stack set up at the end. */. align 4 _ rambase :. long 0 _ ramstart :. long 0 _ ramend :. to use them in the C file, long 0 makes a statement in the include/ASM/bfin-global.h: extern unsigned long _ ramstart, _ ramend, _ rambase; then they are initialized in the setup_arch function: _ ramend = config_mem_size * 1024*1024; _ ramstart = (unsigned long) _ bss_stop; _ rambase = (Unsigned long) _ stext; here _ bss_stop is defined in the LDF file: bsz_sdram zero_init {... Input_section_align (4 ). = (. + 3)/4*4; ___ bss_stop = .; _ end =. ;}> mem_sdram while bsz_sdram is the last segment in the kernel, SO _ ramstart points to the first available byte after the kernel. _ Stext is also a variable defined in the LDF file :. text {input_section_align (4 ). = (. + 3)/4*4; _ text = .; _ text = .; _ stext = .; ....... Input_section_align (4 ). = (. + 3)/4*4; _ etext =.;}> mem_sdram_text and. text is the first segment in the kernel, SO _ rambase points to the starting position of the kernel. Pay attention to the definition of _ ramend. Although a fixed value is assigned to it here, you can change it by setting the startup parameter in the Bootstrap program, if the Bootstrap program uses mem = 32 m, the following code will be triggered in the parse_linline_early function: If (! Memcmp (to, "mem =", 4) {to + = 4; memsize = memparse (to, & to); If (memsize) _ ramend = memsize ;} else if (! Memcmp (to, "max_mem =", 8 )){.... To change the value.
1.1.2 memory_start and memory_endThese two global variables are almost all used at the same time. They are defined in arch/Blackfin/kernel/setup. in C: Unsigned long memory_start, memory_end, physical_mem_end; initialize them in the setup_arch function: memory_start = page_align (_ ramstart);/* to align the pointer to the (next) page boundary */# define page_align (ADDR) + PAGE_SIZE-1) & page_mask) that is, memory_start points to the end of the kernel, but the page is aligned (4 K) up ). /* By now the stack is part of the init task */memory_end = _ ramend-dma_uncached_region; # If defined (config_dma_uncached_2m) # define dma_uncached_region (2*1024*1024) # Elif defined (config_dma_uncached_1m) # define dma_uncached_region (1024*1024) # else # define dma_uncached_region (0) # endif indicates that memory_end points to the highest available physical memory. When MTD is not enabled, run the following code: # If (defined (config_bfin_icache) & anomaly_05000263) /* due to a hardware anomaly we need to limit the size of usable * instruction memory to Max 60 MB, 56 If hunt_for_zero is on * 05000263-hardware loop was upted when taking an icplb exception */# If (defined (config_debug_hunt_for_zero) if (memory_end> = 56*1024*1024) memory_end = 56*1024*1024; # else if (memory_end> = 60*1024*1024) memory_end = 60*1024*1024; # endif/* config_debug_hunt_for_zero */printk (kern_notice "Warning: limiting memory to % limb due to hardware anomaly 05000263/N ", memory_end> 20); # endif/* anomaly_05000263 */due to anomaly_05000263, memory_end is limited to 60 m, that is, 0x03c0 0000. # If! Defined (config_mtd_uclinux) memory_end-= size_4k;/* in case there is no valid cplb behind memory_end make sure we don't get to close */# endif, the value of memory_end is 0x03bf f000. And will not change. When MTD is enabled, memory_end points to the location of the physical memory minus the ramdisk size.
1.1.3 nr_kernel_pages and nr_all_pagesThe two values are defined in mm/page_alloc.c: Unsigned long _ meminitdata nr_kernel_pages; unsigned long _ meminitdata nr_all_pages; they are assigned initial values in the free_area_init_core initialization function: static void _ meminit free_area_init_core (struct pglist_data * pgdat, unsigned long * zones_size, unsigned long * zholes_size ){... For (j = 0; j <max_nr_zones; j ++) {struct zone * zone = pgdat-> node_zones + J; unsigned long size, realsize, memmap_pages; // size = realsize = the number of page tables of SDRAM. For m sdram, the value is x3fff size = zone_spanned_pages_in_node (NID, J, zones_size); realsize = size-limit (NID, J, zholes_size);/** adjust realsize so that it accounts for how much memory * is used by this zone for memmap. this affe CTS the watermark * and per-CPU initialisations */memmap_pages = (size * sizeof (struct page)> page_shift; If (realsize> = memmap_pages) {realsize-= memmap_pages; printk (kern_debug "% s zone: % lu pages used for memmap/N", zone_names [J], memmap_pages);} else printk (kern_warning "% s zone: % lu pages exceeds realsize % lu/N ", zone_names [J], memmap_pages, realsize);/* account for reserved pages * /// The value of dma_reserve can be imported from the bootstrap, where it is 0 if (j = 0 & realsize> dma_reserve) {realsize-= dma_reserve; printk (kern_debug "% s zone: % lu pages reserved/N", zone_names [0], dma_reserve);} // is_highmem_idx is always if (! Is_highmem_idx (j) nr_kernel_pages + = realsize; nr_all_pages + = realsize ;....} From the code above, both values indicate the number of available pages, and the memory range is from 0 to 60 m, excluding the pages occupied by the page array. If MTD is not enabled for 64 msdram (the actual limit is 60 m), the value is 0x3b6a.
1.1.4 mem_mapThe global variable is defined in mm/nommu. in C: struct page * mem_map; each 4 K page in the kernel corresponds to a struct page, and mem_map is the header pointer pointing to this page array. Its Initialization is completed by alloc_node_mem_map: static void _ init_refok alloc_node_mem_map (struct pglist_data * pgdat ){... /* IA64 gets its own node_mem_map, before this, without bootmem */If (! Pgdat-> node_mem_map) {unsigned long size, start, end; struct page * map; /** the zone's endpoints aren't required to be max_order * aligned but the node_mem_map endpoints must be in order * For the buddy allocator to function correctly. */START = pgdat-> node_start_pfn &~ (Max_order_nr_pages-1); End = pgdat-> node_start_pfn + pgdat-> node_spanned_pages; end = align (end, max_order_nr_pages); size = (end-start) * sizeof (struct page); map = alloc_remap (pgdat-> node_id, size); If (! Map) map = alloc_bootmem_node (pgdat, size); pgdat-> node_mem_map = map + (pgdat-> node_start_pfn-Start);}/** with no discontig, the global mem_map is just set as node 0's */If (pgdat = node_data (0) {mem_map = node_data (0)-> node_mem_map ;}} the value of this function is the same as that of node_mem_map in pglist_data. Here, pgdat points to the globally unique pglist_data: extern struct pglist_data contig_page_data; the value of pgdat-> node_start_pfn is 0. The pgdat-> node_spanned_pages value is the number of pages (4 K) in the entire SDRAM.
1.1.5 contig_page_dataThe kernel supports the so-called NUMA structure, which divides the storage space of the entire system into several discontinuous nodes. Each node is described using a pglist_data file and then placed in a linked list, however, in the bf561 system kernel, a macro named node_data is defined in include/Linux/mmzone. in H, extern struct pglist_data contig_page_data; # define node_data (NID) (& contig_page_data) can be seen from this definition that there is actually only one pglist_data in the kernel. Contig_page_data.
1.1.6 vm_total_pagesThe value is defined in mm/vmscan. in C: Long vm_total_pages;/* the total number of pages which the VM controls */It indicates the number of available pages of the memory. Its Initialization is void _ meminit build_all_zonelists (void ){... Vm_total_pages = nr_free_pagecache_pages (); printk ("built % I zonelists. total pages: % LD/N ", num_online_nodes (), vm_total_pages);} the function is complete. For 64 M memory (the actual limit is 60 m), the value is 0x3b6a.