xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5] Livepatch for ARM 64 and 32.
@ 2016-09-21 17:32 Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/ Konrad Rzeszutek Wilk
                   ` (15 more replies)
  0 siblings, 16 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall

Hey!
Since v4:[https://lists.xen.org/archives/html/xen-devel/2016-09/msg01734.html]
 - Added Acks/Reviewed-by
 - Reworked "arm: poison initmem when it is freed." and
   "xen/arm32: Add an helper to invalidate all instruction caches"
 - Moved "livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH" to
   be in front of "livepatch: tests: Make them compile under ARM64"
 - Fixed up code as suggested by reviewers.

v3: [https://lists.xen.org/archives/html/xen-devel/2016-09/msg01127.html]
 - Addressed Jan's comment (most are renaming)
 - Addressed Julien's and Jan's idea of HAS_ALTERNATIVE
 - Addressed Julien's review comments of "arm: poison initmem when it is freed."

v2: [http://www.gossamer-threads.com/lists/xen/devel/444461?page=last]
 - Addressed the two outstanding concerns: CPU bit feature to test alternative
   test-case, and errata #843419 on some Cortex-A53 
 - Dealt with comments from Jan, Julien and Andrew.
 - Fixed (offlist) with Julien ARM32 not branching properly.
 - Committed some of the patches that had been reviewed/Acked.

v1 (and RFC): 
[https://lists.xen.org/archives/html/xen-devel/2016-08/msg01835.html]
 - Acted on most all comments.
 - Added ARM 32 support.

The patches are based on: [PATCH v7] Livepatch fixes and features for v4.8.
https://lists.xen.org/archives/html/xen-devel/2016-09/msg02305.html

And the git tree is:
 git://xenbits.xen.org/people/konradwilk/xen.git livepatch.v4.8.v7

These patches enable livepatching to work on ARM64 and ARM32. They have
been tested on multi-CPU environments (Foundation Model, 4CPU for ARM64;
and ARM CubieTruck for ARM32).

The state of the patches is as follow:

Legend:
 r - Reviewed
 a - Acked


    arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/
a   arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]
 r  livepatch: Reject payloads with .alternative or .ex_table if support is not built-in.
    arm: poison initmem when it is freed.
a   livepatch: Initial ARM64 support.
    livepatch: ARM/x86: Check displacement of old_addr and new_addr
 r  livepatch: ARM 32|64: Ignore mapping symbols: $[d,a,x]
    livepatch/arm/x86: Check payload for for unwelcomed symbols.
a   livepatch: Move test-cases to their own sub-directory in test.
    livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH
    livepatch: tests: Make them compile under ARM64
    xen/arm32: Add an helper to invalidate all instruction caches
ar  bug/x86/arm: Align bug_frames sections.
a   livepatch: Initial ARM32 support.
a   livepatch, arm[32|64]: Share arch_livepatch_revert
    livepatch: arm[32,64],x86: NOP test-case

Please review!

Konrad Rzeszutek Wilk (16):
      arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/
      arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]
      livepatch: Reject payloads with .alternative or .ex_table if support is not built-in.
      arm: poison initmem when it is freed.
      livepatch: Initial ARM64 support.
      livepatch: ARM/x86: Check displacement of old_addr and new_addr
      livepatch: ARM 32|64: Ignore mapping symbols: $[d,a,x]
      livepatch/arm/x86: Check payload for for unwelcomed symbols.
      livepatch: Move test-cases to their own sub-directory in test.
      livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH
      livepatch: tests: Make them compile under ARM64
      xen/arm32: Add an helper to invalidate all instruction caches
      bug/x86/arm: Align bug_frames sections.
      livepatch: Initial ARM32 support.
      livepatch, arm[32|64]: Share arch_livepatch_revert
      livepatch: arm[32,64],x86: NOP test-case

 .gitignore                                  |   8 +-
 MAINTAINERS                                 |   2 +
 docs/misc/livepatch.markdown                |  17 +-
 xen/Makefile                                |   5 +-
 xen/arch/arm/Kconfig                        |   7 +-
 xen/arch/arm/Makefile                       |  18 +-
 xen/arch/arm/arm32/Makefile                 |   1 +
 xen/arch/arm/arm32/livepatch.c              | 298 +++++++++++++++++
 xen/arch/arm/arm64/Makefile                 |   1 +
 xen/arch/arm/arm64/livepatch.c              | 481 ++++++++++++++++++++++++++++
 xen/arch/arm/domain.c                       |   6 +
 xen/arch/arm/livepatch.c                    | 159 +++++++--
 xen/arch/arm/mm.c                           |  15 +-
 xen/arch/arm/traps.c                        |   6 +
 xen/arch/arm/xen.lds.S                      |   8 +-
 xen/arch/x86/Kconfig                        |   2 +
 xen/arch/x86/Makefile                       |   5 -
 xen/arch/x86/livepatch.c                    |  14 +
 xen/arch/x86/test/Makefile                  |  85 -----
 xen/arch/x86/test/xen_bye_world.c           |  34 --
 xen/arch/x86/test/xen_bye_world_func.c      |  22 --
 xen/arch/x86/test/xen_hello_world.c         |  67 ----
 xen/arch/x86/test/xen_hello_world_func.c    |  39 ---
 xen/arch/x86/test/xen_replace_world.c       |  33 --
 xen/arch/x86/test/xen_replace_world_func.c  |  22 --
 xen/arch/x86/xen.lds.S                      |   1 -
 xen/common/Kconfig                          |   8 +-
 xen/common/livepatch.c                      |  20 +-
 xen/common/livepatch_elf.c                  |   7 +
 xen/include/asm-arm/alternative.h           |   4 +-
 xen/include/asm-arm/arm32/page.h            |  16 +
 xen/include/asm-arm/bug.h                   |   1 +
 xen/include/asm-arm/config.h                |   5 +
 xen/include/asm-arm/cpuerrata.h             |   4 +-
 xen/include/asm-arm/cpufeature.h            |   3 +-
 xen/include/asm-arm/livepatch.h             |  39 +++
 xen/include/asm-x86/bug.h                   |   1 +
 xen/include/asm-x86/livepatch.h             |   4 +
 xen/include/xen/elfstructs.h                |  79 ++++-
 xen/include/xen/livepatch.h                 |  21 +-
 xen/include/xen/types.h                     |   9 +
 xen/test/Makefile                           |   7 +
 xen/test/livepatch/Makefile                 | 109 +++++++
 xen/test/livepatch/xen_bye_world.c          |  34 ++
 xen/test/livepatch/xen_bye_world_func.c     |  22 ++
 xen/test/livepatch/xen_hello_world.c        |  67 ++++
 xen/test/livepatch/xen_hello_world_func.c   |  47 +++
 xen/test/livepatch/xen_nop.c                |  49 +++
 xen/test/livepatch/xen_replace_world.c      |  33 ++
 xen/test/livepatch/xen_replace_world_func.c |  22 ++
 50 files changed, 1610 insertions(+), 357 deletions(-)

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:21   ` Julien Grall
  2016-09-21 17:32 ` [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE] Konrad Rzeszutek Wilk
                   ` (14 subsequent siblings)
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Doug Goldstein, Jan Beulich, Konrad Rzeszutek Wilk

No functional change. We resist the temptation to move
the entries in the Kconfig file to be more in alphabetical
order as the "arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]"
will move one of the entries to common file.

Suggested-by: Jan Beulich <JBeulich@suse.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Doug Goldstein <cardoe@cardoe.com>

v4: New submission.
    [Forgot to post as part of the patch series, included as
    inline reply to one of the patches].
v5: Don't sort the HAS_ALTERNATIVE and HAS_GICV3 in alphabetical
    order.
---
 xen/arch/arm/Kconfig              | 6 +++---
 xen/arch/arm/Makefile             | 2 +-
 xen/arch/arm/xen.lds.S            | 2 +-
 xen/include/asm-arm/alternative.h | 4 ++--
 xen/include/asm-arm/cpuerrata.h   | 4 ++--
 5 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 797c91f..558d013 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -12,8 +12,8 @@ config ARM_32
 config ARM_64
 	def_bool y
 	depends on 64BIT
+	select HAS_ALTERNATIVE
 	select HAS_GICV3
-	select ALTERNATIVE
 
 config ARM
 	def_bool y
@@ -45,13 +45,13 @@ config ACPI
 config HAS_GICV3
 	bool
 
-config ALTERNATIVE
+config HAS_ALTERNATIVE
 	bool
 
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
-	depends on ALTERNATIVE
+	depends on HAS_ALTERNATIVE
 
 config ARM64_ERRATUM_827319
 	bool "Cortex-A53: 827319: Data cache clean instructions might cause overlapping transactions to the interconnect"
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 64fdf41..61e655b 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -4,7 +4,7 @@ subdir-y += platforms
 subdir-$(CONFIG_ARM_64) += efi
 subdir-$(CONFIG_ACPI) += acpi
 
-obj-$(CONFIG_ALTERNATIVE) += alternative.o
+obj-$(CONFIG_HAS_ALTERNATIVE) += alternative.o
 obj-y += bootfdt.o
 obj-y += cpu.o
 obj-y += cpuerrata.o
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 3c5e7ba..47b910d 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -151,7 +151,7 @@ SECTIONS
        *(.initcall1.init)
        __initcall_end = .;
 
-#ifdef CONFIG_ALTERNATIVE
+#ifdef CONFIG_HAS_ALTERNATIVE
        . = ALIGN(4);
        __alt_instructions = .;
        *(.altinstructions)
diff --git a/xen/include/asm-arm/alternative.h b/xen/include/asm-arm/alternative.h
index 9f88fd9..6851217 100644
--- a/xen/include/asm-arm/alternative.h
+++ b/xen/include/asm-arm/alternative.h
@@ -5,7 +5,7 @@
 #include <xen/config.h>
 #include <xen/kconfig.h>
 
-#ifdef CONFIG_ALTERNATIVE
+#ifdef CONFIG_HAS_ALTERNATIVE
 
 #ifndef __ASSEMBLY__
 
@@ -154,7 +154,7 @@ int apply_alternatives(const struct alt_instr *start, const struct alt_instr *en
 #define ALTERNATIVE(oldinstr, newinstr, ...)   \
 	_ALTERNATIVE_CFG(oldinstr, newinstr, __VA_ARGS__, 1)
 
-#else /* !CONFIG_ALTERNATIVE */
+#else /* !CONFIG_HAS_ALTERNATIVE */
 
 static inline void apply_alternatives_all(void)
 {
diff --git a/xen/include/asm-arm/cpuerrata.h b/xen/include/asm-arm/cpuerrata.h
index 5e35b4f..8c57c6a 100644
--- a/xen/include/asm-arm/cpuerrata.h
+++ b/xen/include/asm-arm/cpuerrata.h
@@ -7,7 +7,7 @@
 
 void check_local_cpu_errata(void);
 
-#ifdef CONFIG_ALTERNATIVE
+#ifdef CONFIG_HAS_ALTERNATIVE
 
 #define CHECK_WORKAROUND_HELPER(erratum, feature, arch)         \
 static inline bool_t check_workaround_##erratum(void)           \
@@ -27,7 +27,7 @@ static inline bool_t check_workaround_##erratum(void)           \
     }                                                           \
 }
 
-#else /* CONFIG_ALTERNATIVE */
+#else /* CONFIG_HAS_ALTERNATIVE */
 
 #define CHECK_WORKAROUND_HELPER(erratum, feature, arch)         \
 static inline bool_t check_workaround_##erratum(void)           \
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/ Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:23   ` Julien Grall
  2016-09-22 15:30   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in Konrad Rzeszutek Wilk
                   ` (13 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Doug Goldstein, Jan Beulich, Konrad Rzeszutek Wilk

x86 implements all of them by default - and we just
add two extra HAS_ variables to be declared in autoconf.h.

ARM 64 only has alternative while ARM 32 has none of them.

And while at it change the livepatch common code that
would benefit from this.

Acked-by: Jan Beulich <jbeulich@suse.com> [relevant parts]
Suggested-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Doug Goldstein <cardoe@cardoe.com>

v2: First submission
v3: Move the config options to common code
    Don't include <xen/config.h> in the file.
    Don't even include <xen/kconfig.h> in the file as xen/Rules.mk automatically
    includes the config.h for every GCC invocation.
v4: Depend on "arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/"
    Remove the extra newline in arch/x86/Kconfig
v5: Add Jan's Ack.
---
 xen/arch/arm/Kconfig   | 3 ---
 xen/arch/x86/Kconfig   | 2 ++
 xen/common/Kconfig     | 6 ++++++
 xen/common/livepatch.c | 4 +++-
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 558d013..2e023d1 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -45,9 +45,6 @@ config ACPI
 config HAS_GICV3
 	bool
 
-config HAS_ALTERNATIVE
-	bool
-
 endmenu
 
 menu "ARM errata workaround via the alternative framework"
diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index 265fd79..96ca2bf 100644
--- a/xen/arch/x86/Kconfig
+++ b/xen/arch/x86/Kconfig
@@ -7,8 +7,10 @@ config X86
 	select ACPI_LEGACY_TABLES_LOOKUP
 	select COMPAT
 	select CORE_PARKING
+	select HAS_ALTERNATIVE
 	select HAS_CPUFREQ
 	select HAS_EHCI
+	select HAS_EX_TABLE
 	select HAS_GDBSX
 	select HAS_IOPORTS
 	select HAS_KEXEC
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 4331874..81e0017 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -11,9 +11,15 @@ config COMPAT
 config CORE_PARKING
 	bool
 
+config HAS_ALTERNATIVE
+	bool
+
 config HAS_DEVICE_TREE
 	bool
 
+config HAS_EX_TABLE
+	bool
+
 config HAS_MEM_ACCESS
 	bool
 
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 5f9986d..292dd2e 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -643,7 +643,7 @@ static int prepare_payload(struct payload *payload,
                                   sizeof(*region->frame[i].bugs);
     }
 
-#ifndef CONFIG_ARM
+#ifdef CONFIG_HAS_ALTERNATIVE
     sec = livepatch_elf_sec_by_name(elf, ".altinstructions");
     if ( sec )
     {
@@ -674,7 +674,9 @@ static int prepare_payload(struct payload *payload,
         }
         apply_alternatives(start, end);
     }
+#endif
 
+#ifdef CONFIG_HAS_EX_TABLE
     sec = livepatch_elf_sec_by_name(elf, ".ex_table");
     if ( sec )
     {
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/ Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE] Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-23 12:47   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 04/16] arm: poison initmem when it is freed Konrad Rzeszutek Wilk
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

If the payload had the sections mentioned but the hypervisor
did not support some of them (say on ARM the .ex_table) - instead
of ignoring them - it should forbid loading of such payload.

Reviewed-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
v4: Added Julien's Reviewed-by tag.
---
 xen/common/livepatch.c | 16 ++++++++++++----
 1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 292dd2e..66f23e0 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -643,10 +643,10 @@ static int prepare_payload(struct payload *payload,
                                   sizeof(*region->frame[i].bugs);
     }
 
-#ifdef CONFIG_HAS_ALTERNATIVE
     sec = livepatch_elf_sec_by_name(elf, ".altinstructions");
     if ( sec )
     {
+#ifdef CONFIG_HAS_ALTERNATIVE
         struct alt_instr *a, *start, *end;
 
         if ( sec->sec->sh_size % sizeof(*a) )
@@ -673,13 +673,17 @@ static int prepare_payload(struct payload *payload,
             }
         }
         apply_alternatives(start, end);
-    }
+#else
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: We don't support alternative patching!\n",
+                elf->name);
+        return -EOPNOTSUPP;
 #endif
+    }
 
-#ifdef CONFIG_HAS_EX_TABLE
     sec = livepatch_elf_sec_by_name(elf, ".ex_table");
     if ( sec )
     {
+#ifdef CONFIG_HAS_EX_TABLE
         struct exception_table_entry *s, *e;
 
         if ( !sec->sec->sh_size ||
@@ -698,8 +702,12 @@ static int prepare_payload(struct payload *payload,
 
         region->ex = s;
         region->ex_end = e;
-    }
+#else
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: We don't support .ex_table!\n",
+                elf->name);
+        return -EOPNOTSUPP;
 #endif
+    }
 
     return 0;
 }
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 04/16] arm: poison initmem when it is freed.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (2 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:28   ` Julien Grall
  2016-09-21 17:32 ` [PATCH v5 05/16] livepatch: Initial ARM64 support Konrad Rzeszutek Wilk
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Konrad Rzeszutek Wilk

The current byte sequence is '0xcc' which makes sense on x86,
but on ARM it is:

cccccccc        stclgt  12, cr12, [ip], {204}   ; 0xcc

Picking something more ARM applicable such as:

efefefef        svc     0x00efefef

Creates a nice crash if one executes that code:
(XEN) CPU1: Unexpected Trap: Supervisor Call

But unfortunately that may not be a good choice either as in the future
we may want to implement support for it.

Julien suggested that we use a 4-byte insn instruction instead
of trying to work with one byte. To make sure nothing goes bad
we also require that the __init_[begin|end] be aligned properly.

As such on ARM 32 we use the udf instruction (see A8.8.247
in ARM DDI 0406C.c) and on ARM 64 use the AARCH64_BREAK_FAULT
instruction (aka brk instruction).

We don't have to worry about Thumb code so this instruction
is a safe to execute.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v3: New submission
v4: Instead of using 0xef, use specific insn for architectures.
v5: Add BUILD_BUG_ON
    Fix the loop to cover the full 'len' instead of 1/4 of it
    (used __init_begin which is a char instead of uint32_t).
---
 xen/arch/arm/mm.c      | 15 ++++++++++++++-
 xen/arch/arm/xen.lds.S |  6 ++++++
 2 files changed, 20 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c
index 07e2037..99588a3 100644
--- a/xen/arch/arm/mm.c
+++ b/xen/arch/arm/mm.c
@@ -994,8 +994,21 @@ void free_init_memory(void)
 {
     paddr_t pa = virt_to_maddr(__init_begin);
     unsigned long len = __init_end - __init_begin;
+    uint32_t insn;
+    unsigned int i, nr = len / sizeof(insn);
+    uint32_t *p;
+
     set_pte_flags_on_range(__init_begin, len, mg_rw);
-    memset(__init_begin, 0xcc, len);
+#ifdef CONFIG_ARM_32
+    /* udf instruction i.e (see A8.8.247 in ARM DDI 0406C.c) */
+    insn = 0xe7f000f0;
+#else
+    insn = AARCH64_BREAK_FAULT;
+#endif
+    p = (uint32_t *)__init_begin;
+    for ( i = 0; i < nr; i++ )
+        *(p + i) = insn;
+
     set_pte_flags_on_range(__init_begin, len, mg_clear);
     init_domheap_pages(pa, pa + len);
     printk("Freed %ldkB init memory.\n", (long)(__init_end-__init_begin)>>10);
diff --git a/xen/arch/arm/xen.lds.S b/xen/arch/arm/xen.lds.S
index 47b910d..ddef595 100644
--- a/xen/arch/arm/xen.lds.S
+++ b/xen/arch/arm/xen.lds.S
@@ -221,3 +221,9 @@ SECTIONS
  * code running on the boot time identity map cannot cross a section boundary.
  */
 ASSERT( _end_boot - start <= PAGE_SIZE, "Boot code is larger than 4K")
+/*
+ * __init_[begin|end] MUST be at word size boundary otherwise we cannot
+ * write fault instructions in the space properly.
+ */
+ASSERT(IS_ALIGNED(__init_begin,     4), "__init_begin is misaligned")
+ASSERT(IS_ALIGNED(__init_end,       4), "__init_end is misaligned")
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 05/16] livepatch: Initial ARM64 support.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (3 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 04/16] arm: poison initmem when it is freed Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:49   ` Julien Grall
  2016-09-23 13:38   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr Konrad Rzeszutek Wilk
                   ` (10 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Konrad Rzeszutek Wilk

As compared to x86 the va of the hypervisor .text
is locked down - we cannot modify the running pagetables
to have the .ro flag unset. We borrow the same idea that
alternative patching has - which is to vmap the entire
.text region and use the alternative virtual address
for patching.

Since we are doing vmap we may fail, hence the
arch_livepatch_quiesce was changed (see "x86,arm:
Change arch_livepatch_quiesce() declaration") to return
an error value which will be bubbled in payload->rc and
provided to the user (along with messages in the ring buffer).

The livepatch virtual address space (where the new functions
are) needs to be close to the hypervisor virtual address
so that the trampoline can reach it. As such we re-use
the BOOT_RELOC_VIRT_START which is not used after bootup
(alternatively we can also use the space after the _end to
FIXMAP_ADDR(0), but that may be too small).

The ELF relocation engine at the start was coded from
the "ELF for the ARM 64-bit Architecture (AArch64)"
(http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf)
but after a while of trying to write the correct bit shifting
and masking from scratch I ended up borrowing from Linux, the
'reloc_insn_imm' (Linux v4.7 arch/arm64/kernel/module.c function.
See 257cb251925f854da435cbf79b140984413871ac "arm64: Loadable modules")

And while at it - we also utilize code from Linux to construct
the right branch instruction (see "arm64/insn: introduce
aarch64_insn_gen_{nop|branch_imm}() helper functions").

In the livepatch payload loading code we tweak the #ifdef to
only exclude ARM_32. The exceptions are not part of ARM 32/64 hence
they are still behind the #ifdef.

We also expand the MAINTAINERS file to include the arm64 and arm32
platform specific livepatch file.

Acked-by: Jan Beulich <jbeulich@suse.com> [non-arm parts]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc  Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

RFC: Wholy cow! It works!
v1: Finished the various TODOs and reviews outlined by Julien in RFC.
v2: Call check_for_livepatch_work in leave_hypervisor_tail not in
    reset_stack_and_jump
   - Move ARM 32 components in other patch
   - Blacklist platform options in Kconfig
   - Added R_AARCH64_LDST128_ABS_LO12_NC, R_AARCH64_TSTBR14, and
     R_AARCH64_ADR_PREL_PG_HI21_NC
   - Added do_reloc and reloc_data along with overflow checks from Linux.
   - Use apply_alternatives without any #ifdef
   - Use leave_hypervisor_tail to call check_for_livepatch_work
   - Add ASSERT that isns is not AARCH64_BREAK_FAULT
   - Spun out arch_livepatch_quiesce changes in seperate patch.
   - Spun out changes to config.h (document ones) to seperate patch.
   - Move the livepatch.h to include/xen/asm-arm.
   - Add LIVEPATCH_VMAP_END and LIVEPATCH_VMAP_START in config.h
   - In arch_livepatch_secure use switch for va_type.
   - Drop the #ifndef CONFIG_ARM for .ex_table (see
     "arm/x86: Add HAS_ALTERNATIVE and HAS_EX_TABLE")
   - Piggyback on "x86: change modify_xen_mappings to return error"
      so that arch_livepatch_secure can return errors.
   - Moves comment about branch predictor out of this patch.
v3: Fix StyleGuide violations (switch statements)
   - Fix incorrect cast of addr when reverting.
   - Drop old_ptr variable.
   - Use bool_t values instead of numbers.
   - Sprinkle \n as requested by Julien.
   - In arch_livepatch_quiesce use 1U instead of 1.
   - Use C99 #defines for [U,]INT[16,32]_[MIN,MAX] instead of Linux
     kernel ones ([S,U][16,32]_[MIN,MAX]).
   - Include the ELF relocations for R_AARCH64_[ABS,PRE]16, and
     all the various groupings for R_AARCH64_MOVW_[UABS,SABS,PREL]_*
     family.
   - Redo the NOP patching to use more of the opaque size (so up to 7
     instructions in one go).
   - Drop the cpu_to_le32 macros as they are not needed (and can allow
     use to share more code with ARM32).
   - Flush out func->old_addr instead of vmap pointer when reverting.
v4: Added Jan's Ack
   s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
   s/arch_livepatch_insn_len/livepatch_insn_len/
v5: Added 'fallthrough' comments on the switch statements.
   - Added more invalidate of dcache on the old_addr and the vmap area.
   - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
   - Move most of  docs part from "livepatch: ARM/x86: Check displacement of
     old_addr and new_addr" in this patch.
   - Added syncing of data cache along with explanation for its usage.
---
 MAINTAINERS                     |   1 +
 docs/misc/livepatch.markdown    |  14 +-
 xen/arch/arm/Makefile           |  13 +-
 xen/arch/arm/arm32/Makefile     |   1 +
 xen/arch/arm/arm32/livepatch.c  |  38 ++++
 xen/arch/arm/arm64/Makefile     |   1 +
 xen/arch/arm/arm64/livepatch.c  | 488 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domain.c           |   6 +
 xen/arch/arm/livepatch.c        | 103 +++++++--
 xen/arch/arm/traps.c            |   6 +
 xen/common/Kconfig              |   2 +-
 xen/include/asm-arm/config.h    |   5 +
 xen/include/asm-arm/livepatch.h |  28 +++
 xen/include/xen/elfstructs.h    |  57 ++++-
 xen/include/xen/types.h         |   9 +
 15 files changed, 746 insertions(+), 26 deletions(-)
 create mode 100644 xen/arch/arm/arm32/livepatch.c
 create mode 100644 xen/arch/arm/arm64/livepatch.c
 create mode 100644 xen/include/asm-arm/livepatch.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9b30600..1c39146 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,6 +269,7 @@ S:  Supported
 F:  docs/misc/livepatch.markdown
 F:  tools/misc/xen-livepatch.c
 F:  xen/arch/*/livepatch*
+F:  xen/arch/*/*/livepatch*
 F:  xen/common/livepatch*
 F:  xen/include/asm-*/livepatch.h
 F:  xen/include/xen/livepatch*
diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown
index f2ae52a..ff2cfb8 100644
--- a/docs/misc/livepatch.markdown
+++ b/docs/misc/livepatch.markdown
@@ -1108,7 +1108,7 @@ and no .data or .bss sections.
 The hypervisor should verify that the in-place patching would fit within
 the code or data.
 
-### Trampoline (e9 opcode)
+### Trampoline (e9 opcode), x86
 
 The e9 opcode used for jmpq uses a 32-bit signed displacement. That means
 we are limited to up to 2GB of virtual address to place the new code
@@ -1143,3 +1143,15 @@ that in the hypervisor is advised.
 The tool for generating payloads currently does perform a compile-time
 check to ensure that the function to be replaced is large enough.
 
+#### Trampoline (ea opcode), ARM
+
+The unconditional branch instruction (for the encoding see the
+DDI 0406C.c and DDI 0487A.j Architecture Reference Manual's).
+with proper offset is used for an unconditional branch to the new code.
+This means that that `old_size` **MUST** be at least four bytes if patching
+in trampoline.
+
+The new code is placed in the 8M - 10M virtual address space while the
+Xen code is in 2M - 4M. That gives us enough space.
+
+The hypervisor also checks the displacement during loading of the payload.
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 61e655b..5cee84d 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -59,6 +59,15 @@ ALL_OBJS := $(TARGET_SUBARCH)/head.o $(ALL_OBJS)
 
 DEPS += $(TARGET_SUBARCH)/.head.o.d
 
+ifdef CONFIG_LIVEPATCH
+all_symbols = --all-symbols
+ifdef CONFIG_FAST_SYMBOL_LOOKUP
+all_symbols = --all-symbols --sort-by-name
+endif
+else
+all_symbols =
+endif
+
 $(TARGET): $(TARGET)-syms $(TARGET).axf
 	$(OBJCOPY) -O binary -S $< $@
 ifeq ($(CONFIG_ARM_64),y)
@@ -94,12 +103,12 @@ $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
 	    $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
 	$(NM) -pa --format=sysv $(@D)/.$(@F).0 \
-		| $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).0.S
 	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
 	    $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
 	$(NM) -pa --format=sysv $(@D)/.$(@F).1 \
-		| $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).1.S
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).1.S
 	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
 	    $(@D)/.$(@F).1.o -o $@
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index b20db64..4395693 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -4,6 +4,7 @@ obj-$(EARLY_PRINTK) += debug.o
 obj-y += domctl.o
 obj-y += domain.o
 obj-y += entry.o
+obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += proc-v7.o proc-caxx.o
 obj-y += smpboot.o
 obj-y += traps.o
diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
new file mode 100644
index 0000000..80f9646
--- /dev/null
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/livepatch_elf.h>
+#include <xen/livepatch.h>
+
+void arch_livepatch_apply(struct livepatch_func *func)
+{
+}
+
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+}
+
+int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
+{
+    return -EOPNOTSUPP;
+}
+
+int arch_livepatch_perform_rela(struct livepatch_elf *elf,
+                                const struct livepatch_elf_sec *base,
+                                const struct livepatch_elf_sec *rela)
+{
+    return -ENOSYS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index c1fa43f..149b6b3 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -6,6 +6,7 @@ obj-y += domctl.o
 obj-y += domain.o
 obj-y += entry.o
 obj-y += insn.o
+obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += smpboot.o
 obj-y += traps.o
 obj-y += vfp.o
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
new file mode 100644
index 0000000..7cb1812
--- /dev/null
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -0,0 +1,488 @@
+/*
+ *  Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <xen/bitops.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/livepatch_elf.h>
+#include <xen/livepatch.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+#include <asm/insn.h>
+#include <asm/livepatch.h>
+
+void arch_livepatch_apply(struct livepatch_func *func)
+{
+    uint32_t insn;
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
+
+    ASSERT(vmap_of_xen_text);
+
+    len = livepatch_insn_len(func);
+    if ( !len )
+        return;
+
+    /* Save old ones. */
+    memcpy(func->opaque, func->old_addr, len);
+
+    if ( func->new_addr )
+        insn = aarch64_insn_gen_branch_imm((unsigned long)func->old_addr,
+                                           (unsigned long)func->new_addr,
+                                           AARCH64_INSN_BRANCH_NOLINK);
+    else
+        insn = aarch64_insn_gen_nop();
+
+    ASSERT(insn != AARCH64_BREAK_FAULT);
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = len / sizeof(uint32_t);
+
+    /* PATCH! */
+    for ( i = 0; i < len; i++ )
+        *(new_ptr + i) = insn;
+
+    /*
+    * When we upload the payload, it will go through the data cache
+    * (the region is cacheable). Until the data cache is cleaned, the data
+    * may not reach the memory. And in the case the data and instruction cache
+    * are separated, we may read invalid instruction from the memory because
+    * the data cache have not yet synced with the memory. Hence sync it.
+    */
+    if ( func->new_addr )
+        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
+}
+
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = livepatch_insn_len(func) / sizeof(uint32_t);
+    for ( i = 0; i < len; i++ )
+    {
+        uint32_t insn;
+
+        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
+        /* PATCH! */
+        *(new_ptr + i) = insn;
+    }
+}
+
+int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
+{
+    const Elf_Ehdr *hdr = elf->hdr;
+
+    if ( hdr->e_machine != EM_AARCH64 ||
+         hdr->e_ident[EI_CLASS] != ELFCLASS64 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
+                elf->name);
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+enum aarch64_reloc_op {
+    RELOC_OP_NONE,
+    RELOC_OP_ABS,
+    RELOC_OP_PREL,
+    RELOC_OP_PAGE,
+};
+
+static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val)
+{
+    switch ( reloc_op )
+    {
+    case RELOC_OP_ABS:
+        return val;
+
+    case RELOC_OP_PREL:
+        return val - (u64)place;
+
+    case RELOC_OP_PAGE:
+        return (val & ~0xfff) - ((u64)place & ~0xfff);
+
+    case RELOC_OP_NONE:
+        return 0;
+
+    }
+
+    dprintk(XENLOG_DEBUG, LIVEPATCH "do_reloc: unknown relocation operation %d\n", reloc_op);
+
+    return 0;
+}
+
+static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
+{
+    s64 sval = do_reloc(op, place, val);
+
+    switch ( len )
+    {
+    case 16:
+        *(s16 *)place = sval;
+        if ( sval < INT16_MIN || sval > UINT16_MAX )
+	        return -EOVERFLOW;
+        break;
+
+    case 32:
+        *(s32 *)place = sval;
+        if ( sval < INT32_MIN || sval > UINT32_MAX )
+	        return -EOVERFLOW;
+        break;
+
+    case 64:
+        *(s64 *)place = sval;
+        break;
+
+    default:
+        dprintk(XENLOG_DEBUG, LIVEPATCH "Invalid length (%d) for data relocation\n", len);
+        return 0;
+    }
+
+    return 0;
+}
+
+enum aarch64_insn_movw_imm_type {
+    AARCH64_INSN_IMM_MOVNZ,
+    AARCH64_INSN_IMM_MOVKZ,
+};
+
+static int reloc_insn_movw(enum aarch64_reloc_op op, void *dest, u64 val,
+                           int lsb, enum aarch64_insn_movw_imm_type imm_type)
+{
+    u64 imm;
+    s64 sval;
+    u32 insn = *(u32 *)dest;
+
+    sval = do_reloc(op, dest, val);
+    imm = sval >> lsb;
+
+    if ( imm_type == AARCH64_INSN_IMM_MOVNZ )
+    {
+        /*
+         * For signed MOVW relocations, we have to manipulate the
+         * instruction encoding depending on whether or not the
+         * immediate is less than zero.
+         */
+        insn &= ~(3 << 29);
+        if ( sval >= 0 )
+        {
+            /* >=0: Set the instruction to MOVZ (opcode 10b). */
+            insn |= 2 << 29;
+        }
+        else
+        {
+            /*
+             * <0: Set the instruction to MOVN (opcode 00b).
+             *     Since we've masked the opcode already, we
+             *     don't need to do anything other than
+             *     inverting the new immediate field.
+             */
+            imm = ~imm;
+        }
+    }
+
+    /* Update the instruction with the new encoding. */
+    insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_16, insn, imm);
+    *(u32 *)dest = insn;
+
+    if ( imm > UINT16_MAX )
+        return -EOVERFLOW;
+
+    return 0;
+}
+
+static int reloc_insn_imm(enum aarch64_reloc_op op, void *dest, u64 val,
+                          int lsb, int len, enum aarch64_insn_imm_type imm_type)
+{
+    u64 imm, imm_mask;
+    s64 sval;
+    u32 insn = *(u32 *)dest;
+
+    /* Calculate the relocation value. */
+    sval = do_reloc(op, dest, val);
+    sval >>= lsb;
+
+    /* Extract the value bits and shift them to bit 0. */
+    imm_mask = (BIT(lsb + len) - 1) >> lsb;
+    imm = sval & imm_mask;
+
+    /* Update the instruction's immediate field. */
+    insn = aarch64_insn_encode_immediate(imm_type, insn, imm);
+    *(u32 *)dest = insn;
+
+    /*
+     * Extract the upper value bits (including the sign bit) and
+     * shift them to bit 0.
+     */
+    sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
+
+    /*
+     * Overflow has occurred if the upper bits are not all equal to
+     * the sign bit of the value.
+     */
+    if ( (u64)(sval + 1) >= 2 )
+        return -EOVERFLOW;
+    return 0;
+}
+
+int arch_livepatch_perform_rela(struct livepatch_elf *elf,
+                                const struct livepatch_elf_sec *base,
+                                const struct livepatch_elf_sec *rela)
+{
+    const Elf_RelA *r;
+    unsigned int symndx, i;
+    uint64_t val;
+    void *dest;
+    bool_t overflow_check;
+
+    for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+    {
+        int ovf = 0;
+
+        r = rela->data + i * rela->sec->sh_entsize;
+
+        symndx = ELF64_R_SYM(r->r_info);
+
+        if ( symndx > elf->nsym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
+
+        dest = base->load_addr + r->r_offset; /* P */
+        val = elf->sym[symndx].sym->st_value +  r->r_addend; /* S+A */
+
+        overflow_check = true;
+
+        /* ARM64 operations at minimum are always 32-bit. */
+        if ( r->r_offset >= base->sec->sh_size ||
+            (r->r_offset + sizeof(uint32_t)) > base->sec->sh_size )
+            goto bad_offset;
+
+        switch ( ELF64_R_TYPE(r->r_info) )
+        {
+        /* Data */
+        case R_AARCH64_ABS64:
+            if ( r->r_offset + sizeof(uint64_t) > base->sec->sh_size )
+                goto bad_offset;
+            overflow_check = false;
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 64);
+            break;
+
+        case R_AARCH64_ABS32:
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 32);
+            break;
+
+        case R_AARCH64_ABS16:
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 16);
+            break;
+
+        case R_AARCH64_PREL64:
+            if ( r->r_offset + sizeof(uint64_t) > base->sec->sh_size )
+                goto bad_offset;
+            overflow_check = false;
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 64);
+            break;
+
+        case R_AARCH64_PREL32:
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 32);
+            break;
+
+        case R_AARCH64_PREL16:
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 16);
+            break;
+
+        /* MOVW instruction relocations. */
+        case R_AARCH64_MOVW_UABS_G0_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G0:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G1_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G1:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G2_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G2:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G3:
+            /* We're using the top bits so we can't overflow. */
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 48,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G0:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G1:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G2:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G0_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G0:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G1_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G1:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G2_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G2:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G3:
+            /* We're using the top bits so we can't overflow. */
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 48,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        /* Instructions. */
+        case R_AARCH64_ADR_PREL_LO21:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 0, 21,
+                                 AARCH64_INSN_IMM_ADR);
+            break;
+
+        case R_AARCH64_ADR_PREL_PG_HI21_NC:
+            overflow_check = false;
+        case R_AARCH64_ADR_PREL_PG_HI21:
+            ovf = reloc_insn_imm(RELOC_OP_PAGE, dest, val, 12, 21,
+                                 AARCH64_INSN_IMM_ADR);
+            break;
+
+        case R_AARCH64_LDST8_ABS_LO12_NC:
+            /* Fallthrough. */
+
+        case R_AARCH64_ADD_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 0, 12,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST16_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 1, 11,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST32_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 2, 10,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST64_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 3, 9,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST128_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 4, 8,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_TSTBR14:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 19,
+                                 AARCH64_INSN_IMM_14);
+            break;
+
+        case R_AARCH64_CONDBR19:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 19,
+                                 AARCH64_INSN_IMM_19);
+            break;
+
+        case R_AARCH64_JUMP26:
+        case R_AARCH64_CALL26:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 26,
+                                 AARCH64_INSN_IMM_26);
+            break;
+
+        default:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation %lu\n",
+                    elf->name, ELF64_R_TYPE(r->r_info));
+            return -EOPNOTSUPP;
+        }
+
+        if ( overflow_check && ovf == -EOVERFLOW )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
+                    elf->name, i, rela->name, base->name);
+            return ovf;
+        }
+    }
+    return 0;
+
+ bad_offset:
+    dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation offset is past %s section!\n",
+            elf->name, base->name);
+    return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 20bb2ba..607ee59 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -13,6 +13,7 @@
 #include <xen/hypercall.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/livepatch.h>
 #include <xen/sched.h>
 #include <xen/softirq.h>
 #include <xen/wait.h>
