netlib.narod.ru< Назад | Оглавление | Далее >

include/asm-i386/pgtable.h

10876 #ifndef _I386_PGTABLE_H
10877 #define _I386_PGTABLE_H
10878 
10879 #include <linux/config.h>
10880 
10881 /* The Linux memory management assumes a three-level page
10882  * table setup. On the i386, we use that, but "fold" the
10883  * mid level into the top-level page table, so that we
10884  * physically have the same two-level page table as the
10885  * i386 mmu expects.
10886  *
10887  * This file contains the functions and defines necessary
10888  * to modify and use the i386 page table tree.  */
10889 #ifndef __ASSEMBLY__
10890 #include <asm/processor.h>
10891 #include <asm/fixmap.h>
10892 #include <linux/tasks.h>
10893 
10894 /* Caches aren't brain-dead on the intel. */
10895 #define flush_cache_all()               do { } while (0)
10896 #define flush_cache_mm(mm)              do { } while (0)
10897 #define flush_cache_range(mm, start, end)               \
10898                                         do { } while (0)
10899 #define flush_cache_page(vma, vmaddr)   do { } while (0)
10900 #define flush_page_to_ram(page)         do { } while (0)
10901 #define flush_icache_range(start, end)  do { } while (0)
10902 
10903 /* TLB flushing:
10904  *
10905  *  - flush_tlb() flushes the current mm struct TLBs
10906  *  - flush_tlb_all() flushes all processes TLBs
10907  *  - flush_tlb_mm(mm) flushes the specified mm context
10908  *    TLB's
10909  *  - flush_tlb_page(vma, vmaddr) flushes one page
10910  *  - flush_tlb_range(mm, start, end) flushes a range of
10911  *    pages
10912  *
10913  * ..but the i386 has somewhat limited tlb flushing
10914  * capabilities, and page-granular flushes are available
10915  * only on i486 and up.  */
10916 
 Комментарий
