ia64/xen-unstable

annotate xen/common/memory.c @ 6486:1de508b9063b

Replace dom_mem_op hypercall with memory_op hypercall with
better interface. Fix "mem=" parameter on x86/64 boot.

Signed-off-by: Keir Fraser <keir@xensource.com>
author kaf24@firebug.cl.cam.ac.uk
date Tue Aug 30 11:53:47 2005 +0000 (2005-08-30)
parents
children b043928b0873
rev   line source
kaf24@6486 1 /******************************************************************************
kaf24@6486 2 * memory.c
kaf24@6486 3 *
kaf24@6486 4 * Code to handle memory-related requests.
kaf24@6486 5 *
kaf24@6486 6 * Copyright (c) 2003-2004, B Dragovic
kaf24@6486 7 * Copyright (c) 2003-2005, K A Fraser
kaf24@6486 8 */
kaf24@6486 9
kaf24@6486 10 #include <xen/config.h>
kaf24@6486 11 #include <xen/types.h>
kaf24@6486 12 #include <xen/lib.h>
kaf24@6486 13 #include <xen/mm.h>
kaf24@6486 14 #include <xen/perfc.h>
kaf24@6486 15 #include <xen/sched.h>
kaf24@6486 16 #include <xen/event.h>
kaf24@6486 17 #include <xen/shadow.h>
kaf24@6486 18 #include <asm/current.h>
kaf24@6486 19 #include <asm/hardirq.h>
kaf24@6486 20 #include <public/memory.h>
kaf24@6486 21
kaf24@6486 22 static long
kaf24@6486 23 increase_reservation(
kaf24@6486 24 struct domain *d,
kaf24@6486 25 unsigned long *extent_list,
kaf24@6486 26 unsigned int nr_extents,
kaf24@6486 27 unsigned int extent_order,
kaf24@6486 28 unsigned int flags)
kaf24@6486 29 {
kaf24@6486 30 struct pfn_info *page;
kaf24@6486 31 unsigned long i;
kaf24@6486 32
kaf24@6486 33 if ( (extent_list != NULL)
kaf24@6486 34 && !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
kaf24@6486 35 return 0;
kaf24@6486 36
kaf24@6486 37 if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
kaf24@6486 38 {
kaf24@6486 39 DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
kaf24@6486 40 return 0;
kaf24@6486 41 }
kaf24@6486 42
kaf24@6486 43 for ( i = 0; i < nr_extents; i++ )
kaf24@6486 44 {
kaf24@6486 45 if ( hypercall_preempt_check() )
kaf24@6486 46 return i;
kaf24@6486 47
kaf24@6486 48 if ( unlikely((page = alloc_domheap_pages(
kaf24@6486 49 d, extent_order, flags)) == NULL) )
kaf24@6486 50 {
kaf24@6486 51 DPRINTK("Could not allocate a frame\n");
kaf24@6486 52 return i;
kaf24@6486 53 }
kaf24@6486 54
kaf24@6486 55 /* Inform the domain of the new page's machine address. */
kaf24@6486 56 if ( (extent_list != NULL)
kaf24@6486 57 && (__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
kaf24@6486 58 return i;
kaf24@6486 59 }
kaf24@6486 60
kaf24@6486 61 return nr_extents;
kaf24@6486 62 }
kaf24@6486 63
kaf24@6486 64 static long
kaf24@6486 65 decrease_reservation(
kaf24@6486 66 struct domain *d,
kaf24@6486 67 unsigned long *extent_list,
kaf24@6486 68 unsigned int nr_extents,
kaf24@6486 69 unsigned int extent_order,
kaf24@6486 70 unsigned int flags)
kaf24@6486 71 {
kaf24@6486 72 struct pfn_info *page;
kaf24@6486 73 unsigned long i, j, mpfn;
kaf24@6486 74
kaf24@6486 75 if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
kaf24@6486 76 return 0;
kaf24@6486 77
kaf24@6486 78 for ( i = 0; i < nr_extents; i++ )
kaf24@6486 79 {
kaf24@6486 80 if ( hypercall_preempt_check() )
kaf24@6486 81 return i;
kaf24@6486 82
kaf24@6486 83 if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
kaf24@6486 84 return i;
kaf24@6486 85
kaf24@6486 86 for ( j = 0; j < (1 << extent_order); j++ )
kaf24@6486 87 {
kaf24@6486 88 if ( unlikely((mpfn + j) >= max_page) )
kaf24@6486 89 {
kaf24@6486 90 DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
kaf24@6486 91 d->domain_id, mpfn + j, max_page);
kaf24@6486 92 return i;
kaf24@6486 93 }
kaf24@6486 94
kaf24@6486 95 page = &frame_table[mpfn + j];
kaf24@6486 96 if ( unlikely(!get_page(page, d)) )
kaf24@6486 97 {
kaf24@6486 98 DPRINTK("Bad page free for domain %u\n", d->domain_id);
kaf24@6486 99 return i;
kaf24@6486 100 }
kaf24@6486 101
kaf24@6486 102 if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
kaf24@6486 103 put_page_and_type(page);
kaf24@6486 104
kaf24@6486 105 if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
kaf24@6486 106 put_page(page);
kaf24@6486 107
kaf24@6486 108 shadow_sync_and_drop_references(d, page);
kaf24@6486 109
kaf24@6486 110 put_page(page);
kaf24@6486 111 }
kaf24@6486 112 }
kaf24@6486 113
kaf24@6486 114 return nr_extents;
kaf24@6486 115 }
kaf24@6486 116
kaf24@6486 117 /*
kaf24@6486 118 * To allow safe resume of do_memory_op() after preemption, we need to know
kaf24@6486 119 * at what point in the page list to resume. For this purpose I steal the
kaf24@6486 120 * high-order bits of the @cmd parameter, which are otherwise unused and zero.
kaf24@6486 121 */
kaf24@6486 122 #define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
kaf24@6486 123
kaf24@6486 124 long do_memory_op(int cmd, void *arg)
kaf24@6486 125 {
kaf24@6486 126 struct domain *d;
kaf24@6486 127 int rc, start_extent, op, flags = 0;
kaf24@6486 128 struct xen_memory_reservation reservation;
kaf24@6486 129
kaf24@6486 130 op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
kaf24@6486 131
kaf24@6486 132 switch ( op )
kaf24@6486 133 {
kaf24@6486 134 case XENMEM_increase_reservation:
kaf24@6486 135 case XENMEM_decrease_reservation:
kaf24@6486 136 if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
kaf24@6486 137 return -EFAULT;
kaf24@6486 138
kaf24@6486 139 start_extent = cmd >> START_EXTENT_SHIFT;
kaf24@6486 140 if ( unlikely(start_extent > reservation.nr_extents) )
kaf24@6486 141 return -EINVAL;
kaf24@6486 142
kaf24@6486 143 if ( reservation.extent_start != NULL )
kaf24@6486 144 reservation.extent_start += start_extent;
kaf24@6486 145 reservation.nr_extents -= start_extent;
kaf24@6486 146
kaf24@6486 147 if ( unlikely(reservation.address_bits != 0)
kaf24@6486 148 && (reservation.address_bits > (get_order(max_page)+PAGE_SHIFT)) )
kaf24@6486 149 {
kaf24@6486 150 if ( reservation.address_bits < 31 )
kaf24@6486 151 return -ENOMEM;
kaf24@6486 152 flags = ALLOC_DOM_DMA;
kaf24@6486 153 }
kaf24@6486 154
kaf24@6486 155 if ( likely(reservation.domid == DOMID_SELF) )
kaf24@6486 156 d = current->domain;
kaf24@6486 157 else if ( !IS_PRIV(current->domain) )
kaf24@6486 158 return -EPERM;
kaf24@6486 159 else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
kaf24@6486 160 return -ESRCH;
kaf24@6486 161
kaf24@6486 162 rc = ((op == XENMEM_increase_reservation) ?
kaf24@6486 163 increase_reservation : decrease_reservation)(
kaf24@6486 164 d,
kaf24@6486 165 reservation.extent_start,
kaf24@6486 166 reservation.nr_extents,
kaf24@6486 167 reservation.extent_order,
kaf24@6486 168 flags);
kaf24@6486 169
kaf24@6486 170 if ( unlikely(reservation.domid != DOMID_SELF) )
kaf24@6486 171 put_domain(d);
kaf24@6486 172
kaf24@6486 173 rc += start_extent;
kaf24@6486 174
kaf24@6486 175 if ( (rc != reservation.nr_extents) && hypercall_preempt_check() )
kaf24@6486 176 return hypercall2_create_continuation(
kaf24@6486 177 __HYPERVISOR_memory_op,
kaf24@6486 178 op | (rc << START_EXTENT_SHIFT),
kaf24@6486 179 arg);
kaf24@6486 180
kaf24@6486 181 break;
kaf24@6486 182
kaf24@6486 183 case XENMEM_maximum_ram_page:
kaf24@6486 184 if ( put_user(max_page, (unsigned long *)arg) )
kaf24@6486 185 return -EFAULT;
kaf24@6486 186 rc = -ENOSYS;
kaf24@6486 187 break;
kaf24@6486 188
kaf24@6486 189 default:
kaf24@6486 190 rc = -ENOSYS;
kaf24@6486 191 break;
kaf24@6486 192 }
kaf24@6486 193
kaf24@6486 194 return rc;
kaf24@6486 195 }
kaf24@6486 196
kaf24@6486 197 /*
kaf24@6486 198 * Local variables:
kaf24@6486 199 * mode: C
kaf24@6486 200 * c-set-style: "BSD"
kaf24@6486 201 * c-basic-offset: 4
kaf24@6486 202 * tab-width: 4
kaf24@6486 203 * indent-tabs-mode: nil
kaf24@6486 204 * End:
kaf24@6486 205 */