@@ -55,6 +56,11 @@ void idle_loop(void)
 
         do_tasklet();
         do_softirq();
+        /*
+         * We MUST be last (or before dsb, wfi). Otherwise after we get the
+         * softirq we would execute dsb,wfi (and sleep) and not patch.
+         */
+        check_for_livepatch_work();
     }
 }
 
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 7f067a0..9284766 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -6,44 +6,82 @@
 #include <xen/lib.h>
 #include <xen/livepatch_elf.h>
 #include <xen/livepatch.h>
+#include <xen/vmap.h>
+
+#include <asm/livepatch.h>
+#include <asm/mm.h>
+
+void *vmap_of_xen_text;
 
 int arch_livepatch_quiesce(void)
 {
-    return -ENOSYS;
+    mfn_t text_mfn;
+    unsigned int text_order;
+
+    if ( vmap_of_xen_text )
+        return -EINVAL;
+
+    text_mfn = _mfn(virt_to_mfn(_start));
+    text_order = get_order_from_bytes(_end - _start);
+
+    /*
+     * The text section is read-only. So re-map Xen to be able to patch
+     * the code.
+     */
+    vmap_of_xen_text = __vmap(&text_mfn, 1U << text_order, 1, 1, PAGE_HYPERVISOR,
+                              VMAP_DEFAULT);
+
+    if ( !vmap_of_xen_text )
+    {
+        printk(XENLOG_ERR LIVEPATCH "Failed to setup vmap of hypervisor! (order=%u)\n",
+               text_order);
+        return -ENOMEM;
+    }
+
+    return 0;
 }
 
 void arch_livepatch_revive(void)
 {
+    /*
+     * Nuke the instruction cache. Data cache has been cleaned before in
+     * arch_livepatch_apply.
+     */
+    invalidate_icache();
+
+    if ( vmap_of_xen_text )
+        vunmap(vmap_of_xen_text);
+
+    vmap_of_xen_text = NULL;
 }
 
 int arch_livepatch_verify_func(const struct livepatch_func *func)
 {
-    return -ENOSYS;
-}
+    /* If NOPing only do up to maximum amount we can put in the ->opaque. */
+    if ( !func->new_addr && func->new_size > sizeof(func->opaque) &&
+         func->new_size % ARCH_PATCH_INSN_SIZE )
+        return -EOPNOTSUPP;
 
-void arch_livepatch_apply(struct livepatch_func *func)
-{
-}
+    if ( func->old_size < ARCH_PATCH_INSN_SIZE )
+        return -EINVAL;
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
+    return 0;
 }
 
 void arch_livepatch_post_action(void)
 {
+    /* arch_livepatch_revive has nuked the instruction cache. */
 }
 
 void arch_livepatch_mask(void)
 {
+    /* Mask System Error (SError) */
+    local_abort_disable();
 }
 
 void arch_livepatch_unmask(void)
 {
-}
-
-int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
-{
-    return -ENOSYS;
+    local_abort_enable();
 }
 
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
@@ -53,20 +91,43 @@ int arch_livepatch_perform_rel(struct livepatch_elf *elf,
     return -ENOSYS;
 }
 
-int arch_livepatch_perform_rela(struct livepatch_elf *elf,
-                                const struct livepatch_elf_sec *base,
-                                const struct livepatch_elf_sec *rela)
-{
-    return -ENOSYS;
-}
-
 int arch_livepatch_secure(const void *va, unsigned int pages, enum va_type type)
 {
-    return -ENOSYS;
+    unsigned long start = (unsigned long)va;
+    unsigned int flags = 0;
+
+    ASSERT(va);
+    ASSERT(pages);
+
+    switch ( type )
+    {
+    case LIVEPATCH_VA_RX:
+        flags = PTE_RO; /* R set, NX clear */
+        break;
+
+    case LIVEPATCH_VA_RW:
+        flags = PTE_NX; /* R clear, NX set */
+        break;
+
+    case LIVEPATCH_VA_RO:
+        flags = PTE_NX | PTE_RO; /* R set, NX set */
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    return modify_xen_mappings(start, start + pages * PAGE_SIZE, flags);
 }
 
 void __init arch_livepatch_init(void)
 {
+    void *start, *end;
+
+    start = (void *)LIVEPATCH_VMAP_START;
+    end = (void *)LIVEPATCH_VMAP_END;
+
+    vm_init_type(VMAP_XEN, start, end);
 }
 
 /*
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 39a05fd..cd6c222 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -24,6 +24,7 @@
 #include <xen/symbols.h>
 #include <xen/irq.h>
 #include <xen/lib.h>
+#include <xen/livepatch.h>
 #include <xen/mm.h>
 #include <xen/errno.h>
 #include <xen/hypercall.h>
@@ -2689,6 +2690,11 @@ asmlinkage void leave_hypervisor_tail(void)
         }
         local_irq_enable();
         do_softirq();
+        /*
+         * Must be the last one - as the IPI will trigger us to come here
+         * and we want to patch the hypervisor with almost no stack.
+         */
+        check_for_livepatch_work();
     }
 }
 
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 81e0017..0f26027 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -217,7 +217,7 @@ config CRYPTO
 config LIVEPATCH
 	bool "Live patching support (TECH PREVIEW)"
 	default n
-	depends on X86 && HAS_BUILD_ID = "y"
+	depends on !ARM_32 && HAS_BUILD_ID = "y"
 	---help---
 	  Allows a running Xen hypervisor to be dynamically patched using
 	  binary patches without rebooting. This is primarily used to binarily
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 6772555..ba61f65 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -80,6 +80,7 @@
  *   4M -   6M   Fixmap: special-purpose 4K mapping slots
  *   6M -   8M   Early boot mapping of FDT
  *   8M -  10M   Early relocation address (used when relocating Xen)
+ *               and later for livepatch vmap (if compiled in)
  *
  * ARM32 layout:
  *   0  -  10M   <COMMON>
@@ -113,6 +114,10 @@
 #define FIXMAP_ADDR(n)        (_AT(vaddr_t,0x00400000) + (n) * PAGE_SIZE)
 #define BOOT_FDT_VIRT_START    _AT(vaddr_t,0x00600000)
 #define BOOT_RELOC_VIRT_START  _AT(vaddr_t,0x00800000)
+#ifdef CONFIG_LIVEPATCH
+#define LIVEPATCH_VMAP_START   _AT(vaddr_t,0x00800000)
+#define LIVEPATCH_VMAP_END     (LIVEPATCH_VMAP_START + MB(2))
+#endif
 
 #define HYPERVISOR_VIRT_START  XEN_VIRT_START
 
