首先,感谢无艺术噪音的好建议。
我选择与 usr task (vaddr : 0 - 4G) 共享 3G - 4G-1 内核空间地址来切换任务。
我认为任务切换是这样的:
当 usr 任务在其自己的地址空间中运行时,会出现时钟中断
跳转到 usr 地址空间的 3G(也是内核 3G 空间)。
上下文保存
schedule ()
{
....
switch_ttb_base (ttb_base);
// 我认为是关键,(taskA --> TaskB)
// 当ttb_base 切换时,地址空间发生变化,
// 看起来TaskB 被中断&& 到达这里。
// 所以,上下文恢复后,它会返回到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只是停止。我不知道为什么?任何帮助表示赞赏!