0

まず、artless noise からの良い提案に感謝します。
3G - 4G-1 カーネル空間アドレスを usr タスク (vaddr : 0 - 4G) と共有してタスクを切り替えることにしました。
タスクの切り替えは次のようになると思います:

  1. usr タスクが独自のアドレス空間で実行されているときにクロック割り込みが発生する

  2. usr アドレス空間の 3G に分岐します (カーネルの 3G 空間でもあります)。

  3. コンテキスト保存

  4. スケジュール ()
    {
    ....
    switch_ttb_base (ttb_base);
    // 鍵だと思います、(taskA --> TaskB)
    // ttb_base を切り替えると、アドレス空間が変わります
    // TaskB が中断されたようです && ここに到着します。
    // したがって、コンテキストが復元された後、TaskB に戻り
    ます。
    ....
    }

  5. コンテキストの復元

  6. 新しい usr タスクへの分岐

したがって、カーネル 3G アドレスを共有するには、page_tbls をカーネル 3G アドレスから usr page_tbls にコピーする必要があります。
これが私のコードです(ARM920T、S3C2440)

#define INIT_L1_BASE        (0x30100000)            /* 16K */
#define INIT_L2_BASE        (0x30104000)            /* 64k */

#define KERNEL_IMG_SIZE     (0x20000)           /* 128 K */  
#define KERNEL_CODE_START   (0xC0000000)        /* 3G start */

#define TTB_BASE            (0x30000000)          
#define PAGE_DIR            (TTB_BASE)          
#define TTB_FULL_SIZE       (0x4000)            /* 16K */   
#define PAGE_TABLE          (TTB_BASE+TTB_FULL_SIZE)                 

#define PAGE_DIR_SIZE       (0x4000)            /* 16k */
#define PAGE_TBL_SIZE       (0x10000)           /* 64K */

void copy_kernel_page_tbls (unsigned dest_ttb,unsigned vaddr,unsigned size)
{
    if ((size & 0xFFFFF) || (vaddr & 0xFFFFF))                            /* 1M alignment */
        panic ( "trying to copy page tables with non-1M alignment !\n" );
    volatile unsigned *_from_page_dir,*_to_page_dir;

    _from_page_dir = (volatile unsigned *)(TTB_BASE);
    _to_page_dir = (volatile unsigned *)dest_ttb;

    unsigned l1_idx;
    unsigned i = 0,j = 0,k = 0,page;
    volatile unsigned *_to_page_tbl,*_from_page_tbl;

    for (k = 0 ,size >>= 20 ; k < size ; k ++,vaddr += 0x100000 ) 
    {
        l1_idx = vaddr>>20;
        if ( !(_from_page_dir[l1_idx] & ~0x3FF)) 
            continue;
        if ( !(_to_page_dir[l1_idx] & ~0x3FF) ) {                       /* if dest page dir unit is empty */
            i = l1_idx & ~3;
            if ((_to_page_dir[i+0] & ~0x3FF) || (_to_page_dir[i+1] & ~0x3FF)
            ||  (_to_page_dir[i+2] & ~0x3FF) || (_to_page_dir[i+3] & ~0x3FF) )
            {
                panic ( "page dir corrupts with l1_idx %d !\n",l1_idx );
            }
            if (!(page = find_free_page ())) 
                panic ( "no more free page !\n" );                      /* alloc a page page dir*/
            wordset ((void*)page,AP_FAULT_ALL|CB|TTB1_SPG,0x1000);      /* set all be fault  */

            _to_page_dir[i+0] = (page + 0x000)|DOMAIN_SYS|TTB0_COARSE;  /* small page 1st 1KB */
            _to_page_dir[i+1] = (page + 0x400)|DOMAIN_SYS|TTB0_COARSE;  /* small page 2nd 1KB */
            _to_page_dir[i+2] = (page + 0x800)|DOMAIN_SYS|TTB0_COARSE;  /* small page 3rd 1KB */
            _to_page_dir[i+3] = (page + 0xC00)|DOMAIN_SYS|TTB0_COARSE;  /* small page 4th 1KB */
        }
        _from_page_tbl = (volatile unsigned*)(_from_page_dir[l1_idx] & ~(0x3FF));
        _to_page_tbl = (volatile unsigned*)(_to_page_dir[l1_idx] & ~(0x3FF));

        /* continue copying .... */
        for (j = 0 ; j < 256 ; j++ ) {                                  /* 256 * 4K */
            if (_from_page_tbl[j] & ~0xFFF) 
                _to_page_tbl[j] = _from_page_tbl[j];            /* FIXME : change attribute */
        }
    }
}

私はこう呼んでいます

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 ();
    }

ARM が停止しました。理由がわかりません。どんな助けでも大歓迎です!

4

1 に答える 1

0

mmuキャッシュ操作をテストするためにmmuテストを行いました

ttbベースを次のように切り替えます:

void change_ttb_base (unsigned ttb)
{
    sync_dcaches ();
    invalidate_icache ();
    invalidate_dcaches ();
    set_ttb_base (ttb);
    invalidate_tlbs ();
}

私の s3c2440 ボードでは、0x30000000 - 0x34000000 は sdram アドレスです。sdram アドレス空間でテストを行い、ttb_base が正常に切り替えられました!

しかし、コードが上位 3G アドレスで実行されると、change_ttb_base () を呼び出した後、ARM は停止します。おそらく、上位 3G アドレスで実行されるコードには MMU アドレス変換が必要です。ttb_base を変更し、すべての i & d キャッシュと tlbs を無効にします。 ARMコアは次のステップが何であるかを知らないので、ただ停止してください.....

そうですか???

于 2013-05-12T07:49:05.247 に答える