aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/ia64/dom0_ops.c
diff options
context:
space:
mode:
Diffstat (limited to 'xen/arch/ia64/dom0_ops.c')
-rw-r--r--xen/arch/ia64/dom0_ops.c157
1 files changed, 157 insertions, 0 deletions
diff --git a/xen/arch/ia64/dom0_ops.c b/xen/arch/ia64/dom0_ops.c
index c1b1d5c241..10bbd60957 100644
--- a/xen/arch/ia64/dom0_ops.c
+++ b/xen/arch/ia64/dom0_ops.c
@@ -27,6 +27,128 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
switch ( op->cmd )
{
+ case DOM0_GETPAGEFRAMEINFO:
+ {
+ struct pfn_info *page;
+ unsigned long pfn = op->u.getpageframeinfo.pfn;
+ domid_t dom = op->u.getpageframeinfo.domain;
+ struct domain *d;
+
+ ret = -EINVAL;
+
+ if ( unlikely(pfn >= max_page) ||
+ unlikely((d = find_domain_by_id(dom)) == NULL) )
+ break;
+
+ page = &frame_table[pfn];
+
+ if ( likely(get_page(page, d)) )
+ {
+ ret = 0;
+
+ op->u.getpageframeinfo.type = NOTAB;
+
+ if ( (page->u.inuse.type_info & PGT_count_mask) != 0 )
+ {
+ switch ( page->u.inuse.type_info & PGT_type_mask )
+ {
+ default:
+ panic("No such page type\n");
+ break;
+ }
+ }
+
+ put_page(page);
+ }
+
+ put_domain(d);
+
+ copy_to_user(u_dom0_op, op, sizeof(*op));
+ }
+ break;
+
+ case DOM0_GETPAGEFRAMEINFO2:
+ {
+#define GPF2_BATCH 128
+ int n,j;
+ int num = op->u.getpageframeinfo2.num;
+ domid_t dom = op->u.getpageframeinfo2.domain;
+ unsigned long *s_ptr = (unsigned long*) op->u.getpageframeinfo2.array;
+ struct domain *d;
+ unsigned long *l_arr;
+ ret = -ESRCH;
+
+ if ( unlikely((d = find_domain_by_id(dom)) == NULL) )
+ break;
+
+ if ( unlikely(num > 1024) )
+ {
+ ret = -E2BIG;
+ break;
+ }
+
+ l_arr = (unsigned long *)alloc_xenheap_page();
+
+ ret = 0;
+ for( n = 0; n < num; )
+ {
+ int k = ((num-n)>GPF2_BATCH)?GPF2_BATCH:(num-n);
+
+ if ( copy_from_user(l_arr, &s_ptr[n], k*sizeof(unsigned long)) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ for( j = 0; j < k; j++ )
+ {
+ struct pfn_info *page;
+ unsigned long mfn = l_arr[j];
+
+ if ( unlikely(mfn >= max_page) )
+ goto e2_err;
+
+ page = &frame_table[mfn];
+
+ if ( likely(get_page(page, d)) )
+ {
+ unsigned long type = 0;
+
+ switch( page->u.inuse.type_info & PGT_type_mask )
+ {
+ default:
+ panic("No such page type\n");
+ break;
+ }
+
+ if ( page->u.inuse.type_info & PGT_pinned )
+ type |= LPINTAB;
+ l_arr[j] |= type;
+ put_page(page);
+ }
+ else
+ {
+ e2_err:
+ l_arr[j] |= XTAB;
+ }
+
+ }
+
+ if ( copy_to_user(&s_ptr[n], l_arr, k*sizeof(unsigned long)) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ n += j;
+ }
+
+ free_xenheap_page((unsigned long)l_arr);
+
+ put_domain(d);
+ }
+ break;
+#ifndef CONFIG_VTI
/*
* NOTE: DOM0_GETMEMLIST has somewhat different semantics on IA64 -
* it actually allocates and maps pages.
@@ -70,7 +192,42 @@ long arch_do_dom0_op(dom0_op_t *op, dom0_op_t *u_dom0_op)
}
}
break;
+#else
+ case DOM0_GETMEMLIST:
+ {
+ int i;
+ struct domain *d = find_domain_by_id(op->u.getmemlist.domain);
+ unsigned long max_pfns = op->u.getmemlist.max_pfns;
+ unsigned long pfn;
+ unsigned long *buffer = op->u.getmemlist.buffer;
+ struct list_head *list_ent;
+
+ ret = -EINVAL;
+ if (!d) {
+ ret = 0;
+
+ spin_lock(&d->page_alloc_lock);
+ list_ent = d->page_list.next;
+ for (i = 0; (i < max_pfns) && (list_ent != &d->page_list); i++) {
+ pfn = list_entry(list_ent, struct pfn_info, list) -
+ frame_table;
+ if (put_user(pfn, buffer)) {
+ ret = -EFAULT;
+ break;
+ }
+ buffer++;
+ list_ent = frame_table[pfn].list.next;
+ }
+ spin_unlock(&d->page_alloc_lock);
+ op->u.getmemlist.num_pfns = i;
+ copy_to_user(u_dom0_op, op, sizeof(*op));
+
+ put_domain(d);
+ }
+ }
+ break;
+#endif // CONFIG_VTI
default:
ret = -ENOSYS;