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>
This commit is contained in:
kaf24@firebug.cl.cam.ac.uk committed 2005-08-30 11:53:47 +00:00
1 parent 855b34ec99
commit e4dfe0cdba
22 files changed
+435 -285

No files matched your search

@@ -115,9 +115,9 @@ dma_supported(struct device *dev, u64 mask)
if (swiotlb)
return swiotlb_dma_supported(dev, mask);
/*
* By default we'll BUG when an infeasible DMA is requested, and
* request swiotlb=force (see IOMMU_BUG_ON).
*/
* By default we'll BUG when an infeasible DMA is requested, and
* request swiotlb=force (see IOMMU_BUG_ON).
*/
return 1;
}
EXPORT_SYMBOL(dma_supported);
@@ -55,6 +55,7 @@
#include <asm/io.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/xen-public/physdev.h>
#include <asm-xen/xen-public/memory.h>
#include "setup_arch_pre.h"
#include <bios_ebda.h>
@@ -1585,15 +1586,21 @@ void __init setup_arch(char **cmdline_p)
(unsigned int *)xen_start_info.mfn_list,
xen_start_info.nr_pages * sizeof(unsigned int));
} else {
struct xen_memory_reservation reservation = {
.extent_start = (unsigned long *)xen_start_info.mfn_list + max_pfn,
.nr_extents = xen_start_info.nr_pages - max_pfn,
.extent_order = 0,
.domid = DOMID_SELF
};
memcpy(phys_to_machine_mapping,
(unsigned int *)xen_start_info.mfn_list,
max_pfn * sizeof(unsigned int));
/* N.B. below relies on sizeof(int) == sizeof(long). */
if (HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation,
(unsigned long *)xen_start_info.mfn_list + max_pfn,
xen_start_info.nr_pages - max_pfn, 0) !=
(xen_start_info.nr_pages - max_pfn)) BUG();
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation,
&reservation) !=
(xen_start_info.nr_pages - max_pfn));
}
free_bootmem(
__pa(xen_start_info.mfn_list),
@@ -35,6 +35,7 @@
#include <asm/pgtable.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/balloon.h>
#include <asm-xen/xen-public/memory.h>
#include <linux/module.h>
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
#include <linux/percpu.h>
@@ -320,6 +321,12 @@ void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
pmd_t *pmd;
pte_t *pte;
unsigned long mfn, i, flags;
struct xen_memory_reservation reservation = {
.extent_start = &mfn,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
};
scrub_pages(vstart, 1 << order);
@@ -336,13 +343,15 @@ void xen_create_contiguous_region(unsigned long vstart, unsigned int order)
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
INVALID_P2M_ENTRY;
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation, &reservation) != 1);
}
/* 2. Get a new contiguous memory extent. */
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_increase_reservation, &mfn, 1, order | (32<<8)) != 1);
reservation.extent_order = order;
reservation.address_bits = 31; /* aacraid limitation */
BUG_ON(HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation) != 1);
/* 3. Map the new extent in place of old pages. */
for (i = 0; i < (1<<order); i++) {
@@ -367,6 +376,12 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
pmd_t *pmd;
pte_t *pte;
unsigned long mfn, i, flags;
struct xen_memory_reservation reservation = {
.extent_start = &mfn,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
};
scrub_pages(vstart, 1 << order);
@@ -385,14 +400,14 @@ void xen_destroy_contiguous_region(unsigned long vstart, unsigned int order)
vstart + (i*PAGE_SIZE), __pte_ma(0), 0));
phys_to_machine_mapping[(__pa(vstart)>>PAGE_SHIFT)+i] =
INVALID_P2M_ENTRY;
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation, &reservation) != 1);
}
/* 2. Map new pages in place of old pages. */
for (i = 0; i < (1<<order); i++) {
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_increase_reservation, &mfn, 1, 0) != 1);
BUG_ON(HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation) != 1);
BUG_ON(HYPERVISOR_update_va_mapping(
vstart + (i*PAGE_SIZE),
pfn_pte_ma(mfn, PAGE_KERNEL), 0));
@@ -734,9 +734,9 @@ void __init setup_arch(char **cmdline_p)
/* Make sure we have a large enough P->M table. */
if (end_pfn > xen_start_info.nr_pages) {
phys_to_machine_mapping = alloc_bootmem(
max_pfn * sizeof(u32));
end_pfn * sizeof(u32));
memset(phys_to_machine_mapping, ~0,
max_pfn * sizeof(u32));
end_pfn * sizeof(u32));
memcpy(phys_to_machine_mapping,
(u32 *)xen_start_info.mfn_list,
xen_start_info.nr_pages * sizeof(u32));
@@ -749,11 +749,8 @@ void __init setup_arch(char **cmdline_p)
pfn_to_mfn_frame_list = alloc_bootmem(PAGE_SIZE);
for ( i=0, j=0; i < end_pfn; i+=(PAGE_SIZE/sizeof(u32)), j++ )
{
pfn_to_mfn_frame_list[j] =
virt_to_mfn(&phys_to_machine_mapping[i]);
}
}
#endif
@@ -466,7 +466,7 @@ static inline int make_readonly(unsigned long paddr)
return readonly;
}
void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
static void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
{
long i, j, k;
unsigned long paddr;
@@ -502,16 +502,17 @@ void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
pte = alloc_low_page(&pte_phys);
pte_save = pte;
for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr += PTE_SIZE) {
if ((paddr >= end) ||
((paddr >> PAGE_SHIFT)
>= xen_start_info.nr_pages)) {
__set_pte(pte, __pte(0));
continue;
}
if (make_readonly(paddr)) {
__set_pte(pte,
__pte(paddr | (_KERNPG_TABLE & ~_PAGE_RW)));
continue;
}
if (paddr >= end) {
for (; k < PTRS_PER_PTE; k++, pte++)
__set_pte(pte, __pte(0));
break;
}
__set_pte(pte, __pte(paddr | _KERNPG_TABLE));
}
pte = pte_save;
@@ -44,6 +44,7 @@
#include <asm-xen/xen_proc.h>
#include <asm-xen/hypervisor.h>
#include <asm-xen/balloon.h>
#include <asm-xen/xen-public/memory.h>
#include <asm/pgalloc.h>
#include <asm/pgtable.h>
#include <asm/uaccess.h>
@@ -168,6 +169,11 @@ static void balloon_process(void *unused)
struct page *page;
long credit, debt, rc;
void *v;
struct xen_memory_reservation reservation = {
.address_bits = 0,
.extent_order = 0,
.domid = DOMID_SELF
};
down(&balloon_mutex);
@@ -180,14 +186,18 @@ static void balloon_process(void *unused)
goto out;
balloon_lock(flags);
rc = HYPERVISOR_dom_mem_op(
MEMOP_increase_reservation, mfn_list, credit, 0);
reservation.extent_start = mfn_list;
reservation.nr_extents = credit;
rc = HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation);
balloon_unlock(flags);
if (rc < credit) {
/* We hit the Xen hard limit: reprobe. */
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation,
mfn_list, rc, 0) != rc);
reservation.extent_start = mfn_list;
reservation.nr_extents = rc;
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation,
&reservation) != rc);
hard_limit = current_pages + rc - driver_pages;
vfree(mfn_list);
goto retry;
@@ -261,8 +271,10 @@ static void balloon_process(void *unused)
balloon_append(pfn_to_page(pfn));
}
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation,mfn_list, debt, 0) != debt);
reservation.extent_start = mfn_list;
reservation.nr_extents = debt;
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation, &reservation) != debt);
current_pages -= debt;
}
@@ -438,11 +450,17 @@ static int dealloc_pte_fn(
pte_t *pte, struct page *pte_page, unsigned long addr, void *data)
{
unsigned long mfn = pte_mfn(*pte);
struct xen_memory_reservation reservation = {
.extent_start = &mfn,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
};
set_pte(pte, __pte_ma(0));
phys_to_machine_mapping[__pa(addr) >> PAGE_SHIFT] =
INVALID_P2M_ENTRY;
BUG_ON(HYPERVISOR_dom_mem_op(
MEMOP_decrease_reservation, &mfn, 1, 0) != 1);
BUG_ON(HYPERVISOR_memory_op(
XENMEM_decrease_reservation, &reservation) != 1);
return 0;
}
@@ -12,6 +12,7 @@
#include "common.h"
#include <asm-xen/balloon.h>
#include <asm-xen/xen-public/memory.h>
#if defined(CONFIG_XEN_NETDEV_GRANT_TX) || defined(CONFIG_XEN_NETDEV_GRANT_RX)
#include <asm-xen/xen-public/grant_table.h>
@@ -110,10 +111,16 @@ static spinlock_t mfn_lock = SPIN_LOCK_UNLOCKED;
static unsigned long alloc_mfn(void)
{
unsigned long mfn = 0, flags;
struct xen_memory_reservation reservation = {
.extent_start = mfn_list,
.nr_extents = MAX_MFN_ALLOC,
.extent_order = 0,
.domid = DOMID_SELF
};
spin_lock_irqsave(&mfn_lock, flags);
if ( unlikely(alloc_index == 0) )
alloc_index = HYPERVISOR_dom_mem_op(
MEMOP_increase_reservation, mfn_list, MAX_MFN_ALLOC, 0);
alloc_index = HYPERVISOR_memory_op(
XENMEM_increase_reservation, &reservation);
if ( alloc_index != 0 )
mfn = mfn_list[--alloc_index];
spin_unlock_irqrestore(&mfn_lock, flags);
@@ -124,11 +131,17 @@ static unsigned long alloc_mfn(void)
static void free_mfn(unsigned long mfn)
{
unsigned long flags;
struct xen_memory_reservation reservation = {
.extent_start = &mfn,
.nr_extents = 1,
.extent_order = 0,
.domid = DOMID_SELF
};
spin_lock_irqsave(&mfn_lock, flags);
if ( alloc_index != MAX_MFN_ALLOC )
mfn_list[alloc_index++] = mfn;
else if ( HYPERVISOR_dom_mem_op(MEMOP_decrease_reservation,
&mfn, 1, 0) != 1 )
else if ( HYPERVISOR_memory_op(XENMEM_decrease_reservation, &reservation)
!= 1 )
BUG();
spin_unlock_irqrestore(&mfn_lock, flags);
}
@@ -50,6 +50,7 @@
#include <asm-xen/evtchn.h>
#include <asm-xen/xenbus.h>
#include <asm-xen/xen-public/io/netif.h>
#include <asm-xen/xen-public/memory.h>
#include <asm-xen/balloon.h>
#include <asm/page.h>
#include <asm/uaccess.h>
@@ -328,6 +329,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
struct sk_buff *skb;
int i, batch_target;
NETIF_RING_IDX req_prod = np->rx->req_prod;
struct xen_memory_reservation reservation;
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
int ref;
#endif
@@ -388,12 +390,15 @@ static void network_alloc_rx_buffers(struct net_device *dev)
rx_mcl[i-1].args[MULTI_UVMFLAGS_INDEX] = UVMF_TLB_FLUSH|UVMF_ALL;
/* Give away a batch of pages. */
rx_mcl[i].op = __HYPERVISOR_dom_mem_op;
rx_mcl[i].args[0] = MEMOP_decrease_reservation;
rx_mcl[i].args[1] = (unsigned long)rx_pfn_array;
rx_mcl[i].args[2] = (unsigned long)i;
rx_mcl[i].args[3] = 0;
rx_mcl[i].args[4] = DOMID_SELF;
rx_mcl[i].op = __HYPERVISOR_memory_op;
rx_mcl[i].args[0] = XENMEM_decrease_reservation;
rx_mcl[i].args[1] = (unsigned long)&reservation;
reservation.extent_start = rx_pfn_array;
reservation.nr_extents = i;
reservation.extent_order = 0;
reservation.address_bits = 0;
reservation.domid = DOMID_SELF;
/* Tell the ballon driver what is going on. */
balloon_update_driver_allowance(i);
@@ -401,7 +406,7 @@ static void network_alloc_rx_buffers(struct net_device *dev)
/* Zap PTEs and give away pages in one big multicall. */
(void)HYPERVISOR_multicall(rx_mcl, i+1);
/* Check return status of HYPERVISOR_dom_mem_op(). */
/* Check return status of HYPERVISOR_memory_op(). */
if (unlikely(rx_mcl[i].result != i))
panic("Unable to reduce memory reservation\n");
@@ -236,12 +236,10 @@ HYPERVISOR_update_descriptor(
}
static inline int
HYPERVISOR_dom_mem_op(
unsigned int op, unsigned long *extent_list,
unsigned long nr_extents, unsigned int extent_order)
HYPERVISOR_memory_op(
unsigned int cmd, void *arg)
{
return _hypercall5(int, dom_mem_op, op, extent_list,
nr_extents, extent_order, DOMID_SELF);
return _hypercall2(int, memory_op, cmd, arg);
}
static inline int
@@ -231,12 +231,10 @@ HYPERVISOR_update_descriptor(
}
static inline int
HYPERVISOR_dom_mem_op(
unsigned int op, unsigned long *extent_list,
unsigned long nr_extents, unsigned int extent_order)
HYPERVISOR_memory_op(
unsigned int cmd, void *arg)
{
return _hypercall5(int, dom_mem_op, op, extent_list,
nr_extents, extent_order, DOMID_SELF);
return _hypercall2(int, memory_op, cmd, arg);
}
static inline int
+7 -2
View File
@@ -7,6 +7,7 @@
*/
#include "xc_private.h"
#include <xen/memory.h>
int xc_domain_create(int xc_handle,
u32 ssidref,
@@ -265,9 +266,13 @@ int xc_domain_memory_increase_reservation(int xc_handle,
{
int err;
unsigned int npages = mem_kb / (PAGE_SIZE/1024);
struct xen_memory_reservation reservation = {
.nr_extents = npages,
.extent_order = 0,
.domid = DOMID_SELF
};
err = xc_dom_mem_op(xc_handle, MEMOP_increase_reservation, NULL,
npages, 0, domid);
err = xc_memory_op(xc_handle, XENMEM_increase_reservation, &reservation);
if (err == npages)
return 0;
+12 -6
View File
@@ -8,11 +8,10 @@
#include <stdlib.h>
#include <unistd.h>
#include "xg_private.h"
#include <xenctrl.h>
#include <xen/linux/suspend.h>
#include <xen/memory.h>
#define MAX_BATCH_SIZE 1024
@@ -411,7 +410,8 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
/* Get the list of PFNs that are not in the psuedo-phys map */
{
unsigned int count, *pfntab;
unsigned int count;
unsigned long *pfntab;
int rc;
if ( read_exact(io_fd, &count, sizeof(count)) != sizeof(count) )
@@ -443,9 +443,15 @@ int xc_linux_restore(int xc_handle, int io_fd, u32 dom, unsigned long nr_pfns,
if ( count > 0 )
{
if ( (rc = xc_dom_mem_op( xc_handle,
MEMOP_decrease_reservation,
pfntab, count, 0, dom )) <0 )
struct xen_memory_reservation reservation = {
.extent_start = pfntab,
.nr_extents = count,
.extent_order = 0,
.domid = DOMID_SELF
};
if ( (rc = xc_memory_op(xc_handle,
XENMEM_decrease_reservation,
&reservation)) != count )
{
ERR("Could not decrease reservation : %d",rc);
goto out;
+45 -18
View File
@@ -6,6 +6,7 @@
#include <zlib.h>
#include "xc_private.h"
#include <xen/memory.h>
void *xc_map_foreign_batch(int xc_handle, u32 dom, int prot,
unsigned long *arr, int num )
@@ -187,28 +188,43 @@ int xc_finish_mmu_updates(int xc_handle, xc_mmu_t *mmu)
return flush_mmu_updates(xc_handle, mmu);
}
int xc_dom_mem_op(int xc_handle,
unsigned int memop,
unsigned int *extent_list,
unsigned int nr_extents,
unsigned int extent_order,
domid_t domid)
int xc_memory_op(int xc_handle,
int cmd,
void *arg)
{
privcmd_hypercall_t hypercall;
struct xen_memory_reservation *reservation = arg;
long ret = -EINVAL;
hypercall.op = __HYPERVISOR_dom_mem_op;
hypercall.arg[0] = (unsigned long)memop;
hypercall.arg[1] = (unsigned long)extent_list;
hypercall.arg[2] = (unsigned long)nr_extents;
hypercall.arg[3] = (unsigned long)extent_order;
hypercall.arg[4] = (unsigned long)domid;
hypercall.op = __HYPERVISOR_memory_op;
hypercall.arg[0] = (unsigned long)cmd;
hypercall.arg[1] = (unsigned long)arg;
if ( (extent_list != NULL) &&
(mlock(extent_list, nr_extents*sizeof(unsigned long)) != 0) )
switch ( cmd )
{
PERROR("Could not lock memory for Xen hypercall");
goto out1;
case XENMEM_increase_reservation:
case XENMEM_decrease_reservation:
if ( mlock(reservation, sizeof(*reservation)) != 0 )
{
PERROR("Could not mlock");
goto out1;
}
if ( (reservation->extent_start != NULL) &&
(mlock(reservation->extent_start,
reservation->nr_extents * sizeof(unsigned long)) != 0) )
{
PERROR("Could not mlock");
safe_munlock(reservation, sizeof(*reservation));
goto out1;
}
break;
case XENMEM_maximum_ram_page:
if ( mlock(arg, sizeof(unsigned long)) != 0 )
{
PERROR("Could not mlock");
goto out1;
}
break;
}
if ( (ret = do_xen_hypercall(xc_handle, &hypercall)) < 0 )
@@ -217,8 +233,19 @@ int xc_dom_mem_op(int xc_handle,
" rebuild the user-space tool set?\n",ret,errno);
}
if ( extent_list != NULL )
safe_munlock(extent_list, nr_extents*sizeof(unsigned long));
switch ( cmd )
{
case XENMEM_increase_reservation:
case XENMEM_decrease_reservation:
safe_munlock(reservation, sizeof(*reservation));
if ( reservation->extent_start != NULL )
safe_munlock(reservation->extent_start,
reservation->nr_extents * sizeof(unsigned long));
break;
case XENMEM_maximum_ram_page:
safe_munlock(arg, sizeof(unsigned long));
break;
}
out1:
return ret;
+1 -3
View File
@@ -430,9 +430,7 @@ int xc_ia64_get_pfn_list(int xc_handle, u32 domid, unsigned long *pfn_buf,
int xc_mmuext_op(int xc_handle, struct mmuext_op *op, unsigned int nr_ops,
domid_t dom);
int xc_dom_mem_op(int xc_handle, unsigned int memop, unsigned int *extent_list,
unsigned int nr_extents, unsigned int extent_order,
domid_t domid);
int xc_memory_op(int xc_handle, int cmd, void *arg);
int xc_get_pfn_type_batch(int xc_handle, u32 dom, int num, unsigned long *arr);
+2 -2
View File
@@ -790,7 +790,7 @@ ENTRY(hypercall_table)
.long do_get_debugreg
.long do_update_descriptor /* 10 */
.long do_ni_hypercall
.long do_dom_mem_op
.long do_memory_op
.long do_multicall
.long do_update_va_mapping
.long do_set_timer_op /* 15 */
@@ -823,7 +823,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_get_debugreg */
.byte 4 /* do_update_descriptor */ /* 10 */
.byte 0 /* do_ni_hypercall */
.byte 5 /* do_dom_mem_op */
.byte 2 /* do_memory_op */
.byte 2 /* do_multicall */
.byte 4 /* do_update_va_mapping */
.byte 2 /* do_set_timer_op */ /* 15 */
+2 -2
View File
@@ -616,7 +616,7 @@ ENTRY(hypercall_table)
.quad do_get_debugreg
.quad do_update_descriptor /* 10 */
.quad do_ni_hypercall
.quad do_dom_mem_op
.quad do_memory_op
.quad do_multicall
.quad do_update_va_mapping
.quad do_set_timer_op /* 15 */
@@ -649,7 +649,7 @@ ENTRY(hypercall_args_table)
.byte 1 /* do_get_debugreg */
.byte 2 /* do_update_descriptor */ /* 10 */
.byte 0 /* do_ni_hypercall */
.byte 5 /* do_dom_mem_op */
.byte 2 /* do_memory_op */
.byte 2 /* do_multicall */
.byte 3 /* do_update_va_mapping */
.byte 1 /* do_set_timer_op */ /* 15 */
-1
View File
@@ -2,7 +2,6 @@
include $(BASEDIR)/Rules.mk
ifeq ($(TARGET_ARCH),ia64)
#OBJS := $(subst dom_mem_ops.o,,$(OBJS))
OBJS := $(subst grant_table.o,,$(OBJS))
endif
-186
View File
@@ -1,186 +0,0 @@
/******************************************************************************
* dom_mem_ops.c
*
* Code to handle memory related requests from domains eg. balloon driver.
*
* Copyright (c) 2003-2004, B Dragovic & K A Fraser.
*/
#include <xen/config.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/mm.h>
#include <xen/perfc.h>
#include <xen/sched.h>
#include <xen/event.h>
#include <xen/shadow.h>
#include <asm/current.h>
#include <asm/hardirq.h>
/*
* To allow safe resume of do_dom_mem_op() after preemption, we need to know
* at what point in the page list to resume. For this purpose I steal the
* high-order bits of the @op parameter, which are otherwise unused and zero.
*/
#define START_EXTENT_SHIFT 4 /* op[:4] == start_extent */
#define PREEMPT_CHECK(_op) \
if ( hypercall_preempt_check() ) \
return hypercall5_create_continuation( \
__HYPERVISOR_dom_mem_op, \
(_op) | (i << START_EXTENT_SHIFT), \
extent_list, nr_extents, extent_order, \
(d == current->domain) ? DOMID_SELF : d->domain_id);
static long
alloc_dom_mem(struct domain *d,
unsigned long *extent_list,
unsigned long start_extent,
unsigned int nr_extents,
unsigned int extent_order,
unsigned int flags)
{
struct pfn_info *page;
unsigned long i;
if ( (extent_list != NULL) &&
!array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
return start_extent;
if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
{
DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
return start_extent;
}
for ( i = start_extent; i < nr_extents; i++ )
{
PREEMPT_CHECK(MEMOP_increase_reservation);
if ( unlikely((page = alloc_domheap_pages(d, extent_order,
flags)) == NULL) )
{
DPRINTK("Could not allocate a frame\n");
return i;
}
/* 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 i;
}
static long
free_dom_mem(struct domain *d,
unsigned long *extent_list,
unsigned long start_extent,
unsigned int nr_extents,
unsigned int extent_order)
{
struct pfn_info *page;
unsigned long i, j, mpfn;
if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
return start_extent;
for ( i = start_extent; i < nr_extents; i++ )
{
PREEMPT_CHECK(MEMOP_decrease_reservation);
if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
return i;
for ( j = 0; j < (1 << extent_order); j++ )
{
if ( unlikely((mpfn + j) >= max_page) )
{
DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
d->domain_id, mpfn + j, max_page);
return i;
}
page = &frame_table[mpfn + j];
if ( unlikely(!get_page(page, d)) )
{
DPRINTK("Bad page free for domain %u\n", d->domain_id);
return i;
}
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
shadow_sync_and_drop_references(d, page);
put_page(page);
}
}
return i;
}
long
do_dom_mem_op(unsigned long op,
unsigned long *extent_list,
unsigned int nr_extents,
unsigned int extent_order,
domid_t domid)
{
struct domain *d;
unsigned long rc, start_extent;
unsigned int address_bits_order;
/* Extract @start_extent from @op. */
start_extent = op >> START_EXTENT_SHIFT;
op &= (1 << START_EXTENT_SHIFT) - 1;
/* seperate extent_order and address_bits_order */
address_bits_order = (extent_order >> 8) & 0xff;
extent_order &= 0xff;
if ( unlikely(start_extent > nr_extents) )
return -EINVAL;
if ( likely(domid == DOMID_SELF) )
d = current->domain;
else if ( unlikely(!IS_PRIV(current->domain)) )
return -EPERM;
else if ( unlikely((d = find_domain_by_id(domid)) == NULL) )
return -ESRCH;
switch ( op )
{
case MEMOP_increase_reservation:
rc = alloc_dom_mem(
d, extent_list, start_extent, nr_extents, extent_order,
(address_bits_order <= 32) ? ALLOC_DOM_DMA : 0);
break;
case MEMOP_decrease_reservation:
rc = free_dom_mem(
d, extent_list, start_extent, nr_extents, extent_order);
break;
default:
rc = -ENOSYS;
break;
}
if ( unlikely(domid != DOMID_SELF) )
put_domain(d);
return rc;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
+205
View File
@@ -0,0 +1,205 @@
/******************************************************************************
* memory.c
*
* Code to handle memory-related requests.
*
* Copyright (c) 2003-2004, B Dragovic
* Copyright (c) 2003-2005, K A Fraser
*/
#include <xen/config.h>
#include <xen/types.h>
#include <xen/lib.h>
#include <xen/mm.h>
#include <xen/perfc.h>
#include <xen/sched.h>
#include <xen/event.h>
#include <xen/shadow.h>
#include <asm/current.h>
#include <asm/hardirq.h>
#include <public/memory.h>
static long
increase_reservation(
struct domain *d,
unsigned long *extent_list,
unsigned int nr_extents,
unsigned int extent_order,
unsigned int flags)
{
struct pfn_info *page;
unsigned long i;
if ( (extent_list != NULL)
&& !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
return 0;
if ( (extent_order != 0) && !IS_CAPABLE_PHYSDEV(current->domain) )
{
DPRINTK("Only I/O-capable domains may allocate > order-0 memory.\n");
return 0;
}
for ( i = 0; i < nr_extents; i++ )
{
if ( hypercall_preempt_check() )
return i;
if ( unlikely((page = alloc_domheap_pages(
d, extent_order, flags)) == NULL) )
{
DPRINTK("Could not allocate a frame\n");
return i;
}
/* 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
decrease_reservation(
struct domain *d,
unsigned long *extent_list,
unsigned int nr_extents,
unsigned int extent_order,
unsigned int flags)
{
struct pfn_info *page;
unsigned long i, j, mpfn;
if ( !array_access_ok(extent_list, nr_extents, sizeof(*extent_list)) )
return 0;
for ( i = 0; i < nr_extents; i++ )
{
if ( hypercall_preempt_check() )
return i;
if ( unlikely(__get_user(mpfn, &extent_list[i]) != 0) )
return i;
for ( j = 0; j < (1 << extent_order); j++ )
{
if ( unlikely((mpfn + j) >= max_page) )
{
DPRINTK("Domain %u page number out of range (%lx >= %lx)\n",
d->domain_id, mpfn + j, max_page);
return i;
}
page = &frame_table[mpfn + j];
if ( unlikely(!get_page(page, d)) )
{
DPRINTK("Bad page free for domain %u\n", d->domain_id);
return i;
}
if ( test_and_clear_bit(_PGT_pinned, &page->u.inuse.type_info) )
put_page_and_type(page);
if ( test_and_clear_bit(_PGC_allocated, &page->count_info) )
put_page(page);
shadow_sync_and_drop_references(d, page);
put_page(page);
}
}
return nr_extents;
}
/*
* To allow safe resume of do_memory_op() after preemption, we need to know
* at what point in the page list to resume. For this purpose I steal the
* high-order bits of the @cmd parameter, which are otherwise unused and zero.
*/
#define START_EXTENT_SHIFT 4 /* cmd[:4] == start_extent */
long do_memory_op(int cmd, void *arg)
{
struct domain *d;
int rc, start_extent, op, flags = 0;
struct xen_memory_reservation reservation;
op = cmd & ((1 << START_EXTENT_SHIFT) - 1);
switch ( op )
{
case XENMEM_increase_reservation:
case XENMEM_decrease_reservation:
if ( copy_from_user(&reservation, arg, sizeof(reservation)) )
return -EFAULT;
start_extent = cmd >> START_EXTENT_SHIFT;
if ( unlikely(start_extent > reservation.nr_extents) )
return -EINVAL;
if ( reservation.extent_start != NULL )
reservation.extent_start += start_extent;
reservation.nr_extents -= start_extent;
if ( unlikely(reservation.address_bits != 0)
&& (reservation.address_bits > (get_order(max_page)+PAGE_SHIFT)) )
{
if ( reservation.address_bits < 31 )
return -ENOMEM;
flags = ALLOC_DOM_DMA;
}
if ( likely(reservation.domid == DOMID_SELF) )
d = current->domain;
else if ( !IS_PRIV(current->domain) )
return -EPERM;
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);
if ( unlikely(reservation.domid != DOMID_SELF) )
put_domain(d);
rc += start_extent;
if ( (rc != reservation.nr_extents) && hypercall_preempt_check() )
return hypercall2_create_continuation(
__HYPERVISOR_memory_op,
op | (rc << START_EXTENT_SHIFT),
arg);
break;
case XENMEM_maximum_ram_page:
if ( put_user(max_page, (unsigned long *)arg) )
return -EFAULT;
rc = -ENOSYS;
break;
default:
rc = -ENOSYS;
break;
}
return rc;
}
/*
* Local variables:
* mode: C
* c-set-style: "BSD"
* c-basic-offset: 4
* tab-width: 4
* indent-tabs-mode: nil
* End:
*/
+1 -1
View File
@@ -216,7 +216,7 @@ unsigned long alloc_boot_pages(unsigned long nr_pfns, unsigned long pfn_align)
#define NR_ZONES 3
#define MAX_DMADOM_PFN 0xFFFFF
#define MAX_DMADOM_PFN 0x7FFFF /* 31 addressable bits */
#define pfn_dom_zone_type(_pfn) \
(((_pfn) <= MAX_DMADOM_PFN) ? MEMZONE_DMADOM : MEMZONE_DOM)
+50
View File
@@ -0,0 +1,50 @@
/******************************************************************************
* memory.h
*
* Memory reservation and information.
*
* Copyright (c) 2005, Keir Fraser <keir@xensource.com>
*/
#ifndef __XEN_PUBLIC_MEMORY_H__
#define __XEN_PUBLIC_MEMORY_H__
/* arg == addr of struct xen_memory_reservation. */
#define XENMEM_increase_reservation 0
/* arg == addr of struct xen_memory_reservation. */
#define XENMEM_decrease_reservation 1
/* arg == addr of unsigned long. */
#define XENMEM_maximum_ram_page 2
typedef struct xen_memory_reservation {
/*
* MFN bases of extents to free (XENMEM_decrease_reservation).
* MFN bases of extents that were allocated (XENMEM_increase_reservation).
*/
unsigned long *extent_start;
/* Number of extents, and size/alignment of each (2^extent_order pages). */
unsigned long nr_extents;
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.
*/
unsigned int address_bits;
/*
* Domain whose reservation is being changed.
* Unprivileged domains can specify only DOMID_SELF.
*/
domid_t domid;
} xen_memory_reservation_t;
#endif /* __XEN_PUBLIC_MEMORY_H__ */
+1 -7
View File
@@ -42,7 +42,7 @@
#define __HYPERVISOR_set_debugreg 8
#define __HYPERVISOR_get_debugreg 9
#define __HYPERVISOR_update_descriptor 10
#define __HYPERVISOR_dom_mem_op 12
#define __HYPERVISOR_memory_op 12
#define __HYPERVISOR_multicall 13
#define __HYPERVISOR_update_va_mapping 14
#define __HYPERVISOR_set_timer_op 15
@@ -224,12 +224,6 @@ struct mmuext_op {
#define CONSOLEIO_write 0
#define CONSOLEIO_read 1
/*
* Commands to HYPERVISOR_dom_mem_op().
*/
#define MEMOP_increase_reservation 0
#define MEMOP_decrease_reservation 1
/*
* Commands to HYPERVISOR_vm_assist().
*/
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.