/*
* arch/arm/hvm.c
*
* Arch-specific hardware virtual machine abstractions.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope 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.
*
* You should have received a copy of the GNU General Public License along with
* this program; If not, see .
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int hvm_allow_set_param(const struct domain *d, unsigned int param)
{
switch ( param )
{
/*
* The following parameters are intended for toolstack usage only.
* They may not be set by the domain.
*
* The {STORE,CONSOLE}_EVTCHN values will need to become read/write to
* the guest (not just the toolstack) if a new ABI hasn't appeared by
* the time migration support is added.
*/
case HVM_PARAM_CALLBACK_IRQ:
case HVM_PARAM_STORE_PFN:
case HVM_PARAM_STORE_EVTCHN:
case HVM_PARAM_CONSOLE_PFN:
case HVM_PARAM_CONSOLE_EVTCHN:
case HVM_PARAM_MONITOR_RING_PFN:
return d == current->domain ? -EPERM : 0;
/* Writeable only by Xen, hole, deprecated, or out-of-range. */
default:
return -EINVAL;
}
}
static int hvm_allow_get_param(const struct domain *d, unsigned int param)
{
switch ( param )
{
/* The following parameters can be read by the guest and toolstack. */
case HVM_PARAM_CALLBACK_IRQ:
case HVM_PARAM_STORE_PFN:
case HVM_PARAM_STORE_EVTCHN:
case HVM_PARAM_CONSOLE_PFN:
case HVM_PARAM_CONSOLE_EVTCHN:
return 0;
/*
* The following parameters are intended for toolstack usage only.
* They may not be read by the domain.
*/
case HVM_PARAM_MONITOR_RING_PFN:
return d == current->domain ? -EPERM : 0;
/* Hole, deprecated, or out-of-range. */
default:
return -EINVAL;
}
}
long do_hvm_op(unsigned long op, XEN_GUEST_HANDLE_PARAM(void) arg)
{
long rc = 0;
switch ( op )
{
case HVMOP_set_param:
case HVMOP_get_param:
{
struct xen_hvm_param a;
struct domain *d;
if ( copy_from_guest(&a, arg, 1) )
return -EFAULT;
d = rcu_lock_domain_by_any_id(a.domid);
if ( d == NULL )
return -ESRCH;
rc = xsm_hvm_param(XSM_TARGET, d, op);
if ( rc )
goto param_fail;
if ( op == HVMOP_set_param )
{
rc = hvm_allow_set_param(d, a.index);
if ( rc )
goto param_fail;
d->arch.hvm.params[a.index] = a.value;
}
else
{
rc = hvm_allow_get_param(d, a.index);
if ( rc )
goto param_fail;
a.value = d->arch.hvm.params[a.index];
rc = copy_to_guest(arg, &a, 1) ? -EFAULT : 0;
}
param_fail:
rcu_unlock_domain(d);
break;
}
case HVMOP_guest_request_vm_event:
if ( guest_handle_is_null(arg) )
monitor_guest_request();
else
rc = -EINVAL;
break;
default:
{
gdprintk(XENLOG_DEBUG, "HVMOP op=%lu: not implemented\n", op);
rc = -ENOSYS;
break;
}
}
return rc;
}
/*
* Local variables:
* mode: C
* c-file-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/