mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
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:
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,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;
|
||||
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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:
|
||||
*/
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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__ */
|
||||
@@ -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().
|
||||
*/
|
||||
|
||||