物理地址映射
2012-04-20 18:01
85 查看
http://lxr.linux.no/linux+v3.3.2/arch/x86/include/asm/e820.h#L58
58struct e820entry { 59 __u64 addr; /* start of memory segment */ 60 __u64 size; /* size of memory segment */ 61 __u32 type; /* type of memory segment */ 62} __attribute__((packed));
http://lxr.linux.no/linux+v3.3.2/arch/x86/include/asm/bootparam.h#L96
95/* The so-called "zeropage" */ 96struct boot_params { 97 struct screen_info screen_info; /* 0x000 */ 98 struct apm_bios_info apm_bios_info; /* 0x040 */ 99 __u8 _pad2[4]; /* 0x054 */ 100 __u64 tboot_addr; /* 0x058 */ 101 struct ist_info ist_info; /* 0x060 */ 102 __u8 _pad3[16]; /* 0x070 */ 103 __u8 hd0_info[16]; /* obsolete! */ /* 0x080 */ 104 __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */ 105 struct sys_desc_table sys_desc_table; /* 0x0a0 */ 106 struct olpc_ofw_header olpc_ofw_header; /* 0x0b0 */ 107 __u8 _pad4[128]; /* 0x0c0 */ 108 struct edid_info edid_info; /* 0x140 */ 109 struct efi_info efi_info; /* 0x1c0 */ 110 __u32 alt_mem_k; /* 0x1e0 */ 111 __u32 scratch; /* Scratch field! */ /* 0x1e4 */ 112 __u8 e820_entries; /* 0x1e8 */ 113 __u8 eddbuf_entries; /* 0x1e9 */ 114 __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ 115 __u8 _pad6[6]; /* 0x1eb */ 116 struct setup_header hdr; /* setup header */ /* 0x1f1 */ 117 __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; 118 __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ 119 struct e820entry e820_map[E820MAX]; /* 0x2d0 */ 120 __u8 _pad8[48]; /* 0xcd0 */ 121 struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */ 122 __u8 _pad9[276]; /* 0xeec */ 123} __attribute__((packed)); 124 125enum { 126 X86_SUBARCH_PC = 0, 127 X86_SUBARCH_LGUEST, 128 X86_SUBARCH_XEN, 129 X86_SUBARCH_MRST, 130 X86_SUBARCH_CE4100, 131 X86_NR_SUBARCHS, 132};
中断号int 0x15,通过0xe820参数取得内存布局,将内存信息复制到boot_params.e820_map中。
20static int detect_memory_e820(void) 21{ 22 int count = 0; 23 struct biosregs ireg, oreg; 24 struct e820entry *desc = boot_params.e820_map; 25 static struct e820entry buf; /* static so it is zeroed */ 26 27 initregs(&ireg); 28 ireg.ax = 0xe820; 29 ireg.cx = sizeof buf; 30 ireg.edx = SMAP; 31 ireg.di = (size_t)&buf; 32 33 /* 34 * Note: at least one BIOS is known which assumes that the 35 * buffer pointed to by one e820 call is the same one as 36 * the previous call, and only changes modified fields. Therefore, 37 * we use a temporary buffer and copy the results entry by entry. 38 * 39 * This routine deliberately does not try to account for 40 * ACPI 3+ extended attributes. This is because there are 41 * BIOSes in the field which report zero for the valid bit for 42 * all ranges, and we don't currently make any use of the 43 * other attribute bits. Revisit this if we see the extended 44 * attribute bits deployed in a meaningful way in the future. 45 */ 46 47 do { 48 intcall(0x15, &ireg, &oreg); 49 ireg.ebx = oreg.ebx; /* for next iteration... */ 50 51 /* BIOSes which terminate the chain with CF = 1 as opposed 52 to %ebx = 0 don't always report the SMAP signature on 53 the final, failing, probe. */ 54 if (oreg.eflags & X86_EFLAGS_CF) 55 break; 56 57 /* Some BIOSes stop returning SMAP in the middle of 58 the search loop. We don't know exactly how the BIOS 59 screwed up the map at that point, we might have a 60 partial map, the full map, or complete garbage, so 61 just return failure. */ 62 if (oreg.eax != SMAP) { 63 count = 0; 64 break; 65 } 66 67 *desc++ = buf; 68 count++; 69 } while (ireg.ebx && count < ARRAY_SIZE(boot_params.e820_map)); 70 71 return boot_params.e820_entries = count; 72}
函数detect_memory_e820连续地调用中断,并将所获取的内容复制到boot_params中去。
http://lxr.linux.no/linux+v3.3.2/arch/x86/kernel/e820.c#L1006
1006char *__init default_machine_specific_memory_setup(void)1007{1008 char *who = "BIOS-e820";1009 u32 new_nr;1010 /*1011 * Try to copy the BIOS-supplied E820-map.1012 *1013 * Otherwise fake a memory map; one section from 0k->640k,1014 * the next section from 1mb->appropriate_mem_k1015 */1016 new_nr = boot_params.e820_entries;1017 sanitize_e820_map(boot_params.e820_map,1018 ARRAY_SIZE(boot_params.e820_map),1019 &new_nr);1020 boot_params.e820_entries = new_nr;1021 if (append_e820_map(boot_params.e820_map, boot_params.e820_entries)1022 < 0) {1023 u64 mem_size;10241025 /* compare results from other methods and take the greater */1026 if (boot_params.alt_mem_k1027 < boot_params.screen_info.ext_mem_k) {1028 mem_size = boot_params.screen_info.ext_mem_k;1029 who = "BIOS-88";1030 } else {1031 mem_size = boot_params.alt_mem_k;1032 who = "BIOS-e801";1033 }10341035 e820.nr_map = 0;1036 e820_add_region(0, LOWMEMSIZE(), E820_RAM);1037 e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);1038 }10391040 /* In case someone cares... */1041 return who;1042}
函数append_e820_map 调用__append_e820_map将探测到的e820_map添加到
379static int __init __append_e820_map(struct e820entry *biosmap, int nr_map) 380{ 381 while (nr_map) { 382 u64 start = biosmap->addr; 383 u64 size = biosmap->size; 384 u64 end = start + size; 385 u32 type = biosmap->type; 386 387 /* Overflow in 64 bits? Ignore the memory map. */ 388 if (start > end) 389 return -1; 390 391 e820_add_region(start, size, type); 392 393 biosmap++; 394 nr_map--; 395 } 396 return 0; 397}
对此函数传进来的两个参数分别为:数组boot_params.e820_map, 个数boot_params.e820_entries,做简单判断后调用e820_add_region->
__e820_add_region(&e820, start, size, type);
有两个全局变量
struct e820map e820;struct e820map e820_saved; //参考原文注释
7/* 108 * Add a memory region to the kernel e820 map. 109 */ 110static void __init __e820_add_region(struct e820map *e820x, u64 start, u64 size, 111 int type) 112{ 113 int x = e820x->nr_map; 114 115 if (x >= ARRAY_SIZE(e820x->map)) { 116 printk(KERN_ERR "Ooops! Too many entries in the memory map!\n"); 117 return; 118 } 119 120 e820x->map[x].addr = start; 121 e820x->map[x].size = size; 122 e820x->map[x].type = type; 123 e820x->nr_map++; 124}
相关文章推荐
- 虚拟地址与物理地址怎么映射
- [置顶] Linux 虚拟地址与物理地址的映射关系分析【转】
- 浅析逻辑地址与物理地址映射关系
- Linux内核访问外设I/O资源的方式(设备物理地址和设备虚拟地址),静态映射和动态映射
- linux中S3C2440的物理地址映射到虚拟地址详解
- linux中S3C2440的物理地址映射到虚拟地址详解
- 虚拟地址与物理地址的映射
- 线性地址到物理地址的映射
- 逻辑地址到物理地址的映射与二级页表
- 在vb中使用Iphlpapi.dll获取网络信息 第二章 第十节 获取本机已探测的IP – 物理地址映射表
- 有时间分析 物理地址到虚拟地址的映射
- Windows内存管理之虚拟地址到物理地址的映射
- Linux驱动虚拟地址和物理地址的映射
- 进程 线性地址到物理地址的映射
- ARM中虚拟地址到物理地址的映射示意图
- 函数 ioremap 物理地址到内核映射空间的映射函数
- Linux 虚拟地址与物理地址的映射关系分析
- 通过mmap将连续物理地址映射到用户空间
- linux下特定处理器的设备物理地址和虚拟物理地址的静态映射的实现