debuggers.hg

view xen/common/dom_mem_ops.c @ 3136:f1c44a4d4998

bitkeeper revision 1.1159.1.446 (41a48ee42Omqs3zoJHTZPhLlPx5LUw)

Merge arcadians.cl.cam.ac.uk:/auto/groups/xeno/BK/xen-unstable.bk
into arcadians.cl.cam.ac.uk:/auto/groups/xeno/users/cl349/BK/xen.bk-smp
author cl349@arcadians.cl.cam.ac.uk
date Wed Nov 24 13:38:44 2004 +0000 (2004-11-24)
parents f80e2182e92a 2754a2ed61c3
children 75f82adfcc90
line source
1 /******************************************************************************
2 * dom_mem_ops.c
3 *
4 * Code to handle memory related requests from domains eg. balloon driver.
5 *
6 * Copyright (c) 2003-2004, B Dragovic & K A Fraser.
7 */
9 #include <xen/config.h>
10 #include <xen/types.h>
11 #include <xen/lib.h>
12 #include <xen/mm.h>
13 #include <xen/perfc.h>
14 #include <xen/sched.h>
15 #include <xen/event.h>
16 #include <asm/domain_page.h>
18 static long alloc_dom_mem(struct domain *d,
19 unsigned long *extent_list,
20 unsigned long nr_extents,
21 unsigned int extent_order)
22 {
23 struct pfn_info *page;
24 unsigned long i;
26 if ( unlikely(!access_ok(VERIFY_WRITE, extent_list,
27 nr_extents*sizeof(*extent_list))) )
28 return 0;
30 if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
31 {
32 DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
33 return 0;
34 }
36 for ( i = 0; i < nr_extents; i++ )
37 {
38 hypercall_may_preempt(
39 __HYPERVISOR_dom_mem_op, 5,
40 MEMOP_increase_reservation,
41 &extent_list[i], nr_extents-i, extent_order,
42 (d == current) ? DOMID_SELF : d->id);
44 if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) )
45 {
46 DPRINTK("Could not allocate a frame\n");
47 return i;
48 }
50 /* Inform the domain of the new page's machine address. */
51 if ( unlikely(__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
52 return i;
53 }
55 return i;
56 }
58 static long free_dom_mem(struct domain *d,
59 unsigned long *extent_list,
60 unsigned long nr_extents,
61 unsigned int extent_order)
62 {
63 struct pfn_info *page;
64 unsigned long i, j, mpfn;
66 if ( unlikely(!access_ok(VERIFY_READ, extent_list,
67 nr_extents*sizeof(*extent_list))) )
68 return 0;
70 for ( i = 0; i < nr_extents; i++ )
71 {
72 hypercall_may_preempt(
73 __HYPERVISOR_dom_mem_op, 5,
74 MEMOP_decrease_reservation,
75 &extent_list[i], nr_extents-i, extent_order,
76 (d == current) ? DOMID_SELF : d->id);
78 if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
79 return i;
81 for ( j = 0; j < (1 << extent_order); j++ )
82 {
83 if ( unlikely((mpfn + j) >= max_page) )
84 {
85 DPRINTK("Domain %u page number out of range (%08lx>=%08lx)\n",
86 d->id, mpfn + j, max_page);
87 return i;
88 }
90 page = &frame_table[mpfn + j];
91 if ( unlikely(!get_page(page, d)) )
92 {
93 DPRINTK("Bad page free for domain %u\n", d->id);
94 return i;
95 }
97 if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
98 put_page_and_type(page);
100 if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
101 put_page(page);
103 put_page(page);
104 }
105 }
107 return i;
108 }
110 long do_dom_mem_op(unsigned int op,
111 unsigned long *extent_list,
112 unsigned long nr_extents,
113 unsigned int extent_order,
114 domid_t domid)
115 {
116 struct domain *d;
117 long rc;
119 if ( likely(domid == DOMID_SELF) )
120 d = current->domain;
121 else if ( unlikely(!IS_PRIV(current->domain)) )
122 return -EPERM;
123 else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
124 return -ESRCH;
126 LOCK_BIGLOCK(d);
128 switch ( op )
129 {
130 case MEMOP_increase_reservation:
131 rc = alloc_dom_mem(d, extent_list, nr_extents, extent_order);
132 break;
133 case MEMOP_decrease_reservation:
134 rc = free_dom_mem(d, extent_list, nr_extents, extent_order);
135 break;
136 default:
137 rc = -ENOSYS;
138 break;
139 }
141 if ( unlikely(domid != DOMID_SELF) )
142 put_domain(d);
144 UNLOCK_BIGLOCK(d);
146 return rc;
147 }