Skip to content

Commit

Permalink
[PATCH] i386: encapsulate copying of pgd entries
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Zachary Amsden authored and Linus Torvalds committed Sep 5, 2005
1 parent 748f2ed commit d7271b1
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 7 deletions.
4 changes: 2 additions & 2 deletions arch/i386/kernel/smpboot.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,8 +1017,8 @@ int __devinit smp_prepare_cpu(int cpu)
tsc_sync_disabled = 1;

/* init low mem mapping */
memcpy(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
sizeof(swapper_pg_dir[0]) * KERNEL_PGD_PTRS);
clone_pgd_range(swapper_pg_dir, swapper_pg_dir + USER_PGD_PTRS,
KERNEL_PGD_PTRS);
flush_tlb_all();
schedule_work(&task);
wait_for_completion(&done);
Expand Down
10 changes: 5 additions & 5 deletions arch/i386/mm/pgtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,19 +207,19 @@ void pgd_ctor(void *pgd, kmem_cache_t *cache, unsigned long unused)
{
unsigned long flags;

if (PTRS_PER_PMD == 1)
if (PTRS_PER_PMD == 1) {
memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
spin_lock_irqsave(&pgd_lock, flags);
}

memcpy((pgd_t *)pgd + USER_PTRS_PER_PGD,
clone_pgd_range((pgd_t *)pgd + USER_PTRS_PER_PGD,
swapper_pg_dir + USER_PTRS_PER_PGD,
(PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));

KERNEL_PGD_PTRS);
if (PTRS_PER_PMD > 1)
return;

pgd_list_add(pgd);
spin_unlock_irqrestore(&pgd_lock, flags);
memset(pgd, 0, USER_PTRS_PER_PGD*sizeof(pgd_t));
}

/* never called when PTRS_PER_PMD > 1 */
Expand Down
15 changes: 15 additions & 0 deletions include/asm-i386/pgtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,21 @@ static inline void ptep_set_wrprotect(struct mm_struct *mm, unsigned long addr,
clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
}

/*
* 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.
*/
static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
{
memcpy(dst, src, count * sizeof(pgd_t));
}

/*
* Macro to mark a page protection value as "uncacheable". On processors which do not support
* it, this is a no-op.
Expand Down

0 comments on commit d7271b1

Please sign in to comment.