Subject: USPACE hardwiring on cxtswitch
To: None <port-mips@netbsd.org>
From: Toru Nishimura <nisimura@itc.aist-nara.ac.jp>
List: port-mips
Date: 04/03/2000 18:42:04
Here goes the hack job made last night to change MIPS context
switch code path. Not well tested well, yet. Code verification is
welcome.
Process USPACE (a storage for pcb and kernel stack) is hardwired in
TLB when a process newly gets CPU tick is about to start the
execution. cpu_switch_resume() should be followings;
void
cpu_switch_resume(p)
struct proc *p;
{
vaddr_t va = (vaddr_t)p->p_addr;
if (va <= MIPS_KSEG2_START)
return;
MIPS_TBIS(va);
MIPS_TBIS(va + PAGE_SIZE);
MIPS_TBDATA(0, va, p->p_md.md_upte[0] | PG_G); /* misnomer? */
MIPS_TBDATA(1, va, p->p_md.md_upte[1] | PG_G);
}
Now, it'd be invoked as;
3:
/*
* Switch to new context.
*/
jal _C_LABEL(cpu_switch_resume) # wiredown USPACE
move s7, a0 # save newproc
lw a0, P_ADDR(s7)
sw s7, _C_LABEL(curproc)
sw a0, _C_LABEL(curpcb)
jal _C_LABEL(pmap_activate) # assign new ASID
move a0, s7
sw zero, _C_LABEL(want_resched) # we've context switched
REG_PROLOGUE
REG_L v0, U_PCB_CONTEXT+SF_REG_SR(a0)
...
The sample implementation of mips1_cpu_switch_resume() is;
LEAF_NOPROFILE(mips1_cpu_switch_resume)
lw a1, P_MD_UPTE_0(a0) # a1 = upte[0]
lw a2, P_MD_UPTE_1(a0) # a2 = upte[1]
lw s0, P_ADDR(a0) # va = p->p_addr
li s2, MIPS_KSEG2_START
blt s0, s2, resume
nop
mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va
nop
tlbp # probe 1st VPN
mfc0 s1, MIPS_COP_0_TLB_INDEX
nop
bltz s1, entry0set
li s1, MIPS_KSEG0_START # found, then
mtc0 s1, MIPS_COP_0_TLB_HI
mtc0 zero, MIPS_COP_0_TLB_LOW
nop
tlbwi # TBIS(va)
nop
mtc0 s0, MIPS_COP_0_TLB_HI # set 1st VPN again
entry0set:
mtc0 zero, MIPS_COP_0_TLB_INDEX # TLB index #0
ori a1, a1, MIPS1_PG_G
mtc0 a1, MIPS_COP_0_TLB_LOW # 1st PFN w/ PG_G
nop
tlbwi # set TLB entry #0
addu s0, s0, NBPG
mtc0 s0, MIPS_COP_0_TLB_HI # VPN = va+NBPG
nop
tlbp # probe 2nd VPN
mfc0 s1, MIPS_COP_0_TLB_INDEX
nop
bltz s1, entry1set
li s1, MIPS_KSEG0_START # found, then
mtc0 s1, MIPS_COP_0_TLB_HI
mtc0 zero, MIPS_COP_0_TLB_LOW
nop
tlbwi # TBIS(va+NBPG)
nop
mtc0 s0, MIPS_COP_0_TLB_HI # set 2nd VPN again
entry1set:
li s1, 1 << MIPS1_TLB_INDEX_SHIFT
mtc0 s1, MIPS_COP_0_TLB_INDEX # TLB index #1
ori a2, a2, MIPS1_PG_G
mtc0 a2, MIPS_COP_0_TLB_LOW # 2nd PFN w/ PG_G
nop
tlbwi # set TLB entry #1
resume:
j ra
nop
END(mips1_cpu_switch_resume)
pmap_activate() would be;
void
pmap_activate(p)
struct proc *p;
{
pmap_t pmap = p->p_vmspace->vm_map.pmap;
if (p == curproc) {
#ifdef MIPS3
if (CPUISMIPS3)
mips3_write_xcontext_upper((u_int32_t)pmap->pm_segtab);
#endif
MachSetPID(pmap->pm_asid);
}
p->p_addr->u_pcb.pcb_segtab = pmap->pm_segtab; /* XXX */
}
and pmap_asid_alloc(), which was renamed from pmap_alloc_asid(), is;
void
pmap_asid_alloc(pmap)
struct pmap *pmap;
{
if (pmap == pmap_kernel())
return;
if (pmap->pm_asid == PMAP_ASID_RESERVED &&
pmap->pm_asidgen == pmap_asid_generation)
return;
if (pmap_next_asid >= pmap_max_asid) {
MIPS_TBIAP();
pmap_next_asid = 1;
pmap_asid_generation += 1;
}
pmap->pm_asid = pmap_next_asid++;
pmap->pm_asidgen = pmap_asid_generation;
}
I'll post mips3_cpu_switch_resume() later.
Tohru Nishimura
Nara Institute of Science and Technology