[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] merge with xen-unstable.hg
# HG changeset patch # User Alex Williamson <alex.williamson@xxxxxx> # Date 1196438073 25200 # Node ID 32ec5dbe2978fdff4682912de0c78a14d479a8a3 # Parent f9ca1d8c9e656ece820f140c40e3443f39f5d09a # Parent 3057f813da143f0dd6086129b5ce65a97c85e146 merge with xen-unstable.hg --- extras/mini-os/arch/x86/mm.c | 3 extras/mini-os/gnttab.c | 14 + extras/mini-os/lib/string.c | 2 extras/mini-os/netfront.c | 6 extras/mini-os/xenbus/xenbus.c | 1 xen/arch/x86/domctl.c | 13 - xen/arch/x86/hvm/hpet.c | 2 xen/arch/x86/hvm/platform.c | 13 + xen/arch/x86/hvm/vlapic.c | 15 +- xen/arch/x86/hvm/vmx/realmode.c | 84 ++++++++--- xen/arch/x86/hvm/vmx/vmcs.c | 25 ++- xen/arch/x86/hvm/vmx/vmx.c | 7 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c | 22 ++- xen/arch/x86/x86_32/xen.lds.S | 5 xen/arch/x86/x86_64/xen.lds.S | 3 xen/arch/x86/x86_emulate.c | 213 ++++++++++++++++++++++++++---- xen/drivers/char/console.c | 2 xen/include/asm-x86/hvm/vmx/intel-iommu.h | 3 xen/include/asm-x86/hvm/vmx/vmcs.h | 2 xen/include/asm-x86/hvm/vmx/vmx.h | 2 20 files changed, 344 insertions(+), 93 deletions(-) diff -r f9ca1d8c9e65 -r 32ec5dbe2978 extras/mini-os/arch/x86/mm.c --- a/extras/mini-os/arch/x86/mm.c Thu Nov 29 12:15:43 2007 -0700 +++ b/extras/mini-os/arch/x86/mm.c Fri Nov 30 08:54:33 2007 -0700 @@ -270,6 +270,9 @@ void build_pagetable(unsigned long *star start_address += PAGE_SIZE; } + if (HYPERVISOR_update_va_mapping(0, (pte_t) {}, UVMF_INVLPG)) + printk("Unable to unmap page 0\n"); + *start_pfn = pt_pfn; } diff -r f9ca1d8c9e65 -r 32ec5dbe2978 extras/mini-os/gnttab.c --- a/extras/mini-os/gnttab.c Thu Nov 29 12:15:43 2007 -0700 +++ b/extras/mini-os/gnttab.c Fri Nov 30 08:54:33 2007 -0700 @@ -18,6 +18,7 @@ #include <os.h> #include <mm.h> #include <gnttab.h> +#include <semaphore.h> #define NR_RESERVED_ENTRIES 8 @@ -31,20 +32,29 @@ static grant_entry_t *gnttab_table; static grant_ref_t gnttab_list[NR_GRANT_ENTRIES]; +static __DECLARE_SEMAPHORE_GENERIC(gnttab_sem, NR_GRANT_ENTRIES); static void put_free_entry(grant_ref_t ref) { + unsigned long flags; + local_irq_save(flags); gnttab_list[ref] = gnttab_list[0]; gnttab_list[0] = ref; - + local_irq_restore(flags); + up(&gnttab_sem); } static grant_ref_t get_free_entry(void) { - unsigned int ref = gnttab_list[0]; + unsigned int ref; + unsigned long flags; + down(&gnttab_sem); + local_irq_save(flags); + ref = gnttab_list[0]; gnttab_list[0] = gnttab_list[ref]; + local_irq_restore(flags); return ref; } diff -r f9ca1d8c9e65 -r 32ec5dbe2978 extras/mini-os/lib/string.c --- a/extras/mini-os/lib/string.c Thu Nov 29 12:15:43 2007 -0700 +++ b/extras/mini-os/lib/string.c Fri Nov 30 08:54:33 2007 -0700 @@ -142,7 +142,7 @@ char * strchr(const char * s, int c) char * strrchr(const char * s, int c) { - const char *res; + const char *res = NULL; for(; *s != '\0'; ++s) if (*s == (char) c) res = s; diff -r f9ca1d8c9e65 -r 32ec5dbe2978 extras/mini-os/netfront.c --- a/extras/mini-os/netfront.c Thu Nov 29 12:15:43 2007 -0700 +++ b/extras/mini-os/netfront.c Fri Nov 30 08:54:33 2007 -0700 @@ -147,6 +147,7 @@ moretodo: struct net_buffer* buf = &rx_buffers[id]; void* page = buf->page; + /* We are sure to have free gnttab entries since they got released above */ buf->gref = req->gref = gnttab_grant_access(0,virt_to_mfn(page),0); @@ -436,8 +437,9 @@ void netfront_xmit(unsigned char* data,i down(&tx_sem); local_irq_save(flags); - id = get_id_from_freelist(tx_freelist); + local_irq_restore(flags); + buf = &tx_buffers[id]; page = buf->page; @@ -461,7 +463,7 @@ void netfront_xmit(unsigned char* data,i if(notify) notify_remote_via_evtchn(info->evtchn); + local_irq_save(flags); network_tx_buf_gc(); - local_irq_restore(flags); } diff -r f9ca1d8c9e65 -r 32ec5dbe2978 extras/mini-os/xenbus/xenbus.c --- a/extras/mini-os/xenbus/xenbus.c Thu Nov 29 12:15:43 2007 -0700 +++ b/extras/mini-os/xenbus/xenbus.c Fri Nov 30 08:54:33 2007 -0700 @@ -79,7 +79,6 @@ void wait_for_watch(void) schedule(); remove_waiter(w); wake(current); - remove_wait_queue(&w); } char* xenbus_wait_for_value(const char* path,const char* value) diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/domctl.c --- a/xen/arch/x86/domctl.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/domctl.c Fri Nov 30 08:54:33 2007 -0700 @@ -709,11 +709,6 @@ long arch_do_domctl( evc = &domctl->u.ext_vcpucontext; - ret = (evc->size < sizeof(*evc)) ? -EINVAL : 0; - evc->size = sizeof(*evc); - if ( ret != 0 ) - break; - ret = -ESRCH; d = rcu_lock_domain_by_id(domctl->domain); if ( d == NULL ) @@ -726,6 +721,7 @@ long arch_do_domctl( if ( domctl->cmd == XEN_DOMCTL_get_ext_vcpucontext ) { + evc->size = sizeof(*evc); #ifdef __x86_64__ evc->sysenter_callback_cs = v->arch.sysenter_callback_cs; evc->sysenter_callback_eip = v->arch.sysenter_callback_eip; @@ -744,6 +740,9 @@ long arch_do_domctl( } else { + ret = -EINVAL; + if ( evc->size != sizeof(*evc) ) + goto ext_vcpucontext_out; #ifdef __x86_64__ fixup_guest_code_selector(d, evc->sysenter_callback_cs); v->arch.sysenter_callback_cs = evc->sysenter_callback_cs; @@ -755,7 +754,6 @@ long arch_do_domctl( v->arch.syscall32_disables_events = evc->syscall32_disables_events; #else /* We do not support syscall/syscall32/sysenter on 32-bit Xen. */ - ret = -EINVAL; if ( (evc->sysenter_callback_cs & ~3) || evc->sysenter_callback_eip || (evc->syscall32_callback_cs & ~3) || @@ -768,7 +766,8 @@ long arch_do_domctl( ext_vcpucontext_out: rcu_unlock_domain(d); - if ( copy_to_guest(u_domctl, domctl, 1) ) + if ( (domctl->cmd == XEN_DOMCTL_get_ext_vcpucontext) && + copy_to_guest(u_domctl, domctl, 1) ) ret = -EFAULT; } break; diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/hpet.c --- a/xen/arch/x86/hvm/hpet.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/hpet.c Fri Nov 30 08:54:33 2007 -0700 @@ -170,7 +170,7 @@ static unsigned long hpet_read( result = val; if ( length != 8 ) - result = (val >> ((addr & 7) * 8)) & ((1UL << (length * 8)) - 1); + result = (val >> ((addr & 7) * 8)) & ((1ULL << (length * 8)) - 1); spin_unlock(&h->lock); diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/platform.c --- a/xen/arch/x86/hvm/platform.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/platform.c Fri Nov 30 08:54:33 2007 -0700 @@ -1051,13 +1051,18 @@ void handle_mmio(unsigned long gpa) } if ( mmio_decode(address_bytes, inst, mmio_op, &ad_size, - &op_size, &seg_sel) == DECODE_failure ) { - printk("handle_mmio: failed to decode instruction\n"); - printk("mmio opcode: gpa 0x%lx, len %d:", gpa, inst_len); + &op_size, &seg_sel) == DECODE_failure ) + { + gdprintk(XENLOG_WARNING, + "handle_mmio: failed to decode instruction\n"); + gdprintk(XENLOG_WARNING, + "mmio opcode: gpa 0x%lx, len %d:", gpa, inst_len); for ( i = 0; i < inst_len; i++ ) printk(" %02x", inst[i] & 0xFF); printk("\n"); - domain_crash_synchronous(); + + hvm_inject_exception(TRAP_invalid_op, HVM_DELIVER_NO_ERROR_CODE, 0); + return; } regs->eip += inst_len; /* advance %eip */ diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/vlapic.c --- a/xen/arch/x86/hvm/vlapic.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/vlapic.c Fri Nov 30 08:54:33 2007 -0700 @@ -661,7 +661,8 @@ static void vlapic_write(struct vcpu *v, case APIC_TMICT: { - uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)val * vlapic->hw.timer_divisor; + uint64_t period = (uint64_t)APIC_BUS_CYCLE_NS * + (uint32_t)val * vlapic->hw.timer_divisor; vlapic_set_reg(vlapic, APIC_TMICT, val); create_periodic_time(current, &vlapic->pt, period, vlapic->pt.irq, @@ -820,8 +821,10 @@ static void lapic_rearm(struct vlapic *s unsigned long tmict; tmict = vlapic_get_reg(s, APIC_TMICT); - if (tmict > 0) { - uint64_t period = APIC_BUS_CYCLE_NS * (uint32_t)tmict * s->hw.timer_divisor; + if ( tmict > 0 ) + { + uint64_t period = (uint64_t)APIC_BUS_CYCLE_NS * + (uint32_t)tmict * s->hw.timer_divisor; uint32_t lvtt = vlapic_get_reg(s, APIC_LVTT); s->pt.irq = lvtt & APIC_VECTOR_MASK; @@ -830,9 +833,9 @@ static void lapic_rearm(struct vlapic *s &s->timer_last_update); printk("lapic_load to rearm the actimer:" - "bus cycle is %uns, " - "saved tmict count %lu, period %"PRIu64"ns, irq=%"PRIu8"\n", - APIC_BUS_CYCLE_NS, tmict, period, s->pt.irq); + "bus cycle is %uns, " + "saved tmict count %lu, period %"PRIu64"ns, irq=%"PRIu8"\n", + APIC_BUS_CYCLE_NS, tmict, period, s->pt.irq); } lapic_info(s); diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/vmx/realmode.c --- a/xen/arch/x86/hvm/vmx/realmode.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/realmode.c Fri Nov 30 08:54:33 2007 -0700 @@ -88,12 +88,12 @@ static void realmode_deliver_exception( if ( rm_ctxt->ctxt.addr_size == 32 ) { - regs->esp -= 4; + regs->esp -= 6; pstk = regs->esp; } else { - pstk = (uint16_t)(regs->esp - 4); + pstk = (uint16_t)(regs->esp - 6); regs->esp &= ~0xffff; regs->esp |= pstk; } @@ -237,7 +237,8 @@ realmode_emulate_cmpxchg( unsigned int bytes, struct x86_emulate_ctxt *ctxt) { - return X86EMUL_UNHANDLEABLE; + /* Fix this in case the guest is really relying on r-m-w atomicity. */ + return realmode_emulate_write(seg, offset, new, bytes, ctxt); } static int @@ -329,6 +330,36 @@ realmode_read_cr( case 3: case 4: *val = current->arch.hvm_vcpu.guest_cr[reg]; + break; + default: + return X86EMUL_UNHANDLEABLE; + } + + return X86EMUL_OKAY; +} + +static int +realmode_write_cr( + unsigned int reg, + unsigned long val, + struct x86_emulate_ctxt *ctxt) +{ + switch ( reg ) + { + case 0: + if ( !hvm_set_cr0(val) ) + return X86EMUL_UNHANDLEABLE; + break; + case 2: + current->arch.hvm_vcpu.guest_cr[2] = val; + break; + case 3: + if ( !hvm_set_cr3(val) ) + return X86EMUL_UNHANDLEABLE; + break; + case 4: + if ( !hvm_set_cr4(val) ) + return X86EMUL_UNHANDLEABLE; break; default: return X86EMUL_UNHANDLEABLE; @@ -411,6 +442,7 @@ static struct x86_emulate_ops realmode_e .read_io = realmode_read_io, .write_io = realmode_write_io, .read_cr = realmode_read_cr, + .write_cr = realmode_write_cr, .write_rflags = realmode_write_rflags, .wbinvd = realmode_wbinvd, .cpuid = realmode_cpuid, @@ -419,12 +451,12 @@ static struct x86_emulate_ops realmode_e .inject_sw_interrupt = realmode_inject_sw_interrupt }; -int vmx_realmode(struct cpu_user_regs *regs) +void vmx_realmode(struct cpu_user_regs *regs) { struct vcpu *curr = current; struct realmode_emulate_ctxt rm_ctxt; unsigned long intr_info; - int i, rc = 0; + int i, rc; u32 intr_shadow, new_intr_shadow; rm_ctxt.ctxt.regs = regs; @@ -487,29 +519,43 @@ int vmx_realmode(struct cpu_user_regs *r hvm_hlt(regs->eflags); if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) - { - rc = 0; break; - } if ( rc == X86EMUL_UNHANDLEABLE ) { - gdprintk(XENLOG_DEBUG, - "RM %04x:%08lx: %02x %02x %02x %02x %02x %02x\n", + gdprintk(XENLOG_ERR, + "Real-mode emulation failed @ %04x:%08lx: " + "%02x %02x %02x %02x %02x %02x\n", rm_ctxt.seg_reg[x86_seg_cs].sel, rm_ctxt.insn_buf_eip, rm_ctxt.insn_buf[0], rm_ctxt.insn_buf[1], rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3], rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]); - gdprintk(XENLOG_ERR, "Emulation failed\n"); - rc = -EINVAL; - break; - } + domain_crash_synchronous(); + } + } + + /* + * Cannot enter protected mode with bogus selector RPLs and DPLs. Hence we + * fix up as best we can, even though this deviates from native execution + */ + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) + { + /* CS.RPL == SS.RPL == SS.DPL == 0. */ + rm_ctxt.seg_reg[x86_seg_cs].sel &= ~3; + rm_ctxt.seg_reg[x86_seg_ss].sel &= ~3; + /* DS,ES,FS,GS: The most uninvasive trick is to set DPL == RPL. */ + rm_ctxt.seg_reg[x86_seg_ds].attr.fields.dpl = + rm_ctxt.seg_reg[x86_seg_ds].sel & 3; + rm_ctxt.seg_reg[x86_seg_es].attr.fields.dpl = + rm_ctxt.seg_reg[x86_seg_es].sel & 3; + rm_ctxt.seg_reg[x86_seg_fs].attr.fields.dpl = + rm_ctxt.seg_reg[x86_seg_fs].sel & 3; + rm_ctxt.seg_reg[x86_seg_gs].attr.fields.dpl = + rm_ctxt.seg_reg[x86_seg_gs].sel & 3; } for ( i = 0; i < 10; i++ ) hvm_set_segment_register(curr, i, &rm_ctxt.seg_reg[i]); - - return rc; } int vmx_realmode_io_complete(void) @@ -520,12 +566,6 @@ int vmx_realmode_io_complete(void) if ( !curr->arch.hvm_vmx.real_mode_io_in_progress ) return 0; -#if 0 - gdprintk(XENLOG_DEBUG, "RM I/O %d %c bytes=%d addr=%lx data=%lx\n", - p->type, p->dir ? 'R' : 'W', - (int)p->size, (long)p->addr, (long)p->data); -#endif - curr->arch.hvm_vmx.real_mode_io_in_progress = 0; if ( p->dir == IOREQ_READ ) { diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/vmx/vmcs.c --- a/xen/arch/x86/hvm/vmx/vmcs.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vmcs.c Fri Nov 30 08:54:33 2007 -0700 @@ -819,9 +819,15 @@ static unsigned long vmr(unsigned long f return rc ? 0 : val; } -void vmcs_dump_vcpu(void) -{ +void vmcs_dump_vcpu(struct vcpu *v) +{ + struct cpu_user_regs *regs = &v->arch.guest_context.user_regs; unsigned long long x; + + if ( v == current ) + regs = guest_cpu_user_regs(); + + vmx_vmcs_enter(v); printk("*** Guest State ***\n"); printk("CR0: actual=0x%016llx, shadow=0x%016llx, gh_mask=%016llx\n", @@ -841,11 +847,14 @@ void vmcs_dump_vcpu(void) printk(" target2=%016llx, target3=%016llx\n", (unsigned long long)vmr(CR3_TARGET_VALUE2), (unsigned long long)vmr(CR3_TARGET_VALUE3)); - printk("RSP = 0x%016llx RIP = 0x%016llx\n", + printk("RSP = 0x%016llx (0x%016llx) RIP = 0x%016llx (0x%016llx)\n", (unsigned long long)vmr(GUEST_RSP), - (unsigned long long)vmr(GUEST_RIP)); - printk("RFLAGS=0x%016llx DR7 = 0x%016llx\n", + (unsigned long long)regs->esp, + (unsigned long long)vmr(GUEST_RIP), + (unsigned long long)regs->eip); + printk("RFLAGS=0x%016llx (0x%016llx) DR7 = 0x%016llx\n", (unsigned long long)vmr(GUEST_RFLAGS), + (unsigned long long)regs->eflags, (unsigned long long)vmr(GUEST_DR7)); printk("Sysenter RSP=%016llx CS:RIP=%04x:%016llx\n", (unsigned long long)vmr(GUEST_SYSENTER_ESP), @@ -926,6 +935,8 @@ void vmcs_dump_vcpu(void) (uint32_t)vmr(IDT_VECTORING_ERROR_CODE)); printk("TPR Threshold = 0x%02x\n", (uint32_t)vmr(TPR_THRESHOLD)); + + vmx_vmcs_exit(v); } static void vmcs_dump(unsigned char ch) @@ -945,9 +956,7 @@ static void vmcs_dump(unsigned char ch) for_each_vcpu ( d, v ) { printk("\tVCPU %d\n", v->vcpu_id); - vmx_vmcs_enter(v); - vmcs_dump_vcpu(); - vmx_vmcs_exit(v); + vmcs_dump_vcpu(v); } } diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vmx.c Fri Nov 30 08:54:33 2007 -0700 @@ -2722,6 +2722,7 @@ static void vmx_failed_vmentry(unsigned { unsigned int failed_vmentry_reason = (uint16_t)exit_reason; unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION); + struct vcpu *curr = current; printk("Failed vm entry (exit reason 0x%x) ", exit_reason); switch ( failed_vmentry_reason ) @@ -2734,7 +2735,7 @@ static void vmx_failed_vmentry(unsigned break; case EXIT_REASON_MACHINE_CHECK: printk("caused by machine check.\n"); - HVMTRACE_0D(MCE, current); + HVMTRACE_0D(MCE, curr); do_machine_check(regs); break; default: @@ -2743,10 +2744,10 @@ static void vmx_failed_vmentry(unsigned } printk("************* VMCS Area **************\n"); - vmcs_dump_vcpu(); + vmcs_dump_vcpu(curr); printk("**************************************\n"); - domain_crash(current->domain); + domain_crash(curr->domain); } asmlinkage void vmx_vmexit_handler(struct cpu_user_regs *regs) diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/hvm/vmx/vtd/intel-iommu.c --- a/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/hvm/vmx/vtd/intel-iommu.c Fri Nov 30 08:54:33 2007 -0700 @@ -276,6 +276,9 @@ static int __iommu_flush_context( unsigned long flag; unsigned long start_time; + /* Domain id in context is 1 based */ + did++; + /* * In the non-present entry flush case, if hardware doesn't cache * non-present entry we do nothing and if hardware cache non-present @@ -359,6 +362,9 @@ static int __iommu_flush_iotlb(struct io u64 val = 0, val_iva = 0; unsigned long flag; unsigned long start_time; + + /* Domain id in context is 1 based */ + did++; /* * In the non-present entry flush case, if hardware doesn't cache @@ -1037,6 +1043,18 @@ static int domain_context_mapping_one( context_set_translation_type(*context, CONTEXT_TT_PASS_THRU); else { + if ( !hd->pgd ) + { + struct dma_pte *pgd = (struct dma_pte *)alloc_xenheap_page(); + if ( !pgd ) + { + spin_unlock_irqrestore(&hd->mapping_lock, flags); + return -ENOMEM; + } + memset(pgd, 0, PAGE_SIZE); + hd->pgd = pgd; + } + context_set_address_root(*context, virt_to_maddr(hd->pgd)); context_set_translation_type(*context, CONTEXT_TT_MULTI_LEVEL); } @@ -1429,7 +1447,7 @@ void iommu_domain_teardown(struct domain return_devices_to_dom0(d); } -static int domain_context_mapped(struct domain *domain, struct pci_dev *pdev) +static int domain_context_mapped(struct pci_dev *pdev) { struct acpi_drhd_unit *drhd; struct iommu *iommu; @@ -1589,7 +1607,7 @@ static int iommu_prepare_rmrr_dev( if ( ret ) return ret; - if ( domain_context_mapped(d, pdev) == 0 ) + if ( domain_context_mapped(pdev) == 0 ) { drhd = acpi_find_matched_drhd_unit(pdev); ret = domain_context_mapping(d, drhd->iommu, pdev); diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/x86_32/xen.lds.S --- a/xen/arch/x86/x86_32/xen.lds.S Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/x86_32/xen.lds.S Fri Nov 30 08:54:33 2007 -0700 @@ -63,8 +63,9 @@ SECTIONS __initcall_start = .; .initcall.init : { *(.initcall1.init) } :text __initcall_end = .; - .xsm_initcall.init : { __xsm_initcall_start = .; - *(.xsm_initcall.init) __xsm_initcall_end = .; } + __xsm_initcall_start = .; + .xsm_initcall.init : { *(.xsm_initcall.init) } :text + __xsm_initcall_end = .; . = ALIGN(PAGE_SIZE); __init_end = .; diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/x86_64/xen.lds.S --- a/xen/arch/x86/x86_64/xen.lds.S Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/x86_64/xen.lds.S Fri Nov 30 08:54:33 2007 -0700 @@ -61,6 +61,9 @@ SECTIONS __initcall_start = .; .initcall.init : { *(.initcall1.init) } :text __initcall_end = .; + __xsm_initcall_start = .; + .xsm_initcall.init : { *(.xsm_initcall.init) } :text + __xsm_initcall_end = .; . = ALIGN(PAGE_SIZE); __init_end = .; diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/arch/x86/x86_emulate.c Fri Nov 30 08:54:33 2007 -0700 @@ -152,7 +152,8 @@ static uint8_t opcode_table[256] = { DstReg|SrcMem|ModRM|Mov, DstReg|SrcMem|ModRM|Mov, ByteOp|DstMem|SrcImm|ModRM|Mov, DstMem|SrcImm|ModRM|Mov, /* 0xC8 - 0xCF */ - 0, 0, 0, 0, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, + ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, /* 0xD0 - 0xD7 */ ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, ByteOp|DstMem|SrcImplicit|ModRM, DstMem|SrcImplicit|ModRM, @@ -190,7 +191,7 @@ static uint8_t twobyte_table[256] = { /* 0x28 - 0x2F */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x30 - 0x37 */ - ImplicitOps, 0, ImplicitOps, 0, 0, 0, 0, 0, + ImplicitOps, ImplicitOps, ImplicitOps, 0, 0, 0, 0, 0, /* 0x38 - 0x3F */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x40 - 0x47 */ @@ -227,10 +228,10 @@ static uint8_t twobyte_table[256] = { ByteOp|DstMem|SrcNone|ModRM|Mov, ByteOp|DstMem|SrcNone|ModRM|Mov, /* 0xA0 - 0xA7 */ ImplicitOps, ImplicitOps, ImplicitOps, DstBitBase|SrcReg|ModRM, - 0, 0, 0, 0, + DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, 0, /* 0xA8 - 0xAF */ ImplicitOps, ImplicitOps, 0, DstBitBase|SrcReg|ModRM, - 0, 0, 0, DstReg|SrcMem|ModRM, + DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, 0, DstReg|SrcMem|ModRM, /* 0xB0 - 0xB7 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, DstReg|SrcMem|ModRM|Mov, DstBitBase|SrcReg|ModRM, @@ -269,6 +270,13 @@ struct operand { } mem; }; }; + +/* MSRs. */ +#define MSR_TSC 0x10 + +/* Control register flags. */ +#define CR0_PE (1<<0) +#define CR4_TSD (1<<2) /* EFLAGS bit definitions. */ #define EFLG_VIP (1<<20) @@ -476,13 +484,13 @@ do{ asm volatile ( }) #define insn_fetch_type(_type) ((_type)insn_fetch_bytes(sizeof(_type))) -#define _truncate_ea(ea, byte_width) \ +#define truncate_word(ea, byte_width) \ ({ unsigned long __ea = (ea); \ unsigned int _width = (byte_width); \ ((_width == sizeof(unsigned long)) ? __ea : \ (__ea & ((1UL << (_width << 3)) - 1))); \ }) -#define truncate_ea(ea) _truncate_ea((ea), ad_bytes) +#define truncate_ea(ea) truncate_word((ea), ad_bytes) #define mode_64bit() (def_ad_bytes == 8) @@ -500,12 +508,11 @@ do { } \ }) -/* Given byte has even parity (even number of 1s)? */ -static int even_parity(uint8_t v) +/* Given longword has even parity (even number of 1s)? */ +static int even_parity(unsigned long v) { - asm ( "test %%al,%%al; setp %%al" - : "=a" (v) : "0" (v) ); - return v; + asm ( "test %0,%0; setp %b0" : "=a" (v) : "0" (v) ); + return (uint8_t)v; } /* Update address held in a register, based on addressing mode. */ @@ -526,10 +533,10 @@ do { #define sp_pre_dec(dec) ({ \ _register_address_increment(_regs.esp, -(dec), ctxt->sp_size/8); \ - _truncate_ea(_regs.esp, ctxt->sp_size/8); \ + truncate_word(_regs.esp, ctxt->sp_size/8); \ }) #define sp_post_inc(inc) ({ \ - unsigned long __esp = _truncate_ea(_regs.esp, ctxt->sp_size/8); \ + unsigned long __esp = truncate_word(_regs.esp, ctxt->sp_size/8); \ _register_address_increment(_regs.esp, (inc), ctxt->sp_size/8); \ __esp; \ }) @@ -738,7 +745,7 @@ in_realmode( return 0; rc = ops->read_cr(0, &cr0, ctxt); - return (!rc && !(cr0 & 1)); + return (!rc && !(cr0 & CR0_PE)); } static int @@ -1477,7 +1484,7 @@ x86_emulate( case 0xc4: /* les */ { unsigned long sel; dst.val = x86_seg_es; - les: + les: /* dst.val identifies the segment */ generate_exception_if(src.type != OP_MEM, EXC_UD); if ( (rc = ops->read(src.mem.seg, src.mem.off + src.bytes, &sel, 2, ctxt)) != 0 ) @@ -1716,7 +1723,8 @@ x86_emulate( break; case 2: /* call (near) */ case 4: /* jmp (near) */ - if ( ((op_bytes = dst.bytes) != 8) && mode_64bit() ) + dst.type = OP_NONE; + if ( (dst.bytes != 8) && mode_64bit() ) { dst.bytes = op_bytes = 8; if ( dst.type == OP_REG ) @@ -1732,7 +1740,7 @@ x86_emulate( break; case 3: /* call (far, absolute indirect) */ case 5: /* jmp (far, absolute indirect) */ { - unsigned long sel, eip = dst.val; + unsigned long sel; if ( (rc = ops->read(dst.mem.seg, dst.mem.off+dst.bytes, &sel, 2, ctxt)) ) @@ -1752,7 +1760,7 @@ x86_emulate( if ( (rc = load_seg(x86_seg_cs, sel, ctxt, ops)) != 0 ) goto done; - _regs.eip = eip; + _regs.eip = dst.val; dst.type = OP_NONE; break; @@ -1859,7 +1867,7 @@ x86_emulate( src.val = x86_seg_es; pop_seg: fail_if(ops->write_segment == NULL); - /* 64-bit mode: PUSH defaults to a 64-bit operand. */ + /* 64-bit mode: POP defaults to a 64-bit operand. */ if ( mode_64bit() && (op_bytes == 4) ) op_bytes = 8; if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), @@ -1907,7 +1915,7 @@ x86_emulate( _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0; _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0; - _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0; + _regs.eflags |= even_parity((uint8_t)_regs.eax) ? EFLG_PF : 0; break; } @@ -1931,7 +1939,7 @@ x86_emulate( _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0; _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0; - _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0; + _regs.eflags |= even_parity((uint8_t)_regs.eax) ? EFLG_PF : 0; break; } @@ -1998,9 +2006,18 @@ x86_emulate( (unsigned long *)&_regs.ecx, (unsigned long *)&_regs.eax }; generate_exception_if(mode_64bit(), EXC_UD); for ( i = 0; i < 8; i++ ) + { if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), - regs[i], op_bytes, ctxt)) != 0 ) - goto done; + &dst.val, op_bytes, ctxt)) != 0 ) + goto done; + switch ( op_bytes ) + { + case 1: *(uint8_t *)regs[i] = (uint8_t)dst.val; break; + case 2: *(uint16_t *)regs[i] = (uint16_t)dst.val; break; + case 4: *regs[i] = (uint32_t)dst.val; break; /* 64b: zero-ext */ + case 8: *regs[i] = dst.val; break; + } + } break; } @@ -2257,6 +2274,77 @@ x86_emulate( op_bytes = mode_64bit() ? 8 : op_bytes; if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset), &dst.val, op_bytes, ctxt)) != 0 ) + goto done; + _regs.eip = dst.val; + break; + } + + case 0xc8: /* enter imm16,imm8 */ { + uint16_t size = insn_fetch_type(uint16_t); + uint8_t depth = insn_fetch_type(uint8_t) & 31; + int i; + + dst.type = OP_REG; + dst.bytes = (mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes; + dst.reg = (unsigned long *)&_regs.ebp; + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), + _regs.ebp, dst.bytes, ctxt)) ) + goto done; + dst.val = _regs.esp; + + if ( depth > 0 ) + { + for ( i = 1; i < depth; i++ ) + { + unsigned long ebp, temp_data; + ebp = truncate_word(_regs.ebp - i*dst.bytes, ctxt->sp_size/8); + if ( (rc = ops->read(x86_seg_ss, ebp, + &temp_data, dst.bytes, ctxt)) || + (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), + temp_data, dst.bytes, ctxt)) ) + goto done; + } + if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(dst.bytes), + dst.val, dst.bytes, ctxt)) ) + goto done; + } + + sp_pre_dec(size); + break; + } + + case 0xc9: /* leave */ + /* First writeback, to %%esp. */ + dst.type = OP_REG; + dst.bytes = (mode_64bit() && (op_bytes == 4)) ? 8 : op_bytes; + dst.reg = (unsigned long *)&_regs.esp; + dst.val = _regs.ebp; + + /* Flush first writeback, since there is a second. */ + switch ( dst.bytes ) + { + case 1: *(uint8_t *)dst.reg = (uint8_t)dst.val; break; + case 2: *(uint16_t *)dst.reg = (uint16_t)dst.val; break; + case 4: *dst.reg = (uint32_t)dst.val; break; /* 64b: zero-ext */ + case 8: *dst.reg = dst.val; break; + } + + /* Second writeback, to %%ebp. */ + dst.reg = (unsigned long *)&_regs.ebp; + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(dst.bytes), + &dst.val, dst.bytes, ctxt)) ) + goto done; + break; + + case 0xca: /* ret imm16 (far) */ + case 0xcb: /* ret (far) */ { + int offset = (b == 0xca) ? insn_fetch_type(uint16_t) : 0; + op_bytes = mode_64bit() ? 8 : op_bytes; + if ( (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes), + &dst.val, op_bytes, ctxt)) || + (rc = ops->read(x86_seg_ss, sp_post_inc(op_bytes + offset), + &src.val, op_bytes, ctxt)) || + (rc = load_seg(x86_seg_cs, (uint16_t)src.val, ctxt, ops)) ) goto done; _regs.eip = dst.val; break; @@ -2317,7 +2405,7 @@ x86_emulate( _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0; _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0; - _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0; + _regs.eflags |= even_parity((uint8_t)_regs.eax) ? EFLG_PF : 0; break; } @@ -2329,7 +2417,7 @@ x86_emulate( _regs.eflags &= ~(EFLG_SF|EFLG_ZF|EFLG_PF); _regs.eflags |= ((uint8_t)_regs.eax == 0) ? EFLG_ZF : 0; _regs.eflags |= (( int8_t)_regs.eax < 0) ? EFLG_SF : 0; - _regs.eflags |= even_parity(_regs.eax) ? EFLG_PF : 0; + _regs.eflags |= even_parity((uint8_t)_regs.eax) ? EFLG_PF : 0; break; } @@ -2528,6 +2616,35 @@ x86_emulate( emulate_2op_SrcV_nobyte("bt", src, dst, _regs.eflags); break; + case 0xa4: /* shld imm8,r,r/m */ + case 0xa5: /* shld %%cl,r,r/m */ + case 0xac: /* shrd imm8,r,r/m */ + case 0xad: /* shrd %%cl,r,r/m */ { + uint8_t shift, width = dst.bytes << 3; + shift = (b & 1) ? (uint8_t)_regs.ecx : insn_fetch_type(uint8_t); + if ( (shift &= width - 1) == 0 ) + break; + dst.orig_val = truncate_word(dst.orig_val, dst.bytes); + dst.val = ((shift == width) ? src.val : + (b & 8) ? + /* shrd */ + ((dst.orig_val >> shift) | + truncate_word(src.val << (width - shift), dst.bytes)) : + /* shld */ + ((dst.orig_val << shift) | + ((src.val >> (width - shift)) & ((1ull << shift) - 1)))); + dst.val = truncate_word(dst.val, dst.bytes); + _regs.eflags &= ~(EFLG_OF|EFLG_SF|EFLG_ZF|EFLG_PF|EFLG_CF); + if ( (dst.val >> ((b & 8) ? (shift - 1) : (width - shift))) & 1 ) + _regs.eflags |= EFLG_CF; + if ( ((dst.val ^ dst.orig_val) >> (width - 1)) & 1 ) + _regs.eflags |= EFLG_OF; + _regs.eflags |= ((dst.val >> (width - 1)) & 1) ? EFLG_SF : 0; + _regs.eflags |= (dst.val == 0) ? EFLG_ZF : 0; + _regs.eflags |= even_parity(dst.val) ? EFLG_PF : 0; + break; + } + case 0xb3: btr: /* btr */ emulate_2op_SrcV_nobyte("btr", src, dst, _regs.eflags); break; @@ -2651,6 +2768,7 @@ x86_emulate( { case 0x01: /* Grp7 */ { struct segment_register reg; + unsigned long base, limit, cr0, cr0w; switch ( modrm_reg & 7 ) { @@ -2676,16 +2794,40 @@ x86_emulate( fail_if(ops->write_segment == NULL); memset(®, 0, sizeof(reg)); if ( (rc = ops->read(ea.mem.seg, ea.mem.off+0, - (unsigned long *)®.limit, 2, ctxt)) || + &limit, 2, ctxt)) || (rc = ops->read(ea.mem.seg, ea.mem.off+2, - (unsigned long *)®.base, - mode_64bit() ? 8 : 4, ctxt)) ) + &base, mode_64bit() ? 8 : 4, ctxt)) ) goto done; + reg.base = base; + reg.limit = limit; if ( op_bytes == 2 ) reg.base &= 0xffffff; if ( (rc = ops->write_segment((modrm_reg & 1) ? x86_seg_idtr : x86_seg_gdtr, ®, ctxt)) ) + goto done; + break; + case 4: /* smsw */ + ea.bytes = 2; + dst = ea; + fail_if(ops->read_cr == NULL); + if ( (rc = ops->read_cr(0, &dst.val, ctxt)) ) + goto done; + d |= Mov; /* force writeback */ + break; + case 6: /* lmsw */ + fail_if(ops->read_cr == NULL); + fail_if(ops->write_cr == NULL); + if ( (rc = ops->read_cr(0, &cr0, ctxt)) ) + goto done; + if ( ea.type == OP_REG ) + cr0w = *ea.reg; + else if ( (rc = ops->read(ea.mem.seg, ea.mem.off, + &cr0w, 2, ctxt)) ) + goto done; + cr0 &= 0xffff0000; + cr0 |= (uint16_t)cr0w; + if ( (rc = ops->write_cr(0, cr0, ctxt)) ) goto done; break; default: @@ -2763,6 +2905,21 @@ x86_emulate( break; } + case 0x31: /* rdtsc */ { + unsigned long cr4; + uint64_t val; + fail_if(ops->read_cr == NULL); + if ( (rc = ops->read_cr(4, &cr4, ctxt)) ) + goto done; + generate_exception_if((cr4 & CR4_TSD) && !mode_ring0(), EXC_GP); + fail_if(ops->read_msr == NULL); + if ( (rc = ops->read_msr(MSR_TSC, &val, ctxt)) != 0 ) + goto done; + _regs.edx = (uint32_t)(val >> 32); + _regs.eax = (uint32_t)(val >> 0); + break; + } + case 0x32: /* rdmsr */ { uint64_t val; generate_exception_if(!mode_ring0(), EXC_GP); diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/drivers/char/console.c --- a/xen/drivers/char/console.c Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/drivers/char/console.c Fri Nov 30 08:54:33 2007 -0700 @@ -835,7 +835,7 @@ void debugtrace_printk(const char *fmt, snprintf(buf, sizeof(buf), "%u ", ++count); va_start(args, fmt); - (void)vsnprintf(buf + strlen(buf), sizeof(buf), fmt, args); + (void)vsnprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), fmt, args); va_end(args); if ( debugtrace_send_to_console ) diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/include/asm-x86/hvm/vmx/intel-iommu.h --- a/xen/include/asm-x86/hvm/vmx/intel-iommu.h Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/include/asm-x86/hvm/vmx/intel-iommu.h Fri Nov 30 08:54:33 2007 -0700 @@ -89,7 +89,8 @@ #define cap_plmr(c) (((c) >> 5) & 1) #define cap_rwbf(c) (((c) >> 4) & 1) #define cap_afl(c) (((c) >> 3) & 1) -#define cap_ndoms(c) (2 ^ (4 + 2 * ((c) & 0x7))) +#define cap_ndoms(c) (1 << (4 + 2 * ((c) & 0x7))) + /* * Extended Capability Register */ diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Fri Nov 30 08:54:33 2007 -0700 @@ -28,7 +28,7 @@ #endif extern void start_vmx(void); -extern void vmcs_dump_vcpu(void); +extern void vmcs_dump_vcpu(struct vcpu *v); extern void setup_vmcs_dump(void); extern int vmx_cpu_up(void); extern void vmx_cpu_down(void); diff -r f9ca1d8c9e65 -r 32ec5dbe2978 xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Thu Nov 29 12:15:43 2007 -0700 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Fri Nov 30 08:54:33 2007 -0700 @@ -37,7 +37,7 @@ void vmx_cpuid_intercept( unsigned int *eax, unsigned int *ebx, unsigned int *ecx, unsigned int *edx); void vmx_wbinvd_intercept(void); -int vmx_realmode(struct cpu_user_regs *regs); +void vmx_realmode(struct cpu_user_regs *regs); int vmx_realmode_io_complete(void); /* _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |