[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v7 05/15] x86/hvm: add length to mmio check op
When memory mapped I/O is range checked by internal handlers, the length of the access should be taken into account. Signed-off-by: Paul Durrant <paul.durrant@xxxxxxxxxx> Cc: Keir Fraser <keir@xxxxxxx> Cc: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- v7: - No change v6: - Added Andrew's reviewed-by v5: - Simplified by leaving mmio_check() implementation alone and calling to check last byte if first-byte check passes --- xen/arch/x86/hvm/intercept.c | 23 ++++++++++++++++++++--- xen/include/asm-x86/hvm/io.h | 16 ++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index a44baa1..f9535ea 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -35,9 +35,20 @@ static bool_t hvm_mmio_accept(const struct hvm_io_handler *handler, const ioreq_t *p) { + paddr_t first = hvm_mmio_first_byte(p); + paddr_t last = hvm_mmio_last_byte(p); + BUG_ON(handler->type != IOREQ_TYPE_COPY); - return handler->mmio.ops->check(current, p->addr); + if ( !handler->mmio.ops->check(current, first) ) + return 0; + + /* Make sure the handler will accept the whole access */ + if ( p->size > 1 && + !handler->mmio.ops->check(current, last) ) + domain_crash(current->domain); + + return 1; } static int hvm_mmio_read(const struct hvm_io_handler *handler, @@ -106,7 +117,8 @@ static const struct hvm_io_ops portio_ops = { int hvm_process_io_intercept(const struct hvm_io_handler *handler, ioreq_t *p) { - struct hvm_vcpu_io *vio = ¤t->arch.hvm_vcpu.hvm_io; + struct vcpu *curr = current; + struct hvm_vcpu_io *vio = &curr->arch.hvm_vcpu.hvm_io; const struct hvm_io_ops *ops = (p->type == IOREQ_TYPE_COPY) ? &mmio_ops : &portio_ops; int rc = X86EMUL_OKAY, i, step = p->df ? -p->size : p->size; @@ -215,6 +227,9 @@ int hvm_process_io_intercept(const struct hvm_io_handler *handler, if ( i != 0 ) { + if ( rc == X86EMUL_UNHANDLEABLE ) + domain_crash(curr->domain); + p->count = i; rc = X86EMUL_OKAY; } @@ -331,7 +346,9 @@ bool_t hvm_mmio_internal(paddr_t gpa) { ioreq_t p = { .type = IOREQ_TYPE_COPY, - .addr = gpa + .addr = gpa, + .count = 1, + .size = 1, }; return hvm_find_io_handler(&p) != NULL; diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 1a37243..a01502a 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -43,6 +43,22 @@ struct hvm_mmio_ops { hvm_mmio_write_t write; }; +static inline paddr_t hvm_mmio_first_byte(const ioreq_t *p) +{ + return p->df ? + p->addr - (p->count - 1ul) * p->size : + p->addr; +} + +static inline paddr_t hvm_mmio_last_byte(const ioreq_t *p) +{ + unsigned long count = p->count; + + return p->df ? + p->addr + p->size - 1: + p->addr + (count * p->size) - 1; +} + typedef int (*portio_action_t)( int dir, unsigned int port, unsigned int bytes, uint32_t *val); -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |