📄 space.c
字号:
la = (VB*)laddr + plen; if ( plen >= len ) { break; } } } while ( i == (W)N_PTE ); if ( plen > len ) { plen = len; } return plen;}/* * Check access attribute of logical space * In a logical space of the task, check if it is possible to make access to len bytes * of area (starting from a logical address laddr) from env environment in mode. * If it is possible, return E_OK; if not possible, return E_MACV. * * (*) Do not execute LockSEG(). * It causes deadlock when called from the disk driver. */EXPORT ER _ChkSpace( VP laddr, W len, UW mode, UW env ){ VP la; PDE *pde; PTE *pte; UW chk_u, chk_w; UW imask; W i; W plen = 0; /* Attributes necessary for access */ chk_u = ( (env & (UW)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) )? 1U: 0U; chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U; /* Check non-logical spaces using a section table. */ if ( !isLogicalSpace(laddr) ) { for ( i = (W)SECTION_NO(laddr); i < MAX_SECTION; ++i ) { if ( SATB->s[i].s == 0 ) { break; /* There is no section table. */ } /* Check access right. */ if ( SATB->s[i].u < chk_u ) { break; } if ( SATB->s[i].w < chk_w ) { break; } if ( plen == 0 ) { /* First page */ plen = SECTION_SIZE - (W)SECTION_OFS(laddr); } else { plen += SECTION_SIZE; } if ( plen > len ) { break; } } goto ret; } 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 = SATB + PDIR_NUM(la); if ( pde->c[0].p == 0U ) { /* No page table */ EI(imask); break; } /* Obtain page table address. */ pte = PFAtoLADR(pde->c[0].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. */ if ( pte[i].c.u < chk_u ) { break; } if ( pte[i].c.w < chk_w ) { 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 );ret:#ifdef DEBUG if ( plen < len ) { DEBUG_PRINT(("_ChkSpace(%#x, %d, %d, %#x) = E_MACV\n", laddr, len, mode, env)); }#endif return ( plen >= len )? E_OK: E_MACV;}/* * Check access attribute of logical space(TC character string) * In a logical space of the task, check if it is possible to make access to an area * (starting from a logical address str to TNULL or to the max-th character) from * env environment in mode. When set at "max = 0", ignore the number (max) of characters. * If it is possible, return the number of characters or the value of max (when "max > 0" * and TNULL is not found before the max-th character); if not possible, return E_MACV. * * (*) It is assumed that str is an even-number address. * (*) Do not execute LockSEG(). * It causes deadlock when called from the disk driver. */EXPORT W _ChkSpaceTstr( TC *str, W max, UW mode, UW env ){ TC *tp = str; PDE *pde; PTE *pte; UW chk_u, chk_w; UW imask; W i, n;#ifdef DEBUG W _max = max;#endif /* Attributes necessary for access */ chk_u = ( (env & (UW)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) )? 1U: 0U; chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U; /* Check non-logical spaces using a section table. */ if ( !isLogicalSpace(tp) ) { for ( i = (W)SECTION_NO(tp); i < MAX_SECTION; ++i ) { if ( SATB->s[i].s == 0 ) { break; /* There is no section table. */ } /* Check access right. */ if ( SATB->s[i].u < chk_u ) { break; } if ( SATB->s[i].w < chk_w ) { break; } /* Number of characters within this section */ n = (SECTION_SIZE - (W)SECTION_OFS(tp)) / (W)sizeof(TC); /* TNULL checking */ while ( --n >= 0 ) { if ( *tp == TNULL ) { return tp - str; } tp++; if ( --max == 0 ) { return tp - str; } } } goto err_ret; } for ( ;; ) { /* Disable interruption to prevent deletion of the page table while it is checked. */ DI(imask); /* Obtain page directory entry */ pde = SATB + PDIR_NUM(tp); if ( pde->c[0].p == 0U ) { break; /* No page table */ } /* Obtain page table address. */ pte = PFAtoLADR(pde->c[0].pfa); /* Page table entry */ pte += PTBL_NUM(tp); if ( pte->w == (UW)PTE_NONE ) { break; /* Invalid PTE */ } /* Check access right. */ if ( pte->c.u < chk_u ) { break; } if ( pte->c.w < chk_w ) { break; } EI(imask); /* Number of characters within this page */ n = (PAGESIZE - (W)POFS_NUM(tp)) / (W)sizeof(TC); /* TNULL checking (Page-in may occur.) */ while ( --n >= 0 ) { if ( *tp == TNULL ) { return tp - str; } tp++; if ( --max == 0 ) { return tp - str; } } } EI(imask);err_ret: DEBUG_PRINT(("_ChkSpaceTstr(%#x, %d, %d, %#x) = E_MACV\n", str, _max, mode, env)); return E_MACV;}/* * Check access attribute of logical space(B character string) * In a logical space of the task, check if it is possible to make access to an area * (starting from a logical address str to '\0' or to the max-th byte) from * env environment in mode. When set at "max = 0", ignore the number (max) of bytes. * If it is possible, return the number of bytes or the value of max (when "max > 0" * and '\0' is not found before the max-th byte); if not possible, return E_MACV. * * (*) Do not execute LockSEG(). * It causes deadlock when called from the disk driver. */EXPORT W _ChkSpaceBstr( UB *str, W max, UW mode, UW env ){ UB *p = str; PDE *pde; PTE *pte; UW chk_u, chk_w; UW imask; W i, n;#ifdef DEBUG W _max = max;#endif /* Attributes necessary for access */ chk_u = ( (env & (UW)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) )? 1U: 0U; chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U; /* Check non-logical spaces using a section table. */ if ( !isLogicalSpace(p) ) { for ( i = (W)SECTION_NO(p); i < MAX_SECTION; ++i ) { if ( SATB->s[i].s == 0 ) { break; /* There is no section table. */ } /* Check access right. */ if ( SATB->s[i].u < chk_u ) { break; } if ( SATB->s[i].w < chk_w ) { break; } /* Number of characters within this section */ n = SECTION_SIZE - (W)SECTION_OFS(p); /* '\0' checking */ while ( --n >= 0 ) { if ( *p == '\0' ) { return p - str; } p++; if ( --max == 0 ) { return p - str; } } } goto err_ret; } for ( ;; ) { /* Disable interruption to prevent deletion of the page table while it is checked. */ DI(imask); /* Obtain page directory entry */ pde = SATB + PDIR_NUM(p); if ( pde->c[0].p == 0U ) { break; /* No page table */ } /* Obtain page table address. */ pte = PFAtoLADR(pde->c[0].pfa); /* Page table entry */ pte += PTBL_NUM(p); if ( pte->w == (UW)PTE_NONE ) { break; /* Invalid PTE */ } /* Check access right. */ if ( pte->c.u < chk_u ) { break; } if ( pte->c.w < chk_w ) { break; } EI(imask); /* Number of characters within this page */ n = PAGESIZE - (W)POFS_NUM(p); /* '\0' checking (Page-in may occur.) */ 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)TMF_PPL(TSD_LSC_PPL_3)) == (UW)TMF_PPL(TSD_LSC_PPL_3) )? 1U: 0U; chk_w = ( (mode & MA_WRITE) != 0U )? 1U: 0U; /* Check non-logical spaces using a section table. */ if ( !isLogicalSpace(laddr) ) { for ( i = (W)SECTION_NO(laddr); i < MAX_SECTION; ++i ) { if ( SATB->s[i].s == 0 ) { break; /* There is no section table. */ } /* Check access right. */ if ( SATB->s[i].u < chk_u ) { break; } if ( SATB->s[i].w < chk_w ) { break; } if ( plen == 0 ) { /* First page */ plen = SECTION_SIZE - (W)SECTION_OFS(laddr); } else { plen += SECTION_SIZE; } if ( plen > len ) { break; } } return ( len < plen )? len: plen; } 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[0].p == 0U ) { /* No page table */ EI(imask); break; } /* Obtain page table address. */ pte = PFAtoLADR(pde->c[0].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. */ if ( pte[i].c.u < chk_u ) { break; } if ( pte[i].c.w < chk_w ) { 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; BOOL curspc; W i, n, alen; 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_WRITE, SCInfo.taskmode); if ( err < E_OK ) { goto err_ret1; } /* Non-logical spaces are accessed directly. */ if ( !isLogicalSpace(laddr) ) { n = _ChkSpaceLen(laddr, len, MA_READ, SCInfo.taskmode, lsid); if ( n > 0 ) { memmove(buf, laddr, (size_t)n); } return n; } /* Make buf resident. */ err = __LockSpace(buf, len); if ( err < E_OK ) { goto err_ret1; } /* To refer to physical memory directly, flush the cache. */ ExtFlushCacheWT(); /* Performed in the current space: TRUE */ curspc = ( !isLocalSpace(laddr) || isCurrentSpace(lsid) ); 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[0].p == 0U ) { break; /* No page table */ } /* Obtain page table address. */ pte = PFAtoLADR(pde->c[0].pfa); for ( i = (W)PTBL_NUM(la); i < (W)N_PTE; ++i ) { if ( pte[i].w == (UW)PTE_NONE ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -