[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 11/20] PVH xen: introduce pvh.c



>>> On 15.05.13 at 02:52, Mukesh Rathor <mukesh.rathor@xxxxxxxxxx> wrote:
> --- /dev/null
> +++ b/xen/arch/x86/hvm/pvh.c
> @@ -0,0 +1,202 @@
> +/*
> + * 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>
> +
> +
> +static int pvh_grant_table_op(unsigned int cmd, XEN_GUEST_HANDLE(void) uop,
> +                              unsigned int count)
> +{
> +#ifndef NDEBUG

The whole function should be in such a conditional (if it's really
needed, which I previously said I doubt). Without doing so, and
with the way you have pvh_hypercall64_table[], build will fail
for debug=n.

> +    switch ( cmd )
> +    {
> +    /* the following grant ops have been tested for PVH guest. */
> +    case GNTTABOP_map_grant_ref:
> +    case GNTTABOP_unmap_grant_ref:
> +    case GNTTABOP_setup_table:
> +    case GNTTABOP_copy:
> +    case GNTTABOP_query_size:
> +    case GNTTABOP_set_version:
> +        return do_grant_table_op(cmd, uop, count);
> +    }
> +    return -ENOSYS;
> +#else
> +    return do_grant_table_op(cmd, uop, count);
> +#endif
> +}
> +
> +static long pvh_vcpu_op(int cmd, int vcpuid, XEN_GUEST_HANDLE(void) arg)
> +{
> +    long rc = -ENOSYS;
> +
> +#ifndef NDEBUG
> +    int valid = 0;
> +
> +    switch ( cmd )
> +    {
> +    case VCPUOP_register_runstate_memory_area:
> +    case VCPUOP_get_runstate_info:
> +    case VCPUOP_set_periodic_timer:
> +    case VCPUOP_stop_periodic_timer:
> +    case VCPUOP_set_singleshot_timer:
> +    case VCPUOP_stop_singleshot_timer:
> +    case VCPUOP_is_up:
> +    case VCPUOP_up:
> +    case VCPUOP_initialise:
> +        valid = 1;
> +    }
> +    if ( !valid )
> +        return rc;
> +#endif
> +
> +    rc = do_vcpu_op(cmd, vcpuid, arg);
> +
> +    /* pvh boot vcpu setting context for bringing up smp vcpu */
> +    if ( cmd == VCPUOP_initialise )
> +        vmx_vmcs_enter(current);

This is wrong in three ways - for one, you can't call a vmx function
from here, then the operation also doesn't appear to belong here,
and with pvh_hypercall64_table[] not even existing in non-debug
builds this won't happen there at all (which is making very clear that
these function overrides are plain wrong, as I had tried to tell you
from the beginning).

