ia64/xen-unstable

changeset 18790:8e18dd41c6c7

x86: reduce GDT switching

Both idle and HVM vCPU-s can easily run on the GDT mapped into general
hypervisor space (rather than that placed in per-vCPU virtual space).

This makes unnecessary some of the additions c/s 18520 did.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 12 12:01:35 2008 +0000 (2008-11-12)
parents 2bd99c5faa42
children 8de4b4e9a435
files xen/arch/x86/cpu/common.c xen/arch/x86/domain.c xen/arch/x86/domain_build.c xen/arch/x86/hvm/vmx/vmcs.c xen/arch/x86/setup.c xen/arch/x86/smpboot.c xen/arch/x86/x86_32/mm.c xen/arch/x86/x86_64/mm.c xen/include/asm-x86/page.h
line diff
     1.1 --- a/xen/arch/x86/cpu/common.c	Wed Nov 12 11:50:25 2008 +0000
     1.2 +++ b/xen/arch/x86/cpu/common.c	Wed Nov 12 12:01:35 2008 +0000
     1.3 @@ -564,7 +564,10 @@ void __cpuinit cpu_init(void)
     1.4  {
     1.5  	int cpu = smp_processor_id();
     1.6  	struct tss_struct *t = &init_tss[cpu];
     1.7 -	char gdt_load[10];
     1.8 +	struct desc_ptr gdt_desc = {
     1.9 +		.base = (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY),
    1.10 +		.limit = LAST_RESERVED_GDT_BYTE
    1.11 +	};
    1.12  
    1.13  	if (cpu_test_and_set(cpu, cpu_initialized)) {
    1.14  		printk(KERN_WARNING "CPU#%d already initialized!\n", cpu);
    1.15 @@ -578,9 +581,7 @@ void __cpuinit cpu_init(void)
    1.16  	/* Install correct page table. */
    1.17  	write_ptbase(current);
    1.18  
    1.19 -	*(unsigned short *)(&gdt_load[0]) = LAST_RESERVED_GDT_BYTE;
    1.20 -	*(unsigned long  *)(&gdt_load[2]) = GDT_VIRT_START(current);
    1.21 -	asm volatile ( "lgdt %0" : "=m" (gdt_load) );
    1.22 +	asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
    1.23  
    1.24  	/* No nested task. */
    1.25  	asm volatile ("pushf ; andw $0xbfff,(%"__OP"sp) ; popf" );
     2.1 --- a/xen/arch/x86/domain.c	Wed Nov 12 11:50:25 2008 +0000
     2.2 +++ b/xen/arch/x86/domain.c	Wed Nov 12 12:01:35 2008 +0000
     2.3 @@ -310,12 +310,7 @@ int vcpu_initialise(struct vcpu *v)
     2.4          if ( is_idle_domain(d) )
     2.5          {
     2.6              v->arch.schedule_tail = continue_idle_domain;
     2.7 -            if ( v->vcpu_id )
     2.8 -                v->arch.cr3 = d->vcpu[0]->arch.cr3;
     2.9 -            else if ( !*idle_vcpu )
    2.10 -                v->arch.cr3 = __pa(idle_pg_table);
    2.11 -            else if ( !(v->arch.cr3 = clone_idle_pagetable(v)) )
    2.12 -                return -ENOMEM;
    2.13 +            v->arch.cr3           = __pa(idle_pg_table);
    2.14          }
    2.15  
    2.16          v->arch.guest_context.ctrlreg[4] =
    2.17 @@ -1172,14 +1167,18 @@ static void paravirt_ctxt_switch_to(stru
    2.18      }
    2.19  }
    2.20  
    2.21 +static inline int need_full_gdt(struct vcpu *v)
    2.22 +{
    2.23 +    return (!is_hvm_vcpu(v) && !is_idle_vcpu(v));
    2.24 +}
    2.25 +
    2.26  static void __context_switch(void)
    2.27  {
    2.28      struct cpu_user_regs *stack_regs = guest_cpu_user_regs();
    2.29 -    unsigned int          i, cpu = smp_processor_id();
    2.30 +    unsigned int          cpu = smp_processor_id();
    2.31      struct vcpu          *p = per_cpu(curr_vcpu, cpu);
    2.32      struct vcpu          *n = current;
    2.33      struct desc_struct   *gdt;
    2.34 -    struct page_info     *page;
    2.35      struct desc_ptr       gdt_desc;
    2.36  
    2.37      ASSERT(p != n);
    2.38 @@ -1208,16 +1207,19 @@ static void __context_switch(void)
    2.39  
    2.40      gdt = !is_pv_32on64_vcpu(n) ? per_cpu(gdt_table, cpu) :
    2.41                                    per_cpu(compat_gdt_table, cpu);
    2.42 -    page = virt_to_page(gdt);
    2.43 -    for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
    2.44 +    if ( need_full_gdt(n) )
    2.45      {
    2.46 -        l1e_write(n->domain->arch.mm_perdomain_pt +
    2.47 -                  (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
    2.48 -                  FIRST_RESERVED_GDT_PAGE + i,
    2.49 -                  l1e_from_page(page + i, __PAGE_HYPERVISOR));
    2.50 +        struct page_info *page = virt_to_page(gdt);
    2.51 +        unsigned int i;
    2.52 +        for ( i = 0; i < NR_RESERVED_GDT_PAGES; i++ )
    2.53 +            l1e_write(n->domain->arch.mm_perdomain_pt +
    2.54 +                      (n->vcpu_id << GDT_LDT_VCPU_SHIFT) +
    2.55 +                      FIRST_RESERVED_GDT_PAGE + i,
    2.56 +                      l1e_from_page(page + i, __PAGE_HYPERVISOR));
    2.57      }
    2.58  
    2.59 -    if ( p->vcpu_id != n->vcpu_id )
    2.60 +    if ( need_full_gdt(p) &&
    2.61 +         ((p->vcpu_id != n->vcpu_id) || !need_full_gdt(n)) )
    2.62      {
    2.63          gdt_desc.limit = LAST_RESERVED_GDT_BYTE;
    2.64          gdt_desc.base  = (unsigned long)(gdt - FIRST_RESERVED_GDT_ENTRY);
    2.65 @@ -1226,8 +1228,10 @@ static void __context_switch(void)
    2.66  
    2.67      write_ptbase(n);
    2.68  
    2.69 -    if ( p->vcpu_id != n->vcpu_id )
    2.70 +    if ( need_full_gdt(n) &&
    2.71 +         ((p->vcpu_id != n->vcpu_id) || !need_full_gdt(p)) )
    2.72      {
    2.73 +        gdt_desc.limit = LAST_RESERVED_GDT_BYTE;
    2.74          gdt_desc.base = GDT_VIRT_START(n);
    2.75          asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
    2.76      }
     3.1 --- a/xen/arch/x86/domain_build.c	Wed Nov 12 11:50:25 2008 +0000
     3.2 +++ b/xen/arch/x86/domain_build.c	Wed Nov 12 12:01:35 2008 +0000
     3.3 @@ -194,30 +194,6 @@ static void __init process_dom0_ioports_
     3.4      }
     3.5  }
     3.6  
     3.7 -/* We run on dom0's page tables for the final part of the build process. */
     3.8 -static void dom0_pt_enter(struct vcpu *v)
     3.9 -{
    3.10 -    struct desc_ptr gdt_desc = {
    3.11 -        .limit = LAST_RESERVED_GDT_BYTE,
    3.12 -        .base = (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY)
    3.13 -    };
    3.14 -
    3.15 -    asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
    3.16 -    write_ptbase(v);
    3.17 -}
    3.18 -
    3.19 -/* Return to idle domain's page tables. */
    3.20 -static void dom0_pt_exit(void)
    3.21 -{
    3.22 -    struct desc_ptr gdt_desc = {
    3.23 -        .limit = LAST_RESERVED_GDT_BYTE,
    3.24 -        .base = GDT_VIRT_START(current)
    3.25 -    };
    3.26 -
    3.27 -    write_ptbase(current);
    3.28 -    asm volatile ( "lgdt %0" : : "m" (gdt_desc) );
    3.29 -}
    3.30 -
    3.31  int __init construct_dom0(
    3.32      struct domain *d,
    3.33      unsigned long _image_start, unsigned long image_len, 
    3.34 @@ -729,7 +705,8 @@ int __init construct_dom0(
    3.35      else
    3.36          update_cr3(v);
    3.37  
    3.38 -    dom0_pt_enter(v);
    3.39 +    /* We run on dom0's page tables for the final part of the build process. */
    3.40 +    write_ptbase(v);
    3.41  
    3.42      /* Copy the OS image and free temporary buffer. */
    3.43      elf.dest = (void*)vkern_start;
    3.44 @@ -741,11 +718,11 @@ int __init construct_dom0(
    3.45               (parms.virt_hypercall >= v_end) )
    3.46          {
    3.47              write_ptbase(current);
    3.48 -            local_irq_enable();
    3.49              printk("Invalid HYPERCALL_PAGE field in ELF notes.\n");
    3.50              return -1;
    3.51          }
    3.52 -        hypercall_page_initialise(d, (void *)(unsigned long)parms.virt_hypercall);
    3.53 +        hypercall_page_initialise(
    3.54 +            d, (void *)(unsigned long)parms.virt_hypercall);
    3.55      }
    3.56  
    3.57      /* Copy the initial ramdisk. */
    3.58 @@ -826,7 +803,8 @@ int __init construct_dom0(
    3.59          xlat_start_info(si, XLAT_start_info_console_dom0);
    3.60  #endif
    3.61  
    3.62 -    dom0_pt_exit();
    3.63 +    /* Return to idle domain's page tables. */
    3.64 +    write_ptbase(current);
    3.65  
    3.66  #if defined(__i386__)
    3.67      /* Destroy low mappings - they were only for our convenience. */
     4.1 --- a/xen/arch/x86/hvm/vmx/vmcs.c	Wed Nov 12 11:50:25 2008 +0000
     4.2 +++ b/xen/arch/x86/hvm/vmx/vmcs.c	Wed Nov 12 12:01:35 2008 +0000
     4.3 @@ -444,6 +444,8 @@ static void vmx_set_host_env(struct vcpu
     4.4  {
     4.5      unsigned int cpu = smp_processor_id();
     4.6  
     4.7 +    __vmwrite(HOST_GDTR_BASE,
     4.8 +              (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENTRY));
     4.9      __vmwrite(HOST_IDTR_BASE, (unsigned long)idt_tables[cpu]);
    4.10  
    4.11      __vmwrite(HOST_TR_SELECTOR, TSS_ENTRY << 3);
    4.12 @@ -541,9 +543,6 @@ static int construct_vmcs(struct vcpu *v
    4.13      __vmwrite(IO_BITMAP_A, virt_to_maddr((char *)hvm_io_bitmap + 0));
    4.14      __vmwrite(IO_BITMAP_B, virt_to_maddr((char *)hvm_io_bitmap + PAGE_SIZE));
    4.15  
    4.16 -    /* Host GDTR base. */
    4.17 -    __vmwrite(HOST_GDTR_BASE, GDT_VIRT_START(v));
    4.18 -
    4.19      /* Host data selectors. */
    4.20      __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS);
    4.21      __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS);
     5.1 --- a/xen/arch/x86/setup.c	Wed Nov 12 11:50:25 2008 +0000
     5.2 +++ b/xen/arch/x86/setup.c	Wed Nov 12 12:01:35 2008 +0000
     5.3 @@ -230,7 +230,6 @@ static void __init percpu_init_areas(voi
     5.4  static void __init init_idle_domain(void)
     5.5  {
     5.6      struct domain *idle_domain;
     5.7 -    unsigned int i;
     5.8  
     5.9      /* Domain creation requires that scheduler structures are initialised. */
    5.10      scheduler_init();
    5.11 @@ -243,12 +242,6 @@ static void __init init_idle_domain(void
    5.12      idle_vcpu[0] = this_cpu(curr_vcpu) = current;
    5.13  
    5.14      setup_idle_pagetable();
    5.15 -
    5.16 -    for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
    5.17 -        idle_domain->arch.mm_perdomain_pt[FIRST_RESERVED_GDT_PAGE + i] =
    5.18 -            l1e_from_page(virt_to_page(boot_cpu_gdt_table) + i,
    5.19 -                          __PAGE_HYPERVISOR);
    5.20 -
    5.21  }
    5.22  
    5.23  static void __init srat_detect_node(int cpu)
    5.24 @@ -456,6 +449,7 @@ void __init __start_xen(unsigned long mb
    5.25      parse_video_info();
    5.26  
    5.27      set_current((struct vcpu *)0xfffff000); /* debug sanity */
    5.28 +    idle_vcpu[0] = current;
    5.29      set_processor_id(0); /* needed early, for smp_processor_id() */
    5.30      if ( cpu_has_efer )
    5.31          rdmsrl(MSR_EFER, this_cpu(efer));
     6.1 --- a/xen/arch/x86/smpboot.c	Wed Nov 12 11:50:25 2008 +0000
     6.2 +++ b/xen/arch/x86/smpboot.c	Wed Nov 12 12:01:35 2008 +0000
     6.3 @@ -821,7 +821,7 @@ static int __devinit do_boot_cpu(int api
     6.4   */
     6.5  {
     6.6  	unsigned long boot_error;
     6.7 -	unsigned int i;
     6.8 +	unsigned int order;
     6.9  	int timeout;
    6.10  	unsigned long start_eip;
    6.11  	unsigned short nmi_high = 0, nmi_low = 0;
    6.12 @@ -857,21 +857,21 @@ static int __devinit do_boot_cpu(int api
    6.13  
    6.14  	gdt = per_cpu(gdt_table, cpu);
    6.15  	if (gdt == boot_cpu_gdt_table) {
    6.16 -		i = get_order_from_pages(NR_RESERVED_GDT_PAGES);
    6.17 +		order = get_order_from_pages(NR_RESERVED_GDT_PAGES);
    6.18  #ifdef __x86_64__
    6.19  #ifdef CONFIG_COMPAT
    6.20 -		page = alloc_domheap_pages(NULL, i,
    6.21 +		page = alloc_domheap_pages(NULL, order,
    6.22  					   MEMF_node(cpu_to_node(cpu)));
    6.23  		per_cpu(compat_gdt_table, cpu) = gdt = page_to_virt(page);
    6.24  		memcpy(gdt, boot_cpu_compat_gdt_table,
    6.25  		       NR_RESERVED_GDT_PAGES * PAGE_SIZE);
    6.26  		gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
    6.27  #endif
    6.28 -		page = alloc_domheap_pages(NULL, i,
    6.29 +		page = alloc_domheap_pages(NULL, order,
    6.30  					   MEMF_node(cpu_to_node(cpu)));
    6.31  		per_cpu(gdt_table, cpu) = gdt = page_to_virt(page);
    6.32  #else
    6.33 -		per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(i);
    6.34 +		per_cpu(gdt_table, cpu) = gdt = alloc_xenheap_pages(order);
    6.35  #endif
    6.36  		memcpy(gdt, boot_cpu_gdt_table,
    6.37  		       NR_RESERVED_GDT_PAGES * PAGE_SIZE);
    6.38 @@ -879,13 +879,6 @@ static int __devinit do_boot_cpu(int api
    6.39  		gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a = cpu;
    6.40  	}
    6.41  
    6.42 -	for (i = 0; i < NR_RESERVED_GDT_PAGES; ++i)
    6.43 -		v->domain->arch.mm_perdomain_pt
    6.44 -			[(v->vcpu_id << GDT_LDT_VCPU_SHIFT) +
    6.45 -			 FIRST_RESERVED_GDT_PAGE + i]
    6.46 -			= l1e_from_page(virt_to_page(gdt) + i,
    6.47 -					__PAGE_HYPERVISOR);
    6.48 -
    6.49  #ifdef __i386__
    6.50  	if (!per_cpu(doublefault_tss, cpu)) {
    6.51  		per_cpu(doublefault_tss, cpu) = alloc_xenheap_page();
     7.1 --- a/xen/arch/x86/x86_32/mm.c	Wed Nov 12 11:50:25 2008 +0000
     7.2 +++ b/xen/arch/x86/x86_32/mm.c	Wed Nov 12 12:01:35 2008 +0000
     7.3 @@ -132,30 +132,6 @@ void __init setup_idle_pagetable(void)
     7.4                                  __PAGE_HYPERVISOR));
     7.5  }
     7.6  
     7.7 -unsigned long clone_idle_pagetable(struct vcpu *v)
     7.8 -{
     7.9 -    unsigned int i;
    7.10 -    struct domain *d = v->domain;
    7.11 -    l3_pgentry_t *l3_table = v->arch.pae_l3_cache.table[0];
    7.12 -    l2_pgentry_t *l2_table = alloc_xenheap_page();
    7.13 -
    7.14 -    if ( !l2_table )
    7.15 -        return 0;
    7.16 -
    7.17 -    memcpy(l3_table, idle_pg_table, L3_PAGETABLE_ENTRIES * sizeof(*l3_table));
    7.18 -    l3_table[l3_table_offset(PERDOMAIN_VIRT_START)] =
    7.19 -        l3e_from_page(virt_to_page(l2_table), _PAGE_PRESENT);
    7.20 -
    7.21 -    copy_page(l2_table, idle_pg_table_l2 +
    7.22 -              l3_table_offset(PERDOMAIN_VIRT_START) * L2_PAGETABLE_ENTRIES);
    7.23 -    for ( i = 0; i < PDPT_L2_ENTRIES; ++i )
    7.24 -        l2_table[l2_table_offset(PERDOMAIN_VIRT_START) + i] =
    7.25 -            l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i,
    7.26 -                          __PAGE_HYPERVISOR);
    7.27 -
    7.28 -    return __pa(l3_table);
    7.29 -}
    7.30 -
    7.31  void __init zap_low_mappings(l2_pgentry_t *dom0_l2)
    7.32  {
    7.33      int i;
     8.1 --- a/xen/arch/x86/x86_64/mm.c	Wed Nov 12 11:50:25 2008 +0000
     8.2 +++ b/xen/arch/x86/x86_64/mm.c	Wed Nov 12 12:01:35 2008 +0000
     8.3 @@ -21,7 +21,6 @@
     8.4  #include <xen/lib.h>
     8.5  #include <xen/init.h>
     8.6  #include <xen/mm.h>
     8.7 -#include <xen/numa.h>
     8.8  #include <xen/sched.h>
     8.9  #include <xen/guest_access.h>
    8.10  #include <asm/current.h>
    8.11 @@ -207,24 +206,6 @@ void __init setup_idle_pagetable(void)
    8.12                    __PAGE_HYPERVISOR));
    8.13  }
    8.14  
    8.15 -unsigned long clone_idle_pagetable(struct vcpu *v)
    8.16 -{
    8.17 -    struct domain *d = v->domain;
    8.18 -    struct page_info *page = alloc_domheap_page(NULL,
    8.19 -                                                MEMF_node(vcpu_to_node(v)));
    8.20 -    l4_pgentry_t *l4_table = page_to_virt(page);
    8.21 -
    8.22 -    if ( !page )
    8.23 -        return 0;
    8.24 -
    8.25 -    copy_page(l4_table, idle_pg_table);
    8.26 -    l4_table[l4_table_offset(PERDOMAIN_VIRT_START)] =
    8.27 -        l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3),
    8.28 -                      __PAGE_HYPERVISOR);
    8.29 -
    8.30 -    return __pa(l4_table);
    8.31 -}
    8.32 -
    8.33  void __init zap_low_mappings(void)
    8.34  {
    8.35      BUG_ON(num_online_cpus() != 1);
     9.1 --- a/xen/include/asm-x86/page.h	Wed Nov 12 11:50:25 2008 +0000
     9.2 +++ b/xen/include/asm-x86/page.h	Wed Nov 12 12:01:35 2008 +0000
     9.3 @@ -278,7 +278,6 @@ extern unsigned int   m2p_compat_vstart;
     9.4  #endif
     9.5  void paging_init(void);
     9.6  void setup_idle_pagetable(void);
     9.7 -unsigned long clone_idle_pagetable(struct vcpu *);
     9.8  #endif /* !defined(__ASSEMBLY__) */
     9.9  
    9.10  #define _PAGE_PRESENT  0x001U