物理地址映射

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_k
1015         */
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;
1024
1025                /* compare results from other methods and take the greater */
1026                if (boot_params.alt_mem_k
1027                    < 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                }
1034
1035                e820.nr_map = 0;
1036                e820_add_region(0, LOWMEMSIZE(), E820_RAM);
1037                e820_add_region(HIGH_MEMORY, mem_size << 10, E820_RAM);
1038        }
1039
1040        /* 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}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值