⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 space.c

📁 T-kernel 的extension源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *---------------------------------------------------------------------- *    T-Kernel / Standard Extension * *    Copyright (C) 2006 by Ken Sakamura. All rights reserved. *    T-Kernel / Standard Extension is distributed  *      under the T-License for T-Kernel / Standard Extension. *---------------------------------------------------------------------- * *    Version:   1.00.00 *    Released by T-Engine Forum(http://www.t-engine.org) at 2006/8/11. * *---------------------------------------------------------------------- *//* *	space.c (memory) * *	Segment management (SH7751R Virtual storage version) *	Logical space control * *	(*) It is necessary to use some functions prior to T-Kernel/OS startup. *	   As for shared space, it must be able to do so without T-Kernel/OS *	   system call. *	   (Exercise care in processing related to Imalloc) */#include "segmgr.h"#include "prcinfo.h"#define TSD_ULS_VAL_M1	(-1)#define TSD_LSC_PPL_3	3#define TSD_MCM_RTN_M1	(-1)Inline VP CurrentUATB( void );LOCAL UW GetLSID_uatb( VP uatb );LOCAL PDE* GetPDE( VP laddr, VP uatb, ER *p_err );LOCAL W	 MonitorCheckMemory( VP laddr );/* * Page directory position (logical address) *	A unique space page directory is a table of unique spaces for the maximum number of *	processes + 1. At the start is a unique space for "lsid = 0" used in tasks that do *	not have unique spaces. */EXPORT PDE *SATB;	/* Shared space */EXPORT PDE *UATB;	/* Unique space */EXPORT UW MaxLSID;	/* Maximum number of unique spaces *//* * Obtain LSID */EXPORT UW GetLSID_pinfo( PINFO *pinfo ){#if USE_PROCESS_MANAGER	return (UW)((((UB*)pinfo - (UB*)TopPI) / PINFO_sz) + 1);#endif	return 0;}EXPORT UW GetLSID_tid( ID taskid ){	return (UW)GetTSKSPC_tid(taskid).lsid;}LOCAL UW GetLSID_uatb( VP uatb ){	return (UW)(( (PDE*)uatb - UATB ) / NUM_PDIR_ENTRIES);}/* * Obtain UATB */EXPORT VP GetUATB_lsid( UW lsid ){	if ( lsid >= MaxLSID ) {		DEBUG_PRINT(("GetUATB_lsid illegal lsid = %d\n", lsid));		lsid = 0;  /* Invalid LSID */	}	return UATB + (lsid * (UW)NUM_PDIR_ENTRIES);}EXPORT VP GetUATB_tid( ID taskid ){	return GetTSKSPC_tid(taskid).uatb;}/* * Obtain PINFO */EXPORT PINFO* GetPINFO_lsid( UW lsid ){#if USE_PROCESS_MANAGER	if ( lsid <= 0U ) {		return NULL;	}	if ( lsid >= MaxLSID ) {		DEBUG_PRINT(("GetPINFO_lsid illegal lsid = %d\n", lsid));		return NULL;  /* Invalid LSID */	}	return (PINFO*)((UB*)TopPI + ((lsid - 1U) * (UW)PINFO_sz));#endif	return NULL;}/* * Obtain T_TSKSPC */EXPORT T_TSKSPC GetTSKSPC_pinfo( PINFO *pinfo ){	T_TSKSPC	tskspc;	tskspc.lsid = (INT)GetLSID_pinfo(pinfo);	tskspc.uatb = GetUATB_lsid((UW)tskspc.lsid);	return tskspc;}EXPORT T_TSKSPC GetTSKSPC_lsid( UW lsid ){	T_TSKSPC	tskspc;	tskspc.lsid = ( lsid >= MaxLSID )? 0: (INT)lsid;	tskspc.uatb = GetUATB_lsid(lsid);	return tskspc;}EXPORT T_TSKSPC GetTSKSPC_tid( ID taskid ){	T_TSKSPC	tskspc;	ER		err;	err = tk_get_tsp(taskid, &tskspc);	if ( err < E_OK ) {		DEBUG_PRINT(("GetTSKSPC_tid err = %d\n", err));		tskspc.lsid = 0;		tskspc.uatb = UATB;	}	return tskspc;}/* * Switch logical spaces */EXPORT ER ChangeLogicalSpace( T_TSKSPC *curspc, T_TSKSPC chgspc ){	ER	err;	if ( curspc != NULL ) {		err = tk_get_tsp(TSK_SELF, curspc);		if ( err < E_OK ) {			goto err_ret;		}	}	err = tk_set_tsp(TSK_SELF, &chgspc);	if ( err < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("ChangeLogicalSpace err = %d\n", err));	return err;}/* * Obtain UATB for current space */Inline VP CurrentUATB( void ){	UW	uatb;	uatb = *(_UW*)TTB;	if ( uatb == 0U ) {		uatb = (UW)UATB;	}	return (VP)uatb;}/* ------------------------------------------------------------------------ */#define	UpdateTLB2	UpdateTLB/* * Obtain page directory entry */LOCAL PDE* GetPDE( VP laddr, VP uatb, ER *p_err ){	PDE	*pde;	if ( isLocalSpace(laddr) != 0 ) {		/* Unique space */		if ( uatb == 0 ) {			/* No unique space */			*p_err = E_PAR;			goto err_ret;		}		pde = (PDE*)uatb + PDIR_NUM(laddr);	} else {		/* Shared space */		pde = SATB + PDIR_NUM(laddr);	}	return pde;err_ret:	DEBUG_PRINT(("GetPDE err = %d\n", *p_err));	return NULL;}/* ------------------------------------------------------------------------ *//* *	Page table access function *//* * Initialize page table access handle *	"lsid = 0" indicates the current space. */EXPORT void InitPTH( PTH *pth, VP laddr, UW lsid ){	if ( lsid == 0U ) {		/* When "lsid is 0", the function is also called from the page fault handler.		 * Therefore, TSK_SELF cannot be used to obtain the current space.		 * Obtain uatb for the current space from TTB register.		 */		pth->uatb   = CurrentUATB();		pth->lsid   = GetLSID_uatb(pth->uatb);	} else {		pth->uatb   = GetUATB_lsid(lsid);		pth->lsid   = lsid;	}	pth->laddr = PageAlignL(laddr);	pth->pde   = NULL;}/* * Termination processing of page table access handle *	When set at "purge = TRUE", purge all TLB. *	When set at "purge = FALSE", do not purge TLB. */EXPORT void EndPTH( PTH *pth, BOOL purge ){	if ( purge != 0 ) {		PurgeAllTLB();	}}/* * Move to the next page table entry. *	Immediately after InitPTH(), move to the first page specified by InitPTH(). *	Cannot move across a boundary between shared and unique spaces (operation is not guaranteed). */EXPORT ER NextPTE( PTH *pth ){	PDE	*pde = pth->pde;	ER	err;	if ( pde != NULL ) {		/* Second and subsequent times: move to the next page */		pth->laddr = NextPage(pth->laddr);		if ( ++(pth->i) >= (W)N_PTE ) {			pde = NULL;		}	}	if ( pde == NULL ) {		/* Obtain page directory entry */		pde = GetPDE(pth->laddr, pth->uatb, &err);		if ( pde == NULL ) {			goto err_ret;		}		/* If there is no page table, return error. */		if ( pde->c.p == 0 ) {			err = E_MACV;			goto err_ret;		}		/* Position of page table entry */		pth->pde = pde;		pth->pte = PFAtoLADR(pde->c.pfa);		pth->i   = (W)PTBL_NUM(pth->laddr);	}	return E_OK;err_ret:	DEBUG_PRINT(("NextPTE err = %d\n", err));	return err;}/* * Fetch from the current page table */EXPORT UW GetPTE( PTH *pth ){	return pth->pte[pth->i].w;}/* * Set to the current page table *	When set at "purge = TRUE", purge TLB of intended pages. *	When set at "purge = FALSE", do not purge TLB. */EXPORT void SetPTE( PTH *pth, UW pte, BOOL purge ){	pth->pte[pth->i].w = pte;	if ( purge != 0 ) {		PurgePageTLB(pth->laddr, pth->lsid);	}}/* * Change the current page table. *	pte = pte & pte_m | pte_v * *	When set at "purge = TRUE", purge TLB of intended pages. *	When set at "purge = FALSE", do not purge TLB. * *	Return a page table setting value before change. */EXPORT UW ChgPTE( PTH *pth, UW pte_v, UW pte_m, BOOL purge ){	PTE	old_pte, new_pte;	UW	imask;	DI(imask);	old_pte.w = pth->pte[pth->i].w;	new_pte.w = (old_pte.w & pte_m) | pte_v;	if ( old_pte.c.p != 0 ) {		if ( new_pte.c.p == 0 ) {			/* To cancel pages,			   flush and cancel the cache. */			ExtFlushCache(pth->laddr, pth->lsid, old_pte.w);		} else if ( (old_pte.c.d != 0) && (new_pte.c.d == 0) ) {			/* To clear dirty bits,			   write back (do not cancel) the cache. */			FlushDCache(pth->laddr, pth->lsid);		}	}	pth->pte[pth->i].w = new_pte.w;	EI(imask);	if ( purge != 0 ) {		PurgePageTLB(pth->laddr, pth->lsid);	}	return old_pte.w;}/* * Load page table into TLB *	The current logical space must match pth->lsid. *	Called in interrupt-disabled state and used for TLB exception handler only. */EXPORT void LoadTLB( PTH *pth, UW mmucr ){	UpdateTLB(pth->laddr, pth->lsid, pth->pte[pth->i].w);}/* ------------------------------------------------------------------------ *//* * Refer to page table */EXPORT UW GET_PTE( VP laddr, UW lsid ){	PDE	*pde;	PTE	*pte;	ER	err;	/* Obtain page directory */	pde = GetPDE(laddr, GetUATB_lsid(lsid), &err);	if ( pde == NULL ) {		goto err_ret;	}	/* If there is no page table, return error. */	if ( pde->c.p == 0 ) {		err = E_MACV;		goto err_ret;	}	pte = PFAtoLADR(pde->c.pfa);	return pte[PTBL_NUM(laddr)].w;err_ret:	DEBUG_PRINT(("GET_PTE err = %d\n", err));	return PTE_NONE;}/* * Change page table *	pte = pte & pte_m | pte_v * *	When set at "purge = TRUE", purge TLB of intended pages. *	When set at "purge = FALSE", do not purge TLB. * *	Return a page table setting value before change. */EXPORT UW CHG_PTE( VP laddr, UW lsid, UW pte_v, UW pte_m, BOOL purge ){	PDE	*pde;	PTE	*pte;	PTE	old_pte, new_pte;	UW	imask;	ER	err;	/* Obtain page directory */	pde = GetPDE(laddr, GetUATB_lsid(lsid), &err);	if ( pde == NULL ) {		goto err_ret;	}	/* If there is no page table, return error. */	if ( pde->c.p == 0 ) {		err = E_MACV;		goto err_ret;	}	pte = PFAtoLADR(pde->c.pfa);	pte += PTBL_NUM(laddr);	DI(imask);	old_pte.w = pte->w;	new_pte.w = (old_pte.w & pte_m) | pte_v;	if ( old_pte.c.p != 0 ) {		if ( new_pte.c.p == 0 ) {			/* To cancel pages,			   flush and cancel the cache. */			ExtFlushCache(laddr, lsid, old_pte.w);		} else if ( (old_pte.c.d != 0) && (new_pte.c.d == 0) ) {			/* To clear dirty bits,			   write back (do not cancel) the cache. */			FlushDCache(laddr, lsid);		}	}	pte->w = new_pte.w;	EI(imask);	if ( purge != 0 ) {		PurgePageTLB(laddr, lsid);	}	return old_pte.w;err_ret:	DEBUG_PRINT(("CHG_PTE laddr = %#x lsid = %d err = %d\n",					laddr, lsid, err));	return PTE_NONE;}/* ------------------------------------------------------------------------ *//* * Generate logical space *	In lsid logical space, allocate virtual memory with set_pte attribute to npage of *	area (starting from a page that includes a logical address laddr). If the logical *	set_pte is a value (PTE) specified for a page table. */EXPORT ER __MakeSpace( VP laddr, W npage, UW lsid, UW set_pte ){	VP	la = laddr;	W	np = npage;	PTE	set;	VP	uatb;	PDE	*pde;	PTE	*pte;	PFE	*pfe;	W	i;	ER	err;	/* For a shared space, specify "lsid = 0". */	if ( !isLocalSpace(laddr)) {		lsid = 0;	}	set.w = set_pte;	uatb = GetUATB_lsid(lsid);	while ( np > 0 ) {		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( pde == NULL ) {			goto err_ret;		}		/* If there is no page table, obtain a new one. */		if ( pde->c.p == 0 ) {			/* Obtain page table */			pfe = GetPFM(PFS_lock, FALSE);			if ( pfe == NULL ) {				err = E_NOMEM;				goto err_ret;			}			pte = PFEtoLADR(pfe);			/* Initialize page table */			memset_w(pte, PTE_NONE, (size_t)N_PTE);			/* Set page directory */			pde->w = (UW)PDE_NORM | (UW)toPhysicalAddress(pte);		} else {			/* Obtain page table address and page number */			pte = PFAtoLADR(pde->c.pfa);			pfe = LADRtoPFE(pte);		}		/* Set page table */		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			if ( pte[i].w != (UW)PTE_NONE ) {				/* This page is already used. */				err = E_MACV;				goto err_ret;			}			pte[i] = set;			PurgePageTLB(la, lsid);			pfe->dbn_no++;		/* Number of valid pages */			la = NextPage(la);	/* Next page */			if ( --np <= 0 ) {				break;			}		}	}	return E_OK;err_ret:	(void)__UnmakeSpace(laddr, npage - np, lsid);	DEBUG_PRINT(("__MakeSpace err = %d\n", err));	return err;}EXPORT ER _MakeSpace( VP laddr, W npage, UW lsid, UW set_pte ){	ER	err;	if ( (set_pte & (UW)(PT_Present|PT_Valid)) != 0U ) {		err = E_PAR;		goto err_ret;	}	LockSEG();	err = __MakeSpace(laddr, npage, lsid, set_pte);	UnlockSEG();	return err;err_ret:	DEBUG_PRINT(("_MakeSpace err = %d\n", err));	return err;}/* * Delete logical space *	In lsid logical space, delete virtual memory with set_pte attribute allocated to npage *	of area (starting from a page that includes a logical address laddr). If the logical *	space does not have a process unique space, specify "lsid = 0". *	Locked pages are unlocked. */EXPORT ER __UnmakeSpace( VP laddr, W npage, UW lsid ){	VP	la  = laddr;	W	np  = npage;	VP	uatb;	PDE	*pde;	PTE	*pte;	PFE	*pfe;	PINFO	*pinfo;	W	i;	ER	err, error = E_OK;	/* For a shared space, specify "lsid = 0". */	if ( !isLocalSpace(laddr)) {		lsid = 0;	}	/* When performed on a unique space, obtain PINFO on the process. */	pinfo = GetPINFO_lsid(lsid);	uatb = GetUATB_lsid(lsid);	while ( np > 0 ) {		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( pde == NULL ) {			error = err;		}		if ( (pde == NULL) || (pde->c.p == 0) ) {			/* No page table */			i = (W)(N_PTE - PTBL_NUM(la));			la = (VP)((VB*)la + (PAGESIZE * i));			np -= i;			continue;		}		/* Obtain page table address and page number */		pte = PFAtoLADR(pde->c.pfa);		pfe = LADRtoPFE(pte);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			PTE old;			old = pte[i];			if ( old.w != (UW)PTE_NONE ) {				/* If pages are valid, flush the cache. */				if ( old.c.p != 0 ) {					ExtFlushCache(la, lsid, old.w);				}				/* Set invalid PTE */				pte[i].w = PTE_NONE;				PurgePageTLB(la, lsid);				/* Discontinue relations with PTE. */				err = UnlinkPage(old, pinfo);				if ( err < E_OK ) {					error = err;				}				pfe->dbn_no--;	/* Number of valid pages */			}			la = NextPage(la);	/* Next page */			if ( --np <= 0 ) {				break;			}		}		if ( pfe->dbn_no == 0 ) {			/* When a page table becomes empty,			   delete the page table itself. */			pde->w = PDE_NONE;			/* Release page frames for page tables. */			DiscardPageFrame(pfe);		}	}	if ( error < E_OK ) {		goto err_ret;	}	return E_OK;err_ret:	DEBUG_PRINT(("__UnmakeSpace err = %d\n", error));	return error;}EXPORT ER _UnmakeSpace( VP laddr, W npage, UW lsid ){	ER	err;	LockSEG();	err = __UnmakeSpace(laddr, npage, lsid);	UnlockSEG();	return err;}/* * Change logical space attribute *	In lsid logical space, change attributes of virtual memory allocated to npage of area *	(starting from a page that includes a logical address laddr) into chg_pte. *	Change attributes related to specification of access mode and copy-on-write only. *	The other attributes of page table are not changed. *	If the logical space does not have a process unique space, specify "lsid = 0". */EXPORT ER __ChangeSpace( VP laddr, W npage, UW lsid, UW chg_pte ){const	UW	CHG_MSK = (PT_Writable|PT_User|PT_CopyOnWrite);	VP	la  = laddr;	W	np  = npage;	VP	uatb;	PDE	*pde;	PTE	*pte;	W	i;	ER	err, error = E_OK;	/* For a shared space, specify "lsid = 0". */	if ( !isLocalSpace(laddr) ) {		lsid = 0;	}	chg_pte &= CHG_MSK;	uatb = GetUATB_lsid(lsid);	while ( np > 0 ) {		/* Obtain page directory entry */		pde = GetPDE(la, uatb, &err);		if ( pde == NULL ) {			error = err;		}		if ( (pde == NULL) || (pde->c.p == 0) ) {			/* No page table */			i = (W)(N_PTE - PTBL_NUM(la));			la = (VP)((VB*)la + (PAGESIZE * i));			np -= i;			continue;		}		/* Obtain page table address. */		pte = PFAtoLADR(pde->c.pfa);		for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) {			/* Change attribute of page table. */			pte[i].w = (pte[i].w & ~CHG_MSK) | chg_pte;			PurgePageTLB(la, lsid);			la = NextPage(la);	/* Next page */			if ( --np <= 0 ) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -