From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paul Durrant Subject: [PATCH v5 06/16] x86/hvm: add length to mmio check op Date: Tue, 30 Jun 2015 14:05:48 +0100 Message-ID: <1435669558-5421-7-git-send-email-paul.durrant@citrix.com> References: <1435669558-5421-1-git-send-email-paul.durrant@citrix.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1Z9vEm-0003XL-BH for xen-devel@lists.xenproject.org; Tue, 30 Jun 2015 13:06:08 +0000 In-Reply-To: <1435669558-5421-1-git-send-email-paul.durrant@citrix.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xenproject.org Cc: Andrew Cooper , Paul Durrant , Keir Fraser , Jan Beulich List-Id: xen-devel@lists.xenproject.org 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 Cc: Keir Fraser Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/hvm/intercept.c | 22 +++++++++++++++++++--- xen/include/asm-x86/hvm/io.h | 16 ++++++++++++++++ 2 files changed, 35 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index 7d36785..42050f4 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -35,9 +35,19 @@ 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; + + 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, @@ -112,7 +122,8 @@ static const struct hvm_io_ops portio_ops = { static 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 : @@ -223,6 +234,9 @@ static 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; } @@ -342,7 +356,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 3f6a39a..78c9704 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, uint16_t port, unsigned int bytes, uint32_t *val); -- 1.7.10.4