@@ -1089,12 +1089,25 @@ static int linear_read(unsigned long addr, unsigned int bytes, void *p_data,
uint32_t pfec, struct hvm_emulate_ctxt *hvmemul_ctxt)
{
pagefault_info_t pfinfo;
- int rc = hvm_copy_from_guest_linear(p_data, addr, bytes, pfec, &pfinfo);
+ unsigned int offset = addr & ~PAGE_MASK;
+ int rc;
- switch ( rc )
+ if ( offset + bytes > PAGE_SIZE )
{
- unsigned int offset, part1;
+ unsigned int part1 = PAGE_SIZE - offset;
+
+ /* Split the access at the page boundary. */
+ rc = linear_read(addr, part1, p_data, pfec, hvmemul_ctxt);
+ if ( rc == X86EMUL_OKAY )
+ rc = linear_read(addr + part1, bytes - part1, p_data + part1,
+ pfec, hvmemul_ctxt);
+ return rc;
+ }
+
+ rc = hvm_copy_from_guest_linear(p_data, addr, bytes, pfec, &pfinfo);
+ switch ( rc )
+ {
case HVMTRANS_okay:
return X86EMUL_OKAY;
@@ -1106,19 +1119,9 @@ static int linear_read(unsigned long addr, unsigned int bytes, void *p_data,
if ( pfec & PFEC_insn_fetch )
return X86EMUL_UNHANDLEABLE;
- offset = addr & ~PAGE_MASK;
- if ( offset + bytes <= PAGE_SIZE )
- return hvmemul_linear_mmio_read(addr, bytes, p_data, pfec,
- hvmemul_ctxt,
- known_gla(addr, bytes, pfec));
-
- /* Split the access at the page boundary. */
- part1 = PAGE_SIZE - offset;
- rc = linear_read(addr, part1, p_data, pfec, hvmemul_ctxt);
- if ( rc == X86EMUL_OKAY )
- rc = linear_read(addr + part1, bytes - part1, p_data + part1,
- pfec, hvmemul_ctxt);
- return rc;
+ return hvmemul_linear_mmio_read(addr, bytes, p_data, pfec,
+ hvmemul_ctxt,
+ known_gla(addr, bytes, pfec));
case HVMTRANS_gfn_paged_out:
case HVMTRANS_gfn_shared:
@@ -1132,12 +1135,25 @@ static int linear_write(unsigned long addr, unsigned int bytes, void *p_data,
uint32_t pfec, struct hvm_emulate_ctxt *hvmemul_ctxt)
{
pagefault_info_t pfinfo;
- int rc = hvm_copy_to_guest_linear(addr, p_data, bytes, pfec, &pfinfo);
+ unsigned int offset = addr & ~PAGE_MASK;
+ int rc;
- switch ( rc )
+ if ( offset + bytes > PAGE_SIZE )
{
- unsigned int offset, part1;
+ unsigned int part1 = PAGE_SIZE - offset;
+
+ /* Split the access at the page boundary. */
+ rc = linear_write(addr, part1, p_data, pfec, hvmemul_ctxt);
+ if ( rc == X86EMUL_OKAY )
+ rc = linear_write(addr + part1, bytes - part1, p_data + part1,
+ pfec, hvmemul_ctxt);
+ return rc;
+ }
+
+ rc = hvm_copy_to_guest_linear(addr, p_data, bytes, pfec, &pfinfo);
+ switch ( rc )
+ {
case HVMTRANS_okay:
return X86EMUL_OKAY;
@@ -1146,19 +1162,9 @@ static int linear_write(unsigned long addr, unsigned int bytes, void *p_data,
return X86EMUL_EXCEPTION;
case HVMTRANS_bad_gfn_to_mfn:
- offset = addr & ~PAGE_MASK;
- if ( offset + bytes <= PAGE_SIZE )
- return hvmemul_linear_mmio_write(addr, bytes, p_data, pfec,
- hvmemul_ctxt,
- known_gla(addr, bytes, pfec));
-
- /* Split the access at the page boundary. */
- part1 = PAGE_SIZE - offset;
- rc = linear_write(addr, part1, p_data, pfec, hvmemul_ctxt);
- if ( rc == X86EMUL_OKAY )
- rc = linear_write(addr + part1, bytes - part1, p_data + part1,
- pfec, hvmemul_ctxt);
- return rc;
+ return hvmemul_linear_mmio_write(addr, bytes, p_data, pfec,
+ hvmemul_ctxt,
+ known_gla(addr, bytes, pfec));
case HVMTRANS_gfn_paged_out:
case HVMTRANS_gfn_shared: