From 4af35bad437f20acacf65b18cb8d0eff4d5de089 Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 22 Feb 2007 12:21:29 +0000 Subject: [PATCH 1/9] [XEN] don't emulate stack operations on shadowed pages Signed-off-by: Tim Deegan --- xen/arch/x86/mm/shadow/multi.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index cce70bc522..f5b4e0eb3b 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2902,7 +2902,23 @@ static int sh_page_fault(struct vcpu *v, if ( is_hvm_domain(d) ) hvm_store_cpu_guest_regs(v, regs, NULL); - SHADOW_PRINTK("emulate: eip=%#lx\n", (unsigned long)regs->eip); + SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", + (unsigned long)regs->eip, (unsigned long)regs->esp); + + /* Check whether this looks like a stack operation. */ + if ( (va & PAGE_MASK) == (regs->esp & PAGE_MASK) ) + { + /* Forcibly unshadow and return. It's important to do this before + * we emulate: if the faulting stack operation was the guest handling + * an interrupt, then + * (a) the instruction at %eip is irrelevant; and + * (b) we might inject some other fault and mask the real one */ + gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: " + "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", + (unsigned long)regs->esp, va, mfn_x(gmfn)); + sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */); + goto done; + } emul_ops = shadow_init_emulation(&emul_ctxt, regs); From 20b4aeb2239ce3e682aa1a1cc67c660f15a38134 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 22 Feb 2007 12:49:44 +0000 Subject: [PATCH 2/9] hvm: Do not take shadow-emulation path if we are trying to inject an event into the HVM guest. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 8 ++++++++ xen/arch/x86/hvm/vmx/vmx.c | 14 ++++++++++++++ xen/arch/x86/mm/shadow/multi.c | 29 +++++++++++++++++++++++------ xen/include/asm-x86/hvm/hvm.h | 7 +++++++ 4 files changed, 52 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index cff193c4cf..a6dd6307f4 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -982,6 +982,12 @@ static void svm_hvm_inject_exception( v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2; } +static int svm_injection_pending(struct vcpu *v) +{ + struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; + return (vmcb->vintr.fields.irq || vmcb->exitintinfo.fields.v); +} + int start_svm(void) { u32 eax, ecx, edx; @@ -1058,6 +1064,8 @@ int start_svm(void) hvm_funcs.init_ap_context = svm_init_ap_context; hvm_funcs.init_hypercall_page = svm_init_hypercall_page; + hvm_funcs.injection_pending = svm_injection_pending; + hvm_enable(); return 1; diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 0301781c18..017a818d1d 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -990,6 +990,18 @@ static void vmx_update_vtpr(struct vcpu *v, unsigned long value) /* VMX doesn't have a V_TPR field */ } +static int vmx_injection_pending(struct vcpu *v) +{ + unsigned int idtv_info_field; + + ASSERT(v == current); + + idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD); + + return (v->arch.hvm_vmx.vector_injected || + (idtv_info_field & INTR_INFO_VALID_MASK)); +} + /* Setup HVM interfaces */ static void vmx_setup_hvm_funcs(void) { @@ -1025,6 +1037,8 @@ static void vmx_setup_hvm_funcs(void) hvm_funcs.init_ap_context = vmx_init_ap_context; hvm_funcs.init_hypercall_page = vmx_init_hypercall_page; + + hvm_funcs.injection_pending = vmx_injection_pending; } int start_vmx(void) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index f5b4e0eb3b..1f5cbb3aba 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2901,18 +2901,35 @@ static int sh_page_fault(struct vcpu *v, goto not_a_shadow_fault; if ( is_hvm_domain(d) ) + { + /* + * If we are in the middle of injecting an exception or interrupt then + * we should not emulate: it is not the instruction at %eip that caused + * the fault. Furthermore it is almost certainly the case the handler + * stack is currently considered to be a page table, so we should + * unshadow the faulting page before exiting. + */ + if ( hvm_injection_pending(v) ) + { + gdprintk(XENLOG_DEBUG, "write to pagetable during event " + "injection: cr2=%#lx, mfn=%#lx\n", + va, mfn_x(gmfn)); + sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */); + goto done; + } + hvm_store_cpu_guest_regs(v, regs, NULL); + } + SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", (unsigned long)regs->eip, (unsigned long)regs->esp); - /* Check whether this looks like a stack operation. */ + /* + * Check whether this looks like a stack operation. + * If so, forcibly unshadow and return. + */ if ( (va & PAGE_MASK) == (regs->esp & PAGE_MASK) ) { - /* Forcibly unshadow and return. It's important to do this before - * we emulate: if the faulting stack operation was the guest handling - * an interrupt, then - * (a) the instruction at %eip is irrelevant; and - * (b) we might inject some other fault and mask the real one */ gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: " "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", (unsigned long)regs->esp, va, mfn_x(gmfn)); diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 125c73d2ce..57c263a7b5 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -134,6 +134,8 @@ struct hvm_function_table { int vcpuid, int trampoline_vector); void (*init_hypercall_page)(struct domain *d, void *hypercall_page); + + int (*injection_pending)(struct vcpu *v); }; extern struct hvm_function_table hvm_funcs; @@ -262,4 +264,9 @@ hvm_inject_exception(unsigned int trapnr, int errcode, unsigned long cr2) int hvm_bringup_ap(int vcpuid, int trampoline_vector); +static inline int hvm_injection_pending(struct vcpu *v) +{ + return hvm_funcs.injection_pending(v); +} + #endif /* __ASM_X86_HVM_HVM_H__ */ From 15130ac0dc5b63d9a4b86b1cfc667f2229954209 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 22 Feb 2007 13:03:49 +0000 Subject: [PATCH 3/9] hvm: Turn stack-pointer comparison on shadow-emulate path into a heuristic which we can allow to fail. Signed-off-by: Keir Fraser --- xen/arch/x86/mm/shadow/multi.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 1f5cbb3aba..e348bebaa6 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2909,7 +2909,7 @@ static int sh_page_fault(struct vcpu *v, * stack is currently considered to be a page table, so we should * unshadow the faulting page before exiting. */ - if ( hvm_injection_pending(v) ) + if ( unlikely(hvm_injection_pending(v)) ) { gdprintk(XENLOG_DEBUG, "write to pagetable during event " "injection: cr2=%#lx, mfn=%#lx\n", @@ -2925,16 +2925,20 @@ static int sh_page_fault(struct vcpu *v, (unsigned long)regs->eip, (unsigned long)regs->esp); /* - * Check whether this looks like a stack operation. - * If so, forcibly unshadow and return. + * Check whether this looks like a stack operation. If so, unshadow the + * faulting page. We can allow this to fail: if it does fail then we + * carry on and emulate, otherwise we bail immediately. Failure is + * tolerated because this is only a heuristic (e.g., stack segment base + * address is ignored). */ - if ( (va & PAGE_MASK) == (regs->esp & PAGE_MASK) ) + if ( unlikely((va & PAGE_MASK) == (regs->esp & PAGE_MASK)) ) { gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: " "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", (unsigned long)regs->esp, va, mfn_x(gmfn)); - sh_remove_shadows(v, gmfn, 0 /* thorough */, 1 /* must succeed */); - goto done; + sh_remove_shadows(v, gmfn, 0 /* thorough */, 0 /* can fail */); + if ( !(mfn_to_page(gmfn)->count_info & PGC_page_table) ) + goto done; } emul_ops = shadow_init_emulation(&emul_ctxt, regs); From 1df42b817ab03ec2407d04b3f3d876dfb5a1b39b Mon Sep 17 00:00:00 2001 From: Tim Deegan Date: Thu, 22 Feb 2007 14:58:26 +0000 Subject: [PATCH 4/9] Fix perfc=y build Signed-off-by: Tim Deegan --- xen/include/xen/perfc.h | 1 + 1 file changed, 1 insertion(+) diff --git a/xen/include/xen/perfc.h b/xen/include/xen/perfc.h index 97ef9cd2ed..935d995554 100644 --- a/xen/include/xen/perfc.h +++ b/xen/include/xen/perfc.h @@ -5,6 +5,7 @@ #ifdef PERF_COUNTERS #include +#include #include /* From 92eb4bd779250e470191a0d36f4a310134fb76c8 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 22 Feb 2007 15:22:16 +0000 Subject: [PATCH 5/9] x86: Detect shadow-emulate write to stack from inside the write handler, where we can quite conveniently check whether the access segment is SS. This will only give a false positive for non-stack writes that override the destination segment to SS, which it is probably safe to assume will never happen when the destination is a legitimate page table! For now, instead of bailing and unshadowing just increment a perfctr and we'll see if that increases fast under any reasonable workload. Signed-off-by: Keir Fraser --- xen/arch/x86/mm/shadow/common.c | 4 ++++ xen/arch/x86/mm/shadow/multi.c | 17 ----------------- xen/include/asm-x86/perfc_defn.h | 1 + 3 files changed, 5 insertions(+), 17 deletions(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index f74d18a3c6..e3b4821010 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -275,6 +275,10 @@ hvm_emulate_write(enum x86_segment seg, unsigned long addr; int rc; + /* How many emulations could we save if we unshadowed on stack writes? */ + if ( seg == x86_seg_ss ) + perfc_incrc(shadow_fault_emulate_stack); + rc = hvm_translate_linear_addr( seg, offset, bytes, hvm_access_write, sh_ctxt, &addr); if ( rc ) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index e348bebaa6..a1748058f9 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2924,23 +2924,6 @@ static int sh_page_fault(struct vcpu *v, SHADOW_PRINTK("emulate: eip=%#lx esp=%#lx\n", (unsigned long)regs->eip, (unsigned long)regs->esp); - /* - * Check whether this looks like a stack operation. If so, unshadow the - * faulting page. We can allow this to fail: if it does fail then we - * carry on and emulate, otherwise we bail immediately. Failure is - * tolerated because this is only a heuristic (e.g., stack segment base - * address is ignored). - */ - if ( unlikely((va & PAGE_MASK) == (regs->esp & PAGE_MASK)) ) - { - gdprintk(XENLOG_DEBUG, "guest stack is on a shadowed frame: " - "%%esp=%#lx, cr2=%#lx, mfn=%#lx\n", - (unsigned long)regs->esp, va, mfn_x(gmfn)); - sh_remove_shadows(v, gmfn, 0 /* thorough */, 0 /* can fail */); - if ( !(mfn_to_page(gmfn)->count_info & PGC_page_table) ) - goto done; - } - emul_ops = shadow_init_emulation(&emul_ctxt, regs); /* diff --git a/xen/include/asm-x86/perfc_defn.h b/xen/include/asm-x86/perfc_defn.h index ba1e32c8fd..054fa0f1af 100644 --- a/xen/include/asm-x86/perfc_defn.h +++ b/xen/include/asm-x86/perfc_defn.h @@ -56,6 +56,7 @@ PERFCOUNTER_CPU(shadow_fault_bail_user_supervisor, PERFCOUNTER_CPU(shadow_fault_emulate_read, "shadow_fault emulates a read") PERFCOUNTER_CPU(shadow_fault_emulate_write, "shadow_fault emulates a write") PERFCOUNTER_CPU(shadow_fault_emulate_failed, "shadow_fault emulator fails") +PERFCOUNTER_CPU(shadow_fault_emulate_stack, "shadow_fault emulate stack write") PERFCOUNTER_CPU(shadow_fault_mmio, "shadow_fault handled as mmio") PERFCOUNTER_CPU(shadow_fault_fixed, "shadow_fault fixed fault") PERFCOUNTER_CPU(shadow_ptwr_emulate, "shadow causes ptwr to emulate") From 6a20532c7b680a6aef8896491f14226157f4cb85 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 22 Feb 2007 15:26:21 +0000 Subject: [PATCH 6/9] alloc_boot_pages() allocates downwards from high memory. This conserves low memory. Provide new function alloc_boot_low_pages() for those callers who actually require lowmem pages (e.g., below 4GB). Based on a patch by Chris Lalancette Signed-off-by: Keir Fraser --- xen/arch/x86/setup.c | 8 ++---- xen/common/page_alloc.c | 62 ++++++++++++++++++++++++++++++----------- xen/include/xen/mm.h | 7 +++-- 3 files changed, 53 insertions(+), 24 deletions(-) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index bb15e9b955..79adbd5f7f 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -508,7 +508,6 @@ void __init __start_xen(multiboot_info_t *mbi) unsigned long kdump_start, kdump_size, k; /* Mark images pages as free for now. */ - init_boot_pages(initial_images_start, initial_images_end); kdump_start = kexec_crash_area.start; @@ -526,17 +525,14 @@ void __init __start_xen(multiboot_info_t *mbi) kdump_size >>= PAGE_SHIFT; /* Allocate pages for Kdump memory area. */ - - k = alloc_boot_pages_at(kdump_size, kdump_start); - if ( k != kdump_start ) + if ( !reserve_boot_pages(kdump_start, kdump_size) ) panic("Unable to reserve Kdump memory\n"); /* Allocate pages for relocated initial images. */ - k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0; k += (initial_images_end - initial_images_start) >> PAGE_SHIFT; - k = alloc_boot_pages(k, 1); + k = alloc_boot_low_pages(k, 1); if ( k == 0 ) panic("Unable to allocate initial images memory\n"); diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c index 1102d2fd5b..b7e8416d94 100644 --- a/xen/common/page_alloc.c +++ b/xen/common/page_alloc.c @@ -95,9 +95,10 @@ static unsigned long scrub_pages; static unsigned long *alloc_bitmap; #define PAGES_PER_MAPWORD (sizeof(unsigned long) * 8) -#define allocated_in_map(_pn) \ -( !! (alloc_bitmap[(_pn)/PAGES_PER_MAPWORD] & \ - (1UL<<((_pn)&(PAGES_PER_MAPWORD-1)))) ) +#define allocated_in_map(_pn) \ +({ unsigned long ___pn = (_pn); \ + !!(alloc_bitmap[___pn/PAGES_PER_MAPWORD] & \ + (1UL<<(___pn&(PAGES_PER_MAPWORD-1)))); }) /* * Hint regarding bitwise arithmetic in map_{alloc,free}: @@ -240,36 +241,65 @@ void init_boot_pages(paddr_t ps, paddr_t pe) } } -unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at) +int reserve_boot_pages(unsigned long first_pfn, unsigned long nr_pfns) { unsigned long i; for ( i = 0; i < nr_pfns; i++ ) - if ( allocated_in_map(pfn_at + i) ) + if ( allocated_in_map(first_pfn + i) ) break; - if ( i == nr_pfns ) + if ( i != nr_pfns ) + return 0; + + map_alloc(first_pfn, nr_pfns); + return 1; +} + +unsigned long alloc_boot_low_pages( + unsigned long nr_pfns, unsigned long pfn_align) +{ + unsigned long pg, i; + + /* Search forwards to obtain lowest available range. */ + for ( pg = first_valid_mfn & ~(pfn_align-1); + (pg + nr_pfns) < max_page; + pg = (pg + i + pfn_align - 1) & ~(pfn_align - 1) ) { - map_alloc(pfn_at, nr_pfns); - return pfn_at; + for ( i = 0; i < nr_pfns; i++ ) + if ( allocated_in_map(pg+i) ) + break; + if ( i == nr_pfns ) + { + map_alloc(pg, nr_pfns); + return pg; + } } return 0; } -unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align) +unsigned long alloc_boot_pages( + unsigned long nr_pfns, unsigned long pfn_align) { - unsigned long pg; + unsigned long pg, i; - pg = first_valid_mfn & ~(pfn_align-1); - while ( (pg + nr_pfns) < max_page ) + /* Search backwards to obtain highest available range. */ + for ( pg = (max_page - nr_pfns) & ~(pfn_align - 1); + pg >= first_valid_mfn; + pg = (pg + i - nr_pfns) & ~(pfn_align - 1) ) { - if ( alloc_boot_pages_at(nr_pfns, pg) != 0 ) - break; - pg += pfn_align; + for ( i = 0; i < nr_pfns; i++ ) + if ( allocated_in_map(pg+i) ) + break; + if ( i == nr_pfns ) + { + map_alloc(pg, nr_pfns); + return pg; + } } - return pg; + return 0; } diff --git a/xen/include/xen/mm.h b/xen/include/xen/mm.h index 2326b70442..9a121b1f08 100644 --- a/xen/include/xen/mm.h +++ b/xen/include/xen/mm.h @@ -39,8 +39,11 @@ struct page_info; /* Boot-time allocator. Turns into generic allocator after bootstrap. */ paddr_t init_boot_allocator(paddr_t bitmap_start); void init_boot_pages(paddr_t ps, paddr_t pe); -unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align); -unsigned long alloc_boot_pages_at(unsigned long nr_pfns, unsigned long pfn_at); +unsigned long alloc_boot_pages( + unsigned long nr_pfns, unsigned long pfn_align); +unsigned long alloc_boot_low_pages( + unsigned long nr_pfns, unsigned long pfn_align); +int reserve_boot_pages(unsigned long first_pfn, unsigned long nr_pfns); void end_boot_allocator(void); /* Generic allocator. These functions are *not* interrupt-safe. */ From 22c07c8f80658a1873425e1893445f41a98e468f Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Thu, 22 Feb 2007 22:27:40 +0000 Subject: [PATCH 7/9] x86/64: Fix a user of alloc_boot_pages() who should use alloc_boot_low_pages() instead. Signed-off-by: Keir Fraser --- xen/arch/x86/setup.c | 9 +++++++-- xen/arch/x86/x86_64/mm.c | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c index 79adbd5f7f..61271bbee3 100644 --- a/xen/arch/x86/setup.c +++ b/xen/arch/x86/setup.c @@ -476,7 +476,7 @@ void __init __start_xen(multiboot_info_t *mbi) s = initial_images_end; init_boot_pages(s, e); -#if defined (CONFIG_X86_64) +#if defined(CONFIG_X86_64) /* * x86/64 maps all registered RAM. Points to note: * 1. The initial pagetable already maps low 1GB, so skip that. @@ -532,7 +532,12 @@ void __init __start_xen(multiboot_info_t *mbi) k = ((initial_images_end - initial_images_start) & ~PAGE_MASK) ? 1 : 0; k += (initial_images_end - initial_images_start) >> PAGE_SHIFT; - k = alloc_boot_low_pages(k, 1); +#if defined(CONFIG_X86_32) + /* Must allocate within bootstrap 1:1 limits. */ + k = alloc_boot_low_pages(k, 1); /* 0x0 - HYPERVISOR_VIRT_START */ +#else + k = alloc_boot_pages(k, 1); +#endif if ( k == 0 ) panic("Unable to allocate initial images memory\n"); diff --git a/xen/arch/x86/x86_64/mm.c b/xen/arch/x86/x86_64/mm.c index a482c10a06..b098b21f5e 100644 --- a/xen/arch/x86/x86_64/mm.c +++ b/xen/arch/x86/x86_64/mm.c @@ -44,7 +44,8 @@ struct page_info *alloc_xen_pagetable(void) if ( !early_boot ) return alloc_domheap_page(NULL); - pfn = alloc_boot_pages(1, 1); + /* Early pagetables must come from low 1GB of memory. */ + pfn = alloc_boot_low_pages(1, 1); /* 0x0 - 0x40000000 */ return ((pfn == 0) ? NULL : mfn_to_page(pfn)); } From 11e8d023ca155afdc579b4a7a53de44da19dea9f Mon Sep 17 00:00:00 2001 From: Jake Wires Date: Thu, 22 Feb 2007 21:32:17 -0800 Subject: [PATCH 8/9] [TAPDISK] minor changes to tapdisk and plugins * open all parent images read-only * expose parent image names to tapdisk (needed for locking api) Signed-off-by: Jake Wires --- tools/blktap/drivers/block-aio.c | 25 +++-- tools/blktap/drivers/block-qcow.c | 81 +++++++++-------- tools/blktap/drivers/block-ram.c | 22 +++-- tools/blktap/drivers/block-sync.c | 20 ++-- tools/blktap/drivers/block-vmdk.c | 23 +++-- tools/blktap/drivers/img2qcow.c | 2 +- tools/blktap/drivers/qcow2raw.c | 4 +- tools/blktap/drivers/tapdisk.c | 146 +++++++++++++++++++----------- tools/blktap/drivers/tapdisk.h | 44 ++++++--- 9 files changed, 224 insertions(+), 143 deletions(-) diff --git a/tools/blktap/drivers/block-aio.c b/tools/blktap/drivers/block-aio.c index bbcc4c785a..733407b8c6 100644 --- a/tools/blktap/drivers/block-aio.c +++ b/tools/blktap/drivers/block-aio.c @@ -152,9 +152,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -int tdaio_open (struct disk_driver *dd, const char *name) +int tdaio_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int i, fd, ret = 0; + int i, fd, ret = 0, o_flags; struct td_state *s = dd->td_state; struct tdaio_state *prv = (struct tdaio_state *)dd->private; @@ -187,12 +187,15 @@ int tdaio_open (struct disk_driver *dd, const char *name) prv->iocb_free[i] = &prv->iocb_list[i]; /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -280,6 +283,9 @@ int tdaio_submit(struct disk_driver *dd) int ret; struct tdaio_state *prv = (struct tdaio_state *)dd->private; + if (!prv->iocb_queued) + return 0; + ret = io_submit(prv->aio_ctx, prv->iocb_queued, prv->iocb_queue); /* XXX: TODO: Handle error conditions here. */ @@ -324,12 +330,13 @@ int tdaio_do_callbacks(struct disk_driver *dd, int sid) return rsp; } -int tdaio_has_parent(struct disk_driver *dd) +int tdaio_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdaio_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdaio_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -341,8 +348,8 @@ struct tap_disk tapdisk_aio = { .td_queue_read = tdaio_queue_read, .td_queue_write = tdaio_queue_write, .td_submit = tdaio_submit, - .td_has_parent = tdaio_has_parent, - .td_get_parent = tdaio_get_parent, .td_close = tdaio_close, .td_do_callbacks = tdaio_do_callbacks, + .td_get_parent_id = tdaio_get_parent_id, + .td_validate_parent = tdaio_validate_parent }; diff --git a/tools/blktap/drivers/block-qcow.c b/tools/blktap/drivers/block-qcow.c index 2859b08829..185c670111 100644 --- a/tools/blktap/drivers/block-qcow.c +++ b/tools/blktap/drivers/block-qcow.c @@ -209,23 +209,6 @@ static int init_aio_state(struct disk_driver *dd) return -1; } -/* - *Test if block is zero. - * Return: - * 1 for TRUE - * 0 for FALSE - */ -static inline int IS_ZERO(char *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - /*if not zero, return false*/ - if (ZERO_TEST(*(buf + i))) return 0; - } - return 1; -} - static uint32_t gen_cksum(char *ptr, int len) { unsigned char *md; @@ -825,9 +808,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize qcow state. */ -int tdqcow_open (struct disk_driver *dd, const char *name) +int tdqcow_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int fd, len, i, shift, ret, size, l1_table_size; + int fd, len, i, shift, ret, size, l1_table_size, o_flags; struct td_state *bs = dd->td_state; struct tdqcow_state *s = (struct tdqcow_state *)dd->private; char *buf; @@ -838,7 +821,9 @@ int tdqcow_open (struct disk_driver *dd, const char *name) DPRINTF("QCOW: Opening %s\n",name); - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if (fd < 0) { DPRINTF("Unable to open %s (%d)\n",name,0 - errno); return -1; @@ -1016,7 +1001,8 @@ int tdqcow_queue_read(struct disk_driver *dd, uint64_t sector, * as busy and try again later */ return cb(dd, -EBUSY, sector + n, nb_sectors - n, id, private); - } else rsp += ret; + } else + rsp += ret; } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) { aio_unlock(s, sector); if (decompress_cluster(s, cluster_offset) < 0) { @@ -1403,21 +1389,15 @@ int qcow_compress_cluster(struct tdqcow_state *s, int64_t sector_num, return 0; } -int tdqcow_has_parent(struct disk_driver *dd) -{ - struct tdqcow_state *s = (struct tdqcow_state *)dd->private; - return (s->backing_file_offset ? 1 : 0); -} - -int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd) +int tdqcow_get_parent_id(struct disk_driver *dd, struct disk_id *id) { off_t off; char *buf, *filename; - int len, secs, ret = -1; - struct tdqcow_state *child = (struct tdqcow_state *)cdd->private; + int len, secs, err = -EINVAL; + struct tdqcow_state *child = (struct tdqcow_state *)dd->private; if (!child->backing_file_offset) - return -1; + return TD_NO_PARENT; /* read the backing file name */ len = child->backing_file_size; @@ -1432,14 +1412,39 @@ int tdqcow_get_parent(struct disk_driver *cdd, struct disk_driver *pdd) if (read(child->fd, buf, secs << 9) != secs << 9) goto out; - filename = buf + (child->backing_file_offset - off); - filename[len] = '\0'; + filename = buf + (child->backing_file_offset - off); + filename[len] = '\0'; - /*Open backing file*/ - ret = tdqcow_open(pdd, filename); + id->name = strdup(filename); + id->drivertype = DISK_TYPE_QCOW; + err = 0; out: free(buf); - return ret; + return err; +} + +int tdqcow_validate_parent(struct disk_driver *child, + struct disk_driver *parent, td_flag_t flags) +{ + struct stat stats; + uint64_t psize, csize; + struct tdqcow_state *c = (struct tdqcow_state *)child->private; + struct tdqcow_state *p = (struct tdqcow_state *)parent->private; + + if (stat(p->name, &stats)) + return -EINVAL; + if (get_filesize(p->name, &psize, &stats)) + return -EINVAL; + + if (stat(c->name, &stats)) + return -EINVAL; + if (get_filesize(c->name, &csize, &stats)) + return -EINVAL; + + if (csize != psize) + return -EINVAL; + + return 0; } struct tap_disk tapdisk_qcow = { @@ -1449,8 +1454,8 @@ struct tap_disk tapdisk_qcow = { .td_queue_read = tdqcow_queue_read, .td_queue_write = tdqcow_queue_write, .td_submit = tdqcow_submit, - .td_has_parent = tdqcow_has_parent, - .td_get_parent = tdqcow_get_parent, .td_close = tdqcow_close, .td_do_callbacks = tdqcow_do_callbacks, + .td_get_parent_id = tdqcow_get_parent_id, + .td_validate_parent = tdqcow_validate_parent }; diff --git a/tools/blktap/drivers/block-ram.c b/tools/blktap/drivers/block-ram.c index c23dd6b27e..3b4ef7ceb5 100644 --- a/tools/blktap/drivers/block-ram.c +++ b/tools/blktap/drivers/block-ram.c @@ -135,11 +135,11 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize ram state. */ -int tdram_open (struct disk_driver *dd, const char *name) +int tdram_open (struct disk_driver *dd, const char *name, td_flag_t flags) { char *p; uint64_t size; - int i, fd, ret = 0, count = 0; + int i, fd, ret = 0, count = 0, o_flags; struct td_state *s = dd->td_state; struct tdram_state *prv = (struct tdram_state *)dd->private; @@ -167,12 +167,15 @@ int tdram_open (struct disk_driver *dd, const char *name) } /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ((fd == -1) && (errno == EINVAL)) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -275,12 +278,13 @@ int tdram_do_callbacks(struct disk_driver *dd, int sid) return 1; } -int tdram_has_parent(struct disk_driver *dd) +int tdram_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdram_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdram_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -292,8 +296,8 @@ struct tap_disk tapdisk_ram = { .td_queue_read = tdram_queue_read, .td_queue_write = tdram_queue_write, .td_submit = tdram_submit, - .td_has_parent = tdram_has_parent, - .td_get_parent = tdram_get_parent, .td_close = tdram_close, .td_do_callbacks = tdram_do_callbacks, + .td_get_parent_id = tdram_get_parent_id, + .td_validate_parent = tdram_validate_parent }; diff --git a/tools/blktap/drivers/block-sync.c b/tools/blktap/drivers/block-sync.c index 367eb70ab9..74f77d6f61 100644 --- a/tools/blktap/drivers/block-sync.c +++ b/tools/blktap/drivers/block-sync.c @@ -118,9 +118,9 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -int tdsync_open (struct disk_driver *dd, const char *name) +int tdsync_open (struct disk_driver *dd, const char *name, td_flag_t flags) { - int i, fd, ret = 0; + int i, fd, ret = 0, o_flags; struct td_state *s = dd->td_state; struct tdsync_state *prv = (struct tdsync_state *)dd->private; @@ -130,11 +130,14 @@ int tdsync_open (struct disk_driver *dd, const char *name) return (0 - errno); /* Open the file */ - fd = open(name, O_RDWR | O_DIRECT | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ + o_flags &= ~O_DIRECT; fd = open(name, O_RDWR | O_LARGEFILE); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -223,12 +226,13 @@ int tdsync_do_callbacks(struct disk_driver *dd, int sid) return 1; } -int tdsync_has_parent(struct disk_driver *dd) +int tdsync_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -int tdsync_get_parent(struct disk_driver *dd, struct disk_driver *parent) +int tdsync_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -240,8 +244,8 @@ struct tap_disk tapdisk_sync = { .td_queue_read = tdsync_queue_read, .td_queue_write = tdsync_queue_write, .td_submit = tdsync_submit, - .td_has_parent = tdsync_has_parent, - .td_get_parent = tdsync_get_parent, .td_close = tdsync_close, .td_do_callbacks = tdsync_do_callbacks, + .td_get_parent_id = tdsync_get_parent_id, + .td_validate_parent = tdsync_validate_parent }; diff --git a/tools/blktap/drivers/block-vmdk.c b/tools/blktap/drivers/block-vmdk.c index 5a6a5ca775..4ab88373ea 100644 --- a/tools/blktap/drivers/block-vmdk.c +++ b/tools/blktap/drivers/block-vmdk.c @@ -119,10 +119,11 @@ static inline void init_fds(struct disk_driver *dd) } /* Open the disk file and initialize aio state. */ -static int tdvmdk_open (struct disk_driver *dd, const char *name) +static int tdvmdk_open (struct disk_driver *dd, + const char *name, td_flag_t flags) { int ret, fd; - int l1_size, i; + int l1_size, i, o_flags; uint32_t magic; struct td_state *s = dd->td_state; struct tdvmdk_state *prv = (struct tdvmdk_state *)dd->private; @@ -133,12 +134,15 @@ static int tdvmdk_open (struct disk_driver *dd, const char *name) return -1; /* Open the file */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags = O_DIRECT | O_LARGEFILE | + ((flags == TD_RDONLY) ? O_RDONLY : O_RDWR); + fd = open(name, o_flags); if ( (fd == -1) && (errno == EINVAL) ) { /* Maybe O_DIRECT isn't supported. */ - fd = open(name, O_RDWR | O_LARGEFILE); + o_flags &= ~O_DIRECT; + fd = open(name, o_flags); if (fd != -1) DPRINTF("WARNING: Accessing image without" "O_DIRECT! (%s)\n", name); @@ -394,12 +398,13 @@ static int tdvmdk_do_callbacks(struct disk_driver *dd, int sid) return 1; } -static int tdvmdk_has_parent(struct disk_driver *dd) +static int tdvmdk_get_parent_id(struct disk_driver *dd, struct disk_id *id) { - return 0; + return TD_NO_PARENT; } -static int tdvmdk_get_parent(struct disk_driver *dd, struct disk_driver *parent) +static int tdvmdk_validate_parent(struct disk_driver *dd, + struct disk_driver *parent, td_flag_t flags) { return -EINVAL; } @@ -411,8 +416,8 @@ struct tap_disk tapdisk_vmdk = { .td_queue_read = tdvmdk_queue_read, .td_queue_write = tdvmdk_queue_write, .td_submit = tdvmdk_submit, - .td_has_parent = tdvmdk_has_parent, - .td_get_parent = tdvmdk_get_parent, .td_close = tdvmdk_close, .td_do_callbacks = tdvmdk_do_callbacks, + .td_get_parent_id = tdvmdk_get_parent_id, + .td_validate_parent = tdvmdk_validate_parent }; diff --git a/tools/blktap/drivers/img2qcow.c b/tools/blktap/drivers/img2qcow.c index 7baf28fb02..926cf2742e 100644 --- a/tools/blktap/drivers/img2qcow.c +++ b/tools/blktap/drivers/img2qcow.c @@ -201,7 +201,7 @@ int main(int argc, char *argv[]) dd.private = malloc(dd.drv->private_data_size); /*Open qcow file*/ - if (dd.drv->td_open(&dd, argv[1])!=0) { + if (dd.drv->td_open(&dd, argv[1], 0)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[1]); exit(-1); } diff --git a/tools/blktap/drivers/qcow2raw.c b/tools/blktap/drivers/qcow2raw.c index 8adf573309..55ae4ad108 100644 --- a/tools/blktap/drivers/qcow2raw.c +++ b/tools/blktap/drivers/qcow2raw.c @@ -169,7 +169,7 @@ int main(int argc, char *argv[]) ddqcow.drv = &tapdisk_qcow; ddqcow.private = malloc(ddqcow.drv->private_data_size); - if (ddqcow.drv->td_open(&ddqcow, argv[2])!=0) { + if (ddqcow.drv->td_open(&ddqcow, argv[2], TD_RDONLY)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n",argv[2]); exit(-1); } else DFPRINTF("QCOW file opened, size %llu\n", @@ -270,7 +270,7 @@ int main(int argc, char *argv[]) ddaio.drv = &tapdisk_aio; ddaio.private = malloc(ddaio.drv->private_data_size); - if (ddaio.drv->td_open(&ddaio, argv[1])!=0) { + if (ddaio.drv->td_open(&ddaio, argv[1], 0)!=0) { DFPRINTF("Unable to open Qcow file [%s]\n", argv[1]); exit(-1); } diff --git a/tools/blktap/drivers/tapdisk.c b/tools/blktap/drivers/tapdisk.c index 6215770d97..43a037a053 100644 --- a/tools/blktap/drivers/tapdisk.c +++ b/tools/blktap/drivers/tapdisk.c @@ -81,6 +81,15 @@ void daemonize(void) return; } +static void free_driver(struct disk_driver *d) +{ + if (d->name) + free(d->name); + if (d->private) + free(d->private); + free(d); +} + static void unmap_disk(struct td_state *s) { tapdev_info_t *info = s->ring_info; @@ -91,8 +100,7 @@ static void unmap_disk(struct td_state *s) while (dd) { tmp = dd->next; dd->drv->td_close(dd); - free(dd->private); - free(dd); + free_driver(dd); dd = tmp; } @@ -112,7 +120,6 @@ static void unmap_disk(struct td_state *s) free(s); return; - } void sig_handler(int sig) @@ -205,26 +212,6 @@ static struct td_state *state_init(void) return s; } -static struct disk_driver *disk_init(struct td_state *s, struct tap_disk *drv) -{ - struct disk_driver *dd; - - dd = calloc(1, sizeof(struct disk_driver)); - if (!dd) - return NULL; - - dd->private = malloc(drv->private_data_size); - if (!dd->private) { - free(dd); - return NULL; - } - - dd->drv = drv; - dd->td_state = s; - - return dd; -} - static int map_new_dev(struct td_state *s, int minor) { int tap_fd; @@ -280,49 +267,94 @@ static int map_new_dev(struct td_state *s, int minor) return -1; } -static int open_disk(struct td_state *s, struct disk_driver *dd, char *path) +static struct disk_driver *disk_init(struct td_state *s, + struct tap_disk *drv, char *name) +{ + struct disk_driver *dd; + + dd = calloc(1, sizeof(struct disk_driver)); + if (!dd) + return NULL; + + dd->private = malloc(drv->private_data_size); + if (!dd->private) { + free(dd); + return NULL; + } + + dd->drv = drv; + dd->td_state = s; + dd->name = name; + + return dd; +} + +static int open_disk(struct td_state *s, struct tap_disk *drv, char *path) { int err; - struct disk_driver *d = dd; + char *dup; + struct disk_id id; + struct disk_driver *d; - err = dd->drv->td_open(dd, path); + dup = strdup(path); + if (!dup) + return -ENOMEM; + + memset(&id, 0, sizeof(struct disk_id)); + s->disks = d = disk_init(s, drv, dup); + if (!d) + return -ENOMEM; + + err = drv->td_open(d, path, 0); if (err) - return err; + goto fail; /* load backing files as necessary */ - while (d->drv->td_has_parent(d)) { + while ((err = d->drv->td_get_parent_id(d, &id)) == 0) { struct disk_driver *new; - new = calloc(1, sizeof(struct disk_driver)); + if (id.drivertype > MAX_DISK_TYPES || + !get_driver(id.drivertype) || !id.name) + goto fail; + + dup = strdup(id.name); + if (!dup) + goto fail; + + new = disk_init(s, get_driver(id.drivertype), dup); if (!new) goto fail; - new->drv = d->drv; - new->td_state = s; - new->private = malloc(new->drv->private_data_size); - if (!new->private) { - free(new); - goto fail; - } - - err = d->drv->td_get_parent(d, new); + + err = new->drv->td_open(new, new->name, TD_RDONLY); if (err) goto fail; + err = d->drv->td_validate_parent(d, new, 0); + if (err) { + d->next = new; + goto fail; + } + d = d->next = new; + free(id.name); } - return 0; + if (err >= 0) + return 0; fail: DPRINTF("failed opening disk\n"); - while (dd) { - d = dd->next; - dd->drv->td_close(dd); - free(dd->private); - free(dd); - dd = d; + if (id.name) + free(id.name); + d = s->disks; + while (d) { + struct disk_driver *tmp = d->next; + d->drv->td_close(d); + free_driver(d); + d = tmp; } - return err; + s->disks = NULL; + return -1; } static int read_msg(char *buf) @@ -334,7 +366,6 @@ static int read_msg(char *buf) msg_newdev_t *msg_dev; msg_pid_t *msg_pid; struct tap_disk *drv; - struct disk_driver *dd; int ret = -1; struct td_state *s = NULL; fd_list_entry_t *entry; @@ -369,14 +400,8 @@ static int read_msg(char *buf) if (s == NULL) goto params_done; - s->disks = dd = disk_init(s, drv); - if (!dd) { - free(s); - goto params_done; - } - /*Open file*/ - ret = open_disk(s, dd, path); + ret = open_disk(s, drv, path); if (ret) goto params_done; @@ -785,6 +810,19 @@ int main(int argc, char *argv[]) } } + /* completed io from above may have + * queued new requests on chained disks */ + if (progress_made) { + td_for_each_disk(ptr->s, dd) { + dd->early += + dd->drv->td_submit(dd); + if (dd->early > 0) { + io_done(dd, 10); + dd->early = 0; + } + } + } + if (FD_ISSET(ptr->tap_fd, &readfds) || (info->busy.req && progress_made)) get_io_request(ptr->s); diff --git a/tools/blktap/drivers/tapdisk.h b/tools/blktap/drivers/tapdisk.h index 7b03fa0762..b76d46cce5 100644 --- a/tools/blktap/drivers/tapdisk.h +++ b/tools/blktap/drivers/tapdisk.h @@ -42,10 +42,15 @@ * * - The fd used for poll is an otherwise unused pipe, which allows poll to * be safely called without ever returning anything. - * + * * NOTE: tapdisk uses the number of sectors submitted per request as a * ref count. Plugins must use the callback function to communicate the * completion--or error--of every sector submitted to them. + * + * td_get_parent_id returns: + * 0 if parent id successfully retrieved + * TD_NO_PARENT if no parent exists + * -errno on error */ #ifndef TAPDISK_H_ @@ -71,12 +76,23 @@ #define MAX_IOFD 2 #define BLK_NOT_ALLOCATED 99 +#define TD_NO_PARENT 1 + +typedef uint32_t td_flag_t; + +#define TD_RDONLY 1 struct td_state; struct tap_disk; +struct disk_id { + char *name; + int drivertype; +}; + struct disk_driver { int early; + char *name; void *private; int io_fd[MAX_IOFD]; struct tap_disk *drv; @@ -105,18 +121,20 @@ typedef int (*td_callback_t)(struct disk_driver *dd, int res, uint64_t sector, struct tap_disk { const char *disk_type; int private_data_size; - int (*td_open) (struct disk_driver *dd, const char *name); - int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, - int nb_sectors, char *buf, td_callback_t cb, - int id, void *prv); - int (*td_submit) (struct disk_driver *dd); - int (*td_has_parent) (struct disk_driver *dd); - int (*td_get_parent) (struct disk_driver *dd, struct disk_driver *p); - int (*td_close) (struct disk_driver *dd); - int (*td_do_callbacks)(struct disk_driver *dd, int sid); + int (*td_open) (struct disk_driver *dd, + const char *name, td_flag_t flags); + int (*td_queue_read) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *prv); + int (*td_queue_write) (struct disk_driver *dd, uint64_t sector, + int nb_sectors, char *buf, td_callback_t cb, + int id, void *prv); + int (*td_submit) (struct disk_driver *dd); + int (*td_close) (struct disk_driver *dd); + int (*td_do_callbacks) (struct disk_driver *dd, int sid); + int (*td_get_parent_id) (struct disk_driver *dd, struct disk_id *id); + int (*td_validate_parent)(struct disk_driver *dd, + struct disk_driver *p, td_flag_t flags); }; typedef struct disk_info { From 66c10a7e53c813942e154de3ceba8a10b6a192d2 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 23 Feb 2007 10:35:16 +0000 Subject: [PATCH 9/9] hvm: Rename injection_pending() to event_injection_faulted(). Fix the VMX and SVM handlers to reflect the new semantics (which is what is actually required by the one caller, in shadow fault path). Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/svm/svm.c | 6 +++--- xen/arch/x86/hvm/vmx/vmx.c | 8 +++----- xen/arch/x86/mm/shadow/multi.c | 2 +- xen/include/asm-x86/hvm/hvm.h | 6 +++--- 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c index a6dd6307f4..e68c42fc30 100644 --- a/xen/arch/x86/hvm/svm/svm.c +++ b/xen/arch/x86/hvm/svm/svm.c @@ -982,10 +982,10 @@ static void svm_hvm_inject_exception( v->arch.hvm_svm.vmcb->cr2 = v->arch.hvm_svm.cpu_cr2 = cr2; } -static int svm_injection_pending(struct vcpu *v) +static int svm_event_injection_faulted(struct vcpu *v) { struct vmcb_struct *vmcb = v->arch.hvm_svm.vmcb; - return (vmcb->vintr.fields.irq || vmcb->exitintinfo.fields.v); + return vmcb->exitintinfo.fields.v; } int start_svm(void) @@ -1064,7 +1064,7 @@ int start_svm(void) hvm_funcs.init_ap_context = svm_init_ap_context; hvm_funcs.init_hypercall_page = svm_init_hypercall_page; - hvm_funcs.injection_pending = svm_injection_pending; + hvm_funcs.event_injection_faulted = svm_event_injection_faulted; hvm_enable(); diff --git a/xen/arch/x86/hvm/vmx/vmx.c b/xen/arch/x86/hvm/vmx/vmx.c index 017a818d1d..3565fdee22 100644 --- a/xen/arch/x86/hvm/vmx/vmx.c +++ b/xen/arch/x86/hvm/vmx/vmx.c @@ -990,16 +990,14 @@ static void vmx_update_vtpr(struct vcpu *v, unsigned long value) /* VMX doesn't have a V_TPR field */ } -static int vmx_injection_pending(struct vcpu *v) +static int vmx_event_injection_faulted(struct vcpu *v) { unsigned int idtv_info_field; ASSERT(v == current); idtv_info_field = __vmread(IDT_VECTORING_INFO_FIELD); - - return (v->arch.hvm_vmx.vector_injected || - (idtv_info_field & INTR_INFO_VALID_MASK)); + return (idtv_info_field & INTR_INFO_VALID_MASK); } /* Setup HVM interfaces */ @@ -1038,7 +1036,7 @@ static void vmx_setup_hvm_funcs(void) hvm_funcs.init_hypercall_page = vmx_init_hypercall_page; - hvm_funcs.injection_pending = vmx_injection_pending; + hvm_funcs.event_injection_faulted = vmx_event_injection_faulted; } int start_vmx(void) diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index a1748058f9..248e90216b 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -2909,7 +2909,7 @@ static int sh_page_fault(struct vcpu *v, * stack is currently considered to be a page table, so we should * unshadow the faulting page before exiting. */ - if ( unlikely(hvm_injection_pending(v)) ) + if ( unlikely(hvm_event_injection_faulted(v)) ) { gdprintk(XENLOG_DEBUG, "write to pagetable during event " "injection: cr2=%#lx, mfn=%#lx\n", diff --git a/xen/include/asm-x86/hvm/hvm.h b/xen/include/asm-x86/hvm/hvm.h index 57c263a7b5..b5ca99f84b 100644 --- a/xen/include/asm-x86/hvm/hvm.h +++ b/xen/include/asm-x86/hvm/hvm.h @@ -135,7 +135,7 @@ struct hvm_function_table { void (*init_hypercall_page)(struct domain *d, void *hypercall_page); - int (*injection_pending)(struct vcpu *v); + int (*event_injection_faulted)(struct vcpu *v); }; extern struct hvm_function_table hvm_funcs; @@ -264,9 +264,9 @@ hvm_inject_exception(unsigned int trapnr, int errcode, unsigned long cr2) int hvm_bringup_ap(int vcpuid, int trampoline_vector); -static inline int hvm_injection_pending(struct vcpu *v) +static inline int hvm_event_injection_faulted(struct vcpu *v) { - return hvm_funcs.injection_pending(v); + return hvm_funcs.event_injection_faulted(v); } #endif /* __ASM_X86_HVM_HVM_H__ */