您的位置:首页 > Web前端

物理地址映射

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}

                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息