[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH v8 17/21] xen/x86: allow HVM guests to use hypercalls to bring up vCPUs
El 12/11/15 a les 17.57, Jan Beulich ha escrit: >>>> On 06.11.15 at 17:05, <roger.pau@xxxxxxxxxx> wrote: >> @@ -1183,6 +1184,301 @@ int arch_set_info_guest( >> #undef c >> } >> >> +static inline int check_segment(struct segment_register reg, > > Passed by value? Hm, right, will pass by reference in next version. > >> + enum x86_segment seg) >> +{ >> + >> + if ( reg.attr.fields.pad != 0 ) >> + { >> + gprintk(XENLOG_ERR, >> + "Attribute bits 12-15 of the segment are not zero\n"); >> + return -EINVAL; >> + } >> + >> + if ( reg.sel == 0 && reg.base == 0 && reg.limit == 0 && > > What's the sel check good for when your only caller only ever calls > you with it being zero? I don't mind removing the sel == 0 check but I don't think it hurts either. > Looking at base or limit here doesn't seem > right either. I'm sorry but I'm not following you here, why is this not right? Would you rather conclude that the user is trying to load a null segment by just looking at the attributes field (and checking it's 0)? >> + reg.attr.bytes == 0) >> + { >> + if ( seg == x86_seg_cs || seg == x86_seg_ss ) >> + { >> + gprintk(XENLOG_ERR, "Null selector provided for CS or SS\n"); >> + return -EINVAL; >> + } >> + return 0; >> + } >> + >> + if ( reg.attr.fields.p != 1 ) > > This is effectively a boolean field - no need for "!= 1", should be > just !. Ack. >> + { >> + gprintk(XENLOG_ERR, "Non-present segment provided\n"); >> + return -EINVAL; >> + } >> + >> + if ( seg == x86_seg_cs && !(reg.attr.fields.type & 0x8) ) >> + { >> + gprintk(XENLOG_ERR, "CS is missing code type\n"); >> + return -EINVAL; >> + } >> + >> + if ( seg != x86_seg_cs && !!(reg.attr.fields.type & 0x8) ) > > No need for !! here. Also only SS is disallowed to get code segments > loaded. For other selector registers they're okay when readable. > >> + { >> + gprintk(XENLOG_ERR, "Non code segment with code type set\n"); >> + return -EINVAL; >> + } > > SS must be writable. OK, I've fixed both issues and also added a check to make sure the S attribute bit is set for all segments except TR. >> +int arch_set_info_hvm_guest(struct vcpu *v, const vcpu_hvm_context_t *ctx) >> +{ >> + struct cpu_user_regs *uregs = &v->arch.user_regs; >> + struct segment_register cs, ds, ss, es, tr; >> + int rc; >> + >> + if ( ctx->pad != 0 ) >> + { >> + gprintk(XENLOG_ERR, "Padding field != 0\n"); > > Please don't. OK, I'm also going to remove the other gprintk below regarding non 0 padding. > >> + return -EINVAL; >> + } >> + >> + switch ( ctx->mode ) >> + { >> + default: >> + return -EINVAL; >> + >> + case VCPU_HVM_MODE_32B: >> + { >> + const struct vcpu_hvm_x86_32 *regs = &ctx->cpu_regs.x86_32; >> + uint32_t limit; >> + >> + if ( ctx->cpu_regs.x86_32.pad1 != 0 || >> + ctx->cpu_regs.x86_32.pad2[0] != 0 || >> + ctx->cpu_regs.x86_32.pad2[1] != 0 || >> + ctx->cpu_regs.x86_32.pad2[2] != 0 ) >> + { >> + gprintk(XENLOG_ERR, "Padding field != 0\n"); >> + return -EINVAL; >> + } >> + >> +#define SEG(s, r) \ >> + (struct segment_register){ .sel = 0, .base = (r)->s ## _base, \ >> + .limit = (r)->s ## _limit, .attr.bytes = (r)->s ## _ar } >> + cs = SEG(cs, regs); >> + ds = SEG(ds, regs); >> + ss = SEG(ss, regs); >> + es = SEG(es, regs); >> + tr = SEG(tr, regs); >> +#undef SEG >> + >> + rc = check_segment(cs, x86_seg_cs); >> + rc |= check_segment(ds, x86_seg_ds); >> + rc |= check_segment(ss, x86_seg_ss); >> + rc |= check_segment(es, x86_seg_es); >> + rc |= check_segment(tr, x86_seg_tr); >> + if ( rc != 0 ) >> + return rc; >> + >> + /* Basic sanity checks. */ >> + limit = cs.limit; >> + if ( cs.attr.fields.g ) >> + limit = (limit << 12) | 0xfff; >> + if ( regs->eip > limit ) >> + { >> + gprintk(XENLOG_ERR, "EIP (%#08x) outside CS limit (%#08x)\n", >> + regs->eip, limit); >> + return -EINVAL; >> + } >> + >> + if ( ds.attr.fields.p && ds.attr.fields.dpl > cs.attr.fields.dpl ) >> + { >> + gprintk(XENLOG_ERR, "DS.DPL (%u) is greater than CS.DPL (%u)\n", >> + ds.attr.fields.dpl, cs.attr.fields.dpl); > > Indentation. Done (and fixed others above and below). > >> + return -EINVAL; >> + } >> + >> + if ( ss.attr.fields.p && ss.attr.fields.dpl != cs.attr.fields.dpl ) >> + { >> + gprintk(XENLOG_ERR, "SS.DPL (%u) is different than CS.DPL >> (%u)\n", >> + ss.attr.fields.dpl, cs.attr.fields.dpl); >> + return -EINVAL; >> + } > > I think this should go ahead of the DS one. Also I don't think > either CS or SS would be okay with the present bit clear, even > less so in 32-bit mode. Yes, CS or SS cannot have the present bit clear, we already make sure of that in the check_segment function above. This condition can indeed be simplified. >> +int arch_initialize_vcpu(struct vcpu *v, XEN_GUEST_HANDLE_PARAM(void) arg) >> +{ >> + struct domain *d = v->domain; >> + int rc; >> + >> + if ( is_hvm_vcpu(v) ) >> + { >> + struct vcpu_hvm_context ctxt; >> + >> + if ( copy_from_guest(&ctxt, arg, 1) ) >> + return -EFAULT; >> + >> + domain_lock(d); >> + rc = v->is_initialised ? -EEXIST : arch_set_info_hvm_guest(v, >> &ctxt); >> + domain_unlock(d); >> + } >> + else >> + { >> + struct vcpu_guest_context *ctxt; >> + >> + if ( (ctxt = alloc_vcpu_guest_context()) == NULL ) >> + return -ENOMEM; >> + >> + if ( copy_from_guest(ctxt, arg, 1) ) >> + { >> + free_vcpu_guest_context(ctxt); >> + return -EFAULT; >> + } >> + >> + domain_lock(d); >> + rc = v->is_initialised ? -EEXIST : arch_set_info_guest(v, ctxt); >> + domain_unlock(d); >> + >> + free_vcpu_guest_context(ctxt); >> + } > > This else branch looks suspiciously like the ARM variant, and iirc I > had asked already on an earlier version to have this handled in > common code (with ARM simply using the common function for its > arch_initialize_vcpu()). Done, I've created a default_initalize_vcpu that's shared between ARM and x86 PV guests. The arch_initialize_vcpu implementation on ARM is just a stub that calls default_initialize_vcpu. Roger. _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |