WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [linux-2.6.18-xen] [IA64] Foreign p2m: linux side

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [linux-2.6.18-xen] [IA64] Foreign p2m: linux side
From: "Xen patchbot-linux-2.6.18-xen" <patchbot-linux-2.6.18-xen@xxxxxxxxxxxxxxxxxxx>
Date: Tue, 11 Sep 2007 15:31:09 -0700
Delivery-date: Tue, 11 Sep 2007 15:36:12 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/cgi-bin/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Alex Williamson <alex.williamson@xxxxxx>
# Date 1189110805 21600
# Node ID e1466633683cf0bdba9ef905d0a79702ba05a751
# Parent  d796a96253a23957b61b07c73301768da6f970ec
[IA64] Foreign p2m: linux side

Signed-off-by: Isaku Yamahata <yamahata@xxxxxxxxxxxxx>
---
 arch/ia64/xen/hypervisor.c        |  223 ++++++++++++++++++++++++++++++++++++--
 arch/ia64/xen/xcom_hcall.c        |    6 -
 arch/ia64/xen/xcom_privcmd.c      |    3 
 include/asm-ia64/hypercall.h      |   17 ++
 include/asm-ia64/xen/xcom_hcall.h |    2 
 include/xen/interface/arch-ia64.h |    7 +
 6 files changed, 251 insertions(+), 7 deletions(-)

diff -r d796a96253a2 -r e1466633683c arch/ia64/xen/hypervisor.c
--- a/arch/ia64/xen/hypervisor.c        Thu Sep 06 12:05:58 2007 -0600
+++ b/arch/ia64/xen/hypervisor.c        Thu Sep 06 14:33:25 2007 -0600
@@ -584,6 +584,10 @@ struct xen_ia64_privcmd_range {
        unsigned long                   pgoff; // in PAGE_SIZE
        struct resource*                res;
 
+       // for foreign domain p2m mapping
+       void*                           private;
+       void (*callback)(struct xen_ia64_privcmd_range* range, void* arg);
+
        unsigned long                   num_entries;
        struct xen_ia64_privcmd_entry   entries[0];
 };
@@ -765,6 +769,9 @@ xen_ia64_privcmd_vma_close(struct vm_are
                        BUG_ON(entry->gpfn != INVALID_GPFN);
                }
 #endif
+               if (privcmd_range->callback)
+                       (*privcmd_range->callback)(privcmd_range,
+                                                  privcmd_range->private);
                release_resource(privcmd_range->res);
                kfree(privcmd_range->res);
                vfree(privcmd_range);
@@ -825,6 +832,8 @@ privcmd_mmap(struct file * file, struct 
        atomic_set(&privcmd_range->ref_count, 1);
        privcmd_range->pgoff = vma->vm_pgoff;
        privcmd_range->num_entries = num_entries;
+       privcmd_range->private = NULL;
+       privcmd_range->callback = NULL;
        for (i = 0; i < privcmd_range->num_entries; i++) {
                xen_ia64_privcmd_init_entry(&privcmd_range->entries[i]);
        }
@@ -979,6 +988,12 @@ static struct notifier_block p2m_expose_
 };
 #endif
 
