Chinaunix首页 | 论坛 | 博客
  • 博客访问: 114855
  • 博文数量: 32
  • 博客积分: 1470
  • 博客等级: 上尉
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2009-07-13 21:27
文章分类

全部博文(32)

文章存档

2011年(5)

2010年(27)

我的朋友

分类:

2010-09-30 22:09:02

一直想写写APIC这个玩意,可惜一直没时间。不多说了,直接入正题。
从start_kernel(void)开始,这个函数中,跟APIC有关的函数包括以下几个
setup_arch(&command_line);
smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */
trap_init();
init_IRQ();
rest_init();
这五个函数涉及到了所有的APIC初始化的代码,包含LAPIC和IOAPIC。
从第一个函数开始看起
setup_arch(&command_line);
其实,这个函数里的APIC相关的代码,主要是对于MP table进行分析,从BIOS中读取MP表,然后用表中的值初始化一些相关的数据结构。
在这个函数中,调用的与APIC有关的函数如下
setup_memory() -> setup_bootmem_allocator() -> find_smp_config();
acpi_boot_table_init();
acpi_boot_init();
get_smp_config();
 
看第一个函数
void __init find_smp_config (void)
{
 unsigned int address;
 /*
  * FIXME: Linux assumes you have 640K of base ram..
  * this continues the error...
  *
  * 1) Scan the bottom 1K for a signature
  * 2) Scan the top 1K of base RAM
  * 3) Scan the 64K of bios
  */
 if (smp_scan_config(0x0,0x400) ||
  smp_scan_config(639*0x400,0x400) ||
   smp_scan_config(0xF0000,0x10000))
  return;
 /*
  * If it is an SMP machine we should know now, unless the
  * configuration is in an EISA/MCA bus machine with an
  * extended bios data area.
  *
  * there is a real-mode segmented pointer pointing to the
  * 4K EBDA area at 0x40E, calculate and scan it here.
  *
  * NOTE! There are Linux loaders that will corrupt the EBDA
  * area, and as such this kind of SMP config may be less
  * trustworthy, simply because the SMP table may have been
  * stomped on during early boot. These loaders are buggy and
  * should be fixed.
  *
  * MP1.4 SPEC states to only scan first 1K of 4K EBDA.
  */
 address = get_bios_ebda();
 if (address)
  smp_scan_config(address, 0x400);
}
 
关键就是找到MP table所在的地址,这里还是实模式
/*
 * there is a real-mode segmented pointer pointing to the
 * 4K EBDA area at 0x40E.这个表的地址是0x40E
 */
static inline unsigned long get_bios_ebda(void)
{
 unsigned long address = *(unsigned short *)phys_to_virt(0x40EUL);
 address <<= 4;
 return address;
}
而smp_scan_config()这个函数的作用是,以address为基地址,搜索0x400的范围内,希望能够找到一个MP table。而MP table的主要标志,就是以“_MP_”开头,于是,在函数中
mpf = (struct intel_mp_floating *)bp;
  if ((*bp == SMP_MAGIC_IDENT) &&
   (mpf->mpf_length == 1) &&
   !mpf_checksum((unsigned char *)bp, 16) &&
   ((mpf->mpf_specification == 1)
    || (mpf->mpf_specification == 4)) ) {
   smp_found_config = 1;
其中,这个SMP_MAGIC_IDENT宏是
#define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_')
没错,就是“_MP_”。
如果条件都符合,那么全局变量smp_found_config = 1;就被设置成了1,表示找到了MP table。并且后面把这个MP table的地址mpf_found = mpf;
 
找到MP table之后,我们就要以此表为依据,初始化一些变量结构体等,以备将来的需要。
 
 
阅读(1989) | 评论(0) | 转发(0) |
0

上一篇:APIC编程需要的资料

下一篇:原子操作

给主人留下些什么吧!~~