|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC 17/44] x86/smp: Infrastructure for allocating and freeing percpu pagetables
Pagetables are allocated and freed along with the other smp datastructures,
and the root of the pagetables is stored in the percpu_mappings variable.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
xen/arch/x86/smpboot.c | 91 ++++++++++++++++++++++++++++++++++++++++++++++
xen/include/asm-x86/page.h | 1 +
xen/include/asm-x86/smp.h | 1 +
3 files changed, 93 insertions(+)
diff --git a/xen/arch/x86/smpboot.c b/xen/arch/x86/smpboot.c
index a855301..1f92831 100644
--- a/xen/arch/x86/smpboot.c
+++ b/xen/arch/x86/smpboot.c
@@ -58,6 +58,7 @@
unsigned long __read_mostly trampoline_phys;
DEFINE_PER_CPU_READ_MOSTLY(paddr_t, percpu_idle_pt);
+DEFINE_PER_CPU_READ_MOSTLY(l4_pgentry_t, percpu_mappings);
/* representing HT siblings of each logical CPU */
DEFINE_PER_CPU_READ_MOSTLY(cpumask_var_t, cpu_sibling_mask);
@@ -644,6 +645,7 @@ static int cpu_smpboot_alloc_common(unsigned int cpu)
unsigned int memflags = 0;
nodeid_t node = cpu_to_node(cpu);
l4_pgentry_t *l4t = NULL;
+ l3_pgentry_t *l3t = NULL;
struct page_info *pg;
int rc = -ENOMEM;
@@ -663,15 +665,103 @@ static int cpu_smpboot_alloc_common(unsigned int cpu)
if ( rc )
goto out;
+ rc = -ENOMEM;
+
+ /* Percpu L3 table, containing the percpu mappings. */
+ pg = alloc_domheap_page(NULL, memflags);
+ if ( !pg )
+ goto out;
+ l3t = __map_domain_page(pg);
+ clear_page(l3t);
+ per_cpu(percpu_mappings, cpu) = l4t[l4_table_offset(PERCPU_LINEAR_START)] =
+ l4e_from_page(pg, __PAGE_HYPERVISOR);
+
rc = 0; /* Success */
out:
+ if ( l3t )
+ unmap_domain_page(l3t);
if ( l4t )
unmap_domain_page(l4t);
return rc;
}
+/*
+ * Dismantles the pagetable structure under per_cpu(percpu_mappings, cpu),
+ * freeing all pagetable frames, and any RAM frames which are mapped with
+ * MAP_PERCPU_AUTOFREE.
+ */
+static void free_perpcpu_pagetables(unsigned int cpu)
+{
+ l4_pgentry_t *percpu_mappings = &per_cpu(percpu_mappings, cpu);
+ unsigned int l3i;
+ l3_pgentry_t *l3t = NULL;
+
+ if ( !l4e_get_intpte(*percpu_mappings) )
+ return;
+
+ l3t = map_domain_page(l4e_get_mfn(*percpu_mappings));
+
+ for ( l3i = 0; l3i < L3_PAGETABLE_ENTRIES; ++l3i )
+ {
+ l3_pgentry_t l3e = l3t[l3i];
+
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+ continue;
+
+ if ( !(l3e_get_flags(l3e) & _PAGE_PSE) )
+ {
+ unsigned int l2i;
+ l2_pgentry_t *l2t = __map_domain_page(l3e_get_page(l3e));
+
+ for ( l2i = 0; l2i < L2_PAGETABLE_ENTRIES; ++l2i )
+ {
+ l2_pgentry_t l2e = l2t[l2i];
+
+ if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ continue;
+
+ if ( !(l2e_get_flags(l2e) & _PAGE_PSE) )
+ {
+ unsigned int l1i;
+ l1_pgentry_t *l1t = __map_domain_page(l2e_get_page(l2e));
+
+ for ( l1i = 0; l1i < L1_PAGETABLE_ENTRIES; ++l1i )
+ {
+ l1_pgentry_t l1e = l1t[l1i];
+
+ if ( !(l1e_get_flags(l1e) & _PAGE_PRESENT) )
+ continue;
+
+ if ( l1e_get_flags(l1e) & MAP_PERCPU_AUTOFREE )
+ {
+ struct page_info *pg = l1e_get_page(l1e);
+
+ if ( is_xen_heap_page(pg) )
+ free_xenheap_page(page_to_virt(pg));
+ else
+ free_domheap_page(pg);
+ }
+ }
+
+ unmap_domain_page(l1t);
+ }
+
+ free_domheap_page(l2e_get_page(l2e));
+ }
+
+ unmap_domain_page(l2t);
+ }
+
+ free_domheap_page(l3e_get_page(l3e));
+ }
+
+ unmap_domain_page(l3t);
+ free_domheap_page(l4e_get_page(*percpu_mappings));
+ *percpu_mappings = l4e_empty();
+}
+
static void cpu_smpboot_free(unsigned int cpu)
{
unsigned int order, socket = cpu_to_socket(cpu);
@@ -733,6 +823,7 @@ static void cpu_smpboot_free(unsigned int cpu)
}
pt_shadow_free(cpu);
+ free_perpcpu_pagetables(cpu);
}
static int cpu_smpboot_alloc(unsigned int cpu)
diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h
index 45ca742..f330c75 100644
--- a/xen/include/asm-x86/page.h
+++ b/xen/include/asm-x86/page.h
@@ -344,6 +344,7 @@ void efi_update_l4_pgtable(unsigned int l4idx,
l4_pgentry_t);
#define __PAGE_HYPERVISOR_UC (__PAGE_HYPERVISOR | _PAGE_PCD | _PAGE_PWT)
#define MAP_SMALL_PAGES _PAGE_AVAIL0 /* don't use superpages mappings */
+#define MAP_PERCPU_AUTOFREE _PAGE_AVAIL1
#ifndef __ASSEMBLY__
diff --git a/xen/include/asm-x86/smp.h b/xen/include/asm-x86/smp.h
index 5fea27d..46bbf0d 100644
--- a/xen/include/asm-x86/smp.h
+++ b/xen/include/asm-x86/smp.h
@@ -20,6 +20,7 @@
#ifndef __ASSEMBLY__
DECLARE_PER_CPU(paddr_t, percpu_idle_pt);
+DECLARE_PER_CPU(l4_pgentry_t, percpu_mappings);
/*
* Private routines/data
--
2.1.4
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |