ia64/xen-unstable

view xen/common/dom_mem_ops.c @ 5935:55a5ad2f028d

dom_mem_ops address_bitsd fix.
author kaf24@firebug.cl.cam.ac.uk
date Fri Jul 29 11:21:39 2005 +0000 (2005-07-29)
parents 51094fae410e
children b53a65034532 1efe6f4163ee e173a853dc46 d4fd332df775 04dfb5158f3a f294acb25858
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 <xen/shadow.h>
17 #include <asm/current.h>
18 #include <asm/hardirq.h>
20 /*
21 * To allow safe resume of do_dom_mem_op() after preemption, we need to know
22 * at what point in the page list to resume. For this purpose I steal the
23 * high-order bits of the @op parameter, which are otherwise unused and zero.
24 */
25 #define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
27 #define PREEMPT_CHECK(_op) \
28 if ( hypercall_preempt_check() ) \
29 return hypercall5_create_continuation( \
30 __HYPERVISOR_dom_mem_op, \
31 (_op) | (i << START_EXTENT_SHIFT), \
32 extent_list, nr_extents, extent_order, \
33 (d == current->domain) ? DOMID_SELF : d->domain_id);
35 static long
36 alloc_dom_mem(struct domain *d,
37 unsigned long *extent_list,
38 unsigned long start_extent,
39 unsigned int nr_extents,
40 unsigned int extent_order,
41 unsigned int flags)
42 {
43 struct pfn_info *page;
44 unsigned long i;
46 if ( (extent_list != NULL) &&
47 !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
48 return start_extent;
50 if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
51 {
52 DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
53 return start_extent;
54 }
56 for ( i = start_extent; i < nr_extents; i++ )
57 {
58 PREEMPT_CHECK(MEMOP_increase_reservation);
60 if ( unlikely((page = alloc_domheap_pages(d, extent_order,
61 flags)) == NULL) )
62 {
63 DPRINTK("Could not allocate a frame\n");
64 return i;
65 }
67 /* Inform the domain of the new page's machine address. */
68 if ( (extent_list != NULL) &&
69 (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
70 return i;
71 }
73 return i;
74 }
76 static long
77 free_dom_mem(struct domain *d,
78 unsigned long *extent_list,
79 unsigned long start_extent,
80 unsigned int nr_extents,
81 unsigned int extent_order)
82 {
83 struct pfn_info *page;
84 unsigned long i, j, mpfn;
86 if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
87 return start_extent;
89 for ( i = start_extent; i < nr_extents; i++ )
90 {
91 PREEMPT_CHECK(MEMOP_decrease_reservation);
93 if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
94 return i;
96 for ( j = 0; j < (1 << extent_order); j++ )
97 {
98 if ( unlikely((mpfn + j) >= max_page) )
99 {
100 DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
101 d->domain_id, mpfn + j, max_page);
102 return i;
103 }
105 page = &frame_table[mpfn + j];
106 if ( unlikely(!get_page(page, d)) )
107 {
108 DPRINTK("Bad page free for domain %u\n", d->domain_id);
109 return i;
110 }
112 if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
113 put_page_and_type(page);
115 if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
116 put_page(page);
118 shadow_sync_and_drop_references(d, page);
120 put_page(page);
121 }
122 }
124 return i;
125 }
127 long
128 do_dom_mem_op(unsigned long op,
129 unsigned long *extent_list,
130 unsigned int nr_extents,
131 unsigned int extent_order,
132 domid_t domid)
133 {
134 struct domain *d;
135 unsigned long rc, start_extent;
136 unsigned int address_bits_order;
138 /* Extract @start_extent from @op. */
139 start_extent = op >> START_EXTENT_SHIFT;
140 op &= (1 << START_EXTENT_SHIFT) - 1;
142 /* seperate extent_order and address_bits_order */
143 address_bits_order = (extent_order >> 8) & 0xff;
144 extent_order &= 0xff;
146 if ( unlikely(start_extent > nr_extents) )
147 return -EINVAL;
149 if ( likely(domid == DOMID_SELF) )
150 d = current->domain;
151 else if ( unlikely(!IS_PRIV(current->domain)) )
152 return -EPERM;
153 else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
154 return -ESRCH;
156 switch ( op )
157 {
158 case MEMOP_increase_reservation:
159 rc = alloc_dom_mem(
160 d, extent_list, start_extent, nr_extents, extent_order,
161 (address_bits_order <= 32) ? ALLOC_DOM_DMA : 0);
162 break;
163 case MEMOP_decrease_reservation:
164 rc = free_dom_mem(
165 d, extent_list, start_extent, nr_extents, extent_order);
166 break;
167 default:
168 rc = -ENOSYS;
169 break;
170 }
172 if ( unlikely(domid != DOMID_SELF) )
173 put_domain(d);
175 return rc;
176 }
178 /*
179 * Local variables:
180 * mode: C
181 * c-set-style: "BSD"
182 * c-basic-offset: 4
183 * tab-width: 4
184 * indent-tabs-mode: nil
185 * End:
186 */