debuggers.hg

view xen/common/dom_mem_ops.c @ 3726:88957a238191

bitkeeper revision 1.1159.1.544 (4207248crq3YxiyLWjUehtHv_Yd3tg)

Merge tempest.cl.cam.ac.uk:/auto/groups/xeno-xenod/BK/xeno.bk
into tempest.cl.cam.ac.uk:/local/scratch/smh22/xen-unstable.bk
author smh22@tempest.cl.cam.ac.uk
date Mon Feb 07 08:19:24 2005 +0000 (2005-02-07)
parents 0373a9f51f2a 7db5b671b347
children f5f2757b3aa2
line source
1 /* -*- Mode:C; c-basic-offset:4; tab-width:4; indent-tabs-mode:nil -*- */
2 /******************************************************************************
3 * dom_mem_ops.c
4 *
5 * Code to handle memory related requests from domains eg. balloon driver.
6 *
7 * Copyright (c) 2003-2004, B Dragovic & K A Fraser.
8 */
10 #include <xen/config.h>
11 #include <xen/types.h>
12 #include <xen/lib.h>
13 #include <xen/mm.h>
14 #include <xen/perfc.h>
15 #include <xen/sched.h>
16 #include <xen/event.h>
17 #include <asm/domain_page.h>
19 /*
20 * To allow safe resume of do_dom_mem_op() after preemption, we need to know
21 * at what point in the page list to resume. For this purpose I steal the
22 * high-order bits of the @op parameter, which are otherwise unused and zero.
23 */
24 #define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
26 #define PREEMPT_CHECK(_op) \
27 if ( hypercall_preempt_check() ) \
28 return hypercall_create_continuation( \
29 __HYPERVISOR_dom_mem_op, 5, \
30 (_op) | (i << START_EXTENT_SHIFT), \
31 extent_list, nr_extents, extent_order, \
32 (d == current->domain) ? DOMID_SELF : d->id);
34 static long
35 alloc_dom_mem(struct domain *d,
36 unsigned long *extent_list,
37 unsigned long start_extent,
38 unsigned int nr_extents,
39 unsigned int extent_order)
40 {
41 struct pfn_info *page;
42 unsigned long i;
44 if ( unlikely(!array_access_ok(VERIFY_WRITE, extent_list,
45 nr_extents, sizeof(*extent_list))) )
46 return start_extent;
48 if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
49 {
50 DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
51 return start_extent;
52 }
54 for ( i = start_extent; i < nr_extents; i++ )
55 {
56 PREEMPT_CHECK(MEMOP_increase_reservation);
58 if ( unlikely((page = alloc_domheap_pages(d, extent_order)) == NULL) )
59 {
60 DPRINTK("Could not allocate a frame\n");
61 return i;
62 }
64 /* Inform the domain of the new page's machine address. */
65 if ( unlikely(__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
66 return i;
67 }
69 return i;
70 }
72 static long
73 free_dom_mem(struct domain *d,
74 unsigned long *extent_list,
75 unsigned long start_extent,
76 unsigned int nr_extents,
77 unsigned int extent_order)
78 {
79 struct pfn_info *page;
80 unsigned long i, j, mpfn;
82 if ( unlikely(!array_access_ok(VERIFY_READ, extent_list,
83 nr_extents, sizeof(*extent_list))) )
84 return start_extent;
86 for ( i = start_extent; i < nr_extents; i++ )
87 {
88 PREEMPT_CHECK(MEMOP_decrease_reservation);
90 if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
91 return i;
93 for ( j = 0; j < (1 << extent_order); j++ )
94 {
95 if ( unlikely((mpfn + j) >= max_page) )
96 {
97 DPRINTK("Domain %u page number out of range (%08lx>=%08lx)\n",
98 d->id, mpfn + j, max_page);
99 return i;
100 }
102 page = &frame_table[mpfn + j];
103 if ( unlikely(!get_page(page, d)) )
104 {
105 DPRINTK("Bad page free for domain %u\n", d->id);
106 return i;
107 }
109 if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
110 put_page_and_type(page);
112 if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
113 put_page(page);
115 put_page(page);
116 }
117 }
119 return i;
120 }
122 long
123 do_dom_mem_op(unsigned long op,
124 unsigned long *extent_list,
125 unsigned long nr_extents,
126 unsigned int extent_order,
127 domid_t domid)
128 {
129 struct domain *d;
130 unsigned long rc, start_extent;
132 /* Extract @start_extent from @op. */
133 start_extent = op >> START_EXTENT_SHIFT;
134 op &= (1 << START_EXTENT_SHIFT) - 1;
136 if ( unlikely(start_extent > nr_extents) ||
137 unlikely(nr_extents > ~0U) ) /* can pack into a uint? */
138 return -EINVAL;
140 if ( likely(domid == DOMID_SELF) )
141 d = current->domain;
142 else if ( unlikely(!IS_PRIV(current->domain)) )
143 return -EPERM;
144 else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
145 return -ESRCH;
147 LOCK_BIGLOCK(d);
149 switch ( op )
150 {
151 case MEMOP_increase_reservation:
152 rc = alloc_dom_mem(
153 d, extent_list, start_extent,
154 (unsigned int)nr_extents, extent_order);
155 break;
156 case MEMOP_decrease_reservation:
157 rc = free_dom_mem(
158 d, extent_list, start_extent,
159 (unsigned int)nr_extents, extent_order);
160 break;
161 default:
162 rc = -ENOSYS;
163 break;
164 }
166 if ( unlikely(domid != DOMID_SELF) )
167 put_domain(d);
169 UNLOCK_BIGLOCK(d);
171 return rc;
172 }