|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 18/18] PVH xen: introduce vmx_pvh.c
>>> On 25.06.13 at 02:01, Mukesh Rathor <mukesh.rathor@xxxxxxxxxx> wrote:
> --- /dev/null
> +++ b/xen/arch/x86/hvm/vmx/vmx_pvh.c
Just pvh.c please - the directory we're in already tells us that this is
VMX.
> @@ -0,0 +1,523 @@
> +/*
> + * Copyright (C) 2013, Mukesh Rathor, Oracle Corp. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public
> + * License v2 as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + * General Public License for more details.
> + */
> +
> +#include <xen/hypercall.h>
> +#include <xen/guest_access.h>
> +#include <asm/p2m.h>
> +#include <asm/traps.h>
> +#include <asm/hvm/vmx/vmx.h>
> +#include <public/sched.h>
> +#include <asm/hvm/nestedhvm.h>
> +#include <asm/xstate.h>
> +
> +#ifndef NDEBUG
> +int pvhdbg = 0;
This apparently not being declared in a header suggests that it
should be static.
> +#define dbgp1(...) do { (pvhdbg == 1) ? printk(__VA_ARGS__) : 0; } while ( 0
> )
> +#else
> +#define dbgp1(...) ((void)0)
> +#endif
> +
> +
> +/* NOTE: this does NOT read the CS. */
Should probably also say why.
> +static void read_vmcs_selectors(struct cpu_user_regs *regs)
> +{
> + regs->ss = __vmread(GUEST_SS_SELECTOR);
> + regs->ds = __vmread(GUEST_DS_SELECTOR);
> + regs->es = __vmread(GUEST_ES_SELECTOR);
> + regs->gs = __vmread(GUEST_GS_SELECTOR);
> + regs->fs = __vmread(GUEST_FS_SELECTOR);
> +}
By only conditionally reading the selector registers, how do you
guarantee that read_segment_register() would always read
valid values? I think that macro needs to not look at "regs->?s"
at all...
> +static int vmxit_debug(struct cpu_user_regs *regs)
> +{
> + struct vcpu *vp = current;
> + unsigned long exit_qualification = __vmread(EXIT_QUALIFICATION);
> +
> + write_debugreg(6, exit_qualification | 0xffff0ff0);
> +
> + /* gdbsx or another debugger. */
> + if ( vp->domain->domain_id != 0 && /* never pause dom0 */
> + guest_kernel_mode(vp, regs) && vp->domain->debugger_attached )
> +
Bogus double blank, and bogus blank line.
> + domain_pause_for_debugger();
> + else
> + hvm_inject_hw_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE);
> +
> + return 0;
> +}
[...]
> +static int vmxit_invalid_op(struct cpu_user_regs *regs)
> +{
> + if ( guest_kernel_mode(current, regs) ||
> !emulate_forced_invalid_op(regs) )
Did you perhaps mean !guest_kernel_mode()?
> + default:
> + gdprintk(XENLOG_G_WARNING,
> + "PVH: Unhandled trap:%d. IP:%lx\n", vector, regs->eip);
gdprintk() shouldn't be used with XENLOG_G_*.
> +void vmx_pvh_vmexit_handler(struct cpu_user_regs *regs)
> +{
> + unsigned long exit_qualification;
> + unsigned int exit_reason = __vmread(VM_EXIT_REASON);
> + int rc=0, ccpu = smp_processor_id();
> + struct vcpu *v = current;
> +
> + dbgp1("PVH:[%d]left VMCS exitreas:%d RIP:%lx RSP:%lx EFLAGS:%lx
> CR0:%lx\n",
> + ccpu, exit_reason, regs->rip, regs->rsp, regs->rflags,
> + __vmread(GUEST_CR0));
> +
> + /* For guest_kernel_mode which is called from most places below. */
> + regs->cs = __vmread(GUEST_CS_SELECTOR);
Which raises the question of whether your uses of
guest_kernel_mode() are appropriate in the first place: Before this
series there's no use at all under xen/arch/x86/hvm/.
And if it is, I'd like to point out once again that this check should be
looking at SS.DPL, not CS.RPL.
> + if ( rc )
> + {
> + exit_qualification = __vmread(EXIT_QUALIFICATION);
> + gdprintk(XENLOG_G_WARNING,
> + "PVH: [%d] exit_reas:%d 0x%x qual:%ld 0x%lx cr0:0x%016lx\n",
Please use %#x and alike in favor of 0x%x etc.
> +int vmx_pvh_set_vcpu_info(struct vcpu *v, struct vcpu_guest_context *ctxtp)
> +{
> + if ( v->vcpu_id == 0 )
> + return 0;
> +
> + vmx_vmcs_enter(v);
> + __vmwrite(GUEST_GDTR_BASE, ctxtp->gdt.pvh.addr);
> + __vmwrite(GUEST_GDTR_LIMIT, ctxtp->gdt.pvh.limit);
> + __vmwrite(GUEST_GS_BASE, ctxtp->gs_base_user);
> +
> + __vmwrite(GUEST_CS_SELECTOR, ctxtp->user_regs.cs);
> + __vmwrite(GUEST_DS_SELECTOR, ctxtp->user_regs.ds);
> + __vmwrite(GUEST_ES_SELECTOR, ctxtp->user_regs.es);
> + __vmwrite(GUEST_SS_SELECTOR, ctxtp->user_regs.ss);
> + __vmwrite(GUEST_GS_SELECTOR, ctxtp->user_regs.gs);
How does this work without also writing the "hidden" register
fields?
> + if ( vmx_add_guest_msr(MSR_SHADOW_GS_BASE) )
> + {
> + vmx_vmcs_exit(v);
> + return -EINVAL;
> + }
> + vmx_write_guest_msr(MSR_SHADOW_GS_BASE, ctxtp->gs_base_kernel);
So you write both GS bases, but not the base of FS (and above
its selector is being skipped too)?
And there are other parts of struct vcpu_guest_context that
I don't see getting mirrored - are all of them getting handled
elsewhere?
Jan
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |