本文共 2740 字,大约阅读时间需要 9 分钟。
Linux板级内存管理之-物理内存描述的两种实现方法
osboy - mcuos.com站长原创
mcuos.com@gmail.com
(1)物理内存的描述 我们知道物理内存的描述,在linux内核里面是通过meminfo的机构体来实现的。 - struct membank {
- unsigned long start;
- unsigned long size;
- unsigned short node;
- unsigned short highmem;
- };
-
- struct meminfo {
- int nr_banks;
- struct membank bank[NR_BANKS];
- };
对于我们新唐的arm9 nuc900来说,开发板内存是64Mbytes的,所以这里的: start = 0x0,因为我们是从0x0作为sdram的基地址的,所以填写0. size = 64M, node,因为我们板子的内存是平坦式的,不存在多个内存节点node,所以这个只有一个0. (2)物理内存的信息,是如何告知内核的? 有两种方法:
(2.1)静态设置fixup函数里面的meminfo结构体 - MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
- /* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
- .phys_io = REALVIEW_EB_UART0_BASE & SECTION_MASK,
- .io_pg_offst = (IO_ADDRESS(REALVIEW_EB_UART0_BASE) >> 18) & 0xfffc,
- .boot_params = PHYS_OFFSET + 0x00000100,
- .fixup = realview_fixup,
- .map_io = realview_eb_map_io,
- .init_irq = gic_init_irq,
- .timer = &realview_eb_timer,
- .init_machine = realview_eb_init,
- MACHINE_END
-
-
- /*
- * Setup the memory banks.
- */
- void realview_fixup(struct machine_desc *mdesc, struct tag *tags, char **from,
- struct meminfo *meminfo)
- {
- /*
- * Most RealView platforms have 512MB contiguous RAM at 0x70000000.
- * Half of this is mirrored at 0.
- */
- #ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
- meminfo->bank[0].start = 0x70000000;
- meminfo->bank[0].size = SZ_512M;
- meminfo->nr_banks = 1;
- #else
- meminfo->bank[0].start = 0;
- meminfo->bank[0].size = SZ_256M;
- meminfo->nr_banks = 1;
- #endif
- }
复制代码 (2.2)通过内核参数设置“mem=”来设置 我们新唐的开发板内存64M,所以我这kernel的参数中设置mem=64M。那么内核有专门的解释这个参数的函数: - static int __init early_mem(char *p)
- {
- static int usermem __initdata = 0;
- unsigned long size, start;
- char *endp;
-
- /*
- * If the user specifies memory size, we
- * blow away any automatically generated
- * size.
- */
- if (usermem == 0) {
- usermem = 1;
- meminfo.nr_banks = 0;
- }
-
- start = PHYS_OFFSET;
- size = memparse(p, &endp);
- if (*endp == '@')
- start = memparse(endp + 1, NULL);
-
- arm_add_memory(start, size);
-
- return 0;
- }
- early_param("mem", early_mem);
复制代码 内核通过该函数解析64M这个数字,最终通过函数arm_add_memroy函数来初始化meminfo这个结构体变量: - static int __init arm_add_memory(unsigned long start, unsigned long size)
- {
- struct membank *bank = &meminfo.bank[meminfo.nr_banks];
-
- if (meminfo.nr_banks >= NR_BANKS) {
- printk(KERN_CRIT "NR_BANKS too low, "
- "ignoring memory at %#lx\n", start);
- return -EINVAL;
- }
-
- /*
- * Ensure that start/size are aligned to a page boundary.
- * Size is appropriately rounded down, start is rounded up.
- */
- size -= start & ~PAGE_MASK;
- bank->start = PAGE_ALIGN(start);
- bank->size = size & PAGE_MASK;
- bank->node = PHYS_TO_NID(start);
-
- /*
- * Check whether this memory region has non-zero size or
- * invalid node number.
- */
- if (bank->size == 0 || bank->node >= MAX_NUMNODES)
- return -EINVAL;
-
- meminfo.nr_banks++;
- return 0;
- }
复制代码 至此,这两种方式都实现了一个功能,那就是把你的板子的内存的起始基地址和内存大小,节点数等信息通知给内核,内核最终会通过meminfo来实现对物理内存的管理。 转载地址:http://vfkci.baihongyu.com/