Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1638517
  • 博文数量: 197
  • 博客积分: 10046
  • 博客等级: 上将
  • 技术积分: 1983
  • 用 户 组: 普通用户
  • 注册时间: 2006-08-07 12:36
个人简介

在外企做服务器开发, 目前是项目经理, 管理两个server开发的项目。不做嵌入式好久了。

文章分类
文章存档

2011年(2)

2010年(6)

2009年(18)

2008年(30)

2007年(100)

2006年(41)

分类: LINUX

2009-03-18 18:09:10

/*
 * FIXME: This function should really be written in assembly. Actually
 * requirement is that it does not touch stack, because %esp will be
 * wrong during resume before restore_processor_context(). Check
 * assembly if you modify this.
 *
 * SMP support:
 * All SMP processors enter this routine during suspend. The one through
 * which the suspend is initiated (which, for simplicity, is always CPU 0)
 * sends the others here using an IPI during do_swsusp2_suspend_1. They
 * remain here until after the atomic copy of the kernel is made, to ensure
 * that they don't mess with memory in the meantime (even just idling will
 * do that). Once the atomic copy is made, they are free to carry on idling.
 * Note that we must let them go, because if we're using compression, the
 * vfree calls in the compressors will result in IPIs being called and hanging
 * because the CPUs are still here.
 *
 * At resume time, we do a similar thing. CPU 0 sends the others in here using
 * an IPI. It then copies the original kernel back, restores its own processor
 * context and flushes local tlbs before freeing the others to do the same.
 * They can then go back to idling while CPU 0 reloads pageset 2, cleans up
 * and unfreezes the processes.
 *
 * (Remember that freezing and thawing processes also uses IPIs, as may
 * decompressing the data. Again, therefore, we cannot leave the other processors
 * in here).
 *
 * At the moment, we do nothing about APICs, even though the code is there.
 */

void do_swsusp_lowlevel(int resume)
{

//    int xx_nr = 0;

    if (!resume) {
//suspend code

        do_swsusp2_suspend_1();
        printk("save_processor_context.\n");
        save_processor_context();    /* We need to capture registers and memory at "same time" */
        printk("After save_processor_context.");
        do_swsusp2_suspend_2();        /* If everything goes okay, this function does not return */
        return;
    }

    printk("swapper_pg_dir = %#x\n",swapper_pg_dir); //0x802da000


    /* We want to run from swapper_pg_dir, since swapper_pg_dir is stored in constant
     * place in memory
     */

     /*bob,this is not necessary for x86 and MIPS architecture
     * especially,MIPS doesn't care PageTable, but care TLB
     */

       // __asm__( "movl %%ecx,%%cr3\n" ::"c"(__pa(swapper_pg_dir)));

     // asm volatile("movl %0,%%cr3"::"r" (__pa(swapper_pg_dir)));


    /*
     * Final function for resuming: after copying the pages to their original
     * position, it restores the register state.
     *
     * What about page tables? Writing data pages may toggle
     * accessed/dirty bits in our page tables. That should be no problems
     * with 4MB page tables. That's why we require have_pse.
     *
     * This loops destroys stack from under itself, so it better should
     * not use any stack space, itself. When this function is entered at
     * resume time, we move stack to _old_ place. This is means that this
     * function must use no stack and no local variables in registers,
     * until calling restore_processor_context();
     *
     * Critical section here: no one should touch saved memory after
     * do_swsusp2_resume_1; copying works, because nr_copy_pages,
     * pagedir_resume, loop and loop2 are nosavedata.
     */


    do_swsusp2_resume_1();

    printk("after do_swsusp_resume_1() \n");
    printk("Calling dump_stack() , file(%s),function(%s),line(%d) \n", __FILE__,__FUNCTION__,__LINE__);
    dump_stack();
    
#if 1
    state1 = swsusp_action;
    state2 = swsusp_debug_state;
    state3 = console_loglevel;


//    c_loops_per_jiffy_ref = cpu_data->loops_per_jiffy;

//    cpu_khz_ref = cpu_khz;

    
    origrange = pagedir_resume.origranges.first;
    copyrange = pagedir_resume.destranges.first;
    origoffset = origrange->minimum;
    copyoffset = copyrange->minimum;
    origpage = (unsigned long *) (page_address(mem_map + origoffset));
    copypage = (unsigned long *) (page_address(mem_map + copyoffset));

    printk("origoffset=%d\n",origoffset);
    printk("copyoffset=%d\n",copyoffset);
    
//    printk("will loop \n");

#if 1
    while (origrange) {

        printk("in loop copy \n");
        printk("Calling dump_stack() , file(%s),function(%s),line(%d) \n", __FILE__,__FUNCTION__,__LINE__);
        dump_stack();

        printk("================origoffset(%d), origrange->maximum=%d==============\n",origoffset,origrange->maximum);        
        printk("================copyoffset(%d),copyrange->maximum=%d=============\n\n",copyoffset,copyrange->maximum);
        //copy page content from copy page into original page,this is in physical memory

        for (loop=0; loop < (PAGE_SIZE / sizeof(unsigned long)); loop++)
            *(origpage + loop) = *(copypage + loop);

        /* use memcpy function */
        //memcpy((char *)origpage,(char *)copypage,PAGE_SIZE);

        
        if (origoffset < origrange->maximum) {
            origoffset++;
            origpage += (PAGE_SIZE / sizeof(unsigned long));
        } else {
            origrange = origrange->next;
            if (origrange) {
                origoffset = origrange->minimum;
                origpage = (unsigned long *) (page_address(mem_map + origoffset));
                printk("will to next chain\n");
                printk("origrange->maximum=%d\n\n\n",origrange->maximum);
            }
        }

        if (copyoffset < copyrange->maximum) {
            copyoffset++;
            copypage += (PAGE_SIZE / sizeof(unsigned long));
        } else {
            copyrange = copyrange->next;
            if (copyrange) {
                copyoffset = copyrange->minimum;
                copypage = (unsigned long *) (page_address(mem_map + copyoffset));
            }
        }
    }
#endif
    printk("will restore_processor_context() \n");
    restore_processor_context();

    //flush TLB ,bob

    //__flush_tlb_all();

    printk("will flush_tlb_all() \n");
    flush_tlb_all();

    
    /* Get other CPUs to restore their contexts and flush their tlbs. */
    /*
    swsusp_state &= ~FREEZE_SMP;
        while (atomic_read(&swsusp_cpu_counter)) {
        cpu_relax();
        smp_mb();
    }
    */


/* Ahah, we now run with our old stack, and with registers copied from
   suspend time */

//    cpu_data->loops_per_jiffy = c_loops_per_jiffy_ref;

//    loops_per_jiffy = c_loops_per_jiffy_ref;

//    cpu_khz = cpu_khz_ref;


    swsusp_action = state1;
    swsusp_debug_state = state2;
    console_loglevel = state3;

    printk("will into do_swsusp2_resume_2() \n");
    do_swsusp2_resume_2();

#endif
}

阅读(2501) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~