|
|
Power 6/32 Unix version 1.2b
#include "definitions"
extern long iob0, iob1, iob2, iob3, ss1;
extern long unused, u0p1pt, u0p2pt, scb, savvec4, savvec5, savvec6, savvec7;
extern long *p_ptr, exp_par0, exp_par1, exp_par2, exp_par3;
long Failpc, test_va, Tpsl;
/* This test will test access protections on PTE in TAHOE memory
management scheme.
The main loop of the test running in USER space, KERNEL privilege.
*/
protect()
{ long *temp, pg_no, pte, saved_pte, pte_sys, pte_p0, pte_p1, pte_p2;
if (ss1) writes("** Subtest2 : Access protection fault\n");
pg_no = 0;
asm("mfpr $SBR,_savvec4");
savvec4 |= 0xc0000000;
asm("mtpr _savvec4,$P0BR"); /* Double map P0 into System space */
asm("mfpr $SLR,_savvec4");
asm("mtpr _savvec4,$P0LR");
asm("mtpr $3,$DCK");
asm("mtpr $0,$TBIA");
asm("mtpr $0,$PADC");
asm("mtpr $1,$MME");
asm("jmp *$0f"); /* Go virtual */
asm("0:");
/* Set up SPT */
pg_no = TEST_PTESYS; /* Map 1st unused PTE to */
pte = IOB0; /* physical page iob0 (22) */
fixpfn_pte(SBR,pg_no, &pte_sys, pte);
/* Set up P0PT */
pg_no = TEST_PTEP0; /* Map PTE. 60 in P0PT */
pte = IOB1; /* physical page iob1 (23) */
fixpfn_pte(P0BR,pg_no, &pte_p0, pte);
/* Set up P1PT */
temp = &u0p1pt; /* Map PTE. 0 in P1PT */
*temp = IOB2; /* physical page iob2 (24) */
savvec4 = ((long)temp) | SADDR;
asm("mtpr _savvec4,$P1BR");
asm("mtpr $1,$P1LR");
/* Set up P2PT */
temp = &u0p2pt; /* Map PTE. 0 in P2PT */
*temp = IOB3; /* physical page iob3 (25) */
savvec4 = ((long)temp) | SADDR;
savvec4 -= (LAST_VPGNO << 2);
asm("mtpr _savvec4, $P2BR");
asm("mtpr $0xffffe, $P2LR"); /* Use only 1 entry */
/* Map test area to allow USER to execute code */
asm("movab rd_access,_savvec4");
pg_no = (savvec4 >> PGSHIFT) & 0xfffff;
fixpv_pte(SBR, pg_no, &saved_pte, PTE_UW | PTE_V);
fixpv_pte(SBR, pg_no+1, &saved_pte, PTE_UW | PTE_V);
prot(); /* Do test .. */
fixpv_pte(SBR, pg_no, &saved_pte, PTE_KW | PTE_V);
fixpv_pte(SBR, pg_no+1, &saved_pte, PTE_KW | PTE_V);
/* Restore original PTEs */
pg_no = TEST_PTESYS;
pte = IOB0;
fixpfn_pte(SBR,pg_no, &pte_sys, pte_sys&0x3fffff);
pg_no = TEST_PTEP0;
pte = IOB1;
fixpfn_pte(P0BR,pg_no, &pte_p0, pte_p0&0x3fffff);
pg_no = TEST_PTEP1;
pte = IOB2;
fixpfn_pte(P1BR,pg_no, &pte_p1, pte_p1&0x3fffff);
pg_no = TEST_PTEP2;
pte = IOB3;
fixpfn_pte(P2BR,pg_no, &pte_p2, pte_p2&0x3fffff);
asm("mtpr $0,$MME"); /* Back to physical */
asm("mtpr $0,$P0LR"); /* Invalidate P0BR */
}
prot()
{ long access_md, privilege, exp_int;
/* PTE : No Access */
access_md = PTE_NOACC | PTE_V;
/* Try all privileges with R/W access on all tables */
exp_int = TRUE;
for(privilege=USER; privilege>=KERNEL; privilege--)
chmaps_prot(access_md,privilege,"rw",exp_int);
/* PTE : Kernel Read */
access_md = PTE_KR | PTE_V;
chmaps_prot(access_md,USER,"rw",exp_int);
chmaps_prot(access_md,KERNEL,"w",exp_int);
exp_int = FALSE;
chmaps_prot(access_md,KERNEL,"r",exp_int);
/* PTE : Kernel Write */
access_md = PTE_KW | PTE_V;
exp_int = TRUE;
chmaps_prot(access_md,USER,"rw",exp_int);
exp_int = FALSE;
chmaps_prot(access_md,0,"rw",exp_int);
/* PTE : User Read/Kernel Read */
access_md = PTE_URKR | PTE_V;
exp_int = TRUE;
chmaps_prot(access_md,USER,"w",exp_int);
chmaps_prot(access_md,KERNEL,"w",exp_int);
exp_int = FALSE;
chmaps_prot(access_md,USER,"r",exp_int);
chmaps_prot(access_md,KERNEL,"r",exp_int);
/* PTE : User Read/ Kernel Read/Write */
access_md = PTE_URKW | PTE_V;
exp_int = TRUE;
chmaps_prot(access_md,USER,"w",exp_int);
exp_int = FALSE;
chmaps_prot(access_md,USER,"r",exp_int);
chmaps_prot(access_md,KERNEL,"rw",exp_int);
/* PTE : User Read/Write/ Kernel Read/Write */
access_md = PTE_UW | PTE_V;
exp_int = FALSE;
for(privilege=USER; privilege>=KERNEL; privilege--)
chmaps_prot(access_md,privilege,"rw",exp_int);
}
char *spc_str;
chmaps_prot(access_md,priv,run_access,exp_int)
long access_md, priv, exp_int;
char *run_access;
{ long pg_table, pte_no, space;
for (pg_table=SBR; pg_table<=P2BR; pg_table += 2)
{
if (pg_table == SBR) {
pte_no = TEST_PTESYS;
space = SADDR; }
if (pg_table == P0BR) {
pte_no = TEST_PTEP0;
space = P0ADDR; }
if (pg_table == P1BR) {
pte_no = TEST_PTEP1;
space = P1ADDR; }
if (pg_table == P2BR) {
pte_no = TEST_PTEP2;
space = P2ADDR; }
force_flt(pg_table,pte_no,access_md,priv,run_access,space,exp_int);
}
}
/* This routine forces protection faults with read and write access
to page table specified by tbl_no . The access bits of this PTE
is set to value of pte_access, the process that access this PTE
is running in the mode specified by rum_mode.
tbl_no : (0,1,2,3) corresponding to P0PT, P1PT, P2PT, SPT.
which_pte : PTE to be accessed
pte_access : valid and protection bits to be set on PTE
access : "r", "rw", "w"/ "R", "RW", "W"
run_mode : privilege of process when access PTE
*/
force_flt(tbl_no, which_pte, pte_access, run_mode, access, addr_space, exp_int)
long tbl_no, which_pte, pte_access, run_mode, addr_space, exp_int;
char *access;
{
long *st_base, saved_vec1,saved_vec2,saved_pte,test_adr,tflag;
long ix, handler_adr;
char *acc_str, *pmode_str;
/* Set protection bits of target PTE */
fixpv_pte(tbl_no,which_pte,&saved_pte,pte_access);
/* Get virtual address of test location */
test_adr = (which_pte<<PGSHIFT)|addr_space;
for(ix=0;ix<2;ix++)
{
if (access[ix]==NULL) break;
/* Set handler of protection fault */
if (exp_int==TRUE)
asm("movab pro_flt1,_savvec4");
else
asm("movab pro_flt2,_savvec4");
handler_adr = savvec4;
set_handler(PROT_VEC,&saved_vec1,handler_adr);
/* Set handler for DATA ALIGNMENT FAULT */
asm("movab chmk_hd,_savvec4");
handler_adr = savvec4;
set_handler(ALIGN_FLT,&saved_vec2,handler_adr);
/* Set expected parameter words */
exp_par1 = exp_par2 = exp_par3 = 0;
exp_par1 = test_adr;
if ((access[ix]=='r') || (access[ix]=='R'))
{ /* protection violation, read access */
asm("movab rd_access,_exp_par2"); /* Expected PC */
exp_par0 = 0;
}
else
{ /* protection violation, write access */
asm("movab wr_access,_exp_par2");
exp_par0 = 4;
}
asm("mtpr $0xbfffb3fc,$USP"); /* Set up user stack */
asm("movab (sp),_savvec5");
savvec5 -= 40; /* KSP is 10 longword after ISP */
asm("mtpr _savvec5,$KSP");
/* set up to change privilege */
exp_par3 = run_mode << 24;
Tpsl = exp_par3; /* PSL when force fault */
Failpc = exp_par2; /* PC to force fault */
asm("pushl _exp_par3");
asm("pushl _exp_par2"); /* Push PSL, PC on current stack */
/* Change mode */
test_va = savvec5 = test_adr;
asm("movl _savvec5,r0");
/* Enable false */
asm("mtpr $64,$DCR");
asm("rei"); /* Go : Amem ... */
asm("halt"); /* REI fails ... */
asm("rtn0_p0:");
asm("movl r0,_savvec5"); /* flag indicate where return from */
tflag = savvec5;
st_base = &scb;
/* Restore Prot_fault, ALIGN_FLT vectors */
*(st_base + PROT_VEC) = saved_vec1;
*(st_base + ALIGN_FLT) = saved_vec2;
if (tflag && exp_int)
{ /* Error : expected event did not happen */
writes("** Expected protection fault didnot occured\n");
ac_error1();
asm("halt");
}
/* check fault parameters pushed on stack */
if ((exp_int==TRUE)&&(tflag==FALSE)) chk_fpars("");
}
/* Restore tested PTE's */
savvec5 = tbl_no;
asm("mfpr _savvec5,_savvec6");
st_base = (long *)savvec6;
st_base += which_pte;
*st_base = saved_pte;
}
/* Handler of protection fault exception. */
ptfx_handler()
{
asm(".align 2");
asm("pro_flt1:"); /* EXPECTED INTERRUPT */
asm("mtpr $0x1f,$IPL");
asm("movab (sp),_savvec5"); /* set pointer to parameters */
p_ptr = (long *)savvec5;
asm("svpctx"); /* switch back to ISP */
asm("clrl r0");
asm("jmp rtn0_p0"); /* return to test */
asm(".align 2");
asm("pro_flt2:"); /* UNEXPECTED INTERRUPT */
asm("mtpr $0x1f,$IPL");
asm("movab (sp),_savvec5"); /* set pointer to parameters */
asm("movl fp,_saved_fp"); /* save fp */
asm("movab (sp),fp"); /* set new frame pointer for next CALLS */
p_ptr = (long *)savvec5;
writes("** Unexpected protection fault\n");
ac_error1();
prt_par("** Parameters : ",p_ptr); /* print fault parameters */
asm("svpctx"); /* switch back to ISP */
asm("clrl r0");
asm("movl _saved_fp,fp"); /* restore fp */
asm("halt");
asm("jmp rtn0_p0"); /* return to test */
}
chmk_handler()
{
asm(".align 2");
asm("chmk_hd:"); /* Come here by causing a data not align fault */
/* return to test */
asm("mtpr $0x1f,$IPL"); /* Set IPL to HIGH */
asm("svpctx"); /* switch back to ISP */
asm("movl $1,r0"); /* set flag to indicate return from here */
asm("jmp rtn0_p0");
}
TEST_AREA()
{
asm("rd_access:");
asm("movl (r0),r12"); /* should cause protection fault exception !! */
/* Get back KERNEL privilege by causing a data not align fault */
asm("movl align_f,r10");
asm("halt"); /* otherwise HALT .... */
asm("wr_access:");
asm("movl $1,(r0)"); /* should cause protection fault exception !! */
/* Get back KERNEL privilege by causing a data not align fault */
asm("movl align_f,r10");
asm("halt"); /* otherwise HALT .... */
asm(".align 1"); /* Word align */
asm("align_f:");
asm(".long 0");
}
/* Print fault parameters of memory management exceptions */
prt_par(str,par)
char *str;
long *par;
{
writes(str);
writeh(*par++); writes(" ");
writeh(*par++); writes(" ");
writeh(*par++); writes(" ");
writeh(*par); writec('\n');
}
/* This routine assumes that global pointer p_ptr points to the actual
parameters pushed on the stack, and exp_par0 is the 1 of the expected
parameters.
*/
chk_fpars(msg)
char *msg;
{ long *pars, *e_pars;
long act_param0, act_param1, act_param2, act_param3;
e_pars = &exp_par0; /* pointer to expected parameters */
pars = p_ptr; /* pointer to actual parameters */
act_param0 = *pars++;
act_param1 = *pars++;
act_param2 = *pars++;
act_param3 = (*pars) & 0xffffffc0; /* Mask out PSW flags */
if ((exp_par0 != act_param0) || (exp_par1 != act_param1) ||
(exp_par2 != act_param2) || (exp_par3 != act_param3)) {
writes(msg);
writes("** Error in fault paramters\n");
ac_error1();
prt_par("** Expected : ",&exp_par0);
prt_par("** Actual : ",p_ptr);
asm("halt");
}
}
ac_error1()
{
writes("** PC : "); writeh(Failpc); writec('\n');
writes("** VA : "); writeh(test_va); writec('\n');
writes("** PSL : "); writeh(Tpsl); writec('\n');
prt_base(test_va);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.