diff --git a/xen/include/asm-arm/livepatch.h b/xen/include/asm-arm/livepatch.h
new file mode 100644
index 0000000..929c7d9
--- /dev/null
+++ b/xen/include/asm-arm/livepatch.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ */
+
+#ifndef __XEN_ARM_LIVEPATCH_H__
+#define __XEN_ARM_LIVEPATCH_H__
+
+/* On ARM32,64 instructions are always 4 bytes long. */
+#define ARCH_PATCH_INSN_SIZE 4
+
+/*
+ * The va of the hypervisor .text region. We need this as the
+ * normal va are write protected.
+ */
+extern void *vmap_of_xen_text;
+
+#endif /* __XEN_ARM_LIVEPATCH_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/elfstructs.h b/xen/include/xen/elfstructs.h
index 5f2082e..7329987 100644
--- a/xen/include/xen/elfstructs.h
+++ b/xen/include/xen/elfstructs.h
@@ -177,6 +177,7 @@ typedef struct {
 #define EM_IA_64	50		/* Intel Merced */
 #define EM_X86_64	62		/* AMD x86-64 architecture */
 #define EM_VAX		75		/* DEC VAX */
+#define EM_AARCH64	183		/* ARM 64-bit */
 
 /* Version */
 #define EV_NONE		0		/* Invalid */
@@ -353,12 +354,66 @@ typedef struct {
 #define	ELF64_R_TYPE(info)	((info) & 0xFFFFFFFF)
 #define ELF64_R_INFO(s,t) 	(((s) << 32) + (u_int32_t)(t))
 
-/* x86-64 relocation types. We list only the ones Live Patch implements. */
+/*
+ * Relocation types for x86_64 and ARM 64. We list only the ones Live Patch
+ * implements.
+ */
 #define R_X86_64_NONE		0	/* No reloc */
 #define R_X86_64_64	    	1	/* Direct 64 bit  */
 #define R_X86_64_PC32		2	/* PC relative 32 bit signed */
 #define R_X86_64_PLT32		4	/* 32 bit PLT address */
 
+/*
+ * S - address of symbol.
+ * A - addend for relocation (r_addend)
+ * P - address of the dest being relocated (derieved from r_offset)
+ * NC -  No check for overflow.
+ *
+ * The defines also use _PREL for PC-relative address, and _NC is No Check.
+ */
+#define R_AARCH64_ABS64			257 /* Direct 64 bit. S+A, NC*/
+#define R_AARCH64_ABS32			258 /* Direct 32 bit. S+A */
+#define R_AARCH64_ABS16			259 /* Direct 16 bit, S+A */
+#define R_AARCH64_PREL64		260 /* S+A-P, NC */
+#define R_AARCH64_PREL32		261 /* S+A-P */
+#define R_AARCH64_PREL16		262 /* S+A-P */
+
+/* Instructions. */
+#define R_AARCH64_MOVW_UABS_G0		263
+#define R_AARCH64_MOVW_UABS_G0_NC	264
+#define R_AARCH64_MOVW_UABS_G1		265
+#define R_AARCH64_MOVW_UABS_G1_NC	266
+#define R_AARCH64_MOVW_UABS_G2		267
+#define R_AARCH64_MOVW_UABS_G2_NC	268
+#define R_AARCH64_MOVW_UABS_G3		269
+
+#define R_AARCH64_MOVW_SABS_G0		270
+#define R_AARCH64_MOVW_SABS_G1		271
+#define R_AARCH64_MOVW_SABS_G2		272
+
+#define R_AARCH64_ADR_PREL_LO21		274 /* ADR imm, [20:0]. S+A-P */
+#define R_AARCH64_ADR_PREL_PG_HI21	275 /* ADRP imm, [32:12]. Page(S+A) - Page(P).*/
+#define R_AARCH64_ADR_PREL_PG_HI21_NC	276
+#define R_AARCH64_ADD_ABS_LO12_NC	277 /* ADD imm. [11:0]. S+A, NC */
+
+#define R_AARCH64_TSTBR14		279
+#define R_AARCH64_CONDBR19		280 /* Bits 20:2, S+A-P */
+#define R_AARCH64_JUMP26		282 /* Bits 27:2, S+A-P */
+#define R_AARCH64_CALL26		283 /* Bits 27:2, S+A-P */
+#define R_AARCH64_LDST16_ABS_LO12_NC	284 /* LD/ST to bits 11:1, S+A, NC */
+#define R_AARCH64_LDST32_ABS_LO12_NC	285 /* LD/ST to bits 11:2, S+A, NC */
+#define R_AARCH64_LDST64_ABS_LO12_NC	286 /* LD/ST to bits 11:3, S+A, NC */
+#define R_AARCH64_LDST8_ABS_LO12_NC	278 /* LD/ST to bits 11:0, S+A, NC */
+#define R_AARCH64_LDST128_ABS_LO12_NC	299
+
+#define R_AARCH64_MOVW_PREL_G0		287
+#define R_AARCH64_MOVW_PREL_G0_NC	288
+#define R_AARCH64_MOVW_PREL_G1		289
+#define R_AARCH64_MOVW_PREL_G1_NC	290
+#define R_AARCH64_MOVW_PREL_G2		291
+#define R_AARCH64_MOVW_PREL_G2_NC	292
+#define R_AARCH64_MOVW_PREL_G3		293
+
 /* Program Header */
 typedef struct {
 	Elf32_Word	p_type;		/* segment type */
diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h
index 7bdc83b..c79c353 100644
--- a/xen/include/xen/types.h
+++ b/xen/include/xen/types.h
@@ -14,6 +14,15 @@
 #define NULL ((void*)0)
 #endif
 
+#define INT16_MIN       (-32767-1)
+#define INT32_MIN       (-2147483647-1)
+
+#define INT16_MAX       (32767)
+#define INT32_MAX       (2147483647)
+
+#define UINT16_MAX      (65535)
+#define UINT32_MAX      (4294967295U)
+
 #define INT_MAX         ((int)(~0U>>1))
 #define INT_MIN         (-INT_MAX - 1)
 #define UINT_MAX        (~0U)
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (4 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 05/16] livepatch: Initial ARM64 support Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:55   ` Julien Grall
  2016-09-23 14:36   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x] Konrad Rzeszutek Wilk
                   ` (9 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

If the distance is too big we are in trouble - as our relocation
distance can surely be clipped, or still have a valid width - but
cause an overflow of distance.

On various architectures the maximum displacement for a unconditional
branch/jump varies. ARM32 is +/- 32MB, ARM64 is +/- 128MB while x86
for 32-bit relocations is +/- 2G.

Note: On x86 we could use the 64-bit jmpq instruction which
would provide much bigger displacement to do a jump, but we would
still have issues with the new function not being able to reach
any of the old functions (as all the relocations would assume 32-bit
displacement). And "furthermore would require an register or
memory location to load/store the address to." (From Jan).

On ARM the conditional branch supports even a smaller displacement
but fortunately we are not using that.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>

v3: New submission.
v4: s/arch_livepatch_verify_distance/livepatch_verify_distance/
    s/LIVEPATCH_ARCH_RANGE/ARCH_LIVEPATCH_RANGE/
v5: Updated commit description with Jan's comment
    Ditch the casting of long on calculating offset.
    Move most of the docs in "livepatch: Initial ARM64 support."
    Drop the cast on assigning ARCH_LIVEPATCH_RANGE to an variable.
---
 docs/misc/livepatch.markdown    |  3 +++
 xen/arch/arm/arm64/livepatch.c  |  1 +
 xen/common/livepatch.c          |  4 ++++
 xen/include/asm-arm/livepatch.h | 11 +++++++++++
 xen/include/asm-x86/livepatch.h |  3 +++
 xen/include/xen/livepatch.h     | 17 ++++++++++++++++-
 6 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown
index ff2cfb8..16f45f3 100644
--- a/docs/misc/livepatch.markdown
+++ b/docs/misc/livepatch.markdown
@@ -1151,6 +1151,9 @@ with proper offset is used for an unconditional branch to the new code.
 This means that that `old_size` **MUST** be at least four bytes if patching
 in trampoline.
 
+The instruction offset is limited on ARM32 to +/- 32MB to displacement
+and on ARM64 to +/- 128MB displacement.
+
 The new code is placed in the 8M - 10M virtual address space while the
 Xen code is in 2M - 4M. That gives us enough space.
 
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 7cb1812..d3fc9ac 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -40,6 +40,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
     else
         insn = aarch64_insn_gen_nop();
 
+    /* Verified in livepatch_verify_distance. */
     ASSERT(insn != AARCH64_BREAK_FAULT);
 
     new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 66f23e0..f2f866c 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -545,6 +545,10 @@ static int prepare_payload(struct payload *payload,
         rc = resolve_old_address(f, elf);
         if ( rc )
             return rc;
+
+        rc = livepatch_verify_distance(f);
+        if ( rc )
+            return rc;
     }
 
     sec = livepatch_elf_sec_by_name(elf, ".livepatch.hooks.load");
diff --git a/xen/include/asm-arm/livepatch.h b/xen/include/asm-arm/livepatch.h
index 929c7d9..482d74f 100644
--- a/xen/include/asm-arm/livepatch.h
+++ b/xen/include/asm-arm/livepatch.h
@@ -6,6 +6,8 @@
 #ifndef __XEN_ARM_LIVEPATCH_H__
 #define __XEN_ARM_LIVEPATCH_H__
 
+#include <xen/sizes.h> /* For SZ_* macros. */
+
 /* On ARM32,64 instructions are always 4 bytes long. */
 #define ARCH_PATCH_INSN_SIZE 4
 
@@ -15,6 +17,15 @@
  */
 extern void *vmap_of_xen_text;
 
+/* These ranges are only for unconditional branches. */
+#ifdef CONFIG_ARM_32
+/* ARM32: A4.3 IN ARM DDI 0406C.j -  we are using only ARM instructions in Xen.*/
+#define ARCH_LIVEPATCH_RANGE SZ_32M
+#else
+/* ARM64: C1.3.2 in ARM DDI 0487A.j */
+#define ARCH_LIVEPATCH_RANGE SZ_128M
+#endif
+
 #endif /* __XEN_ARM_LIVEPATCH_H__ */
 
 /*
diff --git a/xen/include/asm-x86/livepatch.h b/xen/include/asm-x86/livepatch.h
index 5e04aa1..7dfc2e7 100644
--- a/xen/include/asm-x86/livepatch.h
+++ b/xen/include/asm-x86/livepatch.h
@@ -6,7 +6,10 @@
 #ifndef __XEN_X86_LIVEPATCH_H__
 #define __XEN_X86_LIVEPATCH_H__
 
+#include <xen/sizes.h> /* For SZ_* macros. */
+
 #define ARCH_PATCH_INSN_SIZE 5
+#define ARCH_LIVEPATCH_RANGE SZ_2G
 
 #endif /* __XEN_X86_LIVEPATCH_H__ */
 
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index b7f66d4..b7b84e7 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -12,6 +12,7 @@ struct livepatch_elf_sym;
 struct xen_sysctl_livepatch_op;
 
 #include <xen/elfstructs.h>
+#include <xen/errno.h> /* For -ENOSYS or -EOVERFLOW */
 #ifdef CONFIG_LIVEPATCH
 
 /*
@@ -79,6 +80,21 @@ unsigned int livepatch_insn_len(const struct livepatch_func *func)
 
     return ARCH_PATCH_INSN_SIZE;
 }
+
+static inline int livepatch_verify_distance(const struct livepatch_func *func)
+{
+    long offset;
+    long range = ARCH_LIVEPATCH_RANGE;
+
+    if ( !func->new_addr ) /* Ignore NOPs. */
+        return 0;
+
+    offset = func->old_addr - func->new_addr;
+    if ( offset < -range || offset >= range )
+        return -EOVERFLOW;
+
+    return 0;
+}
 /*
  * These functions are called around the critical region patching live code,
  * for an architecture to take make appropratie global state adjustments.
@@ -103,7 +119,6 @@ void arch_livepatch_unmask(void);
 #define init_or_livepatch_data        __initdata
 #define init_or_livepatch             __init
 
-#include <xen/errno.h> /* For -ENOSYS */
 static inline int livepatch_op(struct xen_sysctl_livepatch_op *op)
 {
     return -ENOSYS;
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x]
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (5 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 12:56   ` Julien Grall
  2016-09-23 14:44   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols Konrad Rzeszutek Wilk
                   ` (8 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

Those symbols are used to help final linkers to replace insn.
The ARM ELF specification mandates that they are present
to denote the start of certain CPU features. There are two
variants of it - short and long format.

Either way - we can ignore these symbols.

Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> [x86 bits]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v1: First submission
v2: Update the order of symbols, fix title
    Add {} in after the first if - per Jan's recommendation.
v3: Add Andrew's Review tag
    Make the function return an bool_t.
    Skip check for '$t'
    Fix spelling of comments.
    s/arch_is_payload_symbol/arch_livepatch_symbol_ok/
v4: s/bool_t/bool/
v5: Removed an extra space in the conditional.
---
 xen/arch/arm/livepatch.c    | 33 +++++++++++++++++++++++++++++++++
 xen/arch/x86/livepatch.c    |  7 +++++++
 xen/common/livepatch.c      |  2 +-
 xen/include/xen/livepatch.h |  2 ++
 4 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 9284766..9959315 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -84,6 +84,39 @@ void arch_livepatch_unmask(void)
     local_abort_enable();
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /*
+     * - Mapping symbols - denote the "start of a sequence of bytes of the
+     *   appropriate type" to mark certain features - such as start of region
+     *   containing data ($d); ARM ($a), or A64 ($x) instructions.
+     *   We ignore Thumb instructions ($t) as we shouldn't have them.
+     *
+     * The format is either short: '$x' or long: '$x.<any>'. We do not
+     * need this and more importantly - each payload will contain this
+     * resulting in symbol collisions.
+     */
+    if ( *sym->name == '$' && sym->name[1] != '\0' )
+    {
+        char p = sym->name[1];
+        size_t len = strlen(sym->name);
+
+        if ( (len >= 3 && (sym->name[2] == '.' )) || (len == 2) )
+        {
+            if ( p == 'd' ||
+#ifdef CONFIG_ARM_32
+                 p == 'a'
+#else
+                 p == 'x'
+#endif
+               )
+                return false;
+        }
+    }
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index b0d81d7..7a369a0 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -124,6 +124,13 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return 0;
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index f2f866c..082f553 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -749,7 +749,7 @@ static bool_t is_payload_symbol(const struct livepatch_elf *elf,
          !strncmp(sym->name, ".L", 2) )
         return 0;
 
-    return 1;
+    return arch_livepatch_symbol_ok(elf, sym);
 }
 
 static int build_symbol_table(struct payload *payload,
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index b7b84e7..e8c67d6 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -48,6 +48,8 @@ bool_t is_patch(const void *addr);
 
 /* Arch hooks. */
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (6 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x] Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:00   ` Julien Grall
  2016-09-23 14:49   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test Konrad Rzeszutek Wilk
                   ` (7 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

Certain platforms, such as ARM [32|64] add extra mapping symbols
such as $x (for ARM64 instructions), or more interesting to
this patch: $t (for Thumb instructions). These symbols are suppose
to help the final linker to make any adjustments (such as
add an veneer). But more importantly - we do not compile Xen
with any Thumb instructions (which are variable length) - and
if we find these mapping symbols we should disallow such payload.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
    Use &sym[i] instead of sym (as that will always be NULL).
v4: Use bool instead of int for return
    Update comment in common code about ARM odd symbols.
    s/_check/_deny/ to make it more clear.
v5: Also check for $t.* wildcard.
    Use Julien's variant where we roll the [2] check in the return.
---
 xen/arch/arm/livepatch.c    | 16 ++++++++++++++++
 xen/arch/x86/livepatch.c    |  7 +++++++
 xen/common/livepatch_elf.c  |  7 +++++++
 xen/include/xen/livepatch.h |  2 ++
 4 files changed, 32 insertions(+)

diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 9959315..5a99ab5 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -117,6 +117,22 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+#ifdef CONFIG_ARM_32
+    /*
+     * Xen does not use Thumb instructions - and we should not see any of
+     * them. If we do, abort.
+     */
+    if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
+    {
+        return ( !sym->name[2] || sym->name[2] == '.' );
+    }
+#endif
+    return false;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index 7a369a0..9663ef6 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -131,6 +131,13 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return false;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/common/livepatch_elf.c b/xen/common/livepatch_elf.c
index f46990e..ec74beb 100644
--- a/xen/common/livepatch_elf.c
+++ b/xen/common/livepatch_elf.c
@@ -251,6 +251,13 @@ static int elf_get_sym(struct livepatch_elf *elf, const void *data)
 
         sym[i].sym = s;
         sym[i].name = strtab_sec->data + delta;
+        /* e.g. On ARM we should NEVER see $t* symbols. */
+        if ( arch_livepatch_symbol_deny(elf, &sym[i]) )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Symbol '%s' should not be in payload!\n",
+                    elf->name, sym[i].name);
+            return -EINVAL;
+        }
     }
     elf->nsym = nsym;
 
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index e8c67d6..98ec012 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -50,6 +50,8 @@ bool_t is_patch(const void *addr);
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
 bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
                               const struct livepatch_elf_sym *sym);
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (7 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:01   ` Julien Grall
  2016-09-23 14:51   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH Konrad Rzeszutek Wilk
                   ` (6 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

So they can be shared with ARM64 (but not yet, so they
are only built on x86).

No functional change.

We also need to tweak the MAINTAINERS and .gitignore file.

Also we need to update SUBDIRS to include the new 'test'
directory so 'cscope' can show the example livepatches.

Acked-by: Jan Beulich <jbeulich@suse.com> [for directory]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v1: First submission
v2: Move to test/livepatch per Jan's recommendation
v3: Sort MAINTAINERS for livepatch.
    Add Jan's Acked-by.
    Added on the SUBDIRS the 'test' directory
    Change title of patch (common-> own sub-directory)
---
 .gitignore                                                     | 8 ++++----
 MAINTAINERS                                                    | 1 +
 xen/Makefile                                                   | 5 +++--
 xen/arch/arm/Makefile                                          | 3 ---
 xen/arch/x86/Makefile                                          | 5 -----
 xen/test/Makefile                                              | 9 +++++++++
 xen/{arch/x86/test => test/livepatch}/Makefile                 | 0
 xen/{arch/x86/test => test/livepatch}/xen_bye_world.c          | 0
 xen/{arch/x86/test => test/livepatch}/xen_bye_world_func.c     | 0
 xen/{arch/x86/test => test/livepatch}/xen_hello_world.c        | 0
 xen/{arch/x86/test => test/livepatch}/xen_hello_world_func.c   | 0
 xen/{arch/x86/test => test/livepatch}/xen_replace_world.c      | 0
 xen/{arch/x86/test => test/livepatch}/xen_replace_world_func.c | 0
 13 files changed, 17 insertions(+), 14 deletions(-)
 create mode 100644 xen/test/Makefile
 rename xen/{arch/x86/test => test/livepatch}/Makefile (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_bye_world.c (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_bye_world_func.c (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_hello_world.c (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_hello_world_func.c (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_replace_world.c (100%)
 rename xen/{arch/x86/test => test/livepatch}/xen_replace_world_func.c (100%)

diff --git a/.gitignore b/.gitignore
index cc64fc9..eeabe0b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -254,10 +254,6 @@ xen/arch/x86/efi.lds
 xen/arch/x86/efi/check.efi
 xen/arch/x86/efi/disabled
 xen/arch/x86/efi/mkreloc
-xen/arch/x86/test/config.h
-xen/arch/x86/test/xen_hello_world.livepatch
-xen/arch/x86/test/xen_bye_world.livepatch
-xen/arch/x86/test/xen_replace_world.livepatch
 xen/arch/*/efi/boot.c
 xen/arch/*/efi/compat.c
 xen/arch/*/efi/efi.h
@@ -274,6 +270,10 @@ xen/include/public/public
 xen/include/xen/*.new
 xen/include/xen/acm_policy.h
 xen/include/xen/compile.h
+xen/test/livepatch/config.h
+xen/test/livepatch/xen_bye_world.livepatch
+xen/test/livepatch/xen_hello_world.livepatch
+xen/test/livepatch/xen_replace_world.livepatch
 xen/tools/kconfig/.tmp_gtkcheck
 xen/tools/kconfig/.tmp_qtcheck
 xen/tools/symbols
diff --git a/MAINTAINERS b/MAINTAINERS
index 1c39146..8c5b756 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -273,6 +273,7 @@ F:  xen/arch/*/*/livepatch*
 F:  xen/common/livepatch*
 F:  xen/include/asm-*/livepatch.h
 F:  xen/include/xen/livepatch*
+F:  xen/test/livepatch/*
 
 MACHINE CHECK (MCA) & RAS
 M:	Christoph Egger <chegger@amazon.de>
diff --git a/xen/Makefile b/xen/Makefile
index 012509b..e989a20 100644
--- a/xen/Makefile
+++ b/xen/Makefile
@@ -80,7 +80,7 @@ _install: $(TARGET)$(CONFIG_XEN_INSTALL_SUFFIX)
 
 .PHONY: _tests
 _tests:
-	$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) tests
+	$(MAKE) -f $(BASEDIR)/Rules.mk -C test tests
 
 .PHONY: _uninstall
 _uninstall: D=$(DESTDIR)
@@ -114,6 +114,7 @@ _clean: delete-unfresh-files
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C xsm clean
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C crypto clean
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C arch/$(TARGET_ARCH) clean
+	$(MAKE) -f $(BASEDIR)/Rules.mk -C test clean
 	$(MAKE) -f $(BASEDIR)/tools/kconfig/Makefile.kconfig ARCH=$(ARCH) SRCARCH=$(SRCARCH) clean
 	find . \( -name "*.o" -o -name ".*.d" \) -exec rm -f {} \;
 	rm -f include/asm $(TARGET) $(TARGET).gz $(TARGET).efi $(TARGET).efi.map $(TARGET)-syms $(TARGET)-syms.map *~ core
@@ -189,7 +190,7 @@ include/asm-$(TARGET_ARCH)/asm-offsets.h: arch/$(TARGET_ARCH)/asm-offsets.s
 	  echo ""; \
 	  echo "#endif") <$< >$@
 
-SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers
+SUBDIRS = xsm arch/$(TARGET_ARCH) common drivers test
 define all_sources
     ( find include/asm-$(TARGET_ARCH) -name '*.h' -print; \
       find include -name 'asm-*' -prune -o -name '*.h' -print; \
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 5cee84d..1d9051c 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -74,9 +74,6 @@ ifeq ($(CONFIG_ARM_64),y)
 	ln -sf $(notdir $@)  ../../$(notdir $@).efi
 endif
 
-.PHONY: tests
-tests:
-
 $(TARGET).axf: $(TARGET)-syms
 	# XXX: VE model loads by VMA so instead of
 	# making a proper ELF we link with LMA == VMA and adjust crudely
diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index d3875c5..931917d 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -93,10 +93,6 @@ $(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
 	./boot/mkelf32 $(notes_phdrs) $(TARGET)-syms $(TARGET) 0x100000 \
 	`$(NM) -nr $(TARGET)-syms | head -n 1 | sed -e 's/^\([^ ]*\).*/0x\1/'`
 
-.PHONY: tests
-tests:
-	$(MAKE) -f $(BASEDIR)/Rules.mk -C test livepatch
-
 ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o $(BASEDIR)/arch/x86/efi/built_in.o $(ALL_OBJS)
 
 ifeq ($(lto),y)
@@ -226,4 +222,3 @@ clean::
 	rm -f $(BASEDIR)/.xen.efi.[0-9]* efi/*.o efi/.*.d efi/*.efi efi/disabled efi/mkreloc
 	rm -f boot/reloc.S boot/reloc.lnk boot/reloc.bin
 	rm -f note.o
-	$(MAKE) -f $(BASEDIR)/Rules.mk -C test clean
diff --git a/xen/test/Makefile b/xen/test/Makefile
new file mode 100644
index 0000000..8c53040
--- /dev/null
+++ b/xen/test/Makefile
@@ -0,0 +1,9 @@
+.PHONY: tests
+tests:
+ifeq ($(XEN_TARGET_ARCH),x86_64)
+	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
+endif
+
+.PHONY: clean
+clean::
+	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch clean
diff --git a/xen/arch/x86/test/Makefile b/xen/test/livepatch/Makefile
similarity index 100%
rename from xen/arch/x86/test/Makefile
rename to xen/test/livepatch/Makefile
diff --git a/xen/arch/x86/test/xen_bye_world.c b/xen/test/livepatch/xen_bye_world.c
similarity index 100%
rename from xen/arch/x86/test/xen_bye_world.c
rename to xen/test/livepatch/xen_bye_world.c
diff --git a/xen/arch/x86/test/xen_bye_world_func.c b/xen/test/livepatch/xen_bye_world_func.c
similarity index 100%
rename from xen/arch/x86/test/xen_bye_world_func.c
rename to xen/test/livepatch/xen_bye_world_func.c
diff --git a/xen/arch/x86/test/xen_hello_world.c b/xen/test/livepatch/xen_hello_world.c
similarity index 100%
rename from xen/arch/x86/test/xen_hello_world.c
rename to xen/test/livepatch/xen_hello_world.c
diff --git a/xen/arch/x86/test/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
similarity index 100%
rename from xen/arch/x86/test/xen_hello_world_func.c
rename to xen/test/livepatch/xen_hello_world_func.c
diff --git a/xen/arch/x86/test/xen_replace_world.c b/xen/test/livepatch/xen_replace_world.c
similarity index 100%
rename from xen/arch/x86/test/xen_replace_world.c
rename to xen/test/livepatch/xen_replace_world.c
diff --git a/xen/arch/x86/test/xen_replace_world_func.c b/xen/test/livepatch/xen_replace_world_func.c
similarity index 100%
rename from xen/arch/x86/test/xen_replace_world_func.c
rename to xen/test/livepatch/xen_replace_world_func.c
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (8 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:03   ` Julien Grall
  2016-09-27  9:49   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64 Konrad Rzeszutek Wilk
                   ` (5 subsequent siblings)
  15 siblings, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

To use as a common way of testing alternative patching for
livepatches. Both architectures have this FEATURE and the
test-cases can piggyback on that.

Suggested-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission
v4: Move the LIVEPATCH_FEATURE to asm-x86/livepatch.h
v5: Reorder the patch to be before " livepatch: tests: Make them
    compile under ARM64"
    Always expose FEATURE_LIVEPATCH on ARM.
---
 xen/arch/arm/livepatch.c                  | 3 +++
 xen/include/asm-arm/cpufeature.h          | 3 ++-
 xen/include/asm-x86/livepatch.h           | 1 +
 xen/test/livepatch/xen_hello_world_func.c | 3 ++-
 4 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 5a99ab5..7855bc5 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -8,6 +8,7 @@
 #include <xen/livepatch.h>
 #include <xen/vmap.h>
 
+#include <asm/cpufeature.h>
 #include <asm/livepatch.h>
 #include <asm/mm.h>
 
@@ -177,6 +178,8 @@ void __init arch_livepatch_init(void)
     end = (void *)LIVEPATCH_VMAP_END;
 
     vm_init_type(VMAP_XEN, start, end);
+
+    cpus_set_cap(LIVEPATCH_FEATURE);
 }
 
 /*
diff --git a/xen/include/asm-arm/cpufeature.h b/xen/include/asm-arm/cpufeature.h
index 66e930f..af60fe3 100644
--- a/xen/include/asm-arm/cpufeature.h
+++ b/xen/include/asm-arm/cpufeature.h
@@ -39,8 +39,9 @@
 #define ARM64_WORKAROUND_DEVICE_LOAD_ACQUIRE    1
 #define ARM32_WORKAROUND_766422 2
 #define ARM64_WORKAROUND_834220 3
+#define LIVEPATCH_FEATURE   4
 
-#define ARM_NCAPS           4
+#define ARM_NCAPS           5
 
 #ifndef __ASSEMBLY__
 
diff --git a/xen/include/asm-x86/livepatch.h b/xen/include/asm-x86/livepatch.h
index 7dfc2e7..00aefd2 100644
--- a/xen/include/asm-x86/livepatch.h
+++ b/xen/include/asm-x86/livepatch.h
@@ -10,6 +10,7 @@
 
 #define ARCH_PATCH_INSN_SIZE 5
 #define ARCH_LIVEPATCH_RANGE SZ_2G
+#define LIVEPATCH_FEATURE    X86_FEATURE_ALWAYS
 
 #endif /* __XEN_X86_LIVEPATCH_H__ */
 
diff --git a/xen/test/livepatch/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
index 03d6b84..0321f3e 100644
--- a/xen/test/livepatch/xen_hello_world_func.c
+++ b/xen/test/livepatch/xen_hello_world_func.c
@@ -6,6 +6,7 @@
 #include <xen/types.h>
 
 #include <asm/alternative.h>
+#include <asm/livepatch.h>
 #include <asm/nops.h>
 #include <asm/uaccess.h>
 
@@ -17,7 +18,7 @@ const char *xen_hello_world(void)
     unsigned long tmp;
     int rc;
 
-    alternative(ASM_NOP8, ASM_NOP1, X86_FEATURE_LM);
+    alternative(ASM_NOP8, ASM_NOP1, LIVEPATCH_FEATURE);
     /*
      * Any BUG, or WARN_ON will contain symbol and payload name. Furthermore
      * exceptions will be caught and processed properly.
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (9 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:10   ` Julien Grall
  2016-09-21 17:32 ` [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches Konrad Rzeszutek Wilk
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Wei Liu, Konrad Rzeszutek Wilk, George Dunlap, Andrew Cooper,
	Tim Deegan, Jan Beulich, Ian Jackson

We need to two things:
1) Wrap the platform-specific objcopy parameters in defines
   The input and output parameters for $(OBJCOPY) are different
   based on the platforms. As such provide them in the
   OBJCOPY_MAGIC define and use that.

2) The alternative is a bit different (exists only under ARM64
   and x86), while and there are no exceptions under ARM at all.
   We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
   how it is done on x86.

We are not yet attempting to build them under ARM32 so
that is still ifdefed out.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>

v1: First submission
v2: Corrected description by Julien
    Add #ifeq instead of #else for ARM case.
v3: Moved 'asm(alter..)' by one space to the left.
v4: Rebase on top of "livepatch/tests: Make .livepatch.depends be read-only"
    Rewrote the commit description 2) a bit.
---
 xen/test/Makefile                         |  2 +-
 xen/test/livepatch/Makefile               | 12 ++++++++++--
 xen/test/livepatch/xen_hello_world_func.c |  7 +++++++
 3 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/xen/test/Makefile b/xen/test/Makefile
index 8c53040..95c1755 100644
--- a/xen/test/Makefile
+++ b/xen/test/Makefile
@@ -1,6 +1,6 @@
 .PHONY: tests
 tests:
-ifeq ($(XEN_TARGET_ARCH),x86_64)
+ifneq $(XEN_TARGET_ARCH),arm32)
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
 endif
 
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 48ff843..5db4d9c 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -1,5 +1,12 @@
 include $(XEN_ROOT)/Config.mk
 
+ifeq ($(XEN_TARGET_ARCH),x86_64)
+OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
+endif
+ifeq ($(XEN_TARGET_ARCH),arm64)
+OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
+endif
+
 CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
 CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
 
@@ -54,8 +61,9 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
 .PHONY: note.o
 note.o:
 	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
-	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
+		   --rename-section=.data=.livepatch.depends -S $@.bin $@
 	rm -f $@.bin
 
 #
@@ -65,7 +73,7 @@ note.o:
 .PHONY: hello_world_note.o
 hello_world_note.o: $(LIVEPATCH)
 	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(LIVEPATCH) $@.bin
-	$(OBJCOPY)  -I binary -O elf64-x86-64 -B i386:x86-64 \
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
 	rm -f $@.bin
 
diff --git a/xen/test/livepatch/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
index 0321f3e..c5c0da1 100644
--- a/xen/test/livepatch/xen_hello_world_func.c
+++ b/xen/test/livepatch/xen_hello_world_func.c
@@ -7,14 +7,17 @@
 
 #include <asm/alternative.h>
 #include <asm/livepatch.h>
+#ifdef CONFIG_X86
 #include <asm/nops.h>
 #include <asm/uaccess.h>
 
 static unsigned long *non_canonical_addr = (unsigned long *)0xdead000000000000ULL;
+#endif
 
 /* Our replacement function for xen_extra_version. */
 const char *xen_hello_world(void)
 {
+#ifdef CONFIG_X86
     unsigned long tmp;
     int rc;
 
@@ -25,6 +28,10 @@ const char *xen_hello_world(void)
      */
     rc = __get_user(tmp, non_canonical_addr);
     BUG_ON(rc != -EFAULT);
+#endif
+#ifdef CONFIG_ARM_64
+    asm(ALTERNATIVE("nop", "nop", LIVEPATCH_FEATURE));
+#endif
 
     return "Hello World";
 }
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (10 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64 Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:17   ` Julien Grall
  2016-09-21 17:32 ` [PATCH v5 13/16] bug/x86/arm: Align bug_frames sections Konrad Rzeszutek Wilk
                   ` (3 subsequent siblings)
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Konrad Rzeszutek Wilk

This is similar to commit fb9d877a9c0f3d4d15db8f6e0c5506ea641862c6
"xen/arm64: Add an helper to invalidate all instruction caches"
except it is on ARM32 side.

When we are flushing the cache we are most likley also want
to flush the branch predictor too. Hence we add this.

And we also need to follow this with dsb()/isb() which are
memory barriers().

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v2: First submission
v3: Squashed "xen/arm32/livepatch: Add BPICALLIS to helper to invalidate
    all instruction caches" in this patch.
v4: Added dsb()/isb() instructions.
---
 xen/include/asm-arm/arm32/page.h | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/xen/include/asm-arm/arm32/page.h b/xen/include/asm-arm/arm32/page.h
index bccdbfc..ea4b312 100644
--- a/xen/include/asm-arm/arm32/page.h
+++ b/xen/include/asm-arm/arm32/page.h
@@ -30,6 +30,22 @@ static inline void write_pte(lpae_t *p, lpae_t pte)
 #define __clean_and_invalidate_dcache_one(R) STORE_CP32(R, DCCIMVAC)
 
 /*
+ * Invalidate all instruction caches in Inner Shareable domain to PoU.
+ * We also need to flush the branch predictor for ARMv7 as it may be
+ * architecturally visible to the software (see B2.2.4 in ARM DDI 0406C.b).
+ */
+static inline void invalidate_icache(void)
+{
+    asm volatile (
+        CMD_CP32(ICIALLUIS)     /* Flush I-cache. */
+        CMD_CP32(BPIALLIS)      /* Flush branch predictor. */
+        : : : "memory");
+
+    dsb(ish);                   /* Ensure completion of the flush I-cache */
+    isb();                      /* Synchronize fetched instruction stream. */
+}
+
+/*
  * Flush all hypervisor mappings from the TLB and branch predictor of
  * the local processor.
  *
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 13/16] bug/x86/arm: Align bug_frames sections.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (11 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 14/16] livepatch: Initial ARM32 support Konrad Rzeszutek Wilk
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

Most of the WARN_ON or BUG_ON sections are properly aligned on
x86. However on ARM and on x86 assembler the macros don't include
any alignment information - hence they end up being the default
byte granularity.

On ARM32 it is paramount that the alignment is word-size (4)
otherwise if one tries to use (uint32_t*) access (such
as livepatch ELF relocations) we get a Data Abort.

Enforcing bug_frames to have the proper alignment across all
architectures and in both C and x86 makes them all the same.

Furthermore on x86 the bloat-o-meter detects that with this
change:

add/remove: 0/0 grow/shrink: 0/0 up/down: 0/0 (0)
function                                     old     new   delta

On ARM32:
add/remove: 1/0 grow/shrink: 0/1 up/down: 384/-288 (96)
function                                     old     new   delta
gnttab_unpopulate_status_frames                -     384    +384
do_grant_table_op                          10808   10520    -288

And ARM64:
add/remove: 1/2 grow/shrink: 0/1 up/down: 4164/-4236 (-72)
function                                     old     new   delta
gnttab_map_grant_ref                           -    4164   +4164
do_grant_table_op                           9892    9836     -56
grant_map_exists                             300       -    -300
__gnttab_map_grant_ref                      3880       -   -3880

Reviewed-by: Julien Grall <julien.grall@arm.com>
Acked-by: Jan Beulich <jbeulich@suse.com> [x86 parts]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: First submission. Replaces the "livepatch/elf: Adjust section aligment to word"
    patch.
v4: Remove the .ALIGN(4) in xen.lds.S for x86 (the only place needing
    that change).
    Update the commit description with correct x86 results
    Remove the . = ALIGN(4); in linker filer on x86 [the only file needing the change]
v5: Add Jan's Ack on x86 parts.
v6: Added Julien's Reviewed-by
    s/aligment/alignment/
    s/align 4/p2align 2/ as the align semnatics varies by platforms, while
    p2align is the same across all of them.
---
 xen/arch/x86/xen.lds.S    | 1 -
 xen/include/asm-arm/bug.h | 1 +
 xen/include/asm-x86/bug.h | 1 +
 3 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/xen/arch/x86/xen.lds.S b/xen/arch/x86/xen.lds.S
index d903c31..7676de9 100644
--- a/xen/arch/x86/xen.lds.S
+++ b/xen/arch/x86/xen.lds.S
@@ -79,7 +79,6 @@ SECTIONS
   .rodata : {
        _srodata = .;
        /* Bug frames table */
-       . = ALIGN(4);
        __start_bug_frames = .;
        *(.bug_frames.0)
        __stop_bug_frames_0 = .;
diff --git a/xen/include/asm-arm/bug.h b/xen/include/asm-arm/bug.h
index 68353e1..4704e2d 100644
--- a/xen/include/asm-arm/bug.h
+++ b/xen/include/asm-arm/bug.h
@@ -52,6 +52,7 @@ struct bug_frame {
          ".popsection\n"                                                    \
          ".pushsection .bug_frames." __stringify(type) ", \"a\", %progbits\n"\
          "4:\n"                                                             \
+         ".p2align 2\n"                                                     \
          ".long (1b - 4b)\n"                                                \
          ".long (2b - 4b)\n"                                                \
          ".long (3b - 4b)\n"                                                \
diff --git a/xen/include/asm-x86/bug.h b/xen/include/asm-x86/bug.h
index c5d2d4c..9bb4a19 100644
--- a/xen/include/asm-x86/bug.h
+++ b/xen/include/asm-x86/bug.h
@@ -98,6 +98,7 @@ extern const struct bug_frame __start_bug_frames[],
     .popsection
 
     .pushsection .bug_frames.\type, "a", @progbits
+        .p2align 2
         .L\@bf:
         .long (.L\@ud - .L\@bf) + \
                ((\line >> BUG_LINE_LO_WIDTH) << BUG_DISP_WIDTH)
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 14/16] livepatch: Initial ARM32 support.
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (12 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 13/16] bug/x86/arm: Align bug_frames sections Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-27 16:39   ` Julien Grall
  2016-09-21 17:32 ` [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert Konrad Rzeszutek Wilk
  2016-09-21 17:32 ` [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case Konrad Rzeszutek Wilk
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Konrad Rzeszutek Wilk

The patch piggybacks on: livepatch: Initial ARM64 support, which
brings up all of the necessary livepatch infrastructure pieces in.

This patch adds three major pieces:

 1) ELF relocations. ARM32 uses SHT_REL instead of SHT_RELA which
    means the adddendum had to be extracted from within the
    instruction. Which required parsing BL/BLX, B/BL<cond>,
    MOVT, and MOVW instructions.

    The code was written from scratch using the ARM ELF manual
    (and the ARM Architecture Reference Manual)

 2) Inserting an trampoline. We use the B (branch to address)
    which uses an offset that is based on the PC value: PC + imm32.
    Because we insert the branch at the start of the old function
    we have to account for the instruction already being fetched
    and subtract -8 from the delta (new_addr - old_addr). See
    ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)

 3) Allows the test-cases to be built under ARM 32.
    The "livepatch: tests: Make them compile under ARM64"
    put in the right infrastructure for it and we piggyback on it.

Acked-by: Julien Grall <julien.grall@arm.com>
Acked-by: Jan Beulich <jbeulich@suse.com> [for non-ARM parts]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v2: First submission.
v3: Use LIVEPATCH_ARCH_RANGE instead of NEGATIVE_32MB macro
   -Use PATCH_INSN_SIZE instead of the value 4.
   -Ditch the old_ptr local variable.
   -Use 8 for evaluating the branch instead of 4. Based on ARM docs.
   -NOP patch up to sizeof(opaque) % PATCH_INSN_SIZE (so 7 instructions).
   -Don't mask 0x00FFFFF_E_ after shifting, instead mask by 0x00FFFFF_F_.
    The reason is that offset is constructed by shifting by two the insn
    (except the first two bytes) by left which meant we would have cleared
    offset[2]! - and jumped to a location that was -4 bytes off.
   -Update commit description to have -8 instead of -4 delta and also
    include reference to spec.
v4: Added Jan's Ack.
   s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
   s/arch_livepatch_insn_len/livepatch_insn_len/
   s/LIVEPATCH_ARCH_RANGE/ARCH_LIVEPATCH_RANGE/
v5: Added Julien's Ack.
   - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
   - Added explanation for the usage of data cache and why we need to sync it.
---
 xen/arch/arm/arm32/livepatch.c | 279 ++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/arm64/livepatch.c |   7 ++
 xen/arch/arm/livepatch.c       |   7 --
 xen/common/Kconfig             |   2 +-
 xen/include/xen/elfstructs.h   |  24 +++-
 xen/test/Makefile              |   2 -
 xen/test/livepatch/Makefile    |   3 +
 7 files changed, 311 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 80f9646..3f47326 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -3,28 +3,303 @@
  */
 
 #include <xen/errno.h>
+#include <xen/kernel.h>
 #include <xen/lib.h>
 #include <xen/livepatch_elf.h>
 #include <xen/livepatch.h>
 
+#include <asm/page.h>
+#include <asm/livepatch.h>
+
 void arch_livepatch_apply(struct livepatch_func *func)
 {
+    uint32_t insn;
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
+
+    ASSERT(vmap_of_xen_text);
+
+    len = livepatch_insn_len(func);
+    if ( !len )
+        return;
+
+    /* Save old ones. */
+    memcpy(func->opaque, func->old_addr, len);
+
+    if ( func->new_addr )
+    {
+        s32 delta;
+
+        /*
+         * PC is current address (old_addr) + 8 bytes. The semantics for a
+         * unconditional branch is to jump to PC + imm32 (offset).
+         *
+         * ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
+         *
+         */
+        delta = (s32)func->new_addr - (s32)(func->old_addr + 8);
+
+        /* The arch_livepatch_symbol_ok should have caught it. */
+        ASSERT(delta >= -(s32)ARCH_LIVEPATCH_RANGE ||
+               delta < (s32)ARCH_LIVEPATCH_RANGE);
+
+        /* CPU shifts by two (left) when decoding, so we shift right by two. */
+        delta = delta >> 2;
+        /* Lets not modify the cond. */
+        delta &= 0x00FFFFFF;
+
+        insn = 0xea000000 | delta;
+    }
+    else
+        insn = 0xe1a00000; /* mov r0, r0 */
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = len / sizeof(uint32_t);
+
+    /* PATCH! */
+    for ( i = 0; i < len; i++ )
+        *(new_ptr + i) = insn;
+
+    /*
+    * When we upload the payload, it will go through the data cache
+    * (the region is cacheable). Until the data cache is cleaned, the data
+    * may not reach the memory. And in the case the data and instruction cache
+    * are separated, we may read invalid instruction from the memory because
+    * the data cache have not yet synced with the memory. Hence sync it.
+    */
+    if ( func->new_addr )
+        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
 }
 
 void arch_livepatch_revert(const struct livepatch_func *func)
 {
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = livepatch_insn_len(func) / sizeof(uint32_t);
+    for ( i = 0; i < len; i++ )
+    {
+        uint32_t insn;
+
+        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
+        /* PATCH! */
+        *(new_ptr + i) = insn;
+    }
 }
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
-    return -EOPNOTSUPP;
+    const Elf_Ehdr *hdr = elf->hdr;
+
+    if ( hdr->e_machine != EM_ARM ||
+         hdr->e_ident[EI_CLASS] != ELFCLASS32 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
+                elf->name);
+        return -EOPNOTSUPP;
+    }
+
+    if ( (hdr->e_flags & EF_ARM_EABI_MASK) != EF_ARM_EABI_VER5 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF EABI(%x)!\n",
+                elf->name, hdr->e_flags);
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+static s32 get_addend(unsigned char type, void *dest)
+{
+    s32 addend = 0;
+
+    switch ( type ) {
+    case R_ARM_NONE:
+        /* ignore */
+        break;
+
+    case R_ARM_ABS32:
+        addend = *(u32 *)dest;
+        break;
+
+    case R_ARM_REL32:
+        addend = *(u32 *)dest;
+        break;
+
+    case R_ARM_MOVW_ABS_NC:
+    case R_ARM_MOVT_ABS:
+        addend =  (*(u32 *)dest & 0x00000FFF);
+        addend |= (*(u32 *)dest & 0x000F0000) >> 4;
+        /* Addend is to sign-extend ([19:16],[11:0]). */
+        addend = (s16)addend;
+        break;
+
+    case R_ARM_CALL:
+    case R_ARM_JUMP24:
+        /* Addend = sign_extend (insn[23:0]) << 2 */
+        addend = ((*(u32 *)dest & 0xFFFFFF) ^ 0x800000) - 0x800000;
+        addend = addend << 2;
+        break;
+    }
+
+    return addend;
+}
+
+static int perform_rel(unsigned char type, void *dest, uint32_t val, s32 addend)
+{
+
+    switch ( type ) {
+    case R_ARM_NONE:
+        /* ignore */
+        break;
+
+    case R_ARM_ABS32: /* (S + A) | T */
+        *(u32 *)dest = (val + addend);
+        break;
+
+    case R_ARM_REL32: /* ((S + A) | T) – P */
+        *(u32 *)dest = (val + addend) - (uint32_t)dest;
+        break;
+
+    case R_ARM_MOVW_ABS_NC: /* S + A */
+    case R_ARM_MOVT_ABS: /* S + A */
+        /* Clear addend if needed . */
+        if ( addend )
+            *(u32 *)dest &= 0xFFF0F000;
+
+        if ( type == R_ARM_MOVT_ABS )
+        {
+            /*
+             * Almost the same as MOVW except it uses the 16 bit
+             * high value. Putting it in insn requires shifting right by
+             * 16-bit (as we only have 16-bit for imm.
+             */
+            val &= 0xFFFF0000; /* ResultMask */
+            val = val >> 16;
+        }
+        else
+        {
+            /* MOVW loads 16 bits into the bottom half of a register. */
+            val &= 0xFFFF;
+        }
+        /* [11:0] = Result_Mask(X) & 0xFFF,[19:16] = Result_Mask(X) >> 12 */
+        *(u32 *)dest |= val & 0xFFF;
+        *(u32 *)dest |= (val >> 12) << 16;
+        break;
+
+    case R_ARM_CALL:
+    case R_ARM_JUMP24: /* (S + A) - P */
+        /* Clear the old addend. */
+        if ( addend )
+            *(u32 *)dest &= 0xFF000000;
+
+        val += addend - (uint32_t)dest;
+
+        /*
+         * arch_livepatch_verify_distance can't account of addend so we have
+         * to do the check here as well.
+         */
+        if ( (s32)val < -(s32)ARCH_LIVEPATCH_RANGE ||
+             (s32)val >= (s32)ARCH_LIVEPATCH_RANGE )
+            return -EOVERFLOW;
+
+        /* CPU always shifts insn by two, so complement it. */
+        val = val >> 2;
+        val &= 0x00FFFFFE;
+        *(u32 *)dest |= (uint32_t)val;
+        break;
+
+    default:
+         return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+int arch_livepatch_perform(struct livepatch_elf *elf,
+                           const struct livepatch_elf_sec *base,
+                           const struct livepatch_elf_sec *rela,
+                           bool use_rela)
+{
+    const Elf_RelA *r_a;
+    const Elf_Rel *r;
+    unsigned int symndx, i;
+    uint32_t val;
+    void *dest;
+    int rc = 0;
+
+    for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+    {
+        unsigned char type;
+        s32 addend = 0;
+
+        if ( use_rela )
+        {
+            r_a = rela->data + i * rela->sec->sh_entsize;
+            symndx = ELF32_R_SYM(r_a->r_info);
+            type = ELF32_R_TYPE(r_a->r_info);
+            dest = base->load_addr + r_a->r_offset; /* P */
+            addend = r_a->r_addend;
+        }
+        else
+        {
+            r = rela->data + i * rela->sec->sh_entsize;
+            symndx = ELF32_R_SYM(r->r_info);
+            type = ELF32_R_TYPE(r->r_info);
+            dest = base->load_addr + r->r_offset; /* P */
+        }
+
+        if ( symndx > elf->nsym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative symbol wants symbol@%u which is past end!\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
+
+        if ( !use_rela )
+            addend = get_addend(type, dest);
+
+        val = elf->sym[symndx].sym->st_value; /* S */
+
+        rc = perform_rel(type, dest, val, addend);
+        switch ( rc ) {
+        case -EOVERFLOW:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
+                    elf->name, i, rela->name, base->name);
+            break;
+
+        case -EOPNOTSUPP:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation #%x\n",
+                    elf->name, type);
+            break;
+
+        default:
+            break;
+        }
+
+        if ( rc )
+            break;
+    }
+
+    return rc;
+}
+
+int arch_livepatch_perform_rel(struct livepatch_elf *elf,
+                               const struct livepatch_elf_sec *base,
+                               const struct livepatch_elf_sec *rela)
+{
+    return arch_livepatch_perform(elf, base, rela, false);
 }
 
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
 {
-    return -ENOSYS;
+    return arch_livepatch_perform(elf, base, rela, true);
 }
 
 /*
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index d3fc9ac..ea8044d 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -237,6 +237,13 @@ static int reloc_insn_imm(enum aarch64_reloc_op op, void *dest, u64 val,
     return 0;
 }
 
+int arch_livepatch_perform_rel(struct livepatch_elf *elf,
+                               const struct livepatch_elf_sec *base,
+                               const struct livepatch_elf_sec *rela)
+{
+    return -ENOSYS;
+}
+
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 7855bc5..6ee7081 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -134,13 +134,6 @@ bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
     return false;
 }
 
-int arch_livepatch_perform_rel(struct livepatch_elf *elf,
-                               const struct livepatch_elf_sec *base,
-                               const struct livepatch_elf_sec *rela)
-{
-    return -ENOSYS;
-}
-
 int arch_livepatch_secure(const void *va, unsigned int pages, enum va_type type)
 {
     unsigned long start = (unsigned long)va;
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 0f26027..d4f10ca 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -217,7 +217,7 @@ config CRYPTO
 config LIVEPATCH
 	bool "Live patching support (TECH PREVIEW)"
 	default n
-	depends on !ARM_32 && HAS_BUILD_ID = "y"
+	depends on HAS_BUILD_ID = "y"
 	---help---
 	  Allows a running Xen hypervisor to be dynamically patched using
 	  binary patches without rebooting. This is primarily used to binarily
diff --git a/xen/include/xen/elfstructs.h b/xen/include/xen/elfstructs.h
index 7329987..e543212 100644
--- a/xen/include/xen/elfstructs.h
+++ b/xen/include/xen/elfstructs.h
@@ -103,6 +103,15 @@ typedef uint64_t	Elf64_Xword;
                       (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
                       (ehdr).e_ident[EI_MAG3] == ELFMAG3)
 
+/* e_flags */
+#define EF_ARM_EABI_MASK	0xff000000
+#define EF_ARM_EABI_UNKNOWN	0x00000000
+#define EF_ARM_EABI_VER1	0x01000000
+#define EF_ARM_EABI_VER2	0x02000000
+#define EF_ARM_EABI_VER3	0x03000000
+#define EF_ARM_EABI_VER4	0x04000000
+#define EF_ARM_EABI_VER5	0x05000000
+
 /* ELF Header */
 typedef struct elfhdr {
 	unsigned char	e_ident[EI_NIDENT]; /* ELF Identification */
@@ -364,9 +373,22 @@ typedef struct {
 #define R_X86_64_PLT32		4	/* 32 bit PLT address */
 
 /*
+ * ARM32 relocation types. See
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
  * S - address of symbol.
- * A - addend for relocation (r_addend)
+ * A - addend for relocation (r_addend or need to extract from insn)
  * P - address of the dest being relocated (derieved from r_offset)
+ */
+#define R_ARM_NONE              0
+#define R_ARM_ABS32             2	/* Direct 32-bit. S+A */
+#define R_ARM_REL32             3	/* PC relative. S+A */
+#define R_ARM_CALL              28	/* SignExtend([23:0]) << 2. S+A-P */
+#define R_ARM_JUMP24            29	/* Same as R_ARM_CALL */
+#define R_ARM_MOVW_ABS_NC       43	/* SignExtend([19:16],[11:0])&0xFFFF, S+A */
+#define R_ARM_MOVT_ABS          44	/* SignExtend([19:16],[11:0))&0xFFFF0000 */
+					/*  >> 16, S+A. */
+
+/*
  * NC -  No check for overflow.
  *
  * The defines also use _PREL for PC-relative address, and _NC is No Check.
diff --git a/xen/test/Makefile b/xen/test/Makefile
index 95c1755..d91b319 100644
--- a/xen/test/Makefile
+++ b/xen/test/Makefile
@@ -1,8 +1,6 @@
 .PHONY: tests
 tests:
-ifneq $(XEN_TARGET_ARCH),arm32)
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
-endif
 
 .PHONY: clean
 clean::
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 5db4d9c..4d66a40 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -6,6 +6,9 @@ endif
 ifeq ($(XEN_TARGET_ARCH),arm64)
 OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
 endif
+ifeq ($(XEN_TARGET_ARCH),arm32)
+OBJCOPY_MAGIC := -I binary -O elf32-littlearm -B arm
+endif
 
 CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
 CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (13 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 14/16] livepatch: Initial ARM32 support Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-23 14:59   ` Ross Lagerwall
  2016-09-21 17:32 ` [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case Konrad Rzeszutek Wilk
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Konrad Rzeszutek Wilk

It is exactly the same in both platforms.

No functional change.

Acked-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v3: New submission.
v4: s/arch_livepatch_insn_len/livepatch_insn_len/
    s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
v5: Added Julien's Acked-by.
    Fixed comments.
  - Rebase on top "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
  - s/_jmp//
---
 xen/arch/arm/arm32/livepatch.c | 17 +----------------
 xen/arch/arm/arm64/livepatch.c | 17 +----------------
 xen/arch/arm/livepatch.c       | 17 +++++++++++++++++
 3 files changed, 19 insertions(+), 32 deletions(-)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 3f47326..7e600f2 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -74,22 +74,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
         clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
 }
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
-    uint32_t *new_ptr;
-    unsigned int i, len;
-
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
-    len = livepatch_insn_len(func) / sizeof(uint32_t);
-    for ( i = 0; i < len; i++ )
-    {
-        uint32_t insn;
-
-        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
-        /* PATCH! */
-        *(new_ptr + i) = insn;
-    }
-}
+/* arch_livepatch_revert shared with ARM 32/ARM 64. */
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index ea8044d..a7a292f 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -61,22 +61,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
         clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
 }
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
-    uint32_t *new_ptr;
-    unsigned int i, len;
-
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
-    len = livepatch_insn_len(func) / sizeof(uint32_t);
-    for ( i = 0; i < len; i++ )
-    {
-        uint32_t insn;
-
-        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
-        /* PATCH! */
-        *(new_ptr + i) = insn;
-    }
-}
+/* arch_livepatch_revert shared with ARM 32/ARM 64. */
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 6ee7081..2d62a24 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -69,6 +69,23 @@ int arch_livepatch_verify_func(const struct livepatch_func *func)
     return 0;
 }
 
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = livepatch_insn_len(func) / sizeof(uint32_t);
+    for ( i = 0; i < len; i++ )
+    {
+        uint32_t insn;
+
+        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
+        /* PATCH! */
+        *(new_ptr + i) = insn;
+    }
+}
+
 void arch_livepatch_post_action(void)
 {
     /* arch_livepatch_revive has nuked the instruction cache. */
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case
  2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
                   ` (14 preceding siblings ...)
  2016-09-21 17:32 ` [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert Konrad Rzeszutek Wilk
@ 2016-09-21 17:32 ` Konrad Rzeszutek Wilk
  2016-09-22 13:23   ` Julien Grall
  15 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-21 17:32 UTC (permalink / raw)
  To: konrad, xen-devel, ross.lagerwall, sstabellini, julien.grall
  Cc: Andrew Cooper, Jan Beulich, Konrad Rzeszutek Wilk

The test-case is quite simple - we NOP the 'xen_minor_version'.
The amount of NOPs depends on the architecture.

On x86 the function is 11 bytes long:

   55                      push   %rbp      <- NOP
   48 89 e5                mov    %rsp,%rbp <- NOP
   b8 04 00 00 00          mov    $0x4,%eax <- NOP
   5d                      pop    %rbp      <- NOP
   c3                      retq

We can NOP everything but the last instruction (so 10 bytes).

On ARM64 its 8 bytes:

  52800100    mov w0, #0x8         <- NOP
  d65f03c0    ret

We can NOP the first instruction.

While on ARM32 there are 24 bytes:

  e52db004        push    {fp}
  e28db000        add     fp, sp, #0 <- NOP
  e3a00008        mov     r0, #8     <- NOP
  e24bd000        sub     sp, fp, #0 <- NOP
  e49db004        pop     {fp}
  e12fff1e        bx      lr

And we can NOP instruction 2,3, and 4.

Granted this code may be different per compiler!

Hence if anybody does run this test-case - they should
verify that the assumptions made here are correct.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
---
 xen/test/livepatch/Makefile  | 15 +++++++++++++-
 xen/test/livepatch/xen_nop.c | 49 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 63 insertions(+), 1 deletion(-)
 create mode 100644 xen/test/livepatch/xen_nop.c

diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 4d66a40..d7a4735 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -18,6 +18,7 @@ CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
 LIVEPATCH := xen_hello_world.livepatch
 LIVEPATCH_BYE := xen_bye_world.livepatch
 LIVEPATCH_REPLACE := xen_replace_world.livepatch
+LIVEPATCH_NOP := xen_nop.livepatch
 
 default: livepatch
 
@@ -25,10 +26,12 @@ install: livepatch
 	$(INSTALL_DATA) $(LIVEPATCH) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH)
 	$(INSTALL_DATA) $(LIVEPATCH_BYE) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_BYE)
 	$(INSTALL_DATA) $(LIVEPATCH_REPLACE) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_REPLACE)
+	$(INSTALL_DATA) $(LIVEPATCH_NOP) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_NOP)
 uninstall:
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH)
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_BYE)
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_REPLACE)
+	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_NOP)
 
 .PHONY: clean
 clean::
