# HG changeset patch
# User Hollis Blanchard <hollisb@xxxxxxxxxx>
# Node ID a906930d3c20d0145f86ac34c96534899c481cda
# Parent 04cc593ae49eff5e5de1fcf4225ef8018e987a0c
[POWERPC] have tools explicitly allocate domU real mode areas
- don't allocate RMA in arch_domain_create()
- create new DOM0_ALLOC_REAL_MODE_AREA dom0_op
- expose dom0 op through libxc and python bindings
- move Xend memory allocation code into new allocMem() method
- subclass XendDomainInfo to supply a PowerPC allocMem(), which understands
about RMAs and calls the new dom0 op
- don't try to free_domheap_pages(NULL) (happened when destroying a domain
after creation error)
- make allocate_rma() free previously allocated RMAs
- set domain->shared_info in allocate_rma()
- add CPU-specific cpu_rma_valid() accessor to make sure Xend chose a good size
- allocate dom0's RMA in __start_xen()
Signed-off-by: Hollis Blanchard <hollisb@xxxxxxxxxx>
---
tools/libxc/powerpc64/Makefile | 2
tools/libxc/powerpc64/xc_memory.c | 43 +++++++++++
tools/libxc/xenctrl.h | 4 +
tools/python/xen/lowlevel/xc/xc.c | 28 +++++++
tools/python/xen/xend/XendDomainInfo.py | 121 +++++++++++++++++++++++++-------
xen/arch/powerpc/dom0_ops.c | 16 ++++
xen/arch/powerpc/domain.c | 22 -----
xen/arch/powerpc/domain_build.c | 3
xen/arch/powerpc/mm.c | 34 ++++++--
xen/arch/powerpc/powerpc64/ppc970.c | 5 +
xen/arch/powerpc/setup.c | 7 +
xen/include/asm-powerpc/processor.h | 1
xen/include/public/dom0_ops.h | 9 ++
13 files changed, 235 insertions(+), 60 deletions(-)
diff -r 04cc593ae49e -r a906930d3c20 tools/libxc/powerpc64/Makefile
--- a/tools/libxc/powerpc64/Makefile Mon Aug 28 18:29:39 2006 -0400
+++ b/tools/libxc/powerpc64/Makefile Mon Aug 28 18:13:38 2006 -0500
@@ -1,2 +1,4 @@ GUEST_SRCS-y += powerpc64/xc_linux_build
GUEST_SRCS-y += powerpc64/xc_linux_build.c
GUEST_SRCS-y += powerpc64/ft_build.c
+
+CTRL_SRCS-y += powerpc64/xc_memory.c
diff -r 04cc593ae49e -r a906930d3c20 tools/libxc/xenctrl.h
--- a/tools/libxc/xenctrl.h Mon Aug 28 18:29:39 2006 -0400
+++ b/tools/libxc/xenctrl.h Mon Aug 28 18:13:38 2006 -0500
@@ -434,6 +434,10 @@ int xc_domain_memory_populate_physmap(in
unsigned int address_bits,
xen_pfn_t *extent_start);
+int xc_alloc_real_mode_area(int xc_handle,
+ uint32_t domid,
+ unsigned int log);
+
int xc_domain_translate_gpfn_list(int xc_handle,
uint32_t domid,
unsigned long nr_gpfns,
diff -r 04cc593ae49e -r a906930d3c20 tools/python/xen/lowlevel/xc/xc.c
--- a/tools/python/xen/lowlevel/xc/xc.c Mon Aug 28 18:29:39 2006 -0400
+++ b/tools/python/xen/lowlevel/xc/xc.c Mon Aug 28 18:13:38 2006 -0500
@@ -810,6 +810,26 @@ static PyObject *pyxc_domain_memory_incr
return zero;
}
+static PyObject *pyxc_alloc_real_mode_area(XcObject *self,
+ PyObject *args,
+ PyObject *kwds)
+{
+ uint32_t dom;
+ unsigned int log;
+
+ static char *kwd_list[] = { "dom", "log", NULL };
+
+ if ( !PyArg_ParseTupleAndKeywords(args, kwds, "ii", kwd_list,
+ &dom, &log) )
+ return NULL;
+
+ if ( xc_alloc_real_mode_area(self->xc_handle, dom, log) )
+ return PyErr_SetFromErrno(xc_error);
+
+ Py_INCREF(zero);
+ return zero;
+}
+
static PyObject *pyxc_domain_ioport_permission(XcObject *self,
PyObject *args,
PyObject *kwds)
@@ -1205,6 +1225,14 @@ static PyMethodDef pyxc_methods[] = {
"Increase a domain's memory reservation\n"
" dom [int]: Identifier of domain.\n"
" mem_kb [long]: .\n"
+ "Returns: [int] 0 on success; -1 on error.\n" },
+
+ { "alloc_real_mode_area",
+ (PyCFunction)pyxc_alloc_real_mode_area,
+ METH_VARARGS | METH_KEYWORDS, "\n"
+ "Allocate a domain's real mode area.\n"
+ " dom [int]: Identifier of domain.\n"
+ " log [int]: Specifies the area's size.\n"
"Returns: [int] 0 on success; -1 on error.\n" },
{ "domain_ioport_permission",
diff -r 04cc593ae49e -r a906930d3c20 tools/python/xen/xend/XendDomainInfo.py
--- a/tools/python/xen/xend/XendDomainInfo.py Mon Aug 28 18:29:39 2006 -0400
+++ b/tools/python/xen/xend/XendDomainInfo.py Mon Aug 28 18:13:38 2006 -0500
@@ -35,6 +35,7 @@ from xen.util import asserts
from xen.util import asserts
from xen.util.blkif import blkdev_uname_to_file
from xen.util import security
+import arch
import balloon
import image
import sxp
@@ -187,7 +188,7 @@ def create(config):
log.debug("XendDomainInfo.create(%s)", config)
- vm = XendDomainInfo(parseConfig(config))
+ vm = findDomainClass()(parseConfig(config))
try:
vm.construct()
vm.initDomain()
@@ -237,13 +238,13 @@ def recreate(xeninfo, priv):
'Uuid in store does not match uuid for existing domain %d: '
'%s != %s' % (domid, uuid2_str, xeninfo['uuid']))
- vm = XendDomainInfo(xeninfo, domid, dompath, True, priv)
+ vm = findDomainClass()(xeninfo, domid, dompath, True, priv)
except Exception, exn:
if priv:
log.warn(str(exn))
- vm = XendDomainInfo(xeninfo, domid, dompath, True, priv)
+ vm = findDomainClass()(xeninfo, domid, dompath, True, priv)
vm.recreateDom()
vm.removeVm()
vm.storeVmDetails()
@@ -262,7 +263,7 @@ def restore(config):
log.debug("XendDomainInfo.restore(%s)", config)
- vm = XendDomainInfo(parseConfig(config), None, None, False, False, True)
+ vm = findDomainClass()(parseConfig(config), None, None, False, False, True)
try:
vm.construct()
vm.storeVmDetails()
@@ -1266,6 +1267,9 @@ class XendDomainInfo:
self.info['image'],
self.info['device'])
+
+ self.allocMem()
+
localtime = self.info['localtime']
if localtime is not None and localtime == 1:
xc.domain_set_time_offset(self.domid)
@@ -1279,28 +1283,6 @@ class XendDomainInfo:
for v in range(0, self.info['max_vcpu_id']+1):
xc.vcpu_setaffinity(self.domid, v, self.info['cpus'])
- # set memory limit
- maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
- xc.domain_setmaxmem(self.domid, maxmem)
-
- mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
-
- # get the domain's shadow memory requirement
- shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
- shadow_kb_req = self.info['shadow_memory'] * 1024
- if shadow_kb_req > shadow_kb:
- shadow_kb = shadow_kb_req
-
- # Make sure there's enough RAM available for the domain
- balloon.free(mem_kb + shadow_kb)
-
- # Set up the shadow memory
- shadow_cur = xc.shadow_mem_control(self.domid, shadow_kb / 1024)
- self.info['shadow_memory'] = shadow_cur
-
- # initial memory allocation
- xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
-
self.createChannels()
channel_details = self.image.createImage()
@@ -1321,6 +1303,28 @@ class XendDomainInfo:
except RuntimeError, exn:
raise VmError(str(exn))
+ def allocMem(self):
+ # set memory limit
+ maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
+ xc.domain_setmaxmem(self.domid, maxmem)
+
+ mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
+
+ # get the domain's shadow memory requirement
+ shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
+ shadow_kb_req = self.info['shadow_memory'] * 1024
+ if shadow_kb_req > shadow_kb:
+ shadow_kb = shadow_kb_req
+
+ # Make sure there's enough RAM available for the domain
+ balloon.free(mem_kb + shadow_kb)
+
+ # Set up the shadow memory
+ shadow_cur = xc.shadow_mem_control(self.domid, shadow_kb / 1024)
+ self.info['shadow_memory'] = shadow_cur
+
+ # initial memory allocation
+ xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
## public:
@@ -1694,6 +1698,71 @@ class XendDomainInfo:
def infoIsSet(self, name):
return name in self.info and self.info[name] is not None
+class XendDomainInfoPPC(XendDomainInfo):
+ _rmaLogs = {
+ "970": (26, 27, 28, 30, 34, 38),
+ }
+
+ def getRealModeLogs(self):
+ """Returns a list of RMA sizes this processor supports."""
+ cputype = "970" # XXX extract from cpuinfo or device tree
+ return self._rmaLogs[cputype]
+
+ def allocMem(self):
+ try:
+ # set memory limit
+ maxmem = self.image.getRequiredMemory(self.info['maxmem'] * 1024)
+ xc.domain_setmaxmem(self.domid, maxmem)
+
+ mem_kb = self.image.getRequiredMemory(self.info['memory'] * 1024)
+
+ # get the domain's shadow memory requirement
+ shadow_kb = self.image.getRequiredShadowMemory(mem_kb)
+ shadow_kb_req = self.info['shadow_memory'] * 1024
+ if shadow_kb_req > shadow_kb:
+ shadow_kb = shadow_kb_req
+
+ # Make sure there's enough RAM available for the domain
+ balloon.free(mem_kb + shadow_kb)
+
+ # Set up the shadow memory, i.e. the PowerPC hash table
+ shadow_cur = xc.shadow_mem_control(self.domid, shadow_kb / 1024)
+ self.info['shadow_memory'] = shadow_cur
+
+ # use smallest RMA size available
+ rma_log = self.getRealModeLogs()[0]
+
+ rma_kb = (1 << rma_log) / 1024
+ if mem_kb < rma_kb:
+ raise ValueError("Domain memory must be at least %d KB" % \
+ rma_kb)
+
+ # allocate the RMA
+ xc.alloc_real_mode_area(self.domid, rma_log)
+
+ # now allocate the remaining memory as order-0 allocations
+ mem_kb -= rma_kb
+ if mem_kb > 0:
+ log.debug("increase_reservation(%d, %d, %d)", self.domid,
+ mem_kb, 0)
+ xc.domain_memory_increase_reservation(self.domid, mem_kb, 0, 0)
+
+ except RuntimeError, exn:
+ raise VmError(str(exn))
+
+
+domainTypes = {
+ "ia64": XendDomainInfo,
+ "powerpc": XendDomainInfoPPC,
+ "x86": XendDomainInfo,
+}
+
+def findDomainClass():
+ type = arch.type
+ try:
+ return domainTypes[type]
+ except KeyError:
+ raise VmError("Unsupported architecture: " + type)
#============================================================================
# Register device controllers and their device config types.
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/dom0_ops.c
--- a/xen/arch/powerpc/dom0_ops.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/dom0_ops.c Mon Aug 28 18:13:38 2006 -0500
@@ -26,6 +26,7 @@
#include <xen/shadow.h>
#include <public/xen.h>
#include <public/dom0_ops.h>
+#include <asm/processor.h>
extern void arch_getdomaininfo_ctxt(struct vcpu *v, vcpu_guest_context_t *c);
extern long arch_do_dom0_op(struct dom0_op *op, XEN_GUEST_HANDLE(dom0_op_t)
u_dom0_op);
@@ -108,6 +109,21 @@ long arch_do_dom0_op(struct dom0_op *op,
}
}
break;
+ case DOM0_ALLOC_REAL_MODE_AREA:
+ {
+ struct domain *d;
+ unsigned int log = op->u.alloc_real_mode_area.log;
+
+ d = find_domain_by_id(op->u.alloc_real_mode_area.domain);
+ if (d == NULL)
+ return -ESRCH;
+
+ if (!cpu_rma_valid(log))
+ return -EINVAL;
+
+ return allocate_rma(d, log - PAGE_SHIFT);
+ }
+ break;
default:
printk("%s: unsupported op: 0x%x\n", __func__, (op->cmd));
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/domain.c
--- a/xen/arch/powerpc/domain.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/domain.c Mon Aug 28 18:13:38 2006 -0500
@@ -75,31 +75,12 @@ unsigned long hypercall_create_continuat
int arch_domain_create(struct domain *d)
{
- unsigned long rma_base;
- unsigned long rma_sz;
- uint rma_order_pages;
- int rc;
-
if (d->domain_id == IDLE_DOMAIN_ID) {
d->shared_info = (void *)alloc_xenheap_page();
clear_page(d->shared_info);
return 0;
}
-
- /* allocate the real mode area */
- rma_order_pages = cpu_default_rma_order_pages();
- d->max_pages = 1UL << rma_order_pages;
- d->tot_pages = 0;
-
- rc = allocate_rma(d, rma_order_pages);
- if (rc)
- return rc;
- rma_base = page_to_maddr(d->arch.rma_page);
- rma_sz = rma_size(rma_order_pages);
-
- d->shared_info = (shared_info_t *)
- (rma_addr(&d->arch, RMA_SHARED_INFO) + rma_base);
d->arch.large_page_sizes = cpu_large_page_orders(
d->arch.large_page_order, ARRAY_SIZE(d->arch.large_page_order));
@@ -264,7 +245,8 @@ void sync_vcpu_execstate(struct vcpu *v)
void domain_relinquish_resources(struct domain *d)
{
- free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
+ if (d->arch.rma_page)
+ free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
free_extents(d);
}
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/domain_build.c
--- a/xen/arch/powerpc/domain_build.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/domain_build.c Mon Aug 28 18:13:38 2006 -0500
@@ -154,9 +154,6 @@ int construct_dom0(struct domain *d,
return -EINVAL;
}
printk("*** LOADING DOMAIN 0 ***\n");
-
- /* By default DOM0 is allocated all available memory. */
- d->max_pages = ~0U;
/* default is the max(1/16th of memory, CONFIG_MIN_DOM0_PAGES) */
if (dom0_nrpages == 0) {
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/mm.c
--- a/xen/arch/powerpc/mm.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/mm.c Mon Aug 28 18:13:38 2006 -0500
@@ -301,26 +301,40 @@ uint allocate_extents(struct domain *d,
return total_nrpages;
}
-
-int allocate_rma(struct domain *d, unsigned int order_pages)
-{
+
+int allocate_rma(struct domain *d, unsigned int order)
+{
+ struct vcpu *v;
ulong rma_base;
- ulong rma_sz = rma_size(order_pages);
-
- d->arch.rma_page = alloc_domheap_pages(d, order_pages, 0);
+ ulong rma_sz;
+
+ if (d->arch.rma_page)
+ free_domheap_pages(d->arch.rma_page, d->arch.rma_order);
+
+ d->arch.rma_page = alloc_domheap_pages(d, order, 0);
if (d->arch.rma_page == NULL) {
- DPRINTK("Could not allocate order_pages=%d RMA for domain %u\n",
- order_pages, d->domain_id);
+ DPRINTK("Could not allocate order=%d RMA for domain %u\n",
+ order, d->domain_id);
return -ENOMEM;
}
- d->arch.rma_order = order_pages;
+ d->arch.rma_order = order;
rma_base = page_to_maddr(d->arch.rma_page);
+ rma_sz = rma_size(d->arch.rma_order);
BUG_ON(rma_base & (rma_sz - 1)); /* check alignment */
- /* XXX */
+ /* XXX shouldn't be needed */
printk("clearing RMA: 0x%lx[0x%lx]\n", rma_base, rma_sz);
memset((void *)rma_base, 0, rma_sz);
+
+ d->shared_info = (shared_info_t *)
+ (rma_addr(&d->arch, RMA_SHARED_INFO) + rma_base);
+
+ /* if there are already running vcpus, adjust v->vcpu_info */
+ /* XXX untested */
+ for_each_vcpu(d, v) {
+ v->vcpu_info = &d->shared_info->vcpu_info[v->vcpu_id];
+ }
return 0;
}
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/powerpc64/ppc970.c
--- a/xen/arch/powerpc/powerpc64/ppc970.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/powerpc64/ppc970.c Mon Aug 28 18:13:38 2006 -0500
@@ -66,6 +66,11 @@ unsigned int cpu_default_rma_order_pages
unsigned int cpu_default_rma_order_pages(void)
{
return rma_orders[0].order - PAGE_SHIFT;
+}
+
+int cpu_rma_valid(unsigned int log)
+{
+ return cpu_find_rma(log) != NULL;
}
unsigned int cpu_large_page_orders(uint *sizes, uint max)
diff -r 04cc593ae49e -r a906930d3c20 xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/arch/powerpc/setup.c Mon Aug 28 18:13:38 2006 -0500
@@ -349,8 +349,13 @@ static void __init __start_xen(multiboot
/* Create initial domain 0. */
dom0 = domain_create(0);
- if ((dom0 == NULL) || (alloc_vcpu(dom0, 0, 0) == NULL))
+ if (dom0 == NULL)
panic("Error creating domain 0\n");
+ dom0->max_pages = ~0U;
+ if (0 > allocate_rma(dom0, cpu_default_rma_order_pages()))
+ panic("Error allocating domain 0 RMA\n");
+ if (NULL == alloc_vcpu(dom0, 0, 0))
+ panic("Error creating domain 0 vcpu 0\n");
set_bit(_DOMF_privileged, &dom0->domain_flags);
/* post-create hooks sets security label */
diff -r 04cc593ae49e -r a906930d3c20 xen/include/asm-powerpc/processor.h
--- a/xen/include/asm-powerpc/processor.h Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/include/asm-powerpc/processor.h Mon Aug 28 18:13:38 2006 -0500
@@ -42,6 +42,7 @@ extern void show_backtrace(ulong sp, ulo
extern void show_backtrace(ulong sp, ulong lr, ulong pc);
extern unsigned int cpu_extent_order(void);
extern unsigned int cpu_default_rma_order_pages(void);
+extern int cpu_rma_valid(unsigned int log);
extern uint cpu_large_page_orders(uint *sizes, uint max);
extern void cpu_initialize(int cpuid);
extern void cpu_init_vcpu(struct vcpu *);
diff -r 04cc593ae49e -r a906930d3c20 xen/include/public/dom0_ops.h
--- a/xen/include/public/dom0_ops.h Mon Aug 28 18:29:39 2006 -0400
+++ b/xen/include/public/dom0_ops.h Mon Aug 28 18:13:38 2006 -0500
@@ -556,6 +556,14 @@ struct dom0_settimeoffset {
};
typedef struct dom0_settimeoffset dom0_settimeoffset_t;
DEFINE_XEN_GUEST_HANDLE(dom0_settimeoffset_t);
+
+#define DOM0_ALLOC_REAL_MODE_AREA 51
+struct dom0_alloc_real_mode_area {
+ domid_t domain;
+ uint32_t log;
+};
+typedef struct dom0_alloc_real_mode_area dom0_alloc_real_mode_area_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_alloc_real_mode_area_t);
struct dom0_op {
uint32_t cmd;
@@ -600,6 +608,7 @@ struct dom0_op {
struct dom0_hypercall_init hypercall_init;
struct dom0_domain_setup domain_setup;
struct dom0_settimeoffset settimeoffset;
+ struct dom0_alloc_real_mode_area alloc_real_mode_area;
uint8_t pad[128];
} u;
};
diff -r 04cc593ae49e -r a906930d3c20 tools/libxc/powerpc64/xc_memory.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/libxc/powerpc64/xc_memory.c Mon Aug 28 18:13:38 2006 -0500
@@ -0,0 +1,43 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Copyright (C) IBM Corporation 2006
+ *
+ * Authors: Hollis Blanchard <hollisb@xxxxxxxxxx>
+ */
+
+#include "xc_private.h"
+#include <xen/dom0_ops.h>
+#include <xen/memory.h>
+
+int xc_alloc_real_mode_area(int xc_handle,
+ uint32_t domain,
+ unsigned int log)
+{
+ DECLARE_DOM0_OP;
+ int err;
+
+ op.cmd = DOM0_ALLOC_REAL_MODE_AREA;
+ op.u.alloc_real_mode_area.domain = domain;
+ op.u.alloc_real_mode_area.log = log;
+
+ err = do_dom0_op(xc_handle, &op);
+
+ if (err > 0)
+ DPRINTF("Failed real mode area allocation for dom %u (log %u)\n",
+ domain, log);
+
+ return err;
+}
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|