[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 |