10917 #define __flush_tlb()                                   \
10918 do { unsigned long tmpreg;                              \
10919  __asm__ __volatile__("movl %%cr3,%0\n\tmovl %0,%%cr3": \
10920                   "=r" (tmpreg) : :"memory"); } while (0)
10921 
10922 #ifndef CONFIG_X86_INVLPG
10923 #define __flush_tlb_one(addr) flush_tlb()
10924 #else
10925 #define __flush_tlb_one(addr)                           \
10926 __asm__ __volatile__("invlpg %0": :"m" (*(char *) addr))
10927 #endif
10928 
10929 #ifndef __SMP__
10930 
10931 #define flush_tlb() __flush_tlb()
10932 #define flush_tlb_all() __flush_tlb()
10933 #define local_flush_tlb() __flush_tlb()
10934 
10935 static inline void flush_tlb_mm(struct mm_struct *mm)
10936 {
10937   if (mm == current->mm)
10938     __flush_tlb();
10939 }
10940 
10941 static inline void flush_tlb_page(
10942   struct vm_area_struct *vma, unsigned long addr)
10943 {
10944   if (vma->vm_mm == current->mm)
10945     __flush_tlb_one(addr);
10946 }
10947 
10948 static inline void flush_tlb_range(struct mm_struct *mm,
10949   unsigned long start, unsigned long end)
10950 {
10951   if (mm == current->mm)
10952     __flush_tlb();
10953 }
10954 
10955 #else
10956 
10957 /* We aren't very clever about this yet - SMP could
10958  * certainly avoid some global flushes..  */
10959 #include <asm/smp.h>
10960 
10961 #define local_flush_tlb()                               \
10962   __flush_tlb()
10963 
10964 
10965 #define CLEVER_SMP_INVALIDATE
10966 #ifdef CLEVER_SMP_INVALIDATE
10967 
10968 /* Smarter SMP flushing macros. c/o Linus Torvalds.
10969  * These mean you can really definitely utterly forget
10970  * about writing to user space from interrupts. (It's not
10971  * allowed anyway).  */
10972 
10973 static inline void flush_tlb_current_task(void)
10974 {
10975   /* just one copy of this mm? */
10976   if (atomic_read(&current->mm->count) == 1)
10977     local_flush_tlb();      /* and that's us, so.. */
10978   else
10979     smp_flush_tlb();
10980 }
10981 
10982 #define flush_tlb() flush_tlb_current_task()
10983 
10984 #define flush_tlb_all() smp_flush_tlb()
10985 
10986 static inline void flush_tlb_mm(struct mm_struct * mm)
10987 {
10988   if (mm == current->mm && atomic_read(&mm->count) == 1)
10989     local_flush_tlb();
10990   else
10991     smp_flush_tlb();
10992 }
10993 
10994 static inline void flush_tlb_page(
10995   struct vm_area_struct * vma, unsigned long va)
10996 {
10997   if (vma->vm_mm == current->mm &&
10998       atomic_read(&current->mm->count) == 1)
10999     __flush_tlb_one(va);
11000   else
11001     smp_flush_tlb();
11002 }
11003 
11004 static inline void flush_tlb_range(struct mm_struct * mm,
11005   unsigned long start, unsigned long end)
11006 {
11007   flush_tlb_mm(mm);
11008 }
11009 
11010 
11011 #else
11012 
11013 #define flush_tlb()                                     \
11014   smp_flush_tlb()
11015 
11016 #define flush_tlb_all() flush_tlb()
11017 
11018 static inline void flush_tlb_mm(struct mm_struct *mm)
11019 {
11020   flush_tlb();
11021 }
11022 
11023 static inline void flush_tlb_page(
11024   struct vm_area_struct *vma, unsigned long addr)
11025 {
11026   flush_tlb();
11027 }
11028 
11029 static inline void flush_tlb_range(struct mm_struct *mm,
11030   unsigned long start, unsigned long end)
11031 {
11032   flush_tlb();
11033 }
11034 #endif
11035 #endif
11036 #endif /* !__ASSEMBLY__ */
11037 
11038 
11039 /* Certain architectures need to do special things when
11040  * PTEs within a page table are directly modified.  Thus,
11041  * the following hook is made available.  */
11042 #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
11043 
11044 /* PMD_SHIFT determines the size of the area a
11045  * second-level page table can map */
11046 #define PMD_SHIFT       22
11047 #define PMD_SIZE        (1UL << PMD_SHIFT)
11048 #define PMD_MASK        (~(PMD_SIZE-1))
11049 
11050 /* PGDIR_SHIFT determines what a third-level page table
11051  * entry can map */
11052 #define PGDIR_SHIFT     22
11053 #define PGDIR_SIZE      (1UL << PGDIR_SHIFT)
11054 #define PGDIR_MASK      (~(PGDIR_SIZE-1))
11055 
11056 /* entries per page directory level: the i386 is
11057  * two-level, so we don't really have any PMD directory
11058  * physically.  */
11059 #define PTRS_PER_PTE    1024
11060 #define PTRS_PER_PMD    1
11061 #define PTRS_PER_PGD    1024
11062 #define USER_PTRS_PER_PGD       (TASK_SIZE/PGDIR_SIZE)
11063 
11064 /* pgd entries used up by user/kernel: */
11065 
11066 #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
11067 #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
11068 #define __USER_PGD_PTRS                                 \
11069         ((__PAGE_OFFSET >> PGDIR_SHIFT) & 0x3ff)
11070 #define __KERNEL_PGD_PTRS (PTRS_PER_PGD-__USER_PGD_PTRS)
11071 
11072 #ifndef __ASSEMBLY__
11073 /* Just any arbitrary offset to the start of the vmalloc
11074  * VM area: the current 8MB value just means that there
11075  * will be a 8MB "hole" after the physical memory until
11076  * the kernel virtual memory starts.  That means that any
11077  * out-of-bounds memory accesses will hopefully be
11078  * caught.  The vmalloc() routines leaves a hole of 4kB
11079  * between each vmalloced area for the same reason. ;) */
11080 #define VMALLOC_OFFSET  (8*1024*1024)
11081 #define VMALLOC_START   (((unsigned long) high_memory + \
11082                    VMALLOC_OFFSET) & ~(VMALLOC_OFFSET-1))
11083 #define VMALLOC_VMADDR(x) ((unsigned long)(x))
11084 #define VMALLOC_END     (FIXADDR_START)
11085 
11086 /* The 4MB page is guessing..  Detailed in the infamous
11087  * "Chapter H" of the Pentium details, but assuming intel
11088  * did the straightforward thing, this bit set in the
11089  * page directory entry just means that the page
11090  * directory entry points directly to a 4MB-aligned block
11091  * of memory.  */
11092 #define _PAGE_PRESENT   0x001
11093 #define _PAGE_RW        0x002
11094 #define _PAGE_USER      0x004
11095 #define _PAGE_WT        0x008
11096 #define _PAGE_PCD       0x010
11097 #define _PAGE_ACCESSED  0x020
11098 #define _PAGE_DIRTY     0x040
11099 /* 4 MB page, Pentium+, if present.. */
11100 #define _PAGE_4M        0x080
11101 #define _PAGE_GLOBAL    0x100 /* Global TLB entry PPro+*/
11102 
11103 #define _PAGE_PROTNONE  0x080   /* If not present */
11104 
11105 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW       |\
11106                         _PAGE_USER    | _PAGE_ACCESSED |\
11107                         _PAGE_DIRTY)
11108 #define _KERNPG_TABLE  (_PAGE_PRESENT   | _PAGE_RW     |\
11109                          _PAGE_ACCESSED | _PAGE_DIRTY)
11110 #define _PAGE_CHG_MASK (PAGE_MASK      | _PAGE_ACCESSED|\
11111                          _PAGE_DIRTY)
11112 
11113 #define PAGE_NONE      __pgprot(_PAGE_PROTNONE  |       \
11114                                 _PAGE_ACCESSED)
11115 #define PAGE_SHARED    __pgprot(_PAGE_PRESENT   |       \
11116                                 _PAGE_RW        |       \
11117                                 _PAGE_USER      |       \
11118                                 _PAGE_ACCESSED)
11119 #define PAGE_COPY      __pgprot(_PAGE_PRESENT   |       \
11120                                 _PAGE_USER      |       \
11121                                 _PAGE_ACCESSED)
11122 #define PAGE_READONLY  __pgprot(_PAGE_PRESENT   |       \
11123                                 _PAGE_USER      |       \
11124                                 _PAGE_ACCESSED)
11125 #define PAGE_KERNEL    __pgprot(_PAGE_PRESENT   |       \
11126                                 _PAGE_RW        |       \
11127                                 _PAGE_DIRTY     |       \
11128                                 _PAGE_ACCESSED)
11129 #define PAGE_KERNEL_RO __pgprot(_PAGE_PRESENT   |       \
11130                                 _PAGE_DIRTY     |       \
11131                                 _PAGE_ACCESSED)
11132 
11133 /* The i386 can't do page protection for execute, and
11134  * considers that the same are read.  Also, write
11135  * permissions imply read permissions. This is the
11136  * closest we can get..  */
11137 #define __P000  PAGE_NONE
11138 #define __P001  PAGE_READONLY
11139 #define __P010  PAGE_COPY
11140 #define __P011  PAGE_COPY
11141 #define __P100  PAGE_READONLY
11142 #define __P101  PAGE_READONLY
11143 #define __P110  PAGE_COPY
11144 #define __P111  PAGE_COPY
11145 
11146 #define __S000  PAGE_NONE
11147 #define __S001  PAGE_READONLY
11148 #define __S010  PAGE_SHARED
11149 #define __S011  PAGE_SHARED
11150 #define __S100  PAGE_READONLY
11151 #define __S101  PAGE_READONLY
11152 #define __S110  PAGE_SHARED
11153 #define __S111  PAGE_SHARED
11154 
11155 /* Define this if things work differently on an i386 and
11156  * an i486: it will (on an i486) warn about kernel memory
11157  * accesses that are done without a
11158  * 'verify_area(VERIFY_WRITE,..)'  */
11159 #undef TEST_VERIFY_AREA
11160 
11161 /* page table for 0-4MB for everybody */
11162 extern unsigned long pg0[1024];
11163 /* zero page used for uninitialized stuff */
11164 extern unsigned long empty_zero_page[1024];
11165 
11166 /* BAD_PAGETABLE is used when we need a bogus page-table,
11167  * while BAD_PAGE is used for a bogus page.  ZERO_PAGE is
11168  * a global shared page that is always zero: used for
11169  * zero-mapped memory areas etc..  */
11170 extern pte_t __bad_page(void);
11171 extern pte_t * __bad_pagetable(void);
11172 
11173 #define BAD_PAGETABLE __bad_pagetable()
11174 #define BAD_PAGE __bad_page()
11175 #define ZERO_PAGE ((unsigned long) empty_zero_page)
11176 
11177 /* number of bits that fit into a memory pointer */
11178 #define BITS_PER_PTR (8*sizeof(unsigned long))
11179 
11180 /* to align the pointer to a pointer address */
11181 #define PTR_MASK (~(sizeof(void*)-1))
11182 
11183 /* sizeof(void*)==1<<SIZEOF_PTR_LOG2 */
11184 /* 64-bit machines, beware!  SRB. */
11185 #define SIZEOF_PTR_LOG2                 2
11186 
11187 /* to find an entry in a page-table */
11188 #define PAGE_PTR(address)                               \
11189 ((unsigned long)(address)>>                             \
11190  (PAGE_SHIFT-SIZEOF_PTR_LOG2)&PTR_MASK&~PAGE_MASK)
11191 
11192 /* to set the page-dir */
11193 #define SET_PAGE_DIR(tsk,pgdir)                         \
11194 do {                                                    \
11195   unsigned long __pgdir = __pa(pgdir);                  \
11196   (tsk)->tss.cr3 = __pgdir;                             \
11197   if ((tsk) == current)                                 \
11198     __asm__                                             \
11199     __volatile__("movl %0,%%cr3": :"r" (__pgdir));      \
11200 } while (0)
11201 
11202 #define pte_none(x)     (!pte_val(x))
11203 #define pte_present(x)  (pte_val(x) &                   \
11204                          (_PAGE_PRESENT|_PAGE_PROTNONE))
11205 #define pte_clear(xp) do { pte_val(*(xp)) = 0; } while(0)
11206 
11207 #define pmd_none(x)     (!pmd_val(x))
11208 #define pmd_bad(x)                                      \
11209   ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) !=         \
11210    _KERNPG_TABLE)
11211 #define pmd_present(x)  (pmd_val(x) & _PAGE_PRESENT)
11212 #define pmd_clear(xp) do { pmd_val(*(xp)) = 0; } while(0)
11213 
11214 /* The "pgd_xxx()" functions here are trivial for a
11215  * folded two-level setup: the pgd is never bad, and a
11216  * pmd always exists (as it's folded into the pgd entry)
11217  */
11218 extern inline int pgd_none(pgd_t pgd)       { return 0; }
11219 extern inline int pgd_bad(pgd_t pgd)        { return 0; }
11220 extern inline int pgd_present(pgd_t pgd)    { return 1; }
11221 extern inline void pgd_clear(pgd_t * pgdp)  { }
11222 
11223 /* The following only work if pte_present() is true.
11224  * Undefined behaviour if not..  */
11225 extern inline int pte_read(pte_t pte)                   \
11226   { return pte_val(pte) & _PAGE_USER; }
11227 extern inline int pte_exec(pte_t pte)                   \
11228   { return pte_val(pte) & _PAGE_USER; }
11229 extern inline int pte_dirty(pte_t pte)                  \
11230   { return pte_val(pte) & _PAGE_DIRTY; }
11231 extern inline int pte_young(pte_t pte)                  \
11232   { return pte_val(pte) & _PAGE_ACCESSED; }
11233 extern inline int pte_write(pte_t pte)                  \
11234   { return pte_val(pte) & _PAGE_RW; }
11235 
11236 extern inline pte_t pte_rdprotect(pte_t pte)            \
11237   { pte_val(pte) &= ~_PAGE_USER; return pte; }
11238 extern inline pte_t pte_exprotect(pte_t pte)            \
11239   { pte_val(pte) &= ~_PAGE_USER; return pte; }
11240 extern inline pte_t pte_mkclean(pte_t pte)              \
11241   { pte_val(pte) &= ~_PAGE_DIRTY; return pte; }
11242 extern inline pte_t pte_mkold(pte_t pte)                \
11243   { pte_val(pte) &= ~_PAGE_ACCESSED; return pte; }
11244 extern inline pte_t pte_wrprotect(pte_t pte)            \
11245   { pte_val(pte) &= ~_PAGE_RW; return pte; }
11246 extern inline pte_t pte_mkread(pte_t pte)               \
11247   { pte_val(pte) |= _PAGE_USER; return pte; }
11248 extern inline pte_t pte_mkexec(pte_t pte)               \
11249   { pte_val(pte) |= _PAGE_USER; return pte; }
11250 extern inline pte_t pte_mkdirty(pte_t pte)              \
11251   { pte_val(pte) |= _PAGE_DIRTY; return pte; }
11252 extern inline pte_t pte_mkyoung(pte_t pte)              \
11253   { pte_val(pte) |= _PAGE_ACCESSED; return pte; }
11254 extern inline pte_t pte_mkwrite(pte_t pte)              \
11255   { pte_val(pte) |= _PAGE_RW; return pte; }
11256 
11257 /* Conversion functions: convert a page and protection to
11258  * a page entry, and a page entry and page directory to
11259  * the page they refer to.  */
11260 #define mk_pte(page, pgprot)                            \
11261   ({ pte_t __pte;                                       \
11262      pte_val(__pte) = __pa(page) + pgprot_val(pgprot);  \
11263      __pte; })
11264 
11265 /* This takes a physical page address that is used by the
11266  * remapping functions */
11267 #define mk_pte_phys(physpage, pgprot)                   \
11268 ({ pte_t __pte;                                         \
11269    pte_val(__pte) = physpage + pgprot_val(pgprot);      \
11270    __pte; })
11271 
11272 extern inline pte_t pte_modify(pte_t pte,
11273                                pgprot_t newprot)
11274 { pte_val(pte) = (pte_val(pte) & _PAGE_CHG_MASK) |
11275                  pgprot_val(newprot); return pte; }
11276 
11277 #define pte_page(pte)                                   \
11278 ((unsigned long) __va(pte_val(pte) & PAGE_MASK))
11279 
11280 #define pmd_page(pmd)                                   \
11281 ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
11282 
11283 /* to find an entry in a page-table-directory */
 Комментарий