> +    return rc;
> +}
> +
> +static long pvh_physdev_op(int cmd, XEN_GUEST_HANDLE(void) arg)
> +{
> +#ifndef NDEBUG

Same as for grant table op above.

> +    int valid = 0;
> +    switch ( cmd )
> +    {
> +     case PHYSDEVOP_map_pirq:
> +     case PHYSDEVOP_unmap_pirq:
> +     case PHYSDEVOP_eoi:
> +     case PHYSDEVOP_irq_status_query:
> +     case PHYSDEVOP_get_free_pirq:
> +         valid = 1;
> +     }
> +     if ( !valid && !IS_PRIV(current->domain) )
> +        return -ENOSYS;
> +#endif
> +    return do_physdev_op(cmd, arg);
> +}
> +
> +static long pvh_hvm_op(unsigned long op, XEN_GUEST_HANDLE(void) arg)
> +{
> +    long rc = -EINVAL;
> +    struct xen_hvm_param harg;
> +    struct domain *d;
> +
> +    if ( copy_from_guest(&harg, arg, 1) )
> +        return -EFAULT;
> +
> +    rc = rcu_lock_target_domain_by_id(harg.domid, &d);
> +    if ( rc != 0 )
> +        return rc;
> +
> +    if ( is_hvm_domain(d) )
> +    {
> +        /* pvh dom0 is building an hvm guest */
> +        rcu_unlock_domain(d);
> +        return do_hvm_op(op, arg);
> +    }
> +
> +    rc = -ENOSYS;
> +    if ( op == HVMOP_set_param )
> +    {
> +        if ( harg.index == HVM_PARAM_CALLBACK_IRQ )
> +        {
> +            struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq;
> +            uint64_t via = harg.value;
> +            uint8_t via_type = (uint8_t)(via >> 56) + 1;
> +
> +            if ( via_type == HVMIRQ_callback_vector )
> +            {
> +                hvm_irq->callback_via_type = HVMIRQ_callback_vector;
> +                hvm_irq->callback_via.vector = (uint8_t)via;
> +                rc = 0;
> +            }
> +        }
> +    }
> +    rcu_unlock_domain(d);
> +    if ( rc )
> +        gdprintk(XENLOG_DEBUG, "op:%ld -ENOSYS\n", op);

This should be dropped.

> +
> +    return rc;
> +}
> +
> +#ifndef NDEBUG
> +/* PVH 32bitfixme */
> +static hvm_hypercall_t *pvh_hypercall64_table[NR_hypercalls] = {
> +    [__HYPERVISOR_platform_op]     = (hvm_hypercall_t *)do_platform_op,
> +    [__HYPERVISOR_memory_op]       = (hvm_hypercall_t *)do_memory_op,
> +    [__HYPERVISOR_xen_version]     = (hvm_hypercall_t *)do_xen_version,
> +    [__HYPERVISOR_console_io]      = (hvm_hypercall_t *)do_console_io,
> +    [__HYPERVISOR_grant_table_op]  = (hvm_hypercall_t *)pvh_grant_table_op,
> +    [__HYPERVISOR_vcpu_op]         = (hvm_hypercall_t *)pvh_vcpu_op,
> +    [__HYPERVISOR_mmuext_op]       = (hvm_hypercall_t *)do_mmuext_op,
> +    [__HYPERVISOR_xsm_op]          = (hvm_hypercall_t *)do_xsm_op,
> +    [__HYPERVISOR_sched_op]        = (hvm_hypercall_t *)do_sched_op,
> +    [__HYPERVISOR_event_channel_op]= (hvm_hypercall_t *)do_event_channel_op,
> +    [__HYPERVISOR_physdev_op]      = (hvm_hypercall_t *)pvh_physdev_op,
> +    [__HYPERVISOR_hvm_op]          = (hvm_hypercall_t *)pvh_hvm_op,
> +    [__HYPERVISOR_sysctl]          = (hvm_hypercall_t *)do_sysctl,
> +    [__HYPERVISOR_domctl]          = (hvm_hypercall_t *)do_domctl
> +};
> +#endif
> +
> +/*
> + * Check if hypercall is valid
> + * Returns: 0 if hcall is not valid with eax set to the errno to ret to guest
> + */
> +static bool_t hcall_valid(struct cpu_user_regs *regs)
> +{
> +    struct segment_register sreg;
> +
> +    hvm_get_segment_register(current, x86_seg_ss, &sreg);
> +    if ( unlikely(sreg.attr.fields.dpl != 0) )
> +    {
> +        regs->eax = -EPERM;
> +        return 0;
> +    }
> +
> +    return 1;
> +}
> +
> +/* PVH 32bitfixme */
> +int pvh_do_hypercall(struct cpu_user_regs *regs)
> +{
> +    uint32_t hnum = regs->eax;
> +
> +    if ( hnum >= NR_hypercalls || pvh_hypercall64_table[hnum] == NULL )
> +    {
> +        gdprintk(XENLOG_WARNING, "PVH: Unimplemented HCALL:%d. Returning "
> +                 "-ENOSYS. domid:%d IP:%lx SP:%lx\n",
> +                 hnum, current->domain->domain_id, regs->rip, regs->rsp);
> +        regs->eax = -ENOSYS;
> +        vmx_update_guest_eip();
> +        return HVM_HCALL_completed;
> +    }
> +
> +    if ( !hcall_valid(regs) )
> +        return HVM_HCALL_completed;
> +
> +    current->arch.hvm_vcpu.hcall_preempted = 0;
> +    regs->rax = pvh_hypercall64_table[hnum](regs->rdi, regs->rsi, regs->rdx,
> +                                            regs->r10, regs->r8, regs->r9);

Another build error with debug=n?

> +
> +    if ( current->arch.hvm_vcpu.hcall_preempted )
> +        return HVM_HCALL_preempted;
> +
> +    return HVM_HCALL_completed;
> +}

Jan

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.