x86-64: don't use xmalloc_array() for allocation of the (per-CPU) IDTs
authorJan Beulich <jbeulich@suse.com>
Thu, 13 Oct 2011 08:02:34 +0000 (10:02 +0200)
committerJan Beulich <jbeulich@suse.com>
Thu, 13 Oct 2011 08:02:34 +0000 (10:02 +0200)
The IDTs being exactly a page in size, using xmalloc() here is rather
inefficient, as this requires double the amount to be allocated (with
almost an entire page wasted). For hot plugged CPUs, this at once
eliminates one more non-order-zero runtime allocation.

For x86-32, however, the IDT is exactly half a page, so allocating a
full page seems wasteful here, so it continues to use xmalloc() as
before.

With most of the affected functions' bodies now being inside #ifdef-s,
it might be reasonable to split those parts out into subarch-specific
code...

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Acked-by: Keir Fraser <keir@xen.org>
xen/arch/x86/smpboot.c

index b49edb509a38979251deadc39a874ae08f1f324b..6dd3b34959f337f9a498eacec3a5bd833d899ff9 100644 (file)
@@ -639,9 +639,6 @@ static void cpu_smpboot_free(unsigned int cpu)
 {
     unsigned int order;
 
-    xfree(idt_tables[cpu]);
-    idt_tables[cpu] = NULL;
-
     order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
 #ifdef __x86_64__
     if ( per_cpu(compat_gdt_table, cpu) )
@@ -650,10 +647,15 @@ static void cpu_smpboot_free(unsigned int cpu)
         free_domheap_pages(virt_to_page(per_cpu(compat_gdt_table, cpu)),
                            order);
     per_cpu(compat_gdt_table, cpu) = NULL;
+    order = get_order_from_bytes(IDT_ENTRIES * sizeof(**idt_tables));
+    if ( idt_tables[cpu] )
+        free_domheap_pages(virt_to_page(idt_tables[cpu]), order);
 #else
     free_xenheap_pages(per_cpu(gdt_table, cpu), order);
+    xfree(idt_tables[cpu]);
 #endif
     per_cpu(gdt_table, cpu) = NULL;
+    idt_tables[cpu] = NULL;
 
     if ( stack_base[cpu] != NULL )
     {
@@ -691,19 +693,25 @@ static int cpu_smpboot_alloc(unsigned int cpu)
     if ( !page )
         goto oom;
     per_cpu(gdt_table, cpu) = gdt = page_to_virt(page);
+    order = get_order_from_bytes(IDT_ENTRIES * sizeof(**idt_tables));
+    page = alloc_domheap_pages(NULL, order,
+                               MEMF_node(cpu_to_node(cpu)));
+    if ( !page )
+        goto oom;
+    idt_tables[cpu] = page_to_virt(page);
 #else
     per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(order, 0);
     if ( !gdt )
         goto oom;
+    idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES);
+    if ( idt_tables[cpu] == NULL )
+        goto oom;
 #endif
     memcpy(gdt, boot_cpu_gdt_table,
            NR_RESERVED_GDT_PAGES * PAGE_SIZE);
     BUILD_BUG_ON(NR_CPUS > 0x10000);
     gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
 
-    idt_tables[cpu] = xmalloc_array(idt_entry_t, IDT_ENTRIES);
-    if ( idt_tables[cpu] == NULL )
-        goto oom;
     memcpy(idt_tables[cpu], idt_table,
            IDT_ENTRIES*sizeof(idt_entry_t));