# HG changeset patch
# User kaf24@xxxxxxxxxxxxxxxxxxxx
# Node ID c3cfc4ff3b08b01051e6fa0741e1e014a1307aea
# Parent 549130374cfad466e526bed31199c7a5eee5eb38
Implement new memory_op() XENMEM_machphys_mfn_list. Replaces old
privcmd Linux ioctl and includes an implementation for x86/64.
Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>
diff -r 549130374cfa -r c3cfc4ff3b08
linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c
--- a/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Nov 25
16:58:36 2005
+++ b/linux-2.6-xen-sparse/drivers/xen/privcmd/privcmd.c Fri Nov 25
17:43:35 2005
@@ -213,55 +213,6 @@
break;
#endif
-#ifndef __ia64__
- case IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS: {
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
- unsigned long m2pv, m2p_mfn;
- privcmd_m2pmfns_t m;
- unsigned long __user *p;
- int i;
-
-#if defined (__x86_64__)
- /*
- ** XXX SMH: the below procedure won't work for 64 since
- ** we don't have access to the memory which maps the M2P.
- ** A proper fix will probably involve moving this
- ** functionality to Xen - for now just return an error
- ** here rather than GPF'ing in the kernel.
- */
- ret = -EINVAL;
- break;
-#endif
-
- if (copy_from_user(&m, udata, sizeof(m)))
- return -EFAULT;
-
- m2pv = (unsigned long)machine_to_phys_mapping;
-
- p = m.arr;
-
- for (i=0; i < m.num; i++) {
- pgd = pgd_offset_k(m2pv);
- pud = pud_offset(pgd, m2pv);
- pmd = pmd_offset(pud, m2pv);
- m2p_mfn = (*(uint64_t *)pmd >> PAGE_SHIFT)&0xFFFFFFFF;
- m2p_mfn += pte_index(m2pv);
-
- if (put_user(m2p_mfn, p + i))
- return -EFAULT;
-
- m2pv += (1 << 21);
- }
-
- ret = 0;
- break;
-
- }
- break;
-#endif
-
default:
ret = -EINVAL;
break;
diff -r 549130374cfa -r c3cfc4ff3b08
linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h
--- a/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Fri Nov
25 16:58:36 2005
+++ b/linux-2.6-xen-sparse/include/asm-xen/linux-public/privcmd.h Fri Nov
25 17:43:35 2005
@@ -59,11 +59,6 @@
unsigned long __user *arr; /* array of mfns - top nibble set on err */
} privcmd_mmapbatch_t;
-typedef struct privcmd_m2pmfns {
- int num; /* max number of mfns to return */
- unsigned long __user *arr; /* array of mfns */
-} privcmd_m2pmfns_t;
-
typedef struct privcmd_blkmsg
{
unsigned long op;
@@ -82,8 +77,6 @@
_IOC(_IOC_NONE, 'P', 2, sizeof(privcmd_mmap_t))
#define IOCTL_PRIVCMD_MMAPBATCH \
_IOC(_IOC_NONE, 'P', 3, sizeof(privcmd_mmapbatch_t))
-#define IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS \
- _IOC(_IOC_READ, 'P', 4, sizeof(unsigned long))
#endif /* __LINUX_PUBLIC_PRIVCMD_H__ */
diff -r 549130374cfa -r c3cfc4ff3b08 tools/libxc/xc_linux_save.c
--- a/tools/libxc/xc_linux_save.c Fri Nov 25 16:58:36 2005
+++ b/tools/libxc/xc_linux_save.c Fri Nov 25 17:43:35 2005
@@ -502,7 +502,7 @@
unsigned long max_mfn,
int prot)
{
- privcmd_m2pmfns_t m2p_mfns;
+ struct xen_machphys_mfn_list xmml;
privcmd_mmap_t ioctlx;
privcmd_mmap_entry_t *entries;
unsigned long m2p_chunks, m2p_size;
@@ -512,50 +512,45 @@
m2p_size = M2P_SIZE(max_mfn);
m2p_chunks = M2P_CHUNKS(max_mfn);
-
- m2p_mfns.num = m2p_chunks;
-
- if(!(m2p_mfns.arr = malloc(m2p_chunks * sizeof(unsigned long)))) {
+ xmml.max_extents = m2p_chunks;
+ if (!(xmml.extent_start = malloc(m2p_chunks * sizeof(unsigned long)))) {
ERR("failed to allocate space for m2p mfns!\n");
return NULL;
}
- if (ioctl(xc_handle, IOCTL_PRIVCMD_GET_MACH2PHYS_MFNS, &m2p_mfns) < 0) {
+ if (xc_memory_op(xc_handle, XENMEM_machphys_mfn_list, &xmml) ||
+ (xmml.nr_extents != m2p_chunks)) {
ERR("xc_get_m2p_mfns:");
return NULL;
}
- if((m2p = mmap(NULL, m2p_size, prot,
- MAP_SHARED, xc_handle, 0)) == MAP_FAILED) {
+ if ((m2p = mmap(NULL, m2p_size, prot,
+ MAP_SHARED, xc_handle, 0)) == MAP_FAILED) {
ERR("failed to mmap m2p");
return NULL;
}
-
-
- if(!(entries = malloc(m2p_chunks * sizeof(privcmd_mmap_entry_t)))) {
+
+ if (!(entries = malloc(m2p_chunks * sizeof(privcmd_mmap_entry_t)))) {
ERR("failed to allocate space for mmap entries!\n");
return NULL;
}
-
ioctlx.num = m2p_chunks;
ioctlx.dom = DOMID_XEN;
ioctlx.entry = entries;
- for(i=0; i < m2p_chunks; i++) {
-
+ for (i=0; i < m2p_chunks; i++) {
entries[i].va = (unsigned long)(((void *)m2p) + (i * M2P_CHUNK_SIZE));
- entries[i].mfn = m2p_mfns.arr[i];
+ entries[i].mfn = xmml.extent_start[i];
entries[i].npages = M2P_CHUNK_SIZE >> PAGE_SHIFT;
-
- }
-
- if((rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx)) < 0) {
+ }
+
+ if ((rc = ioctl(xc_handle, IOCTL_PRIVCMD_MMAP, &ioctlx)) < 0) {
ERR("ioctl_mmap failed (rc = %d)", rc);
return NULL;
}
-
- free(m2p_mfns.arr);
+
+ free(xmml.extent_start);
free(entries);
return m2p;
diff -r 549130374cfa -r c3cfc4ff3b08 tools/libxc/xc_private.c
--- a/tools/libxc/xc_private.c Fri Nov 25 16:58:36 2005
+++ b/tools/libxc/xc_private.c Fri Nov 25 17:43:35 2005
@@ -190,6 +190,7 @@
{
DECLARE_HYPERCALL;
struct xen_memory_reservation *reservation = arg;
+ struct xen_machphys_mfn_list *xmml = arg;
long ret = -EINVAL;
hypercall.op = __HYPERVISOR_memory_op;
@@ -214,6 +215,20 @@
goto out1;
}
break;
+ case XENMEM_machphys_mfn_list:
+ if ( mlock(xmml, sizeof(*xmml)) != 0 )
+ {
+ PERROR("Could not mlock");
+ goto out1;
+ }
+ if ( mlock(xmml->extent_start,
+ xmml->max_extents * sizeof(unsigned long)) != 0 )
+ {
+ PERROR("Could not mlock");
+ safe_munlock(xmml, sizeof(*xmml));
+ goto out1;
+ }
+ break;
}
ret = do_xen_hypercall(xc_handle, &hypercall);
@@ -226,6 +241,11 @@
if ( reservation->extent_start != NULL )
safe_munlock(reservation->extent_start,
reservation->nr_extents * sizeof(unsigned long));
+ break;
+ case XENMEM_machphys_mfn_list:
+ safe_munlock(xmml, sizeof(*xmml));
+ safe_munlock(xmml->extent_start,
+ xmml->max_extents * sizeof(unsigned long));
break;
}
diff -r 549130374cfa -r c3cfc4ff3b08 xen/arch/x86/x86_32/mm.c
--- a/xen/arch/x86/x86_32/mm.c Fri Nov 25 16:58:36 2005
+++ b/xen/arch/x86/x86_32/mm.c Fri Nov 25 17:43:35 2005
@@ -27,6 +27,7 @@
#include <asm/page.h>
#include <asm/flushtlb.h>
#include <asm/fixmap.h>
+#include <public/memory.h>
extern l1_pgentry_t *mapcache;
@@ -184,6 +185,41 @@
}
}
+long arch_memory_op(int op, void *arg)
+{
+ struct xen_machphys_mfn_list xmml;
+ unsigned long mfn;
+ unsigned int i, max;
+ long rc = 0;
+
+ switch ( op )
+ {
+ case XENMEM_machphys_mfn_list:
+ if ( copy_from_user(&xmml, arg, sizeof(xmml)) )
+ return -EFAULT;
+
+ max = min_t(unsigned int, xmml.max_extents, mpt_size >> 21);
+
+ for ( i = 0; i < max; i++ )
+ {
+ mfn = l2e_get_pfn(idle_pg_table_l2[l2_linear_offset(
+ RDWR_MPT_VIRT_START + (i << 21))]) + l1_table_offset(i << 21);
+ if ( put_user(mfn, &xmml.extent_start[i]) )
+ return -EFAULT;
+ }
+
+ if ( put_user(i, &((struct xen_machphys_mfn_list *)arg)->nr_extents) )
+ return -EFAULT;
+
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
+}
long do_stack_switch(unsigned long ss, unsigned long esp)
{
diff -r 549130374cfa -r c3cfc4ff3b08 xen/arch/x86/x86_64/mm.c
--- a/xen/arch/x86/x86_64/mm.c Fri Nov 25 16:58:36 2005
+++ b/xen/arch/x86/x86_64/mm.c Fri Nov 25 17:43:35 2005
@@ -28,6 +28,7 @@
#include <asm/flushtlb.h>
#include <asm/fixmap.h>
#include <asm/msr.h>
+#include <public/memory.h>
struct pfn_info *alloc_xen_pagetable(void)
{
@@ -172,6 +173,51 @@
page_set_owner(&frame_table[m2p_start_mfn+i], dom_xen);
}
}
+}
+
+long arch_memory_op(int op, void *arg)
+{
+ struct xen_machphys_mfn_list xmml;
+ l3_pgentry_t l3e;
+ l2_pgentry_t l2e;
+ unsigned long mfn, v;
+ unsigned int i;
+ long rc = 0;
+
+ switch ( op )
+ {
+ case XENMEM_machphys_mfn_list:
+ if ( copy_from_user(&xmml, arg, sizeof(xmml)) )
+ return -EFAULT;
+
+ for ( v = RDWR_MPT_VIRT_START; v != RDWR_MPT_VIRT_END; v += 1 << 21 )
+ {
+ l3e = l4e_to_l3e(idle_pg_table[l4_table_offset(v)])[
+ l3_table_offset(v)];
+ if ( !(l3e_get_flags(l3e) & _PAGE_PRESENT) )
+ break;
+ l2e = l3e_to_l2e(l3e)[l2_table_offset(v)];
+ if ( !(l2e_get_flags(l2e) & _PAGE_PRESENT) )
+ break;
+ mfn = l2e_get_pfn(l2e) + l1_table_offset(v);
+ if ( i == xmml.max_extents )
+ break;
+ if ( put_user(mfn, &xmml.extent_start[i]) )
+ return -EFAULT;
+ i++;
+ }
+
+ if ( put_user(i, &((struct xen_machphys_mfn_list *)arg)->nr_extents) )
+ return -EFAULT;
+
+ break;
+
+ default:
+ rc = -ENOSYS;
+ break;
+ }
+
+ return rc;
}
long do_stack_switch(unsigned long ss, unsigned long esp)
diff -r 549130374cfa -r c3cfc4ff3b08 xen/common/memory.c
--- a/xen/common/memory.c Fri Nov 25 16:58:36 2005
+++ b/xen/common/memory.c Fri Nov 25 17:43:35 2005
@@ -215,7 +215,7 @@
break;
default:
- rc = -ENOSYS;
+ rc = arch_memory_op(op, arg);
break;
}
diff -r 549130374cfa -r c3cfc4ff3b08 xen/include/asm-ia64/mm.h
--- a/xen/include/asm-ia64/mm.h Fri Nov 25 16:58:36 2005
+++ b/xen/include/asm-ia64/mm.h Fri Nov 25 17:43:35 2005
@@ -440,4 +440,7 @@
#define __gpa_to_mpa(_d, gpa) \
((__gpfn_to_mfn((_d),(gpa)>>PAGE_SHIFT)<<PAGE_SHIFT)|((gpa)&~PAGE_MASK))
+/* Arch-specific portion of memory_op hypercall. */
+#define arch_memory_op(op, arg) (-ENOSYS)
+
#endif /* __ASM_IA64_MM_H__ */
diff -r 549130374cfa -r c3cfc4ff3b08 xen/include/asm-x86/mm.h
--- a/xen/include/asm-x86/mm.h Fri Nov 25 16:58:36 2005
+++ b/xen/include/asm-x86/mm.h Fri Nov 25 17:43:35 2005
@@ -379,6 +379,9 @@
void propagate_page_fault(unsigned long addr, u16 error_code);
-extern int __sync_lazy_execstate(void);
+int __sync_lazy_execstate(void);
+
+/* Arch-specific portion of memory_op hypercall. */
+long arch_memory_op(int op, void *arg);
#endif /* __ASM_X86_MM_H__ */
diff -r 549130374cfa -r c3cfc4ff3b08 xen/include/public/memory.h
--- a/xen/include/public/memory.h Fri Nov 25 16:58:36 2005
+++ b/xen/include/public/memory.h Fri Nov 25 17:43:35 2005
@@ -60,6 +60,34 @@
#define XENMEM_current_reservation 3
#define XENMEM_maximum_reservation 4
+/*
+ * Returns a list of MFN bases of 2MB extents comprising the machine_to_phys
+ * mapping table. Architectures which do not have a m2p table do not implement
+ * this command.
+ * arg == addr of xen_machphys_mfn_list_t.
+ */
+#define XENMEM_machphys_mfn_list 5
+typedef struct xen_machphys_mfn_list {
+ /*
+ * Size of the 'extent_start' array. Fewer entries will be filled if the
+ * machphys table is smaller than max_extents * 2MB.
+ */
+ unsigned int max_extents;
+
+ /*
+ * Pointer to buffer to fill with list of extent starts. If there are
+ * any large discontiguities in the machine address space, 2MB gaps in
+ * the machphys table will be represented by an MFN base of zero.
+ */
+ unsigned long *extent_start;
+
+ /*
+ * Number of extents written to the above array. This will be smaller
+ * than 'max_extents' if the machphys table is smaller than max_e * 2MB.
+ */
+ unsigned int nr_extents;
+} xen_machphys_mfn_list_t;
+
#endif /* __XEN_PUBLIC_MEMORY_H__ */
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|