# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID 17dc21008351fcbe2b326b267541d23bfba3b388
# Parent 2e82fd7a69212955b75c6adaed4ae2a58ae45399
New memory hypercall 'populate_physmap'. Accepts a list of
pseudophys frame numbers to be populated with memory.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 2e82fd7a6921 -r 17dc21008351
linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c
--- a/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Fri Jan 27
11:48:32 2006
+++ b/linux-2.6-xen-sparse/arch/xen/i386/mm/hypervisor.c Fri Jan 27
11:49:47 2006
@@ -315,9 +315,9 @@
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long mfn, i, flags;
+ unsigned long frame, i, flags;
struct xen_memory_reservation reservation = {
- .extent_start = &mfn,
+ .extent_start = &frame,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
@@ -333,7 +333,7 @@
pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
- mfn = pte_mfn(*pte);
+ frame = pte_mfn(*pte);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -345,7 +345,8 @@
/* 2. Get a new contiguous memory extent. */
reservation.extent_order = order;
reservation.address_bits = address_bits;
- if (HYPERVISOR_memory_op(XENMEM_increase_reservation,
+ frame = __pa(vstart) >> PAGE_SHIFT;
+ if (HYPERVISOR_memory_op(XENMEM_populate_physmap,
&reservation) != 1)
goto fail;
@@ -353,9 +354,8 @@
for (i = 0; i < (1<<order); i++) {
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
- pfn_pte_ma(mfn+i, PAGE_KERNEL), 0));
- xen_machphys_update(mfn+i, (__pa(vstart)>>PAGE_SHIFT)+i);
- set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn+i);
+ pfn_pte_ma(frame+i, PAGE_KERNEL), 0));
+ set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame+i);
}
flush_tlb_all();
@@ -371,13 +371,13 @@
reservation.address_bits = 0;
for (i = 0; i < (1<<order); i++) {
+ frame = (__pa(vstart) >> PAGE_SHIFT) + i;
BUG_ON(HYPERVISOR_memory_op(
- XENMEM_increase_reservation, &reservation) != 1);
+ XENMEM_populate_physmap, &reservation) != 1);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
- pfn_pte_ma(mfn, PAGE_KERNEL), 0));
- xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
- set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+ pfn_pte_ma(frame, PAGE_KERNEL), 0));
+ set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
}
flush_tlb_all();
@@ -393,9 +393,9 @@
pud_t *pud;
pmd_t *pmd;
pte_t *pte;
- unsigned long mfn, i, flags;
+ unsigned long frame, i, flags;
struct xen_memory_reservation reservation = {
- .extent_start = &mfn,
+ .extent_start = &frame,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
@@ -413,7 +413,7 @@
pud = pud_offset(pgd, (vstart + (i*PAGE_SIZE)));
pmd = pmd_offset(pud, (vstart + (i*PAGE_SIZE)));
pte = pte_offset_kernel(pmd, (vstart + (i*PAGE_SIZE)));
- mfn = pte_mfn(*pte);
+ frame = pte_mfn(*pte);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i,
@@ -424,13 +424,13 @@
/* 2. Map new pages in place of old pages. */
for (i = 0; i < (1<<order); i++) {
+ frame = (__pa(vstart) >> PAGE_SHIFT) + i;
BUG_ON(HYPERVISOR_memory_op(
- XENMEM_increase_reservation, &reservation) != 1);
+ XENMEM_populate_physmap, &reservation) != 1);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
- pfn_pte_ma(mfn, PAGE_KERNEL), 0));
- xen_machphys_update(mfn, (__pa(vstart)>>PAGE_SHIFT)+i);
- set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, mfn);
+ pfn_pte_ma(frame, PAGE_KERNEL), 0));
+ set_phys_to_machine((__pa(vstart)>>PAGE_SHIFT)+i, frame);
}
flush_tlb_all();
diff -r 2e82fd7a6921 -r 17dc21008351
linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c
--- a/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Fri Jan 27
11:48:32 2006
+++ b/linux-2.6-xen-sparse/drivers/xen/balloon/balloon.c Fri Jan 27
11:49:47 2006
@@ -139,6 +139,21 @@
return page;
}
+static struct page *balloon_first_page(void)
+{
+ if (list_empty(&ballooned_pages))
+ return NULL;
+ return LIST_TO_PAGE(ballooned_pages.next);
+}
+
+static struct page *balloon_next_page(struct page *page)
+{
+ struct list_head *next = PAGE_TO_LIST(page)->next;
+ if (next == &ballooned_pages)
+ return NULL;
+ return LIST_TO_PAGE(next);
+}
+
static void balloon_alarm(unsigned long unused)
{
schedule_work(&balloon_worker);
@@ -154,7 +169,7 @@
static int increase_reservation(unsigned long nr_pages)
{
- unsigned long *mfn_list, pfn, i, flags;
+ unsigned long *frame_list, pfn, i, flags;
struct page *page;
long rc;
struct xen_memory_reservation reservation = {
@@ -166,20 +181,27 @@
if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
nr_pages = PAGE_SIZE / sizeof(unsigned long);
- mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (mfn_list == NULL)
+ frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (frame_list == NULL)
return -ENOMEM;
balloon_lock(flags);
- reservation.extent_start = mfn_list;
+ page = balloon_first_page();
+ for (i = 0; i < nr_pages; i++) {
+ BUG_ON(page == NULL);
+ frame_list[i] = page_to_pfn(page);;
+ page = balloon_next_page(page);
+ }
+
+ reservation.extent_start = frame_list;
reservation.nr_extents = nr_pages;
rc = HYPERVISOR_memory_op(
- XENMEM_increase_reservation, &reservation);
+ XENMEM_populate_physmap, &reservation);
if (rc < nr_pages) {
int ret;
/* We hit the Xen hard limit: reprobe. */
- reservation.extent_start = mfn_list;
+ reservation.extent_start = frame_list;
reservation.nr_extents = rc;
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation,
&reservation);
@@ -196,15 +218,15 @@
BUG_ON(phys_to_machine_mapping_valid(pfn));
/* Update P->M and M->P tables. */
- set_phys_to_machine(pfn, mfn_list[i]);
- xen_machphys_update(mfn_list[i], pfn);
+ set_phys_to_machine(pfn, frame_list[i]);
+ xen_machphys_update(frame_list[i], pfn);
/* Link back into the page tables if not highmem. */
if (pfn < max_low_pfn) {
int ret;
ret = HYPERVISOR_update_va_mapping(
(unsigned long)__va(pfn << PAGE_SHIFT),
- pfn_pte_ma(mfn_list[i], PAGE_KERNEL),
+ pfn_pte_ma(frame_list[i], PAGE_KERNEL),
0);
BUG_ON(ret);
}
@@ -221,14 +243,14 @@
out:
balloon_unlock(flags);
- free_page((unsigned long)mfn_list);
+ free_page((unsigned long)frame_list);
return 0;
}
static int decrease_reservation(unsigned long nr_pages)
{
- unsigned long *mfn_list, pfn, i, flags;
+ unsigned long *frame_list, pfn, i, flags;
struct page *page;
void *v;
int need_sleep = 0;
@@ -242,8 +264,8 @@
if (nr_pages > (PAGE_SIZE / sizeof(unsigned long)))
nr_pages = PAGE_SIZE / sizeof(unsigned long);
- mfn_list = (unsigned long *)__get_free_page(GFP_KERNEL);
- if (mfn_list == NULL)
+ frame_list = (unsigned long *)__get_free_page(GFP_KERNEL);
+ if (frame_list == NULL)
return -ENOMEM;
for (i = 0; i < nr_pages; i++) {
@@ -254,7 +276,7 @@
}
pfn = page_to_pfn(page);
- mfn_list[i] = pfn_to_mfn(pfn);
+ frame_list[i] = pfn_to_mfn(pfn);
if (!PageHighMem(page)) {
v = phys_to_virt(pfn << PAGE_SHIFT);
@@ -280,12 +302,12 @@
/* No more mappings: invalidate P2M and add to balloon. */
for (i = 0; i < nr_pages; i++) {
- pfn = mfn_to_pfn(mfn_list[i]);
+ pfn = mfn_to_pfn(frame_list[i]);
set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
balloon_append(pfn_to_page(pfn));
}
- reservation.extent_start = mfn_list;
+ reservation.extent_start = frame_list;
reservation.nr_extents = nr_pages;
ret = HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation);
BUG_ON(ret != nr_pages);
@@ -295,7 +317,7 @@
balloon_unlock(flags);
- free_page((unsigned long)mfn_list);
+ free_page((unsigned long)frame_list);
return need_sleep;
}
diff -r 2e82fd7a6921 -r 17dc21008351 xen/common/memory.c
--- a/xen/common/memory.c Fri Jan 27 11:48:32 2006
+++ b/xen/common/memory.c Fri Jan 27 11:49:47 2006
@@ -30,7 +30,7 @@
int *preempted)
{
struct pfn_info *page;
- unsigned int i;
+ unsigned long i;
if ( (extent_list != NULL) &&
!array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
@@ -52,7 +52,7 @@
d, extent_order, flags)) == NULL) )
{
DPRINTK("Could not allocate order=%d extent: "
- "id=%d flags=%x (%d of %d)\n",
+ "id=%d flags=%x (%ld of %d)\n",
extent_order, d->domain_id, flags, i, nr_extents);
return i;
}
@@ -60,6 +60,58 @@
/* Inform the domain of the new page's machine address. */
if ( (extent_list != NULL) &&
(__put_user(page_to_pfn(page), &extent_list[i]) != 0) )
+ return i;
+ }
+
+ return nr_extents;
+}
+
+static long
+populate_physmap(
+ struct domain *d,
+ unsigned long *extent_list,
+ unsigned int nr_extents,
+ unsigned int extent_order,
+ unsigned int flags,
+ int *preempted)
+{
+ struct pfn_info *page;
+ unsigned long i, j, pfn, mfn;
+
+ if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
+ return 0;
+
+ if ( (extent_order != 0) &&
+ !multipage_allocation_permitted(current->domain) )
+ return 0;
+
+ for ( i = 0; i < nr_extents; i++ )
+ {
+ if ( hypercall_preempt_check() )
+ {
+ *preempted = 1;
+ return i;
+ }
+
+ if ( unlikely((page = alloc_domheap_pages(
+ d, extent_order, flags)) == NULL) )
+ {
+ DPRINTK("Could not allocate order=%d extent: "
+ "id=%d flags=%x (%ld of %d)\n",
+ extent_order, d->domain_id, flags, i, nr_extents);
+ return i;
+ }
+
+ mfn = page_to_pfn(page);
+
+ if ( unlikely(__get_user(pfn, &extent_list[i]) != 0) )
+ return i;
+
+ for ( j = 0; j < (1 << extent_order); j++ )
+ set_pfn_from_mfn(mfn + j, pfn + j);
+
+ /* Inform the domain of the new page's machine address. */
+ if ( __put_user(mfn, &extent_list[i]) != 0 )
return i;
}
@@ -76,7 +128,7 @@
int *preempted)
{
struct pfn_info *page;
- unsigned long i, j, mpfn;
+ unsigned long i, j, mfn;
if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
return 0;
@@ -89,19 +141,19 @@
return i;
}
- if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
+ if ( unlikely(__get_user(mfn, &extent_list[i]) != 0) )
return i;
for ( j = 0; j < (1 << extent_order); j++ )
{
- if ( unlikely((mpfn + j) >= max_page) )
+ if ( unlikely((mfn + j) >= max_page) )
{
DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
- d->domain_id, mpfn + j, max_page);
+ d->domain_id, mfn + j, max_page);
return i;
}
- page = pfn_to_page(mpfn + j);
+ page = pfn_to_page(mfn + j);
if ( unlikely(!get_page(page, d)) )
{
DPRINTK("Bad page free for domain %u\n", d->domain_id);
@@ -143,6 +195,7 @@
{
case XENMEM_increase_reservation:
case XENMEM_decrease_reservation:
+ case XENMEM_populate_physmap:
if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
return -EFAULT;
@@ -170,14 +223,37 @@
else if ( (d = find_domain_by_id(reservation.domid)) == NULL )
return -ESRCH;
- rc = ((op == XENMEM_increase_reservation) ?
- increase_reservation : decrease_reservation)(
- d,
- reservation.extent_start,
- reservation.nr_extents,
- reservation.extent_order,
- flags,
- &preempted);
+ switch ( op )
+ {
+ case XENMEM_increase_reservation:
+ rc = increase_reservation(
+ d,
+ reservation.extent_start,
+ reservation.nr_extents,
+ reservation.extent_order,
+ flags,
+ &preempted);
+ break;
+ case XENMEM_decrease_reservation:
+ rc = decrease_reservation(
+ d,
+ reservation.extent_start,
+ reservation.nr_extents,
+ reservation.extent_order,
+ flags,
+ &preempted);
+ break;
+ case XENMEM_populate_physmap:
+ default:
+ rc = populate_physmap(
+ d,
+ reservation.extent_start,
+ reservation.nr_extents,
+ reservation.extent_order,
+ flags,
+ &preempted);
+ break;
+ }
if ( unlikely(reservation.domid != DOMID_SELF) )
put_domain(d);
diff -r 2e82fd7a6921 -r 17dc21008351 xen/include/public/memory.h
--- a/xen/include/public/memory.h Fri Jan 27 11:48:32 2006
+++ b/xen/include/public/memory.h Fri Jan 27 11:49:47 2006
@@ -16,11 +16,18 @@
*/
#define XENMEM_increase_reservation 0
#define XENMEM_decrease_reservation 1
+#define XENMEM_populate_physmap 6
typedef struct xen_memory_reservation {
/*
- * MFN bases of extents to free (XENMEM_decrease_reservation).
- * MFN bases of extents that were allocated (XENMEM_increase_reservation).
+ * XENMEM_increase_reservation:
+ * OUT: MFN bases of extents that were allocated
+ * XENMEM_decrease_reservation:
+ * IN: MFN bases of extents to free
+ * XENMEM_populate_physmap:
+ * IN: PFN bases of extents to populate with memory
+ * OUT: MFN bases of extents that were allocated
+ * (NB. This command also updates the mach_to_phys translation table)
*/
unsigned long *extent_start;
@@ -29,11 +36,10 @@
unsigned int extent_order;
/*
- * XENMEM_increase_reservation: maximum # bits addressable by the user
- * of the allocated region (e.g., I/O devices often have a 32-bit
- * limitation even in 64-bit systems). If zero then the user has no
- * addressing restriction.
- * XENMEM_decrease_reservation: unused.
+ * Mmaximum # bits addressable by the user of the allocated region (e.g.,
+ * I/O devices often have a 32-bit limitation even in 64-bit systems). If
+ * zero then the user has no addressing restriction.
+ * This field is not used by XENMEM_decrease_reservation.
*/
unsigned int address_bits;
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|