aboutsummaryrefslogtreecommitdiffstats
path: root/patches/linux-2.6.16-rc4/pmd-shared.patch
blob: 3764a3219e71a9017d8a68972d24800ceadd1729 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
diff -pruN ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pageattr.c ./arch/i386/mm/pageattr.c
--- ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pageattr.c	2006-02-02 17:39:29.000000000 +0000
+++ ./arch/i386/mm/pageattr.c	2006-02-02 17:45:14.000000000 +0000
@@ -78,7 +78,7 @@ static void set_pmd_pte(pte_t *kpte, uns
 	unsigned long flags;
 
 	set_pte_atomic(kpte, pte); 	/* change init_mm */
-	if (PTRS_PER_PMD > 1)
+	if (HAVE_SHARED_KERNEL_PMD)
 		return;
 
 	spin_lock_irqsave(&pgd_lock, flags);
diff -pruN ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pgtable.c ./arch/i386/mm/pgtable.c
--- ../pristine-linux-2.6.16-rc1-git4/arch/i386/mm/pgtable.c	2006-01-03 03:21:10.000000000 +0000
+++ ./arch/i386/mm/pgtable.c	2006-02-02 17:45:14.000000000 +0000
@@ -215,9 +215,10 @@ void pgd_ctor(void *pgd, kmem_cache_t *c
 		spin_lock_irqsave(&pgd_lock, flags);
 	}
 
-	clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
-			swapper_pg_dir + USER_PTRS_PER_PGD,
-			KERNEL_PGD_PTRS);
+	if (PTRS_PER_PMD == 1 || HAVE_SHARED_KERNEL_PMD)
+		clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
+				swapper_pg_dir + USER_PTRS_PER_PGD,
+				KERNEL_PGD_PTRS);
 	if (PTRS_PER_PMD > 1)
 		return;
 
@@ -249,6 +250,30 @@ pgd_t *pgd_alloc(struct mm_struct *mm)
 			goto out_oom;
 		set_pgd(&pgd[i], __pgd(1 + __pa(pmd)));
 	}
+
+	if (!HAVE_SHARED_KERNEL_PMD) {
+		unsigned long flags;
+
+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
+			pmd_t *pmd = kmem_cache_alloc(pmd_cache, GFP_KERNEL);
+			if (!pmd)
+				goto out_oom;
+			set_pgd(&pgd[USER_PTRS_PER_PGD], __pgd(1 + __pa(pmd)));
+		}
+
+		spin_lock_irqsave(&pgd_lock, flags);
+		for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
+			unsigned long v = (unsigned long)i << PGDIR_SHIFT;
+			pgd_t *kpgd = pgd_offset_k(v);
+			pud_t *kpud = pud_offset(kpgd, v);
+			pmd_t *kpmd = pmd_offset(kpud, v);
+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
+			memcpy(pmd, kpmd, PAGE_SIZE);
+		}
+		pgd_list_add(pgd);
+		spin_unlock_irqrestore(&pgd_lock, flags);
+	}
+
 	return pgd;
 
 out_oom:
@@ -263,9 +288,23 @@ void pgd_free(pgd_t *pgd)
 	int i;
 
 	/* in the PAE case user pgd entries are overwritten before usage */
-	if (PTRS_PER_PMD > 1)
-		for (i = 0; i < USER_PTRS_PER_PGD; ++i)
-			kmem_cache_free(pmd_cache, (void *)__va(pgd_val(pgd[i])-1));
+	if (PTRS_PER_PMD > 1) {
+		for (i = 0; i < USER_PTRS_PER_PGD; ++i) {
+			pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
+			kmem_cache_free(pmd_cache, pmd);
+		}
+		if (!HAVE_SHARED_KERNEL_PMD) {
+			unsigned long flags;
+			spin_lock_irqsave(&pgd_lock, flags);
+			pgd_list_del(pgd);
+			spin_unlock_irqrestore(&pgd_lock, flags);
+			for (i = USER_PTRS_PER_PGD; i < PTRS_PER_PGD; i++) {
+				pmd_t *pmd = (void *)__va(pgd_val(pgd[i])-1);
+				memset(pmd, 0, PTRS_PER_PMD*sizeof(pmd_t));
+				kmem_cache_free(pmd_cache, pmd);
+			}
+		}
+	}
 	/* in the non-PAE case, free_pgtables() clears user pgd entries */
 	kmem_cache_free(pgd_cache, pgd);
 }
diff -pruN ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-2level-defs.h ./include/asm-i386/pgtable-2level-defs.h
--- ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-2level-defs.h	2006-01-03 03:21:10.000000000 +0000
+++ ./include/asm-i386/pgtable-2level-defs.h	2006-02-02 17:45:14.000000000 +0000
@@ -1,6 +1,8 @@
 #ifndef _I386_PGTABLE_2LEVEL_DEFS_H
 #define _I386_PGTABLE_2LEVEL_DEFS_H
 
+#define HAVE_SHARED_KERNEL_PMD 0
+
 /*
  * traditional i386 two-level paging structure:
  */
diff -pruN ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-3level-defs.h ./include/asm-i386/pgtable-3level-defs.h
--- ../pristine-linux-2.6.16-rc1-git4/include/asm-i386/pgtable-3level-defs.h	2006-01-03 03:21:10.000000000 +0000
+++ ./include/asm-i386/pgtable-3level-defs.h	2006-02-02 17:45:14.000000000 +0000
@@ -1,6 +1,8 @@
 #ifndef _I386_PGTABLE_3LEVEL_DEFS_H
 #define _I386_PGTABLE_3LEVEL_DEFS_H
 
+#define HAVE_SHARED_KERNEL_PMD 1
+
 /*
  * PGDIR_SHIFT determines what a top-level page table entry can map
  */