Arm 我的ttb_基址切换有问题

Arm 我的ttb_基址切换有问题,arm,Arm,首先,感谢来自artless noise的好建议。 我选择与usr任务(vaddr:0-4G)共享3G-4G-1内核空间地址以切换任务。 我认为任务切换是这样的: 当usr任务在其自己的地址空间中运行时,会出现时钟中断 分支到usr地址空间的3G(也是内核3G空间)。 上下文保存 附表() { .. switch_ttb_base(ttb_base);//我认为这是关键,(taskA-->TaskB) //当ttb_基址切换时,地址空间发生变化, //看起来TaskB被中断并到达此处。 /

首先,感谢来自artless noise的好建议。
我选择与usr任务(vaddr:0-4G)共享3G-4G-1内核空间地址以切换任务。
我认为任务切换是这样的:

  • 当usr任务在其自己的地址空间中运行时,会出现时钟中断

  • 分支到usr地址空间的3G(也是内核3G空间)。

  • 上下文保存

  • 附表()
    {
    ..
    switch_ttb_base(ttb_base);
    //我认为这是关键,(taskA-->TaskB)
    //当ttb_基址切换时,地址空间发生变化,
    //看起来TaskB被中断并到达此处。
    //因此,在恢复上下文后,它将返回到TaskB
    //看起来TaskB刚才被中断了!
    ..
    }

  • 上下文恢复

  • 分支到新的usr任务

  • 因此,为了共享内核3G地址,我应该将页面从内核3G地址复制到usr页面。
    这是我的代码,(ARM920T,S3C2440)


    手臂停下,我不知道为什么?感谢您的帮助

    我做了一个mmu测试来测试mmu缓存操作

    我将ttb底座切换为:

    void change_ttb_base (unsigned ttb)
    {
        sync_dcaches ();
        invalidate_icache ();
        invalidate_dcaches ();
        set_ttb_base (ttb);
        invalidate_tlbs ();
    }
    
    在我的s3c2440板上,0x30000000-0x340000000是sdram地址,我在sdram地址空间上进行测试, ttb_基地切换成功

    但是当代码在高3G地址运行时,在我调用change_ttb_base()之后,ARM就停止了。我想,在高3G地址运行的代码需要MMU地址转换,我更改了ttb_base并使所有I&d缓存和TLB无效,所以ARM核心不知道下一步是什么,所以就停止吧


    是这样吗?

    不回答您的问题,但是ARM有域和pid寄存器用于快速上下文切换。您可以使用这些功能并避免缓存刷新。每个上下文切换只需要更改一个域和pid寄存器。更改
    TTB_基
    非常昂贵。通常,对于上下文切换,只需更新第二级表并刷新该范围。对于域和PID,甚至通常也不需要这样做。所有进程的操作系统和硬件映射(高内存)保持不变。即使是共享库
    text
    ,如libc,也可以跨进程映射。vaddr for libc文本映射相同,意味着MMU更新更小,进程间缓存效果更好。但FCSE只能使用32M。32M对我来说似乎不太好。是的,FCSE限制为32M,但通常主进程映射在此范围内。共享库位于其他位置。您不需要刷新缓存或TLB,因此使用FCSE可以提高性能。DACR或域没有此限制;我相信只有16个,但支持全4G。您可以将FCSE与DACR相结合,以拥有更多的进程。典型系统没有数百个活动进程。此外,可能不需要您的某些更新。你可以懒散,把它们留给故障处理程序。我认为你在排序上可能仍然有问题。在前几次失效后,指令在
    set\u ttb\u base()
    之前被提取到缓存中。很难说,有些事情将取决于新旧ttb_基地。你的问题很难回答,因为它涉及到ARM系统的许多方面。谢谢,也许我应该阅读ARM linux的源代码并尝试更多的测试!谢谢上帝!!!!!。我在没有映射端口的情况下切换了ttb_基,然后我使用uart_printk()来编写这个端口。当然,ARM将停止。。。。。。。我真粗心!!!!
    copy_kernel_page_tbls (INIT_L1_BASE,KERNEL_CODE_START,1<<30);   /* 1G size */
    
    extern unsigned long __ticks;
    
        #define __DEBUG__
    
        static   
        void schedlue ( void )
        {
            // ..............
    
            sync_dcaches ();
            invalidate_icaches ();
            invalidate_dcaches ();
    
            invalidate_tlbs();                                  
            set_ttb_base(current_p->ttb_base);                         
        }
    
        void __do_timer0 (void)
        {
                static unsigned i = 0;
                ++ i;
            current_p = task_st[i & 1];         /* just 2 tasks */
            __ticks ++;
    
            .....
            .....
            schedule ();
        }
    
    void change_ttb_base (unsigned ttb)
    {
        sync_dcaches ();
        invalidate_icache ();
        invalidate_dcaches ();
        set_ttb_base (ttb);
        invalidate_tlbs ();
    }