blob: 30099a7552e3f332273ebaa7244f667f42b6e4d9 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
|
#ifndef _I386_PGALLOC_3LEVEL_H
#define _I386_PGALLOC_3LEVEL_H
/*
* Intel Physical Address Extension (PAE) Mode - three-level page
* tables on PPro+ CPUs. Page-table allocation routines.
*
* Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
*/
extern __inline__ pmd_t *get_pmd_slow(void)
{
pmd_t *ret = (pmd_t *)__get_free_page(GFP_KERNEL);
if (ret)
memset(ret, 0, PAGE_SIZE);
return ret;
}
extern __inline__ pmd_t *get_pmd_fast(void)
{
unsigned long *ret;
if ((ret = pmd_quicklist) != NULL) {
pmd_quicklist = (unsigned long *)(*ret);
ret[0] = 0;
pgtable_cache_size--;
} else
ret = (unsigned long *)get_pmd_slow();
return (pmd_t *)ret;
}
extern __inline__ void free_pmd_fast(pmd_t *pmd)
{
*(unsigned long *)pmd = (unsigned long) pmd_quicklist;
pmd_quicklist = (unsigned long *) pmd;
pgtable_cache_size++;
}
extern __inline__ void free_pmd_slow(pmd_t *pmd)
{
free_page((unsigned long)pmd);
}
extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
{
if (!pgd)
BUG();
address = (address >> PMD_SHIFT) & (PTRS_PER_PMD - 1);
if (pgd_none(*pgd)) {
pmd_t *page = get_pmd_fast();
if (!page)
page = get_pmd_slow();
if (page) {
if (pgd_none(*pgd)) {
set_pgd(pgd, __pgd(1 + __pa(page)));
__flush_tlb();
return page + address;
} else
free_pmd_fast(page);
} else
return NULL;
}
return (pmd_t *)pgd_page(*pgd) + address;
}
#endif /* _I386_PGALLOC_3LEVEL_H */
|