@@ -41,9 +44,13 @@ clean::
 .PHONY: config.h
 config.h: OLD_CODE_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_extra_version)
 config.h: NEW_CODE_SZ=$(call CODE_SZ,$<,xen_hello_world)
+config.h: MINOR_VERSION_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_minor_version)
+config.h: MINOR_VERSION_ADDR=$(call CODE_ADDR,$(BASEDIR)/xen-syms,xen_minor_version)
 config.h: xen_hello_world_func.o
 	(set -e; \
 	 echo "#define NEW_CODE_SZ $(NEW_CODE_SZ)"; \
+	 echo "#define MINOR_VERSION_SZ $(MINOR_VERSION_SZ)"; \
+	 echo "#define MINOR_VERSION_ADDR $(MINOR_VERSION_ADDR)"; \
 	 echo "#define OLD_CODE_SZ $(OLD_CODE_SZ)") > $@
 
 xen_hello_world.o: config.h
@@ -92,5 +99,11 @@ xen_replace_world.o: config.h
 $(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_REPLACE) $^
 
+xen_nop.o: config.h
+
+.PHONY: $(LIVEPATCH_NOP)
+$(LIVEPATCH_NOP): xen_nop.o note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NOP) $^
+
 .PHONY: livepatch
-livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE)
+livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP)
diff --git a/xen/test/livepatch/xen_nop.c b/xen/test/livepatch/xen_nop.c
new file mode 100644
index 0000000..3827979
--- /dev/null
+++ b/xen/test/livepatch/xen_nop.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ */
+
+#include "config.h"
+#include <xen/types.h>
+
+#include <public/sysctl.h>
+
+/*
+ * All of the .new_size and .old_addr are based on assumptions that the
+ * code for 'xen_minor_version' is compiled in specific way. Before
+ * running this test-case you MUST verify that the assumptions are
+ * correct (Hint: make debug and look in xen.s).
+ */
+struct livepatch_func __section(".livepatch.funcs") livepatch_nop = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .old_size = MINOR_VERSION_SZ,
+
+#ifdef CONFIG_X86
+    .old_addr = (void *)MINOR_VERSION_ADDR,
+    /* Everything but the last instruction: "req". */
+    .new_size = MINOR_VERSION_SZ-1,
+#endif
+
+#ifdef CONFIG_ARM_64
+    .old_addr = (void *)MINOR_VERSION_ADDR,
+    /* Replace the first one: "mov w0, #0x8".  */
+    .new_size = 4,
+#endif
+
+#ifdef CONFIG_ARM_32
+    /* Skip the first instruction: "push {fp}". */
+    .old_addr = (void *)(MINOR_VERSION_ADDR + 4),
+    /* And replace the next three instructions. */
+    .new_size = 3 * 4,
+#endif
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/
  2016-09-21 17:32 ` [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/ Konrad Rzeszutek Wilk
@ 2016-09-22 12:21   ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:21 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Doug Goldstein, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> No functional change. We resist the temptation to move
> the entries in the Kconfig file to be more in alphabetical
> order as the "arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]"
> will move one of the entries to common file.
>
> Suggested-by: Jan Beulich <JBeulich@suse.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]
  2016-09-21 17:32 ` [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE] Konrad Rzeszutek Wilk
@ 2016-09-22 12:23   ` Julien Grall
  2016-09-22 15:30   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:23 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Doug Goldstein, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> x86 implements all of them by default - and we just
> add two extra HAS_ variables to be declared in autoconf.h.
>
> ARM 64 only has alternative while ARM 32 has none of them.
>
> And while at it change the livepatch common code that
> would benefit from this.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [relevant parts]
> Suggested-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/16] arm: poison initmem when it is freed.
  2016-09-21 17:32 ` [PATCH v5 04/16] arm: poison initmem when it is freed Konrad Rzeszutek Wilk
@ 2016-09-22 12:28   ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:28 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> The current byte sequence is '0xcc' which makes sense on x86,
> but on ARM it is:
>
> cccccccc        stclgt  12, cr12, [ip], {204}   ; 0xcc
>
> Picking something more ARM applicable such as:
>
> efefefef        svc     0x00efefef
>
> Creates a nice crash if one executes that code:
> (XEN) CPU1: Unexpected Trap: Supervisor Call
>
> But unfortunately that may not be a good choice either as in the future
> we may want to implement support for it.
>
> Julien suggested that we use a 4-byte insn instruction instead
> of trying to work with one byte. To make sure nothing goes bad
> we also require that the __init_[begin|end] be aligned properly.
>
> As such on ARM 32 we use the udf instruction (see A8.8.247
> in ARM DDI 0406C.c) and on ARM 64 use the AARCH64_BREAK_FAULT
> instruction (aka brk instruction).
>
> We don't have to worry about Thumb code so this instruction
> is a safe to execute.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/16] livepatch: Initial ARM64 support.
  2016-09-21 17:32 ` [PATCH v5 05/16] livepatch: Initial ARM64 support Konrad Rzeszutek Wilk
@ 2016-09-22 12:49   ` Julien Grall
  2016-09-23 13:38   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:49 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:

[...]

> diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown
> index f2ae52a..ff2cfb8 100644
> --- a/docs/misc/livepatch.markdown
> +++ b/docs/misc/livepatch.markdown
> @@ -1108,7 +1108,7 @@ and no .data or .bss sections.
>  The hypervisor should verify that the in-place patching would fit within
>  the code or data.
>
> -### Trampoline (e9 opcode)
> +### Trampoline (e9 opcode), x86
>
>  The e9 opcode used for jmpq uses a 32-bit signed displacement. That means
>  we are limited to up to 2GB of virtual address to place the new code
> @@ -1143,3 +1143,15 @@ that in the hypervisor is advised.
>  The tool for generating payloads currently does perform a compile-time
>  check to ensure that the function to be replaced is large enough.
>
> +#### Trampoline (ea opcode), ARM

Please drop "(ea opcode)" as it is only valid for ARM32.

> +
> +The unconditional branch instruction (for the encoding see the
> +DDI 0406C.c and DDI 0487A.j Architecture Reference Manual's).
> +with proper offset is used for an unconditional branch to the new code.
> +This means that that `old_size` **MUST** be at least four bytes if patching
> +in trampoline.
> +
> +The new code is placed in the 8M - 10M virtual address space while the
> +Xen code is in 2M - 4M. That gives us enough space.
> +
> +The hypervisor also checks the displacement during loading of the payload.

[...]

> diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
> new file mode 100644
> index 0000000..7cb1812
> --- /dev/null
> +++ b/xen/arch/arm/arm64/livepatch.c

[...]

> +void arch_livepatch_apply(struct livepatch_func *func)
> +{
> +    uint32_t insn;
> +    uint32_t *new_ptr;
> +    unsigned int i, len;
> +
> +    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
> +    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
> +
> +    ASSERT(vmap_of_xen_text);
> +
> +    len = livepatch_insn_len(func);
> +    if ( !len )
> +        return;
> +
> +    /* Save old ones. */
> +    memcpy(func->opaque, func->old_addr, len);
> +
> +    if ( func->new_addr )
> +        insn = aarch64_insn_gen_branch_imm((unsigned long)func->old_addr,
> +                                           (unsigned long)func->new_addr,
> +                                           AARCH64_INSN_BRANCH_NOLINK);
> +    else
> +        insn = aarch64_insn_gen_nop();
> +
> +    ASSERT(insn != AARCH64_BREAK_FAULT);
> +
> +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> +    len = len / sizeof(uint32_t);
> +
> +    /* PATCH! */
> +    for ( i = 0; i < len; i++ )
> +        *(new_ptr + i) = insn;
> +
> +    /*
> +    * When we upload the payload, it will go through the data cache
> +    * (the region is cacheable). Until the data cache is cleaned, the data
> +    * may not reach the memory. And in the case the data and instruction cache
> +    * are separated, we may read invalid instruction from the memory because
> +    * the data cache have not yet synced with the memory. Hence sync it.
> +    */
> +    if ( func->new_addr )
> +        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);

Why did you drop the clean_and_invalidate_dcache_va_range to the 
instruction just patched?

I guess it is because my mail in the previous thread was confusing, 
sorry for that.

"> Or did you mean the old_addr (the one we just patched?)

We don't care about the previous function. It will never changed except 
for the instruction patched.
"

I meant that it is not necessary to flush the whole region of the old 
code (Xen already flushed it at boot time), but only the region you 
patched. The interesting bit in the ARM ARM is B2.3.4 DDI 0487A.j.

So the code should look like:

if ( func->new_addr )
    clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);


> +}
> +
> +void arch_livepatch_revert(const struct livepatch_func *func)
> +{
> +    uint32_t *new_ptr;
> +    unsigned int i, len;
> +
> +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> +    len = livepatch_insn_len(func) / sizeof(uint32_t);
> +    for ( i = 0; i < len; i++ )
> +    {
> +        uint32_t insn;
> +
> +        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> +        /* PATCH! */
> +        *(new_ptr + i) = insn;
> +    }

Similarly:

clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);



> +}
> +

[...]

> diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
> index 7f067a0..9284766 100644
> --- a/xen/arch/arm/livepatch.c
> +++ b/xen/arch/arm/livepatch.c

[...]

>  void arch_livepatch_revive(void)
>  {
> +    /*
> +     * Nuke the instruction cache. Data cache has been cleaned before in
> +     * arch_livepatch_apply.

NIT: Would it be worth to mention arch_livepatch_revert here?

> +     */
> +    invalidate_icache();
> +
> +    if ( vmap_of_xen_text )
> +        vunmap(vmap_of_xen_text);
> +
> +    vmap_of_xen_text = NULL;
>  }

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-21 17:32 ` [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr Konrad Rzeszutek Wilk
@ 2016-09-22 12:55   ` Julien Grall
  2016-09-23 14:36   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:55 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> diff --git a/xen/include/asm-arm/livepatch.h b/xen/include/asm-arm/livepatch.h
> index 929c7d9..482d74f 100644
> --- a/xen/include/asm-arm/livepatch.h
> +++ b/xen/include/asm-arm/livepatch.h
> @@ -6,6 +6,8 @@
>  #ifndef __XEN_ARM_LIVEPATCH_H__
>  #define __XEN_ARM_LIVEPATCH_H__
>
> +#include <xen/sizes.h> /* For SZ_* macros. */
> +
>  /* On ARM32,64 instructions are always 4 bytes long. */
>  #define ARCH_PATCH_INSN_SIZE 4
>
> @@ -15,6 +17,15 @@
>   */
>  extern void *vmap_of_xen_text;
>
> +/* These ranges are only for unconditional branches. */
> +#ifdef CONFIG_ARM_32
> +/* ARM32: A4.3 IN ARM DDI 0406C.j -  we are using only ARM instructions in Xen.*/

NIT: There is no j revision of the ARMv7 manual. The latest on is 0406C.c.

With that:

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x]
  2016-09-21 17:32 ` [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x] Konrad Rzeszutek Wilk
@ 2016-09-22 12:56   ` Julien Grall
  2016-09-23 14:44   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 12:56 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> Those symbols are used to help final linkers to replace insn.
> The ARM ELF specification mandates that they are present
> to denote the start of certain CPU features. There are two
> variants of it - short and long format.
>
> Either way - we can ignore these symbols.
>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> [x86 bits]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-21 17:32 ` [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols Konrad Rzeszutek Wilk
@ 2016-09-22 13:00   ` Julien Grall
  2016-09-23  1:29     ` Konrad Rzeszutek Wilk
  2016-09-23 14:49   ` Ross Lagerwall
  1 sibling, 1 reply; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:00 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> Certain platforms, such as ARM [32|64] add extra mapping symbols
> such as $x (for ARM64 instructions), or more interesting to
> this patch: $t (for Thumb instructions). These symbols are suppose

nit: s/are suppose to/are supposed to/

> to help the final linker to make any adjustments (such as
> add an veneer). But more importantly - we do not compile Xen
> with any Thumb instructions (which are variable length) - and
> if we find these mapping symbols we should disallow such payload.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>
> v3: New submission.
>     Use &sym[i] instead of sym (as that will always be NULL).
> v4: Use bool instead of int for return
>     Update comment in common code about ARM odd symbols.
>     s/_check/_deny/ to make it more clear.
> v5: Also check for $t.* wildcard.
>     Use Julien's variant where we roll the [2] check in the return.
> ---
>  xen/arch/arm/livepatch.c    | 16 ++++++++++++++++
>  xen/arch/x86/livepatch.c    |  7 +++++++
>  xen/common/livepatch_elf.c  |  7 +++++++
>  xen/include/xen/livepatch.h |  2 ++
>  4 files changed, 32 insertions(+)
>
> diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
> index 9959315..5a99ab5 100644
> --- a/xen/arch/arm/livepatch.c
> +++ b/xen/arch/arm/livepatch.c
> @@ -117,6 +117,22 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
>      return true;
>  }
>
> +bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
> +                                const struct livepatch_elf_sym *sym)
> +{
> +#ifdef CONFIG_ARM_32

Out of interest, is there any particular reason to use #ifdef rather 
than adding the function in {arm32/arm64}/livepatch.c?

> +    /*
> +     * Xen does not use Thumb instructions - and we should not see any of
> +     * them. If we do, abort.
> +     */
> +    if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
> +    {
> +        return ( !sym->name[2] || sym->name[2] == '.' );
> +    }

NIT: You could drop { } here.

> +#endif
> +    return false;
> +}

Regardless the answer to my question:

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test.
  2016-09-21 17:32 ` [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test Konrad Rzeszutek Wilk
@ 2016-09-22 13:01   ` Julien Grall
  2016-09-23 14:51   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:01 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> So they can be shared with ARM64 (but not yet, so they
> are only built on x86).
>
> No functional change.
>
> We also need to tweak the MAINTAINERS and .gitignore file.
>
> Also we need to update SUBDIRS to include the new 'test'
> directory so 'cscope' can show the example livepatches.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [for directory]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>
> ---
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>
> v1: First submission
> v2: Move to test/livepatch per Jan's recommendation
> v3: Sort MAINTAINERS for livepatch.
>     Add Jan's Acked-by.
>     Added on the SUBDIRS the 'test' directory
>     Change title of patch (common-> own sub-directory)
> ---
>  .gitignore                                                     | 8 ++++----
>  MAINTAINERS                                                    | 1 +
>  xen/Makefile                                                   | 5 +++--
>  xen/arch/arm/Makefile                                          | 3 ---

I am not sure if you want an ack for this small ARM change. So FWIW:

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH
  2016-09-21 17:32 ` [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH Konrad Rzeszutek Wilk
@ 2016-09-22 13:03   ` Julien Grall
  2016-09-27  9:49   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:03 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> To use as a common way of testing alternative patching for
> livepatches. Both architectures have this FEATURE and the
> test-cases can piggyback on that.
>
> Suggested-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

For the ARM part:

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-21 17:32 ` [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64 Konrad Rzeszutek Wilk
@ 2016-09-22 13:10   ` Julien Grall
  2016-09-22 19:26     ` Konrad Rzeszutek Wilk
  2016-09-23  1:33     ` Konrad Rzeszutek Wilk
  0 siblings, 2 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:10 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Wei Liu, George Dunlap, Andrew Cooper, Ian Jackson, Tim Deegan,
	Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> We need to two things:
> 1) Wrap the platform-specific objcopy parameters in defines
>    The input and output parameters for $(OBJCOPY) are different
>    based on the platforms. As such provide them in the
>    OBJCOPY_MAGIC define and use that.
>
> 2) The alternative is a bit different (exists only under ARM64
>    and x86), while and there are no exceptions under ARM at all.
>    We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
>    how it is done on x86.
>
> We are not yet attempting to build them under ARM32 so
> that is still ifdefed out.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>
> ---
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Tim Deegan <tim@xen.org>
> Cc: Wei Liu <wei.liu2@citrix.com>
>
> v1: First submission
> v2: Corrected description by Julien
>     Add #ifeq instead of #else for ARM case.
> v3: Moved 'asm(alter..)' by one space to the left.
> v4: Rebase on top of "livepatch/tests: Make .livepatch.depends be read-only"
>     Rewrote the commit description 2) a bit.
> ---
>  xen/test/Makefile                         |  2 +-
>  xen/test/livepatch/Makefile               | 12 ++++++++++--
>  xen/test/livepatch/xen_hello_world_func.c |  7 +++++++
>  3 files changed, 18 insertions(+), 3 deletions(-)
>
> diff --git a/xen/test/Makefile b/xen/test/Makefile
> index 8c53040..95c1755 100644
> --- a/xen/test/Makefile
> +++ b/xen/test/Makefile
> @@ -1,6 +1,6 @@
>  .PHONY: tests
>  tests:
I am wondering if there is any way to use the
> -ifeq ($(XEN_TARGET_ARCH),x86_64)
> +ifneq $(XEN_TARGET_ARCH),arm32)

NIT: I am wondering if you could instead use CONFIG_LIVEPATCH here, so 
the tests would only be built when livepatch is enabled.

>  	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
>  endif
>
> diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
> index 48ff843..5db4d9c 100644
> --- a/xen/test/livepatch/Makefile
> +++ b/xen/test/livepatch/Makefile
> @@ -1,5 +1,12 @@
>  include $(XEN_ROOT)/Config.mk
>
> +ifeq ($(XEN_TARGET_ARCH),x86_64)
> +OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
> +endif
> +ifeq ($(XEN_TARGET_ARCH),arm64)
> +OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
> +endif
> +
>  CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
>  CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
>
> @@ -54,8 +61,9 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
>  .PHONY: note.o
>  note.o:
>  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
> -	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
> +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
>  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
> +		   --rename-section=.data=.livepatch.depends -S $@.bin $@

I am not sure why you added this line. Did you intend to replace the 
previous one?

>  	rm -f $@.bin
>
>  #
> @@ -65,7 +73,7 @@ note.o:
>  .PHONY: hello_world_note.o
>  hello_world_note.o: $(LIVEPATCH)
>  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(LIVEPATCH) $@.bin
> -	$(OBJCOPY)  -I binary -O elf64-x86-64 -B i386:x86-64 \
> +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
>  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
>  	rm -f $@.bin
>
> diff --git a/xen/test/livepatch/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
> index 0321f3e..c5c0da1 100644
> --- a/xen/test/livepatch/xen_hello_world_func.c
> +++ b/xen/test/livepatch/xen_hello_world_func.c
> @@ -7,14 +7,17 @@
>
>  #include <asm/alternative.h>
>  #include <asm/livepatch.h>
> +#ifdef CONFIG_X86
>  #include <asm/nops.h>
>  #include <asm/uaccess.h>
>
>  static unsigned long *non_canonical_addr = (unsigned long *)0xdead000000000000ULL;
> +#endif
>
>  /* Our replacement function for xen_extra_version. */
>  const char *xen_hello_world(void)
>  {
> +#ifdef CONFIG_X86
>      unsigned long tmp;
>      int rc;
>
> @@ -25,6 +28,10 @@ const char *xen_hello_world(void)
>       */
>      rc = __get_user(tmp, non_canonical_addr);
>      BUG_ON(rc != -EFAULT);
> +#endif
> +#ifdef CONFIG_ARM_64

NIT: I would use:

#if defined(CONFIG_ARM) && defined(CONFIG_HAS_ALTERNATIVE)

in order to handle alternative if we decide to add support for ARM32.

> +    asm(ALTERNATIVE("nop", "nop", LIVEPATCH_FEATURE));
> +#endif
>
>      return "Hello World";
>  }
>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches
  2016-09-21 17:32 ` [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches Konrad Rzeszutek Wilk
@ 2016-09-22 13:17   ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:17 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> This is similar to commit fb9d877a9c0f3d4d15db8f6e0c5506ea641862c6
> "xen/arm64: Add an helper to invalidate all instruction caches"
> except it is on ARM32 side.
>
> When we are flushing the cache we are most likley also want

s/likley/likely/

> to flush the branch predictor too. Hence we add this.
>
> And we also need to follow this with dsb()/isb() which are
> memory barriers().
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Reviewed-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case
  2016-09-21 17:32 ` [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case Konrad Rzeszutek Wilk
@ 2016-09-22 13:23   ` Julien Grall
  2016-09-23  1:35     ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 57+ messages in thread
From: Julien Grall @ 2016-09-22 13:23 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini
  Cc: Andrew Cooper, Jan Beulich

Hi Konrad,

On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> The test-case is quite simple - we NOP the 'xen_minor_version'.
> The amount of NOPs depends on the architecture.
>
> On x86 the function is 11 bytes long:
>
>    55                      push   %rbp      <- NOP
>    48 89 e5                mov    %rsp,%rbp <- NOP
>    b8 04 00 00 00          mov    $0x4,%eax <- NOP
>    5d                      pop    %rbp      <- NOP
>    c3                      retq
>
> We can NOP everything but the last instruction (so 10 bytes).
>
> On ARM64 its 8 bytes:
>
>   52800100    mov w0, #0x8         <- NOP
>   d65f03c0    ret
>
> We can NOP the first instruction.
>
> While on ARM32 there are 24 bytes:
>
>   e52db004        push    {fp}
>   e28db000        add     fp, sp, #0 <- NOP
>   e3a00008        mov     r0, #8     <- NOP
>   e24bd000        sub     sp, fp, #0 <- NOP
>   e49db004        pop     {fp}
>   e12fff1e        bx      lr
>
> And we can NOP instruction 2,3, and 4.

Why don't you NOP push {fp} and pop {fp}? At first glance, I am a bit 
surprised that the compiler is generating them (maybe it is because you 
have debug enabled?) and would have expect to have:

mov r0, #8
bx lr

NOPing all the instructions but the last one would simplify at lot the 
test case below.

[...]

> --- /dev/null
> +++ b/xen/test/livepatch/xen_nop.c
> @@ -0,0 +1,49 @@
> +/*
> + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
> + *
> + */
> +
> +#include "config.h"
> +#include <xen/types.h>
> +
> +#include <public/sysctl.h>
> +
> +/*
> + * All of the .new_size and .old_addr are based on assumptions that the
> + * code for 'xen_minor_version' is compiled in specific way. Before
> + * running this test-case you MUST verify that the assumptions are
> + * correct (Hint: make debug and look in xen.s).
> + */
> +struct livepatch_func __section(".livepatch.funcs") livepatch_nop = {
> +    .version = LIVEPATCH_PAYLOAD_VERSION,
> +    .old_size = MINOR_VERSION_SZ,
> +
> +#ifdef CONFIG_X86
> +    .old_addr = (void *)MINOR_VERSION_ADDR,
> +    /* Everything but the last instruction: "req". */
> +    .new_size = MINOR_VERSION_SZ-1,
> +#endif
> +
> +#ifdef CONFIG_ARM_64
> +    .old_addr = (void *)MINOR_VERSION_ADDR,
> +    /* Replace the first one: "mov w0, #0x8".  */
> +    .new_size = 4,
> +#endif
> +
> +#ifdef CONFIG_ARM_32
> +    /* Skip the first instruction: "push {fp}". */
> +    .old_addr = (void *)(MINOR_VERSION_ADDR + 4),
> +    /* And replace the next three instructions. */
> +    .new_size = 3 * 4,
> +#endif
> +};

With my suggestion above, the two ARM code could become:

#ifdef CONFIG_ARM
	.old_addr = (void *)MINOR_VERSION_ADDR,
	.new_size = MINOR_VERSION_SIZE - 4,
#endif

The "- 4" is to avoid replacing the return.

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE]
  2016-09-21 17:32 ` [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE] Konrad Rzeszutek Wilk
  2016-09-22 12:23   ` Julien Grall
@ 2016-09-22 15:30   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-22 15:30 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, Doug Goldstein, julien.grall,
	Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> x86 implements all of them by default - and we just
> add two extra HAS_ variables to be declared in autoconf.h.
>
> ARM 64 only has alternative while ARM 32 has none of them.
>
> And while at it change the livepatch common code that
> would benefit from this.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [relevant parts]
> Suggested-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-22 13:10   ` Julien Grall
@ 2016-09-22 19:26     ` Konrad Rzeszutek Wilk
  2016-09-23  1:33     ` Konrad Rzeszutek Wilk
  1 sibling, 0 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-22 19:26 UTC (permalink / raw)
  To: Julien Grall
  Cc: sstabellini, Wei Liu, ross.lagerwall, George Dunlap,
	Andrew Cooper, Ian Jackson, Tim Deegan, Jan Beulich, xen-devel

On Thu, Sep 22, 2016 at 02:10:26PM +0100, Julien Grall wrote:
> Hi Konrad,
> 
> On 21/09/16 18:32, Konrad Rzeszutek Wilk wrote:
> > We need to two things:
> > 1) Wrap the platform-specific objcopy parameters in defines
> >    The input and output parameters for $(OBJCOPY) are different
> >    based on the platforms. As such provide them in the
> >    OBJCOPY_MAGIC define and use that.
> > 
> > 2) The alternative is a bit different (exists only under ARM64
> >    and x86), while and there are no exceptions under ARM at all.
> >    We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
> >    how it is done on x86.
> > 
> > We are not yet attempting to build them under ARM32 so
> > that is still ifdefed out.
> > 
> > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > 
> > ---
> > Cc: Andrew Cooper <andrew.cooper3@citrix.com>
> > Cc: George Dunlap <George.Dunlap@eu.citrix.com>
> > Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> > Cc: Jan Beulich <jbeulich@suse.com>
> > Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > Cc: Stefano Stabellini <sstabellini@kernel.org>
> > Cc: Tim Deegan <tim@xen.org>
> > Cc: Wei Liu <wei.liu2@citrix.com>
> > 
> > v1: First submission
> > v2: Corrected description by Julien
> >     Add #ifeq instead of #else for ARM case.
> > v3: Moved 'asm(alter..)' by one space to the left.
> > v4: Rebase on top of "livepatch/tests: Make .livepatch.depends be read-only"
> >     Rewrote the commit description 2) a bit.
> > ---
> >  xen/test/Makefile                         |  2 +-
> >  xen/test/livepatch/Makefile               | 12 ++++++++++--
> >  xen/test/livepatch/xen_hello_world_func.c |  7 +++++++
> >  3 files changed, 18 insertions(+), 3 deletions(-)
> > 
> > diff --git a/xen/test/Makefile b/xen/test/Makefile
> > index 8c53040..95c1755 100644
> > --- a/xen/test/Makefile
> > +++ b/xen/test/Makefile
> > @@ -1,6 +1,6 @@
> >  .PHONY: tests
> >  tests:
> I am wondering if there is any way to use the
> > -ifeq ($(XEN_TARGET_ARCH),x86_64)
> > +ifneq $(XEN_TARGET_ARCH),arm32)

Sure.
> 
> NIT: I am wondering if you could instead use CONFIG_LIVEPATCH here, so the
> tests would only be built when livepatch is enabled.

The tests are not built by default. But perhaps that can be done
in a future patch? (and have the check in test/livepatch instead).
> 
> >  	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
> >  endif
> > 
> > diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
> > index 48ff843..5db4d9c 100644
> > --- a/xen/test/livepatch/Makefile
> > +++ b/xen/test/livepatch/Makefile
> > @@ -1,5 +1,12 @@
> >  include $(XEN_ROOT)/Config.mk
> > 
> > +ifeq ($(XEN_TARGET_ARCH),x86_64)
> > +OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
> > +endif
> > +ifeq ($(XEN_TARGET_ARCH),arm64)
> > +OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
> > +endif
> > +
> >  CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
> >  CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
> > 
> > @@ -54,8 +61,9 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
> >  .PHONY: note.o
> >  note.o:
> >  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
> > -	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
> > +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
> >  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
> > +		   --rename-section=.data=.livepatch.depends -S $@.bin $@
> 
> I am not sure why you added this line. Did you intend to replace the
> previous one?

