1 | /* |
2 | * This file is subject to the terms and conditions of the GNU General Public |
3 | * License. See the file "COPYING" in the main directory of this archive |
4 | * for more details. |
5 | * |
6 | * Copyright (C) 2003 by Ralf Baechle |
7 | */ |
8 | #include <linux/init.h> |
9 | #include <linux/mm.h> |
10 | #include <linux/memblock.h> |
11 | #include <linux/highmem.h> |
12 | #include <asm/fixmap.h> |
13 | #include <asm/pgalloc.h> |
14 | #include <asm/tlbflush.h> |
15 | |
16 | void pgd_init(void *addr) |
17 | { |
18 | unsigned long *p = (unsigned long *)addr; |
19 | int i; |
20 | |
21 | for (i = 0; i < USER_PTRS_PER_PGD; i+=8) { |
22 | p[i + 0] = (unsigned long) invalid_pte_table; |
23 | p[i + 1] = (unsigned long) invalid_pte_table; |
24 | p[i + 2] = (unsigned long) invalid_pte_table; |
25 | p[i + 3] = (unsigned long) invalid_pte_table; |
26 | p[i + 4] = (unsigned long) invalid_pte_table; |
27 | p[i + 5] = (unsigned long) invalid_pte_table; |
28 | p[i + 6] = (unsigned long) invalid_pte_table; |
29 | p[i + 7] = (unsigned long) invalid_pte_table; |
30 | } |
31 | } |
32 | |
33 | #if defined(CONFIG_TRANSPARENT_HUGEPAGE) |
34 | pmd_t mk_pmd(struct page *page, pgprot_t prot) |
35 | { |
36 | pmd_t pmd; |
37 | |
38 | pmd_val(pmd) = (page_to_pfn(page) << PFN_PTE_SHIFT) | pgprot_val(prot); |
39 | |
40 | return pmd; |
41 | } |
42 | |
43 | |
44 | void set_pmd_at(struct mm_struct *mm, unsigned long addr, |
45 | pmd_t *pmdp, pmd_t pmd) |
46 | { |
47 | *pmdp = pmd; |
48 | } |
49 | #endif /* defined(CONFIG_TRANSPARENT_HUGEPAGE) */ |
50 | |
51 | void __init pagetable_init(void) |
52 | { |
53 | unsigned long vaddr; |
54 | pgd_t *pgd_base; |
55 | #ifdef CONFIG_HIGHMEM |
56 | pgd_t *pgd; |
57 | p4d_t *p4d; |
58 | pud_t *pud; |
59 | pmd_t *pmd; |
60 | pte_t *pte; |
61 | #endif |
62 | |
63 | /* Initialize the entire pgd. */ |
64 | pgd_init(swapper_pg_dir); |
65 | pgd_init(&swapper_pg_dir[USER_PTRS_PER_PGD]); |
66 | |
67 | pgd_base = swapper_pg_dir; |
68 | |
69 | /* |
70 | * Fixed mappings: |
71 | */ |
72 | vaddr = __fix_to_virt(__end_of_fixed_addresses - 1); |
73 | fixrange_init(vaddr & PMD_MASK, vaddr + FIXADDR_SIZE, pgd_base); |
74 | |
75 | #ifdef CONFIG_HIGHMEM |
76 | /* |
77 | * Permanent kmaps: |
78 | */ |
79 | vaddr = PKMAP_BASE; |
80 | fixrange_init(vaddr & PMD_MASK, vaddr + PAGE_SIZE*LAST_PKMAP, pgd_base); |
81 | |
82 | pgd = swapper_pg_dir + pgd_index(vaddr); |
83 | p4d = p4d_offset(pgd, vaddr); |
84 | pud = pud_offset(p4d, vaddr); |
85 | pmd = pmd_offset(pud, vaddr); |
86 | pte = pte_offset_kernel(pmd, vaddr); |
87 | pkmap_page_table = pte; |
88 | #endif |
89 | } |
90 | |