まず、artless noise からの良い提案に感謝します。
3G - 4G-1 カーネル空間アドレスを usr タスク (vaddr : 0 - 4G) と共有してタスクを切り替えることにしました。
タスクの切り替えは次のようになると思います:
usr タスクが独自のアドレス空間で実行されているときにクロック割り込みが発生する
usr アドレス空間の 3G に分岐します (カーネルの 3G 空間でもあります)。
コンテキスト保存
スケジュール ()
{
....
switch_ttb_base (ttb_base);
// 鍵だと思います、(taskA --> TaskB)
// ttb_base を切り替えると、アドレス空間が変わります
// TaskB が中断されたようです && ここに到着します。
// したがって、コンテキストが復元された後、TaskB に戻り
ます。
....
}コンテキストの復元
新しい 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 が停止しました。理由がわかりません。どんな助けでも大歓迎です!