Corrects a (memory) bug of the paravirtualization feature in kernel 2.6.25
(which got corrected later in 2.6.29).
Signed-off-by: Alexander Stadler <sa.maillists at univie.ac.at>
------
diff -urN openwrt-8.09/arch/x86/xen/enlighten.c openwrt/arch/x86/xen/enlighten.c
--- a/arch/x86/xen/enlighten.c 2008-09-08 12:20:51.000000000 +0200
+++ b/arch/x86/xen/enlighten.c 2009-04-03 14:27:56.000000000 +0200
@@ -1059,6 +1059,8 @@
.pte_update = paravirt_nop,
.pte_update_defer = paravirt_nop,
+ .pgd_free = paravirt_nop,
+
.alloc_pt = xen_alloc_pt_init,
.release_pt = xen_release_pt_init,
.alloc_pd = xen_alloc_pt_init,
diff -urN openwrt-8.09/arch/x86/kernel/paravirt.c
openwrt/arch/x86/kernel/paravirt.c
--- a/arch/x86/kernel/paravirt.c 2008-09-08 12:20:51.000000000 +0200
+++ b/arch/x86/kernel/paravirt.c 2009-04-03 14:27:56.000000000 +0200
@@ -382,6 +382,8 @@
.flush_tlb_single = native_flush_tlb_single,
.flush_tlb_others = native_flush_tlb_others,
+ .pgd_free = paravirt_nop,
+
.alloc_pt = paravirt_nop,
.alloc_pd = paravirt_nop,
.alloc_pd_clone = paravirt_nop,
diff -urN openwrt-8.09/include/asm-x86/paravirt.h
openwrt/include/asm-x86/paravirt.h
--- a/include/asm-x86/paravirt.h 2008-09-08 12:20:51.000000000 +0200
+++ b/include/asm-x86/paravirt.h 2009-04-03 14:27:56.000000000 +0200
@@ -219,6 +219,9 @@
void (*flush_tlb_others)(const cpumask_t *cpus, struct mm_struct *mm,
unsigned long va);
+ /* Hook for freeing a pagetable top-level */
+ void (*pgd_free) (struct mm_struct *mm, pgd_t *pgd);
+
/* Hooks for allocating/releasing pagetable pages */
void (*alloc_pt)(struct mm_struct *mm, u32 pfn);
void (*alloc_pd)(struct mm_struct *mm, u32 pfn);
@@ -894,6 +897,11 @@
PVOP_VCALL3(pv_mmu_ops.flush_tlb_others, &cpumask, mm, va);
}
+static inline void paravirt_pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ PVOP_VCALL2(pv_mmu_ops.pgd_free, mm, pgd);
+}
+
static inline void paravirt_alloc_pt(struct mm_struct *mm, unsigned pfn)
{
PVOP_VCALL2(pv_mmu_ops.alloc_pt, mm, pfn);
diff -urN openwrt-8.09/include/asm-x86/pgalloc_32.h
openwrt/include/asm-x86/pgalloc_32.h
--- a/include/asm-x86/pgalloc_32.h 2008-09-08 12:20:51.000000000 +0200
+++ b/include/asm-x86/pgalloc_32.h 2009-04-03 14:27:56.000000000 +0200
@@ -13,6 +13,7 @@
#define paravirt_alloc_pt(mm, pfn) do { } while (0)
#define paravirt_alloc_pd(mm, pfn) do { } while (0)
#define paravirt_alloc_pd_clone(pfn, clonepfn, start, count) do { } while (0)
+#define paravirt_pgd_free(mm, pgd) do { } while (0)
#define paravirt_release_pt(pfn) do { } while (0)
#define paravirt_release_pd(pfn) do { } while (0)
#endif
diff -urN openwrt-8.09/arch/x86/mm/pgtable_32.c openwrt/arch/x86/mm/pgtable_32.c
--- a/arch/x86/mm/pgtable_32.c 2008-09-08 12:20:51.000000000 +0200
+++ b/arch/x86/mm/pgtable_32.c 2009-04-03 14:27:56.000000000 +0200
@@ -351,6 +351,7 @@
if (pgd && !pgd_prepopulate_pmd(mm, pgd)) {
pgd_dtor(pgd);
+ paravirt_pgd_free(mm, pgd);
free_page((unsigned long)pgd);
pgd = NULL;
}
@@ -362,6 +363,7 @@
{
pgd_mop_up_pmds(mm, pgd);
pgd_dtor(pgd);
+ paravirt_pgd_free(mm, pgd);
free_page((unsigned long)pgd);
}
diff -urN openwrt-8.09/arch/x86/kernel/vmi_32.c openwrt/arch/x86/kernel/vmi_32.c
--- a/arch/x86/kernel/vmi_32.c 2008-09-08 12:20:51.000000000 +0200
+++ b/arch/x86/kernel/vmi_32.c 2009-04-03 14:27:56.000000000 +0200
@@ -428,6 +428,16 @@
vmi_set_page_type(pfn, VMI_PAGE_NORMAL);
}
+/*
+ * We use the pgd_free hook for releasing the pgd page:
+ */
+static void vmi_pgd_free(struct mm_struct *mm, pgd_t *pgd)
+{
+ unsigned long pfn = __pa(pgd) >> PAGE_SHIFT;
+
+ vmi_ops.release_page(pfn, VMI_PAGE_L2);
+}
+
/*
* Helper macros for MMU update flags. We can defer updates until a flush
* or page invalidation only if the update is to the current address space
@@ -880,6 +890,7 @@
if (vmi_ops.release_page) {
pv_mmu_ops.release_pt = vmi_release_pt;
pv_mmu_ops.release_pd = vmi_release_pd;
+ pv_mmu_ops.pgd_free = vmi_pgd_free;
}
/* Set linear is needed in all cases */
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel