📄 space.c
字号:
while ( --n >= 0 ) { if ( *p == '\0' ) { return p - str; } p++; if ( --max == 0 ) { return p - str; } } } EI(imask);err_ret: DEBUG_PRINT(("_ChkSpaceBstr(%#x, %d, %d, %#x) = E_MACV\n", str, _max, mode, env)); return E_MACV;}/* * Check access attribute of logical space * In lsid logical space, check if it is possible to make access to up to len bytes of * area (starting from a logical address laddr) from env environment in mode. * mode = [MA_READ] | [MA_WRITE] | [MA_EXECUTE] * When set at "mode = 0", check the existence of memory. * As a return value, return the size of accessible area. * Return value 0 - len Number of accessible bytes * < 0 Error * * (*) Do not execute LockSEG(). * It causes deadlock when called from the disk driver. */EXPORT W _ChkSpaceLen( VP laddr, W len, UW mode, UW env, UW lsid ){ VP uatb; VP la; PDE *pde; PTE *pte; UW chk_u, chk_w; UW imask; W i; W plen = 0; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret1; } /* Attributes necessary for access */ chk_u = ( ((env & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3)) && (mode != 0U) )? 1: 0; chk_w = ( (mode & MA_WRITE) != 0U )? 1: 0; /* Check non-logical spaces in a fixed manner. */ if ( !isLogicalSpace(laddr) ) { if ( (chk_u > 0U) && !isP0(laddr) ) { err = E_MACV; goto err_ret1; } return len; } uatb = GetUATB_lsid(lsid); do { la = (VB*)laddr + plen; /* Disable interruption to prevent deletion of the page table while it is checked. */ DI(imask); /* Obtain page directory entry */ pde = GetPDE(la, uatb, &err); if ( pde == NULL ) { goto err_ret2; } if ( pde->c.p == 0 ) { /* No page table */ EI(imask); break; } /* 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 */ } /* Check access right. Enable writing for CopyOnWrite. */ if ( pte[i].c.u < chk_u ) { break; } if ( (pte[i].c.w < chk_w) && (pte[i].c.cow == 0) ) { break; } if ( plen == 0 ) { /* First page */ plen = PAGESIZE - (W)POFS_NUM(la); } else { plen += PAGESIZE; } if ( plen >= len ) { break; } } EI(imask); } while ( i == (W)N_PTE ); return ( len < plen )? len: plen;err_ret2: EI(imask);err_ret1: DEBUG_PRINT(("_ChkSpaceLen(%#x, %d, %d, %#x, %d) = %d\n", laddr, len, mode, env, lsid, err)); return err;}/* * Read from memory * Read up to len bytes (starting from a logical address laddr on lsid logical space) * and store it in the logical address buf located in a logical space of the task. * Read a range of memory (starting from laddr) regardless of access right and return * the number of bytes as a return value. * It is necessary to prepare writable memory space for len bytes * in buf area. * When called from user level, return error (E_CTX). * Return value 0 - len Number of read bytes * < 0 Error */EXPORT W __ReadMemSpace( VP laddr, VP buf, W len, UW lsid ){ VP uatb; VB *la, *pa; PDE *pde; PTE *pte; W i, n, alen; UW mdr; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret1; } /* Disable calls from user level. */ Asm("stc r2_bank, %0" : "=r"(mdr)); if ( (mdr & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3) ) { err = E_CTX; goto err_ret1; } /* Check buf access. */ err = _ChkSpace(buf, len, MA_WRITE, mdr); if ( err < E_OK ) { goto err_ret1; } /* Non-logical spaces are accessed directly. */ if ( !isLogicalSpace(laddr) ) { memmove(buf, laddr, (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; } } pa = PFAtoLADR(pte[i].c.pfa); pte[i].c.a = 1; /* Set access bit */ if ( alen == 0 ) { /* First page */ n = PAGESIZE - (W)POFS_NUM(la); if ( n > len ) { n = len; } memcpy(buf, pa + POFS_NUM(la), (size_t)n); } else { n = len - alen; if ( n > PAGESIZE ) { n = PAGESIZE; } memcpy((VB*)buf + alen, pa, (size_t)n); } 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(("__ReadMemSpace err = %d\n", err)); return err;}EXPORT W _ReadMemSpace( VP laddr, VP buf, W len, UW lsid ){ W err; LockSEG(); err = __ReadMemSpace(laddr, buf, len, lsid); UnlockSEG(); return err;}/* * Write to memory * Write up to len bytes from the logical address buf located in a logical space * of the task 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. * It is necessary to prepare readable memory space for len bytes * in buf area. * When called from user level, return error (E_CTX). * 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; UW mdr; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret1; } /* Disable calls from user level. */ Asm("stc r2_bank, %0" : "=r"(mdr)); if ( (mdr & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_PPL(TSD_LSC_PPL_3) ) { err = E_CTX; goto err_ret1; } /* Check buf access. */ err = _ChkSpace(buf, len, MA_READ, mdr); 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. */ 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); } 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; UW mdr; ER err; if ( len <= 0 ) { err = E_PAR; goto err_ret; } /* Disable calls from user level. */ Asm("stc r2_bank, %0" : "=r"(mdr)); if ( (mdr & (UW)MDR_PPL(TSD_LSC_PPL_3)) == (UW)MDR_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. */ if ( alen == 0 ) { /* First page */ n = PAGESIZE - (W)POFS_NUM(la); if ( n > len ) { n = len; } memset(pa + POFS_NUM(la), (INT)data, (size_t)n); } else { n = len - alen; if ( n > PAGESIZE ) { n = PAGESIZE; } memset(pa, (INT)data, (size_t)n); } 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;}/* ------------------------------------------------------------------------ *//* * Memory check function for monitor */LOCAL 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 ) { pde = (PDE*)CurrentUATB(); lsid = GetLSID_uatb(pde); } else { pde = SATB; lsid = 0; } 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 */ UpdateTLB2(laddr, lsid, pte->w); return 1; /* Physical memory is allocated. */}/* ------------------------------------------------------------------------ *//* * Initialization related to logical space control * (Before T-Kernel/OS startup) */EXPORT ER InitLogicalSpace( RealMemoryInfo *meminfo ){ W sz; ER err; /* 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); /* Register provisional page fault handler */ RegistTmpPageFaultHdr(); /* Enable MMU */ *(_UW*)PTEH = 0; *(_UW*)TTB = 0; *(_UW*)MMUCR = (UW)MMU_AT | (UW)MMU_TF; /* Register memory check function for monitor */ SCInfo.chkmem = (FP)MonitorCheckMemory; 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/OS startup) * * (*) In the case of SH, page tables are not necessary in physical memory areas. */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.clr, 'C'), /* clear */ M(pte.c.cow, 'O'), /* copy on write */ M(pte.c.w, 'W'), /* writable */ M(pte.c.u, 'U'), /* user */ M(pte.c.c, 'c'), /* cachable */ M(pte.c.wt, 't'), /* write through */ 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 + -