内核堆栈: thread_info
head.s: MTC0 zero, CP0_CONTEXT # clear context register
PTR_LA $28,
init_thread_union PTR_LI sp, _THREAD_SIZE - 32
PTR_ADDU
sp, $28 set_saved_sp sp, t0, t1
PTR_SUBU sp, 4 * SZREG # init stack pointerinit_task.c:union thread_union
init_thread_union __attribute__((__section__(".data.init_task"),
__aligned__(THREAD_SIZE))) =
{ INIT_THREAD_INFO(init_task) };
sched.hunion
thread_union {
struct thread_info thread_info;
unsigned long stack[
THREAD_SIZE/sizeof(long)];
};
//////////////////////////////////////////////////////
/*mem init */
setup_arch()->prom_init()->prom_meminit()->add_memory_region()
add_memory_region 修改boot_mem_map,boot_mem_map.nr_map记录所有内存
linux->arch->mips->init.c:
void __init bootmem_init(void) 根据 boot_mem_map 标记物理内存:
start_kernel()-->setup_arch()-->arch_mem_init()->bootmem_init
->add_active_range 标记物理内存 ,max_low_pfn
bootmem_init:根据boot_mem_map标记高底端内存页表界限:
min_low_pfn,max_low_pfn,highstart_pfn,highend_pfn
//函数内部
max_pfn = max_low_pfn;
if (max_low_pfn > PFN_DOWN(HIGHMEM_START)) //已有内存超过低端上限
{
#ifdef CONFIG_HIGHMEM //如果打开高端则标记高端
highstart_pfn = PFN_DOWN(HIGHMEM_START);
highend_pfn = max_low_pfn;
#endif
max_low_pfn = PFN_DOWN(HIGHMEM_START);//只保留低端
}
//
free_area_init_node->alloc_node_mem_map(分配mem_map)
//
setup_arch->arch_mem_init->paging_init->
free_area_init_nodes( 调用add_active_range 的结果)
->free_area_init_node->free_area_init_core
->memmap_init_zone(填充 mem_map)
//
paging_init会调用min_low_pfn,max_low_pfn,highstart_pfn,highend_pfn
配置max_zone_pfns 供free_area_init_nodes 计算各个zone的界限
//
free_area_init_nodes 计算各个zone的s上下限:
arch_zone_lowest_possible_pfn,arch_zone_highest_possible_pfn
这个两个变量针对所有的node,
free_area_init_nodes-> free_area_init_node
->calculate_node_totalpages->zone_spanned_pages_in_node
zone_spanned_pages_in_node->get_pfn_range_for_nid
get_pfn_range_for_nid 计算每个node 的上下限:node_start_pfn, node_end_pfn
最后adjust_zone_range_for_zone_movable获取node有效页表数
calculate_node_totalpages->calculate_node_totalpages
->zone_absent_pages_in_node
分别计算所有页表数(包含空洞)
与number of page frames in holes
//MIPS 34K SMP_MT 模式
//init TC&VPE
start_kernel()->
rest_init()->kernel_init()->smp_prepare_cpus()->msmtc_prepare_cpus()
msmtc_prepare_cpus()->smtc_prepare_cpus()->
->emt(EMT_ENABLE); evpe(EVPE_ENABLE);
(/* Arm multithreading and enable other VPEs - but all TCs are Halted */)
/*启用各个CPU 并初始化后 进入idle*/
kernel_init->()smp_init()->cpu_up->_cpu_up _cpu_up->__cpu_up()->
msmtc_boot_secondary()->smtc_boot_secondary():
set "tc_restart:" register ->
head.s:smp_bootstrap()->start_secondary()->cpu_idle()
smtc_boot_secondary()->write_tc_c0_tcrestart()
|->write_tc_c0_tchalt()
//个TC优先级时间设置
TCSCHEDULE_MT_WRITE
#define TCSCHEDULE_MT_READ() mftc0(2,6)
#define TCSCHEDULE_MT_WRITE(val) mttc0(2,6,(val))
//except_vector
void __init trap_init(void)
{
.....
if (cpu_has_mipsmt)
//set_except_vector(25, handle_mt);
set_except_vector(25, smtc_thread_exception_handler);
smtc_thread_exception()->smtc_do_pending_irqs()->smtc_handle_pending_ipis()
->smp_call_function_interrupt()
//调度 schedule获取当前 cpu ID 选择process
schedule()->context_switch()->switch_to()
linux/include/asm-mips/system.h:
#define switch_to(prev,next,last)->
extern asmlinkage void *resume(void *last, void *next, void *next_ti);
(r4k_switch.s)
//enable向量interrupt
start_kernel()->trap_init->per_cpu_trap_init()->change_c0_intctl(0x3e0, VECTORSPACING);
注:
change_c0_intctl (mipsregs.h);
static inline unsigned int \
change_c0_##name(unsigned int change, unsigned int new)
//enable interrupt
.macro local_irq_enable reg=t0(asmmacro.h)