mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
x86: allow control domain to limit machine addresses given to a particular guest
This allows domains which make buggy assumptions about the maximum possible MFN to be worked around. Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
This commit is contained in:
1 parent
04e28c8d4f
commit
41296317a3
11 files changed
+140
-2
No files matched your search
@@ -993,6 +993,35 @@ int xc_domain_subscribe_for_suspend(
|
||||
return do_domctl(xc_handle, &domctl);
|
||||
}
|
||||
|
||||
int xc_domain_set_machine_address_size(int xc,
|
||||
uint32_t domid,
|
||||
unsigned int width)
|
||||
{
|
||||
DECLARE_DOMCTL;
|
||||
|
||||
memset(&domctl, 0, sizeof(domctl));
|
||||
domctl.domain = domid;
|
||||
domctl.cmd = XEN_DOMCTL_set_machine_address_size;
|
||||
domctl.u.address_size.size = width;
|
||||
|
||||
return do_domctl(xc, &domctl);
|
||||
}
|
||||
|
||||
|
||||
int xc_domain_get_machine_address_size(int xc, uint32_t domid)
|
||||
{
|
||||
DECLARE_DOMCTL;
|
||||
int rc;
|
||||
|
||||
memset(&domctl, 0, sizeof(domctl));
|
||||
domctl.domain = domid;
|
||||
domctl.cmd = XEN_DOMCTL_get_machine_address_size;
|
||||
|
||||
rc = do_domctl(xc, &domctl);
|
||||
|
||||
return rc == 0 ? domctl.u.address_size.size : rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -1076,6 +1076,12 @@ int xc_domain_bind_pt_isa_irq(int xc_handle,
|
||||
uint32_t domid,
|
||||
uint8_t machine_irq);
|
||||
|
||||
int xc_domain_set_machine_address_size(int handle,
|
||||
uint32_t domid,
|
||||
unsigned int width);
|
||||
int xc_domain_get_machine_address_size(int handle,
|
||||
uint32_t domid);
|
||||
|
||||
/* Set the target domain */
|
||||
int xc_domain_set_target(int xc_handle,
|
||||
uint32_t domid,
|
||||
|
||||
@@ -843,6 +843,22 @@ static PyObject *pyxc_dom_set_cpuid(XcObject *self,
|
||||
return pyxc_create_cpuid_dict(regs_transform);
|
||||
}
|
||||
|
||||
static PyObject *pyxc_dom_set_machine_address_size(XcObject *self,
|
||||
PyObject *args,
|
||||
PyObject *kwds)
|
||||
{
|
||||
uint32_t dom, width;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ii", &dom, &width))
|
||||
return NULL;
|
||||
|
||||
if (xc_domain_set_machine_address_size(self->xc_handle, dom, width) != 0)
|
||||
return pyxc_error_to_exception();
|
||||
|
||||
Py_INCREF(zero);
|
||||
return zero;
|
||||
}
|
||||
|
||||
#endif /* __i386__ || __x86_64__ */
|
||||
|
||||
static PyObject *pyxc_hvm_build(XcObject *self,
|
||||
@@ -1889,6 +1905,13 @@ static PyMethodDef pyxc_methods[] = {
|
||||
"Set the default cpuid policy for a domain.\n"
|
||||
" dom [int]: Identifier of domain.\n\n"
|
||||
"Returns: [int] 0 on success; exception on error.\n" },
|
||||
|
||||
{ "domain_set_machine_address_size",
|
||||
(PyCFunction)pyxc_dom_set_machine_address_size,
|
||||
METH_VARARGS, "\n"
|
||||
"Set maximum machine address size for this domain.\n"
|
||||
" dom [int]: Identifier of domain.\n"
|
||||
" width [int]: Maximum machine address width.\n" },
|
||||
#endif
|
||||
|
||||
{ NULL, NULL, 0, NULL }
|
||||
|
||||
@@ -207,6 +207,7 @@ XENAPI_CFG_TYPES = {
|
||||
'pci': str,
|
||||
'cpuid' : dict,
|
||||
'cpuid_check' : dict,
|
||||
'machine_address_size': int,
|
||||
}
|
||||
|
||||
# List of legacy configuration keys that have no equivalent in the
|
||||
|
||||
@@ -2223,6 +2223,11 @@ class XendDomainInfo:
|
||||
shadow_cur = xc.shadow_mem_control(self.domid, shadow / 1024)
|
||||
self.info['shadow_memory'] = shadow_cur
|
||||
|
||||
# machine address size
|
||||
if self.info.has_key('machine_address_size'):
|
||||
log.debug("_initDomain: setting maximum machine address size %d" % self.info['machine_address_size'])
|
||||
xc.domain_set_machine_address_size(self.domid, self.info['machine_address_size'])
|
||||
|
||||
self._createChannels()
|
||||
|
||||
channel_details = self.image.createImage()
|
||||
|
||||
@@ -563,6 +563,10 @@ gopts.var('cpuid_check', val="IN[,SIN]:eax=EAX,ebx=EBX,exc=ECX,edx=EDX",
|
||||
fn=append_value, default=[],
|
||||
use="""Cpuid check description.""")
|
||||
|
||||
gopts.var('machine_address_size', val='BITS',
|
||||
fn=set_int, default=None,
|
||||
use="""Maximum machine address size""")
|
||||
|
||||
def err(msg):
|
||||
"""Print an error to stderr and exit.
|
||||
"""
|
||||
@@ -611,6 +615,9 @@ def configure_image(vals):
|
||||
if vals.vhpt != 0:
|
||||
config_image.append(['vhpt', vals.vhpt])
|
||||
|
||||
if vals.machine_address_size:
|
||||
config_image.append(['machine_address_size', vals.machine_address_size])
|
||||
|
||||
return config_image
|
||||
|
||||
def configure_disks(config_devs, vals):
|
||||
@@ -863,7 +870,7 @@ def make_config(vals):
|
||||
'restart', 'on_poweroff',
|
||||
'on_reboot', 'on_crash', 'vcpus', 'vcpu_avail', 'features',
|
||||
'on_xend_start', 'on_xend_stop', 'target', 'cpuid',
|
||||
'cpuid_check'])
|
||||
'cpuid_check', 'machine_address_size'])
|
||||
|
||||
if vals.uuid is not None:
|
||||
config.append(['uuid', vals.uuid])
|
||||
|
||||
@@ -490,6 +490,57 @@ long arch_do_domctl(
|
||||
}
|
||||
break;
|
||||
|
||||
case XEN_DOMCTL_set_machine_address_size:
|
||||
{
|
||||
struct domain *d;
|
||||
|
||||
ret = -ESRCH;
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_machine_address_size(d, domctl->cmd);
|
||||
if ( ret )
|
||||
rcu_unlock_domain(d);
|
||||
|
||||
ret = -EBUSY;
|
||||
if ( d->tot_pages > 0 )
|
||||
goto set_machine_address_size_out;
|
||||
|
||||
d->arch.physaddr_bitsize = domctl->u.address_size.size;
|
||||
|
||||
ret = 0;
|
||||
set_machine_address_size_out:
|
||||
rcu_unlock_domain(d);
|
||||
}
|
||||
break;
|
||||
|
||||
case XEN_DOMCTL_get_machine_address_size:
|
||||
{
|
||||
struct domain *d;
|
||||
|
||||
ret = -ESRCH;
|
||||
if ( (d = rcu_lock_domain_by_id(domctl->domain)) == NULL )
|
||||
break;
|
||||
|
||||
ret = xsm_machine_address_size(d, domctl->cmd);
|
||||
if ( ret )
|
||||
{
|
||||
rcu_unlock_domain(d);
|
||||
break;
|
||||
}
|
||||
|
||||
domctl->u.address_size.size = d->arch.physaddr_bitsize;
|
||||
|
||||
ret = 0;
|
||||
rcu_unlock_domain(d);
|
||||
|
||||
if ( copy_to_guest(u_domctl, domctl, 1) )
|
||||
ret = -EFAULT;
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case XEN_DOMCTL_sendtrigger:
|
||||
{
|
||||
struct domain *d;
|
||||
|
||||
@@ -475,7 +475,8 @@ int check_descriptor(const struct domain *dom, struct desc_struct *d)
|
||||
void domain_set_alloc_bitsize(struct domain *d)
|
||||
{
|
||||
if ( !is_pv_32on64_domain(d) ||
|
||||
(MACH2PHYS_COMPAT_NR_ENTRIES(d) >= max_page) )
|
||||
(MACH2PHYS_COMPAT_NR_ENTRIES(d) >= max_page) ||
|
||||
d->arch.physaddr_bitsize > 0 )
|
||||
return;
|
||||
d->arch.physaddr_bitsize =
|
||||
/* 2^n entries can be contained in guest's p2m mapping space */
|
||||
|
||||
@@ -607,6 +607,14 @@ struct xen_domctl_subscribe {
|
||||
typedef struct xen_domctl_subscribe xen_domctl_subscribe_t;
|
||||
DEFINE_XEN_GUEST_HANDLE(xen_domctl_subscribe_t);
|
||||
|
||||
/*
|
||||
* Define the maximum machine address size which should be allocated
|
||||
* to a guest.
|
||||
*/
|
||||
#define XEN_DOMCTL_set_machine_address_size 51
|
||||
#define XEN_DOMCTL_get_machine_address_size 52
|
||||
|
||||
|
||||
struct xen_domctl {
|
||||
uint32_t cmd;
|
||||
uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
|
||||
|
||||
@@ -119,6 +119,7 @@ struct xsm_operations {
|
||||
int (*hypercall_init) (struct domain *d);
|
||||
int (*hvmcontext) (struct domain *d, uint32_t op);
|
||||
int (*address_size) (struct domain *d, uint32_t op);
|
||||
int (*machine_address_size) (struct domain *d, uint32_t op);
|
||||
int (*hvm_param) (struct domain *d, unsigned long op);
|
||||
int (*hvm_set_pci_intx_level) (struct domain *d);
|
||||
int (*hvm_set_isa_irq_level) (struct domain *d);
|
||||
@@ -448,6 +449,11 @@ static inline int xsm_address_size (struct domain *d, uint32_t cmd)
|
||||
return xsm_call(address_size(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_machine_address_size (struct domain *d, uint32_t cmd)
|
||||
{
|
||||
return xsm_call(machine_address_size(d, cmd));
|
||||
}
|
||||
|
||||
static inline int xsm_hvm_param (struct domain *d, unsigned long op)
|
||||
{
|
||||
return xsm_call(hvm_param(d, op));
|
||||
|
||||
@@ -467,6 +467,7 @@ void xsm_fixup_ops (struct xsm_operations *ops)
|
||||
set_to_dummy_if_null(ops, hypercall_init);
|
||||
set_to_dummy_if_null(ops, hvmcontext);
|
||||
set_to_dummy_if_null(ops, address_size);
|
||||
set_to_dummy_if_null(ops, machine_address_size);
|
||||
set_to_dummy_if_null(ops, hvm_param);
|
||||
set_to_dummy_if_null(ops, hvm_set_pci_intx_level);
|
||||
set_to_dummy_if_null(ops, hvm_set_isa_irq_level);
|
||||
|
||||