From c8ce168255631f44852026487da0a133c26ee35c Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 08:48:39 -0700 Subject: [PATCH 01/95] [IA64] Remove VALIDATE_VT code Signed-off-by: Zhang Xin --- xen/arch/ia64/Rules.mk | 4 ---- xen/arch/ia64/linux-xen/head.S | 16 ---------------- xen/arch/ia64/xen/domain.c | 31 ------------------------------- xen/include/asm-ia64/config.h | 4 ---- 4 files changed, 55 deletions(-) diff --git a/xen/arch/ia64/Rules.mk b/xen/arch/ia64/Rules.mk index e63faf67ef..eefd5fe1ab 100644 --- a/xen/arch/ia64/Rules.mk +++ b/xen/arch/ia64/Rules.mk @@ -4,7 +4,6 @@ HAS_ACPI := y HAS_VGA := y xenoprof := y -VALIDATE_VT ?= n no_warns ?= n xen_ia64_expose_p2m ?= y xen_ia64_pervcpu_vhpt ?= y @@ -37,9 +36,6 @@ CFLAGS += -DIA64 -DXEN -DLINUX_2_6 CFLAGS += -ffixed-r13 -mfixed-range=f2-f5,f12-f127 CFLAGS += -g #CFLAGS += -DVTI_DEBUG -ifeq ($(VALIDATE_VT),y) -CFLAGS += -DVALIDATE_VT -endif ifeq ($(xen_ia64_expose_p2m),y) CFLAGS += -DCONFIG_XEN_IA64_EXPOSE_P2M endif diff --git a/xen/arch/ia64/linux-xen/head.S b/xen/arch/ia64/linux-xen/head.S index 22145109da..5c8c60cbb6 100644 --- a/xen/arch/ia64/linux-xen/head.S +++ b/xen/arch/ia64/linux-xen/head.S @@ -267,13 +267,8 @@ start_ap: /* * Switch into virtual mode: */ -#if defined(XEN) && defined(VALIDATE_VT) - movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH\ - |IA64_PSR_DI) -#else movl r16=(IA64_PSR_IT|IA64_PSR_IC|IA64_PSR_DT|IA64_PSR_RT|IA64_PSR_DFH|IA64_PSR_BN \ |IA64_PSR_DI) -#endif ;; mov cr.ipsr=r16 movl r17=1f @@ -292,11 +287,7 @@ start_ap: ;; // set IVT entry point---can't access I/O ports without it -#if defined(XEN) && defined(VALIDATE_VT) - movl r3=vmx_ia64_ivt -#else movl r3=ia64_ivt -#endif ;; mov cr.iva=r3 movl r2=FPSR_DEFAULT @@ -368,15 +359,8 @@ start_ap: .load_current: // load the "current" pointer (r13) and ar.k6 with the current task -#if defined(XEN) && defined(VALIDATE_VT) - mov r21=r2 - ;; - bsw.1 - ;; -#else mov IA64_KR(CURRENT)=r2 // virtual address mov IA64_KR(CURRENT_STACK)=r16 -#endif mov r13=r2 /* * Reserve space at the top of the stack for "struct pt_regs". Kernel diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index f28d2040e0..dc4ead671f 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -996,12 +996,6 @@ int construct_dom0(struct domain *d, unsigned long bp_mpa; struct ia64_boot_param *bp; -#ifdef VALIDATE_VT - unsigned int vmx_dom0 = 0; - unsigned long mfn; - struct page_info *page = NULL; -#endif - //printk("construct_dom0: starting\n"); /* Sanity! */ @@ -1022,23 +1016,6 @@ int construct_dom0(struct domain *d, if ( rc != 0 ) return rc; -#ifdef VALIDATE_VT - /* Temp workaround */ - if (running_on_sim) - dsi.xen_section_string = (char *)1; - - /* Check whether dom0 is vti domain */ - if ((!vmx_enabled) && !dsi.xen_section_string) { - printk("Lack of hardware support for unmodified vmx dom0\n"); - panic(""); - } - - if (vmx_enabled && !dsi.xen_section_string) { - printk("Dom0 is vmx domain!\n"); - vmx_dom0 = 1; - } -#endif - p_start = dsi.v_start; pkern_start = dsi.v_kernstart; pkern_end = dsi.v_kernend; @@ -1132,14 +1109,6 @@ int construct_dom0(struct domain *d, printk("Dom0: 0x%lx\n", (u64)dom0); -#ifdef VALIDATE_VT - /* VMX specific construction for Dom0, if hardware supports VMX - * and Dom0 is unmodified image - */ - if (vmx_dom0) - vmx_final_setup_guest(v); -#endif - set_bit(_VCPUF_initialised, &v->vcpu_flags); /* Build firmware. diff --git a/xen/include/asm-ia64/config.h b/xen/include/asm-ia64/config.h index 063e6e33eb..5010a86e7b 100644 --- a/xen/include/asm-ia64/config.h +++ b/xen/include/asm-ia64/config.h @@ -183,11 +183,7 @@ void sort_main_extable(void); #define find_first_set_bit(x) (ffs(x)-1) // FIXME: Is this right??? // see drivers/char/console.c -#ifndef VALIDATE_VT #define OPT_CONSOLE_STR "com1" -#else -#define OPT_CONSOLE_STR "com2" -#endif #define __nocast From 93dcb1dab57c6d53ff3ab6832cf1f5ed7039dc86 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 09:08:03 -0700 Subject: [PATCH 02/95] [IA64] Avoid dom0 insufficient memory panic when creating guests When there is not enough memory to create a domain, we need not panic domain0. Just prevent it from creating. Signed-off-by: Zhang Xin --- xen/arch/ia64/vmx/vmmu.c | 39 +++++++++++++++++++++++++++--------- xen/arch/ia64/vmx/vmx_init.c | 7 +++++-- xen/arch/ia64/xen/domain.c | 8 +++++--- xen/include/asm-ia64/vmmu.h | 2 +- xen/include/asm-ia64/vmx.h | 2 +- 5 files changed, 42 insertions(+), 16 deletions(-) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index aaf4055674..145cd4c447 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -129,13 +129,15 @@ purge_machine_tc_by_domid(domid_t domid) #endif } -static void init_domain_vhpt(struct vcpu *v) +static int init_domain_vhpt(struct vcpu *v) { struct page_info *page; void * vbase; page = alloc_domheap_pages (NULL, VCPU_VHPT_ORDER, 0); if ( page == NULL ) { - panic_domain(vcpu_regs(v),"No enough contiguous memory for init_domain_vhpt\n"); + printk("No enough contiguous memory for init_domain_vhpt\n"); + + return -1; } vbase = page_to_virt(page); memset(vbase, 0, VCPU_VHPT_SIZE); @@ -147,18 +149,36 @@ static void init_domain_vhpt(struct vcpu *v) VHPT(v,cch_sz) = VCPU_VHPT_SIZE - VHPT(v,hash_sz); thash_init(&(v->arch.vhpt),VCPU_VHPT_SHIFT-1); v->arch.arch_vmx.mpta = v->arch.vhpt.pta.val; + + return 0; } +static void free_domain_vhpt(struct vcpu *v) +{ + struct page_info *page; -void init_domain_tlb(struct vcpu *v) + if (v->arch.vhpt.hash) { + page = virt_to_page(v->arch.vhpt.hash); + free_domheap_pages(page, VCPU_VHPT_ORDER); + } + + return; +} + +int init_domain_tlb(struct vcpu *v) { struct page_info *page; void * vbase; - init_domain_vhpt(v); + + if (init_domain_vhpt(v) != 0) + return -1; + page = alloc_domheap_pages (NULL, VCPU_VTLB_ORDER, 0); if ( page == NULL ) { - panic_domain(vcpu_regs(v),"No enough contiguous memory for init_domain_tlb\n"); + printk("No enough contiguous memory for init_domain_tlb\n"); + free_domain_vhpt(v); + return -1; } vbase = page_to_virt(page); memset(vbase, 0, VCPU_VTLB_SIZE); @@ -169,8 +189,11 @@ void init_domain_tlb(struct vcpu *v) VTLB(v,cch_buf) = (void *)((u64)vbase + VTLB(v,hash_sz)); VTLB(v,cch_sz) = VCPU_VTLB_SIZE - VTLB(v,hash_sz); thash_init(&(v->arch.vtlb),VCPU_VTLB_SHIFT-1); + + return 0; } + void free_domain_tlb(struct vcpu *v) { struct page_info *page; @@ -179,10 +202,8 @@ void free_domain_tlb(struct vcpu *v) page = virt_to_page(v->arch.vtlb.hash); free_domheap_pages(page, VCPU_VTLB_ORDER); } - if ( v->arch.vhpt.hash) { - page = virt_to_page(v->arch.vhpt.hash); - free_domheap_pages(page, VCPU_VHPT_ORDER); - } + + free_domain_vhpt(v); } /* diff --git a/xen/arch/ia64/vmx/vmx_init.c b/xen/arch/ia64/vmx/vmx_init.c index c4cb0150ea..2ae82ed086 100644 --- a/xen/arch/ia64/vmx/vmx_init.c +++ b/xen/arch/ia64/vmx/vmx_init.c @@ -290,7 +290,7 @@ static void vmx_release_assist_channel(struct vcpu *v) * Initialize VMX envirenment for guest. Only the 1st vp/vcpu * is registered here. */ -void +int vmx_final_setup_guest(struct vcpu *v) { vpd_t *vpd; @@ -305,7 +305,8 @@ vmx_final_setup_guest(struct vcpu *v) * to this solution. Maybe it can be deferred until we know created * one as vmx domain */ #ifndef HASH_VHPT - init_domain_tlb(v); + if (init_domain_tlb(v) != 0) + return -1; #endif vmx_create_event_channels(v); @@ -322,6 +323,8 @@ vmx_final_setup_guest(struct vcpu *v) /* Set up guest 's indicator for VTi domain*/ set_bit(ARCH_VMX_DOMAIN, &v->arch.arch_vmx.flags); + + return 0; } void diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index dc4ead671f..c0b00e83d3 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -585,9 +585,11 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c) if (test_bit(_VCPUF_initialised, &v->vcpu_flags)) return 0; - if (d->arch.is_vti) - vmx_final_setup_guest(v); - else { + if (d->arch.is_vti) { + rc = vmx_final_setup_guest(v); + if (rc != 0) + return rc; + } else { rc = vcpu_late_initialise(v); if (rc != 0) return rc; diff --git a/xen/include/asm-ia64/vmmu.h b/xen/include/asm-ia64/vmmu.h index 4b86a33711..9c436ce0e6 100644 --- a/xen/include/asm-ia64/vmmu.h +++ b/xen/include/asm-ia64/vmmu.h @@ -295,7 +295,7 @@ extern u64 machine_thash(PTA pta, u64 va); extern void purge_machine_tc_by_domid(domid_t domid); extern void machine_tlb_insert(struct vcpu *d, thash_data_t *tlb); extern ia64_rr vmmu_get_rr(struct vcpu *vcpu, u64 va); -extern void init_domain_tlb(struct vcpu *d); +extern int init_domain_tlb(struct vcpu *d); extern void free_domain_tlb(struct vcpu *v); extern thash_data_t * vsa_thash(PTA vpta, u64 va, u64 vrr, u64 *tag); extern thash_data_t * vhpt_lookup(u64 va); diff --git a/xen/include/asm-ia64/vmx.h b/xen/include/asm-ia64/vmx.h index 4e0971278a..5cd0e8c9bf 100644 --- a/xen/include/asm-ia64/vmx.h +++ b/xen/include/asm-ia64/vmx.h @@ -31,7 +31,7 @@ extern void identify_vmx_feature(void); extern unsigned int vmx_enabled; extern void vmx_init_env(void); -extern void vmx_final_setup_guest(struct vcpu *v); +extern int vmx_final_setup_guest(struct vcpu *v); extern void vmx_save_state(struct vcpu *v); extern void vmx_load_state(struct vcpu *v); extern void vmx_setup_platform(struct domain *d); From 60330d0d7fcd7141e3458298a9a4506842668702 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 09:45:26 -0700 Subject: [PATCH 03/95] [IA64] Move asm/percpu.h to linux-xen Modified by upcoming lazy FP save/restore code Signed-off-by: Alex Williamson --- xen/include/asm-ia64/linux-xen/asm/README.origin | 1 + xen/include/asm-ia64/{linux => linux-xen}/asm/percpu.h | 0 xen/include/asm-ia64/linux/asm/README.origin | 1 - 3 files changed, 1 insertion(+), 1 deletion(-) rename xen/include/asm-ia64/{linux => linux-xen}/asm/percpu.h (100%) diff --git a/xen/include/asm-ia64/linux-xen/asm/README.origin b/xen/include/asm-ia64/linux-xen/asm/README.origin index 23aa5b3ef4..e843a71b92 100644 --- a/xen/include/asm-ia64/linux-xen/asm/README.origin +++ b/xen/include/asm-ia64/linux-xen/asm/README.origin @@ -18,6 +18,7 @@ meminit.h -> linux/include/asm-ia64/meminit.h numa.h -> linux/include/asm-ia64/numa.h page.h -> linux/include/asm-ia64/page.h pal.h -> linux/include/asm-ia64/pal.h +percpu.h -> linux/include/asm-ia64/percpu.h pgalloc.h -> linux/include/asm-ia64/pgalloc.h pgtable.h -> linux/include/asm-ia64/pgtable.h processor.h -> linux/include/asm-ia64/processor.h diff --git a/xen/include/asm-ia64/linux/asm/percpu.h b/xen/include/asm-ia64/linux-xen/asm/percpu.h similarity index 100% rename from xen/include/asm-ia64/linux/asm/percpu.h rename to xen/include/asm-ia64/linux-xen/asm/percpu.h diff --git a/xen/include/asm-ia64/linux/asm/README.origin b/xen/include/asm-ia64/linux/asm/README.origin index 48ca126508..1167eab7d2 100644 --- a/xen/include/asm-ia64/linux/asm/README.origin +++ b/xen/include/asm-ia64/linux/asm/README.origin @@ -28,7 +28,6 @@ numnodes.h -> linux/include/asm-ia64/numnodes.h param.h -> linux/include/asm-ia64/param.h patch.h -> linux/include/asm-ia64/patch.h pci.h -> linux/include/asm-ia64/pci.h -percpu.h -> linux/include/asm-ia64/percpu.h rse.h -> linux/include/asm-ia64/rse.h sal.h -> linux/include/asm-ia64/sal.h sections.h -> linux/include/asm-ia64/sections.h From 3bfc06d3e53065070cd359de599285aabd6de7e1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 10:52:07 -0700 Subject: [PATCH 04/95] [IA64] Implement eager save, lazy restore FP algorithm Signed-off-by: Anthony Xu --- xen/arch/ia64/asm-offsets.c | 1 + xen/arch/ia64/asm-xsi-offsets.c | 2 + xen/arch/ia64/vmx/optvfault.S | 15 +++ xen/arch/ia64/vmx/vmx_process.c | 62 ++++++---- xen/arch/ia64/vmx/vmx_vcpu.c | 3 + xen/arch/ia64/xen/domain.c | 127 +++++++++++++------- xen/arch/ia64/xen/faults.c | 20 +++ xen/arch/ia64/xen/hyperprivop.S | 39 +++++- xen/arch/ia64/xen/vcpu.c | 33 ++++- xen/include/asm-ia64/domain.h | 1 + xen/include/asm-ia64/linux-xen/asm/percpu.h | 5 + xen/include/asm-ia64/vcpu.h | 1 + xen/include/public/arch-ia64.h | 4 +- 13 files changed, 241 insertions(+), 72 deletions(-) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index 571f396e96..c10cac45c7 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -57,6 +57,7 @@ void foo(void) DEFINE(IA64_VCPU_DOMAIN_OFFSET, offsetof (struct vcpu, domain)); DEFINE(IA64_VCPU_HYPERCALL_CONTINUATION_OFS, offsetof (struct vcpu, arch.hypercall_continuation)); + DEFINE(IA64_VCPU_FP_PSR_OFFSET, offsetof (struct vcpu, arch.fp_psr)); DEFINE(IA64_VCPU_META_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_rr0)); DEFINE(IA64_VCPU_META_SAVED_RR0_OFFSET, offsetof (struct vcpu, arch.metaphysical_saved_rr0)); DEFINE(IA64_VCPU_BREAKIMM_OFFSET, offsetof (struct vcpu, arch.breakimm)); diff --git a/xen/arch/ia64/asm-xsi-offsets.c b/xen/arch/ia64/asm-xsi-offsets.c index e3696909da..4e84d41077 100755 --- a/xen/arch/ia64/asm-xsi-offsets.c +++ b/xen/arch/ia64/asm-xsi-offsets.c @@ -61,6 +61,8 @@ void foo(void) DEFINE_MAPPED_REG_OFS(XSI_ITIR_OFS, itir); DEFINE_MAPPED_REG_OFS(XSI_ITV_OFS, itv); DEFINE_MAPPED_REG_OFS(XSI_PTA_OFS, pta); + DEFINE_MAPPED_REG_OFS(XSI_VPSR_DFH_OFS, vpsr_dfh); + DEFINE_MAPPED_REG_OFS(XSI_HPSR_DFH_OFS, hpsr_dfh); DEFINE_MAPPED_REG_OFS(XSI_PSR_IC_OFS, interrupt_collection_enabled); DEFINE_MAPPED_REG_OFS(XSI_VPSR_PP_OFS, vpsr_pp); DEFINE_MAPPED_REG_OFS(XSI_METAPHYS_OFS, metaphysical_mode); diff --git a/xen/arch/ia64/vmx/optvfault.S b/xen/arch/ia64/vmx/optvfault.S index cadf461752..6163437e5b 100644 --- a/xen/arch/ia64/vmx/optvfault.S +++ b/xen/arch/ia64/vmx/optvfault.S @@ -192,6 +192,13 @@ GLOBAL_ENTRY(vmx_asm_rsm) ;; st8 [r17]=r19 and r20=r20,r28 + adds r27=IA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=[r27] + ;; + tbit.nz p8,p0= r27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1 ;; mov cr.ipsr=r20 tbit.nz p6,p0=r23,0 @@ -360,6 +367,14 @@ vmx_asm_mov_to_psr_1: add r20=r19,r20 mov b0=r24 ;; + adds r27=IA64_VCPU_FP_PSR_OFFSET,r21 + ;; + ld8 r27=[r27] + ;; + tbit.nz p8,p0=r27,IA64_PSR_DFH_BIT + ;; + (p8) dep r20=-1,r20,IA64_PSR_DFH_BIT,1 + ;; mov cr.ipsr=r20 cmp.ne p6,p0=r0,r0 ;; diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index acce2c0bf9..7e1c1ab3bd 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -79,36 +79,56 @@ static u64 vec2off[68] = {0x0,0x400,0x800,0xc00,0x1000,0x1400,0x1800, void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim, - u64 vector, REGS *regs) + u64 vec, REGS *regs) { - u64 status; + u64 status, vector; VCPU *vcpu = current; u64 vpsr = VCPU(vcpu, vpsr); - vector=vec2off[vector]; + + vector = vec2off[vec]; if(!(vpsr&IA64_PSR_IC)&&(vector!=IA64_DATA_NESTED_TLB_VECTOR)){ panic_domain(regs, "Guest nested fault vector=%lx!\n", vector); } - else{ // handle fpswa emulation + + switch (vec) { + + case 25: // IA64_DISABLED_FPREG_VECTOR + + if (FP_PSR(vcpu) & IA64_PSR_DFH) { + FP_PSR(vcpu) = IA64_PSR_MFH; + if (__ia64_per_cpu_var(fp_owner) != vcpu) + __ia64_load_fpu(vcpu->arch._thread.fph); + } + if (!(VCPU(vcpu, vpsr) & IA64_PSR_DFH)) { + regs->cr_ipsr &= ~IA64_PSR_DFH; + return; + } + + break; + + case 32: // IA64_FP_FAULT_VECTOR + // handle fpswa emulation // fp fault - if (vector == IA64_FP_FAULT_VECTOR) { - status = handle_fpu_swa(1, regs, isr); - if (!status) { - vcpu_increment_iip(vcpu); - return; - } else if (IA64_RETRY == status) - return; - } + status = handle_fpu_swa(1, regs, isr); + if (!status) { + vcpu_increment_iip(vcpu); + return; + } else if (IA64_RETRY == status) + return; + break; + + case 33: // IA64_FP_TRAP_VECTOR //fp trap - else if (vector == IA64_FP_TRAP_VECTOR) { - status = handle_fpu_swa(0, regs, isr); - if (!status) - return; - else if (IA64_RETRY == status) { - vcpu_decrement_iip(vcpu); - return; - } + status = handle_fpu_swa(0, regs, isr); + if (!status) + return; + else if (IA64_RETRY == status) { + vcpu_decrement_iip(vcpu); + return; } - } + break; + + } VCPU(vcpu,isr)=isr; VCPU(vcpu,iipa) = regs->cr_iip; if (vector == IA64_BREAK_VECTOR || vector == IA64_SPECULATION_VECTOR) diff --git a/xen/arch/ia64/vmx/vmx_vcpu.c b/xen/arch/ia64/vmx/vmx_vcpu.c index 5c1ab3305f..f0418a8998 100644 --- a/xen/arch/ia64/vmx/vmx_vcpu.c +++ b/xen/arch/ia64/vmx/vmx_vcpu.c @@ -141,6 +141,9 @@ vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value) regs->cr_ipsr = (regs->cr_ipsr & mask ) | ( value & (~mask) ); + if (FP_PSR(vcpu) & IA64_PSR_DFH) + regs->cr_ipsr |= IA64_PSR_DFH; + check_mm_mode_switch(vcpu, old_psr, new_psr); return ; } diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index c0b00e83d3..17f2483761 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -68,6 +68,8 @@ static void init_switch_stack(struct vcpu *v); DEFINE_PER_CPU(uint8_t *, current_psr_i_addr); DEFINE_PER_CPU(int *, current_psr_ic_addr); +DEFINE_PER_CPU(struct vcpu *, fp_owner); + #include static void @@ -135,12 +137,44 @@ static void flush_vtlb_for_context_switch(struct vcpu* prev, struct vcpu* next) } } +static void lazy_fp_switch(struct vcpu *prev, struct vcpu *next) +{ + /* + * Implement eager save, lazy restore + */ + if (!is_idle_vcpu(prev)) { + if (VMX_DOMAIN(prev)) { + if (FP_PSR(prev) & IA64_PSR_MFH) { + __ia64_save_fpu(prev->arch._thread.fph); + __ia64_per_cpu_var(fp_owner) = prev; + } + } else { + if (PSCB(prev, hpsr_mfh)) { + __ia64_save_fpu(prev->arch._thread.fph); + __ia64_per_cpu_var(fp_owner) = prev; + } + } + } + + if (!is_idle_vcpu(next)) { + if (VMX_DOMAIN(next)) { + FP_PSR(next) = IA64_PSR_DFH; + vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH; + } else { + PSCB(next, hpsr_dfh) = 1; + PSCB(next, hpsr_mfh) = 0; + vcpu_regs(next)->cr_ipsr |= IA64_PSR_DFH; + } + } +} + void schedule_tail(struct vcpu *prev) { extern char ia64_ivt; - context_saved(prev); + context_saved(prev); ia64_disable_vhpt_walker(); + if (VMX_DOMAIN(current)) { vmx_do_launch(current); migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, @@ -148,7 +182,7 @@ void schedule_tail(struct vcpu *prev) } else { ia64_set_iva(&ia64_ivt); load_region_regs(current); - ia64_set_pta(vcpu_pta(current)); + ia64_set_pta(vcpu_pta(current)); vcpu_load_kernel_regs(current); __ia64_per_cpu_var(current_psr_i_addr) = ¤t->domain-> shared_info->vcpu_info[current->vcpu_id].evtchn_upcall_mask; @@ -165,64 +199,67 @@ void context_switch(struct vcpu *prev, struct vcpu *next) local_irq_save(spsr); - if (!is_idle_domain(prev->domain)) - __ia64_save_fpu(prev->arch._thread.fph); - if (!is_idle_domain(next->domain)) - __ia64_load_fpu(next->arch._thread.fph); - if (VMX_DOMAIN(prev)) { - vmx_save_state(prev); - if (!VMX_DOMAIN(next)) { - /* VMX domains can change the physical cr.dcr. - * Restore default to prevent leakage. */ - ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK - | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP - | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); - } + vmx_save_state(prev); + if (!VMX_DOMAIN(next)) { + /* VMX domains can change the physical cr.dcr. + * Restore default to prevent leakage. */ + ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK + | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP + | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); + } } if (VMX_DOMAIN(next)) - vmx_load_state(next); + vmx_load_state(next); ia64_disable_vhpt_walker(); - /*ia64_psr(ia64_task_regs(next))->dfh = !ia64_is_local_fpu_owner(next);*/ + lazy_fp_switch(prev, current); + prev = ia64_switch_to(next); /* Note: ia64_switch_to does not return here at vcpu initialization. */ - //cpu_set(smp_processor_id(), current->domain->domain_dirty_cpumask); - - if (VMX_DOMAIN(current)){ - vmx_load_all_rr(current); - migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, - current->processor); + if (VMX_DOMAIN(current)) { + vmx_load_all_rr(current); + migrate_timer(¤t->arch.arch_vmx.vtm.vtm_timer, + current->processor); } else { - struct domain *nd; - extern char ia64_ivt; + struct domain *nd; + extern char ia64_ivt; - ia64_set_iva(&ia64_ivt); + ia64_set_iva(&ia64_ivt); - nd = current->domain; - if (!is_idle_domain(nd)) { - load_region_regs(current); - ia64_set_pta(vcpu_pta(current)); - vcpu_load_kernel_regs(current); - vcpu_set_next_timer(current); - if (vcpu_timer_expired(current)) - vcpu_pend_timer(current); - __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info-> - vcpu_info[current->vcpu_id].evtchn_upcall_mask; - __ia64_per_cpu_var(current_psr_ic_addr) = - (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS); - } else { - /* When switching to idle domain, only need to disable vhpt - * walker. Then all accesses happen within idle context will - * be handled by TR mapping and identity mapping. - */ - __ia64_per_cpu_var(current_psr_i_addr) = NULL; - __ia64_per_cpu_var(current_psr_ic_addr) = NULL; + nd = current->domain; + if (!is_idle_domain(nd)) { + load_region_regs(current); + ia64_set_pta(vcpu_pta(current)); + vcpu_load_kernel_regs(current); + vcpu_set_next_timer(current); + if (vcpu_timer_expired(current)) + vcpu_pend_timer(current); + __ia64_per_cpu_var(current_psr_i_addr) = &nd->shared_info-> + vcpu_info[current->vcpu_id].evtchn_upcall_mask; + __ia64_per_cpu_var(current_psr_ic_addr) = + (int *)(nd->arch.shared_info_va + XSI_PSR_IC_OFS); + } else { + /* When switching to idle domain, only need to disable vhpt + * walker. Then all accesses happen within idle context will + * be handled by TR mapping and identity mapping. + */ + __ia64_per_cpu_var(current_psr_i_addr) = NULL; + __ia64_per_cpu_var(current_psr_ic_addr) = NULL; } } local_irq_restore(spsr); + + /* lazy fp */ + if (current->processor != current->arch.last_processor) { + unsigned long *addr; + addr = (unsigned long *)per_cpu_addr(fp_owner, + current->arch.last_processor); + ia64_cmpxchg(acq, addr, current, 0, 8); + } + flush_vtlb_for_context_switch(prev, current); context_saved(prev); } diff --git a/xen/arch/ia64/xen/faults.c b/xen/arch/ia64/xen/faults.c index 02606b1228..77a4eaa514 100644 --- a/xen/arch/ia64/xen/faults.c +++ b/xen/arch/ia64/xen/faults.c @@ -92,6 +92,9 @@ void reflect_interruption(unsigned long isr, struct pt_regs *regs, regs->cr_iip = ((unsigned long)PSCBX(v, iva) + vector) & ~0xffUL; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + if (PSCB(v, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(v, vpsr_dfh) = 0; v->vcpu_info->evtchn_upcall_mask = 1; PSCB(v, interrupt_collection_enabled) = 0; @@ -152,6 +155,9 @@ void reflect_event(void) regs->cr_iip = v->arch.event_callback_ip; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + if (PSCB(v, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(v, vpsr_dfh) = 0; v->vcpu_info->evtchn_upcall_mask = 1; PSCB(v, interrupt_collection_enabled) = 0; } @@ -261,6 +267,10 @@ void ia64_do_page_fault(unsigned long address, unsigned long isr, ((unsigned long)PSCBX(current, iva) + fault) & ~0xffUL; regs->cr_ipsr = (regs->cr_ipsr & ~DELIVER_PSR_CLR) | DELIVER_PSR_SET; + + if (PSCB(current, hpsr_dfh)) + regs->cr_ipsr |= IA64_PSR_DFH; + PSCB(current, vpsr_dfh) = 0; perfc_incra(slow_reflect, fault >> 8); return; } @@ -608,6 +618,16 @@ ia64_handle_reflection(unsigned long ifa, struct pt_regs *regs, vector = IA64_GENEX_VECTOR; break; case 25: + if (PSCB(v, hpsr_dfh)) { + PSCB(v, hpsr_dfh) = 0; + PSCB(v, hpsr_mfh) = 1; + if (__ia64_per_cpu_var(fp_owner) != v) + __ia64_load_fpu(v->arch._thread.fph); + } + if (!PSCB(v, vpsr_dfh)) { + regs->cr_ipsr &= ~IA64_PSR_DFH; + return; + } vector = IA64_DISABLED_FPREG_VECTOR; break; case 26: diff --git a/xen/arch/ia64/xen/hyperprivop.S b/xen/arch/ia64/xen/hyperprivop.S index 2b940d0922..5248d671ee 100644 --- a/xen/arch/ia64/xen/hyperprivop.S +++ b/xen/arch/ia64/xen/hyperprivop.S @@ -252,6 +252,10 @@ ENTRY(hyper_ssm_i) movl r27=~DELIVER_PSR_CLR;; or r29=r29,r28;; and r29=r29,r27;; + // set hpsr_dfh to ipsr + adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r28];; + dep r29=r28,r29,IA64_PSR_DFH_BIT,1;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set) extr.u r29=r30,IA64_PSR_CPL0_BIT,2;; @@ -269,6 +273,12 @@ ENTRY(hyper_ssm_i) movl r22=THIS_CPU(current_psr_i_addr) adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; ld8 r22=[r22] + ;; + adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r27];; + st1 [r27]=r0 + dep r30=r28,r30,IA64_PSR_DFH_BIT,1 + ;; st8 [r21]=r30;; // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 @@ -607,6 +617,10 @@ ENTRY(fast_reflect) movl r27=~(DELIVER_PSR_CLR|IA64_PSR_CPL0);; or r29=r29,r28;; and r29=r29,r27;; + // set hpsr_dfh to ipsr + adds r28=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r28];; + dep r29=r28,r29,IA64_PSR_DFH_BIT,1;; mov cr.ipsr=r29;; // set shared_mem ipsr (from ipsr in r30 with ipsr.ri already set) extr.u r29=r30,IA64_PSR_CPL0_BIT,2;; @@ -629,7 +643,13 @@ ENTRY(fast_reflect) (p6) dep r30=0,r30,IA64_PSR_I_BIT,1 (p7) dep r30=-1,r30,IA64_PSR_I_BIT,1 ;; mov r22=1 - adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 ;; + adds r21=XSI_IPSR_OFS-XSI_PSR_IC_OFS,r18 + ;; + adds r27=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r28=[r27];; + st1 [r27]=r0 + dep r30=r28,r30,IA64_PSR_DFH_BIT,1 + ;; st8 [r21]=r30 ;; // set shared_mem interrupt_delivery_enabled to 0 // set shared_mem interrupt_collection_enabled to 0 @@ -1104,6 +1124,18 @@ just_do_rfi: ;; or r21=r21,r20 ;; + adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + tbit.z p8,p9 = r21, IA64_PSR_DFH_BIT + ;; + (p9) mov r27=1;; + (p9) st1 [r20]=r27 + ;; + (p8) st1 [r20]=r0 + (p8) adds r20=XSI_HPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + (p8) ld1 r27=[r20] + ;; + (p8) dep r21=r27,r21, IA64_PSR_DFH_BIT, 1 + ;; mov cr.ipsr=r21 adds r20=XSI_BANKNUM_OFS-XSI_PSR_IC_OFS,r18 ;; ld4 r21=[r20];; @@ -1489,6 +1521,11 @@ ENTRY(hyper_get_psr) ld1 r21=[r20];; dep r8=r21,r8,IA64_PSR_I_BIT,1 ;; + // set vpsr.dfh + adds r20=XSI_VPSR_DFH_OFS-XSI_PSR_IC_OFS,r18;; + ld1 r21=[r20];; + dep r8=r21,r8,IA64_PSR_DFH_BIT,1 + ;; mov r25=cr.iip extr.u r26=r24,41,2 ;; cmp.eq p6,p7=2,r26 ;; diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index 9b554b1b64..bef5059b9f 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -141,6 +141,9 @@ void vcpu_init_regs(struct vcpu *v) /* dt/rt/it:1;i/ic:1, si:1, vm/bn:1, ac:1 */ /* Need to be expanded as macro */ regs->cr_ipsr = 0x501008826008; + /* lazy fp */ + FP_PSR(v) = IA64_PSR_DFH; + regs->cr_ipsr |= IA64_PSR_DFH; } else { regs->cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BITS_TO_SET | IA64_PSR_BN; @@ -148,6 +151,10 @@ void vcpu_init_regs(struct vcpu *v) | IA64_PSR_RI | IA64_PSR_IS); // domain runs at PL2 regs->cr_ipsr |= 2UL << IA64_PSR_CPL0_BIT; + // lazy fp + PSCB(v, hpsr_dfh) = 1; + PSCB(v, hpsr_mfh) = 0; + regs->cr_ipsr |= IA64_PSR_DFH; } regs->cr_ifs = 1UL << 63; /* or clear? */ regs->ar_fpsr = FPSR_DEFAULT; @@ -265,8 +272,10 @@ IA64FAULT vcpu_reset_psr_sm(VCPU * vcpu, u64 imm24) IA64_PSR_I | IA64_PSR_IC | IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH)) return IA64_ILLOP_FAULT; - if (imm.dfh) - ipsr->dfh = 0; + if (imm.dfh) { + ipsr->dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (imm.dfl) ipsr->dfl = 0; if (imm.pp) { @@ -320,8 +329,10 @@ IA64FAULT vcpu_set_psr_sm(VCPU * vcpu, u64 imm24) IA64_PSR_DT | IA64_PSR_DFL | IA64_PSR_DFH; if (imm24 & ~mask) return IA64_ILLOP_FAULT; - if (imm.dfh) + if (imm.dfh) { + PSCB(vcpu, vpsr_dfh) = 1; ipsr->dfh = 1; + } if (imm.dfl) ipsr->dfl = 1; if (imm.pp) { @@ -386,8 +397,13 @@ IA64FAULT vcpu_set_psr_l(VCPU * vcpu, u64 val) //if (val & ~(IA64_PSR_PP | IA64_PSR_UP | IA64_PSR_SP)) // return IA64_ILLOP_FAULT; // however trying to set other bits can't be an error as it is in ssm - if (newpsr.dfh) + if (newpsr.dfh) { ipsr->dfh = 1; + PSCB(vcpu, vpsr_dfh) = 1; + } else { + ipsr->dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (newpsr.dfl) ipsr->dfl = 1; if (newpsr.pp) { @@ -466,6 +482,8 @@ IA64FAULT vcpu_get_psr(VCPU * vcpu, u64 * pval) newpsr.pp = 1; else newpsr.pp = 0; + newpsr.dfh = PSCB(vcpu, vpsr_dfh); + *pval = *(unsigned long *)&newpsr; *pval &= (MASK(0, 32) | MASK(35, 2)); return IA64_NO_FAULT; @@ -497,6 +515,7 @@ u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) psr.ia64_psr.ic = PSCB(vcpu, interrupt_collection_enabled); psr.ia64_psr.i = !vcpu->vcpu_info->evtchn_upcall_mask; psr.ia64_psr.bn = PSCB(vcpu, banknum); + psr.ia64_psr.dfh = PSCB(vcpu, vpsr_dfh); psr.ia64_psr.dt = 1; psr.ia64_psr.it = 1; psr.ia64_psr.rt = 1; @@ -1343,6 +1362,12 @@ IA64FAULT vcpu_rfi(VCPU * vcpu) if (psr.ia64_psr.cpl < 3) psr.ia64_psr.cpl = 2; int_enable = psr.ia64_psr.i; + if (psr.ia64_psr.dfh) { + PSCB(vcpu, vpsr_dfh) = 1; + } else { + psr.ia64_psr.dfh = PSCB(vcpu, hpsr_dfh); + PSCB(vcpu, vpsr_dfh) = 0; + } if (psr.ia64_psr.ic) PSCB(vcpu, interrupt_collection_enabled) = 1; if (psr.ia64_psr.dt && psr.ia64_psr.rt && psr.ia64_psr.it) diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 2090908bf2..82a54c28b5 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -175,6 +175,7 @@ struct arch_vcpu { unsigned long metaphysical_rr4; // from arch_domain (so is pinned) unsigned long metaphysical_saved_rr0; // from arch_domain (so is pinned) unsigned long metaphysical_saved_rr4; // from arch_domain (so is pinned) + unsigned long fp_psr; // used for lazy float register int breakimm; // from arch_domain (so is pinned) int starting_rid; /* first RID assigned to domain */ int ending_rid; /* one beyond highest RID assigned to domain */ diff --git a/xen/include/asm-ia64/linux-xen/asm/percpu.h b/xen/include/asm-ia64/linux-xen/asm/percpu.h index 2b14dee29c..4e11b3cd5d 100644 --- a/xen/include/asm-ia64/linux-xen/asm/percpu.h +++ b/xen/include/asm-ia64/linux-xen/asm/percpu.h @@ -43,6 +43,9 @@ DECLARE_PER_CPU(unsigned long, local_per_cpu_offset); #define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) #define __get_cpu_var(var) (*RELOC_HIDE(&per_cpu__##var, __ia64_per_cpu_var(local_per_cpu_offset))) +#ifdef XEN +#define per_cpu_addr(var, cpu) (RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu])) +#endif extern void percpu_modcopy(void *pcpudst, const void *src, unsigned long size); extern void setup_per_cpu_areas (void); @@ -67,6 +70,8 @@ extern void *per_cpu_init(void); */ #define __ia64_per_cpu_var(var) (per_cpu__##var) +DECLARE_PER_CPU(struct vcpu *, fp_owner); + #endif /* !__ASSEMBLY__ */ #endif /* _ASM_IA64_PERCPU_H */ diff --git a/xen/include/asm-ia64/vcpu.h b/xen/include/asm-ia64/vcpu.h index 1f0684263a..7b99f0b5bb 100644 --- a/xen/include/asm-ia64/vcpu.h +++ b/xen/include/asm-ia64/vcpu.h @@ -20,6 +20,7 @@ extern u64 cycle_to_ns(u64 cycle); #define VCPU(_v,_x) (_v->arch.privregs->_x) #define PSCB(_v,_x) VCPU(_v,_x) #define PSCBX(_v,_x) (_v->arch._x) +#define FP_PSR(_v) PSCBX(_v, fp_psr) #define SPURIOUS_VECTOR 0xf diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index ac8292d2a0..84aa57e833 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -288,7 +288,9 @@ struct mapped_regs { unsigned char *interrupt_mask_addr; int pending_interruption; unsigned char vpsr_pp; - unsigned char reserved5_2[3]; + unsigned char vpsr_dfh; + unsigned char hpsr_dfh; + unsigned char hpsr_mfh; unsigned long reserved5_1[4]; int metaphysical_mode; // 1 = use metaphys mapping, 0 = use virtual int banknum; // 0 or 1, which virtual register bank is active From fd188b183270ebc0a8bc1d9fd2e7a1713a6fcccb Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 11:48:29 -0700 Subject: [PATCH 05/95] [IA64] Fix broken switch stack unw_init_running() needs to be called later in the OS INIT handler to prevent the switch stack from being broken by calls to other functions. Signed-off-by: Akio Takebe --- xen/arch/ia64/linux-xen/mca.c | 60 ++++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c index 8715ef1d5e..faa73e6672 100644 --- a/xen/arch/ia64/linux-xen/mca.c +++ b/xen/arch/ia64/linux-xen/mca.c @@ -684,16 +684,7 @@ fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_sta #ifdef XEN static spinlock_t init_dump_lock = SPIN_LOCK_UNLOCKED; static spinlock_t show_stack_lock = SPIN_LOCK_UNLOCKED; - -static void -save_ksp (struct unw_frame_info *info, void *arg) -{ - current->arch._thread.ksp = (__u64)(info->sw) - 16; - wmb(); -} - -/* FIXME */ -int try_crashdump(struct pt_regs *a) { return 0; } +static atomic_t num_stopped_cpus = ATOMIC_INIT(0); #define CPU_FLUSH_RETRY_MAX 5 static void @@ -716,6 +707,35 @@ init_cache_flush (void) } printk("\nPAL cache flush failed. status=%ld\n",rval); } + +static void inline +save_ksp (struct unw_frame_info *info) +{ + current->arch._thread.ksp = (__u64)(info->sw) - 16; + wmb(); + init_cache_flush(); +} + +static void +freeze_cpu_osinit (struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + atomic_inc(&num_stopped_cpus); + printk("%s: CPU%d init handler done\n", + __FUNCTION__, smp_processor_id()); + for (;;) + local_irq_disable(); +} + +/* FIXME */ +static void +try_crashdump(struct unw_frame_info *info, void *arg) +{ + save_ksp(info); + printk("\nINIT dump complete. Please reboot now.\n"); + for (;;) + local_irq_disable(); +} #endif /* XEN */ static void @@ -741,7 +761,8 @@ init_handler_platform (pal_min_state_area_t *ms, show_min_state(ms); #ifdef XEN - printk("Backtrace of current vcpu (vcpu_id %d)\n", current->vcpu_id); + printk("Backtrace of current vcpu (vcpu_id %d of domid %d)\n", + current->vcpu_id, current->domain->domain_id); #else printk("Backtrace of current task (pid %d, %s)\n", current->pid, current->comm); fetch_min_state(ms, pt, sw); @@ -749,20 +770,21 @@ init_handler_platform (pal_min_state_area_t *ms, unw_init_from_interruption(&info, current, pt, sw); ia64_do_show_stack(&info, NULL); #ifdef XEN - unw_init_running(save_ksp, NULL); spin_unlock(&show_stack_lock); - wmb(); - init_cache_flush(); if (spin_trylock(&init_dump_lock)) { #ifdef CONFIG_SMP - udelay(5*1000000); + int other_cpus = num_online_cpus() - 1; + int wait = 1000 * other_cpus; + + while ((atomic_read(&num_stopped_cpus) != other_cpus) && wait--) + udelay(1000); + if (other_cpus && wait < 0) + printk("timeout %d\n", atomic_read(&num_stopped_cpus)); #endif - if (try_crashdump(pt) == 0) - printk("\nINIT dump complete. Please reboot now.\n"); + unw_init_running(try_crashdump, pt); } - printk("%s: CPU%d init handler done\n", - __FUNCTION__, smp_processor_id()); + unw_init_running(freeze_cpu_osinit, NULL); #else /* XEN */ #ifdef CONFIG_SMP /* read_trylock() would be handy... */ From affb7d88442e871f1a8796fd4002f89b69f96e57 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 12:01:38 -0700 Subject: [PATCH 06/95] [IA64] Improve INIT call trace Signed-off-by: Akio Takebe --- xen/arch/ia64/linux-xen/mca.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/linux-xen/mca.c b/xen/arch/ia64/linux-xen/mca.c index faa73e6672..5a820973b4 100644 --- a/xen/arch/ia64/linux-xen/mca.c +++ b/xen/arch/ia64/linux-xen/mca.c @@ -84,6 +84,7 @@ #include #include #include +#include #endif #if defined(IA64_MCA_DEBUG_INFO) @@ -685,6 +686,7 @@ fetch_min_state (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_sta static spinlock_t init_dump_lock = SPIN_LOCK_UNLOCKED; static spinlock_t show_stack_lock = SPIN_LOCK_UNLOCKED; static atomic_t num_stopped_cpus = ATOMIC_INIT(0); +extern void show_stack (struct task_struct *, unsigned long *); #define CPU_FLUSH_RETRY_MAX 5 static void @@ -773,6 +775,8 @@ init_handler_platform (pal_min_state_area_t *ms, spin_unlock(&show_stack_lock); if (spin_trylock(&init_dump_lock)) { + struct domain *d; + struct vcpu *v; #ifdef CONFIG_SMP int other_cpus = num_online_cpus() - 1; int wait = 1000 * other_cpus; @@ -782,7 +786,19 @@ init_handler_platform (pal_min_state_area_t *ms, if (other_cpus && wait < 0) printk("timeout %d\n", atomic_read(&num_stopped_cpus)); #endif - unw_init_running(try_crashdump, pt); + if (opt_noreboot) { + /* this route is for dump routine */ + unw_init_running(try_crashdump, pt); + } else { + for_each_domain(d) { + for_each_vcpu(d, v) { + printk("Backtrace of current vcpu " + "(vcpu_id %d of domid %d)\n", + v->vcpu_id, d->domain_id); + show_stack(v, NULL); + } + } + } } unw_init_running(freeze_cpu_osinit, NULL); #else /* XEN */ From ea5725a36c19cde5ba314199c130443aba6ac1f6 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 23 Jan 2007 12:07:02 -0700 Subject: [PATCH 07/95] [IA64] Fix Xen crash when creating VTI domain Xend will do a hypercall to destory domain when creating VTI guest fails. If "is_vti" is not set at that point, HV will call relinquish_vcpu_resource(), which is for non-VTI. It may try to free a NULL pointer, so dom0 crash. This patch fix it. Signed-off-by: Xu Anthony Signed-off-by: Zhang Xin --- xen/arch/ia64/xen/vhpt.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c index c8846efc45..67341328de 100644 --- a/xen/arch/ia64/xen/vhpt.c +++ b/xen/arch/ia64/xen/vhpt.c @@ -177,7 +177,9 @@ pervcpu_vhpt_alloc(struct vcpu *v) void pervcpu_vhpt_free(struct vcpu *v) { - free_domheap_pages(v->arch.vhpt_page, VHPT_SIZE_LOG2 - PAGE_SHIFT); + if (likely(v->arch.vhpt_page != NULL)) + free_domheap_pages(v->arch.vhpt_page, + VHPT_SIZE_LOG2 - PAGE_SHIFT); } #endif From 794cb93dfd8591ea1af7463255aaced0cd92d737 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Wed, 24 Jan 2007 12:16:44 -0700 Subject: [PATCH 08/95] [IA64] ptc_ga might not purge vtlb SMP Windows sometimes failed to boot up with BSOD. If VTLB hasn't been used in region 0, ptc_ga for other region doesn't purge VTLBs. Signed-off-by: Kouya Shimura --- xen/arch/ia64/vmx/vmmu.c | 3 ++- xen/arch/ia64/vmx/vtlb.c | 11 ++++++++++- xen/include/asm-ia64/vmmu.h | 1 + 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index 145cd4c447..d75cc441ca 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -574,7 +574,8 @@ static void ptc_ga_remote_func (void *varg) mpta = ia64_get_pta(); ia64_set_pta(v->arch.arch_vmx.mpta&(~1)); ia64_srlz_d(); - vmx_vcpu_ptc_l(v, REGION_OFFSET(vadr), args->ps); + vadr = PAGEALIGN(vadr, args->ps); + thash_purge_entries_remote(v, vadr, args->ps); VMX(v, vrr[0]) = oldrid; VMX(v, psbits[0]) = oldpsbits; ia64_set_rr(0x0,moldrid); diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index f85c9e63b4..cb0181b9a0 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -261,7 +261,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) * purge software guest tlb */ -void vtlb_purge(VCPU *v, u64 va, u64 ps) +static void vtlb_purge(VCPU *v, u64 va, u64 ps) { thash_data_t *cur; u64 start, curadr, size, psbits, tag, rr_ps, num; @@ -442,6 +442,15 @@ void thash_purge_entries(VCPU *v, u64 va, u64 ps) vhpt_purge(v, va, ps); } +void thash_purge_entries_remote(VCPU *v, u64 va, u64 ps) +{ + u64 old_va = va; + va = REGION_OFFSET(va); + if (vcpu_quick_region_check(v->arch.tc_regions, old_va)) + vtlb_purge(v, va, ps); + vhpt_purge(v, va, ps); +} + u64 translate_phy_pte(VCPU *v, u64 *pte, u64 itir, u64 va) { u64 ps, ps_mask, paddr, maddr; diff --git a/xen/include/asm-ia64/vmmu.h b/xen/include/asm-ia64/vmmu.h index 9c436ce0e6..905d122f68 100644 --- a/xen/include/asm-ia64/vmmu.h +++ b/xen/include/asm-ia64/vmmu.h @@ -271,6 +271,7 @@ extern thash_data_t *thash_find_next_overlap(thash_cb_t *hcb); * */ extern void thash_purge_entries(struct vcpu *v, u64 va, u64 ps); +extern void thash_purge_entries_remote(struct vcpu *v, u64 va, u64 ps); extern void thash_purge_and_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa, int type); /* From 83a7f58cce168d57e4a15bfe52b66b3905c1bc43 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Wed, 24 Jan 2007 12:21:37 -0700 Subject: [PATCH 09/95] [IA64] xen might misunderstand a normal page as I/O page Hypervisor might misunderstand a normal page as I/O page if a guest OS uses the ig field in the guest VHPT. It seems to be harmless but slightly slow down. Full description: http://lists.xensource.com/archives/html/xen-ia64-devel/2007-01/msg00218.html Signed-off-by: Kouya Shimura --- xen/arch/ia64/vmx/vtlb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index cb0181b9a0..7ed628ba66 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -248,6 +248,7 @@ u64 guest_vhpt_lookup(u64 iha, u64 *pte) "tnat.nz p6,p7=r9;;" "(p6) mov %0=1;" "(p6) mov r9=r0;" + "(p7) extr.u r9=r9,0,53;;" "(p7) mov %0=r0;" "(p7) st8 [%2]=r9;;" "ssm psr.ic;;" From fa2fb716ec66a48d122aea14a50c24bec93b6e05 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Wed, 24 Jan 2007 12:28:05 -0700 Subject: [PATCH 10/95] [IA64] Fix oops message from timer_interrupton VTI domain This patch intends to fix the oops message from timer_interrupt on VTI domain. This problem occurred when we test PV-on-HVM driver by ltp-20061121. Typical message shown as follows. ltp Now Running...( Exception mode ) dom=domVTI 1 times Unable to find swap-space signature Oops: timer tick before it's due (itc=ed98bb5849,itm=ed98bb5849) Oops: timer tick before it's due (itc=f20bca8ca3,itm=f20bca8ca3) Oops: timer tick before it's due (itc=f4ea4e2b32,itm=f4ea4e2b32) mmap1(7392): unaligned access to 0x60000fffffffb634, ip=0x200000000004fad0 mmap1(7392): unaligned access to 0x60000fffffffb634, ip=0x200000000004fad0 ltp End These oops messages are generated because timer_interrupt checks the condition itc > itm. Currently Xen-hypervisor outputs following values, max(current_itc,vtm->last_itc). Sometimes oops message appeared if we use the value of vtm->last_itc as ia64_get_itc() return value, because the vtm->last_itc is same as itm. To fix this issue, it needs to add return value like +1. But, ia64_get_itc() is handled at vmx_asm_mov_from_ar@optvfault.S and it works same logic of now_itc()@vlsapic.c. And these routines shared vtm->last_itc. So I fix this problem by adding +1 at caller of update_last_itc. Signed-off-by: Atsushi SAKAI --- xen/arch/ia64/vmx/vlsapic.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vlsapic.c b/xen/arch/ia64/vmx/vlsapic.c index 7a495ee547..4bc9ab5cc7 100644 --- a/xen/arch/ia64/vmx/vlsapic.c +++ b/xen/arch/ia64/vmx/vlsapic.c @@ -171,7 +171,12 @@ static void vtm_timer_fn(void *data) } else vtm->pending = 1; - update_last_itc(vtm, VCPU(vcpu, itm)); // update vITC + /* + * "+ 1" is for fixing oops message at timer_interrupt() on VTI guest. + * If oops checking condition changed to timer_after_eq() on VTI guest, + * this parameter should be erased. + */ + update_last_itc(vtm, VCPU(vcpu, itm) + 1); // update vITC } void vtm_init(VCPU *vcpu) From f19b3abd3e7eb1ee357e36653a4052386922cd48 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Thu, 25 Jan 2007 14:40:45 -0700 Subject: [PATCH 11/95] [IA64] Set IRQ_PER_CPU status on percpu IRQs This is necessary to prevent percpu IRQs from being triggered when CPUs are offlined. Also remove some extraneous printks and rename variables. Signed-off-by: Alex Williamson --- .../arch/ia64/kernel/irq_ia64.c | 69 ++++++++++--------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c index 495eb496f5..bb38388ece 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c @@ -303,81 +303,85 @@ static struct irqaction resched_irqaction = { * required. */ static void -xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save) +xen_register_percpu_irq (unsigned int vec, struct irqaction *action, int save) { unsigned int cpu = smp_processor_id(); - int ret = 0; + irq_desc_t *desc; + int irq = 0; if (xen_slab_ready) { - switch (irq) { + switch (vec) { case IA64_TIMER_VECTOR: sprintf(timer_name[cpu], "%s%d", action->name, cpu); - ret = bind_virq_to_irqhandler(VIRQ_ITC, cpu, + irq = bind_virq_to_irqhandler(VIRQ_ITC, cpu, action->handler, action->flags, timer_name[cpu], action->dev_id); - per_cpu(timer_irq,cpu) = ret; - printk(KERN_INFO "register VIRQ_ITC (%s) to xen irq (%d)\n", timer_name[cpu], ret); + per_cpu(timer_irq,cpu) = irq; break; case IA64_IPI_RESCHEDULE: sprintf(resched_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(RESCHEDULE_VECTOR, cpu, action->handler, action->flags, resched_name[cpu], action->dev_id); - per_cpu(resched_irq,cpu) = ret; - printk(KERN_INFO "register RESCHEDULE_VECTOR (%s) to xen irq (%d)\n", resched_name[cpu], ret); + per_cpu(resched_irq,cpu) = irq; break; case IA64_IPI_VECTOR: sprintf(ipi_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(IPI_VECTOR, cpu, action->handler, action->flags, ipi_name[cpu], action->dev_id); - per_cpu(ipi_irq,cpu) = ret; - printk(KERN_INFO "register IPI_VECTOR (%s) to xen irq (%d)\n", ipi_name[cpu], ret); - break; - case IA64_SPURIOUS_INT_VECTOR: + per_cpu(ipi_irq,cpu) = irq; break; case IA64_CMC_VECTOR: sprintf(cmc_name[cpu], "%s%d", action->name, cpu); - ret = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, + irq = bind_virq_to_irqhandler(VIRQ_MCA_CMC, cpu, action->handler, action->flags, cmc_name[cpu], action->dev_id); - per_cpu(cmc_irq,cpu) = ret; - printk(KERN_INFO "register VIRQ_MCA_CMC (%s) to xen " - "irq (%d)\n", cmc_name[cpu], ret); + per_cpu(cmc_irq,cpu) = irq; break; case IA64_CMCP_VECTOR: sprintf(cmcp_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(CMCP_VECTOR, cpu, action->handler, action->flags, cmcp_name[cpu], action->dev_id); - per_cpu(cmcp_irq,cpu) = ret; - printk(KERN_INFO "register CMCP_VECTOR (%s) to xen " - "irq (%d)\n", cmcp_name[cpu], ret); + per_cpu(cmcp_irq,cpu) = irq; break; case IA64_CPEP_VECTOR: sprintf(cpep_name[cpu], "%s%d", action->name, cpu); - ret = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu, + irq = bind_ipi_to_irqhandler(CPEP_VECTOR, cpu, action->handler, action->flags, cpep_name[cpu], action->dev_id); - per_cpu(cpep_irq,cpu) = ret; - printk(KERN_INFO "register CPEP_VECTOR (%s) to xen " - "irq (%d)\n", cpep_name[cpu], ret); + per_cpu(cpep_irq,cpu) = irq; break; case IA64_CPE_VECTOR: - printk(KERN_WARNING "register IA64_CPE_VECTOR " - "IGNORED\n"); + case IA64_MCA_RENDEZ_VECTOR: + case IA64_PERFMON_VECTOR: + case IA64_MCA_WAKEUP_VECTOR: + case IA64_SPURIOUS_INT_VECTOR: + /* No need to complain, these aren't supported. */ break; default: - printk(KERN_WARNING "Percpu irq %d is unsupported by xen!\n", irq); + printk(KERN_WARNING "Percpu irq %d is unsupported " + "by xen!\n", vec); break; } - BUG_ON(ret < 0); + BUG_ON(irq < 0); + + if (irq > 0) { + /* + * Mark percpu. Without this, migrate_irqs() will + * mark the interrupt for migrations and trigger it + * on cpu hotplug. + */ + desc = irq_descp(irq); + desc->status |= IRQ_PER_CPU; + } } /* For BSP, we cache registered percpu irqs, and then re-walk @@ -385,7 +389,7 @@ xen_register_percpu_irq (unsigned int irq, struct irqaction *action, int save) */ if (!cpu && save) { BUG_ON(saved_irq_cnt == MAX_LATE_IRQ); - saved_percpu_irqs[saved_irq_cnt].irq = irq; + saved_percpu_irqs[saved_irq_cnt].irq = vec; saved_percpu_irqs[saved_irq_cnt].action = action; saved_irq_cnt++; if (!xen_slab_ready) @@ -572,7 +576,8 @@ ia64_send_ipi (int cpu, int vector, int delivery_mode, int redirect) irq = per_cpu(ipi_to_irq, cpu)[CPEP_VECTOR]; break; default: - printk(KERN_WARNING"Unsupported IPI type 0x%x\n", vector); + printk(KERN_WARNING "Unsupported IPI type 0x%x\n", + vector); irq = 0; break; } From 0e60d00e1986c0d6db070168e7576b64d5582ebf Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Thu, 25 Jan 2007 14:58:41 -0700 Subject: [PATCH 12/95] [IA64] Optimize vmx_vcpu_thash() Implement in assembly Signed-off-by: Zhang Xin --- xen/arch/ia64/asm-offsets.c | 1 + xen/arch/ia64/vmx/optvfault.S | 60 +++++++++++++++++++++++++++++++ xen/arch/ia64/vmx/vmx_ivt.S | 2 ++ xen/include/asm-ia64/vmx_mm_def.h | 4 ++- 4 files changed, 66 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/asm-offsets.c b/xen/arch/ia64/asm-offsets.c index c10cac45c7..6105406441 100644 --- a/xen/arch/ia64/asm-offsets.c +++ b/xen/arch/ia64/asm-offsets.c @@ -200,6 +200,7 @@ void foo(void) DEFINE(IA64_VPD_BASE_OFFSET, offsetof (struct vcpu, arch.privregs)); DEFINE(IA64_VPD_VIFS_OFFSET, offsetof (mapped_regs_t, ifs)); DEFINE(IA64_VLSAPIC_INSVC_BASE_OFFSET, offsetof (struct vcpu, arch.insvc[0])); + DEFINE(IA64_VPD_VPTA_OFFSET, offsetof (struct mapped_regs, pta)); DEFINE(IA64_VPD_CR_VPTA_OFFSET, offsetof (cr_t, pta)); DEFINE(XXX_THASH_SIZE, sizeof (thash_data_t)); diff --git a/xen/arch/ia64/vmx/optvfault.S b/xen/arch/ia64/vmx/optvfault.S index 6163437e5b..cf827ed98b 100644 --- a/xen/arch/ia64/vmx/optvfault.S +++ b/xen/arch/ia64/vmx/optvfault.S @@ -15,6 +15,7 @@ #include #include #include +#include #define ACCE_MOV_FROM_AR #define ACCE_MOV_FROM_RR @@ -22,6 +23,7 @@ #define ACCE_RSM #define ACCE_SSM #define ACCE_MOV_TO_PSR +#define ACCE_THASH //mov r1=ar3 GLOBAL_ENTRY(vmx_asm_mov_from_ar) @@ -418,6 +420,64 @@ ENTRY(vmx_asm_dispatch_vexirq) br.many vmx_dispatch_vexirq END(vmx_asm_dispatch_vexirq) +// thash +// TODO: add support when pta.vf = 1 +GLOBAL_ENTRY(vmx_asm_thash) +#ifndef ACCE_THASH + br.many vmx_virtualization_fault_back +#endif + extr.u r17=r25,20,7 // get r3 from opcode in r25 + extr.u r18=r25,6,7 // get r1 from opcode in r25 + movl r20=asm_mov_from_reg + ;; + adds r30=vmx_asm_thash_back1-asm_mov_from_reg,r20 + shladd r17=r17,4,r20 // get addr of MOVE_FROM_REG(r17) + adds r16=IA64_VPD_BASE_OFFSET,r21 // get vcpu.arch.priveregs + ;; + mov r24=b0 + ;; + ld8 r16=[r16] // get VPD addr + mov b0=r17 + br.many b0 // r19 return value + ;; +vmx_asm_thash_back1: + shr.u r23=r19,61 // get RR number + adds r25=VCPU_VRR0_OFS,r21 // get vcpu->arch.arch_vmx.vrr[0]'s addr + adds r16=IA64_VPD_VPTA_OFFSET,r16 // get vpta + ;; + shladd r27=r23,3,r25 // get vcpu->arch.arch_vmx.vrr[r23]'s addr + ld8 r17=[r16] // get PTA + mov r26=1 + ;; + extr.u r29=r17,2,6 // get pta.size + ld8 r25=[r27] // get vcpu->arch.arch_vmx.vrr[r23]'s value + ;; + extr.u r25=r25,2,6 // get rr.ps + shl r22=r26,r29 // 1UL << pta.size + ;; + shr.u r23=r19,r25 // vaddr >> rr.ps + adds r26=3,r29 // pta.size + 3 + shl r27=r17,3 // pta << 3 + ;; + shl r23=r23,3 // (vaddr >> rr.ps) << 3 + shr.u r27=r27,r26 // (pta << 3) >> (pta.size+3) + movl r16=VRN_MASK + ;; + adds r22=-1,r22 // (1UL << pta.size) - 1 + shl r27=r27,r29 // ((pta<<3)>>(pta.size+3))<>(pta.size + 3))<> IA64_VRN_SHIFT) +#ifndef __ASSEMBLY__ typedef enum { INSTRUCTION, DATA, REGISTER } miss_type; //typedef enum { MVHPT, STLB } vtlb_loc_type_t; @@ -169,5 +170,6 @@ bits_v(uint64_t v, uint32_t bs, uint32_t be) "M" ((len))); \ ret; \ }) +#endif #endif From cf443da1e611a06cb94c72ac0b6081ff55db6173 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Fri, 26 Jan 2007 14:11:21 -0700 Subject: [PATCH 13/95] [IA64] Remove dead code Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_entry.S | 144 ---------------------------------- 1 file changed, 144 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index fa2a53670f..0bdfc3bb82 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -425,148 +425,6 @@ ia64_vmm_entry_out: END(ia64_vmm_entry) -#ifdef XEN_DBL_MAPPING /* will be removed */ - -#define VMX_PURGE_RR7 0 -#define VMX_INSERT_RR7 1 -/* - * in0: old rr7 - * in1: virtual address of xen image - * in2: virtual address of vhpt table - */ -GLOBAL_ENTRY(vmx_purge_double_mapping) - alloc loc1 = ar.pfs,5,9,0,0 - mov loc0 = rp - movl r8 = 1f - ;; - movl loc4 = KERNEL_TR_PAGE_SHIFT - movl loc5 = VCPU_TLB_SHIFT - mov loc6 = psr - movl loc7 = XEN_RR7_SWITCH_STUB - mov loc8 = (1< Date: Fri, 26 Jan 2007 14:19:37 -0700 Subject: [PATCH 14/95] [IA64] Register NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ is used but not registered. I've never experienced but system will panic in the very long run. Signed-off-by: Kouya Shimura --- xen/arch/ia64/xen/xensetup.c | 5 +++++ xen/include/asm-ia64/flushtlb.h | 1 + 2 files changed, 6 insertions(+) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 0d1eaf23dd..3f7b9f1f47 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -26,6 +26,7 @@ #include #include #include +#include unsigned long xenheap_phys_end, total_pages; @@ -436,6 +437,10 @@ void start_kernel(void) init_xen_time(); /* initialise the time */ timer_init(); +#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK + open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); +#endif + #ifdef CONFIG_SMP if ( opt_nosmp ) { diff --git a/xen/include/asm-ia64/flushtlb.h b/xen/include/asm-ia64/flushtlb.h index 0966d72711..b470ac1615 100644 --- a/xen/include/asm-ia64/flushtlb.h +++ b/xen/include/asm-ia64/flushtlb.h @@ -32,6 +32,7 @@ extern volatile u32 tlbflush_clock; #define tlbflush_current_time() tlbflush_clock u32 tlbflush_clock_inc_and_return(void); +void new_tlbflush_clock_period(void); static inline void tlbflush_update_time(volatile u32* time, u32 timestamp) From 0a743ae4d8c1bc516a128983c2fa17c6def47412 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:25:44 -0700 Subject: [PATCH 15/95] [IA64] arch_vcpu_reset() stub Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/domain.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 5eab071de5..314f2c79b1 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -556,6 +556,12 @@ void arch_domain_destroy(struct domain *d) deallocate_rid_range(d); } +int arch_vcpu_reset(struct vcpu *v) +{ + /* FIXME: Stub for now */ + return 0; +} + void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) { int i; From 40e58e4840962e6c566eddf62aca3bb7a4835ecc Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:26:28 -0700 Subject: [PATCH 16/95] [IA64] Update for RCU code Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/xensetup.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 3f7b9f1f47..e63378cd23 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -437,6 +437,8 @@ void start_kernel(void) init_xen_time(); /* initialise the time */ timer_init(); + rcu_init(); + #ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK open_softirq(NEW_TLBFLUSH_CLOCK_PERIOD_SOFTIRQ, new_tlbflush_clock_period); #endif @@ -469,6 +471,7 @@ printk("num_online_cpus=%d, max_cpus=%d\n",num_online_cpus(),max_cpus); if ( num_online_cpus() >= max_cpus ) break; if ( !cpu_online(i) ) { + rcu_online_cpu(i); __cpu_up(i); } } From 2f320fa64f771ae8a2619362ba3a469556c214ad Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:29:21 -0700 Subject: [PATCH 17/95] [IA64] Kludge for XEN_GUEST_HANDLE_64 This is ugly, but the include spaghetti around xen.h isn't giving us the right defines. This should be removed with the includes are untangled. Signed-off-by: Alex Williamson --- xen/include/public/arch-ia64.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index 84aa57e833..cdb8f9de85 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -37,6 +37,8 @@ #define DEFINE_XEN_GUEST_HANDLE(name) __DEFINE_XEN_GUEST_HANDLE(name, name) #define XEN_GUEST_HANDLE(name) __guest_handle_ ## name +#define XEN_GUEST_HANDLE_64(name) XEN_GUEST_HANDLE(name) +#define uint64_aligned_t uint64_t #define set_xen_guest_handle(hnd, val) do { (hnd).p = val; } while (0) #ifdef __XEN_TOOLS__ #define get_xen_guest_handle(val, hnd) do { val = (hnd).p; } while (0) From 95699218f0e8f7609ec468e464b6aa37ebb4760f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:30:19 -0700 Subject: [PATCH 18/95] [IA64] Fix for irq_desc() missing in new upstream Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c index ea03497039..8524560326 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/irq_ia64.c @@ -395,7 +395,7 @@ xen_register_percpu_irq (unsigned int vec, struct irqaction *action, int save) * mark the interrupt for migrations and trigger it * on cpu hotplug. */ - desc = irq_descp(irq); + desc = irq_desc + irq; desc->status |= IRQ_PER_CPU; } } From ba0bcf40529bc9ca9553dfe7b1359c1219d63054 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:31:08 -0700 Subject: [PATCH 19/95] [IA64] Update installing the panic notifier for new upstream Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index c2699f43e1..a56bbbdc53 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -454,7 +454,8 @@ setup_arch (char **cmdline_p) setup_xen_features(); /* Register a call for panic conditions. */ - notifier_chain_register(&panic_notifier_list, &xen_panic_block); + atomic_notifier_chain_register(&panic_notifier_list, + &xen_panic_block); } #endif From 4493c1e82f2b665846d4bb1f60edda0b581969fc Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:32:27 -0700 Subject: [PATCH 20/95] [IA64] update xensetup.S for new upstream Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S index f0a75468fa..08676b88f8 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S @@ -875,9 +875,6 @@ skip_rbs_switch: st8 [r2]=r8 st8 [r3]=r10 .work_pending: - tbit.nz p6,p0=r31,TIF_SIGDELAYED // signal delayed from MCA/INIT/NMI/PMI context? -(p6) br.cond.sptk.few .sigdelayed - ;; tbit.z p6,p0=r31,TIF_NEED_RESCHED // current_thread_info()->need_resched==0? (p6) br.cond.sptk.few .notify #ifdef CONFIG_PREEMPT @@ -913,17 +910,6 @@ skip_rbs_switch: (pLvSys)br.cond.sptk.few .work_pending_syscall_end br.cond.sptk.many .work_processed_kernel // don't re-check -// There is a delayed signal that was detected in MCA/INIT/NMI/PMI context where -// it could not be delivered. Deliver it now. The signal might be for us and -// may set TIF_SIGPENDING, so redrive ia64_leave_* after processing the delayed -// signal. - -.sigdelayed: - br.call.sptk.many rp=do_sigdelayed - cmp.eq p6,p0=r0,r0 // p6 <- 1, always re-check -(pLvSys)br.cond.sptk.few .work_pending_syscall_end - br.cond.sptk.many .work_processed_kernel // re-check - .work_pending_syscall_end: adds r2=PT(R8)+16,r12 adds r3=PT(R10)+16,r12 From 2be162b951fb5c5b450a54da356dd86ed412777e Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:33:18 -0700 Subject: [PATCH 21/95] [IA64] New resend_irq_on_evtchn() params Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h b/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h index 6369480485..922184d514 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/hw_irq.h @@ -104,10 +104,9 @@ extern void register_percpu_irq (ia64_vector vec, struct irqaction *action); static inline void ia64_resend_irq(unsigned int vector) { #ifdef CONFIG_XEN - extern void resend_irq_on_evtchn(struct hw_interrupt_type *h, - unsigned int i); + extern int resend_irq_on_evtchn(unsigned int i); if (is_running_on_xen()) - resend_irq_on_evtchn(h, vector); + resend_irq_on_evtchn(vector); else #endif /* CONFIG_XEN */ platform_send_ipi(smp_processor_id(), vector, IA64_IPI_DM_INT, 0); From c77420064f61df61c2ecfc6da230895f0ceef4cd Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 28 Jan 2007 16:37:02 -0700 Subject: [PATCH 22/95] [IA64] Remove PG_foreign hack Signed-off-by: Alex Williamson --- .../arch/ia64/xen/hypervisor.c | 6 --- linux-2.6-xen-sparse/include/asm-ia64/maddr.h | 3 -- linux-2.6-xen-sparse/include/asm-ia64/page.h | 38 ------------------- 3 files changed, 47 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c index f65cf94ee1..695dc3bce5 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c +++ b/linux-2.6-xen-sparse/arch/ia64/xen/hypervisor.c @@ -416,12 +416,6 @@ HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count) } EXPORT_SYMBOL(HYPERVISOR_grant_table_op); -/////////////////////////////////////////////////////////////////////////// -// PageForeign(), SetPageForeign(), ClearPageForeign() - -struct address_space xen_ia64_foreign_dummy_mapping; -EXPORT_SYMBOL(xen_ia64_foreign_dummy_mapping); - /////////////////////////////////////////////////////////////////////////// // foreign mapping #include diff --git a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h index cacad452d8..c43348f26a 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/maddr.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/maddr.h @@ -84,9 +84,6 @@ mfn_to_local_pfn(unsigned long mfn) #endif /* !CONFIG_XEN */ -/* XXX to compile set_phys_to_machine(vaddr, FOREIGN_FRAME(m)) */ -#define FOREIGN_FRAME(m) (INVALID_P2M_ENTRY) - #define mfn_to_pfn(mfn) (mfn) #define pfn_to_mfn(pfn) (pfn) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/page.h b/linux-2.6-xen-sparse/include/asm-ia64/page.h index e8ad9ec4ee..4641560dab 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h @@ -236,44 +236,6 @@ get_order (unsigned long size) #include #include #include // to compile netback, netfront - -/* - * XXX hack! - * Linux/IA64 uses PG_arch_1. - * This hack will be removed once PG_foreign bit is taken. - * #include - */ -#ifdef __ASM_XEN_FOREIGN_PAGE_H__ -# error "don't include include/xen/foreign_page.h!" -#endif - -extern struct address_space xen_ia64_foreign_dummy_mapping; -#define PageForeign(page) \ - ((page)->mapping == &xen_ia64_foreign_dummy_mapping) - -#define SetPageForeign(page, dtor) do { \ - set_page_private((page), (unsigned long)(dtor)); \ - (page)->mapping = &xen_ia64_foreign_dummy_mapping; \ - smp_rmb(); \ -} while (0) - -#define ClearPageForeign(page) do { \ - (page)->mapping = NULL; \ - smp_rmb(); \ - set_page_private((page), 0); \ -} while (0) - -#define PageForeignDestructor(page) \ - ( (void (*) (struct page *)) page_private(page) ) - -#define arch_free_page(_page,_order) \ -({ int foreign = PageForeign(_page); \ - if (foreign) \ - (PageForeignDestructor(_page))(_page); \ - foreign; \ -}) -#define HAVE_ARCH_FREE_PAGE - #include #endif /* CONFIG_XEN */ From 530aa67db78a2d24a3f876a7ca3c7f1e5198b055 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Mon, 29 Jan 2007 11:17:15 -0700 Subject: [PATCH 23/95] [IA64] Update buildconfigs Mainly just taking defaults from make oldconfig. Signed-off-by: Alex Williamson --- buildconfigs/linux-defconfig_xen0_ia64 | 209 +++++++++++++++++++------ buildconfigs/linux-defconfig_xenU_ia64 | 182 +++++++++++++++------ buildconfigs/linux-defconfig_xen_ia64 | 200 +++++++++++++++++------ 3 files changed, 439 insertions(+), 152 deletions(-) diff --git a/buildconfigs/linux-defconfig_xen0_ia64 b/buildconfigs/linux-defconfig_xen0_ia64 index dc97753420..782c1f4925 100644 --- a/buildconfigs/linux-defconfig_xen0_ia64 +++ b/buildconfigs/linux-defconfig_xen0_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xen0 -# Tue Nov 14 10:39:09 2006 +# Linux kernel version: 2.6.18-xen0 +# Mon Jan 29 10:16:18 2007 # # @@ -21,14 +21,16 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_EXTRA_PASS=y @@ -40,11 +42,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -55,7 +55,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y @@ -64,6 +63,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -86,8 +86,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -96,6 +98,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -123,6 +126,7 @@ CONFIG_NR_CPUS=16 CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -132,6 +136,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -163,6 +168,7 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y @@ -185,7 +191,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -215,6 +221,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -229,7 +237,10 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -240,6 +251,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -280,12 +294,12 @@ CONFIG_BRIDGE_NETFILTER=y CONFIG_BRIDGE=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -314,6 +328,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -352,6 +367,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -463,6 +479,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -472,10 +489,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_FC=y -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -488,7 +503,13 @@ CONFIG_SCSI_QLOGIC_1280=y # CONFIG_MD=y # CONFIG_BLK_DEV_MD is not set -# CONFIG_BLK_DEV_DM is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_CRYPT=m +CONFIG_DM_SNAPSHOT=m +CONFIG_DM_MIRROR=m +CONFIG_DM_ZERO=m +CONFIG_DM_MULTIPATH=m +CONFIG_DM_MULTIPATH_EMC=m # # Fusion MPT device support @@ -607,6 +628,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -709,6 +731,7 @@ CONFIG_GAMEPORT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -722,6 +745,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -755,6 +779,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set CONFIG_AGP_I460=y CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -799,10 +825,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -821,9 +847,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -838,13 +862,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -873,10 +897,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -887,25 +913,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -917,10 +944,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -928,20 +985,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -953,7 +1014,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -972,6 +1032,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -1002,9 +1063,11 @@ CONFIG_SND_SEQ_DUMMY=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1025,6 +1088,7 @@ CONFIG_SND_MPU401=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set CONFIG_SND_ATIIXP=y # CONFIG_SND_ATIIXP_MODEM is not set @@ -1037,6 +1101,18 @@ CONFIG_SND_ATIIXP=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -1057,6 +1133,7 @@ CONFIG_SND_FM801=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1076,12 +1153,14 @@ CONFIG_SND_FM801=y # Open Sound System # CONFIG_SOUND_PRIME=y -# CONFIG_OBSOLETE_OSS_DRIVER is not set -# CONFIG_SOUND_FUSION is not set +# CONFIG_OSS_OBSOLETE_DRIVER is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ICH is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_TVMIXER is not set # @@ -1089,6 +1168,7 @@ CONFIG_SOUND_PRIME=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1107,6 +1187,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1117,7 +1198,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1154,9 +1234,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1170,21 +1248,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1214,10 +1277,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1236,6 +1301,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1245,6 +1323,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1269,7 +1365,6 @@ CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1278,6 +1373,7 @@ CONFIG_XFS_EXPORT=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1312,7 +1408,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1358,7 +1453,9 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=y # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1437,9 +1534,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1452,14 +1551,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1513,7 +1617,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1539,6 +1642,7 @@ CONFIG_XEN_PCIDEV_BACKEND_SLOT=y # CONFIG_XEN_TPMDEV_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y +# CONFIG_XEN_FRAMEBUFFER is not set # CONFIG_XEN_SCRUB_PAGES is not set CONFIG_XEN_DISABLE_SERIAL=y CONFIG_XEN_SYSFS=y @@ -1547,3 +1651,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xenU_ia64 b/buildconfigs/linux-defconfig_xenU_ia64 index 537fd311a9..ed518155e7 100644 --- a/buildconfigs/linux-defconfig_xenU_ia64 +++ b/buildconfigs/linux-defconfig_xenU_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xenU -# Wed Oct 4 12:54:26 2006 +# Linux kernel version: 2.6.18-xenU +# Mon Jan 29 10:26:51 2007 # # @@ -21,13 +21,15 @@ CONFIG_SYSVIPC=y # CONFIG_POSIX_MQUEUE is not set CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y # CONFIG_KALLSYMS_ALL is not set # CONFIG_KALLSYMS_EXTRA_PASS is not set @@ -39,11 +41,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -53,7 +53,6 @@ CONFIG_BASE_SMALL=0 # CONFIG_MODULES=y # CONFIG_MODULE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y # CONFIG_MODVERSIONS is not set # CONFIG_MODULE_SRCVERSION_ALL is not set # CONFIG_KMOD is not set @@ -61,6 +60,7 @@ CONFIG_OBSOLETE_MODPARM=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -83,8 +83,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -93,6 +95,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -117,9 +120,10 @@ CONFIG_IOSAPIC=y CONFIG_FORCE_MAX_ZONEORDER=11 CONFIG_SMP=y CONFIG_NR_CPUS=16 -# CONFIG_HOTPLUG_CPU is not set +CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -129,6 +133,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -161,7 +166,9 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y +CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y CONFIG_ACPI_BLACKLIST_YEAR=0 # CONFIG_ACPI_DEBUG is not set @@ -182,7 +189,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -212,6 +219,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -226,7 +235,10 @@ CONFIG_IP_FIB_HASH=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -237,6 +249,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set @@ -276,7 +291,6 @@ CONFIG_NETFILTER=y # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -305,6 +319,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -342,6 +357,7 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -399,6 +415,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -408,9 +425,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -# CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -532,6 +548,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -609,6 +626,7 @@ CONFIG_SERIO=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -616,7 +634,7 @@ CONFIG_HW_CONSOLE=y # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_ACPI=y +CONFIG_SERIAL_8250_PCI=y CONFIG_SERIAL_8250_NR_UARTS=8 CONFIG_SERIAL_8250_RUNTIME_UARTS=4 CONFIG_SERIAL_8250_EXTENDED=y @@ -653,6 +671,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set # CONFIG_AGP_I460 is not set CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -697,10 +717,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -719,9 +739,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -736,13 +754,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -771,10 +789,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -785,25 +805,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -815,10 +836,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -826,20 +877,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -851,7 +906,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -870,6 +924,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -900,9 +955,11 @@ CONFIG_SND_SEQUENCER=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -923,6 +980,7 @@ CONFIG_SND_AC97_BUS=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set # CONFIG_SND_ATIIXP is not set # CONFIG_SND_ATIIXP_MODEM is not set @@ -980,6 +1038,7 @@ CONFIG_SND_FM801=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -998,6 +1057,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1008,7 +1068,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1044,9 +1103,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1060,21 +1117,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1104,10 +1146,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set @@ -1125,6 +1169,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1134,6 +1191,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1157,6 +1232,7 @@ CONFIG_FS_MBCACHE=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1191,7 +1267,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1311,9 +1386,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1326,14 +1403,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=17 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1387,7 +1469,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1402,6 +1483,8 @@ CONFIG_XEN_XENBUS_DEV=y # CONFIG_XEN_BACKEND is not set CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_XEN_NETDEV_FRONTEND=y +CONFIG_XEN_FRAMEBUFFER=y +CONFIG_XEN_KEYBOARD=y # CONFIG_XEN_SCRUB_PAGES is not set # CONFIG_XEN_DISABLE_SERIAL is not set CONFIG_XEN_SYSFS=y @@ -1410,3 +1493,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y diff --git a/buildconfigs/linux-defconfig_xen_ia64 b/buildconfigs/linux-defconfig_xen_ia64 index 2e41eb5892..0d9c15f989 100644 --- a/buildconfigs/linux-defconfig_xen_ia64 +++ b/buildconfigs/linux-defconfig_xen_ia64 @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.16.29-xen -# Tue Nov 14 10:38:50 2006 +# Linux kernel version: 2.6.18-xen +# Mon Jan 29 10:01:13 2007 # # @@ -21,14 +21,16 @@ CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_BSD_PROCESS_ACCT=y # CONFIG_BSD_PROCESS_ACCT_V3 is not set -CONFIG_SYSCTL=y +# CONFIG_TASKSTATS is not set # CONFIG_AUDIT is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y # CONFIG_CPUSETS is not set +# CONFIG_RELAY is not set CONFIG_INITRAMFS_SOURCE="" CONFIG_CC_OPTIMIZE_FOR_SIZE=y # CONFIG_EMBEDDED is not set +CONFIG_SYSCTL=y CONFIG_KALLSYMS=y CONFIG_KALLSYMS_ALL=y CONFIG_KALLSYMS_EXTRA_PASS=y @@ -40,11 +42,9 @@ CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_EPOLL=y CONFIG_SHMEM=y -CONFIG_CC_ALIGN_FUNCTIONS=0 -CONFIG_CC_ALIGN_LABELS=0 -CONFIG_CC_ALIGN_LOOPS=0 -CONFIG_CC_ALIGN_JUMPS=0 CONFIG_SLAB=y +CONFIG_VM_EVENT_COUNTERS=y +CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 # CONFIG_SLOB is not set @@ -55,7 +55,6 @@ CONFIG_BASE_SMALL=0 CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y # CONFIG_MODULE_FORCE_UNLOAD is not set -CONFIG_OBSOLETE_MODPARM=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y CONFIG_KMOD=y @@ -64,6 +63,7 @@ CONFIG_STOP_MACHINE=y # # Block layer # +# CONFIG_BLK_DEV_IO_TRACE is not set # # IO Schedulers @@ -86,8 +86,10 @@ CONFIG_64BIT=y CONFIG_MMU=y CONFIG_SWIOTLB=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_FIND_NEXT_BIT=y CONFIG_GENERIC_CALIBRATE_DELAY=y CONFIG_TIME_INTERPOLATION=y +CONFIG_DMI=y CONFIG_EFI=y CONFIG_GENERIC_IOMAP=y CONFIG_XEN=y @@ -96,6 +98,7 @@ CONFIG_XEN_IA64_EXPOSE_P2M=y CONFIG_XEN_IA64_EXPOSE_P2M_USE_DTR=y CONFIG_SCHED_NO_NO_OMIT_FRAME_POINTER=y CONFIG_DMA_IS_DMA32=y +CONFIG_AUDIT_ARCH=y # CONFIG_IA64_GENERIC is not set CONFIG_IA64_DIG=y # CONFIG_IA64_HP_ZX1 is not set @@ -123,6 +126,7 @@ CONFIG_NR_CPUS=16 CONFIG_HOTPLUG_CPU=y CONFIG_ARCH_ENABLE_MEMORY_HOTPLUG=y # CONFIG_SCHED_SMT is not set +# CONFIG_PERMIT_BSP_REMOVE is not set # CONFIG_PREEMPT is not set CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y @@ -132,6 +136,7 @@ CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set CONFIG_SPLIT_PTLOCK_CPUS=4 +CONFIG_RESOURCES_64BIT=y CONFIG_ARCH_SELECT_MEMORY_MODEL=y CONFIG_ARCH_DISCONTIGMEM_ENABLE=y CONFIG_ARCH_FLATMEM_ENABLE=y @@ -163,6 +168,7 @@ CONFIG_PM_LEGACY=y CONFIG_ACPI=y CONFIG_ACPI_BUTTON=y CONFIG_ACPI_FAN=y +# CONFIG_ACPI_DOCK is not set CONFIG_ACPI_PROCESSOR=y CONFIG_ACPI_HOTPLUG_CPU=y CONFIG_ACPI_THERMAL=y @@ -185,7 +191,7 @@ CONFIG_PCI=y CONFIG_PCI_DOMAINS=y CONFIG_XEN_PCIDEV_FRONTEND=y # CONFIG_XEN_PCIDEV_FE_DEBUG is not set -CONFIG_PCI_LEGACY_PROC=y +# CONFIG_PCIEPORTBUS is not set # CONFIG_PCI_DEBUG is not set # @@ -215,6 +221,8 @@ CONFIG_NET=y CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set CONFIG_UNIX=y +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set # CONFIG_NET_KEY is not set CONFIG_INET=y CONFIG_IP_MULTICAST=y @@ -229,7 +237,10 @@ CONFIG_SYN_COOKIES=y # CONFIG_INET_AH is not set # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set +# CONFIG_INET_XFRM_TUNNEL is not set # CONFIG_INET_TUNNEL is not set +CONFIG_INET_XFRM_MODE_TRANSPORT=y +CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -240,6 +251,9 @@ CONFIG_TCP_CONG_BIC=y # # CONFIG_IP_VS is not set # CONFIG_IPV6 is not set +# CONFIG_INET6_XFRM_TUNNEL is not set +# CONFIG_INET6_TUNNEL is not set +# CONFIG_NETWORK_SECMARK is not set CONFIG_NETFILTER=y # CONFIG_NETFILTER_DEBUG is not set CONFIG_BRIDGE_NETFILTER=y @@ -280,12 +294,12 @@ CONFIG_BRIDGE_NETFILTER=y CONFIG_BRIDGE=y # CONFIG_VLAN_8021Q is not set # CONFIG_DECNET is not set +CONFIG_LLC=y # CONFIG_LLC2 is not set # CONFIG_IPX is not set # CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set -# CONFIG_NET_DIVERT is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set @@ -314,6 +328,7 @@ CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y # CONFIG_DEBUG_DRIVER is not set +# CONFIG_SYS_HYPERVISOR is not set # # Connector - unified userspace <-> kernelspace linker @@ -352,6 +367,7 @@ CONFIG_BLK_DEV_NBD=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 CONFIG_BLK_DEV_INITRD=y # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set @@ -463,6 +479,7 @@ CONFIG_SCSI_SAS_ATTRS=y # CONFIG_MEGARAID_LEGACY is not set # CONFIG_MEGARAID_SAS is not set # CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_HPTIOP is not set # CONFIG_SCSI_DMX3191D is not set # CONFIG_SCSI_FUTURE_DOMAIN is not set # CONFIG_SCSI_IPS is not set @@ -472,10 +489,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1 CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 -# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +CONFIG_SCSI_SYM53C8XX_MMIO=y # CONFIG_SCSI_IPR is not set -CONFIG_SCSI_QLOGIC_FC=y -# CONFIG_SCSI_QLOGIC_FC_FIRMWARE is not set CONFIG_SCSI_QLOGIC_1280=y # CONFIG_SCSI_QLA_FC is not set # CONFIG_SCSI_LPFC is not set @@ -613,6 +628,7 @@ CONFIG_TIGON3=y # CONFIG_CHELSIO_T1 is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set +# CONFIG_MYRI10GE is not set # # Token Ring devices @@ -715,6 +731,7 @@ CONFIG_GAMEPORT=y CONFIG_VT=y CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y +# CONFIG_VT_HW_CONSOLE_BINDING is not set CONFIG_SERIAL_NONSTANDARD=y # CONFIG_COMPUTONE is not set # CONFIG_ROCKETPORT is not set @@ -728,6 +745,7 @@ CONFIG_SERIAL_NONSTANDARD=y # CONFIG_N_HDLC is not set # CONFIG_SPECIALIX is not set # CONFIG_SX is not set +# CONFIG_RIO is not set # CONFIG_STALDRV is not set # @@ -761,6 +779,8 @@ CONFIG_EFI_RTC=y # Ftape, the floppy tape device driver # CONFIG_AGP=y +# CONFIG_AGP_SIS is not set +# CONFIG_AGP_VIA is not set CONFIG_AGP_I460=y CONFIG_DRM=y # CONFIG_DRM_TDFX is not set @@ -805,10 +825,10 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_I2C_I810 is not set # CONFIG_I2C_PIIX4 is not set # CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_OCORES is not set # CONFIG_I2C_PARPORT_LIGHT is not set # CONFIG_I2C_PROSAVAGE is not set # CONFIG_I2C_SAVAGE4 is not set -# CONFIG_SCx200_ACB is not set # CONFIG_I2C_SIS5595 is not set # CONFIG_I2C_SIS630 is not set # CONFIG_I2C_SIS96X is not set @@ -827,9 +847,7 @@ CONFIG_I2C_ALGOPCF=y # CONFIG_SENSORS_PCF8574 is not set # CONFIG_SENSORS_PCA9539 is not set # CONFIG_SENSORS_PCF8591 is not set -# CONFIG_SENSORS_RTC8564 is not set # CONFIG_SENSORS_MAX6875 is not set -# CONFIG_RTC_X1205_I2C is not set # CONFIG_I2C_DEBUG_CORE is not set # CONFIG_I2C_DEBUG_ALGO is not set # CONFIG_I2C_DEBUG_BUS is not set @@ -844,13 +862,13 @@ CONFIG_I2C_ALGOPCF=y # # Dallas's 1-wire bus # -# CONFIG_W1 is not set # # Hardware Monitoring support # CONFIG_HWMON=y # CONFIG_HWMON_VID is not set +# CONFIG_SENSORS_ABITUGURU is not set # CONFIG_SENSORS_ADM1021 is not set # CONFIG_SENSORS_ADM1025 is not set # CONFIG_SENSORS_ADM1026 is not set @@ -879,10 +897,12 @@ CONFIG_HWMON=y # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_SIS5595 is not set # CONFIG_SENSORS_SMSC47M1 is not set +# CONFIG_SENSORS_SMSC47M192 is not set # CONFIG_SENSORS_SMSC47B397 is not set # CONFIG_SENSORS_VIA686A is not set # CONFIG_SENSORS_VT8231 is not set # CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83791D is not set # CONFIG_SENSORS_W83792D is not set # CONFIG_SENSORS_W83L785TS is not set # CONFIG_SENSORS_W83627HF is not set @@ -893,25 +913,26 @@ CONFIG_HWMON=y # Misc devices # -# -# Multimedia Capabilities Port drivers -# - # # Multimedia devices # CONFIG_VIDEO_DEV=y +CONFIG_VIDEO_V4L1=y +CONFIG_VIDEO_V4L1_COMPAT=y +CONFIG_VIDEO_V4L2=y # -# Video For Linux +# Video Capture Adapters # # -# Video Adapters +# Video Capture Adapters # # CONFIG_VIDEO_ADV_DEBUG is not set +# CONFIG_VIDEO_VIVI is not set # CONFIG_VIDEO_BT848 is not set # CONFIG_VIDEO_CPIA is not set +# CONFIG_VIDEO_CPIA2 is not set # CONFIG_VIDEO_SAA5246A is not set # CONFIG_VIDEO_SAA5249 is not set # CONFIG_TUNER_3036 is not set @@ -923,10 +944,40 @@ CONFIG_VIDEO_DEV=y # CONFIG_VIDEO_HEXIUM_ORION is not set # CONFIG_VIDEO_HEXIUM_GEMINI is not set # CONFIG_VIDEO_CX88 is not set + +# +# Encoders and Decoders +# +# CONFIG_VIDEO_MSP3400 is not set +# CONFIG_VIDEO_CS53L32A is not set +# CONFIG_VIDEO_TLV320AIC23B is not set +# CONFIG_VIDEO_WM8775 is not set +# CONFIG_VIDEO_WM8739 is not set +# CONFIG_VIDEO_CX2341X is not set +# CONFIG_VIDEO_CX25840 is not set +# CONFIG_VIDEO_SAA711X is not set +# CONFIG_VIDEO_SAA7127 is not set +# CONFIG_VIDEO_UPD64031A is not set +# CONFIG_VIDEO_UPD64083 is not set + +# +# V4L USB devices +# +# CONFIG_VIDEO_PVRUSB2 is not set # CONFIG_VIDEO_EM28XX is not set +# CONFIG_USB_VICAM is not set +# CONFIG_USB_IBMCAM is not set +# CONFIG_USB_KONICAWC is not set +# CONFIG_USB_QUICKCAM_MESSENGER is not set +# CONFIG_USB_ET61X251 is not set # CONFIG_VIDEO_OVCAMCHIP is not set -# CONFIG_VIDEO_AUDIO_DECODER is not set -# CONFIG_VIDEO_DECODER is not set +# CONFIG_USB_W9968CF is not set +# CONFIG_USB_OV511 is not set +# CONFIG_USB_SE401 is not set +# CONFIG_USB_SN9C102 is not set +# CONFIG_USB_STV680 is not set +# CONFIG_USB_ZC0301 is not set +# CONFIG_USB_PWC is not set # # Radio Adapters @@ -934,20 +985,24 @@ CONFIG_VIDEO_DEV=y # CONFIG_RADIO_GEMTEK_PCI is not set # CONFIG_RADIO_MAXIRADIO is not set # CONFIG_RADIO_MAESTRO is not set +# CONFIG_USB_DSBR is not set # # Digital Video Broadcasting Devices # # CONFIG_DVB is not set +# CONFIG_USB_DABUSB is not set # # Graphics support # +CONFIG_FIRMWARE_EDID=y CONFIG_FB=y CONFIG_FB_CFB_FILLRECT=y CONFIG_FB_CFB_COPYAREA=y CONFIG_FB_CFB_IMAGEBLIT=y # CONFIG_FB_MACMODES is not set +# CONFIG_FB_BACKLIGHT is not set CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_TILEBLITTING is not set # CONFIG_FB_CIRRUS is not set @@ -959,7 +1014,6 @@ CONFIG_FB_MODE_HELPERS=y # CONFIG_FB_NVIDIA is not set # CONFIG_FB_RIVA is not set # CONFIG_FB_MATROX is not set -# CONFIG_FB_RADEON_OLD is not set CONFIG_FB_RADEON=y CONFIG_FB_RADEON_I2C=y CONFIG_FB_RADEON_DEBUG=y @@ -978,6 +1032,7 @@ CONFIG_FB_RADEON_DEBUG=y # Console display driver support # CONFIG_VGA_CONSOLE=y +# CONFIG_VGACON_SOFT_SCROLLBACK is not set CONFIG_DUMMY_CONSOLE=y # CONFIG_FRAMEBUFFER_CONSOLE is not set @@ -1008,9 +1063,11 @@ CONFIG_SND_SEQ_DUMMY=y CONFIG_SND_OSSEMUL=y CONFIG_SND_MIXER_OSS=y CONFIG_SND_PCM_OSS=y +CONFIG_SND_PCM_OSS_PLUGINS=y CONFIG_SND_SEQUENCER_OSS=y # CONFIG_SND_DYNAMIC_MINORS is not set CONFIG_SND_SUPPORT_OLD_API=y +CONFIG_SND_VERBOSE_PROCFS=y # CONFIG_SND_VERBOSE_PRINTK is not set # CONFIG_SND_DEBUG is not set @@ -1031,6 +1088,7 @@ CONFIG_SND_MPU401=y # PCI devices # # CONFIG_SND_AD1889 is not set +# CONFIG_SND_ALS300 is not set # CONFIG_SND_ALI5451 is not set CONFIG_SND_ATIIXP=y # CONFIG_SND_ATIIXP_MODEM is not set @@ -1043,6 +1101,18 @@ CONFIG_SND_ATIIXP=y # CONFIG_SND_CMIPCI is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_CS46XX is not set +# CONFIG_SND_DARLA20 is not set +# CONFIG_SND_GINA20 is not set +# CONFIG_SND_LAYLA20 is not set +# CONFIG_SND_DARLA24 is not set +# CONFIG_SND_GINA24 is not set +# CONFIG_SND_LAYLA24 is not set +# CONFIG_SND_MONA is not set +# CONFIG_SND_MIA is not set +# CONFIG_SND_ECHO3G is not set +# CONFIG_SND_INDIGO is not set +# CONFIG_SND_INDIGOIO is not set +# CONFIG_SND_INDIGODJ is not set # CONFIG_SND_EMU10K1 is not set # CONFIG_SND_EMU10K1X is not set # CONFIG_SND_ENS1370 is not set @@ -1063,6 +1133,7 @@ CONFIG_SND_FM801=y # CONFIG_SND_MIXART is not set # CONFIG_SND_NM256 is not set # CONFIG_SND_PCXHR is not set +# CONFIG_SND_RIPTIDE is not set # CONFIG_SND_RME32 is not set # CONFIG_SND_RME96 is not set # CONFIG_SND_RME9652 is not set @@ -1082,12 +1153,14 @@ CONFIG_SND_FM801=y # Open Sound System # CONFIG_SOUND_PRIME=y -# CONFIG_OBSOLETE_OSS_DRIVER is not set -# CONFIG_SOUND_FUSION is not set +# CONFIG_OSS_OBSOLETE_DRIVER is not set +# CONFIG_SOUND_BT878 is not set +# CONFIG_SOUND_ES1371 is not set # CONFIG_SOUND_ICH is not set # CONFIG_SOUND_TRIDENT is not set # CONFIG_SOUND_MSNDCLAS is not set # CONFIG_SOUND_MSNDPIN is not set +# CONFIG_SOUND_VIA82CXXX is not set # CONFIG_SOUND_TVMIXER is not set # @@ -1095,6 +1168,7 @@ CONFIG_SOUND_PRIME=y # CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y +CONFIG_USB_ARCH_HAS_EHCI=y CONFIG_USB=y # CONFIG_USB_DEBUG is not set @@ -1113,6 +1187,7 @@ CONFIG_USB_BANDWIDTH=y CONFIG_USB_EHCI_HCD=y # CONFIG_USB_EHCI_SPLIT_ISO is not set # CONFIG_USB_EHCI_ROOT_HUB_TT is not set +# CONFIG_USB_EHCI_TT_NEWSCHED is not set # CONFIG_USB_ISP116X_HCD is not set CONFIG_USB_OHCI_HCD=y # CONFIG_USB_OHCI_BIG_ENDIAN is not set @@ -1123,7 +1198,6 @@ CONFIG_USB_UHCI_HCD=y # # USB Device Class drivers # -# CONFIG_OBSOLETE_OSS_USB_DRIVER is not set # CONFIG_USB_ACM is not set # CONFIG_USB_PRINTER is not set @@ -1160,9 +1234,7 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_ACECAD is not set # CONFIG_USB_KBTAB is not set # CONFIG_USB_POWERMATE is not set -# CONFIG_USB_MTOUCH is not set -# CONFIG_USB_ITMTOUCH is not set -# CONFIG_USB_EGALAX is not set +# CONFIG_USB_TOUCHSCREEN is not set # CONFIG_USB_YEALINK is not set # CONFIG_USB_XPAD is not set # CONFIG_USB_ATI_REMOTE is not set @@ -1176,21 +1248,6 @@ CONFIG_USB_HIDDEV=y # CONFIG_USB_MDC800 is not set # CONFIG_USB_MICROTEK is not set -# -# USB Multimedia devices -# -# CONFIG_USB_DABUSB is not set -# CONFIG_USB_VICAM is not set -# CONFIG_USB_DSBR is not set -# CONFIG_USB_ET61X251 is not set -# CONFIG_USB_IBMCAM is not set -# CONFIG_USB_KONICAWC is not set -# CONFIG_USB_OV511 is not set -# CONFIG_USB_SE401 is not set -# CONFIG_USB_SN9C102 is not set -# CONFIG_USB_STV680 is not set -# CONFIG_USB_PWC is not set - # # USB Network Adapters # @@ -1220,10 +1277,12 @@ CONFIG_USB_MON=y # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_LCD is not set # CONFIG_USB_LED is not set +# CONFIG_USB_CYPRESS_CY7C63 is not set # CONFIG_USB_CYTHERM is not set # CONFIG_USB_PHIDGETKIT is not set # CONFIG_USB_PHIDGETSERVO is not set # CONFIG_USB_IDMOUSE is not set +# CONFIG_USB_APPLEDISPLAY is not set # CONFIG_USB_SISUSBVGA is not set # CONFIG_USB_LD is not set # CONFIG_USB_TEST is not set @@ -1242,6 +1301,19 @@ CONFIG_USB_MON=y # # CONFIG_MMC is not set +# +# LED devices +# +# CONFIG_NEW_LEDS is not set + +# +# LED drivers +# + +# +# LED Triggers +# + # # InfiniBand support # @@ -1251,6 +1323,24 @@ CONFIG_USB_MON=y # EDAC - error detection and reporting (RAS) (EXPERIMENTAL) # +# +# Real Time Clock +# +# CONFIG_RTC_CLASS is not set + +# +# DMA Engine support +# +# CONFIG_DMA_ENGINE is not set + +# +# DMA Clients +# + +# +# DMA Devices +# + # # File systems # @@ -1275,7 +1365,6 @@ CONFIG_REISERFS_FS_SECURITY=y # CONFIG_JFS_FS is not set CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=y -CONFIG_XFS_EXPORT=y # CONFIG_XFS_QUOTA is not set # CONFIG_XFS_SECURITY is not set # CONFIG_XFS_POSIX_ACL is not set @@ -1284,6 +1373,7 @@ CONFIG_XFS_EXPORT=y # CONFIG_MINIX_FS is not set # CONFIG_ROMFS_FS is not set CONFIG_INOTIFY=y +CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=y @@ -1318,7 +1408,6 @@ CONFIG_SYSFS=y CONFIG_TMPFS=y # CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y -# CONFIG_RELAYFS_FS is not set # CONFIG_CONFIGFS_FS is not set # @@ -1364,7 +1453,9 @@ CONFIG_SMB_NLS_DEFAULT=y CONFIG_SMB_NLS_REMOTE="cp437" CONFIG_CIFS=y # CONFIG_CIFS_STATS is not set +# CONFIG_CIFS_WEAK_PW_HASH is not set # CONFIG_CIFS_XATTR is not set +# CONFIG_CIFS_DEBUG2 is not set # CONFIG_CIFS_EXPERIMENTAL is not set # CONFIG_NCP_FS is not set # CONFIG_CODA_FS is not set @@ -1443,9 +1534,11 @@ CONFIG_NLS_UTF8=y # CONFIG_CRC16 is not set CONFIG_CRC32=y # CONFIG_LIBCRC32C is not set +CONFIG_PLIST=y CONFIG_GENERIC_HARDIRQS=y CONFIG_GENERIC_IRQ_PROBE=y CONFIG_GENERIC_PENDING_IRQ=y +CONFIG_IRQ_PER_CPU=y # # Instrumentation Support @@ -1458,14 +1551,19 @@ CONFIG_GENERIC_PENDING_IRQ=y # # CONFIG_PRINTK_TIME is not set CONFIG_MAGIC_SYSRQ=y +CONFIG_UNUSED_SYMBOLS=y CONFIG_DEBUG_KERNEL=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_DETECT_SOFTLOCKUP=y # CONFIG_SCHEDSTATS is not set # CONFIG_DEBUG_SLAB is not set -CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RT_MUTEXES is not set +# CONFIG_RT_MUTEX_TESTER is not set # CONFIG_DEBUG_SPINLOCK is not set +CONFIG_DEBUG_MUTEXES=y +# CONFIG_DEBUG_RWSEMS is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set +# CONFIG_DEBUG_LOCKING_API_SELFTESTS is not set # CONFIG_DEBUG_KOBJECT is not set # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_FS is not set @@ -1519,7 +1617,6 @@ CONFIG_CRYPTO_DES=y # # CONFIG_XEN_UTIL is not set CONFIG_XEN_BALLOON=y -# CONFIG_XEN_DEVMEM is not set CONFIG_XEN_REBOOT=y # CONFIG_XEN_SMPBOOT is not set CONFIG_XEN_INTERFACE_VERSION=0x00030203 @@ -1555,3 +1652,4 @@ CONFIG_XEN_COMPAT_030002_AND_LATER=y CONFIG_XEN_COMPAT_030002=y CONFIG_HAVE_IRQ_IGNORE_UNHANDLED=y CONFIG_NO_IDLE_HZ=y +CONFIG_XEN_DEVMEM=y From 0bf55ad11aee51ec964904535b7a9ba0b694870f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 30 Jan 2007 23:35:32 -0700 Subject: [PATCH 24/95] [IA64] Include dummy EFI memory descriptors for unmapped ranges This eliminates a lot of warnings about dom0 trying to do UC mappings to WB ranges. Linux doesn't deal well with holes within a granule. Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/dom_fw.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/xen/dom_fw.c b/xen/arch/ia64/xen/dom_fw.c index b122a793ca..8130486472 100644 --- a/xen/arch/ia64/xen/dom_fw.c +++ b/xen/arch/ia64/xen/dom_fw.c @@ -599,7 +599,17 @@ complete_dom0_memmap(struct domain *d, case EFI_UNUSABLE_MEMORY: case EFI_PAL_CODE: - /* Discard. */ + /* + * We don't really need these, but holes in the + * memory map may cause Linux to assume there are + * uncacheable ranges within a granule. + */ + dom_md->type = EFI_UNUSABLE_MEMORY; + dom_md->phys_addr = start; + dom_md->virt_addr = 0; + dom_md->num_pages = (end - start) >> EFI_PAGE_SHIFT; + dom_md->attribute = EFI_MEMORY_WB; + num_mds++; break; default: From 2353f24ee82062624cca85f70bf7d9fa288908bd Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Wed, 31 Jan 2007 10:59:56 -0700 Subject: [PATCH 25/95] [IA64] Add arch_free_page() Without this, Linux can hit bad_page() Signed-off-by: Isaku Yamahata --- linux-2.6-xen-sparse/include/asm-ia64/page.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/linux-2.6-xen-sparse/include/asm-ia64/page.h b/linux-2.6-xen-sparse/include/asm-ia64/page.h index 4641560dab..c4b69c9e8e 100644 --- a/linux-2.6-xen-sparse/include/asm-ia64/page.h +++ b/linux-2.6-xen-sparse/include/asm-ia64/page.h @@ -238,6 +238,15 @@ get_order (unsigned long size) #include // to compile netback, netfront #include +#define arch_free_page(_page, _order) \ +({ \ + int foreign = PageForeign(_page); \ + if (foreign) \ + PageForeignDestructor(_page); \ + foreign; \ +}) +#define HAVE_ARCH_FREE_PAGE + #endif /* CONFIG_XEN */ #endif /* __ASSEMBLY__ */ From 3b8a7d56a4778c6d10bfabff162b12619b04a7ca Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Thu, 1 Feb 2007 12:53:34 -0700 Subject: [PATCH 26/95] [IA64] Optimize VTI domain hypercall path Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_entry.S | 192 +++++++++++++++++++- xen/arch/ia64/vmx/vmx_ivt.S | 291 ++++++++++++++++++++++++++++++- xen/arch/ia64/vmx/vmx_minstate.h | 1 + xen/arch/ia64/vmx/vmx_process.c | 2 +- 4 files changed, 473 insertions(+), 13 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index 0bdfc3bb82..48a516d36c 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -190,12 +190,8 @@ GLOBAL_ENTRY(ia64_leave_hypervisor) PT_REGS_UNWIND_INFO(0) rsm psr.i ;; - alloc loc0=ar.pfs,0,1,1,0 - ;; - adds out0=16,r12 br.call.sptk.many b0=leave_hypervisor_tail ;; - mov ar.pfs=loc0 adds r20=PT(PR)+16,r12 adds r8=PT(EML_UNAT)+16,r12 ;; @@ -302,11 +298,9 @@ GLOBAL_ENTRY(ia64_leave_hypervisor) ;; mov ar.fpsr=r19 mov ar.ccv=r18 - ;; -//rbs_switch - shr.u r18=r20,16 ;; +vmx_rbs_switch: movl r19= THIS_CPU(ia64_phys_stacked_size_p8) ;; ld4 r19=[r19] @@ -368,7 +362,7 @@ vmx_rse_clear_invalid: ;; mov cr.ipsr=r31 mov cr.iip=r30 - mov cr.ifs=r29 +(pNonSys) mov cr.ifs=r29 mov ar.pfs=r27 adds r18=IA64_VPD_BASE_OFFSET,r21 ;; @@ -425,6 +419,188 @@ ia64_vmm_entry_out: END(ia64_vmm_entry) + +/* + * ia64_leave_syscall(): Same as ia64_leave_kernel, except that it doesn't + * need to switch to bank 0 and doesn't restore the scratch registers. + * To avoid leaking kernel bits, the scratch registers are set to + * the following known-to-be-safe values: + * + * r1: restored (global pointer) + * r2: cleared + * r3: 1 (when returning to user-level) + * r8-r11: restored (syscall return value(s)) + * r12: restored (user-level stack pointer) + * r13: restored (user-level thread pointer) + * r14: set to __kernel_syscall_via_epc + * r15: restored (syscall #) + * r16-r17: cleared + * r18: user-level b6 + * r19: cleared + * r20: user-level ar.fpsr + * r21: user-level b0 + * r22: cleared + * r23: user-level ar.bspstore + * r24: user-level ar.rnat + * r25: user-level ar.unat + * r26: user-level ar.pfs + * r27: user-level ar.rsc + * r28: user-level ip + * r29: user-level psr + * r30: user-level cfm + * r31: user-level pr + * f6-f11: cleared + * pr: restored (user-level pr) + * b0: restored (user-level rp) + * b6: restored + * b7: set to __kernel_syscall_via_epc + * ar.unat: restored (user-level ar.unat) + * ar.pfs: restored (user-level ar.pfs) + * ar.rsc: restored (user-level ar.rsc) + * ar.rnat: restored (user-level ar.rnat) + * ar.bspstore: restored (user-level ar.bspstore) + * ar.fpsr: restored (user-level ar.fpsr) + * ar.ccv: cleared + * ar.csd: cleared + * ar.ssd: cleared + */ +GLOBAL_ENTRY(ia64_leave_hypercall) + PT_REGS_UNWIND_INFO(0) + /* + * work.need_resched etc. mustn't get changed by this CPU before it returns to + * user- or fsys-mode, hence we disable interrupts early on. + * + * p6 controls whether current_thread_info()->flags needs to be check for + * extra work. We always check for extra work when returning to user-level. + * With CONFIG_PREEMPT, we also check for extra work when the preempt_count + * is 0. After extra work processing has been completed, execution + * resumes at .work_processed_syscall with p6 set to 1 if the extra-work-check + * needs to be redone. + */ +(pUStk) rsm psr.i + cmp.eq pLvSys,p0=r0,r0 // pLvSys=1: leave from syscall +(pUStk) cmp.eq.unc p6,p0=r0,r0 // p6 <- pUStk + ;; + br.call.sptk.many b0=leave_hypervisor_tail +.work_processed_syscall: + //clean up bank 1 registers + mov r16=r0 + mov r17=r0 + mov r18=r0 + mov r19=r0 + mov r20=r0 + mov r21=r0 + mov r22=r0 + mov r23=r0 + mov r24=r0 + mov r25=r0 + mov r26=r0 + mov r27=r0 + mov r28=r0 + mov r29=r0 + mov r30=r0 + mov r31=r0 + bsw.0 + ;; + adds r2=PT(LOADRS)+16,r12 + adds r3=PT(AR_BSPSTORE)+16,r12 +#ifndef XEN + adds r18=TI_FLAGS+IA64_TASK_SIZE,r13 + ;; +(p6) ld4 r31=[r18] // load current_thread_info()->flags +#endif + ;; + ld8 r20=[r2],PT(B6)-PT(LOADRS) // load ar.rsc value for "loadrs" + nop.i 0 + ;; +// mov r16=ar.bsp // M2 get existing backing store pointer + ld8 r18=[r2],PT(R9)-PT(B6) // load b6 +#ifndef XEN +(p6) and r15=TIF_WORK_MASK,r31 // any work other than TIF_SYSCALL_TRACE? +#endif + ;; + ld8 r24=[r3],PT(R11)-PT(AR_BSPSTORE) // load ar.bspstore (may be garbage) +#ifndef XEN +(p6) cmp4.ne.unc p6,p0=r15, r0 // any special work pending? +(p6) br.cond.spnt .work_pending_syscall +#endif + ;; + // start restoring the state saved on the kernel stack (struct pt_regs): + ld8 r9=[r2],PT(CR_IPSR)-PT(R9) + ld8 r11=[r3],PT(CR_IIP)-PT(R11) +//(pNonSys) break 0 // bug check: we shouldn't be here if pNonSys is TRUE! + ;; + invala // M0|1 invalidate ALAT + rsm psr.i | psr.ic // M2 turn off interrupts and interruption collection + cmp.eq p9,p0=r0,r0 // A set p9 to indicate that we should restore cr.ifs + + ld8 r31=[r2],32 // M0|1 load cr.ipsr + ld8 r30=[r3],16 // M0|1 load cr.iip + ;; +// ld8 r29=[r2],16 // M0|1 load cr.ifs + ld8 r28=[r3],16 // M0|1 load ar.unat +//(pUStk) add r14=IA64_TASK_THREAD_ON_USTACK_OFFSET,r13 + ;; + ld8 r27=[r2],PT(B0)-PT(AR_PFS) // M0|1 load ar.pfs +(pKStk) mov r22=psr // M2 read PSR now that interrupts are disabled + nop 0 + ;; + ld8 r22=[r2],PT(AR_RNAT)-PT(B0) // M0|1 load b0 + ld8 r26=[r3],PT(PR)-PT(AR_RSC) // M0|1 load ar.rsc + mov f6=f0 // F clear f6 + ;; + ld8 r25=[r2],PT(AR_FPSR)-PT(AR_RNAT) // M0|1 load ar.rnat (may be garbage) + ld8 r23=[r3],PT(R1)-PT(PR) // M0|1 load predicates + mov f7=f0 // F clear f7 + ;; + ld8 r20=[r2],PT(R12)-PT(AR_FPSR) // M0|1 load ar.fpsr + ld8.fill r1=[r3],16 // M0|1 load r1 +//(pUStk) mov r17=1 // A + ;; +//(pUStk) st1 [r14]=r17 // M2|3 + ld8.fill r13=[r3],16 // M0|1 + mov f8=f0 // F clear f8 + ;; + ld8.fill r12=[r2] // M0|1 restore r12 (sp) +#ifdef XEN + ld8.fill r2=[r3] // M0|1 +#else + ld8.fill r15=[r3] // M0|1 restore r15 +#endif + mov b6=r18 // I0 restore b6 + mov ar.fpsr=r20 +// addl r17=THIS_CPU(ia64_phys_stacked_size_p8),r0 // A + mov f9=f0 // F clear f9 +//(pKStk) br.cond.dpnt.many skip_rbs_switch // B + +// srlz.d // M0 ensure interruption collection is off (for cover) +// shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition + cover // B add current frame into dirty partition & set cr.ifs + ;; +//(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 + mov r19=ar.bsp // M2 get new backing store pointer + adds r18=IA64_RBS_OFFSET, r21 + ;; + sub r18=r19,r18 // get byte size of existing "dirty" partition + ;; + shl r20=r18,16 // set rsc.load + mov f10=f0 // F clear f10 +#ifdef XEN + mov r14=r0 +#else + movl r14=__kernel_syscall_via_epc // X +#endif + ;; + mov.m ar.csd=r0 // M2 clear ar.csd + mov.m ar.ccv=r0 // M2 clear ar.ccv + mov b7=r14 // I0 clear b7 (hint with __kernel_syscall_via_epc) + + mov.m ar.ssd=r0 // M2 clear ar.ssd + mov f11=f0 // F clear f11 + br.cond.sptk.many vmx_rbs_switch // B +END(ia64_leave_hypercall) + + /* * in0: new rr7 * in1: virtual address of shared_info diff --git a/xen/arch/ia64/vmx/vmx_ivt.S b/xen/arch/ia64/vmx/vmx_ivt.S index cf9b554298..de2b0ba9eb 100644 --- a/xen/arch/ia64/vmx/vmx_ivt.S +++ b/xen/arch/ia64/vmx/vmx_ivt.S @@ -59,6 +59,14 @@ #include #include #include +#include + +#if 1 +# define PSR_DEFAULT_BITS psr.ac +#else +# define PSR_DEFAULT_BITS 0 +#endif + #ifdef VTI_DEBUG /* @@ -431,17 +439,152 @@ ENTRY(vmx_break_fault) VMX_DBG_FAULT(11) mov r31=pr mov r19=11 - mov r30=cr.iim + mov r17=cr.iim ;; #ifdef VTI_DEBUG // break 0 is already handled in vmx_ia64_handle_break. - cmp.eq p6,p7=r30,r0 + cmp.eq p6,p7=r17,r0 (p6) br.sptk vmx_fault_11 ;; #endif - br.sptk.many vmx_dispatch_break_fault + mov r29=cr.ipsr + adds r22=IA64_VCPU_BREAKIMM_OFFSET, r21 ;; - VMX_FAULT(11); + ld4 r22=[r22] + extr.u r24=r29,IA64_PSR_CPL0_BIT,2 + cmp.eq p0,p6=r0,r0 + ;; + cmp.ne.or p6,p0=r22,r17 + cmp.ne.or p6,p0=r0,r24 +(p6) br.sptk.many vmx_dispatch_break_fault + ;; + /* + * The streamlined system call entry/exit paths only save/restore the initial part + * of pt_regs. This implies that the callers of system-calls must adhere to the + * normal procedure calling conventions. + * + * Registers to be saved & restored: + * CR registers: cr.ipsr, cr.iip, cr.ifs + * AR registers: ar.unat, ar.pfs, ar.rsc, ar.rnat, ar.bspstore, ar.fpsr + * others: pr, b0, b6, loadrs, r1, r11, r12, r13, r15 + * Registers to be restored only: + * r8-r11: output value from the system call. + * + * During system call exit, scratch registers (including r15) are modified/cleared + * to prevent leaking bits from kernel to user level. + */ + +// mov.m r16=IA64_KR(CURRENT) // M2 r16 <- current task (12 cyc) + mov r14=r21 + bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + ;; + mov r29=cr.ipsr // M2 (12 cyc) + mov r31=pr // I0 (2 cyc) + mov r16=r14 + mov r15=r2 + + mov r17=cr.iim // M2 (2 cyc) + mov.m r27=ar.rsc // M2 (12 cyc) +// mov r18=__IA64_BREAK_SYSCALL // A + + mov.m ar.rsc=0 // M2 + mov.m r21=ar.fpsr // M2 (12 cyc) + mov r19=b6 // I0 (2 cyc) + ;; + mov.m r23=ar.bspstore // M2 (12 cyc) + mov.m r24=ar.rnat // M2 (5 cyc) + mov.i r26=ar.pfs // I0 (2 cyc) + + invala // M0|1 + nop.m 0 // M + mov r20=r1 // A save r1 + + nop.m 0 +// movl r30=sys_call_table // X + movl r30=ia64_hypercall_table // X + + mov r28=cr.iip // M2 (2 cyc) +// cmp.eq p0,p7=r18,r17 // I0 is this a system call? +//(p7) br.cond.spnt non_syscall // B no -> + // + // From this point on, we are definitely on the syscall-path + // and we can use (non-banked) scratch registers. + // +/////////////////////////////////////////////////////////////////////// + mov r1=r16 // A move task-pointer to "addl"-addressable reg + mov r2=r16 // A setup r2 for ia64_syscall_setup +// add r9=TI_FLAGS+IA64_TASK_SIZE,r16 // A r9 = ¤t_thread_info()->flags + +// adds r16=IA64_TASK_THREAD_ON_USTACK_OFFSET,r16 +// adds r15=-1024,r15 // A subtract 1024 from syscall number +// mov r3=NR_syscalls - 1 + mov r3=NR_hypercalls - 1 + ;; +// ld1.bias r17=[r16] // M0|1 r17 = current->thread.on_ustack flag +// ld4 r9=[r9] // M0|1 r9 = current_thread_info()->flags + mov r9=r0 // force flags = 0 + extr.u r8=r29,41,2 // I0 extract ei field from cr.ipsr + + shladd r30=r15,3,r30 // A r30 = sys_call_table + 8*(syscall-1024) + addl r22=IA64_RBS_OFFSET,r1 // A compute base of RBS + cmp.leu p6,p7=r15,r3 // A syscall number in range? + ;; + + lfetch.fault.excl.nt1 [r22] // M0|1 prefetch RBS +(p6) ld8 r30=[r30] // M0|1 load address of syscall entry point + tnat.nz.or p7,p0=r15 // I0 is syscall nr a NaT? + + mov.m ar.bspstore=r22 // M2 switch to kernel RBS + cmp.eq p8,p9=2,r8 // A isr.ei==2? + ;; + +(p8) mov r8=0 // A clear ei to 0 +//(p7) movl r30=sys_ni_syscall // X +(p7) movl r30=do_ni_hypercall // X + +(p8) adds r28=16,r28 // A switch cr.iip to next bundle +(p9) adds r8=1,r8 // A increment ei to next slot + nop.i 0 + ;; + + mov.m r25=ar.unat // M2 (5 cyc) + dep r29=r8,r29,41,2 // I0 insert new ei into cr.ipsr +// adds r15=1024,r15 // A restore original syscall number + // + // If any of the above loads miss in L1D, we'll stall here until + // the data arrives. + // +/////////////////////////////////////////////////////////////////////// +// st1 [r16]=r0 // M2|3 clear current->thread.on_ustack flag + mov b6=r30 // I0 setup syscall handler branch reg early + cmp.ne pKStk,pUStk=r0,r0 // A were we on kernel stacks already? + +// and r9=_TIF_SYSCALL_TRACEAUDIT,r9 // A mask trace or audit + mov r18=ar.bsp // M2 (12 cyc) + ;; +(pUStk) addl r1=IA64_STK_OFFSET-IA64_PT_REGS_SIZE,r1 // A compute base of memory stack +// cmp.eq p14,p0=r9,r0 // A are syscalls being traced/audited? +// br.call.sptk.many b7=ia64_syscall_setup // B + br.call.sptk.many b7=ia64_hypercall_setup // B +1: + mov ar.rsc=0x3 // M2 set eager mode, pl 0, LE, loadrs=0 +// nop 0 +// bsw.1 // B (6 cyc) regs are saved, switch to bank 1 + ;; + ssm psr.ic | PSR_DEFAULT_BITS // M2 now it's safe to re-enable intr.-collection +// movl r3=ia64_ret_from_syscall // X + movl r3=ia64_leave_hypercall // X + ;; + + srlz.i // M0 ensure interruption collection is on + mov rp=r3 // I0 set the real return addr + //(p10) br.cond.spnt.many ia64_ret_from_syscall // B return if bad call-frame or r15 is a NaT + (p15) ssm psr.i // M2 restore psr.i + //(p14) br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) + br.call.sptk.many b6=b6 // B invoke syscall-handker (ignore return addr) +// br.cond.spnt.many ia64_trace_syscall // B do syscall-tracing thingamagic + ;; + VMX_FAULT(11) END(vmx_break_fault) .org vmx_ia64_ivt+0x3000 @@ -613,6 +756,146 @@ END(vmx_virtual_exirq) // 0x3800 Entry 14 (size 64 bundles) Reserved VMX_DBG_FAULT(14) VMX_FAULT(14) + // this code segment is from 2.6.16.13 + + /* + * There is no particular reason for this code to be here, other than that + * there happens to be space here that would go unused otherwise. If this + * fault ever gets "unreserved", simply moved the following code to a more + * suitable spot... + * + * ia64_syscall_setup() is a separate subroutine so that it can + * allocate stacked registers so it can safely demine any + * potential NaT values from the input registers. + * + * On entry: + * - executing on bank 0 or bank 1 register set (doesn't matter) + * - r1: stack pointer + * - r2: current task pointer + * - r3: preserved + * - r11: original contents (saved ar.pfs to be saved) + * - r12: original contents (sp to be saved) + * - r13: original contents (tp to be saved) + * - r15: original contents (syscall # to be saved) + * - r18: saved bsp (after switching to kernel stack) + * - r19: saved b6 + * - r20: saved r1 (gp) + * - r21: saved ar.fpsr + * - r22: kernel's register backing store base (krbs_base) + * - r23: saved ar.bspstore + * - r24: saved ar.rnat + * - r25: saved ar.unat + * - r26: saved ar.pfs + * - r27: saved ar.rsc + * - r28: saved cr.iip + * - r29: saved cr.ipsr + * - r31: saved pr + * - b0: original contents (to be saved) + * On exit: + * - p10: TRUE if syscall is invoked with more than 8 out + * registers or r15's Nat is true + * - r1: kernel's gp + * - r3: preserved (same as on entry) + * - r8: -EINVAL if p10 is true + * - r12: points to kernel stack + * - r13: points to current task + * - r14: preserved (same as on entry) + * - p13: preserved + * - p15: TRUE if interrupts need to be re-enabled + * - ar.fpsr: set to kernel settings + * - b6: preserved (same as on entry) + */ +GLOBAL_ENTRY(ia64_hypercall_setup) +#if PT(B6) != 0 +# error This code assumes that b6 is the first field in pt_regs. +#endif + st8 [r1]=r19 // save b6 + add r16=PT(CR_IPSR),r1 // initialize first base pointer + add r17=PT(R11),r1 // initialize second base pointer + ;; + alloc r19=ar.pfs,8,0,0,0 // ensure in0-in7 are writable + st8 [r16]=r29,PT(AR_PFS)-PT(CR_IPSR) // save cr.ipsr + tnat.nz p8,p0=in0 + + st8.spill [r17]=r11,PT(CR_IIP)-PT(R11) // save r11 + tnat.nz p9,p0=in1 +(pKStk) mov r18=r0 // make sure r18 isn't NaT + ;; + + st8 [r16]=r26,PT(CR_IFS)-PT(AR_PFS) // save ar.pfs + st8 [r17]=r28,PT(AR_UNAT)-PT(CR_IIP) // save cr.iip + mov r28=b0 // save b0 (2 cyc) + ;; + + st8 [r17]=r25,PT(AR_RSC)-PT(AR_UNAT) // save ar.unat + dep r19=0,r19,38,26 // clear all bits but 0..37 [I0] +(p8) mov in0=-1 + ;; + + st8 [r16]=r19,PT(AR_RNAT)-PT(CR_IFS) // store ar.pfs.pfm in cr.ifs + extr.u r11=r19,7,7 // I0 // get sol of ar.pfs + and r8=0x7f,r19 // A // get sof of ar.pfs + + st8 [r17]=r27,PT(AR_BSPSTORE)-PT(AR_RSC)// save ar.rsc + tbit.nz p15,p0=r29,IA64_PSR_I_BIT // I0 +(p9) mov in1=-1 + ;; + +(pUStk) sub r18=r18,r22 // r18=RSE.ndirty*8 + tnat.nz p10,p0=in2 + add r11=8,r11 + ;; +(pKStk) adds r16=PT(PR)-PT(AR_RNAT),r16 // skip over ar_rnat field +(pKStk) adds r17=PT(B0)-PT(AR_BSPSTORE),r17 // skip over ar_bspstore field + tnat.nz p11,p0=in3 + ;; +(p10) mov in2=-1 + tnat.nz p12,p0=in4 // [I0] +(p11) mov in3=-1 + ;; +(pUStk) st8 [r16]=r24,PT(PR)-PT(AR_RNAT) // save ar.rnat +(pUStk) st8 [r17]=r23,PT(B0)-PT(AR_BSPSTORE) // save ar.bspstore + shl r18=r18,16 // compute ar.rsc to be used for "loadrs" + ;; + st8 [r16]=r31,PT(LOADRS)-PT(PR) // save predicates + st8 [r17]=r28,PT(R1)-PT(B0) // save b0 + tnat.nz p13,p0=in5 // [I0] + ;; + st8 [r16]=r18,PT(R12)-PT(LOADRS) // save ar.rsc value for "loadrs" + st8.spill [r17]=r20,PT(R13)-PT(R1) // save original r1 +(p12) mov in4=-1 + ;; + +.mem.offset 0,0; st8.spill [r16]=r12,PT(AR_FPSR)-PT(R12) // save r12 +.mem.offset 8,0; st8.spill [r17]=r13,PT(R15)-PT(R13) // save r13 +(p13) mov in5=-1 + ;; + st8 [r16]=r21,PT(R8)-PT(AR_FPSR) // save ar.fpsr + tnat.nz p13,p0=in6 + cmp.lt p10,p9=r11,r8 // frame size can't be more than local+8 + ;; + mov r8=1 +(p9) tnat.nz p10,p0=r15 + adds r12=-16,r1 // switch to kernel memory stack (with 16 bytes of scratch) + + st8.spill [r17]=r15 // save r15 + tnat.nz p8,p0=in7 + nop.i 0 + + mov r13=r2 // establish `current' + movl r1=__gp // establish kernel global pointer + ;; + st8 [r16]=r8 // ensure pt_regs.r8 != 0 (see handle_syscall_error) +(p13) mov in6=-1 +(p8) mov in7=-1 + + cmp.eq pSys,pNonSys=r0,r0 // set pSys=1, pNonSys=0 + movl r17=FPSR_DEFAULT + ;; + mov.m ar.fpsr=r17 // set ar.fpsr to kernel default value +(p10) mov r8=-EINVAL + br.ret.sptk.many b7 +END(ia64_hypercall_setup) .org vmx_ia64_ivt+0x3c00 diff --git a/xen/arch/ia64/vmx/vmx_minstate.h b/xen/arch/ia64/vmx/vmx_minstate.h index 8ac2c73f92..02a60ec07a 100644 --- a/xen/arch/ia64/vmx/vmx_minstate.h +++ b/xen/arch/ia64/vmx/vmx_minstate.h @@ -174,6 +174,7 @@ ;; \ st8 [r16]=r29,16; /* save b0 */ \ st8 [r17]=r18,16; /* save ar.rsc value for "loadrs" */ \ + cmp.eq pNonSys,pSys=r0,r0 /* initialize pSys=0, pNonSys=1 */ \ ;; \ .mem.offset 0,0; st8.spill [r16]=r20,16; /* save original r1 */ \ .mem.offset 8,0; st8.spill [r17]=r12,16; \ diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 7e1c1ab3bd..37f8780426 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -214,7 +214,7 @@ void save_banked_regs_to_vpd(VCPU *v, REGS *regs) // ONLY gets called from ia64_leave_kernel // ONLY call with interrupts disabled?? (else might miss one?) // NEVER successful if already reflecting a trap/fault because psr.i==0 -void leave_hypervisor_tail(struct pt_regs *regs) +void leave_hypervisor_tail(void) { struct domain *d = current->domain; struct vcpu *v = current; From 33ff2afbc0a09f1fa1e6e758bc9da99bf57de240 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Thu, 1 Feb 2007 13:54:26 -0700 Subject: [PATCH 27/95] [IA64] Fix compile warnings in xenentry.S Signed-off-by: Akio Takebe --- linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S index 08676b88f8..08bd970460 100644 --- a/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S +++ b/linux-2.6-xen-sparse/arch/ia64/xen/xenentry.S @@ -124,6 +124,8 @@ GLOBAL_ENTRY(ia64_switch_to) ;; itr.d dtr[r25]=r23 // wire in new mapping... #ifdef CONFIG_XEN + ;; + srlz.d mov r9=1 movl r8=XSI_PSR_IC ;; From 9aee93077301b348e869b8c0410e47f5f09d15ab Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 11:28:54 -0700 Subject: [PATCH 28/95] [IA64] Bug fix new_tlbflush_clock_period() __vhpt_flush() might be called from new_tlbflush_clock_period() even if the vcpu doesn't have the per-vcpu-vhpt. It erases 64KB memory content that starts from machine address 0. Signed-off-by: Kouya Shimura --- xen/arch/ia64/xen/flushtlb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/ia64/xen/flushtlb.c b/xen/arch/ia64/xen/flushtlb.c index 0c77c1b6df..c7008db3ff 100644 --- a/xen/arch/ia64/xen/flushtlb.c +++ b/xen/arch/ia64/xen/flushtlb.c @@ -88,6 +88,8 @@ new_tlbflush_clock_period(void) smp_mb(); for_each_domain(d) { for_each_vcpu(d, v) { + if (!test_bit(_VCPUF_initialised, &v->vcpu_flags) || VMX_DOMAIN(v)) + continue; if (HAS_PERVCPU_VHPT(v->domain)) vcpu_vhpt_flush(v); } From 4d4ed60a2cf30c0de744eb4fac37772cca1c390b Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 11:36:12 -0700 Subject: [PATCH 29/95] [IA64] Fix PAL_HALT for paravirtualized domains machine_halt() stops the vcpus, but no longer destroys the domain. This should be more in-line with the behavior on native hardware. Signed-off-by: Akio Takebe --- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 8 ++++++++ xen/arch/ia64/xen/fw_emul.c | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index a56bbbdc53..74f21997c7 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -95,6 +95,13 @@ xen_panic_event(struct notifier_block *this, unsigned long event, void *ptr) static struct notifier_block xen_panic_block = { xen_panic_event, NULL, 0 /* try to go last */ }; + +void xen_pm_power_off(void) +{ + printk("%s called\n", __FUNCTION__); + local_irq_disable(); + HYPERVISOR_shutdown(SHUTDOWN_poweroff); +} #endif extern void ia64_setup_printk_clock(void); @@ -456,6 +463,7 @@ setup_arch (char **cmdline_p) /* Register a call for panic conditions. */ atomic_notifier_chain_register(&panic_notifier_list, &xen_panic_block); + pm_power_off = xen_pm_power_off; } #endif diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 2a9f8fcb53..905d29c6fd 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -605,9 +605,11 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3) printk ("Domain0 halts the machine\n"); console_start_sync(); (*efi.reset_system)(EFI_RESET_SHUTDOWN,0,0,NULL); + } else { + set_bit(_VCPUF_down, ¤t->vcpu_flags); + vcpu_sleep_nosync(current); + status = PAL_STATUS_SUCCESS; } - else - domain_shutdown(current->domain, SHUTDOWN_poweroff); break; case PAL_HALT_LIGHT: if (VMX_DOMAIN(current)) { From a91d0a10c5207a48cf8fc06ca88c98c900aa17a7 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 11:37:48 -0700 Subject: [PATCH 30/95] [IA64] Fix xencons_early_setup build warning Signed-off-by: Akio Takebe --- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 1 + 1 file changed, 1 insertion(+) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index 74f21997c7..f3ad6143dc 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -63,6 +63,7 @@ #ifdef CONFIG_XEN #include #include +#include #endif #include From e56135da179e64b1abfe4c463bcfa4ba08c6922f Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 11:41:25 -0700 Subject: [PATCH 31/95] [IA64] Fix usage of 14 bit immediate value of IA64_RBS_OFFSET Limit is exceeded w/ 16k page size Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_entry.S | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index 48a516d36c..1e0b85b313 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -575,12 +575,14 @@ GLOBAL_ENTRY(ia64_leave_hypercall) // srlz.d // M0 ensure interruption collection is off (for cover) // shr.u r18=r19,16 // I0|1 get byte size of existing "dirty" partition + mov r3=r21 cover // B add current frame into dirty partition & set cr.ifs ;; //(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 mov r19=ar.bsp // M2 get new backing store pointer - adds r18=IA64_RBS_OFFSET, r21 + adds r18=IA64_RBS_OFFSET, r3 ;; + mov r3=r0 sub r18=r19,r18 // get byte size of existing "dirty" partition ;; shl r20=r18,16 // set rsc.load From d11e9be9c47b95bb7278f090d4dd24e35ac73c47 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 12:06:59 -0700 Subject: [PATCH 32/95] [IA64] Xen build warning fixes Missing include and remove an sprintf Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/xensetup.c | 1 + xen/include/asm-ia64/linux-xen/linux/efi.h | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 84a93d5046..37de379e2a 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -27,6 +27,7 @@ #include #include #include +#include unsigned long xenheap_phys_end, total_pages; diff --git a/xen/include/asm-ia64/linux-xen/linux/efi.h b/xen/include/asm-ia64/linux-xen/linux/efi.h index 73781ec165..2eb12715a1 100644 --- a/xen/include/asm-ia64/linux-xen/linux/efi.h +++ b/xen/include/asm-ia64/linux-xen/linux/efi.h @@ -280,7 +280,11 @@ efi_guidcmp (efi_guid_t left, efi_guid_t right) static inline char * efi_guid_unparse(efi_guid_t *guid, char *out) { +#ifndef XEN sprintf(out, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", +#else + snprintf(out, 37, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", +#endif guid->b[3], guid->b[2], guid->b[1], guid->b[0], guid->b[5], guid->b[4], guid->b[7], guid->b[6], guid->b[8], guid->b[9], guid->b[10], guid->b[11], From c4c9842abd9d1a40956ee11433244ff4f73055c1 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Sun, 4 Feb 2007 12:18:48 -0700 Subject: [PATCH 33/95] [IA64] Remove verbosity from xen_pm_power_off Signed-off-by: Alex Williamson --- linux-2.6-xen-sparse/arch/ia64/kernel/setup.c | 1 - 1 file changed, 1 deletion(-) diff --git a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c index f3ad6143dc..1fd352463c 100644 --- a/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c +++ b/linux-2.6-xen-sparse/arch/ia64/kernel/setup.c @@ -99,7 +99,6 @@ static struct notifier_block xen_panic_block = { void xen_pm_power_off(void) { - printk("%s called\n", __FUNCTION__); local_irq_disable(); HYPERVISOR_shutdown(SHUTDOWN_poweroff); } From 6b50b2d9039bbfc121ec5afb28305d58509e41ac Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Mon, 5 Feb 2007 13:55:47 -0700 Subject: [PATCH 34/95] [IA64] Additional HVM hypercall fix Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_entry.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vmx_entry.S b/xen/arch/ia64/vmx/vmx_entry.S index 1e0b85b313..74bf2ca4d3 100644 --- a/xen/arch/ia64/vmx/vmx_entry.S +++ b/xen/arch/ia64/vmx/vmx_entry.S @@ -580,7 +580,7 @@ GLOBAL_ENTRY(ia64_leave_hypercall) ;; //(pUStk) ld4 r17=[r17] // M0|1 r17 = cpu_data->phys_stacked_size_p8 mov r19=ar.bsp // M2 get new backing store pointer - adds r18=IA64_RBS_OFFSET, r3 + addl r18=IA64_RBS_OFFSET, r3 ;; mov r3=r0 sub r18=r19,r18 // get byte size of existing "dirty" partition From 570b1fe16eb2edd4a9eeae83ab1e075fd9d899a3 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Mon, 5 Feb 2007 14:24:27 -0700 Subject: [PATCH 35/95] [IA64] Fix tlbflush_clock arch_vcpu.tlbflush_timestamp is unused and new_tlbflush_clock_period() flushes vhpt unnecessarily. Signed-off-by: Isaku Yamahata --- xen/arch/ia64/xen/domain.c | 3 --- xen/arch/ia64/xen/flushtlb.c | 44 +++++++---------------------------- xen/arch/ia64/xen/vhpt.c | 4 ---- xen/include/asm-ia64/domain.h | 3 --- 4 files changed, 8 insertions(+), 46 deletions(-) diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 4f870ff7cd..6b76df3e58 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -448,9 +448,6 @@ int vcpu_late_initialise(struct vcpu *v) assign_domain_page(d, IA64_XMAPPEDREGS_PADDR(v->vcpu_id) + i, virt_to_maddr(v->arch.privregs + i)); - tlbflush_update_time(&v->arch.tlbflush_timestamp, - tlbflush_current_time()); - return 0; } diff --git a/xen/arch/ia64/xen/flushtlb.c b/xen/arch/ia64/xen/flushtlb.c index c7008db3ff..19aabf6c50 100644 --- a/xen/arch/ia64/xen/flushtlb.c +++ b/xen/arch/ia64/xen/flushtlb.c @@ -59,46 +59,18 @@ tlbflush_clock_inc_and_return(void) return t2; } +static void +tlbflush_clock_local_flush(void *unused) +{ + local_vhpt_flush(); + local_flush_tlb_all(); +} + void new_tlbflush_clock_period(void) { - /* - *XXX TODO - * If flushing all vcpu's vhpt takes too long, it can be done backgroundly. - * In such case tlbflush time comparison is done using only 31bit - * similar to linux jiffies comparison. - * vhpt should be flushed gradually before wraping 31bits. - * - * Sample calculation. - * Currently Xen/IA64 can create up to 64 domains at the same time. - * Vhpt size is currently 64KB. (This might be changed later though) - * Suppose each domains have 4 vcpus (or 16 vcpus). - * then the memory size which must be flushed is 16MB (64MB). - */ - struct domain* d; - struct vcpu* v; - /* flush all vhpt of vcpu of all existing domain. */ - read_lock(&domlist_lock); - for_each_domain(d) { - for_each_vcpu(d, v) { - vcpu_purge_tr_entry(&PSCBX(v,dtlb)); - vcpu_purge_tr_entry(&PSCBX(v,itlb)); - } - } - smp_mb(); - for_each_domain(d) { - for_each_vcpu(d, v) { - if (!test_bit(_VCPUF_initialised, &v->vcpu_flags) || VMX_DOMAIN(v)) - continue; - if (HAS_PERVCPU_VHPT(v->domain)) - vcpu_vhpt_flush(v); - } - } - read_unlock(&domlist_lock); - /* unlock has release semantics */ - /* flush all vhpt of physical cpu and mTLB */ - on_each_cpu((void (*)(void *))local_flush_tlb_all, NULL, 1, 1); + on_each_cpu(tlbflush_clock_local_flush, NULL, 1, 1); /* * if global TLB shootdown is finished, increment tlbflush_time diff --git a/xen/arch/ia64/xen/vhpt.c b/xen/arch/ia64/xen/vhpt.c index 67341328de..d5bae1156a 100644 --- a/xen/arch/ia64/xen/vhpt.c +++ b/xen/arch/ia64/xen/vhpt.c @@ -54,11 +54,7 @@ local_vhpt_flush(void) void vcpu_vhpt_flush(struct vcpu* v) { - /* increment flush clock before flush */ - u32 flush_time = tlbflush_clock_inc_and_return(); __vhpt_flush(vcpu_vhpt_maddr(v)); - /* this must be after flush */ - tlbflush_update_time(&v->arch.tlbflush_timestamp, flush_time); perfc_incrc(vcpu_vhpt_flush); } diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index 82a54c28b5..ce734c8677 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -200,9 +200,6 @@ struct arch_vcpu { struct page_info* vhpt_page; unsigned long vhpt_entries; #endif -#ifdef CONFIG_XEN_IA64_TLBFLUSH_CLOCK - u32 tlbflush_timestamp; -#endif #define INVALID_PROCESSOR INT_MAX int last_processor; }; From 8f3bd63696257f2a644eb7fb34efe1aa04709ce5 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Mon, 5 Feb 2007 15:23:39 -0700 Subject: [PATCH 36/95] [IA64] Turn on dcr.dm inside XEN For xeno, dcr.dm is alway set to 1, For VTI-domain, if guest cpl > 0, dcr.dm is set to 1, if guest cpl == 0, dcr.dm is set to 0, This is because Window ld.s on tr mapped page. Signed-off-by: Anthony Xu --- xen/arch/ia64/vmx/vmx_interrupt.c | 2 +- xen/arch/ia64/vmx/vmx_phy_mode.c | 2 +- xen/arch/ia64/vmx/vmx_vcpu.c | 17 +++++++++++++++++ xen/arch/ia64/vmx/vmx_virt.c | 4 ++-- xen/arch/ia64/xen/domain.c | 9 ++++----- xen/arch/ia64/xen/vcpu.c | 13 +++---------- xen/include/asm-ia64/domain.h | 1 - xen/include/asm-ia64/vmx_vcpu.h | 21 +-------------------- xen/include/asm-ia64/vmx_vpd.h | 9 --------- xen/include/asm-ia64/xenkregs.h | 4 ++++ 10 files changed, 33 insertions(+), 49 deletions(-) diff --git a/xen/arch/ia64/vmx/vmx_interrupt.c b/xen/arch/ia64/vmx/vmx_interrupt.c index 211aa93b36..7dc4db744c 100644 --- a/xen/arch/ia64/vmx/vmx_interrupt.c +++ b/xen/arch/ia64/vmx/vmx_interrupt.c @@ -99,7 +99,7 @@ inject_guest_interruption(VCPU *vcpu, u64 vec) pt_isr.ir = 0; VMX(vcpu,cr_isr) = pt_isr.val; collect_interruption(vcpu); - + vmx_ia64_set_dcr(vcpu); vmx_vcpu_get_iva(vcpu,&viva); regs->cr_iip = viva + vec; } diff --git a/xen/arch/ia64/vmx/vmx_phy_mode.c b/xen/arch/ia64/vmx/vmx_phy_mode.c index ce4fd9036c..b6155aa670 100644 --- a/xen/arch/ia64/vmx/vmx_phy_mode.c +++ b/xen/arch/ia64/vmx/vmx_phy_mode.c @@ -188,7 +188,7 @@ vmx_load_all_rr(VCPU *vcpu) (void *)vcpu->arch.privregs, (void *)vcpu->arch.vhpt.hash, pal_vaddr ); ia64_set_pta(VMX(vcpu, mpta)); - ia64_set_dcr(VMX(vcpu, mdcr)); + vmx_ia64_set_dcr(vcpu); ia64_srlz_d(); ia64_set_psr(psr); diff --git a/xen/arch/ia64/vmx/vmx_vcpu.c b/xen/arch/ia64/vmx/vmx_vcpu.c index f0418a8998..2dc2114db5 100644 --- a/xen/arch/ia64/vmx/vmx_vcpu.c +++ b/xen/arch/ia64/vmx/vmx_vcpu.c @@ -78,6 +78,22 @@ struct guest_psr_bundle guest_psr_buf[100]; unsigned long guest_psr_index = 0; #endif + +void +vmx_ia64_set_dcr(VCPU *v) +{ + unsigned long dcr_bits = IA64_DEFAULT_DCR_BITS; + + // if guest is runing on cpl > 0, set dcr.dm=1 + // if geust is runing on cpl = 0, set dcr.dm=0 + // because Guest OS may ld.s on tr mapped page. + if (!(VCPU(v, vpsr) & IA64_PSR_CPL)) + dcr_bits &= ~IA64_DCR_DM; + + ia64_set_dcr(dcr_bits); +} + + void vmx_vcpu_set_psr(VCPU *vcpu, unsigned long value) { @@ -261,6 +277,7 @@ IA64FAULT vmx_vcpu_rfi(VCPU *vcpu) else vcpu_bsw0(vcpu); vmx_vcpu_set_psr(vcpu,psr); + vmx_ia64_set_dcr(vcpu); ifs=VCPU(vcpu,ifs); if(ifs>>63) regs->cr_ifs = ifs; diff --git a/xen/arch/ia64/vmx/vmx_virt.c b/xen/arch/ia64/vmx/vmx_virt.c index 9926c6ed8f..57e1552971 100644 --- a/xen/arch/ia64/vmx/vmx_virt.c +++ b/xen/arch/ia64/vmx/vmx_virt.c @@ -1234,7 +1234,7 @@ IA64FAULT vmx_emul_mov_to_cr(VCPU *vcpu, INST64 inst) #endif //CHECK_FAULT r2 = cr_igfld_mask(inst.M32.cr3,r2); switch (inst.M32.cr3) { - case 0: return vmx_vcpu_set_dcr(vcpu,r2); + case 0: return vcpu_set_dcr(vcpu,r2); case 1: return vmx_vcpu_set_itm(vcpu,r2); case 2: return vmx_vcpu_set_iva(vcpu,r2); case 8: return vmx_vcpu_set_pta(vcpu,r2); @@ -1299,7 +1299,7 @@ IA64FAULT vmx_emul_mov_from_cr(VCPU *vcpu, INST64 inst) // from_cr_cnt[inst.M33.cr3]++; switch (inst.M33.cr3) { - case 0: return vmx_cr_get(dcr); + case 0: return cr_get(dcr); case 1: return vmx_cr_get(itm); case 2: return vmx_cr_get(iva); case 8: return vmx_cr_get(pta); diff --git a/xen/arch/ia64/xen/domain.c b/xen/arch/ia64/xen/domain.c index 6b76df3e58..9c21d02949 100644 --- a/xen/arch/ia64/xen/domain.c +++ b/xen/arch/ia64/xen/domain.c @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -204,9 +205,7 @@ void context_switch(struct vcpu *prev, struct vcpu *next) if (!VMX_DOMAIN(next)) { /* VMX domains can change the physical cr.dcr. * Restore default to prevent leakage. */ - ia64_setreg(_IA64_REG_CR_DCR, (IA64_DCR_DP | IA64_DCR_DK - | IA64_DCR_DX | IA64_DCR_DR | IA64_DCR_PP - | IA64_DCR_DA | IA64_DCR_DD | IA64_DCR_LC)); + ia64_setreg(_IA64_REG_CR_DCR, IA64_DEFAULT_DCR_BITS); } } if (VMX_DOMAIN(next)) @@ -582,7 +581,7 @@ void arch_get_info_guest(struct vcpu *v, vcpu_guest_context_u c) er->dtrs[i].rid = v->arch.dtrs[i].rid; } er->event_callback_ip = v->arch.event_callback_ip; - er->dcr = v->arch.dcr; + er->dcr = PSCB(v,dcr); er->iva = v->arch.iva; } @@ -618,7 +617,7 @@ int arch_set_info_guest(struct vcpu *v, vcpu_guest_context_u c) er->dtrs[i].rid); } v->arch.event_callback_ip = er->event_callback_ip; - v->arch.dcr = er->dcr; + PSCB(v,dcr) = er->dcr; v->arch.iva = er->iva; } diff --git a/xen/arch/ia64/xen/vcpu.c b/xen/arch/ia64/xen/vcpu.c index bef5059b9f..a21574ec2b 100644 --- a/xen/arch/ia64/xen/vcpu.c +++ b/xen/arch/ia64/xen/vcpu.c @@ -501,7 +501,7 @@ BOOLEAN vcpu_get_psr_i(VCPU * vcpu) u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) { - u64 dcr = PSCBX(vcpu, dcr); + u64 dcr = PSCB(vcpu, dcr); PSR psr; //printk("*** vcpu_get_ipsr_int_state (0x%016lx)...\n",prevpsr); @@ -532,10 +532,7 @@ u64 vcpu_get_ipsr_int_state(VCPU * vcpu, u64 prevpsr) IA64FAULT vcpu_get_dcr(VCPU * vcpu, u64 * pval) { -//verbose("vcpu_get_dcr: called @%p\n",PSCB(vcpu,iip)); - // Reads of cr.dcr on Xen always have the sign bit set, so - // a domain can differentiate whether it is running on SP or not - *pval = PSCBX(vcpu, dcr) | 0x8000000000000000L; + *pval = PSCB(vcpu, dcr); return IA64_NO_FAULT; } @@ -651,11 +648,7 @@ IA64FAULT vcpu_get_iha(VCPU * vcpu, u64 * pval) IA64FAULT vcpu_set_dcr(VCPU * vcpu, u64 val) { - // Reads of cr.dcr on SP always have the sign bit set, so - // a domain can differentiate whether it is running on SP or not - // Thus, writes of DCR should ignore the sign bit -//verbose("vcpu_set_dcr: called\n"); - PSCBX(vcpu, dcr) = val & ~0x8000000000000000L; + PSCB(vcpu, dcr) = val; return IA64_NO_FAULT; } diff --git a/xen/include/asm-ia64/domain.h b/xen/include/asm-ia64/domain.h index ce734c8677..66f9caec2e 100644 --- a/xen/include/asm-ia64/domain.h +++ b/xen/include/asm-ia64/domain.h @@ -162,7 +162,6 @@ struct arch_vcpu { unsigned long irr[4]; /* Interrupt request register. */ unsigned long insvc[4]; /* Interrupt in service. */ unsigned long iva; - unsigned long dcr; unsigned long domain_itm; unsigned long domain_itm_last; diff --git a/xen/include/asm-ia64/vmx_vcpu.h b/xen/include/asm-ia64/vmx_vcpu.h index 24b3b60578..fda5e82389 100644 --- a/xen/include/asm-ia64/vmx_vcpu.h +++ b/xen/include/asm-ia64/vmx_vcpu.h @@ -126,17 +126,12 @@ extern void dnat_page_consumption(VCPU * vcpu, uint64_t vadr); extern void data_page_not_present(VCPU * vcpu, u64 vadr); extern void inst_page_not_present(VCPU * vcpu, u64 vadr); extern void data_access_rights(VCPU * vcpu, u64 vadr); +extern void vmx_ia64_set_dcr(VCPU * v); /************************************************************************** VCPU control register access routines **************************************************************************/ -static inline IA64FAULT vmx_vcpu_get_dcr(VCPU * vcpu, u64 * pval) -{ - *pval = VCPU(vcpu, dcr); - return IA64_NO_FAULT; -} - static inline IA64FAULT vmx_vcpu_get_itm(VCPU * vcpu, u64 * pval) { *pval = VCPU(vcpu, itm); @@ -233,20 +228,6 @@ static inline IA64FAULT vmx_vcpu_get_lrr1(VCPU * vcpu, u64 * pval) return IA64_NO_FAULT; } -static inline IA64FAULT vmx_vcpu_set_dcr(VCPU * vcpu, u64 val) -{ - u64 mdcr, mask; - VCPU(vcpu, dcr) = val; - /* All vDCR bits will go to mDCR, except for be/pp/dm bits */ - mdcr = ia64_get_dcr(); - /* Machine dcr.dm masked to handle guest ld.s on tr mapped page */ - mask = IA64_DCR_BE | IA64_DCR_PP | IA64_DCR_DM; - mdcr = (mdcr & mask) | (val & (~mask)); - ia64_set_dcr(mdcr); - VMX(vcpu, mdcr) = mdcr; - return IA64_NO_FAULT; -} - static inline IA64FAULT vmx_vcpu_set_itm(VCPU * vcpu, u64 val) { vtm_set_itm(vcpu, val); diff --git a/xen/include/asm-ia64/vmx_vpd.h b/xen/include/asm-ia64/vmx_vpd.h index 8e4eb4f55c..e8876bb154 100644 --- a/xen/include/asm-ia64/vmx_vpd.h +++ b/xen/include/asm-ia64/vmx_vpd.h @@ -86,16 +86,7 @@ struct arch_vmx_struct { unsigned long cr_isr; /* for emulation */ unsigned long cause; unsigned long opcode; - -// unsigned long mrr5; -// unsigned long mrr6; -// unsigned long mrr7; - unsigned long mdcr; unsigned long mpta; -// unsigned long rfi_pfs; -// unsigned long rfi_iip; -// unsigned long rfi_ipsr; -// unsigned long rfi_ifs; unsigned long flags; unsigned long xen_port; unsigned char xtp; diff --git a/xen/include/asm-ia64/xenkregs.h b/xen/include/asm-ia64/xenkregs.h index d2dcd2bc84..4050bb700f 100644 --- a/xen/include/asm-ia64/xenkregs.h +++ b/xen/include/asm-ia64/xenkregs.h @@ -13,6 +13,10 @@ #define IA64_PSR_VM_BIT 46 #define IA64_PSR_VM (__IA64_UL(1) << IA64_PSR_VM_BIT) +#define IA64_DEFAULT_DCR_BITS (IA64_DCR_PP | IA64_DCR_LC | IA64_DCR_DM | \ + IA64_DCR_DP | IA64_DCR_DK | IA64_DCR_DX | \ + IA64_DCR_DR | IA64_DCR_DA | IA64_DCR_DD) + /* Interruption Function State */ #define IA64_IFS_V_BIT 63 #define IA64_IFS_V (__IA64_UL(1) << IA64_IFS_V_BIT) From d7e51f76c87e031bab860bfc2086136d53c2f05a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Mon, 5 Feb 2007 15:41:58 -0700 Subject: [PATCH 37/95] [IA64] Fix for compiling PV-on-HVM driver on IPF Signed-off-by: Tsunehisa Doi Signed-off-by: Tomonari Horikoshi Signed-off-by: Anthony Xu --- unmodified_drivers/linux-2.6/overrides.mk | 3 +++ .../linux-2.6/platform-pci/xen_support.c | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/unmodified_drivers/linux-2.6/overrides.mk b/unmodified_drivers/linux-2.6/overrides.mk index 81416b2b10..818723a492 100644 --- a/unmodified_drivers/linux-2.6/overrides.mk +++ b/unmodified_drivers/linux-2.6/overrides.mk @@ -6,3 +6,6 @@ # a Xen kernel to find the right headers) EXTRA_CFLAGS += -D__XEN_INTERFACE_VERSION__=0x00030202 EXTRA_CFLAGS += -I$(M)/include -I$(M)/compat-include -DHAVE_XEN_PLATFORM_COMPAT_H +ifeq ($(ARCH),ia64) + EXTRA_CFLAGS += -DCONFIG_VMX_GUEST +endif diff --git a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c index 423d2f2e24..589d8365ec 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/xen_support.c +++ b/unmodified_drivers/linux-2.6/platform-pci/xen_support.c @@ -30,6 +30,23 @@ #include #endif +#if defined (__ia64__) +unsigned long __hypercall(unsigned long a1, unsigned long a2, + unsigned long a3, unsigned long a4, + unsigned long a5, unsigned long cmd) +{ + unsigned long __res; + __asm__ __volatile__ (";;\n" + "mov r2=%1\n" + "break 0x1000 ;;\n" + "mov %0=r8 ;;\n" + : "=r"(__res) : "r"(cmd) : "r2", "r8", "memory"); + + return __res; +} +EXPORT_SYMBOL(__hypercall); +#endif + void xen_machphys_update(unsigned long mfn, unsigned long pfn) { BUG(); From a356cbd5f6fd8c7a786e1ff6d3b330431ccbc296 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 6 Feb 2007 09:26:25 -0700 Subject: [PATCH 38/95] [IA64] Follow to allow PV-on-HVM callback irq to be identified by PCI device. Also delete IA64 specific spec concerned with IA64_CALLBACK_IRQ_RID. Signed-off-by: Tsunehisa Doi --- .../linux-2.6/platform-pci/platform-pci.c | 12 +++-------- xen/arch/ia64/vmx/vmx_process.c | 20 ++++++++++++------- xen/include/public/arch-ia64.h | 4 ---- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c index e6ff4107cb..1cbfcf11b9 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @@ -181,23 +181,18 @@ static int get_hypercall_stubs(void) static uint64_t get_callback_via(struct pci_dev *pdev) { + u8 pin; #ifdef __ia64__ int irq, rid; for (irq = 0; irq < 16; irq++) { if (isa_irq_to_vector(irq) == pdev->irq) - return irq; + return irq; /* ISA IRQ */ } - /* use Requester-ID as callback_irq */ - /* RID: '<#bus(8)><#dev(5)><#func(3)>' (cf. PCI-Express spec) */ - rid = ((pdev->bus->number & 0xff) << 8) | pdev->devfn; - printk(KERN_INFO DRV_NAME ":use Requester-ID(%04x) as callback irq\n", - rid); - return rid | IA64_CALLBACK_IRQ_RID; #else /* !__ia64__ */ - u8 pin; if (pdev->irq < 16) return pdev->irq; /* ISA IRQ */ +#endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) pin = pdev->pin; @@ -211,7 +206,6 @@ static uint64_t get_callback_via(struct pci_dev *pdev) ((uint64_t)pdev->bus->number << 16) | ((uint64_t)(pdev->devfn & 0xff) << 8) | ((uint64_t)(pin - 1) & 3)); -#endif } /* Invalidate foreign mappings (e.g., in qemu-based device model). */ diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 37f8780426..0b4858e682 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -227,17 +227,23 @@ void leave_hypervisor_tail(void) local_irq_disable(); if (v->vcpu_id == 0) { - int callback_irq = + unsigned long callback_irq = d->arch.hvm_domain.params[HVM_PARAM_CALLBACK_IRQ]; + /* + * val[63:56] == 1: val[55:0] is a delivery PCI INTx line: + * Domain = val[47:32], Bus = val[31:16], + * DevFn = val[15: 8], IntX = val[ 1: 0] + * val[63:56] == 0: val[55:0] is a delivery as GSI + */ if (callback_irq != 0 && local_events_need_delivery()) { /* change level for para-device callback irq */ /* use level irq to send discrete event */ - if (callback_irq & IA64_CALLBACK_IRQ_RID) { - /* case of using Requester-ID as callback irq */ - /* RID: '<#bus(8)><#dev(5)><#func(3)>' */ - int dev = (callback_irq >> 3) & 0x1f; - viosapic_set_pci_irq(d, dev, 0, 1); - viosapic_set_pci_irq(d, dev, 0, 0); + if ((uint8_t)(callback_irq >> 56) == 1) { + /* case of using PCI INTx line as callback irq */ + int pdev = (callback_irq >> 11) & 0x1f; + int pintx = callback_irq & 3; + viosapic_set_pci_irq(d, pdev, pintx, 1); + viosapic_set_pci_irq(d, pdev, pintx, 0); } else { /* case of using GSI as callback irq */ viosapic_set_irq(d, callback_irq, 1); diff --git a/xen/include/public/arch-ia64.h b/xen/include/public/arch-ia64.h index cdb8f9de85..24e7020649 100644 --- a/xen/include/public/arch-ia64.h +++ b/xen/include/public/arch-ia64.h @@ -64,10 +64,6 @@ DEFINE_XEN_GUEST_HANDLE(xen_pfn_t); #define VIRQ_MCA_CMC VIRQ_ARCH_1 /* MCA cmc interrupt */ #define VIRQ_MCA_CPE VIRQ_ARCH_2 /* MCA cpe interrupt */ -/* Arch specific callback irq definition */ -/* using Requester-ID(RID) as callback irq */ -#define IA64_CALLBACK_IRQ_RID (1 << 31) - /* Maximum number of virtual CPUs in multi-processor guests. */ /* WARNING: before changing this, check that shared_info fits on a page */ #define MAX_VIRT_CPUS 64 From de644844069eb5ce529f2f7d9cbcf7cad25d7675 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 6 Feb 2007 09:28:07 -0700 Subject: [PATCH 39/95] [IA64] Fix wrong arg to vhpt_enabled() in vmx_hpw_miss() Signed-off-by: Kouya Shimura --- xen/arch/ia64/vmx/vmx_process.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 0b4858e682..308a4de0ba 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -393,7 +393,7 @@ vmx_hpw_miss(u64 vadr , u64 vec, REGS* regs) if (!vpsr.ic) misr.ni = 1; - if(!vhpt_enabled(v, vadr, misr.rs?RSE_REF:DATA_REF)){ + if (!vhpt_enabled(v, vadr, INST_REF)) { vcpu_set_isr(v, misr.val); alt_itlb(v, vadr); return IA64_FAULT; From 25cc9bc4716cec1d055f3b660501e3a6372c4bae Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 6 Feb 2007 15:08:09 -0700 Subject: [PATCH 40/95] [IA64] Don't complain about PAL_LOGICAL_TO_PHYSICAL It's optional Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/fw_emul.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xen/arch/ia64/xen/fw_emul.c b/xen/arch/ia64/xen/fw_emul.c index 905d29c6fd..60f955ff79 100644 --- a/xen/arch/ia64/xen/fw_emul.c +++ b/xen/arch/ia64/xen/fw_emul.c @@ -625,6 +625,9 @@ xen_pal_emulator(unsigned long index, u64 in1, u64 in2, u64 in3) if (VMX_DOMAIN(current)) status = PAL_STATUS_SUCCESS; break; + case PAL_LOGICAL_TO_PHYSICAL: + /* Optional, no need to complain about being unimplemented */ + break; default: printk("xen_pal_emulator: UNIMPLEMENTED PAL CALL %lu!!!!\n", index); From 1c143ba820d281a95409b1295ec75136d92a71a8 Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Tue, 6 Feb 2007 15:20:26 -0700 Subject: [PATCH 41/95] [IA64] Don't assume legacy com2 If com1 isn't at a legacy I/O port address, don't assume legacy com2 exists. Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/xensetup.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/xen/arch/ia64/xen/xensetup.c b/xen/arch/ia64/xen/xensetup.c index 37de379e2a..8909136b26 100644 --- a/xen/arch/ia64/xen/xensetup.c +++ b/xen/arch/ia64/xen/xensetup.c @@ -267,13 +267,16 @@ void start_kernel(void) early_setup_arch(&cmdline); /* We initialise the serial devices very early so we can get debugging. */ - if (running_on_sim) hpsim_serial_init(); + if (running_on_sim) + hpsim_serial_init(); else { - ns16550_init(0, &ns16550_com1); - /* Also init com2 for Tiger4. */ - ns16550_com2.io_base = 0x2f8; - ns16550_com2.irq = 3; - ns16550_init(1, &ns16550_com2); + ns16550_init(0, &ns16550_com1); + if (ns16550_com1.io_base == 0x3f8) { + /* Also init com2 for Tiger4. */ + ns16550_com2.io_base = 0x2f8; + ns16550_com2.irq = 3; + ns16550_init(1, &ns16550_com2); + } } serial_init_preirq(); From 9c3844a97e1efdbd7ce22d3fa634ad07c4448146 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 22:59:35 +0000 Subject: [PATCH 42/95] [TPM] TIS dm suspend code fix This fixes a bug in the TPM TIS device model's state suspend code and adds some casts to variables to avoid compiler warnings. Signed-off-by: Stefan Berger --- tools/ioemu/hw/tpm_tis.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/ioemu/hw/tpm_tis.c b/tools/ioemu/hw/tpm_tis.c index ace469f1ec..452516c182 100644 --- a/tools/ioemu/hw/tpm_tis.c +++ b/tools/ioemu/hw/tpm_tis.c @@ -517,7 +517,7 @@ static uint32_t tis_mem_readl(void *opaque, target_phys_addr_t addr) #ifdef DEBUG_TPM fprintf(logfile," read(%08x) = %08x\n", - addr, + (int)addr, val); #endif @@ -538,7 +538,7 @@ static void tis_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val) #ifdef DEBUG_TPM fprintf(logfile,"write(%08x) = %08x\n", - addr, + (int)addr, val); #endif @@ -757,10 +757,11 @@ static CPUWriteMemoryFunc *tis_writefn[3]={ static void tpm_save(QEMUFile* f,void* opaque) { tpmState* s=(tpmState*)opaque; + uint8_t locty = s->active_loc; int c; /* need to wait for outstanding requests to complete */ - if (IS_COMM_WITH_VTPM(s)) { + if (s->loc[locty].state == STATE_EXECUTION) { int repeats = 30; /* 30 seconds; really should be infty */ while (repeats > 0 && !(s->loc[s->active_loc].sts & STS_DATA_AVAILABLE)) { @@ -777,6 +778,10 @@ static void tpm_save(QEMUFile* f,void* opaque) } } + if (IS_COMM_WITH_VTPM(s)) { + close_vtpm_channel(s, 1); + } + qemu_put_be32s(f,&s->offset); qemu_put_buffer(f, s->buffer.buf, TPM_MAX_PKT); qemu_put_8s(f, &s->active_loc); @@ -993,7 +998,7 @@ static int TPM_Receive(tpmState *s, tpmBuffer *buffer) uint32_t size = tpm_get_size_from_buffer(buffer->buf); if (size + sizeof(buffer->instance) != off) { fprintf(logfile,"TPM: Packet size is bad! %d != %d\n", - size + sizeof(buffer->instance), + (int)(size + sizeof(buffer->instance)), off); } else { uint32_t ret; From 09a4bf86cfa76d98c7d2732bc56dd5b1c2851e34 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 23:01:35 +0000 Subject: [PATCH 43/95] [TPM] Set tcpa calls in the rombios and other fixes. This patch places some tcpa calls into the rombios that had previously not applied anymore or were not set. Force the reads from MMIO memory locations that the compiler otherwise optimizes away (-O2) if there was an immediate write to the same memory location before. Use #define'd constants wherever possible. Fix all remaining compiler warnings. Signed-off-by: Stefan Berger --- .../firmware/rombios/32bit/tcgbios/tcgbios.c | 14 +++-- .../rombios/32bit/tcgbios/tpm_drivers.c | 52 ++++++++++++------- tools/firmware/rombios/32bit/util.h | 15 ++++++ tools/firmware/rombios/rombios.c | 13 +++-- 4 files changed, 65 insertions(+), 29 deletions(-) diff --git a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c index 07d91d2f36..dc1a9e0d51 100644 --- a/tools/firmware/rombios/32bit/tcgbios/tcgbios.c +++ b/tools/firmware/rombios/32bit/tcgbios/tcgbios.c @@ -146,7 +146,7 @@ static tcpa_acpi_t tcpa_acpi; static int tpm_driver_to_use = TPM_INVALID_DRIVER; static -uint32_t MA_IsTPMPresent() +uint32_t MA_IsTPMPresent(void) { uint32_t rc = 0; unsigned int i; @@ -263,11 +263,11 @@ void tcpa_acpi_init(void) { struct acpi_20_rsdt *rsdt; uint32_t length; - struct acpi_20_tcpa *tcpa; + struct acpi_20_tcpa *tcpa = (void *)0; uint16_t found = 0; uint16_t rsdp_off; uint16_t off; - struct acpi_20_rsdp *rsdp; + struct acpi_20_rsdp *rsdp = (void *)0; if (MA_IsTPMPresent() == 0) { return; @@ -732,8 +732,8 @@ void tcpa_ipl(Bit32u seg) void tcpa_measure_post(Bit32u from, Bit32u to) { struct pcpes pcpes; /* PCClientPCREventStruc */ - memset(&pcpes, 0x0, sizeof(pcpes)); int len = to - from; + memset(&pcpes, 0x0, sizeof(pcpes)); if (len > 0) { sha1((unsigned char *)from, @@ -986,7 +986,7 @@ uint32_t PassThroughToTPM32(struct pttti *pttti, { uint32_t rc = 0; uint8_t *cmd32; - uint32_t resbuflen; + uint32_t resbuflen = 0; if (TCG_IsShutdownPreBootInterface() != 0) { rc = (TCG_PC_TPMERROR | @@ -1277,9 +1277,7 @@ typedef struct _sha1_ctx { } sha1_ctx; -static inline uint32_t rol(val, rol) - uint32_t val; - uint16_t rol; +static inline uint32_t rol(uint32_t val, uint16_t rol) { return (val << rol) | (val >> (32 - rol)); } diff --git a/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c index 7534b32992..5a49b0038c 100644 --- a/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c +++ b/tools/firmware/rombios/32bit/tcgbios/tpm_drivers.c @@ -27,12 +27,27 @@ #include "tpm_drivers.h" #include "tcgbios.h" +#define STS_VALID (1 << 7) /* 0x80 */ +#define STS_COMMAND_READY (1 << 6) /* 0x40 */ +#define STS_TPM_GO (1 << 5) /* 0x20 */ +#define STS_DATA_AVAILABLE (1 << 4) /* 0x10 */ +#define STS_EXPECT (1 << 3) /* 0x08 */ +#define STS_RESPONSE_RETRY (1 << 1) /* 0x02 */ + +#define ACCESS_TPM_REG_VALID_STS (1 << 7) /* 0x80 */ +#define ACCESS_ACTIVE_LOCALITY (1 << 5) /* 0x20 */ +#define ACCESS_BEEN_SEIZED (1 << 4) /* 0x10 */ +#define ACCESS_SEIZE (1 << 3) /* 0x08 */ +#define ACCESS_PENDING_REQUEST (1 << 2) /* 0x04 */ +#define ACCESS_REQUEST_USE (1 << 1) /* 0x02 */ +#define ACCESS_TPM_ESTABLISHMENT (1 << 0) /* 0x01 */ + static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time, uint8_t mask, uint8_t expect) { uint32_t rc = 0; while (time > 0) { - uint8_t sts = addr[TPM_STS]; + uint8_t sts = mmio_readb(&addr[TPM_STS]); if ((sts & mask) == expect) { rc = 1; break; @@ -45,16 +60,17 @@ static uint32_t tis_wait_sts(uint8_t *addr, uint32_t time, static uint32_t tis_activate(uint32_t baseaddr) { - uint32_t rc = 0; + uint32_t rc = 1; uint8_t *tis_addr = (uint8_t*)baseaddr; uint8_t acc; /* request access to locality */ - tis_addr[TPM_ACCESS] = 0x2; + tis_addr[TPM_ACCESS] = ACCESS_REQUEST_USE; - acc = tis_addr[TPM_ACCESS]; - if ((acc & 0x20) != 0) { - tis_addr[TPM_STS] = 0x40; - rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40); + acc = mmio_readb(&tis_addr[TPM_ACCESS]); + if ((acc & ACCESS_ACTIVE_LOCALITY) != 0) { + tis_addr[TPM_STS] = STS_COMMAND_READY; + rc = tis_wait_sts(tis_addr, 100, + STS_COMMAND_READY, STS_COMMAND_READY); } return rc; } @@ -64,8 +80,8 @@ uint32_t tis_ready(uint32_t baseaddr) uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - tis_addr[TPM_STS] = 0x40; - rc = tis_wait_sts(tis_addr, 100, 0x40, 0x40); + tis_addr[TPM_STS] = STS_COMMAND_READY; + rc = tis_wait_sts(tis_addr, 100, STS_COMMAND_READY, STS_COMMAND_READY); return rc; } @@ -81,8 +97,7 @@ uint32_t tis_senddata(uint32_t baseaddr, unsigned char *data, uint32_t len) uint16_t burst = 0; uint32_t ctr = 0; while (burst == 0 && ctr < 2000) { - burst = (((uint16_t)tis_addr[TPM_STS+1]) ) + - (((uint16_t)tis_addr[TPM_STS+2]) << 8); + burst = mmio_readw((uint16_t *)&tis_addr[TPM_STS+1]); if (burst == 0) { mssleep(1); ctr++; @@ -120,11 +135,11 @@ uint32_t tis_readresp(uint32_t baseaddr, unsigned char *buffer, uint32_t len) uint32_t sts; while (offset < len) { - buffer[offset] = tis_addr[TPM_DATA_FIFO]; + buffer[offset] = mmio_readb(&tis_addr[TPM_DATA_FIFO]); offset++; - sts = tis_addr[TPM_STS]; + sts = mmio_readb(&tis_addr[TPM_STS]); /* data left ? */ - if ((sts & 0x10) == 0) { + if ((sts & STS_DATA_AVAILABLE) == 0) { break; } } @@ -136,7 +151,7 @@ uint32_t tis_waitdatavalid(uint32_t baseaddr) { uint8_t *tis_addr = (uint8_t*)baseaddr; uint32_t rc = 0; - if (tis_wait_sts(tis_addr, 1000, 0x80, 0x80) == 0) { + if (tis_wait_sts(tis_addr, 1000, STS_VALID, STS_VALID) == 0) { rc = TCG_NO_RESPONSE; } return rc; @@ -146,8 +161,9 @@ uint32_t tis_waitrespready(uint32_t baseaddr, uint32_t timeout) { uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - tis_addr[TPM_STS] = 0x20; - if (tis_wait_sts(tis_addr, timeout, 0x10, 0x10) == 0) { + tis_addr[TPM_STS] = STS_TPM_GO; + if (tis_wait_sts(tis_addr, timeout, + STS_DATA_AVAILABLE, STS_DATA_AVAILABLE) == 0) { rc = TCG_NO_RESPONSE; } return rc; @@ -158,7 +174,7 @@ uint32_t tis_probe(uint32_t baseaddr) { uint32_t rc = 0; uint8_t *tis_addr = (uint8_t*)baseaddr; - uint32_t didvid = *(uint32_t*)&tis_addr[TPM_DID_VID]; + uint32_t didvid = mmio_readl((uint32_t *)&tis_addr[TPM_DID_VID]); if ((didvid != 0) && (didvid != 0xffffffff)) { rc = 1; } diff --git a/tools/firmware/rombios/32bit/util.h b/tools/firmware/rombios/32bit/util.h index 1a29a8cbe1..6d05b502d5 100644 --- a/tools/firmware/rombios/32bit/util.h +++ b/tools/firmware/rombios/32bit/util.h @@ -24,5 +24,20 @@ void byte_to_hex(char *digits, uint8_t byte); void uuid_to_string(char *dest, uint8_t *uuid); int printf(const char *fmt, ...); +static inline uint8_t mmio_readb(uint8_t *addr) +{ + return *(volatile uint8_t *)addr; +} + +static inline uint16_t mmio_readw(uint16_t *addr) +{ + return *(volatile uint16_t *)addr; +} + +static inline uint32_t mmio_readl(uint32_t *addr) +{ + return *(volatile uint32_t *)addr; +} + #endif diff --git a/tools/firmware/rombios/rombios.c b/tools/firmware/rombios/rombios.c index a874b23d15..414a2ec252 100644 --- a/tools/firmware/rombios/rombios.c +++ b/tools/firmware/rombios/rombios.c @@ -5722,9 +5722,6 @@ int13_cdemu(DS, ES, DI, SI, BP, SP, BX, DX, CX, AX, IP, CS, FLAGS) goto int13_fail; } -#if BX_TCGBIOS - tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */ -#endif switch (GET_AH()) { @@ -7741,6 +7738,10 @@ ASM_END } } +#if BX_TCGBIOS + tcpa_add_bootdevice((Bit32u)0L, (Bit32u)bootdrv); +#endif + /* Canonicalize bootseg:bootip */ bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; @@ -7760,6 +7761,9 @@ ASM_END bootdrv = (Bit8u)(status>>8); bootseg = read_word(ebda_seg,&EbdaData->cdemu.load_segment); /* Canonicalize bootseg:bootip */ +#if BX_TCGBIOS + tcpa_add_bootdevice((Bit32u)1L, (Bit32u)0L); +#endif bootip = (bootseg & 0x0fff) << 4; bootseg &= 0xf000; break; @@ -7773,6 +7777,9 @@ ASM_END default: return; } +#if BX_TCGBIOS + tcpa_ipl((Bit32u)bootseg); /* specs: 8.2.3 steps 4 and 5 */ +#endif /* Debugging info */ printf("Booting from %x:%x\n", bootseg, bootip); From bec98603f540df827009a761b931e9068e6599d4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 23:10:05 +0000 Subject: [PATCH 44/95] Fix up xentrace record extraction in xentrace_format for 64-bit architectures. Signed-off-by: Thomas Friebel --- tools/xentrace/xentrace_format | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/xentrace/xentrace_format b/tools/xentrace/xentrace_format index 537785824a..36536c24a6 100644 --- a/tools/xentrace/xentrace_format +++ b/tools/xentrace/xentrace_format @@ -107,6 +107,9 @@ while not interrupted: (tsc, event, d1, d2, d3, d4, d5) = struct.unpack(TRCREC, line) + # Event field is 'uint32_t', not 'long'. + event &= 0xffffffff + #tsc = (tscH<<32) | tscL #print i, tsc From 15587769c8833c12ab9dc0bdea10e0b649778699 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 23:12:59 +0000 Subject: [PATCH 45/95] minios: Fix netfront for ia64. Signed-off-by: Dietmar Hahn --- extras/mini-os/gnttab.c | 5 +++++ extras/mini-os/netfront.c | 4 +++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/extras/mini-os/gnttab.c b/extras/mini-os/gnttab.c index da92fc33c9..4d75897a98 100644 --- a/extras/mini-os/gnttab.c +++ b/extras/mini-os/gnttab.c @@ -21,7 +21,12 @@ #define NR_RESERVED_ENTRIES 8 +/* NR_GRANT_FRAMES must be less than or equal to that configured in Xen */ +#ifdef __ia64__ +#define NR_GRANT_FRAMES 1 +#else #define NR_GRANT_FRAMES 4 +#endif #define NR_GRANT_ENTRIES (NR_GRANT_FRAMES * PAGE_SIZE / sizeof(grant_entry_t)) static grant_entry_t *gnttab_table; diff --git a/extras/mini-os/netfront.c b/extras/mini-os/netfront.c index 4c10dc8770..088f67a3bb 100644 --- a/extras/mini-os/netfront.c +++ b/extras/mini-os/netfront.c @@ -349,7 +349,9 @@ done: init_rx_buffers(); unsigned char rawmac[6]; - sscanf(mac,"%x:%x:%x:%x:%x:%x", + /* Special conversion specifier 'hh' needed for __ia64__. Without + this mini-os panics with 'Unaligned reference'. */ + sscanf(mac,"%hhx:%hhx:%hhx:%hhx:%hhx:%hhx", &rawmac[0], &rawmac[1], &rawmac[2], From e471d8c8bf76cb7bd85d6e3b69a41358f8ac8325 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 23:14:21 +0000 Subject: [PATCH 46/95] hvm: vcpu reset support for x86 INIT IPI, needed for CPU hotplug. Signed-off-by: Xin Li --- xen/arch/x86/hvm/hvm.c | 33 +++++++++++++++++++++----------- xen/arch/x86/hvm/svm/vmcb.c | 3 ++- xen/arch/x86/hvm/vlapic.c | 17 ++++++---------- xen/arch/x86/hvm/vmx/vmcs.c | 16 ++++++++++++---- xen/include/asm-x86/hvm/hvm.h | 1 + xen/include/asm-x86/hvm/vlapic.h | 2 ++ 6 files changed, 45 insertions(+), 27 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 3ecaf9d7de..39ef3c1221 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -273,6 +273,24 @@ void hvm_vcpu_destroy(struct vcpu *v) /*free_xen_event_channel(v, v->arch.hvm_vcpu.xen_port);*/ } + +void hvm_vcpu_reset(struct vcpu *v) +{ + vcpu_pause(v); + + vlapic_reset(vcpu_vlapic(v)); + + hvm_funcs.vcpu_initialise(v); + + set_bit(_VCPUF_down, &v->vcpu_flags); + clear_bit(_VCPUF_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_fpu_initialised, &v->vcpu_flags); + clear_bit(_VCPUF_fpu_dirtied, &v->vcpu_flags); + clear_bit(_VCPUF_blocked, &v->vcpu_flags); + + vcpu_unpause(v); +} + static void hvm_vcpu_down(void) { struct vcpu *v = current; @@ -624,20 +642,13 @@ void hvm_hypercall_page_initialise(struct domain *d, */ int hvm_bringup_ap(int vcpuid, int trampoline_vector) { - struct vcpu *bsp = current, *v; - struct domain *d = bsp->domain; + struct vcpu *v; + struct domain *d = current->domain; struct vcpu_guest_context *ctxt; int rc = 0; BUG_ON(!is_hvm_domain(d)); - if ( bsp->vcpu_id != 0 ) - { - gdprintk(XENLOG_ERR, "Not calling hvm_bringup_ap from BSP context.\n"); - domain_crash(bsp->domain); - return -EINVAL; - } - if ( (v = d->vcpu[vcpuid]) == NULL ) return -ENOENT; @@ -668,8 +679,8 @@ int hvm_bringup_ap(int vcpuid, int trampoline_vector) goto out; } - if ( test_and_clear_bit(_VCPUF_down, &d->vcpu[vcpuid]->vcpu_flags) ) - vcpu_wake(d->vcpu[vcpuid]); + if ( test_and_clear_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_wake(v); gdprintk(XENLOG_INFO, "AP %d bringup suceeded.\n", vcpuid); out: diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 46d98f9215..642d9d0026 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -209,7 +209,8 @@ int svm_create_vmcb(struct vcpu *v) struct arch_svm_struct *arch_svm = &v->arch.hvm_svm; int rc; - if ( (arch_svm->vmcb = alloc_vmcb()) == NULL ) + if ( (arch_svm->vmcb == NULL) && + (arch_svm->vmcb = alloc_vmcb()) == NULL ) { printk("Failed to create a new VMCB\n"); return -ENOMEM; diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index b38dee2e85..cc4964980d 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -83,8 +83,6 @@ static unsigned int vlapic_lvt_mask[VLAPIC_LVT_NUM] = #define vlapic_base_address(vlapic) \ (vlapic->hw.apic_base_msr & MSR_IA32_APICBASE_BASE) -static int vlapic_reset(struct vlapic *vlapic); - /* * Generic APIC bitmap vector update & search routines. */ @@ -293,8 +291,11 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, break; case APIC_DM_SMI: + gdprintk(XENLOG_WARNING, "Ignoring guest SMI\n"); + break; + case APIC_DM_NMI: - gdprintk(XENLOG_WARNING, "Ignoring guest SMI/NMI\n"); + gdprintk(XENLOG_WARNING, "Ignoring guest NMI\n"); break; case APIC_DM_INIT: @@ -303,10 +304,7 @@ static int vlapic_accept_irq(struct vcpu *v, int delivery_mode, break; /* FIXME How to check the situation after vcpu reset? */ if ( test_bit(_VCPUF_initialised, &v->vcpu_flags) ) - { - gdprintk(XENLOG_ERR, "Reset hvm vcpu not supported yet\n"); - goto exit_and_crash; - } + hvm_vcpu_reset(v); v->arch.hvm_vcpu.init_sipi_sipi_state = HVM_VCPU_INIT_SIPI_SIPI_STATE_WAIT_SIPI; result = 1; @@ -764,7 +762,7 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode) } /* Reset the VLPAIC back to its power-on/reset state. */ -static int vlapic_reset(struct vlapic *vlapic) +void vlapic_reset(struct vlapic *vlapic) { struct vcpu *v = vlapic_vcpu(vlapic); int i; @@ -793,8 +791,6 @@ static int vlapic_reset(struct vlapic *vlapic) vlapic_set_reg(vlapic, APIC_SPIV, 0xff); vlapic->hw.disabled |= VLAPIC_SW_DISABLED; - - return 1; } #ifdef HVM_DEBUG_SUSPEND @@ -922,7 +918,6 @@ int vlapic_init(struct vcpu *v) { dprintk(XENLOG_ERR, "malloc vlapic regs error for vcpu %x\n", v->vcpu_id); - xfree(vlapic); return -ENOMEM; } diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 20c3ddf61b..5f12c0805b 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -295,6 +295,11 @@ static void construct_vmcs(struct vcpu *v) vmx_vmcs_enter(v); + v->arch.hvm_vmx.cpu_cr2 = 0; + v->arch.hvm_vmx.cpu_cr3 = 0; + memset(&v->arch.hvm_vmx.msr_state, 0, sizeof(v->arch.hvm_vmx.msr_state)); + v->arch.hvm_vmx.vmxassist_enabled = 0; + /* VMCS controls. */ __vmwrite(PIN_BASED_VM_EXEC_CONTROL, vmx_pin_based_exec_control); __vmwrite(VM_EXIT_CONTROLS, vmx_vmexit_control); @@ -448,10 +453,13 @@ static void construct_vmcs(struct vcpu *v) int vmx_create_vmcs(struct vcpu *v) { - if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL ) - return -ENOMEM; - - __vmx_clear_vmcs(v); + if ( v->arch.hvm_vmx.vmcs == NULL ) + { + if ( (v->arch.hvm_vmx.vmcs = vmx_alloc_vmcs()) == NULL ) + return -ENOMEM; + + __vmx_clear_vmcs(v); + } construct_vmcs(v); diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 1e8093dafa..125c73d2ce 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -153,6 +153,7 @@ void hvm_domain_destroy(struct domain *d); int hvm_vcpu_initialise(struct vcpu *v); void hvm_vcpu_destroy(struct vcpu *v); +void hvm_vcpu_reset(struct vcpu *vcpu); void hvm_send_assist_req(struct vcpu *v); diff --git a/xen/include/asm-x86/hvm/vlapic.h b/xen/include/asm-x86/hvm/vlapic.h index 4700f63fb5..6d174ebfd6 100644 --- a/xen/include/asm-x86/hvm/vlapic.h +++ b/xen/include/asm-x86/hvm/vlapic.h @@ -78,6 +78,8 @@ int cpu_get_apic_interrupt(struct vcpu *v, int *mode); int vlapic_init(struct vcpu *v); void vlapic_destroy(struct vcpu *v); +void vlapic_reset(struct vlapic *vlapic); + void vlapic_msr_set(struct vlapic *vlapic, uint64_t value); int vlapic_accept_pic_intr(struct vcpu *v); From 00aabc5c805ecaf86d9f10e04de3ba40bf02bdcc Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Tue, 6 Feb 2007 23:36:53 +0000 Subject: [PATCH 47/95] linux/i386: Improve critical region handling code - use symbolics instead of raw numbers (going to help the 2.6.20 port, as those numbers change there) - fold instructions where possible - move fixup table into .rodata Signed-off-by: Jan Beulich --- .../arch/i386/kernel/entry-xen.S | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S index 9d10f5c573..ab569d974b 100644 --- a/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S +++ b/linux-2.6-xen-sparse/arch/i386/kernel/entry-xen.S @@ -747,7 +747,7 @@ ENTRY(hypervisor_callback) jb 11f cmpl $sysexit_ecrit,%eax ja 11f - addl $0x34,%esp # Remove cs...ebx from stack frame. + addl $OLDESP,%esp # Remove eflags...ebx from stack frame. 11: push %esp call evtchn_do_upcall add $4,%esp @@ -777,18 +777,13 @@ ecrit: /**** END OF CRITICAL REGION ****/ # provides the number of bytes which have already been popped from the # interrupted stack frame. critical_region_fixup: - addl $critical_fixup_table-scrit,%eax - movzbl (%eax),%eax # %eax contains num bytes popped - cmpb $0xff,%al # 0xff => vcpu_info critical region + movzbl critical_fixup_table-scrit(%eax),%ecx # %eax contains num bytes popped + cmpb $0xff,%cl # 0xff => vcpu_info critical region jne 15f - GET_THREAD_INFO(%ebp) - xorl %eax,%eax -15: mov %esp,%esi - add %eax,%esi # %esi points at end of src region - mov %esp,%edi - add $0x34,%edi # %edi points at end of dst region - mov %eax,%ecx - shr $2,%ecx # convert words to bytes + xorl %ecx,%ecx +15: leal (%esp,%ecx),%esi # %esi points at end of src region + leal OLDESP(%esp),%edi # %edi points at end of dst region + shrl $2,%ecx # convert words to bytes je 17f # skip loop if nothing to copy 16: subl $4,%esi # pre-decrementing copy loop subl $4,%edi @@ -798,6 +793,7 @@ critical_region_fixup: 17: movl %edi,%esp # final %edi is top of merged stack jmp 11b +.section .rodata,"a" critical_fixup_table: .byte 0xff,0xff,0xff # testb $0xff,(%esi) = __TEST_PENDING .byte 0xff,0xff # jnz 14f @@ -814,6 +810,7 @@ critical_fixup_table: .byte 0x28 # iret .byte 0xff,0xff,0xff,0xff # movb $1,1(%esi) .byte 0x00,0x00 # jmp 11b +.previous # Hypervisor uses this for application faults while it executes. # We get here for two reasons: @@ -1194,6 +1191,7 @@ ENTRY(fixup_4gb_segment) jmp error_code .section .rodata,"a" +.align 4 #include "syscall_table.S" syscall_table_size=(.-sys_call_table) From 3310ae17fd5484afa292b12665c460a104e0d2f4 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 7 Feb 2007 00:39:48 +0000 Subject: [PATCH 48/95] linux: Zap /proc/interrupts count when a dynamic IRQ is unbound. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/core/evtchn.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c index 51436b69cc..3e66f3be45 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/evtchn.c @@ -424,7 +424,7 @@ static int bind_ipi_to_irq(unsigned int ipi, unsigned int cpu) static void unbind_from_irq(unsigned int irq) { struct evtchn_close close; - int evtchn = evtchn_from_irq(irq); + int cpu, evtchn = evtchn_from_irq(irq); spin_lock(&irq_mapping_update_lock); @@ -452,6 +452,10 @@ static void unbind_from_irq(unsigned int irq) evtchn_to_irq[evtchn] = -1; irq_info[irq] = IRQ_UNBOUND; + + /* Zap stats across IRQ changes of use. */ + for_each_possible_cpu(cpu) + kstat_cpu(cpu).irqs[irq] = 0; } spin_unlock(&irq_mapping_update_lock); From 326d80a41220644cbaa82b25058437dff32c4e44 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Wed, 7 Feb 2007 00:51:26 +0000 Subject: [PATCH 49/95] Update .hgignore list --- .hgignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.hgignore b/.hgignore index 95b03e6db2..85ddd9d976 100644 --- a/.hgignore +++ b/.hgignore @@ -107,6 +107,7 @@ ^tools/firmware/rombios/BIOS-bochs-[^/]*$ ^tools/firmware/rombios/_rombios[^/]*_\.c$ ^tools/firmware/rombios/rombios[^/]*\.s$ +^tools/firmware/rombios/32bit/32bitbios_flat\.h$ ^tools/firmware/vmxassist/gen$ ^tools/firmware/vmxassist/offsets\.h$ ^tools/firmware/vmxassist/vmxassist$ From a38c7c1575e655ccdee168a265058a41ae13b548 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 02:16:56 +0000 Subject: [PATCH 50/95] linux: Fix softlockup interaction with noidlehz. next_timer_interrupt() must check for when timer ISR is due to wake up the softlockup thread. Signed-off-by: Kevin Tian Signed-off-by: Keir Fraser --- patches/linux-2.6.18/series | 1 + .../linux-2.6.18/softlockup-no-idle-hz.patch | 56 +++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 patches/linux-2.6.18/softlockup-no-idle-hz.patch diff --git a/patches/linux-2.6.18/series b/patches/linux-2.6.18/series index 62b3e0e0d7..85bbae63e4 100644 --- a/patches/linux-2.6.18/series +++ b/patches/linux-2.6.18/series @@ -18,3 +18,4 @@ git-dbaab49f92ff6ae6255762a948375e4036cbdbd2.patch x86-elfnote-as-preprocessor-macro.patch fixaddr-top.patch git-c06cb8b1c4d25e5b4d7a2d7c2462619de1e0dbc4.patch +softlockup-no-idle-hz.patch diff --git a/patches/linux-2.6.18/softlockup-no-idle-hz.patch b/patches/linux-2.6.18/softlockup-no-idle-hz.patch new file mode 100644 index 0000000000..6799bfc4bf --- /dev/null +++ b/patches/linux-2.6.18/softlockup-no-idle-hz.patch @@ -0,0 +1,56 @@ +diff -pruN ../orig-linux-2.6.18/include/linux/sched.h ./include/linux/sched.h +--- ../orig-linux-2.6.18/include/linux/sched.h 2006-09-20 04:42:06.000000000 +0100 ++++ ./include/linux/sched.h 2007-02-07 01:10:24.000000000 +0000 +@@ -211,10 +211,15 @@ extern void update_process_times(int use + extern void scheduler_tick(void); + + #ifdef CONFIG_DETECT_SOFTLOCKUP ++extern unsigned long softlockup_get_next_event(void); + extern void softlockup_tick(void); + extern void spawn_softlockup_task(void); + extern void touch_softlockup_watchdog(void); + #else ++static inline unsigned long softlockup_get_next_event(void) ++{ ++ return MAX_JIFFY_OFFSET; ++} + static inline void softlockup_tick(void) + { + } +diff -pruN ../orig-linux-2.6.18/kernel/softlockup.c ./kernel/softlockup.c +--- ../orig-linux-2.6.18/kernel/softlockup.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/softlockup.c 2007-02-07 01:53:22.000000000 +0000 +@@ -40,6 +40,19 @@ void touch_softlockup_watchdog(void) + } + EXPORT_SYMBOL(touch_softlockup_watchdog); + ++unsigned long softlockup_get_next_event(void) ++{ ++ int this_cpu = smp_processor_id(); ++ unsigned long touch_timestamp = per_cpu(touch_timestamp, this_cpu); ++ ++ if (per_cpu(print_timestamp, this_cpu) == touch_timestamp || ++ did_panic || ++ !per_cpu(watchdog_task, this_cpu)) ++ return MAX_JIFFY_OFFSET; ++ ++ return min_t(long, 0, touch_timestamp + HZ - jiffies); ++} ++ + /* + * This callback runs from the timer interrupt, and checks + * whether the watchdog thread has hung or not: +diff -pruN ../orig-linux-2.6.18/kernel/timer.c ./kernel/timer.c +--- ../orig-linux-2.6.18/kernel/timer.c 2006-09-20 04:42:06.000000000 +0100 ++++ ./kernel/timer.c 2007-02-07 01:29:34.000000000 +0000 +@@ -485,7 +485,9 @@ unsigned long next_timer_interrupt(void) + if (hr_expires < 3) + return hr_expires + jiffies; + } +- hr_expires += jiffies; ++ hr_expires = min_t(unsigned long, ++ softlockup_get_next_event(), ++ hr_expires) + jiffies; + + base = __get_cpu_var(tvec_bases); + spin_lock(&base->lock); From b364d04f1d59e2276ce598f26ab9c48d1dc351d9 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 12:25:18 +0000 Subject: [PATCH 51/95] Revert 13805: losetup -r is not portable which breaks CD support on Debian Sarge, FC4, probably others. Signed-off-by: Tim Deegan --- tools/examples/block | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/tools/examples/block b/tools/examples/block index ac4313ecd9..2b6b991125 100644 --- a/tools/examples/block +++ b/tools/examples/block @@ -367,13 +367,7 @@ mount it read-write in a guest domain." fatal 'Failed to find an unused loop device' fi - cmode=`canonicalise_mode $mode` - if [ "$cmode" == 'r' ] - then - do_or_die losetup -r "$loopdev" "$file" - else - do_or_die losetup "$loopdev" "$file" - fi + do_or_die losetup "$loopdev" "$file" xenstore_write "$XENBUS_PATH/node" "$loopdev" write_dev "$loopdev" release_lock "block" From c2ce43578e7d653614e85ad761f687fa297b70ae Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 10:21:15 +0000 Subject: [PATCH 52/95] [HVM] Save/restore: move save/restore routines out of intercept.c Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/Makefile | 1 + xen/arch/x86/hvm/intercept.c | 176 ------------------------------ xen/arch/x86/hvm/save.c | 204 +++++++++++++++++++++++++++++++++++ 3 files changed, 205 insertions(+), 176 deletions(-) create mode 100644 xen/arch/x86/hvm/save.c diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile index 9fbcf51ede..d94fd082ee 100644 --- a/xen/arch/x86/hvm/Makefile +++ b/xen/arch/x86/hvm/Makefile @@ -15,3 +15,4 @@ obj-y += vpt.o obj-y += vioapic.o obj-y += vlapic.o obj-y += vpic.o +obj-y += save.o diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index f130a252ab..3de58812c3 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -29,8 +29,6 @@ #include #include #include -#include -#include extern struct hvm_mmio_handler hpet_mmio_handler; @@ -157,180 +155,6 @@ static inline void hvm_mmio_access(struct vcpu *v, } } -/* List of handlers for various HVM save and restore types */ -static struct { - hvm_save_handler save; - hvm_load_handler load; - const char *name; -} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, ""},}; - -/* Init-time function to add entries to that list */ -void hvm_register_savevm(uint16_t typecode, - const char *name, - hvm_save_handler save_state, - hvm_load_handler load_state) -{ - ASSERT(typecode <= HVM_SAVE_CODE_MAX); - ASSERT(hvm_sr_handlers[typecode].save == NULL); - ASSERT(hvm_sr_handlers[typecode].load == NULL); - hvm_sr_handlers[typecode].save = save_state; - hvm_sr_handlers[typecode].load = load_state; - hvm_sr_handlers[typecode].name = name; -} - - -int hvm_save(struct domain *d, hvm_domain_context_t *h) -{ - uint32_t eax, ebx, ecx, edx; - char *c; - struct hvm_save_header hdr; - struct hvm_save_end end; - hvm_save_handler handler; - uint16_t i; - - hdr.magic = HVM_FILE_MAGIC; - hdr.version = HVM_FILE_VERSION; - - /* Save some CPUID bits */ - cpuid(1, &eax, &ebx, &ecx, &edx); - hdr.cpuid = eax; - - /* Save xen changeset */ - c = strrchr(XEN_CHANGESET, ':'); - if ( c ) - hdr.changeset = simple_strtoll(c, NULL, 16); - else - hdr.changeset = -1ULL; /* Unknown */ - - if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) - { - gdprintk(XENLOG_ERR, "HVM save: failed to write header\n"); - return -EFAULT; - } - - /* Save all available kinds of state */ - for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) - { - handler = hvm_sr_handlers[i].save; - if ( handler != NULL ) - { - gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name); - if ( handler(d, h) != 0 ) - { - gdprintk(XENLOG_ERR, - "HVM save: failed to save type %"PRIu16"\n", i); - return -EFAULT; - } - } - } - - /* Save an end-of-file marker */ - if ( hvm_save_entry(END, 0, h, &end) != 0 ) - { - /* Run out of data */ - gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n"); - return -EFAULT; - } - - /* Save macros should not have let us overrun */ - ASSERT(h->cur <= h->size); - return 0; -} - -int hvm_load(struct domain *d, hvm_domain_context_t *h) -{ - uint32_t eax, ebx, ecx, edx; - char *c; - uint64_t cset; - struct hvm_save_header hdr; - struct hvm_save_descriptor *desc; - hvm_load_handler handler; - struct vcpu *v; - - /* Read the save header, which must be first */ - if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) - return -1; - - if (hdr.magic != HVM_FILE_MAGIC) { - gdprintk(XENLOG_ERR, - "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic); - return -1; - } - - if (hdr.version != HVM_FILE_VERSION) { - gdprintk(XENLOG_ERR, - "HVM restore: unsupported version %u\n", hdr.version); - return -1; - } - - cpuid(1, &eax, &ebx, &ecx, &edx); - /*TODO: need to define how big a difference is acceptable */ - if (hdr.cpuid != eax) - gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") " - "does not match host (%#"PRIx32").\n", hdr.cpuid, eax); - - - c = strrchr(XEN_CHANGESET, ':'); - if ( hdr.changeset == -1ULL ) - gdprintk(XENLOG_WARNING, - "HVM restore: Xen changeset was not saved.\n"); - else if ( c == NULL ) - gdprintk(XENLOG_WARNING, - "HVM restore: Xen changeset is not available.\n"); - else - { - cset = simple_strtoll(c, NULL, 16); - if ( hdr.changeset != cset ) - gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64 - ") does not match host (%#"PRIx64").\n", hdr.changeset, cset); - } - - /* Down all the vcpus: we only re-enable the ones that had state saved. */ - for_each_vcpu(d, v) - if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) - vcpu_sleep_nosync(v); - - while(1) { - - if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) - { - /* Run out of data */ - gdprintk(XENLOG_ERR, - "HVM restore: save did not end with a null entry\n"); - return -1; - } - - /* Read the typecode of the next entry and check for the end-marker */ - desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); - if ( desc->typecode == 0 ) - return 0; - - /* Find the handler for this entry */ - if ( desc->typecode > HVM_SAVE_CODE_MAX - || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) - { - gdprintk(XENLOG_ERR, - "HVM restore: unknown entry typecode %u\n", - desc->typecode); - return -1; - } - - /* Load the entry */ - gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", - hvm_sr_handlers[desc->typecode].name, desc->instance); - if ( handler(d, h) != 0 ) - { - gdprintk(XENLOG_ERR, - "HVM restore: failed to load entry %u/%u\n", - desc->typecode, desc->instance); - return -1; - } - } - - /* Not reached */ -} - - int hvm_buffered_io_intercept(ioreq_t *p) { struct vcpu *v = current; diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c new file mode 100644 index 0000000000..313f140d24 --- /dev/null +++ b/xen/arch/x86/hvm/save.c @@ -0,0 +1,204 @@ +/* + * hvm/save.c: Save and restore HVM guest's emulated hardware state. + * + * Copyright (c) 2004, Intel Corporation. + * Copyright (c) 2007, XenSource Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + + +/* List of handlers for various HVM save and restore types */ +static struct { + hvm_save_handler save; + hvm_load_handler load; + const char *name; +} hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, ""},}; + +/* Init-time function to add entries to that list */ +void hvm_register_savevm(uint16_t typecode, + const char *name, + hvm_save_handler save_state, + hvm_load_handler load_state) +{ + ASSERT(typecode <= HVM_SAVE_CODE_MAX); + ASSERT(hvm_sr_handlers[typecode].save == NULL); + ASSERT(hvm_sr_handlers[typecode].load == NULL); + hvm_sr_handlers[typecode].save = save_state; + hvm_sr_handlers[typecode].load = load_state; + hvm_sr_handlers[typecode].name = name; +} + + +int hvm_save(struct domain *d, hvm_domain_context_t *h) +{ + uint32_t eax, ebx, ecx, edx; + char *c; + struct hvm_save_header hdr; + struct hvm_save_end end; + hvm_save_handler handler; + uint16_t i; + + hdr.magic = HVM_FILE_MAGIC; + hdr.version = HVM_FILE_VERSION; + + /* Save some CPUID bits */ + cpuid(1, &eax, &ebx, &ecx, &edx); + hdr.cpuid = eax; + + /* Save xen changeset */ + c = strrchr(XEN_CHANGESET, ':'); + if ( c ) + hdr.changeset = simple_strtoll(c, NULL, 16); + else + hdr.changeset = -1ULL; /* Unknown */ + + if ( hvm_save_entry(HEADER, 0, h, &hdr) != 0 ) + { + gdprintk(XENLOG_ERR, "HVM save: failed to write header\n"); + return -EFAULT; + } + + /* Save all available kinds of state */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + { + handler = hvm_sr_handlers[i].save; + if ( handler != NULL ) + { + gdprintk(XENLOG_INFO, "HVM save: %s\n", hvm_sr_handlers[i].name); + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM save: failed to save type %"PRIu16"\n", i); + return -EFAULT; + } + } + } + + /* Save an end-of-file marker */ + if ( hvm_save_entry(END, 0, h, &end) != 0 ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, "HVM save: no room for end marker.\n"); + return -EFAULT; + } + + /* Save macros should not have let us overrun */ + ASSERT(h->cur <= h->size); + return 0; +} + +int hvm_load(struct domain *d, hvm_domain_context_t *h) +{ + uint32_t eax, ebx, ecx, edx; + char *c; + uint64_t cset; + struct hvm_save_header hdr; + struct hvm_save_descriptor *desc; + hvm_load_handler handler; + struct vcpu *v; + + /* Read the save header, which must be first */ + if ( hvm_load_entry(HEADER, h, &hdr) != 0 ) + return -1; + + if (hdr.magic != HVM_FILE_MAGIC) { + gdprintk(XENLOG_ERR, + "HVM restore: bad magic number %#"PRIx32"\n", hdr.magic); + return -1; + } + + if (hdr.version != HVM_FILE_VERSION) { + gdprintk(XENLOG_ERR, + "HVM restore: unsupported version %u\n", hdr.version); + return -1; + } + + cpuid(1, &eax, &ebx, &ecx, &edx); + /*TODO: need to define how big a difference is acceptable */ + if (hdr.cpuid != eax) + gdprintk(XENLOG_WARNING, "HVM restore: saved CPUID (%#"PRIx32") " + "does not match host (%#"PRIx32").\n", hdr.cpuid, eax); + + + c = strrchr(XEN_CHANGESET, ':'); + if ( hdr.changeset == -1ULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset was not saved.\n"); + else if ( c == NULL ) + gdprintk(XENLOG_WARNING, + "HVM restore: Xen changeset is not available.\n"); + else + { + cset = simple_strtoll(c, NULL, 16); + if ( hdr.changeset != cset ) + gdprintk(XENLOG_WARNING, "HVM restore: saved Xen changeset (%#"PRIx64 + ") does not match host (%#"PRIx64").\n", hdr.changeset, cset); + } + + /* Down all the vcpus: we only re-enable the ones that had state saved. */ + for_each_vcpu(d, v) + if ( test_and_set_bit(_VCPUF_down, &v->vcpu_flags) ) + vcpu_sleep_nosync(v); + + while(1) { + + if ( h->size - h->cur < sizeof(struct hvm_save_descriptor) ) + { + /* Run out of data */ + gdprintk(XENLOG_ERR, + "HVM restore: save did not end with a null entry\n"); + return -1; + } + + /* Read the typecode of the next entry and check for the end-marker */ + desc = (struct hvm_save_descriptor *)(&h->data[h->cur]); + if ( desc->typecode == 0 ) + return 0; + + /* Find the handler for this entry */ + if ( desc->typecode > HVM_SAVE_CODE_MAX + || (handler = hvm_sr_handlers[desc->typecode].load) == NULL ) + { + gdprintk(XENLOG_ERR, + "HVM restore: unknown entry typecode %u\n", + desc->typecode); + return -1; + } + + /* Load the entry */ + gdprintk(XENLOG_INFO, "HVM restore: %s %"PRIu16"\n", + hvm_sr_handlers[desc->typecode].name, desc->instance); + if ( handler(d, h) != 0 ) + { + gdprintk(XENLOG_ERR, + "HVM restore: failed to load entry %u/%u\n", + desc->typecode, desc->instance); + return -1; + } + } + + /* Not reached */ +} From 01d0fc79ac7a215f39e6b40e7250a9d63a20bd31 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 12:41:46 +0000 Subject: [PATCH 53/95] [HVM] Save/restore: dynamically calculate the size of the save buffer Signed-off-by: Tim Deegan --- tools/libxc/xc_domain.c | 8 +++++--- tools/libxc/xc_hvm_save.c | 19 +++++++++--------- xen/arch/x86/domctl.c | 25 +++++++++++++++++++----- xen/arch/x86/hvm/hpet.c | 2 +- xen/arch/x86/hvm/hvm.c | 3 ++- xen/arch/x86/hvm/i8254.c | 2 +- xen/arch/x86/hvm/irq.c | 9 ++++++--- xen/arch/x86/hvm/rtc.c | 2 +- xen/arch/x86/hvm/save.c | 27 +++++++++++++++++++++++++- xen/arch/x86/hvm/vioapic.c | 2 +- xen/arch/x86/hvm/vlapic.c | 6 ++++-- xen/arch/x86/hvm/vpic.c | 2 +- xen/include/asm-x86/hvm/support.h | 32 ++++++++++++++++++++++--------- xen/include/public/domctl.h | 3 ++- 14 files changed, 103 insertions(+), 39 deletions(-) diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index e557f43f13..73d229dc61 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -252,12 +252,14 @@ int xc_domain_hvm_getcontext(int xc_handle, domctl.u.hvmcontext.size = size; set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf); - if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) - return ret; + if ( ctxt_buf ) + if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) + return ret; ret = do_domctl(xc_handle, &domctl); - unlock_pages(ctxt_buf, size); + if ( ctxt_buf ) + unlock_pages(ctxt_buf, size); return (ret < 0 ? -1 : domctl.u.hvmcontext.size); } diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index d9cca58d07..e6f5ee1dde 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -32,12 +32,6 @@ #include "xg_private.h" #include "xg_save_restore.h" -/* - * Size of a buffer big enough to take the HVM state of a domain. - * Ought to calculate this a bit more carefully, or maybe ask Xen. - */ -#define HVM_CTXT_SIZE 8192 - /* ** Default values for important tuning parameters. Can override by passing ** non-zero replacement values to xc_hvm_save(). @@ -286,6 +280,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned long *pfn_batch = NULL; /* A copy of hvm domain context buffer*/ + uint32_t hvm_buf_size; uint8_t *hvm_buf = NULL; /* Live mapping of shared info structure */ @@ -431,9 +426,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn); - hvm_buf = malloc(HVM_CTXT_SIZE); + hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); + if ( hvm_buf_size == -1 ) + { + ERROR("Couldn't get HVM context size from Xen"); + goto out; + } + hvm_buf = malloc(hvm_buf_size); - if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) { + if (!to_send ||!to_skip ||!page_array ||!hvm_buf) { ERROR("Couldn't allocate memory"); goto out; } @@ -661,7 +662,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, - HVM_CTXT_SIZE)) == -1) { + hvm_buf_size)) == -1) { ERROR("HVM:Could not get hvm buffer"); goto out; } diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index d73ae65bd5..384faf48e4 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -326,10 +326,6 @@ long arch_do_domctl( struct hvm_domain_context c; struct domain *d; - c.cur = 0; - c.size = domctl->u.hvmcontext.size; - c.data = NULL; - ret = -ESRCH; if ( (d = get_domain_by_id(domctl->domain)) == NULL ) break; @@ -338,19 +334,38 @@ long arch_do_domctl( if ( !is_hvm_domain(d) ) goto gethvmcontext_out; + c.cur = 0; + c.size = hvm_save_size(d); + c.data = NULL; + + if ( guest_handle_is_null(domctl->u.hvmcontext.buffer) ) + { + /* Client is querying for the correct buffer size */ + domctl->u.hvmcontext.size = c.size; + ret = 0; + goto gethvmcontext_out; + } + + /* Check that the client has a big enough buffer */ + ret = -ENOSPC; + if ( domctl->u.hvmcontext.size < c.size ) + goto gethvmcontext_out; + + /* Allocate our own marshalling buffer */ ret = -ENOMEM; if ( (c.data = xmalloc_bytes(c.size)) == NULL ) goto gethvmcontext_out; ret = hvm_save(d, &c); + domctl->u.hvmcontext.size = c.cur; if ( copy_to_guest(domctl->u.hvmcontext.buffer, c.data, c.size) != 0 ) ret = -EFAULT; + gethvmcontext_out: if ( copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; - gethvmcontext_out: if ( c.data != NULL ) xfree(c.data); diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index 6269e149a8..419a886eba 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -409,7 +409,7 @@ static int hpet_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load); +HVM_REGISTER_SAVE_RESTORE(HPET, hpet_save, hpet_load, 1, HVMSR_PER_DOM); void hpet_init(struct vcpu *v) { diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 39ef3c1221..96c827d235 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -227,7 +227,8 @@ static int hvm_load_cpu_ctxt(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt); +HVM_REGISTER_SAVE_RESTORE(CPU, hvm_save_cpu_ctxt, hvm_load_cpu_ctxt, + 1, HVMSR_PER_VCPU); int hvm_vcpu_initialise(struct vcpu *v) { diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index 11ae4ff0ca..a3a21809fe 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -445,7 +445,7 @@ static int pit_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load); +HVM_REGISTER_SAVE_RESTORE(PIT, pit_save, pit_load, 1, HVMSR_PER_DOM); static void pit_reset(void *opaque) { diff --git a/xen/arch/x86/hvm/irq.c b/xen/arch/x86/hvm/irq.c index 6d8432c1ba..aa531b33fb 100644 --- a/xen/arch/x86/hvm/irq.c +++ b/xen/arch/x86/hvm/irq.c @@ -480,6 +480,9 @@ static int irq_load_link(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci); -HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa); -HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link); +HVM_REGISTER_SAVE_RESTORE(PCI_IRQ, irq_save_pci, irq_load_pci, + 1, HVMSR_PER_DOM); +HVM_REGISTER_SAVE_RESTORE(ISA_IRQ, irq_save_isa, irq_load_isa, + 1, HVMSR_PER_DOM); +HVM_REGISTER_SAVE_RESTORE(PCI_LINK, irq_save_link, irq_load_link, + 1, HVMSR_PER_DOM); diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c index d2ee7f8825..5cda6bbb75 100644 --- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -417,7 +417,7 @@ static int rtc_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load); +HVM_REGISTER_SAVE_RESTORE(RTC, rtc_save, rtc_load, 1, HVMSR_PER_DOM); void rtc_init(struct vcpu *v, int base) diff --git a/xen/arch/x86/hvm/save.c b/xen/arch/x86/hvm/save.c index 313f140d24..a19043c175 100644 --- a/xen/arch/x86/hvm/save.c +++ b/xen/arch/x86/hvm/save.c @@ -35,13 +35,16 @@ static struct { hvm_save_handler save; hvm_load_handler load; const char *name; + size_t size; + int kind; } hvm_sr_handlers [HVM_SAVE_CODE_MAX + 1] = {{NULL, NULL, ""},}; /* Init-time function to add entries to that list */ void hvm_register_savevm(uint16_t typecode, const char *name, hvm_save_handler save_state, - hvm_load_handler load_state) + hvm_load_handler load_state, + size_t size, int kind) { ASSERT(typecode <= HVM_SAVE_CODE_MAX); ASSERT(hvm_sr_handlers[typecode].save == NULL); @@ -49,6 +52,28 @@ void hvm_register_savevm(uint16_t typecode, hvm_sr_handlers[typecode].save = save_state; hvm_sr_handlers[typecode].load = load_state; hvm_sr_handlers[typecode].name = name; + hvm_sr_handlers[typecode].size = size; + hvm_sr_handlers[typecode].kind = kind; +} + +size_t hvm_save_size(struct domain *d) +{ + struct vcpu *v; + size_t sz; + int i; + + /* Basic overhead for header and footer */ + sz = (2 * sizeof (struct hvm_save_descriptor)) + HVM_SAVE_LENGTH(HEADER); + + /* Plus space for each thing we will be saving */ + for ( i = 0; i <= HVM_SAVE_CODE_MAX; i++ ) + if ( hvm_sr_handlers[i].kind == HVMSR_PER_VCPU ) + for_each_vcpu(d, v) + sz += hvm_sr_handlers[i].size; + else + sz += hvm_sr_handlers[i].size; + + return sz; } diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index 4e444ce93d..0ce59f94b1 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -514,7 +514,7 @@ static int ioapic_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load); +HVM_REGISTER_SAVE_RESTORE(IOAPIC, ioapic_save, ioapic_load, 1, HVMSR_PER_DOM); void vioapic_init(struct domain *d) { diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index cc4964980d..858c9ab6e2 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -904,8 +904,10 @@ static int lapic_load_regs(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden); -HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs); +HVM_REGISTER_SAVE_RESTORE(LAPIC, lapic_save_hidden, lapic_load_hidden, + 1, HVMSR_PER_VCPU); +HVM_REGISTER_SAVE_RESTORE(LAPIC_REGS, lapic_save_regs, lapic_load_regs, + 1, HVMSR_PER_VCPU); int vlapic_init(struct vcpu *v) { diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c index 41e3ed11a4..3a5b2a16a8 100644 --- a/xen/arch/x86/hvm/vpic.c +++ b/xen/arch/x86/hvm/vpic.c @@ -440,7 +440,7 @@ static int vpic_load(struct domain *d, hvm_domain_context_t *h) return 0; } -HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load); +HVM_REGISTER_SAVE_RESTORE(PIC, vpic_save, vpic_load, 2, HVMSR_PER_DOM); void vpic_init(struct domain *d) { diff --git a/xen/include/asm-x86/hvm/support.h b/xen/include/asm-x86/hvm/support.h index 6d57140fae..6fe753458c 100644 --- a/xen/include/asm-x86/hvm/support.h +++ b/xen/include/asm-x86/hvm/support.h @@ -221,23 +221,37 @@ typedef int (*hvm_save_handler) (struct domain *d, typedef int (*hvm_load_handler) (struct domain *d, hvm_domain_context_t *h); -/* Init-time function to declare a pair of handlers for a type */ +/* Init-time function to declare a pair of handlers for a type, + * and the maximum buffer space needed to save this type of state */ void hvm_register_savevm(uint16_t typecode, const char *name, hvm_save_handler save_state, - hvm_load_handler load_state); + hvm_load_handler load_state, + size_t size, int kind); -/* Syntactic sugar around that function */ -#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load) \ -static int __hvm_register_##_x##_save_and_restore(void) \ -{ \ - hvm_register_savevm(HVM_SAVE_CODE(_x), #_x, &_save, &_load); \ - return 0; \ -} \ +/* The space needed for saving can be per-domain or per-vcpu: */ +#define HVMSR_PER_DOM 0 +#define HVMSR_PER_VCPU 1 + +/* Syntactic sugar around that function: specify the max number of + * saves, and this calculates the size of buffer needed */ +#define HVM_REGISTER_SAVE_RESTORE(_x, _save, _load, _num, _k) \ +static int __hvm_register_##_x##_save_and_restore(void) \ +{ \ + hvm_register_savevm(HVM_SAVE_CODE(_x), \ + #_x, \ + &_save, \ + &_load, \ + (_num) * (HVM_SAVE_LENGTH(_x) \ + + sizeof (struct hvm_save_descriptor)), \ + _k); \ + return 0; \ +} \ __initcall(__hvm_register_##_x##_save_and_restore); /* Entry points for saving and restoring HVM domain state */ +size_t hvm_save_size(struct domain *d); int hvm_save(struct domain *d, hvm_domain_context_t *h); int hvm_load(struct domain *d, hvm_domain_context_t *h); diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h index 93f44f3ba5..f7ea2d8acc 100644 --- a/xen/include/public/domctl.h +++ b/xen/include/public/domctl.h @@ -390,7 +390,8 @@ DEFINE_XEN_GUEST_HANDLE(xen_domctl_settimeoffset_t); #define XEN_DOMCTL_sethvmcontext 34 typedef struct xen_domctl_hvmcontext { uint32_t size; /* IN/OUT: size of buffer / bytes filled */ - XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT */ + XEN_GUEST_HANDLE(uint8_t) buffer; /* IN/OUT: data, or call gethvmcontext + * with NULL buffer to get size req'd */ } xen_domctl_hvmcontext_t; DEFINE_XEN_GUEST_HANDLE(xen_domctl_hvmcontext_t); From 73b12747dcd24fa182b9ff6e2ed0dc37193acafa Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 12:58:07 +0000 Subject: [PATCH 54/95] [XEN] Remove bogus assertion in shadow emulation path Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/multi.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 8b8b8585a7..9e0d0e1fbf 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3875,11 +3875,9 @@ static inline void * emulate_map_dest(struct vcpu *v, goto page_fault; } - /* Attempted a write to a bad gfn? This should never happen: - * after all, we're here because this write is to a page table. */ - BUG_ON(!mfn_valid(mfn)); + if ( !mfn_valid(mfn) ) + return NULL; - ASSERT(sh_mfn_is_a_page_table(mfn)); *mfnp = mfn; return sh_map_domain_page(mfn) + (vaddr & ~PAGE_MASK); From b64ef24e2f1684085b9f12aef1dc5fbd5bea5c3f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:08:47 +0000 Subject: [PATCH 55/95] hvm: Add PCI subsystem ID to emulated devices. This patch adds the PCI Subsystem ID 5853:0001 to the virtual devices emulated by qemu (ide, nic, vga). Signed-off-by: Gerd Hoffmann --- tools/ioemu/hw/cirrus_vga.c | 4 ++++ tools/ioemu/hw/ide.c | 4 ++++ tools/ioemu/hw/rtl8139.c | 6 ++++-- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 3c316d6dc9..292673ae6a 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -3339,6 +3339,10 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, pci_conf[0x0a] = PCI_CLASS_SUB_VGA; pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY; pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; /* setup VGA */ s = &d->cirrus_vga; diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index ef203a2f8a..3bf2c7d594 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -2502,6 +2502,10 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage pci_conf[0x0e] = 0x00; // header_type + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; pci_register_io_region((PCIDevice *)d, 4, 0x10, PCI_ADDRESS_SPACE_IO, bmdma_map); diff --git a/tools/ioemu/hw/rtl8139.c b/tools/ioemu/hw/rtl8139.c index 77e3c6d9fb..e4ba40dfe3 100644 --- a/tools/ioemu/hw/rtl8139.c +++ b/tools/ioemu/hw/rtl8139.c @@ -3423,8 +3423,10 @@ void pci_rtl8139_init(PCIBus *bus, NICInfo *nd) pci_conf[0x0e] = 0x00; /* header_type */ pci_conf[0x3d] = 1; /* interrupt pin 0 */ pci_conf[0x34] = 0xdc; - pci_conf[0x2c] = pci_conf[0x00]; // same as Vendor ID - pci_conf[0x2d] = pci_conf[0x01]; + pci_conf[0x2c] = 0x53; /* subsystem vendor: XenSource */ + pci_conf[0x2d] = 0x58; + pci_conf[0x2e] = 0x01; /* subsystem device */ + pci_conf[0x2f] = 0x00; s = &d->rtl8139; From 6b91de464c93f0c24e72de22d81a8192a39920e4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:12:40 +0000 Subject: [PATCH 56/95] pvfb: Split mouse and keyboard into separate devices. This patch creates two separate input devices for keyboard and mouse events. The reason for this is to separate them in the linux input layer and allow them being routed different ways. Use case: Configure the X-Server like this to get the mouse events directly from the linux input layer, which has the major advantage that absolute coordinates work correctly: Section "InputDevice" Driver "evdev" Identifier "Mouse" Option "Device" "/dev/input/event" EndSection This makes the keyboard stop working though in case mouse and keyboard events are coming through the same input device, at least with older Xorg (6.9) versions. Signed-off-by: Gerd Hoffmann Assign fake pci product identifiers down from 0xffff. This may help clarify that the devices are not actually PCI. Also it reduces probability of accidental conflict if further real PCI assignments occur in future (0x0002, 0x0003, ... would be obvious next identifiers to allocate). Signed-off-by: Keir Fraser --- .../drivers/xen/fbfront/xenkbd.c | 97 +++++++++++++------ 1 file changed, 67 insertions(+), 30 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c index e4debd83d3..a34beafcda 100644 --- a/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/fbfront/xenkbd.c @@ -29,10 +29,12 @@ struct xenkbd_info { - struct input_dev *dev; + struct input_dev *kbd; + struct input_dev *ptr; struct xenkbd_page *page; int irq; struct xenbus_device *xbdev; + char phys[32]; }; static int xenkbd_remove(struct xenbus_device *); @@ -56,23 +58,36 @@ static irqreturn_t input_handler(int rq, void *dev_id, struct pt_regs *regs) rmb(); /* ensure we see ring contents up to prod */ for (cons = page->in_cons; cons != prod; cons++) { union xenkbd_in_event *event; + struct input_dev *dev; event = &XENKBD_IN_RING_REF(page, cons); + dev = info->ptr; switch (event->type) { case XENKBD_TYPE_MOTION: - input_report_rel(info->dev, REL_X, event->motion.rel_x); - input_report_rel(info->dev, REL_Y, event->motion.rel_y); + input_report_rel(dev, REL_X, event->motion.rel_x); + input_report_rel(dev, REL_Y, event->motion.rel_y); break; case XENKBD_TYPE_KEY: - input_report_key(info->dev, event->key.keycode, event->key.pressed); + dev = NULL; + if (test_bit(event->key.keycode, info->kbd->keybit)) + dev = info->kbd; + if (test_bit(event->key.keycode, info->ptr->keybit)) + dev = info->ptr; + if (dev) + input_report_key(dev, event->key.keycode, + event->key.pressed); + else + printk("xenkbd: unhandled keycode 0x%x\n", + event->key.keycode); break; case XENKBD_TYPE_POS: - input_report_abs(info->dev, ABS_X, event->pos.abs_x); - input_report_abs(info->dev, ABS_Y, event->pos.abs_y); + input_report_abs(dev, ABS_X, event->pos.abs_x); + input_report_abs(dev, ABS_Y, event->pos.abs_y); break; } + if (dev) + input_sync(dev); } - input_sync(info->dev); mb(); /* ensure we got ring contents */ page->in_cons = cons; notify_remote_via_irq(info->irq); @@ -85,7 +100,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, { int ret, i; struct xenkbd_info *info; - struct input_dev *input_dev; + struct input_dev *kbd, *ptr; info = kzalloc(sizeof(*info), GFP_KERNEL); if (!info) { @@ -94,6 +109,7 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, } dev->dev.driver_data = info; info->xbdev = dev; + snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename); info->page = (void *)__get_free_page(GFP_KERNEL); if (!info->page) @@ -101,32 +117,52 @@ int __devinit xenkbd_probe(struct xenbus_device *dev, info->page->in_cons = info->page->in_prod = 0; info->page->out_cons = info->page->out_prod = 0; - input_dev = input_allocate_device(); - if (!input_dev) + /* keyboard */ + kbd = input_allocate_device(); + if (!kbd) goto error_nomem; + kbd->name = "Xen Virtual Keyboard"; + kbd->phys = info->phys; + kbd->id.bustype = BUS_PCI; + kbd->id.vendor = 0x5853; + kbd->id.product = 0xffff; + kbd->evbit[0] = BIT(EV_KEY); + for (i = KEY_ESC; i < KEY_UNKNOWN; i++) + set_bit(i, kbd->keybit); + for (i = KEY_OK; i < KEY_MAX; i++) + set_bit(i, kbd->keybit); - input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); - input_dev->keybit[LONG(BTN_MOUSE)] - = BIT(BTN_LEFT) | BIT(BTN_MIDDLE) | BIT(BTN_RIGHT); - /* TODO additional buttons */ - input_dev->relbit[0] = BIT(REL_X) | BIT(REL_Y); - - /* FIXME not sure this is quite right */ - for (i = 0; i < 256; i++) - set_bit(i, input_dev->keybit); - - input_dev->name = "Xen Virtual Keyboard/Mouse"; - - input_set_abs_params(input_dev, ABS_X, 0, XENFB_WIDTH, 0, 0); - input_set_abs_params(input_dev, ABS_Y, 0, XENFB_HEIGHT, 0, 0); - - ret = input_register_device(input_dev); + ret = input_register_device(kbd); if (ret) { - input_free_device(input_dev); - xenbus_dev_fatal(dev, ret, "input_register_device"); + input_free_device(kbd); + xenbus_dev_fatal(dev, ret, "input_register_device(kbd)"); goto error; } - info->dev = input_dev; + info->kbd = kbd; + + /* pointing device */ + ptr = input_allocate_device(); + if (!ptr) + goto error_nomem; + ptr->name = "Xen Virtual Pointer"; + ptr->phys = info->phys; + ptr->id.bustype = BUS_PCI; + ptr->id.vendor = 0x5853; + ptr->id.product = 0xfffe; + ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS); + for (i = BTN_LEFT; i <= BTN_TASK; i++) + set_bit(i, ptr->keybit); + ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y); + input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0); + input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0); + + ret = input_register_device(ptr); + if (ret) { + input_free_device(ptr); + xenbus_dev_fatal(dev, ret, "input_register_device(ptr)"); + goto error; + } + info->ptr = ptr; ret = xenkbd_connect_backend(dev, info); if (ret < 0) @@ -155,7 +191,8 @@ static int xenkbd_remove(struct xenbus_device *dev) struct xenkbd_info *info = dev->dev.driver_data; xenkbd_disconnect_backend(info); - input_unregister_device(info->dev); + input_unregister_device(info->kbd); + input_unregister_device(info->ptr); free_page((unsigned long)info->page); kfree(info); return 0; From e7f13aefbd2e782f83d47a62bf1cf549b51ec933 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:20:28 +0000 Subject: [PATCH 57/95] Dom0 VNC server should not drop any of teh 8 supported mouse button event types. Signed-off-by: Daniel P. Berrange --- tools/xenfb/vncfb.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/xenfb/vncfb.c b/tools/xenfb/vncfb.c index c2a7e5d02d..1ae06809fc 100644 --- a/tools/xenfb/vncfb.c +++ b/tools/xenfb/vncfb.c @@ -57,7 +57,8 @@ unsigned char keycode_table[512]; static void *kbd_layout; static int btnmap[] = { - BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_FORWARD, BTN_BACK + BTN_LEFT, BTN_MIDDLE, BTN_RIGHT, BTN_SIDE, + BTN_EXTRA, BTN_FORWARD, BTN_BACK, BTN_TASK }; static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) @@ -73,11 +74,12 @@ static void on_kbd_event(rfbBool down, rfbKeySym keycode, rfbClientPtr cl) */ rfbScreenInfoPtr server = cl->screen; struct xenfb *xenfb = server->screenData; + int scancode; - if( keycode >= 'A' && keycode <= 'Z' ) + if (keycode >= 'A' && keycode <= 'Z') keycode += 'a' - 'A'; - int scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; + scancode = keycode_table[keysym2scancode(kbd_layout, keycode)]; if (scancode == 0) return; if (xenfb_send_key(xenfb, down, scancode) < 0) From a8d52901714bbef1f07df0cca60b43ad61405a07 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 7 Feb 2007 16:22:55 +0000 Subject: [PATCH 58/95] Improve hotplug script error reporting via xenstore. Use this to detect and report up-front in vif-bridge script whether the bridge device exists or not. Signed-off-by: Daniel P. Berrange --- tools/examples/vif-bridge | 7 ++++ tools/examples/xen-hotplug-common.sh | 5 ++- tools/python/xen/xend/server/DevController.py | 37 ++++++++++--------- 3 files changed, 29 insertions(+), 20 deletions(-) diff --git a/tools/examples/vif-bridge b/tools/examples/vif-bridge index 0935ad2fae..6bee562c4b 100755 --- a/tools/examples/vif-bridge +++ b/tools/examples/vif-bridge @@ -46,6 +46,13 @@ then fi fi +RET=0 +ip link show $bridge 1>/dev/null 2>&1 || RET=1 +if [ "$RET" -eq 1 ] +then + fatal "Could not find bridge device $bridge" +fi + case "$command" in online) setup_bridge_port "$vif" diff --git a/tools/examples/xen-hotplug-common.sh b/tools/examples/xen-hotplug-common.sh index c825dae593..980a62704e 100644 --- a/tools/examples/xen-hotplug-common.sh +++ b/tools/examples/xen-hotplug-common.sh @@ -28,14 +28,15 @@ export LANG="POSIX" unset $(set | grep ^LC_ | cut -d= -f1) fatal() { - xenstore_write "$XENBUS_PATH"/hotplug-status error + xenstore_write "$XENBUS_PATH/hotplug-error" "$*" \ + "$XENBUS_PATH/hotplug-status" error log err "$@" exit 1 } success() { # Tell DevController that backend is "connected" - xenstore_write "$XENBUS_PATH"/hotplug-status connected + xenstore_write "$XENBUS_PATH/hotplug-status" connected } do_or_die() { diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 8256d2265f..47f03e1994 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -153,9 +153,9 @@ class DevController: log.debug("Waiting for %s.", devid) if not self.hotplug: - return - - status = self.waitForBackend(devid) + return + + (status, err) = self.waitForBackend(devid) if status == Timeout: self.destroyDevice(devid, False) @@ -165,25 +165,22 @@ class DevController: elif status == Error: self.destroyDevice(devid, False) - raise VmError("Device %s (%s) could not be connected. " - "Backend device not found." % - (devid, self.deviceClass)) - + if err is None: + raise VmError("Device %s (%s) could not be connected. " + "Backend device not found." % + (devid, self.deviceClass)) + else: + raise VmError("Device %s (%s) could not be connected. " + "%s" % (devid, self.deviceClass, err)) elif status == Missing: # Don't try to destroy the device; it's already gone away. raise VmError("Device %s (%s) could not be connected. " "Device not found." % (devid, self.deviceClass)) elif status == Busy: - err = None - frontpath = self.frontendPath(devid) - backpath = xstransact.Read(frontpath, "backend") - if backpath: - err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) - if not err: - err = "Busy." - self.destroyDevice(devid, False) + if err is None: + err = "Busy." raise VmError("Device %s (%s) could not be connected.\n%s" % (devid, self.deviceClass, err)) @@ -478,17 +475,21 @@ class DevController: frontpath = self.frontendPath(devid) backpath = xstransact.Read(frontpath, "backend") + if backpath: statusPath = backpath + '/' + HOTPLUG_STATUS_NODE ev = Event() result = { 'status': Timeout } - + xswatch(statusPath, hotplugStatusCallback, ev, result) ev.wait(DEVICE_CREATE_TIMEOUT) - return result['status'] + + err = xstransact.Read(backpath, HOTPLUG_ERROR_NODE) + + return (result['status'], err) else: - return Missing + return (Missing, None) def backendPath(self, backdom, devid): From ac13f58c67efde3695d1f976536c9a13ccd56d1a Mon Sep 17 00:00:00 2001 From: "awilliam@xenbuild2.aw" Date: Wed, 7 Feb 2007 10:14:41 -0700 Subject: [PATCH 59/95] [IA64] Clean up error messages from lookup_domain_mpa() Guest I/O port accesses aren't very interesting, so reduce their log level Signed-off-by: Alex Williamson --- xen/arch/ia64/xen/mm.c | 27 ++++++++++++++++--------- xen/include/asm-ia64/linux-xen/asm/io.h | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/xen/arch/ia64/xen/mm.c b/xen/arch/ia64/xen/mm.c index 5cdb25c397..9b153b7f51 100644 --- a/xen/arch/ia64/xen/mm.c +++ b/xen/arch/ia64/xen/mm.c @@ -525,7 +525,9 @@ u64 translate_domain_pte(u64 pteval, u64 address, u64 itir__, u64* logps, This can happen when domU tries to touch i/o port space. Also prevents possible address aliasing issues. */ - printk("Warning: UC to WB for mpaddr=%lx\n", mpaddr); + if (!(mpaddr - IO_PORTS_PADDR < IO_PORTS_SIZE)) + gdprintk(XENLOG_WARNING, "Warning: UC to WB " + "for mpaddr=%lx\n", mpaddr); pteval = (pteval & ~_PAGE_MA_MASK) | _PAGE_MA_WB; } break; @@ -690,7 +692,6 @@ unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, if (pte != NULL) { pte_t tmp_pte = *pte;// pte is volatile. copy the value. if (pte_present(tmp_pte)) { -//printk("lookup_domain_page: found mapping for %lx, pte=%lx\n",mpaddr,pte_val(*pte)); if (entry != NULL) p2m_entry_set(entry, pte, tmp_pte); return pte_val(tmp_pte); @@ -698,14 +699,20 @@ unsigned long lookup_domain_mpa(struct domain *d, unsigned long mpaddr, return GPFN_INV_MASK; } - printk("%s: d 0x%p id %d current 0x%p id %d\n", - __func__, d, d->domain_id, current, current->vcpu_id); - if (mpaddr < d->arch.convmem_end) - printk("%s: non-allocated mpa 0x%lx (< 0x%lx)\n", __func__, - mpaddr, d->arch.convmem_end); - else - printk("%s: bad mpa 0x%lx (=> 0x%lx)\n", __func__, - mpaddr, d->arch.convmem_end); + if (mpaddr < d->arch.convmem_end) { + gdprintk(XENLOG_WARNING, "vcpu %d iip 0x%016lx: non-allocated mpa " + "0x%lx (< 0x%lx)\n", current->vcpu_id, PSCB(current, iip), + mpaddr, d->arch.convmem_end); + } else if (mpaddr - IO_PORTS_PADDR < IO_PORTS_SIZE) { + /* Log I/O port probing, but complain less loudly about it */ + gdprintk(XENLOG_INFO, "vcpu %d iip 0x%016lx: bad I/O port access " + "0x%lx\n ", current->vcpu_id, PSCB(current, iip), + IO_SPACE_SPARSE_DECODING(mpaddr - IO_PORTS_PADDR)); + } else { + gdprintk(XENLOG_WARNING, "vcpu %d iip 0x%016lx: bad mpa 0x%lx " + "(=> 0x%lx)\n", current->vcpu_id, PSCB(current, iip), + mpaddr, d->arch.convmem_end); + } if (entry != NULL) p2m_entry_set(entry, NULL, __pte(0)); diff --git a/xen/include/asm-ia64/linux-xen/asm/io.h b/xen/include/asm-ia64/linux-xen/asm/io.h index 3ad22c0547..3182a944aa 100644 --- a/xen/include/asm-ia64/linux-xen/asm/io.h +++ b/xen/include/asm-ia64/linux-xen/asm/io.h @@ -49,7 +49,7 @@ #ifdef XEN /* Offset to IO port; do not catch error. */ -#define IO_SPACE_SPARSE_DECODING(off) ((((off) >> 12) << 2) | (off & 0x3)) +#define IO_SPACE_SPARSE_DECODING(off) ((((off) >> 12) << 2) | ((off) & 0x3)) #define IO_SPACE_SPARSE_PORTS_PER_PAGE (0x4 << (PAGE_SHIFT - 12)) #endif From 431be892ae4676cc17d7b0888567ba24b45b4149 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 17:29:21 +0000 Subject: [PATCH 60/95] [XEND] Open save/restore files with O_LARGEFILE if possible Signed-off-by: Tim Deegan --- tools/python/xen/xend/XendDomain.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/python/xen/xend/XendDomain.py b/tools/python/xen/xend/XendDomain.py index 303a615ad8..0c8cddde48 100644 --- a/tools/python/xen/xend/XendDomain.py +++ b/tools/python/xen/xend/XendDomain.py @@ -800,7 +800,10 @@ class XendDomain: "support.") path = self._managed_check_point_path(dom_uuid) - fd = os.open(path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(path, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, path) @@ -840,8 +843,11 @@ class XendDomain: # Restore that replaces the existing XendDomainInfo try: log.debug('Current DomainInfo state: %d' % dominfo.state) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE XendCheckpoint.restore(self, - os.open(chkpath, os.O_RDONLY), + os.open(chkpath, oflags), dominfo, paused = start_paused) os.unlink(chkpath) @@ -1009,7 +1015,10 @@ class XendDomain: @raise XendError: Failure to restore domain """ try: - fd = os.open(src, os.O_RDONLY) + oflags = os.O_RDONLY + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(src, oflags) try: return self.domain_restore_fd(fd, paused=paused) finally: @@ -1193,7 +1202,10 @@ class XendDomain: if dominfo.getDomid() == DOM0_ID: raise XendError("Cannot save privileged domain %i" % domid) - fd = os.open(dst, os.O_WRONLY | os.O_CREAT | os.O_TRUNC) + oflags = os.O_WRONLY | os.O_CREAT | os.O_TRUNC + if hasattr(os, "O_LARGEFILE"): + oflags |= os.O_LARGEFILE + fd = os.open(dst, oflags) try: # For now we don't support 'live checkpoint' XendCheckpoint.save(fd, dominfo, False, False, dst) From 2b30444fe2a045eeaa1e6d7e656ad34989350ebc Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 7 Feb 2007 17:29:52 +0000 Subject: [PATCH 61/95] [HVM] Save/restore: don't try to save the MMIO memory-hole at 4GB. Also remove two integer arrays that were set to a[i] == i. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_save.c | 70 +++++++++++++++------------------------ 1 file changed, 27 insertions(+), 43 deletions(-) diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index e6f5ee1dde..fdd2799743 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "xc_private.h" #include "xg_private.h" @@ -275,9 +276,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, /* A copy of the CPU context of the guest. */ vcpu_guest_context_t ctxt; - /* A table containg the type of each PFN (/not/ MFN!). */ - unsigned long *pfn_type = NULL; - unsigned long *pfn_batch = NULL; + /* A table containg the PFNs (/not/ MFN!) to map. */ + xen_pfn_t *pfn_batch = NULL; /* A copy of hvm domain context buffer*/ uint32_t hvm_buf_size; @@ -290,7 +290,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned char *region_base = NULL; uint32_t nr_pfns, rec_size, nr_vcpus; - unsigned long *page_array = NULL; /* power of 2 order of max_pfn */ int order_nr; @@ -361,18 +360,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - max_pfn = live_shinfo->arch.max_pfn; - DPRINTF("saved hvm domain info:max_memkb=0x%lx, max_mfn=0x%lx, nr_pages=0x%lx\n", info.max_memkb, max_mfn, info.nr_pages); - /* nr_pfns: total pages excluding vga acc mem - * max_pfn: nr_pfns + 0x20 vga hole(0xa0~0xc0) - * getdomaininfo.tot_pages: all the allocated pages for this domain - */ if (live) { ERROR("hvm domain doesn't support live migration now.\n"); goto out; - + if (xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY, NULL, 0, NULL, 0, NULL) < 0) { @@ -381,6 +374,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } /* excludes vga acc mem */ + /* XXX will need to check whether acceleration is enabled here! */ nr_pfns = info.nr_pages - 0x800; last_iter = 0; @@ -396,8 +390,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, ERROR("HVM Domain appears not to have suspended"); goto out; } - nr_pfns = info.nr_pages; - DPRINTF("after suspend hvm domain nr_pages=0x%x.\n", nr_pfns); + + nr_pfns = info.nr_pages; } DPRINTF("after 1st handle hvm domain nr_pfns=0x%x, nr_pages=0x%lx, max_memkb=0x%lx, live=%d.\n", @@ -406,10 +400,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, info.max_memkb, live); - nr_pfns = info.nr_pages; - - /*XXX: caculate the VGA hole*/ - max_pfn = nr_pfns + 0x20; + /* Calculate the highest PFN of "normal" memory: + * HVM memory is sequential except for the VGA and MMIO holes, and + * we have nr_pfns of it (which now excludes the cirrus video RAM) */ + max_pfn = nr_pfns; + /* Skip the VGA hole from 0xa0000 to 0xc0000 */ + max_pfn += 0x20; + /* Skip the MMIO hole: 256MB just below 4GB */ + if ( max_pfn >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) ) + max_pfn += (HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT); skip_this_iter = 0;/*XXX*/ /* pretend we sent all the pages last iteration */ @@ -424,7 +423,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, to_send = malloc(BITMAP_SIZE); to_skip = malloc(BITMAP_SIZE); - page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn); hvm_buf_size = xc_domain_hvm_getcontext(xc_handle, dom, 0, 0); if ( hvm_buf_size == -1 ) @@ -434,7 +432,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } hvm_buf = malloc(hvm_buf_size); - if (!to_send ||!to_skip ||!page_array ||!hvm_buf) { + if (!to_send ||!to_skip ||!hvm_buf) { ERROR("Couldn't allocate memory"); goto out; } @@ -454,26 +452,16 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, analysis_phase(xc_handle, dom, max_pfn, to_skip, 0); - /* get all the HVM domain pfns */ - for ( i = 0; i < max_pfn; i++) - page_array[i] = i; - /* We want zeroed memory so use calloc rather than malloc. */ - pfn_type = calloc(MAX_BATCH_SIZE, sizeof(*pfn_type)); pfn_batch = calloc(MAX_BATCH_SIZE, sizeof(*pfn_batch)); - if ((pfn_type == NULL) || (pfn_batch == NULL)) { - ERROR("failed to alloc memory for pfn_type and/or pfn_batch arrays"); + if (pfn_batch == NULL) { + ERROR("failed to alloc memory for pfn_batch array"); errno = ENOMEM; goto out; } - if (lock_pages(pfn_type, MAX_BATCH_SIZE * sizeof(*pfn_type))) { - ERROR("Unable to lock"); - goto out; - } - /* Start writing out the saved-domain record. */ if (!write_exact(io_fd, &max_pfn, sizeof(unsigned long))) { ERROR("write: max_pfn"); @@ -511,16 +499,15 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } - /* load pfn_type[] with the mfn of all the pages we're doing in + /* load pfn_batch[] with the mfn of all the pages we're doing in this batch. */ for (batch = 0; batch < MAX_BATCH_SIZE && N < max_pfn ; N++) { int n = permute(N, max_pfn, order_nr); if (debug) { - DPRINTF("%d pfn= %08lx mfn= %08lx %d \n", - iter, (unsigned long)n, page_array[n], - test_bit(n, to_send)); + DPRINTF("%d pfn= %08lx %d \n", + iter, (unsigned long)n, test_bit(n, to_send)); } if (!last_iter && test_bit(n, to_send)&& test_bit(n, to_skip)) @@ -530,10 +517,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, (test_bit(n, to_send) && last_iter))) continue; - if (n >= 0xa0 && n < 0xc0) { -/* DPRINTF("get a vga hole pfn= %x.\n", n);*/ + /* Skip PFNs that aren't really there */ + if ((n >= 0xa0 && n < 0xc0) /* VGA hole */ + || (n >= (HVM_BELOW_4G_MMIO_START >> PAGE_SHIFT) + && n < (1ULL << 32) >> PAGE_SHIFT)) /* 4G MMIO hole */ continue; - } + /* ** we get here if: ** 1. page is marked to_send & hasn't already been re-dirtied @@ -541,7 +530,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, */ pfn_batch[batch] = n; - pfn_type[batch] = page_array[n]; batch++; } @@ -573,7 +561,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - sent_this_iter += batch; munmap(region_base, batch*PAGE_SIZE); @@ -723,9 +710,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } free(hvm_buf); - free(page_array); - - free(pfn_type); free(pfn_batch); free(to_send); free(to_skip); From 51efffe71249ca3250c3c4be0192525c41a7dc81 Mon Sep 17 00:00:00 2001 From: "wim@xen-wim.site" Date: Wed, 7 Feb 2007 16:53:01 -0800 Subject: [PATCH 62/95] [blktap] Allow HVM booting from blktap device(s) Signed-off-by: wim colgate --- tools/ioemu/xenstore.c | 60 +++++++++++++++++- tools/python/xen/xend/XendConfig.py | 41 ++++++++++++ tools/python/xen/xend/XendDomainInfo.py | 56 ++++++++++++++++- .../xen/xend/server/BlktapController.py | 62 +++++++++++++++++++ tools/python/xen/xend/server/DevController.py | 13 ++++ 5 files changed, 230 insertions(+), 2 deletions(-) diff --git a/tools/ioemu/xenstore.c b/tools/ioemu/xenstore.c index 21a8ed08b7..6b1036bcbf 100644 --- a/tools/ioemu/xenstore.c +++ b/tools/ioemu/xenstore.c @@ -10,6 +10,7 @@ #include "vl.h" #include "block_int.h" +#include static struct xs_handle *xsh = NULL; static char *hd_filename[MAX_DISKS]; @@ -52,11 +53,40 @@ void xenstore_check_new_media_present(int timeout) qemu_mod_timer(insert_timer, qemu_get_clock(rt_clock) + timeout); } +static int waitForDevice(char *path, char *field, char *desired) +{ + char *buf = NULL, *stat = NULL; + unsigned int len; + int val = 1; + + /* loop until we find a value in xenstore, return + * if it was what we wanted, or not + */ + while (1) { + if (pasprintf(&buf, "%s/%s", path, field) == -1) + goto done; + free(stat); + stat = xs_read(xsh, XBT_NULL, buf, &len); + if (stat == NULL) { + usleep(100000); /* 1/10th second, no path found */ + } else { + val = strcmp(stat, desired); + goto done; + } + } + +done: + free(stat); + free(buf); + return val; +} + void xenstore_parse_domain_config(int domid) { char **e = NULL; char *buf = NULL, *path; - char *bpath = NULL, *dev = NULL, *params = NULL, *type = NULL; + char *fpath = NULL, *bpath = NULL, + *dev = NULL, *params = NULL, *type = NULL; int i; unsigned int len, num, hd_index; @@ -120,7 +150,35 @@ void xenstore_parse_domain_config(int domid) hd_filename[hd_index] = params; /* strdup() */ params = NULL; /* don't free params on re-use */ } + /* + * check if device has a phantom vbd; the phantom is hooked + * to the frontend device (for ease of cleanup), so lookup + * the frontend device, and see if there is a phantom_vbd + * if there is, we will use resolution as the filename + */ + if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1) + continue; + free(fpath); + fpath = xs_read(xsh, XBT_NULL, buf, &len); + if (fpath != NULL) { + + if (waitForDevice(fpath, "hotplug-status", "connected")) { + continue; + } + + if (pasprintf(&buf, "%s/dev", fpath) == -1) + continue; + params = xs_read(xsh, XBT_NULL, buf , &len); + if (params != NULL) { + free(hd_filename[hd_index]); + hd_filename[hd_index] = params; + params = NULL; /* don't free params on re-use */ + } + } bs_table[hd_index] = bdrv_new(dev); + /* re-establish buf */ + if (pasprintf(&buf, "%s/params", bpath) == -1) + continue; /* check if it is a cdrom */ if (type && !strcmp(type, "cdrom")) { bdrv_set_type_hint(bs_table[hd_index], BDRV_TYPE_CDROM); diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index 223a90cf6e..fa19165e77 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -1148,6 +1148,47 @@ class XendConfig(dict): # no valid device to add return '' + def phantom_device_add(self, dev_type, cfg_xenapi = None, + target = None): + """Add a phantom tap device configuration in XenAPI struct format. + """ + + if target == None: + target = self + + if dev_type not in XendDevices.valid_devices() and \ + dev_type not in XendDevices.pseudo_devices(): + raise XendConfigError("XendConfig: %s not a valid device type" % + dev_type) + + if cfg_xenapi == None: + raise XendConfigError("XendConfig: device_add requires some " + "config.") + + if cfg_xenapi: + log.debug("XendConfig.phantom_device_add: %s" % str(cfg_xenapi)) + + if cfg_xenapi: + dev_info = {} + if dev_type in ('vbd', 'tap'): + if dev_type == 'vbd': + dev_info['uname'] = cfg_xenapi.get('image', '') + dev_info['dev'] = '%s:disk' % cfg_xenapi.get('device') + elif dev_type == 'tap': + if cfg_xenapi.get('image').find('tap:') == -1: + dev_info['uname'] = 'tap:qcow:%s' % cfg_xenapi.get('image') + dev_info['dev'] = '/dev/%s' % cfg_xenapi.get('device') + dev_info['uname'] = cfg_xenapi.get('image') + dev_info['mode'] = cfg_xenapi.get('mode') + dev_info['backend'] = '0' + dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_info['uuid'] = dev_uuid + self['devices'][dev_uuid] = (dev_type, dev_info) + self['vbd_refs'].append(dev_uuid) + return dev_uuid + + return '' + def console_add(self, protocol, location, other_config = {}): dev_uuid = uuid.createString() if protocol == 'vt100': diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index ddc240b96b..160ee25a90 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1565,19 +1565,54 @@ class XendDomainInfo: # VM Destroy # + def _prepare_phantom_paths(self): + # get associated devices to destroy + # build list of phantom devices to be removed after normal devices + plist = [] + from xen.xend.xenstore.xstransact import xstransact + t = xstransact("%s/device/vbd" % GetDomainPath(self.domid)) + for dev in t.list(): + backend_phantom_vbd = xstransact.Read("%s/device/vbd/%s/phantom_vbd" \ + % (self.dompath, dev)) + if backend_phantom_vbd is not None: + frontend_phantom_vbd = xstransact.Read("%s/frontend" \ + % backend_phantom_vbd) + plist.append(backend_phantom_vbd) + plist.append(frontend_phantom_vbd) + return plist + + def _cleanup_phantom_devs(self, plist): + # remove phantom devices + if not plist == []: + time.sleep(2) + for paths in plist: + if paths.find('backend') != -1: + from xen.xend.server import DevController + # Modify online status /before/ updating state (latter is watched by + # drivers, so this ordering avoids a race). + xstransact.Write(paths, 'online', "0") + xstransact.Write(paths, 'state', str(DevController.xenbusState['Closing'])) + # force + xstransact.Remove(paths) + def destroy(self): """Cleanup VM and destroy domain. Nothrow guarantee.""" log.debug("XendDomainInfo.destroy: domid=%s", str(self.domid)) + paths = self._prepare_phantom_paths() + self._cleanupVm() if self.dompath is not None: self.destroyDomain() + self._cleanup_phantom_devs(paths) def destroyDomain(self): log.debug("XendDomainInfo.destroyDomain(%s)", str(self.domid)) + paths = self._prepare_phantom_paths() + try: if self.domid is not None: xc.domain_destroy(self.domid) @@ -1591,7 +1626,7 @@ class XendDomainInfo: XendDomain.instance().remove_domain(self) self.cleanupDomain() - + self._cleanup_phantom_devs(paths) def resumeDomain(self): log.debug("XendDomainInfo.resumeDomain(%s)", str(self.domid)) @@ -2211,6 +2246,25 @@ class XendDomainInfo: return dev_uuid + def create_phantom_vbd_with_vdi(self, xenapi_vbd, vdi_image_path): + """Create a VBD using a VDI from XendStorageRepository. + + @param xenapi_vbd: vbd struct from the Xen API + @param vdi_image_path: VDI UUID + @rtype: string + @return: uuid of the device + """ + xenapi_vbd['image'] = vdi_image_path + dev_uuid = self.info.phantom_device_add('tap', cfg_xenapi = xenapi_vbd) + if not dev_uuid: + raise XendError('Failed to create device') + + if self.state == XEN_API_VM_POWER_STATE_RUNNING: + _, config = self.info['devices'][dev_uuid] + config['devid'] = self.getDeviceController('tap').createDevice(config) + + return config['devid'] + def create_vif(self, xenapi_vif): """Create VIF device from the passed struct in Xen API format. diff --git a/tools/python/xen/xend/server/BlktapController.py b/tools/python/xen/xend/server/BlktapController.py index 062769a061..420a4bdbe6 100644 --- a/tools/python/xen/xend/server/BlktapController.py +++ b/tools/python/xen/xend/server/BlktapController.py @@ -2,7 +2,10 @@ from xen.xend.server.blkif import BlkifController +from xen.xend.XendLogging import log +phantomDev = 0; +phantomId = 0; class BlktapController(BlkifController): def __init__(self, vm): @@ -12,3 +15,62 @@ class BlktapController(BlkifController): """@see DevController#frontendRoot""" return "%s/device/vbd" % self.vm.getDomainPath() + + def getDeviceDetails(self, config): + (devid, back, front) = BlkifController.getDeviceDetails(self, config) + + phantomDevid = 0 + wrapped = False + + try: + imagetype = self.vm.info['image']['type'] + except: + imagetype = "" + + if imagetype == 'hvm': + tdevname = back['dev'] + index = ['c', 'd', 'e', 'f', 'g', 'h', 'i', \ + 'j', 'l', 'm', 'n', 'o', 'p'] + while True: + global phantomDev + global phantomId + import os, stat + + phantomId = phantomId + 1 + if phantomId == 16: + if index[phantomDev] == index[-1]: + if wrapped: + raise VmError(" No loopback block \ + devices are available. ") + wrapped = True + phantomDev = 0 + else: + phantomDev = phantomDev + 1 + phantomId = 1 + devname = 'xvd%s%d' % (index[phantomDev], phantomId) + try: + info = os.stat('/dev/%s' % devname) + except: + break + + vbd = { 'mode': 'w', 'device': devname } + fn = 'tap:%s' % back['params'] + + # recurse ... by creating the vbd, then fallthrough + # and finish creating the original device + + from xen.xend import XendDomain + dom0 = XendDomain.instance().privilegedDomain() + phantomDevid = dom0.create_phantom_vbd_with_vdi(vbd, fn) + # we need to wait for this device at a higher level + # the vbd that gets created will have a link to us + # and will let them do it there + + # add a hook to point to the phantom device, + # root path is always the same (dom0 tap) + if phantomDevid != 0: + front['phantom_vbd'] = '/local/domain/0/backend/tap/0/%s' \ + % str(phantomDevid) + + return (devid, back, front) + diff --git a/tools/python/xen/xend/server/DevController.py b/tools/python/xen/xend/server/DevController.py index 47f03e1994..0016ff89a3 100644 --- a/tools/python/xen/xend/server/DevController.py +++ b/tools/python/xen/xend/server/DevController.py @@ -473,6 +473,19 @@ class DevController: def waitForBackend(self, devid): frontpath = self.frontendPath(devid) + # lookup a phantom + phantomPath = xstransact.Read(frontpath, 'phantom_vbd') + if phantomPath is not None: + log.debug("Waiting for %s's phantom %s.", devid, phantomPath) + statusPath = phantomPath + '/' + HOTPLUG_STATUS_NODE + ev = Event() + result = { 'status': Timeout } + xswatch(statusPath, hotplugStatusCallback, ev, result) + ev.wait(DEVICE_CREATE_TIMEOUT) + err = xstransact.Read(statusPath, HOTPLUG_ERROR_NODE) + if result['status'] != 'Connected': + return (result['status'], err) + backpath = xstransact.Read(frontpath, "backend") From 49d6f8401bf93c7a5ac411db31d7a84a77df66b4 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 10:44:53 +0000 Subject: [PATCH 63/95] [XEN] When removing pages, drop shadow refs before complaining about refcount. Signed-off-by: Tim Deegan --- xen/common/memory.c | 10 ++++++---- xen/include/asm-x86/shadow.h | 5 +++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/xen/common/memory.c b/xen/common/memory.c index 78887e19a6..fcd483818d 100644 --- a/xen/common/memory.c +++ b/xen/common/memory.c @@ -175,11 +175,13 @@ int guest_remove_page(struct domain *d, unsigned long gmfn) if ( unlikely(!page_is_removable(page)) ) { + shadow_drop_references(d, page); /* We'll make this a guest-visible error in future, so take heed! */ - gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx (pseudophys %lx):" - " count=%lx type=%lx\n", - d->domain_id, mfn, get_gpfn_from_mfn(mfn), - (unsigned long)page->count_info, page->u.inuse.type_info); + if ( !page_is_removable(page) ) + gdprintk(XENLOG_INFO, "Dom%d freeing in-use page %lx " + "(pseudophys %lx): count=%lx type=%lx\n", + d->domain_id, mfn, get_gpfn_from_mfn(mfn), + (unsigned long)page->count_info, page->u.inuse.type_info); } guest_physmap_remove_page(d, gmfn, mfn); diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index 2afc0b0562..a4a489dcf5 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -355,8 +355,9 @@ int sh_remove_all_mappings(struct vcpu *v, mfn_t target_mfn); static inline void shadow_drop_references(struct domain *d, struct page_info *p) { - /* See the comment about locking in sh_remove_all_mappings */ - sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); + if ( unlikely(shadow_mode_enabled(d)) ) + /* See the comment about locking in sh_remove_all_mappings */ + sh_remove_all_mappings(d->vcpu[0], _mfn(page_to_mfn(p))); } /* Remove all shadows of the guest mfn. */ From 9c47bd3d1e8e66c787f3dbf1f475dd536ab5d184 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 11:03:29 +0000 Subject: [PATCH 64/95] [XEN] kexec: Remove asm/kexec.h. Move the single inline function into arch specific machine_kexec.c with the other arch specific kexec functions. IA64 already had a stub in both kexec.h and machine_kexec.c. Signed-off-by: Ian Campbell --- xen/arch/powerpc/machine_kexec.c | 5 ++++ xen/arch/x86/crash.c | 1 - xen/arch/x86/machine_kexec.c | 15 +++++++++++- xen/common/kexec.c | 1 - xen/include/asm-ia64/kexec.h | 25 ------------------- xen/include/asm-powerpc/kexec.h | 25 ------------------- xen/include/asm-x86/kexec.h | 20 --------------- xen/include/asm-x86/x86_32/kexec.h | 39 ------------------------------ xen/include/asm-x86/x86_64/kexec.h | 38 ----------------------------- xen/include/xen/kexec.h | 1 + 10 files changed, 20 insertions(+), 150 deletions(-) delete mode 100644 xen/include/asm-ia64/kexec.h delete mode 100644 xen/include/asm-powerpc/kexec.h delete mode 100644 xen/include/asm-x86/kexec.h delete mode 100644 xen/include/asm-x86/x86_32/kexec.h delete mode 100644 xen/include/asm-x86/x86_64/kexec.h diff --git a/xen/arch/powerpc/machine_kexec.c b/xen/arch/powerpc/machine_kexec.c index 2debd26a7e..51ddd75890 100644 --- a/xen/arch/powerpc/machine_kexec.c +++ b/xen/arch/powerpc/machine_kexec.c @@ -19,6 +19,11 @@ void machine_reboot_kexec(xen_kexec_image_t *image) printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); } +void machine_kexec(xen_kexec_image_t *image) +{ + printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); +} + /* * Local variables: * mode: C diff --git a/xen/arch/x86/crash.c b/xen/arch/x86/crash.c index 73eb4724a8..cae1768633 100644 --- a/xen/arch/x86/crash.c +++ b/xen/arch/x86/crash.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 81c392a7d3..54fa466793 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -15,11 +15,15 @@ #include #include #include -#include #include #include #include +typedef void (*relocate_new_kernel_t)( + unsigned long indirection_page, + unsigned long page_list, + unsigned long start_address); + int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) { unsigned long prev_ma = 0; @@ -94,6 +98,15 @@ void machine_reboot_kexec(xen_kexec_image_t *image) BUG(); } +void machine_kexec(xen_kexec_image_t *image) +{ + relocate_new_kernel_t rnk; + + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, (unsigned long)image->page_list, + image->start_address); +} + /* * Local variables: * mode: C diff --git a/xen/common/kexec.c b/xen/common/kexec.c index a9e85cad7f..80314a6673 100644 --- a/xen/common/kexec.c +++ b/xen/common/kexec.c @@ -6,7 +6,6 @@ * - Magnus Damm */ -#include #include #include #include diff --git a/xen/include/asm-ia64/kexec.h b/xen/include/asm-ia64/kexec.h deleted file mode 100644 index 45756e8f64..0000000000 --- a/xen/include/asm-ia64/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef __IA64_KEXEC_H__ -#define __IA64_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* __IA64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-powerpc/kexec.h b/xen/include/asm-powerpc/kexec.h deleted file mode 100644 index f228972047..0000000000 --- a/xen/include/asm-powerpc/kexec.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _ASM_KEXEC_H__ -#define _ASM_KEXEC_H__ - -#include /* for printk() used in stub */ -#include -#include -#include - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - printk("STUB: " __FILE__ ": %s: not implemented\n", __FUNCTION__); -} - -#endif /* _ASM_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ - diff --git a/xen/include/asm-x86/kexec.h b/xen/include/asm-x86/kexec.h deleted file mode 100644 index d137337da0..0000000000 --- a/xen/include/asm-x86/kexec.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef __X86_KEXEC_H__ -#define __X86_KEXEC_H__ - -#ifdef __x86_64__ -#include -#else -#include -#endif - -#endif /* __X86_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/x86_32/kexec.h b/xen/include/asm-x86/x86_32/kexec.h deleted file mode 100644 index cb4ada715e..0000000000 --- a/xen/include/asm-x86/x86_32/kexec.h +++ /dev/null @@ -1,39 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_KEXEC_X86_32_H__ -#define __X86_KEXEC_X86_32_H__ - -#include -#include - -typedef asmlinkage void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address, - unsigned int has_pae); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address, (unsigned long)cpu_has_pae); -} - -#endif /* __X86_KEXEC_X86_32_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/asm-x86/x86_64/kexec.h b/xen/include/asm-x86/x86_64/kexec.h deleted file mode 100644 index c54dbb9ba6..0000000000 --- a/xen/include/asm-x86/x86_64/kexec.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * kexec.h - * - * Based heavily on machine_kexec.c and kexec.h from Linux 2.6.19-rc1 - * - */ - -#ifndef __X86_64_KEXEC_H__ -#define __X86_64_KEXEC_H__ - -#include -#include - -typedef void (*relocate_new_kernel_t)( - unsigned long indirection_page, - unsigned long page_list, - unsigned long start_address); - -static inline void machine_kexec(xen_kexec_image_t *image) -{ - relocate_new_kernel_t rnk; - - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); -} - -#endif /* __X86_64_KEXEC_H__ */ - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ diff --git a/xen/include/xen/kexec.h b/xen/include/xen/kexec.h index be09c0a1ab..523846af06 100644 --- a/xen/include/xen/kexec.h +++ b/xen/include/xen/kexec.h @@ -25,6 +25,7 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image); void machine_kexec_unload(int type, int slot, xen_kexec_image_t *image); void machine_kexec_reserved(xen_kexec_reserve_t *reservation); void machine_reboot_kexec(xen_kexec_image_t *image); +void machine_kexec(xen_kexec_image_t *image); void kexec_crash(void); void kexec_crash_save_cpu(void); crash_xen_info_t *kexec_crash_save_info(void); From cc1b02ddd4b54154944d31a82f56b84cd616362e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 11:03:32 +0000 Subject: [PATCH 65/95] [XEN] kexec: add compatability shim for kexec in 32on64 mode. Signed-off-by: Ian Campbell --- xen/arch/x86/machine_kexec.c | 48 +++++++++-- xen/arch/x86/x86_64/Makefile | 1 + xen/arch/x86/x86_64/compat_kexec.S | 126 +++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 7 deletions(-) create mode 100644 xen/arch/x86/x86_64/compat_kexec.S diff --git a/xen/arch/x86/machine_kexec.c b/xen/arch/x86/machine_kexec.c index 54fa466793..5e82975366 100644 --- a/xen/arch/x86/machine_kexec.c +++ b/xen/arch/x86/machine_kexec.c @@ -21,7 +21,7 @@ typedef void (*relocate_new_kernel_t)( unsigned long indirection_page, - unsigned long page_list, + unsigned long *page_list, unsigned long start_address); int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) @@ -44,8 +44,26 @@ int machine_kexec_load(int type, int slot, xen_kexec_image_t *image) else { /* Odd pages: va for previous ma. */ - set_fixmap(fix_base + (k >> 1), prev_ma); - image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + if ( IS_COMPAT(dom0) ) + { + + /* + * The compatability bounce code sets up a page table + * with a 1-1 mapping of the first 1G of memory so + * VA==PA here. + * + * This Linux purgatory code still sets up separate + * high and low mappings on the control page (entries + * 0 and 1) but it is harmless if they are equal since + * that PT is not live at the time. + */ + image->page_list[k] = prev_ma; + } + else + { + set_fixmap(fix_base + (k >> 1), prev_ma); + image->page_list[k] = fix_to_virt(fix_base + (k >> 1)); + } } } @@ -100,11 +118,27 @@ void machine_reboot_kexec(xen_kexec_image_t *image) void machine_kexec(xen_kexec_image_t *image) { - relocate_new_kernel_t rnk; +#ifdef CONFIG_COMPAT + if ( IS_COMPAT(dom0) ) + { + extern void compat_machine_kexec(unsigned long rnk, + unsigned long indirection_page, + unsigned long *page_list, + unsigned long start_address); + compat_machine_kexec(image->page_list[1], + image->indirection_page, + image->page_list, + image->start_address); + } + else +#endif + { + relocate_new_kernel_t rnk; - rnk = (relocate_new_kernel_t) image->page_list[1]; - (*rnk)(image->indirection_page, (unsigned long)image->page_list, - image->start_address); + rnk = (relocate_new_kernel_t) image->page_list[1]; + (*rnk)(image->indirection_page, image->page_list, + image->start_address); + } } /* diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index df5632e0a0..372cce5892 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -1,4 +1,5 @@ obj-y += entry.o +obj-y += compat_kexec.o obj-y += gpr_switch.o obj-y += mm.o obj-y += traps.o diff --git a/xen/arch/x86/x86_64/compat_kexec.S b/xen/arch/x86/x86_64/compat_kexec.S new file mode 100644 index 0000000000..c06db6fc7e --- /dev/null +++ b/xen/arch/x86/x86_64/compat_kexec.S @@ -0,0 +1,126 @@ +/* + * Compatibility kexec handler. + */ + +#include + +#include +#include +#include + +.text + + .code64 + +ENTRY(compat_machine_kexec) + /* x86/64 x86/32 */ + /* %rdi - relocate_new_kernel_t CALL */ + /* %rsi - indirection page 4(%esp) */ + /* %rdx - page_list 8(%esp) */ + /* %rcx - start address 12(%esp) */ + /* cpu has pae 16(%esp) */ + + /* Shim the 64 bit page_list into a 32 bit page_list. */ + mov $12,%r9 + lea compat_page_list(%rip), %rbx +1: dec %r9 + movl (%rdx,%r9,8),%eax + movl %eax,(%rbx,%r9,4) + test %r9,%r9 + jnz 1b + + movq %rbx,%rdx + mov $__PAGE_OFFSET,%rbx + sub %rbx, %rdx + + /* + * Setup an identity mapped region in PML4[0] of idle page + * table. + */ + lea idle_pg_table_l3(%rip),%rax + sub %rbx,%rax + or $0x63,%rax + mov %rax, idle_pg_table(%rip) + + /* Switch to idle page table. */ + movq $(idle_pg_table - __PAGE_OFFSET), %rax + movq %rax, %cr3 + + /* Jump to low identity mapping in compatibility mode. */ + ljmp *compatibility_mode_far(%rip) + ud2 + +compatibility_mode_far: + .long compatibility_mode - __PAGE_OFFSET + .long __HYPERVISOR_CS32 + + .code32 + +compatibility_mode: + /* Setup some sane segments. */ + movl $__HYPERVISOR_DS32, %eax + movl %eax, %ds + movl %eax, %es + movl %eax, %fs + movl %eax, %gs + movl %eax, %ss + + /* Push arguments onto stack. */ + pushl $1 /* 16(%esp) - cpu has pae */ + pushl %ecx /* 12(%esp) - start address */ + pushl %edx /* 8(%esp) - page list */ + pushl %esi /* 4(%esp) - indirection page */ + pushl %edi /* 0(%esp) - CALL */ + + /* Disable paging and therefore leave 64 bit mode. */ + movl %cr0, %eax + andl $~X86_CR0_PG, %eax + movl %eax, %cr0 + + /* Switch to 32 bit page table. */ + movl $compat_pg_table - __PAGE_OFFSET, %eax + movl %eax, %cr3 + + /* Clear MSR_EFER[LME], disabling long mode */ + movl $MSR_EFER,%ecx + rdmsr + btcl $_EFER_LME,%eax + wrmsr + + /* Re-enable paging, but only 32 bit mode now. */ + movl %cr0, %eax + orl $X86_CR0_PG, %eax + movl %eax, %cr0 + + popl %eax + call *%eax + ud2 + +compat_page_list: + .fill 12,4,0 + + .align 32,0 + + /* + * These compat page tables contain an identity mapping of the + * first 1G of the physical address space. + */ +compat_pg_table: + .long compat_pg_table_l2 + 0*PAGE_SIZE + 0x01 - __PAGE_OFFSET, 0 + .long 0, 0 + .long 0, 0 + .long 0, 0 + + .align 4096,0 + +compat_pg_table_l2: + .macro identmap from=0, count=512 + .if \count-1 + identmap "(\from+0)","(\count/2)" + identmap "(\from+(0x200000*(\count/2)))","(\count/2)" + .else + .quad 0x00000000000000e3 + \from + .endif + .endm + + identmap From 8bc62853df8dd3507ba7d5d839654afd1e164e53 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Thu, 8 Feb 2007 12:33:32 +0000 Subject: [PATCH 66/95] [XEN] Fix typos in comment describing 32on64 memory layout Signed-off-by: Ian Campbell --- xen/include/asm-x86/config.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/include/asm-x86/config.h b/xen/include/asm-x86/config.h index 71e3dd8e4a..34cd754186 100644 --- a/xen/include/asm-x86/config.h +++ b/xen/include/asm-x86/config.h @@ -145,9 +145,9 @@ * Compatibility guest area layout: * 0x0000000000000000 - 0x00000000f57fffff [3928MB, PML4:0] * Guest-defined use. - * 0x0000000f58000000 - 0x00000000ffffffff [168MB, PML4:0] + * 0x00000000f5800000 - 0x00000000ffffffff [168MB, PML4:0] * Read-only machine-to-phys translation table (GUEST ACCESSIBLE). - * 0x0000000000000000 - 0x00000000ffffffff [508GB, PML4:0] + * 0x0000000100000000 - 0x0000007fffffffff [508GB, PML4:0] * Unused. * 0x0000008000000000 - 0x000000ffffffffff [512GB, 2^39 bytes, PML4:1] * Hypercall argument translation area. From 8abe0e51d15e6038599fa0d631e78ab41d5aef1b Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 13:42:49 +0000 Subject: [PATCH 67/95] [HVM] Save/restore: save pmtimer count register Also remove the repeating timer from pmtimer.c because it doesn't do anything. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/hvm.c | 2 - xen/arch/x86/hvm/pmtimer.c | 75 ++++++++++++++++++++--------------- xen/include/asm-x86/hvm/vpt.h | 14 +++---- xen/include/public/hvm/save.h | 12 +++++- 4 files changed, 58 insertions(+), 45 deletions(-) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 96c827d235..9147737846 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -106,7 +106,6 @@ void hvm_migrate_timers(struct vcpu *v) pit_migrate_timers(v); rtc_migrate_timers(v); hpet_migrate_timers(v); - pmtimer_migrate_timers(v); if ( vcpu_vlapic(v)->pt.enabled ) migrate_timer(&vcpu_vlapic(v)->pt.timer, v->processor); } @@ -170,7 +169,6 @@ void hvm_domain_destroy(struct domain *d) { pit_deinit(d); rtc_deinit(d); - pmtimer_deinit(d); hpet_deinit(d); if ( d->arch.hvm_domain.shared_page_va ) diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 28be242f84..a396d27df4 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -2,17 +2,6 @@ #include #include -#define TMR_STS (1 << 0) -static void pmt_update_status(void *opaque) -{ - PMTState *s = opaque; - s->pm1_status |= TMR_STS; - - /* TODO: When TMR_EN == 1, generate a SCI event */ - - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); -} - static int handle_pmt_io(ioreq_t *p) { struct vcpu *v = current; @@ -30,42 +19,62 @@ static int handle_pmt_io(ioreq_t *p) /* PM_TMR_BLK is read-only */ return 1; } else if (p->dir == 1) { /* read */ + /* Set the correct value in the timer, accounting for time + * elapsed since the last time we did that. */ curr_gtime = hvm_get_guest_time(s->vcpu); - s->pm1_timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; - p->data = s->pm1_timer; + s->pm.timer += ((curr_gtime - s->last_gtime) * s->scale) >> 32; + p->data = s->pm.timer; s->last_gtime = curr_gtime; return 1; } return 0; } +static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + uint32_t x; + + /* Update the counter to the guest's current time. We always save + * with the domain paused, so the saved time should be after the + * last_gtime, but just in case, make sure we only go forwards */ + x = ((s->vcpu->arch.hvm_vcpu.guest_time - s->last_gtime) * s->scale) >> 32; + if ( x < 1UL<<31 ) + s->pm.timer += x; + return hvm_save_entry(PMTIMER, 0, h, &s->pm); +} + +static int pmtimer_load(struct domain *d, hvm_domain_context_t *h) +{ + PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; + + /* Reload the counter */ + if ( hvm_load_entry(PMTIMER, h, &s->pm) ) + return -EINVAL; + + /* Calculate future counter values from now. */ + s->last_gtime = hvm_get_guest_time(s->vcpu); + + return 0; +} + +HVM_REGISTER_SAVE_RESTORE(PMTIMER, pmtimer_save, pmtimer_load, + 1, HVMSR_PER_DOM); + + void pmtimer_init(struct vcpu *v, int base) { PMTState *s = &v->domain->arch.hvm_domain.pl_time.vpmt; - s->pm1_timer = 0; - s->pm1_status = 0; + s->pm.timer = 0; s->scale = ((uint64_t)FREQUENCE_PMTIMER << 32) / ticks_per_sec(v); s->vcpu = v; - init_timer(&s->timer, pmt_update_status, s, v->processor); - /* ACPI supports a 32-bit power management timer */ - set_timer(&s->timer, NOW() + (1000000000ULL << 31) / FREQUENCE_PMTIMER); - + /* Not implemented: we should set TMR_STS (bit 0 of PM1a_STS) every + * time the timer's top bit flips, and generate an SCI if TMR_EN + * (bit 0 of PM1a_EN) is set. For now, those registers are in + * qemu-dm, and we just calculate the timer's value on demand. */ + register_portio_handler(v->domain, base, 4, handle_pmt_io); } -void pmtimer_migrate_timers(struct vcpu *v) -{ - struct PMTState *vpmt = &v->domain->arch.hvm_domain.pl_time.vpmt; - - if (vpmt->vcpu == v) - migrate_timer(&vpmt->timer, v->processor); -} - -void pmtimer_deinit(struct domain *d) -{ - PMTState *s = &d->arch.hvm_domain.pl_time.vpmt; - - kill_timer(&s->timer); -} diff --git a/xen/include/asm-x86/hvm/vpt.h b/xen/include/asm-x86/hvm/vpt.h index 78c7b536d4..02bc3fa05c 100644 --- a/xen/include/asm-x86/hvm/vpt.h +++ b/xen/include/asm-x86/hvm/vpt.h @@ -94,14 +94,12 @@ typedef struct RTCState { struct periodic_time pt; } RTCState; -#define FREQUENCE_PMTIMER 3579545 +#define FREQUENCE_PMTIMER 3579545 /* Timer should run at 3.579545 MHz */ typedef struct PMTState { - uint32_t pm1_timer; - uint32_t pm1_status; - uint64_t last_gtime; - struct timer timer; - uint64_t scale; - struct vcpu *vcpu; + struct hvm_hw_pmtimer pm; /* 32bit timer value */ + struct vcpu *vcpu; /* Keeps sync with this vcpu's guest-time */ + uint64_t last_gtime; /* Last (guest) time we updated the timer */ + uint64_t scale; /* Multiplier to get from tsc to timer ticks */ } PMTState; struct pl_time { /* platform time */ @@ -134,8 +132,6 @@ void rtc_migrate_timers(struct vcpu *v); void rtc_deinit(struct domain *d); int is_rtc_periodic_irq(void *opaque); void pmtimer_init(struct vcpu *v, int base); -void pmtimer_migrate_timers(struct vcpu *v); -void pmtimer_deinit(struct domain *d); void hpet_migrate_timers(struct vcpu *v); void hpet_init(struct vcpu *v); diff --git a/xen/include/public/hvm/save.h b/xen/include/public/hvm/save.h index 7ed26495c8..c6a856a558 100644 --- a/xen/include/public/hvm/save.h +++ b/xen/include/public/hvm/save.h @@ -382,10 +382,20 @@ struct hvm_hw_hpet { DECLARE_HVM_SAVE_TYPE(HPET, 12, struct hvm_hw_hpet); +/* + * PM timer + */ + +struct hvm_hw_pmtimer { + uint32_t timer; +}; + +DECLARE_HVM_SAVE_TYPE(PMTIMER, 13, struct hvm_hw_pmtimer); + /* * Largest type-code in use */ -#define HVM_SAVE_CODE_MAX 12 +#define HVM_SAVE_CODE_MAX 13 /* From de602931ef7752d469b206b21ffad7f38810cda6 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 8 Feb 2007 15:00:33 +0000 Subject: [PATCH 68/95] [HVM] Save/restore: don't try to set the console ring MFN in a HVM restore. In particular, don't print an uninitialized stack variable, which causes XMLRPC exceptions in xend. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_restore.c | 5 ++--- tools/libxc/xenguest.h | 3 +-- tools/libxc/xg_private.c | 3 +-- tools/python/xen/xend/XendCheckpoint.py | 7 +++++-- tools/xcutils/xc_restore.c | 5 +++-- 5 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 6622b49f79..4cf27fdb8b 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -69,7 +69,6 @@ read_exact(int fd, void *buf, size_t count) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, unsigned long *store_mfn, - unsigned int console_evtchn, unsigned long *console_mfn, unsigned int pae, unsigned int apic) { DECLARE_DOMCTL; @@ -104,8 +103,8 @@ int xc_hvm_restore(int xc_handle, int io_fd, memsize = (unsigned long long)*store_mfn; v_end = memsize << 20; - DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, console_evtchn=%d, *console_mfn=%ld, pae=%u, apic=%u.\n", - dom, nr_pfns, store_evtchn, *store_mfn, console_evtchn, *console_mfn, pae, apic); + DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", + dom, nr_pfns, store_evtchn, *store_mfn, pae, apic); max_pfn = nr_pfns; diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 7b5a2af0a4..3800b0cb13 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -58,8 +58,7 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, */ int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic); /** diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index f45c2ebb0d..6f4f28f988 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -210,8 +210,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, __attribute__((weak)) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, unsigned long nr_pfns, unsigned int store_evtchn, - unsigned long *store_mfn, unsigned int console_evtchn, - unsigned long *console_mfn, + unsigned long *store_mfn, unsigned int pae, unsigned int apic) { errno = ENOSYS; diff --git a/tools/python/xen/xend/XendCheckpoint.py b/tools/python/xen/xend/XendCheckpoint.py index 6eda8edf76..63368bd654 100644 --- a/tools/python/xen/xend/XendCheckpoint.py +++ b/tools/python/xen/xend/XendCheckpoint.py @@ -239,8 +239,11 @@ def restore(xd, fd, dominfo = None, paused = False): forkHelper(cmd, fd, handler.handler, True) - if handler.store_mfn is None or handler.console_mfn is None: - raise XendError('Could not read store/console MFN') + if handler.store_mfn is None: + raise XendError('Could not read store MFN') + + if not is_hvm and handler.console_mfn is None: + raise XendError('Could not read console MFN') dominfo.waitForDevices() # Wait for backends to set up if not paused: diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 8e26d9bb70..6629e33082 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -45,14 +45,15 @@ main(int argc, char **argv) /* pass the memsize to xc_hvm_restore to find the store_mfn */ store_mfn = hvm; ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, - &store_mfn, console_evtchn, &console_mfn, pae, apic); + &store_mfn, pae, apic); } else ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, &store_mfn, console_evtchn, &console_mfn); if (ret == 0) { printf("store-mfn %li\n", store_mfn); - printf("console-mfn %li\n", console_mfn); + if (!hvm) + printf("console-mfn %li\n", console_mfn); fflush(stdout); } From 1f226801508c962af561b9192381bf7f68cb7ee1 Mon Sep 17 00:00:00 2001 From: Ewan Mellor Date: Thu, 8 Feb 2007 16:52:05 +0000 Subject: [PATCH 69/95] Fix localtime setting for PV domains. Signed-off-by: Atsushi SAKAI --- tools/python/xen/xend/XendDomainInfo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index 160ee25a90..6c4a9afcb4 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1416,7 +1416,7 @@ class XendDomainInfo: self.info['image'], self.info['devices']) - localtime = self.info.get('localtime', False) + localtime = self.info.get('platform_localtime', False) if localtime: xc.domain_set_time_offset(self.domid) From d4a9cc151365ad63cb2100e5b768319bf498312a Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:04:26 +0000 Subject: [PATCH 70/95] Add example xen-detect.c code for detecting application execution in Xen PV or HVM contexts, using the Xen CPUID extensions. Signed-off-by: Keir Fraser --- .hgignore | 1 + tools/misc/Makefile | 2 +- tools/misc/xen-detect.c | 107 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 tools/misc/xen-detect.c diff --git a/.hgignore b/.hgignore index 85ddd9d976..4a3636cab5 100644 --- a/.hgignore +++ b/.hgignore @@ -138,6 +138,7 @@ ^tools/misc/miniterm/miniterm$ ^tools/misc/xc_shadow$ ^tools/misc/xen_cpuperf$ +^tools/misc/xen-detect$ ^tools/misc/xenperf$ ^tools/pygrub/build/.*$ ^tools/python/build/.*$ diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 80b52c0063..494ebc95ec 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,7 @@ CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -TARGETS = xenperf xc_shadow +TARGETS = xenperf xc_shadow xen-detect INSTALL_BIN = $(TARGETS) xencons INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf diff --git a/tools/misc/xen-detect.c b/tools/misc/xen-detect.c new file mode 100644 index 0000000000..6ac23f4453 --- /dev/null +++ b/tools/misc/xen-detect.c @@ -0,0 +1,107 @@ +/****************************************************************************** + * xen_detect.c + * + * Simple GNU C / POSIX application to detect execution on Xen VMM platform. + * + * Copyright (c) 2007, XenSource Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include +#include + +static int pv_context; + +static void cpuid(uint32_t idx, + uint32_t *eax, + uint32_t *ebx, + uint32_t *ecx, + uint32_t *edx) +{ + asm volatile ( + "test %1,%1 ; jz 1f ; ud2a ; .ascii \"xen\" ; 1: cpuid" + : "=a" (*eax), "=b" (*ebx), "=c" (*ecx), "=d" (*edx) + : "0" (idx), "1" (pv_context) ); +} + +static int check_for_xen(void) +{ + uint32_t eax, ebx, ecx, edx; + char signature[13]; + + cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + *(uint32_t *)(signature + 0) = ebx; + *(uint32_t *)(signature + 4) = ecx; + *(uint32_t *)(signature + 8) = edx; + signature[12] = '\0'; + + if ( strcmp("XenVMMXenVMM", signature) || (eax < 0x40000002) ) + return 0; + + cpuid(0x40000001, &eax, &ebx, &ecx, &edx); + printf("Running in %s context on Xen v%d.%d.\n", + pv_context ? "PV" : "HVM", (uint16_t)(eax >> 16), (uint16_t)eax); + return 1; +} + +int main(void) +{ + pid_t pid; + int status; + uint32_t dummy; + + /* Check for execution in HVM context. */ + if ( check_for_xen() ) + return 0; + + /* Now we check for execution in PV context. */ + pv_context = 1; + + /* + * Fork a child to test the paravirtualised CPUID instruction. + * If executed outside Xen PV context, the extended opcode will fault. + */ + pid = fork(); + switch ( pid ) + { + case 0: + /* Child: test paravirtualised CPUID opcode and then exit cleanly. */ + cpuid(0x40000000, &dummy, &dummy, &dummy, &dummy); + exit(0); + case -1: + fprintf(stderr, "Fork failed.\n"); + return 0; + } + + /* + * Parent waits for child to terminate and checks for clean exit. + * Only if the exit is clean is it safe for us to try the extended CPUID. + */ + waitpid(pid, &status, 0); + if ( WIFEXITED(status) && check_for_xen() ) + return 0; + + printf("Not running on Xen.\n"); + return 0; +} From c68414307be76e655696398f1ed72466c1e4b869 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 8 Feb 2007 17:07:36 +0000 Subject: [PATCH 71/95] Fix xen-detect build. Signed-off-by: Keir Fraser --- tools/misc/Makefile | 2 +- tools/misc/xen-detect.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 494ebc95ec..dce732f273 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -41,5 +41,5 @@ clean: %.o: %.c $(HDRS) Makefile $(CC) -c $(CFLAGS) -o $@ $< -$(TARGETS): %: %.o Makefile +xenperf xc_shadow: %: %.o Makefile $(CC) $(CFLAGS) -o $@ $< -L$(XEN_LIBXC) -lxenctrl diff --git a/tools/misc/xen-detect.c b/tools/misc/xen-detect.c index 6ac23f4453..c918945f81 100644 --- a/tools/misc/xen-detect.c +++ b/tools/misc/xen-detect.c @@ -26,6 +26,7 @@ #include #include +#include #include #include #include From 9e81ed4de392d2785759a552d74b58aa09c0fb4f Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:15:38 +0000 Subject: [PATCH 72/95] Fix a typo in console_steal(). Signed-off-by: Kevin Tian --- xen/drivers/char/console.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 01eda8a06d..7eea5b2b4e 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -223,7 +223,7 @@ int console_steal(int handle, void (*fn)(const char *)) if ( (handle == -1) || (handle != sercon_handle) ) return 0; - if ( serial_steal_fn == NULL ) + if ( serial_steal_fn != NULL ) return -EBUSY; serial_steal_fn = fn; From ed293612d54a3d1626e9ac53eaf2f495a7fe6a92 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:19:49 +0000 Subject: [PATCH 73/95] Move skb_pull_rcsum() to its usual place in skbuff.c --- linux-2.6-xen-sparse/net/core/skbuff.c | 46 +++++++++++++------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/linux-2.6-xen-sparse/net/core/skbuff.c b/linux-2.6-xen-sparse/net/core/skbuff.c index e7bbe91b8f..c8e7259cc0 100644 --- a/linux-2.6-xen-sparse/net/core/skbuff.c +++ b/linux-2.6-xen-sparse/net/core/skbuff.c @@ -1896,6 +1896,29 @@ int skb_append_datato_frags(struct sock *sk, struct sk_buff *skb, return 0; } +/** + * skb_pull_rcsum - pull skb and update receive checksum + * @skb: buffer to update + * @start: start of data before pull + * @len: length of data pulled + * + * This function performs an skb_pull on the packet and updates + * update the CHECKSUM_HW checksum. It should be used on receive + * path processing instead of skb_pull unless you know that the + * checksum difference is zero (e.g., a valid IP header) or you + * are setting ip_summed to CHECKSUM_NONE. + */ +unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) +{ + BUG_ON(len > skb->len); + skb->len -= len; + BUG_ON(skb->len < skb->data_len); + skb_postpull_rcsum(skb, skb->data, len); + return skb->data += len; +} + +EXPORT_SYMBOL_GPL(skb_pull_rcsum); + /** * skb_segment - Perform protocol segmentation on skb. * @skb: buffer to segment @@ -2022,29 +2045,6 @@ err: EXPORT_SYMBOL_GPL(skb_segment); -/** - * skb_pull_rcsum - pull skb and update receive checksum - * @skb: buffer to update - * @start: start of data before pull - * @len: length of data pulled - * - * This function performs an skb_pull on the packet and updates - * update the CHECKSUM_HW checksum. It should be used on receive - * path processing instead of skb_pull unless you know that the - * checksum difference is zero (e.g., a valid IP header) or you - * are setting ip_summed to CHECKSUM_NONE. - */ -unsigned char *skb_pull_rcsum(struct sk_buff *skb, unsigned int len) -{ - BUG_ON(len > skb->len); - skb->len -= len; - BUG_ON(skb->len < skb->data_len); - skb_postpull_rcsum(skb, skb->data, len); - return skb->data += len; -} - -EXPORT_SYMBOL_GPL(skb_pull_rcsum); - void __init skb_init(void) { skbuff_head_cache = kmem_cache_create("skbuff_head_cache", From a9a8f70bdf30e1b7ae7d50f3b86788fc93329ff9 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:21:04 +0000 Subject: [PATCH 74/95] Remove unnecessarily modified a.out.h. Signed-off-by: Jan Beulich --- linux-2.6-xen-sparse/include/asm-i386/a.out.h | 26 ------------------- 1 file changed, 26 deletions(-) delete mode 100644 linux-2.6-xen-sparse/include/asm-i386/a.out.h diff --git a/linux-2.6-xen-sparse/include/asm-i386/a.out.h b/linux-2.6-xen-sparse/include/asm-i386/a.out.h deleted file mode 100644 index 66db22938f..0000000000 --- a/linux-2.6-xen-sparse/include/asm-i386/a.out.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __I386_A_OUT_H__ -#define __I386_A_OUT_H__ - -struct exec -{ - unsigned long a_info; /* Use macros N_MAGIC, etc for access */ - unsigned a_text; /* length of text, in bytes */ - unsigned a_data; /* length of data, in bytes */ - unsigned a_bss; /* length of uninitialized data area for file, in bytes */ - unsigned a_syms; /* length of symbol table data in file, in bytes */ - unsigned a_entry; /* start address */ - unsigned a_trsize; /* length of relocation info for text, in bytes */ - unsigned a_drsize; /* length of relocation info for data, in bytes */ -}; - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifdef __KERNEL__ - -#define STACK_TOP (TASK_SIZE - 3*PAGE_SIZE) - -#endif - -#endif /* __A_OUT_GNU_H__ */ From 17c65a4118cecd755d5d82f935b08d2789882fd0 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:38:30 +0000 Subject: [PATCH 75/95] Small cleanups to PV-on-HVM support code. Signed-off-by: Keir Fraser --- .../linux-2.6/platform-pci/platform-pci.c | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c index 1cbfcf11b9..bb7120b028 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-pci.c @@ -118,14 +118,10 @@ unsigned long alloc_xen_mmio(unsigned long len) { unsigned long addr; - addr = 0; - if (platform_mmio_alloc + len <= platform_mmiolen) - { - addr = platform_mmio + platform_mmio_alloc; - platform_mmio_alloc += len; - } else { - panic("ran out of xen mmio space"); - } + addr = platform_mmio + platform_mmio_alloc; + platform_mmio_alloc += len; + BUG_ON(platform_mmio_alloc > platform_mmiolen); + return addr; } @@ -182,16 +178,17 @@ static int get_hypercall_stubs(void) static uint64_t get_callback_via(struct pci_dev *pdev) { u8 pin; + int irq; + #ifdef __ia64__ - int irq, rid; for (irq = 0; irq < 16; irq++) { if (isa_irq_to_vector(irq) == pdev->irq) return irq; /* ISA IRQ */ } #else /* !__ia64__ */ - - if (pdev->irq < 16) - return pdev->irq; /* ISA IRQ */ + irq = pdev->irq; + if (irq < 16) + return irq; /* ISA IRQ */ #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,16) From 821a81792e9cf6dbbe79cee253d2f022b63078e7 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 17:46:14 +0000 Subject: [PATCH 76/95] Use printk log-level limiting even during Xen boot. Signed-off-by: Alex Williamson --- xen/drivers/char/console.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index 7eea5b2b4e..cfc7e98a17 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -102,7 +102,7 @@ static void parse_guest_loglvl(char *s); custom_param("loglvl", parse_loglvl); custom_param("guest_loglvl", parse_guest_loglvl); -static atomic_t print_everything = ATOMIC_INIT(1); +static atomic_t print_everything = ATOMIC_INIT(0); #define ___parse_loglvl(s, ps, lvlstr, lvlnum) \ if ( !strncmp((s), (lvlstr), strlen(lvlstr)) ) { \ @@ -569,9 +569,6 @@ void console_endboot(void) /* Serial input is directed to DOM0 by default. */ switch_serial_input(); - - /* Now we implement the logging thresholds. */ - console_end_log_everything(); } void console_start_log_everything(void) From a3ba6d1d9cd6785fdb2e07eeccd45a5117535f67 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 18:01:42 +0000 Subject: [PATCH 77/95] [HVM][SVM] Do not advertise FFXSR feature. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 2 ++ xen/include/asm-x86/cpufeature.h | 1 + 2 files changed, 3 insertions(+) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index 76112e14ef..bad0b12b92 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -1199,6 +1199,8 @@ static void svm_vmexit_do_cpuid(struct vmcb_struct *vmcb, /* So far, we do not support 3DNow for the guest. */ clear_bit(X86_FEATURE_3DNOW & 31, &edx); clear_bit(X86_FEATURE_3DNOWEXT & 31, &edx); + /* no FFXSR instructions feature. */ + clear_bit(X86_FEATURE_FFXSR & 31, &edx); } else if ( input == 0x80000007 || input == 0x8000000A ) { diff --git a/xen/include/asm-x86/cpufeature.h b/xen/include/asm-x86/cpufeature.h index a6f2f757bc..754c6dbf5a 100644 --- a/xen/include/asm-x86/cpufeature.h +++ b/xen/include/asm-x86/cpufeature.h @@ -93,6 +93,7 @@ #define X86_FEATURE_LAHF_LM (6*32+ 0) /* LAHF/SAHF in long mode */ #define X86_FEATURE_CMP_LEGACY (6*32+ 1) /* If yes HyperThreading not valid */ #define X86_FEATURE_SVME (6*32+ 2) /* Secure Virtual Machine */ +#define X86_FEATURE_FFXSR (6*32+25) /* FFXSR instruction optimizations */ #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) #define boot_cpu_has(bit) test_bit(bit, boot_cpu_data.x86_capability) From 68c07a2a243843fb35a0ceab09b293cc263eab08 Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Thu, 8 Feb 2007 18:18:56 +0000 Subject: [PATCH 78/95] x86: hide assembly labels Prevent the fault recovery labels to clutter the symbol table and the disassembly. Signed-off-by: Jan Beulich --- xen/arch/x86/x86_32/entry.S | 107 +++++++++++++++-------------- xen/arch/x86/x86_64/compat/entry.S | 64 ++++++++--------- xen/arch/x86/x86_64/entry.S | 48 ++++++------- 3 files changed, 111 insertions(+), 108 deletions(-) diff --git a/xen/arch/x86/x86_32/entry.S b/xen/arch/x86/x86_32/entry.S index 454e963fe3..286c4b5fb7 100644 --- a/xen/arch/x86/x86_32/entry.S +++ b/xen/arch/x86/x86_32/entry.S @@ -84,10 +84,10 @@ restore_all_guest: jmp restore_all_vm86 1: #endif -FLT1: mov UREGS_ds(%esp),%ds -FLT2: mov UREGS_es(%esp),%es -FLT3: mov UREGS_fs(%esp),%fs -FLT4: mov UREGS_gs(%esp),%gs +.Lft1: mov UREGS_ds(%esp),%ds +.Lft2: mov UREGS_es(%esp),%es +.Lft3: mov UREGS_fs(%esp),%fs +.Lft4: mov UREGS_gs(%esp),%gs restore_all_vm86: popl %ebx popl %ecx @@ -97,9 +97,9 @@ restore_all_vm86: popl %ebp popl %eax addl $4,%esp -FLT5: iret +.Lft5: iret .section .fixup,"ax" -FIX5: subl $28,%esp +.Lfx5: subl $28,%esp pushl 28(%esp) # error_code/entry_vector movl %eax,UREGS_eax+4(%esp) movl %ebp,UREGS_ebp+4(%esp) @@ -108,7 +108,7 @@ FIX5: subl $28,%esp movl %edx,UREGS_edx+4(%esp) movl %ecx,UREGS_ecx+4(%esp) movl %ebx,UREGS_ebx+4(%esp) -FIX1: SET_XEN_SEGMENTS(a) +.Lfx1: SET_XEN_SEGMENTS(a) movl %eax,%fs movl %eax,%gs sti @@ -116,11 +116,11 @@ FIX1: SET_XEN_SEGMENTS(a) pushfl # EFLAGS movl $__HYPERVISOR_CS,%eax pushl %eax # CS - movl $DBLFLT1,%eax + movl $.Ldf1,%eax pushl %eax # EIP pushl %esi # error_code/entry_vector jmp handle_exception -DBLFLT1:GET_CURRENT(%ebx) +.Ldf1: GET_CURRENT(%ebx) jmp test_all_events failsafe_callback: GET_CURRENT(%ebx) @@ -142,14 +142,14 @@ failsafe_callback: jmp test_all_events .previous .section __pre_ex_table,"a" - .long FLT1,FIX1 - .long FLT2,FIX1 - .long FLT3,FIX1 - .long FLT4,FIX1 - .long FLT5,FIX5 + .long .Lft1,.Lfx1 + .long .Lft2,.Lfx1 + .long .Lft3,.Lfx1 + .long .Lft4,.Lfx1 + .long .Lft5,.Lfx5 .previous .section __ex_table,"a" - .long DBLFLT1,failsafe_callback + .long .Ldf1,failsafe_callback .previous ALIGN @@ -288,32 +288,33 @@ create_bounce_frame: testl $(2|X86_EFLAGS_VM),%ecx jz ring1 /* jump if returning to an existing ring-1 activation */ movl VCPU_kernel_sp(%ebx),%esi -FLT6: mov VCPU_kernel_ss(%ebx),%gs +.Lft6: mov VCPU_kernel_ss(%ebx),%gs testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_1 + jz .Lnvm86_1 subl $16,%esi /* push ES/DS/FS/GS (VM86 stack frame) */ movl UREGS_es+4(%esp),%eax -FLT7: movl %eax,%gs:(%esi) +.Lft7: movl %eax,%gs:(%esi) movl UREGS_ds+4(%esp),%eax -FLT8: movl %eax,%gs:4(%esi) +.Lft8: movl %eax,%gs:4(%esi) movl UREGS_fs+4(%esp),%eax -FLT9: movl %eax,%gs:8(%esi) +.Lft9: movl %eax,%gs:8(%esi) movl UREGS_gs+4(%esp),%eax -FLT10: movl %eax,%gs:12(%esi) -nvm86_1:subl $8,%esi /* push SS/ESP (inter-priv iret) */ +.Lft10: movl %eax,%gs:12(%esi) +.Lnvm86_1: + subl $8,%esi /* push SS/ESP (inter-priv iret) */ movl UREGS_esp+4(%esp),%eax -FLT11: movl %eax,%gs:(%esi) +.Lft11: movl %eax,%gs:(%esi) movl UREGS_ss+4(%esp),%eax -FLT12: movl %eax,%gs:4(%esi) +.Lft12: movl %eax,%gs:4(%esi) jmp 1f ring1: /* obtain ss/esp from oldss/oldesp -- a ring-1 activation exists */ movl UREGS_esp+4(%esp),%esi -FLT13: mov UREGS_ss+4(%esp),%gs +.Lft13: mov UREGS_ss+4(%esp),%gs 1: /* Construct a stack frame: EFLAGS, CS/EIP */ movb TRAPBOUNCE_flags(%edx),%cl subl $12,%esi movl UREGS_eip+4(%esp),%eax -FLT14: movl %eax,%gs:(%esi) +.Lft14: movl %eax,%gs:(%esi) movl VCPU_vcpu_info(%ebx),%eax pushl VCPUINFO_upcall_mask(%eax) testb $TBF_INTERRUPT,%cl @@ -324,49 +325,51 @@ FLT14: movl %eax,%gs:(%esi) movw UREGS_cs+4(%esp),%ax # Bits 0-15: CS #ifdef CONFIG_X86_SUPERVISOR_MODE_KERNEL testw $2,%ax - jnz FLT15 + jnz .Lft15 and $~3,%ax # RPL 1 -> RPL 0 #endif -FLT15: movl %eax,%gs:4(%esi) +.Lft15: movl %eax,%gs:4(%esi) test $0x00FF0000,%eax # Bits 16-23: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask movl UREGS_eflags+4(%esp),%eax andl $~X86_EFLAGS_IF,%eax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -FLT16: movl %eax,%gs:8(%esi) +.Lft16: movl %eax,%gs:8(%esi) test $TBF_EXCEPTION_ERRCODE,%cl jz 1f subl $4,%esi # push error_code onto guest frame movl TRAPBOUNCE_error_code(%edx),%eax -FLT17: movl %eax,%gs:(%esi) +.Lft17: movl %eax,%gs:(%esi) 1: testb $TBF_FAILSAFE,%cl jz 2f subl $16,%esi # add DS/ES/FS/GS to failsafe stack frame testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_2 + jz .Lnvm86_2 xorl %eax,%eax # VM86: we write zero selector values -FLT18: movl %eax,%gs:(%esi) -FLT19: movl %eax,%gs:4(%esi) -FLT20: movl %eax,%gs:8(%esi) -FLT21: movl %eax,%gs:12(%esi) +.Lft18: movl %eax,%gs:(%esi) +.Lft19: movl %eax,%gs:4(%esi) +.Lft20: movl %eax,%gs:8(%esi) +.Lft21: movl %eax,%gs:12(%esi) jmp 2f -nvm86_2:movl UREGS_ds+4(%esp),%eax # non-VM86: write real selector values -FLT22: movl %eax,%gs:(%esi) +.Lnvm86_2: + movl UREGS_ds+4(%esp),%eax # non-VM86: write real selector values +.Lft22: movl %eax,%gs:(%esi) movl UREGS_es+4(%esp),%eax -FLT23: movl %eax,%gs:4(%esi) +.Lft23: movl %eax,%gs:4(%esi) movl UREGS_fs+4(%esp),%eax -FLT24: movl %eax,%gs:8(%esi) +.Lft24: movl %eax,%gs:8(%esi) movl UREGS_gs+4(%esp),%eax -FLT25: movl %eax,%gs:12(%esi) +.Lft25: movl %eax,%gs:12(%esi) 2: testl $X86_EFLAGS_VM,UREGS_eflags+4(%esp) - jz nvm86_3 + jz .Lnvm86_3 xorl %eax,%eax /* zero DS-GS, just as a real CPU would */ movl %eax,UREGS_ds+4(%esp) movl %eax,UREGS_es+4(%esp) movl %eax,UREGS_fs+4(%esp) movl %eax,UREGS_gs+4(%esp) -nvm86_3:/* Rewrite our stack frame and return to ring 1. */ +.Lnvm86_3: + /* Rewrite our stack frame and return to ring 1. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ andl $~(X86_EFLAGS_VM|X86_EFLAGS_RF|\ X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+4(%esp) @@ -382,16 +385,16 @@ nvm86_3:/* Rewrite our stack frame and return to ring 1. */ movb $0,TRAPBOUNCE_flags(%edx) ret .section __ex_table,"a" - .long FLT6,domain_crash_synchronous , FLT7,domain_crash_synchronous - .long FLT8,domain_crash_synchronous , FLT9,domain_crash_synchronous - .long FLT10,domain_crash_synchronous , FLT11,domain_crash_synchronous - .long FLT12,domain_crash_synchronous , FLT13,domain_crash_synchronous - .long FLT14,domain_crash_synchronous , FLT15,domain_crash_synchronous - .long FLT16,domain_crash_synchronous , FLT17,domain_crash_synchronous - .long FLT18,domain_crash_synchronous , FLT19,domain_crash_synchronous - .long FLT20,domain_crash_synchronous , FLT21,domain_crash_synchronous - .long FLT22,domain_crash_synchronous , FLT23,domain_crash_synchronous - .long FLT24,domain_crash_synchronous , FLT25,domain_crash_synchronous + .long .Lft6,domain_crash_synchronous , .Lft7,domain_crash_synchronous + .long .Lft8,domain_crash_synchronous , .Lft9,domain_crash_synchronous + .long .Lft10,domain_crash_synchronous , .Lft11,domain_crash_synchronous + .long .Lft12,domain_crash_synchronous , .Lft13,domain_crash_synchronous + .long .Lft14,domain_crash_synchronous , .Lft15,domain_crash_synchronous + .long .Lft16,domain_crash_synchronous , .Lft17,domain_crash_synchronous + .long .Lft18,domain_crash_synchronous , .Lft19,domain_crash_synchronous + .long .Lft20,domain_crash_synchronous , .Lft21,domain_crash_synchronous + .long .Lft22,domain_crash_synchronous , .Lft23,domain_crash_synchronous + .long .Lft24,domain_crash_synchronous , .Lft25,domain_crash_synchronous .previous domain_crash_synchronous_string: diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 070deec3d1..736ae2ac89 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -123,10 +123,10 @@ compat_bad_hypercall: compat_restore_all_guest: RESTORE_ALL addq $8,%rsp -CFLT0: iretq +.Lft0: iretq .section .fixup,"ax" -CFIX0: popq -15*8-8(%rsp) # error_code/entry_vector +.Lfx0: popq -15*8-8(%rsp) # error_code/entry_vector SAVE_ALL # 15*8 bytes pushed movq -8(%rsp),%rsi # error_code/entry_vector sti # after stack abuse (-1024(%rsp)) @@ -135,11 +135,11 @@ CFIX0: popq -15*8-8(%rsp) # error_code/entry_vector pushq %rax # RSP pushfq # RFLAGS pushq $__HYPERVISOR_CS # CS - leaq CDBLFLT0(%rip),%rax + leaq .Ldf0(%rip),%rax pushq %rax # RIP pushq %rsi # error_code/entry_vector jmp handle_exception -CDBLFLT0:GET_CURRENT(%rbx) +.Ldf0: GET_CURRENT(%rbx) jmp compat_test_all_events compat_failsafe_callback: GET_CURRENT(%rbx) @@ -157,10 +157,10 @@ compat_failsafe_callback: jmp compat_test_all_events .previous .section __pre_ex_table,"a" - .quad CFLT0,CFIX0 + .quad .Lft0,.Lfx0 .previous .section __ex_table,"a" - .quad CDBLFLT0,compat_failsafe_callback + .quad .Ldf0,compat_failsafe_callback .previous /* %rdx: trap_bounce, %rbx: struct vcpu */ @@ -180,16 +180,16 @@ compat_create_bounce_frame: jz 1f /* Push new frame at registered guest-OS stack base. */ movl VCPU_kernel_sp(%rbx),%esi -CFLT1: mov VCPU_kernel_ss(%rbx),%fs +.Lft1: mov VCPU_kernel_ss(%rbx),%fs subl $2*4,%esi movl UREGS_rsp+8(%rsp),%eax -CFLT2: movl %eax,%fs:(%rsi) +.Lft2: movl %eax,%fs:(%rsi) movl UREGS_ss+8(%rsp),%eax -CFLT3: movl %eax,%fs:4(%rsi) +.Lft3: movl %eax,%fs:4(%rsi) jmp 2f 1: /* In kernel context already: push new frame at existing %rsp. */ movl UREGS_rsp+8(%rsp),%esi -CFLT4: mov UREGS_ss+8(%rsp),%fs +.Lft4: mov UREGS_ss+8(%rsp),%fs 2: movb TRAPBOUNCE_flags(%rdx),%cl subl $3*4,%esi @@ -201,7 +201,7 @@ CFLT4: mov UREGS_ss+8(%rsp),%fs popq %rax shll $16,%eax # Bits 16-23: saved_upcall_mask movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS -CFLT5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask +.Lft5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask shrl $16,%eax testb %al,%al # Bits 0-7: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask @@ -209,25 +209,25 @@ CFLT5: movl %eax,%fs:4(%rsi) # CS / saved_upcall_mask andl $~X86_EFLAGS_IF,%eax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -CFLT6: movl %eax,%fs:2*4(%rsi) # EFLAGS +.Lft6: movl %eax,%fs:2*4(%rsi) # EFLAGS movl UREGS_rip+8(%rsp),%eax -CFLT7: movl %eax,%fs:(%rsi) # EIP +.Lft7: movl %eax,%fs:(%rsi) # EIP testb $TBF_EXCEPTION_ERRCODE,%cl jz 1f subl $4,%esi movl TRAPBOUNCE_error_code(%rdx),%eax -CFLT8: movl %eax,%fs:(%rsi) # ERROR CODE +.Lft8: movl %eax,%fs:(%rsi) # ERROR CODE 1: testb $TBF_FAILSAFE,%cl jz 2f subl $4*4,%esi movl %gs,%eax -CFLT9: movl %eax,%fs:3*4(%rsi) # GS -CFLT10: movl %edi,%fs:2*4(%rsi) # FS +.Lft9: movl %eax,%fs:3*4(%rsi) # GS +.Lft10: movl %edi,%fs:2*4(%rsi) # FS movl %es,%eax -CFLT11: movl %eax,%fs:1*4(%rsi) # ES +.Lft11: movl %eax,%fs:1*4(%rsi) # ES movl %ds,%eax -CFLT12: movl %eax,%fs:0*4(%rsi) # DS +.Lft12: movl %eax,%fs:0*4(%rsi) # DS 2: /* Rewrite our stack frame and return to guest-OS mode. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ @@ -236,7 +236,7 @@ CFLT12: movl %eax,%fs:0*4(%rsi) # DS X86_EFLAGS_NT|X86_EFLAGS_TF),UREGS_eflags+8(%rsp) mov %fs,UREGS_ss+8(%rsp) movl %esi,UREGS_rsp+8(%rsp) -CFLT13: mov %edi,%fs +.Lft13: mov %edi,%fs movzwl TRAPBOUNCE_cs(%rdx),%eax /* Null selectors (0-3) are not allowed. */ testl $~3,%eax @@ -247,18 +247,18 @@ CFLT13: mov %edi,%fs movb $0,TRAPBOUNCE_flags(%rdx) ret .section .fixup,"ax" -CFIX13: +.Lfx13: xorl %edi,%edi - jmp CFLT13 + jmp .Lft13 .previous .section __ex_table,"a" - .quad CFLT1,domain_crash_synchronous , CFLT2,compat_crash_page_fault - .quad CFLT3,compat_crash_page_fault_4 , CFLT4,domain_crash_synchronous - .quad CFLT5,compat_crash_page_fault_4 , CFLT6,compat_crash_page_fault_8 - .quad CFLT7,compat_crash_page_fault , CFLT8,compat_crash_page_fault - .quad CFLT9,compat_crash_page_fault_12, CFLT10,compat_crash_page_fault_8 - .quad CFLT11,compat_crash_page_fault_4 , CFLT12,compat_crash_page_fault - .quad CFLT13,CFIX13 + .quad .Lft1,domain_crash_synchronous , .Lft2,compat_crash_page_fault + .quad .Lft3,compat_crash_page_fault_4 , .Lft4,domain_crash_synchronous + .quad .Lft5,compat_crash_page_fault_4 , .Lft6,compat_crash_page_fault_8 + .quad .Lft7,compat_crash_page_fault , .Lft8,compat_crash_page_fault + .quad .Lft9,compat_crash_page_fault_12, .Lft10,compat_crash_page_fault_8 + .quad .Lft11,compat_crash_page_fault_4 , .Lft12,compat_crash_page_fault + .quad .Lft13,.Lfx13 .previous compat_crash_page_fault_12: @@ -268,17 +268,17 @@ compat_crash_page_fault_8: compat_crash_page_fault_4: addl $4,%esi compat_crash_page_fault: -CFLT14: mov %edi,%fs +.Lft14: mov %edi,%fs movl %esi,%edi call show_page_walk jmp domain_crash_synchronous .section .fixup,"ax" -CFIX14: +.Lfx14: xorl %edi,%edi - jmp CFLT14 + jmp .Lft14 .previous .section __ex_table,"a" - .quad CFLT14,CFIX14 + .quad .Lft14,.Lfx14 .previous .section .rodata, "a", @progbits diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 24f7ea6eb5..8fa21a309d 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -56,10 +56,10 @@ restore_all_guest: /* No special register assumptions. */ iret_exit_to_guest: addq $8,%rsp -FLT1: iretq +.Lft1: iretq .section .fixup,"ax" -FIX1: popq -15*8-8(%rsp) # error_code/entry_vector +.Lfx1: popq -15*8-8(%rsp) # error_code/entry_vector SAVE_ALL # 15*8 bytes pushed movq -8(%rsp),%rsi # error_code/entry_vector sti # after stack abuse (-1024(%rsp)) @@ -68,11 +68,11 @@ FIX1: popq -15*8-8(%rsp) # error_code/entry_vector pushq %rax # RSP pushf # RFLAGS pushq $__HYPERVISOR_CS # CS - leaq DBLFLT1(%rip),%rax + leaq .Ldf1(%rip),%rax pushq %rax # RIP pushq %rsi # error_code/entry_vector jmp handle_exception -DBLFLT1:GET_CURRENT(%rbx) +.Ldf1: GET_CURRENT(%rbx) jmp test_all_events failsafe_callback: GET_CURRENT(%rbx) @@ -87,10 +87,10 @@ failsafe_callback: jmp test_all_events .previous .section __pre_ex_table,"a" - .quad FLT1,FIX1 + .quad .Lft1,.Lfx1 .previous .section __ex_table,"a" - .quad DBLFLT1,failsafe_callback + .quad .Ldf1,failsafe_callback .previous ALIGN @@ -249,9 +249,9 @@ create_bounce_frame: 1: movb TRAPBOUNCE_flags(%rdx),%cl subq $40,%rsi movq UREGS_ss+8(%rsp),%rax -FLT2: movq %rax,32(%rsi) # SS +.Lft2: movq %rax,32(%rsi) # SS movq UREGS_rsp+8(%rsp),%rax -FLT3: movq %rax,24(%rsi) # RSP +.Lft3: movq %rax,24(%rsi) # RSP movq VCPU_vcpu_info(%rbx),%rax pushq VCPUINFO_upcall_mask(%rax) testb $TBF_INTERRUPT,%cl @@ -260,7 +260,7 @@ FLT3: movq %rax,24(%rsi) # RSP popq %rax shlq $32,%rax # Bits 32-39: saved_upcall_mask movw UREGS_cs+8(%rsp),%ax # Bits 0-15: CS -FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask +.Lft4: movq %rax,8(%rsi) # CS / saved_upcall_mask shrq $32,%rax testb $0xFF,%al # Bits 0-7: saved_upcall_mask setz %ch # %ch == !saved_upcall_mask @@ -268,30 +268,30 @@ FLT4: movq %rax,8(%rsi) # CS / saved_upcall_mask andq $~X86_EFLAGS_IF,%rax shlb $1,%ch # Bit 9 (EFLAGS.IF) orb %ch,%ah # Fold EFLAGS.IF into %eax -FLT5: movq %rax,16(%rsi) # RFLAGS +.Lft5: movq %rax,16(%rsi) # RFLAGS movq UREGS_rip+8(%rsp),%rax -FLT6: movq %rax,(%rsi) # RIP +.Lft6: movq %rax,(%rsi) # RIP testb $TBF_EXCEPTION_ERRCODE,%cl jz 1f subq $8,%rsi movl TRAPBOUNCE_error_code(%rdx),%eax -FLT7: movq %rax,(%rsi) # ERROR CODE +.Lft7: movq %rax,(%rsi) # ERROR CODE 1: testb $TBF_FAILSAFE,%cl jz 2f subq $32,%rsi movl %gs,%eax -FLT8: movq %rax,24(%rsi) # GS +.Lft8: movq %rax,24(%rsi) # GS movl %fs,%eax -FLT9: movq %rax,16(%rsi) # FS +.Lft9: movq %rax,16(%rsi) # FS movl %es,%eax -FLT10: movq %rax,8(%rsi) # ES +.Lft10: movq %rax,8(%rsi) # ES movl %ds,%eax -FLT11: movq %rax,(%rsi) # DS +.Lft11: movq %rax,(%rsi) # DS 2: subq $16,%rsi movq UREGS_r11+8(%rsp),%rax -FLT12: movq %rax,8(%rsi) # R11 +.Lft12: movq %rax,8(%rsi) # R11 movq UREGS_rcx+8(%rsp),%rax -FLT13: movq %rax,(%rsi) # RCX +.Lft13: movq %rax,(%rsi) # RCX /* Rewrite our stack frame and return to guest-OS mode. */ /* IA32 Ref. Vol. 3: TF, VM, RF and NT flags are cleared on trap. */ /* Also clear AC: alignment checks shouldn't trigger in kernel mode. */ @@ -308,12 +308,12 @@ FLT13: movq %rax,(%rsi) # RCX movb $0,TRAPBOUNCE_flags(%rdx) ret .section __ex_table,"a" - .quad FLT2,domain_crash_synchronous , FLT3,domain_crash_synchronous - .quad FLT4,domain_crash_synchronous , FLT5,domain_crash_synchronous - .quad FLT6,domain_crash_synchronous , FLT7,domain_crash_synchronous - .quad FLT8,domain_crash_synchronous , FLT9,domain_crash_synchronous - .quad FLT10,domain_crash_synchronous , FLT11,domain_crash_synchronous - .quad FLT12,domain_crash_synchronous , FLT13,domain_crash_synchronous + .quad .Lft2,domain_crash_synchronous , .Lft3,domain_crash_synchronous + .quad .Lft4,domain_crash_synchronous , .Lft5,domain_crash_synchronous + .quad .Lft6,domain_crash_synchronous , .Lft7,domain_crash_synchronous + .quad .Lft8,domain_crash_synchronous , .Lft9,domain_crash_synchronous + .quad .Lft10,domain_crash_synchronous , .Lft11,domain_crash_synchronous + .quad .Lft12,domain_crash_synchronous , .Lft13,domain_crash_synchronous .previous domain_crash_synchronous_string: From 1947b2fc1a0e8c532081091f05a9a69428996814 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 8 Feb 2007 21:30:29 +0000 Subject: [PATCH 79/95] Fix x86/64 build. Signed-off-by: Keir Fraser --- xen/arch/x86/x86_64/Makefile | 3 ++- xen/arch/x86/x86_64/compat/entry.S | 23 ++++++++++++++++++++--- xen/arch/x86/x86_64/entry.S | 8 ++------ 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/xen/arch/x86/x86_64/Makefile b/xen/arch/x86/x86_64/Makefile index 372cce5892..98f20a43c6 100644 --- a/xen/arch/x86/x86_64/Makefile +++ b/xen/arch/x86/x86_64/Makefile @@ -1,3 +1,5 @@ +subdir-y += compat + obj-y += entry.o obj-y += compat_kexec.o obj-y += gpr_switch.o @@ -13,7 +15,6 @@ ifeq ($(CONFIG_COMPAT),y) # extra dependencies compat.o: ../compat.c domctl.o: ../domctl.c -entry.o: compat/entry.S mm.o: compat/mm.c physdev.o: ../physdev.c platform_hypercall.o: ../platform_hypercall.c diff --git a/xen/arch/x86/x86_64/compat/entry.S b/xen/arch/x86/x86_64/compat/entry.S index 736ae2ac89..3f1d1b8d07 100644 --- a/xen/arch/x86/x86_64/compat/entry.S +++ b/xen/arch/x86/x86_64/compat/entry.S @@ -2,10 +2,27 @@ * Compatibility hypercall routines. */ +#include +#include +#include +#include +#include +#include #include +#include -.text +#define GET_GUEST_REGS(reg) \ + movq $~(STACK_SIZE-1),reg; \ + andq %rsp,reg; \ + orq $(STACK_SIZE-CPUINFO_sizeof),reg; +#define GET_CURRENT(reg) \ + movq $STACK_SIZE-8, reg; \ + orq %rsp, reg; \ + andq $~7,reg; \ + movq (reg),reg; + + ALIGN ENTRY(compat_hypercall) pushq $0 movl $TRAP_syscall,4(%rsp) @@ -62,7 +79,7 @@ compat_skip_clobber: movl %eax,UREGS_rax(%rsp) # save the return value /* %rbx: struct vcpu */ -compat_test_all_events: +ENTRY(compat_test_all_events) cli # tests must not race interrupts /*compat_test_softirqs:*/ movl VCPU_processor(%rbx),%eax @@ -164,7 +181,7 @@ compat_failsafe_callback: .previous /* %rdx: trap_bounce, %rbx: struct vcpu */ -compat_post_handle_exception: +ENTRY(compat_post_handle_exception) testb $TBF_EXCEPTION,TRAPBOUNCE_flags(%rdx) jz compat_test_all_events call compat_create_bounce_frame diff --git a/xen/arch/x86/x86_64/entry.S b/xen/arch/x86/x86_64/entry.S index 8fa21a309d..36b5c5e1ad 100644 --- a/xen/arch/x86/x86_64/entry.S +++ b/xen/arch/x86/x86_64/entry.S @@ -319,7 +319,7 @@ create_bounce_frame: domain_crash_synchronous_string: .asciz "domain_crash_sync called from entry.S\n" -domain_crash_synchronous: +ENTRY(domain_crash_synchronous) # Get out of the guest-save area of the stack. GET_GUEST_REGS(%rax) movq %rax,%rsp @@ -357,7 +357,7 @@ ENTRY(ret_from_intr) ALIGN /* No special register assumptions. */ -handle_exception: +ENTRY(handle_exception) SAVE_ALL testb $X86_EFLAGS_IF>>8,UREGS_eflags+1(%rsp) jz exception_with_ints_disabled @@ -633,7 +633,3 @@ ENTRY(hypercall_args_table) .rept NR_hypercalls-(.-hypercall_args_table) .byte 0 /* do_ni_hypercall */ .endr - -#ifdef CONFIG_COMPAT -#include "compat/entry.S" -#endif From b15e0dd802bee0657e0774090b3ab3a51dd4e0f4 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 8 Feb 2007 21:36:35 +0000 Subject: [PATCH 80/95] Fix non-x86 build. --- tools/misc/Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/misc/Makefile b/tools/misc/Makefile index dce732f273..35abbbf08f 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -9,7 +9,9 @@ CFLAGS += $(INCLUDES) HDRS = $(wildcard *.h) -TARGETS = xenperf xc_shadow xen-detect +TARGETS-y := xenperf xc_shadow +TARGETS-$(CONFIG_X86) += xen-detect +TARGETS := $(TARGETS-y) INSTALL_BIN = $(TARGETS) xencons INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf From 982965741d777beb7f79e46e15a05f8c6dd2ce1e Mon Sep 17 00:00:00 2001 From: Alastair Tse Date: Fri, 9 Feb 2007 10:21:12 +0000 Subject: [PATCH 81/95] Add missing Makefile in x86_64/compat so that it builds on x86_64. Signed-off-by: Alastair Tse --- xen/arch/x86/x86_64/compat/Makefile | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 xen/arch/x86/x86_64/compat/Makefile diff --git a/xen/arch/x86/x86_64/compat/Makefile b/xen/arch/x86/x86_64/compat/Makefile new file mode 100644 index 0000000000..6547e0c737 --- /dev/null +++ b/xen/arch/x86/x86_64/compat/Makefile @@ -0,0 +1,2 @@ +obj-y += entry.o + From e0bc4531dfc430497e311f13192781ce215d40b8 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Fri, 9 Feb 2007 10:48:41 +0000 Subject: [PATCH 82/95] [HVM] Save/restore: disentangle max_pfn from nr_pages. These have been used interchangeably, which is OK for PV domains but not for HVM. This fixes an over-allocation by 256MB when restoring HVM guests that have more than 4GB of RAM. Signed-off-by: Tim Deegan --- tools/libxc/xc_hvm_restore.c | 56 +++++++++++++++++------------------- tools/libxc/xenguest.h | 2 +- tools/libxc/xg_private.c | 2 +- tools/xcutils/xc_restore.c | 10 +++---- 4 files changed, 33 insertions(+), 37 deletions(-) diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index 4cf27fdb8b..ec3eeb8999 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -41,11 +41,8 @@ static unsigned long hvirt_start; /* #levels of page tables used by the currrent guest */ static unsigned int pt_levels; -/* total number of pages used by the current guest */ -static unsigned long max_pfn; - -/* A table mapping each PFN to its new MFN. */ -static xen_pfn_t *p2m = NULL; +/* A list of PFNs that exist, used when allocating memory to the guest */ +static xen_pfn_t *pfns = NULL; static ssize_t read_exact(int fd, void *buf, size_t count) @@ -67,7 +64,7 @@ read_exact(int fd, void *buf, size_t count) } int xc_hvm_restore(int xc_handle, int io_fd, - uint32_t dom, unsigned long nr_pfns, + uint32_t dom, unsigned long max_pfn, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int pae, unsigned int apic) { @@ -90,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, unsigned long long v_end, memsize; unsigned long shared_page_nr; - unsigned long mfn, pfn; + unsigned long pfn; unsigned int prev_pc, this_pc; int verify = 0; @@ -99,22 +96,26 @@ int xc_hvm_restore(int xc_handle, int io_fd, struct xen_add_to_physmap xatp; + /* Number of pages of memory the guest has. *Not* the same as max_pfn. */ + unsigned long nr_pages; + /* hvm guest mem size (Mb) */ memsize = (unsigned long long)*store_mfn; v_end = memsize << 20; + nr_pages = (unsigned long) memsize << (20 - PAGE_SHIFT); - DPRINTF("xc_hvm_restore:dom=%d, nr_pfns=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", - dom, nr_pfns, store_evtchn, *store_mfn, pae, apic); - - max_pfn = nr_pfns; + DPRINTF("xc_hvm_restore:dom=%d, nr_pages=0x%lx, store_evtchn=%d, *store_mfn=%ld, pae=%u, apic=%u.\n", + dom, nr_pages, store_evtchn, *store_mfn, pae, apic); + if(!get_platform_info(xc_handle, dom, &max_mfn, &hvirt_start, &pt_levels)) { ERROR("Unable to get platform info."); return 1; } - DPRINTF("xc_hvm_restore start: max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", + DPRINTF("xc_hvm_restore start: nr_pages = %lx, max_pfn = %lx, max_mfn = %lx, hvirt_start=%lx, pt_levels=%d\n", + nr_pages, max_pfn, max_mfn, hvirt_start, @@ -127,30 +128,30 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - p2m = malloc(max_pfn * sizeof(xen_pfn_t)); - if (p2m == NULL) { + pfns = malloc(max_pfn * sizeof(xen_pfn_t)); + if (pfns == NULL) { ERROR("memory alloc failed"); errno = ENOMEM; goto out; } - if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(max_pfn)) != 0) { + if(xc_domain_setmaxmem(xc_handle, dom, PFN_TO_KB(nr_pages)) != 0) { errno = ENOMEM; goto out; } for ( i = 0; i < max_pfn; i++ ) - p2m[i] = i; + pfns[i] = i; for ( i = HVM_BELOW_4G_RAM_END >> PAGE_SHIFT; i < max_pfn; i++ ) - p2m[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; + pfns[i] += HVM_BELOW_4G_MMIO_LENGTH >> PAGE_SHIFT; /* Allocate memory for HVM guest, skipping VGA hole 0xA0000-0xC0000. */ rc = xc_domain_memory_populate_physmap( - xc_handle, dom, (max_pfn > 0xa0) ? 0xa0 : max_pfn, - 0, 0, &p2m[0x00]); - if ( (rc == 0) && (max_pfn > 0xc0) ) + xc_handle, dom, (nr_pages > 0xa0) ? 0xa0 : nr_pages, + 0, 0, &pfns[0x00]); + if ( (rc == 0) && (nr_pages > 0xc0) ) rc = xc_domain_memory_populate_physmap( - xc_handle, dom, max_pfn - 0xc0, 0, 0, &p2m[0xc0]); + xc_handle, dom, nr_pages - 0xc0, 0, 0, &pfns[0xc0]); if ( rc != 0 ) { PERROR("Could not allocate memory for HVM guest.\n"); @@ -171,9 +172,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, goto out; } - for ( i = 0; i < max_pfn; i++) - p2m[i] = i; - prev_pc = 0; n = 0; @@ -181,7 +179,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, int j; - this_pc = (n * 100) / max_pfn; + this_pc = (n * 100) / nr_pages; if ( (this_pc - prev_pc) >= 5 ) { PPRINTF("\b\b\b\b%3d%%", this_pc); @@ -234,8 +232,6 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - mfn = p2m[pfn]; - /* In verify mode, we use a copy; otherwise we work in place */ page = verify ? (void *)buf : (region_base + i*PAGE_SIZE); @@ -252,8 +248,8 @@ int xc_hvm_restore(int xc_handle, int io_fd, int v; - DPRINTF("************** pfn=%lx mfn=%lx gotcs=%08lx " - "actualcs=%08lx\n", pfn, p2m[pfn], + DPRINTF("************** pfn=%lx gotcs=%08lx " + "actualcs=%08lx\n", pfn, csum_page(region_base + i*PAGE_SIZE), csum_page(buf)); @@ -361,7 +357,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, out: if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); - free(p2m); + free(pfns); free(hvm_buf); DPRINTF("Restore exit with rc=%d\n", rc); diff --git a/tools/libxc/xenguest.h b/tools/libxc/xenguest.h index 3800b0cb13..7e19442bd4 100644 --- a/tools/libxc/xenguest.h +++ b/tools/libxc/xenguest.h @@ -57,7 +57,7 @@ int xc_linux_restore(int xc_handle, int io_fd, uint32_t dom, * @return 0 on success, -1 on failure */ int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, - unsigned long nr_pfns, unsigned int store_evtchn, + unsigned long max_pfn, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int pae, unsigned int apic); diff --git a/tools/libxc/xg_private.c b/tools/libxc/xg_private.c index 6f4f28f988..751c56d59b 100644 --- a/tools/libxc/xg_private.c +++ b/tools/libxc/xg_private.c @@ -209,7 +209,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, __attribute__((weak)) int xc_hvm_restore(int xc_handle, int io_fd, uint32_t dom, - unsigned long nr_pfns, unsigned int store_evtchn, + unsigned long max_pfn, unsigned int store_evtchn, unsigned long *store_mfn, unsigned int pae, unsigned int apic) { diff --git a/tools/xcutils/xc_restore.c b/tools/xcutils/xc_restore.c index 6629e33082..0eaf3210a3 100644 --- a/tools/xcutils/xc_restore.c +++ b/tools/xcutils/xc_restore.c @@ -18,14 +18,14 @@ int main(int argc, char **argv) { - unsigned int xc_fd, io_fd, domid, nr_pfns, store_evtchn, console_evtchn; + unsigned int xc_fd, io_fd, domid, max_pfn, store_evtchn, console_evtchn; unsigned int hvm, pae, apic; int ret; unsigned long store_mfn, console_mfn; if (argc != 9) errx(1, - "usage: %s iofd domid nr_pfns store_evtchn console_evtchn hvm pae apic", + "usage: %s iofd domid max_pfn store_evtchn console_evtchn hvm pae apic", argv[0]); xc_fd = xc_interface_open(); @@ -34,7 +34,7 @@ main(int argc, char **argv) io_fd = atoi(argv[1]); domid = atoi(argv[2]); - nr_pfns = atoi(argv[3]); + max_pfn = atoi(argv[3]); store_evtchn = atoi(argv[4]); console_evtchn = atoi(argv[5]); hvm = atoi(argv[6]); @@ -44,10 +44,10 @@ main(int argc, char **argv) if (hvm) { /* pass the memsize to xc_hvm_restore to find the store_mfn */ store_mfn = hvm; - ret = xc_hvm_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, + ret = xc_hvm_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn, &store_mfn, pae, apic); } else - ret = xc_linux_restore(xc_fd, io_fd, domid, nr_pfns, store_evtchn, + ret = xc_linux_restore(xc_fd, io_fd, domid, max_pfn, store_evtchn, &store_mfn, console_evtchn, &console_mfn); if (ret == 0) { From 71444c520f32fa633e92a3311bb4fbedc8a9518f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Feb 2007 17:38:33 +0000 Subject: [PATCH 83/95] Print all by default in debug builds. --- xen/drivers/char/console.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c index cfc7e98a17..03045963c9 100644 --- a/xen/drivers/char/console.c +++ b/xen/drivers/char/console.c @@ -72,10 +72,17 @@ static DEFINE_SPINLOCK(console_lock); * Note, in the above algorithm, to disable rate limiting simply make * the lower threshold equal to the upper. */ +#ifdef NDEBUG #define XENLOG_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_LOWER_THRESHOLD 2 /* Always print ERR and WARNING */ #define XENLOG_GUEST_UPPER_THRESHOLD 2 /* Do not print INFO and DEBUG */ #define XENLOG_GUEST_LOWER_THRESHOLD 0 /* Rate-limit ERR and WARNING */ +#else +#define XENLOG_UPPER_THRESHOLD 4 /* Do not discard anything */ +#define XENLOG_LOWER_THRESHOLD 4 /* Print everything */ +#define XENLOG_GUEST_UPPER_THRESHOLD 4 /* Do not discard anything */ +#define XENLOG_GUEST_LOWER_THRESHOLD 4 /* Print everything */ +#endif /* * The XENLOG_DEFAULT is the default given to printks that * do not have any print level associated with them. From 50cdf11efc6399a99e06bf6e6ee1522cad34bcf5 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 9 Feb 2007 18:19:24 +0000 Subject: [PATCH 84/95] [HVM] Fill in mmio decode gaps for Grp1 immediate opcodes. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/platform.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 1c8e4c11c4..8eb73f53e6 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -513,14 +513,30 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); switch ( ins_subtype ) { - case 7: /* cmp $imm, m32/16 */ - mmio_op->instr = INSTR_CMP; + case 0: /* add $imm, m32/16 */ + mmio_op->instr = INSTR_ADD; return DECODE_success; case 1: /* or $imm, m32/16 */ mmio_op->instr = INSTR_OR; return DECODE_success; + case 4: /* and $imm, m32/16 */ + mmio_op->instr = INSTR_AND; + return DECODE_success; + + case 5: /* sub $imm, m32/16 */ + mmio_op->instr = INSTR_SUB; + return DECODE_success; + + case 6: /* xor $imm, m32/16 */ + mmio_op->instr = INSTR_XOR; + return DECODE_success; + + case 7: /* cmp $imm, m32/16 */ + mmio_op->instr = INSTR_CMP; + return DECODE_success; + default: printk("%x/%x, This opcode isn't handled yet!\n", *opcode, ins_subtype); From 193ca2e8bbd7103200f2786f00a8c06aa54948e3 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 13 Feb 2007 15:32:25 +0000 Subject: [PATCH 85/95] [LINUX] Call ctrl_alt_del() to trigger a reboot so we benefit from the generic infrastructure for cad_pid etc. Add a ctrl_alt_del() implemenation to the PV on HVM compatibility layer since ctrl_alt_del() is not exported on native kernels. Signed-off-by: Ian Campbell --- linux-2.6-xen-sparse/drivers/xen/core/reboot.c | 3 ++- unmodified_drivers/linux-2.6/platform-pci/platform-compat.c | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c index af3fe3a15c..aab244a738 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c @@ -100,6 +100,7 @@ static void __shutdown_handler(void *unused) static void shutdown_handler(struct xenbus_watch *watch, const char **vec, unsigned int len) { + extern void ctrl_alt_del(void); char *str; struct xenbus_transaction xbt; int err; @@ -129,7 +130,7 @@ static void shutdown_handler(struct xenbus_watch *watch, if (strcmp(str, "poweroff") == 0) shutting_down = SHUTDOWN_POWEROFF; else if (strcmp(str, "reboot") == 0) - kill_proc(1, SIGINT, 1); /* interrupt init */ + ctrl_alt_del(); else if (strcmp(str, "suspend") == 0) shutting_down = SHUTDOWN_SUSPEND; else if (strcmp(str, "halt") == 0) diff --git a/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c b/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c index 5a0bb9bce8..7e1ad1f169 100644 --- a/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c +++ b/unmodified_drivers/linux-2.6/platform-pci/platform-compat.c @@ -13,6 +13,12 @@ static int system_state = 1; EXPORT_SYMBOL(system_state); #endif +static inline void ctrl_alt_del(void) +{ + kill_proc(1, SIGINT, 1); /* interrupt init */ +} +EXPORT_SYMBOL(ctrl_alt_del); + #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) size_t strcspn(const char *s, const char *reject) { From 22d7d00f7ec5b86c001105174acf82319f00b552 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Feb 2007 12:02:20 +0000 Subject: [PATCH 86/95] [XEN] New paging-assistance interface. Adds paging_* functions, wrapping the existing shadow_* ones, so that later hardware paging assistance can be hooked in at this level. Separates p2m maintenance code into its own files. Adjusts shadow code to comply with the new interfaces. Changes all callers in arch/x86 to use the new interfaces. Signed-off-by: Wei Huang Signed-off-by: Tim Deegan --- xen/arch/x86/domain.c | 52 +- xen/arch/x86/domain_build.c | 10 +- xen/arch/x86/domctl.c | 4 +- xen/arch/x86/hvm/hvm.c | 9 +- xen/arch/x86/hvm/io.c | 2 +- xen/arch/x86/hvm/platform.c | 8 +- xen/arch/x86/hvm/svm/intr.c | 2 +- xen/arch/x86/hvm/svm/svm.c | 30 +- xen/arch/x86/hvm/svm/vmcb.c | 4 +- xen/arch/x86/hvm/vlapic.c | 1 - xen/arch/x86/hvm/vmx/vmcs.c | 2 +- xen/arch/x86/hvm/vmx/vmx.c | 34 +- xen/arch/x86/mm.c | 89 +-- xen/arch/x86/mm/Makefile | 3 + xen/arch/x86/mm/p2m.c | 699 +++++++++++++++++ xen/arch/x86/mm/paging.c | 143 ++++ xen/arch/x86/mm/shadow/common.c | 1163 ++++++++--------------------- xen/arch/x86/mm/shadow/multi.c | 132 ++-- xen/arch/x86/mm/shadow/multi.h | 2 +- xen/arch/x86/mm/shadow/private.h | 105 ++- xen/arch/x86/mm/shadow/types.h | 10 +- xen/arch/x86/setup.c | 2 +- xen/arch/x86/sysctl.c | 1 - xen/arch/x86/traps.c | 10 +- xen/arch/x86/x86_32/domain_page.c | 1 - xen/arch/x86/x86_64/traps.c | 1 - xen/include/asm-x86/domain.h | 90 ++- xen/include/asm-x86/mm.h | 63 +- xen/include/asm-x86/p2m.h | 142 ++++ xen/include/asm-x86/page.h | 2 + xen/include/asm-x86/paging.h | 376 ++++++++++ xen/include/asm-x86/shadow.h | 375 +--------- 32 files changed, 2042 insertions(+), 1525 deletions(-) create mode 100644 xen/arch/x86/mm/p2m.c create mode 100644 xen/arch/x86/mm/paging.c create mode 100644 xen/include/asm-x86/p2m.h create mode 100644 xen/include/asm-x86/paging.h diff --git a/xen/arch/x86/domain.c b/xen/arch/x86/domain.c index 653ceafb0b..bca683c59b 100644 --- a/xen/arch/x86/domain.c +++ b/xen/arch/x86/domain.c @@ -37,7 +37,7 @@ #include #include #include -#include +#include #include #include #include @@ -331,6 +331,7 @@ int vcpu_initialise(struct vcpu *v) pae_l3_cache_init(&v->arch.pae_l3_cache); + paging_vcpu_init(v); if ( is_hvm_domain(d) ) { @@ -424,7 +425,7 @@ int arch_domain_create(struct domain *d) HYPERVISOR_COMPAT_VIRT_START(d) = __HYPERVISOR_COMPAT_VIRT_START; #endif - shadow_domain_init(d); + paging_domain_init(d); if ( !is_idle_domain(d) ) { @@ -464,7 +465,7 @@ void arch_domain_destroy(struct domain *d) hvm_domain_destroy(d); } - shadow_final_teardown(d); + paging_final_teardown(d); free_xenheap_pages( d->arch.mm_perdomain_pt, @@ -613,7 +614,7 @@ int arch_set_info_guest( { cr3_pfn = gmfn_to_mfn(d, xen_cr3_to_pfn(c.nat->ctrlreg[3])); - if ( shadow_mode_refcounts(d) + if ( paging_mode_refcounts(d) ? !get_page(mfn_to_page(cr3_pfn), d) : !get_page_and_type(mfn_to_page(cr3_pfn), d, PGT_base_page_table) ) @@ -631,7 +632,7 @@ int arch_set_info_guest( cr3_pfn = gmfn_to_mfn(d, compat_cr3_to_pfn(c.cmp->ctrlreg[3])); - if ( shadow_mode_refcounts(d) + if ( paging_mode_refcounts(d) ? !get_page(mfn_to_page(cr3_pfn), d) : !get_page_and_type(mfn_to_page(cr3_pfn), d, PGT_l3_page_table) ) @@ -652,8 +653,8 @@ int arch_set_info_guest( /* Don't redo final setup */ set_bit(_VCPUF_initialised, &v->vcpu_flags); - if ( shadow_mode_enabled(d) ) - shadow_update_paging_modes(v); + if ( paging_mode_enabled(d) ) + paging_update_paging_modes(v); update_cr3(v); @@ -1406,7 +1407,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1427,7 +1428,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) pfn = pagetable_get_pfn(v->arch.guest_table); if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1443,7 +1444,7 @@ static void vcpu_destroy_pagetables(struct vcpu *v) pfn = pagetable_get_pfn(v->arch.guest_table_user); if ( pfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(pfn)); else put_page_and_type(mfn_to_page(pfn)); @@ -1464,8 +1465,8 @@ void domain_relinquish_resources(struct domain *d) for_each_vcpu ( d, v ) vcpu_destroy_pagetables(v); - /* Tear down shadow mode stuff. */ - shadow_teardown(d); + /* Tear down paging-assistance stuff. */ + paging_teardown(d); /* * Relinquish GDT mappings. No need for explicit unmapping of the LDT as @@ -1484,35 +1485,12 @@ void domain_relinquish_resources(struct domain *d) void arch_dump_domain_info(struct domain *d) { - if ( shadow_mode_enabled(d) ) - { - printk(" shadow mode: "); - if ( d->arch.shadow.mode & SHM2_enable ) - printk("enabled "); - if ( shadow_mode_refcounts(d) ) - printk("refcounts "); - if ( shadow_mode_log_dirty(d) ) - printk("log_dirty "); - if ( shadow_mode_translate(d) ) - printk("translate "); - if ( shadow_mode_external(d) ) - printk("external "); - printk("\n"); - } + paging_dump_domain_info(d); } void arch_dump_vcpu_info(struct vcpu *v) { - if ( shadow_mode_enabled(v->domain) ) - { - if ( v->arch.shadow.mode ) - printk(" shadowed %u-on-%u, %stranslated\n", - v->arch.shadow.mode->guest_levels, - v->arch.shadow.mode->shadow_levels, - shadow_vcpu_mode_translate(v) ? "" : "not "); - else - printk(" not shadowed\n"); - } + paging_dump_vcpu_info(v); } /* diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c index b32f57861c..5755eef718 100644 --- a/xen/arch/x86/domain_build.c +++ b/xen/arch/x86/domain_build.c @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include @@ -777,8 +777,8 @@ int construct_dom0(struct domain *d, (void)alloc_vcpu(d, i, i); /* Set up CR3 value for write_ptbase */ - if ( shadow_mode_enabled(v->domain) ) - shadow_update_paging_modes(v); + if ( paging_mode_enabled(v->domain) ) + paging_update_paging_modes(v); else update_cr3(v); @@ -918,8 +918,8 @@ int construct_dom0(struct domain *d, regs->eflags = X86_EFLAGS_IF; if ( opt_dom0_shadow ) - if ( shadow_enable(d, SHM2_enable) == 0 ) - shadow_update_paging_modes(v); + if ( paging_enable(d, PG_SH_enable) == 0 ) + paging_update_paging_modes(v); if ( supervisor_mode_kernel ) { diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 384faf48e4..8d4901b0c3 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include #include @@ -42,7 +42,7 @@ long arch_do_domctl( d = get_domain_by_id(domctl->domain); if ( d != NULL ) { - ret = shadow_domctl(d, + ret = paging_domctl(d, &domctl->u.shadow_op, guest_handle_cast(u_domctl, void)); put_domain(d); diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 9147737846..57d58e7647 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -30,11 +30,10 @@ #include #include #include -#include #include #include #include -#include +#include #include #include #include @@ -155,7 +154,7 @@ int hvm_domain_initialise(struct domain *d) spin_lock_init(&d->arch.hvm_domain.buffered_io_lock); spin_lock_init(&d->arch.hvm_domain.irq_lock); - rc = shadow_enable(d, SHM2_refcounts|SHM2_translate|SHM2_external); + rc = paging_enable(d, PG_SH_enable|PG_refcounts|PG_translate|PG_external); if ( rc != 0 ) return rc; @@ -383,7 +382,7 @@ static int __hvm_copy(void *buf, paddr_t addr, int size, int dir, int virt) count = min_t(int, PAGE_SIZE - (addr & ~PAGE_MASK), todo); if ( virt ) - mfn = get_mfn_from_gpfn(shadow_gva_to_gfn(current, addr)); + mfn = get_mfn_from_gpfn(paging_gva_to_gfn(current, addr)); else mfn = get_mfn_from_gpfn(addr >> PAGE_SHIFT); @@ -600,7 +599,7 @@ void hvm_do_hypercall(struct cpu_user_regs *pregs) return; } - if ( current->arch.shadow.mode->guest_levels == 4 ) + if ( current->arch.paging.mode->guest_levels == 4 ) { pregs->rax = hvm_hypercall64_table[pregs->rax](pregs->rdi, pregs->rsi, diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 013e723f35..4637515bf4 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 8eb73f53e6..404c9b62fc 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -21,7 +21,6 @@ #include #include #include -#include #include #include #include @@ -29,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -809,7 +809,7 @@ void send_pio_req(unsigned long port, unsigned long count, int size, if ( value_is_ptr ) /* get physical address of data */ { if ( hvm_paging_enabled(current) ) - p->data = shadow_gva_to_gpa(current, value); + p->data = paging_gva_to_gpa(current, value); else p->data = value; /* guest VA == guest PA */ } @@ -865,7 +865,7 @@ static void send_mmio_req(unsigned char type, unsigned long gpa, if ( value_is_ptr ) { if ( hvm_paging_enabled(v) ) - p->data = shadow_gva_to_gpa(v, value); + p->data = paging_gva_to_gpa(v, value); else p->data = value; /* guest VA == guest PA */ } @@ -981,7 +981,7 @@ void handle_mmio(unsigned long gpa) if ( ad_size == WORD ) addr &= 0xFFFF; addr += hvm_get_segment_base(v, x86_seg_es); - if ( shadow_gva_to_gpa(v, addr) == gpa ) + if ( paging_gva_to_gpa(v, addr) == gpa ) { enum x86_segment seg; diff --git a/xen/arch/x86/hvm/svm/intr.c b/xen/arch/x86/hvm/svm/intr.c index e3e0f0a40e..a4a458c72d 100644 --- a/xen/arch/x86/hvm/svm/intr.c +++ b/xen/arch/x86/hvm/svm/intr.c @@ -24,10 +24,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index bad0b12b92..cc9043e413 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -29,7 +29,8 @@ #include #include #include -#include +#include +#include #include #include #include @@ -491,9 +492,6 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_svm.cpu_cr3 = c->cr3; } @@ -560,7 +558,7 @@ int svm_vmcb_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmcb->sysenter_esp = c->sysenter_esp; vmcb->sysenter_eip = c->sysenter_eip; - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1095,7 +1093,7 @@ static int svm_do_page_fault(unsigned long va, struct cpu_user_regs *regs) "svm_do_page_fault = 0x%lx, eip = %lx, error_code = %lx", va, (unsigned long)current->arch.hvm_svm.vmcb->rip, (unsigned long)regs->error_code); - return shadow_fault(va, regs); + return paging_fault(va, regs); } @@ -1730,7 +1728,7 @@ static int svm_set_cr0(unsigned long value) v->arch.guest_table = pagetable_from_pfn(mfn); if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); @@ -1753,7 +1751,7 @@ static int svm_set_cr0(unsigned long value) svm_inject_exception(v, TRAP_gp_fault, 1, 0); return 0; } - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } else if ( (value & (X86_CR0_PE | X86_CR0_PG)) == X86_CR0_PE ) { @@ -1763,7 +1761,7 @@ static int svm_set_cr0(unsigned long value) clear_bit(SVM_CPU_STATE_LMA_ENABLED, &v->arch.hvm_svm.cpu_state); } /* we should take care of this kind of situation */ - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } return 1; @@ -1866,7 +1864,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) goto bad_cr3; - shadow_update_cr3(v); + paging_update_cr3(v); } else { @@ -1917,7 +1915,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) v->arch.guest_table = pagetable_from_pfn(mfn); if ( old_base_mfn ) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); @@ -1946,7 +1944,7 @@ static int mov_to_cr(int gpreg, int cr, struct cpu_user_regs *regs) * all TLB entries except global entries. */ if ((old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE)) - shadow_update_paging_modes(v); + paging_update_paging_modes(v); break; case 8: @@ -2289,7 +2287,7 @@ void svm_handle_invlpg(const short invlpga, struct cpu_user_regs *regs) __update_guest_eip (vmcb, inst_len); } - shadow_invlpg(v, g_vaddr); + paging_invlpg(v, g_vaddr); } @@ -2660,7 +2658,7 @@ void walk_shadow_and_guest_pt(unsigned long gva) struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; paddr_t gpa; - gpa = shadow_gva_to_gpa(current, gva); + gpa = paging_gva_to_gpa(current, gva); printk("gva = %lx, gpa=%"PRIpaddr", gCR3=%x\n", gva, gpa, (u32)vmcb->cr3); if( !svm_paging_enabled(v) || mmio_space(gpa) ) return; @@ -2726,7 +2724,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF) { if (svm_paging_enabled(v) && - !mmio_space(shadow_gva_to_gpa(current, vmcb->exitinfo2))) + !mmio_space(paging_gva_to_gpa(current, vmcb->exitinfo2))) { printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64"," "I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", " @@ -2736,7 +2734,7 @@ asmlinkage void svm_vmexit_handler(struct cpu_user_regs *regs) (u64)vmcb->exitinfo1, (u64)vmcb->exitinfo2, (u64)vmcb->exitintinfo.bytes, - (u64)shadow_gva_to_gpa(current, vmcb->exitinfo2)); + (u64)paging_gva_to_gpa(current, vmcb->exitinfo2)); } else { diff --git a/xen/arch/x86/hvm/svm/vmcb.c b/xen/arch/x86/hvm/svm/vmcb.c index 642d9d0026..0a0622fb75 100644 --- a/xen/arch/x86/hvm/svm/vmcb.c +++ b/xen/arch/x86/hvm/svm/vmcb.c @@ -23,10 +23,10 @@ #include #include #include -#include #include #include #include +#include #include #include #include @@ -196,7 +196,7 @@ static int construct_vmcb(struct vcpu *v) read_cr4() & ~(X86_CR4_PGE | X86_CR4_PSE | X86_CR4_PAE); vmcb->cr4 = arch_svm->cpu_shadow_cr4 | SVM_CR4_HOST_MASK; - shadow_update_paging_modes(v); + paging_update_paging_modes(v); vmcb->cr3 = v->arch.hvm_vcpu.hw_cr3; arch_svm->vmcb->exception_intercepts = MONITOR_DEFAULT_EXCEPTION_BITMAP; diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index 858c9ab6e2..450dcb3237 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/hvm/vmx/vmcs.c b/xen/arch/x86/hvm/vmx/vmcs.c index 5f12c0805b..9aa54d1922 100644 --- a/xen/arch/x86/hvm/vmx/vmcs.c +++ b/xen/arch/x86/hvm/vmx/vmcs.c @@ -448,7 +448,7 @@ static void construct_vmcs(struct vcpu *v) vmx_vmcs_exit(v); - shadow_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ + paging_update_paging_modes(v); /* will update HOST & GUEST_CR3 as reqd */ } int vmx_create_vmcs(struct vcpu *v) diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0a4c008b37..d3ba86b7d0 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -35,12 +35,13 @@ #include #include #include +#include +#include #include #include #include #include #include -#include #include #include #include @@ -484,9 +485,6 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = c->cr3; } @@ -556,7 +554,7 @@ int vmx_vmcs_restore(struct vcpu *v, struct hvm_hw_cpu *c) vmx_vmcs_exit(v); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1126,7 +1124,7 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs) } #endif - result = shadow_fault(va, regs); + result = paging_fault(va, regs); TRACE_VMEXIT(2, result); #if 0 @@ -1277,7 +1275,7 @@ static void vmx_do_invlpg(unsigned long va) * We do the safest things first, then try to update the shadow * copying from guest */ - shadow_invlpg(v, va); + paging_invlpg(v, va); } @@ -1691,9 +1689,6 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = c->cr3; } @@ -1753,7 +1748,7 @@ static int vmx_world_restore(struct vcpu *v, struct vmx_assist_context *c) __vmwrite(GUEST_LDTR_BASE, c->ldtr_base); __vmwrite(GUEST_LDTR_AR_BYTES, c->ldtr_arbytes.bytes); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); return 0; bad_cr3: @@ -1906,14 +1901,11 @@ static int vmx_set_cr0(unsigned long value) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - shadow_update_paging_modes(v); + paging_update_paging_modes(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); - /* - * arch->shadow_table should hold the next CR3 for shadow - */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); } @@ -1981,7 +1973,7 @@ static int vmx_set_cr0(unsigned long value) vm_entry_value &= ~VM_ENTRY_IA32E_MODE; __vmwrite(VM_ENTRY_CONTROLS, vm_entry_value); } - shadow_update_paging_modes(v); + paging_update_paging_modes(v); } return 1; @@ -2070,7 +2062,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) mfn = get_mfn_from_gpfn(value >> PAGE_SHIFT); if (mfn != pagetable_get_pfn(v->arch.guest_table)) goto bad_cr3; - shadow_update_cr3(v); + paging_update_cr3(v); } else { /* * If different, make a shadow. Check if the PDBR is valid @@ -2084,9 +2076,6 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) v->arch.guest_table = pagetable_from_pfn(mfn); if (old_base_mfn) put_page(mfn_to_page(old_base_mfn)); - /* - * arch.shadow_table should now hold the next CR3 for shadow - */ v->arch.hvm_vmx.cpu_cr3 = value; update_cr3(v); HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx", value); @@ -2120,9 +2109,6 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) HVM_DBG_LOG(DBG_LEVEL_VMMU, "New arch.guest_table = %lx", (unsigned long) (mfn << PAGE_SHIFT)); - /* - * arch->shadow_table should hold the next CR3 for shadow - */ HVM_DBG_LOG(DBG_LEVEL_VMMU, "Update CR3 value = %lx, mfn = %lx", v->arch.hvm_vmx.cpu_cr3, mfn); @@ -2148,7 +2134,7 @@ static int mov_to_cr(int gp, int cr, struct cpu_user_regs *regs) * all TLB entries except global entries. */ if ( (old_cr ^ value) & (X86_CR4_PSE | X86_CR4_PGE | X86_CR4_PAE) ) - shadow_update_paging_modes(v); + paging_update_paging_modes(v); break; case 8: diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index f23638cdb9..2ef442f546 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -99,6 +99,7 @@ #include #include #include +#include #include #include #include @@ -385,9 +386,9 @@ void update_cr3(struct vcpu *v) { unsigned long cr3_mfn=0; - if ( shadow_mode_enabled(v->domain) ) + if ( paging_mode_enabled(v->domain) ) { - shadow_update_cr3(v); + paging_update_cr3(v); return; } @@ -615,7 +616,7 @@ get_page_from_l1e( * qemu-dm helper process in dom0 to map the domain's memory without * messing up the count of "real" writable mappings.) */ okay = (((l1e_get_flags(l1e) & _PAGE_RW) && - !(unlikely(shadow_mode_external(d) && (d != current->domain)))) + !(unlikely(paging_mode_external(d) && (d != current->domain)))) ? get_page_and_type(page, d, PGT_writable_page) : get_page(page, d)); if ( !okay ) @@ -804,9 +805,9 @@ void put_page_from_l1e(l1_pgentry_t l1e, struct domain *d) } /* Remember we didn't take a type-count of foreign writable mappings - * to shadow external domains */ + * to paging-external domains */ if ( (l1e_get_flags(l1e) & _PAGE_RW) && - !(unlikely((e != d) && shadow_mode_external(e))) ) + !(unlikely((e != d) && paging_mode_external(e))) ) { put_page_and_type(page); } @@ -1259,20 +1260,13 @@ static inline int update_intpte(intpte_t *p, { int rv = 1; #ifndef PTE_UPDATE_WITH_CMPXCHG - if ( unlikely(shadow_mode_enabled(v->domain)) ) - rv = shadow_write_guest_entry(v, p, new, _mfn(mfn)); - else - rv = (!__copy_to_user(p, &new, sizeof(new))); + rv = paging_write_guest_entry(v, p, new, _mfn(mfn)); #else { intpte_t t = old; for ( ; ; ) { - if ( unlikely(shadow_mode_enabled(v->domain)) ) - rv = shadow_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); - else - rv = (!cmpxchg_user(p, t, new)); - + rv = paging_cmpxchg_guest_entry(v, p, &t, new, _mfn(mfn)); if ( unlikely(rv == 0) ) { MEM_LOG("Failed to update %" PRIpte " -> %" PRIpte @@ -1310,7 +1304,7 @@ static int mod_l1_entry(l1_pgentry_t *pl1e, l1_pgentry_t nl1e, if ( unlikely(__copy_from_user(&ol1e, pl1e, sizeof(ol1e)) != 0) ) return 0; - if ( unlikely(shadow_mode_refcounts(d)) ) + if ( unlikely(paging_mode_refcounts(d)) ) return UPDATE_ENTRY(l1, pl1e, ol1e, nl1e, gl1mfn, current); if ( l1e_get_flags(nl1e) & _PAGE_PRESENT ) @@ -1572,7 +1566,7 @@ void free_page_type(struct page_info *page, unsigned long type) */ queue_deferred_ops(owner, DOP_FLUSH_ALL_TLBS); - if ( unlikely(shadow_mode_enabled(owner)) ) + if ( unlikely(paging_mode_enabled(owner)) ) { /* A page table is dirtied when its type count becomes zero. */ mark_dirty(owner, page_to_mfn(page)); @@ -1771,7 +1765,7 @@ int new_guest_cr3(unsigned long mfn) #ifdef CONFIG_COMPAT if ( IS_COMPAT(d) ) { - okay = shadow_mode_refcounts(d) + okay = paging_mode_refcounts(d) ? 0 /* Old code was broken, but what should it be? */ : mod_l4_entry(__va(pagetable_get_paddr(v->arch.guest_table)), l4e_from_pfn(mfn, (_PAGE_PRESENT|_PAGE_RW| @@ -1788,7 +1782,7 @@ int new_guest_cr3(unsigned long mfn) return 1; } #endif - okay = shadow_mode_refcounts(d) + okay = paging_mode_refcounts(d) ? get_page_from_pagenr(mfn, d) : get_page_and_type_from_pagenr(mfn, PGT_root_page_table, d); if ( unlikely(!okay) ) @@ -1808,7 +1802,7 @@ int new_guest_cr3(unsigned long mfn) if ( likely(old_base_mfn != 0) ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(old_base_mfn)); else put_page_and_type(mfn_to_page(old_base_mfn)); @@ -1861,7 +1855,7 @@ static int set_foreigndom(domid_t domid) d->domain_id); okay = 0; } - else if ( unlikely(shadow_mode_translate(d)) ) + else if ( unlikely(paging_mode_translate(d)) ) { MEM_LOG("Cannot mix foreign mappings with translated domains"); okay = 0; @@ -2007,7 +2001,7 @@ int do_mmuext_op( if ( (op.cmd - MMUEXT_PIN_L1_TABLE) > (CONFIG_PAGING_LEVELS - 1) ) break; - if ( shadow_mode_refcounts(FOREIGNDOM) ) + if ( paging_mode_refcounts(FOREIGNDOM) ) break; okay = get_page_and_type_from_pagenr(mfn, type, FOREIGNDOM); @@ -2032,7 +2026,7 @@ int do_mmuext_op( break; case MMUEXT_UNPIN_TABLE: - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) break; if ( unlikely(!(okay = get_page_from_pagenr(mfn, d))) ) @@ -2070,7 +2064,7 @@ int do_mmuext_op( } if (likely(mfn != 0)) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) okay = get_page_from_pagenr(mfn, d); else okay = get_page_and_type_from_pagenr( @@ -2087,7 +2081,7 @@ int do_mmuext_op( v->arch.guest_table_user = pagetable_from_pfn(mfn); if ( old_mfn != 0 ) { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) put_page(mfn_to_page(old_mfn)); else put_page_and_type(mfn_to_page(old_mfn)); @@ -2101,8 +2095,8 @@ int do_mmuext_op( break; case MMUEXT_INVLPG_LOCAL: - if ( !shadow_mode_enabled(d) - || shadow_invlpg(v, op.arg1.linear_addr) != 0 ) + if ( !paging_mode_enabled(d) + || paging_invlpg(v, op.arg1.linear_addr) != 0 ) local_flush_tlb_one(op.arg1.linear_addr); break; @@ -2149,7 +2143,7 @@ int do_mmuext_op( unsigned long ptr = op.arg1.linear_addr; unsigned long ents = op.arg2.nr_ents; - if ( shadow_mode_external(d) ) + if ( paging_mode_external(d) ) { MEM_LOG("ignoring SET_LDT hypercall from external " "domain %u", d->domain_id); @@ -2298,9 +2292,9 @@ int do_mmu_update( case PGT_l3_page_table: case PGT_l4_page_table: { - if ( shadow_mode_refcounts(d) ) + if ( paging_mode_refcounts(d) ) { - MEM_LOG("mmu update on shadow-refcounted domain!"); + MEM_LOG("mmu update on auto-refcounted domain!"); break; } @@ -2351,13 +2345,7 @@ int do_mmu_update( if ( unlikely(!get_page_type(page, PGT_writable_page)) ) break; - if ( unlikely(shadow_mode_enabled(d)) ) - okay = shadow_write_guest_entry(v, va, req.val, _mfn(mfn)); - else - { - *(intpte_t *)va = req.val; - okay = 1; - } + okay = paging_write_guest_entry(v, va, req.val, _mfn(mfn)); put_page_type(page); } @@ -2380,9 +2368,9 @@ int do_mmu_update( break; } - if ( unlikely(shadow_mode_translate(FOREIGNDOM)) ) + if ( unlikely(paging_mode_translate(FOREIGNDOM)) ) { - MEM_LOG("Mach-phys update on shadow-translate guest"); + MEM_LOG("Mach-phys update on auto-translate guest"); break; } @@ -2472,7 +2460,7 @@ static int create_grant_pte_mapping( goto failed; } - if ( !shadow_mode_refcounts(d) ) + if ( !paging_mode_refcounts(d) ) put_page_from_l1e(ol1e, d); put_page_type(page); @@ -2578,7 +2566,7 @@ static int create_grant_va_mapping( if ( !okay ) return GNTST_general_error; - if ( !shadow_mode_refcounts(d) ) + if ( !paging_mode_refcounts(d) ) put_page_from_l1e(ol1e, d); return GNTST_okay; @@ -2704,7 +2692,7 @@ int do_update_va_mapping(unsigned long va, u64 val64, perfc_incrc(calls_to_update_va); - if ( unlikely(!__addr_ok(va) && !shadow_mode_external(d)) ) + if ( unlikely(!__addr_ok(va) && !paging_mode_external(d)) ) return -EINVAL; LOCK_BIGLOCK(d); @@ -2744,8 +2732,8 @@ int do_update_va_mapping(unsigned long va, u64 val64, switch ( (bmap_ptr = flags & ~UVMF_FLUSHTYPE_MASK) ) { case UVMF_LOCAL: - if ( !shadow_mode_enabled(d) - || (shadow_invlpg(current, va) != 0) ) + if ( !paging_mode_enabled(d) + || (paging_invlpg(current, va) != 0) ) local_flush_tlb_one(va); break; case UVMF_ALL: @@ -2980,7 +2968,7 @@ long arch_memory_op(int op, XEN_GUEST_HANDLE(void) arg) break; } - if ( !shadow_mode_translate(d) || (mfn == 0) ) + if ( !paging_mode_translate(d) || (mfn == 0) ) { put_domain(d); return -EINVAL; @@ -3235,17 +3223,12 @@ static int ptwr_emulated_update( if ( do_cmpxchg ) { int okay; + intpte_t t = old; ol1e = l1e_from_intpte(old); - if ( shadow_mode_enabled(d) ) - { - intpte_t t = old; - okay = shadow_cmpxchg_guest_entry(v, (intpte_t *) pl1e, - &t, val, _mfn(mfn)); - okay = (okay && t == old); - } - else - okay = (cmpxchg((intpte_t *)pl1e, old, val) == old); + okay = paging_cmpxchg_guest_entry(v, (intpte_t *) pl1e, + &t, val, _mfn(mfn)); + okay = (okay && t == old); if ( !okay ) { diff --git a/xen/arch/x86/mm/Makefile b/xen/arch/x86/mm/Makefile index 5043fd9501..a58211d91a 100644 --- a/xen/arch/x86/mm/Makefile +++ b/xen/arch/x86/mm/Makefile @@ -1 +1,4 @@ subdir-y += shadow + +obj-y += paging.o +obj-y += p2m.o diff --git a/xen/arch/x86/mm/p2m.c b/xen/arch/x86/mm/p2m.c new file mode 100644 index 0000000000..cc42ed8c6a --- /dev/null +++ b/xen/arch/x86/mm/p2m.c @@ -0,0 +1,699 @@ +/****************************************************************************** + * arch/x86/mm/p2m.c + * + * physical-to-machine mappings for automatically-translated domains. + * + * Parts of this code are Copyright (c) 2007 by Advanced Micro Devices. + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* Debugging and auditing of the P2M code? */ +#define P2M_AUDIT 0 +#define P2M_DEBUGGING 1 + +/* The P2M lock. This protects all updates to the p2m table. + * Updates are expected to be safe against concurrent reads, + * which do *not* require the lock */ + +#define p2m_lock_init(_d) \ + do { \ + spin_lock_init(&(_d)->arch.p2m.lock); \ + (_d)->arch.p2m.locker = -1; \ + (_d)->arch.p2m.locker_function = "nobody"; \ + } while (0) + +#define p2m_lock(_d) \ + do { \ + if ( unlikely((_d)->arch.p2m.locker == current->processor) )\ + { \ + printk("Error: p2m lock held by %s\n", \ + (_d)->arch.p2m.locker_function); \ + BUG(); \ + } \ + spin_lock(&(_d)->arch.p2m.lock); \ + ASSERT((_d)->arch.p2m.locker == -1); \ + (_d)->arch.p2m.locker = current->processor; \ + (_d)->arch.p2m.locker_function = __func__; \ + } while (0) + +#define p2m_unlock(_d) \ + do { \ + ASSERT((_d)->arch.p2m.locker == current->processor); \ + (_d)->arch.p2m.locker = -1; \ + (_d)->arch.p2m.locker_function = "nobody"; \ + spin_unlock(&(_d)->arch.p2m.lock); \ + } while (0) + + + +/* Printouts */ +#define P2M_PRINTK(_f, _a...) \ + debugtrace_printk("p2m: %s(): " _f, __func__, ##_a) +#define P2M_ERROR(_f, _a...) \ + printk("pg error: %s(): " _f, __func__, ##_a) +#if P2M_DEBUGGING +#define P2M_DEBUG(_f, _a...) \ + debugtrace_printk("p2mdebug: %s(): " _f, __func__, ##_a) +#else +#define P2M_DEBUG(_f, _a...) do { (void)(_f); } while(0) +#endif + + +/* Override macros from asm/page.h to make them work with mfn_t */ +#undef mfn_to_page +#define mfn_to_page(_m) (frame_table + mfn_x(_m)) +#undef mfn_valid +#define mfn_valid(_mfn) (mfn_x(_mfn) < max_page) +#undef page_to_mfn +#define page_to_mfn(_pg) (_mfn((_pg) - frame_table)) + + + +// Find the next level's P2M entry, checking for out-of-range gfn's... +// Returns NULL on error. +// +static l1_pgentry_t * +p2m_find_entry(void *table, unsigned long *gfn_remainder, + unsigned long gfn, u32 shift, u32 max) +{ + u32 index; + + index = *gfn_remainder >> shift; + if ( index >= max ) + { + P2M_DEBUG("gfn=0x%lx out of range " + "(gfn_remainder=0x%lx shift=%d index=0x%x max=0x%x)\n", + gfn, *gfn_remainder, shift, index, max); + return NULL; + } + *gfn_remainder &= (1 << shift) - 1; + return (l1_pgentry_t *)table + index; +} + +// Walk one level of the P2M table, allocating a new table if required. +// Returns 0 on error. +// +static int +p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table, + unsigned long *gfn_remainder, unsigned long gfn, u32 shift, + u32 max, unsigned long type) +{ + l1_pgentry_t *p2m_entry; + l1_pgentry_t new_entry; + void *next; + ASSERT(d->arch.p2m.alloc_page); + + if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, + shift, max)) ) + return 0; + + if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) ) + { + struct page_info *pg = d->arch.p2m.alloc_page(d); + if ( pg == NULL ) + return 0; + list_add_tail(&pg->list, &d->arch.p2m.pages); + pg->u.inuse.type_info = type | 1 | PGT_validated; + pg->count_info = 1; + + new_entry = l1e_from_pfn(mfn_x(page_to_mfn(pg)), + __PAGE_HYPERVISOR|_PAGE_USER); + + switch ( type ) { + case PGT_l3_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 4); + break; + case PGT_l2_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 3); + break; + case PGT_l1_page_table: + paging_write_p2m_entry(d, gfn, p2m_entry, new_entry, 2); + break; + default: + BUG(); + break; + } + } + *table_mfn = _mfn(l1e_get_pfn(*p2m_entry)); + next = map_domain_page(mfn_x(*table_mfn)); + unmap_domain_page(*table); + *table = next; + + return 1; +} + +// Returns 0 on error (out of memory) +static int +set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) +{ + // XXX -- this might be able to be faster iff current->domain == d + mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); + void *table =map_domain_page(mfn_x(table_mfn)); + unsigned long gfn_remainder = gfn; + l1_pgentry_t *p2m_entry; + l1_pgentry_t entry_content; + int rv=0; + +#if CONFIG_PAGING_LEVELS >= 4 + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L4_PAGETABLE_SHIFT - PAGE_SHIFT, + L4_PAGETABLE_ENTRIES, PGT_l3_page_table) ) + goto out; +#endif +#if CONFIG_PAGING_LEVELS >= 3 + // When using PAE Xen, we only allow 33 bits of pseudo-physical + // address in translated guests (i.e. 8 GBytes). This restriction + // comes from wanting to map the P2M table into the 16MB RO_MPT hole + // in Xen's address space for translated PV guests. + // + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L3_PAGETABLE_SHIFT - PAGE_SHIFT, + (CONFIG_PAGING_LEVELS == 3 + ? 8 + : L3_PAGETABLE_ENTRIES), + PGT_l2_page_table) ) + goto out; +#endif + if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, + L2_PAGETABLE_SHIFT - PAGE_SHIFT, + L2_PAGETABLE_ENTRIES, PGT_l1_page_table) ) + goto out; + + p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn, + 0, L1_PAGETABLE_ENTRIES); + ASSERT(p2m_entry); + + /* Track the highest gfn for which we have ever had a valid mapping */ + if ( mfn_valid(mfn) && (gfn > d->arch.p2m.max_mapped_pfn) ) + d->arch.p2m.max_mapped_pfn = gfn; + + if ( mfn_valid(mfn) ) + entry_content = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); + else + entry_content = l1e_empty(); + + /* level 1 entry */ + paging_write_p2m_entry(d, gfn, p2m_entry, entry_content, 1); + + /* Success */ + rv = 1; + + out: + unmap_domain_page(table); + return rv; +} + + +/* Init the datastructures for later use by the p2m code */ +void p2m_init(struct domain *d) +{ + p2m_lock_init(d); + INIT_LIST_HEAD(&d->arch.p2m.pages); +} + + +// Allocate a new p2m table for a domain. +// +// The structure of the p2m table is that of a pagetable for xen (i.e. it is +// controlled by CONFIG_PAGING_LEVELS). +// +// The alloc_page and free_page functions will be used to get memory to +// build the p2m, and to release it again at the end of day. +// +// Returns 0 for success or -errno. +// +int p2m_alloc_table(struct domain *d, + struct page_info * (*alloc_page)(struct domain *d), + void (*free_page)(struct domain *d, struct page_info *pg)) + +{ + mfn_t mfn; + struct list_head *entry; + struct page_info *page, *p2m_top; + unsigned int page_count = 0; + unsigned long gfn; + + p2m_lock(d); + + if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) + { + P2M_ERROR("p2m already allocated for this domain\n"); + p2m_unlock(d); + return -EINVAL; + } + + P2M_PRINTK("allocating p2m table\n"); + + d->arch.p2m.alloc_page = alloc_page; + d->arch.p2m.free_page = free_page; + + p2m_top = d->arch.p2m.alloc_page(d); + if ( p2m_top == NULL ) + { + p2m_unlock(d); + return -ENOMEM; + } +list_add_tail(&p2m_top->list, &d->arch.p2m.pages); + + p2m_top->count_info = 1; + p2m_top->u.inuse.type_info = +#if CONFIG_PAGING_LEVELS == 4 + PGT_l4_page_table +#elif CONFIG_PAGING_LEVELS == 3 + PGT_l3_page_table +#elif CONFIG_PAGING_LEVELS == 2 + PGT_l2_page_table +#endif + | 1 | PGT_validated; + + d->arch.phys_table = pagetable_from_mfn(page_to_mfn(p2m_top)); + + P2M_PRINTK("populating p2m table\n"); + + /* Initialise physmap tables for slot zero. Other code assumes this. */ + gfn = 0; +mfn = _mfn(INVALID_MFN); + if ( !set_p2m_entry(d, gfn, mfn) ) + goto error; + + for ( entry = d->page_list.next; + entry != &d->page_list; + entry = entry->next ) + { + page = list_entry(entry, struct page_info, list); + mfn = page_to_mfn(page); + gfn = get_gpfn_from_mfn(mfn_x(mfn)); + page_count++; + if ( +#ifdef __x86_64__ + (gfn != 0x5555555555555555L) +#else + (gfn != 0x55555555L) +#endif + && gfn != INVALID_M2P_ENTRY + && !set_p2m_entry(d, gfn, mfn) ) + goto error; + } + + P2M_PRINTK("p2m table initialised (%u pages)\n", page_count); + p2m_unlock(d); + return 0; + + error: + P2M_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%" + PRI_mfn "\n", gfn, mfn_x(mfn)); + p2m_unlock(d); + return -ENOMEM; +} + +void p2m_teardown(struct domain *d) +/* Return all the p2m pages to Xen. + * We know we don't have any extra mappings to these pages */ +{ + struct list_head *entry, *n; + struct page_info *pg; + + p2m_lock(d); + d->arch.phys_table = pagetable_null(); + + list_for_each_safe(entry, n, &d->arch.p2m.pages) + { + pg = list_entry(entry, struct page_info, list); + list_del(entry); + d->arch.p2m.free_page(d, pg); + } + p2m_unlock(d); +} + +mfn_t +gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn) +/* Read another domain's p2m entries */ +{ + mfn_t mfn; + paddr_t addr = ((paddr_t)gpfn) << PAGE_SHIFT; + l2_pgentry_t *l2e; + l1_pgentry_t *l1e; + + ASSERT(paging_mode_translate(d)); + mfn = pagetable_get_mfn(d->arch.phys_table); + + + if ( gpfn > d->arch.p2m.max_mapped_pfn ) + /* This pfn is higher than the highest the p2m map currently holds */ + return _mfn(INVALID_MFN); + +#if CONFIG_PAGING_LEVELS >= 4 + { + l4_pgentry_t *l4e = map_domain_page(mfn_x(mfn)); + l4e += l4_table_offset(addr); + if ( (l4e_get_flags(*l4e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l4e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l4e_get_pfn(*l4e)); + unmap_domain_page(l4e); + } +#endif +#if CONFIG_PAGING_LEVELS >= 3 + { + l3_pgentry_t *l3e = map_domain_page(mfn_x(mfn)); +#if CONFIG_PAGING_LEVELS == 3 + /* On PAE hosts the p2m has eight l3 entries, not four (see + * shadow_set_p2m_entry()) so we can't use l3_table_offset. + * Instead, just count the number of l3es from zero. It's safe + * to do this because we already checked that the gfn is within + * the bounds of the p2m. */ + l3e += (addr >> L3_PAGETABLE_SHIFT); +#else + l3e += l3_table_offset(addr); +#endif + if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l3e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l3e_get_pfn(*l3e)); + unmap_domain_page(l3e); + } +#endif + + l2e = map_domain_page(mfn_x(mfn)); + l2e += l2_table_offset(addr); + if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l2e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l2e_get_pfn(*l2e)); + unmap_domain_page(l2e); + + l1e = map_domain_page(mfn_x(mfn)); + l1e += l1_table_offset(addr); + if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 ) + { + unmap_domain_page(l1e); + return _mfn(INVALID_MFN); + } + mfn = _mfn(l1e_get_pfn(*l1e)); + unmap_domain_page(l1e); + + return mfn; +} + +#if P2M_AUDIT +static void audit_p2m(struct domain *d) +{ + struct list_head *entry; + struct page_info *page; + struct domain *od; + unsigned long mfn, gfn, m2pfn, lp2mfn = 0; + mfn_t p2mfn; + unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0; + int test_linear; + + if ( !paging_mode_translate(d) ) + return; + + //P2M_PRINTK("p2m audit starts\n"); + + test_linear = ( (d == current->domain) + && !pagetable_is_null(current->arch.monitor_table) ); + if ( test_linear ) + local_flush_tlb(); + + /* Audit part one: walk the domain's page allocation list, checking + * the m2p entries. */ + for ( entry = d->page_list.next; + entry != &d->page_list; + entry = entry->next ) + { + page = list_entry(entry, struct page_info, list); + mfn = mfn_x(page_to_mfn(page)); + + // P2M_PRINTK("auditing guest page, mfn=%#lx\n", mfn); + + od = page_get_owner(page); + + if ( od != d ) + { + P2M_PRINTK("wrong owner %#lx -> %p(%u) != %p(%u)\n", + mfn, od, (od?od->domain_id:-1), d, d->domain_id); + continue; + } + + gfn = get_gpfn_from_mfn(mfn); + if ( gfn == INVALID_M2P_ENTRY ) + { + orphans_i++; + //P2M_PRINTK("orphaned guest page: mfn=%#lx has invalid gfn\n", + // mfn); + continue; + } + + if ( gfn == 0x55555555 ) + { + orphans_d++; + //P2M_PRINTK("orphaned guest page: mfn=%#lx has debug gfn\n", + // mfn); + continue; + } + + p2mfn = gfn_to_mfn_foreign(d, gfn); + if ( mfn_x(p2mfn) != mfn ) + { + mpbad++; + P2M_PRINTK("map mismatch mfn %#lx -> gfn %#lx -> mfn %#lx" + " (-> gfn %#lx)\n", + mfn, gfn, mfn_x(p2mfn), + (mfn_valid(p2mfn) + ? get_gpfn_from_mfn(mfn_x(p2mfn)) + : -1u)); + /* This m2p entry is stale: the domain has another frame in + * this physical slot. No great disaster, but for neatness, + * blow away the m2p entry. */ + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); + } + + if ( test_linear && (gfn <= d->arch.p2m.max_mapped_pfn) ) + { + lp2mfn = mfn_x(gfn_to_mfn_current(gfn)); + if ( lp2mfn != mfn_x(p2mfn) ) + { + P2M_PRINTK("linear mismatch gfn %#lx -> mfn %#lx " + "(!= mfn %#lx)\n", gfn, lp2mfn, mfn_x(p2mfn)); + } + } + + // P2M_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx, lp2mfn=%#lx\n", + // mfn, gfn, p2mfn, lp2mfn); + } + + /* Audit part two: walk the domain's p2m table, checking the entries. */ + if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) + { + l2_pgentry_t *l2e; + l1_pgentry_t *l1e; + int i1, i2; + +#if CONFIG_PAGING_LEVELS == 4 + l4_pgentry_t *l4e; + l3_pgentry_t *l3e; + int i3, i4; + l4e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#elif CONFIG_PAGING_LEVELS == 3 + l3_pgentry_t *l3e; + int i3; + l3e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#else /* CONFIG_PAGING_LEVELS == 2 */ + l2e = map_domain_page(mfn_x(pagetable_get_mfn(d->arch.phys_table))); +#endif + + gfn = 0; +#if CONFIG_PAGING_LEVELS >= 3 +#if CONFIG_PAGING_LEVELS >= 4 + for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ ) + { + if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l3e = map_domain_page(mfn_x(_mfn(l4e_get_pfn(l4e[i4])))); +#endif /* now at levels 3 or 4... */ + for ( i3 = 0; + i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8); + i3++ ) + { + if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l2e = map_domain_page(mfn_x(_mfn(l3e_get_pfn(l3e[i3])))); +#endif /* all levels... */ + for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) + { + if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) + { + gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); + continue; + } + l1e = map_domain_page(mfn_x(_mfn(l2e_get_pfn(l2e[i2])))); + + for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) + { + if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) ) + continue; + mfn = l1e_get_pfn(l1e[i1]); + ASSERT(mfn_valid(_mfn(mfn))); + m2pfn = get_gpfn_from_mfn(mfn); + if ( m2pfn != gfn ) + { + pmbad++; + P2M_PRINTK("mismatch: gfn %#lx -> mfn %#lx" + " -> gfn %#lx\n", gfn, mfn, m2pfn); + BUG(); + } + } + unmap_domain_page(l1e); + } +#if CONFIG_PAGING_LEVELS >= 3 + unmap_domain_page(l2e); + } +#if CONFIG_PAGING_LEVELS >= 4 + unmap_domain_page(l3e); + } +#endif +#endif + +#if CONFIG_PAGING_LEVELS == 4 + unmap_domain_page(l4e); +#elif CONFIG_PAGING_LEVELS == 3 + unmap_domain_page(l3e); +#else /* CONFIG_PAGING_LEVELS == 2 */ + unmap_domain_page(l2e); +#endif + + } + + //P2M_PRINTK("p2m audit complete\n"); + //if ( orphans_i | orphans_d | mpbad | pmbad ) + // P2M_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n", + // orphans_i + orphans_d, orphans_i, orphans_d, + if ( mpbad | pmbad ) + P2M_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n", + pmbad, mpbad); +} +#else +#define audit_p2m(_d) do { (void)(_d); } while(0) +#endif /* P2M_AUDIT */ + + + +static void +p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn) +{ + if ( !paging_mode_translate(d) ) + return; + P2M_DEBUG("removing gfn=%#lx mfn=%#lx\n", gfn, mfn); + + ASSERT(mfn_x(gfn_to_mfn(d, gfn)) == mfn); + //ASSERT(mfn_to_gfn(d, mfn) == gfn); + + set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); + set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); +} + +void +guest_physmap_remove_page(struct domain *d, unsigned long gfn, + unsigned long mfn) +{ + p2m_lock(d); + audit_p2m(d); + p2m_remove_page(d, gfn, mfn); + audit_p2m(d); + p2m_unlock(d); +} + +void +guest_physmap_add_page(struct domain *d, unsigned long gfn, + unsigned long mfn) +{ + unsigned long ogfn; + mfn_t omfn; + + if ( !paging_mode_translate(d) ) + return; + + p2m_lock(d); + audit_p2m(d); + + P2M_DEBUG("adding gfn=%#lx mfn=%#lx\n", gfn, mfn); + + omfn = gfn_to_mfn(d, gfn); + if ( mfn_valid(omfn) ) + { + set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); + set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY); + } + + ogfn = mfn_to_gfn(d, _mfn(mfn)); + if ( +#ifdef __x86_64__ + (ogfn != 0x5555555555555555L) +#else + (ogfn != 0x55555555L) +#endif + && (ogfn != INVALID_M2P_ENTRY) + && (ogfn != gfn) ) + { + /* This machine frame is already mapped at another physical address */ + P2M_DEBUG("aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", + mfn, ogfn, gfn); + if ( mfn_valid(omfn = gfn_to_mfn(d, ogfn)) ) + { + P2M_DEBUG("old gfn=%#lx -> mfn %#lx\n", + ogfn , mfn_x(omfn)); + if ( mfn_x(omfn) == mfn ) + p2m_remove_page(d, ogfn, mfn); + } + } + + set_p2m_entry(d, gfn, _mfn(mfn)); + set_gpfn_from_mfn(mfn, gfn); + + audit_p2m(d); + p2m_unlock(d); +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/mm/paging.c b/xen/arch/x86/mm/paging.c new file mode 100644 index 0000000000..4605dd5e24 --- /dev/null +++ b/xen/arch/x86/mm/paging.c @@ -0,0 +1,143 @@ +/****************************************************************************** + * arch/x86/paging.c + * + * x86 specific paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Copyright (c) 2007 XenSource Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include + +/* Xen command-line option to enable hardware-assisted paging */ +int opt_hap_enabled = 0; +boolean_param("hap", opt_hap_enabled); + +/* Printouts */ +#define PAGING_PRINTK(_f, _a...) \ + debugtrace_printk("pg: %s(): " _f, __func__, ##_a) +#define PAGING_ERROR(_f, _a...) \ + printk("pg error: %s(): " _f, __func__, ##_a) +#define PAGING_DEBUG(flag, _f, _a...) \ + do { \ + if (PAGING_DEBUG_ ## flag) \ + debugtrace_printk("pgdebug: %s(): " _f, __func__, ##_a); \ + } while (0) + + +/* Domain paging struct initialization. */ +void paging_domain_init(struct domain *d) +{ + p2m_init(d); + shadow_domain_init(d); +} + +/* vcpu paging struct initialization goes here */ +void paging_vcpu_init(struct vcpu *v) +{ + shadow_vcpu_init(v); +} + + +int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE(void) u_domctl) +{ + /* Here, dispatch domctl to the appropriate paging code */ + return shadow_domctl(d, sc, u_domctl); +} + +/* Call when destroying a domain */ +void paging_teardown(struct domain *d) +{ + shadow_teardown(d); + /* Call other modes' teardown code here */ +} + +/* Call once all of the references to the domain have gone away */ +void paging_final_teardown(struct domain *d) +{ + shadow_teardown(d); + /* Call other modes' final teardown code here */ +} + +/* Enable an arbitrary paging-assistance mode. Call once at domain + * creation. */ +int paging_enable(struct domain *d, u32 mode) +{ + if ( mode & PG_SH_enable ) + return shadow_enable(d, mode); + else + /* No other modes supported yet */ + return -EINVAL; +} + +/* Print paging-assistance info to the console */ +void paging_dump_domain_info(struct domain *d) +{ + if ( paging_mode_enabled(d) ) + { + printk(" paging assistance: "); + if ( paging_mode_shadow(d) ) + printk("shadow "); + if ( paging_mode_hap(d) ) + printk("hap "); + if ( paging_mode_refcounts(d) ) + printk("refcounts "); + if ( paging_mode_log_dirty(d) ) + printk("log_dirty "); + if ( paging_mode_translate(d) ) + printk("translate "); + if ( paging_mode_external(d) ) + printk("external "); + printk("\n"); + } +} + +void paging_dump_vcpu_info(struct vcpu *v) +{ + if ( paging_mode_enabled(v->domain) ) + { + printk(" paging assistance: "); + if ( paging_mode_shadow(v->domain) ) + { + if ( v->arch.paging.mode ) + printk("shadowed %u-on-%u, %stranslated\n", + v->arch.paging.mode->guest_levels, + v->arch.paging.mode->shadow.shadow_levels, + paging_vcpu_mode_translate(v) ? "" : "not "); + else + printk("not shadowed\n"); + } + else if ( paging_mode_hap(v->domain) && v->arch.paging.mode ) + printk("hap, %u levels\n", + v->arch.paging.mode->guest_levels); + else + printk("none\n"); + } +} + + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index b00f9d6b25..ff229fa7c5 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -47,12 +47,27 @@ void shadow_domain_init(struct domain *d) int i; shadow_lock_init(d); for ( i = 0; i <= SHADOW_MAX_ORDER; i++ ) - INIT_LIST_HEAD(&d->arch.shadow.freelists[i]); - INIT_LIST_HEAD(&d->arch.shadow.p2m_freelist); - INIT_LIST_HEAD(&d->arch.shadow.p2m_inuse); - INIT_LIST_HEAD(&d->arch.shadow.pinned_shadows); + INIT_LIST_HEAD(&d->arch.paging.shadow.freelists[i]); + INIT_LIST_HEAD(&d->arch.paging.shadow.p2m_freelist); + INIT_LIST_HEAD(&d->arch.paging.shadow.pinned_shadows); } +/* Setup the shadow-specfic parts of a vcpu struct. Note: The most important + * job is to initialize the update_paging_modes() function pointer, which is + * used to initialized the rest of resources. Therefore, it really does not + * matter to have v->arch.paging.mode pointing to any mode, as long as it can + * be compiled. + */ +void shadow_vcpu_init(struct vcpu *v) +{ +#if CONFIG_PAGING_LEVELS == 4 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); +#elif CONFIG_PAGING_LEVELS == 3 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); +#elif CONFIG_PAGING_LEVELS == 2 + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); +#endif +} #if SHADOW_AUDIT int shadow_audit_enable = 0; @@ -265,7 +280,7 @@ hvm_emulate_write(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_write( + return v->arch.paging.mode->shadow.x86_emulate_write( v, addr, &val, bytes, sh_ctxt); } @@ -288,7 +303,7 @@ hvm_emulate_cmpxchg(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_cmpxchg( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg( v, addr, old, new, bytes, sh_ctxt); } @@ -312,7 +327,7 @@ hvm_emulate_cmpxchg8b(enum x86_segment seg, if ( rc ) return rc; - return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b( v, addr, old_lo, old_hi, new_lo, new_hi, sh_ctxt); } @@ -353,7 +368,7 @@ pv_emulate_write(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_write( + return v->arch.paging.mode->shadow.x86_emulate_write( v, offset, &val, bytes, sh_ctxt); } @@ -368,7 +383,7 @@ pv_emulate_cmpxchg(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_cmpxchg( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg( v, offset, old, new, bytes, sh_ctxt); } @@ -384,7 +399,7 @@ pv_emulate_cmpxchg8b(enum x86_segment seg, struct sh_emulate_ctxt *sh_ctxt = container_of(ctxt, struct sh_emulate_ctxt, ctxt); struct vcpu *v = current; - return v->arch.shadow.mode->x86_emulate_cmpxchg8b( + return v->arch.paging.mode->shadow.x86_emulate_cmpxchg8b( v, offset, old_lo, old_hi, new_lo, new_hi, sh_ctxt); } @@ -721,7 +736,7 @@ static inline int chunk_is_available(struct domain *d, int order) int i; for ( i = order; i <= SHADOW_MAX_ORDER; i++ ) - if ( !list_empty(&d->arch.shadow.freelists[i]) ) + if ( !list_empty(&d->arch.paging.shadow.freelists[i]) ) return 1; return 0; } @@ -783,7 +798,7 @@ void shadow_prealloc(struct domain *d, unsigned int order) /* Stage one: walk the list of pinned pages, unpinning them */ perfc_incrc(shadow_prealloc_1); - list_for_each_backwards_safe(l, t, &d->arch.shadow.pinned_shadows) + list_for_each_backwards_safe(l, t, &d->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); smfn = shadow_page_to_mfn(sp); @@ -823,9 +838,9 @@ void shadow_prealloc(struct domain *d, unsigned int order) SHADOW_PRINTK("Can't pre-allocate %i shadow pages!\n" " shadow pages total = %u, free = %u, p2m=%u\n", 1 << order, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); BUG(); } @@ -840,7 +855,7 @@ static void shadow_blow_tables(struct domain *d) int i; /* Pass one: unpin all pinned pages */ - list_for_each_backwards_safe(l,t, &d->arch.shadow.pinned_shadows) + list_for_each_backwards_safe(l,t, &d->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); smfn = shadow_page_to_mfn(sp); @@ -905,9 +920,9 @@ mfn_t shadow_alloc(struct domain *d, /* Find smallest order which can satisfy the request. */ for ( i = order; i <= SHADOW_MAX_ORDER; i++ ) - if ( !list_empty(&d->arch.shadow.freelists[i]) ) + if ( !list_empty(&d->arch.paging.shadow.freelists[i]) ) { - sp = list_entry(d->arch.shadow.freelists[i].next, + sp = list_entry(d->arch.paging.shadow.freelists[i].next, struct shadow_page_info, list); list_del(&sp->list); @@ -916,10 +931,10 @@ mfn_t shadow_alloc(struct domain *d, { i--; sp->order = i; - list_add_tail(&sp->list, &d->arch.shadow.freelists[i]); + list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[i]); sp += 1 << i; } - d->arch.shadow.free_pages -= 1 << order; + d->arch.paging.shadow.free_pages -= 1 << order; /* Init page info fields and clear the pages */ for ( i = 0; i < 1<arch.shadow.free_pages += 1 << order; + d->arch.paging.shadow.free_pages += 1 << order; for ( i = 0; i < 1<arch.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i ) - v->arch.shadow.last_writeable_pte_smfn = 0; + if ( v->arch.paging.shadow.last_writeable_pte_smfn == mfn_x(smfn) + i ) + v->arch.paging.shadow.last_writeable_pte_smfn = 0; } #endif /* Strip out the type: this is now a free shadow page */ @@ -1019,7 +1034,7 @@ void shadow_free(struct domain *d, mfn_t smfn) } sp->order = order; - list_add_tail(&sp->list, &d->arch.shadow.freelists[order]); + list_add_tail(&sp->list, &d->arch.paging.shadow.freelists[order]); } /* Divert some memory from the pool to be used by the p2m mapping. @@ -1033,19 +1048,19 @@ void shadow_free(struct domain *d, mfn_t smfn) * returns non-zero on success. */ static int -shadow_alloc_p2m_pages(struct domain *d) +sh_alloc_p2m_pages(struct domain *d) { struct page_info *pg; u32 i; ASSERT(shadow_locked_by_me(d)); - if ( d->arch.shadow.total_pages + if ( d->arch.paging.shadow.total_pages < (shadow_min_acceptable_pages(d) + (1<arch.shadow.p2m_pages += (1<arch.shadow.total_pages -= (1<arch.paging.shadow.p2m_pages += (1<arch.paging.shadow.total_pages -= (1<arch.shadow.p2m_freelist); + pg->count_info = 1; + list_add_tail(&pg[i].list, &d->arch.paging.shadow.p2m_freelist); } return 1; } // Returns 0 if no memory is available... -mfn_t +struct page_info * shadow_alloc_p2m_page(struct domain *d) { struct list_head *entry; struct page_info *pg; mfn_t mfn; void *p; + + shadow_lock(d); - if ( list_empty(&d->arch.shadow.p2m_freelist) && - !shadow_alloc_p2m_pages(d) ) - return _mfn(0); - entry = d->arch.shadow.p2m_freelist.next; + if ( list_empty(&d->arch.paging.shadow.p2m_freelist) && + !sh_alloc_p2m_pages(d) ) + { + shadow_unlock(d); + return NULL; + } + entry = d->arch.paging.shadow.p2m_freelist.next; list_del(entry); - list_add_tail(entry, &d->arch.shadow.p2m_inuse); + + shadow_unlock(d); + pg = list_entry(entry, struct page_info, list); - pg->count_info = 1; mfn = page_to_mfn(pg); p = sh_map_domain_page(mfn); clear_page(p); sh_unmap_domain_page(p); - return mfn; + return pg; +} + +void +shadow_free_p2m_page(struct domain *d, struct page_info *pg) +{ + ASSERT(page_get_owner(pg) == d); + /* Should have just the one ref we gave it in alloc_p2m_page() */ + if ( (pg->count_info & PGC_count_mask) != 1 ) + { + SHADOW_ERROR("Odd p2m page count c=%#x t=%"PRtype_info"\n", + pg->count_info, pg->u.inuse.type_info); + } + /* Free should not decrement domain's total allocation, since + * these pages were allocated without an owner. */ + page_set_owner(pg, NULL); + free_domheap_pages(pg, 0); + d->arch.paging.shadow.p2m_pages--; + perfc_decr(shadow_alloc_count); } #if CONFIG_PAGING_LEVELS == 3 @@ -1130,344 +1170,6 @@ static void p2m_install_entry_in_monitors(struct domain *d, } #endif -// Find the next level's P2M entry, checking for out-of-range gfn's... -// Returns NULL on error. -// -static l1_pgentry_t * -p2m_find_entry(void *table, unsigned long *gfn_remainder, - unsigned long gfn, u32 shift, u32 max) -{ - u32 index; - - index = *gfn_remainder >> shift; - if ( index >= max ) - { - SHADOW_DEBUG(P2M, "gfn=0x%lx out of range " - "(gfn_remainder=0x%lx shift=%d index=0x%x max=0x%x)\n", - gfn, *gfn_remainder, shift, index, max); - return NULL; - } - *gfn_remainder &= (1 << shift) - 1; - return (l1_pgentry_t *)table + index; -} - -// Walk one level of the P2M table, allocating a new table if required. -// Returns 0 on error. -// -static int -p2m_next_level(struct domain *d, mfn_t *table_mfn, void **table, - unsigned long *gfn_remainder, unsigned long gfn, u32 shift, - u32 max, unsigned long type) -{ - l1_pgentry_t *p2m_entry; - void *next; - - if ( !(p2m_entry = p2m_find_entry(*table, gfn_remainder, gfn, - shift, max)) ) - return 0; - - if ( !(l1e_get_flags(*p2m_entry) & _PAGE_PRESENT) ) - { - mfn_t mfn = shadow_alloc_p2m_page(d); - if ( mfn_x(mfn) == 0 ) - return 0; - *p2m_entry = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); - mfn_to_page(mfn)->u.inuse.type_info = type | 1 | PGT_validated; - mfn_to_page(mfn)->count_info = 1; -#if CONFIG_PAGING_LEVELS == 3 - if (type == PGT_l2_page_table) - { - struct vcpu *v; - /* We have written to the p2m l3: need to sync the per-vcpu - * copies of it in the monitor tables */ - p2m_install_entry_in_monitors(d, (l3_pgentry_t *)p2m_entry); - /* Also, any vcpus running on shadows of the p2m need to - * reload their CR3s so the change propagates to the shadow */ - ASSERT(shadow_locked_by_me(d)); - for_each_vcpu(d, v) - { - if ( pagetable_get_pfn(v->arch.guest_table) - == pagetable_get_pfn(d->arch.phys_table) - && v->arch.shadow.mode != NULL ) - v->arch.shadow.mode->update_cr3(v, 0); - } - } -#endif - /* The P2M can be shadowed: keep the shadows synced */ - if ( d->vcpu[0] != NULL ) - (void)sh_validate_guest_entry(d->vcpu[0], *table_mfn, - p2m_entry, sizeof *p2m_entry); - } - *table_mfn = _mfn(l1e_get_pfn(*p2m_entry)); - next = sh_map_domain_page(*table_mfn); - sh_unmap_domain_page(*table); - *table = next; - - return 1; -} - -// Returns 0 on error (out of memory) -int -shadow_set_p2m_entry(struct domain *d, unsigned long gfn, mfn_t mfn) -{ - // XXX -- this might be able to be faster iff current->domain == d - mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); - void *table = sh_map_domain_page(table_mfn); - unsigned long gfn_remainder = gfn; - l1_pgentry_t *p2m_entry; - int rv=0; - -#if CONFIG_PAGING_LEVELS >= 4 - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L4_PAGETABLE_SHIFT - PAGE_SHIFT, - L4_PAGETABLE_ENTRIES, PGT_l3_page_table) ) - goto out; -#endif -#if CONFIG_PAGING_LEVELS >= 3 - // When using PAE Xen, we only allow 33 bits of pseudo-physical - // address in translated guests (i.e. 8 GBytes). This restriction - // comes from wanting to map the P2M table into the 16MB RO_MPT hole - // in Xen's address space for translated PV guests. - // - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L3_PAGETABLE_SHIFT - PAGE_SHIFT, - (CONFIG_PAGING_LEVELS == 3 - ? 8 - : L3_PAGETABLE_ENTRIES), - PGT_l2_page_table) ) - goto out; -#endif - if ( !p2m_next_level(d, &table_mfn, &table, &gfn_remainder, gfn, - L2_PAGETABLE_SHIFT - PAGE_SHIFT, - L2_PAGETABLE_ENTRIES, PGT_l1_page_table) ) - goto out; - - p2m_entry = p2m_find_entry(table, &gfn_remainder, gfn, - 0, L1_PAGETABLE_ENTRIES); - ASSERT(p2m_entry); - if ( mfn_valid(mfn) ) - *p2m_entry = l1e_from_pfn(mfn_x(mfn), __PAGE_HYPERVISOR|_PAGE_USER); - else - *p2m_entry = l1e_empty(); - - /* Track the highest gfn for which we have ever had a valid mapping */ - if ( mfn_valid(mfn) && (gfn > d->arch.max_mapped_pfn) ) - d->arch.max_mapped_pfn = gfn; - - /* The P2M can be shadowed: keep the shadows synced */ - if ( d->vcpu[0] != NULL ) - (void)sh_validate_guest_entry(d->vcpu[0], table_mfn, - p2m_entry, sizeof(*p2m_entry)); - - /* Success */ - rv = 1; - - out: - sh_unmap_domain_page(table); - return rv; -} - -// Allocate a new p2m table for a domain. -// -// The structure of the p2m table is that of a pagetable for xen (i.e. it is -// controlled by CONFIG_PAGING_LEVELS). -// -// Returns 0 if p2m table could not be initialized -// -static int -shadow_alloc_p2m_table(struct domain *d) -{ - mfn_t p2m_top, mfn; - struct list_head *entry; - struct page_info *page; - unsigned int page_count = 0; - unsigned long gfn; - - SHADOW_PRINTK("allocating p2m table\n"); - ASSERT(pagetable_get_pfn(d->arch.phys_table) == 0); - - p2m_top = shadow_alloc_p2m_page(d); - mfn_to_page(p2m_top)->count_info = 1; - mfn_to_page(p2m_top)->u.inuse.type_info = -#if CONFIG_PAGING_LEVELS == 4 - PGT_l4_page_table -#elif CONFIG_PAGING_LEVELS == 3 - PGT_l3_page_table -#elif CONFIG_PAGING_LEVELS == 2 - PGT_l2_page_table -#endif - | 1 | PGT_validated; - - if ( mfn_x(p2m_top) == 0 ) - return 0; - - d->arch.phys_table = pagetable_from_mfn(p2m_top); - - SHADOW_PRINTK("populating p2m table\n"); - - /* Initialise physmap tables for slot zero. Other code assumes this. */ - gfn = 0; - mfn = _mfn(INVALID_MFN); - if ( !shadow_set_p2m_entry(d, gfn, mfn) ) - goto error; - - /* Build a p2m map that matches the m2p entries for this domain's - * allocated pages. Skip any pages that have an explicitly invalid - * or obviously bogus m2p entry. */ - for ( entry = d->page_list.next; - entry != &d->page_list; - entry = entry->next ) - { - page = list_entry(entry, struct page_info, list); - mfn = page_to_mfn(page); - gfn = get_gpfn_from_mfn(mfn_x(mfn)); - page_count++; - if ( -#ifdef __x86_64__ - (gfn != 0x5555555555555555L) -#else - (gfn != 0x55555555L) -#endif - && gfn != INVALID_M2P_ENTRY - && (gfn < - (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof (l1_pgentry_t)) - && !shadow_set_p2m_entry(d, gfn, mfn) ) - goto error; - } - - SHADOW_PRINTK("p2m table initialised (%u pages)\n", page_count); - return 1; - - error: - SHADOW_PRINTK("failed to initialize p2m table, gfn=%05lx, mfn=%" - SH_PRI_mfn "\n", gfn, mfn_x(mfn)); - return 0; -} - -mfn_t -sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn) -/* Read another domain's p2m entries */ -{ - mfn_t mfn; - paddr_t addr = ((paddr_t)gpfn) << PAGE_SHIFT; - l2_pgentry_t *l2e; - l1_pgentry_t *l1e; - - ASSERT(shadow_mode_translate(d)); - mfn = pagetable_get_mfn(d->arch.phys_table); - - - if ( gpfn > d->arch.max_mapped_pfn ) - /* This pfn is higher than the highest the p2m map currently holds */ - return _mfn(INVALID_MFN); - -#if CONFIG_PAGING_LEVELS >= 4 - { - l4_pgentry_t *l4e = sh_map_domain_page(mfn); - l4e += l4_table_offset(addr); - if ( (l4e_get_flags(*l4e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l4e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l4e_get_pfn(*l4e)); - sh_unmap_domain_page(l4e); - } -#endif -#if CONFIG_PAGING_LEVELS >= 3 - { - l3_pgentry_t *l3e = sh_map_domain_page(mfn); -#if CONFIG_PAGING_LEVELS == 3 - /* On PAE hosts the p2m has eight l3 entries, not four (see - * shadow_set_p2m_entry()) so we can't use l3_table_offset. - * Instead, just count the number of l3es from zero. It's safe - * to do this because we already checked that the gfn is within - * the bounds of the p2m. */ - l3e += (addr >> L3_PAGETABLE_SHIFT); -#else - l3e += l3_table_offset(addr); -#endif - if ( (l3e_get_flags(*l3e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l3e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l3e_get_pfn(*l3e)); - sh_unmap_domain_page(l3e); - } -#endif - - l2e = sh_map_domain_page(mfn); - l2e += l2_table_offset(addr); - if ( (l2e_get_flags(*l2e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l2e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l2e_get_pfn(*l2e)); - sh_unmap_domain_page(l2e); - - l1e = sh_map_domain_page(mfn); - l1e += l1_table_offset(addr); - if ( (l1e_get_flags(*l1e) & _PAGE_PRESENT) == 0 ) - { - sh_unmap_domain_page(l1e); - return _mfn(INVALID_MFN); - } - mfn = _mfn(l1e_get_pfn(*l1e)); - sh_unmap_domain_page(l1e); - - return mfn; -} - -unsigned long -shadow_gfn_to_mfn_foreign(unsigned long gpfn) -{ - return mfn_x(sh_gfn_to_mfn_foreign(current->domain, gpfn)); -} - - -static void shadow_p2m_teardown(struct domain *d) -/* Return all the p2m pages to Xen. - * We know we don't have any extra mappings to these pages */ -{ - struct list_head *entry, *n; - struct page_info *pg; - - d->arch.phys_table = pagetable_null(); - - list_for_each_safe(entry, n, &d->arch.shadow.p2m_inuse) - { - pg = list_entry(entry, struct page_info, list); - list_del(entry); - /* Should have just the one ref we gave it in alloc_p2m_page() */ - if ( (pg->count_info & PGC_count_mask) != 1 ) - { - SHADOW_PRINTK("Odd p2m page count c=%#x t=%"PRtype_info"\n", - pg->count_info, pg->u.inuse.type_info); - } - ASSERT(page_get_owner(pg) == d); - /* Free should not decrement domain's total allocation, since - * these pages were allocated without an owner. */ - page_set_owner(pg, NULL); - free_domheap_pages(pg, 0); - d->arch.shadow.p2m_pages--; - perfc_decr(shadow_alloc_count); - } - list_for_each_safe(entry, n, &d->arch.shadow.p2m_freelist) - { - list_del(entry); - pg = list_entry(entry, struct page_info, list); - ASSERT(page_get_owner(pg) == d); - /* Free should not decrement domain's total allocation. */ - page_set_owner(pg, NULL); - free_domheap_pages(pg, 0); - d->arch.shadow.p2m_pages--; - perfc_decr(shadow_alloc_count); - } - ASSERT(d->arch.shadow.p2m_pages == 0); -} - /* Set the pool of shadow pages to the required number of pages. * Input will be rounded up to at least shadow_min_acceptable_pages(), * plus space for the p2m table. @@ -1491,11 +1193,11 @@ static unsigned int sh_set_allocation(struct domain *d, pages = (pages + ((1<arch.shadow.total_pages, pages); + d->arch.paging.shadow.total_pages, pages); - while ( d->arch.shadow.total_pages != pages ) + while ( d->arch.paging.shadow.total_pages != pages ) { - if ( d->arch.shadow.total_pages < pages ) + if ( d->arch.paging.shadow.total_pages < pages ) { /* Need to allocate more memory from domheap */ sp = (struct shadow_page_info *) @@ -1505,8 +1207,8 @@ static unsigned int sh_set_allocation(struct domain *d, SHADOW_PRINTK("failed to allocate shadow pages.\n"); return -ENOMEM; } - d->arch.shadow.free_pages += 1<arch.shadow.total_pages += 1<arch.paging.shadow.free_pages += 1<arch.paging.shadow.total_pages += 1<order = SHADOW_MAX_ORDER; list_add_tail(&sp->list, - &d->arch.shadow.freelists[SHADOW_MAX_ORDER]); + &d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER]); } - else if ( d->arch.shadow.total_pages > pages ) + else if ( d->arch.paging.shadow.total_pages > pages ) { /* Need to return memory to domheap */ shadow_prealloc(d, SHADOW_MAX_ORDER); - ASSERT(!list_empty(&d->arch.shadow.freelists[SHADOW_MAX_ORDER])); - sp = list_entry(d->arch.shadow.freelists[SHADOW_MAX_ORDER].next, + ASSERT(!list_empty(&d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER])); + sp = list_entry(d->arch.paging.shadow.freelists[SHADOW_MAX_ORDER].next, struct shadow_page_info, list); list_del(&sp->list); - d->arch.shadow.free_pages -= 1<arch.shadow.total_pages -= 1<arch.paging.shadow.free_pages -= 1<arch.paging.shadow.total_pages -= 1<arch.shadow.total_pages; + unsigned int pg = d->arch.paging.shadow.total_pages; return ((pg >> (20 - PAGE_SHIFT)) + ((pg & ((1 << (20 - PAGE_SHIFT)) - 1)) ? 1 : 0)); } @@ -1583,7 +1285,7 @@ static void sh_hash_audit_bucket(struct domain *d, int bucket) if ( !(SHADOW_AUDIT_ENABLE) ) return; - sp = d->arch.shadow.hash_table[bucket]; + sp = d->arch.paging.shadow.hash_table[bucket]; while ( sp ) { /* Not a shadow? */ @@ -1608,7 +1310,7 @@ static void sh_hash_audit_bucket(struct domain *d, int bucket) if ( (gpg->u.inuse.type_info & PGT_type_mask) == PGT_writable_page && (gpg->u.inuse.type_info & PGT_count_mask) != 0 ) { - SHADOW_ERROR("MFN %#lx shadowed (by %#"SH_PRI_mfn")" + SHADOW_ERROR("MFN %#lx shadowed (by %#"PRI_mfn")" " but has typecount %#lx\n", sp->backpointer, mfn_x(shadow_page_to_mfn(sp)), gpg->u.inuse.type_info); @@ -1652,13 +1354,13 @@ static int shadow_hash_alloc(struct domain *d) struct shadow_page_info **table; ASSERT(shadow_locked_by_me(d)); - ASSERT(!d->arch.shadow.hash_table); + ASSERT(!d->arch.paging.shadow.hash_table); table = xmalloc_array(struct shadow_page_info *, SHADOW_HASH_BUCKETS); if ( !table ) return 1; memset(table, 0, SHADOW_HASH_BUCKETS * sizeof (struct shadow_page_info *)); - d->arch.shadow.hash_table = table; + d->arch.paging.shadow.hash_table = table; return 0; } @@ -1667,10 +1369,10 @@ static int shadow_hash_alloc(struct domain *d) static void shadow_hash_teardown(struct domain *d) { ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); - xfree(d->arch.shadow.hash_table); - d->arch.shadow.hash_table = NULL; + xfree(d->arch.paging.shadow.hash_table); + d->arch.paging.shadow.hash_table = NULL; } @@ -1683,7 +1385,7 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1692,16 +1394,16 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) key = sh_hash(n, t); sh_hash_audit_bucket(d, key); - sp = d->arch.shadow.hash_table[key]; + sp = d->arch.paging.shadow.hash_table[key]; prev = NULL; while(sp) { if ( sp->backpointer == n && sp->type == t ) { /* Pull-to-front if 'sp' isn't already the head item */ - if ( unlikely(sp != d->arch.shadow.hash_table[key]) ) + if ( unlikely(sp != d->arch.paging.shadow.hash_table[key]) ) { - if ( unlikely(d->arch.shadow.hash_walking != 0) ) + if ( unlikely(d->arch.paging.shadow.hash_walking != 0) ) /* Can't reorder: someone is walking the hash chains */ return shadow_page_to_mfn(sp); else @@ -1710,8 +1412,8 @@ mfn_t shadow_hash_lookup(struct vcpu *v, unsigned long n, unsigned int t) /* Delete sp from the list */ prev->next_shadow = sp->next_shadow; /* Re-insert it at the head of the list */ - sp->next_shadow = d->arch.shadow.hash_table[key]; - d->arch.shadow.hash_table[key] = sp; + sp->next_shadow = d->arch.paging.shadow.hash_table[key]; + d->arch.paging.shadow.hash_table[key] = sp; } } else @@ -1737,7 +1439,7 @@ void shadow_hash_insert(struct vcpu *v, unsigned long n, unsigned int t, key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1748,8 +1450,8 @@ void shadow_hash_insert(struct vcpu *v, unsigned long n, unsigned int t, /* Insert this shadow at the top of the bucket */ sp = mfn_to_shadow_page(smfn); - sp->next_shadow = d->arch.shadow.hash_table[key]; - d->arch.shadow.hash_table[key] = sp; + sp->next_shadow = d->arch.paging.shadow.hash_table[key]; + d->arch.paging.shadow.hash_table[key] = sp; sh_hash_audit_bucket(d, key); } @@ -1763,7 +1465,7 @@ void shadow_hash_delete(struct vcpu *v, unsigned long n, unsigned int t, key_t key; ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_table); + ASSERT(d->arch.paging.shadow.hash_table); ASSERT(t); sh_hash_audit(d); @@ -1773,13 +1475,13 @@ void shadow_hash_delete(struct vcpu *v, unsigned long n, unsigned int t, sh_hash_audit_bucket(d, key); sp = mfn_to_shadow_page(smfn); - if ( d->arch.shadow.hash_table[key] == sp ) + if ( d->arch.paging.shadow.hash_table[key] == sp ) /* Easy case: we're deleting the head item. */ - d->arch.shadow.hash_table[key] = sp->next_shadow; + d->arch.paging.shadow.hash_table[key] = sp->next_shadow; else { /* Need to search for the one we want */ - x = d->arch.shadow.hash_table[key]; + x = d->arch.paging.shadow.hash_table[key]; while ( 1 ) { ASSERT(x); /* We can't have hit the end, since our target is @@ -1818,15 +1520,15 @@ static void hash_foreach(struct vcpu *v, /* Say we're here, to stop hash-lookups reordering the chains */ ASSERT(shadow_locked_by_me(d)); - ASSERT(d->arch.shadow.hash_walking == 0); - d->arch.shadow.hash_walking = 1; + ASSERT(d->arch.paging.shadow.hash_walking == 0); + d->arch.paging.shadow.hash_walking = 1; for ( i = 0; i < SHADOW_HASH_BUCKETS; i++ ) { /* WARNING: This is not safe against changes to the hash table. * The callback *must* return non-zero if it has inserted or * deleted anything from the hash (lookups are OK, though). */ - for ( x = d->arch.shadow.hash_table[i]; x; x = x->next_shadow ) + for ( x = d->arch.paging.shadow.hash_table[i]; x; x = x->next_shadow ) { if ( callback_mask & (1 << x->type) ) { @@ -1839,7 +1541,7 @@ static void hash_foreach(struct vcpu *v, } if ( done ) break; } - d->arch.shadow.hash_walking = 0; + d->arch.paging.shadow.hash_walking = 0; } @@ -2008,27 +1710,27 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, * and that mapping is likely to be in the current pagetable, * in the guest's linear map (on non-HIGHPTE linux and windows)*/ -#define GUESS(_a, _h) do { \ - if ( v->arch.shadow.mode->guess_wrmap(v, (_a), gmfn) ) \ - perfc_incrc(shadow_writeable_h_ ## _h); \ - if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 ) \ - return 1; \ +#define GUESS(_a, _h) do { \ + if ( v->arch.paging.mode->shadow.guess_wrmap(v, (_a), gmfn) ) \ + perfc_incrc(shadow_writeable_h_ ## _h); \ + if ( (pg->u.inuse.type_info & PGT_count_mask) == 0 ) \ + return 1; \ } while (0) - if ( v->arch.shadow.mode->guest_levels == 2 ) + if ( v->arch.paging.mode->guest_levels == 2 ) { if ( level == 1 ) /* 32bit non-PAE w2k3: linear map at 0xC0000000 */ GUESS(0xC0000000UL + (fault_addr >> 10), 1); /* Linux lowmem: first 896MB is mapped 1-to-1 above 0xC0000000 */ - if ((gfn = sh_mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) + if ((gfn = mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) GUESS(0xC0000000UL + (gfn << PAGE_SHIFT), 4); } #if CONFIG_PAGING_LEVELS >= 3 - else if ( v->arch.shadow.mode->guest_levels == 3 ) + else if ( v->arch.paging.mode->guest_levels == 3 ) { /* 32bit PAE w2k3: linear map at 0xC0000000 */ switch ( level ) @@ -2038,11 +1740,11 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, } /* Linux lowmem: first 896MB is mapped 1-to-1 above 0xC0000000 */ - if ((gfn = sh_mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) + if ((gfn = mfn_to_gfn(v->domain, gmfn)) < 0x38000 ) GUESS(0xC0000000UL + (gfn << PAGE_SHIFT), 4); } #if CONFIG_PAGING_LEVELS >= 4 - else if ( v->arch.shadow.mode->guest_levels == 4 ) + else if ( v->arch.paging.mode->guest_levels == 4 ) { /* 64bit w2k3: linear map at 0x0000070000000000 */ switch ( level ) @@ -2054,7 +1756,7 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, /* 64bit Linux direct map at 0xffff810000000000; older kernels * had it at 0x0000010000000000UL */ - gfn = sh_mfn_to_gfn(v->domain, gmfn); + gfn = mfn_to_gfn(v->domain, gmfn); GUESS(0xffff810000000000UL + (gfn << PAGE_SHIFT), 4); GUESS(0x0000010000000000UL + (gfn << PAGE_SHIFT), 4); } @@ -2073,10 +1775,10 @@ int sh_remove_write_access(struct vcpu *v, mfn_t gmfn, * the writeable mapping by looking at the same MFN where the last * brute-force search succeeded. */ - if ( v->arch.shadow.last_writeable_pte_smfn != 0 ) + if ( v->arch.paging.shadow.last_writeable_pte_smfn != 0 ) { unsigned long old_count = (pg->u.inuse.type_info & PGT_count_mask); - mfn_t last_smfn = _mfn(v->arch.shadow.last_writeable_pte_smfn); + mfn_t last_smfn = _mfn(v->arch.paging.shadow.last_writeable_pte_smfn); int shtype = mfn_to_shadow_page(last_smfn)->type; if ( callbacks[shtype] ) @@ -2431,7 +2133,7 @@ sh_remove_all_shadows_and_parents(struct vcpu *v, mfn_t gmfn) static void sh_update_paging_modes(struct vcpu *v) { struct domain *d = v->domain; - struct shadow_paging_mode *old_mode = v->arch.shadow.mode; + struct paging_mode *old_mode = v->arch.paging.mode; mfn_t old_guest_table; ASSERT(shadow_locked_by_me(d)); @@ -2446,8 +2148,8 @@ static void sh_update_paging_modes(struct vcpu *v) // First, tear down any old shadow tables held by this vcpu. // - if ( v->arch.shadow.mode ) - v->arch.shadow.mode->detach_old_tables(v); + if ( v->arch.paging.mode ) + v->arch.paging.mode->shadow.detach_old_tables(v); if ( !is_hvm_domain(d) ) { @@ -2456,17 +2158,17 @@ static void sh_update_paging_modes(struct vcpu *v) /// #if CONFIG_PAGING_LEVELS == 4 if ( pv_32bit_guest(v) ) - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); else - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,4,4); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,4,4); #elif CONFIG_PAGING_LEVELS == 3 - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #elif CONFIG_PAGING_LEVELS == 2 - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); #else #error unexpected paging mode #endif - v->arch.shadow.translate_enabled = !!shadow_mode_translate(d); + v->arch.paging.translate_enabled = !!shadow_mode_translate(d); } else { @@ -2476,8 +2178,8 @@ static void sh_update_paging_modes(struct vcpu *v) ASSERT(shadow_mode_translate(d)); ASSERT(shadow_mode_external(d)); - v->arch.shadow.translate_enabled = !!hvm_paging_enabled(v); - if ( !v->arch.shadow.translate_enabled ) + v->arch.paging.translate_enabled = !!hvm_paging_enabled(v); + if ( !v->arch.paging.translate_enabled ) { /* Set v->arch.guest_table to use the p2m map, and choose * the appropriate shadow mode */ @@ -2485,11 +2187,11 @@ static void sh_update_paging_modes(struct vcpu *v) #if CONFIG_PAGING_LEVELS == 2 v->arch.guest_table = pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table)); - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,2,2); #elif CONFIG_PAGING_LEVELS == 3 v->arch.guest_table = pagetable_from_pfn(pagetable_get_pfn(d->arch.phys_table)); - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #else /* CONFIG_PAGING_LEVELS == 4 */ { l4_pgentry_t *l4e; @@ -2501,7 +2203,7 @@ static void sh_update_paging_modes(struct vcpu *v) pagetable_from_pfn(l4e_get_pfn(l4e[0])); sh_unmap_domain_page(l4e); } - v->arch.shadow.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode,3,3); #endif /* Fix up refcounts on guest_table */ get_page(mfn_to_page(pagetable_get_mfn(v->arch.guest_table)), d); @@ -2514,7 +2216,7 @@ static void sh_update_paging_modes(struct vcpu *v) if ( hvm_long_mode_enabled(v) ) { // long mode guest... - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 4, 4); } else @@ -2523,7 +2225,7 @@ static void sh_update_paging_modes(struct vcpu *v) { #if CONFIG_PAGING_LEVELS >= 3 // 32-bit PAE mode guest... - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 3, 3); #else SHADOW_ERROR("PAE not supported in 32-bit Xen\n"); @@ -2535,10 +2237,10 @@ static void sh_update_paging_modes(struct vcpu *v) { // 32-bit 2 level guest... #if CONFIG_PAGING_LEVELS >= 3 - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 3, 2); #else - v->arch.shadow.mode = + v->arch.paging.mode = &SHADOW_INTERNAL_NAME(sh_paging_mode, 2, 2); #endif } @@ -2546,25 +2248,25 @@ static void sh_update_paging_modes(struct vcpu *v) if ( pagetable_is_null(v->arch.monitor_table) ) { - mfn_t mmfn = v->arch.shadow.mode->make_monitor_table(v); + mfn_t mmfn = v->arch.paging.mode->shadow.make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(mmfn); make_cr3(v, mfn_x(mmfn)); hvm_update_host_cr3(v); } - if ( v->arch.shadow.mode != old_mode ) + if ( v->arch.paging.mode != old_mode ) { SHADOW_PRINTK("new paging mode: d=%u v=%u pe=%d g=%u s=%u " "(was g=%u s=%u)\n", d->domain_id, v->vcpu_id, is_hvm_domain(d) ? !!hvm_paging_enabled(v) : 1, - v->arch.shadow.mode->guest_levels, - v->arch.shadow.mode->shadow_levels, + v->arch.paging.mode->guest_levels, + v->arch.paging.mode->shadow.shadow_levels, old_mode ? old_mode->guest_levels : 0, - old_mode ? old_mode->shadow_levels : 0); + old_mode ? old_mode->shadow.shadow_levels : 0); if ( old_mode && - (v->arch.shadow.mode->shadow_levels != - old_mode->shadow_levels) ) + (v->arch.paging.mode->shadow.shadow_levels != + old_mode->shadow.shadow_levels) ) { /* Need to make a new monitor table for the new mode */ mfn_t new_mfn, old_mfn; @@ -2584,9 +2286,9 @@ static void sh_update_paging_modes(struct vcpu *v) old_mfn = pagetable_get_mfn(v->arch.monitor_table); v->arch.monitor_table = pagetable_null(); - new_mfn = v->arch.shadow.mode->make_monitor_table(v); + new_mfn = v->arch.paging.mode->shadow.make_monitor_table(v); v->arch.monitor_table = pagetable_from_mfn(new_mfn); - SHADOW_PRINTK("new monitor table %"SH_PRI_mfn "\n", + SHADOW_PRINTK("new monitor table %"PRI_mfn "\n", mfn_x(new_mfn)); /* Don't be running on the old monitor table when we @@ -2596,7 +2298,7 @@ static void sh_update_paging_modes(struct vcpu *v) if ( v == current ) write_ptbase(v); hvm_update_host_cr3(v); - old_mode->destroy_monitor_table(v, old_mfn); + old_mode->shadow.destroy_monitor_table(v, old_mfn); } } @@ -2606,7 +2308,7 @@ static void sh_update_paging_modes(struct vcpu *v) // This *does* happen, at least for CR4.PGE... } - v->arch.shadow.mode->update_cr3(v, 0); + v->arch.paging.mode->update_cr3(v, 0); } void shadow_update_paging_modes(struct vcpu *v) @@ -2626,9 +2328,7 @@ static void sh_new_mode(struct domain *d, u32 new_mode) ASSERT(shadow_locked_by_me(d)); ASSERT(d != current->domain); - d->arch.shadow.mode = new_mode; - if ( new_mode & SHM2_translate ) - shadow_audit_p2m(d); + d->arch.paging.mode = new_mode; for_each_vcpu(d, v) sh_update_paging_modes(v); } @@ -2642,75 +2342,75 @@ int shadow_enable(struct domain *d, u32 mode) unsigned int old_pages; int rv = 0; - mode |= SHM2_enable; + mode |= PG_SH_enable; domain_pause(d); - shadow_lock(d); /* Sanity check the arguments */ if ( (d == current->domain) || shadow_mode_enabled(d) || - ((mode & SHM2_translate) && !(mode & SHM2_refcounts)) || - ((mode & SHM2_external) && !(mode & SHM2_translate)) ) + ((mode & PG_translate) && !(mode & PG_refcounts)) || + ((mode & PG_external) && !(mode & PG_translate)) ) { rv = -EINVAL; - goto out; + goto out_unlocked; } - // XXX -- eventually would like to require that all memory be allocated - // *after* shadow_enabled() is called... So here, we would test to make - // sure that d->page_list is empty. -#if 0 - spin_lock(&d->page_alloc_lock); - if ( !list_empty(&d->page_list) ) - { - spin_unlock(&d->page_alloc_lock); - rv = -EINVAL; - goto out; - } - spin_unlock(&d->page_alloc_lock); -#endif - /* Init the shadow memory allocation if the user hasn't done so */ - old_pages = d->arch.shadow.total_pages; + old_pages = d->arch.paging.shadow.total_pages; if ( old_pages == 0 ) - if ( sh_set_allocation(d, 256, NULL) != 0 ) /* Use at least 1MB */ + { + unsigned int r; + shadow_lock(d); + r = sh_set_allocation(d, 256, NULL); /* Use at least 1MB */ + shadow_unlock(d); + if ( r != 0 ) { sh_set_allocation(d, 0, NULL); rv = -ENOMEM; - goto out; - } + goto out_unlocked; + } + } + + /* Init the P2M table. Must be done before we take the shadow lock + * to avoid possible deadlock. */ + if ( mode & PG_translate ) + { + rv = p2m_alloc_table(d, shadow_alloc_p2m_page, shadow_free_p2m_page); + if (rv != 0) + goto out_unlocked; + } + + shadow_lock(d); + + /* Sanity check again with the lock held */ + if ( shadow_mode_enabled(d) ) + { + rv = -EINVAL; + goto out_locked; + } /* Init the hash table */ if ( shadow_hash_alloc(d) != 0 ) { - sh_set_allocation(d, old_pages, NULL); rv = -ENOMEM; - goto out; + goto out_locked; } - /* Init the P2M table */ - if ( mode & SHM2_translate ) - if ( !shadow_alloc_p2m_table(d) ) - { - shadow_hash_teardown(d); - sh_set_allocation(d, old_pages, NULL); - shadow_p2m_teardown(d); - rv = -ENOMEM; - goto out; - } - #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) /* We assume we're dealing with an older 64bit linux guest until we * see the guest use more than one l4 per vcpu. */ - d->arch.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL; + d->arch.paging.shadow.opt_flags = SHOPT_LINUX_L3_TOPLEVEL; #endif /* Update the bits */ sh_new_mode(d, mode); - shadow_audit_p2m(d); - out: + + out_locked: shadow_unlock(d); + out_unlocked: + if ( rv != 0 && !pagetable_is_null(d->arch.phys_table) ) + p2m_teardown(d); domain_unpause(d); return rv; } @@ -2721,6 +2421,8 @@ void shadow_teardown(struct domain *d) { struct vcpu *v; mfn_t mfn; + struct list_head *entry, *n; + struct page_info *pg; ASSERT(test_bit(_DOMF_dying, &d->domain_flags)); ASSERT(d != current->domain); @@ -2733,48 +2435,55 @@ void shadow_teardown(struct domain *d) /* Release the shadow and monitor tables held by each vcpu */ for_each_vcpu(d, v) { - if ( v->arch.shadow.mode ) + if ( v->arch.paging.mode ) { - v->arch.shadow.mode->detach_old_tables(v); + v->arch.paging.mode->shadow.detach_old_tables(v); if ( shadow_mode_external(d) ) { mfn = pagetable_get_mfn(v->arch.monitor_table); if ( mfn_valid(mfn) && (mfn_x(mfn) != 0) ) - v->arch.shadow.mode->destroy_monitor_table(v, mfn); + v->arch.paging.mode->shadow.destroy_monitor_table(v, mfn); v->arch.monitor_table = pagetable_null(); } } } } - if ( d->arch.shadow.total_pages != 0 ) + list_for_each_safe(entry, n, &d->arch.paging.shadow.p2m_freelist) + { + list_del(entry); + pg = list_entry(entry, struct page_info, list); + shadow_free_p2m_page(d, pg); + } + + if ( d->arch.paging.shadow.total_pages != 0 ) { SHADOW_PRINTK("teardown of domain %u starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); /* Destroy all the shadows and release memory to domheap */ sh_set_allocation(d, 0, NULL); /* Release the hash table back to xenheap */ - if (d->arch.shadow.hash_table) + if (d->arch.paging.shadow.hash_table) shadow_hash_teardown(d); /* Release the log-dirty bitmap of dirtied pages */ sh_free_log_dirty_bitmap(d); /* Should not have any more memory held */ SHADOW_PRINTK("teardown done." " Shadow pages total = %u, free = %u, p2m=%u\n", - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); - ASSERT(d->arch.shadow.total_pages == 0); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); + ASSERT(d->arch.paging.shadow.total_pages == 0); } /* We leave the "permanent" shadow modes enabled, but clear the * log-dirty mode bit. We don't want any more mark_dirty() * calls now that we've torn down the bitmap */ - d->arch.shadow.mode &= ~SHM2_log_dirty; + d->arch.paging.mode &= ~PG_log_dirty; shadow_unlock(d); } @@ -2782,30 +2491,28 @@ void shadow_teardown(struct domain *d) void shadow_final_teardown(struct domain *d) /* Called by arch_domain_destroy(), when it's safe to pull down the p2m map. */ { - SHADOW_PRINTK("dom %u final teardown starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); /* Double-check that the domain didn't have any shadow memory. * It is possible for a domain that never got domain_kill()ed * to get here with its shadow allocation intact. */ - if ( d->arch.shadow.total_pages != 0 ) + if ( d->arch.paging.shadow.total_pages != 0 ) shadow_teardown(d); /* It is now safe to pull down the p2m map. */ - if ( d->arch.shadow.p2m_pages != 0 ) - shadow_p2m_teardown(d); + p2m_teardown(d); SHADOW_PRINTK("dom %u final teardown done." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); } static int shadow_one_bit_enable(struct domain *d, u32 mode) @@ -2814,12 +2521,14 @@ static int shadow_one_bit_enable(struct domain *d, u32 mode) ASSERT(shadow_locked_by_me(d)); /* Sanity check the call */ - if ( d == current->domain || (d->arch.shadow.mode & mode) ) + if ( d == current->domain || (d->arch.paging.mode & mode) ) { return -EINVAL; } - if ( d->arch.shadow.mode == 0 ) + mode |= PG_SH_enable; + + if ( d->arch.paging.mode == 0 ) { /* Init the shadow memory allocation and the hash table */ if ( sh_set_allocation(d, 1, NULL) != 0 @@ -2831,7 +2540,7 @@ static int shadow_one_bit_enable(struct domain *d, u32 mode) } /* Update the bits */ - sh_new_mode(d, d->arch.shadow.mode | mode); + sh_new_mode(d, d->arch.paging.mode | mode); return 0; } @@ -2843,26 +2552,26 @@ static int shadow_one_bit_disable(struct domain *d, u32 mode) ASSERT(shadow_locked_by_me(d)); /* Sanity check the call */ - if ( d == current->domain || !(d->arch.shadow.mode & mode) ) + if ( d == current->domain || !(d->arch.paging.mode & mode) ) { return -EINVAL; } /* Update the bits */ - sh_new_mode(d, d->arch.shadow.mode & ~mode); - if ( d->arch.shadow.mode == 0 ) + sh_new_mode(d, d->arch.paging.mode & ~mode); + if ( d->arch.paging.mode == 0 ) { /* Get this domain off shadows */ SHADOW_PRINTK("un-shadowing of domain %u starts." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); for_each_vcpu(d, v) { - if ( v->arch.shadow.mode ) - v->arch.shadow.mode->detach_old_tables(v); + if ( v->arch.paging.mode ) + v->arch.paging.mode->shadow.detach_old_tables(v); #if CONFIG_PAGING_LEVELS == 4 if ( !(v->arch.flags & TF_kernel_mode) ) make_cr3(v, pagetable_get_pfn(v->arch.guest_table_user)); @@ -2885,9 +2594,9 @@ static int shadow_one_bit_disable(struct domain *d, u32 mode) SHADOW_PRINTK("un-shadowing of domain %u done." " Shadow pages total = %u, free = %u, p2m=%u\n", d->domain_id, - d->arch.shadow.total_pages, - d->arch.shadow.free_pages, - d->arch.shadow.p2m_pages); + d->arch.paging.shadow.total_pages, + d->arch.paging.shadow.free_pages, + d->arch.paging.shadow.p2m_pages); } return 0; @@ -2909,7 +2618,7 @@ static int shadow_test_enable(struct domain *d) goto out; } - ret = shadow_one_bit_enable(d, SHM2_enable); + ret = shadow_one_bit_enable(d, PG_SH_enable); out: shadow_unlock(d); domain_unpause(d); @@ -2923,7 +2632,7 @@ static int shadow_test_disable(struct domain *d) domain_pause(d); shadow_lock(d); - ret = shadow_one_bit_disable(d, SHM2_enable); + ret = shadow_one_bit_disable(d, PG_SH_enable); shadow_unlock(d); domain_unpause(d); @@ -2933,19 +2642,19 @@ static int shadow_test_disable(struct domain *d) static int sh_alloc_log_dirty_bitmap(struct domain *d) { - ASSERT(d->arch.shadow.dirty_bitmap == NULL); - d->arch.shadow.dirty_bitmap_size = + ASSERT(d->arch.paging.shadow.dirty_bitmap == NULL); + d->arch.paging.shadow.dirty_bitmap_size = (arch_get_max_pfn(d) + (BITS_PER_LONG - 1)) & ~(BITS_PER_LONG - 1); - d->arch.shadow.dirty_bitmap = + d->arch.paging.shadow.dirty_bitmap = xmalloc_array(unsigned long, - d->arch.shadow.dirty_bitmap_size / BITS_PER_LONG); - if ( d->arch.shadow.dirty_bitmap == NULL ) + d->arch.paging.shadow.dirty_bitmap_size / BITS_PER_LONG); + if ( d->arch.paging.shadow.dirty_bitmap == NULL ) { - d->arch.shadow.dirty_bitmap_size = 0; + d->arch.paging.shadow.dirty_bitmap_size = 0; return -ENOMEM; } - memset(d->arch.shadow.dirty_bitmap, 0, d->arch.shadow.dirty_bitmap_size/8); + memset(d->arch.paging.shadow.dirty_bitmap, 0, d->arch.paging.shadow.dirty_bitmap_size/8); return 0; } @@ -2953,11 +2662,11 @@ sh_alloc_log_dirty_bitmap(struct domain *d) static void sh_free_log_dirty_bitmap(struct domain *d) { - d->arch.shadow.dirty_bitmap_size = 0; - if ( d->arch.shadow.dirty_bitmap ) + d->arch.paging.shadow.dirty_bitmap_size = 0; + if ( d->arch.paging.shadow.dirty_bitmap ) { - xfree(d->arch.shadow.dirty_bitmap); - d->arch.shadow.dirty_bitmap = NULL; + xfree(d->arch.paging.shadow.dirty_bitmap); + d->arch.paging.shadow.dirty_bitmap = NULL; } } @@ -2989,7 +2698,7 @@ static int shadow_log_dirty_enable(struct domain *d) goto out; } - ret = shadow_one_bit_enable(d, SHM2_log_dirty); + ret = shadow_one_bit_enable(d, PG_log_dirty); if ( ret != 0 ) sh_free_log_dirty_bitmap(d); @@ -3005,7 +2714,7 @@ static int shadow_log_dirty_disable(struct domain *d) domain_pause(d); shadow_lock(d); - ret = shadow_one_bit_disable(d, SHM2_log_dirty); + ret = shadow_one_bit_disable(d, PG_log_dirty); if ( !shadow_mode_log_dirty(d) ) sh_free_log_dirty_bitmap(d); shadow_unlock(d); @@ -3017,100 +2726,52 @@ static int shadow_log_dirty_disable(struct domain *d) /**************************************************************************/ /* P2M map manipulations */ -static void -sh_p2m_remove_page(struct domain *d, unsigned long gfn, unsigned long mfn) +/* shadow specific code which should be called when P2M table entry is updated + * with new content. It is responsible for update the entry, as well as other + * shadow processing jobs. + */ +void +shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn, l1_pgentry_t *p, + l1_pgentry_t new, unsigned int level) { - struct vcpu *v; + struct domain *d = v->domain; + mfn_t table_mfn = pagetable_get_mfn(d->arch.phys_table); + mfn_t mfn; + + shadow_lock(d); - if ( !shadow_mode_translate(d) ) - return; - - v = current; - if ( v->domain != d ) - v = d->vcpu[0]; - - SHADOW_DEBUG(P2M, "removing gfn=%#lx mfn=%#lx\n", gfn, mfn); - - ASSERT(mfn_x(sh_gfn_to_mfn(d, gfn)) == mfn); - //ASSERT(sh_mfn_to_gfn(d, mfn) == gfn); - - if ( v != NULL ) - { - sh_remove_all_shadows_and_parents(v, _mfn(mfn)); - if ( sh_remove_all_mappings(v, _mfn(mfn)) ) - flush_tlb_mask(d->domain_dirty_cpumask); + /* handle physmap_add and physmap_remove */ + mfn = gfn_to_mfn(d, gfn); + if ( v != NULL && level == 1 && mfn_valid(mfn) ) { + sh_remove_all_shadows_and_parents(v, mfn); + if ( sh_remove_all_mappings(v, mfn) ) + flush_tlb_mask(d->domain_dirty_cpumask); } + + /* update the entry with new content */ + safe_write_pte(p, new); - shadow_set_p2m_entry(d, gfn, _mfn(INVALID_MFN)); - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); -} + /* The P2M can be shadowed: keep the shadows synced */ + if ( d->vcpu[0] != NULL ) + (void)sh_validate_guest_entry(d->vcpu[0], table_mfn, p, sizeof(*p)); -void -shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn, - unsigned long mfn) -{ - shadow_lock(d); - shadow_audit_p2m(d); - sh_p2m_remove_page(d, gfn, mfn); - shadow_audit_p2m(d); - shadow_unlock(d); -} - -void -shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, - unsigned long mfn) -{ - unsigned long ogfn; - mfn_t omfn; - - if ( !shadow_mode_translate(d) ) - return; - - shadow_lock(d); - shadow_audit_p2m(d); - - SHADOW_DEBUG(P2M, "adding gfn=%#lx mfn=%#lx\n", gfn, mfn); - - omfn = sh_gfn_to_mfn(d, gfn); - if ( mfn_valid(omfn) ) - { - /* Get rid of the old mapping, especially any shadows */ - struct vcpu *v = current; - if ( v->domain != d ) - v = d->vcpu[0]; - if ( v != NULL ) - { - sh_remove_all_shadows_and_parents(v, omfn); - if ( sh_remove_all_mappings(v, omfn) ) - flush_tlb_mask(d->domain_dirty_cpumask); + /* install P2M in monitors for PAE Xen */ +#if CONFIG_PAGING_LEVELS == 3 + if ( level == 3 ) { + struct vcpu *v; + /* We have written to the p2m l3: need to sync the per-vcpu + * copies of it in the monitor tables */ + p2m_install_entry_in_monitors(d, (l3_pgentry_t *)p); + /* Also, any vcpus running on shadows of the p2m need to + * reload their CR3s so the change propagates to the shadow */ + for_each_vcpu(d, v) { + if ( pagetable_get_pfn(v->arch.guest_table) + == pagetable_get_pfn(d->arch.phys_table) + && v->arch.paging.mode != NULL ) + v->arch.paging.mode->update_cr3(v, 0); } - set_gpfn_from_mfn(mfn_x(omfn), INVALID_M2P_ENTRY); } - - ogfn = sh_mfn_to_gfn(d, _mfn(mfn)); - if ( -#ifdef __x86_64__ - (ogfn != 0x5555555555555555L) -#else - (ogfn != 0x55555555L) #endif - && (ogfn != INVALID_M2P_ENTRY) - && (ogfn != gfn) ) - { - /* This machine frame is already mapped at another physical address */ - SHADOW_DEBUG(P2M, "aliased! mfn=%#lx, old gfn=%#lx, new gfn=%#lx\n", - mfn, ogfn, gfn); - if ( mfn_valid(omfn = sh_gfn_to_mfn(d, ogfn)) ) - { - SHADOW_DEBUG(P2M, "old gfn=%#lx -> mfn %#lx\n", - ogfn , mfn_x(omfn)); - if ( mfn_x(omfn) == mfn ) - sh_p2m_remove_page(d, ogfn, mfn); - } - } - - shadow_set_p2m_entry(d, gfn, _mfn(mfn)); - set_gpfn_from_mfn(mfn, gfn); #if (SHADOW_OPTIMIZATIONS & SHOPT_FAST_FAULT_PATH) /* If we're doing FAST_FAULT_PATH, then shadow mode may have @@ -3122,7 +2783,6 @@ shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, shadow_blow_tables(d); #endif - shadow_audit_p2m(d); shadow_unlock(d); } @@ -3151,11 +2811,11 @@ static int shadow_log_dirty_op( SHADOW_DEBUG(LOGDIRTY, "log-dirty %s: dom %u faults=%u dirty=%u\n", (clean) ? "clean" : "peek", d->domain_id, - d->arch.shadow.fault_count, - d->arch.shadow.dirty_count); + d->arch.paging.shadow.fault_count, + d->arch.paging.shadow.dirty_count); - sc->stats.fault_count = d->arch.shadow.fault_count; - sc->stats.dirty_count = d->arch.shadow.dirty_count; + sc->stats.fault_count = d->arch.paging.shadow.fault_count; + sc->stats.dirty_count = d->arch.paging.shadow.dirty_count; if ( clean ) { @@ -3164,22 +2824,22 @@ static int shadow_log_dirty_op( * but for now, we just unshadow everything except Xen. */ shadow_blow_tables(d); - d->arch.shadow.fault_count = 0; - d->arch.shadow.dirty_count = 0; + d->arch.paging.shadow.fault_count = 0; + d->arch.paging.shadow.dirty_count = 0; } if ( guest_handle_is_null(sc->dirty_bitmap) ) /* caller may have wanted just to clean the state or access stats. */ peek = 0; - if ( (peek || clean) && (d->arch.shadow.dirty_bitmap == NULL) ) + if ( (peek || clean) && (d->arch.paging.shadow.dirty_bitmap == NULL) ) { rv = -EINVAL; /* perhaps should be ENOMEM? */ goto out; } - if ( sc->pages > d->arch.shadow.dirty_bitmap_size ) - sc->pages = d->arch.shadow.dirty_bitmap_size; + if ( sc->pages > d->arch.paging.shadow.dirty_bitmap_size ) + sc->pages = d->arch.paging.shadow.dirty_bitmap_size; #define CHUNK (8*1024) /* Transfer and clear in 1kB chunks for L1 cache. */ for ( i = 0; i < sc->pages; i += CHUNK ) @@ -3192,7 +2852,7 @@ static int shadow_log_dirty_op( { if ( copy_to_guest_offset( sc->dirty_bitmap, i/8, - (uint8_t *)d->arch.shadow.dirty_bitmap + (i/8), bytes) ) + (uint8_t *)d->arch.paging.shadow.dirty_bitmap + (i/8), bytes) ) { rv = -EFAULT; goto out; @@ -3200,7 +2860,7 @@ static int shadow_log_dirty_op( } if ( clean ) - memset((uint8_t *)d->arch.shadow.dirty_bitmap + (i/8), 0, bytes); + memset((uint8_t *)d->arch.paging.shadow.dirty_bitmap + (i/8), 0, bytes); } #undef CHUNK @@ -3221,7 +2881,7 @@ void sh_mark_dirty(struct domain *d, mfn_t gmfn) if ( !shadow_mode_log_dirty(d) || !mfn_valid(gmfn) ) return; - ASSERT(d->arch.shadow.dirty_bitmap != NULL); + ASSERT(d->arch.paging.shadow.dirty_bitmap != NULL); /* We /really/ mean PFN here, even for non-translated guests. */ pfn = get_gpfn_from_mfn(mfn_x(gmfn)); @@ -3235,24 +2895,24 @@ void sh_mark_dirty(struct domain *d, mfn_t gmfn) return; /* N.B. Can use non-atomic TAS because protected by shadow_lock. */ - if ( likely(pfn < d->arch.shadow.dirty_bitmap_size) ) + if ( likely(pfn < d->arch.paging.shadow.dirty_bitmap_size) ) { - if ( !__test_and_set_bit(pfn, d->arch.shadow.dirty_bitmap) ) + if ( !__test_and_set_bit(pfn, d->arch.paging.shadow.dirty_bitmap) ) { SHADOW_DEBUG(LOGDIRTY, - "marked mfn %" SH_PRI_mfn " (pfn=%lx), dom %d\n", + "marked mfn %" PRI_mfn " (pfn=%lx), dom %d\n", mfn_x(gmfn), pfn, d->domain_id); - d->arch.shadow.dirty_count++; + d->arch.paging.shadow.dirty_count++; } } else { SHADOW_PRINTK("mark_dirty OOR! " - "mfn=%" SH_PRI_mfn " pfn=%lx max=%x (dom %d)\n" + "mfn=%" PRI_mfn " pfn=%lx max=%x (dom %d)\n" "owner=%d c=%08x t=%" PRtype_info "\n", mfn_x(gmfn), pfn, - d->arch.shadow.dirty_bitmap_size, + d->arch.paging.shadow.dirty_bitmap_size, d->domain_id, (page_get_owner(mfn_to_page(gmfn)) ? page_get_owner(mfn_to_page(gmfn))->domain_id @@ -3292,7 +2952,7 @@ int shadow_domctl(struct domain *d, return rc; if ( is_hvm_domain(d) ) return -EINVAL; - if ( d->arch.shadow.mode & SHM2_enable ) + if ( d->arch.paging.mode & PG_SH_enable ) if ( (rc = shadow_test_disable(d)) != 0 ) return rc; return 0; @@ -3304,7 +2964,7 @@ int shadow_domctl(struct domain *d, return shadow_log_dirty_enable(d); case XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE: - return shadow_enable(d, SHM2_refcounts|SHM2_translate); + return shadow_enable(d, PG_refcounts|PG_translate); case XEN_DOMCTL_SHADOW_OP_CLEAN: case XEN_DOMCTL_SHADOW_OP_PEEK: @@ -3313,7 +2973,7 @@ int shadow_domctl(struct domain *d, case XEN_DOMCTL_SHADOW_OP_ENABLE: if ( sc->mode & XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY ) return shadow_log_dirty_enable(d); - return shadow_enable(d, sc->mode << SHM2_shift); + return shadow_enable(d, sc->mode << PG_mode_shift); case XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION: sc->mb = shadow_get_allocation(d); @@ -3390,7 +3050,7 @@ void shadow_audit_tables(struct vcpu *v) else { /* Audit only the current mode's tables */ - switch ( v->arch.shadow.mode->guest_levels ) + switch ( v->arch.paging.mode->guest_levels ) { case 2: mask = (SHF_L1_32|SHF_FL1_32|SHF_L2_32); break; case 3: mask = (SHF_L1_PAE|SHF_FL1_PAE|SHF_L2_PAE @@ -3406,199 +3066,6 @@ void shadow_audit_tables(struct vcpu *v) #endif /* Shadow audit */ - -/**************************************************************************/ -/* Auditing p2m tables */ - -#if SHADOW_AUDIT & SHADOW_AUDIT_P2M - -void shadow_audit_p2m(struct domain *d) -{ - struct list_head *entry; - struct page_info *page; - struct domain *od; - unsigned long mfn, gfn, m2pfn, lp2mfn = 0; - mfn_t p2mfn; - unsigned long orphans_d = 0, orphans_i = 0, mpbad = 0, pmbad = 0; - int test_linear; - - if ( !(SHADOW_AUDIT_ENABLE) || !shadow_mode_translate(d) ) - return; - - //SHADOW_PRINTK("p2m audit starts\n"); - - test_linear = ( (d == current->domain) - && !pagetable_is_null(current->arch.monitor_table) ); - if ( test_linear ) - local_flush_tlb(); - - /* Audit part one: walk the domain's page allocation list, checking - * the m2p entries. */ - for ( entry = d->page_list.next; - entry != &d->page_list; - entry = entry->next ) - { - page = list_entry(entry, struct page_info, list); - mfn = mfn_x(page_to_mfn(page)); - - // SHADOW_PRINTK("auditing guest page, mfn=%#lx\n", mfn); - - od = page_get_owner(page); - - if ( od != d ) - { - SHADOW_PRINTK("wrong owner %#lx -> %p(%u) != %p(%u)\n", - mfn, od, (od?od->domain_id:-1), d, d->domain_id); - continue; - } - - gfn = get_gpfn_from_mfn(mfn); - if ( gfn == INVALID_M2P_ENTRY ) - { - orphans_i++; - //SHADOW_PRINTK("orphaned guest page: mfn=%#lx has invalid gfn\n", - // mfn); - continue; - } - - if ( gfn == 0x55555555 ) - { - orphans_d++; - //SHADOW_PRINTK("orphaned guest page: mfn=%#lx has debug gfn\n", - // mfn); - continue; - } - - p2mfn = sh_gfn_to_mfn_foreign(d, gfn); - if ( mfn_x(p2mfn) != mfn ) - { - mpbad++; - SHADOW_PRINTK("map mismatch mfn %#lx -> gfn %#lx -> mfn %#lx" - " (-> gfn %#lx)\n", - mfn, gfn, mfn_x(p2mfn), - (mfn_valid(p2mfn) - ? get_gpfn_from_mfn(mfn_x(p2mfn)) - : -1u)); - /* This m2p entry is stale: the domain has another frame in - * this physical slot. No great disaster, but for neatness, - * blow away the m2p entry. */ - set_gpfn_from_mfn(mfn, INVALID_M2P_ENTRY); - } - - if ( test_linear && (gfn <= d->arch.max_mapped_pfn) ) - { - lp2mfn = gfn_to_mfn_current(gfn); - if ( mfn_x(lp2mfn) != mfn_x(p2mfn) ) - { - SHADOW_PRINTK("linear mismatch gfn %#lx -> mfn %#lx " - "(!= mfn %#lx)\n", gfn, - mfn_x(lp2mfn), mfn_x(p2mfn)); - } - } - - // SHADOW_PRINTK("OK: mfn=%#lx, gfn=%#lx, p2mfn=%#lx, lp2mfn=%#lx\n", - // mfn, gfn, p2mfn, lp2mfn); - } - - /* Audit part two: walk the domain's p2m table, checking the entries. */ - if ( pagetable_get_pfn(d->arch.phys_table) != 0 ) - { - l2_pgentry_t *l2e; - l1_pgentry_t *l1e; - int i1, i2; - -#if CONFIG_PAGING_LEVELS == 4 - l4_pgentry_t *l4e; - l3_pgentry_t *l3e; - int i3, i4; - l4e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#elif CONFIG_PAGING_LEVELS == 3 - l3_pgentry_t *l3e; - int i3; - l3e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#else /* CONFIG_PAGING_LEVELS == 2 */ - l2e = sh_map_domain_page(pagetable_get_mfn(d->arch.phys_table)); -#endif - - gfn = 0; -#if CONFIG_PAGING_LEVELS >= 3 -#if CONFIG_PAGING_LEVELS >= 4 - for ( i4 = 0; i4 < L4_PAGETABLE_ENTRIES; i4++ ) - { - if ( !(l4e_get_flags(l4e[i4]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L4_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l3e = sh_map_domain_page(_mfn(l4e_get_pfn(l4e[i4]))); -#endif /* now at levels 3 or 4... */ - for ( i3 = 0; - i3 < ((CONFIG_PAGING_LEVELS==4) ? L3_PAGETABLE_ENTRIES : 8); - i3++ ) - { - if ( !(l3e_get_flags(l3e[i3]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L3_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l2e = sh_map_domain_page(_mfn(l3e_get_pfn(l3e[i3]))); -#endif /* all levels... */ - for ( i2 = 0; i2 < L2_PAGETABLE_ENTRIES; i2++ ) - { - if ( !(l2e_get_flags(l2e[i2]) & _PAGE_PRESENT) ) - { - gfn += 1 << (L2_PAGETABLE_SHIFT - PAGE_SHIFT); - continue; - } - l1e = sh_map_domain_page(_mfn(l2e_get_pfn(l2e[i2]))); - - for ( i1 = 0; i1 < L1_PAGETABLE_ENTRIES; i1++, gfn++ ) - { - if ( !(l1e_get_flags(l1e[i1]) & _PAGE_PRESENT) ) - continue; - mfn = l1e_get_pfn(l1e[i1]); - ASSERT(mfn_valid(_mfn(mfn))); - m2pfn = get_gpfn_from_mfn(mfn); - if ( m2pfn != gfn ) - { - pmbad++; - SHADOW_PRINTK("mismatch: gfn %#lx -> mfn %#lx" - " -> gfn %#lx\n", gfn, mfn, m2pfn); - BUG(); - } - } - sh_unmap_domain_page(l1e); - } -#if CONFIG_PAGING_LEVELS >= 3 - sh_unmap_domain_page(l2e); - } -#if CONFIG_PAGING_LEVELS >= 4 - sh_unmap_domain_page(l3e); - } -#endif -#endif - -#if CONFIG_PAGING_LEVELS == 4 - sh_unmap_domain_page(l4e); -#elif CONFIG_PAGING_LEVELS == 3 - sh_unmap_domain_page(l3e); -#else /* CONFIG_PAGING_LEVELS == 2 */ - sh_unmap_domain_page(l2e); -#endif - - } - - //SHADOW_PRINTK("p2m audit complete\n"); - //if ( orphans_i | orphans_d | mpbad | pmbad ) - // SHADOW_PRINTK("p2m audit found %lu orphans (%lu inval %lu debug)\n", - // orphans_i + orphans_d, orphans_i, orphans_d, - if ( mpbad | pmbad ) - SHADOW_PRINTK("p2m audit found %lu odd p2m, %lu bad m2p entries\n", - pmbad, mpbad); -} - -#endif /* p2m audit */ - /* * Local variables: * mode: C diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 9e0d0e1fbf..5a1638df19 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -353,21 +353,21 @@ static inline void print_gw(walk_t *gw) SHADOW_PRINTK("GUEST WALK TO %#lx:\n", gw->va); #if GUEST_PAGING_LEVELS >= 3 /* PAE or 64... */ #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ - SHADOW_PRINTK(" l4mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l4mfn)); + SHADOW_PRINTK(" l4mfn=%" PRI_mfn "\n", mfn_x(gw->l4mfn)); SHADOW_PRINTK(" l4e=%p\n", gw->l4e); if ( gw->l4e ) SHADOW_PRINTK(" *l4e=%" SH_PRI_gpte "\n", gw->l4e->l4); #endif /* PAE or 64... */ - SHADOW_PRINTK(" l3mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l3mfn)); + SHADOW_PRINTK(" l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn)); SHADOW_PRINTK(" l3e=%p\n", gw->l3e); if ( gw->l3e ) SHADOW_PRINTK(" *l3e=%" SH_PRI_gpte "\n", gw->l3e->l3); #endif /* All levels... */ - SHADOW_PRINTK(" l2mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l2mfn)); + SHADOW_PRINTK(" l2mfn=%" PRI_mfn "\n", mfn_x(gw->l2mfn)); SHADOW_PRINTK(" l2e=%p\n", gw->l2e); if ( gw->l2e ) SHADOW_PRINTK(" *l2e=%" SH_PRI_gpte "\n", gw->l2e->l2); - SHADOW_PRINTK(" l1mfn=%" SH_PRI_mfn "\n", mfn_x(gw->l1mfn)); + SHADOW_PRINTK(" l1mfn=%" PRI_mfn "\n", mfn_x(gw->l1mfn)); SHADOW_PRINTK(" l1e=%p\n", gw->l1e); if ( gw->l1e ) SHADOW_PRINTK(" *l1e=%" SH_PRI_gpte "\n", gw->l1e->l1); @@ -1572,7 +1572,7 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) #if GUEST_PAGING_LEVELS == 4 #if (SHADOW_OPTIMIZATIONS & SHOPT_LINUX_L3_TOPLEVEL) if ( shadow_type == SH_type_l4_64_shadow && - unlikely(v->domain->arch.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) ) + unlikely(v->domain->arch.paging.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) ) { /* We're shadowing a new l4, but we've been assuming the guest uses * only one l4 per vcpu and context switches using an l4 entry. @@ -1584,7 +1584,7 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) struct shadow_page_info *sp; struct vcpu *v2; int l4count = 0, vcpus = 0; - list_for_each(l, &v->domain->arch.shadow.pinned_shadows) + list_for_each(l, &v->domain->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); if ( sp->type == SH_type_l4_64_shadow ) @@ -1595,13 +1595,13 @@ sh_make_shadow(struct vcpu *v, mfn_t gmfn, u32 shadow_type) if ( l4count > 2 * vcpus ) { /* Unpin all the pinned l3 tables, and don't pin any more. */ - list_for_each_safe(l, t, &v->domain->arch.shadow.pinned_shadows) + list_for_each_safe(l, t, &v->domain->arch.paging.shadow.pinned_shadows) { sp = list_entry(l, struct shadow_page_info, list); if ( sp->type == SH_type_l3_64_shadow ) sh_unpin(v, shadow_page_to_mfn(sp)); } - v->domain->arch.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL; + v->domain->arch.paging.shadow.opt_flags &= ~SHOPT_LINUX_L3_TOPLEVEL; } } #endif @@ -1641,7 +1641,7 @@ make_fl1_shadow(struct vcpu *v, gfn_t gfn) mfn_t smfn = shadow_alloc(v->domain, SH_type_fl1_shadow, (unsigned long) gfn_x(gfn)); - SHADOW_DEBUG(MAKE_SHADOW, "(%" SH_PRI_gfn ")=>%" SH_PRI_mfn "\n", + SHADOW_DEBUG(MAKE_SHADOW, "(%" SH_PRI_gfn ")=>%" PRI_mfn "\n", gfn_x(gfn), mfn_x(smfn)); set_fl1_shadow_status(v, gfn, smfn); @@ -1851,7 +1851,7 @@ static shadow_l2e_t * shadow_get_and_create_l2e(struct vcpu *v, #elif GUEST_PAGING_LEVELS == 3 /* PAE... */ /* We never demand-shadow PAE l3es: they are only created in * sh_update_cr3(). Check if the relevant sl3e is present. */ - shadow_l3e_t *sl3e = ((shadow_l3e_t *)&v->arch.shadow.l3table) + shadow_l3e_t *sl3e = ((shadow_l3e_t *)&v->arch.paging.shadow.l3table) + shadow_l3_linear_offset(gw->va); if ( !(shadow_l3e_get_flags(*sl3e) & _PAGE_PRESENT) ) return NULL; @@ -2358,7 +2358,7 @@ static int validate_gl1e(struct vcpu *v, void *new_ge, mfn_t sl1mfn, void *se) gfn = guest_l1e_get_gfn(*new_gl1e); gmfn = vcpu_gfn_to_mfn(v, gfn); - mmio = (is_hvm_vcpu(v) && shadow_vcpu_mode_translate(v) && !mfn_valid(gmfn)); + mmio = (is_hvm_vcpu(v) && paging_vcpu_mode_translate(v) && !mfn_valid(gmfn)); l1e_propagate_from_guest(v, new_gl1e, _mfn(INVALID_MFN), gmfn, &new_sl1e, ft_prefetch, mmio); @@ -2506,7 +2506,7 @@ sh_map_and_validate_gl1e(struct vcpu *v, mfn_t gl1mfn, static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) { #if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW - if ( v->arch.shadow.last_emulated_mfn == mfn_x(gmfn) && + if ( v->arch.paging.shadow.last_emulated_mfn == mfn_x(gmfn) && sh_mfn_is_a_page_table(gmfn) ) { u32 flags = mfn_to_page(gmfn)->shadow_flags; @@ -2516,7 +2516,7 @@ static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) sh_remove_shadows(v, gmfn, 1, 0 /* Fast, can fail to unshadow */ ); } } - v->arch.shadow.last_emulated_mfn = mfn_x(gmfn); + v->arch.paging.shadow.last_emulated_mfn = mfn_x(gmfn); #endif } @@ -2524,7 +2524,7 @@ static inline void check_for_early_unshadow(struct vcpu *v, mfn_t gmfn) static inline void reset_early_unshadow(struct vcpu *v) { #if SHADOW_OPTIMIZATIONS & SHOPT_EARLY_UNSHADOW - v->arch.shadow.last_emulated_mfn = INVALID_MFN; + v->arch.paging.shadow.last_emulated_mfn = INVALID_MFN; #endif } @@ -2589,7 +2589,7 @@ static void sh_prefetch(struct vcpu *v, walk_t *gw, gfn = guest_l1e_get_gfn(gl1e); gmfn = vcpu_gfn_to_mfn(v, gfn); mmio = ( is_hvm_vcpu(v) - && shadow_vcpu_mode_translate(v) + && paging_vcpu_mode_translate(v) && mmio_space(gfn_to_paddr(gfn)) ); /* Propagate the entry. Safe to use a pointer to our local @@ -2631,6 +2631,7 @@ static int sh_page_fault(struct vcpu *v, SHADOW_PRINTK("d:v=%u:%u va=%#lx err=%u\n", v->domain->domain_id, v->vcpu_id, va, regs->error_code); + perfc_incrc(shadow_fault); // // XXX: Need to think about eventually mapping superpages directly in the // shadow (when possible), as opposed to splintering them into a @@ -2651,7 +2652,7 @@ static int sh_page_fault(struct vcpu *v, if ( sh_l1e_is_gnp(sl1e) ) { if ( likely(!is_hvm_domain(d) || - shadow_vcpu_mode_translate(v)) ) + paging_vcpu_mode_translate(v)) ) { /* Not-present in a guest PT: pass to the guest as * a not-present fault (by flipping two bits). */ @@ -2701,7 +2702,7 @@ static int sh_page_fault(struct vcpu *v, if ( unlikely(shadow_locked_by_me(d)) ) { SHADOW_ERROR("Recursive shadow fault: lock was taken by %s\n", - d->arch.shadow.locker_function); + d->arch.paging.shadow.locker_function); return 0; } @@ -2726,7 +2727,7 @@ static int sh_page_fault(struct vcpu *v, // if ( unlikely(!(guest_l1e_get_flags(gw.eff_l1e) & _PAGE_PRESENT)) ) { - if ( is_hvm_domain(d) && !shadow_vcpu_mode_translate(v) ) + if ( is_hvm_domain(d) && !paging_vcpu_mode_translate(v) ) { /* Not present in p2m map, means this is mmio */ gpa = va; @@ -2784,13 +2785,13 @@ static int sh_page_fault(struct vcpu *v, gfn = guest_l1e_get_gfn(gw.eff_l1e); gmfn = vcpu_gfn_to_mfn(v, gfn); mmio = (is_hvm_domain(d) - && shadow_vcpu_mode_translate(v) + && paging_vcpu_mode_translate(v) && mmio_space(gfn_to_paddr(gfn))); if ( !mmio && !mfn_valid(gmfn) ) { perfc_incrc(shadow_fault_bail_bad_gfn); - SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"SH_PRI_mfn"\n", + SHADOW_PRINTK("BAD gfn=%"SH_PRI_gfn" gmfn=%"PRI_mfn"\n", gfn_x(gfn), mfn_x(gmfn)); goto not_a_shadow_fault; } @@ -2848,7 +2849,7 @@ static int sh_page_fault(struct vcpu *v, } perfc_incrc(shadow_fault_fixed); - d->arch.shadow.fault_count++; + d->arch.paging.shadow.fault_count++; reset_early_unshadow(v); done: @@ -2949,7 +2950,7 @@ sh_invlpg(struct vcpu *v, unsigned long va) return 0; } #elif SHADOW_PAGING_LEVELS == 3 - if ( !(l3e_get_flags(v->arch.shadow.l3table[shadow_l3_linear_offset(va)]) + if ( !(l3e_get_flags(v->arch.paging.shadow.l3table[shadow_l3_linear_offset(va)]) & _PAGE_PRESENT) ) // no need to flush anything if there's no SL2... return 0; @@ -3120,7 +3121,7 @@ sh_update_linear_entries(struct vcpu *v) } /* Shadow l3 tables are made up by sh_update_cr3 */ - sl3e = v->arch.shadow.l3table; + sl3e = v->arch.paging.shadow.l3table; for ( i = 0; i < SHADOW_L3_PAGETABLE_ENTRIES; i++ ) { @@ -3161,13 +3162,13 @@ sh_update_linear_entries(struct vcpu *v) #if GUEST_PAGING_LEVELS == 2 /* Shadow l3 tables were built by sh_update_cr3 */ if ( shadow_mode_external(d) ) - shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table; + shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; else BUG(); /* PV 2-on-3 is not supported yet */ #else /* GUEST_PAGING_LEVELS == 3 */ - shadow_l3e = (shadow_l3e_t *)&v->arch.shadow.l3table; + shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; /* Always safe to use guest_vtable, because it's globally mapped */ guest_l3e = v->arch.guest_vtable; @@ -3370,7 +3371,7 @@ sh_set_toplevel_shadow(struct vcpu *v, install_new_entry: /* Done. Install it */ - SHADOW_PRINTK("%u/%u [%u] gmfn %#"SH_PRI_mfn" smfn %#"SH_PRI_mfn"\n", + SHADOW_PRINTK("%u/%u [%u] gmfn %#"PRI_mfn" smfn %#"PRI_mfn"\n", GUEST_PAGING_LEVELS, SHADOW_PAGING_LEVELS, slot, mfn_x(gmfn), mfn_x(pagetable_get_mfn(new_entry))); v->arch.shadow_table[slot] = new_entry; @@ -3410,7 +3411,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) if ( do_locking ) shadow_lock(v->domain); ASSERT(shadow_locked_by_me(v->domain)); - ASSERT(v->arch.shadow.mode); + ASSERT(v->arch.paging.mode); //// //// vcpu->arch.guest_table is already set @@ -3425,7 +3426,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) ASSERT(shadow_mode_external(d)); // Is paging enabled on this vcpu? - if ( shadow_vcpu_mode_translate(v) ) + if ( paging_vcpu_mode_translate(v) ) { gfn = _gfn(paddr_to_pfn(hvm_get_guest_ctrl_reg(v, 3))); gmfn = vcpu_gfn_to_mfn(v, gfn); @@ -3472,7 +3473,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) sh_unmap_domain_page_global(v->arch.guest_vtable); if ( shadow_mode_external(d) ) { - if ( shadow_vcpu_mode_translate(v) ) + if ( paging_vcpu_mode_translate(v) ) /* Paging enabled: find where in the page the l3 table is */ guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); else @@ -3566,7 +3567,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) #endif /// - /// v->arch.shadow.l3table + /// v->arch.paging.shadow.l3table /// #if SHADOW_PAGING_LEVELS == 3 { @@ -3581,7 +3582,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* 3-on-3: make a PAE l3 that points at the four l2 pages */ smfn = pagetable_get_mfn(v->arch.shadow_table[i]); #endif - v->arch.shadow.l3table[i] = + v->arch.paging.shadow.l3table[i] = (mfn_x(smfn) == 0) ? shadow_l3e_empty() : shadow_l3e_from_mfn(smfn, _PAGE_PRESENT); @@ -3605,8 +3606,8 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated. * Don't use make_cr3 because (a) we know it's below 4GB, and * (b) it's not necessarily page-aligned, and make_cr3 takes a pfn */ - ASSERT(virt_to_maddr(&v->arch.shadow.l3table) <= 0xffffffe0ULL); - v->arch.cr3 = virt_to_maddr(&v->arch.shadow.l3table); + ASSERT(virt_to_maddr(&v->arch.paging.shadow.l3table) <= 0xffffffe0ULL); + v->arch.cr3 = virt_to_maddr(&v->arch.paging.shadow.l3table); #else /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */ make_cr3(v, pagetable_get_pfn(v->arch.shadow_table[0])); @@ -3622,7 +3623,7 @@ sh_update_cr3(struct vcpu *v, int do_locking) ASSERT(is_hvm_domain(d)); #if SHADOW_PAGING_LEVELS == 3 /* 2-on-3 or 3-on-3: Use the PAE shadow l3 table we just fabricated */ - hvm_update_guest_cr3(v, virt_to_maddr(&v->arch.shadow.l3table)); + hvm_update_guest_cr3(v, virt_to_maddr(&v->arch.paging.shadow.l3table)); #else /* 2-on-2 or 4-on-4: Just use the shadow top-level directly */ hvm_update_guest_cr3(v, pagetable_get_paddr(v->arch.shadow_table[0])); @@ -3665,7 +3666,7 @@ static int sh_guess_wrmap(struct vcpu *v, unsigned long vaddr, mfn_t gmfn) if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) ) return 0; #elif SHADOW_PAGING_LEVELS == 3 - sl3p = ((shadow_l3e_t *) v->arch.shadow.l3table) + sl3p = ((shadow_l3e_t *) v->arch.paging.shadow.l3table) + shadow_l3_linear_offset(vaddr); if ( !(shadow_l3e_get_flags(*sl3p) & _PAGE_PRESENT) ) return 0; @@ -3709,7 +3710,7 @@ int sh_rm_write_access_from_l1(struct vcpu *v, mfn_t sl1mfn, (void) shadow_set_l1e(v, sl1e, ro_sl1e, sl1mfn); #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC /* Remember the last shadow that we shot a writeable mapping in */ - v->arch.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn); + v->arch.paging.shadow.last_writeable_pte_smfn = mfn_x(base_sl1mfn); #endif if ( (mfn_to_page(readonly_mfn)->u.inuse.type_info & PGT_count_mask) == 0 ) @@ -4050,8 +4051,8 @@ sh_x86_emulate_cmpxchg8b(struct vcpu *v, unsigned long vaddr, #define AUDIT_FAIL(_level, _fmt, _a...) do { \ printk("Shadow %u-on-%u audit failed at level %i, index %i\n" \ - "gl" #_level "mfn = %" SH_PRI_mfn \ - " sl" #_level "mfn = %" SH_PRI_mfn \ + "gl" #_level "mfn = %" PRI_mfn \ + " sl" #_level "mfn = %" PRI_mfn \ " &gl" #_level "e = %p &sl" #_level "e = %p" \ " gl" #_level "e = %" SH_PRI_gpte \ " sl" #_level "e = %" SH_PRI_pte "\nError: " _fmt "\n", \ @@ -4105,7 +4106,7 @@ audit_gfn_to_mfn(struct vcpu *v, gfn_t gfn, mfn_t gmfn) != PGT_writable_page ) return _mfn(gfn_x(gfn)); /* This is a paging-disabled shadow */ else - return sh_gfn_to_mfn(v->domain, gfn_x(gfn)); + return gfn_to_mfn(v->domain, gfn_x(gfn)); } @@ -4156,7 +4157,7 @@ int sh_audit_l1_table(struct vcpu *v, mfn_t sl1mfn, mfn_t x) gmfn = audit_gfn_to_mfn(v, gfn, gl1mfn); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(1, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } } @@ -4219,8 +4220,8 @@ int sh_audit_l2_table(struct vcpu *v, mfn_t sl2mfn, mfn_t x) SH_type_l1_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(2, "bad translation: gfn %" SH_PRI_gfn - " (--> %" SH_PRI_mfn ")" - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " (--> %" PRI_mfn ")" + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), (guest_l2e_get_flags(*gl2e) & _PAGE_PSE) ? 0 : mfn_x(audit_gfn_to_mfn(v, gfn, gl2mfn)), @@ -4262,7 +4263,7 @@ int sh_audit_l3_table(struct vcpu *v, mfn_t sl3mfn, mfn_t x) : SH_type_l2_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(3, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } }); @@ -4297,7 +4298,7 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x) SH_type_l3_shadow); if ( mfn_x(gmfn) != mfn_x(mfn) ) AUDIT_FAIL(4, "bad translation: gfn %" SH_PRI_gfn - " --> %" SH_PRI_mfn " != mfn %" SH_PRI_mfn, + " --> %" PRI_mfn " != mfn %" PRI_mfn, gfn_x(gfn), mfn_x(gmfn), mfn_x(mfn)); } }); @@ -4314,30 +4315,29 @@ int sh_audit_l4_table(struct vcpu *v, mfn_t sl4mfn, mfn_t x) /**************************************************************************/ /* Entry points into this mode of the shadow code. * This will all be mangled by the preprocessor to uniquify everything. */ -struct shadow_paging_mode sh_paging_mode = { - .page_fault = sh_page_fault, - .invlpg = sh_invlpg, - .gva_to_gpa = sh_gva_to_gpa, - .gva_to_gfn = sh_gva_to_gfn, - .update_cr3 = sh_update_cr3, - .map_and_validate_gl1e = sh_map_and_validate_gl1e, - .map_and_validate_gl2e = sh_map_and_validate_gl2e, - .map_and_validate_gl2he = sh_map_and_validate_gl2he, - .map_and_validate_gl3e = sh_map_and_validate_gl3e, - .map_and_validate_gl4e = sh_map_and_validate_gl4e, - .detach_old_tables = sh_detach_old_tables, - .x86_emulate_write = sh_x86_emulate_write, - .x86_emulate_cmpxchg = sh_x86_emulate_cmpxchg, - .x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b, - .make_monitor_table = sh_make_monitor_table, - .destroy_monitor_table = sh_destroy_monitor_table, - .guest_map_l1e = sh_guest_map_l1e, - .guest_get_eff_l1e = sh_guest_get_eff_l1e, +struct paging_mode sh_paging_mode = { + .page_fault = sh_page_fault, + .invlpg = sh_invlpg, + .gva_to_gpa = sh_gva_to_gpa, + .gva_to_gfn = sh_gva_to_gfn, + .update_cr3 = sh_update_cr3, + .update_paging_modes = shadow_update_paging_modes, + .write_p2m_entry = shadow_write_p2m_entry, + .write_guest_entry = shadow_write_guest_entry, + .cmpxchg_guest_entry = shadow_cmpxchg_guest_entry, + .guest_map_l1e = sh_guest_map_l1e, + .guest_get_eff_l1e = sh_guest_get_eff_l1e, + .guest_levels = GUEST_PAGING_LEVELS, + .shadow.detach_old_tables = sh_detach_old_tables, + .shadow.x86_emulate_write = sh_x86_emulate_write, + .shadow.x86_emulate_cmpxchg = sh_x86_emulate_cmpxchg, + .shadow.x86_emulate_cmpxchg8b = sh_x86_emulate_cmpxchg8b, + .shadow.make_monitor_table = sh_make_monitor_table, + .shadow.destroy_monitor_table = sh_destroy_monitor_table, #if SHADOW_OPTIMIZATIONS & SHOPT_WRITABLE_HEURISTIC - .guess_wrmap = sh_guess_wrmap, + .shadow.guess_wrmap = sh_guess_wrmap, #endif - .guest_levels = GUEST_PAGING_LEVELS, - .shadow_levels = SHADOW_PAGING_LEVELS, + .shadow.shadow_levels = SHADOW_PAGING_LEVELS, }; /* diff --git a/xen/arch/x86/mm/shadow/multi.h b/xen/arch/x86/mm/shadow/multi.h index 97903059d4..323c0c7e64 100644 --- a/xen/arch/x86/mm/shadow/multi.h +++ b/xen/arch/x86/mm/shadow/multi.h @@ -115,5 +115,5 @@ SHADOW_INTERNAL_NAME(sh_destroy_monitor_table, SHADOW_LEVELS, GUEST_LEVELS) (struct vcpu *v, mfn_t mmfn); #endif -extern struct shadow_paging_mode +extern struct paging_mode SHADOW_INTERNAL_NAME(sh_paging_mode, SHADOW_LEVELS, GUEST_LEVELS); diff --git a/xen/arch/x86/mm/shadow/private.h b/xen/arch/x86/mm/shadow/private.h index 21d78eb2de..44c0c37c47 100644 --- a/xen/arch/x86/mm/shadow/private.h +++ b/xen/arch/x86/mm/shadow/private.h @@ -41,13 +41,12 @@ #define SHADOW_AUDIT_ENTRIES 0x04 /* Check this walk's shadows */ #define SHADOW_AUDIT_ENTRIES_FULL 0x08 /* Check every shadow */ #define SHADOW_AUDIT_ENTRIES_MFNS 0x10 /* Check gfn-mfn map in shadows */ -#define SHADOW_AUDIT_P2M 0x20 /* Check the p2m table */ #ifdef NDEBUG #define SHADOW_AUDIT 0 #define SHADOW_AUDIT_ENABLE 0 #else -#define SHADOW_AUDIT 0x15 /* Basic audit of all except p2m. */ +#define SHADOW_AUDIT 0x15 /* Basic audit of all */ #define SHADOW_AUDIT_ENABLE shadow_audit_enable extern int shadow_audit_enable; #endif @@ -84,9 +83,9 @@ extern int shadow_audit_enable; #define SHADOW_DEBUG_PROPAGATE 1 #define SHADOW_DEBUG_MAKE_SHADOW 1 #define SHADOW_DEBUG_DESTROY_SHADOW 1 -#define SHADOW_DEBUG_P2M 0 #define SHADOW_DEBUG_A_AND_D 1 #define SHADOW_DEBUG_EMULATE 1 +#define SHADOW_DEBUG_P2M 1 #define SHADOW_DEBUG_LOGDIRTY 0 /****************************************************************************** @@ -108,36 +107,36 @@ extern int shadow_audit_enable; #error shadow.h currently requires CONFIG_SMP #endif -#define shadow_lock_init(_d) \ - do { \ - spin_lock_init(&(_d)->arch.shadow.lock); \ - (_d)->arch.shadow.locker = -1; \ - (_d)->arch.shadow.locker_function = "nobody"; \ +#define shadow_lock_init(_d) \ + do { \ + spin_lock_init(&(_d)->arch.paging.shadow.lock); \ + (_d)->arch.paging.shadow.locker = -1; \ + (_d)->arch.paging.shadow.locker_function = "nobody"; \ } while (0) #define shadow_locked_by_me(_d) \ - (current->processor == (_d)->arch.shadow.locker) + (current->processor == (_d)->arch.paging.shadow.locker) -#define shadow_lock(_d) \ - do { \ - if ( unlikely((_d)->arch.shadow.locker == current->processor) ) \ - { \ - printk("Error: shadow lock held by %s\n", \ - (_d)->arch.shadow.locker_function); \ - BUG(); \ - } \ - spin_lock(&(_d)->arch.shadow.lock); \ - ASSERT((_d)->arch.shadow.locker == -1); \ - (_d)->arch.shadow.locker = current->processor; \ - (_d)->arch.shadow.locker_function = __func__; \ +#define shadow_lock(_d) \ + do { \ + if ( unlikely((_d)->arch.paging.shadow.locker == current->processor) )\ + { \ + printk("Error: shadow lock held by %s\n", \ + (_d)->arch.paging.shadow.locker_function); \ + BUG(); \ + } \ + spin_lock(&(_d)->arch.paging.shadow.lock); \ + ASSERT((_d)->arch.paging.shadow.locker == -1); \ + (_d)->arch.paging.shadow.locker = current->processor; \ + (_d)->arch.paging.shadow.locker_function = __func__; \ } while (0) -#define shadow_unlock(_d) \ - do { \ - ASSERT((_d)->arch.shadow.locker == current->processor); \ - (_d)->arch.shadow.locker = -1; \ - (_d)->arch.shadow.locker_function = "nobody"; \ - spin_unlock(&(_d)->arch.shadow.lock); \ +#define shadow_unlock(_d) \ + do { \ + ASSERT((_d)->arch.paging.shadow.locker == current->processor); \ + (_d)->arch.paging.shadow.locker = -1; \ + (_d)->arch.paging.shadow.locker_function = "nobody"; \ + spin_unlock(&(_d)->arch.paging.shadow.lock); \ } while (0) @@ -152,13 +151,6 @@ extern void shadow_audit_tables(struct vcpu *v); #define shadow_audit_tables(_v) do {} while(0) #endif -#if SHADOW_AUDIT & SHADOW_AUDIT_P2M -extern void shadow_audit_p2m(struct domain *d); -#else -#define shadow_audit_p2m(_d) do {} while(0) -#endif - - /****************************************************************************** * Macro for dealing with the naming of the internal names of the * shadow code's external entry points. @@ -304,7 +296,7 @@ static inline int sh_type_is_pinnable(struct vcpu *v, unsigned int t) * page. When we're shadowing those kernels, we have to pin l3 * shadows so they don't just evaporate on every context switch. * For all other guests, we'd rather use the up-pointer field in l3s. */ - if ( unlikely((v->domain->arch.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) + if ( unlikely((v->domain->arch.paging.shadow.opt_flags & SHOPT_LINUX_L3_TOPLEVEL) && CONFIG_PAGING_LEVELS >= 4 && t == SH_type_l3_64_shadow) ) return 1; @@ -379,12 +371,11 @@ void sh_install_xen_entries_in_l2h(struct vcpu *v, mfn_t sl2hmfn); void sh_install_xen_entries_in_l2(struct vcpu *v, mfn_t gl2mfn, mfn_t sl2mfn); /* Update the shadows in response to a pagetable write from Xen */ -extern int sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, - void *entry, u32 size); +int sh_validate_guest_entry(struct vcpu *v, mfn_t gmfn, void *entry, u32 size); /* Update the shadows in response to a pagetable write from a HVM guest */ -extern void sh_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, - void *entry, u32 size); +void sh_validate_guest_pt_write(struct vcpu *v, mfn_t gmfn, + void *entry, u32 size); /* Remove all writeable mappings of a guest frame from the shadows. * Returns non-zero if we need to flush TLBs. @@ -394,6 +385,21 @@ extern int sh_remove_write_access(struct vcpu *v, mfn_t readonly_mfn, unsigned int level, unsigned long fault_addr); +/* Allocate/free functions for passing to the P2M code. */ +struct page_info *shadow_alloc_p2m_page(struct domain *d); +void shadow_free_p2m_page(struct domain *d, struct page_info *pg); + +/* Functions that atomically write PT/P2M entries and update state */ +void shadow_write_p2m_entry(struct vcpu *v, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); +int shadow_write_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn); +int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, mfn_t gmfn); + + + /****************************************************************************** * Flags used in the return value of the shadow_set_lXe() functions... */ @@ -477,19 +483,6 @@ sh_unmap_domain_page_global(void *p) unmap_domain_page_global(p); } -static inline mfn_t -pagetable_get_mfn(pagetable_t pt) -{ - return _mfn(pagetable_get_pfn(pt)); -} - -static inline pagetable_t -pagetable_from_mfn(mfn_t mfn) -{ - return pagetable_from_pfn(mfn_x(mfn)); -} - - /****************************************************************************** * Log-dirty mode bitmap handling */ @@ -502,13 +495,13 @@ sh_mfn_is_dirty(struct domain *d, mfn_t gmfn) { unsigned long pfn; ASSERT(shadow_mode_log_dirty(d)); - ASSERT(d->arch.shadow.dirty_bitmap != NULL); + ASSERT(d->arch.paging.shadow.dirty_bitmap != NULL); /* We /really/ mean PFN here, even for non-translated guests. */ pfn = get_gpfn_from_mfn(mfn_x(gmfn)); if ( likely(VALID_M2P(pfn)) - && likely(pfn < d->arch.shadow.dirty_bitmap_size) - && test_bit(pfn, d->arch.shadow.dirty_bitmap) ) + && likely(pfn < d->arch.paging.shadow.dirty_bitmap_size) + && test_bit(pfn, d->arch.paging.shadow.dirty_bitmap) ) return 1; return 0; @@ -612,7 +605,7 @@ static inline int sh_pin(struct vcpu *v, mfn_t smfn) sp->pinned = 1; } /* Put it at the head of the list of pinned shadows */ - list_add(&sp->list, &v->domain->arch.shadow.pinned_shadows); + list_add(&sp->list, &v->domain->arch.paging.shadow.pinned_shadows); return 1; } diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h index e2edebe555..b94289e674 100644 --- a/xen/arch/x86/mm/shadow/types.h +++ b/xen/arch/x86/mm/shadow/types.h @@ -414,15 +414,9 @@ valid_gfn(gfn_t m) static inline mfn_t vcpu_gfn_to_mfn(struct vcpu *v, gfn_t gfn) { - if ( !shadow_vcpu_mode_translate(v) ) + if ( !paging_vcpu_mode_translate(v) ) return _mfn(gfn_x(gfn)); - return sh_gfn_to_mfn(v->domain, gfn_x(gfn)); -} - -static inline gfn_t -mfn_to_gfn(struct domain *d, mfn_t mfn) -{ - return _gfn(sh_mfn_to_gfn(d, mfn)); + return gfn_to_mfn(v->domain, gfn_x(gfn)); } static inline paddr_t diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 0e010e2724..bb15e9b955 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -29,7 +29,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/xen/arch/x86/sysctl.c b/xen/arch/x86/sysctl.c index 0f265825bd..fe4c049908 100644 --- a/xen/arch/x86/sysctl.c +++ b/xen/arch/x86/sysctl.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/traps.c b/xen/arch/x86/traps.c index dfa22bce04..83be2a3032 100644 --- a/xen/arch/x86/traps.c +++ b/xen/arch/x86/traps.c @@ -46,7 +46,7 @@ #include #include #include -#include +#include #include #include #include @@ -860,8 +860,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) if ( unlikely(IN_HYPERVISOR_RANGE(addr)) ) { - if ( shadow_mode_external(d) && guest_mode(regs) ) - return shadow_fault(addr, regs); + if ( paging_mode_external(d) && guest_mode(regs) ) + return paging_fault(addr, regs); if ( (addr >= GDT_LDT_VIRT_START) && (addr < GDT_LDT_VIRT_END) ) return handle_gdt_ldt_mapping_fault( addr - GDT_LDT_VIRT_START, regs); @@ -876,8 +876,8 @@ static int fixup_page_fault(unsigned long addr, struct cpu_user_regs *regs) ptwr_do_page_fault(v, addr, regs) ) return EXCRET_fault_fixed; - if ( shadow_mode_enabled(d) ) - return shadow_fault(addr, regs); + if ( paging_mode_enabled(d) ) + return paging_fault(addr, regs); return 0; } diff --git a/xen/arch/x86/x86_32/domain_page.c b/xen/arch/x86/x86_32/domain_page.c index 9080de1a87..cb414df253 100644 --- a/xen/arch/x86/x86_32/domain_page.c +++ b/xen/arch/x86/x86_32/domain_page.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/arch/x86/x86_64/traps.c b/xen/arch/x86/x86_64/traps.c index 65d9c427dc..0c6ee1de35 100644 --- a/xen/arch/x86/x86_64/traps.c +++ b/xen/arch/x86/x86_64/traps.c @@ -16,7 +16,6 @@ #include #include #include -#include #include #include #include diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index 83315353e1..b148d5682e 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -58,19 +58,22 @@ extern void toggle_guest_mode(struct vcpu *); */ extern void hypercall_page_initialise(struct domain *d, void *); +/************************************************/ +/* shadow paging extension */ +/************************************************/ struct shadow_domain { - u32 mode; /* flags to control shadow operation */ spinlock_t lock; /* shadow domain lock */ int locker; /* processor which holds the lock */ const char *locker_function; /* Func that took it */ + unsigned int opt_flags; /* runtime tunable optimizations on/off */ + struct list_head pinned_shadows; + + /* Memory allocation */ struct list_head freelists[SHADOW_MAX_ORDER + 1]; struct list_head p2m_freelist; - struct list_head p2m_inuse; - struct list_head pinned_shadows; unsigned int total_pages; /* number of pages allocated */ unsigned int free_pages; /* number of pages on freelists */ - unsigned int p2m_pages; /* number of pages in p2m map */ - unsigned int opt_flags; /* runtime tunable optimizations on/off */ + unsigned int p2m_pages; /* number of pages allocates to p2m */ /* Shadow hashtable */ struct shadow_page_info **hash_table; @@ -85,6 +88,61 @@ struct shadow_domain { unsigned int dirty_count; }; +struct shadow_vcpu { +#if CONFIG_PAGING_LEVELS >= 3 + /* PAE guests: per-vcpu shadow top-level table */ + l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); +#endif + /* Last MFN that we emulated a write to. */ + unsigned long last_emulated_mfn; + /* MFN of the last shadow that we shot a writeable mapping in */ + unsigned long last_writeable_pte_smfn; +}; + +/************************************************/ +/* p2m handling */ +/************************************************/ + +struct p2m_domain { + /* Lock that protects updates to the p2m */ + spinlock_t lock; + int locker; /* processor which holds the lock */ + const char *locker_function; /* Func that took it */ + + /* Pages used to construct the p2m */ + struct list_head pages; + + /* Functions to call to get or free pages for the p2m */ + struct page_info * (*alloc_page )(struct domain *d); + void (*free_page )(struct domain *d, + struct page_info *pg); + + /* Highest guest frame that's ever been mapped in the p2m */ + unsigned long max_mapped_pfn; +}; + +/************************************************/ +/* common paging data structure */ +/************************************************/ +struct paging_domain { + u32 mode; /* flags to control paging operation */ + + /* extension for shadow paging support */ + struct shadow_domain shadow; + + /* Other paging assistance code will have structs here */ +}; + +struct paging_vcpu { + /* Pointers to mode-specific entry points. */ + struct paging_mode *mode; + /* HVM guest: paging enabled (CR0.PG)? */ + unsigned int translate_enabled:1; + + /* paging support extension */ + struct shadow_vcpu shadow; +}; + struct arch_domain { l1_pgentry_t *mm_perdomain_pt; @@ -108,12 +166,11 @@ struct arch_domain struct hvm_domain hvm_domain; - struct shadow_domain shadow; + struct paging_domain paging; + struct p2m_domain p2m ; /* Shadow translated domain: P2M mapping */ pagetable_t phys_table; - /* Highest guest frame that's ever been mapped in the p2m */ - unsigned long max_mapped_pfn; /* Pseudophysical e820 map (XENMEM_memory_map). */ struct e820entry e820[3]; @@ -139,21 +196,6 @@ struct pae_l3_cache { }; #define pae_l3_cache_init(c) ((void)0) #endif -struct shadow_vcpu { -#if CONFIG_PAGING_LEVELS >= 3 - /* PAE guests: per-vcpu shadow top-level table */ - l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); -#endif - /* Pointers to mode-specific entry points. */ - struct shadow_paging_mode *mode; - /* Last MFN that we emulated a write to. */ - unsigned long last_emulated_mfn; - /* MFN of the last shadow that we shot a writeable mapping in */ - unsigned long last_writeable_pte_smfn; - /* HVM guest: paging enabled (CR0.PG)? */ - unsigned int translate_enabled:1; -}; - struct arch_vcpu { /* Needs 16-byte aligment for FXSAVE/FXRSTOR. */ @@ -205,7 +247,7 @@ struct arch_vcpu /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; - struct shadow_vcpu shadow; + struct paging_vcpu paging; } __cacheline_aligned; /* shorthands to improve code legibility */ diff --git a/xen/include/asm-x86/mm.h b/xen/include/asm-x86/mm.h index 405a753b39..334d581479 100644 --- a/xen/include/asm-x86/mm.h +++ b/xen/include/asm-x86/mm.h @@ -246,6 +246,64 @@ pae_copy_root(struct vcpu *v, l3_pgentry_t *l3tab); int check_descriptor(const struct domain *, struct desc_struct *d); + +/****************************************************************************** + * With shadow pagetables, the different kinds of address start + * to get get confusing. + * + * Virtual addresses are what they usually are: the addresses that are used + * to accessing memory while the guest is running. The MMU translates from + * virtual addresses to machine addresses. + * + * (Pseudo-)physical addresses are the abstraction of physical memory the + * guest uses for allocation and so forth. For the purposes of this code, + * we can largely ignore them. + * + * Guest frame numbers (gfns) are the entries that the guest puts in its + * pagetables. For normal paravirtual guests, they are actual frame numbers, + * with the translation done by the guest. + * + * Machine frame numbers (mfns) are the entries that the hypervisor puts + * in the shadow page tables. + * + * Elsewhere in the xen code base, the name "gmfn" is generally used to refer + * to a "machine frame number, from the guest's perspective", or in other + * words, pseudo-physical frame numbers. However, in the shadow code, the + * term "gmfn" means "the mfn of a guest page"; this combines naturally with + * other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a + * guest L2 page), etc... + */ + +/* With this defined, we do some ugly things to force the compiler to + * give us type safety between mfns and gfns and other integers. + * TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions + * that translate beween int and foo_t. + * + * It does have some performance cost because the types now have + * a different storage attribute, so may not want it on all the time. */ + +#ifndef NDEBUG +#define TYPE_SAFETY 1 +#endif + +#ifdef TYPE_SAFETY +#define TYPE_SAFE(_type,_name) \ +typedef struct { _type _name; } _name##_t; \ +static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \ +static inline _type _name##_x(_name##_t n) { return n._name; } +#else +#define TYPE_SAFE(_type,_name) \ +typedef _type _name##_t; \ +static inline _name##_t _##_name(_type n) { return n; } \ +static inline _type _name##_x(_name##_t n) { return n; } +#endif + +TYPE_SAFE(unsigned long,mfn); + +/* Macro for printk formats: use as printk("%"PRI_mfn"\n", mfn_x(foo)); */ +#define PRI_mfn "05lx" + + /* * The MPT (machine->physical mapping table) is an array of word-sized * values, indexed on machine frame number. It is expected that guest OSes @@ -269,13 +327,12 @@ int check_descriptor(const struct domain *, struct desc_struct *d); #endif #define get_gpfn_from_mfn(mfn) (machine_to_phys_mapping[(mfn)]) - #define mfn_to_gmfn(_d, mfn) \ - ( (shadow_mode_translate(_d)) \ + ( (paging_mode_translate(_d)) \ ? get_gpfn_from_mfn(mfn) \ : (mfn) ) -#define gmfn_to_mfn(_d, gpfn) mfn_x(sh_gfn_to_mfn(_d, gpfn)) +#define gmfn_to_mfn(_d, gpfn) mfn_x(gfn_to_mfn(_d, gpfn)) #define INVALID_MFN (~0UL) diff --git a/xen/include/asm-x86/p2m.h b/xen/include/asm-x86/p2m.h new file mode 100644 index 0000000000..89c030977f --- /dev/null +++ b/xen/include/asm-x86/p2m.h @@ -0,0 +1,142 @@ +/****************************************************************************** + * include/asm-x86/paging.h + * + * physical-to-machine mappings for automatically-translated domains. + * + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_P2M_H +#define _XEN_P2M_H + + +/* The phys_to_machine_mapping is the reversed mapping of MPT for full + * virtualization. It is only used by shadow_mode_translate()==true + * guests, so we steal the address space that would have normally + * been used by the read-only MPT map. + */ +#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START) + + +/* Read the current domain's P2M table. */ +static inline mfn_t gfn_to_mfn_current(unsigned long gfn) +{ + l1_pgentry_t l1e = l1e_empty(); + int ret; + + if ( gfn > current->domain->arch.p2m.max_mapped_pfn ) + return _mfn(INVALID_MFN); + + /* Don't read off the end of the p2m table */ + ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t)); + + ret = __copy_from_user(&l1e, + &phys_to_machine_mapping[gfn], + sizeof(l1e)); + + if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) ) + return _mfn(l1e_get_pfn(l1e)); + + return _mfn(INVALID_MFN); +} + +/* Read another domain's P2M table, mapping pages as we go */ +mfn_t gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn); + +/* General conversion function from gfn to mfn */ +static inline mfn_t gfn_to_mfn(struct domain *d, unsigned long gfn) +{ + if ( !paging_mode_translate(d) ) + return _mfn(gfn); + if ( likely(current->domain == d) ) + return gfn_to_mfn_current(gfn); + else + return gfn_to_mfn_foreign(d, gfn); +} + +/* General conversion function from mfn to gfn */ +static inline unsigned long mfn_to_gfn(struct domain *d, mfn_t mfn) +{ + if ( paging_mode_translate(d) ) + return get_gpfn_from_mfn(mfn_x(mfn)); + else + return mfn_x(mfn); +} + +/* Compatibility function for HVM code */ +static inline unsigned long get_mfn_from_gpfn(unsigned long pfn) +{ + return mfn_x(gfn_to_mfn_current(pfn)); +} + +/* Is this guest address an mmio one? (i.e. not defined in p2m map) */ +static inline int mmio_space(paddr_t gpa) +{ + unsigned long gfn = gpa >> PAGE_SHIFT; + return !mfn_valid(mfn_x(gfn_to_mfn_current(gfn))); +} + +/* Translate the frame number held in an l1e from guest to machine */ +static inline l1_pgentry_t +gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e) +{ + if ( unlikely(paging_mode_translate(d)) ) + l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)), + l1e_get_flags(l1e)); + return l1e; +} + + + +/* Init the datastructures for later use by the p2m code */ +void p2m_init(struct domain *d); + +/* Allocate a new p2m table for a domain. + * + * The alloc_page and free_page functions will be used to get memory to + * build the p2m, and to release it again at the end of day. + * + * Returns 0 for success or -errno. */ +int p2m_alloc_table(struct domain *d, + struct page_info * (*alloc_page)(struct domain *d), + void (*free_page)(struct domain *d, struct page_info *pg)); + +/* Return all the p2m resources to Xen. */ +void p2m_teardown(struct domain *d); + +/* Add a page to a domain's p2m table */ +void guest_physmap_add_page(struct domain *d, unsigned long gfn, + unsigned long mfn); + +/* Remove a page from a domain's p2m table */ +void guest_physmap_remove_page(struct domain *d, unsigned long gfn, + unsigned long mfn); + + +#endif /* _XEN_P2M_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 53ddc287fc..1adc4b481d 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -208,8 +208,10 @@ typedef struct { u64 pfn; } pagetable_t; #define pagetable_get_paddr(x) ((paddr_t)(x).pfn << PAGE_SHIFT) #define pagetable_get_page(x) mfn_to_page((x).pfn) #define pagetable_get_pfn(x) ((x).pfn) +#define pagetable_get_mfn(x) _mfn(((x).pfn)) #define pagetable_is_null(x) ((x).pfn == 0) #define pagetable_from_pfn(pfn) ((pagetable_t) { (pfn) }) +#define pagetable_from_mfn(mfn) ((pagetable_t) { mfn_x(mfn) }) #define pagetable_from_page(pg) pagetable_from_pfn(page_to_mfn(pg)) #define pagetable_from_paddr(p) pagetable_from_pfn((p)>>PAGE_SHIFT) #define pagetable_null() pagetable_from_pfn(0) diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h new file mode 100644 index 0000000000..63ef49d693 --- /dev/null +++ b/xen/include/asm-x86/paging.h @@ -0,0 +1,376 @@ +/****************************************************************************** + * include/asm-x86/paging.h + * + * Common interface for paging support + * Copyright (c) 2007 Advanced Micro Devices (Wei Huang) + * Parts of this code are Copyright (c) 2006 by XenSource Inc. + * Parts of this code are Copyright (c) 2006 by Michael A Fetterman + * Parts based on earlier work by Michael A Fetterman, Ian Pratt et al. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef _XEN_PAGING_H +#define _XEN_PAGING_H + +#include +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * Macros to tell which paging mode a domain is in */ + +#define PG_SH_shift 20 +#define PG_HAP_shift 21 +/* We're in one of the shadow modes */ +#define PG_SH_enable (1U << PG_SH_shift) +#define PG_HAP_enable (1U << PG_HAP_shift) + +/* common paging mode bits */ +#define PG_mode_shift 10 +/* Refcounts based on shadow tables instead of guest tables */ +#define PG_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << PG_mode_shift) +/* Enable log dirty mode */ +#define PG_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << PG_mode_shift) +/* Xen does p2m translation, not guest */ +#define PG_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << PG_mode_shift) +/* Xen does not steal address space from the domain for its own booking; + * requires VT or similar mechanisms */ +#define PG_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << PG_mode_shift) + +#define paging_mode_enabled(_d) ((_d)->arch.paging.mode) +#define paging_mode_shadow(_d) ((_d)->arch.paging.mode & PG_SH_enable) +#define paging_mode_hap(_d) ((_d)->arch.paging.mode & PG_HAP_enable) + +#define paging_mode_refcounts(_d) ((_d)->arch.paging.mode & PG_refcounts) +#define paging_mode_log_dirty(_d) ((_d)->arch.paging.mode & PG_log_dirty) +#define paging_mode_translate(_d) ((_d)->arch.paging.mode & PG_translate) +#define paging_mode_external(_d) ((_d)->arch.paging.mode & PG_external) + +/****************************************************************************** + * The equivalent for a particular vcpu of a shadowed domain. */ + +/* Is this vcpu using the P2M table to translate between GFNs and MFNs? + * + * This is true of translated HVM domains on a vcpu which has paging + * enabled. (HVM vcpus with paging disabled are using the p2m table as + * its paging table, so no translation occurs in this case.) + * It is also true for all vcpus of translated PV domains. */ +#define paging_vcpu_mode_translate(_v) ((_v)->arch.paging.translate_enabled) + + + +/***************************************************************************** + * Mode-specific entry points into the shadow code. + * + * These shouldn't be used directly by callers; rather use the functions + * below which will indirect through this table as appropriate. */ + +struct sh_emulate_ctxt; +struct shadow_paging_mode { + void (*detach_old_tables )(struct vcpu *v); + int (*x86_emulate_write )(struct vcpu *v, unsigned long va, + void *src, u32 bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va, + unsigned long old, + unsigned long new, + unsigned int bytes, + struct sh_emulate_ctxt *sh_ctxt); + int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va, + unsigned long old_lo, + unsigned long old_hi, + unsigned long new_lo, + unsigned long new_hi, + struct sh_emulate_ctxt *sh_ctxt); + mfn_t (*make_monitor_table )(struct vcpu *v); + void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); + int (*guess_wrmap )(struct vcpu *v, + unsigned long vaddr, mfn_t gmfn); + /* For outsiders to tell what mode we're in */ + unsigned int shadow_levels; +}; + + +/************************************************/ +/* common paging interface */ +/************************************************/ +struct paging_mode { + int (*page_fault )(struct vcpu *v, unsigned long va, + struct cpu_user_regs *regs); + int (*invlpg )(struct vcpu *v, unsigned long va); + paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va); + unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va); + void (*update_cr3 )(struct vcpu *v, int do_locking); + void (*update_paging_modes )(struct vcpu *v); + void (*write_p2m_entry )(struct vcpu *v, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level); + int (*write_guest_entry )(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn); + int (*cmpxchg_guest_entry )(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, + mfn_t gmfn); + void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, + unsigned long *gl1mfn); + void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, + void *eff_l1e); + unsigned int guest_levels; + + /* paging support extension */ + struct shadow_paging_mode shadow; +}; + + +/***************************************************************************** + * Entry points into the paging-assistance code */ + +/* Initialize the paging resource for vcpu struct. It is called by + * vcpu_initialise() in domain.c */ +void paging_vcpu_init(struct vcpu *v); + +/* Set up the paging-assistance-specific parts of a domain struct at + * start of day. Called for every domain from arch_domain_create() */ +void paging_domain_init(struct domain *d); + +/* Handler for paging-control ops: operations from user-space to enable + * and disable ephemeral shadow modes (test mode and log-dirty mode) and + * manipulate the log-dirty bitmap. */ +int paging_domctl(struct domain *d, xen_domctl_shadow_op_t *sc, + XEN_GUEST_HANDLE(void) u_domctl); + +/* Call when destroying a domain */ +void paging_teardown(struct domain *d); + +/* Call once all of the references to the domain have gone away */ +void paging_final_teardown(struct domain *d); + +/* Enable an arbitrary paging-assistance mode. Call once at domain + * creation. */ +int paging_enable(struct domain *d, u32 mode); + + +/* Page fault handler + * Called from pagefault handler in Xen, and from the HVM trap handlers + * for pagefaults. Returns 1 if this fault was an artefact of the + * paging code (and the guest should retry) or 0 if it is not (and the + * fault should be handled elsewhere or passed to the guest). + * + * Note: under shadow paging, this function handles all page faults; + * however, for hardware-assisted paging, this function handles only + * host page faults (i.e. nested page faults). */ +static inline int +paging_fault(unsigned long va, struct cpu_user_regs *regs) +{ + struct vcpu *v = current; + return v->arch.paging.mode->page_fault(v, va, regs); +} + +/* Handle invlpg requests on vcpus. + * Returns 1 if the invlpg instruction should be issued on the hardware, + * or 0 if it's safe not to do so. */ +static inline int paging_invlpg(struct vcpu *v, unsigned long va) +{ + return v->arch.paging.mode->invlpg(v, va); +} + +/* Translate a guest virtual address to the physical address that the + * *guest* pagetables would map it to. */ +static inline paddr_t paging_gva_to_gpa(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return (paddr_t) va; + + return v->arch.paging.mode->gva_to_gpa(v, va); +} + +/* Translate a guest virtual address to the frame number that the + * *guest* pagetables would map it to. */ +static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va) +{ + if ( unlikely(!paging_vcpu_mode_translate(v)) ) + return va >> PAGE_SHIFT; + + return v->arch.paging.mode->gva_to_gfn(v, va); +} + +/* Update all the things that are derived from the guest's CR3. + * Called when the guest changes CR3; the caller can then use v->arch.cr3 + * as the value to load into the host CR3 to schedule this vcpu */ +static inline void paging_update_cr3(struct vcpu *v) +{ + v->arch.paging.mode->update_cr3(v, 1); +} + +/* Update all the things that are derived from the guest's CR0/CR3/CR4. + * Called to initialize paging structures if the paging mode + * has changed, and when bringing up a VCPU for the first time. */ +static inline void paging_update_paging_modes(struct vcpu *v) +{ + v->arch.paging.mode->update_paging_modes(v); +} + + +/* Write a new value into the guest pagetable, and update the + * paging-assistance state appropriately. Returns 0 if we page-faulted, + * 1 for success. */ +static inline int paging_write_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t new, mfn_t gmfn) +{ + if ( unlikely(paging_mode_enabled(v->domain) + && v->arch.paging.mode != NULL) ) + return v->arch.paging.mode->write_guest_entry(v, p, new, gmfn); + else + return (!__copy_to_user(p, &new, sizeof(new))); +} + + +/* Cmpxchg a new value into the guest pagetable, and update the + * paging-assistance state appropriately. Returns 0 if we page-faulted, + * 1 if not. N.B. caller should check the value of "old" to see if the + * cmpxchg itself was successful. */ +static inline int paging_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, + intpte_t *old, intpte_t new, + mfn_t gmfn) +{ + if ( unlikely(paging_mode_enabled(v->domain) + && v->arch.paging.mode != NULL) ) + return v->arch.paging.mode->cmpxchg_guest_entry(v, p, old, new, gmfn); + else + return (!cmpxchg_user(p, *old, new)); +} + +/* Helper function that writes a pte in such a way that a concurrent read + * never sees a half-written entry that has _PAGE_PRESENT set */ +static inline void safe_write_pte(l1_pgentry_t *p, l1_pgentry_t new) +{ +#if CONFIG_PAGING_LEVELS == 3 + /* PAE machines write 64bit PTEs as two 32bit writes. */ + volatile unsigned long *d = (unsigned long *) p; + unsigned long *s = (unsigned long *) &new; + BUILD_BUG_ON(sizeof (l1_pgentry_t) != 2 * sizeof (unsigned long)); + d[0] = 0; + d[1] = s[1]; + d[0] = s[0]; +#else + *p = new; +#endif +} + +/* Atomically write a P2M entry and update the paging-assistance state + * appropriately. */ +static inline void paging_write_p2m_entry(struct domain *d, unsigned long gfn, + l1_pgentry_t *p, l1_pgentry_t new, + unsigned int level) +{ + struct vcpu *v = current; + if ( v->domain != d ) + v = d->vcpu[0]; + if ( likely(paging_mode_enabled(d) && v->arch.paging.mode != NULL) ) + { + return v->arch.paging.mode->write_p2m_entry(v, gfn, p, new, level); + } + else + safe_write_pte(p, new); +} + +/* Print paging-assistance info to the console */ +void paging_dump_domain_info(struct domain *d); +void paging_dump_vcpu_info(struct vcpu *v); + + +/***************************************************************************** + * Access to the guest pagetables */ + +/* Get a mapping of a PV guest's l1e for this virtual address. */ +static inline void * +guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn) +{ + l2_pgentry_t l2e; + + if ( unlikely(paging_mode_translate(v->domain)) ) + return v->arch.paging.mode->guest_map_l1e(v, addr, gl1mfn); + + /* Find this l1e and its enclosing l1mfn in the linear map */ + if ( __copy_from_user(&l2e, + &__linear_l2_table[l2_linear_offset(addr)], + sizeof(l2_pgentry_t)) != 0 ) + return NULL; + /* Check flags that it will be safe to read the l1e */ + if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE)) + != _PAGE_PRESENT ) + return NULL; + *gl1mfn = l2e_get_pfn(l2e); + return &__linear_l1_table[l1_linear_offset(addr)]; +} + +/* Pull down the mapping we got from guest_map_l1e() */ +static inline void +guest_unmap_l1e(struct vcpu *v, void *p) +{ + if ( unlikely(paging_mode_translate(v->domain)) ) + unmap_domain_page(p); +} + +/* Read the guest's l1e that maps this address. */ +static inline void +guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ + if ( likely(!paging_mode_translate(v->domain)) ) + { + ASSERT(!paging_mode_external(v->domain)); + if ( __copy_from_user(eff_l1e, + &__linear_l1_table[l1_linear_offset(addr)], + sizeof(l1_pgentry_t)) != 0 ) + *(l1_pgentry_t *)eff_l1e = l1e_empty(); + return; + } + + v->arch.paging.mode->guest_get_eff_l1e(v, addr, eff_l1e); +} + +/* Read the guest's l1e that maps this address, from the kernel-mode + * pagetables. */ +static inline void +guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) +{ +#if defined(__x86_64__) + int user_mode = !(v->arch.flags & TF_kernel_mode); +#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) +#else +#define TOGGLE_MODE() ((void)0) +#endif + + TOGGLE_MODE(); + guest_get_eff_l1e(v, addr, eff_l1e); + TOGGLE_MODE(); +} + + + +#endif /* XEN_PAGING_H */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/include/asm-x86/shadow.h b/xen/include/asm-x86/shadow.h index a4a489dcf5..5a3dbfc72e 100644 --- a/xen/include/asm-x86/shadow.h +++ b/xen/include/asm-x86/shadow.h @@ -28,45 +28,26 @@ #include #include #include +#include +#include /***************************************************************************** - * Macros to tell which shadow paging mode a domain is in */ + * Macros to tell which shadow paging mode a domain is in*/ -#define SHM2_shift 10 -/* We're in one of the shadow modes */ -#define SHM2_enable (1U << SHM2_shift) -/* Refcounts based on shadow tables instead of guest tables */ -#define SHM2_refcounts (XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT << SHM2_shift) -/* Enable log dirty mode */ -#define SHM2_log_dirty (XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY << SHM2_shift) -/* Xen does p2m translation, not guest */ -#define SHM2_translate (XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE << SHM2_shift) -/* Xen does not steal address space from the domain for its own booking; - * requires VT or similar mechanisms */ -#define SHM2_external (XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL << SHM2_shift) - -#define shadow_mode_enabled(_d) ((_d)->arch.shadow.mode) -#define shadow_mode_refcounts(_d) ((_d)->arch.shadow.mode & SHM2_refcounts) -#define shadow_mode_log_dirty(_d) ((_d)->arch.shadow.mode & SHM2_log_dirty) -#define shadow_mode_translate(_d) ((_d)->arch.shadow.mode & SHM2_translate) -#define shadow_mode_external(_d) ((_d)->arch.shadow.mode & SHM2_external) +#define shadow_mode_enabled(_d) paging_mode_shadow(_d) +#define shadow_mode_refcounts(_d) (paging_mode_shadow(_d) && \ + paging_mode_refcounts(_d)) +#define shadow_mode_log_dirty(_d) (paging_mode_shadow(_d) && \ + paging_mode_log_dirty(_d)) +#define shadow_mode_translate(_d) (paging_mode_shadow(_d) && \ + paging_mode_translate(_d)) +#define shadow_mode_external(_d) (paging_mode_shadow(_d) && \ + paging_mode_external(_d)) /* Xen traps & emulates all reads of all page table pages: * not yet supported */ #define shadow_mode_trap_reads(_d) ({ (void)(_d); 0; }) - -/****************************************************************************** - * The equivalent for a particular vcpu of a shadowed domain. */ - -/* Is this vcpu using the P2M table to translate between GFNs and MFNs? - * - * This is true of translated HVM domains on a vcpu which has paging - * enabled. (HVM vcpus with paging disabled are using the p2m table as - * its paging table, so no translation occurs in this case.) - * It is also true for all vcpus of translated PV domains. */ -#define shadow_vcpu_mode_translate(_v) ((_v)->arch.shadow.translate_enabled) - /* * 32on64 support */ @@ -76,122 +57,18 @@ #define pv_32bit_guest(_v) (!is_hvm_vcpu(_v)) #endif -/****************************************************************************** - * With shadow pagetables, the different kinds of address start - * to get get confusing. - * - * Virtual addresses are what they usually are: the addresses that are used - * to accessing memory while the guest is running. The MMU translates from - * virtual addresses to machine addresses. - * - * (Pseudo-)physical addresses are the abstraction of physical memory the - * guest uses for allocation and so forth. For the purposes of this code, - * we can largely ignore them. - * - * Guest frame numbers (gfns) are the entries that the guest puts in its - * pagetables. For normal paravirtual guests, they are actual frame numbers, - * with the translation done by the guest. - * - * Machine frame numbers (mfns) are the entries that the hypervisor puts - * in the shadow page tables. - * - * Elsewhere in the xen code base, the name "gmfn" is generally used to refer - * to a "machine frame number, from the guest's perspective", or in other - * words, pseudo-physical frame numbers. However, in the shadow code, the - * term "gmfn" means "the mfn of a guest page"; this combines naturally with - * other terms such as "smfn" (the mfn of a shadow page), gl2mfn (the mfn of a - * guest L2 page), etc... - */ - -/* With this defined, we do some ugly things to force the compiler to - * give us type safety between mfns and gfns and other integers. - * TYPE_SAFE(int foo) defines a foo_t, and _foo() and foo_x() functions - * that translate beween int and foo_t. - * - * It does have some performance cost because the types now have - * a different storage attribute, so may not want it on all the time. */ -#ifndef NDEBUG -#define TYPE_SAFETY 1 -#endif - -#ifdef TYPE_SAFETY -#define TYPE_SAFE(_type,_name) \ -typedef struct { _type _name; } _name##_t; \ -static inline _name##_t _##_name(_type n) { return (_name##_t) { n }; } \ -static inline _type _name##_x(_name##_t n) { return n._name; } -#else -#define TYPE_SAFE(_type,_name) \ -typedef _type _name##_t; \ -static inline _name##_t _##_name(_type n) { return n; } \ -static inline _type _name##_x(_name##_t n) { return n; } -#endif - -TYPE_SAFE(unsigned long,mfn) - -/* Macro for printk formats: use as printk("%"SH_PRI_mfn"\n", mfn_x(foo)); */ -#define SH_PRI_mfn "05lx" - - -/***************************************************************************** - * Mode-specific entry points into the shadow code. - * - * These shouldn't be used directly by callers; rather use the functions - * below which will indirect through this table as appropriate. */ - -struct sh_emulate_ctxt; -struct shadow_paging_mode { - int (*page_fault )(struct vcpu *v, unsigned long va, - struct cpu_user_regs *regs); - int (*invlpg )(struct vcpu *v, unsigned long va); - paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va); - unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va); - void (*update_cr3 )(struct vcpu *v, int do_locking); - int (*map_and_validate_gl1e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl2e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl2he)(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl3e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - int (*map_and_validate_gl4e )(struct vcpu *v, mfn_t gmfn, - void *new_guest_entry, u32 size); - void (*detach_old_tables )(struct vcpu *v); - int (*x86_emulate_write )(struct vcpu *v, unsigned long va, - void *src, u32 bytes, - struct sh_emulate_ctxt *sh_ctxt); - int (*x86_emulate_cmpxchg )(struct vcpu *v, unsigned long va, - unsigned long old, - unsigned long new, - unsigned int bytes, - struct sh_emulate_ctxt *sh_ctxt); - int (*x86_emulate_cmpxchg8b )(struct vcpu *v, unsigned long va, - unsigned long old_lo, - unsigned long old_hi, - unsigned long new_lo, - unsigned long new_hi, - struct sh_emulate_ctxt *sh_ctxt); - mfn_t (*make_monitor_table )(struct vcpu *v); - void (*destroy_monitor_table )(struct vcpu *v, mfn_t mmfn); - void * (*guest_map_l1e )(struct vcpu *v, unsigned long va, - unsigned long *gl1mfn); - void (*guest_get_eff_l1e )(struct vcpu *v, unsigned long va, - void *eff_l1e); - int (*guess_wrmap )(struct vcpu *v, - unsigned long vaddr, mfn_t gmfn); - /* For outsiders to tell what mode we're in */ - unsigned int shadow_levels; - unsigned int guest_levels; -}; - /***************************************************************************** * Entry points into the shadow code */ /* Set up the shadow-specific parts of a domain struct at start of day. - * Called for every domain from arch_domain_create() */ + * Called from paging_domain_init(). */ void shadow_domain_init(struct domain *d); +/* Setup the shadow-specific parts of a vcpu struct. It is called by + * paging_vcpu_init() in paging.c */ +void shadow_vcpu_init(struct vcpu *v); + /* Enable an arbitrary shadow mode. Call once at domain creation. */ int shadow_enable(struct domain *d, u32 mode); @@ -218,137 +95,12 @@ static inline void mark_dirty(struct domain *d, unsigned long gmfn) shadow_mark_dirty(d, _mfn(gmfn)); } -/* Handle page-faults caused by the shadow pagetable mechanisms. - * Called from pagefault handler in Xen, and from the HVM trap handlers - * for pagefaults. Returns 1 if this fault was an artefact of the - * shadow code (and the guest should retry) or 0 if it is not (and the - * fault should be handled elsewhere or passed to the guest). */ -static inline int shadow_fault(unsigned long va, struct cpu_user_regs *regs) -{ - struct vcpu *v = current; - perfc_incrc(shadow_fault); - return v->arch.shadow.mode->page_fault(v, va, regs); -} - -/* Handle invlpg requests on shadowed vcpus. - * Returns 1 if the invlpg instruction should be issued on the hardware, - * or 0 if it's safe not to do so. */ -static inline int shadow_invlpg(struct vcpu *v, unsigned long va) -{ - return v->arch.shadow.mode->invlpg(v, va); -} - -/* Translate a guest virtual address to the physical address that the - * *guest* pagetables would map it to. */ -static inline paddr_t shadow_gva_to_gpa(struct vcpu *v, unsigned long va) -{ - if ( unlikely(!shadow_vcpu_mode_translate(v)) ) - return (paddr_t) va; - return v->arch.shadow.mode->gva_to_gpa(v, va); -} - -/* Translate a guest virtual address to the frame number that the - * *guest* pagetables would map it to. */ -static inline unsigned long shadow_gva_to_gfn(struct vcpu *v, unsigned long va) -{ - if ( unlikely(!shadow_vcpu_mode_translate(v)) ) - return va >> PAGE_SHIFT; - return v->arch.shadow.mode->gva_to_gfn(v, va); -} - -/* Update all the things that are derived from the guest's CR3. - * Called when the guest changes CR3; the caller can then use v->arch.cr3 - * as the value to load into the host CR3 to schedule this vcpu */ -static inline void shadow_update_cr3(struct vcpu *v) -{ - v->arch.shadow.mode->update_cr3(v, 1); -} - /* Update all the things that are derived from the guest's CR0/CR3/CR4. * Called to initialize paging structures if the paging mode * has changed, and when bringing up a VCPU for the first time. */ void shadow_update_paging_modes(struct vcpu *v); -/***************************************************************************** - * Access to the guest pagetables */ - -/* Get a mapping of a PV guest's l1e for this virtual address. */ -static inline void * -guest_map_l1e(struct vcpu *v, unsigned long addr, unsigned long *gl1mfn) -{ - l2_pgentry_t l2e; - - if ( unlikely(shadow_mode_translate(v->domain)) ) - return v->arch.shadow.mode->guest_map_l1e(v, addr, gl1mfn); - - /* Find this l1e and its enclosing l1mfn in the linear map */ - if ( __copy_from_user(&l2e, - &__linear_l2_table[l2_linear_offset(addr)], - sizeof(l2_pgentry_t)) != 0 ) - return NULL; - /* Check flags that it will be safe to read the l1e */ - if ( (l2e_get_flags(l2e) & (_PAGE_PRESENT | _PAGE_PSE)) - != _PAGE_PRESENT ) - return NULL; - *gl1mfn = l2e_get_pfn(l2e); - return &__linear_l1_table[l1_linear_offset(addr)]; -} - -/* Pull down the mapping we got from guest_map_l1e() */ -static inline void -guest_unmap_l1e(struct vcpu *v, void *p) -{ - if ( unlikely(shadow_mode_translate(v->domain)) ) - unmap_domain_page(p); -} - -/* Read the guest's l1e that maps this address. */ -static inline void -guest_get_eff_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) -{ - if ( likely(!shadow_mode_translate(v->domain)) ) - { - ASSERT(!shadow_mode_external(v->domain)); - if ( __copy_from_user(eff_l1e, - &__linear_l1_table[l1_linear_offset(addr)], - sizeof(l1_pgentry_t)) != 0 ) - *(l1_pgentry_t *)eff_l1e = l1e_empty(); - return; - } - - v->arch.shadow.mode->guest_get_eff_l1e(v, addr, eff_l1e); -} - -/* Read the guest's l1e that maps this address, from the kernel-mode - * pagetables. */ -static inline void -guest_get_eff_kern_l1e(struct vcpu *v, unsigned long addr, void *eff_l1e) -{ -#if defined(__x86_64__) - int user_mode = !(v->arch.flags & TF_kernel_mode); -#define TOGGLE_MODE() if ( user_mode ) toggle_guest_mode(v) -#else -#define TOGGLE_MODE() ((void)0) -#endif - - TOGGLE_MODE(); - guest_get_eff_l1e(v, addr, eff_l1e); - TOGGLE_MODE(); -} - -/* Write a new value into the guest pagetable, and update the shadows - * appropriately. Returns 0 if we page-faulted, 1 for success. */ -int shadow_write_guest_entry(struct vcpu *v, intpte_t *p, - intpte_t new, mfn_t gmfn); - -/* Cmpxchg a new value into the guest pagetable, and update the shadows - * appropriately. Returns 0 if we page-faulted, 1 if not. - * N.B. caller should check the value of "old" to see if the - * cmpxchg itself was successful. */ -int shadow_cmpxchg_guest_entry(struct vcpu *v, intpte_t *p, - intpte_t *old, intpte_t new, mfn_t gmfn); - /* Remove all mappings of the guest page from the shadows. * This is called from common code. It does not flush TLBs. */ int sh_remove_all_mappings(struct vcpu *v, mfn_t target_mfn); @@ -368,99 +120,6 @@ static inline void shadow_remove_all_shadows(struct vcpu *v, mfn_t gmfn) sh_remove_shadows(v, gmfn, 0 /* Be thorough */, 1 /* Must succeed */); } -/**************************************************************************/ -/* Guest physmap (p2m) support - * - * The phys_to_machine_mapping is the reversed mapping of MPT for full - * virtualization. It is only used by shadow_mode_translate()==true - * guests, so we steal the address space that would have normally - * been used by the read-only MPT map. - */ -#define phys_to_machine_mapping ((l1_pgentry_t *)RO_MPT_VIRT_START) - -/* Add a page to a domain's p2m table */ -void shadow_guest_physmap_add_page(struct domain *d, unsigned long gfn, - unsigned long mfn); - -/* Remove a page from a domain's p2m table */ -void shadow_guest_physmap_remove_page(struct domain *d, unsigned long gfn, - unsigned long mfn); - -/* Aliases, called from common code. */ -#define guest_physmap_add_page shadow_guest_physmap_add_page -#define guest_physmap_remove_page shadow_guest_physmap_remove_page - -/* Read the current domain's P2M table. */ -static inline mfn_t sh_gfn_to_mfn_current(unsigned long gfn) -{ - l1_pgentry_t l1e = l1e_empty(); - int ret; - - if ( gfn > current->domain->arch.max_mapped_pfn ) - return _mfn(INVALID_MFN); - - /* Don't read off the end of the p2m table */ - ASSERT(gfn < (RO_MPT_VIRT_END - RO_MPT_VIRT_START) / sizeof(l1_pgentry_t)); - - ret = __copy_from_user(&l1e, - &phys_to_machine_mapping[gfn], - sizeof(l1e)); - - if ( (ret == 0) && (l1e_get_flags(l1e) & _PAGE_PRESENT) ) - return _mfn(l1e_get_pfn(l1e)); - - return _mfn(INVALID_MFN); -} - -/* Read another domain's P2M table, mapping pages as we go */ -mfn_t sh_gfn_to_mfn_foreign(struct domain *d, unsigned long gpfn); - -/* General conversion function from gfn to mfn */ -static inline mfn_t -sh_gfn_to_mfn(struct domain *d, unsigned long gfn) -{ - if ( !shadow_mode_translate(d) ) - return _mfn(gfn); - if ( likely(current->domain == d) ) - return sh_gfn_to_mfn_current(gfn); - else - return sh_gfn_to_mfn_foreign(d, gfn); -} - -/* Compatibility function for HVM code */ -static inline unsigned long get_mfn_from_gpfn(unsigned long pfn) -{ - return mfn_x(sh_gfn_to_mfn_current(pfn)); -} - -/* General conversion function from mfn to gfn */ -static inline unsigned long -sh_mfn_to_gfn(struct domain *d, mfn_t mfn) -{ - if ( shadow_mode_translate(d) ) - return get_gpfn_from_mfn(mfn_x(mfn)); - else - return mfn_x(mfn); -} - -/* Is this guest address an mmio one? (i.e. not defined in p2m map) */ -static inline int -mmio_space(paddr_t gpa) -{ - unsigned long gfn = gpa >> PAGE_SHIFT; - return !mfn_valid(mfn_x(sh_gfn_to_mfn_current(gfn))); -} - -/* Translate the frame number held in an l1e from guest to machine */ -static inline l1_pgentry_t -gl1e_to_ml1e(struct domain *d, l1_pgentry_t l1e) -{ - if ( unlikely(shadow_mode_translate(d)) ) - l1e = l1e_from_pfn(gmfn_to_mfn(d, l1e_get_pfn(l1e)), - l1e_get_flags(l1e)); - return l1e; -} - #endif /* _XEN_SHADOW_H */ /* From e036449798d2de2b6752f492ff8c0c377e08be9e Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 12:10:01 +0000 Subject: [PATCH 87/95] Support INC/DEC in mmio decoder. Opcodes 0xFE and 0xFF. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/platform.c | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 404c9b62fc..76202a36c0 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -690,6 +690,39 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, } else return DECODE_failure; + case 0xFE: + case 0xFF: + { + unsigned char ins_subtype = (opcode[1] >> 3) & 7; + + if ( opcode[0] == 0xFE ) { + *op_size = BYTE; + GET_OP_SIZE_FOR_BYTE(size_reg); + } else { + GET_OP_SIZE_FOR_NONEBYTE(*op_size); + size_reg = *op_size; + } + + mmio_op->immediate = 1; + mmio_op->operand[0] = mk_operand(size_reg, 0, 0, IMMEDIATE); + mmio_op->operand[1] = mk_operand(size_reg, 0, 0, MEMORY); + + switch ( ins_subtype ) { + case 0: /* inc */ + mmio_op->instr = INSTR_ADD; + return DECODE_success; + + case 1: /* dec */ + mmio_op->instr = INSTR_OR; + return DECODE_success; + + default: + printk("%x/%x, This opcode isn't handled yet!\n", + *opcode, ins_subtype); + return DECODE_failure; + } + } + case 0x0F: break; From ed160caea01684db9b49b3aff8cdd336be15ca1a Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 12:14:49 +0000 Subject: [PATCH 88/95] Fix DEC instruction decode. Turn into SUB, not OR. :-) Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 76202a36c0..32246da991 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -713,7 +713,7 @@ static int mmio_decode(int address_bytes, unsigned char *opcode, return DECODE_success; case 1: /* dec */ - mmio_op->instr = INSTR_OR; + mmio_op->instr = INSTR_SUB; return DECODE_success; default: From b3fa47dbc82442b632ef45db863eb015039046b0 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 12:35:36 +0000 Subject: [PATCH 89/95] Add missing breaks to {set,get}_address_size domctls. Signed-off-by: Gerd Hoffmann --- xen/arch/x86/domctl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 8d4901b0c3..2f06d73cb1 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -398,6 +398,7 @@ long arch_do_domctl( put_domain(d); } + break; case XEN_DOMCTL_get_address_size: { @@ -412,6 +413,7 @@ long arch_do_domctl( ret = 0; put_domain(d); } + break; default: ret = -ENOSYS; From 56d4085f507c1e75dff9b0e81ad34cf607d216a1 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 12:37:13 +0000 Subject: [PATCH 90/95] Make libelf not fail on unknown elf notes. Signed-off-by: Gerd Hoffmann --- xen/common/libelf/libelf-dominfo.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c index 9d45b8ae21..e3fee4552a 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -107,9 +107,9 @@ int elf_xen_parse_note(struct elf_binary *elf, if ((type >= sizeof(note_desc) / sizeof(note_desc[0])) || (NULL == note_desc[type].name)) { - elf_err(elf, "%s: unknown xen elf note (0x%x)\n", + elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", __FUNCTION__, type); - return -1; + return 0; } if (note_desc[type].str) From 34bac08a56e084bdd11dd83cba9a35be886079d8 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Feb 2007 14:44:07 +0000 Subject: [PATCH 91/95] [XEN] Re-sync PAE l3 shadows when PV guests change them -in particular, for PAE Solaris guests Signed-off-by: Tim Deegan --- xen/arch/x86/mm.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 2ef442f546..2d0afd735f 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -977,6 +977,19 @@ static void pae_flush_pgd( l3_pgentry_t *l3tab_ptr; struct pae_l3_cache *cache; + if ( unlikely(shadow_mode_enabled(d)) ) + { + cpumask_t m = CPU_MASK_NONE; + /* Re-shadow this l3 table on any vcpus that are using it */ + for_each_vcpu ( d, v ) + if ( pagetable_get_pfn(v->arch.guest_table) == mfn ) + { + paging_update_cr3(v); + cpus_or(m, m, v->vcpu_dirty_cpumask); + } + flush_tlb_mask(m); + } + /* If below 4GB then the pgdir is not shadowed in low memory. */ if ( !l3tab_needs_shadow(mfn) ) return; From 4e5334d94c5ca1ad77aa8d7dab48e7f01af3465d Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Wed, 14 Feb 2007 14:46:18 +0000 Subject: [PATCH 92/95] [XEN] Snapshot PAE l3es when they are shadowed. We don't update the shadows so we mustn't look at the guest l3es or we'll be confused by them if they change. Signed-off-by: Tim Deegan --- xen/arch/x86/hvm/svm/svm.c | 2 +- xen/arch/x86/mm.c | 3 - xen/arch/x86/mm/shadow/multi.c | 111 +++++++++++++------------- xen/arch/x86/mm/shadow/page-guest32.h | 5 -- xen/arch/x86/mm/shadow/types.h | 2 - xen/include/asm-x86/domain.h | 6 +- xen/include/asm-x86/page.h | 3 - 7 files changed, 60 insertions(+), 72 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index cc9043e413..d3df4a5c3e 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -2679,7 +2679,7 @@ void walk_shadow_and_guest_pt(unsigned long gva) shadow_sync_va(v, gva); gpte.l1 = 0; - __copy_from_user(&gpte, &linear_pg_table[ l1_linear_offset(gva) ], + __copy_from_user(&gpte, &__linear_l1_table[ l1_linear_offset(gva) ], sizeof(gpte) ); printk( "G-PTE = %x, flags=%x\n", gpte.l1, l1e_get_flags(gpte) ); diff --git a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c index 2d0afd735f..5d043ad598 100644 --- a/xen/arch/x86/mm.c +++ b/xen/arch/x86/mm.c @@ -374,9 +374,6 @@ void write_ptbase(struct vcpu *v) /* Should be called after CR3 is updated. * Updates vcpu->arch.cr3 and, for HVM guests, vcpu->arch.hvm_vcpu.cpu_cr3. * - * Also updates other state derived from CR3 (vcpu->arch.guest_vtable, - * shadow_vtable, etc). - * * Uses values found in vcpu->arch.(guest_table and guest_table_user), and * for HVM guests, arch.monitor_table and hvm's guest CR3. * diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 5a1638df19..fec6551d8c 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -237,7 +237,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) #if GUEST_PAGING_LEVELS >= 4 /* 64-bit only... */ /* Get l4e from the top level table */ gw->l4mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l4e = (guest_l4e_t *)v->arch.guest_vtable + guest_l4_table_offset(va); + gw->l4e = (guest_l4e_t *)v->arch.paging.shadow.guest_vtable + + guest_l4_table_offset(va); /* Walk down to the l3e */ if ( !(guest_l4e_get_flags(*gw->l4e) & _PAGE_PRESENT) ) return 0; gw->l3mfn = vcpu_gfn_to_mfn(v, guest_l4e_get_gfn(*gw->l4e)); @@ -248,9 +249,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) gw->l3e = ((guest_l3e_t *)sh_map_domain_page(gw->l3mfn)) + guest_l3_table_offset(va); #else /* PAE only... */ - /* Get l3e from the top level table */ - gw->l3mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l3e = (guest_l3e_t *)v->arch.guest_vtable + guest_l3_table_offset(va); + /* Get l3e from the cache of the guest's top level table */ + gw->l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e[guest_l3_table_offset(va)]; #endif /* PAE or 64... */ /* Walk down to the l2e */ if ( !(guest_l3e_get_flags(*gw->l3e) & _PAGE_PRESENT) ) return 0; @@ -264,7 +264,8 @@ guest_walk_tables(struct vcpu *v, unsigned long va, walk_t *gw, int guest_op) #else /* 32-bit only... */ /* Get l2e from the top level table */ gw->l2mfn = pagetable_get_mfn(v->arch.guest_table); - gw->l2e = (guest_l2e_t *)v->arch.guest_vtable + guest_l2_table_offset(va); + gw->l2e = (guest_l2e_t *)v->arch.paging.shadow.guest_vtable + + guest_l2_table_offset(va); #endif /* All levels... */ if ( !(guest_l2e_get_flags(*gw->l2e) & _PAGE_PRESENT) ) return 0; @@ -357,8 +358,8 @@ static inline void print_gw(walk_t *gw) SHADOW_PRINTK(" l4e=%p\n", gw->l4e); if ( gw->l4e ) SHADOW_PRINTK(" *l4e=%" SH_PRI_gpte "\n", gw->l4e->l4); -#endif /* PAE or 64... */ SHADOW_PRINTK(" l3mfn=%" PRI_mfn "\n", mfn_x(gw->l3mfn)); +#endif /* PAE or 64... */ SHADOW_PRINTK(" l3e=%p\n", gw->l3e); if ( gw->l3e ) SHADOW_PRINTK(" *l3e=%" SH_PRI_gpte "\n", gw->l3e->l3); @@ -3169,8 +3170,7 @@ sh_update_linear_entries(struct vcpu *v) #else /* GUEST_PAGING_LEVELS == 3 */ shadow_l3e = (shadow_l3e_t *)&v->arch.paging.shadow.l3table; - /* Always safe to use guest_vtable, because it's globally mapped */ - guest_l3e = v->arch.guest_vtable; + guest_l3e = (guest_l3e_t *)&v->arch.paging.shadow.gl3e; #endif /* GUEST_PAGING_LEVELS */ @@ -3268,39 +3268,37 @@ sh_update_linear_entries(struct vcpu *v) } -/* Removes vcpu->arch.guest_vtable and vcpu->arch.shadow_table[]. +/* Removes vcpu->arch.paging.shadow.guest_vtable and vcpu->arch.shadow_table[]. * Does all appropriate management/bookkeeping/refcounting/etc... */ static void sh_detach_old_tables(struct vcpu *v) { - struct domain *d = v->domain; mfn_t smfn; int i = 0; //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// - if ( v->arch.guest_vtable ) + +#if GUEST_PAGING_LEVELS == 3 + /* PAE guests don't have a mapping of the guest top-level table */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); +#else + if ( v->arch.paging.shadow.guest_vtable ) { -#if GUEST_PAGING_LEVELS == 4 + struct domain *d = v->domain; if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 3 - if ( 1 || shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#elif GUEST_PAGING_LEVELS == 2 - if ( shadow_mode_external(d) || shadow_mode_translate(d) ) - sh_unmap_domain_page_global(v->arch.guest_vtable); -#endif - v->arch.guest_vtable = NULL; + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = NULL; } +#endif + //// //// vcpu->arch.shadow_table[] //// - #if GUEST_PAGING_LEVELS == 3 /* PAE guests have four shadow_table entries */ for ( i = 0 ; i < 4 ; i++ ) @@ -3398,7 +3396,9 @@ sh_update_cr3(struct vcpu *v, int do_locking) struct domain *d = v->domain; mfn_t gmfn; #if GUEST_PAGING_LEVELS == 3 + guest_l3e_t *gl3e; u32 guest_idx=0; + int i; #endif /* Don't do anything on an uninitialised vcpu */ @@ -3457,55 +3457,54 @@ sh_update_cr3(struct vcpu *v, int do_locking) //// - //// vcpu->arch.guest_vtable + //// vcpu->arch.paging.shadow.guest_vtable //// #if GUEST_PAGING_LEVELS == 4 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l4_table; + v->arch.paging.shadow.guest_vtable = __linear_l4_table; #elif GUEST_PAGING_LEVELS == 3 - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - if ( shadow_mode_external(d) ) - { - if ( paging_vcpu_mode_translate(v) ) - /* Paging enabled: find where in the page the l3 table is */ - guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); - else - /* Paging disabled: l3 is at the start of a page (in the p2m) */ - guest_idx = 0; - - // Ignore the low 2 bits of guest_idx -- they are really just - // cache control. - guest_idx &= ~3; - - // XXX - why does this need a global map? - v->arch.guest_vtable = - (guest_l3e_t *)sh_map_domain_page_global(gmfn) + guest_idx; - } + /* On PAE guests we don't use a mapping of the guest's own top-level + * table. We cache the current state of that table and shadow that, + * until the next CR3 write makes us refresh our cache. */ + ASSERT(v->arch.paging.shadow.guest_vtable == NULL); + + if ( shadow_mode_external(d) && paging_vcpu_mode_translate(v) ) + /* Paging enabled: find where in the page the l3 table is */ + guest_idx = guest_index((void *)hvm_get_guest_ctrl_reg(v, 3)); else - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + /* Paging disabled or PV: l3 is at the start of a page */ + guest_idx = 0; + + // Ignore the low 2 bits of guest_idx -- they are really just + // cache control. + guest_idx &= ~3; + + gl3e = ((guest_l3e_t *)sh_map_domain_page(gmfn)) + guest_idx; + for ( i = 0; i < 4 ; i++ ) + v->arch.paging.shadow.gl3e[i] = gl3e[i]; + sh_unmap_domain_page(gl3e); #elif GUEST_PAGING_LEVELS == 2 if ( shadow_mode_external(d) || shadow_mode_translate(d) ) { - if ( v->arch.guest_vtable ) - sh_unmap_domain_page_global(v->arch.guest_vtable); - v->arch.guest_vtable = sh_map_domain_page_global(gmfn); + if ( v->arch.paging.shadow.guest_vtable ) + sh_unmap_domain_page_global(v->arch.paging.shadow.guest_vtable); + v->arch.paging.shadow.guest_vtable = sh_map_domain_page_global(gmfn); } else - v->arch.guest_vtable = __linear_l2_table; + v->arch.paging.shadow.guest_vtable = __linear_l2_table; #else #error this should never happen #endif #if 0 - printk("%s %s %d gmfn=%05lx guest_vtable=%p\n", - __func__, __FILE__, __LINE__, gmfn, v->arch.guest_vtable); + printk("%s %s %d gmfn=%05lx shadow.guest_vtable=%p\n", + __func__, __FILE__, __LINE__, gmfn, v->arch.paging.shadow.guest_vtable); #endif //// @@ -3523,10 +3522,10 @@ sh_update_cr3(struct vcpu *v, int do_locking) /* PAE guests have four shadow_table entries, based on the * current values of the guest's four l3es. */ { - int i, flush = 0; + int flush = 0; gfn_t gl2gfn; mfn_t gl2mfn; - guest_l3e_t *gl3e = (guest_l3e_t*)v->arch.guest_vtable; + guest_l3e_t *gl3e = (guest_l3e_t*)&v->arch.paging.shadow.gl3e; /* First, make all four entries read-only. */ for ( i = 0; i < 4; i++ ) { diff --git a/xen/arch/x86/mm/shadow/page-guest32.h b/xen/arch/x86/mm/shadow/page-guest32.h index e93206169a..5d333bd91b 100644 --- a/xen/arch/x86/mm/shadow/page-guest32.h +++ b/xen/arch/x86/mm/shadow/page-guest32.h @@ -87,11 +87,6 @@ static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags) #define l2_table_offset_32(a) \ (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1)) -#define linear_l1_table_32 \ - ((l1_pgentry_32_t *)(LINEAR_PT_VIRT_START)) - -#define linear_pg_table_32 linear_l1_table_32 - #endif /* __X86_PAGE_GUEST_H__ */ /* diff --git a/xen/arch/x86/mm/shadow/types.h b/xen/arch/x86/mm/shadow/types.h index b94289e674..48670c31c1 100644 --- a/xen/arch/x86/mm/shadow/types.h +++ b/xen/arch/x86/mm/shadow/types.h @@ -447,10 +447,8 @@ struct shadow_walk_t guest_l2e_t *l2e; /* Pointer to guest's level 2 entry */ guest_l1e_t *l1e; /* Pointer to guest's level 1 entry */ guest_l1e_t eff_l1e; /* Effective level 1 entry */ -#if GUEST_PAGING_LEVELS >= 3 #if GUEST_PAGING_LEVELS >= 4 mfn_t l4mfn; /* MFN that the level 4 entry is in */ -#endif mfn_t l3mfn; /* MFN that the level 3 entry is in */ #endif mfn_t l2mfn; /* MFN that the level 2 entry is in */ diff --git a/xen/include/asm-x86/domain.h b/xen/include/asm-x86/domain.h index b148d5682e..3237f53e8e 100644 --- a/xen/include/asm-x86/domain.h +++ b/xen/include/asm-x86/domain.h @@ -92,7 +92,11 @@ struct shadow_vcpu { #if CONFIG_PAGING_LEVELS >= 3 /* PAE guests: per-vcpu shadow top-level table */ l3_pgentry_t l3table[4] __attribute__((__aligned__(32))); + /* PAE guests: per-vcpu cache of the top-level *guest* entries */ + l3_pgentry_t gl3e[4] __attribute__((__aligned__(32))); #endif + /* Non-PAE guests: pointer to guest top-level pagetable */ + void *guest_vtable; /* Last MFN that we emulated a write to. */ unsigned long last_emulated_mfn; /* MFN of the last shadow that we shot a writeable mapping in */ @@ -242,8 +246,6 @@ struct arch_vcpu pagetable_t monitor_table; /* (MFN) hypervisor PT (for HVM) */ unsigned long cr3; /* (MA) value to install in HW CR3 */ - void *guest_vtable; /* virtual addr of pagetable */ - /* Current LDT details. */ unsigned long shadow_ldt_mapcnt; diff --git a/xen/include/asm-x86/page.h b/xen/include/asm-x86/page.h index 1adc4b481d..31ec281920 100644 --- a/xen/include/asm-x86/page.h +++ b/xen/include/asm-x86/page.h @@ -278,9 +278,6 @@ typedef struct { u64 pfn; } pagetable_t; #define __linear_l4_table \ ((l4_pgentry_t *)(__linear_l3_table + l3_linear_offset(LINEAR_PT_VIRT_START))) -#define linear_l1_table __linear_l1_table -#define linear_pg_table linear_l1_table -#define linear_l2_table(v) ((l2_pgentry_t *)(v)->arch.guest_vtable) #ifndef __ASSEMBLY__ #if CONFIG_PAGING_LEVELS == 3 From df8a199bd05a115472208da9d8bc0550f086bf29 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 15:54:47 +0000 Subject: [PATCH 93/95] Another domctl fix to insert missing copy_to_guest. Signed-off-by: Gerd Hoffmann --- xen/arch/x86/domctl.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c index 2f06d73cb1..69e2259d7f 100644 --- a/xen/arch/x86/domctl.c +++ b/xen/arch/x86/domctl.c @@ -412,6 +412,9 @@ long arch_do_domctl( ret = 0; put_domain(d); + + if ( copy_to_guest(u_domctl, domctl, 1) ) + ret = -EFAULT; } break; From ced24e96c7119fee13e8bb495352882b07db4363 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 16:05:28 +0000 Subject: [PATCH 94/95] linux: quieten some driver printk logging. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c | 5 +++-- linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c | 5 +++-- linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c | 2 +- linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c | 6 +++--- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c index 0d9b5e34b4..3c89453030 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkback/xenbus.c @@ -344,7 +344,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } @@ -488,7 +488,8 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - printk("blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + printk(KERN_INFO + "blkback: ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c index 58a79e7e4d..3f3344b3bd 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/blktap/xenbus.c @@ -272,7 +272,7 @@ static void tap_frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); xenbus_switch_state(dev, XenbusStateInitWait); } @@ -369,7 +369,8 @@ static int connect_ring(struct backend_info *be) xenbus_dev_fatal(dev, err, "unknown fe protocol %s", protocol); return -1; } - printk("blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n", + printk(KERN_INFO + "blktap: ring-ref %ld, event-channel %d, protocol %d (%s)\n", ring_ref, evtchn, be->blkif->blk_protocol, protocol); /* Map the shared frame, irq etc. */ diff --git a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c index 7d301965f4..12a3dc26f8 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c +++ b/linux-2.6-xen-sparse/drivers/xen/netback/xenbus.c @@ -217,7 +217,7 @@ static void frontend_changed(struct xenbus_device *dev, switch (frontend_state) { case XenbusStateInitialising: if (dev->state == XenbusStateClosed) { - printk("%s: %s: prepare for reconnect\n", + printk(KERN_INFO "%s: %s: prepare for reconnect\n", __FUNCTION__, dev->nodename); if (be->netif) { netif_disconnect(be->netif); diff --git a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c index bd86948fed..80d1a3e995 100644 --- a/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/netfront/netfront.c @@ -1505,7 +1505,7 @@ static void netif_release_rx_bufs(struct netfront_info *np) int id, ref; if (np->copying_receiver) { - printk("%s: fix me for copying receiver.\n", __FUNCTION__); + WPRINTK("%s: fix me for copying receiver.\n", __FUNCTION__); return; } @@ -1555,8 +1555,8 @@ static void netif_release_rx_bufs(struct netfront_info *np) xfer++; } - printk("%s: %d xfer, %d noxfer, %d unused\n", - __FUNCTION__, xfer, noxfer, unused); + IPRINTK("%s: %d xfer, %d noxfer, %d unused\n", + __FUNCTION__, xfer, noxfer, unused); if (xfer) { /* Some pages are no longer absent... */ From 9efb2db0a351d08c9d939b45b1731e08d61aac0c Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Wed, 14 Feb 2007 16:06:10 +0000 Subject: [PATCH 95/95] libelf: use xen code style. Signed-off-by: Keir Fraser --- xen/common/libelf/libelf-dominfo.c | 499 +++++++++++++++------------- xen/common/libelf/libelf-loader.c | 123 +++---- xen/common/libelf/libelf-private.h | 26 +- xen/common/libelf/libelf-relocate.c | 343 ++++++++++--------- xen/common/libelf/libelf-tools.c | 121 ++++--- 5 files changed, 589 insertions(+), 523 deletions(-) diff --git a/xen/common/libelf/libelf-dominfo.c b/xen/common/libelf/libelf-dominfo.c index e3fee4552a..bbe9235309 100644 --- a/xen/common/libelf/libelf-dominfo.c +++ b/xen/common/libelf/libelf-dominfo.c @@ -15,61 +15,63 @@ const char *elf_xen_feature_names[] = { [XENFEAT_pae_pgdir_above_4gb] = "pae_pgdir_above_4gb" }; const int elf_xen_features = - sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]); +sizeof(elf_xen_feature_names) / sizeof(elf_xen_feature_names[0]); int elf_xen_parse_features(const char *features, - uint32_t *supported, - uint32_t *required) + uint32_t *supported, + uint32_t *required) { char feature[64]; int pos, len, i; - if (NULL == features) - return 0; - for (pos = 0; features[pos] != '\0'; pos += len) - { - memset(feature, 0, sizeof(feature)); - for (len = 0;; len++) - { - if (len >= sizeof(feature)-1) - break; - if (features[pos + len] == '\0') - break; - if (features[pos + len] == '|') - { - len++; - break; - } - feature[len] = features[pos + len]; - } + if ( features == NULL ) + return 0; - for (i = 0; i < elf_xen_features; i++) - { - if (!elf_xen_feature_names[i]) - continue; - if (NULL != required && feature[0] == '!') - { - /* required */ - if (0 == strcmp(feature + 1, elf_xen_feature_names[i])) - { - elf_xen_feature_set(i, supported); - elf_xen_feature_set(i, required); - break; - } - } - else - { - /* supported */ - if (0 == strcmp(feature, elf_xen_feature_names[i])) - { - elf_xen_feature_set(i, supported); - break; - } - } - } - if (i == elf_xen_features) - return -1; + for ( pos = 0; features[pos] != '\0'; pos += len ) + { + memset(feature, 0, sizeof(feature)); + for ( len = 0;; len++ ) + { + if ( len >= sizeof(feature)-1 ) + break; + if ( features[pos + len] == '\0' ) + break; + if ( features[pos + len] == '|' ) + { + len++; + break; + } + feature[len] = features[pos + len]; + } + + for ( i = 0; i < elf_xen_features; i++ ) + { + if ( !elf_xen_feature_names[i] ) + continue; + if ( (required != NULL) && (feature[0] == '!') ) + { + /* required */ + if ( !strcmp(feature + 1, elf_xen_feature_names[i]) ) + { + elf_xen_feature_set(i, supported); + elf_xen_feature_set(i, required); + break; + } + } + else + { + /* supported */ + if ( !strcmp(feature, elf_xen_feature_names[i]) ) + { + elf_xen_feature_set(i, supported); + break; + } + } + } + if ( i == elf_xen_features ) + return -1; } + return 0; } @@ -77,26 +79,26 @@ int elf_xen_parse_features(const char *features, /* xen elf notes */ int elf_xen_parse_note(struct elf_binary *elf, - struct elf_dom_parms *parms, - const elf_note *note) + struct elf_dom_parms *parms, + const elf_note *note) { /* *INDENT-OFF* */ static const struct { - char *name; - int str; + char *name; + int str; } note_desc[] = { - [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0}, - [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0}, - [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", 0}, - [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0}, - [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0}, - [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1}, - [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, - [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, - [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, - [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, - [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, - [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, + [XEN_ELFNOTE_ENTRY] = { "ENTRY", 0}, + [XEN_ELFNOTE_HYPERCALL_PAGE] = { "HYPERCALL_PAGE", 0}, + [XEN_ELFNOTE_VIRT_BASE] = { "VIRT_BASE", 0}, + [XEN_ELFNOTE_PADDR_OFFSET] = { "PADDR_OFFSET", 0}, + [XEN_ELFNOTE_HV_START_LOW] = { "HV_START_LOW", 0}, + [XEN_ELFNOTE_XEN_VERSION] = { "XEN_VERSION", 1}, + [XEN_ELFNOTE_GUEST_OS] = { "GUEST_OS", 1}, + [XEN_ELFNOTE_GUEST_VERSION] = { "GUEST_VERSION", 1}, + [XEN_ELFNOTE_LOADER] = { "LOADER", 1}, + [XEN_ELFNOTE_PAE_MODE] = { "PAE_MODE", 1}, + [XEN_ELFNOTE_FEATURES] = { "FEATURES", 1}, + [XEN_ELFNOTE_BSD_SYMTAB] = { "BSD_SYMTAB", 1}, }; /* *INDENT-ON* */ @@ -104,73 +106,73 @@ int elf_xen_parse_note(struct elf_binary *elf, uint64_t val = 0; int type = elf_uval(elf, note, type); - if ((type >= sizeof(note_desc) / sizeof(note_desc[0])) || - (NULL == note_desc[type].name)) + if ( (type >= sizeof(note_desc) / sizeof(note_desc[0])) || + (note_desc[type].name == NULL) ) { - elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", - __FUNCTION__, type); - return 0; + elf_msg(elf, "%s: unknown xen elf note (0x%x)\n", + __FUNCTION__, type); + return 0; } - if (note_desc[type].str) + if ( note_desc[type].str ) { - str = elf_note_desc(elf, note); - elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, - note_desc[type].name, str); + str = elf_note_desc(elf, note); + elf_msg(elf, "%s: %s = \"%s\"\n", __FUNCTION__, + note_desc[type].name, str); } else { - val = elf_note_numeric(elf, note); - elf_msg(elf, "%s: %s = 0x%" PRIx64 "\n", __FUNCTION__, - note_desc[type].name, val); + val = elf_note_numeric(elf, note); + elf_msg(elf, "%s: %s = 0x%" PRIx64 "\n", __FUNCTION__, + note_desc[type].name, val); } - switch (type) + switch ( type ) { case XEN_ELFNOTE_LOADER: - safe_strcpy(parms->loader, str); - break; + safe_strcpy(parms->loader, str); + break; case XEN_ELFNOTE_GUEST_OS: - safe_strcpy(parms->guest_os, str); - break; + safe_strcpy(parms->guest_os, str); + break; case XEN_ELFNOTE_GUEST_VERSION: - safe_strcpy(parms->guest_ver, str); - break; + safe_strcpy(parms->guest_ver, str); + break; case XEN_ELFNOTE_XEN_VERSION: - safe_strcpy(parms->xen_ver, str); - break; + safe_strcpy(parms->xen_ver, str); + break; case XEN_ELFNOTE_PAE_MODE: - if (0 == strcmp(str, "yes")) - parms->pae = 2 /* extended_cr3 */; - if (strstr(str, "bimodal")) - parms->pae = 3 /* bimodal */; - break; + if ( !strcmp(str, "yes") ) + parms->pae = 2 /* extended_cr3 */; + if ( strstr(str, "bimodal") ) + parms->pae = 3 /* bimodal */; + break; case XEN_ELFNOTE_BSD_SYMTAB: - if (0 == strcmp(str, "yes")) - parms->bsd_symtab = 1; - break; + if ( !strcmp(str, "yes") ) + parms->bsd_symtab = 1; + break; case XEN_ELFNOTE_VIRT_BASE: - parms->virt_base = val; - break; + parms->virt_base = val; + break; case XEN_ELFNOTE_ENTRY: - parms->virt_entry = val; - break; + parms->virt_entry = val; + break; case XEN_ELFNOTE_PADDR_OFFSET: - parms->elf_paddr_offset = val; - break; + parms->elf_paddr_offset = val; + break; case XEN_ELFNOTE_HYPERCALL_PAGE: - parms->virt_hypercall = val; - break; + parms->virt_hypercall = val; + break; case XEN_ELFNOTE_HV_START_LOW: - parms->virt_hv_start_low = val; - break; + parms->virt_hv_start_low = val; + break; case XEN_ELFNOTE_FEATURES: - if (0 != elf_xen_parse_features(str, parms->f_supported, - parms->f_required)) - return -1; - break; + if ( elf_xen_parse_features(str, parms->f_supported, + parms->f_required) ) + return -1; + break; } return 0; @@ -180,83 +182,85 @@ int elf_xen_parse_note(struct elf_binary *elf, /* __xen_guest section */ int elf_xen_parse_guest_info(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { const char *h; char name[32], value[128]; int len; h = parms->guest_info; - while (*h) + while ( *h ) { - memset(name, 0, sizeof(name)); - memset(value, 0, sizeof(value)); - for (len = 0;; len++, h++) { - if (len >= sizeof(name)-1) - break; - if (*h == '\0') - break; - if (*h == ',') - { - h++; - break; - } - if (*h == '=') - { - h++; - for (len = 0;; len++, h++) { - if (len >= sizeof(value)-1) - break; - if (*h == '\0') - break; - if (*h == ',') - { - h++; - break; - } - value[len] = *h; - } - break; - } - name[len] = *h; - } - elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value); + memset(name, 0, sizeof(name)); + memset(value, 0, sizeof(value)); + for ( len = 0;; len++, h++ ) + { + if ( len >= sizeof(name)-1 ) + break; + if ( *h == '\0' ) + break; + if ( *h == ',' ) + { + h++; + break; + } + if ( *h == '=' ) + { + h++; + for ( len = 0;; len++, h++ ) + { + if ( len >= sizeof(value)-1 ) + break; + if ( *h == '\0' ) + break; + if ( *h == ',' ) + { + h++; + break; + } + value[len] = *h; + } + break; + } + name[len] = *h; + } + elf_msg(elf, "%s: %s=\"%s\"\n", __FUNCTION__, name, value); - /* strings */ - if (0 == strcmp(name, "LOADER")) - safe_strcpy(parms->loader, value); - if (0 == strcmp(name, "GUEST_OS")) - safe_strcpy(parms->guest_os, value); - if (0 == strcmp(name, "GUEST_VER")) - safe_strcpy(parms->guest_ver, value); - if (0 == strcmp(name, "XEN_VER")) - safe_strcpy(parms->xen_ver, value); - if (0 == strcmp(name, "PAE")) - { - if (0 == strcmp(value, "yes[extended-cr3]")) - parms->pae = 2 /* extended_cr3 */; - else if (0 == strncmp(value, "yes", 3)) - parms->pae = 1 /* yes */; - } - if (0 == strcmp(name, "BSD_SYMTAB")) - parms->bsd_symtab = 1; + /* strings */ + if ( !strcmp(name, "LOADER") ) + safe_strcpy(parms->loader, value); + if ( !strcmp(name, "GUEST_OS") ) + safe_strcpy(parms->guest_os, value); + if ( !strcmp(name, "GUEST_VER") ) + safe_strcpy(parms->guest_ver, value); + if ( !strcmp(name, "XEN_VER") ) + safe_strcpy(parms->xen_ver, value); + if ( !strcmp(name, "PAE") ) + { + if ( !strcmp(value, "yes[extended-cr3]") ) + parms->pae = 2 /* extended_cr3 */; + else if ( !strncmp(value, "yes", 3) ) + parms->pae = 1 /* yes */; + } + if ( !strcmp(name, "BSD_SYMTAB") ) + parms->bsd_symtab = 1; - /* longs */ - if (0 == strcmp(name, "VIRT_BASE")) - parms->virt_base = strtoull(value, NULL, 0); - if (0 == strcmp(name, "VIRT_ENTRY")) - parms->virt_entry = strtoull(value, NULL, 0); - if (0 == strcmp(name, "ELF_PADDR_OFFSET")) - parms->elf_paddr_offset = strtoull(value, NULL, 0); - if (0 == strcmp(name, "HYPERCALL_PAGE")) - parms->virt_hypercall = (strtoull(value, NULL, 0) << 12) + - parms->virt_base; + /* longs */ + if ( !strcmp(name, "VIRT_BASE") ) + parms->virt_base = strtoull(value, NULL, 0); + if ( !strcmp(name, "VIRT_ENTRY") ) + parms->virt_entry = strtoull(value, NULL, 0); + if ( !strcmp(name, "ELF_PADDR_OFFSET") ) + parms->elf_paddr_offset = strtoull(value, NULL, 0); + if ( !strcmp(name, "HYPERCALL_PAGE") ) + parms->virt_hypercall = (strtoull(value, NULL, 0) << 12) + + parms->virt_base; - /* other */ - if (0 == strcmp(name, "FEATURES")) - if (0 != elf_xen_parse_features(value, parms->f_supported, - parms->f_required)) - return -1; + /* other */ + if ( !strcmp(name, "FEATURES") ) + if ( elf_xen_parse_features(value, parms->f_supported, + parms->f_required) ) + return -1; } return 0; } @@ -265,54 +269,59 @@ int elf_xen_parse_guest_info(struct elf_binary *elf, /* sanity checks */ static int elf_xen_note_check(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { - if (NULL == parms->elf_note_start && NULL == parms->guest_info) { - int machine = elf_uval(elf, elf->ehdr, e_machine); - if (EM_386 == machine || EM_X86_64 == machine) { - elf_err(elf, "%s: ERROR: Not a Xen-ELF image: " - "No ELF notes or '__xen_guest' section found.\n", - __FUNCTION__); - return -1; - } - return 0; + if ( (parms->elf_note_start == NULL) && (parms->guest_info == NULL) ) + { + int machine = elf_uval(elf, elf->ehdr, e_machine); + if ( (machine == EM_386) || (machine == EM_X86_64) ) + { + elf_err(elf, "%s: ERROR: Not a Xen-ELF image: " + "No ELF notes or '__xen_guest' section found.\n", + __FUNCTION__); + return -1; + } + return 0; } /* Check the contents of the Xen notes or guest string. */ - if ( ( 0 == strlen(parms->loader) || strncmp(parms->loader, "generic", 7) ) && - ( 0 == strlen(parms->guest_os) || strncmp(parms->guest_os, "linux", 5) ) ) + if ( ((strlen(parms->loader) == 0) || + strncmp(parms->loader, "generic", 7)) && + ((strlen(parms->guest_os) == 0) || + strncmp(parms->guest_os, "linux", 5)) ) { - elf_err(elf, "%s: ERROR: Will only load images built for the generic " - "loader or Linux images", __FUNCTION__); - return -1; + elf_err(elf, "%s: ERROR: Will only load images built for the generic " + "loader or Linux images", __FUNCTION__); + return -1; } - if ( 0 == strlen(parms->xen_ver) || strncmp(parms->xen_ver, "xen-3.0", 7) ) + if ( (strlen(parms->xen_ver) == 0) || + strncmp(parms->xen_ver, "xen-3.0", 7) ) { - elf_err(elf, "%s: ERROR: Xen will only load images built for Xen v3.0\n", - __FUNCTION__); - return -1; + elf_err(elf, "%s: ERROR: Xen will only load images built " + "for Xen v3.0\n", __FUNCTION__); + return -1; } return 0; } static int elf_xen_addr_calc_check(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { - if (UNSET_ADDR != parms->elf_paddr_offset && - UNSET_ADDR == parms->virt_base ) + if ( (parms->elf_paddr_offset != UNSET_ADDR) && + (parms->virt_base == UNSET_ADDR) ) { - elf_err(elf, "%s: ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n", - __FUNCTION__); + elf_err(elf, "%s: ERROR: ELF_PADDR_OFFSET set, VIRT_BASE unset\n", + __FUNCTION__); return -1; } /* Initial guess for virt_base is 0 if it is not explicitly defined. */ - if (UNSET_ADDR == parms->virt_base) + if ( parms->virt_base == UNSET_ADDR ) { - parms->virt_base = 0; - elf_msg(elf, "%s: VIRT_BASE unset, using 0x%" PRIx64 "\n", - __FUNCTION__, parms->virt_base); + parms->virt_base = 0; + elf_msg(elf, "%s: VIRT_BASE unset, using 0x%" PRIx64 "\n", + __FUNCTION__, parms->virt_base); } /* @@ -324,22 +333,22 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, * If we are using the modern ELF notes interface then the default * is 0. */ - if (UNSET_ADDR == parms->elf_paddr_offset) + if ( parms->elf_paddr_offset == UNSET_ADDR ) { - if (parms->elf_note_start) - parms->elf_paddr_offset = 0; - else - parms->elf_paddr_offset = parms->virt_base; - elf_msg(elf, "%s: ELF_PADDR_OFFSET unset, using 0x%" PRIx64 "\n", - __FUNCTION__, parms->elf_paddr_offset); + if ( parms->elf_note_start ) + parms->elf_paddr_offset = 0; + else + parms->elf_paddr_offset = parms->virt_base; + elf_msg(elf, "%s: ELF_PADDR_OFFSET unset, using 0x%" PRIx64 "\n", + __FUNCTION__, parms->elf_paddr_offset); } parms->virt_offset = parms->virt_base - parms->elf_paddr_offset; parms->virt_kstart = elf->pstart + parms->virt_offset; parms->virt_kend = elf->pend + parms->virt_offset; - if (UNSET_ADDR == parms->virt_entry) - parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry); + if ( parms->virt_entry == UNSET_ADDR ) + parms->virt_entry = elf_uval(elf, elf->ehdr, e_entry); elf_msg(elf, "%s: addresses:\n", __FUNCTION__); elf_msg(elf, " virt_base = 0x%" PRIx64 "\n", parms->virt_base); @@ -355,7 +364,7 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, (parms->virt_base > parms->virt_kstart) ) { elf_err(elf, "%s: ERROR: ELF start or entries are out of bounds.\n", - __FUNCTION__); + __FUNCTION__); return -1; } @@ -366,7 +375,7 @@ static int elf_xen_addr_calc_check(struct elf_binary *elf, /* glue it all together ... */ int elf_xen_parse(struct elf_binary *elf, - struct elf_dom_parms *parms) + struct elf_dom_parms *parms) { const elf_note *note; const elf_shdr *shdr; @@ -382,39 +391,49 @@ int elf_xen_parse(struct elf_binary *elf, /* find and parse elf notes */ count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - shdr = elf_shdr_by_index(elf, i); - if (0 == strcmp(elf_section_name(elf, shdr), "__xen_guest")) - parms->guest_info = elf_section_start(elf, shdr); - if (elf_uval(elf, shdr, sh_type) != SHT_NOTE) - continue; - parms->elf_note_start = elf_section_start(elf, shdr); - parms->elf_note_end = elf_section_end(elf, shdr); - for (note = parms->elf_note_start; - (void *)note < parms->elf_note_end; - note = elf_note_next(elf, note)) - { - if (0 != strcmp(elf_note_name(elf, note), "Xen")) - continue; - if (0 != elf_xen_parse_note(elf, parms, note)) - return -1; - xen_elfnotes++; - } + shdr = elf_shdr_by_index(elf, i); + if ( !strcmp(elf_section_name(elf, shdr), "__xen_guest") ) + parms->guest_info = elf_section_start(elf, shdr); + if ( elf_uval(elf, shdr, sh_type) != SHT_NOTE ) + continue; + parms->elf_note_start = elf_section_start(elf, shdr); + parms->elf_note_end = elf_section_end(elf, shdr); + for ( note = parms->elf_note_start; + (void *)note < parms->elf_note_end; + note = elf_note_next(elf, note) ) + { + if ( strcmp(elf_note_name(elf, note), "Xen") ) + continue; + if ( elf_xen_parse_note(elf, parms, note) ) + return -1; + xen_elfnotes++; + } } - if (!xen_elfnotes && parms->guest_info) + if ( !xen_elfnotes && parms->guest_info ) { - parms->elf_note_start = NULL; - parms->elf_note_end = NULL; - elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, - parms->guest_info); - elf_xen_parse_guest_info(elf, parms); + parms->elf_note_start = NULL; + parms->elf_note_end = NULL; + elf_msg(elf, "%s: __xen_guest: \"%s\"\n", __FUNCTION__, + parms->guest_info); + elf_xen_parse_guest_info(elf, parms); } - if (0 != elf_xen_note_check(elf, parms)) - return -1; - if (0 != elf_xen_addr_calc_check(elf, parms)) - return -1; + if ( elf_xen_note_check(elf, parms) != 0 ) + return -1; + if ( elf_xen_addr_calc_check(elf, parms) != 0 ) + return -1; return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c index 381c90b5cc..e106a6f568 100644 --- a/xen/common/libelf/libelf-loader.c +++ b/xen/common/libelf/libelf-loader.c @@ -11,10 +11,10 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) const elf_shdr *shdr; uint64_t i, count, section, offset; - if (!elf_is_elfbinary(image)) + if ( !elf_is_elfbinary(image) ) { - elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__); - return -1; + elf_err(elf, "%s: not an ELF binary\n", __FUNCTION__); + return -1; } memset(elf, 0, sizeof(*elf)); @@ -26,46 +26,46 @@ int elf_init(struct elf_binary *elf, const char *image, size_t size) /* sanity check phdr */ offset = elf_uval(elf, elf->ehdr, e_phoff) + - elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); - if (offset > elf->size) + elf_uval(elf, elf->ehdr, e_phentsize) * elf_phdr_count(elf); + if ( offset > elf->size ) { - elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n", - __FUNCTION__, offset, (unsigned long)elf->size); - return -1; + elf_err(elf, "%s: phdr overflow (off %" PRIx64 " > size %lx)\n", + __FUNCTION__, offset, (unsigned long)elf->size); + return -1; } /* sanity check shdr */ offset = elf_uval(elf, elf->ehdr, e_shoff) + - elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf); - if (offset > elf->size) + elf_uval(elf, elf->ehdr, e_shentsize) * elf_shdr_count(elf); + if ( offset > elf->size ) { - elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n", - __FUNCTION__, offset, (unsigned long)elf->size); - return -1; + elf_err(elf, "%s: shdr overflow (off %" PRIx64 " > size %lx)\n", + __FUNCTION__, offset, (unsigned long)elf->size); + return -1; } /* find section string table */ section = elf_uval(elf, elf->ehdr, e_shstrndx); shdr = elf_shdr_by_index(elf, section); - if (NULL != shdr) - elf->sec_strtab = elf_section_start(elf, shdr); + if ( shdr != NULL ) + elf->sec_strtab = elf_section_start(elf, shdr); /* find symbol table, symbol string table */ count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - shdr = elf_shdr_by_index(elf, i); - if (elf_uval(elf, shdr, sh_type) != SHT_SYMTAB) - continue; - elf->sym_tab = shdr; - shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); - if (NULL == shdr) - { - elf->sym_tab = NULL; - continue; - } - elf->sym_strtab = elf_section_start(elf, shdr); - break; + shdr = elf_shdr_by_index(elf, i); + if ( elf_uval(elf, shdr, sh_type) != SHT_SYMTAB ) + continue; + elf->sym_tab = shdr; + shdr = elf_shdr_by_index(elf, elf_uval(elf, shdr, sh_link)); + if ( shdr == NULL ) + { + elf->sym_tab = NULL; + continue; + } + elf->sym_strtab = elf_section_start(elf, shdr); + break; } return 0; } @@ -91,24 +91,24 @@ void elf_parse_binary(struct elf_binary *elf) uint64_t i, count, paddr, memsz; count = elf_uval(elf, elf->ehdr, e_phnum); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - phdr = elf_phdr_by_index(elf, i); - if (!elf_phdr_is_loadable(elf, phdr)) - continue; - paddr = elf_uval(elf, phdr, p_paddr); - memsz = elf_uval(elf, phdr, p_memsz); - elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64 - " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz); - if (low > paddr) - low = paddr; - if (high < paddr + memsz) - high = paddr + memsz; + phdr = elf_phdr_by_index(elf, i); + if ( !elf_phdr_is_loadable(elf, phdr) ) + continue; + paddr = elf_uval(elf, phdr, p_paddr); + memsz = elf_uval(elf, phdr, p_memsz); + elf_msg(elf, "%s: phdr: paddr=0x%" PRIx64 + " memsz=0x%" PRIx64 "\n", __FUNCTION__, paddr, memsz); + if ( low > paddr ) + low = paddr; + if ( high < paddr + memsz ) + high = paddr + memsz; } elf->pstart = low; elf->pend = high; elf_msg(elf, "%s: memory: 0x%" PRIx64 " -> 0x%" PRIx64 "\n", - __FUNCTION__, elf->pstart, elf->pend); + __FUNCTION__, elf->pstart, elf->pend); } void elf_load_binary(struct elf_binary *elf) @@ -118,18 +118,18 @@ void elf_load_binary(struct elf_binary *elf) char *dest; count = elf_uval(elf, elf->ehdr, e_phnum); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - phdr = elf_phdr_by_index(elf, i); - if (!elf_phdr_is_loadable(elf, phdr)) - continue; - paddr = elf_uval(elf, phdr, p_paddr); - offset = elf_uval(elf, phdr, p_offset); - filesz = elf_uval(elf, phdr, p_filesz); - memsz = elf_uval(elf, phdr, p_memsz); - dest = elf_get_ptr(elf, paddr); - memcpy(dest, elf->image + offset, filesz); - memset(dest + filesz, 0, memsz - filesz); + phdr = elf_phdr_by_index(elf, i); + if ( !elf_phdr_is_loadable(elf, phdr) ) + continue; + paddr = elf_uval(elf, phdr, p_paddr); + offset = elf_uval(elf, phdr, p_offset); + filesz = elf_uval(elf, phdr, p_filesz); + memsz = elf_uval(elf, phdr, p_memsz); + dest = elf_get_ptr(elf, paddr); + memcpy(dest, elf->image + offset, filesz); + memset(dest + filesz, 0, memsz - filesz); } } @@ -144,13 +144,24 @@ uint64_t elf_lookup_addr(struct elf_binary * elf, const char *symbol) uint64_t value; sym = elf_sym_by_name(elf, symbol); - if (NULL == sym) + if ( sym == NULL ) { - elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol); - return -1; + elf_err(elf, "%s: not found: %s\n", __FUNCTION__, symbol); + return -1; } + value = elf_uval(elf, sym, st_value); elf_msg(elf, "%s: symbol \"%s\" at 0x%" PRIx64 "\n", __FUNCTION__, - symbol, value); + symbol, value); return value; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-private.h b/xen/common/libelf/libelf-private.h index c404638f66..321fa5eb63 100644 --- a/xen/common/libelf/libelf-private.h +++ b/xen/common/libelf/libelf-private.h @@ -12,9 +12,9 @@ #include #define elf_msg(elf, fmt, args ... ) \ - if (elf->verbose) printk(fmt, ## args ) + if (elf->verbose) printk(fmt, ## args ) #define elf_err(elf, fmt, args ... ) \ - printk(fmt, ## args ) + printk(fmt, ## args ) #define strtoull(str, end, base) simple_strtoull(str, end, base) #define bswap_16(x) swab16(x) @@ -43,12 +43,12 @@ #include "xc_private.h" #define elf_msg(elf, fmt, args ... ) \ - if (elf->log && elf->verbose) fprintf(elf->log, fmt , ## args ) -#define elf_err(elf, fmt, args ... ) do { \ - if (elf->log) \ - fprintf(elf->log, fmt , ## args ); \ - xc_set_error(XC_INVALID_KERNEL, fmt , ## args ); \ - } while (0) + if (elf->log && elf->verbose) fprintf(elf->log, fmt , ## args ) +#define elf_err(elf, fmt, args ... ) do { \ + if (elf->log) \ + fprintf(elf->log, fmt , ## args ); \ + xc_set_error(XC_INVALID_KERNEL, fmt , ## args ); \ +} while (0) #define safe_strcpy(d,s) \ do { strncpy((d),(s),sizeof((d))-1); \ @@ -58,3 +58,13 @@ do { strncpy((d),(s),sizeof((d))-1); \ #endif #endif /* __LIBELF_PRIVATE_H_ */ + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-relocate.c b/xen/common/libelf/libelf-relocate.c index 7356a94016..89cea4411b 100644 --- a/xen/common/libelf/libelf-relocate.c +++ b/xen/common/libelf/libelf-relocate.c @@ -46,22 +46,22 @@ static const char *rel_names_i386[] = { }; static int elf_reloc_i386(struct elf_binary *elf, int type, - uint64_t addr, uint64_t value) + uint64_t addr, uint64_t value) { void *ptr = elf_get_ptr(elf, addr); uint32_t *u32; - switch (type) + switch ( type ) { case 1 /* R_386_32 */ : - u32 = ptr; - *u32 += elf->reloc_offset; - break; + u32 = ptr; + *u32 += elf->reloc_offset; + break; case 2 /* R_386_PC32 */ : - /* nothing */ - break; + /* nothing */ + break; default: - return -1; + return -1; } return 0; } @@ -96,54 +96,57 @@ static const char *rel_names_x86_64[] = { }; static int elf_reloc_x86_64(struct elf_binary *elf, int type, - uint64_t addr, uint64_t value) + uint64_t addr, uint64_t value) { void *ptr = elf_get_ptr(elf, addr); uint64_t *u64; uint32_t *u32; int32_t *s32; - switch (type) + switch ( type ) { case 1 /* R_X86_64_64 */ : - u64 = ptr; - value += elf->reloc_offset; - *u64 = value; - break; + u64 = ptr; + value += elf->reloc_offset; + *u64 = value; + break; case 2 /* R_X86_64_PC32 */ : - u32 = ptr; - *u32 = value - addr; - if (*u32 != (uint32_t) (value - addr)) - { - elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32 " != 0x%" PRIx32 "\n", - *u32, (uint32_t) (value - addr)); - return -1; - } - break; + u32 = ptr; + *u32 = value - addr; + if ( *u32 != (uint32_t)(value - addr) ) + { + elf_err(elf, "R_X86_64_PC32 overflow: 0x%" PRIx32 + " != 0x%" PRIx32 "\n", + *u32, (uint32_t) (value - addr)); + return -1; + } + break; case 10 /* R_X86_64_32 */ : - u32 = ptr; - value += elf->reloc_offset; - *u32 = value; - if (*u32 != value) - { - elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", - *u32, value); - return -1; - } - break; + u32 = ptr; + value += elf->reloc_offset; + *u32 = value; + if ( *u32 != value ) + { + elf_err(elf, "R_X86_64_32 overflow: 0x%" PRIx32 + " != 0x%" PRIx64 "\n", + *u32, value); + return -1; + } + break; case 11 /* R_X86_64_32S */ : - s32 = ptr; - value += elf->reloc_offset; - *s32 = value; - if (*s32 != (int64_t) value) - { - elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32 " != 0x%" PRIx64 "\n", - *s32, (int64_t) value); - return -1; - } - break; + s32 = ptr; + value += elf->reloc_offset; + *s32 = value; + if ( *s32 != (int64_t) value ) + { + elf_err(elf, "R_X86_64_32S overflow: 0x%" PRIx32 + " != 0x%" PRIx64 "\n", + *s32, (int64_t) value); + return -1; + } + break; default: - return -1; + return -1; } return 0; } @@ -154,19 +157,19 @@ static struct relocs { const char **names; int count; int (*func) (struct elf_binary * elf, int type, uint64_t addr, - uint64_t value); + uint64_t value); } relocs[] = /* *INDENT-OFF* */ { [EM_386] = { - .names = rel_names_i386, - .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]), - .func = elf_reloc_i386, + .names = rel_names_i386, + .count = sizeof(rel_names_i386) / sizeof(rel_names_i386[0]), + .func = elf_reloc_i386, }, [EM_X86_64] = { - .names = rel_names_x86_64, - .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]), - .func = elf_reloc_x86_64, + .names = rel_names_x86_64, + .count = sizeof(rel_names_x86_64) / sizeof(rel_names_x86_64[0]), + .func = elf_reloc_x86_64, } }; /* *INDENT-ON* */ @@ -175,18 +178,18 @@ static struct relocs { static const char *rela_name(int machine, int type) { - if (machine > sizeof(relocs) / sizeof(relocs[0])) - return "unknown mach"; - if (!relocs[machine].names) - return "unknown mach"; - if (type > relocs[machine].count) - return "unknown rela"; + if ( machine > sizeof(relocs) / sizeof(relocs[0]) ) + return "unknown mach"; + if ( !relocs[machine].names ) + return "unknown mach"; + if ( type > relocs[machine].count ) + return "unknown rela"; return relocs[machine].names[type]; } static int elf_reloc_section(struct elf_binary *elf, - const elf_shdr * rels, - const elf_shdr * sect, const elf_shdr * syms) + const elf_shdr * rels, + const elf_shdr * sect, const elf_shdr * syms) { const void *ptr, *end; const elf_shdr *shdr; @@ -204,18 +207,18 @@ static int elf_reloc_section(struct elf_binary *elf, int machine; machine = elf_uval(elf, elf->ehdr, e_machine); - if (machine >= sizeof(relocs) / sizeof(relocs[0]) || - NULL == relocs[machine].func) + if ( (machine >= (sizeof(relocs) / sizeof(relocs[0]))) || + (relocs[machine].func == NULL) ) { - elf_err(elf, "%s: can't handle machine %d\n", - __FUNCTION__, machine); - return -1; + elf_err(elf, "%s: can't handle machine %d\n", + __FUNCTION__, machine); + return -1; } - if (elf_swap(elf)) + if ( elf_swap(elf) ) { - elf_err(elf, "%s: non-native byte order, relocation not supported\n", - __FUNCTION__); - return -1; + elf_err(elf, "%s: non-native byte order, relocation not supported\n", + __FUNCTION__); + return -1; } s_type = elf_uval(elf, rels, sh_type); @@ -223,89 +226,89 @@ static int elf_reloc_section(struct elf_binary *elf, ptr = elf_section_start(elf, rels); end = elf_section_end(elf, rels); - for (; ptr < end; ptr += rsize) + for ( ; ptr < end; ptr += rsize ) { - switch (s_type) - { - case SHT_REL: - rel = ptr; - r_offset = elf_uval(elf, rel, r_offset); - r_info = elf_uval(elf, rel, r_info); - r_addend = 0; - break; - case SHT_RELA: - rela = ptr; - r_offset = elf_uval(elf, rela, r_offset); - r_info = elf_uval(elf, rela, r_info); - r_addend = elf_uval(elf, rela, r_addend); - break; - default: - /* can't happen */ - return -1; - } - if (elf_64bit(elf)) - { - r_type = ELF64_R_TYPE(r_info); - r_sym = ELF64_R_SYM(r_info); - } - else - { - r_type = ELF32_R_TYPE(r_info); - r_sym = ELF32_R_SYM(r_info); - } + switch ( s_type ) + { + case SHT_REL: + rel = ptr; + r_offset = elf_uval(elf, rel, r_offset); + r_info = elf_uval(elf, rel, r_info); + r_addend = 0; + break; + case SHT_RELA: + rela = ptr; + r_offset = elf_uval(elf, rela, r_offset); + r_info = elf_uval(elf, rela, r_info); + r_addend = elf_uval(elf, rela, r_addend); + break; + default: + /* can't happen */ + return -1; + } + if ( elf_64bit(elf) ) + { + r_type = ELF64_R_TYPE(r_info); + r_sym = ELF64_R_SYM(r_info); + } + else + { + r_type = ELF32_R_TYPE(r_info); + r_sym = ELF32_R_SYM(r_info); + } - sym = elf_sym_by_index(elf, r_sym); - shndx = elf_uval(elf, sym, st_shndx); - switch (shndx) - { - case SHN_UNDEF: - sname = "*UNDEF*"; - sbase = 0; - break; - case SHN_COMMON: - elf_err(elf, "%s: invalid section: %" PRId64 "\n", - __FUNCTION__, shndx); - return -1; - case SHN_ABS: - sname = "*ABS*"; - sbase = 0; - break; - default: - shdr = elf_shdr_by_index(elf, shndx); - if (NULL == shdr) - { - elf_err(elf, "%s: invalid section: %" PRId64 "\n", - __FUNCTION__, shndx); - return -1; - } - sname = elf_section_name(elf, shdr); - sbase = elf_uval(elf, shdr, sh_addr); - } + sym = elf_sym_by_index(elf, r_sym); + shndx = elf_uval(elf, sym, st_shndx); + switch ( shndx ) + { + case SHN_UNDEF: + sname = "*UNDEF*"; + sbase = 0; + break; + case SHN_COMMON: + elf_err(elf, "%s: invalid section: %" PRId64 "\n", + __FUNCTION__, shndx); + return -1; + case SHN_ABS: + sname = "*ABS*"; + sbase = 0; + break; + default: + shdr = elf_shdr_by_index(elf, shndx); + if ( shdr == NULL ) + { + elf_err(elf, "%s: invalid section: %" PRId64 "\n", + __FUNCTION__, shndx); + return -1; + } + sname = elf_section_name(elf, shdr); + sbase = elf_uval(elf, shdr, sh_addr); + } - addr = r_offset; - value = elf_uval(elf, sym, st_value); - value += r_addend; + addr = r_offset; + value = elf_uval(elf, sym, st_value); + value += r_addend; - if (elf->log && elf->verbose > 1) - { - uint64_t st_name = elf_uval(elf, sym, st_name); - const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*"; + if ( elf->log && (elf->verbose > 1) ) + { + uint64_t st_name = elf_uval(elf, sym, st_name); + const char *name = st_name ? elf->sym_strtab + st_name : "*NONE*"; - elf_msg(elf, - "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 "," - " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]" - " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n", - __FUNCTION__, rela_name(machine, r_type), r_type, r_offset, - r_addend, name, elf_uval(elf, sym, st_value), sname, sbase, - addr, value); - } + elf_msg(elf, + "%s: type %s [%d], off 0x%" PRIx64 ", add 0x%" PRIx64 "," + " sym %s [0x%" PRIx64 "], sec %s [0x%" PRIx64 "]" + " -> addr 0x%" PRIx64 " value 0x%" PRIx64 "\n", + __FUNCTION__, rela_name(machine, r_type), r_type, r_offset, + r_addend, name, elf_uval(elf, sym, st_value), sname, sbase, + addr, value); + } - if (-1 == relocs[machine].func(elf, r_type, addr, value)) - { - elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n", - __FUNCTION__, rela_name(machine, r_type), r_type); - return -1; - } + if ( relocs[machine].func(elf, r_type, addr, value) == -1 ) + { + elf_err(elf, "%s: unknown/unsupported reloc type %s [%d]\n", + __FUNCTION__, rela_name(machine, r_type), r_type); + return -1; + } } return 0; } @@ -316,30 +319,40 @@ int elf_reloc(struct elf_binary *elf) uint64_t i, count, type; count = elf_shdr_count(elf); - for (i = 0; i < count; i++) + for ( i = 0; i < count; i++ ) { - rels = elf_shdr_by_index(elf, i); - type = elf_uval(elf, rels, sh_type); - if (type != SHT_REL && type != SHT_RELA) - continue; + rels = elf_shdr_by_index(elf, i); + type = elf_uval(elf, rels, sh_type); + if ( (type != SHT_REL) && (type != SHT_RELA) ) + continue; - sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info)); - syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link)); - if (NULL == sect || NULL == syms) - continue; + sect = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_info)); + syms = elf_shdr_by_index(elf, elf_uval(elf, rels, sh_link)); + if ( NULL == sect || NULL == syms ) + continue; - if (!(elf_uval(elf, sect, sh_flags) & SHF_ALLOC)) - { - elf_msg(elf, "%s: relocations for %s, skipping\n", - __FUNCTION__, elf_section_name(elf, sect)); - continue; - } + if ( !(elf_uval(elf, sect, sh_flags) & SHF_ALLOC) ) + { + elf_msg(elf, "%s: relocations for %s, skipping\n", + __FUNCTION__, elf_section_name(elf, sect)); + continue; + } - elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n", - __FUNCTION__, elf_section_name(elf, sect), - elf_uval(elf, sect, sh_addr)); - if (0 != elf_reloc_section(elf, rels, sect, syms)) - return -1; + elf_msg(elf, "%s: relocations for %s @ 0x%" PRIx64 "\n", + __FUNCTION__, elf_section_name(elf, sect), + elf_uval(elf, sect, sh_addr)); + if ( elf_reloc_section(elf, rels, sect, syms) != 0 ) + return -1; } return 0; } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ diff --git a/xen/common/libelf/libelf-tools.c b/xen/common/libelf/libelf-tools.c index a80fd8534d..fb73c4664e 100644 --- a/xen/common/libelf/libelf-tools.c +++ b/xen/common/libelf/libelf-tools.c @@ -7,7 +7,7 @@ /* ------------------------------------------------------------------------ */ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr, - uint64_t offset, size_t size) + uint64_t offset, size_t size) { int need_swap = elf_swap(elf); const uint8_t *u8; @@ -15,27 +15,27 @@ uint64_t elf_access_unsigned(struct elf_binary * elf, const void *ptr, const uint32_t *u32; const uint64_t *u64; - switch (size) + switch ( size ) { case 1: - u8 = ptr + offset; - return *u8; + u8 = ptr + offset; + return *u8; case 2: - u16 = ptr + offset; - return need_swap ? bswap_16(*u16) : *u16; + u16 = ptr + offset; + return need_swap ? bswap_16(*u16) : *u16; case 4: - u32 = ptr + offset; - return need_swap ? bswap_32(*u32) : *u32; + u32 = ptr + offset; + return need_swap ? bswap_32(*u32) : *u32; case 8: - u64 = ptr + offset; - return need_swap ? bswap_64(*u64) : *u64; + u64 = ptr + offset; + return need_swap ? bswap_64(*u64) : *u64; default: - return 0; + return 0; } } int64_t elf_access_signed(struct elf_binary *elf, const void *ptr, - uint64_t offset, size_t size) + uint64_t offset, size_t size) { int need_swap = elf_swap(elf); const int8_t *s8; @@ -43,22 +43,22 @@ int64_t elf_access_signed(struct elf_binary *elf, const void *ptr, const int32_t *s32; const int64_t *s64; - switch (size) + switch ( size ) { case 1: - s8 = ptr + offset; - return *s8; + s8 = ptr + offset; + return *s8; case 2: - s16 = ptr + offset; - return need_swap ? bswap_16(*s16) : *s16; + s16 = ptr + offset; + return need_swap ? bswap_16(*s16) : *s16; case 4: - s32 = ptr + offset; - return need_swap ? bswap_32(*s32) : *s32; + s32 = ptr + offset; + return need_swap ? bswap_32(*s32) : *s32; case 8: - s64 = ptr + offset; - return need_swap ? bswap_64(*s64) : *s64; + s64 = ptr + offset; + return need_swap ? bswap_64(*s64) : *s64; default: - return 0; + return 0; } } @@ -88,11 +88,12 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) const char *sname; int i; - for (i = 0; i < count; i++) { - shdr = elf_shdr_by_index(elf, i); - sname = elf_section_name(elf, shdr); - if (sname && 0 == strcmp(sname, name)) - return shdr; + for ( i = 0; i < count; i++ ) + { + shdr = elf_shdr_by_index(elf, i); + sname = elf_section_name(elf, shdr); + if ( sname && !strcmp(sname, name) ) + return shdr; } return NULL; } @@ -100,31 +101,35 @@ const elf_shdr *elf_shdr_by_name(struct elf_binary *elf, const char *name) const elf_shdr *elf_shdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_shdr_count(elf); - const void *ptr = NULL; + const void *ptr; - if (index < count) - ptr = elf->image - + elf_uval(elf, elf->ehdr, e_shoff) - + elf_uval(elf, elf->ehdr, e_shentsize) * index; + if ( index >= count ) + return NULL; + + ptr = (elf->image + + elf_uval(elf, elf->ehdr, e_shoff) + + elf_uval(elf, elf->ehdr, e_shentsize) * index); return ptr; } const elf_phdr *elf_phdr_by_index(struct elf_binary *elf, int index) { uint64_t count = elf_uval(elf, elf->ehdr, e_phnum); - const void *ptr = NULL; + const void *ptr; - if (index < count) - ptr = elf->image - + elf_uval(elf, elf->ehdr, e_phoff) - + elf_uval(elf, elf->ehdr, e_phentsize) * index; + if ( index >= count ) + return NULL; + + ptr = (elf->image + + elf_uval(elf, elf->ehdr, e_phoff) + + elf_uval(elf, elf->ehdr, e_phentsize) * index); return ptr; } const char *elf_section_name(struct elf_binary *elf, const elf_shdr * shdr) { - if (NULL == elf->sec_strtab) - return "unknown"; + if ( elf->sec_strtab == NULL ) + return "unknown"; return elf->sec_strtab + elf_uval(elf, shdr, sh_name); } @@ -136,7 +141,7 @@ const void *elf_section_start(struct elf_binary *elf, const elf_shdr * shdr) const void *elf_section_end(struct elf_binary *elf, const elf_shdr * shdr) { return elf->image - + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size); + + elf_uval(elf, shdr, sh_offset) + elf_uval(elf, shdr, sh_size); } const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) @@ -146,16 +151,16 @@ const elf_sym *elf_sym_by_name(struct elf_binary *elf, const char *symbol) const elf_sym *sym; uint64_t info, name; - for (; ptr < end; ptr += elf_size(elf, sym)) + for ( ; ptr < end; ptr += elf_size(elf, sym) ) { - sym = ptr; - info = elf_uval(elf, sym, st_info); - name = elf_uval(elf, sym, st_name); - if (ELF32_ST_BIND(info) != STB_GLOBAL) - continue; - if (strcmp(elf->sym_strtab + name, symbol) != 0) - continue; - return sym; + sym = ptr; + info = elf_uval(elf, sym, st_info); + name = elf_uval(elf, sym, st_name); + if ( ELF32_ST_BIND(info) != STB_GLOBAL ) + continue; + if ( strcmp(elf->sym_strtab + name, symbol) ) + continue; + return sym; } return NULL; } @@ -192,9 +197,9 @@ uint64_t elf_note_numeric(struct elf_binary *elf, const elf_note * note) case 2: case 4: case 8: - return elf_access_unsigned(elf, desc, 0, descsz); + return elf_access_unsigned(elf, desc, 0, descsz); default: - return 0; + return 0; } } const elf_note *elf_note_next(struct elf_binary *elf, const elf_note * note) @@ -211,9 +216,7 @@ int elf_is_elfbinary(const void *image) { const Elf32_Ehdr *ehdr = image; - if (IS_ELF(*ehdr)) - return 1; - return 0; + return IS_ELF(*ehdr); } int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr) @@ -223,3 +226,13 @@ int elf_phdr_is_loadable(struct elf_binary *elf, const elf_phdr * phdr) return ((p_type == PT_LOAD) && (p_flags & (PF_W | PF_X)) != 0); } + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */