linux-old/arch/alpha/mm/remap.c
<<
>>
Prefs
   1#include <linux/vmalloc.h>
   2#include <asm/pgalloc.h>
   3
   4/* called with the page_table_lock held */
   5static inline void 
   6remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 
   7               unsigned long phys_addr, unsigned long flags)
   8{
   9        unsigned long end;
  10
  11        address &= ~PMD_MASK;
  12        end = address + size;
  13        if (end > PMD_SIZE)
  14                end = PMD_SIZE;
  15        if (address >= end)
  16                BUG();
  17        do {
  18                if (!pte_none(*pte)) {
  19                        printk("remap_area_pte: page already exists\n");
  20                        BUG();
  21                }
  22                set_pte(pte, 
  23                        mk_pte_phys(phys_addr, 
  24                                    __pgprot(_PAGE_VALID | _PAGE_ASM | 
  25                                             _PAGE_KRE | _PAGE_KWE | flags)));
  26                address += PAGE_SIZE;
  27                phys_addr += PAGE_SIZE;
  28                pte++;
  29        } while (address && (address < end));
  30}
  31
  32/* called with the page_table_lock held */
  33static inline int 
  34remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 
  35               unsigned long phys_addr, unsigned long flags)
  36{
  37        unsigned long end;
  38
  39        address &= ~PGDIR_MASK;
  40        end = address + size;
  41        if (end > PGDIR_SIZE)
  42                end = PGDIR_SIZE;
  43        phys_addr -= address;
  44        if (address >= end)
  45                BUG();
  46        do {
  47                pte_t * pte = pte_alloc(&init_mm, pmd, address);
  48                if (!pte)
  49                        return -ENOMEM;
  50                remap_area_pte(pte, address, end - address, 
  51                                     address + phys_addr, flags);
  52                address = (address + PMD_SIZE) & PMD_MASK;
  53                pmd++;
  54        } while (address && (address < end));
  55        return 0;
  56}
  57
  58int
  59__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
  60                         unsigned long size, unsigned long flags)
  61{
  62        pgd_t * dir;
  63        int error = 0;
  64        unsigned long end = address + size;
  65
  66        phys_addr -= address;
  67        dir = pgd_offset(&init_mm, address);
  68        flush_cache_all();
  69        if (address >= end)
  70                BUG();
  71        spin_lock(&init_mm.page_table_lock);
  72        do {
  73                pmd_t *pmd;
  74                pmd = pmd_alloc(&init_mm, dir, address);
  75                error = -ENOMEM;
  76                if (!pmd)
  77                        break;
  78                if (remap_area_pmd(pmd, address, end - address,
  79                                   phys_addr + address, flags))
  80                        break;
  81                error = 0;
  82                address = (address + PGDIR_SIZE) & PGDIR_MASK;
  83                dir++;
  84        } while (address && (address < end));
  85        spin_unlock(&init_mm.page_table_lock);
  86        return error;
  87}
  88
  89
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.