e820简介

 e820是和BIOS的一个中断相关的,具体说是int 0x15。之所以叫e820是因为在用这个中断时ax必须是0xe820。这个中断的作用是得到系统的内存布局。因为系统内存会有很多段,每段的类型属性也不一样,所以这个查询是“迭代式”的,每次求得一个段。

    我们看内核源代码。主要涉及两个文件:arch/x86/boot/memory.c和arch/x86/kernel/e820_32.c。我们 已经很幸运了,这部分代码已经用C重写过了。你可能会奇怪,启动调用e820时我们还在实模式,怎么能用C呢?答案是,这里用的是16位的C。gcc早已 经支持.code16 gcc模式了。

    看detect_memory_e820()函数,里面就是e820的本质。它把int 0x15放到一个do-while循环里,每次得到的一个内存段放到struct e820entry里,而struct e820entry的结构正是e820返回结果的结构!而像其它启动时获得的结果一样,最终都会被放到boot_params里,e820被放到了 boot_params.e820_map。

如果你对struct e820entry还有疑问,你可以看一下arch/x86/kernel/e820_32.c::print_memory_map(),看看里面是怎么使用它的。

    当然了,在arch/x86/boot/memory.c里,你还会看到另外两个利用int 0x15查询内存的函数,不过用途不一样了。


附:

boot_params结构体定义,其中E820MAX定义为128:

  1. struct e820entry {
        __u64 addr;    /* start of memory segment */
        __u64 size;    /* size of memory segment */
        __u32 type;    /* type of memory segment */
    } __attribute__((packed));

  2. struct boot_params {
  3.     struct screen_info screen_info;         /* 0x000 */
  4.     struct apm_bios_info apm_bios_info;     /* 0x040 */
  5.     __u8  _pad2[12];                /* 0x054 */
  6.     struct ist_info ist_info;           /* 0x060 */
  7.     __u8  _pad3[16];                /* 0x070 */
  8.     __u8  hd0_info[16]; /* obsolete! */     /* 0x080 */
  9.     __u8  hd1_info[16]; /* obsolete! */     /* 0x090 */
  10.     struct sys_desc_table sys_desc_table;       /* 0x0a0 */
  11.     __u8  _pad4[144];               /* 0x0b0 */
  12.     struct edid_info edid_info;         /* 0x140 */
  13.     struct efi_info efi_info;           /* 0x1c0 */
  14.     __u32 alt_mem_k;                /* 0x1e0 */
  15.     __u32 scratch;      /* Scratch field! */    /* 0x1e4 */
  16.     __u8  e820_entries;             /* 0x1e8 */
  17.     __u8  eddbuf_entries;               /* 0x1e9 */
  18.     __u8  edd_mbr_sig_buf_entries;          /* 0x1ea */
  19.     __u8  _pad6[6];                 /* 0x1eb */
  20.     struct setup_header hdr;    /* setup header */  /* 0x1f1 */
  21.     __u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
  22.     __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];  /* 0x290 */
  23.     struct e820entry e820_map[E820MAX];     /* 0x2d0 */
  24.     __u8  _pad8[48];                /* 0xcd0 */
  25.     struct edd_info eddbuf[EDDMAXNR];       /* 0xd00 */
  26.     __u8  _pad9[276];               /* 0xeec */
  27. } __attribute__((packed));


通过bios获取系统内存布局代码如下:

  1. static int detect_memory_e820(void)
  2. {
  3.     int count = 0;
  4.     u32 next = 0;
  5.     u32 size, id;
  6.     u8 err;
  7.     struct e820entry *desc = boot_params.e820_map;
  8.     do {
  9.         size = sizeof(struct e820entry);
  10.         /* Important: %edx is clobbered by some BIOSes,
  11.            so it must be either used for the error output
  12.            or explicitly marked clobbered. */
  13.         asm("int $0x15; setc %0"
  14.             : "=d" (err), "+b" (next), "=a" (id), "+c" (size),
  15.               "=m" (*desc)
  16.             : "D" (desc), "d" (SMAP), "a" (0xe820));
  17.         /* BIOSes which terminate the chain with CF = 1 as opposed
  18.            to %ebx = 0 don't always report the SMAP signature on
  19.            the final, failing, probe. */
  20.         if (err)
  21.             break;
  22.         /* Some BIOSes stop returning SMAP in the middle of
  23.            the search loop.  We don't know exactly how the BIOS
  24.            screwed up the map at that point, we might have a
  25.            partial map, the full map, or complete garbage, so
  26.            just return failure. */
  27.         if (id != SMAP) {
  28.             count = 0;
  29.             break;
  30.         }
  31.         count++;
  32.         desc++;
  33.     } while (next && count < E820MAX);
  34.     return boot_params.e820_entries = count;
  35. }
这个函数执行完毕后,boot_params.e820_map就含有了系统内存布局图。
函数关键部分解释如下:
07 获取启动参数 boot_params里的 e820_map 数组首地址。
15-18 通过中断0x15调用bios例程获得一个内存段的信息,这条语句是按照AT&T的汇编语法格式写的,具体语法可以查看相关资料。
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值