📄 space.c
字号:
* Return value 0 - len Number of written bytes * < 0 Error */EXPORT W __WriteMemSpace( VP laddr, VP buf, W len, UW lsid ){ VP uatb; VB *la, *pa; PDE *pde; PTE *pte; W i, n, alen; UINT imask; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret1; } /* Disable calls from user level. */ if ( (SCInfo.taskmode & (UW)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) ) { err = E_CTX; goto err_ret1; } /* Check buf access. */ err = _ChkSpace(buf, len, MA_READ, SCInfo.taskmode); if ( err < E_OK ) { goto err_ret1; } /* Non-logical spaces are accessed directly. */ if ( !isLogicalSpace(laddr) ) { memmove(laddr, buf, (size_t)len); return len; } /* Make buf resident. */ err = __LockSpace(buf, len); if ( err < E_OK ) { goto err_ret1; } uatb = GetUATB_lsid(lsid); alen = 0; do { la = (VB*)laddr + alen; /* Obtain page directory entry */ pde = GetPDE(la, uatb, &err); if ( pde == NULL ) { goto err_ret2; } if ( pde->c.p == 0 ) { break; /* No page table */ } /* Obtain page table address. */ pte = PFAtoLADR(pde->c.pfa); for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) { if ( pte[i].w == (UW)PTE_NONE ) { break; /* Invalid PTE */ } if ( pte[i].c.p == 0 ) { /* Page in. */ err = PageIn(la, lsid); if ( err < E_OK ) { goto err_ret2; } } if ( pte[i].c.cow != 0 ) { /* Perform copy-on-write. */ err = CopyOnWrite(la, lsid); if ( err < E_OK ) { goto err_ret2; } } pa = PFAtoLADR(pte[i].c.pfa); pte[i].c.a = 1; /* Set access bit */ pte[i].c.d = 1; /* Set update bit. */ /* To access a physical address directly, flush the cache. * Then, disable interrupt to prevent the address from * being cached again by another access. */ DI(imask); ExtFlushCache(la, lsid); if ( alen == 0 ) { /* First page */ n = PAGESIZE - (W)POFS_NUM(la); if ( n > len ) { n = len; } memcpy(pa + POFS_NUM(la), buf, (size_t)n); } else { n = len - alen; if ( n > PAGESIZE ) { n = PAGESIZE; } memcpy(pa, (VB*)buf + alen, (size_t)n); } ExtFlushCache(pa, 0); EI(imask); alen += n; if ( alen >= len ) { break; } } } while ( i == (W)N_PTE ); /* Reset resident state of buf. */ err = __UnlockSpace(buf, len); if ( err < E_OK ) { goto err_ret1; } return alen;err_ret2: (void)__UnlockSpace(buf, len);err_ret1: DEBUG_PRINT(("__WriteMemSpace err = %d\n", err)); return err;}EXPORT W _WriteMemSpace( VP laddr, VP buf, W len, UW lsid ){ W err; LockSEG(); err = __WriteMemSpace(laddr, buf, len, lsid); UnlockSEG(); return err;}/* * Set to memory (Byte) * Write up to len bytes of data to a logical address laddr on * lsid logical space. * Write to a range of memory (starting from laddr) regardless of access right and * return the number of bytes as a return value. * When called from user level, return error (E_CTX). * Return value 0 - len Number of written bytes * < 0 Error */EXPORT W __SetMemSpaceB( VP laddr, W len, UB data, UW lsid ){ VP uatb; VB *la, *pa; PDE *pde; PTE *pte; W i, n, alen; UINT imask; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret; } /* Disable calls from user level. */ if ( (SCInfo.taskmode & (UW)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) ) { err = E_CTX; goto err_ret; } /* Non-logical spaces are accessed directly. */ if ( !isLogicalSpace(laddr) ) { memset(laddr, (W)data, (size_t)len); return len; } uatb = GetUATB_lsid(lsid); alen = 0; do { la = (VB*)laddr + alen; /* Obtain page directory entry */ pde = GetPDE(la, uatb, &err); if ( pde == NULL ) { goto err_ret; } if ( pde->c.p == 0 ) { break; /* No page table */ } /* Obtain page table address. */ pte = PFAtoLADR(pde->c.pfa); for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) { if ( pte[i].w == (UW)PTE_NONE ) { break; /* Invalid PTE */ } if ( pte[i].c.p == 0 ) { /* Page in. */ err = PageIn(la, lsid); if ( err < E_OK ) { goto err_ret; } } if ( pte[i].c.cow != 0 ) { /* Perform copy-on-write. */ err = CopyOnWrite(la, lsid); if ( err < E_OK ) { goto err_ret; } } pa = PFAtoLADR(pte[i].c.pfa); pte[i].c.a = 1; /* Set access bit */ pte[i].c.d = 1; /* Set update bit. */ /* To access a physical address directly, flush the cache. * Then, disable interrupt to prevent the address from * being cached again by another access. */ DI(imask); ExtFlushCache(la, lsid); if ( alen == 0 ) { /* First page */ n = PAGESIZE - (W)POFS_NUM(la); if ( n > len ) { n = len; } memset(pa + POFS_NUM(la), (W)data, (size_t)n); } else { n = len - alen; if ( n > PAGESIZE ) { n = PAGESIZE; } memset(pa, (W)data, (size_t)n); } ExtFlushCache(pa, 0); EI(imask); alen += n; if ( alen >= len ) { break; } } } while ( i == (W)N_PTE ); return alen;err_ret: DEBUG_PRINT(("__SetMemSpaceB err = %d\n", err)); return err;}EXPORT W _SetMemSpaceB( VP laddr, W len, UB data, UW lsid ){ W err; LockSEG(); err = __SetMemSpaceB(laddr, len, data, lsid); UnlockSEG(); return err;}/* ------------------------------------------------------------------------ *//* * Flush memory cache (both instruction/data caches) * Flush an area of size bytes starting from laddr and cancel it. * Since the area is flushed on a page basis, it may include its preceding and succeeding areas. */EXPORT void ExtFlushCacheArea( VP laddr, W size, UW lsid ){ VP la = PageAlignL(laddr); VP end = (B*)laddr + size; VP uatb; PDE *pde; PTE *pte; W i; ER err; /* Ignore non-cached areas. */ if ( isKSEG1(la) ) { return; } /* In non-logical space, cache areas are handled without reference to the page table. */ if ( isKSEG0(la) ) { for ( ; la < end; la = NextPage(la) ) { ExtFlushCache(la, lsid); } return; } uatb = GetUATB_lsid(lsid); while ( la < end ) { /* Obtain page directory entry */ pde = GetPDE(la, uatb, &err); if ( (pde == NULL) || (pde->c.p == 0) ) { /* No page table */ la = (VP)((VB*)la + (PAGESIZE * ((W)N_PTE - (W)PTBL_NUM(la)))); continue; } /* Obtain page table address. */ pte = PFAtoLADR(pde->c.pfa); for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) { /* If pages are valid, flush the cache. */ if ( pte[i].c.p != 0 ) { ExtFlushCache(la, lsid); } la = NextPage(la); /* Next page */ if ( la >= end ) { break; } } } return;}/* * Memory check function for monitor * Check if physical memory is allocated to pages that contain a virtual * address laddr. When physical memory is allocated, register an entry * corresponding to laddr in TLB. * Called in interrupt-disabled state * Return value 1 : Physical memory is allocated. * 0 : Physical memory is not allocated. * -1 : This is not virtual memory. */EXPORT W MonitorCheckMemory( VP laddr ){ PDE *pde; PTE *pte; UW lsid; if ( !isLogicalSpace(laddr) ) { return TSD_MCM_RTN_M1; /* Out of virtual memory area */ } if ( isLocalSpace(laddr) != 0 ) { lsid = CurrentLSID(); pde = GetUATB_lsid(lsid); } else { lsid = 0; pde = SATB; } pde += PDIR_NUM(laddr); if ( pde->c.p == 0 ) { return 0; /* Logical space is not allocated. */ } pte = PFAtoLADR(pde->c.pfa); pte += PTBL_NUM(laddr); if ( pte->c.p == 0 ) { return 0; /* Physical memory is not allocated. */ } /* TLB loading */ UpdateTLB(laddr, lsid, pte->w); return 1; /* Physical memory is allocated. */}/* Entry processing */IMPORT W asmMonitorCheckMemory( VP laddr );/* ------------------------------------------------------------------------ *//* * Cache line size (bytes) */EXPORT W ICacheLineSize; /* Instruction cache */EXPORT W DCacheLineSize; /* Data cache *//* * Initialization related to logical space control * (before T-Kernel startup) */EXPORT ER InitLogicalSpace( RealMemoryInfo *meminfo ){ W sz; ER err; UW cfg; /* Cache line size */ Asm("mfc0 %0, $16": "=r"(cfg)); /* Read config register. */ ICacheLineSize = ( (cfg & TSD_ILS_MSK_0X20) != 0U )? TSD_ILS_VAL_32: TSD_ILS_VAL_16; DCacheLineSize = ( (cfg & TSD_ILS_MSK_0X10) != 0U )? TSD_ILS_VAL_32: TSD_ILS_VAL_16; /* Generate shared space page directory */ SATB = AllocRealMem(meminfo, PAGESIZE); if ( SATB == NULL ) { err = E_NOMEM; goto err_ret; } bzero(SATB, PAGESIZE); /* Maximum number of unique spaces (Max number of processes + 1) */ err = GetSysConf_bms((UB*)"MaxProc", (W*)&MaxLSID, 1); if ( err < E_OK ) { goto err_ret; } MaxLSID++; /* Generate unique space page directory */ sz = (W)MaxLSID * ((W)sizeof(PDE) * NUM_PDIR_ENTRIES); UATB = AllocRealMem(meminfo, (UW)sz); if ( UATB == NULL ) { err = E_NOMEM; goto err_ret; } bzero(UATB, (size_t)sz); /* TLB initialization (cancel all) */ InitializeTLB(); /* Register provisional page fault handler */ RegistTmpPageFaultHdr(); /* Register memory check function for monitor */ SCInfo.chkmem = (FP)asmMonitorCheckMemory; return E_OK;err_ret: BMS_DEBUG_PRINT(("InitLogicalSpace err = %d\n", err)); return err;}/* * Set page table corresponding to the entire real memory area, * and obtain real memory area information. * (before T-Kernel startup) * * (*) In the case of VR, page table is not necessary for physical memory area. */EXPORT ER InitRealMemoryArea( RealMemoryInfo **p_meminfo ){IMPORT VP lowmem_top, lowmem_limit; /* Low-level memory management information */static RealMemoryInfo meminfo; W val[L_SYSCONF_VAL]; UW memend; W i; /* Value limitation on end address of real memory area */ i = GetSysConf((UB*)"RealMemEnd", val); memend = ( i == 1 )? (UW)val[0]: REALMEMORY_END; if ( (UW)lowmem_limit < memend ) { memend = (UW)lowmem_limit; } /* Set memory area information */ meminfo.a[0].b.laddr = lowmem_top; meminfo.a[0].b.nbyte = memend - (UW)lowmem_top; meminfo.n = 1; /* Update free space in memory */ lowmem_top = (VP)memend; *p_meminfo = &meminfo; return E_OK;}/* ======================================================================== *//* * Debug support function */#if DEBUGFUNC_SUPPORT#define M(v, c) ( ( (v) != 0 )? (c): '-' )/* * Indicate state of logical space */EXPORT void DumpSpace( W pid, VP sadr, VP eadr){ PTH pth; PTE pte; W npage; PINFO *pinfo; UW lsid; ER err; if ( pid > 0 ) { err = GetPidToPinfo(pid, &pinfo); if ( err < E_OK ) { DEBUG_PRINT(("** PID ERROR\n")); return; } lsid = GetLSID_pinfo(pinfo); } else { lsid = 0; } if ( !isLogicalSpace(sadr) || !isLogicalSpace(eadr) ) { DEBUG_PRINT(("** NO LOGICAL SPACE\n")); return; } sadr = PageAlignL(sadr); npage = PageCount((UW)eadr - (UW)sadr); DEBUG_PRINT(("[%2d]: LSID:%d UATB:0x%08x\n", pid, lsid, GetUATB_lsid(lsid))); InitPTH(&pth, sadr, lsid); DumpMore(0); while ( --npage >= 0 ) { err = NextPTE(&pth); if ( err < E_OK ) { break; } pte.w = GetPTE(&pth); if ( pte.w == (UW)PTE_NONE ) { continue; } DEBUG_PRINT((" [%08x] %05x %c%c%c%c%c%c%c%c%c%c\n", pth.laddr, /* logical address */ pte.c.pfa, /* page frame address */ M(pte.c.p, 'P'), /* present */ M(pte.c.va, 'V'), /* valid */ M(pte.c.g, 'S'), /* share */ M(pte.c.clr, 'C'), /* clear */ M(pte.c.cow, 'O'), /* copy on write */ M(pte.c.w, 'W'), /* writable */ M(pte.c.u, 'U'), /* user */ ( pte.c.wb != 0 )? 'b': /* write buffer */ M(pte.c.c, 'c'), /* cachable */ M(pte.c.a, 'A'), /* accessed */ M(pte.c.d, 'D') /* dirty */ )); if ( DumpMore(1) ) { break; } } EndPTH(&pth, FALSE);}#endif /* DEBUGFUNC_SUPPORT */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -