PageRenderTime 21ms CodeModel.GetById 10ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/alpha/mm/remap.c

https://bitbucket.org/evzijst/gittest
C | 90 lines | 81 code | 7 blank | 2 comment | 15 complexity | a86cb7b2b76deb1f64455b09279d65f0 MD5 | raw file
 1#include <linux/vmalloc.h>
 2#include <asm/pgalloc.h>
 3#include <asm/cacheflush.h>
 4
 5/* called with the page_table_lock held */
 6static inline void 
 7remap_area_pte(pte_t * pte, unsigned long address, unsigned long size, 
 8	       unsigned long phys_addr, unsigned long flags)
 9{
10	unsigned long end;
11	unsigned long pfn;
12
13	address &= ~PMD_MASK;
14	end = address + size;
15	if (end > PMD_SIZE)
16		end = PMD_SIZE;
17	if (address >= end)
18		BUG();
19	pfn = phys_addr >> PAGE_SHIFT;
20	do {
21		if (!pte_none(*pte)) {
22			printk("remap_area_pte: page already exists\n");
23			BUG();
24		}
25		set_pte(pte, pfn_pte(pfn, 
26				     __pgprot(_PAGE_VALID | _PAGE_ASM | 
27				              _PAGE_KRE | _PAGE_KWE | flags)));
28		address += PAGE_SIZE;
29		pfn++;
30		pte++;
31	} while (address && (address < end));
32}
33
34/* called with the page_table_lock held */
35static inline int 
36remap_area_pmd(pmd_t * pmd, unsigned long address, unsigned long size, 
37	       unsigned long phys_addr, unsigned long flags)
38{
39	unsigned long end;
40
41	address &= ~PGDIR_MASK;
42	end = address + size;
43	if (end > PGDIR_SIZE)
44		end = PGDIR_SIZE;
45	phys_addr -= address;
46	if (address >= end)
47		BUG();
48	do {
49		pte_t * pte = pte_alloc_kernel(&init_mm, pmd, address);
50		if (!pte)
51			return -ENOMEM;
52		remap_area_pte(pte, address, end - address, 
53				     address + phys_addr, flags);
54		address = (address + PMD_SIZE) & PMD_MASK;
55		pmd++;
56	} while (address && (address < end));
57	return 0;
58}
59
60int
61__alpha_remap_area_pages(unsigned long address, unsigned long phys_addr,
62			 unsigned long size, unsigned long flags)
63{
64	pgd_t * dir;
65	int error = 0;
66	unsigned long end = address + size;
67
68	phys_addr -= address;
69	dir = pgd_offset(&init_mm, address);
70	flush_cache_all();
71	if (address >= end)
72		BUG();
73	spin_lock(&init_mm.page_table_lock);
74	do {
75		pmd_t *pmd;
76		pmd = pmd_alloc(&init_mm, dir, address);
77		error = -ENOMEM;
78		if (!pmd)
79			break;
80		if (remap_area_pmd(pmd, address, end - address,
81			           phys_addr + address, flags))
82			break;
83		error = 0;
84		address = (address + PGDIR_SIZE) & PGDIR_MASK;
85		dir++;
86	} while (address && (address < end));
87	spin_unlock(&init_mm.page_table_lock);
88	return error;
89}
90