11284 #define pgd_offset(mm, address)                         \
11285 ((mm)->pgd + ((address) >> PGDIR_SHIFT))
11286 
11287 /* to find an entry in a kernel page-table-directory */
11288 #define pgd_offset_k(address)                           \
11289   pgd_offset(&init_mm, address)
11290 
11291 /* Find an entry in the second-level page table.. */
11292 extern inline pmd_t * pmd_offset(pgd_t * dir,
11293                                  unsigned long address)
11294 {
11295   return (pmd_t *) dir;
11296 }
11297 
11298 /* Find an entry in the third-level page table.. */
11299 #define pte_offset(pmd, address)                        \
11300 ((pte_t *) (pmd_page(*pmd) + ((address>>10) &           \
11301                               ((PTRS_PER_PTE-1)<<2))))
11302 
11303 /* Allocate and free page tables. The xxx_kernel()
11304  * versions are used to allocate a kernel page table -
11305  * this turns on ASN bits if any.  */
11306 
11307 #define pgd_quicklist (current_cpu_data.pgd_quick)
11308 #define pmd_quicklist ((unsigned long *)0)
11309 #define pte_quicklist (current_cpu_data.pte_quick)
11310 #define pgtable_cache_size                              \
11311   (current_cpu_data.pgtable_cache_sz)
11312 
11313 extern __inline__ pgd_t *get_pgd_slow(void)
11314 {
11315   pgd_t *ret=(pgd_t *)__get_free_page(GFP_KERNEL), *init;
11316 
11317   if (ret) {
11318     init = pgd_offset(&init_mm, 0);
11319     memset(ret, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
11320     memcpy(ret + USER_PTRS_PER_PGD,
11321      init + USER_PTRS_PER_PGD,
11322      (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
11323   }
11324   return ret;
11325 }
11326 
11327 extern __inline__ pgd_t *get_pgd_fast(void)
11328 {
11329   unsigned long *ret;
11330 
11331   if((ret = pgd_quicklist) != NULL) {
11332     pgd_quicklist = (unsigned long *)(*ret);
11333     ret[0] = ret[1];
11334     pgtable_cache_size--;
11335   } else
11336     ret = (unsigned long *)get_pgd_slow();
11337   return (pgd_t *)ret;
11338 }
11339 
11340 extern __inline__ void free_pgd_fast(pgd_t *pgd)
11341 {
11342   *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
11343   pgd_quicklist = (unsigned long *) pgd;
11344   pgtable_cache_size++;
11345 }
11346 
11347 extern __inline__ void free_pgd_slow(pgd_t *pgd)
11348 {
11349   free_page((unsigned long)pgd);
11350 }
11351 
11352 extern pte_t *get_pte_slow(pmd_t *pmd,
11353   unsigned long address_preadjusted);
11354 extern pte_t *get_pte_kernel_slow(pmd_t *pmd,
11355   unsigned long address_preadjusted);
11356 
11357 extern __inline__ pte_t *get_pte_fast(void)
11358 {
11359   unsigned long *ret;
11360 
11361   if((ret = (unsigned long *)pte_quicklist) != NULL) {
11362     pte_quicklist = (unsigned long *)(*ret);
11363     ret[0] = ret[1];
11364     pgtable_cache_size--;
11365   }
11366   return (pte_t *)ret;
11367 }
11368 
11369 extern __inline__ void free_pte_fast(pte_t *pte)
11370 {
11371   *(unsigned long *)pte = (unsigned long) pte_quicklist;
11372   pte_quicklist = (unsigned long *) pte;
11373   pgtable_cache_size++;
11374 }
11375 
11376 extern __inline__ void free_pte_slow(pte_t *pte)
11377 {
11378   free_page((unsigned long)pte);
11379 }
11380 
11381 /* We don't use pmd cache, so these are dummy routines */
11382 extern __inline__ pmd_t *get_pmd_fast(void)
11383 {
11384   return (pmd_t *)0;
11385 }
11386 
11387 extern __inline__ void free_pmd_fast(pmd_t *pmd)
11388 {
11389 }
11390 
11391 extern __inline__ void free_pmd_slow(pmd_t *pmd)
11392 {
11393 }
11394 
11395 extern void __bad_pte(pmd_t *pmd);
11396 extern void __bad_pte_kernel(pmd_t *pmd);
11397 
11398 #define pte_free_kernel(pte)    free_pte_fast(pte)
11399 #define pte_free(pte)           free_pte_fast(pte)
11400 #define pgd_free(pgd)           free_pgd_fast(pgd)
11401 #define pgd_alloc()             get_pgd_fast()
11402 
11403 extern inline pte_t * pte_alloc_kernel(
11404   pmd_t * pmd, unsigned long address)
11405 {
11406   address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
11407   if (pmd_none(*pmd)) {
11408     pte_t * page = (pte_t *) get_pte_fast();
11409 
11410     if (!page)
11411       return get_pte_kernel_slow(pmd, address);
11412     pmd_val(*pmd) = _KERNPG_TABLE + __pa(page);
11413     return page + address;
11414   }
11415   if (pmd_bad(*pmd)) {
11416     __bad_pte_kernel(pmd);
11417     return NULL;
11418   }
11419   return (pte_t *) pmd_page(*pmd) + address;
11420 }
11421 
 Комментарий
11422 extern inline pte_t * pte_alloc(pmd_t * pmd,
11423                                 unsigned long address)
11424 {
11425   address = (address >> (PAGE_SHIFT-2)) &
11426             4*(PTRS_PER_PTE - 1);
11427 
 Комментарий
11428   if (pmd_none(*pmd))
11429     goto getnew;
11430   if (pmd_bad(*pmd))
11431     goto fix;
11432   return (pte_t *) (pmd_page(*pmd) + address);
11433 getnew:
11434 {
11435   unsigned long page = (unsigned long) get_pte_fast();
11436 
11437   if (!page)
11438     return get_pte_slow(pmd, address);
11439   pmd_val(*pmd) = _PAGE_TABLE + __pa(page);
11440   return (pte_t *) (page + address);
11441 }
11442 fix:
11443   __bad_pte(pmd);
11444   return NULL;
11445 }
11446 
11447 /* allocating and freeing a pmd is trivial: the 1-entry
11448  * pmd is inside the pgd, so has no extra memory
11449  * associated with it.  */
11450 extern inline void pmd_free(pmd_t * pmd)
11451 {
11452 }
11453 
 Комментарий
11454 extern inline pmd_t * pmd_alloc(pgd_t * pgd,
11455                                 unsigned long address)
11456 {
11457   return (pmd_t *) pgd;
11458 }
11459 
11460 #define pmd_free_kernel         pmd_free
11461 #define pmd_alloc_kernel        pmd_alloc
11462 
11463 extern int do_check_pgt_cache(int, int);
11464 
11465 extern inline void set_pgdir(unsigned long address,
11466                              pgd_t entry)
11467 {
11468   struct task_struct * p;
11469   pgd_t *pgd;
11470 #ifdef __SMP__
11471   int i;
11472 #endif
11473 
11474   read_lock(&tasklist_lock);
11475   for_each_task(p) {
11476     if (!p->mm)
11477       continue;
11478     *pgd_offset(p->mm,address) = entry;
11479   }
11480   read_unlock(&tasklist_lock);
11481 #ifndef __SMP__
11482   for (pgd = (pgd_t *)pgd_quicklist; pgd;
11483        pgd = (pgd_t *)*(unsigned long *)pgd)
11484     pgd[address >> PGDIR_SHIFT] = entry;
11485 #else
11486   /* To pgd_alloc/pgd_free, one holds master kernel lock
11487    * and so does our callee, so we can modify pgd caches
11488    * of other CPUs as well. -jj */
11489   for (i = 0; i < NR_CPUS; i++)
11490     for (pgd = (pgd_t *)cpu_data[i].pgd_quick; pgd;
11491          pgd = (pgd_t *)*(unsigned long *)pgd)
11492       pgd[address >> PGDIR_SHIFT] = entry;
11493 #endif
11494 }
11495 
11496 extern pgd_t swapper_pg_dir[1024];
11497 
11498 /* The i386 doesn't have any external MMU info: the
11499  * kernel page tables contain all the necessary
11500  * information.  */
 Комментарий
11501 extern inline void update_mmu_cache(
11502   struct vm_area_struct * vma,
11503   unsigned long address, pte_t pte)
11504 {
11505 }
11506 
11507 #define SWP_TYPE(entry) (((entry) >> 1) & 0x3f)
11508 #define SWP_OFFSET(entry) ((entry) >> 8)
11509 #define SWP_ENTRY(type,offset)                          \
11510   (((type) << 1) | ((offset) << 8))
11511 
11512 #define module_map      vmalloc
11513 #define module_unmap    vfree
11514 
11515 #endif /* !__ASSEMBLY__ */
11516 
11517 /* Needs to be defined here and not in linux/mm.h, as it
11518  * is arch dependent */
11519 #define PageSkip(page)          (0)
11520 #define kern_addr_valid(addr)   (1)
11521 
11522 #endif /* _I386_PAGE_H */

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz