From: "Jan Beulich" Subject: [PATCH] x86: reduce GDT switching Date: Wed, 12 Nov 2008 09:31:33 +0000 Message-ID: <491AB085.76E4.0078.0@novell.com> Mime-Version: 1.0 Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Return-path: Content-Disposition: inline List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xensource.com Errors-To: xen-devel-bounces@lists.xensource.com To: xen-devel@lists.xensource.com List-Id: xen-devel@lists.xenproject.org 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 Index: 2008-10-27/xen/arch/x86/cpu/common.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/cpu/common.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/cpu/common.c 2008-11-11 11:31:18.0000000= 00 +0100 @@ -564,7 +564,10 @@ void __cpuinit cpu_init(void) { int cpu =3D smp_processor_id(); struct tss_struct *t =3D &init_tss[cpu]; - char gdt_load[10]; + struct desc_ptr gdt_desc =3D { + .base =3D (unsigned long)(this_cpu(gdt_table) - FIRST_RESER= VED_GDT_ENTRY), + .limit =3D LAST_RESERVED_GDT_BYTE + }; =20 if (cpu_test_and_set(cpu, cpu_initialized)) { printk(KERN_WARNING "CPU#%d already initialized!\n", cpu); @@ -578,9 +581,7 @@ void __cpuinit cpu_init(void) /* Install correct page table. */ write_ptbase(current); =20 - *(unsigned short *)(&gdt_load[0]) =3D LAST_RESERVED_GDT_BYTE; - *(unsigned long *)(&gdt_load[2]) =3D GDT_VIRT_START(current); - asm volatile ( "lgdt %0" : "=3Dm" (gdt_load) ); + asm volatile ( "lgdt %0" : : "m" (gdt_desc) ); =20 /* No nested task. */ asm volatile ("pushf ; andw $0xbfff,(%"__OP"sp) ; popf" ); Index: 2008-10-27/xen/arch/x86/domain.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/domain.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/domain.c 2008-11-11 12:20:44.000000000 = +0100 @@ -309,12 +309,7 @@ int vcpu_initialise(struct vcpu *v) if ( is_idle_domain(d) ) { v->arch.schedule_tail =3D continue_idle_domain; - if ( v->vcpu_id ) - v->arch.cr3 =3D d->vcpu[0]->arch.cr3; - else if ( !*idle_vcpu ) - v->arch.cr3 =3D __pa(idle_pg_table); - else if ( !(v->arch.cr3 =3D clone_idle_pagetable(v)) ) - return -ENOMEM; + v->arch.cr3 =3D __pa(idle_pg_table); } =20 v->arch.guest_context.ctrlreg[4] =3D @@ -1171,14 +1166,18 @@ static void paravirt_ctxt_switch_to(stru } } =20 +static inline int need_full_gdt(struct vcpu *v) +{ + return !is_hvm_vcpu(v) && !is_idle_vcpu(v); +} + static void __context_switch(void) { struct cpu_user_regs *stack_regs =3D guest_cpu_user_regs(); - unsigned int i, cpu =3D smp_processor_id(); + unsigned int cpu =3D smp_processor_id(); struct vcpu *p =3D per_cpu(curr_vcpu, cpu); struct vcpu *n =3D current; struct desc_struct *gdt; - struct page_info *page; struct desc_ptr gdt_desc; =20 ASSERT(p !=3D n); @@ -1207,16 +1206,21 @@ static void __context_switch(void) =20 gdt =3D !is_pv_32on64_vcpu(n) ? per_cpu(gdt_table, cpu) : per_cpu(compat_gdt_table, cpu); - page =3D virt_to_page(gdt); - for (i =3D 0; i < NR_RESERVED_GDT_PAGES; ++i) + if ( need_full_gdt(n) ) { - l1e_write(n->domain->arch.mm_perdomain_pt + - (n->vcpu_id << GDT_LDT_VCPU_SHIFT) + - FIRST_RESERVED_GDT_PAGE + i, - l1e_from_page(page + i, __PAGE_HYPERVISOR)); + struct page_info *page =3D virt_to_page(gdt); + unsigned int i; + + for (i =3D 0; i < NR_RESERVED_GDT_PAGES; ++i) + { + l1e_write(n->domain->arch.mm_perdomain_pt + + (n->vcpu_id << GDT_LDT_VCPU_SHIFT) + + FIRST_RESERVED_GDT_PAGE + i, + l1e_from_page(page + i, __PAGE_HYPERVISOR)); + } } =20 - if ( p->vcpu_id !=3D n->vcpu_id ) + if ( need_full_gdt(p) && (p->vcpu_id !=3D n->vcpu_id || !need_full_gdt= (n)) ) { gdt_desc.limit =3D LAST_RESERVED_GDT_BYTE; gdt_desc.base =3D (unsigned long)(gdt - FIRST_RESERVED_GDT_ENTRY)= ; @@ -1225,8 +1229,9 @@ static void __context_switch(void) =20 write_ptbase(n); =20 - if ( p->vcpu_id !=3D n->vcpu_id ) + if ( need_full_gdt(n) && (p->vcpu_id !=3D n->vcpu_id || !need_full_gdt= (p)) ) { + gdt_desc.limit =3D LAST_RESERVED_GDT_BYTE; gdt_desc.base =3D GDT_VIRT_START(n); asm volatile ( "lgdt %0" : : "m" (gdt_desc) ); } Index: 2008-10-27/xen/arch/x86/domain_build.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/domain_build.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/domain_build.c 2008-11-11 11:33:52.0000000= 00 +0100 @@ -197,25 +197,13 @@ static void __init process_dom0_ioports_ /* We run on dom0's page tables for the final part of the build process. = */ static void dom0_pt_enter(struct vcpu *v) { - struct desc_ptr gdt_desc =3D { - .limit =3D LAST_RESERVED_GDT_BYTE, - .base =3D (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT= _ENTRY) - }; - - asm volatile ( "lgdt %0" : : "m" (gdt_desc) ); write_ptbase(v); } =20 /* Return to idle domain's page tables. */ static void dom0_pt_exit(void) { - struct desc_ptr gdt_desc =3D { - .limit =3D LAST_RESERVED_GDT_BYTE, - .base =3D GDT_VIRT_START(current) - }; - write_ptbase(current); - asm volatile ( "lgdt %0" : : "m" (gdt_desc) ); } =20 int __init construct_dom0( Index: 2008-10-27/xen/arch/x86/hvm/vmx/vmcs.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/hvm/vmx/vmcs.c 2008-09-23 09:17:27.0000000= 00 +0200 +++ 2008-10-27/xen/arch/x86/hvm/vmx/vmcs.c 2008-11-11 14:15:56.0000000= 00 +0100 @@ -444,6 +444,8 @@ static void vmx_set_host_env(struct vcpu { unsigned int cpu =3D smp_processor_id(); =20 + __vmwrite(HOST_GDTR_BASE, + (unsigned long)(this_cpu(gdt_table) - FIRST_RESERVED_GDT_ENT= RY)); __vmwrite(HOST_IDTR_BASE, (unsigned long)idt_tables[cpu]); =20 __vmwrite(HOST_TR_SELECTOR, TSS_ENTRY << 3); @@ -541,9 +543,6 @@ static int construct_vmcs(struct vcpu *v __vmwrite(IO_BITMAP_A, virt_to_maddr((char *)hvm_io_bitmap + 0)); __vmwrite(IO_BITMAP_B, virt_to_maddr((char *)hvm_io_bitmap + = PAGE_SIZE)); =20 - /* Host GDTR base. */ - __vmwrite(HOST_GDTR_BASE, GDT_VIRT_START(v)); - /* Host data selectors. */ __vmwrite(HOST_SS_SELECTOR, __HYPERVISOR_DS); __vmwrite(HOST_DS_SELECTOR, __HYPERVISOR_DS); Index: 2008-10-27/xen/arch/x86/setup.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/setup.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/setup.c 2008-11-11 11:31:18.000000000 = +0100 @@ -230,7 +230,6 @@ static void __init percpu_init_areas(voi static void __init init_idle_domain(void) { struct domain *idle_domain; - unsigned int i; =20 /* Domain creation requires that scheduler structures are initialised.= */ scheduler_init(); @@ -243,12 +242,6 @@ static void __init init_idle_domain(void idle_vcpu[0] =3D this_cpu(curr_vcpu) =3D current; =20 setup_idle_pagetable(); - - for (i =3D 0; i < NR_RESERVED_GDT_PAGES; ++i) - idle_domain->arch.mm_perdomain_pt[FIRST_RESERVED_GDT_PAGE + i] = =3D - l1e_from_page(virt_to_page(boot_cpu_gdt_table) + i, - __PAGE_HYPERVISOR); - } =20 static void __init srat_detect_node(int cpu) @@ -456,6 +449,7 @@ void __init __start_xen(unsigned long mb parse_video_info(); =20 set_current((struct vcpu *)0xfffff000); /* debug sanity */ + idle_vcpu[0] =3D current; set_processor_id(0); /* needed early, for smp_processor_id() */ if ( cpu_has_efer ) rdmsrl(MSR_EFER, this_cpu(efer)); Index: 2008-10-27/xen/arch/x86/smpboot.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/smpboot.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/smpboot.c 2008-11-11 11:31:18.000000000 = +0100 @@ -821,7 +821,7 @@ static int __devinit do_boot_cpu(int api */ { unsigned long boot_error; - unsigned int i; + unsigned int order; int timeout; unsigned long start_eip; unsigned short nmi_high =3D 0, nmi_low =3D 0; @@ -857,21 +857,21 @@ static int __devinit do_boot_cpu(int api =20 gdt =3D per_cpu(gdt_table, cpu); if (gdt =3D=3D boot_cpu_gdt_table) { - i =3D get_order_from_pages(NR_RESERVED_GDT_PAGES); + order =3D get_order_from_pages(NR_RESERVED_GDT_PAGES); #ifdef __x86_64__ #ifdef CONFIG_COMPAT - page =3D alloc_domheap_pages(NULL, i, + page =3D alloc_domheap_pages(NULL, order, MEMF_node(cpu_to_node(cpu))); per_cpu(compat_gdt_table, cpu) =3D gdt =3D page_to_virt(pag= e); memcpy(gdt, boot_cpu_compat_gdt_table, NR_RESERVED_GDT_PAGES * PAGE_SIZE); gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a =3D = cpu; #endif - page =3D alloc_domheap_pages(NULL, i, + page =3D alloc_domheap_pages(NULL, order, MEMF_node(cpu_to_node(cpu))); per_cpu(gdt_table, cpu) =3D gdt =3D page_to_virt(page); #else - per_cpu(gdt_table, cpu) =3D gdt =3D alloc_xenheap_pages(i);= + per_cpu(gdt_table, cpu) =3D gdt =3D alloc_xenheap_pages(ord= er); #endif memcpy(gdt, boot_cpu_gdt_table, NR_RESERVED_GDT_PAGES * PAGE_SIZE); @@ -879,13 +879,6 @@ static int __devinit do_boot_cpu(int api gdt[PER_CPU_GDT_ENTRY - FIRST_RESERVED_GDT_ENTRY].a =3D = cpu; } =20 - for (i =3D 0; i < NR_RESERVED_GDT_PAGES; ++i) - v->domain->arch.mm_perdomain_pt - [(v->vcpu_id << GDT_LDT_VCPU_SHIFT) + - FIRST_RESERVED_GDT_PAGE + i] - =3D l1e_from_page(virt_to_page(gdt) + i, - __PAGE_HYPERVISOR); - #ifdef __i386__ if (!per_cpu(doublefault_tss, cpu)) { per_cpu(doublefault_tss, cpu) =3D alloc_xenheap_page(); Index: 2008-10-27/xen/arch/x86/x86_32/mm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/x86_32/mm.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/x86_32/mm.c 2008-11-11 11:31:18.000000000 = +0100 @@ -135,30 +135,6 @@ void __init setup_idle_pagetable(void) __PAGE_HYPERVISOR)); } =20 -unsigned long clone_idle_pagetable(struct vcpu *v) -{ - unsigned int i; - struct domain *d =3D v->domain; - l3_pgentry_t *l3_table =3D v->arch.pae_l3_cache.table[0]; - l2_pgentry_t *l2_table =3D alloc_xenheap_page(); - - if ( !l2_table ) - return 0; - - memcpy(l3_table, idle_pg_table, L3_PAGETABLE_ENTRIES * sizeof(*l3_tabl= e)); - l3_table[l3_table_offset(PERDOMAIN_VIRT_START)] =3D - l3e_from_page(virt_to_page(l2_table), _PAGE_PRESENT); - - copy_page(l2_table, idle_pg_table_l2 + - l3_table_offset(PERDOMAIN_VIRT_START) * L2_PAGETABLE_ENTRIES= ); - for ( i =3D 0; i < PDPT_L2_ENTRIES; ++i ) - l2_table[l2_table_offset(PERDOMAIN_VIRT_START) + i] =3D - l2e_from_page(virt_to_page(d->arch.mm_perdomain_pt) + i, - __PAGE_HYPERVISOR); - - return __pa(l3_table); -} - void __init zap_low_mappings(l2_pgentry_t *dom0_l2) { int i; Index: 2008-10-27/xen/arch/x86/x86_64/mm.c =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/arch/x86/x86_64/mm.c 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/arch/x86/x86_64/mm.c 2008-11-11 11:31:18.000000000 = +0100 @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -210,24 +209,6 @@ void __init setup_idle_pagetable(void) __PAGE_HYPERVISOR)); } =20 -unsigned long clone_idle_pagetable(struct vcpu *v) -{ - struct domain *d =3D v->domain; - struct page_info *page =3D alloc_domheap_page(NULL, - MEMF_node(vcpu_to_node(v))= ); - l4_pgentry_t *l4_table =3D page_to_virt(page); - - if ( !page ) - return 0; - - copy_page(l4_table, idle_pg_table); - l4_table[l4_table_offset(PERDOMAIN_VIRT_START)] =3D - l4e_from_page(virt_to_page(d->arch.mm_perdomain_l3), - __PAGE_HYPERVISOR); - - return __pa(l4_table); -} - void __init zap_low_mappings(void) { BUG_ON(num_online_cpus() !=3D 1); Index: 2008-10-27/xen/include/asm-x86/page.h =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D --- 2008-10-27.orig/xen/include/asm-x86/page.h 2008-11-11 13:56:21.0000000= 00 +0100 +++ 2008-10-27/xen/include/asm-x86/page.h 2008-11-11 11:31:18.0000000= 00 +0100 @@ -278,7 +278,6 @@ extern unsigned int m2p_compat_vstart; #endif void paging_init(void); void setup_idle_pagetable(void); -unsigned long clone_idle_pagetable(struct vcpu *); #endif /* !defined(__ASSEMBLY__) */ =20 #define _PAGE_PRESENT 0x001U