Oh crud! No - thank you for spotting that!
> 
> >  	rm -f $@.bin
> > 
> >  #
> > @@ -65,7 +73,7 @@ note.o:
> >  .PHONY: hello_world_note.o
> >  hello_world_note.o: $(LIVEPATCH)
> >  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(LIVEPATCH) $@.bin
> > -	$(OBJCOPY)  -I binary -O elf64-x86-64 -B i386:x86-64 \
> > +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
> >  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
> >  	rm -f $@.bin
> > 
> > diff --git a/xen/test/livepatch/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
> > index 0321f3e..c5c0da1 100644
> > --- a/xen/test/livepatch/xen_hello_world_func.c
> > +++ b/xen/test/livepatch/xen_hello_world_func.c
> > @@ -7,14 +7,17 @@
> > 
> >  #include <asm/alternative.h>
> >  #include <asm/livepatch.h>
> > +#ifdef CONFIG_X86
> >  #include <asm/nops.h>
> >  #include <asm/uaccess.h>
> > 
> >  static unsigned long *non_canonical_addr = (unsigned long *)0xdead000000000000ULL;
> > +#endif
> > 
> >  /* Our replacement function for xen_extra_version. */
> >  const char *xen_hello_world(void)
> >  {
> > +#ifdef CONFIG_X86
> >      unsigned long tmp;
> >      int rc;
> > 
> > @@ -25,6 +28,10 @@ const char *xen_hello_world(void)
> >       */
> >      rc = __get_user(tmp, non_canonical_addr);
> >      BUG_ON(rc != -EFAULT);
> > +#endif
> > +#ifdef CONFIG_ARM_64
> 
> NIT: I would use:
> 
> #if defined(CONFIG_ARM) && defined(CONFIG_HAS_ALTERNATIVE)
> 
> in order to handle alternative if we decide to add support for ARM32.

/me nods.
> 
> > +    asm(ALTERNATIVE("nop", "nop", LIVEPATCH_FEATURE));
> > +#endif
> > 
> >      return "Hello World";
> >  }
> > 
> 
> Regards,
> 
> -- 
> Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-22 13:00   ` Julien Grall
@ 2016-09-23  1:29     ` Konrad Rzeszutek Wilk
  2016-09-27  8:49       ` Ross Lagerwall
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23  1:29 UTC (permalink / raw)
  To: Julien Grall
  Cc: sstabellini, ross.lagerwall, Andrew Cooper, Jan Beulich, xen-devel

> > +bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
> > +                                const struct livepatch_elf_sym *sym)
> > +{
> > +#ifdef CONFIG_ARM_32
> 
> Out of interest, is there any particular reason to use #ifdef rather than
> adding the function in {arm32/arm64}/livepatch.c?

I updated it be like that:

From 5fc79e4fc3c0770ee4f6e7e0ed666e593deced65 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Tue, 13 Sep 2016 13:15:07 -0400
Subject: [PATCH v6] livepatch/arm/x86: Check payload for for unwelcomed
 symbols.

Certain platforms, such as ARM [32|64] add extra mapping symbols
such as $x (for ARM64 instructions), or more interesting to
this patch: $t (for Thumb instructions). These symbols are supposed
to help the final linker to make any adjustments (such as
add an veneer). But more importantly - we do not compile Xen
with any Thumb instructions (which are variable length) - and
if we find these mapping symbols we should disallow such payload.

Reviewed-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
    Use &sym[i] instead of sym (as that will always be NULL).
v4: Use bool instead of int for return
    Update comment in common code about ARM odd symbols.
    s/_check/_deny/ to make it more clear.
v5: Also check for $t.* wildcard.
    Use Julien's variant where we roll the [2] check in the return.
v6: s/suppose/supposed/ in commit description.
    Move arch_livepatch_symbol_deny in arm[32|64]/livepatch.c
    Added Julien's Reviewed-by.
---
 xen/arch/arm/arm32/livepatch.c | 13 +++++++++++++
 xen/arch/arm/arm64/livepatch.c |  7 +++++++
 xen/arch/x86/livepatch.c       |  7 +++++++
 xen/common/livepatch_elf.c     |  7 +++++++
 xen/include/xen/livepatch.h    |  2 ++
 5 files changed, 36 insertions(+)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 80f9646..5fc2e63 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -20,6 +20,19 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return -EOPNOTSUPP;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /*
+     * Xen does not use Thumb instructions - and we should not see any of
+     * them. If we do, abort.
+     */
+    if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
+        return ( !sym->name[2] || sym->name[2] == '.' );
+
+    return false;
+}
+
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 0fe73d9..0f25e1e 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -95,6 +95,13 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return 0;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on ARM 64. */
+    return false;
+}
+
 enum aarch64_reloc_op {
     RELOC_OP_NONE,
     RELOC_OP_ABS,
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index 7a369a0..9663ef6 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -131,6 +131,13 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return false;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/common/livepatch_elf.c b/xen/common/livepatch_elf.c
index dec904a..53b3fba 100644
--- a/xen/common/livepatch_elf.c
+++ b/xen/common/livepatch_elf.c
@@ -251,6 +251,13 @@ static int elf_get_sym(struct livepatch_elf *elf, const void *data)
 
         sym[i].sym = s;
         sym[i].name = strtab_sec->data + delta;
+        /* e.g. On ARM we should NEVER see $t* symbols. */
+        if ( arch_livepatch_symbol_deny(elf, &sym[i]) )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Symbol '%s' should not be in payload!\n",
+                    elf->name, sym[i].name);
+            return -EINVAL;
+        }
     }
     elf->nsym = nsym;
 
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index e8c67d6..98ec012 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -50,6 +50,8 @@ bool_t is_patch(const void *addr);
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
 bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
                               const struct livepatch_elf_sym *sym);
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-22 13:10   ` Julien Grall
  2016-09-22 19:26     ` Konrad Rzeszutek Wilk
@ 2016-09-23  1:33     ` Konrad Rzeszutek Wilk
  2016-09-23  9:50       ` Julien Grall
  2016-09-27  9:49       ` Ross Lagerwall
  1 sibling, 2 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23  1:33 UTC (permalink / raw)
  To: Julien Grall
  Cc: sstabellini, Wei Liu, ross.lagerwall, George Dunlap,
	Andrew Cooper, Ian Jackson, Tim Deegan, Jan Beulich, xen-devel

.snip..
> > diff --git a/xen/test/Makefile b/xen/test/Makefile
> > index 8c53040..95c1755 100644
> > --- a/xen/test/Makefile
> > +++ b/xen/test/Makefile
> > @@ -1,6 +1,6 @@
> >  .PHONY: tests
> >  tests:
> I am wondering if there is any way to use the
> > -ifeq ($(XEN_TARGET_ARCH),x86_64)
> > +ifneq $(XEN_TARGET_ARCH),arm32)
> 
> NIT: I am wondering if you could instead use CONFIG_LIVEPATCH here, so the
> tests would only be built when livepatch is enabled.

Lets leave it as is and do it in the future. Right now the tests
are not compiled by default so not much harm here. But I do agree that
somehow exposing the CONFIG_LIVEPATCH and latching it off (in say
tests/livepatch/ directory) is a good TODO item.. 
> 
> >  	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
> >  endif
> > 
> > diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
> > index 48ff843..5db4d9c 100644
> > --- a/xen/test/livepatch/Makefile
> > +++ b/xen/test/livepatch/Makefile
> > @@ -1,5 +1,12 @@
> >  include $(XEN_ROOT)/Config.mk
> > 
> > +ifeq ($(XEN_TARGET_ARCH),x86_64)
> > +OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
> > +endif
> > +ifeq ($(XEN_TARGET_ARCH),arm64)
> > +OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
> > +endif
> > +
> >  CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
> >  CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
> > 
> > @@ -54,8 +61,9 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
> >  .PHONY: note.o
> >  note.o:
> >  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
> > -	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
> > +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
> >  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
> > +		   --rename-section=.data=.livepatch.depends -S $@.bin $@
> 
> I am not sure why you added this line. Did you intend to replace the
> previous one?

Fixed.
..snip..
> > @@ -25,6 +28,10 @@ const char *xen_hello_world(void)
> >       */
> >      rc = __get_user(tmp, non_canonical_addr);
> >      BUG_ON(rc != -EFAULT);
> > +#endif
> > +#ifdef CONFIG_ARM_64
> 
> NIT: I would use:
> 
> #if defined(CONFIG_ARM) && defined(CONFIG_HAS_ALTERNATIVE)
> 
> in order to handle alternative if we decide to add support for ARM32.

Done!

Here is the updated patch:


From c0dac442d15b5f0095b199ab4fff1fc414fb5719 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Mon, 19 Sep 2016 16:04:55 -0400
Subject: [PATCH v6] livepatch: tests: Make them compile under ARM64

We need to two things:
1) Wrap the platform-specific objcopy parameters in defines
   The input and output parameters for $(OBJCOPY) are different
   based on the platforms. As such provide them in the
   OBJCOPY_MAGIC define and use that.

2) The alternative is a bit different (exists only under ARM64
   and x86), while and there are no exceptions under ARM at all.
   We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
   how it is done on x86.

We are not yet attempting to build them under ARM32 so
that is still ifdefed out.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Andrew Cooper <andrew.cooper3@citrix.com>
Cc: George Dunlap <George.Dunlap@eu.citrix.com>
Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Tim Deegan <tim@xen.org>
Cc: Wei Liu <wei.liu2@citrix.com>

v1: First submission
v2: Corrected description by Julien
    Add #ifeq instead of #else for ARM case.
v3: Moved 'asm(alter..)' by one space to the left.
v4: Rebase on top of "livepatch/tests: Make .livepatch.depends be read-only"
    Rewrote the commit description 2) a bit.
v6: Fixed the note.o --rename-section
    Replaced CONFIG_ARM_64 with defined(CONFIG_ARM) &&
    defined(CONFIG_HAS_ALTERNATIVE)
---
 xen/test/Makefile                         |  2 +-
 xen/test/livepatch/Makefile               | 11 +++++++++--
 xen/test/livepatch/xen_hello_world_func.c |  7 +++++++
 3 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/xen/test/Makefile b/xen/test/Makefile
index 8c53040..95c1755 100644
--- a/xen/test/Makefile
+++ b/xen/test/Makefile
@@ -1,6 +1,6 @@
 .PHONY: tests
 tests:
-ifeq ($(XEN_TARGET_ARCH),x86_64)
+ifneq $(XEN_TARGET_ARCH),arm32)
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
 endif
 
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 48ff843..d844ad4 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -1,5 +1,12 @@
 include $(XEN_ROOT)/Config.mk
 
+ifeq ($(XEN_TARGET_ARCH),x86_64)
+OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
+endif
+ifeq ($(XEN_TARGET_ARCH),arm64)
+OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
+endif
+
 CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
 CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
 
@@ -54,7 +61,7 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
 .PHONY: note.o
 note.o:
 	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
-	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
 	rm -f $@.bin
 
@@ -65,7 +72,7 @@ note.o:
 .PHONY: hello_world_note.o
 hello_world_note.o: $(LIVEPATCH)
 	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(LIVEPATCH) $@.bin
-	$(OBJCOPY)  -I binary -O elf64-x86-64 -B i386:x86-64 \
+	$(OBJCOPY) $(OBJCOPY_MAGIC) \
 		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
 	rm -f $@.bin
 
diff --git a/xen/test/livepatch/xen_hello_world_func.c b/xen/test/livepatch/xen_hello_world_func.c
index 0321f3e..1518f71 100644
--- a/xen/test/livepatch/xen_hello_world_func.c
+++ b/xen/test/livepatch/xen_hello_world_func.c
@@ -7,14 +7,17 @@
 
 #include <asm/alternative.h>
 #include <asm/livepatch.h>
+#ifdef CONFIG_X86
 #include <asm/nops.h>
 #include <asm/uaccess.h>
 
 static unsigned long *non_canonical_addr = (unsigned long *)0xdead000000000000ULL;
+#endif
 
 /* Our replacement function for xen_extra_version. */
 const char *xen_hello_world(void)
 {
+#ifdef CONFIG_X86
     unsigned long tmp;
     int rc;
 
@@ -25,6 +28,10 @@ const char *xen_hello_world(void)
      */
     rc = __get_user(tmp, non_canonical_addr);
     BUG_ON(rc != -EFAULT);
+#endif
+#if defined(CONFIG_ARM) && defined(CONFIG_HAS_ALTERNATIVE)
+    asm(ALTERNATIVE("nop", "nop", LIVEPATCH_FEATURE));
+#endif
 
     return "Hello World";
 }
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case
  2016-09-22 13:23   ` Julien Grall
@ 2016-09-23  1:35     ` Konrad Rzeszutek Wilk
  2016-09-23  9:53       ` Julien Grall
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23  1:35 UTC (permalink / raw)
  To: Julien Grall
  Cc: sstabellini, ross.lagerwall, Andrew Cooper, Jan Beulich, xen-devel

.snip..
> > While on ARM32 there are 24 bytes:
> > 
> >   e52db004        push    {fp}
> >   e28db000        add     fp, sp, #0 <- NOP
> >   e3a00008        mov     r0, #8     <- NOP
> >   e24bd000        sub     sp, fp, #0 <- NOP
> >   e49db004        pop     {fp}
> >   e12fff1e        bx      lr
> > 
> > And we can NOP instruction 2,3, and 4.
> 
> Why don't you NOP push {fp} and pop {fp}? At first glance, I am a bit
> surprised that the compiler is generating them (maybe it is because you have
> debug enabled?) and would have expect to have:
> 
> mov r0, #8
> bx lr
> 
> NOPing all the instructions but the last one would simplify at lot the test
> case below.
> 
> [...]

..snip..
> With my suggestion above, the two ARM code could become:
> 
> #ifdef CONFIG_ARM
> 	.old_addr = (void *)MINOR_VERSION_ADDR,
> 	.new_size = MINOR_VERSION_SIZE - 4,
> #endif
> 
> The "- 4" is to avoid replacing the return.

Done!

From 8ade51e1866b86c7660277bb19100db337d432b4 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Sat, 10 Sep 2016 20:41:24 -0400
Subject: [PATCH v6] livepatch: arm[32,64],x86: NOP test-case

The test-case is quite simple - we NOP the 'xen_minor_version'.
The amount of NOPs depends on the architecture.

On x86 the function is 11 bytes long:

   55                      push   %rbp      <- NOP
   48 89 e5                mov    %rsp,%rbp <- NOP
   b8 04 00 00 00          mov    $0x4,%eax <- NOP
   5d                      pop    %rbp      <- NOP
   c3                      retq

We can NOP everything but the last instruction (so 10 bytes).

On ARM64 its 8 bytes:

  52800100    mov w0, #0x8         <- NOP
  d65f03c0    ret

We can NOP the first instruction.

While on ARM32 there are 24 bytes:

  e52db004        push    {fp}       <- NOP
  e28db000        add     fp, sp, #0 <- NOP
  e3a00008        mov     r0, #8     <- NOP
  e24bd000        sub     sp, fp, #0 <- NOP
  e49db004        pop     {fp}       <- NOP
  e12fff1e        bx      lr

And we can NOP instructions 1 through 5.

Granted this code may be different per compiler!

Hence if anybody does run this test-case - they should
verify that the assumptions made here are correct.

Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
v4: Redo the ARM code to NOP over push/pop as well.
---
 xen/test/livepatch/Makefile  | 15 +++++++++++++-
 xen/test/livepatch/xen_nop.c | 48 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 xen/test/livepatch/xen_nop.c

diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index 9439f62..76a779a 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -18,6 +18,7 @@ CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
 LIVEPATCH := xen_hello_world.livepatch
 LIVEPATCH_BYE := xen_bye_world.livepatch
 LIVEPATCH_REPLACE := xen_replace_world.livepatch
+LIVEPATCH_NOP := xen_nop.livepatch
 
 default: livepatch
 
@@ -25,10 +26,12 @@ install: livepatch
 	$(INSTALL_DATA) $(LIVEPATCH) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH)
 	$(INSTALL_DATA) $(LIVEPATCH_BYE) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_BYE)
 	$(INSTALL_DATA) $(LIVEPATCH_REPLACE) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_REPLACE)
+	$(INSTALL_DATA) $(LIVEPATCH_NOP) $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_NOP)
 uninstall:
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH)
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_BYE)
 	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_REPLACE)
+	rm -f $(DESTDIR)$(DEBUG_DIR)/$(LIVEPATCH_NOP)
 
 .PHONY: clean
 clean::
@@ -41,9 +44,13 @@ clean::
 .PHONY: config.h
 config.h: OLD_CODE_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_extra_version)
 config.h: NEW_CODE_SZ=$(call CODE_SZ,$<,xen_hello_world)
+config.h: MINOR_VERSION_SZ=$(call CODE_SZ,$(BASEDIR)/xen-syms,xen_minor_version)
+config.h: MINOR_VERSION_ADDR=$(call CODE_ADDR,$(BASEDIR)/xen-syms,xen_minor_version)
 config.h: xen_hello_world_func.o
 	(set -e; \
 	 echo "#define NEW_CODE_SZ $(NEW_CODE_SZ)"; \
+	 echo "#define MINOR_VERSION_SZ $(MINOR_VERSION_SZ)"; \
+	 echo "#define MINOR_VERSION_ADDR $(MINOR_VERSION_ADDR)"; \
 	 echo "#define OLD_CODE_SZ $(OLD_CODE_SZ)") > $@
 
 xen_hello_world.o: config.h
@@ -91,5 +98,11 @@ xen_replace_world.o: config.h
 $(LIVEPATCH_REPLACE): xen_replace_world_func.o xen_replace_world.o note.o
 	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_REPLACE) $^
 
+xen_nop.o: config.h
+
+.PHONY: $(LIVEPATCH_NOP)
+$(LIVEPATCH_NOP): xen_nop.o note.o
+	$(LD) $(LDFLAGS) $(build_id_linker) -r -o $(LIVEPATCH_NOP) $^
+
 .PHONY: livepatch
-livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE)
+livepatch: $(LIVEPATCH) $(LIVEPATCH_BYE) $(LIVEPATCH_REPLACE) $(LIVEPATCH_NOP)
diff --git a/xen/test/livepatch/xen_nop.c b/xen/test/livepatch/xen_nop.c
new file mode 100644
index 0000000..69dcbca
--- /dev/null
+++ b/xen/test/livepatch/xen_nop.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ */
+
+#include "config.h"
+#include <xen/types.h>
+
+#include <public/sysctl.h>
+
+/*
+ * All of the .new_size and .old_addr are based on assumptions that the
+ * code for 'xen_minor_version' is compiled in specific way. Before
+ * running this test-case you MUST verify that the assumptions are
+ * correct (Hint: make debug and look in xen.s).
+ */
+struct livepatch_func __section(".livepatch.funcs") livepatch_nop = {
+    .version = LIVEPATCH_PAYLOAD_VERSION,
+    .old_size = MINOR_VERSION_SZ,
+
+#ifdef CONFIG_X86
+    .old_addr = (void *)MINOR_VERSION_ADDR,
+    /* Everything but the last instruction: "req". */
+    .new_size = MINOR_VERSION_SZ-1,
+#endif
+
+#ifdef CONFIG_ARM_64
+    .old_addr = (void *)MINOR_VERSION_ADDR,
+    /* Replace the first one: "mov w0, #0x8".  */
+    .new_size = 4,
+#endif
+
+#ifdef CONFIG_ARM_32
+    .old_addr = (void *)MINOR_VERSION_ADDR,
+    /* And replace all but the return instruction. */
+    .new_size = MINOR_VERSION_SZ-4,
+#endif
+};
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-23  1:33     ` Konrad Rzeszutek Wilk
@ 2016-09-23  9:50       ` Julien Grall
  2016-09-27  9:49       ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-23  9:50 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Wei Liu, ross.lagerwall, George Dunlap,
	Andrew Cooper, Ian Jackson, Tim Deegan, Jan Beulich, xen-devel

Hi Konrad,

On 23/09/16 02:33, Konrad Rzeszutek Wilk wrote:
> From c0dac442d15b5f0095b199ab4fff1fc414fb5719 Mon Sep 17 00:00:00 2001
> From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Date: Mon, 19 Sep 2016 16:04:55 -0400
> Subject: [PATCH v6] livepatch: tests: Make them compile under ARM64
>
> We need to two things:
> 1) Wrap the platform-specific objcopy parameters in defines
>    The input and output parameters for $(OBJCOPY) are different
>    based on the platforms. As such provide them in the
>    OBJCOPY_MAGIC define and use that.
>
> 2) The alternative is a bit different (exists only under ARM64
>    and x86), while and there are no exceptions under ARM at all.
>    We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
>    how it is done on x86.
>
> We are not yet attempting to build them under ARM32 so
> that is still ifdefed out.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

You can add my ack on this version:

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case
  2016-09-23  1:35     ` Konrad Rzeszutek Wilk
@ 2016-09-23  9:53       ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-23  9:53 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, ross.lagerwall, Andrew Cooper, Jan Beulich, xen-devel

Hi Konrad,

On 23/09/16 02:35, Konrad Rzeszutek Wilk wrote:
> diff --git a/xen/test/livepatch/xen_nop.c b/xen/test/livepatch/xen_nop.c
> new file mode 100644
> index 0000000..69dcbca
> --- /dev/null
> +++ b/xen/test/livepatch/xen_nop.c
> @@ -0,0 +1,48 @@
> +/*
> + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
> + *
> + */
> +
> +#include "config.h"
> +#include <xen/types.h>
> +
> +#include <public/sysctl.h>
> +
> +/*
> + * All of the .new_size and .old_addr are based on assumptions that the
> + * code for 'xen_minor_version' is compiled in specific way. Before
> + * running this test-case you MUST verify that the assumptions are
> + * correct (Hint: make debug and look in xen.s).
> + */
> +struct livepatch_func __section(".livepatch.funcs") livepatch_nop = {
> +    .version = LIVEPATCH_PAYLOAD_VERSION,
> +    .old_size = MINOR_VERSION_SZ,
> +
> +#ifdef CONFIG_X86
> +    .old_addr = (void *)MINOR_VERSION_ADDR,
> +    /* Everything but the last instruction: "req". */
> +    .new_size = MINOR_VERSION_SZ-1,
> +#endif
> +
> +#ifdef CONFIG_ARM_64
> +    .old_addr = (void *)MINOR_VERSION_ADDR,
> +    /* Replace the first one: "mov w0, #0x8".  */
> +    .new_size = 4,

I would prefer if you use .new_size = MINOR_VERSION_SZ - 4 here.

> +#endif
> +
> +#ifdef CONFIG_ARM_32
> +    .old_addr = (void *)MINOR_VERSION_ADDR,
> +    /* And replace all but the return instruction. */
> +    .new_size = MINOR_VERSION_SZ-4,

It means that you could merge the ARM64 and ARM32 case.

With that:

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in.
  2016-09-21 17:32 ` [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in Konrad Rzeszutek Wilk
@ 2016-09-23 12:47   ` Ross Lagerwall
  0 siblings, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 12:47 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> If the payload had the sections mentioned but the hypervisor
> did not support some of them (say on ARM the .ex_table) - instead
> of ignoring them - it should forbid loading of such payload.
>
> Reviewed-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/16] livepatch: Initial ARM64 support.
  2016-09-21 17:32 ` [PATCH v5 05/16] livepatch: Initial ARM64 support Konrad Rzeszutek Wilk
  2016-09-22 12:49   ` Julien Grall
@ 2016-09-23 13:38   ` Ross Lagerwall
  2016-09-23 15:44     ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 13:38 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: julien.grall, sstabellini, Andrew Cooper, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
snip
> +
> +void arch_livepatch_revert(const struct livepatch_func *func)
> +{
> +    uint32_t *new_ptr;
> +    unsigned int i, len;
> +
> +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> +    len = livepatch_insn_len(func) / sizeof(uint32_t);
> +    for ( i = 0; i < len; i++ )
> +    {
> +        uint32_t insn;
> +
> +        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> +        /* PATCH! */
> +        *(new_ptr + i) = insn;
> +    }

Why is this done in a loop? Can't we just memcpy 
livepatch_insn_len(func) bytes into *new_ptr?

> +}
> +
> +int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
> +{
> +    const Elf_Ehdr *hdr = elf->hdr;
> +
> +    if ( hdr->e_machine != EM_AARCH64 ||
> +         hdr->e_ident[EI_CLASS] != ELFCLASS64 )
> +    {
> +        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
> +                elf->name);
> +        return -EOPNOTSUPP;
> +    }
> +
> +    return 0;
> +}
> +
snip
>  int arch_livepatch_verify_func(const struct livepatch_func *func)
>  {
> -    return -ENOSYS;
> -}
> +    /* If NOPing only do up to maximum amount we can put in the ->opaque. */
> +    if ( !func->new_addr && func->new_size > sizeof(func->opaque) &&
> +         func->new_size % ARCH_PATCH_INSN_SIZE )
> +        return -EOPNOTSUPP;

Maybe I'm misunderstanding, but shouldn't this be ( !func->new_addr && 
(func->new_size > sizeof(func->opaque) || func->new_size % 
ARCH_PATCH_INSN_SIZE) ) ?

-- 
Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-21 17:32 ` [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr Konrad Rzeszutek Wilk
  2016-09-22 12:55   ` Julien Grall
@ 2016-09-23 14:36   ` Ross Lagerwall
  2016-09-23 15:37     ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 14:36 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> If the distance is too big we are in trouble - as our relocation
> distance can surely be clipped, or still have a valid width - but
> cause an overflow of distance.
>
> On various architectures the maximum displacement for a unconditional
> branch/jump varies. ARM32 is +/- 32MB, ARM64 is +/- 128MB while x86
> for 32-bit relocations is +/- 2G.
>
> Note: On x86 we could use the 64-bit jmpq instruction which
> would provide much bigger displacement to do a jump, but we would
> still have issues with the new function not being able to reach
> any of the old functions (as all the relocations would assume 32-bit
> displacement). And "furthermore would require an register or
> memory location to load/store the address to." (From Jan).
>
> On ARM the conditional branch supports even a smaller displacement
> but fortunately we are not using that.

Wouldn't this be simpler as a BUILD_BUG_ON() in arch_livepatch_init()?

Something like BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) - 
XEN_VIRT_START) > ARCH_LIVEPATCH_RANGE)?

And BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) - XEN_VIRT_START) 
 > ARCH_LIVEPATCH_RANGE)

And something similar for ARM...

-- 
Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x]
  2016-09-21 17:32 ` [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x] Konrad Rzeszutek Wilk
  2016-09-22 12:56   ` Julien Grall
