[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 19/20] PVH xen: elf and iommu related changes to prep for dom0 PVH



This patch prepares for dom0 PVH by making some changes in the elf
code like use different copy function for PVH. Also, add check in iommu.c
to check for iommu enabled for dom0 PVH.

Changes in V2: None

Changes in V3:
   - introduct early_pvh_copy_or_zero() to replace dbg_rw_mem().

Changes in V5:
   - make v_start static and not pass it around.

Signed-off-by: Mukesh Rathor <mukesh.rathor@xxxxxxxxxx>
---
 xen/arch/x86/domain_build.c       |   40 ++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/setup.c              |    4 +++
 xen/common/libelf/libelf-loader.c |   18 ++++++++++++++++
 xen/drivers/passthrough/iommu.c   |   24 ++++++++++++++++++++-
 xen/include/asm-x86/pvh.h         |    6 +++++
 5 files changed, 89 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index 9980ea2..c5a0e0c 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -35,12 +35,14 @@
 #include <asm/setup.h>
 #include <asm/bzimage.h> /* for bzimage_parse */
 #include <asm/io_apic.h>
+#include <asm/pvh.h>
 
 #include <public/version.h>
 
 static long __initdata dom0_nrpages;
 static long __initdata dom0_min_nrpages;
 static long __initdata dom0_max_nrpages = LONG_MAX;
