# 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
|