@ 2016-09-23 14:44   ` Ross Lagerwall
  2016-09-23 16:13     ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 14:44 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> Those symbols are used to help final linkers to replace insn.
> The ARM ELF specification mandates that they are present
> to denote the start of certain CPU features. There are two
> variants of it - short and long format.
>
> Either way - we can ignore these symbols.
>
> Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> [x86 bits]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>
> ---
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>
> v1: First submission
> v2: Update the order of symbols, fix title
>     Add {} in after the first if - per Jan's recommendation.
> v3: Add Andrew's Review tag
>     Make the function return an bool_t.
>     Skip check for '$t'
>     Fix spelling of comments.
>     s/arch_is_payload_symbol/arch_livepatch_symbol_ok/
> v4: s/bool_t/bool/
> v5: Removed an extra space in the conditional.
> ---
>  xen/arch/arm/livepatch.c    | 33 +++++++++++++++++++++++++++++++++
>  xen/arch/x86/livepatch.c    |  7 +++++++
>  xen/common/livepatch.c      |  2 +-
>  xen/include/xen/livepatch.h |  2 ++
>  4 files changed, 43 insertions(+), 1 deletion(-)
>
> diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
> index 9284766..9959315 100644
> --- a/xen/arch/arm/livepatch.c
> +++ b/xen/arch/arm/livepatch.c
> @@ -84,6 +84,39 @@ void arch_livepatch_unmask(void)
>      local_abort_enable();
>  }
>
> +bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
> +                              const struct livepatch_elf_sym *sym)
> +{
> +    /*
> +     * - Mapping symbols - denote the "start of a sequence of bytes of the
> +     *   appropriate type" to mark certain features - such as start of region
> +     *   containing data ($d); ARM ($a), or A64 ($x) instructions.
> +     *   We ignore Thumb instructions ($t) as we shouldn't have them.
> +     *
> +     * The format is either short: '$x' or long: '$x.<any>'. We do not
> +     * need this and more importantly - each payload will contain this
> +     * resulting in symbol collisions.
> +     */
> +    if ( *sym->name == '$' && sym->name[1] != '\0' )

This would be clear (IMO) as sym->name[0].

Either way,

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-21 17:32 ` [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols Konrad Rzeszutek Wilk
  2016-09-22 13:00   ` Julien Grall
@ 2016-09-23 14:49   ` Ross Lagerwall
  2016-09-23 16:15     ` Konrad Rzeszutek Wilk
  1 sibling, 1 reply; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 14:49 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> Certain platforms, such as ARM [32|64] add extra mapping symbols
> such as $x (for ARM64 instructions), or more interesting to
> this patch: $t (for Thumb instructions). These symbols are suppose
> to help the final linker to make any adjustments (such as
> add an veneer). But more importantly - we do not compile Xen
> with any Thumb instructions (which are variable length) - and
> if we find these mapping symbols we should disallow such payload.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
> Cc: Julien Grall <julien.grall@arm.com
> Cc: Jan Beulich <jbeulich@suse.com>
> Cc: Andrew Cooper <andrew.cooper3@citrix.com>
>
> v3: New submission.
>     Use &sym[i] instead of sym (as that will always be NULL).
> v4: Use bool instead of int for return
>     Update comment in common code about ARM odd symbols.
>     s/_check/_deny/ to make it more clear.
> v5: Also check for $t.* wildcard.
>     Use Julien's variant where we roll the [2] check in the return.
> ---
>  xen/arch/arm/livepatch.c    | 16 ++++++++++++++++
>  xen/arch/x86/livepatch.c    |  7 +++++++
>  xen/common/livepatch_elf.c  |  7 +++++++
>  xen/include/xen/livepatch.h |  2 ++
>  4 files changed, 32 insertions(+)
>
> diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
> index 9959315..5a99ab5 100644
> --- a/xen/arch/arm/livepatch.c
> +++ b/xen/arch/arm/livepatch.c
> @@ -117,6 +117,22 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
>      return true;
>  }
>
> +bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
> +                                const struct livepatch_elf_sym *sym)
> +{
> +#ifdef CONFIG_ARM_32
> +    /*
> +     * Xen does not use Thumb instructions - and we should not see any of
> +     * them. If we do, abort.
> +     */
> +    if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
> +    {
> +        return ( !sym->name[2] || sym->name[2] == '.' );
> +    }
> +#endif
> +    return false;
> +}
> +
>  int arch_livepatch_perform_rel(struct livepatch_elf *elf,
>                                 const struct livepatch_elf_sec *base,
>                                 const struct livepatch_elf_sec *rela)
> diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
> index 7a369a0..9663ef6 100644
> --- a/xen/arch/x86/livepatch.c
> +++ b/xen/arch/x86/livepatch.c
> @@ -131,6 +131,13 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
>      return true;
>  }
>
> +bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
> +                                const struct livepatch_elf_sym *sym)
> +{
> +    /* No special checks on x86. */
> +    return false;
> +}
> +
>  int arch_livepatch_perform_rel(struct livepatch_elf *elf,
>                                 const struct livepatch_elf_sec *base,
>                                 const struct livepatch_elf_sec *rela)
> diff --git a/xen/common/livepatch_elf.c b/xen/common/livepatch_elf.c
> index f46990e..ec74beb 100644
> --- a/xen/common/livepatch_elf.c
> +++ b/xen/common/livepatch_elf.c
> @@ -251,6 +251,13 @@ static int elf_get_sym(struct livepatch_elf *elf, const void *data)
>
>          sym[i].sym = s;
>          sym[i].name = strtab_sec->data + delta;
> +        /* e.g. On ARM we should NEVER see $t* symbols. */

I'd prefer this comment in ARM's arch_livepatch_symbol_deny.

Either way,
Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test.
  2016-09-21 17:32 ` [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test Konrad Rzeszutek Wilk
  2016-09-22 13:01   ` Julien Grall
@ 2016-09-23 14:51   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 14:51 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> So they can be shared with ARM64 (but not yet, so they
> are only built on x86).
>
> No functional change.
>
> We also need to tweak the MAINTAINERS and .gitignore file.
>
> Also we need to update SUBDIRS to include the new 'test'
> directory so 'cscope' can show the example livepatches.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [for directory]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert
  2016-09-21 17:32 ` [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert Konrad Rzeszutek Wilk
@ 2016-09-23 14:59   ` Ross Lagerwall
  2016-09-23 16:15     ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-23 14:59 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: julien.grall, sstabellini, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> It is exactly the same in both platforms.
>
> No functional change.
>
> Acked-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
>
> v3: New submission.
> v4: s/arch_livepatch_insn_len/livepatch_insn_len/
>     s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
> v5: Added Julien's Acked-by.
>     Fixed comments.
>   - Rebase on top "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
>   - s/_jmp//
> ---
>  xen/arch/arm/arm32/livepatch.c | 17 +----------------
>  xen/arch/arm/arm64/livepatch.c | 17 +----------------
>  xen/arch/arm/livepatch.c       | 17 +++++++++++++++++
>  3 files changed, 19 insertions(+), 32 deletions(-)
>
> diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
> index 3f47326..7e600f2 100644
> --- a/xen/arch/arm/arm32/livepatch.c
> +++ b/xen/arch/arm/arm32/livepatch.c
> @@ -74,22 +74,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
>          clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
>  }
>
> -void arch_livepatch_revert(const struct livepatch_func *func)
> -{
> -    uint32_t *new_ptr;
> -    unsigned int i, len;
> -
> -    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> -    len = livepatch_insn_len(func) / sizeof(uint32_t);
> -    for ( i = 0; i < len; i++ )
> -    {
> -        uint32_t insn;
> -
> -        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> -        /* PATCH! */
> -        *(new_ptr + i) = insn;
> -    }
> -}
> +/* arch_livepatch_revert shared with ARM 32/ARM 64. */
>
>  int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
>  {
> diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
> index ea8044d..a7a292f 100644
> --- a/xen/arch/arm/arm64/livepatch.c
> +++ b/xen/arch/arm/arm64/livepatch.c
> @@ -61,22 +61,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
>          clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
>  }
>
> -void arch_livepatch_revert(const struct livepatch_func *func)
> -{
> -    uint32_t *new_ptr;
> -    unsigned int i, len;
> -
> -    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> -    len = livepatch_insn_len(func) / sizeof(uint32_t);
> -    for ( i = 0; i < len; i++ )
> -    {
> -        uint32_t insn;
> -
> -        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> -        /* PATCH! */
> -        *(new_ptr + i) = insn;
> -    }
> -}
> +/* arch_livepatch_revert shared with ARM 32/ARM 64. */
>
>  int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
>  {
> diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
> index 6ee7081..2d62a24 100644
> --- a/xen/arch/arm/livepatch.c
> +++ b/xen/arch/arm/livepatch.c
> @@ -69,6 +69,23 @@ int arch_livepatch_verify_func(const struct livepatch_func *func)
>      return 0;
>  }
>
> +void arch_livepatch_revert(const struct livepatch_func *func)
> +{
> +    uint32_t *new_ptr;
> +    unsigned int i, len;
> +
> +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> +    len = livepatch_insn_len(func) / sizeof(uint32_t);
> +    for ( i = 0; i < len; i++ )
> +    {
> +        uint32_t insn;
> +
> +        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> +        /* PATCH! */
> +        *(new_ptr + i) = insn;
> +    }
> +}
> +

Same as previously, can this not be done with a simple memcpy?

-- 
Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-23 14:36   ` Ross Lagerwall
@ 2016-09-23 15:37     ` Konrad Rzeszutek Wilk
  2016-09-23 15:59       ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 15:37 UTC (permalink / raw)
  To: Ross Lagerwall
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On Fri, Sep 23, 2016 at 03:36:27PM +0100, Ross Lagerwall wrote:
> On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> > If the distance is too big we are in trouble - as our relocation
> > distance can surely be clipped, or still have a valid width - but
> > cause an overflow of distance.
> > 
> > On various architectures the maximum displacement for a unconditional
> > branch/jump varies. ARM32 is +/- 32MB, ARM64 is +/- 128MB while x86
> > for 32-bit relocations is +/- 2G.
> > 
> > Note: On x86 we could use the 64-bit jmpq instruction which
> > would provide much bigger displacement to do a jump, but we would
> > still have issues with the new function not being able to reach
> > any of the old functions (as all the relocations would assume 32-bit
> > displacement). And "furthermore would require an register or
> > memory location to load/store the address to." (From Jan).
> > 
> > On ARM the conditional branch supports even a smaller displacement
> > but fortunately we are not using that.
> 
> Wouldn't this be simpler as a BUILD_BUG_ON() in arch_livepatch_init()?
> 
> Something like BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) -
> XEN_VIRT_START) > ARCH_LIVEPATCH_RANGE)?
> 
> And BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) - XEN_VIRT_START) >
> ARCH_LIVEPATCH_RANGE)
> 
> And something similar for ARM...

What does that have to with the payload? The displacement calculations(checks)
are done when we load the payload.
> 
> -- 
> Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/16] livepatch: Initial ARM64 support.
  2016-09-23 13:38   ` Ross Lagerwall
@ 2016-09-23 15:44     ` Konrad Rzeszutek Wilk
  2016-09-27 16:42       ` Julien Grall
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 15:44 UTC (permalink / raw)
  To: Ross Lagerwall; +Cc: julien.grall, sstabellini, Andrew Cooper, xen-devel

On Fri, Sep 23, 2016 at 02:38:57PM +0100, Ross Lagerwall wrote:
> On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> snip
> > +
> > +void arch_livepatch_revert(const struct livepatch_func *func)
> > +{
> > +    uint32_t *new_ptr;
> > +    unsigned int i, len;
> > +
> > +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> > +    len = livepatch_insn_len(func) / sizeof(uint32_t);
> > +    for ( i = 0; i < len; i++ )
> > +    {
> > +        uint32_t insn;
> > +
> > +        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> > +        /* PATCH! */
> > +        *(new_ptr + i) = insn;
> > +    }
> 
> Why is this done in a loop? Can't we just memcpy livepatch_insn_len(func)
> bytes into *new_ptr?

It can be. 
> 
> > +}
> > +
> > +int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
> > +{
> > +    const Elf_Ehdr *hdr = elf->hdr;
> > +
> > +    if ( hdr->e_machine != EM_AARCH64 ||
> > +         hdr->e_ident[EI_CLASS] != ELFCLASS64 )
> > +    {
> > +        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
> > +                elf->name);
> > +        return -EOPNOTSUPP;
> > +    }
> > +
> > +    return 0;
> > +}
> > +
> snip
> >  int arch_livepatch_verify_func(const struct livepatch_func *func)
> >  {
> > -    return -ENOSYS;
> > -}
> > +    /* If NOPing only do up to maximum amount we can put in the ->opaque. */
> > +    if ( !func->new_addr && func->new_size > sizeof(func->opaque) &&
> > +         func->new_size % ARCH_PATCH_INSN_SIZE )
> > +        return -EOPNOTSUPP;
> 
> Maybe I'm misunderstanding, but shouldn't this be ( !func->new_addr &&
> (func->new_size > sizeof(func->opaque) || func->new_size %
> ARCH_PATCH_INSN_SIZE) ) ?

Yes!

Here is the updated patch:
From deef8f6921c15a4d07209bfba1fc8697dbfeb605 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Mon, 19 Sep 2016 12:24:09 -0400
Subject: [PATCH v6] livepatch: Initial ARM64 support.

As compared to x86 the va of the hypervisor .text
is locked down - we cannot modify the running pagetables
to have the .ro flag unset. We borrow the same idea that
alternative patching has - which is to vmap the entire
.text region and use the alternative virtual address
for patching.

Since we are doing vmap we may fail, hence the
arch_livepatch_quiesce was changed (see "x86,arm:
Change arch_livepatch_quiesce() declaration") to return
an error value which will be bubbled in payload->rc and
provided to the user (along with messages in the ring buffer).

The livepatch virtual address space (where the new functions
are) needs to be close to the hypervisor virtual address
so that the trampoline can reach it. As such we re-use
the BOOT_RELOC_VIRT_START which is not used after bootup
(alternatively we can also use the space after the _end to
FIXMAP_ADDR(0), but that may be too small).

The ELF relocation engine at the start was coded from
the "ELF for the ARM 64-bit Architecture (AArch64)"
(http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf)
but after a while of trying to write the correct bit shifting
and masking from scratch I ended up borrowing from Linux, the
'reloc_insn_imm' (Linux v4.7 arch/arm64/kernel/module.c function.
See 257cb251925f854da435cbf79b140984413871ac "arm64: Loadable modules")

And while at it - we also utilize code from Linux to construct
the right branch instruction (see "arm64/insn: introduce
aarch64_insn_gen_{nop|branch_imm}() helper functions").

In the livepatch payload loading code we tweak the #ifdef to
only exclude ARM_32. The exceptions are not part of ARM 32/64 hence
they are still behind the #ifdef.

We also expand the MAINTAINERS file to include the arm64 and arm32
platform specific livepatch file.

Acked-by: Jan Beulich <jbeulich@suse.com> [non-arm parts]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com>
Cc  Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

RFC: Wholy cow! It works!
v1: Finished the various TODOs and reviews outlined by Julien in RFC.
v2: Call check_for_livepatch_work in leave_hypervisor_tail not in
    reset_stack_and_jump
   - Move ARM 32 components in other patch
   - Blacklist platform options in Kconfig
   - Added R_AARCH64_LDST128_ABS_LO12_NC, R_AARCH64_TSTBR14, and
     R_AARCH64_ADR_PREL_PG_HI21_NC
   - Added do_reloc and reloc_data along with overflow checks from Linux.
   - Use apply_alternatives without any #ifdef
   - Use leave_hypervisor_tail to call check_for_livepatch_work
   - Add ASSERT that isns is not AARCH64_BREAK_FAULT
   - Spun out arch_livepatch_quiesce changes in seperate patch.
   - Spun out changes to config.h (document ones) to seperate patch.
   - Move the livepatch.h to include/xen/asm-arm.
   - Add LIVEPATCH_VMAP_END and LIVEPATCH_VMAP_START in config.h
   - In arch_livepatch_secure use switch for va_type.
   - Drop the #ifndef CONFIG_ARM for .ex_table (see
     "arm/x86: Add HAS_ALTERNATIVE and HAS_EX_TABLE")
   - Piggyback on "x86: change modify_xen_mappings to return error"
      so that arch_livepatch_secure can return errors.
   - Moves comment about branch predictor out of this patch.
v3: Fix StyleGuide violations (switch statements)
   - Fix incorrect cast of addr when reverting.
   - Drop old_ptr variable.
   - Use bool_t values instead of numbers.
   - Sprinkle \n as requested by Julien.
   - In arch_livepatch_quiesce use 1U instead of 1.
   - Use C99 #defines for [U,]INT[16,32]_[MIN,MAX] instead of Linux
     kernel ones ([S,U][16,32]_[MIN,MAX]).
   - Include the ELF relocations for R_AARCH64_[ABS,PRE]16, and
     all the various groupings for R_AARCH64_MOVW_[UABS,SABS,PREL]_*
     family.
   - Redo the NOP patching to use more of the opaque size (so up to 7
     instructions in one go).
   - Drop the cpu_to_le32 macros as they are not needed (and can allow
     use to share more code with ARM32).
   - Flush out func->old_addr instead of vmap pointer when reverting.
v4: Added Jan's Ack
   s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
   s/arch_livepatch_insn_len/livepatch_insn_len/
v5: Added 'fallthrough' comments on the switch statements.
   - Added more invalidate of dcache on the old_addr and the vmap area.
   - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
   - Move most of  docs part from "livepatch: ARM/x86: Check displacement of
     old_addr and new_addr" in this patch.
   - Added syncing of data cache along with explanation for its usage.
v6: Dropped from docs the 'ea opcode' part
   - Reinsert the clean_and_invalidate_dcache_va_range on new_ptr.
   - Update comment in arch_livepatch_revive to mention the revert function too.
   - Fix the NOP check arch_livepatch_verify_func
   - Simplify the arch_livepatch_revert code (no loop, just memcpy).
---
 MAINTAINERS                     |   1 +
 docs/misc/livepatch.markdown    |  14 +-
 xen/arch/arm/Makefile           |  13 +-
 xen/arch/arm/arm32/Makefile     |   1 +
 xen/arch/arm/arm32/livepatch.c  |  38 ++++
 xen/arch/arm/arm64/Makefile     |   1 +
 xen/arch/arm/arm64/livepatch.c  | 485 ++++++++++++++++++++++++++++++++++++++++
 xen/arch/arm/domain.c           |   6 +
 xen/arch/arm/livepatch.c        | 103 +++++++--
 xen/arch/arm/traps.c            |   6 +
 xen/common/Kconfig              |   2 +-
 xen/include/asm-arm/config.h    |   5 +
 xen/include/asm-arm/livepatch.h |  28 +++
 xen/include/xen/elfstructs.h    |  57 ++++-
 xen/include/xen/types.h         |   9 +
 15 files changed, 743 insertions(+), 26 deletions(-)
 create mode 100644 xen/arch/arm/arm32/livepatch.c
 create mode 100644 xen/arch/arm/arm64/livepatch.c
 create mode 100644 xen/include/asm-arm/livepatch.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 9b30600..1c39146 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -269,6 +269,7 @@ S:  Supported
 F:  docs/misc/livepatch.markdown
 F:  tools/misc/xen-livepatch.c
 F:  xen/arch/*/livepatch*
+F:  xen/arch/*/*/livepatch*
 F:  xen/common/livepatch*
 F:  xen/include/asm-*/livepatch.h
 F:  xen/include/xen/livepatch*
diff --git a/docs/misc/livepatch.markdown b/docs/misc/livepatch.markdown
index 3dd6304..5fe93b4 100644
--- a/docs/misc/livepatch.markdown
+++ b/docs/misc/livepatch.markdown
@@ -1108,7 +1108,7 @@ and the .data or .bss sections are of zero length.
 The hypervisor should verify that the in-place patching would fit within
 the code or data.
 
-### Trampoline (e9 opcode)
+### Trampoline (e9 opcode), x86
 
 The e9 opcode used for jmpq uses a 32-bit signed displacement. That means
 we are limited to up to 2GB of virtual address to place the new code
@@ -1143,3 +1143,15 @@ that in the hypervisor is advised.
 The tool for generating payloads currently does perform a compile-time
 check to ensure that the function to be replaced is large enough.
 
+#### Trampoline, ARM
+
+The unconditional branch instruction (for the encoding see the
+DDI 0406C.c and DDI 0487A.j Architecture Reference Manual's).
+with proper offset is used for an unconditional branch to the new code.
+This means that that `old_size` **MUST** be at least four bytes if patching
+in trampoline.
+
+The new code is placed in the 8M - 10M virtual address space while the
+Xen code is in 2M - 4M. That gives us enough space.
+
+The hypervisor also checks the displacement during loading of the payload.
diff --git a/xen/arch/arm/Makefile b/xen/arch/arm/Makefile
index 61e655b..5cee84d 100644
--- a/xen/arch/arm/Makefile
+++ b/xen/arch/arm/Makefile
@@ -59,6 +59,15 @@ ALL_OBJS := $(TARGET_SUBARCH)/head.o $(ALL_OBJS)
 
 DEPS += $(TARGET_SUBARCH)/.head.o.d
 
+ifdef CONFIG_LIVEPATCH
+all_symbols = --all-symbols
+ifdef CONFIG_FAST_SYMBOL_LOOKUP
+all_symbols = --all-symbols --sort-by-name
+endif
+else
+all_symbols =
+endif
+
 $(TARGET): $(TARGET)-syms $(TARGET).axf
 	$(OBJCOPY) -O binary -S $< $@
 ifeq ($(CONFIG_ARM_64),y)
@@ -94,12 +103,12 @@ $(TARGET)-syms: prelink.o xen.lds $(BASEDIR)/common/symbols-dummy.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
 	    $(BASEDIR)/common/symbols-dummy.o -o $(@D)/.$(@F).0
 	$(NM) -pa --format=sysv $(@D)/.$(@F).0 \
-		| $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).0.S
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).0.S
 	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o \
 	    $(@D)/.$(@F).0.o -o $(@D)/.$(@F).1
 	$(NM) -pa --format=sysv $(@D)/.$(@F).1 \
-		| $(BASEDIR)/tools/symbols --sysv --sort >$(@D)/.$(@F).1.S
+		| $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort >$(@D)/.$(@F).1.S
 	$(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1.o
 	$(LD) $(LDFLAGS) -T xen.lds -N prelink.o $(build_id_linker) \
 	    $(@D)/.$(@F).1.o -o $@
diff --git a/xen/arch/arm/arm32/Makefile b/xen/arch/arm/arm32/Makefile
index b20db64..4395693 100644
--- a/xen/arch/arm/arm32/Makefile
+++ b/xen/arch/arm/arm32/Makefile
@@ -4,6 +4,7 @@ obj-$(EARLY_PRINTK) += debug.o
 obj-y += domctl.o
 obj-y += domain.o
 obj-y += entry.o
+obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += proc-v7.o proc-caxx.o
 obj-y += smpboot.o
 obj-y += traps.o
diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
new file mode 100644
index 0000000..80f9646
--- /dev/null
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -0,0 +1,38 @@
+/*
+ *  Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/livepatch_elf.h>
+#include <xen/livepatch.h>
+
+void arch_livepatch_apply(struct livepatch_func *func)
+{
+}
+
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+}
+
+int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
+{
+    return -EOPNOTSUPP;
+}
+
+int arch_livepatch_perform_rela(struct livepatch_elf *elf,
+                                const struct livepatch_elf_sec *base,
+                                const struct livepatch_elf_sec *rela)
+{
+    return -ENOSYS;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/arm64/Makefile b/xen/arch/arm/arm64/Makefile
index c1fa43f..149b6b3 100644
--- a/xen/arch/arm/arm64/Makefile
+++ b/xen/arch/arm/arm64/Makefile
@@ -6,6 +6,7 @@ obj-y += domctl.o
 obj-y += domain.o
 obj-y += entry.o
 obj-y += insn.o
+obj-$(CONFIG_LIVEPATCH) += livepatch.o
 obj-y += smpboot.o
 obj-y += traps.o
 obj-y += vfp.o
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
new file mode 100644
index 0000000..93548aa
--- /dev/null
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -0,0 +1,485 @@
+/*
+ *  Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <xen/bitops.h>
+#include <xen/errno.h>
+#include <xen/lib.h>
+#include <xen/livepatch_elf.h>
+#include <xen/livepatch.h>
+#include <xen/mm.h>
+#include <xen/vmap.h>
+
+#include <asm/bitops.h>
+#include <asm/byteorder.h>
+#include <asm/insn.h>
+#include <asm/livepatch.h>
+
+void arch_livepatch_apply(struct livepatch_func *func)
+{
+    uint32_t insn;
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
+
+    ASSERT(vmap_of_xen_text);
+
+    len = livepatch_insn_len(func);
+    if ( !len )
+        return;
+
+    /* Save old ones. */
+    memcpy(func->opaque, func->old_addr, len);
+
+    if ( func->new_addr )
+        insn = aarch64_insn_gen_branch_imm((unsigned long)func->old_addr,
+                                           (unsigned long)func->new_addr,
+                                           AARCH64_INSN_BRANCH_NOLINK);
+    else
+        insn = aarch64_insn_gen_nop();
+
+    ASSERT(insn != AARCH64_BREAK_FAULT);
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = len / sizeof(uint32_t);
+
+    /* PATCH! */
+    for ( i = 0; i < len; i++ )
+        *(new_ptr + i) = insn;
+
+    /*
+    * When we upload the payload, it will go through the data cache
+    * (the region is cacheable). Until the data cache is cleaned, the data
+    * may not reach the memory. And in the case the data and instruction cache
+    * are separated, we may read invalid instruction from the memory because
+    * the data cache have not yet synced with the memory. Hence sync it.
+    */
+    if ( func->new_addr )
+        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
+    clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
+}
+
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+    uint32_t *new_ptr;
+    unsigned int len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+
+    len = livepatch_insn_len(func);
+    memcpy(new_ptr, func->opaque, len);
+
+    clean_and_invalidate_dcache_va_range(new_ptr, len);
+}
+
+int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
+{
+    const Elf_Ehdr *hdr = elf->hdr;
+
+    if ( hdr->e_machine != EM_AARCH64 ||
+         hdr->e_ident[EI_CLASS] != ELFCLASS64 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
+                elf->name);
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+enum aarch64_reloc_op {
+    RELOC_OP_NONE,
+    RELOC_OP_ABS,
+    RELOC_OP_PREL,
+    RELOC_OP_PAGE,
+};
+
+static u64 do_reloc(enum aarch64_reloc_op reloc_op, void *place, u64 val)
+{
+    switch ( reloc_op )
+    {
+    case RELOC_OP_ABS:
+        return val;
+
+    case RELOC_OP_PREL:
+        return val - (u64)place;
+
+    case RELOC_OP_PAGE:
+        return (val & ~0xfff) - ((u64)place & ~0xfff);
+
+    case RELOC_OP_NONE:
+        return 0;
+
+    }
+
+    dprintk(XENLOG_DEBUG, LIVEPATCH "do_reloc: unknown relocation operation %d\n", reloc_op);
+
+    return 0;
+}
+
+static int reloc_data(enum aarch64_reloc_op op, void *place, u64 val, int len)
+{
+    s64 sval = do_reloc(op, place, val);
+
+    switch ( len )
+    {
+    case 16:
+        *(s16 *)place = sval;
+        if ( sval < INT16_MIN || sval > UINT16_MAX )
+	        return -EOVERFLOW;
+        break;
+
+    case 32:
+        *(s32 *)place = sval;
+        if ( sval < INT32_MIN || sval > UINT32_MAX )
+	        return -EOVERFLOW;
+        break;
+
+    case 64:
+        *(s64 *)place = sval;
+        break;
+
+    default:
+        dprintk(XENLOG_DEBUG, LIVEPATCH "Invalid length (%d) for data relocation\n", len);
+        return 0;
+    }
+
+    return 0;
+}
+
+enum aarch64_insn_movw_imm_type {
+    AARCH64_INSN_IMM_MOVNZ,
+    AARCH64_INSN_IMM_MOVKZ,
+};
+
+static int reloc_insn_movw(enum aarch64_reloc_op op, void *dest, u64 val,
+                           int lsb, enum aarch64_insn_movw_imm_type imm_type)
+{
+    u64 imm;
+    s64 sval;
+    u32 insn = *(u32 *)dest;
+
+    sval = do_reloc(op, dest, val);
+    imm = sval >> lsb;
+
+    if ( imm_type == AARCH64_INSN_IMM_MOVNZ )
+    {
+        /*
+         * For signed MOVW relocations, we have to manipulate the
+         * instruction encoding depending on whether or not the
+         * immediate is less than zero.
+         */
+        insn &= ~(3 << 29);
+        if ( sval >= 0 )
+        {
+            /* >=0: Set the instruction to MOVZ (opcode 10b). */
+            insn |= 2 << 29;
+        }
+        else
+        {
+            /*
+             * <0: Set the instruction to MOVN (opcode 00b).
+             *     Since we've masked the opcode already, we
+             *     don't need to do anything other than
+             *     inverting the new immediate field.
+             */
+            imm = ~imm;
+        }
+    }
+
+    /* Update the instruction with the new encoding. */
+    insn = aarch64_insn_encode_immediate(AARCH64_INSN_IMM_16, insn, imm);
+    *(u32 *)dest = insn;
+
+    if ( imm > UINT16_MAX )
+        return -EOVERFLOW;
+
+    return 0;
+}
+
+static int reloc_insn_imm(enum aarch64_reloc_op op, void *dest, u64 val,
+                          int lsb, int len, enum aarch64_insn_imm_type imm_type)
+{
+    u64 imm, imm_mask;
+    s64 sval;
+    u32 insn = *(u32 *)dest;
+
+    /* Calculate the relocation value. */
+    sval = do_reloc(op, dest, val);
+    sval >>= lsb;
+
+    /* Extract the value bits and shift them to bit 0. */
+    imm_mask = (BIT(lsb + len) - 1) >> lsb;
+    imm = sval & imm_mask;
+
+    /* Update the instruction's immediate field. */
+    insn = aarch64_insn_encode_immediate(imm_type, insn, imm);
+    *(u32 *)dest = insn;
+
+    /*
+     * Extract the upper value bits (including the sign bit) and
+     * shift them to bit 0.
+     */
+    sval = (s64)(sval & ~(imm_mask >> 1)) >> (len - 1);
+
+    /*
+     * Overflow has occurred if the upper bits are not all equal to
+     * the sign bit of the value.
+     */
+    if ( (u64)(sval + 1) >= 2 )
+        return -EOVERFLOW;
+    return 0;
+}
+
+int arch_livepatch_perform_rela(struct livepatch_elf *elf,
+                                const struct livepatch_elf_sec *base,
+                                const struct livepatch_elf_sec *rela)
+{
+    const Elf_RelA *r;
+    unsigned int symndx, i;
+    uint64_t val;
+    void *dest;
+    bool_t overflow_check;
+
+    for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+    {
+        int ovf = 0;
+
+        r = rela->data + i * rela->sec->sh_entsize;
+
+        symndx = ELF64_R_SYM(r->r_info);
+
+        if ( symndx > elf->nsym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation wants symbol@%u which is past end!\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
+
+        dest = base->load_addr + r->r_offset; /* P */
+        val = elf->sym[symndx].sym->st_value +  r->r_addend; /* S+A */
+
+        overflow_check = true;
+
+        /* ARM64 operations at minimum are always 32-bit. */
+        if ( r->r_offset >= base->sec->sh_size ||
+            (r->r_offset + sizeof(uint32_t)) > base->sec->sh_size )
+            goto bad_offset;
+
+        switch ( ELF64_R_TYPE(r->r_info) )
+        {
+        /* Data */
+        case R_AARCH64_ABS64:
+            if ( r->r_offset + sizeof(uint64_t) > base->sec->sh_size )
+                goto bad_offset;
+            overflow_check = false;
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 64);
+            break;
+
+        case R_AARCH64_ABS32:
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 32);
+            break;
+
+        case R_AARCH64_ABS16:
+            ovf = reloc_data(RELOC_OP_ABS, dest, val, 16);
+            break;
+
+        case R_AARCH64_PREL64:
+            if ( r->r_offset + sizeof(uint64_t) > base->sec->sh_size )
+                goto bad_offset;
+            overflow_check = false;
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 64);
+            break;
+
+        case R_AARCH64_PREL32:
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 32);
+            break;
+
+        case R_AARCH64_PREL16:
+            ovf = reloc_data(RELOC_OP_PREL, dest, val, 16);
+            break;
+
+        /* MOVW instruction relocations. */
+        case R_AARCH64_MOVW_UABS_G0_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G0:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G1_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G1:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G2_NC:
+            overflow_check = false;
+            /* Fallthrough. */
+
+        case R_AARCH64_MOVW_UABS_G2:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_UABS_G3:
+            /* We're using the top bits so we can't overflow. */
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 48,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G0:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G1:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_SABS_G2:
+            ovf = reloc_insn_movw(RELOC_OP_ABS, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G0_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G0:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 0,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G1_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G1:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 16,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G2_NC:
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVKZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G2:
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 32,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        case R_AARCH64_MOVW_PREL_G3:
+            /* We're using the top bits so we can't overflow. */
+            overflow_check = false;
+            ovf = reloc_insn_movw(RELOC_OP_PREL, dest, val, 48,
+                                  AARCH64_INSN_IMM_MOVNZ);
+            break;
+
+        /* Instructions. */
+        case R_AARCH64_ADR_PREL_LO21:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 0, 21,
+                                 AARCH64_INSN_IMM_ADR);
+            break;
+
+        case R_AARCH64_ADR_PREL_PG_HI21_NC:
+            overflow_check = false;
+        case R_AARCH64_ADR_PREL_PG_HI21:
+            ovf = reloc_insn_imm(RELOC_OP_PAGE, dest, val, 12, 21,
+                                 AARCH64_INSN_IMM_ADR);
+            break;
+
+        case R_AARCH64_LDST8_ABS_LO12_NC:
+            /* Fallthrough. */
+
+        case R_AARCH64_ADD_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 0, 12,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST16_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 1, 11,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST32_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 2, 10,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST64_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 3, 9,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_LDST128_ABS_LO12_NC:
+            overflow_check = false;
+            ovf = reloc_insn_imm(RELOC_OP_ABS, dest, val, 4, 8,
+                                 AARCH64_INSN_IMM_12);
+            break;
+
+        case R_AARCH64_TSTBR14:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 19,
+                                 AARCH64_INSN_IMM_14);
+            break;
+
+        case R_AARCH64_CONDBR19:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 19,
+                                 AARCH64_INSN_IMM_19);
+            break;
+
+        case R_AARCH64_JUMP26:
+        case R_AARCH64_CALL26:
+            ovf = reloc_insn_imm(RELOC_OP_PREL, dest, val, 2, 26,
+                                 AARCH64_INSN_IMM_26);
+            break;
+
+        default:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation %lu\n",
+                    elf->name, ELF64_R_TYPE(r->r_info));
+            return -EOPNOTSUPP;
+        }
+
+        if ( overflow_check && ovf == -EOVERFLOW )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
+                    elf->name, i, rela->name, base->name);
+            return ovf;
+        }
+    }
+    return 0;
+
+ bad_offset:
+    dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative relocation offset is past %s section!\n",
+            elf->name, base->name);
+    return -EINVAL;
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/arch/arm/domain.c b/xen/arch/arm/domain.c
index 20bb2ba..607ee59 100644
--- a/xen/arch/arm/domain.c
+++ b/xen/arch/arm/domain.c
@@ -13,6 +13,7 @@
 #include <xen/hypercall.h>
 #include <xen/init.h>
 #include <xen/lib.h>
+#include <xen/livepatch.h>
 #include <xen/sched.h>
 #include <xen/softirq.h>
 #include <xen/wait.h>
@@ -55,6 +56,11 @@ void idle_loop(void)
 
         do_tasklet();
         do_softirq();
+        /*
+         * We MUST be last (or before dsb, wfi). Otherwise after we get the
+         * softirq we would execute dsb,wfi (and sleep) and not patch.
+         */
+        check_for_livepatch_work();
     }
 }
 
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 7f067a0..679abf1 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -6,44 +6,82 @@
 #include <xen/lib.h>
 #include <xen/livepatch_elf.h>
 #include <xen/livepatch.h>
+#include <xen/vmap.h>
+
+#include <asm/livepatch.h>
+#include <asm/mm.h>
+
+void *vmap_of_xen_text;
 
 int arch_livepatch_quiesce(void)
 {
-    return -ENOSYS;
+    mfn_t text_mfn;
+    unsigned int text_order;
+
+    if ( vmap_of_xen_text )
+        return -EINVAL;
+
+    text_mfn = _mfn(virt_to_mfn(_start));
+    text_order = get_order_from_bytes(_end - _start);
+
+    /*
+     * The text section is read-only. So re-map Xen to be able to patch
+     * the code.
+     */
+    vmap_of_xen_text = __vmap(&text_mfn, 1U << text_order, 1, 1, PAGE_HYPERVISOR,
+                              VMAP_DEFAULT);
+
+    if ( !vmap_of_xen_text )
+    {
+        printk(XENLOG_ERR LIVEPATCH "Failed to setup vmap of hypervisor! (order=%u)\n",
+               text_order);
+        return -ENOMEM;
+    }
+
+    return 0;
 }
 
 void arch_livepatch_revive(void)
 {
+    /*
+     * Nuke the instruction cache. Data cache has been cleaned before in
+     * arch_livepatch_[apply|revert].
+     */
+    invalidate_icache();
+
+    if ( vmap_of_xen_text )
+        vunmap(vmap_of_xen_text);
+
+    vmap_of_xen_text = NULL;
 }
 
 int arch_livepatch_verify_func(const struct livepatch_func *func)
 {
-    return -ENOSYS;
-}
+    /* If NOPing only do up to maximum amount we can put in the ->opaque. */
+    if ( !func->new_addr && (func->new_size > sizeof(func->opaque) ||
+         func->new_size % ARCH_PATCH_INSN_SIZE) )
+        return -EOPNOTSUPP;
 
-void arch_livepatch_apply(struct livepatch_func *func)
-{
-}
+    if ( func->old_size < ARCH_PATCH_INSN_SIZE )
+        return -EINVAL;
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
+    return 0;
 }
 
 void arch_livepatch_post_action(void)
 {
+    /* arch_livepatch_revive has nuked the instruction cache. */
 }
 
 void arch_livepatch_mask(void)
 {
+    /* Mask System Error (SError) */
+    local_abort_disable();
 }
 
 void arch_livepatch_unmask(void)
 {
-}
-
-int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
-{
-    return -ENOSYS;
+    local_abort_enable();
 }
 
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
@@ -53,20 +91,43 @@ int arch_livepatch_perform_rel(struct livepatch_elf *elf,
     return -ENOSYS;
 }
 
-int arch_livepatch_perform_rela(struct livepatch_elf *elf,
-                                const struct livepatch_elf_sec *base,
-                                const struct livepatch_elf_sec *rela)
-{
-    return -ENOSYS;
-}
-
 int arch_livepatch_secure(const void *va, unsigned int pages, enum va_type type)
 {
-    return -ENOSYS;
+    unsigned long start = (unsigned long)va;
+    unsigned int flags = 0;
+
+    ASSERT(va);
+    ASSERT(pages);
+
+    switch ( type )
+    {
+    case LIVEPATCH_VA_RX:
+        flags = PTE_RO; /* R set, NX clear */
+        break;
+
+    case LIVEPATCH_VA_RW:
+        flags = PTE_NX; /* R clear, NX set */
+        break;
+
+    case LIVEPATCH_VA_RO:
+        flags = PTE_NX | PTE_RO; /* R set, NX set */
+        break;
+
+    default:
+        return -EINVAL;
+    }
+
+    return modify_xen_mappings(start, start + pages * PAGE_SIZE, flags);
 }
 
 void __init arch_livepatch_init(void)
 {
+    void *start, *end;
+
+    start = (void *)LIVEPATCH_VMAP_START;
+    end = (void *)LIVEPATCH_VMAP_END;
+
+    vm_init_type(VMAP_XEN, start, end);
 }
 
 /*
diff --git a/xen/arch/arm/traps.c b/xen/arch/arm/traps.c
index 39a05fd..cd6c222 100644
--- a/xen/arch/arm/traps.c
+++ b/xen/arch/arm/traps.c
@@ -24,6 +24,7 @@
 #include <xen/symbols.h>
 #include <xen/irq.h>
 #include <xen/lib.h>
+#include <xen/livepatch.h>
 #include <xen/mm.h>
 #include <xen/errno.h>
 #include <xen/hypercall.h>
@@ -2689,6 +2690,11 @@ asmlinkage void leave_hypervisor_tail(void)
         }
         local_irq_enable();
         do_softirq();
+        /*
+         * Must be the last one - as the IPI will trigger us to come here
+         * and we want to patch the hypervisor with almost no stack.
+         */
+        check_for_livepatch_work();
     }
 }
 
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 81e0017..0f26027 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -217,7 +217,7 @@ config CRYPTO
 config LIVEPATCH
 	bool "Live patching support (TECH PREVIEW)"
 	default n
-	depends on X86 && HAS_BUILD_ID = "y"
+	depends on !ARM_32 && HAS_BUILD_ID = "y"
 	---help---
 	  Allows a running Xen hypervisor to be dynamically patched using
 	  binary patches without rebooting. This is primarily used to binarily
diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h
index 6772555..ba61f65 100644
--- a/xen/include/asm-arm/config.h
+++ b/xen/include/asm-arm/config.h
@@ -80,6 +80,7 @@
  *   4M -   6M   Fixmap: special-purpose 4K mapping slots
  *   6M -   8M   Early boot mapping of FDT
  *   8M -  10M   Early relocation address (used when relocating Xen)
+ *               and later for livepatch vmap (if compiled in)
  *
  * ARM32 layout:
  *   0  -  10M   <COMMON>
