|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/5] x86/HVM: don't ignore hvm_copy_to_guest_phys() errors during I/O intercept
>>> On 08.10.13 at 20:20, Andrew Cooper <andrew.cooper3@xxxxxxxxxx> wrote:
> On 30/09/13 13:58, Jan Beulich wrote:
>> Building upon the extended retry logic we can now also make sure to
>> not ignore errors resulting from writing data back to guest memory.
>>
>> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
>>
>> --- a/xen/arch/x86/hvm/intercept.c
>> +++ b/xen/arch/x86/hvm/intercept.c
>> @@ -47,6 +47,7 @@ static int hvm_mmio_access(struct vcpu *
>> hvm_mmio_read_t read_handler,
>> hvm_mmio_write_t write_handler)
>> {
>> + struct hvm_vcpu_io *vio = ¤t->arch.hvm_vcpu.hvm_io;
>
> struct vcpu is passed in to this function, which can be used in
> preference to current. (And is possibly fractionally faster unless the
> compiler can prove that v is always current)
Right, I simply overlooked this. Adjusted.
> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
Thanks, Jan
>> unsigned long data;
>> int rc = X86EMUL_OKAY, i, step = p->df ? -p->size : p->size;
>>
>> @@ -54,7 +55,16 @@ static int hvm_mmio_access(struct vcpu *
>> {
>> if ( p->dir == IOREQ_READ )
>> {
>> - rc = read_handler(v, p->addr, p->size, &data);
>> + if ( vio->mmio_retrying )
>> + {
>> + if ( vio->mmio_large_read_bytes != p->size )
>> + return X86EMUL_UNHANDLEABLE;
>> + memcpy(&data, vio->mmio_large_read, p->size);
>> + vio->mmio_large_read_bytes = 0;
>> + vio->mmio_retrying = 0;
>> + }
>> + else
>> + rc = read_handler(v, p->addr, p->size, &data);
>> p->data = data;
>> }
>> else /* p->dir == IOREQ_WRITE */
>> @@ -66,18 +76,48 @@ static int hvm_mmio_access(struct vcpu *
>> {
>> for ( i = 0; i < p->count; i++ )
>> {
>> - int ret;
>> -
>> - rc = read_handler(v, p->addr + step * i, p->size, &data);
>> - if ( rc != X86EMUL_OKAY )
>> - break;
>> - ret = hvm_copy_to_guest_phys(p->data + step * i, &data,
>> p->size);
>> - if ( (ret == HVMCOPY_gfn_paged_out) ||
>> - (ret == HVMCOPY_gfn_shared) )
>> + if ( vio->mmio_retrying )
>> + {
>> + if ( vio->mmio_large_read_bytes != p->size )
>> + return X86EMUL_UNHANDLEABLE;
>> + memcpy(&data, vio->mmio_large_read, p->size);
>> + vio->mmio_large_read_bytes = 0;
>> + vio->mmio_retrying = 0;
>> + }
>> + else
>> {
>> + rc = read_handler(v, p->addr + step * i, p->size, &data);
>> + if ( rc != X86EMUL_OKAY )
>> + break;
>> + }
>> + switch ( hvm_copy_to_guest_phys(p->data + step * i,
>> + &data, p->size) )
>> + {
>> + case HVMCOPY_okay:
>> + break;
>> + case HVMCOPY_gfn_paged_out:
>> + case HVMCOPY_gfn_shared:
>> rc = X86EMUL_RETRY;
>> break;
>> + case HVMCOPY_bad_gfn_to_mfn:
>> + /* Drop the write as real hardware would. */
>> + continue;
>> + case HVMCOPY_bad_gva_to_gfn:
>> + ASSERT(0);
>> + /* fall through */
>> + default:
>> + rc = X86EMUL_UNHANDLEABLE;
>> + break;
>> }
>> + if ( rc != X86EMUL_OKAY)
>> + break;
>> + }
>> +
>> + if ( rc == X86EMUL_RETRY )
>> + {
>> + vio->mmio_retry = 1;
>> + vio->mmio_large_read_bytes = p->size;
>> + memcpy(vio->mmio_large_read, &data, p->size);
>> }
>> }
>> else
>> @@ -109,6 +149,9 @@ static int hvm_mmio_access(struct vcpu *
>> if ( rc != X86EMUL_OKAY )
>> break;
>> }
>> +
>> + if ( rc == X86EMUL_RETRY )
>> + vio->mmio_retry = 1;
>> }
>>
>> if ( i != 0 )
>> @@ -137,6 +180,7 @@ int hvm_mmio_intercept(ioreq_t *p)
>>
>> static int process_portio_intercept(portio_action_t action, ioreq_t *p)
>> {
>> + struct hvm_vcpu_io *vio = ¤t->arch.hvm_vcpu.hvm_io;
>> int rc = X86EMUL_OKAY, i, step = p->df ? -p->size : p->size;
>> uint32_t data;
>>
>> @@ -144,7 +188,16 @@ static int process_portio_intercept(port
>> {
>> if ( p->dir == IOREQ_READ )
>> {
>> - rc = action(IOREQ_READ, p->addr, p->size, &data);
>> + if ( vio->mmio_retrying )
>> + {
>> + if ( vio->mmio_large_read_bytes != p->size )
>> + return X86EMUL_UNHANDLEABLE;
>> + memcpy(&data, vio->mmio_large_read, p->size);
>> + vio->mmio_large_read_bytes = 0;
>> + vio->mmio_retrying = 0;
>> + }
>> + else
>> + rc = action(IOREQ_READ, p->addr, p->size, &data);
>> p->data = data;
>> }
>> else
>> @@ -159,10 +212,48 @@ static int process_portio_intercept(port
>> {
>> for ( i = 0; i < p->count; i++ )
>> {
>> - rc = action(IOREQ_READ, p->addr, p->size, &data);
>> - if ( rc != X86EMUL_OKAY )
>> + if ( vio->mmio_retrying )
>> + {
>> + if ( vio->mmio_large_read_bytes != p->size )
>> + return X86EMUL_UNHANDLEABLE;
>> + memcpy(&data, vio->mmio_large_read, p->size);
>> + vio->mmio_large_read_bytes = 0;
>> + vio->mmio_retrying = 0;
>> + }
>> + else
>> + {
>> + rc = action(IOREQ_READ, p->addr, p->size, &data);
>> + if ( rc != X86EMUL_OKAY )
>> + break;
>> + }
>> + switch ( hvm_copy_to_guest_phys(p->data + step * i,
>> + &data, p->size) )
>> + {
>> + case HVMCOPY_okay:
>> + break;
>> + case HVMCOPY_gfn_paged_out:
>> + case HVMCOPY_gfn_shared:
>> + rc = X86EMUL_RETRY;
>> break;
>> - (void)hvm_copy_to_guest_phys(p->data + step * i, &data,
>> p->size);
>> + case HVMCOPY_bad_gfn_to_mfn:
>> + /* Drop the write as real hardware would. */
>> + continue;
>> + case HVMCOPY_bad_gva_to_gfn:
>> + ASSERT(0);
>> + /* fall through */
>> + default:
>> + rc = X86EMUL_UNHANDLEABLE;
>> + break;
>> + }
>> + if ( rc != X86EMUL_OKAY)
>> + break;
>> + }
>> +
>> + if ( rc == X86EMUL_RETRY )
>> + {
>> + vio->mmio_retry = 1;
>> + vio->mmio_large_read_bytes = p->size;
>> + memcpy(vio->mmio_large_read, &data, p->size);
>> }
>> }
>> else /* p->dir == IOREQ_WRITE */
>> @@ -195,6 +286,9 @@ static int process_portio_intercept(port
>> if ( rc != X86EMUL_OKAY )
>> break;
>> }
>> +
>> + if ( rc == X86EMUL_RETRY )
>> + vio->mmio_retry = 1;
>> }
>>
>> if ( i != 0 )
>>
>>
>>
>>
>> _______________________________________________
>> Xen-devel mailing list
>> Xen-devel@xxxxxxxxxxxxx
>> http://lists.xen.org/xen-devel
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |