From mboxrd@z Thu Jan 1 00:00:00 1970 From: Paul Durrant Subject: [PATCH v2 13/17] x86/hvm: only acquire RAM pages for emulation when we need to Date: Thu, 11 Jun 2015 16:42:57 +0100 Message-ID: <1434037381-10917-14-git-send-email-paul.durrant@citrix.com> References: <1434037381-10917-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 1Z34jM-0008Az-AU for xen-devel@lists.xenproject.org; Thu, 11 Jun 2015 15:49:24 +0000 In-Reply-To: <1434037381-10917-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 If hvmemul_do_io_addr() is called to complete a previously issued emulation then there is no need to acquire the RAM pages again. There is also no need to re-calculate the value of *reps, providing hvmemul_do_io() updates it when returning X86EMUL_OKAY. Signed-off-by: Paul Durrant Cc: Keir Fraser Cc: Jan Beulich Cc: Andrew Cooper --- xen/arch/x86/hvm/emulate.c | 83 ++++++++++++++++++++++++-------------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index 8dd02af..016bc79 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -142,7 +142,6 @@ static int hvmemul_do_io( if ( (p.type != is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO) || (p.addr != addr) || (p.size != size) || - (p.count != *reps) || (p.dir != dir) || (p.df != df) || (p.data_is_ptr != data_is_addr) ) @@ -193,6 +192,7 @@ static int hvmemul_do_io( } } + *reps = p.count; return X86EMUL_OKAY; default: /* @@ -303,60 +303,69 @@ int hvmemul_do_io_addr( unsigned int size, uint8_t dir, bool_t df, paddr_t ram_gpa) { struct vcpu *v = current; + struct hvm_vcpu_io *vio = &v->arch.hvm_vcpu.hvm_io; unsigned long ram_gmfn = paddr_to_pfn(ram_gpa); struct page_info *ram_page[2]; int nr_pages = 0; unsigned long count; int rc; + switch ( vio->io_req.state ) + { + case STATE_IOREQ_NONE: + rc = hvmemul_acquire_page(ram_gmfn, &ram_page[nr_pages]); + if ( rc != X86EMUL_OKAY ) + goto out; - rc = hvmemul_acquire_page(ram_gmfn, &ram_page[nr_pages]); - if ( rc != X86EMUL_OKAY ) - goto out; + nr_pages++; - nr_pages++; + /* Detemine how many reps will fit within this page */ + for ( count = 0; count < *reps; count++ ) + { + paddr_t start, end; - /* Detemine how many reps will fit within this page */ - for ( count = 0; count < *reps; count++ ) - { - paddr_t start, end; + if ( df ) + { + start = ram_gpa - count * size; + end = ram_gpa + size - 1; + } + else + { + start = ram_gpa; + end = ram_gpa + (count + 1) * size - 1; + } - if ( df ) - { - start = ram_gpa - count * size; - end = ram_gpa + size - 1; + if ( paddr_to_pfn(start) != ram_gmfn || + paddr_to_pfn(end) != ram_gmfn ) + break; } - else + + if ( count == 0 ) { - start = ram_gpa; - end = ram_gpa + (count + 1) * size - 1; + /* + * This access must span two pages, so grab a reference + * to the next page and do a single rep. + */ + rc = hvmemul_acquire_page(df ? ram_gmfn - 1 : ram_gmfn + 1, + &ram_page[nr_pages]); + if ( rc != X86EMUL_OKAY ) + goto out; + + nr_pages++; + count = 1; } - - if ( paddr_to_pfn(start) != ram_gmfn || - paddr_to_pfn(end) != ram_gmfn ) - break; - } - - if ( count == 0 ) - { - /* - * This access must span two pages, so grab a reference to - * the next page and do a single rep. - */ - rc = hvmemul_acquire_page(df ? ram_gmfn - 1 : ram_gmfn + 1, - &ram_page[nr_pages]); - if ( rc != X86EMUL_OKAY ) - goto out; - - nr_pages++; - count = 1; - } + break; + case STATE_IORESP_READY: + break; + default: + return X86EMUL_UNHANDLEABLE; + } rc = hvmemul_do_io(is_mmio, addr, &count, size, dir, df, 1, (uint64_t)ram_gpa); if ( rc == X86EMUL_OKAY ) { - v->arch.hvm_vcpu.hvm_io.mmio_retry = (count < *reps); + vio->mmio_retry = (count < *reps); *reps = count; } -- 1.7.10.4