@@ -113,6 +114,10 @@
 #define FIXMAP_ADDR(n)        (_AT(vaddr_t,0x00400000) + (n) * PAGE_SIZE)
 #define BOOT_FDT_VIRT_START    _AT(vaddr_t,0x00600000)
 #define BOOT_RELOC_VIRT_START  _AT(vaddr_t,0x00800000)
+#ifdef CONFIG_LIVEPATCH
+#define LIVEPATCH_VMAP_START   _AT(vaddr_t,0x00800000)
+#define LIVEPATCH_VMAP_END     (LIVEPATCH_VMAP_START + MB(2))
+#endif
 
 #define HYPERVISOR_VIRT_START  XEN_VIRT_START
 
diff --git a/xen/include/asm-arm/livepatch.h b/xen/include/asm-arm/livepatch.h
new file mode 100644
index 0000000..929c7d9
--- /dev/null
+++ b/xen/include/asm-arm/livepatch.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved.
+ *
+ */
+
+#ifndef __XEN_ARM_LIVEPATCH_H__
+#define __XEN_ARM_LIVEPATCH_H__
+
+/* On ARM32,64 instructions are always 4 bytes long. */
+#define ARCH_PATCH_INSN_SIZE 4
+
+/*
+ * The va of the hypervisor .text region. We need this as the
+ * normal va are write protected.
+ */
+extern void *vmap_of_xen_text;
+
+#endif /* __XEN_ARM_LIVEPATCH_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * tab-width: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/xen/elfstructs.h b/xen/include/xen/elfstructs.h
index 5f2082e..7329987 100644
--- a/xen/include/xen/elfstructs.h
+++ b/xen/include/xen/elfstructs.h
@@ -177,6 +177,7 @@ typedef struct {
 #define EM_IA_64	50		/* Intel Merced */
 #define EM_X86_64	62		/* AMD x86-64 architecture */
 #define EM_VAX		75		/* DEC VAX */
+#define EM_AARCH64	183		/* ARM 64-bit */
 
 /* Version */
 #define EV_NONE		0		/* Invalid */
@@ -353,12 +354,66 @@ typedef struct {
 #define	ELF64_R_TYPE(info)	((info) & 0xFFFFFFFF)
 #define ELF64_R_INFO(s,t) 	(((s) << 32) + (u_int32_t)(t))
 
-/* x86-64 relocation types. We list only the ones Live Patch implements. */
+/*
+ * Relocation types for x86_64 and ARM 64. We list only the ones Live Patch
+ * implements.
+ */
 #define R_X86_64_NONE		0	/* No reloc */
 #define R_X86_64_64	    	1	/* Direct 64 bit  */
 #define R_X86_64_PC32		2	/* PC relative 32 bit signed */
 #define R_X86_64_PLT32		4	/* 32 bit PLT address */
 
+/*
+ * S - address of symbol.
+ * A - addend for relocation (r_addend)
+ * P - address of the dest being relocated (derieved from r_offset)
+ * NC -  No check for overflow.
+ *
+ * The defines also use _PREL for PC-relative address, and _NC is No Check.
+ */
+#define R_AARCH64_ABS64			257 /* Direct 64 bit. S+A, NC*/
+#define R_AARCH64_ABS32			258 /* Direct 32 bit. S+A */
+#define R_AARCH64_ABS16			259 /* Direct 16 bit, S+A */
+#define R_AARCH64_PREL64		260 /* S+A-P, NC */
+#define R_AARCH64_PREL32		261 /* S+A-P */
+#define R_AARCH64_PREL16		262 /* S+A-P */
+
+/* Instructions. */
+#define R_AARCH64_MOVW_UABS_G0		263
+#define R_AARCH64_MOVW_UABS_G0_NC	264
+#define R_AARCH64_MOVW_UABS_G1		265
+#define R_AARCH64_MOVW_UABS_G1_NC	266
+#define R_AARCH64_MOVW_UABS_G2		267
+#define R_AARCH64_MOVW_UABS_G2_NC	268
+#define R_AARCH64_MOVW_UABS_G3		269
+
+#define R_AARCH64_MOVW_SABS_G0		270
+#define R_AARCH64_MOVW_SABS_G1		271
+#define R_AARCH64_MOVW_SABS_G2		272
+
+#define R_AARCH64_ADR_PREL_LO21		274 /* ADR imm, [20:0]. S+A-P */
+#define R_AARCH64_ADR_PREL_PG_HI21	275 /* ADRP imm, [32:12]. Page(S+A) - Page(P).*/
+#define R_AARCH64_ADR_PREL_PG_HI21_NC	276
+#define R_AARCH64_ADD_ABS_LO12_NC	277 /* ADD imm. [11:0]. S+A, NC */
+
+#define R_AARCH64_TSTBR14		279
+#define R_AARCH64_CONDBR19		280 /* Bits 20:2, S+A-P */
+#define R_AARCH64_JUMP26		282 /* Bits 27:2, S+A-P */
+#define R_AARCH64_CALL26		283 /* Bits 27:2, S+A-P */
+#define R_AARCH64_LDST16_ABS_LO12_NC	284 /* LD/ST to bits 11:1, S+A, NC */
+#define R_AARCH64_LDST32_ABS_LO12_NC	285 /* LD/ST to bits 11:2, S+A, NC */
+#define R_AARCH64_LDST64_ABS_LO12_NC	286 /* LD/ST to bits 11:3, S+A, NC */
+#define R_AARCH64_LDST8_ABS_LO12_NC	278 /* LD/ST to bits 11:0, S+A, NC */
+#define R_AARCH64_LDST128_ABS_LO12_NC	299
+
+#define R_AARCH64_MOVW_PREL_G0		287
+#define R_AARCH64_MOVW_PREL_G0_NC	288
+#define R_AARCH64_MOVW_PREL_G1		289
+#define R_AARCH64_MOVW_PREL_G1_NC	290
+#define R_AARCH64_MOVW_PREL_G2		291
+#define R_AARCH64_MOVW_PREL_G2_NC	292
+#define R_AARCH64_MOVW_PREL_G3		293
+
 /* Program Header */
 typedef struct {
 	Elf32_Word	p_type;		/* segment type */
diff --git a/xen/include/xen/types.h b/xen/include/xen/types.h
index 7bdc83b..c79c353 100644
--- a/xen/include/xen/types.h
+++ b/xen/include/xen/types.h
@@ -14,6 +14,15 @@
 #define NULL ((void*)0)
 #endif
 
+#define INT16_MIN       (-32767-1)
+#define INT32_MIN       (-2147483647-1)
+
+#define INT16_MAX       (32767)
+#define INT32_MAX       (2147483647)
+
+#define UINT16_MAX      (65535)
+#define UINT32_MAX      (4294967295U)
+
 #define INT_MAX         ((int)(~0U>>1))
 #define INT_MIN         (-INT_MAX - 1)
 #define UINT_MAX        (~0U)
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-23 15:37     ` Konrad Rzeszutek Wilk
@ 2016-09-23 15:59       ` Konrad Rzeszutek Wilk
  2016-09-28 10:21         ` Ross Lagerwall
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 15:59 UTC (permalink / raw)
  To: Ross Lagerwall
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On Fri, Sep 23, 2016 at 11:37:27AM -0400, Konrad Rzeszutek Wilk wrote:
> On Fri, Sep 23, 2016 at 03:36:27PM +0100, Ross Lagerwall wrote:
> > On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> > > If the distance is too big we are in trouble - as our relocation
> > > distance can surely be clipped, or still have a valid width - but
> > > cause an overflow of distance.
> > > 
> > > On various architectures the maximum displacement for a unconditional
> > > branch/jump varies. ARM32 is +/- 32MB, ARM64 is +/- 128MB while x86
> > > for 32-bit relocations is +/- 2G.
> > > 
> > > Note: On x86 we could use the 64-bit jmpq instruction which
> > > would provide much bigger displacement to do a jump, but we would
> > > still have issues with the new function not being able to reach
> > > any of the old functions (as all the relocations would assume 32-bit
> > > displacement). And "furthermore would require an register or
> > > memory location to load/store the address to." (From Jan).
> > > 
> > > On ARM the conditional branch supports even a smaller displacement
> > > but fortunately we are not using that.
> > 
> > Wouldn't this be simpler as a BUILD_BUG_ON() in arch_livepatch_init()?
> > 
> > Something like BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) -
> > XEN_VIRT_START) > ARCH_LIVEPATCH_RANGE)?
> > 
> > And BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) - XEN_VIRT_START) >
> > ARCH_LIVEPATCH_RANGE)
> > 
> > And something similar for ARM...
> 
> What does that have to with the payload? The displacement calculations(checks)
> are done when we load the payload.

Ooh, you are thinking of just making sure that the displacement in virtual
addresses _should_ be OK.

And that BUILD_BUG_ON would certainly do it.

But my thinking was more of the payload either having some wacky relocations (say
having an initial addendum that along with the XEN_VIRT_START -> XEN_VIRT_END)
causes us to be way past the right place (especially with ARM32 where we only
have 32MB distance). And having this extra check makes me sleep better at night.

Adding the BUILD_BUG_ON as a futher check is fine, but as a different patch.

> > 
> > -- 
> > Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x]
  2016-09-23 14:44   ` Ross Lagerwall
@ 2016-09-23 16:13     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 16:13 UTC (permalink / raw)
  To: Ross Lagerwall
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

> > +bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
> > +                              const struct livepatch_elf_sym *sym)
> > +{
> > +    /*
> > +     * - Mapping symbols - denote the "start of a sequence of bytes of the
> > +     *   appropriate type" to mark certain features - such as start of region
> > +     *   containing data ($d); ARM ($a), or A64 ($x) instructions.
> > +     *   We ignore Thumb instructions ($t) as we shouldn't have them.
> > +     *
> > +     * The format is either short: '$x' or long: '$x.<any>'. We do not
> > +     * need this and more importantly - each payload will contain this
> > +     * resulting in symbol collisions.
> > +     */
> > +    if ( *sym->name == '$' && sym->name[1] != '\0' )
> 
> This would be clear (IMO) as sym->name[0].
> 
> Either way,
> 
> Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

Updated it to be:

From e6cafccb4a869e3e649c2295c5003435299fb7df Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Fri, 12 Aug 2016 23:08:32 -0400
Subject: [PATCH v6] livepatch: ARM 32|64: Ignore mapping symbols: $[d,a,x]

Those symbols are used to help final linkers to replace insn.
The ARM ELF specification mandates that they are present
to denote the start of certain CPU features. There are two
variants of it - short and long format.

Either way - we can ignore these symbols.

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Acked-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com> [x86 bits]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v1: First submission
v2: Update the order of symbols, fix title
    Add {} in after the first if - per Jan's recommendation.
v3: Add Andrew's Review tag
    Make the function return an bool_t.
    Skip check for '$t'
    Fix spelling of comments.
    s/arch_is_payload_symbol/arch_livepatch_symbol_ok/
v4: s/bool_t/bool/
v5: Removed an extra space in the conditional.
v6: Added Julien's Acked-by.
    s/*sym-name/sym-name[0]/ on the NULL check.
    Added Julien's Reviewed-by
---
 xen/arch/arm/livepatch.c    | 33 +++++++++++++++++++++++++++++++++
 xen/arch/x86/livepatch.c    |  7 +++++++
 xen/common/livepatch.c      |  2 +-
 xen/include/xen/livepatch.h |  2 ++
 4 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index 679abf1..f467d9d 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -84,6 +84,39 @@ void arch_livepatch_unmask(void)
     local_abort_enable();
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /*
+     * - Mapping symbols - denote the "start of a sequence of bytes of the
+     *   appropriate type" to mark certain features - such as start of region
+     *   containing data ($d); ARM ($a), or A64 ($x) instructions.
+     *   We ignore Thumb instructions ($t) as we shouldn't have them.
+     *
+     * The format is either short: '$x' or long: '$x.<any>'. We do not
+     * need this and more importantly - each payload will contain this
+     * resulting in symbol collisions.
+     */
+    if ( sym->name[0] == '$' && sym->name[1] != '\0' )
+    {
+        char p = sym->name[1];
+        size_t len = strlen(sym->name);
+
+        if ( (len >= 3 && (sym->name[2] == '.' )) || (len == 2) )
+        {
+            if ( p == 'd' ||
+#ifdef CONFIG_ARM_32
+                 p == 'a'
+#else
+                 p == 'x'
+#endif
+               )
+                return false;
+        }
+    }
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index b0d81d7..7a369a0 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -124,6 +124,13 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return 0;
 }
 
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return true;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/common/livepatch.c b/xen/common/livepatch.c
index 2d08c9a..fc8ef99 100644
--- a/xen/common/livepatch.c
+++ b/xen/common/livepatch.c
@@ -747,7 +747,7 @@ static bool_t is_payload_symbol(const struct livepatch_elf *elf,
          !strncmp(sym->name, ".L", 2) )
         return 0;
 
-    return 1;
+    return arch_livepatch_symbol_ok(elf, sym);
 }
 
 static int build_symbol_table(struct payload *payload,
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index b7b84e7..e8c67d6 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -48,6 +48,8 @@ bool_t is_patch(const void *addr);
 
 /* Arch hooks. */
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
+bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
+                              const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-23 14:49   ` Ross Lagerwall
@ 2016-09-23 16:15     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 16:15 UTC (permalink / raw)
  To: Ross Lagerwall
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

> >  int arch_livepatch_perform_rel(struct livepatch_elf *elf,
> >                                 const struct livepatch_elf_sec *base,
> >                                 const struct livepatch_elf_sec *rela)
> > diff --git a/xen/common/livepatch_elf.c b/xen/common/livepatch_elf.c
> > index f46990e..ec74beb 100644
> > --- a/xen/common/livepatch_elf.c
> > +++ b/xen/common/livepatch_elf.c
> > @@ -251,6 +251,13 @@ static int elf_get_sym(struct livepatch_elf *elf, const void *data)
> > 
> >          sym[i].sym = s;
> >          sym[i].name = strtab_sec->data + delta;
> > +        /* e.g. On ARM we should NEVER see $t* symbols. */
> 
> I'd prefer this comment in ARM's arch_livepatch_symbol_deny.

I removed the comment from common code. With the latest patch each architecture
has its own implementation of arch_livepatch_symbol_deny.

> 
> Either way,
> Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

Thanks.

Here is how the updated patch looks like:

From b84b478c4214f97e809f659fe348493c48a51d0c Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Tue, 13 Sep 2016 13:15:07 -0400
Subject: [PATCH v6] livepatch/arm/x86: Check payload for for unwelcomed
 symbols.

Certain platforms, such as ARM [32|64] add extra mapping symbols
such as $x (for ARM64 instructions), or more interesting to
this patch: $t (for Thumb instructions). These symbols are supposed
to help the final linker to make any adjustments (such as
add an veneer). But more importantly - we do not compile Xen
with any Thumb instructions (which are variable length) - and
if we find these mapping symbols we should disallow such payload.

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Reviewed-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Ross Lagerwall <ross.lagerwall@citrix.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>
Cc: Julien Grall <julien.grall@arm.com
Cc: Jan Beulich <jbeulich@suse.com>
Cc: Andrew Cooper <andrew.cooper3@citrix.com>

v3: New submission.
    Use &sym[i] instead of sym (as that will always be NULL).
v4: Use bool instead of int for return
    Update comment in common code about ARM odd symbols.
    s/_check/_deny/ to make it more clear.
v5: Also check for $t.* wildcard.
    Use Julien's variant where we roll the [2] check in the return.
v6: s/suppose/supposed/ in commit description.
    Move arch_livepatch_symbol_deny in arm[32|64]/livepatch.c
    Added Julien's Reviewed-by.
    Added Ross's Reviewed-by.
    Removed comment from common code talking about $t symbol.
---
 xen/arch/arm/arm32/livepatch.c | 13 +++++++++++++
 xen/arch/arm/arm64/livepatch.c |  7 +++++++
 xen/arch/x86/livepatch.c       |  7 +++++++
 xen/common/livepatch_elf.c     |  6 ++++++
 xen/include/xen/livepatch.h    |  2 ++
 5 files changed, 35 insertions(+)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 80f9646..5fc2e63 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -20,6 +20,19 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return -EOPNOTSUPP;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /*
+     * Xen does not use Thumb instructions - and we should not see any of
+     * them. If we do, abort.
+     */
+    if ( sym->name && sym->name[0] == '$' && sym->name[1] == 't' )
+        return ( !sym->name[2] || sym->name[2] == '.' );
+
+    return false;
+}
+
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 774f845..f148927 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -90,6 +90,13 @@ int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
     return 0;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on ARM 64. */
+    return false;
+}
+
 enum aarch64_reloc_op {
     RELOC_OP_NONE,
     RELOC_OP_ABS,
diff --git a/xen/arch/x86/livepatch.c b/xen/arch/x86/livepatch.c
index 7a369a0..9663ef6 100644
--- a/xen/arch/x86/livepatch.c
+++ b/xen/arch/x86/livepatch.c
@@ -131,6 +131,13 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
     return true;
 }
 
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym)
+{
+    /* No special checks on x86. */
+    return false;
+}
+
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela)
diff --git a/xen/common/livepatch_elf.c b/xen/common/livepatch_elf.c
index dec904a..c4a9633 100644
--- a/xen/common/livepatch_elf.c
+++ b/xen/common/livepatch_elf.c
@@ -251,6 +251,12 @@ static int elf_get_sym(struct livepatch_elf *elf, const void *data)
 
         sym[i].sym = s;
         sym[i].name = strtab_sec->data + delta;
+        if ( arch_livepatch_symbol_deny(elf, &sym[i]) )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Symbol '%s' should not be in payload!\n",
+                    elf->name, sym[i].name);
+            return -EINVAL;
+        }
     }
     elf->nsym = nsym;
 
diff --git a/xen/include/xen/livepatch.h b/xen/include/xen/livepatch.h
index e8c67d6..98ec012 100644
--- a/xen/include/xen/livepatch.h
+++ b/xen/include/xen/livepatch.h
@@ -50,6 +50,8 @@ bool_t is_patch(const void *addr);
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf);
 bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
                               const struct livepatch_elf_sym *sym);
+bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
+                                const struct livepatch_elf_sym *sym);
 int arch_livepatch_perform_rel(struct livepatch_elf *elf,
                                const struct livepatch_elf_sec *base,
                                const struct livepatch_elf_sec *rela);
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert
  2016-09-23 14:59   ` Ross Lagerwall
@ 2016-09-23 16:15     ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-23 16:15 UTC (permalink / raw)
  To: Ross Lagerwall; +Cc: julien.grall, sstabellini, xen-devel

> Same as previously, can this not be done with a simple memcpy?

Done!


From caaf99c75f28486737c21f1fc5f584b67e088f35 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Fri, 23 Sep 2016 11:25:12 -0400
Subject: [PATCH v6] livepatch, arm[32|64]: Share arch_livepatch_revert

It is exactly the same in both platforms.

No functional change.

Acked-by: Julien Grall <julien.grall@arm.com>
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v3: New submission.
v4: s/arch_livepatch_insn_len/livepatch_insn_len/
    s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
v5: Added Julien's Acked-by.
    Fixed comments.
  - Rebase on top "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
  - s/_jmp//
v6:
  - Rebase on top ARM64 and ARM32 implementations which now have
    clean_and_invalidate_dcache_va_range on new_ptr.
---
 xen/arch/arm/arm32/livepatch.c | 13 +------------
 xen/arch/arm/arm64/livepatch.c | 13 +------------
 xen/arch/arm/livepatch.c       | 13 +++++++++++++
 3 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index d9a8caa..a7fd5e2 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -75,18 +75,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
     clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
 }
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
-    uint32_t *new_ptr;
-    unsigned int len;
-
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
-
-    len = livepatch_insn_len(func);
-    memcpy(new_ptr, func->opaque, len);
-
-    clean_and_invalidate_dcache_va_range(new_ptr, len);
-}
+/* arch_livepatch_revert shared with ARM 32/ARM 64. */
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index 558acb9..dae64f5 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -62,18 +62,7 @@ void arch_livepatch_apply(struct livepatch_func *func)
     clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
 }
 
-void arch_livepatch_revert(const struct livepatch_func *func)
-{
-    uint32_t *new_ptr;
-    unsigned int len;
-
-    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
-
-    len = livepatch_insn_len(func);
-    memcpy(new_ptr, func->opaque, len);
-
-    clean_and_invalidate_dcache_va_range(new_ptr, len);
-}
+/* arch_livepatch_revert shared with ARM 32/ARM 64. */
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index dfa285c..de95e54 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -69,6 +69,19 @@ int arch_livepatch_verify_func(const struct livepatch_func *func)
     return 0;
 }
 
+void arch_livepatch_revert(const struct livepatch_func *func)
+{
+    uint32_t *new_ptr;
+    unsigned int len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+
+    len = livepatch_insn_len(func);
+    memcpy(new_ptr, func->opaque, len);
+
+    clean_and_invalidate_dcache_va_range(new_ptr, len);
+}
+
 void arch_livepatch_post_action(void)
 {
     /* arch_livepatch_revive has nuked the instruction cache. */
-- 
2.4.11

> 
> -- 
> Ross Lagerwall

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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols.
  2016-09-23  1:29     ` Konrad Rzeszutek Wilk
@ 2016-09-27  8:49       ` Ross Lagerwall
  0 siblings, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-27  8:49 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, Julien Grall, Jan Beulich, xen-devel

On 09/23/2016 02:29 AM, Konrad Rzeszutek Wilk wrote:
>>> +bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
>>> +                                const struct livepatch_elf_sym *sym)
>>> +{
>>> +#ifdef CONFIG_ARM_32
>>
>> Out of interest, is there any particular reason to use #ifdef rather than
>> adding the function in {arm32/arm64}/livepatch.c?
>
> I updated it be like that:
>
> From 5fc79e4fc3c0770ee4f6e7e0ed666e593deced65 Mon Sep 17 00:00:00 2001
> From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Date: Tue, 13 Sep 2016 13:15:07 -0400
> Subject: [PATCH v6] livepatch/arm/x86: Check payload for for unwelcomed
>  symbols.
>
> Certain platforms, such as ARM [32|64] add extra mapping symbols
> such as $x (for ARM64 instructions), or more interesting to
> this patch: $t (for Thumb instructions). These symbols are supposed
> to help the final linker to make any adjustments (such as
> add an veneer). But more importantly - we do not compile Xen
> with any Thumb instructions (which are variable length) - and
> if we find these mapping symbols we should disallow such payload.
>
> Reviewed-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH
  2016-09-21 17:32 ` [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH Konrad Rzeszutek Wilk
  2016-09-22 13:03   ` Julien Grall
@ 2016-09-27  9:49   ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-27  9:49 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
> To use as a common way of testing alternative patching for
> livepatches. Both architectures have this FEATURE and the
> test-cases can piggyback on that.
>
> Suggested-by: Julien Grall <julien.grall@arm.com>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64
  2016-09-23  1:33     ` Konrad Rzeszutek Wilk
  2016-09-23  9:50       ` Julien Grall
@ 2016-09-27  9:49       ` Ross Lagerwall
  1 sibling, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-27  9:49 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Wei Liu, George Dunlap, Andrew Cooper, Ian Jackson,
	Tim Deegan, Julien Grall, Jan Beulich, xen-devel

On 09/23/2016 02:33 AM, Konrad Rzeszutek Wilk wrote:
> .snip..
>>> diff --git a/xen/test/Makefile b/xen/test/Makefile
>>> index 8c53040..95c1755 100644
>>> --- a/xen/test/Makefile
>>> +++ b/xen/test/Makefile
>>> @@ -1,6 +1,6 @@
>>>  .PHONY: tests
>>>  tests:
>> I am wondering if there is any way to use the
>>> -ifeq ($(XEN_TARGET_ARCH),x86_64)
>>> +ifneq $(XEN_TARGET_ARCH),arm32)
>>
>> NIT: I am wondering if you could instead use CONFIG_LIVEPATCH here, so the
>> tests would only be built when livepatch is enabled.
>
> Lets leave it as is and do it in the future. Right now the tests
> are not compiled by default so not much harm here. But I do agree that
> somehow exposing the CONFIG_LIVEPATCH and latching it off (in say
> tests/livepatch/ directory) is a good TODO item..
>>
>>>  	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
>>>  endif
>>>
>>> diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
>>> index 48ff843..5db4d9c 100644
>>> --- a/xen/test/livepatch/Makefile
>>> +++ b/xen/test/livepatch/Makefile
>>> @@ -1,5 +1,12 @@
>>>  include $(XEN_ROOT)/Config.mk
>>>
>>> +ifeq ($(XEN_TARGET_ARCH),x86_64)
>>> +OBJCOPY_MAGIC := -I binary -O elf64-x86-64 -B i386:x86-64
>>> +endif
>>> +ifeq ($(XEN_TARGET_ARCH),arm64)
>>> +OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
>>> +endif
>>> +
>>>  CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
>>>  CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
>>>
>>> @@ -54,8 +61,9 @@ $(LIVEPATCH): xen_hello_world_func.o xen_hello_world.o note.o
>>>  .PHONY: note.o
>>>  note.o:
>>>  	$(OBJCOPY) -O binary --only-section=.note.gnu.build-id $(BASEDIR)/xen-syms $@.bin
>>> -	$(OBJCOPY) -I binary -O elf64-x86-64 -B i386:x86-64 \
>>> +	$(OBJCOPY) $(OBJCOPY_MAGIC) \
>>>  		   --rename-section=.data=.livepatch.depends,alloc,load,readonly,data,contents -S $@.bin $@
>>> +		   --rename-section=.data=.livepatch.depends -S $@.bin $@
>>
>> I am not sure why you added this line. Did you intend to replace the
>> previous one?
>
> Fixed.
> ..snip..
>>> @@ -25,6 +28,10 @@ const char *xen_hello_world(void)
>>>       */
>>>      rc = __get_user(tmp, non_canonical_addr);
>>>      BUG_ON(rc != -EFAULT);
>>> +#endif
>>> +#ifdef CONFIG_ARM_64
>>
>> NIT: I would use:
>>
>> #if defined(CONFIG_ARM) && defined(CONFIG_HAS_ALTERNATIVE)
>>
>> in order to handle alternative if we decide to add support for ARM32.
>
> Done!
>
> Here is the updated patch:
>
>
> From c0dac442d15b5f0095b199ab4fff1fc414fb5719 Mon Sep 17 00:00:00 2001
> From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Date: Mon, 19 Sep 2016 16:04:55 -0400
> Subject: [PATCH v6] livepatch: tests: Make them compile under ARM64
>
> We need to two things:
> 1) Wrap the platform-specific objcopy parameters in defines
>    The input and output parameters for $(OBJCOPY) are different
>    based on the platforms. As such provide them in the
>    OBJCOPY_MAGIC define and use that.
>
> 2) The alternative is a bit different (exists only under ARM64
>    and x86), while and there are no exceptions under ARM at all.
>    We use the LIVEPATCH_FEATURE CPU id feature for ARM similar to
>    how it is done on x86.
>
> We are not yet attempting to build them under ARM32 so
> that is still ifdefed out.
>
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
>

Reviewed-by: Ross Lagerwall <ross.lagerwall@citrix.com>

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 14/16] livepatch: Initial ARM32 support.
  2016-09-21 17:32 ` [PATCH v5 14/16] livepatch: Initial ARM32 support Konrad Rzeszutek Wilk
@ 2016-09-27 16:39   ` Julien Grall
  2016-09-27 17:50     ` Konrad Rzeszutek Wilk
  0 siblings, 1 reply; 57+ messages in thread
From: Julien Grall @ 2016-09-27 16:39 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, konrad, xen-devel, ross.lagerwall, sstabellini

Hi Konrad,

On 21/09/2016 10:32, Konrad Rzeszutek Wilk wrote:
> The patch piggybacks on: livepatch: Initial ARM64 support, which
> brings up all of the necessary livepatch infrastructure pieces in.
>
> This patch adds three major pieces:
>
>  1) ELF relocations. ARM32 uses SHT_REL instead of SHT_RELA which
>     means the adddendum had to be extracted from within the
>     instruction. Which required parsing BL/BLX, B/BL<cond>,
>     MOVT, and MOVW instructions.
>
>     The code was written from scratch using the ARM ELF manual
>     (and the ARM Architecture Reference Manual)
>
>  2) Inserting an trampoline. We use the B (branch to address)
>     which uses an offset that is based on the PC value: PC + imm32.
>     Because we insert the branch at the start of the old function
>     we have to account for the instruction already being fetched
>     and subtract -8 from the delta (new_addr - old_addr). See
>     ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
>
>  3) Allows the test-cases to be built under ARM 32.
>     The "livepatch: tests: Make them compile under ARM64"
>     put in the right infrastructure for it and we piggyback on it.
>
> Acked-by: Julien Grall <julien.grall@arm.com>
> Acked-by: Jan Beulich <jbeulich@suse.com> [for non-ARM parts]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> ---
> Cc: Julien Grall <julien.grall@arm.com>
> Cc: Stefano Stabellini <sstabellini@kernel.org>
>
> v2: First submission.
> v3: Use LIVEPATCH_ARCH_RANGE instead of NEGATIVE_32MB macro
>    -Use PATCH_INSN_SIZE instead of the value 4.
>    -Ditch the old_ptr local variable.
>    -Use 8 for evaluating the branch instead of 4. Based on ARM docs.
>    -NOP patch up to sizeof(opaque) % PATCH_INSN_SIZE (so 7 instructions).
>    -Don't mask 0x00FFFFF_E_ after shifting, instead mask by 0x00FFFFF_F_.
>     The reason is that offset is constructed by shifting by two the insn
>     (except the first two bytes) by left which meant we would have cleared
>     offset[2]! - and jumped to a location that was -4 bytes off.
>    -Update commit description to have -8 instead of -4 delta and also
>     include reference to spec.
> v4: Added Jan's Ack.
>    s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
>    s/arch_livepatch_insn_len/livepatch_insn_len/
>    s/LIVEPATCH_ARCH_RANGE/ARCH_LIVEPATCH_RANGE/
> v5: Added Julien's Ack.

IHMO my ack should not have been retained given that ...

>    - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
>    - Added explanation for the usage of data cache and why we need to sync it.

... you also replace the clean_and_invalidate to the old_ptr by 
clean_and_invalidate to the new_ptr.

> diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
> index 80f9646..3f47326 100644
> --- a/xen/arch/arm/arm32/livepatch.c
> +++ b/xen/arch/arm/arm32/livepatch.c
> @@ -3,28 +3,303 @@
>   */
>
>  #include <xen/errno.h>
> +#include <xen/kernel.h>
>  #include <xen/lib.h>
>  #include <xen/livepatch_elf.h>
>  #include <xen/livepatch.h>
>
> +#include <asm/page.h>
> +#include <asm/livepatch.h>
> +
>  void arch_livepatch_apply(struct livepatch_func *func)
>  {

[...]

> +    /*
> +    * When we upload the payload, it will go through the data cache
> +    * (the region is cacheable). Until the data cache is cleaned, the data
> +    * may not reach the memory. And in the case the data and instruction cache
> +    * are separated, we may read invalid instruction from the memory because
> +    * the data cache have not yet synced with the memory. Hence sync it.
> +    */
> +    if ( func->new_addr )
> +        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);

The clean_and_invalidate on the new_ptr needs to be add back here and ...

>  }
>
>  void arch_livepatch_revert(const struct livepatch_func *func)
>  {
> +    uint32_t *new_ptr;
> +    unsigned int i, len;
> +
> +    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
> +    len = livepatch_insn_len(func) / sizeof(uint32_t);
> +    for ( i = 0; i < len; i++ )
> +    {
> +        uint32_t insn;
> +
> +        memcpy(&insn, func->opaque + (i * sizeof(uint32_t)), ARCH_PATCH_INSN_SIZE);
> +        /* PATCH! */
> +        *(new_ptr + i) = insn;
> +    }

here. See the comments on the ARM64 part (i.e patch #5).

>  }

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/16] livepatch: Initial ARM64 support.
  2016-09-23 15:44     ` Konrad Rzeszutek Wilk
@ 2016-09-27 16:42       ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-27 16:42 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk, Ross Lagerwall
  Cc: sstabellini, Andrew Cooper, xen-devel

Hi Konrad,

On 23/09/2016 08:44, Konrad Rzeszutek Wilk wrote:
> Here is the updated patch:
> From deef8f6921c15a4d07209bfba1fc8697dbfeb605 Mon Sep 17 00:00:00 2001
> From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Date: Mon, 19 Sep 2016 12:24:09 -0400
> Subject: [PATCH v6] livepatch: Initial ARM64 support.
>
> As compared to x86 the va of the hypervisor .text
> is locked down - we cannot modify the running pagetables
> to have the .ro flag unset. We borrow the same idea that
> alternative patching has - which is to vmap the entire
> .text region and use the alternative virtual address
> for patching.
>
> Since we are doing vmap we may fail, hence the
> arch_livepatch_quiesce was changed (see "x86,arm:
> Change arch_livepatch_quiesce() declaration") to return
> an error value which will be bubbled in payload->rc and
> provided to the user (along with messages in the ring buffer).
>
> The livepatch virtual address space (where the new functions
> are) needs to be close to the hypervisor virtual address
> so that the trampoline can reach it. As such we re-use
> the BOOT_RELOC_VIRT_START which is not used after bootup
> (alternatively we can also use the space after the _end to
> FIXMAP_ADDR(0), but that may be too small).
>
> The ELF relocation engine at the start was coded from
> the "ELF for the ARM 64-bit Architecture (AArch64)"
> (http://infocenter.arm.com/help/topic/com.arm.doc.ihi0056b/IHI0056B_aaelf64.pdf)
> but after a while of trying to write the correct bit shifting
> and masking from scratch I ended up borrowing from Linux, the
> 'reloc_insn_imm' (Linux v4.7 arch/arm64/kernel/module.c function.
> See 257cb251925f854da435cbf79b140984413871ac "arm64: Loadable modules")
>
> And while at it - we also utilize code from Linux to construct
> the right branch instruction (see "arm64/insn: introduce
> aarch64_insn_gen_{nop|branch_imm}() helper functions").
>
> In the livepatch payload loading code we tweak the #ifdef to
> only exclude ARM_32. The exceptions are not part of ARM 32/64 hence
> they are still behind the #ifdef.
>
> We also expand the MAINTAINERS file to include the arm64 and arm32
> platform specific livepatch file.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [non-arm parts]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

You can add my acked-by on this version:

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 14/16] livepatch: Initial ARM32 support.
  2016-09-27 16:39   ` Julien Grall
