arm linux启动流程三

5970阅读 0评论2014-08-18 wangbaolin719
分类:LINUX


  1. 一、概述
  2. 如果仔细地阅读完初始化函数start_kernel,就会发现里面还有调用smp_processor_id()函数,这两个函数都是获取多处理器的ID,为什么会需要两个函数呢?其实这里有一个差别的,smp_setup_processor_id()函数可以不调用setup_arch()初始化函数就可以使用,而smp_processor_id()函数是一定要调用setup_arch()初始化函数后,才能使用。smp_setup_processor_id()函数是直接从cpu寄存器获取对称多处理器的ID,而smp_processor_id()函数是获取内核变量保存的处理器ID,因此一定要调用初始化函数。由于smp_setup_processor_id()函数不用调用初始化函数,可以放在内核初始化start_kernel函数的最前面使用,而函数smp_processor_id()只能放到setup_arch()函数调用的后面使用了。

  3. 二、代码
  4. //.../arch/arm/kernel/setup.c
  5. void __init smp_setup_processor_id(void)
  6. {
  7.     int i;
  8.     //判断是否是smp系统,如果是则从arm协处理器读取当前cpuid,否则为0
  9.     u32 mpidr = is_smp() ? read_cpuid_mpidr() & MPIDR_HWID_BITMASK : 0;
  10.     //根据level确定cpu号,即cpu=(mpidr>>0)&0xff
  11.     u32 cpu = MPIDR_AFFINITY_LEVEL(mpidr, 0);
  12.     
  13.     //设置cpu的map数组
  14.     //#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
  15.     cpu_logical_map(0) = cpu;
  16.     //nr_cpu_ids表示系统中cpu总数
  17.     for (i = 1; i < nr_cpu_ids; ++i)
  18.         cpu_logical_map(i) = i == cpu ? 0 : i;
  19.         
  20.     set_my_cpu_offset(0);
  21.     
  22.     pr_info("Booting Linux on physical CPU 0x%x\n", mpidr);
  23. }

  24. //检测是否为SMP架构
  25. static inline bool is_smp(void)
  26. {
  27. #ifndef CONFIG_SMP
  28.     return false;
  29.     //CONFIG_SMP_ON_UP表示可以支援SMP Kernel运行在UniProcessor(單核心)的处理器上
  30. #elif defined(CONFIG_SMP_ON_UP)
  31.     extern unsigned int smp_on_up;
  32.     return !!smp_on_up;
  33. #else
  34.     return true;
  35. #endif
  36. }

  37. //arch/arm/include/asm/cputype.h
  38. static inline unsigned int __attribute_const__ read_cpuid_mpidr(void)
  39. {
  40.     //从arm协处理器CP15的c0中读取当前cpu id
  41.     return read_cpuid(CPUID_MPIDR);
  42. }

  43. #define CPUID_MPIDR 5
  44. #define read_cpuid(reg) \
  45.         ({ \
  46.             unsigned int __val;                                        \
  47.             asm("mrc p15, 0, %0, c0, c0, " __stringify(reg)            \
  48.             : "=r" (__val)     \
  49.             :     \
  50.             : "cc");     \
  51.             __val; \
  52.         })

  53. #define MPIDR_AFFINITY_LEVEL(mpidr, level) \
  54.         ((mpidr >> (MPIDR_LEVEL_BITS * level)) & MPIDR_LEVEL_MASK)

  55. static inline void set_my_cpu_offset(unsigned long off)
  56. {
  57.     //Set TPIDRPRW
  58.     asm volatile("mcr p15, 0, %0, c13, c0, 4" : : "r" (off) : "memory");
  59. }


上一篇:arm linux启动流程二
下一篇:arm linux启动流程四