aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZachary Amsden <zach@vmware.com>2005-09-03 18:56:50 -0400
committerLinus Torvalds <torvalds@evo.osdl.org>2005-09-05 03:06:13 -0400
commitd7271b14b2e9e5905aba0fbf5c4dc4f8980c0cb2 (patch)
tree2e8bb68bb2501be464a4eda66c323978c2d9bb70
parent748f2edb52712aa3d926470a888608dc500d17e8 (diff)
[PATCH] i386: encapsulate copying of pgd entries
Add a clone operation for pgd updates. This helps complete the encapsulation of updates to page tables (or pages about to become page tables) into accessor functions rather than using memcpy() to duplicate them. This is both generally good for consistency and also necessary for running in a hypervisor which requires explicit updates to page table entries. The new function is: clone_pgd_range(pgd_t *dst, pgd_t *src, int count); dst - pointer to pgd range anwhere on a pgd page src - "" count - the number of pgds to copy. dst and src can be on the same page, but the range must not overlap and must not cross a page boundary. Note that I ommitted using this call to copy pgd entries into the software suspend page root, since this is not technically a live paging structure, rather it is used on resume from suspend. CC'ing Pavel in case he has any feedback on this. Thanks to Chris Wright for noticing that this could be more optimal in PAE compiles by eliminating the memset. Signed-off-by: Zachary Amsden <zach@vmware.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--arch/i386/kernel/smpboot.c4
-rw-r--r--arch/i386/mm/pgtable.c10
-rw-r--r--include/asm-i386/pgtable.h15
3 files changed, 22 insertions, 7 deletions
diff --git a/arch/i386/kernel/smpboot.c b/arch/i386/kernel/smpboot.c
index 8ac8e9fd5614..8e950cdff1a0 100644
--- a/arch/i386/kernel/smpboot.c
+++ b/arch/i386/kernel/smpboot.c
@@ -1017,8 +1017,8 @@ int __devinit smp_prepare_cpu(int cpu)
1017 tsc_sync_disabled = 1; 1017 tsc_sync_disabled = 1;
1018 1018
1019 /* init low mem mapping */ 1019 /* init low mem mapping */
1020 memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS, 1020 clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
1021 sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS); 1021 KERNEL_PGD_PTRS);
1022 flush_tlb_all(); 1022 flush_tlb_all();
1023 schedule_work(&task); 1023 schedule_work(&task);
1024 wait_for_completion(&done); 1024 wait_for_completion(&done);
diff --git a/arch/i386/mm/pgtable.c b/arch/i386/mm/pgtable.c
index bd2f7afc7a2a..dcdce2c6c532 100644
--- a/arch/i386/mm/pgtable.c
+++ b/arch/i386/mm/pgtable.c
@@ -207,19 +207,19 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
207{ 207{
208 unsigned long flags; 208 unsigned long flags;
209 209
210 if (PTRS_PER_PMD == 1) 210 if (PTRS_PER_PMD == 1) {
211 memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
211 spin_lock_irqsave(&pgd_lock, flags); 212 spin_lock_irqsave(&pgd_lock, flags);
213 }
212 214
213 memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD, 215 clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
214 swapper_pg_dir + USER_PTRS_PER_PGD, 216 swapper_pg_dir + USER_PTRS_PER_PGD,
215 (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t)); 217 KERNEL_PGD_PTRS);
216
217 if (PTRS_PER_PMD > 1) 218 if (PTRS_PER_PMD > 1)
218 return; 219 return;
219 220
220 pgd_list_add(pgd); 221 pgd_list_add(pgd);
221 spin_unlock_irqrestore(&pgd_lock, flags); 222 spin_unlock_irqrestore(&pgd_lock, flags);
222 memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
223} 223}
224 224
225/* never called when PTRS_PER_PMD > 1 */ 225/* never called when PTRS_PER_PMD > 1 */
diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h
index d74185aee15b..47bc1ffa3d4c 100644
--- a/include/asm-i386/pgtable.h
+++ b/include/asm-i386/pgtable.h
@@ -278,6 +278,21 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
278} 278}
279 279
280/* 280/*
281 * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
282 *
283 * dst - pointer to pgd range anwhere on a pgd page
284 * src - ""
285 * count - the number of pgds to copy.
286 *
287 * dst and src can be on the same page, but the range must not overlap,
288 * and must not cross a page boundary.
289 */
290static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
291{
292 memcpy(dst, src, count * sizeof(pgd_t));
293}
294
295/*
281 * Macro to mark a page protection value as "uncacheable". On processors which do not support 296 * Macro to mark a page protection value as "uncacheable". On processors which do not support
282 * it, this is a no-op. 297 * it, this is a no-op.
283 */ 298 */