[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v9 08/13] Add IOREQ_TYPE_VMWARE_PORT
On 02/26/15 03:07, Jan Beulich wrote: >>>> On 25.02.15 at 21:20, <dslutz@xxxxxxxxxxx> wrote: >> On 02/24/15 10:34, Jan Beulich wrote: >>>>>> On 17.02.15 at 00:05, <dslutz@xxxxxxxxxxx> wrote: >>>> @@ -501,22 +542,50 @@ static void hvm_free_ioreq_gmfn(struct domain *d, >>>> unsigned long gmfn) [snip] >>>> @@ -2429,9 +2552,6 @@ struct hvm_ioreq_server >>>> *hvm_select_ioreq_server(struct >> domain *d, >>>> if ( list_empty(&d->arch.hvm_domain.ioreq_server.list) ) >>>> return NULL; >>>> >>>> - if ( p->type != IOREQ_TYPE_COPY && p->type != IOREQ_TYPE_PIO ) >>>> - return d->arch.hvm_domain.default_ioreq_server; >>> >>> Shouldn't this rather be amended than deleted? >>> >> >> The reason is below: >> >>>> @@ -2474,7 +2594,12 @@ struct hvm_ioreq_server >>>> *hvm_select_ioreq_server(struct domain *d, >>>> BUILD_BUG_ON(IOREQ_TYPE_PIO != HVMOP_IO_RANGE_PORT); >>>> BUILD_BUG_ON(IOREQ_TYPE_COPY != HVMOP_IO_RANGE_MEMORY); >>>> BUILD_BUG_ON(IOREQ_TYPE_PCI_CONFIG != HVMOP_IO_RANGE_PCI); >>>> + BUILD_BUG_ON(IOREQ_TYPE_VMWARE_PORT != >>>> HVMOP_IO_RANGE_VMWARE_PORT); >>>> + BUILD_BUG_ON(IOREQ_TYPE_TIMEOFFSET != HVMOP_IO_RANGE_TIMEOFFSET); >>>> + BUILD_BUG_ON(IOREQ_TYPE_INVALIDATE != HVMOP_IO_RANGE_INVALIDATE); >>>> r = s->range[type]; >>>> + if ( !r ) >>>> + continue; >>> >>> Why, all of the sudden? >>> >> >> This is the replacement for the deleted "if" above. Continue will lead >> to the same return that was remove above (it is at the end). They are >> currently the same because all ioreq servers have the same set of >> ranges. But if it would help, I can change "continue" into the "return >> default". > > So further down you talk of the "special range 1" (see there for > further remarks in this regard) - how would r be NULL here in the > first place? Since there is a hole in the #defines 0,1,2,7,8 (currently) range[6] is where r will be NULL for example. However no current code should be able to get here. So if you want me to I can drop the "if". > That said - yes, making this explicitly do what is > intended (perhaps rather using "break" instead of "return") would > seem very desirable. There simply is no point in continuing the > loop. > Will use break if the "if" is not dropped. >>>> @@ -2501,6 +2626,13 @@ struct hvm_ioreq_server >>>> *hvm_select_ioreq_server(struct domain *d, >>>> } >>>> >>>> break; >>>> + case IOREQ_TYPE_VMWARE_PORT: >>>> + case IOREQ_TYPE_TIMEOFFSET: >>>> + case IOREQ_TYPE_INVALIDATE: >>>> + if ( rangeset_contains_singleton(r, 1) ) >>>> + return s; >>> >>> This literal 1 at least needs explanation (i.e. a comment). >>> >> >> The comment is below (copied here). Will duplicate it here (with any >> adjustments needed): >> >> + * NOTE: The 'special' range of 1 is what is checked for outside >> + * of the three types of I/O. >> >> How about /* The 'special' range of 1 is checked for being enabled */? > > Along these lines, yes (fixed for coding style). And then "1" is not > a range of any kind. I suppose writing it as a proper range (e.g. > [1,1]) would already help. > I will adjust to using [1,1]. >>>> --- a/xen/arch/x86/x86_emulate/x86_emulate.h >>>> +++ b/xen/arch/x86/x86_emulate/x86_emulate.h >>>> @@ -112,6 +112,8 @@ struct __packed segment_register { >>>> #define X86EMUL_RETRY 3 >>>> /* (cmpxchg accessor): CMPXCHG failed. Maps to X86EMUL_RETRY in caller. >>>> */ >>>> #define X86EMUL_CMPXCHG_FAILED 3 >>>> + /* Send part of registers also to DM. */ >>>> +#define X86EMUL_VMPORT_SEND 4 >>> >>> Introducing a new value here seems rather fragile, as various code >>> paths you don't touch would need auditing that they do the right >>> thing upon this value being returned. Plus even conceptually this >>> doesn't belong here - the instruction emulator shouldn't be concerned >>> with things like VMware emulation. >>> >> >> The only place I know of where rc is not checked by name is in >> x86_emulate.c. There are a lot of 0 and != 0 checks. Also in area of >> code there are places that return X86EMUL_OKAY when it looks to me that >> the return value is checked for 0 and ignored otherwise. > > The point aren't the checks against zero, but the ones against the > #define-d values. Code may exist that, after excluding certain > values, assumes that only some specific value can be left. While > we aim at adding ASSERT()s for such cases, I'm nowhere near to > being convinced this is the case everywhere. > >> So I will agree that the use of these defines is complex. However, I >> need a way to pass back X86EMUL_UNHANDLEABLE and send a few registers to >> QEMU. Now since the code path that I need to do this is: >> >> ... >> hvmemul_do_io >> hvm_portio_intercept >> hvm_io_intercept >> process_portio_intercept >> vmport_ioport >> >> >> Since there is only 1 caller to hvm_portio_intercept() -- >> hvmemul_do_io, and hvmemul_do_io does not let X86EMUL_VMPORT_SEND be >> returned. I feel that all code paths currently have been checked. >> Adding a return code to me was the simpler code change. It is possible >> to change process_portio_intercept() by adding special code there to >> adjust the ioreq_t p there, but that looked worse to me. >> >> I can change to using a bit in the return of portio_action_t that would >> be masked in process_portio_intercept() and make the code in >> hvmemul_do_io() less clear since the change of p->type changes in >> process_portio_intercept(), and change to hvmemul_do_io() is much more >> involved. >> >> I am happy to use some other number like 65539 if that would help. Also >> any other name like X86EMUL_UNHANDLEABLE_EXTENDED, SPECIAL_DM_HANDLING, >> etc would be fine with me. I have no issue with defining this in a >> different header file if that would help. > > I understand all this is non-trivial and not necessarily obvious. But > as said before - the x86 instruction emulator should please remain > something acting along _only_ architectural specifications. Any > extensions to support things like what you want to do here should > be added using neutral hooks, responsible for keeping state they > need on their own. > How does (the incorrectly formatted for a smaller diff): diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index f271dfc..9027ab8 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -219,6 +219,7 @@ static int hvmemul_do_io( vio->io_state = HVMIO_handle_mmio_awaiting_completion; break; case X86EMUL_UNHANDLEABLE: + if ( vmport_check_port(p.addr) ) { struct hvm_ioreq_server *s = hvm_select_ioreq_server(curr->domain, &p); @@ -238,8 +239,50 @@ static int hvmemul_do_io( else if ( p_data == NULL ) rc = X86EMUL_OKAY; } - break; } + else + { + struct hvm_ioreq_server *s; + vmware_regs_t *vr; + + BUILD_BUG_ON(sizeof(ioreq_t) < sizeof(vmware_regs_t)); + + p.type = IOREQ_TYPE_VMWARE_PORT; + s = hvm_select_ioreq_server(curr->domain, &p); + vr = get_vmport_regs_any(s, curr); + + /* + * If there is no suitable backing DM, just ignore accesses. If + * we do not have access to registers to pass to QEMU, just + * ignore access. + */ + if ( !s || !vr ) + { + hvm_complete_assist_req(&p); + rc = X86EMUL_OKAY; + vio->io_state = HVMIO_none; + } + else + { + struct cpu_user_regs *regs = guest_cpu_user_regs(); + + p.data = regs->rax; + vr->ebx = regs->_ebx; + vr->ecx = regs->_ecx; + vr->edx = regs->_edx; + vr->esi = regs->_esi; + vr->edi = regs->_edi; + + vio->io_state = HVMIO_handle_pio_awaiting_completion; + if ( !hvm_send_assist_req(s, &p) ) + { + rc = X86EMUL_RETRY; + vio->io_state = HVMIO_none; + } + /* else leave rc as X86EMUL_UNHANDLEABLE for below. */ + } + } + break; default: BUG(); } @@ -248,6 +291,13 @@ static int hvmemul_do_io( { if ( ram_page ) put_page(ram_page); + /* + * If rc is still X86EMUL_UNHANDLEABLE, then were are of + * type IOREQ_TYPE_VMWARE_PORT, so completion in + * hvm_io_assist() with no re-emulation required + */ + if ( rc == X86EMUL_UNHANDLEABLE ) + rc = X86EMUL_OKAY; return rc; } look as the change to emulate.c? Attached is the perspective version of this patch. >>>> --- a/xen/include/public/hvm/hvm_op.h >>>> +++ b/xen/include/public/hvm/hvm_op.h >>>> @@ -314,6 +314,9 @@ >>>> DEFINE_XEN_GUEST_HANDLE(xen_hvm_get_ioreq_server_info_t); >>>> * >>>> * NOTE: unless an emulation request falls entirely within a range mapped >>>> * by a secondary emulator, it will not be passed to that emulator. >>>> + * >>>> + * NOTE: The 'special' range of 1 is what is checked for outside >>>> + * of the three types of I/O. >>>> */ >>>> #define HVMOP_map_io_range_to_ioreq_server 19 >>>> #define HVMOP_unmap_io_range_from_ioreq_server 20 >>>> @@ -324,6 +327,9 @@ struct xen_hvm_io_range { >>>> # define HVMOP_IO_RANGE_PORT 0 /* I/O port range */ >>>> # define HVMOP_IO_RANGE_MEMORY 1 /* MMIO range */ >>>> # define HVMOP_IO_RANGE_PCI 2 /* PCI segment/bus/dev/func range */ >>>> +# define HVMOP_IO_RANGE_VMWARE_PORT 3 /* VMware port special range */ >>>> +# define HVMOP_IO_RANGE_TIMEOFFSET 7 /* TIMEOFFSET special range */ >>>> +# define HVMOP_IO_RANGE_INVALIDATE 8 /* INVALIDATE special range */ >>> >>> I can't seem to connect the comment you add above to the three >>> new #define-s. >>> >> >> Will work on better wording for the comment here and in the code >> that is checking for it. Paul Durrant pointed out that >> HVMOP_IO_RANGE_INVALIDATE is not needed and so the plan is to drop it. >> Does: >> >> + * NOTE: The 'special' range of 1 is what is checked for on >> + * VMWARE_PORT and TIMEOFFSET. >> >> help? > > Calling out the affected ones explicitly is certainly better. Beyond > that see my earlier remark. > Also adjust to [1,1]. Rest is done in a different thread. -Don Slutz > Jan > Attachment:
0016-Add-IOREQ_TYPE_VMWARE_PORT.patch _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |