# HG changeset patch
# User awilliam@xxxxxxxxxxxx
# Date 1172011437 25200
# Node ID 315c348e5f9e2f929032dae3fec3e2583ca91785
# Parent 409e94d0a35babaa945e0406301e151f2550b87a
# Parent e7994a122aab535b7e13fd1686cc3b8ce5d4552a
merge with xen-unstable.hg
---
tools/check/check_crypto_lib | 3 -
xen/acm/acm_simple_type_enforcement_hooks.c | 11 ++--
xen/arch/x86/hvm/io.c | 43 ++++++++++++++-
xen/arch/x86/hvm/platform.c | 77 +++++++++++++++++-----------
xen/arch/x86/hvm/svm/svm.c | 48 ++++++++++++++---
xen/arch/x86/hvm/vmx/vmx.c | 39 ++++++++++++--
xen/arch/x86/mm/shadow/multi.c | 20 -------
xen/arch/x86/mm/shadow/types.h | 3 -
xen/arch/x86/x86_emulate.c | 77 ++++++++++++++++------------
xen/include/asm-x86/hvm/io.h | 2
xen/include/asm-x86/p2m.h | 2
xen/include/asm-x86/paging.h | 15 +----
12 files changed, 228 insertions(+), 112 deletions(-)
diff -r 409e94d0a35b -r 315c348e5f9e tools/check/check_crypto_lib
--- a/tools/check/check_crypto_lib Tue Feb 20 15:12:11 2007 -0700
+++ b/tools/check/check_crypto_lib Tue Feb 20 15:43:57 2007 -0700
@@ -3,8 +3,9 @@
RC=0
+PATH=/sbin:$PATH
set -e
-ldconfig -v 2>&1 | grep -q libcrypto.so || RC=1
+ldconfig -p 2>&1 | grep -q libcrypto.so || RC=1
if test ${RC} -ne 0; then
echo
diff -r 409e94d0a35b -r 315c348e5f9e xen/acm/acm_simple_type_enforcement_hooks.c
--- a/xen/acm/acm_simple_type_enforcement_hooks.c Tue Feb 20 15:12:11
2007 -0700
+++ b/xen/acm/acm_simple_type_enforcement_hooks.c Tue Feb 20 15:43:57
2007 -0700
@@ -235,7 +235,7 @@ ste_init_state(struct acm_ste_policy_buf
}
/* b) check for grant table conflicts on shared pages */
spin_lock(&(*pd)->grant_table->lock);
- for ( i = 0; i < nr_grant_frames((*pd)->grant_table); i++ ) {
+ for ( i = 0; i < nr_grant_entries((*pd)->grant_table); i++ ) {
#define SPP (PAGE_SIZE / sizeof(struct grant_entry))
sha_copy = (*pd)->grant_table->shared[i/SPP][i%SPP];
if ( sha_copy.flags ) {
@@ -244,8 +244,9 @@ ste_init_state(struct acm_ste_policy_buf
(unsigned long)sha_copy.frame);
rdomid = sha_copy.domid;
if ((rdom = get_domain_by_id(rdomid)) == NULL) {
+ spin_unlock(&(*pd)->grant_table->lock);
printkd("%s: domain not found ERROR!\n", __func__);
- goto out_gnttab;
+ goto out;
};
/* rdom now has remote domain */
ste_rssid = GET_SSIDP(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY,
@@ -253,16 +254,16 @@ ste_init_state(struct acm_ste_policy_buf
ste_rssidref = ste_rssid->ste_ssidref;
put_domain(rdom);
if (!have_common_type(ste_ssidref, ste_rssidref)) {
+ spin_unlock(&(*pd)->grant_table->lock);
printkd("%s: Policy violation in grant table sharing
domain %x -> domain %x.\n",
__func__, (*pd)->domain_id, rdomid);
- goto out_gnttab;
+ goto out;
}
}
}
+ spin_unlock(&(*pd)->grant_table->lock);
}
violation = 0;
- out_gnttab:
- spin_unlock(&(*pd)->grant_table->lock);
out:
read_unlock(&domlist_lock);
return violation;
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/hvm/io.c
--- a/xen/arch/x86/hvm/io.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/hvm/io.c Tue Feb 20 15:43:57 2007 -0700
@@ -371,7 +371,20 @@ static void hvm_pio_assist(struct cpu_us
{
unsigned long addr = pio_opp->addr;
if ( hvm_paging_enabled(current) )
- (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
+ {
+ int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
+ if ( rv != 0 )
+ {
+ /* Failed on the page-spanning copy. Inject PF into
+ * the guest for the address where we failed. */
+ addr += p->size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side "
+ "of a page-spanning PIO: va=%#lx\n", addr);
+ hvm_inject_exception(TRAP_page_fault,
+ PFEC_write_access, addr);
+ return;
+ }
+ }
else
(void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
}
@@ -489,7 +502,20 @@ static void hvm_mmio_assist(struct cpu_u
unsigned long addr = mmio_opp->addr;
if (hvm_paging_enabled(current))
- (void)hvm_copy_to_guest_virt(addr, &p->data, p->size);
+ {
+ int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
+ if ( rv != 0 )
+ {
+ /* Failed on the page-spanning copy. Inject PF into
+ * the guest for the address where we failed. */
+ addr += p->size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault writing non-io side of "
+ "a page-spanning MMIO: va=%#lx\n", addr);
+ hvm_inject_exception(TRAP_page_fault,
+ PFEC_write_access, addr);
+ return;
+ }
+ }
else
(void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
}
@@ -689,7 +715,18 @@ static void hvm_mmio_assist(struct cpu_u
case INSTR_PUSH:
mmio_opp->addr += hvm_get_segment_base(current, x86_seg_ss);
- hvm_copy_to_guest_virt(mmio_opp->addr, &p->data, size);
+ {
+ unsigned long addr = mmio_opp->addr;
+ int rv = hvm_copy_to_guest_virt(addr, &p->data, size);
+ if ( rv != 0 )
+ {
+ addr += p->size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault emulating PUSH from MMIO: "
+ "va=%#lx\n", addr);
+ hvm_inject_exception(TRAP_page_fault, PFEC_write_access, addr);
+ return;
+ }
+ }
break;
}
}
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/hvm/platform.c Tue Feb 20 15:43:57 2007 -0700
@@ -815,7 +815,7 @@ int inst_copy_from_guest(unsigned char *
}
void send_pio_req(unsigned long port, unsigned long count, int size,
- long value, int dir, int df, int value_is_ptr)
+ paddr_t value, int dir, int df, int value_is_ptr)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
@@ -823,7 +823,7 @@ void send_pio_req(unsigned long port, un
if ( size == 0 || count == 0 ) {
printk("null pio request? port %lx, count %lx, "
- "size %d, value %lx, dir %d, value_is_ptr %d.\n",
+ "size %d, value %"PRIpaddr", dir %d, value_is_ptr %d.\n",
port, count, size, value, dir, value_is_ptr);
}
@@ -849,15 +849,7 @@ void send_pio_req(unsigned long port, un
p->io_count++;
- if ( value_is_ptr ) /* get physical address of data */
- {
- if ( hvm_paging_enabled(current) )
- p->data = paging_gva_to_gpa(current, value);
- else
- p->data = value; /* guest VA == guest PA */
- }
- else if ( dir == IOREQ_WRITE )
- p->data = value;
+ p->data = value;
if ( hvm_portio_intercept(p) )
{
@@ -870,7 +862,7 @@ void send_pio_req(unsigned long port, un
}
static void send_mmio_req(unsigned char type, unsigned long gpa,
- unsigned long count, int size, long value,
+ unsigned long count, int size, paddr_t value,
int dir, int df, int value_is_ptr)
{
struct vcpu *v = current;
@@ -879,7 +871,8 @@ static void send_mmio_req(unsigned char
if ( size == 0 || count == 0 ) {
printk("null mmio request? type %d, gpa %lx, "
- "count %lx, size %d, value %lx, dir %d, value_is_ptr %d.\n",
+ "count %lx, size %d, value %"PRIpaddr"x, dir %d, "
+ "value_is_ptr %d.\n",
type, gpa, count, size, value, dir, value_is_ptr);
}
@@ -905,15 +898,7 @@ static void send_mmio_req(unsigned char
p->io_count++;
- if ( value_is_ptr )
- {
- if ( hvm_paging_enabled(v) )
- p->data = paging_gva_to_gpa(v, value);
- else
- p->data = value; /* guest VA == guest PA */
- }
- else
- p->data = value;
+ p->data = value;
if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
{
@@ -960,6 +945,7 @@ static void mmio_operands(int type, unsi
#define GET_REPEAT_COUNT() \
(mmio_op->flags & REPZ ? (ad_size == WORD ? regs->ecx & 0xFFFF :
regs->ecx) : 1)
+
void handle_mmio(unsigned long gpa)
{
unsigned long inst_addr;
@@ -1014,7 +1000,8 @@ void handle_mmio(unsigned long gpa)
{
unsigned long count = GET_REPEAT_COUNT();
int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
- unsigned long addr;
+ unsigned long addr, gfn;
+ paddr_t paddr;
int dir, size = op_size;
ASSERT(count);
@@ -1024,7 +1011,9 @@ void handle_mmio(unsigned long gpa)
if ( ad_size == WORD )
addr &= 0xFFFF;
addr += hvm_get_segment_base(v, x86_seg_es);
- if ( paging_gva_to_gpa(v, addr) == gpa )
+ gfn = paging_gva_to_gfn(v, addr);
+ paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+ if ( paddr == gpa )
{
enum x86_segment seg;
@@ -1044,9 +1033,23 @@ void handle_mmio(unsigned long gpa)
default: domain_crash_synchronous();
}
addr += hvm_get_segment_base(v, seg);
+ gfn = paging_gva_to_gfn(v, addr);
+ paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
}
else
dir = IOREQ_READ;
+
+ if ( gfn == INVALID_GFN )
+ {
+ /* The guest does not have the non-mmio address mapped.
+ * Need to send in a page fault */
+ int errcode = 0;
+ /* IO read --> memory write */
+ if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+ regs->eip -= inst_len; /* do not advance %eip */
+ hvm_inject_exception(TRAP_page_fault, errcode, addr);
+ return;
+ }
/*
* In case of a movs spanning multiple pages, we break the accesses
@@ -1065,10 +1068,27 @@ void handle_mmio(unsigned long gpa)
if ( dir == IOREQ_WRITE ) {
if ( hvm_paging_enabled(v) )
- (void)hvm_copy_from_guest_virt(&value, addr, size);
+ {
+ int rv = hvm_copy_from_guest_virt(&value, addr, size);
+ if ( rv != 0 )
+ {
+ /* Failed on the page-spanning copy. Inject PF into
+ * the guest for the address where we failed */
+ regs->eip -= inst_len; /* do not advance %eip */
+ /* Must set CR2 at the failing address */
+ addr += size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault on non-io side of a "
+ "page-spanning MMIO: va=%#lx\n", addr);
+ hvm_inject_exception(TRAP_page_fault, 0, addr);
+ return;
+ }
+ }
else
- (void)hvm_copy_from_guest_phys(&value, addr, size);
- } else
+ (void) hvm_copy_from_guest_phys(&value, addr, size);
+ } else /* dir != IOREQ_WRITE */
+ /* Remember where to write the result, as a *VA*.
+ * Must be a VA so we can handle the page overlap
+ * correctly in hvm_mmio_assist() */
mmio_op->addr = addr;
if ( count != 1 )
@@ -1091,7 +1111,8 @@ void handle_mmio(unsigned long gpa)
ASSERT(count);
- send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size, addr, dir, df, 1);
+ send_mmio_req(IOREQ_TYPE_COPY, gpa, count, size,
+ paddr, dir, df, 1);
}
break;
}
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/hvm/svm/svm.c
--- a/xen/arch/x86/hvm/svm/svm.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/hvm/svm/svm.c Tue Feb 20 15:43:57 2007 -0700
@@ -1589,6 +1589,8 @@ static void svm_io_instruction(struct vc
if (info.fields.str)
{
unsigned long addr, count;
+ paddr_t paddr;
+ unsigned long gfn;
int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
if (!svm_get_io_address(v, regs, size, info, &count, &addr))
@@ -1606,6 +1608,20 @@ static void svm_io_instruction(struct vc
pio_opp->flags |= REPZ;
}
+ /* Translate the address to a physical address */
+ gfn = paging_gva_to_gfn(v, addr);
+ if ( gfn == INVALID_GFN )
+ {
+ /* The guest does not have the RAM address mapped.
+ * Need to send in a page fault */
+ int errcode = 0;
+ /* IO read --> memory write */
+ if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+ svm_hvm_inject_exception(TRAP_page_fault, errcode, addr);
+ return;
+ }
+ paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+
/*
* Handle string pio instructions that cross pages or that
* are unaligned. See the comments in hvm_platform.c/handle_mmio()
@@ -1619,11 +1635,27 @@ static void svm_io_instruction(struct vc
if (dir == IOREQ_WRITE) /* OUTS */
{
- if (hvm_paging_enabled(current))
- (void)hvm_copy_from_guest_virt(&value, addr, size);
+ if ( hvm_paging_enabled(current) )
+ {
+ int rv = hvm_copy_from_guest_virt(&value, addr, size);
+ if ( rv != 0 )
+ {
+ /* Failed on the page-spanning copy. Inject PF into
+ * the guest for the address where we failed. */
+ addr += size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
+ "of a page-spanning PIO: va=%#lx\n", addr);
+ svm_hvm_inject_exception(TRAP_page_fault, 0, addr);
+ return;
+ }
+ }
else
- (void)hvm_copy_from_guest_phys(&value, addr, size);
- }
+ (void) hvm_copy_from_guest_phys(&value, addr, size);
+ } else /* dir != IOREQ_WRITE */
+ /* Remember where to write the result, as a *VA*.
+ * Must be a VA so we can handle the page overlap
+ * correctly in hvm_pio_assist() */
+ pio_opp->addr = addr;
if (count == 1)
regs->eip = vmcb->exitinfo2;
@@ -1645,7 +1677,7 @@ static void svm_io_instruction(struct vc
else
regs->eip = vmcb->exitinfo2;
- send_pio_req(port, count, size, addr, dir, df, 1);
+ send_pio_req(port, count, size, paddr, dir, df, 1);
}
}
else
@@ -2718,7 +2750,8 @@ asmlinkage void svm_vmexit_handler(struc
if (svm_dbg_on && exit_reason == VMEXIT_EXCEPTION_PF)
{
if (svm_paging_enabled(v) &&
- !mmio_space(paging_gva_to_gpa(current, vmcb->exitinfo2)))
+ !mmio_space(
+ paging_gva_to_gfn(current, vmcb->exitinfo2) << PAGE_SHIFT))
{
printk("I%08ld,ExC=%s(%d),IP=%x:%"PRIx64","
"I1=%"PRIx64",I2=%"PRIx64",INT=%"PRIx64", "
@@ -2728,7 +2761,8 @@ asmlinkage void svm_vmexit_handler(struc
(u64)vmcb->exitinfo1,
(u64)vmcb->exitinfo2,
(u64)vmcb->exitintinfo.bytes,
- (u64)paging_gva_to_gpa(current, vmcb->exitinfo2));
+ (((u64)paging_gva_to_gfn(current, vmcb->exitinfo2)
+ << PAGE_SHIFT) | (vmcb->exitinfo2 & ~PAGE_MASK)));
}
else
{
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/hvm/vmx/vmx.c
--- a/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/hvm/vmx/vmx.c Tue Feb 20 15:43:57 2007 -0700
@@ -1426,6 +1426,8 @@ static void vmx_io_instruction(unsigned
if ( test_bit(4, &exit_qualification) ) { /* string instruction */
unsigned long addr, count = 1, base;
+ paddr_t paddr;
+ unsigned long gfn;
u32 ar_bytes, limit;
int sign = regs->eflags & X86_EFLAGS_DF ? -1 : 1;
int long_mode = 0;
@@ -1545,6 +1547,20 @@ static void vmx_io_instruction(unsigned
}
#endif
+ /* Translate the address to a physical address */
+ gfn = paging_gva_to_gfn(current, addr);
+ if ( gfn == INVALID_GFN )
+ {
+ /* The guest does not have the RAM address mapped.
+ * Need to send in a page fault */
+ int errcode = 0;
+ /* IO read --> memory write */
+ if ( dir == IOREQ_READ ) errcode |= PFEC_write_access;
+ vmx_inject_exception(TRAP_page_fault, errcode, addr);
+ return;
+ }
+ paddr = (paddr_t)gfn << PAGE_SHIFT | (addr & ~PAGE_MASK);
+
/*
* Handle string pio instructions that cross pages or that
* are unaligned. See the comments in hvm_domain.c/handle_mmio()
@@ -1557,10 +1573,25 @@ static void vmx_io_instruction(unsigned
if ( dir == IOREQ_WRITE ) /* OUTS */
{
if ( hvm_paging_enabled(current) )
- (void)hvm_copy_from_guest_virt(&value, addr, size);
+ {
+ int rv = hvm_copy_from_guest_virt(&value, addr, size);
+ if ( rv != 0 )
+ {
+ /* Failed on the page-spanning copy. Inject PF into
+ * the guest for the address where we failed. */
+ addr += size - rv;
+ gdprintk(XENLOG_DEBUG, "Pagefault reading non-io side "
+ "of a page-spanning PIO: va=%#lx\n", addr);
+ vmx_inject_exception(TRAP_page_fault, 0, addr);
+ return;
+ }
+ }
else
- (void)hvm_copy_from_guest_phys(&value, addr, size);
- } else
+ (void) hvm_copy_from_guest_phys(&value, addr, size);
+ } else /* dir != IOREQ_WRITE */
+ /* Remember where to write the result, as a *VA*.
+ * Must be a VA so we can handle the page overlap
+ * correctly in hvm_pio_assist() */
pio_opp->addr = addr;
if ( count == 1 )
@@ -1580,7 +1611,7 @@ static void vmx_io_instruction(unsigned
} else
regs->eip += inst_len;
- send_pio_req(port, count, size, addr, dir, df, 1);
+ send_pio_req(port, count, size, paddr, dir, df, 1);
}
} else {
if ( port == 0xe9 && dir == IOREQ_WRITE && size == 1 )
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/mm/shadow/multi.c
--- a/xen/arch/x86/mm/shadow/multi.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/mm/shadow/multi.c Tue Feb 20 15:43:57 2007 -0700
@@ -3038,19 +3038,6 @@ sh_gva_to_gfn(struct vcpu *v, unsigned l
}
-static paddr_t
-sh_gva_to_gpa(struct vcpu *v, unsigned long va)
-/* Called to translate a guest virtual address to what the *guest*
- * pagetables would map it to. */
-{
- unsigned long gfn = sh_gva_to_gfn(v, va);
- if ( gfn == INVALID_GFN )
- return 0;
- else
- return (((paddr_t)gfn) << PAGE_SHIFT) + (va & ~PAGE_MASK);
-}
-
-
static inline void
sh_update_linear_entries(struct vcpu *v)
/* Sync up all the linear mappings for this vcpu's pagetables */
@@ -3932,8 +3919,7 @@ static int safe_not_to_verify_write(mfn_
#if (SHADOW_OPTIMIZATIONS & SHOPT_SKIP_VERIFY)
struct page_info *pg = mfn_to_page(gmfn);
if ( !(pg->shadow_flags & SHF_32)
- && bytes == 4
- && ((unsigned long)dst & 3) == 0 )
+ && ((unsigned long)dst & 7) == 0 )
{
/* Not shadowed 32-bit: aligned 64-bit writes that leave the
* present bit unset are safe to ignore. */
@@ -3942,8 +3928,7 @@ static int safe_not_to_verify_write(mfn_
return 1;
}
else if ( !(pg->shadow_flags & (SHF_PAE|SHF_64))
- && bytes == 8
- && ((unsigned long)dst & 7) == 0 )
+ && ((unsigned long)dst & 3) == 0 )
{
/* Not shadowed PAE/64-bit: aligned 32-bit writes that leave the
* present bit unset are safe to ignore. */
@@ -4350,7 +4335,6 @@ struct paging_mode sh_paging_mode = {
struct paging_mode sh_paging_mode = {
.page_fault = sh_page_fault,
.invlpg = sh_invlpg,
- .gva_to_gpa = sh_gva_to_gpa,
.gva_to_gfn = sh_gva_to_gfn,
.update_cr3 = sh_update_cr3,
.update_paging_modes = shadow_update_paging_modes,
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/mm/shadow/types.h
--- a/xen/arch/x86/mm/shadow/types.h Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/mm/shadow/types.h Tue Feb 20 15:43:57 2007 -0700
@@ -244,6 +244,7 @@ static inline shadow_l4e_t shadow_l4e_fr
/* Type of the guest's frame numbers */
TYPE_SAFE(u32,gfn)
+#undef INVALID_GFN
#define INVALID_GFN ((u32)(-1u))
#define SH_PRI_gfn "05x"
@@ -307,6 +308,7 @@ static inline guest_l2e_t guest_l2e_from
/* Type of the guest's frame numbers */
TYPE_SAFE(unsigned long,gfn)
+#undef INVALID_GFN
#define INVALID_GFN ((unsigned long)(-1ul))
#define SH_PRI_gfn "05lx"
@@ -467,7 +469,6 @@ struct shadow_walk_t
*/
#define sh_page_fault INTERNAL_NAME(sh_page_fault)
#define sh_invlpg INTERNAL_NAME(sh_invlpg)
-#define sh_gva_to_gpa INTERNAL_NAME(sh_gva_to_gpa)
#define sh_gva_to_gfn INTERNAL_NAME(sh_gva_to_gfn)
#define sh_update_cr3 INTERNAL_NAME(sh_update_cr3)
#define sh_rm_write_access_from_l1 INTERNAL_NAME(sh_rm_write_access_from_l1)
diff -r 409e94d0a35b -r 315c348e5f9e xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/arch/x86/x86_emulate.c Tue Feb 20 15:43:57 2007 -0700
@@ -519,6 +519,37 @@ do {
? (uint16_t)_regs.eip : (uint32_t)_regs.eip); \
} while (0)
+static int __handle_rep_prefix(
+ struct cpu_user_regs *int_regs,
+ struct cpu_user_regs *ext_regs,
+ int ad_bytes)
+{
+ unsigned long ecx = ((ad_bytes == 2) ? (uint16_t)int_regs->ecx :
+ (ad_bytes == 4) ? (uint32_t)int_regs->ecx :
+ int_regs->ecx);
+
+ if ( ecx-- == 0 )
+ {
+ ext_regs->eip = int_regs->eip;
+ return 1;
+ }
+
+ if ( ad_bytes == 2 )
+ *(uint16_t *)&int_regs->ecx = ecx;
+ else if ( ad_bytes == 4 )
+ int_regs->ecx = (uint32_t)ecx;
+ else
+ int_regs->ecx = ecx;
+ int_regs->eip = ext_regs->eip;
+ return 0;
+}
+
+#define handle_rep_prefix() \
+do { \
+ if ( rep_prefix && __handle_rep_prefix(&_regs, ctxt->regs, ad_bytes) ) \
+ goto done; \
+} while (0)
+
/*
* Unsigned multiplication with double-word result.
* IN: Multiplicand=m[0], Multiplier=m[1]
@@ -1579,17 +1610,6 @@ x86_emulate(
if ( twobyte )
goto twobyte_special_insn;
- if ( rep_prefix )
- {
- if ( _regs.ecx == 0 )
- {
- ctxt->regs->eip = _regs.eip;
- goto done;
- }
- _regs.ecx--;
- _regs.eip = ctxt->regs->eip;
- }
-
switch ( b )
{
case 0x27: /* daa */ {
@@ -1727,6 +1747,7 @@ x86_emulate(
break;
case 0x6c ... 0x6d: /* ins %dx,%es:%edi */
+ handle_rep_prefix();
generate_exception_if(!mode_iopl(), EXC_GP);
dst.type = OP_MEM;
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
@@ -1741,6 +1762,7 @@ x86_emulate(
break;
case 0x6e ... 0x6f: /* outs %esi,%dx */
+ handle_rep_prefix();
generate_exception_if(!mode_iopl(), EXC_GP);
dst.bytes = !(b & 1) ? 1 : (op_bytes == 8) ? 4 : op_bytes;
if ( (rc = ops->read(ea.mem.seg, truncate_ea(_regs.esi),
@@ -1827,6 +1849,7 @@ x86_emulate(
break;
case 0xa4 ... 0xa5: /* movs */
+ handle_rep_prefix();
dst.type = OP_MEM;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.mem.seg = x86_seg_es;
@@ -1841,6 +1864,7 @@ x86_emulate(
break;
case 0xaa ... 0xab: /* stos */
+ handle_rep_prefix();
dst.type = OP_MEM;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.mem.seg = x86_seg_es;
@@ -1851,6 +1875,7 @@ x86_emulate(
break;
case 0xac ... 0xad: /* lods */
+ handle_rep_prefix();
dst.type = OP_REG;
dst.bytes = (d & ByteOp) ? 1 : op_bytes;
dst.reg = (unsigned long *)&_regs.eax;
@@ -2325,33 +2350,23 @@ x86_emulate(
#endif
case 0xc8 ... 0xcf: /* bswap */
- dst.type = OP_REG;
- dst.reg = decode_register(b & 7, &_regs, 0);
- dst.val = *dst.reg;
+ dst.type = OP_REG;
+ dst.reg = decode_register(
+ (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);
switch ( dst.bytes = op_bytes )
{
- case 2:
- dst.val = (((dst.val & 0x00FFUL) << 8) |
- ((dst.val & 0xFF00UL) >> 8));
+ default: /* case 2: */
+ /* Undefined behaviour. Writes zero on all tested CPUs. */
+ dst.val = 0;
break;
case 4:
- dst.val = (((dst.val & 0x000000FFUL) << 24) |
- ((dst.val & 0x0000FF00UL) << 8) |
- ((dst.val & 0x00FF0000UL) >> 8) |
- ((dst.val & 0xFF000000UL) >> 24));
- break;
#ifdef __x86_64__
+ __asm__ ( "bswap %k0" : "=r" (dst.val) : "0" (*dst.reg) );
+ break;
case 8:
- dst.val = (((dst.val & 0x00000000000000FFUL) << 56) |
- ((dst.val & 0x000000000000FF00UL) << 40) |
- ((dst.val & 0x0000000000FF0000UL) << 24) |
- ((dst.val & 0x00000000FF000000UL) << 8) |
- ((dst.val & 0x000000FF00000000UL) >> 8) |
- ((dst.val & 0x0000FF0000000000UL) >> 24) |
- ((dst.val & 0x00FF000000000000UL) >> 40) |
- ((dst.val & 0xFF00000000000000UL) >> 56));
- break;
#endif
+ __asm__ ( "bswap %0" : "=r" (dst.val) : "0" (*dst.reg) );
+ break;
}
break;
}
diff -r 409e94d0a35b -r 315c348e5f9e xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/include/asm-x86/hvm/io.h Tue Feb 20 15:43:57 2007 -0700
@@ -144,7 +144,7 @@ static inline int irq_masked(unsigned lo
#endif
extern void send_pio_req(unsigned long port, unsigned long count, int size,
- long value, int dir, int df, int value_is_ptr);
+ paddr_t value, int dir, int df, int value_is_ptr);
extern void handle_mmio(unsigned long gpa);
extern void hvm_interrupt_post(struct vcpu *v, int vector, int type);
extern void hvm_io_assist(struct vcpu *v);
diff -r 409e94d0a35b -r 315c348e5f9e xen/include/asm-x86/p2m.h
--- a/xen/include/asm-x86/p2m.h Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/include/asm-x86/p2m.h Tue Feb 20 15:43:57 2007 -0700
@@ -89,7 +89,7 @@ static inline unsigned long get_mfn_from
/* Is this guest address an mmio one? (i.e. not defined in p2m map) */
static inline int mmio_space(paddr_t gpa)
{
- unsigned long gfn = gpa >> PAGE_SHIFT;
+ unsigned long gfn = gpa >> PAGE_SHIFT;
return !mfn_valid(mfn_x(gfn_to_mfn_current(gfn)));
}
diff -r 409e94d0a35b -r 315c348e5f9e xen/include/asm-x86/paging.h
--- a/xen/include/asm-x86/paging.h Tue Feb 20 15:12:11 2007 -0700
+++ b/xen/include/asm-x86/paging.h Tue Feb 20 15:43:57 2007 -0700
@@ -115,7 +115,6 @@ struct paging_mode {
int (*page_fault )(struct vcpu *v, unsigned long va,
struct cpu_user_regs *regs);
int (*invlpg )(struct vcpu *v, unsigned long va);
- paddr_t (*gva_to_gpa )(struct vcpu *v, unsigned long va);
unsigned long (*gva_to_gfn )(struct vcpu *v, unsigned long va);
void (*update_cr3 )(struct vcpu *v, int do_locking);
void (*update_paging_modes )(struct vcpu *v);
@@ -190,18 +189,10 @@ static inline int paging_invlpg(struct v
return v->arch.paging.mode->invlpg(v, va);
}
-/* Translate a guest virtual address to the physical address that the
- * *guest* pagetables would map it to. */
-static inline paddr_t paging_gva_to_gpa(struct vcpu *v, unsigned long va)
-{
- if ( unlikely(!paging_vcpu_mode_translate(v)) )
- return (paddr_t) va;
-
- return v->arch.paging.mode->gva_to_gpa(v, va);
-}
-
/* Translate a guest virtual address to the frame number that the
- * *guest* pagetables would map it to. */
+ * *guest* pagetables would map it to. Returns INVALID_GFN if the guest
+ * tables don't map this address. */
+#define INVALID_GFN (-1UL)
static inline unsigned long paging_gva_to_gfn(struct vcpu *v, unsigned long va)
{
if ( unlikely(!paging_vcpu_mode_translate(v)) )
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|