@ 2016-09-27 17:50     ` Konrad Rzeszutek Wilk
  2016-09-27 23:13       ` Julien Grall
  0 siblings, 1 reply; 57+ messages in thread
From: Konrad Rzeszutek Wilk @ 2016-09-27 17:50 UTC (permalink / raw)
  To: Julien Grall; +Cc: ross.lagerwall, sstabellini, xen-devel

On Tue, Sep 27, 2016 at 09:39:06AM -0700, Julien Grall wrote:
> Hi Konrad,
> 
> On 21/09/2016 10:32, Konrad Rzeszutek Wilk wrote:
> > The patch piggybacks on: livepatch: Initial ARM64 support, which
> > brings up all of the necessary livepatch infrastructure pieces in.
> > 
> > This patch adds three major pieces:
> > 
> >  1) ELF relocations. ARM32 uses SHT_REL instead of SHT_RELA which
> >     means the adddendum had to be extracted from within the
> >     instruction. Which required parsing BL/BLX, B/BL<cond>,
> >     MOVT, and MOVW instructions.
> > 
> >     The code was written from scratch using the ARM ELF manual
> >     (and the ARM Architecture Reference Manual)
> > 
> >  2) Inserting an trampoline. We use the B (branch to address)
> >     which uses an offset that is based on the PC value: PC + imm32.
> >     Because we insert the branch at the start of the old function
> >     we have to account for the instruction already being fetched
> >     and subtract -8 from the delta (new_addr - old_addr). See
> >     ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
> > 
> >  3) Allows the test-cases to be built under ARM 32.
> >     The "livepatch: tests: Make them compile under ARM64"
> >     put in the right infrastructure for it and we piggyback on it.
> > 
> > Acked-by: Julien Grall <julien.grall@arm.com>
> > Acked-by: Jan Beulich <jbeulich@suse.com> [for non-ARM parts]
> > Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> > ---
> > Cc: Julien Grall <julien.grall@arm.com>
> > Cc: Stefano Stabellini <sstabellini@kernel.org>
> > 
> > v2: First submission.
> > v3: Use LIVEPATCH_ARCH_RANGE instead of NEGATIVE_32MB macro
> >    -Use PATCH_INSN_SIZE instead of the value 4.
> >    -Ditch the old_ptr local variable.
> >    -Use 8 for evaluating the branch instead of 4. Based on ARM docs.
> >    -NOP patch up to sizeof(opaque) % PATCH_INSN_SIZE (so 7 instructions).
> >    -Don't mask 0x00FFFFF_E_ after shifting, instead mask by 0x00FFFFF_F_.
> >     The reason is that offset is constructed by shifting by two the insn
> >     (except the first two bytes) by left which meant we would have cleared
> >     offset[2]! - and jumped to a location that was -4 bytes off.
> >    -Update commit description to have -8 instead of -4 delta and also
> >     include reference to spec.
> > v4: Added Jan's Ack.
> >    s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
> >    s/arch_livepatch_insn_len/livepatch_insn_len/
> >    s/LIVEPATCH_ARCH_RANGE/ARCH_LIVEPATCH_RANGE/
> > v5: Added Julien's Ack.
> 
> IHMO my ack should not have been retained given that ...

Ooops!
> 
> >    - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
> >    - Added explanation for the usage of data cache and why we need to sync it.
> 
> ... you also replace the clean_and_invalidate to the old_ptr by
> clean_and_invalidate to the new_ptr.

Ah yes! I had it in my patch queue but neglected to email it out.

Here is what I have in the git branch:

From 8bf07ac18e2cfcf304860aa00ab157e1e7f77ed9 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Date: Thu, 22 Sep 2016 20:15:09 -0400
Subject: [PATCH] livepatch: Initial ARM32 support.

The patch piggybacks on: livepatch: Initial ARM64 support, which
brings up all of the necessary livepatch infrastructure pieces in.

This patch adds three major pieces:

 1) ELF relocations. ARM32 uses SHT_REL instead of SHT_RELA which
    means the adddendum had to be extracted from within the
    instruction. Which required parsing BL/BLX, B/BL<cond>,
    MOVT, and MOVW instructions.

    The code was written from scratch using the ARM ELF manual
    (and the ARM Architecture Reference Manual)

 2) Inserting an trampoline. We use the B (branch to address)
    which uses an offset that is based on the PC value: PC + imm32.
    Because we insert the branch at the start of the old function
    we have to account for the instruction already being fetched
    and subtract -8 from the delta (new_addr - old_addr). See
    ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)

 3) Allows the test-cases to be built under ARM 32.
    The "livepatch: tests: Make them compile under ARM64"
    put in the right infrastructure for it and we piggyback on it.

Acked-by: Jan Beulich <jbeulich@suse.com> [for non-ARM parts]
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
---
Cc: Julien Grall <julien.grall@arm.com>
Cc: Stefano Stabellini <sstabellini@kernel.org>

v2: First submission.
v3: Use LIVEPATCH_ARCH_RANGE instead of NEGATIVE_32MB macro
   -Use PATCH_INSN_SIZE instead of the value 4.
   -Ditch the old_ptr local variable.
   -Use 8 for evaluating the branch instead of 4. Based on ARM docs.
   -NOP patch up to sizeof(opaque) % PATCH_INSN_SIZE (so 7 instructions).
   -Don't mask 0x00FFFFF_E_ after shifting, instead mask by 0x00FFFFF_F_.
    The reason is that offset is constructed by shifting by two the insn
    (except the first two bytes) by left which meant we would have cleared
    offset[2]! - and jumped to a location that was -4 bytes off.
   -Update commit description to have -8 instead of -4 delta and also
    include reference to spec.
v4: Added Jan's Ack.
   s/PATCH_INSN_SIZE/ARCH_PATCH_INSN_SIZE/
   s/arch_livepatch_insn_len/livepatch_insn_len/
   s/LIVEPATCH_ARCH_RANGE/ARCH_LIVEPATCH_RANGE/
v5: Added Julien's Ack.
  - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
  - Added explanation for the usage of data cache and why we need to sync it.
  - Put clean_and_invalidate_dcache_va_range on new_ptr back in.
  - Rebased on top "livepatch/arm/x86: Check payload for for unwelcomed symbols"
  - Simplified the 'arch_livepatch_revert' to be memcpy instead of a loop.
  - Removed Julien's Ack.

---
 xen/arch/arm/arm32/livepatch.c | 276 ++++++++++++++++++++++++++++++++++++++++-
 xen/arch/arm/arm64/livepatch.c |   7 ++
 xen/arch/arm/livepatch.c       |   7 --
 xen/common/Kconfig             |   2 +-
 xen/include/xen/elfstructs.h   |  24 +++-
 xen/test/Makefile              |   2 -
 xen/test/livepatch/Makefile    |   3 +
 7 files changed, 308 insertions(+), 13 deletions(-)

diff --git a/xen/arch/arm/arm32/livepatch.c b/xen/arch/arm/arm32/livepatch.c
index 5fc2e63..d9a8caa 100644
--- a/xen/arch/arm/arm32/livepatch.c
+++ b/xen/arch/arm/arm32/livepatch.c
@@ -3,21 +3,111 @@
  */
 
 #include <xen/errno.h>
+#include <xen/kernel.h>
 #include <xen/lib.h>
 #include <xen/livepatch_elf.h>
 #include <xen/livepatch.h>
 
+#include <asm/page.h>
+#include <asm/livepatch.h>
+
 void arch_livepatch_apply(struct livepatch_func *func)
 {
+    uint32_t insn;
+    uint32_t *new_ptr;
+    unsigned int i, len;
+
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE > sizeof(func->opaque));
+    BUILD_BUG_ON(ARCH_PATCH_INSN_SIZE != sizeof(insn));
+
+    ASSERT(vmap_of_xen_text);
+
+    len = livepatch_insn_len(func);
+    if ( !len )
+        return;
+
+    /* Save old ones. */
+    memcpy(func->opaque, func->old_addr, len);
+
+    if ( func->new_addr )
+    {
+        s32 delta;
+
+        /*
+         * PC is current address (old_addr) + 8 bytes. The semantics for a
+         * unconditional branch is to jump to PC + imm32 (offset).
+         *
+         * ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
+         *
+         */
+        delta = (s32)func->new_addr - (s32)(func->old_addr + 8);
+
+        /* The arch_livepatch_symbol_ok should have caught it. */
+        ASSERT(delta >= -(s32)ARCH_LIVEPATCH_RANGE ||
+               delta < (s32)ARCH_LIVEPATCH_RANGE);
+
+        /* CPU shifts by two (left) when decoding, so we shift right by two. */
+        delta = delta >> 2;
+        /* Lets not modify the cond. */
+        delta &= 0x00FFFFFF;
+
+        insn = 0xea000000 | delta;
+    }
+    else
+        insn = 0xe1a00000; /* mov r0, r0 */
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+    len = len / sizeof(uint32_t);
+
+    /* PATCH! */
+    for ( i = 0; i < len; i++ )
+        *(new_ptr + i) = insn;
+
+    /*
+    * When we upload the payload, it will go through the data cache
+    * (the region is cacheable). Until the data cache is cleaned, the data
+    * may not reach the memory. And in the case the data and instruction cache
+    * are separated, we may read invalid instruction from the memory because
+    * the data cache have not yet synced with the memory. Hence sync it.
+    */
+    if ( func->new_addr )
+        clean_and_invalidate_dcache_va_range(func->new_addr, func->new_size);
+    clean_and_invalidate_dcache_va_range(new_ptr, sizeof (*new_ptr) * len);
 }
 
 void arch_livepatch_revert(const struct livepatch_func *func)
 {
+    uint32_t *new_ptr;
+    unsigned int len;
+
+    new_ptr = func->old_addr - (void *)_start + vmap_of_xen_text;
+
+    len = livepatch_insn_len(func);
+    memcpy(new_ptr, func->opaque, len);
+
+    clean_and_invalidate_dcache_va_range(new_ptr, len);
 }
 
 int arch_livepatch_verify_elf(const struct livepatch_elf *elf)
 {
-    return -EOPNOTSUPP;
+    const Elf_Ehdr *hdr = elf->hdr;
+
+    if ( hdr->e_machine != EM_ARM ||
+         hdr->e_ident[EI_CLASS] != ELFCLASS32 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF Machine type!\n",
+                elf->name);
+        return -EOPNOTSUPP;
+    }
+
+    if ( (hdr->e_flags & EF_ARM_EABI_MASK) != EF_ARM_EABI_VER5 )
+    {
+        dprintk(XENLOG_ERR, LIVEPATCH "%s: Unsupported ELF EABI(%x)!\n",
+                elf->name, hdr->e_flags);
+        return -EOPNOTSUPP;
+    }
+
+    return 0;
 }
 
 bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
@@ -33,11 +123,193 @@ bool arch_livepatch_symbol_deny(const struct livepatch_elf *elf,
     return false;
 }
 
+static s32 get_addend(unsigned char type, void *dest)
+{
+    s32 addend = 0;
+
+    switch ( type ) {
+    case R_ARM_NONE:
+        /* ignore */
+        break;
+
+    case R_ARM_ABS32:
+        addend = *(u32 *)dest;
+        break;
+
+    case R_ARM_REL32:
+        addend = *(u32 *)dest;
+        break;
+
+    case R_ARM_MOVW_ABS_NC:
+    case R_ARM_MOVT_ABS:
+        addend =  (*(u32 *)dest & 0x00000FFF);
+        addend |= (*(u32 *)dest & 0x000F0000) >> 4;
+        /* Addend is to sign-extend ([19:16],[11:0]). */
+        addend = (s16)addend;
+        break;
+
+    case R_ARM_CALL:
+    case R_ARM_JUMP24:
+        /* Addend = sign_extend (insn[23:0]) << 2 */
+        addend = ((*(u32 *)dest & 0xFFFFFF) ^ 0x800000) - 0x800000;
+        addend = addend << 2;
+        break;
+    }
+
+    return addend;
+}
+
+static int perform_rel(unsigned char type, void *dest, uint32_t val, s32 addend)
+{
+
+    switch ( type ) {
+    case R_ARM_NONE:
+        /* ignore */
+        break;
+
+    case R_ARM_ABS32: /* (S + A) | T */
+        *(u32 *)dest = (val + addend);
+        break;
+
+    case R_ARM_REL32: /* ((S + A) | T) – P */
+        *(u32 *)dest = (val + addend) - (uint32_t)dest;
+        break;
+
+    case R_ARM_MOVW_ABS_NC: /* S + A */
+    case R_ARM_MOVT_ABS: /* S + A */
+        /* Clear addend if needed . */
+        if ( addend )
+            *(u32 *)dest &= 0xFFF0F000;
+
+        if ( type == R_ARM_MOVT_ABS )
+        {
+            /*
+             * Almost the same as MOVW except it uses the 16 bit
+             * high value. Putting it in insn requires shifting right by
+             * 16-bit (as we only have 16-bit for imm.
+             */
+            val &= 0xFFFF0000; /* ResultMask */
+            val = val >> 16;
+        }
+        else
+        {
+            /* MOVW loads 16 bits into the bottom half of a register. */
+            val &= 0xFFFF;
+        }
+        /* [11:0] = Result_Mask(X) & 0xFFF,[19:16] = Result_Mask(X) >> 12 */
+        *(u32 *)dest |= val & 0xFFF;
+        *(u32 *)dest |= (val >> 12) << 16;
+        break;
+
+    case R_ARM_CALL:
+    case R_ARM_JUMP24: /* (S + A) - P */
+        /* Clear the old addend. */
+        if ( addend )
+            *(u32 *)dest &= 0xFF000000;
+
+        val += addend - (uint32_t)dest;
+
+        /*
+         * arch_livepatch_verify_distance can't account of addend so we have
+         * to do the check here as well.
+         */
+        if ( (s32)val < -(s32)ARCH_LIVEPATCH_RANGE ||
+             (s32)val >= (s32)ARCH_LIVEPATCH_RANGE )
+            return -EOVERFLOW;
+
+        /* CPU always shifts insn by two, so complement it. */
+        val = val >> 2;
+        val &= 0x00FFFFFE;
+        *(u32 *)dest |= (uint32_t)val;
+        break;
+
+    default:
+         return -EOPNOTSUPP;
+    }
+
+    return 0;
+}
+
+int arch_livepatch_perform(struct livepatch_elf *elf,
+                           const struct livepatch_elf_sec *base,
+                           const struct livepatch_elf_sec *rela,
+                           bool use_rela)
+{
+    const Elf_RelA *r_a;
+    const Elf_Rel *r;
+    unsigned int symndx, i;
+    uint32_t val;
+    void *dest;
+    int rc = 0;
+
+    for ( i = 0; i < (rela->sec->sh_size / rela->sec->sh_entsize); i++ )
+    {
+        unsigned char type;
+        s32 addend = 0;
+
+        if ( use_rela )
+        {
+            r_a = rela->data + i * rela->sec->sh_entsize;
+            symndx = ELF32_R_SYM(r_a->r_info);
+            type = ELF32_R_TYPE(r_a->r_info);
+            dest = base->load_addr + r_a->r_offset; /* P */
+            addend = r_a->r_addend;
+        }
+        else
+        {
+            r = rela->data + i * rela->sec->sh_entsize;
+            symndx = ELF32_R_SYM(r->r_info);
+            type = ELF32_R_TYPE(r->r_info);
+            dest = base->load_addr + r->r_offset; /* P */
+        }
+
+        if ( symndx > elf->nsym )
+        {
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Relative symbol wants symbol@%u which is past end!\n",
+                    elf->name, symndx);
+            return -EINVAL;
+        }
+
+        if ( !use_rela )
+            addend = get_addend(type, dest);
+
+        val = elf->sym[symndx].sym->st_value; /* S */
+
+        rc = perform_rel(type, dest, val, addend);
+        switch ( rc ) {
+        case -EOVERFLOW:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Overflow in relocation %u in %s for %s!\n",
+                    elf->name, i, rela->name, base->name);
+            break;
+
+        case -EOPNOTSUPP:
+            dprintk(XENLOG_ERR, LIVEPATCH "%s: Unhandled relocation #%x\n",
+                    elf->name, type);
+            break;
+
+        default:
+            break;
+        }
+
+        if ( rc )
+            break;
+    }
+
+    return rc;
+}
+
+int arch_livepatch_perform_rel(struct livepatch_elf *elf,
+                               const struct livepatch_elf_sec *base,
+                               const struct livepatch_elf_sec *rela)
+{
+    return arch_livepatch_perform(elf, base, rela, false);
+}
+
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
 {
-    return -ENOSYS;
+    return arch_livepatch_perform(elf, base, rela, true);
 }
 
 /*
diff --git a/xen/arch/arm/arm64/livepatch.c b/xen/arch/arm/arm64/livepatch.c
index f148927..558acb9 100644
--- a/xen/arch/arm/arm64/livepatch.c
+++ b/xen/arch/arm/arm64/livepatch.c
@@ -241,6 +241,13 @@ static int reloc_insn_imm(enum aarch64_reloc_op op, void *dest, u64 val,
     return 0;
 }
 
+int arch_livepatch_perform_rel(struct livepatch_elf *elf,
+                               const struct livepatch_elf_sec *base,
+                               const struct livepatch_elf_sec *rela)
+{
+    return -ENOSYS;
+}
+
 int arch_livepatch_perform_rela(struct livepatch_elf *elf,
                                 const struct livepatch_elf_sec *base,
                                 const struct livepatch_elf_sec *rela)
diff --git a/xen/arch/arm/livepatch.c b/xen/arch/arm/livepatch.c
index b8dbee2..dfa285c 100644
--- a/xen/arch/arm/livepatch.c
+++ b/xen/arch/arm/livepatch.c
@@ -118,13 +118,6 @@ bool arch_livepatch_symbol_ok(const struct livepatch_elf *elf,
     return true;
 }
 
-int arch_livepatch_perform_rel(struct livepatch_elf *elf,
-                               const struct livepatch_elf_sec *base,
-                               const struct livepatch_elf_sec *rela)
-{
-    return -ENOSYS;
-}
-
 int arch_livepatch_secure(const void *va, unsigned int pages, enum va_type type)
 {
     unsigned long start = (unsigned long)va;
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 0f26027..d4f10ca 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -217,7 +217,7 @@ config CRYPTO
 config LIVEPATCH
 	bool "Live patching support (TECH PREVIEW)"
 	default n
-	depends on !ARM_32 && HAS_BUILD_ID = "y"
+	depends on HAS_BUILD_ID = "y"
 	---help---
 	  Allows a running Xen hypervisor to be dynamically patched using
 	  binary patches without rebooting. This is primarily used to binarily
diff --git a/xen/include/xen/elfstructs.h b/xen/include/xen/elfstructs.h
index 7329987..e543212 100644
--- a/xen/include/xen/elfstructs.h
+++ b/xen/include/xen/elfstructs.h
@@ -103,6 +103,15 @@ typedef uint64_t	Elf64_Xword;
                       (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \
                       (ehdr).e_ident[EI_MAG3] == ELFMAG3)
 
+/* e_flags */
+#define EF_ARM_EABI_MASK	0xff000000
+#define EF_ARM_EABI_UNKNOWN	0x00000000
+#define EF_ARM_EABI_VER1	0x01000000
+#define EF_ARM_EABI_VER2	0x02000000
+#define EF_ARM_EABI_VER3	0x03000000
+#define EF_ARM_EABI_VER4	0x04000000
+#define EF_ARM_EABI_VER5	0x05000000
+
 /* ELF Header */
 typedef struct elfhdr {
 	unsigned char	e_ident[EI_NIDENT]; /* ELF Identification */
@@ -364,9 +373,22 @@ typedef struct {
 #define R_X86_64_PLT32		4	/* 32 bit PLT address */
 
 /*
+ * ARM32 relocation types. See
+ * http://infocenter.arm.com/help/topic/com.arm.doc.ihi0044f/IHI0044F_aaelf.pdf
  * S - address of symbol.
- * A - addend for relocation (r_addend)
+ * A - addend for relocation (r_addend or need to extract from insn)
  * P - address of the dest being relocated (derieved from r_offset)
+ */
+#define R_ARM_NONE              0
+#define R_ARM_ABS32             2	/* Direct 32-bit. S+A */
+#define R_ARM_REL32             3	/* PC relative. S+A */
+#define R_ARM_CALL              28	/* SignExtend([23:0]) << 2. S+A-P */
+#define R_ARM_JUMP24            29	/* Same as R_ARM_CALL */
+#define R_ARM_MOVW_ABS_NC       43	/* SignExtend([19:16],[11:0])&0xFFFF, S+A */
+#define R_ARM_MOVT_ABS          44	/* SignExtend([19:16],[11:0))&0xFFFF0000 */
+					/*  >> 16, S+A. */
+
+/*
  * NC -  No check for overflow.
  *
  * The defines also use _PREL for PC-relative address, and _NC is No Check.
diff --git a/xen/test/Makefile b/xen/test/Makefile
index 95c1755..d91b319 100644
--- a/xen/test/Makefile
+++ b/xen/test/Makefile
@@ -1,8 +1,6 @@
 .PHONY: tests
 tests:
-ifneq $(XEN_TARGET_ARCH),arm32)
 	$(MAKE) -f $(BASEDIR)/Rules.mk -C livepatch livepatch
-endif
 
 .PHONY: clean
 clean::
diff --git a/xen/test/livepatch/Makefile b/xen/test/livepatch/Makefile
index d844ad4..9439f62 100644
--- a/xen/test/livepatch/Makefile
+++ b/xen/test/livepatch/Makefile
@@ -6,6 +6,9 @@ endif
 ifeq ($(XEN_TARGET_ARCH),arm64)
 OBJCOPY_MAGIC := -I binary -O elf64-littleaarch64 -B aarch64
 endif
+ifeq ($(XEN_TARGET_ARCH),arm32)
+OBJCOPY_MAGIC := -I binary -O elf32-littlearm -B arm
+endif
 
 CODE_ADDR=$(shell nm --defined $(1) | grep $(2) | awk '{print "0x"$$1}')
 CODE_SZ=$(shell nm --defined -S $(1) | grep $(2) | awk '{ print "0x"$$2}')
-- 
2.4.11


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

^ permalink raw reply related	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 14/16] livepatch: Initial ARM32 support.
  2016-09-27 17:50     ` Konrad Rzeszutek Wilk
@ 2016-09-27 23:13       ` Julien Grall
  0 siblings, 0 replies; 57+ messages in thread
From: Julien Grall @ 2016-09-27 23:13 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk; +Cc: ross.lagerwall, sstabellini, xen-devel

Hi Konrad,

On 27/09/2016 10:50, Konrad Rzeszutek Wilk wrote:
> On Tue, Sep 27, 2016 at 09:39:06AM -0700, Julien Grall wrote:
>>
>>>    - Rebased on "livepatch: Drop _jmp from arch_livepatch_[apply,revert]_jmp"
>>>    - Added explanation for the usage of data cache and why we need to sync it.
>>
>> ... you also replace the clean_and_invalidate to the old_ptr by
>> clean_and_invalidate to the new_ptr.
>
> Ah yes! I had it in my patch queue but neglected to email it out.

Good, I wanted to make sure you replicate the change requested on ARM64 
to ARM32.

>
> Here is what I have in the git branch:
>
> From 8bf07ac18e2cfcf304860aa00ab157e1e7f77ed9 Mon Sep 17 00:00:00 2001
> From: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
> Date: Thu, 22 Sep 2016 20:15:09 -0400
> Subject: [PATCH] livepatch: Initial ARM32 support.
>
> The patch piggybacks on: livepatch: Initial ARM64 support, which
> brings up all of the necessary livepatch infrastructure pieces in.
>
> This patch adds three major pieces:
>
>  1) ELF relocations. ARM32 uses SHT_REL instead of SHT_RELA which
>     means the adddendum had to be extracted from within the
>     instruction. Which required parsing BL/BLX, B/BL<cond>,
>     MOVT, and MOVW instructions.
>
>     The code was written from scratch using the ARM ELF manual
>     (and the ARM Architecture Reference Manual)
>
>  2) Inserting an trampoline. We use the B (branch to address)
>     which uses an offset that is based on the PC value: PC + imm32.
>     Because we insert the branch at the start of the old function
>     we have to account for the instruction already being fetched
>     and subtract -8 from the delta (new_addr - old_addr). See
>     ARM DDI 0406C.c, see A2.3 (pg 45) and A8.8.18 pg (pg 334,335)
>
>  3) Allows the test-cases to be built under ARM 32.
>     The "livepatch: tests: Make them compile under ARM64"
>     put in the right infrastructure for it and we piggyback on it.
>
> Acked-by: Jan Beulich <jbeulich@suse.com> [for non-ARM parts]
> Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>

Acked-by: Julien Grall <julien.grall@arm.com>

Regards,

-- 
Julien Grall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr
  2016-09-23 15:59       ` Konrad Rzeszutek Wilk
@ 2016-09-28 10:21         ` Ross Lagerwall
  0 siblings, 0 replies; 57+ messages in thread
From: Ross Lagerwall @ 2016-09-28 10:21 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: sstabellini, Andrew Cooper, julien.grall, Jan Beulich, xen-devel

On 09/23/2016 04:59 PM, Konrad Rzeszutek Wilk wrote:
> On Fri, Sep 23, 2016 at 11:37:27AM -0400, Konrad Rzeszutek Wilk wrote:
>> On Fri, Sep 23, 2016 at 03:36:27PM +0100, Ross Lagerwall wrote:
>>> On 09/21/2016 06:32 PM, Konrad Rzeszutek Wilk wrote:
>>>> If the distance is too big we are in trouble - as our relocation
>>>> distance can surely be clipped, or still have a valid width - but
>>>> cause an overflow of distance.
>>>>
>>>> On various architectures the maximum displacement for a unconditional
>>>> branch/jump varies. ARM32 is +/- 32MB, ARM64 is +/- 128MB while x86
>>>> for 32-bit relocations is +/- 2G.
>>>>
>>>> Note: On x86 we could use the 64-bit jmpq instruction which
>>>> would provide much bigger displacement to do a jump, but we would
>>>> still have issues with the new function not being able to reach
>>>> any of the old functions (as all the relocations would assume 32-bit
>>>> displacement). And "furthermore would require an register or
>>>> memory location to load/store the address to." (From Jan).
>>>>
>>>> On ARM the conditional branch supports even a smaller displacement
>>>> but fortunately we are not using that.
>>>
>>> Wouldn't this be simpler as a BUILD_BUG_ON() in arch_livepatch_init()?
>>>
>>> Something like BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) -
>>> XEN_VIRT_START) > ARCH_LIVEPATCH_RANGE)?
>>>
>>> And BUILD_BUG_ON(((XEN_VIRT_END - NR_CPUS * PAGE_SIZE) - XEN_VIRT_START) >
>>> ARCH_LIVEPATCH_RANGE)
>>>
>>> And something similar for ARM...
>>
>> What does that have to with the payload? The displacement calculations(checks)
>> are done when we load the payload.
>
> Ooh, you are thinking of just making sure that the displacement in virtual
> addresses _should_ be OK.
>
> And that BUILD_BUG_ON would certainly do it.
>
> But my thinking was more of the payload either having some wacky relocations (say
> having an initial addendum that along with the XEN_VIRT_START -> XEN_VIRT_END)
> causes us to be way past the right place (especially with ARM32 where we only
> have 32MB distance). And having this extra check makes me sleep better at night.

Assuming that you had build checked the maximum possible displacement in 
virtual address space, then the only way a payload would fail the check 
is if either old_addr or new_addr doesn't point to hypervisor code or 
payload code (otherwise it would be in the range), but instead points to 
some other bit of memory. In that case, the payload is so completely 
broken you've got bigger problems...

There are many ways that payloads that can be broken. This checks only a 
special case of the payload being broken -- and only if the incorrect 
bit exceeds a certain range...


I don't really object to the check but it seems like an unnecessarily 
special case.

Cheers,
-- 
Ross Lagerwall

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

^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2016-09-28 10:21 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-21 17:32 [PATCH v5] Livepatch for ARM 64 and 32 Konrad Rzeszutek Wilk
2016-09-21 17:32 ` [PATCH v5 01/16] arm64: s/ALTERNATIVE/HAS_ALTERNATIVE/ Konrad Rzeszutek Wilk
2016-09-22 12:21   ` Julien Grall
2016-09-21 17:32 ` [PATCH v5 02/16] arm/x86/common: Add HAS_[ALTERNATIVE|EX_TABLE] Konrad Rzeszutek Wilk
2016-09-22 12:23   ` Julien Grall
2016-09-22 15:30   ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 03/16] livepatch: Reject payloads with .alternative or .ex_table if support is not built-in Konrad Rzeszutek Wilk
2016-09-23 12:47   ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 04/16] arm: poison initmem when it is freed Konrad Rzeszutek Wilk
2016-09-22 12:28   ` Julien Grall
2016-09-21 17:32 ` [PATCH v5 05/16] livepatch: Initial ARM64 support Konrad Rzeszutek Wilk
2016-09-22 12:49   ` Julien Grall
2016-09-23 13:38   ` Ross Lagerwall
2016-09-23 15:44     ` Konrad Rzeszutek Wilk
2016-09-27 16:42       ` Julien Grall
2016-09-21 17:32 ` [PATCH v5 06/16] livepatch: ARM/x86: Check displacement of old_addr and new_addr Konrad Rzeszutek Wilk
2016-09-22 12:55   ` Julien Grall
2016-09-23 14:36   ` Ross Lagerwall
2016-09-23 15:37     ` Konrad Rzeszutek Wilk
2016-09-23 15:59       ` Konrad Rzeszutek Wilk
2016-09-28 10:21         ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 07/16] livepatch: ARM 32|64: Ignore mapping symbols: $[d, a, x] Konrad Rzeszutek Wilk
2016-09-22 12:56   ` Julien Grall
2016-09-23 14:44   ` Ross Lagerwall
2016-09-23 16:13     ` Konrad Rzeszutek Wilk
2016-09-21 17:32 ` [PATCH v5 08/16] livepatch/arm/x86: Check payload for for unwelcomed symbols Konrad Rzeszutek Wilk
2016-09-22 13:00   ` Julien Grall
2016-09-23  1:29     ` Konrad Rzeszutek Wilk
2016-09-27  8:49       ` Ross Lagerwall
2016-09-23 14:49   ` Ross Lagerwall
2016-09-23 16:15     ` Konrad Rzeszutek Wilk
2016-09-21 17:32 ` [PATCH v5 09/16] livepatch: Move test-cases to their own sub-directory in test Konrad Rzeszutek Wilk
2016-09-22 13:01   ` Julien Grall
2016-09-23 14:51   ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 10/16] livepatch: x86, ARM, alternative: Expose FEATURE_LIVEPATCH Konrad Rzeszutek Wilk
2016-09-22 13:03   ` Julien Grall
2016-09-27  9:49   ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 11/16] livepatch: tests: Make them compile under ARM64 Konrad Rzeszutek Wilk
2016-09-22 13:10   ` Julien Grall
2016-09-22 19:26     ` Konrad Rzeszutek Wilk
2016-09-23  1:33     ` Konrad Rzeszutek Wilk
2016-09-23  9:50       ` Julien Grall
2016-09-27  9:49       ` Ross Lagerwall
2016-09-21 17:32 ` [PATCH v5 12/16] xen/arm32: Add an helper to invalidate all instruction caches Konrad Rzeszutek Wilk
2016-09-22 13:17   ` Julien Grall
2016-09-21 17:32 ` [PATCH v5 13/16] bug/x86/arm: Align bug_frames sections Konrad Rzeszutek Wilk
2016-09-21 17:32 ` [PATCH v5 14/16] livepatch: Initial ARM32 support Konrad Rzeszutek Wilk
2016-09-27 16:39   ` Julien Grall
2016-09-27 17:50     ` Konrad Rzeszutek Wilk
2016-09-27 23:13       ` Julien Grall
2016-09-21 17:32 ` [PATCH v5 15/16] livepatch, arm[32|64]: Share arch_livepatch_revert Konrad Rzeszutek Wilk
2016-09-23 14:59   ` Ross Lagerwall
2016-09-23 16:15     ` Konrad Rzeszutek Wilk
2016-09-21 17:32 ` [PATCH v5 16/16] livepatch: arm[32, 64], x86: NOP test-case Konrad Rzeszutek Wilk
2016-09-22 13:23   ` Julien Grall
2016-09-23  1:35     ` Konrad Rzeszutek Wilk
2016-09-23  9:53       ` Julien Grall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).