File:  [Power 6/32 Unix Tahoe 4.2BSD] / cci / d / memman / ac_prot.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Sun Jul 28 12:24:19 2019 UTC (7 years ago) by root
Branches: bsd, MAIN
CVS tags: v12b, v121, HEAD
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);
}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.