+static inline unsigned long
+p2m_table_size(unsigned long num_pfn)
+{
+       return ((num_pfn + PTRS_PER_PTE - 1) / PTRS_PER_PTE) << PAGE_SHIFT;
+}
+
 static int
 p2m_expose_init(void)
 {
@@ -1018,8 +1033,7 @@ p2m_expose_init(void)
        if (xen_ia64_p2m_expose_use_dtr) {
                unsigned long page_size = 0;
                unsigned long granule_pfn = 0;
-               p2m_size = ((p2m_max_low_pfn - p2m_min_low_pfn +
-                            PTRS_PER_PTE - 1) / PTRS_PER_PTE) << PAGE_SHIFT;
+               p2m_size = p2m_table_size(p2m_max_low_pfn - p2m_min_low_pfn);
                for (i = 0;
                     i < sizeof(p2m_page_shifts)/sizeof(p2m_page_shifts[0]);
                     i++) {
@@ -1036,8 +1050,7 @@ p2m_expose_init(void)
                                                      granule_pfn);
                        num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
                        p2m_expose_size = num_pfn << PAGE_SHIFT;
-                       p2m_size = ((num_pfn + PTRS_PER_PTE - 1) /
-                                   PTRS_PER_PTE) << PAGE_SHIFT;
+                       p2m_size = p2m_table_size(num_pfn);
                        p2m_size = ROUNDUP(p2m_size, granule_pfn << PAGE_SHIFT);
                        if (p2m_size == page_size)
                                break;
@@ -1057,8 +1070,7 @@ p2m_expose_init(void)
                p2m_convert_max_pfn = ROUNDUP(p2m_max_low_pfn, p2m_granule_pfn);
                num_pfn = p2m_convert_max_pfn - p2m_convert_min_pfn;
                p2m_expose_size = num_pfn << PAGE_SHIFT;
-               p2m_size = ((num_pfn + PTRS_PER_PTE - 1) / PTRS_PER_PTE) <<
-                       PAGE_SHIFT;
+               p2m_size = p2m_table_size(num_pfn);
                p2m_size = ROUNDUP(p2m_size, p2m_granule_pfn << PAGE_SHIFT);
                align = max(privcmd_resource_align,
                            p2m_granule_pfn << PAGE_SHIFT);
@@ -1204,6 +1216,205 @@ EXPORT_SYMBOL_GPL(p2m_convert_max_pfn);
 EXPORT_SYMBOL_GPL(p2m_convert_max_pfn);
 EXPORT_SYMBOL_GPL(p2m_pte);
 EXPORT_SYMBOL_GPL(p2m_phystomach);
+
+///////////////////////////////////////////////////////////////////////////
+// foreign domain p2m mapping
+#include <asm/xen/xencomm.h>
+#include <xen/public/privcmd.h>
+
+struct foreign_p2m_private {
+       unsigned long   gpfn;
+       domid_t         domid;
+};
+
+static void
+xen_foreign_p2m_unexpose(struct xen_ia64_privcmd_range* privcmd_range,
+                        void* arg)
+{
+       struct foreign_p2m_private* private = (struct foreign_p2m_private*)arg;
+       int ret;
+
+       privcmd_range->private = NULL;
+       privcmd_range->callback = NULL;
+
+       ret = HYPERVISOR_unexpose_foreign_p2m(private->gpfn, private->domid);
+       if (ret)
+               printk(KERN_WARNING
+                      "unexpose_foreign_p2m hypercall failed.\n");
+       kfree(private);
+}
+
+int
+xen_foreign_p2m_expose(privcmd_hypercall_t* hypercall)
+{
+       // hypercall->
+       // arg0: cmd = IA64_DOM0VP_expose_foreign_p2m
+       // arg1: va
+       // arg2: domid
+       // arg3: __user* memmap_info
+       // arg4: flags
+
+       int ret = 0;
+       struct mm_struct* mm = current->mm;
+
+       unsigned long vaddr = hypercall->arg[1];
+       domid_t domid = hypercall->arg[2];
+       struct xen_ia64_memmap_info __user *u_memmap_info =
+               (struct xen_ia64_memmap_info __user *)hypercall->arg[3];
+
+       struct xen_ia64_memmap_info memmap_info;
+       size_t memmap_size;
+       struct xen_ia64_memmap_info* k_memmap_info = NULL;
+       unsigned long max_gpfn;
+       unsigned long p2m_size;
+       struct resource* res;
+       unsigned long gpfn;
+
+       struct vm_area_struct* vma;
+       void* p;
+       unsigned long prev_src_gpfn_end;
+
+       struct xen_ia64_privcmd_vma* privcmd_vma;
+       struct xen_ia64_privcmd_range* privcmd_range;
+       struct foreign_p2m_private* private = NULL;
+
+       BUG_ON(hypercall->arg[0] != IA64_DOM0VP_expose_foreign_p2m);
+
+       private = kmalloc(sizeof(*private), GFP_KERNEL);
+       if (private == NULL)
+               goto kfree_out;
+
+       if (copy_from_user(&memmap_info, u_memmap_info, sizeof(memmap_info)))
+               return -EFAULT;
+       /* memmap_info integrity check */
+       if (memmap_info.efi_memdesc_size < sizeof(efi_memory_desc_t) ||
+           memmap_info.efi_memmap_size < memmap_info.efi_memdesc_size ||
+           (memmap_info.efi_memmap_size % memmap_info.efi_memdesc_size)
+           != 0) {
+               ret = -EINVAL;
+               goto kfree_out;
+       }
+
+       memmap_size = sizeof(*k_memmap_info) + memmap_info.efi_memmap_size;
+       k_memmap_info = kmalloc(memmap_size, GFP_KERNEL);
+       if (k_memmap_info == NULL)
+               return -ENOMEM;
+       if (copy_from_user(k_memmap_info, u_memmap_info, memmap_size)) {
+               ret = -EFAULT;
+               goto kfree_out;
+       }
+       /* k_memmap_info integrity check is done by the expose foreng p2m 
+          hypercall */
+
+       max_gpfn = HYPERVISOR_memory_op(XENMEM_maximum_gpfn, &domid);
+       if (max_gpfn < 0) {
+               ret = max_gpfn;
+               goto kfree_out;
+       }
+       p2m_size = p2m_table_size(max_gpfn + 1);
+
+       down_write(&mm->mmap_sem);
+
+       vma = find_vma(mm, vaddr);
+       if (vma == NULL || vma->vm_ops != &xen_ia64_privcmd_vm_ops ||
+           vaddr != vma->vm_start ||
+           (vma->vm_flags & VM_WRITE) || (vma->vm_flags & VM_EXEC) ||
+           !privcmd_enforce_singleshot_mapping(vma))
+               goto mmap_out;
+
+       privcmd_vma = (struct xen_ia64_privcmd_vma*)vma->vm_private_data;
+       res = privcmd_vma->range->res;
+       if (p2m_size > (res->end - res->start + 1) ||
+           p2m_size > vma->vm_end - vma->vm_start) {
+               ret = -EINVAL;
+               goto mmap_out;
+       }
+       
+       gpfn = res->start >> PAGE_SHIFT;
+       // arg0: dest_gpfn
+       // arg1: domid
+       // arg2: XEN_GUEST_HANDLE(char) buffer: memmap_info
+       // arg3: flags
+       // The hypercall checks its intergirty/simplfies it and 
+       // copy it back for us.
+       ret = xencomm_arch_expose_foreign_p2m(gpfn, domid,
+             xencomm_map_no_alloc(k_memmap_info, memmap_size),
+             hypercall->arg[4]);
+       if (ret)
+               goto mmap_out;
+
+       privcmd_range = (struct xen_ia64_privcmd_range*)privcmd_vma->range;
+       prev_src_gpfn_end = 0;
+       for (p = k_memmap_info->memdesc;
+            p < (void*)&k_memmap_info->memdesc[0] +
+                    k_memmap_info->efi_memmap_size;
+            p += k_memmap_info->efi_memdesc_size) {
+               efi_memory_desc_t* md = p;
+               unsigned long src_gpfn = md->phys_addr >> PAGE_SHIFT;
+               unsigned long src_gpfn_end =
+                       (md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT)) >>
+                       PAGE_SHIFT;
+               unsigned long num_src_gpfn;
+               unsigned long gpfn_offset;
+               unsigned long size;
+               unsigned int i;
+
+               if (src_gpfn <= prev_src_gpfn_end)
+                       src_gpfn = prev_src_gpfn_end + 1;
+               if (src_gpfn_end <= prev_src_gpfn_end)
+                       continue;
+
+               src_gpfn &= ~(PTRS_PER_PTE - 1);
+               src_gpfn_end = (src_gpfn_end + PTRS_PER_PTE - 1) &
+                       ~(PTRS_PER_PTE - 1);
+               num_src_gpfn = src_gpfn_end - src_gpfn;
+               gpfn_offset = src_gpfn / PTRS_PER_PTE;
+               size = p2m_table_size(num_src_gpfn);
+
+               prev_src_gpfn_end = src_gpfn_end;
+               ret = remap_pfn_range(vma,
+                                     vaddr + (gpfn_offset << PAGE_SHIFT), 
+                                     gpfn + gpfn_offset, size,
+                                     vma->vm_page_prot);
+               if (ret) {
+                       for (i = 0; i < gpfn + gpfn_offset; i++) {
+                               struct xen_ia64_privcmd_entry* entry =
+                                       &privcmd_range->entries[i];
+                               BUG_ON(atomic_read(&entry->map_count) != 1 &&
+                                      atomic_read(&entry->map_count) != 0);
+                               atomic_set(&entry->map_count, 0);
+                               entry->gpfn = INVALID_GPFN;
+                       }
+                       (void)HYPERVISOR_unexpose_foreign_p2m(gpfn, domid);
+                       goto mmap_out;
+               }
+
+               for (i = gpfn_offset;
+                    i < gpfn_offset + (size >> PAGE_SHIFT);
+                    i++) {
+                       struct xen_ia64_privcmd_entry* entry =
+                               &privcmd_range->entries[i];
+                       BUG_ON(atomic_read(&entry->map_count) != 0);
+                       BUG_ON(entry->gpfn != INVALID_GPFN);
+                       atomic_inc(&entry->map_count);
+                       entry->gpfn = gpfn + i;
+               }
+       }
+
+       private->gpfn = gpfn;
+       private->domid = domid;
+
+       privcmd_range->callback = &xen_foreign_p2m_unexpose;
+       privcmd_range->private = private;
+
+mmap_out:
+       up_write(&mm->mmap_sem);
+kfree_out:
+       kfree(k_memmap_info);
+       if (ret != 0)
+               kfree(private);
+       return ret;
+}
 #endif
 
 ///////////////////////////////////////////////////////////////////////////
diff -r d796a96253a2 -r e1466633683c arch/ia64/xen/xcom_hcall.c
--- a/arch/ia64/xen/xcom_hcall.c        Thu Sep 06 12:05:58 2007 -0600
+++ b/arch/ia64/xen/xcom_hcall.c        Thu Sep 06 14:33:25 2007 -0600
@@ -381,7 +381,11 @@ xencomm_hypercall_memory_op(unsigned int
                        return rc;
                xc_area++;
                break;
-               
+
+       case XENMEM_maximum_gpfn:
+               argsize = 0;
+               break;
+
        case XENMEM_maximum_ram_page:
                argsize = 0;
                break;
diff -r d796a96253a2 -r e1466633683c arch/ia64/xen/xcom_privcmd.c
--- a/arch/ia64/xen/xcom_privcmd.c      Thu Sep 06 12:05:58 2007 -0600
+++ b/arch/ia64/xen/xcom_privcmd.c      Thu Sep 06 14:33:25 2007 -0600
@@ -732,6 +732,9 @@ xencomm_privcmd_ia64_dom0vp_op(privcmd_h
                        ret = -EFAULT;
                break;
        }
+       case IA64_DOM0VP_expose_foreign_p2m:
+               ret = xen_foreign_p2m_expose(hypercall);
+               break;
        default:
                printk("%s: unknown IA64 DOM0VP op %d\n", __func__, cmd);
                ret = -EINVAL;
diff -r d796a96253a2 -r e1466633683c include/asm-ia64/hypercall.h
--- a/include/asm-ia64/hypercall.h      Thu Sep 06 12:05:58 2007 -0600
+++ b/include/asm-ia64/hypercall.h      Thu Sep 06 14:33:25 2007 -0600
@@ -373,6 +373,23 @@ HYPERVISOR_expose_p2m(unsigned long conv
        return _hypercall5(unsigned long, ia64_dom0vp_op,
                           IA64_DOM0VP_expose_p2m, conv_start_gpfn,
                           assign_start_gpfn, expose_size, granule_pfn);
+}
+
+static inline int
+xencomm_arch_expose_foreign_p2m(unsigned long gpfn,
+                               domid_t domid, struct xencomm_handle *arg,
+                               unsigned long flags)
+{
+       return _hypercall5(int, ia64_dom0vp_op,
+                          IA64_DOM0VP_expose_foreign_p2m,
+                          gpfn, domid, arg, flags);
+}
+
+static inline int
+HYPERVISOR_unexpose_foreign_p2m(unsigned long gpfn, domid_t domid)
+{
+       return _hypercall3(int, ia64_dom0vp_op,
+                          IA64_DOM0VP_unexpose_foreign_p2m, gpfn, domid);
 }
 #endif
 
diff -r d796a96253a2 -r e1466633683c include/asm-ia64/xen/xcom_hcall.h
--- a/include/asm-ia64/xen/xcom_hcall.h Thu Sep 06 12:05:58 2007 -0600
+++ b/include/asm-ia64/xen/xcom_hcall.h Thu Sep 06 14:33:25 2007 -0600
@@ -60,4 +60,6 @@ struct privcmd_hypercall;
 struct privcmd_hypercall;
 extern int privcmd_hypercall(struct privcmd_hypercall *hypercall);
 
+extern int xen_foreign_p2m_expose(struct privcmd_hypercall *hypercall);
+
 #endif /* _LINUX_XENCOMM_HCALL_H_ */
diff -r d796a96253a2 -r e1466633683c include/xen/interface/arch-ia64.h
--- a/include/xen/interface/arch-ia64.h Thu Sep 06 12:05:58 2007 -0600
+++ b/include/xen/interface/arch-ia64.h Thu Sep 06 14:33:25 2007 -0600
@@ -470,6 +470,13 @@ DEFINE_XEN_GUEST_HANDLE(vcpu_guest_conte
 /* Add an I/O port space range */
 #define IA64_DOM0VP_add_io_space        11
 
+/* expose the foreign domain's p2m table into privileged domain */
+#define IA64_DOM0VP_expose_foreign_p2m  12
+#define         IA64_DOM0VP_EFP_ALLOC_PTE       0x1 /* allocate p2m table */
+
+/* unexpose the foreign domain's p2m table into privileged domain */
+#define IA64_DOM0VP_unexpose_foreign_p2m        13
+
 // flags for page assignement to pseudo physical address space
 #define _ASSIGN_readonly                0
 #define ASSIGN_readonly                 (1UL << _ASSIGN_readonly)

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [linux-2.6.18-xen] [IA64] Foreign p2m: linux side, Xen patchbot-linux-2.6.18-xen <=