* [PATCH 0/3] x86: XSA-112 follow-ups
@ 2015-01-08 15:47 Jan Beulich
2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich
` (2 more replies)
0 siblings, 3 replies; 27+ messages in thread
From: Jan Beulich @ 2015-01-08 15:47 UTC (permalink / raw)
To: xen-devel; +Cc: Keir Fraser
1: also allow REP STOS emulation acceleration
2: HVM: drop pointless parameters from vIOAPIC internal routines
3: HVM: vMSI simplification
Signed-off-by: Jan Beulich <jbeulich@suse.com>
^ permalink raw reply [flat|nested] 27+ messages in thread* [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 15:47 [PATCH 0/3] x86: XSA-112 follow-ups Jan Beulich @ 2015-01-08 15:50 ` Jan Beulich 2015-01-08 16:16 ` Tim Deegan 2015-01-08 19:29 ` Andrew Cooper 2015-01-08 15:51 ` [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines Jan Beulich 2015-01-08 15:52 ` [PATCH 3/3] x86/HVM: vMSI simplification Jan Beulich 2 siblings, 2 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-08 15:50 UTC (permalink / raw) To: xen-devel; +Cc: Keir Fraser [-- Attachment #1: Type: text/plain, Size: 8148 bytes --] While the REP MOVS acceleration appears to have helped qemu-traditional based guests, qemu-upstream (or really the respective video BIOSes) doesn't appear to benefit from that. Instead the acceleration added here provides a visible performance improvement during very early HVM guest boot. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -731,6 +731,17 @@ static int hvmemul_rep_movs_discard( return X86EMUL_OKAY; } +static int hvmemul_rep_stos_discard( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + return X86EMUL_OKAY; +} + static int hvmemul_rep_outs_discard( enum x86_segment src_seg, unsigned long src_offset, @@ -982,6 +993,110 @@ static int hvmemul_rep_movs( return X86EMUL_OKAY; } +static int hvmemul_rep_stos( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct hvm_emulate_ctxt *hvmemul_ctxt = + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + unsigned long addr; + paddr_t gpa; + p2m_type_t p2mt; + bool_t df = !!(ctxt->regs->eflags & X86_EFLAGS_DF); + int rc = hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, reps, + hvm_access_write, hvmemul_ctxt, &addr); + + if ( rc == X86EMUL_OKAY ) + { + uint32_t pfec = PFEC_page_present | PFEC_write_access; + + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + + rc = hvmemul_linear_to_phys( + addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); + } + if ( rc != X86EMUL_OKAY ) + return rc; + + /* Check for MMIO op */ + (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt); + + switch ( p2mt ) + { + unsigned long bytes; + void *buf; + + default: + /* Allocate temporary buffer. */ + for ( ; ; ) + { + bytes = *reps * bytes_per_rep; + buf = xmalloc_bytes(bytes); + if ( buf || *reps <= 1 ) + break; + *reps >>= 1; + } + + if ( !buf ) + buf = p_data; + else + switch ( bytes_per_rep ) + { +#define CASE(bits, suffix) \ + case (bits) / 8: \ + asm ( "rep stos" #suffix \ + :: "a" (*(const uint##bits##_t *)p_data), \ + "D" (buf), "c" (*reps) \ + : "memory" ); \ + break + CASE(8, b); + CASE(16, w); + CASE(32, l); + CASE(64, q); +#undef CASE + + default: + xfree(buf); + ASSERT(!buf); + return X86EMUL_UNHANDLEABLE; + } + + /* Adjust address for reverse store. */ + if ( df ) + gpa -= bytes - bytes_per_rep; + + rc = hvm_copy_to_guest_phys(gpa, buf, bytes); + + if ( buf != p_data ) + xfree(buf); + + switch ( rc ) + { + case HVMCOPY_gfn_paged_out: + case HVMCOPY_gfn_shared: + return X86EMUL_RETRY; + case HVMCOPY_okay: + return X86EMUL_OKAY; + } + + gdprintk(XENLOG_WARNING, + "Failed REP STOS: gpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n", + gpa, *reps, bytes_per_rep); + /* fall through */ + case p2m_mmio_direct: + return X86EMUL_UNHANDLEABLE; + + case p2m_mmio_dm: + return hvmemul_do_mmio(gpa, reps, bytes_per_rep, 0, IOREQ_WRITE, df, + p_data); + } +} + static int hvmemul_read_segment( enum x86_segment seg, struct segment_register *reg, @@ -1239,6 +1354,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins, .rep_outs = hvmemul_rep_outs, .rep_movs = hvmemul_rep_movs, + .rep_stos = hvmemul_rep_stos, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io, @@ -1264,6 +1380,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins_discard, .rep_outs = hvmemul_rep_outs_discard, .rep_movs = hvmemul_rep_movs_discard, + .rep_stos = hvmemul_rep_stos_discard, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io_discard, --- a/xen/arch/x86/hvm/stdvga.c +++ b/xen/arch/x86/hvm/stdvga.c @@ -470,11 +470,11 @@ static int mmio_move(struct hvm_hw_stdvg uint64_t addr = p->addr; p2m_type_t p2mt; struct domain *d = current->domain; + int step = p->df ? -p->size : p->size; if ( p->data_is_ptr ) { uint64_t data = p->data, tmp; - int step = p->df ? -p->size : p->size; if ( p->dir == IOREQ_READ ) { @@ -529,13 +529,18 @@ static int mmio_move(struct hvm_hw_stdvg } } } + else if ( p->dir == IOREQ_WRITE ) + { + for ( i = 0; i < p->count; i++ ) + { + stdvga_mem_write(addr, p->data, p->size); + addr += step; + } + } else { ASSERT(p->count == 1); - if ( p->dir == IOREQ_READ ) - p->data = stdvga_mem_read(addr, p->size); - else - stdvga_mem_write(addr, p->data, p->size); + p->data = stdvga_mem_read(addr, p->size); } read_data = p->data; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2568,15 +2568,25 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - /* unsigned long max_reps = */get_rep_prefix(); - dst.type = OP_MEM; + unsigned long nr_reps = get_rep_prefix(); dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - dst.val = _regs.eax; + if ( (nr_reps == 1) || !ops->rep_stos || + ((rc = ops->rep_stos(&_regs.eax, + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) + { + dst.val = _regs.eax; + dst.type = OP_MEM; + nr_reps = 1; + } + else if ( rc != X86EMUL_OKAY ) + goto done; register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - put_rep_prefix(1); + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); break; } --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -241,6 +241,20 @@ struct x86_emulate_ops struct x86_emulate_ctxt *ctxt); /* + * rep_stos: Emulate STOS: <*p_data> -> <seg:offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_stos)( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* * read_segment: Emulate a read of full context of a segment register. * @reg: [OUT] Contents of segment register (visible and hidden state). */ [-- Attachment #2: x86emul-rep-stos.patch --] [-- Type: text/plain, Size: 8195 bytes --] x86: also allow REP STOS emulation acceleration While the REP MOVS acceleration appears to have helped qemu-traditional based guests, qemu-upstream (or really the respective video BIOSes) doesn't appear to benefit from that. Instead the acceleration added here provides a visible performance improvement during very early HVM guest boot. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -731,6 +731,17 @@ static int hvmemul_rep_movs_discard( return X86EMUL_OKAY; } +static int hvmemul_rep_stos_discard( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + return X86EMUL_OKAY; +} + static int hvmemul_rep_outs_discard( enum x86_segment src_seg, unsigned long src_offset, @@ -982,6 +993,110 @@ static int hvmemul_rep_movs( return X86EMUL_OKAY; } +static int hvmemul_rep_stos( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct hvm_emulate_ctxt *hvmemul_ctxt = + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + unsigned long addr; + paddr_t gpa; + p2m_type_t p2mt; + bool_t df = !!(ctxt->regs->eflags & X86_EFLAGS_DF); + int rc = hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, reps, + hvm_access_write, hvmemul_ctxt, &addr); + + if ( rc == X86EMUL_OKAY ) + { + uint32_t pfec = PFEC_page_present | PFEC_write_access; + + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + + rc = hvmemul_linear_to_phys( + addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); + } + if ( rc != X86EMUL_OKAY ) + return rc; + + /* Check for MMIO op */ + (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt); + + switch ( p2mt ) + { + unsigned long bytes; + void *buf; + + default: + /* Allocate temporary buffer. */ + for ( ; ; ) + { + bytes = *reps * bytes_per_rep; + buf = xmalloc_bytes(bytes); + if ( buf || *reps <= 1 ) + break; + *reps >>= 1; + } + + if ( !buf ) + buf = p_data; + else + switch ( bytes_per_rep ) + { +#define CASE(bits, suffix) \ + case (bits) / 8: \ + asm ( "rep stos" #suffix \ + :: "a" (*(const uint##bits##_t *)p_data), \ + "D" (buf), "c" (*reps) \ + : "memory" ); \ + break + CASE(8, b); + CASE(16, w); + CASE(32, l); + CASE(64, q); +#undef CASE + + default: + xfree(buf); + ASSERT(!buf); + return X86EMUL_UNHANDLEABLE; + } + + /* Adjust address for reverse store. */ + if ( df ) + gpa -= bytes - bytes_per_rep; + + rc = hvm_copy_to_guest_phys(gpa, buf, bytes); + + if ( buf != p_data ) + xfree(buf); + + switch ( rc ) + { + case HVMCOPY_gfn_paged_out: + case HVMCOPY_gfn_shared: + return X86EMUL_RETRY; + case HVMCOPY_okay: + return X86EMUL_OKAY; + } + + gdprintk(XENLOG_WARNING, + "Failed REP STOS: gpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n", + gpa, *reps, bytes_per_rep); + /* fall through */ + case p2m_mmio_direct: + return X86EMUL_UNHANDLEABLE; + + case p2m_mmio_dm: + return hvmemul_do_mmio(gpa, reps, bytes_per_rep, 0, IOREQ_WRITE, df, + p_data); + } +} + static int hvmemul_read_segment( enum x86_segment seg, struct segment_register *reg, @@ -1239,6 +1354,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins, .rep_outs = hvmemul_rep_outs, .rep_movs = hvmemul_rep_movs, + .rep_stos = hvmemul_rep_stos, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io, @@ -1264,6 +1380,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins_discard, .rep_outs = hvmemul_rep_outs_discard, .rep_movs = hvmemul_rep_movs_discard, + .rep_stos = hvmemul_rep_stos_discard, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io_discard, --- a/xen/arch/x86/hvm/stdvga.c +++ b/xen/arch/x86/hvm/stdvga.c @@ -470,11 +470,11 @@ static int mmio_move(struct hvm_hw_stdvg uint64_t addr = p->addr; p2m_type_t p2mt; struct domain *d = current->domain; + int step = p->df ? -p->size : p->size; if ( p->data_is_ptr ) { uint64_t data = p->data, tmp; - int step = p->df ? -p->size : p->size; if ( p->dir == IOREQ_READ ) { @@ -529,13 +529,18 @@ static int mmio_move(struct hvm_hw_stdvg } } } + else if ( p->dir == IOREQ_WRITE ) + { + for ( i = 0; i < p->count; i++ ) + { + stdvga_mem_write(addr, p->data, p->size); + addr += step; + } + } else { ASSERT(p->count == 1); - if ( p->dir == IOREQ_READ ) - p->data = stdvga_mem_read(addr, p->size); - else - stdvga_mem_write(addr, p->data, p->size); + p->data = stdvga_mem_read(addr, p->size); } read_data = p->data; --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -2568,15 +2568,25 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - /* unsigned long max_reps = */get_rep_prefix(); - dst.type = OP_MEM; + unsigned long nr_reps = get_rep_prefix(); dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - dst.val = _regs.eax; + if ( (nr_reps == 1) || !ops->rep_stos || + ((rc = ops->rep_stos(&_regs.eax, + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) + { + dst.val = _regs.eax; + dst.type = OP_MEM; + nr_reps = 1; + } + else if ( rc != X86EMUL_OKAY ) + goto done; register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - put_rep_prefix(1); + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); break; } --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -241,6 +241,20 @@ struct x86_emulate_ops struct x86_emulate_ctxt *ctxt); /* + * rep_stos: Emulate STOS: <*p_data> -> <seg:offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_stos)( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* * read_segment: Emulate a read of full context of a segment register. * @reg: [OUT] Contents of segment register (visible and hidden state). */ [-- Attachment #3: Type: text/plain, Size: 126 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich @ 2015-01-08 16:16 ` Tim Deegan 2015-01-08 16:29 ` Jan Beulich 2015-01-08 19:29 ` Andrew Cooper 1 sibling, 1 reply; 27+ messages in thread From: Tim Deegan @ 2015-01-08 16:16 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 15:50 +0000 on 08 Jan (1420728649), Jan Beulich wrote: > While the REP MOVS acceleration appears to have helped qemu-traditional > based guests, qemu-upstream (or really the respective video BIOSes) > doesn't appear to benefit from that. Instead the acceleration added > here provides a visible performance improvement during very early HVM > guest boot. > > Signed-off-by: Jan Beulich <jbeulich@suse.com> If I read this right, it's allocating and memset()ing a buffer and then copying that buffer to the guest? Would it be better to map the guest frame and write directly? Edge cases where the STOS crosses a frame boundary could happen the old way. Cheers, Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 16:16 ` Tim Deegan @ 2015-01-08 16:29 ` Jan Beulich 2015-01-08 16:56 ` Tim Deegan 0 siblings, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-08 16:29 UTC (permalink / raw) To: Tim Deegan; +Cc: xen-devel, Keir Fraser >>> On 08.01.15 at 17:16, <tim@xen.org> wrote: > At 15:50 +0000 on 08 Jan (1420728649), Jan Beulich wrote: >> While the REP MOVS acceleration appears to have helped qemu-traditional >> based guests, qemu-upstream (or really the respective video BIOSes) >> doesn't appear to benefit from that. Instead the acceleration added >> here provides a visible performance improvement during very early HVM >> guest boot. >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > If I read this right, it's allocating and memset()ing a buffer and > then copying that buffer to the guest? In the non-MMIO case yes. > Would it be better to map the guest frame and write directly? Edge > cases where the STOS crosses a frame boundary could happen the old way. This matches the REP MOVS handling, which also allocates a temporary buffer. I.e. if you wanted this for REP STOS, we should first make it so for REP MOVS. Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 16:29 ` Jan Beulich @ 2015-01-08 16:56 ` Tim Deegan 2015-01-08 17:05 ` Jan Beulich 0 siblings, 1 reply; 27+ messages in thread From: Tim Deegan @ 2015-01-08 16:56 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 16:29 +0000 on 08 Jan (1420730974), Jan Beulich wrote: > >>> On 08.01.15 at 17:16, <tim@xen.org> wrote: > > At 15:50 +0000 on 08 Jan (1420728649), Jan Beulich wrote: > >> While the REP MOVS acceleration appears to have helped qemu-traditional > >> based guests, qemu-upstream (or really the respective video BIOSes) > >> doesn't appear to benefit from that. Instead the acceleration added > >> here provides a visible performance improvement during very early HVM > >> guest boot. > >> > >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > > > If I read this right, it's allocating and memset()ing a buffer and > > then copying that buffer to the guest? > > In the non-MMIO case yes. > > > Would it be better to map the guest frame and write directly? Edge > > cases where the STOS crosses a frame boundary could happen the old way. > > This matches the REP MOVS handling, which also allocates a > temporary buffer. I.e. if you wanted this for REP STOS, we should > first make it so for REP MOVS. Well, REP MOVS is trickier as it would have to handle page crossings in both source and destination. Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 16:56 ` Tim Deegan @ 2015-01-08 17:05 ` Jan Beulich 2015-01-08 18:15 ` Tim Deegan 0 siblings, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-08 17:05 UTC (permalink / raw) To: Tim Deegan; +Cc: xen-devel, Keir Fraser >>> On 08.01.15 at 17:56, <tim@xen.org> wrote: > At 16:29 +0000 on 08 Jan (1420730974), Jan Beulich wrote: >> >>> On 08.01.15 at 17:16, <tim@xen.org> wrote: >> > At 15:50 +0000 on 08 Jan (1420728649), Jan Beulich wrote: >> >> While the REP MOVS acceleration appears to have helped qemu-traditional >> >> based guests, qemu-upstream (or really the respective video BIOSes) >> >> doesn't appear to benefit from that. Instead the acceleration added >> >> here provides a visible performance improvement during very early HVM >> >> guest boot. >> >> >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> >> > >> > If I read this right, it's allocating and memset()ing a buffer and >> > then copying that buffer to the guest? >> >> In the non-MMIO case yes. >> >> > Would it be better to map the guest frame and write directly? Edge >> > cases where the STOS crosses a frame boundary could happen the old way. >> >> This matches the REP MOVS handling, which also allocates a >> temporary buffer. I.e. if you wanted this for REP STOS, we should >> first make it so for REP MOVS. > > Well, REP MOVS is trickier as it would have to handle page crossings > in both source and destination. But I don't think would could blindly map for all sorts of p2mt we get back - we'd have to special case RAM, and deal with the other cases the current way anyway (even if for nothing else than getting a correct error indicator). Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 17:05 ` Jan Beulich @ 2015-01-08 18:15 ` Tim Deegan 0 siblings, 0 replies; 27+ messages in thread From: Tim Deegan @ 2015-01-08 18:15 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 17:05 +0000 on 08 Jan (1420733142), Jan Beulich wrote: > >>> On 08.01.15 at 17:56, <tim@xen.org> wrote: > > At 16:29 +0000 on 08 Jan (1420730974), Jan Beulich wrote: > >> >>> On 08.01.15 at 17:16, <tim@xen.org> wrote: > >> > At 15:50 +0000 on 08 Jan (1420728649), Jan Beulich wrote: > >> >> While the REP MOVS acceleration appears to have helped qemu-traditional > >> >> based guests, qemu-upstream (or really the respective video BIOSes) > >> >> doesn't appear to benefit from that. Instead the acceleration added > >> >> here provides a visible performance improvement during very early HVM > >> >> guest boot. > >> >> > >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > >> > > >> > If I read this right, it's allocating and memset()ing a buffer and > >> > then copying that buffer to the guest? > >> > >> In the non-MMIO case yes. > >> > >> > Would it be better to map the guest frame and write directly? Edge > >> > cases where the STOS crosses a frame boundary could happen the old way. > >> > >> This matches the REP MOVS handling, which also allocates a > >> temporary buffer. I.e. if you wanted this for REP STOS, we should > >> first make it so for REP MOVS. > > > > Well, REP MOVS is trickier as it would have to handle page crossings > > in both source and destination. > > But I don't think would could blindly map for all sorts of p2mt we > get back - we'd have to special case RAM, and deal with the > other cases the current way anyway (even if for nothing else > than getting a correct error indicator). Fair enough - we might as well just have all that once in the hvm_copy code. Reviewed-by: Tim Deegan <tim@xen.org> ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich 2015-01-08 16:16 ` Tim Deegan @ 2015-01-08 19:29 ` Andrew Cooper 2015-01-09 8:42 ` Jan Beulich 2015-01-09 10:27 ` [PATCH v2 " Jan Beulich 1 sibling, 2 replies; 27+ messages in thread From: Andrew Cooper @ 2015-01-08 19:29 UTC (permalink / raw) To: Jan Beulich, xen-devel; +Cc: Keir Fraser On 08/01/15 15:50, Jan Beulich wrote: > + if ( !buf ) > + buf = p_data; > + else > + switch ( bytes_per_rep ) > + { > +#define CASE(bits, suffix) \ > + case (bits) / 8: \ > + asm ( "rep stos" #suffix \ > + :: "a" (*(const uint##bits##_t *)p_data), \ > + "D" (buf), "c" (*reps) \ > + : "memory" ); \ This looks as if it needs output clobbers for D and c ~Andrew ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 19:29 ` Andrew Cooper @ 2015-01-09 8:42 ` Jan Beulich 2015-01-09 10:27 ` [PATCH v2 " Jan Beulich 1 sibling, 0 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-09 8:42 UTC (permalink / raw) To: Andrew Cooper; +Cc: xen-devel, Keir Fraser >>> On 08.01.15 at 20:29, <andrew.cooper3@citrix.com> wrote: > On 08/01/15 15:50, Jan Beulich wrote: >> + if ( !buf ) >> + buf = p_data; >> + else >> + switch ( bytes_per_rep ) >> + { >> +#define CASE(bits, suffix) \ >> + case (bits) / 8: \ >> + asm ( "rep stos" #suffix \ >> + :: "a" (*(const uint##bits##_t *)p_data), \ >> + "D" (buf), "c" (*reps) \ >> + : "memory" ); \ > > This looks as if it needs output clobbers for D and c Well spotted, will fix. Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-08 19:29 ` Andrew Cooper 2015-01-09 8:42 ` Jan Beulich @ 2015-01-09 10:27 ` Jan Beulich 2015-01-09 10:56 ` Andrew Cooper 1 sibling, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-09 10:27 UTC (permalink / raw) To: xen-devel; +Cc: Andrew Cooper, Keir Fraser, Tim Deegan [-- Attachment #1: Type: text/plain, Size: 8842 bytes --] While the REP MOVS acceleration appears to have helped qemu-traditional based guests, qemu-upstream (or really the respective video BIOSes) doesn't appear to benefit from that. Instead the acceleration added here provides a visible performance improvement during very early HVM guest boot. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by Andrew. Add output operand telling the compiler that "buf" is being written. --- unstable.orig/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:36.000000000 +0100 @@ -731,6 +731,17 @@ static int hvmemul_rep_movs_discard( return X86EMUL_OKAY; } +static int hvmemul_rep_stos_discard( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + return X86EMUL_OKAY; +} + static int hvmemul_rep_outs_discard( enum x86_segment src_seg, unsigned long src_offset, @@ -982,6 +993,114 @@ static int hvmemul_rep_movs( return X86EMUL_OKAY; } +static int hvmemul_rep_stos( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct hvm_emulate_ctxt *hvmemul_ctxt = + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + unsigned long addr; + paddr_t gpa; + p2m_type_t p2mt; + bool_t df = !!(ctxt->regs->eflags & X86_EFLAGS_DF); + int rc = hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, reps, + hvm_access_write, hvmemul_ctxt, &addr); + + if ( rc == X86EMUL_OKAY ) + { + uint32_t pfec = PFEC_page_present | PFEC_write_access; + + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + + rc = hvmemul_linear_to_phys( + addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); + } + if ( rc != X86EMUL_OKAY ) + return rc; + + /* Check for MMIO op */ + (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt); + + switch ( p2mt ) + { + unsigned long bytes; + void *buf; + + default: + /* Allocate temporary buffer. */ + for ( ; ; ) + { + bytes = *reps * bytes_per_rep; + buf = xmalloc_bytes(bytes); + if ( buf || *reps <= 1 ) + break; + *reps >>= 1; + } + + if ( !buf ) + buf = p_data; + else + switch ( bytes_per_rep ) + { + unsigned long dummy; + +#define CASE(bits, suffix) \ + case (bits) / 8: \ + asm ( "rep stos" #suffix \ + : "=m" (*(char (*)[bytes])buf), \ + "=D" (dummy), "=c" (dummy) \ + : "a" (*(const uint##bits##_t *)p_data), \ + "1" (buf), "2" (*reps) \ + : "memory" ); \ + break + CASE(8, b); + CASE(16, w); + CASE(32, l); + CASE(64, q); +#undef CASE + + default: + xfree(buf); + ASSERT(!buf); + return X86EMUL_UNHANDLEABLE; + } + + /* Adjust address for reverse store. */ + if ( df ) + gpa -= bytes - bytes_per_rep; + + rc = hvm_copy_to_guest_phys(gpa, buf, bytes); + + if ( buf != p_data ) + xfree(buf); + + switch ( rc ) + { + case HVMCOPY_gfn_paged_out: + case HVMCOPY_gfn_shared: + return X86EMUL_RETRY; + case HVMCOPY_okay: + return X86EMUL_OKAY; + } + + gdprintk(XENLOG_WARNING, + "Failed REP STOS: gpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n", + gpa, *reps, bytes_per_rep); + /* fall through */ + case p2m_mmio_direct: + return X86EMUL_UNHANDLEABLE; + + case p2m_mmio_dm: + return hvmemul_do_mmio(gpa, reps, bytes_per_rep, 0, IOREQ_WRITE, df, + p_data); + } +} + static int hvmemul_read_segment( enum x86_segment seg, struct segment_register *reg, @@ -1239,6 +1358,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins, .rep_outs = hvmemul_rep_outs, .rep_movs = hvmemul_rep_movs, + .rep_stos = hvmemul_rep_stos, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io, @@ -1264,6 +1384,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins_discard, .rep_outs = hvmemul_rep_outs_discard, .rep_movs = hvmemul_rep_movs_discard, + .rep_stos = hvmemul_rep_stos_discard, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io_discard, --- unstable.orig/xen/arch/x86/hvm/stdvga.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/hvm/stdvga.c 2014-11-04 17:42:12.000000000 +0100 @@ -470,11 +470,11 @@ static int mmio_move(struct hvm_hw_stdvg uint64_t addr = p->addr; p2m_type_t p2mt; struct domain *d = current->domain; + int step = p->df ? -p->size : p->size; if ( p->data_is_ptr ) { uint64_t data = p->data, tmp; - int step = p->df ? -p->size : p->size; if ( p->dir == IOREQ_READ ) { @@ -529,13 +529,18 @@ static int mmio_move(struct hvm_hw_stdvg } } } + else if ( p->dir == IOREQ_WRITE ) + { + for ( i = 0; i < p->count; i++ ) + { + stdvga_mem_write(addr, p->data, p->size); + addr += step; + } + } else { ASSERT(p->count == 1); - if ( p->dir == IOREQ_READ ) - p->data = stdvga_mem_read(addr, p->size); - else - stdvga_mem_write(addr, p->data, p->size); + p->data = stdvga_mem_read(addr, p->size); } read_data = p->data; --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:08:19.000000000 +0100 @@ -2568,15 +2568,25 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - /* unsigned long max_reps = */get_rep_prefix(); - dst.type = OP_MEM; + unsigned long nr_reps = get_rep_prefix(); dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - dst.val = _regs.eax; + if ( (nr_reps == 1) || !ops->rep_stos || + ((rc = ops->rep_stos(&_regs.eax, + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) + { + dst.val = _regs.eax; + dst.type = OP_MEM; + nr_reps = 1; + } + else if ( rc != X86EMUL_OKAY ) + goto done; register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - put_rep_prefix(1); + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); break; } --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.h 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.h 2014-11-04 17:06:49.000000000 +0100 @@ -241,6 +241,20 @@ struct x86_emulate_ops struct x86_emulate_ctxt *ctxt); /* + * rep_stos: Emulate STOS: <*p_data> -> <seg:offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_stos)( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* * read_segment: Emulate a read of full context of a segment register. * @reg: [OUT] Contents of segment register (visible and hidden state). */ [-- Attachment #2: x86emul-rep-stos.patch --] [-- Type: text/plain, Size: 8889 bytes --] x86: also allow REP STOS emulation acceleration While the REP MOVS acceleration appears to have helped qemu-traditional based guests, qemu-upstream (or really the respective video BIOSes) doesn't appear to benefit from that. Instead the acceleration added here provides a visible performance improvement during very early HVM guest boot. Signed-off-by: Jan Beulich <jbeulich@suse.com> --- v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by Andrew. Add output operand telling the compiler that "buf" is being written. --- unstable.orig/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:36.000000000 +0100 @@ -731,6 +731,17 @@ static int hvmemul_rep_movs_discard( return X86EMUL_OKAY; } +static int hvmemul_rep_stos_discard( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + return X86EMUL_OKAY; +} + static int hvmemul_rep_outs_discard( enum x86_segment src_seg, unsigned long src_offset, @@ -982,6 +993,114 @@ static int hvmemul_rep_movs( return X86EMUL_OKAY; } +static int hvmemul_rep_stos( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt) +{ + struct hvm_emulate_ctxt *hvmemul_ctxt = + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + unsigned long addr; + paddr_t gpa; + p2m_type_t p2mt; + bool_t df = !!(ctxt->regs->eflags & X86_EFLAGS_DF); + int rc = hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, reps, + hvm_access_write, hvmemul_ctxt, &addr); + + if ( rc == X86EMUL_OKAY ) + { + uint32_t pfec = PFEC_page_present | PFEC_write_access; + + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 ) + pfec |= PFEC_user_mode; + + rc = hvmemul_linear_to_phys( + addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); + } + if ( rc != X86EMUL_OKAY ) + return rc; + + /* Check for MMIO op */ + (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt); + + switch ( p2mt ) + { + unsigned long bytes; + void *buf; + + default: + /* Allocate temporary buffer. */ + for ( ; ; ) + { + bytes = *reps * bytes_per_rep; + buf = xmalloc_bytes(bytes); + if ( buf || *reps <= 1 ) + break; + *reps >>= 1; + } + + if ( !buf ) + buf = p_data; + else + switch ( bytes_per_rep ) + { + unsigned long dummy; + +#define CASE(bits, suffix) \ + case (bits) / 8: \ + asm ( "rep stos" #suffix \ + : "=m" (*(char (*)[bytes])buf), \ + "=D" (dummy), "=c" (dummy) \ + : "a" (*(const uint##bits##_t *)p_data), \ + "1" (buf), "2" (*reps) \ + : "memory" ); \ + break + CASE(8, b); + CASE(16, w); + CASE(32, l); + CASE(64, q); +#undef CASE + + default: + xfree(buf); + ASSERT(!buf); + return X86EMUL_UNHANDLEABLE; + } + + /* Adjust address for reverse store. */ + if ( df ) + gpa -= bytes - bytes_per_rep; + + rc = hvm_copy_to_guest_phys(gpa, buf, bytes); + + if ( buf != p_data ) + xfree(buf); + + switch ( rc ) + { + case HVMCOPY_gfn_paged_out: + case HVMCOPY_gfn_shared: + return X86EMUL_RETRY; + case HVMCOPY_okay: + return X86EMUL_OKAY; + } + + gdprintk(XENLOG_WARNING, + "Failed REP STOS: gpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n", + gpa, *reps, bytes_per_rep); + /* fall through */ + case p2m_mmio_direct: + return X86EMUL_UNHANDLEABLE; + + case p2m_mmio_dm: + return hvmemul_do_mmio(gpa, reps, bytes_per_rep, 0, IOREQ_WRITE, df, + p_data); + } +} + static int hvmemul_read_segment( enum x86_segment seg, struct segment_register *reg, @@ -1239,6 +1358,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins, .rep_outs = hvmemul_rep_outs, .rep_movs = hvmemul_rep_movs, + .rep_stos = hvmemul_rep_stos, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io, @@ -1264,6 +1384,7 @@ static const struct x86_emulate_ops hvm_ .rep_ins = hvmemul_rep_ins_discard, .rep_outs = hvmemul_rep_outs_discard, .rep_movs = hvmemul_rep_movs_discard, + .rep_stos = hvmemul_rep_stos_discard, .read_segment = hvmemul_read_segment, .write_segment = hvmemul_write_segment, .read_io = hvmemul_read_io_discard, --- unstable.orig/xen/arch/x86/hvm/stdvga.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/hvm/stdvga.c 2014-11-04 17:42:12.000000000 +0100 @@ -470,11 +470,11 @@ static int mmio_move(struct hvm_hw_stdvg uint64_t addr = p->addr; p2m_type_t p2mt; struct domain *d = current->domain; + int step = p->df ? -p->size : p->size; if ( p->data_is_ptr ) { uint64_t data = p->data, tmp; - int step = p->df ? -p->size : p->size; if ( p->dir == IOREQ_READ ) { @@ -529,13 +529,18 @@ static int mmio_move(struct hvm_hw_stdvg } } } + else if ( p->dir == IOREQ_WRITE ) + { + for ( i = 0; i < p->count; i++ ) + { + stdvga_mem_write(addr, p->data, p->size); + addr += step; + } + } else { ASSERT(p->count == 1); - if ( p->dir == IOREQ_READ ) - p->data = stdvga_mem_read(addr, p->size); - else - stdvga_mem_write(addr, p->data, p->size); + p->data = stdvga_mem_read(addr, p->size); } read_data = p->data; --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:08:19.000000000 +0100 @@ -2568,15 +2568,25 @@ x86_emulate( } case 0xaa ... 0xab: /* stos */ { - /* unsigned long max_reps = */get_rep_prefix(); - dst.type = OP_MEM; + unsigned long nr_reps = get_rep_prefix(); dst.bytes = (d & ByteOp) ? 1 : op_bytes; dst.mem.seg = x86_seg_es; dst.mem.off = truncate_ea(_regs.edi); - dst.val = _regs.eax; + if ( (nr_reps == 1) || !ops->rep_stos || + ((rc = ops->rep_stos(&_regs.eax, + dst.mem.seg, dst.mem.off, dst.bytes, + &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) + { + dst.val = _regs.eax; + dst.type = OP_MEM; + nr_reps = 1; + } + else if ( rc != X86EMUL_OKAY ) + goto done; register_address_increment( - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); - put_rep_prefix(1); + _regs.edi, + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); + put_rep_prefix(nr_reps); break; } --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.h 2015-01-09 11:19:01.000000000 +0100 +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.h 2014-11-04 17:06:49.000000000 +0100 @@ -241,6 +241,20 @@ struct x86_emulate_ops struct x86_emulate_ctxt *ctxt); /* + * rep_stos: Emulate STOS: <*p_data> -> <seg:offset>. + * @bytes_per_rep: [IN ] Bytes transferred per repetition. + * @reps: [IN ] Maximum repetitions to be emulated. + * [OUT] Number of repetitions actually emulated. + */ + int (*rep_stos)( + void *p_data, + enum x86_segment seg, + unsigned long offset, + unsigned int bytes_per_rep, + unsigned long *reps, + struct x86_emulate_ctxt *ctxt); + + /* * read_segment: Emulate a read of full context of a segment register. * @reg: [OUT] Contents of segment register (visible and hidden state). */ [-- Attachment #3: Type: text/plain, Size: 126 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 10:27 ` [PATCH v2 " Jan Beulich @ 2015-01-09 10:56 ` Andrew Cooper 2015-01-09 11:10 ` Jan Beulich 2015-01-09 11:18 ` Tim Deegan 0 siblings, 2 replies; 27+ messages in thread From: Andrew Cooper @ 2015-01-09 10:56 UTC (permalink / raw) To: Jan Beulich, xen-devel; +Cc: Tim Deegan, Keir Fraser On 09/01/15 10:27, Jan Beulich wrote: > While the REP MOVS acceleration appears to have helped qemu-traditional > based guests, qemu-upstream (or really the respective video BIOSes) > doesn't appear to benefit from that. Instead the acceleration added > here provides a visible performance improvement during very early HVM > guest boot. > > Signed-off-by: Jan Beulich <jbeulich@suse.com> > --- > v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by > Andrew. Add output operand telling the compiler that "buf" is being > written. Is writing buf wise? it looks like you will xfree() a wild pointer, and appears to interfere the "buf != p_data" logic. ~Andrew > > --- unstable.orig/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:01.000000000 +0100 > +++ unstable/xen/arch/x86/hvm/emulate.c 2015-01-09 11:19:36.000000000 +0100 > @@ -731,6 +731,17 @@ static int hvmemul_rep_movs_discard( > return X86EMUL_OKAY; > } > > +static int hvmemul_rep_stos_discard( > + void *p_data, > + enum x86_segment seg, > + unsigned long offset, > + unsigned int bytes_per_rep, > + unsigned long *reps, > + struct x86_emulate_ctxt *ctxt) > +{ > + return X86EMUL_OKAY; > +} > + > static int hvmemul_rep_outs_discard( > enum x86_segment src_seg, > unsigned long src_offset, > @@ -982,6 +993,114 @@ static int hvmemul_rep_movs( > return X86EMUL_OKAY; > } > > +static int hvmemul_rep_stos( > + void *p_data, > + enum x86_segment seg, > + unsigned long offset, > + unsigned int bytes_per_rep, > + unsigned long *reps, > + struct x86_emulate_ctxt *ctxt) > +{ > + struct hvm_emulate_ctxt *hvmemul_ctxt = > + container_of(ctxt, struct hvm_emulate_ctxt, ctxt); > + unsigned long addr; > + paddr_t gpa; > + p2m_type_t p2mt; > + bool_t df = !!(ctxt->regs->eflags & X86_EFLAGS_DF); > + int rc = hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, reps, > + hvm_access_write, hvmemul_ctxt, &addr); > + > + if ( rc == X86EMUL_OKAY ) > + { > + uint32_t pfec = PFEC_page_present | PFEC_write_access; > + > + if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl == 3 ) > + pfec |= PFEC_user_mode; > + > + rc = hvmemul_linear_to_phys( > + addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); > + } > + if ( rc != X86EMUL_OKAY ) > + return rc; > + > + /* Check for MMIO op */ > + (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, &p2mt); > + > + switch ( p2mt ) > + { > + unsigned long bytes; > + void *buf; > + > + default: > + /* Allocate temporary buffer. */ > + for ( ; ; ) > + { > + bytes = *reps * bytes_per_rep; > + buf = xmalloc_bytes(bytes); > + if ( buf || *reps <= 1 ) > + break; > + *reps >>= 1; > + } > + > + if ( !buf ) > + buf = p_data; > + else > + switch ( bytes_per_rep ) > + { > + unsigned long dummy; > + > +#define CASE(bits, suffix) \ > + case (bits) / 8: \ > + asm ( "rep stos" #suffix \ > + : "=m" (*(char (*)[bytes])buf), \ > + "=D" (dummy), "=c" (dummy) \ > + : "a" (*(const uint##bits##_t *)p_data), \ > + "1" (buf), "2" (*reps) \ > + : "memory" ); \ > + break > + CASE(8, b); > + CASE(16, w); > + CASE(32, l); > + CASE(64, q); > +#undef CASE > + > + default: > + xfree(buf); > + ASSERT(!buf); > + return X86EMUL_UNHANDLEABLE; > + } > + > + /* Adjust address for reverse store. */ > + if ( df ) > + gpa -= bytes - bytes_per_rep; > + > + rc = hvm_copy_to_guest_phys(gpa, buf, bytes); > + > + if ( buf != p_data ) > + xfree(buf); > + > + switch ( rc ) > + { > + case HVMCOPY_gfn_paged_out: > + case HVMCOPY_gfn_shared: > + return X86EMUL_RETRY; > + case HVMCOPY_okay: > + return X86EMUL_OKAY; > + } > + > + gdprintk(XENLOG_WARNING, > + "Failed REP STOS: gpa=%"PRIpaddr" reps=%lu bytes_per_rep=%u\n", > + gpa, *reps, bytes_per_rep); > + /* fall through */ > + case p2m_mmio_direct: > + return X86EMUL_UNHANDLEABLE; > + > + case p2m_mmio_dm: > + return hvmemul_do_mmio(gpa, reps, bytes_per_rep, 0, IOREQ_WRITE, df, > + p_data); > + } > +} > + > static int hvmemul_read_segment( > enum x86_segment seg, > struct segment_register *reg, > @@ -1239,6 +1358,7 @@ static const struct x86_emulate_ops hvm_ > .rep_ins = hvmemul_rep_ins, > .rep_outs = hvmemul_rep_outs, > .rep_movs = hvmemul_rep_movs, > + .rep_stos = hvmemul_rep_stos, > .read_segment = hvmemul_read_segment, > .write_segment = hvmemul_write_segment, > .read_io = hvmemul_read_io, > @@ -1264,6 +1384,7 @@ static const struct x86_emulate_ops hvm_ > .rep_ins = hvmemul_rep_ins_discard, > .rep_outs = hvmemul_rep_outs_discard, > .rep_movs = hvmemul_rep_movs_discard, > + .rep_stos = hvmemul_rep_stos_discard, > .read_segment = hvmemul_read_segment, > .write_segment = hvmemul_write_segment, > .read_io = hvmemul_read_io_discard, > --- unstable.orig/xen/arch/x86/hvm/stdvga.c 2015-01-09 11:19:01.000000000 +0100 > +++ unstable/xen/arch/x86/hvm/stdvga.c 2014-11-04 17:42:12.000000000 +0100 > @@ -470,11 +470,11 @@ static int mmio_move(struct hvm_hw_stdvg > uint64_t addr = p->addr; > p2m_type_t p2mt; > struct domain *d = current->domain; > + int step = p->df ? -p->size : p->size; > > if ( p->data_is_ptr ) > { > uint64_t data = p->data, tmp; > - int step = p->df ? -p->size : p->size; > > if ( p->dir == IOREQ_READ ) > { > @@ -529,13 +529,18 @@ static int mmio_move(struct hvm_hw_stdvg > } > } > } > + else if ( p->dir == IOREQ_WRITE ) > + { > + for ( i = 0; i < p->count; i++ ) > + { > + stdvga_mem_write(addr, p->data, p->size); > + addr += step; > + } > + } > else > { > ASSERT(p->count == 1); > - if ( p->dir == IOREQ_READ ) > - p->data = stdvga_mem_read(addr, p->size); > - else > - stdvga_mem_write(addr, p->data, p->size); > + p->data = stdvga_mem_read(addr, p->size); > } > > read_data = p->data; > --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:19:01.000000000 +0100 > +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.c 2015-01-09 11:08:19.000000000 +0100 > @@ -2568,15 +2568,25 @@ x86_emulate( > } > > case 0xaa ... 0xab: /* stos */ { > - /* unsigned long max_reps = */get_rep_prefix(); > - dst.type = OP_MEM; > + unsigned long nr_reps = get_rep_prefix(); > dst.bytes = (d & ByteOp) ? 1 : op_bytes; > dst.mem.seg = x86_seg_es; > dst.mem.off = truncate_ea(_regs.edi); > - dst.val = _regs.eax; > + if ( (nr_reps == 1) || !ops->rep_stos || > + ((rc = ops->rep_stos(&_regs.eax, > + dst.mem.seg, dst.mem.off, dst.bytes, > + &nr_reps, ctxt)) == X86EMUL_UNHANDLEABLE) ) > + { > + dst.val = _regs.eax; > + dst.type = OP_MEM; > + nr_reps = 1; > + } > + else if ( rc != X86EMUL_OKAY ) > + goto done; > register_address_increment( > - _regs.edi, (_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes); > - put_rep_prefix(1); > + _regs.edi, > + nr_reps * ((_regs.eflags & EFLG_DF) ? -dst.bytes : dst.bytes)); > + put_rep_prefix(nr_reps); > break; > } > > --- unstable.orig/xen/arch/x86/x86_emulate/x86_emulate.h 2015-01-09 11:19:01.000000000 +0100 > +++ unstable/xen/arch/x86/x86_emulate/x86_emulate.h 2014-11-04 17:06:49.000000000 +0100 > @@ -241,6 +241,20 @@ struct x86_emulate_ops > struct x86_emulate_ctxt *ctxt); > > /* > + * rep_stos: Emulate STOS: <*p_data> -> <seg:offset>. > + * @bytes_per_rep: [IN ] Bytes transferred per repetition. > + * @reps: [IN ] Maximum repetitions to be emulated. > + * [OUT] Number of repetitions actually emulated. > + */ > + int (*rep_stos)( > + void *p_data, > + enum x86_segment seg, > + unsigned long offset, > + unsigned int bytes_per_rep, > + unsigned long *reps, > + struct x86_emulate_ctxt *ctxt); > + > + /* > * read_segment: Emulate a read of full context of a segment register. > * @reg: [OUT] Contents of segment register (visible and hidden state). > */ > > ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 10:56 ` Andrew Cooper @ 2015-01-09 11:10 ` Jan Beulich 2015-01-09 11:18 ` Tim Deegan 1 sibling, 0 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-09 11:10 UTC (permalink / raw) To: Andrew Cooper; +Cc: xen-devel, Keir Fraser, Tim Deegan >>> On 09.01.15 at 11:56, <andrew.cooper3@citrix.com> wrote: > On 09/01/15 10:27, Jan Beulich wrote: >> While the REP MOVS acceleration appears to have helped qemu-traditional >> based guests, qemu-upstream (or really the respective video BIOSes) >> doesn't appear to benefit from that. Instead the acceleration added >> here provides a visible performance improvement during very early HVM >> guest boot. >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> >> --- >> v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by >> Andrew. Add output operand telling the compiler that "buf" is being >> written. > > Is writing buf wise? it looks like you will xfree() a wild pointer, and > appears to interfere the "buf != p_data" logic. Perhaps the textual description was a little ambiguous, but the code is not: It's not the variable "buf" that gets written, but buf[] in its entirety. Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 10:56 ` Andrew Cooper 2015-01-09 11:10 ` Jan Beulich @ 2015-01-09 11:18 ` Tim Deegan 2015-01-09 11:24 ` Jan Beulich 1 sibling, 1 reply; 27+ messages in thread From: Tim Deegan @ 2015-01-09 11:18 UTC (permalink / raw) To: Andrew Cooper; +Cc: xen-devel, Keir Fraser, Jan Beulich At 10:56 +0000 on 09 Jan (1420797418), Andrew Cooper wrote: > On 09/01/15 10:27, Jan Beulich wrote: > > While the REP MOVS acceleration appears to have helped qemu-traditional > > based guests, qemu-upstream (or really the respective video BIOSes) > > doesn't appear to benefit from that. Instead the acceleration added > > here provides a visible performance improvement during very early HVM > > guest boot. > > > > Signed-off-by: Jan Beulich <jbeulich@suse.com> > > --- > > v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by > > Andrew. Add output operand telling the compiler that "buf" is being > > written. > > Is writing buf wise? it looks like you will xfree() a wild pointer, and > appears to interfere the "buf != p_data" logic. I think the constraints are correct, though the 'memory' clobber makes the rest of it moot. But this: > > + default: > > + xfree(buf); > > + ASSERT(!buf); looks dodgy... Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 11:18 ` Tim Deegan @ 2015-01-09 11:24 ` Jan Beulich 2015-01-09 11:45 ` Tim Deegan 0 siblings, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-09 11:24 UTC (permalink / raw) To: Tim Deegan; +Cc: Andrew Cooper, Keir Fraser, xen-devel >>> On 09.01.15 at 12:18, <tim@xen.org> wrote: > At 10:56 +0000 on 09 Jan (1420797418), Andrew Cooper wrote: >> On 09/01/15 10:27, Jan Beulich wrote: >> > While the REP MOVS acceleration appears to have helped qemu-traditional >> > based guests, qemu-upstream (or really the respective video BIOSes) >> > doesn't appear to benefit from that. Instead the acceleration added >> > here provides a visible performance improvement during very early HVM >> > guest boot. >> > >> > Signed-off-by: Jan Beulich <jbeulich@suse.com> >> > --- >> > v2: fix asm() constraints in hvmemul_rep_stos(), as pointed out by >> > Andrew. Add output operand telling the compiler that "buf" is being >> > written. >> >> Is writing buf wise? it looks like you will xfree() a wild pointer, and >> appears to interfere the "buf != p_data" logic. > > I think the constraints are correct, though the 'memory' clobber makes > the rest of it moot. But this: Ah, yes, the memory clobber could be dropped now that the "=m" is there. >> > + default: >> > + xfree(buf); >> > + ASSERT(!buf); > > looks dodgy... In which way? The "default" is supposed to be unreachable, and sits in the else branch to an if(!buf), i.e. in a release build we'll correctly free the buffer, while in a debug build the ASSERT() will trigger. Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 11:24 ` Jan Beulich @ 2015-01-09 11:45 ` Tim Deegan 2015-01-09 12:10 ` Jan Beulich 0 siblings, 1 reply; 27+ messages in thread From: Tim Deegan @ 2015-01-09 11:45 UTC (permalink / raw) To: Jan Beulich; +Cc: Andrew Cooper, Keir Fraser, xen-devel At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: > >>> On 09.01.15 at 12:18, <tim@xen.org> wrote: > >> > + default: > >> > + xfree(buf); > >> > + ASSERT(!buf); > > > > looks dodgy... > > In which way? The "default" is supposed to be unreachable, and sits > in the else branch to an if(!buf), i.e. in a release build we'll correctly > free the buffer, while in a debug build the ASSERT() will trigger. Oh I see. Can you please use ASSERT(0) for that? Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 11:45 ` Tim Deegan @ 2015-01-09 12:10 ` Jan Beulich 2015-01-09 12:46 ` Andrew Cooper 2015-01-12 14:54 ` George Dunlap 0 siblings, 2 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-09 12:10 UTC (permalink / raw) To: Tim Deegan; +Cc: Andrew Cooper, Keir Fraser, xen-devel >>> On 09.01.15 at 12:45, <tim@xen.org> wrote: > At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: >> >>> On 09.01.15 at 12:18, <tim@xen.org> wrote: >> >> > + default: >> >> > + xfree(buf); >> >> > + ASSERT(!buf); >> > >> > looks dodgy... >> >> In which way? The "default" is supposed to be unreachable, and sits >> in the else branch to an if(!buf), i.e. in a release build we'll correctly >> free the buffer, while in a debug build the ASSERT() will trigger. > > Oh I see. Can you please use ASSERT(0) for that? I sincerely dislike ASSERT(0), but if that's the only way to get the patch accepted... Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 12:10 ` Jan Beulich @ 2015-01-09 12:46 ` Andrew Cooper 2015-01-09 15:20 ` Tim Deegan 2015-01-12 14:54 ` George Dunlap 1 sibling, 1 reply; 27+ messages in thread From: Andrew Cooper @ 2015-01-09 12:46 UTC (permalink / raw) To: Jan Beulich, Tim Deegan; +Cc: xen-devel, Keir Fraser On 09/01/15 12:10, Jan Beulich wrote: >>>> On 09.01.15 at 12:45, <tim@xen.org> wrote: >> At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: >>>>>> On 09.01.15 at 12:18, <tim@xen.org> wrote: >>>>>> + default: >>>>>> + xfree(buf); >>>>>> + ASSERT(!buf); >>>> looks dodgy... >>> In which way? The "default" is supposed to be unreachable, and sits >>> in the else branch to an if(!buf), i.e. in a release build we'll correctly >>> free the buffer, while in a debug build the ASSERT() will trigger. >> Oh I see. Can you please use ASSERT(0) for that? > I sincerely dislike ASSERT(0), but if that's the only way to get > the patch accepted... > > Jan > Perhaps introducing ASSERT_UNREACHABLE() as an alternative which is more obvious in nature than both ASSERT(!buf) and ASSERT(0) ? ~Andrew ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 12:46 ` Andrew Cooper @ 2015-01-09 15:20 ` Tim Deegan 0 siblings, 0 replies; 27+ messages in thread From: Tim Deegan @ 2015-01-09 15:20 UTC (permalink / raw) To: Andrew Cooper; +Cc: xen-devel, Keir Fraser, Jan Beulich At 12:46 +0000 on 09 Jan (1420804005), Andrew Cooper wrote: > On 09/01/15 12:10, Jan Beulich wrote: > >>>> On 09.01.15 at 12:45, <tim@xen.org> wrote: > >> At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: > >>>>>> On 09.01.15 at 12:18, <tim@xen.org> wrote: > >>>>>> + default: > >>>>>> + xfree(buf); > >>>>>> + ASSERT(!buf); > >>>> looks dodgy... > >>> In which way? The "default" is supposed to be unreachable, and sits > >>> in the else branch to an if(!buf), i.e. in a release build we'll correctly > >>> free the buffer, while in a debug build the ASSERT() will trigger. > >> Oh I see. Can you please use ASSERT(0) for that? > > I sincerely dislike ASSERT(0), but if that's the only way to get > > the patch accepted... > > > > Jan > > > > Perhaps introducing ASSERT_UNREACHABLE() as an alternative which is more > obvious in nature than both ASSERT(!buf) and ASSERT(0) ? Fine by me! Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-09 12:10 ` Jan Beulich 2015-01-09 12:46 ` Andrew Cooper @ 2015-01-12 14:54 ` George Dunlap 2015-01-12 15:27 ` Jan Beulich 1 sibling, 1 reply; 27+ messages in thread From: George Dunlap @ 2015-01-12 14:54 UTC (permalink / raw) To: Jan Beulich; +Cc: Andrew Cooper, Keir Fraser, Tim Deegan, xen-devel On Fri, Jan 9, 2015 at 12:10 PM, Jan Beulich <JBeulich@suse.com> wrote: >>>> On 09.01.15 at 12:45, <tim@xen.org> wrote: >> At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: >>> >>> On 09.01.15 at 12:18, <tim@xen.org> wrote: >>> >> > + default: >>> >> > + xfree(buf); >>> >> > + ASSERT(!buf); >>> > >>> > looks dodgy... >>> >>> In which way? The "default" is supposed to be unreachable, and sits >>> in the else branch to an if(!buf), i.e. in a release build we'll correctly >>> free the buffer, while in a debug build the ASSERT() will trigger. >> >> Oh I see. Can you please use ASSERT(0) for that? > > I sincerely dislike ASSERT(0), but if that's the only way to get > the patch accepted... Um, by what set of criteria is ASSERT(!buf) better than ASSERT(0)? At least the second tells the reader that you're not using ASSERT() the normal way. I agree that ASSERT_UNREACHABLE() is probably the best option. -George ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH v2 1/3] x86: also allow REP STOS emulation acceleration 2015-01-12 14:54 ` George Dunlap @ 2015-01-12 15:27 ` Jan Beulich 0 siblings, 0 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-12 15:27 UTC (permalink / raw) To: George Dunlap; +Cc: Andrew Cooper, Tim Deegan, Keir Fraser, xen-devel >>> On 12.01.15 at 15:54, <George.Dunlap@eu.citrix.com> wrote: > On Fri, Jan 9, 2015 at 12:10 PM, Jan Beulich <JBeulich@suse.com> wrote: >>>>> On 09.01.15 at 12:45, <tim@xen.org> wrote: >>> At 11:24 +0000 on 09 Jan (1420799087), Jan Beulich wrote: >>>> >>> On 09.01.15 at 12:18, <tim@xen.org> wrote: >>>> >> > + default: >>>> >> > + xfree(buf); >>>> >> > + ASSERT(!buf); >>>> > >>>> > looks dodgy... >>>> >>>> In which way? The "default" is supposed to be unreachable, and sits >>>> in the else branch to an if(!buf), i.e. in a release build we'll correctly >>>> free the buffer, while in a debug build the ASSERT() will trigger. >>> >>> Oh I see. Can you please use ASSERT(0) for that? >> >> I sincerely dislike ASSERT(0), but if that's the only way to get >> the patch accepted... > > Um, by what set of criteria is ASSERT(!buf) better than ASSERT(0)? At > least the second tells the reader that you're not using ASSERT() the > normal way. Because the resulting message ("0") is completely meaningless, while for "!buf" you at least have a chance of finding the original ASSERT() without line numbers matching up 100%. Jan ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines 2015-01-08 15:47 [PATCH 0/3] x86: XSA-112 follow-ups Jan Beulich 2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich @ 2015-01-08 15:51 ` Jan Beulich 2015-01-08 16:13 ` Tim Deegan 2015-01-08 15:52 ` [PATCH 3/3] x86/HVM: vMSI simplification Jan Beulich 2 siblings, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-08 15:51 UTC (permalink / raw) To: xen-devel; +Cc: Keir Fraser [-- Attachment #1: Type: text/plain, Size: 3050 bytes --] Also simplify a few other operations (without funtional change). Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -46,11 +46,9 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq); -static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic, - unsigned long addr, - unsigned long length) +static uint32_t vioapic_read_indirect(const struct hvm_hw_vioapic *vioapic) { - unsigned long result = 0; + uint32_t result = 0; switch ( vioapic->ioregsel ) { @@ -77,9 +75,8 @@ static unsigned long vioapic_read_indire } redir_content = vioapic->redirtbl[redir_index].bits; - result = (vioapic->ioregsel & 0x1)? - (redir_content >> 32) & 0xffffffff : - redir_content & 0xffffffff; + result = (vioapic->ioregsel & 1) ? (redir_content >> 32) + : redir_content; break; } } @@ -91,21 +88,19 @@ static int vioapic_read( struct vcpu *v, unsigned long addr, unsigned long length, unsigned long *pval) { - struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); + const struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); uint32_t result; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "addr %lx", addr); - addr &= 0xff; - - switch ( addr ) + switch ( addr & 0xff ) { case VIOAPIC_REG_SELECT: result = vioapic->ioregsel; break; case VIOAPIC_REG_WINDOW: - result = vioapic_read_indirect(vioapic, addr, length); + result = vioapic_read_indirect(vioapic); break; default: @@ -169,7 +164,7 @@ static void vioapic_write_redirent( } static void vioapic_write_indirect( - struct hvm_hw_vioapic *vioapic, unsigned long length, unsigned long val) + struct hvm_hw_vioapic *vioapic, uint32_t val) { switch ( vioapic->ioregsel ) { @@ -188,8 +183,8 @@ static void vioapic_write_indirect( { uint32_t redir_index = (vioapic->ioregsel - 0x10) >> 1; - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "change redir index %x val %lx", - redir_index, val); + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "rte[%02x].%s = %08x", + redir_index, vioapic->ioregsel & 1 ? "hi" : "lo", val); if ( redir_index >= VIOAPIC_NUM_PINS ) { @@ -211,16 +206,14 @@ static int vioapic_write( { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); - addr &= 0xff; - - switch ( addr ) + switch ( addr & 0xff ) { case VIOAPIC_REG_SELECT: vioapic->ioregsel = val; break; case VIOAPIC_REG_WINDOW: - vioapic_write_indirect(vioapic, length, val); + vioapic_write_indirect(vioapic, val); break; #if VIOAPIC_VERSION_ID >= 0x20 [-- Attachment #2: x86-vIOAPIC-drop-params.patch --] [-- Type: text/plain, Size: 3113 bytes --] x86/HVM: drop pointless parameters from vIOAPIC internal routines Also simplify a few other operations (without funtional change). Signed-off-by: Jan Beulich <jbeulich@suse.com> --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -46,11 +46,9 @@ static void vioapic_deliver(struct hvm_hw_vioapic *vioapic, int irq); -static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic, - unsigned long addr, - unsigned long length) +static uint32_t vioapic_read_indirect(const struct hvm_hw_vioapic *vioapic) { - unsigned long result = 0; + uint32_t result = 0; switch ( vioapic->ioregsel ) { @@ -77,9 +75,8 @@ static unsigned long vioapic_read_indire } redir_content = vioapic->redirtbl[redir_index].bits; - result = (vioapic->ioregsel & 0x1)? - (redir_content >> 32) & 0xffffffff : - redir_content & 0xffffffff; + result = (vioapic->ioregsel & 1) ? (redir_content >> 32) + : redir_content; break; } } @@ -91,21 +88,19 @@ static int vioapic_read( struct vcpu *v, unsigned long addr, unsigned long length, unsigned long *pval) { - struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); + const struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); uint32_t result; HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "addr %lx", addr); - addr &= 0xff; - - switch ( addr ) + switch ( addr & 0xff ) { case VIOAPIC_REG_SELECT: result = vioapic->ioregsel; break; case VIOAPIC_REG_WINDOW: - result = vioapic_read_indirect(vioapic, addr, length); + result = vioapic_read_indirect(vioapic); break; default: @@ -169,7 +164,7 @@ static void vioapic_write_redirent( } static void vioapic_write_indirect( - struct hvm_hw_vioapic *vioapic, unsigned long length, unsigned long val) + struct hvm_hw_vioapic *vioapic, uint32_t val) { switch ( vioapic->ioregsel ) { @@ -188,8 +183,8 @@ static void vioapic_write_indirect( { uint32_t redir_index = (vioapic->ioregsel - 0x10) >> 1; - HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "change redir index %x val %lx", - redir_index, val); + HVM_DBG_LOG(DBG_LEVEL_IOAPIC, "rte[%02x].%s = %08x", + redir_index, vioapic->ioregsel & 1 ? "hi" : "lo", val); if ( redir_index >= VIOAPIC_NUM_PINS ) { @@ -211,16 +206,14 @@ static int vioapic_write( { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); - addr &= 0xff; - - switch ( addr ) + switch ( addr & 0xff ) { case VIOAPIC_REG_SELECT: vioapic->ioregsel = val; break; case VIOAPIC_REG_WINDOW: - vioapic_write_indirect(vioapic, length, val); + vioapic_write_indirect(vioapic, val); break; #if VIOAPIC_VERSION_ID >= 0x20 [-- Attachment #3: Type: text/plain, Size: 126 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines 2015-01-08 15:51 ` [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines Jan Beulich @ 2015-01-08 16:13 ` Tim Deegan 0 siblings, 0 replies; 27+ messages in thread From: Tim Deegan @ 2015-01-08 16:13 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 15:51 +0000 on 08 Jan (1420728683), Jan Beulich wrote: > Also simplify a few other operations (without funtional change). > > Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Tim Deegan <tim@xen.org> ^ permalink raw reply [flat|nested] 27+ messages in thread
* [PATCH 3/3] x86/HVM: vMSI simplification 2015-01-08 15:47 [PATCH 0/3] x86: XSA-112 follow-ups Jan Beulich 2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich 2015-01-08 15:51 ` [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines Jan Beulich @ 2015-01-08 15:52 ` Jan Beulich 2015-01-08 16:14 ` Tim Deegan 2015-01-09 10:23 ` Andrew Cooper 2 siblings, 2 replies; 27+ messages in thread From: Jan Beulich @ 2015-01-08 15:52 UTC (permalink / raw) To: xen-devel; +Cc: Keir Fraser [-- Attachment #1: Type: text/plain, Size: 1888 bytes --] - struct msixtbl_entry's table_len field can be unsigned int, and by moving it down a little the structure size can be reduced slightly - a disjoint xmalloc()/memset() pair can be converted to xzalloc() - a pointless local variable can be dropped Signed-off-by: Jan Beulich <jbeulich@suse.com> --- unstable.orig/xen/arch/x86/hvm/vmsi.c 2014-11-17 11:40:49.000000000 +0100 +++ unstable/xen/arch/x86/hvm/vmsi.c 2014-11-17 11:43:18.000000000 +0100 @@ -153,9 +153,9 @@ struct msixtbl_entry /* TODO: resolve the potential race by destruction of pdev */ struct pci_dev *pdev; unsigned long gtable; /* gpa of msix table */ - unsigned long table_len; unsigned long table_flags[BITS_TO_LONGS(MAX_MSIX_TABLE_ENTRIES)]; #define MAX_MSIX_ACC_ENTRIES 3 + unsigned int table_len; struct { uint32_t msi_ad[3]; /* Shadow of address low, high and data */ } gentries[MAX_MSIX_ACC_ENTRIES]; @@ -380,16 +380,11 @@ static void add_msixtbl_entry(struct dom uint64_t gtable, struct msixtbl_entry *entry) { - u32 len; - - memset(entry, 0, sizeof(struct msixtbl_entry)); - INIT_LIST_HEAD(&entry->list); INIT_RCU_HEAD(&entry->rcu); atomic_set(&entry->refcnt, 0); - len = pci_msix_get_table_len(pdev); - entry->table_len = len; + entry->table_len = pci_msix_get_table_len(pdev); entry->pdev = pdev; entry->gtable = (unsigned long) gtable; @@ -426,7 +421,7 @@ int msixtbl_pt_register(struct domain *d * xmalloc() with irq_disabled causes the failure of check_lock() * for xenpool->lock. So we allocate an entry beforehand. */ - new_entry = xmalloc(struct msixtbl_entry); + new_entry = xzalloc(struct msixtbl_entry); if ( !new_entry ) return -ENOMEM; [-- Attachment #2: x86-vMSI-table-len.patch --] [-- Type: text/plain, Size: 1914 bytes --] x86/HVM: vMSI simplification - struct msixtbl_entry's table_len field can be unsigned int, and by moving it down a little the structure size can be reduced slightly - a disjoint xmalloc()/memset() pair can be converted to xzalloc() - a pointless local variable can be dropped Signed-off-by: Jan Beulich <jbeulich@suse.com> --- unstable.orig/xen/arch/x86/hvm/vmsi.c 2014-11-17 11:40:49.000000000 +0100 +++ unstable/xen/arch/x86/hvm/vmsi.c 2014-11-17 11:43:18.000000000 +0100 @@ -153,9 +153,9 @@ struct msixtbl_entry /* TODO: resolve the potential race by destruction of pdev */ struct pci_dev *pdev; unsigned long gtable; /* gpa of msix table */ - unsigned long table_len; unsigned long table_flags[BITS_TO_LONGS(MAX_MSIX_TABLE_ENTRIES)]; #define MAX_MSIX_ACC_ENTRIES 3 + unsigned int table_len; struct { uint32_t msi_ad[3]; /* Shadow of address low, high and data */ } gentries[MAX_MSIX_ACC_ENTRIES]; @@ -380,16 +380,11 @@ static void add_msixtbl_entry(struct dom uint64_t gtable, struct msixtbl_entry *entry) { - u32 len; - - memset(entry, 0, sizeof(struct msixtbl_entry)); - INIT_LIST_HEAD(&entry->list); INIT_RCU_HEAD(&entry->rcu); atomic_set(&entry->refcnt, 0); - len = pci_msix_get_table_len(pdev); - entry->table_len = len; + entry->table_len = pci_msix_get_table_len(pdev); entry->pdev = pdev; entry->gtable = (unsigned long) gtable; @@ -426,7 +421,7 @@ int msixtbl_pt_register(struct domain *d * xmalloc() with irq_disabled causes the failure of check_lock() * for xenpool->lock. So we allocate an entry beforehand. */ - new_entry = xmalloc(struct msixtbl_entry); + new_entry = xzalloc(struct msixtbl_entry); if ( !new_entry ) return -ENOMEM; [-- Attachment #3: Type: text/plain, Size: 126 bytes --] _______________________________________________ Xen-devel mailing list Xen-devel@lists.xen.org http://lists.xen.org/xen-devel ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/3] x86/HVM: vMSI simplification 2015-01-08 15:52 ` [PATCH 3/3] x86/HVM: vMSI simplification Jan Beulich @ 2015-01-08 16:14 ` Tim Deegan 2015-01-08 16:30 ` Jan Beulich 2015-01-09 10:23 ` Andrew Cooper 1 sibling, 1 reply; 27+ messages in thread From: Tim Deegan @ 2015-01-08 16:14 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 15:52 +0000 on 08 Jan (1420728734), Jan Beulich wrote: > - struct msixtbl_entry's table_len field can be unsigned int, and by > moving it down a little the structure size can be reduced slightly > - a disjoint xmalloc()/memset() pair can be converted to xzalloc() > - a pointless local variable can be dropped > > Signed-off-by: Jan Beulich <jbeulich@suse.com> Signed-off-by: Tim Deegan <tim@xen.org> ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/3] x86/HVM: vMSI simplification 2015-01-08 16:14 ` Tim Deegan @ 2015-01-08 16:30 ` Jan Beulich 2015-01-08 16:33 ` Tim Deegan 0 siblings, 1 reply; 27+ messages in thread From: Jan Beulich @ 2015-01-08 16:30 UTC (permalink / raw) To: Tim Deegan; +Cc: xen-devel, Keir Fraser >>> On 08.01.15 at 17:14, <tim@xen.org> wrote: > At 15:52 +0000 on 08 Jan (1420728734), Jan Beulich wrote: >> - struct msixtbl_entry's table_len field can be unsigned int, and by >> moving it down a little the structure size can be reduced slightly >> - a disjoint xmalloc()/memset() pair can be converted to xzalloc() >> - a pointless local variable can be dropped >> >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > Signed-off-by: Tim Deegan <tim@xen.org> DYM Reviewed-by? ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/3] x86/HVM: vMSI simplification 2015-01-08 16:30 ` Jan Beulich @ 2015-01-08 16:33 ` Tim Deegan 0 siblings, 0 replies; 27+ messages in thread From: Tim Deegan @ 2015-01-08 16:33 UTC (permalink / raw) To: Jan Beulich; +Cc: xen-devel, Keir Fraser At 16:30 +0000 on 08 Jan (1420731016), Jan Beulich wrote: > >>> On 08.01.15 at 17:14, <tim@xen.org> wrote: > > At 15:52 +0000 on 08 Jan (1420728734), Jan Beulich wrote: > >> - struct msixtbl_entry's table_len field can be unsigned int, and by > >> moving it down a little the structure size can be reduced slightly > >> - a disjoint xmalloc()/memset() pair can be converted to xzalloc() > >> - a pointless local variable can be dropped > >> > >> Signed-off-by: Jan Beulich <jbeulich@suse.com> > > > > Signed-off-by: Tim Deegan <tim@xen.org> > > DYM Reviewed-by? Yes, I do, sorry. Although if I'm making simple errors like that today maybe my review is not worth as much as it might be. :) Tim. ^ permalink raw reply [flat|nested] 27+ messages in thread
* Re: [PATCH 3/3] x86/HVM: vMSI simplification 2015-01-08 15:52 ` [PATCH 3/3] x86/HVM: vMSI simplification Jan Beulich 2015-01-08 16:14 ` Tim Deegan @ 2015-01-09 10:23 ` Andrew Cooper 1 sibling, 0 replies; 27+ messages in thread From: Andrew Cooper @ 2015-01-09 10:23 UTC (permalink / raw) To: Jan Beulich, xen-devel; +Cc: Keir Fraser On 08/01/15 15:52, Jan Beulich wrote: > - struct msixtbl_entry's table_len field can be unsigned int, and by > moving it down a little the structure size can be reduced slightly > - a disjoint xmalloc()/memset() pair can be converted to xzalloc() > - a pointless local variable can be dropped > > Signed-off-by: Jan Beulich <jbeulich@suse.com> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> ^ permalink raw reply [flat|nested] 27+ messages in thread
end of thread, other threads:[~2015-01-12 15:27 UTC | newest] Thread overview: 27+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2015-01-08 15:47 [PATCH 0/3] x86: XSA-112 follow-ups Jan Beulich 2015-01-08 15:50 ` [PATCH 1/3] x86: also allow REP STOS emulation acceleration Jan Beulich 2015-01-08 16:16 ` Tim Deegan 2015-01-08 16:29 ` Jan Beulich 2015-01-08 16:56 ` Tim Deegan 2015-01-08 17:05 ` Jan Beulich 2015-01-08 18:15 ` Tim Deegan 2015-01-08 19:29 ` Andrew Cooper 2015-01-09 8:42 ` Jan Beulich 2015-01-09 10:27 ` [PATCH v2 " Jan Beulich 2015-01-09 10:56 ` Andrew Cooper 2015-01-09 11:10 ` Jan Beulich 2015-01-09 11:18 ` Tim Deegan 2015-01-09 11:24 ` Jan Beulich 2015-01-09 11:45 ` Tim Deegan 2015-01-09 12:10 ` Jan Beulich 2015-01-09 12:46 ` Andrew Cooper 2015-01-09 15:20 ` Tim Deegan 2015-01-12 14:54 ` George Dunlap 2015-01-12 15:27 ` Jan Beulich 2015-01-08 15:51 ` [PATCH 2/3] x86/HVM: drop pointless parameters from vIOAPIC internal routines Jan Beulich 2015-01-08 16:13 ` Tim Deegan 2015-01-08 15:52 ` [PATCH 3/3] x86/HVM: vMSI simplification Jan Beulich 2015-01-08 16:14 ` Tim Deegan 2015-01-08 16:30 ` Jan Beulich 2015-01-08 16:33 ` Tim Deegan 2015-01-09 10:23 ` Andrew Cooper
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.