|
|
Power 6/32 Unix version 1.2b
#include "definitions"
asm(".data");
/* clrl r5 : register mode */
#define I0 2
char CLRL0[] = { 0x4d,0x55 };
/* clrl -(sp) : auto decrement */
#define I1 2
char CLRL1[] = { 0x4d,0x7e };
/* clrl *(sp)+ : auto increment deferred */
#define I2 2
char CLRL2[] = { 0x4d,0x9e };
/* clrl *12(r5)[r6] : longword displacement deferred indexed */
#define I3 7
char CLRL3[] = { 0x4d,0x46,0xf5,0x00,0x00,0x00,0x0c };
/* clrl *loc[r6] : longword relative deferred indexed */
/* loc is 1 Page away from PC */
#define I4 7
char CLRL4[] = { 0x4d,0x46,0xff,0x00,0x00,0x03,0xfc };
/* 4 Operands : emul *12(r3)[r4],r5,*12(r6)[r7],*12(r10)[r9] */
#define I5 20
char EMUL[] = { 0x2e,0x44,0xf3,0x00,0x00,0x00,0x0c,0x55,
0x47,0xf6,0x00,0x00,0x00,0x0c,0x49,0xfa,0x00,0x00,0x00,
0x0c };
char KCALL[] = { 0xcf,0x50 }; /* kcall r0 */
asm(".text");
extern long iob2, iob3, u0p2pt, pcb0, savvec4, savvec5, savvec6, savvec7;
extern long ret_adr, saved_sp, saved_fp, *p_ptr;
/* Demand paging with CALLS instruction
This test run virtual in P0 space with Kernel Privilege. Two entries in
P2PT are mapped to iob2 and iob3. USP is set to 2nd word of page iob3,
PTE of Page iob2 is then set to invalid. Program do
a REI to user code which will execute the "calls" instruction , FP get
push on the stack, FP is set to current SP, at this point SP is pointing
to the 1st longword of page 98 and as soon as processor try to push the
mask/arg on the the stack, SP point to last longword of the invalid page
then page fault occurs.
If USP is set point to a few longwords away from the top of page 98,then
page fault will occur when processor try to push PC or registers on the
stack.
*/
long exp_fp, act_sp, act_fp, act_pc, act_psl;
dmp()
{ long *lptr, t_pte0, t_pte1;
asm("mfpr $SBR,_savvec4");
savvec4 |= (savvec4 | SADDR); /* Make it system address */
asm("mtpr _savvec4,$P0BR"); /* Double map P0PT to SPT */
asm("mfpr $SLR,_savvec4");
asm("mtpr _savvec4,$P0LR");
asm("mtpr $6,$DCK");
asm("mtpr $0,$TBIA");
asm("mtpr $0,$PADC");
asm("mtpr $1,$MME"); /* Enable MME */
asm("jmp *$0f"); /* Go virtual */
asm("0:");
/* Set up P2 space */
lptr = &u0p2pt;
*lptr = (IOB2); /* 1st PTE map to IOB2 */
*(lptr+1) = (IOB3); /* 1st PTE map to IOB3 */
savvec4 = ((long)lptr) | SADDR;
savvec4 -= ((LAST_VPGNO-1) << 2);
asm("mtpr _savvec4,$P2BR");
asm("mtpr $0xffffd,$P2LR"); /* Use only 2 entries */
asm("movab fpc1,_savvec4");
savvec4 = (savvec4 >> PGSHIFT) & PTE_PFN; /* Make test area */
fixpv_pte(P0BR,savvec4,&t_pte0,(PTE_V | PTE_UW)); /* User R/W */
fixpv_pte(P0BR,savvec4+1,&t_pte1,(PTE_V | PTE_UW));
tst_call();
asm("mtpr $0,$MME"); /* Disable MME */
asm("mtpr $0,$P0LR");
}
tst_call()
{ char *msg1, *msg2;
long saved_pte, saved_vec1, saved_vec2, dummy;
long reipc, exp_pc, exp_sp, exp_psl;
/* Set up PCBB */
savvec4 = (long)&pcb0;
asm("mtpr _savvec4,$PCBB");
fixpv_pte(P2BR,TST0_PTEP2,&saved_pte,(PTE_V|PTE_UW));
fixpv_pte(P2BR,TST1_PTEP2,&saved_pte,PTE_UW); /* Set V bit off */
asm("movab fpc1,_savvec4");
exp_pc = savvec4; /* Expected PC */
exp_sp = ((TST0_PTEP2 << PGSHIFT) | 8) | P2ADDR; /* Expected SP */
savvec4 = exp_sp;
asm("mtpr _savvec4,$USP"); /* Set USP point to valid page */
exp_fp = savvec4 + 4;
asm("movab (sp),_savvec4");
savvec4 -= 16; /* KSP is 4 words below IS */
asm("mtpr _savvec4,$KSP"); /* Set KSP */
asm("movab trans_flt,_savvec4"); /* New handler for TRANS_FLT */
set_handler(TRANS_VEC,&saved_vec1,savvec4);
exp_psl = PSL_USR; /* PSL : User mode */
savvec6 = exp_psl;
asm("pushl _savvec6"); /* Push PSL */
asm("movab fpc1,_savvec7");
asm("pushl _savvec7"); /* Push PC */
asm("movl fp,_saved_fp"); /* save FP to return */
asm("movl _exp_fp,fp");
asm("mtpr $1,$PACC"); /* Purge all code cache */
asm("d1pc:");
asm("rei"); /* ISP is saved here */
asm("halt");
asm(".align 2");
asm("rtn_here:");
asm("movl _saved_fp,fp"); /* restore FP */
if (act_pc != exp_pc)
{
msg1="** PC pushed on the stack is not correct.";
d1err(msg1,act_pc,exp_pc,exp_pc,exp_sp);
}
if (exp_sp != act_sp)
{
msg1="** SP is not restored to original value after translation not valid fault";
d1err(msg1,act_sp,exp_sp,exp_pc,exp_sp);
}
if (exp_fp != act_fp)
{
msg2="** FP is not restored to original value after translation not valid fault";
d1err(msg1,act_fp,exp_fp,exp_pc,exp_sp);
}
/* set page at fault to valid and restart instruction at PC */
fixpv_pte(P2BR,TST1_PTEP2,&saved_pte,(PTE_V|PTE_UW));
set_handler(TRANS_VEC,&dummy,saved_vec1); /* restore handler */
asm("movab kcall_dmp,_savvec4"); /* New handler for KCALL */
set_handler(CHMK_VEC,&saved_vec1,savvec4);
asm("pushl _savvec6"); /* Push PSL */
asm("pushl _savvec7"); /* Push PC */
asm("rei");
asm("halt");
asm("good_rtn:");
asm("movl _saved_fp,fp"); /* restore FP */
set_handler(CHMK_VEC,&dummy,saved_vec1);
}
T_AREA()
{
asm("fpc1:");
asm("calls $4,_proc"); /* should cause translation not valid fault */
asm("kcall $0"); /* return */
}
/* Dummy procedure to test demand paging with CALLS instruction */
proc()
{
asm("ret");
}
ex_area()
{
asm(".align 2"); /* Longword align */
asm("trans_flt:");
asm("mtpr $0x1f,$IPL");
asm("movl (sp)+,r12"); /* Pop 1st two paramters */
asm("movl (sp)+,r12");
asm("movl (sp)+,_act_pc"); /* Actual PC */
asm("movl (sp)+,_act_psl"); /* Actual PSL */
asm("movl fp,_act_fp"); /* Actual FP */
asm("mfpr $USP,_act_sp"); /* Actual SP */
asm("svpctx"); /* Switch back to IS */
asm("jmp rtn_here"); /* return */
asm("kcall_dmp:");
asm("mtpr $0x1f,$IPL");
asm("svpctx"); /* Switch back to IS */
asm("jmp good_rtn"); /* return */
}
d1err(msg1,act,exp,pc,sp)
char *msg1;
long act, exp, pc, sp;
{
writes(msg1);
writes("\n** Actual : "); writeh(act);
writes("\n** Expect : "); writeh(exp);
writes("\n** PC (CALLS intruction) : "); writeh(pc);
writes("\n** SP (before CALLS) : "); writeh(sp);
writec('\n');
asm("halt");
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.