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

📄 mmu440lib.c

📁 VxWorks BSP框架源代码包含头文件和驱动
💻 C
📖 第 1 页 / 共 4 页
字号:
    int		 ix;			/* index of L1 entries */    int		 jx;			/* index into L2 table pages */    LEVEL_1_DESC lvl1Desc;		/* current L1 descriptor */    /* we need to enable writes on the level 1 page table and each level 2     * page table. The level 1 page table is MMU_PAGE_SIZE in size, whereas     * the level 2 page table is 4 * MMU_PAGE_SIZE in size.     */    /* write enable the level 1 page table */    mmu440StateSet (pTransTbl, (void *)pTransTbl->l1TblPtr.pL1Desc,		    MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE);    /* go thru the L 1 table and write enable each L 2 table */    for (ix = 0 ; ix < MMU_LVL_2_DESC_NB; ix++)	{	lvl1Desc = * (pTransTbl->l1TblPtr.pL1Desc + ix);	if (lvl1Desc.field.v)	    {	    for (jx = 0; jx < 4; jx++)		{		mmu440StateSet (pTransTbl,		    (void *)(lvl1Desc.field.l2ba << 2) + (jx * MMU_PAGE_SIZE),		    MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE);		}	    }	}    return (OK);    }#endif /* FALSE *//******************************************************************************** mmu440MemPagesWriteDisable - write disable memory holding PTEs** Memory containing translation table descriptors is marked as read only* to protect the descriptors from being corrupted.  This routine write protects* all the memory used to contain a given translation table's descriptors.** RETURNS: N/A*/LOCAL void mmu440MemPagesWriteDisable    (    MMU_TRANS_TBL * pTransTbl		/* Translation table to disable */    )    {    int		 ix;			/* index of L1 entries */    int		 jx;			/* index into L2 table pages */    LEVEL_1_DESC lvl1Desc;		/* current L1 descriptor */    /* we need to disable writes on the level 1 page table and each level 2     * page table. The level 1 page table is MMU_PAGE_SIZE in size, whereas     * the level 2 page table is 4 * MMU_PAGE_SIZE in size.     */    /* write protect the level 1 page table */    mmu440StateSet (pTransTbl, (void *)pTransTbl->l1TblPtr.pL1Desc,		    MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT);    /* go thru the L 1 table and write protect each L 2 table */    for (ix = 0 ; ix < MMU_LVL_2_DESC_NB; ix++)	{	lvl1Desc = * (pTransTbl->l1TblPtr.pL1Desc + ix);	if (lvl1Desc.field.v)	    {	    for (jx = 0; jx < 4; jx++)		{		mmu440StateSet (pTransTbl,		    (void *)(lvl1Desc.field.l2ba << 2) + (jx * MMU_PAGE_SIZE),		    MMU_STATE_MASK_WRITABLE, MMU_STATE_WRITABLE_NOT);		}	    }	}    }/******************************************************************************** mmu440TransTblCreate - create a new translation table.** RETURNS: address of new object or NULL if allocation failed.*/LOCAL MMU_TRANS_TBL * mmu440TransTblCreate (void)    {    MMU_TRANS_TBL *	pNewTransTbl;		/* new translation table */    /* allocate a piece of memory to save the new translation table */    pNewTransTbl = (MMU_TRANS_TBL *) malloc (sizeof (MMU_TRANS_TBL));    /* if the memory can not allocated then return the NULL pointer */    if (pNewTransTbl == NULL)	return (NULL);    /* get a free PID for the new translation table */    pNewTransTbl->pid = mmu440PidAlloc (pNewTransTbl);    if (pNewTransTbl->pid == 0) /* no free PIDs ! */	{	free ((char *) pNewTransTbl);	return (NULL);	}    /*     * initialize the new translation table.     * If the initialization fails then free the memory and return the NULL     * pointer.     */    if (mmu440TransTblInit (pNewTransTbl) == ERROR)	{	free ((char *) pNewTransTbl);	return (NULL);	}    /* return the new translation table created */    return (pNewTransTbl);    }/******************************************************************************** mmu440TransTblInit - initialize a new translation table** Initialize a new translation table.  The level 1 table is copied from the* global translation mmuGlobalTransTbl, so that we will share the global* virtual memory with all other translation tables.** RETURNS: OK, or ERROR if unable to allocate memory.*/LOCAL STATUS mmu440TransTblInit    (    MMU_TRANS_TBL * pNewTransTbl	/* translation table to initialize */    )    {    /*     * Allocate memory space for a new Level 1 descriptor table.  This memory     * needs to be page aligned because, we write protect all the page tables     * later, and we don't want other variables sharing a page with the page     * table itself.     */    pNewTransTbl->l1TblPtr.pL1Desc =	(LEVEL_1_DESC *) memalign (MMU_PAGE_SIZE, MMU_PAGE_SIZE);    /* if the memory cannot be allocated then return ERROR */    if (pNewTransTbl->l1TblPtr.pL1Desc == NULL)	return (ERROR);    /* invalidate all entries in the table */    memset ((void *) pNewTransTbl->l1TblPtr.pL1Desc, 0x00, MMU_PAGE_SIZE);    if (mmuGlobalTransTbl != NULL)	{	/* copy the global level 1 descriptor table to the new table */	memcpy ((void *) pNewTransTbl->l1TblPtr.pL1Desc,	    (void *) mmuGlobalTransTbl->l1TblPtr.pL1Desc, MMU_PAGE_SIZE);	}    /* In AE, would page protect the new L1 descriptor table here */    return (OK);    }/******************************************************************************** mmu440TransTblDelete - delete a translation table.** This routine deletes a translation table.** RETURNS: OK always.*/LOCAL STATUS mmu440TransTblDelete    (    MMU_TRANS_TBL * pTransTbl		/* translation table to be deleted */    )    {    LEVEL_1_DESC 	lvl1Desc;	/* level 1 descriptor */    UINT32		ix;    /* free the PID element for this translation table */    mmu440PidFree (pTransTbl->pid);    /* free level 2 page tables */    for (ix = 0 ; ix < MMU_LVL_2_DESC_NB; ix++)	{	lvl1Desc = * (pTransTbl->l1TblPtr.pL1Desc + ix);	if (lvl1Desc.field.v)	    free ((void *) (lvl1Desc.l1desc & MMU_LVL_1_L2BA_MSK));	}    /* free the level 1 table */    free ((void *) pTransTbl->l1TblPtr.pL1Desc);    return (OK);    }/******************************************************************************** mmu440Enable - turn mmu on or off** On the PPC440, the MMU is always on, so turning it off is a misnomer.* Instead, this function changes the MSR[IS,DS] values, which change which TLB* entries match -- either the static ones that emulate 'real mode', or the ones* that provide dynamic mmu page mapping.** RETURNS: OK*/LOCAL STATUS mmu440Enable    (    BOOL enable			/* TRUE to enable, FALSE to disable MMU */    )    {    int lockKey;		/* lock key for intUnlock() */    if (mmuPpcSelected == 0)	return (OK);    /* lock the interrupt */    lockKey = intLock ();    if (enable)	{	if (mmuPpcSelected & MMU_INST)	    mmuPpcAEnable (MMU_I_ADDR_TRANS);	/* enable instruction MMU */	if (mmuPpcSelected & MMU_DATA)	    mmuPpcAEnable (MMU_D_ADDR_TRANS);	/* enable data MMU */	}    else	{	if (mmuPpcSelected & MMU_INST)	    mmuPpcADisable (MMU_I_ADDR_TRANS);	/* disable instruction MMU */	if (mmuPpcSelected & MMU_DATA)	    mmuPpcADisable (MMU_D_ADDR_TRANS);	/* disable data MMU */	}    /* AE would unmap EA 0x0 - 0x2fff here, but only for user mode tasks */    intUnlock (lockKey);			/* unlock the interrupt */    return (OK);    }/******************************************************************************** mmu440StateSet - set state of virtual memory page*** MMU_STATE_VALID	MMU_STATE_VALID_NOT	valid/invalid* MMU_STATE_WRITABLE	MMU_STATE_WRITABLE_NOT	writable/writeprotected* MMU_STATE_CACHEABLE	MMU_STATE_CACHEABLE_NOT	cachable/notcachable* MMU_STATE_CACHEABLE_WRITETHROUGH* MMU_STATE_CACHEABLE_COPYBACK* MMU_STATE_GUARDED	MMU_STATE_GUARDED_NOT	guarded/un-guarded** RETURNS: OK, or ERROR if descriptor address does not exist.*/LOCAL STATUS mmu440StateSet    (    MMU_TRANS_TBL *	pTransTbl, 	/* translation table */    void *		effectiveAddr,	/* page whose state to modify */    UINT 		stateMask,	/* mask of which state bits to modify */    UINT		state		/* new state bit values */    )    {    LEVEL_2_DESC *	pLvl2Desc;	/* level 2 descriptor address */    LEVEL_2_DESC	lvl2Desc;	/* level 2 descriptor */    BOOL		flush = FALSE;	/* page must be flushed from cache */    /*     * get the level 2 descriptor address. If this descriptor address doesn't     * exist then set errno and return ERROR.     */    if (mmu440Lvl2DescAddrGet (pTransTbl, effectiveAddr, &pLvl2Desc) == ERROR)	{	errno = S_mmuLib_NO_DESCRIPTOR;	return (ERROR);	}    /* make a working copy of the Level 2 Descriptor */    lvl2Desc = *pLvl2Desc;    if (stateMask & MMU_STATE_MASK_CACHEABLE)	{	/*	 * Check if the state to set page corresponding to <effectiveAddr>	 * will not set the cache inhibited and writethrough mode. This mode	 * is not supported by the cache.	 */	if ((state & MMU_STATE_CACHEABLE_NOT) &&	    (state & MMU_STATE_CACHEABLE_WRITETHROUGH))	    {	    return (ERROR);	    }	/*	 * if the page is presently COPYBACK, and we plan to set it to	 * cache inhibited or writeback, flush the page before continuing.	 */	if (lvl2Desc.field.v &&	    ((lvl2Desc.words.word2 & MMU_STATE_MASK_CACHEABLE) ==	     MMU_STATE_CACHEABLE_COPYBACK) &&	    ((state & MMU_STATE_MASK_CACHEABLE) !=	     MMU_STATE_CACHEABLE_COPYBACK))	    {	    flush = TRUE;	    }	}    /*     * set or reset the VALID bit if requested. Since the Valid bit     * in MMU_STATE is in a different bit position than in the TLB Word 0,     * we use an if statement to express the logic clearly rather than     * use a complicated mixture of shift, or, and and.     */    if (stateMask & MMU_STATE_MASK_VALID)	{	if (state & stateMask & MMU_STATE_MASK_VALID)	    lvl2Desc.field.v = 1;	else	    lvl2Desc.field.v = 0;	}    /*     * set or reset the WIMG bits as requested. WIMG and write/execute bits     * are in the same bit positions in MMU_STATE as in TLB Word 2, so we     * can use bitwise arithmetic     */    lvl2Desc.words.word2 &= ~(stateMask & MMU_STATE_MASK_WIMG_WRITABLE_EXECUTE);    lvl2Desc.words.word2 |= (state & stateMask &			     MMU_STATE_MASK_WIMG_WRITABLE_EXECUTE);    /* flush out any copyback data before we change the attribute mapping */    if (flush == TRUE)	cacheArchFlush(DATA_CACHE, effectiveAddr, MMU_PAGE_SIZE);    /* update the Level 2 Descriptor */    mmu440Lvl2DescUpdate (pLvl2Desc, lvl2Desc);    /* invalidate the tlb entry for this effective address */    mmu440Tlbie (pTransTbl, effectiveAddr);    return (OK);    }/******************************************************************************** mmu440StateGet - get state of virtual memory page**/LOCAL STATUS mmu440StateGet    (    MMU_TRANS_TBL *	pTransTbl,	/* tranlation table */    void *		effectiveAddr, 	/* page whose state we're querying */    UINT *		state		/* place to return state value */    )    {    LEVEL_2_DESC *	pLvl2Desc;	/* level 2 descriptor address */    LEVEL_2_DESC	lvl2Desc;	/* level 2 descriptor */    /*     * get the level 2 descriptor address. If this descriptor address doesn't     * exist then set errno and return ERROR.     */    if (mmu440Lvl2DescAddrGet (pTransTbl, effectiveAddr, &pLvl2Desc) == ERROR)	{	errno = S_mmuLib_NO_DESCRIPTOR;	return (ERROR);	}    /* make a working copy the Level 2 Descriptor */    lvl2Desc = *pLvl2Desc;    /* extract the state of the VALID, WIMG and EX, WR bits.     * Note that the valid bit is in a different bit position in L2 desc     * than in the MMU_STATE_VALID.     */    * state = (lvl2Desc.field.v ? MMU_STATE_VALID : 0);    * state |= lvl2Desc.words.word2 & MMU_STATE_MASK_WIMG_WRITABLE_EXECUTE;    return (OK);    }/******************************************************************************** mmu440PageMap - map physical memory page to virtual memory page** The physical page address is entered into the level 2 descriptor* corresponding to the given virtual page.  The state of a newly mapped page* is undefined.** RETURNS: OK, or ERROR if translation table creation failed.*/LOCAL STATUS mmu440PageMap    (    MMU_TRANS_TBL *	pTransTbl, 	/* translation table */    void *		effectiveAddr, 	/* effective address */    void *		physicalAddr	/* physical address */    )    {    LEVEL_1_DESC *	pLvl1Desc;	/* level 1 descriptor address */    LEVEL_1_DESC 	lvl1Desc;	/* level 1 descriptor */    LEVEL_2_DESC *	pLvl2Desc;	/* level 2 descriptor address */    LEVEL_2_DESC 	lvl2Desc;	/* level 2 descriptor */    /* get the level 1 descriptor address */    pLvl1Desc = mmu440Lvl1DescAddrGet (pTransTbl, effectiveAddr);

⌨️ 快捷键说明

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