+static unsigned long __initdata v_start;
 
 /*
  * dom0_mem=[min:<min_amt>,][max:<max_amt>,][<amt>]
@@ -307,6 +309,43 @@ static void __init process_dom0_ioports_disable(void)
     }
 }
 
+ /*
+  * Copy or zero function for dom0 only during boot. This because
+  * raw_copy_to_guest -> copy_to_user_hvm -> __hvm_copy needs curr to
+  * point to the hvm/pvh vcpu which is not all setup yet.
+  *
+  * If src is NULL, then len bytes are zeroed.
+  */
+void __init early_pvh_copy_or_zero(unsigned long dest, const void *src, 
+                                   int len)
+{
+    while ( len > 0 )
+    {
+        char *va;
+        p2m_type_t gfntype;
+        unsigned long mfn, gfn, pagecnt;
+        struct domain *d = get_domain_by_id(0);
+
+        pagecnt = min_t(unsigned long, PAGE_SIZE - (dest & ~PAGE_MASK), len);
+
+        gfn = (dest - v_start) >> PAGE_SHIFT;
+        if ( (mfn = mfn_x(get_gfn_query(d, gfn, &gfntype))) == INVALID_MFN )
+            panic("Unable to get mfn for gfn:%lx\n", gfn);
+        put_gfn(d, gfn);
+
+        va = map_domain_page(mfn) + (dest & (PAGE_SIZE-1));
+        if ( src )
+            memcpy(va, src, pagecnt);
+        else
+            memset(va, 0, pagecnt);
+        unmap_domain_page(va);
+
+        dest += pagecnt;
+        src = src ? src + pagecnt : 0;
+        len -= pagecnt;
+    }
+}
+
 int __init construct_dom0(
     struct domain *d,
     const module_t *image, unsigned long image_headroom,
@@ -355,7 +394,6 @@ int __init construct_dom0(
     unsigned long vstack_end;
     unsigned long vpt_start;
     unsigned long vpt_end;
-    unsigned long v_start;
     unsigned long v_end;
 
     /* Machine address of next candidate page-table page. */
diff --git a/xen/arch/x86/setup.c b/xen/arch/x86/setup.c
index be541cb..6d35d1d 100644
--- a/xen/arch/x86/setup.c
+++ b/xen/arch/x86/setup.c
@@ -60,6 +60,10 @@ integer_param("maxcpus", max_cpus);
 static bool_t __initdata disable_smep;
 invbool_param("smep", disable_smep);
 
+/* Boot dom0 in PVH mode */
+bool_t __initdata opt_dom0pvh;
+boolean_param("dom0pvh", opt_dom0pvh);
+
 /* **** Linux config option: propagated to domain0. */
 /* "acpi=off":    Sisables both ACPI table parsing and interpreter. */
 /* "acpi=force":  Override the disable blacklist.                   */
diff --git a/xen/common/libelf/libelf-loader.c 
b/xen/common/libelf/libelf-loader.c
index 3cf9c59..8387b2e 100644
--- a/xen/common/libelf/libelf-loader.c
+++ b/xen/common/libelf/libelf-loader.c
@@ -16,6 +16,10 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  
USA
  */
 
+#ifdef __XEN__
+#include <asm/pvh.h>
+#endif
+
 #include "libelf-private.h"
 
 /* ------------------------------------------------------------------------ */
@@ -127,6 +131,16 @@ static int elf_load_image(void *dst, const void *src, 
uint64_t filesz, uint64_t
     int rc;
     if ( filesz > ULONG_MAX || memsz > ULONG_MAX )
         return -1;
+
+    if ( opt_dom0pvh )
+    {
+        unsigned long addr = (unsigned long)dst;
+        early_pvh_copy_or_zero(addr, src, filesz);
+        early_pvh_copy_or_zero(addr + filesz, NULL, memsz - filesz);
+
+        return 0;
+    }
+
     rc = raw_copy_to_guest(dst, src, filesz);
     if ( rc != 0 )
         return -1;
@@ -260,6 +274,10 @@ void elf_parse_binary(struct elf_binary *elf)
             __FUNCTION__, elf->pstart, elf->pend);
 }
 
+/*
+ * This function called from the libraries when building guests, and also for
+ * dom0 from construct_dom0().
+ */
 int elf_load_binary(struct elf_binary *elf)
 {
     const elf_phdr *phdr;
diff --git a/xen/drivers/passthrough/iommu.c b/xen/drivers/passthrough/iommu.c
index 93ad122..0dfbd3c 100644
--- a/xen/drivers/passthrough/iommu.c
+++ b/xen/drivers/passthrough/iommu.c
@@ -125,15 +125,27 @@ int iommu_domain_init(struct domain *d)
     return hd->platform_ops->init(d);
 }
 
+static inline void check_dom0_pvh_reqs(struct domain *d)
+{
+    if ( !iommu_enabled )
+        panic("For pvh dom0, iommu must be enabled\n");
+
+    if ( iommu_passthrough )
+        panic("For pvh dom0, dom0-passthrough must not be enabled\n");
+}
+
 void __init iommu_dom0_init(struct domain *d)
 {
     struct hvm_iommu *hd = domain_hvm_iommu(d);
 
+    if ( is_pvh_domain(d) )
+        check_dom0_pvh_reqs(d);
+
     if ( !iommu_enabled )
         return;
 
     register_keyhandler('o', &iommu_p2m_table);
-    d->need_iommu = !!iommu_dom0_strict;
+    d->need_iommu = is_pvh_domain(d) || !!iommu_dom0_strict;
     if ( need_iommu(d) )
     {
         struct page_info *page;
@@ -146,7 +158,15 @@ void __init iommu_dom0_init(struct domain *d)
                  ((page->u.inuse.type_info & PGT_type_mask)
                   == PGT_writable_page) )
                 mapping |= IOMMUF_writable;
-            hd->platform_ops->map_page(d, mfn, mfn, mapping);
+
+            if ( is_pvh_domain(d) )
+            {
+                unsigned long gfn = mfn_to_gfn(d, _mfn(mfn));
+                hd->platform_ops->map_page(d, gfn, mfn, mapping);
+            }
+            else
+                hd->platform_ops->map_page(d, mfn, mfn, mapping);
+
             if ( !(i++ & 0xfffff) )
                 process_pending_softirqs();
         }
diff --git a/xen/include/asm-x86/pvh.h b/xen/include/asm-x86/pvh.h
index 73e59d3..849c7d7 100644
--- a/xen/include/asm-x86/pvh.h
+++ b/xen/include/asm-x86/pvh.h
@@ -1,6 +1,12 @@
 #ifndef __ASM_X86_PVH_H__
 #define __ASM_X86_PVH_H__
 
+#include <asm/types.h>
+
+struct cpu_user_regs;   
 int pvh_do_hypercall(struct cpu_user_regs *regs);
 
+extern bool_t opt_dom0pvh;
+void early_pvh_copy_or_zero(unsigned long dest, const void *src, int len);
+
 #endif  /* __ASM_X86_PVH_H__ */
-- 
1.7.2.3


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.