x86: allow control domain to limit machine addresses given to a particular guest
authorKeir Fraser <keir.fraser@citrix.com>
Fri, 11 Jul 2008 11:51:26 +0000 (12:51 +0100)
committerKeir Fraser <keir.fraser@citrix.com>
Fri, 11 Jul 2008 11:51:26 +0000 (12:51 +0100)
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>
tools/libxc/xc_domain.c
tools/libxc/xenctrl.h
tools/python/xen/lowlevel/xc/xc.c
tools/python/xen/xend/XendConfig.py
tools/python/xen/xend/XendDomainInfo.py
tools/python/xen/xm/create.py
xen/arch/x86/domctl.c
xen/arch/x86/x86_64/mm.c
xen/include/public/domctl.h
xen/include/xsm/xsm.h
xen/xsm/dummy.c

index 3b08922067003d2541150605b1a1f4f75437cb4f..551d8d1ada2ec53337723d2795270c9bbc088ebe 100644 (file)
@@ -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
index b70c3b81930801962a6a070b32fbf53a2d97b9b7..69d58950d53b7e51c9f7ba71515a1086d5667833 100644 (file)
@@ -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,
index 932525507f2264dc0150598832a160a4f3d40c0f..d45aa85dc79dc0128f924c30ac32329bff5014c7 100644 (file)
@@ -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 }
index 0df4c04658e1917feb8c0256657921a5da87d4b8..484621970dc10c0f2c7851cc6e473b1d5d76e56d 100644 (file)
@@ -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
index 719719ff6417d6382e68d1bf9815bd716d51d705..7572383479ccad8e177f7cdbce8c6681ec0904e1 100644 (file)
@@ -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()
index 60b350e3102279c8d78ee27f44e3449f17ac9e4f..cef72c63f3f0213f670d4486116da0ecaa989719 100644 (file)
@@ -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])
index 7b758fe868b0a2b9dcfdf30ed62b338443f31ec6..52add55afa9cb5d139d02733e7a1fa1ab1385d77 100644 (file)
@@ -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;
index febca9f45518ece443da5262bbe2cea6d73f22b9..9ca3007bfca1789724ea667d28d571476df7c148 100644 (file)
@@ -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 */
index d26ac75d5895230d0162035c72d72fc507af1bcf..090681722a242ee98a0b65ef387360969cdae4f9 100644 (file)
@@ -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 */
index 6debf6070c47c0ab20ab68e4b1228df56bc9c2fd..3b495cc052f255878a7e6d6d5be965711125c193 100644 (file)
@@ -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));
index 8379b69c5064979612b5da7ae271690ff58f43cb..fbf19f3943a55d2587c20a88a527e4ce72f49774 100644 (file)
@@ -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);