diff mbox

[v7,4/7] x86/libelf: pass the destination vCPU to libelf for Dom0 build

Message ID 20170222142459.28199-5-roger.pau@citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Roger Pau Monné Feb. 22, 2017, 2:24 p.m. UTC
Allow setting the destination vCPU for libelf, so that elf_load_image can take
it into account when loading the kernel for Dom0. This is needed for PVHv2 Dom0
build, so that hvm_copy_to_guest_phys can be called with a Dom0 vCPU instead of
current (that contains the idle vCPU at this point).

Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
---
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
---
Changes since v6:
 - New in this version.
---
 xen/arch/x86/domain_build.c       |  1 +
 xen/common/libelf/libelf-loader.c | 25 +++++++++++++++++++++++--
 xen/include/xen/libelf.h          |  6 ++++++
 3 files changed, 30 insertions(+), 2 deletions(-)

Comments

Jan Beulich Feb. 23, 2017, 1:47 p.m. UTC | #1
>>> On 22.02.17 at 15:24, <roger.pau@citrix.com> wrote:
> Allow setting the destination vCPU for libelf, so that elf_load_image can take
> it into account when loading the kernel for Dom0. This is needed for PVHv2 Dom0
> build, so that hvm_copy_to_guest_phys can be called with a Dom0 vCPU instead of
> current (that contains the idle vCPU at this point).
> 
> Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>

Reviewed-by: Jan Beulich <jbeulich@suse.com>
albeit ...

> --- a/xen/common/libelf/libelf-loader.c
> +++ b/xen/common/libelf/libelf-loader.c
> @@ -146,6 +146,25 @@ void elf_set_verbose(struct elf_binary *elf)
>      elf->verbose = 1;
>  }
>  
> +static elf_errorstatus elf_memcpy(struct vcpu *v, void *dst, void *src,
> +                                  uint64_t size)
> +{
> +    int rc = 0;
> +
> +#ifdef CONFIG_X86
> +    if ( is_hvm_vcpu(v) )
> +    {
> +        rc = hvm_copy_to_guest_phys((paddr_t)dst, src, size, v);
> +        rc = rc != HVMCOPY_okay ? -1 : 0;
> +    }
> +    else
> +#endif
> +        rc = src == NULL ? raw_clear_guest(dst, size) :
> +                           raw_copy_to_guest(dst, src, size);
> +
> +    return rc;
> +}

... elf_errorstatus is not a correct type for the return values of
raw_{copy_to,clear}_guest(). Nevertheless that's in line with ...

> static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
> {
>     elf_errorstatus rc;

... the variable declared here having been used ...

> @@ -153,10 +172,12 @@ static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, el
>          return -1;
>      /* We trust the dom0 kernel image completely, so we don't care
>       * about overruns etc. here. */
> -    rc = raw_copy_to_guest(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), filesz);
> +    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src),
> +                    filesz);
>      if ( rc != 0 )
>          return -1;
> -    rc = raw_clear_guest(ELF_UNSAFE_PTR(dst + filesz), memsz - filesz);
> +    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst + filesz), NULL,
> +                    memsz - filesz);

... the same (wrong) way, so should be good enough for now.
Ideally the setting of rc in elf_memcpy() would be corrected, though.

Jan
diff mbox

Patch

diff --git a/xen/arch/x86/domain_build.c b/xen/arch/x86/domain_build.c
index aa1625a..d2a1105 100644
--- a/xen/arch/x86/domain_build.c
+++ b/xen/arch/x86/domain_build.c
@@ -1462,6 +1462,7 @@  static int __init construct_dom0_pv(
     /* Copy the OS image and free temporary buffer. */
     elf.dest_base = (void*)vkern_start;
     elf.dest_size = vkern_end - vkern_start;
+    elf_set_vcpu(&elf, v);
     rc = elf_load_binary(&elf);
     if ( rc < 0 )
     {
diff --git a/xen/common/libelf/libelf-loader.c b/xen/common/libelf/libelf-loader.c
index 1644f16..371061c 100644
--- a/xen/common/libelf/libelf-loader.c
+++ b/xen/common/libelf/libelf-loader.c
@@ -146,6 +146,25 @@  void elf_set_verbose(struct elf_binary *elf)
     elf->verbose = 1;
 }
 
+static elf_errorstatus elf_memcpy(struct vcpu *v, void *dst, void *src,
+                                  uint64_t size)
+{
+    int rc = 0;
+
+#ifdef CONFIG_X86
+    if ( is_hvm_vcpu(v) )
+    {
+        rc = hvm_copy_to_guest_phys((paddr_t)dst, src, size, v);
+        rc = rc != HVMCOPY_okay ? -1 : 0;
+    }
+    else
+#endif
+        rc = src == NULL ? raw_clear_guest(dst, size) :
+                           raw_copy_to_guest(dst, src, size);
+
+    return rc;
+}
+
 static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, elf_ptrval src, uint64_t filesz, uint64_t memsz)
 {
     elf_errorstatus rc;
@@ -153,10 +172,12 @@  static elf_errorstatus elf_load_image(struct elf_binary *elf, elf_ptrval dst, el
         return -1;
     /* We trust the dom0 kernel image completely, so we don't care
      * about overruns etc. here. */
-    rc = raw_copy_to_guest(ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src), filesz);
+    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst), ELF_UNSAFE_PTR(src),
+                    filesz);
     if ( rc != 0 )
         return -1;
-    rc = raw_clear_guest(ELF_UNSAFE_PTR(dst + filesz), memsz - filesz);
+    rc = elf_memcpy(elf->vcpu, ELF_UNSAFE_PTR(dst + filesz), NULL,
+                    memsz - filesz);
     if ( rc != 0 )
         return -1;
     return 0;
diff --git a/xen/include/xen/libelf.h b/xen/include/xen/libelf.h
index 1b763f3..b739981 100644
--- a/xen/include/xen/libelf.h
+++ b/xen/include/xen/libelf.h
@@ -212,6 +212,8 @@  struct elf_binary {
     /* misc */
     elf_log_callback *log_callback;
     void *log_caller_data;
+#else
+    struct vcpu *vcpu;
 #endif
     bool verbose;
     const char *broken;
@@ -351,6 +353,10 @@  elf_errorstatus elf_init(struct elf_binary *elf, const char *image, size_t size)
    */
 #ifdef __XEN__
 void elf_set_verbose(struct elf_binary *elf);
+static inline void elf_set_vcpu(struct elf_binary *elf, struct vcpu *v)
+{
+    elf->vcpu = v;
+}
 #else
 void elf_set_log(struct elf_binary *elf, elf_log_callback*,
                  void *log_caller_pointer, bool verbose);