[GIT PULL 0/5] more EFI changes for v4.14

2017-08-25 Thread Ard Biesheuvel
The following changes since commit f1a5b53570001b1bcbf890ac6c4be1db99f8cc28:

  firmware/efi/esrt: Constify attribute_group structures (2017-08-21 09:43:51 
+0200)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/efi/efi.git tags/efi-next

for you to fetch changes up to c4d2793e5a07d5e63d91715a4393fe47c8345112:

  efi: bgrt: use efi_mem_type() (2017-08-25 10:35:23 +0100)


More EFI changes for v4.14:
- add support for requesting the firmware to wipe RAM at warm reboot
- increase the size of the random seed obtained from UEFI so crng
  fast init can complete earlier
- add 'static' to local function pointer
- move efi_mem_type() to common code and replace an open coded instance
  with it in the BGRT driver


Ard Biesheuvel (1):
  efi/random: Increase size of firmware supplied randomness

Colin Ian King (1):
  efi/reboot: Make function pointer orig_pm_power_off static

Jan Beulich (2):
  efi: move efi_mem_type() to common code
  efi: bgrt: use efi_mem_type()

Matthew Garrett (1):
  efi/libstub: Enable reset attack mitigation

 arch/x86/boot/compressed/eboot.c|  3 ++
 arch/x86/platform/efi/efi.c | 19 ---
 drivers/firmware/efi/Kconfig| 10 ++
 drivers/firmware/efi/efi-bgrt.c | 22 +
 drivers/firmware/efi/efi.c  | 40 +++
 drivers/firmware/efi/libstub/Makefile   |  1 +
 drivers/firmware/efi/libstub/arm-stub.c |  3 ++
 drivers/firmware/efi/libstub/random.c   | 10 +++---
 drivers/firmware/efi/libstub/tpm.c  | 58 +
 drivers/firmware/efi/reboot.c   |  2 +-
 include/linux/efi.h |  9 +
 11 files changed, 123 insertions(+), 54 deletions(-)
 create mode 100644 drivers/firmware/efi/libstub/tpm.c
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/5] efi/random: Increase size of firmware supplied randomness

2017-08-25 Thread Ard Biesheuvel
The crng code requires at least 64 bytes (2 * CHACHA20_BLOCK_SIZE)
to complete the fast boot-time init, so provide that many bytes
when invoking UEFI protocols to seed the entropy pool. Also, add
a notice so we can tell from the boot log when the seeding actually
took place.

Cc: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
---
 drivers/firmware/efi/efi.c|  3 ++-
 drivers/firmware/efi/libstub/random.c | 10 --
 include/linux/efi.h   |  2 ++
 3 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 6519be44387c..9e822906adcb 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -522,6 +522,7 @@ int __init efi_config_parse_tables(void *config_tables, int 
count, int sz,
if (seed != NULL) {
add_device_randomness(seed->bits, seed->size);
early_memunmap(seed, sizeof(*seed) + size);
+   pr_notice("seeding entropy pool\n");
} else {
pr_err("Could not map UEFI random seed!\n");
}
@@ -867,7 +868,7 @@ static int update_efi_random_seed(struct notifier_block *nb,
 
seed = memremap(efi.rng_seed, sizeof(*seed), MEMREMAP_WB);
if (seed != NULL) {
-   size = min(seed->size, 32U);
+   size = min(seed->size, EFI_RANDOM_SEED_SIZE);
memunmap(seed);
} else {
pr_err("Could not map UEFI random seed!\n");
diff --git a/drivers/firmware/efi/libstub/random.c 
b/drivers/firmware/efi/libstub/random.c
index 7e72954d5860..e0e603a89aa9 100644
--- a/drivers/firmware/efi/libstub/random.c
+++ b/drivers/firmware/efi/libstub/random.c
@@ -145,8 +145,6 @@ efi_status_t efi_random_alloc(efi_system_table_t 
*sys_table_arg,
return status;
 }
 
-#define RANDOM_SEED_SIZE   32
-
 efi_status_t efi_random_get_seed(efi_system_table_t *sys_table_arg)
 {
efi_guid_t rng_proto = EFI_RNG_PROTOCOL_GUID;
@@ -162,25 +160,25 @@ efi_status_t efi_random_get_seed(efi_system_table_t 
*sys_table_arg)
return status;
 
status = efi_call_early(allocate_pool, EFI_RUNTIME_SERVICES_DATA,
-   sizeof(*seed) + RANDOM_SEED_SIZE,
+   sizeof(*seed) + EFI_RANDOM_SEED_SIZE,
(void **)&seed);
if (status != EFI_SUCCESS)
return status;
 
-   status = rng->get_rng(rng, &rng_algo_raw, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, &rng_algo_raw, EFI_RANDOM_SEED_SIZE,
  seed->bits);
if (status == EFI_UNSUPPORTED)
/*
 * Use whatever algorithm we have available if the raw algorithm
 * is not implemented.
 */
-   status = rng->get_rng(rng, NULL, RANDOM_SEED_SIZE,
+   status = rng->get_rng(rng, NULL, EFI_RANDOM_SEED_SIZE,
  seed->bits);
 
if (status != EFI_SUCCESS)
goto err_freepool;
 
-   seed->size = RANDOM_SEED_SIZE;
+   seed->size = EFI_RANDOM_SEED_SIZE;
status = efi_call_early(install_configuration_table, &rng_table_guid,
seed);
if (status != EFI_SUCCESS)
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 12e05118657c..8dc3d94a3e3c 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1564,6 +1564,8 @@ efi_status_t efi_exit_boot_services(efi_system_table_t 
*sys_table,
void *priv,
efi_exit_boot_map_processing priv_func);
 
+#define EFI_RANDOM_SEED_SIZE   64U
+
 struct linux_efi_random_seed {
u32 size;
u8  bits[];
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/5] efi/libstub: Enable reset attack mitigation

2017-08-25 Thread Ard Biesheuvel
From: Matthew Garrett 

If a machine is reset while secrets are present in RAM, it may be
possible for code executed after the reboot to extract those secrets
from untouched memory. The Trusted Computing Group specified a mechanism
for requesting that the firmware clear all RAM on reset before booting
another OS. This is done by setting the MemoryOverwriteRequestControl
variable at startup. If userspace can ensure that all secrets are
removed as part of a controlled shutdown, it can reset this variable to
0 before triggering a hardware reboot.

Signed-off-by: Matthew Garrett 
Cc: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
---
 arch/x86/boot/compressed/eboot.c|  3 ++
 drivers/firmware/efi/Kconfig| 10 ++
 drivers/firmware/efi/libstub/Makefile   |  1 +
 drivers/firmware/efi/libstub/arm-stub.c |  3 ++
 drivers/firmware/efi/libstub/tpm.c  | 58 +
 include/linux/efi.h |  7 
 6 files changed, 82 insertions(+)
 create mode 100644 drivers/firmware/efi/libstub/tpm.c

diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index c3e869eaef0c..a1686f3dc295 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -997,6 +997,9 @@ struct boot_params *efi_main(struct efi_config *c,
if (boot_params->secure_boot == efi_secureboot_mode_unset)
boot_params->secure_boot = efi_get_secureboot(sys_table);
 
+   /* Ask the firmware to clear memory on unclean shutdown */
+   efi_enable_reset_attack_mitigation(sys_table);
+
setup_graphics(boot_params);
 
setup_efi_pci(boot_params);
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index 394db40ed374..2b4c39fdfa91 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -151,6 +151,16 @@ config APPLE_PROPERTIES
 
  If unsure, say Y if you have a Mac.  Otherwise N.
 
+config RESET_ATTACK_MITIGATION
+   bool "Reset memory attack mitigation"
+   depends on EFI_STUB
+   help
+ Request that the firmware clear the contents of RAM after a reboot
+ using the TCG Platform Reset Attack Mitigation specification. This
+ protects against an attacker forcibly rebooting the system while it
+ still contains secrets in RAM, booting another OS and extracting the
+ secrets.
+
 endmenu
 
 config UEFI_CPER
diff --git a/drivers/firmware/efi/libstub/Makefile 
b/drivers/firmware/efi/libstub/Makefile
index cf81e6cf5ae8..dedf9bde44db 100644
--- a/drivers/firmware/efi/libstub/Makefile
+++ b/drivers/firmware/efi/libstub/Makefile
@@ -30,6 +30,7 @@ OBJECT_FILES_NON_STANDARD := y
 KCOV_INSTRUMENT:= n
 
 lib-y  := efi-stub-helper.o gop.o secureboot.o
+lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o
 
 # include the stub's generic dependencies from lib/ when building for ARM/arm64
 arm-deps := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c sort.c
diff --git a/drivers/firmware/efi/libstub/arm-stub.c 
b/drivers/firmware/efi/libstub/arm-stub.c
index 8181ac179d14..1cb2d1c070c3 100644
--- a/drivers/firmware/efi/libstub/arm-stub.c
+++ b/drivers/firmware/efi/libstub/arm-stub.c
@@ -192,6 +192,9 @@ unsigned long efi_entry(void *handle, efi_system_table_t 
*sys_table,
goto fail_free_cmdline;
}
 
+   /* Ask the firmware to clear memory on unclean shutdown */
+   efi_enable_reset_attack_mitigation(sys_table);
+
secure_boot = efi_get_secureboot(sys_table);
 
/*
diff --git a/drivers/firmware/efi/libstub/tpm.c 
b/drivers/firmware/efi/libstub/tpm.c
new file mode 100644
index ..6224cdbc9669
--- /dev/null
+++ b/drivers/firmware/efi/libstub/tpm.c
@@ -0,0 +1,58 @@
+/*
+ * TPM handling.
+ *
+ * Copyright (C) 2016 CoreOS, Inc
+ * Copyright (C) 2017 Google, Inc.
+ * Matthew Garrett 
+ *
+ * This file is part of the Linux kernel, and is made available under the
+ * terms of the GNU General Public License version 2.
+ */
+#include 
+#include 
+
+#include "efistub.h"
+
+static const efi_char16_t efi_MemoryOverWriteRequest_name[] = {
+   'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't',
+   'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o',
+   'l', 0
+};
+
+#define MEMORY_ONLY_RESET_CONTROL_GUID \
+   EFI_GUID(0xe20939be, 0x32d4, 0x41be, 0xa1, 0x50, 0x89, 0x7f, 0x85, 
0xd4, 0x98, 0x29)
+
+#define get_efi_var(name, vendor, ...) \
+   efi_call_runtime(get_variable, \
+(efi_char16_t *)(name), (efi_guid_t *)(vendor), \
+__VA_ARGS__)
+
+#define set_efi_var(name, vendor, ...) \
+   efi_call_runtime(set_variable, \
+(efi_char16_t *)(name), (efi_guid_t *)(vendor), \
+__VA_ARGS__)
+
+/*
+ * Enable reboot attack mitigation. This requests that the firmware clear the
+ * RAM on next

[PATCH 4/5] efi: move efi_mem_type() to common code

2017-08-25 Thread Ard Biesheuvel
From: Jan Beulich 

This follows efi_mem_attributes(), as it's similarly generic. Drop
__weak from that one though (and don't introduce it for efi_mem_type()
in the first place) to make clear that other overrides to these
functions are really not intended.

Signed-off-by: Jan Beulich 
Cc: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
---
 arch/x86/platform/efi/efi.c | 19 ---
 drivers/firmware/efi/efi.c  | 37 +++--
 2 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index f084d8718ac4..928b6dceeca0 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -1032,25 +1032,6 @@ void __init efi_enter_virtual_mode(void)
efi_dump_pagetable();
 }
 
-/*
- * Convenience functions to obtain memory types and attributes
- */
-u32 efi_mem_type(unsigned long phys_addr)
-{
-   efi_memory_desc_t *md;
-
-   if (!efi_enabled(EFI_MEMMAP))
-   return 0;
-
-   for_each_efi_memory_desc(md) {
-   if ((md->phys_addr <= phys_addr) &&
-   (phys_addr < (md->phys_addr +
- (md->num_pages << EFI_PAGE_SHIFT
-   return md->type;
-   }
-   return 0;
-}
-
 static int __init arch_parse_efi_cmdline(char *str)
 {
if (!str) {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 9e822906adcb..f97f272e16ee 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -792,19 +792,19 @@ char * __init efi_md_typeattr_format(char *buf, size_t 
size,
 }
 
 /*
+ * IA64 has a funky EFI memory map that doesn't work the same way as
+ * other architectures.
+ */
+#ifndef CONFIG_IA64
+/*
  * efi_mem_attributes - lookup memmap attributes for physical address
  * @phys_addr: the physical address to lookup
  *
  * Search in the EFI memory map for the region covering
  * @phys_addr. Returns the EFI memory attributes if the region
  * was found in the memory map, 0 otherwise.
- *
- * Despite being marked __weak, most architectures should *not*
- * override this function. It is __weak solely for the benefit
- * of ia64 which has a funky EFI memory map that doesn't work
- * the same way as other architectures.
  */
-u64 __weak efi_mem_attributes(unsigned long phys_addr)
+u64 efi_mem_attributes(unsigned long phys_addr)
 {
efi_memory_desc_t *md;
 
@@ -820,6 +820,31 @@ u64 __weak efi_mem_attributes(unsigned long phys_addr)
return 0;
 }
 
+/*
+ * efi_mem_type - lookup memmap type for physical address
+ * @phys_addr: the physical address to lookup
+ *
+ * Search in the EFI memory map for the region covering @phys_addr.
+ * Returns the EFI memory type if the region was found in the memory
+ * map, EFI_RESERVED_TYPE (zero) otherwise.
+ */
+u32 efi_mem_type(unsigned long phys_addr)
+{
+   const efi_memory_desc_t *md;
+
+   if (!efi_enabled(EFI_MEMMAP))
+   return 0;
+
+   for_each_efi_memory_desc(md) {
+   if ((md->phys_addr <= phys_addr) &&
+   (phys_addr < (md->phys_addr +
+ (md->num_pages << EFI_PAGE_SHIFT
+   return md->type;
+   }
+   return EFI_RESERVED_TYPE;
+}
+#endif
+
 int efi_status_to_err(efi_status_t status)
 {
int err;
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 3/5] efi/reboot: Make function pointer orig_pm_power_off static

2017-08-25 Thread Ard Biesheuvel
From: Colin Ian King 

The function pointer orig_pm_power_off is local to the source and does
not need to be in global scope, so make it static.

Cleans up sparse warning:
symbol 'orig_pm_power_off' was not declared. Should it be static?

Signed-off-by: Colin Ian King 
Cc: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
---
 drivers/firmware/efi/reboot.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/firmware/efi/reboot.c b/drivers/firmware/efi/reboot.c
index 7117e2d0c7f9..22874544d301 100644
--- a/drivers/firmware/efi/reboot.c
+++ b/drivers/firmware/efi/reboot.c
@@ -5,7 +5,7 @@
 #include 
 #include 
 
-void (*orig_pm_power_off)(void);
+static void (*orig_pm_power_off)(void);
 
 int efi_reboot_quirk_mode = -1;
 
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 5/5] efi: bgrt: use efi_mem_type()

2017-08-25 Thread Ard Biesheuvel
From: Jan Beulich 

Avoid effectively open-coding the function.

Signed-off-by: Jan Beulich 
Cc: Matt Fleming 
Signed-off-by: Ard Biesheuvel 
---
 drivers/firmware/efi/efi-bgrt.c | 22 +-
 1 file changed, 1 insertion(+), 21 deletions(-)

diff --git a/drivers/firmware/efi/efi-bgrt.c b/drivers/firmware/efi/efi-bgrt.c
index b58233e4ed71..50793fda7819 100644
--- a/drivers/firmware/efi/efi-bgrt.c
+++ b/drivers/firmware/efi/efi-bgrt.c
@@ -27,26 +27,6 @@ struct bmp_header {
u32 size;
 } __packed;
 
-static bool efi_bgrt_addr_valid(u64 addr)
-{
-   efi_memory_desc_t *md;
-
-   for_each_efi_memory_desc(md) {
-   u64 size;
-   u64 end;
-
-   if (md->type != EFI_BOOT_SERVICES_DATA)
-   continue;
-
-   size = md->num_pages << EFI_PAGE_SHIFT;
-   end = md->phys_addr + size;
-   if (addr >= md->phys_addr && addr < end)
-   return true;
-   }
-
-   return false;
-}
-
 void __init efi_bgrt_init(struct acpi_table_header *table)
 {
void *image;
@@ -85,7 +65,7 @@ void __init efi_bgrt_init(struct acpi_table_header *table)
goto out;
}
 
-   if (!efi_bgrt_addr_valid(bgrt->image_address)) {
+   if (efi_mem_type(bgrt->image_address) != EFI_BOOT_SERVICES_DATA) {
pr_notice("Ignoring BGRT: invalid image address\n");
goto out;
}
-- 
2.11.0

--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] x86/efi: Use efi_switch_mm() rather than manually twiddling with cr3

2017-08-25 Thread Andy Lutomirski
On Thu, Aug 24, 2017 at 7:36 PM, Sai Praneeth Prakhya
 wrote:
> On Tue, 2017-08-15 at 14:46 -0700, Andy Lutomirski wrote:
>> On Tue, Aug 15, 2017 at 12:18 PM, Sai Praneeth Prakhya
>>  wrote:
>> > +/*
>> > + * Makes the calling kernel thread switch to/from efi_mm context
>> > + * Can be used from SetVirtualAddressMap() or during efi runtime calls
>> > + * (Note: This routine is heavily inspired from use_mm)
>> > + */
>> > +void efi_switch_mm(struct mm_struct *mm)
>> > +{
>> > +   struct task_struct *tsk = current;
>> > +
>> > +   task_lock(tsk);
>> > +   efi_scratch.prev_mm = tsk->active_mm;
>> > +   if (efi_scratch.prev_mm != mm) {
>> > +   mmgrab(mm);
>> > +   tsk->active_mm = mm;
>> > +   }
>> > +   switch_mm(efi_scratch.prev_mm, mm, NULL);
>> > +   task_unlock(tsk);
>> > +
>> > +   if (efi_scratch.prev_mm != mm)
>> > +   mmdrop(efi_scratch.prev_mm);
>>
>> I'm confused.  You're mmdropping an mm that you are still keeping a
>> pointer to.  This is also a bit confusing in the case where you do
>> efi_switch_mm(efi_scratch.prev_mm).
>>
>> This whole manipulation seems fairly dangerous to me for another
>> reason -- you're taking a user thread (I think) and swapping out its
>> mm to something that the user in question should *not* have access to.
>> What if a perf interrupt happens while you're in the alternate mm?
>> What if you segfault and dump core?  Should we maybe just have a flag
>> that says "this cpu is using a funny mm", assert that the flag is
>> clear when scheduling, and teach perf, coredumps, etc not to touch
>> user memory when the flag is set?
>>
>> Admittedly, the latter problem may well have existed even before these 
>> patches.
>
> Hi All,
>
> Could we please decouple the above issue from this patch set, so that we
> could have common efi_mm between x86 and ARM and also improve
> readability and maintainability for x86/efi.

I don't see why not.

>
> As it seems that "Everything EFI as kthread" might solve the above issue
> for real (which might take quite some time to implement, taking into
> consideration the complexity involved and some special case with
> pstore), do you think this patch set seems OK?
>
> If so, I will send out a V2 addressing the mmdropping issue.
>
> Regards,
> Sai
>
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 3/3] x86/efi: Use efi_switch_mm() rather than manually twiddling with cr3

2017-08-25 Thread Andy Lutomirski
On Wed, Aug 23, 2017 at 3:52 PM, Sai Praneeth Prakhya
 wrote:
> On Mon, 2017-08-21 at 08:23 -0700, Andy Lutomirski wrote:
>>
>> > On Aug 21, 2017, at 7:08 AM, Peter Zijlstra  wrote:
>> >
>> >> On Mon, Aug 21, 2017 at 06:56:01AM -0700, Andy Lutomirski wrote:
>> >>
>> >>
>> >>> On Aug 21, 2017, at 3:33 AM, Peter Zijlstra  wrote:
>> >
>> 
>>  Using a kernel thread solves the problem for real.  Anything that
>>  blindly accesses user memory in kernel thread context is terminally
>>  broken no matter what.
>> >>>
>> >>> So perf-callchain doesn't do it 'blindly', it wants either:
>> >>>
>> >>> - user_mode(regs) true, or
>> >>> - task_pt_regs() set.
>> >>>
>> >>> However I'm thinking that if the kernel thread has ->mm == &efi_mm, the
>> >>> EFI code running could very well have user_mode(regs) being true.
>> >>>
>> >>> intel_pmu_pebs_fixup() OTOH 'blindly' assumes that the LBR addresses are
>> >>> accessible. It bails on error though. So while its careful, it does
>> >>> attempt to access the 'user' mapping directly. Which should also trigger
>> >>> with the EFI code.
>> >>>
>> >>> And I'm not seeing anything particularly broken with either. The PEBS
>> >>> fixup relies on the CPU having just executed the code, and if it could
>> >>> fetch and execute the code, why shouldn't it be able to fetch and read?
>> >>
>> >> There are two ways this could be a problem.  One is that u privileged
>> >> user apps shouldn't be able to read from EFI memory.
>> >
>> > Ah, but only root can create per-cpu events or attach events to kernel
>> > threads (with sensible paranoia levels).
>>
>> But this may not need to be percpu.  If a non root user can trigger, say, an 
>> EFI variable read in their own thread context, boom.
>>
> + Tony
>
> Hi Andi,
>
> I am trying to reproduce the issue that we are discussing and hence
> tried an experiment like this:
> A user process continuously reads efi variable by
> "cat /sys/firmware/efi/efivars/Boot-8be4df61-93ca-11d2-aa0d-00e098032b8c" 
> for specified time (Eg: 100 seconds) and simultaneously I ran "perf top" as 
> root (which I suppose should trigger NMI's). I see that everything is fine, 
> no lockups, no kernel crash, no warnings/errors in dmesg.
>
> I see that perf top reports 50% of time is spent in efi function
> (probably efi_get_variable()).
> OverheadShared Object   Symbol
> 50% [unknown]   [k] 0xfffeea967416
>
> 50% is max, on avg it's 35%.
>
> I have tested this on two kernels v4.12 and v3.19. My machine has 8
> cores and to stress test, I further offlined all cpus except cpu0.
>
> Could you please let me know a way to reproduce the issue that we are
> discussing here.
> I think the issue we are concerned here is, when kernel is in efi
> context and an NMI happens and if the NMI handler tries to access user
> space, boom! we don't have user space in efi context. Am I right in
> understanding the issue or is it something else?

The boom isn't a crash, though -- it'll be (potentially) sensitive
information that shows up in the perf record.

As long as EFI isn't using low addresses, there may not be an issue.
But EFI should (maybe) use low addresses, and this'll be more
important.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC Part1 PATCH v3 14/17] x86/boot: Add early boot support when running with SEV active

2017-08-25 Thread Borislav Petkov
Btw,

I don't see our SEV-specific chicken bit which disables SEV only.

Do we need it? If so, maybe something like

mem_encrypt=sme_only

or so.

Or is the mem_encrypt=off chicken bit enough?

What about the use case where you want SME but no encrypted guests?

A bunch of hmmm.

-- 
Regards/Gruss,
Boris.

SUSE Linux GmbH, GF: Felix Imendörffer, Jane Smithard, Graham Norton, HRB 21284 
(AG Nürnberg)
-- 
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC 00/11] KVM, EFI, arm64: EFI Runtime Services Sandboxing

2017-08-25 Thread Florent Revest
Hi,

I just realised that my email client was not configured correctly and
the confidential disclaimer at the bottom of my emails obviously don't
apply. Sorry about that.

Florent

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 2/2] EFI/BGRT: use efi_mem_type()

2017-08-25 Thread Jan Beulich
Avoid effectively open-coding the function.

Signed-off-by: Jan Beulich 
Reviewed-by: Ard Biesheuvel 
---
 drivers/firmware/efi/efi-bgrt.c |   22 +-
 1 file changed, 1 insertion(+), 21 deletions(-)

--- 4.13-rc6-EFI.orig/drivers/firmware/efi/efi-bgrt.c
+++ 4.13-rc6-EFI/drivers/firmware/efi/efi-bgrt.c
@@ -27,26 +27,6 @@ struct bmp_header {
u32 size;
 } __packed;
 
-static bool efi_bgrt_addr_valid(u64 addr)
-{
-   efi_memory_desc_t *md;
-
-   for_each_efi_memory_desc(md) {
-   u64 size;
-   u64 end;
-
-   if (md->type != EFI_BOOT_SERVICES_DATA)
-   continue;
-
-   size = md->num_pages << EFI_PAGE_SHIFT;
-   end = md->phys_addr + size;
-   if (addr >= md->phys_addr && addr < end)
-   return true;
-   }
-
-   return false;
-}
-
 void __init efi_bgrt_init(struct acpi_table_header *table)
 {
void *image;
@@ -85,7 +65,7 @@ void __init efi_bgrt_init(struct acpi_ta
goto out;
}
 
-   if (!efi_bgrt_addr_valid(bgrt->image_address)) {
+   if (efi_mem_type(bgrt->image_address) != EFI_BOOT_SERVICES_DATA) {
pr_notice("Ignoring BGRT: invalid image address\n");
goto out;
}



--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 1/2] EFI: move efi_mem_type() to common code

2017-08-25 Thread Jan Beulich
This follows efi_mem_attributes(), as it's similarly generic. Drop
__weak from that one though (and don't introduce it for efi_mem_type()
in the first place) to make clear that other overrides to these
functions are really not intended.

Signed-off-by: Jan Beulich 
---
v2: Drop __weak as requested.
---
 arch/x86/platform/efi/efi.c |   19 ---
 drivers/firmware/efi/efi.c  |   29 +
 2 files changed, 29 insertions(+), 19 deletions(-)

--- 4.13-rc6-EFI.orig/arch/x86/platform/efi/efi.c   2017-08-23 
08:25:56.360254268 +0200
+++ 4.13-rc6-EFI/arch/x86/platform/efi/efi.c2017-08-24 10:46:34.580986480 
+0200
@@ -1032,25 +1032,6 @@ void __init efi_enter_virtual_mode(void)
efi_dump_pagetable();
 }
 
-/*
- * Convenience functions to obtain memory types and attributes
- */
-u32 efi_mem_type(unsigned long phys_addr)
-{
-   efi_memory_desc_t *md;
-
-   if (!efi_enabled(EFI_MEMMAP))
-   return 0;
-
-   for_each_efi_memory_desc(md) {
-   if ((md->phys_addr <= phys_addr) &&
-   (phys_addr < (md->phys_addr +
- (md->num_pages << EFI_PAGE_SHIFT
-   return md->type;
-   }
-   return 0;
-}
-
 static int __init arch_parse_efi_cmdline(char *str)
 {
if (!str) {
--- 4.13-rc6-EFI.orig/drivers/firmware/efi/efi.c2017-08-23 
08:25:59.792278686 +0200
+++ 4.13-rc6-EFI/drivers/firmware/efi/efi.c 2017-08-25 10:10:34.950714797 
+0200
@@ -791,19 +791,19 @@ char * __init efi_md_typeattr_format(cha
 }
 
 /*
+ * IA64 has a funky EFI memory map that doesn't work the same way as
+ * other architectures.
+ */
+#ifndef CONFIG_IA64
+/*
  * efi_mem_attributes - lookup memmap attributes for physical address
  * @phys_addr: the physical address to lookup
  *
  * Search in the EFI memory map for the region covering
  * @phys_addr. Returns the EFI memory attributes if the region
  * was found in the memory map, 0 otherwise.
- *
- * Despite being marked __weak, most architectures should *not*
- * override this function. It is __weak solely for the benefit
- * of ia64 which has a funky EFI memory map that doesn't work
- * the same way as other architectures.
  */
-u64 __weak efi_mem_attributes(unsigned long phys_addr)
+u64 efi_mem_attributes(unsigned long phys_addr)
 {
efi_memory_desc_t *md;
 
@@ -819,6 +819,31 @@ u64 __weak efi_mem_attributes(unsigned l
return 0;
 }
 
+/*
+ * efi_mem_type - lookup memmap type for physical address
+ * @phys_addr: the physical address to lookup
+ *
+ * Search in the EFI memory map for the region covering @phys_addr.
+ * Returns the EFI memory type if the region was found in the memory
+ * map, EFI_RESERVED_TYPE (zero) otherwise.
+ */
+u32 efi_mem_type(unsigned long phys_addr)
+{
+   const efi_memory_desc_t *md;
+
+   if (!efi_enabled(EFI_MEMMAP))
+   return 0;
+
+   for_each_efi_memory_desc(md) {
+   if ((md->phys_addr <= phys_addr) &&
+   (phys_addr < (md->phys_addr +
+ (md->num_pages << EFI_PAGE_SHIFT
+   return md->type;
+   }
+   return EFI_RESERVED_TYPE;
+}
+#endif
+
 int efi_status_to_err(efi_status_t status)
 {
int err;



--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 01/11] arm64: Add an SMCCC function IDs header

2017-08-25 Thread Florent Revest
The ARM SMC Calling Convention (DEN 0028B) introduces function IDs for
hypercalls, given in the x0 register during an SMC or HVC from a guest.

The document defines ranges of function IDs targeting different kinds of
hypervisors or supervisors.

Two ID ranges are of particular interest for the kernel:
- Standard hypervisor service calls
- Vendor specific hypervisor service calls

This patch introduces a couple of useful macros when working with SMCCC.
They provide defines of those ID ranges to be used by HVC handling (KVM)
or calling. (e.g: to leverage paravirtualized services)

The document also defines standard return values to be written into x0
after a hypercall handling. Once again, those macros can potentially be
used from both the hypervisor or the guest.

Signed-off-by: Florent Revest 
---
 include/linux/smccc_fn.h | 50 
 1 file changed, 50 insertions(+)
 create mode 100644 include/linux/smccc_fn.h

diff --git a/include/linux/smccc_fn.h b/include/linux/smccc_fn.h
new file mode 100644
index 000..f08145d
--- /dev/null
+++ b/include/linux/smccc_fn.h
@@ -0,0 +1,50 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * Copyright (C) 2017 ARM Limited
+ */
+
+#ifndef __LINUX_SMCCC_FN_H
+#define __LINUX_SMCCC_FN_H
+
+/*
+ * Standard return values
+ */
+
+#define SMCCC_STD_RET_SUCCESS  0
+#define SMCCC_STD_RET_UNKNOWN_ID   -1
+
+
+/*
+ * SMC32
+ */
+
+/* Standard hypervisor services interface */
+#define SMCCC32_STD_HYP_FN_BASE0x8500
+#define SMCCC32_STD_HYP_FN(n)  (SMCCC32_STD_HYP_FN_BASE + (n))
+
+/* Vendor specific hypervisor services interface */
+#define SMCCC32_VDR_HYP_FN_BASE0x8600
+#define SMCCC32_VDR_HYP_FN(n)  (SMCCC32_VDR_HYP_FN_BASE + (n))
+
+
+/*
+ * SMC64
+ */
+
+/* Standard hypervisor services interface */
+#define SMCCC64_STD_HYP_FN_BASE0xc500
+#define SMCCC64_STD_HYP_FN(n)  (SMCCC64_STD_HYP_FN_BASE + (n))
+
+/* Vendor specific hypervisor services interface */
+#define SMCCC64_VDR_HYP_FN_BASE0xc600
+#define SMCCC64_VDR_HYP_FN(n)  (SMCCC64_VDR_HYP_FN_BASE + (n))
+
+#endif /* __LINUX_SMCCC_FN_H */
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 06/11] KVM, arm64: Expose a VCPU initialization function

2017-08-25 Thread Florent Revest
KVM's core now offers internal virtual machine capabilities, however on ARM
the KVM_ARM_VCPU_INIT ioctl also has to be used to initialize a virtual CPU

This patch exposes a kvm_arm_vcpu_init() function to the rest of the kernel
on arm64 so that it can be used for arm64 internal VM initialization.

This function actually used to be named kvm_arch_vcpu_ioctl_vcpu_init() but
the "ioctl" part of the name wasn't consistent with the rest of the KVM arm
ioctl handlers. Moreover, it wasn't relevant to the usage of internal VMs.
Therefore it has been decided to rename the function to make it less
misleading.

Signed-off-by: Florent Revest 
---
 arch/arm64/include/asm/kvm_host.h | 2 ++
 virt/kvm/arm/arm.c| 5 ++---
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 65aab35..07b7460 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -372,6 +372,8 @@ static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu 
*vcpu) {}
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}

+int kvm_arm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init);
+
 void kvm_arm_init_debug(void);
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index a39a1e1..aa29a5d 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -888,8 +888,7 @@ static int kvm_vcpu_set_target(struct kvm_vcpu *vcpu,
 }


-static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
-struct kvm_vcpu_init *init)
+int kvm_arm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init)
 {
int ret;

@@ -973,7 +972,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
if (copy_from_user(&init, argp, sizeof(init)))
return -EFAULT;

-   return kvm_arch_vcpu_ioctl_vcpu_init(vcpu, &init);
+   return kvm_arm_vcpu_init(vcpu, &init);
}
case KVM_SET_ONE_REG:
case KVM_GET_ONE_REG: {
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 03/11] KVM: Allow VM lifecycle management without userspace

2017-08-25 Thread Florent Revest
The current codebase of KVM makes many assumptions regarding the origin of
the virtual machine being executed or configured. Indeed, the KVM API
implementation has been written with userspace usage in mind and lots of
userspace-specific code is used (namely preempt_notifiers, eventfd, mmu
notifiers, current->mm...)

The aim of this patch is to make the KVM API (create_vm, create_vcpu etc)
usable from a kernel context. A simple trick is used to distinguish
userspace VMs (coming from QEMU or LKVM...) from internal VMs. (coming
from other subsystems, for example for sandboxing purpose):
  - When a VM is created from an ioctl, kvm->mm is set to current->mm
  - When a VM is created from the kernel, kvm->mm must be set to NULL

This ensures that no userspace program can create internal VMs and allows
to easily check whether a given VM is attached to a process or is internal.

This patch simply encloses the userspace-specific pieces of code of
kvm_main in conditions checking if kvm->mm is present and modifies the
prototype of kvm_create_vm to enable NULL mm.

Signed-off-by: Florent Revest 
---
 virt/kvm/kvm_main.c | 64 ++---
 1 file changed, 41 insertions(+), 23 deletions(-)

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 15252d7..2e7af1a 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -154,7 +154,8 @@ int vcpu_load(struct kvm_vcpu *vcpu)
if (mutex_lock_killable(&vcpu->mutex))
return -EINTR;
cpu = get_cpu();
-   preempt_notifier_register(&vcpu->preempt_notifier);
+   if (vcpu->kvm->mm)
+   preempt_notifier_register(&vcpu->preempt_notifier);
kvm_arch_vcpu_load(vcpu, cpu);
put_cpu();
return 0;
@@ -165,7 +166,8 @@ void vcpu_put(struct kvm_vcpu *vcpu)
 {
preempt_disable();
kvm_arch_vcpu_put(vcpu);
-   preempt_notifier_unregister(&vcpu->preempt_notifier);
+   if (vcpu->kvm->mm)
+   preempt_notifier_unregister(&vcpu->preempt_notifier);
preempt_enable();
mutex_unlock(&vcpu->mutex);
 }
@@ -640,7 +642,7 @@ static int kvm_create_vm_debugfs(struct kvm *kvm, int fd)
return 0;
 }

-static struct kvm *kvm_create_vm(unsigned long type)
+static struct kvm *kvm_create_vm(unsigned long type, struct mm_struct *mm)
 {
int r, i;
struct kvm *kvm = kvm_arch_alloc_vm();
@@ -649,9 +651,11 @@ static struct kvm *kvm_create_vm(unsigned long type)
return ERR_PTR(-ENOMEM);

spin_lock_init(&kvm->mmu_lock);
-   mmgrab(current->mm);
-   kvm->mm = current->mm;
-   kvm_eventfd_init(kvm);
+   kvm->mm = mm;
+   if (mm) {
+   mmgrab(current->mm);
+   kvm_eventfd_init(kvm);
+   }
mutex_init(&kvm->lock);
mutex_init(&kvm->irq_lock);
mutex_init(&kvm->slots_lock);
@@ -697,15 +701,18 @@ static struct kvm *kvm_create_vm(unsigned long type)
goto out_err;
}

-   r = kvm_init_mmu_notifier(kvm);
-   if (r)
-   goto out_err;
+   if (mm) {
+   r = kvm_init_mmu_notifier(kvm);
+   if (r)
+   goto out_err;
+   }

spin_lock(&kvm_lock);
list_add(&kvm->vm_list, &vm_list);
spin_unlock(&kvm_lock);

-   preempt_notifier_inc();
+   if (mm)
+   preempt_notifier_inc();

return kvm;

@@ -721,7 +728,8 @@ static struct kvm *kvm_create_vm(unsigned long type)
for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++)
kvm_free_memslots(kvm, __kvm_memslots(kvm, i));
kvm_arch_free_vm(kvm);
-   mmdrop(current->mm);
+   if (mm)
+   mmdrop(mm);
return ERR_PTR(r);
 }

@@ -772,9 +780,11 @@ static void kvm_destroy_vm(struct kvm *kvm)
cleanup_srcu_struct(&kvm->irq_srcu);
cleanup_srcu_struct(&kvm->srcu);
kvm_arch_free_vm(kvm);
-   preempt_notifier_dec();
+   if (mm)
+   preempt_notifier_dec();
hardware_disable_all();
-   mmdrop(mm);
+   if (mm)
+   mmdrop(mm);
 }

 void kvm_get_kvm(struct kvm *kvm)
@@ -1269,6 +1279,9 @@ unsigned long kvm_host_page_size(struct kvm *kvm, gfn_t 
gfn)
if (kvm_is_error_hva(addr))
return PAGE_SIZE;

+   if (!kvm->mm)
+   return PAGE_SIZE;
+
down_read(¤t->mm->mmap_sem);
vma = find_vma(current->mm, addr);
if (!vma)
@@ -2486,9 +2499,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 
id)
if (r)
goto vcpu_destroy;

-   r = kvm_create_vcpu_debugfs(vcpu);
-   if (r)
-   goto vcpu_destroy;
+   if (kvm->mm) {
+   r = kvm_create_vcpu_debugfs(vcpu);
+   if (r)
+   goto vcpu_destroy;
+   }

mutex_lock(&kvm->lock);
if (kvm_get_vcpu_by_id(kvm, id)) {
@@ -2499,11 +2514,13 @@ static int kvm_vm_ioctl_create_v

[RFC 02/11] KVM: arm64: Return an Unknown ID on unhandled HVC

2017-08-25 Thread Florent Revest
So far, when the KVM hypervisor received an hvc from a guest, it only
routed the hypercall to the PSCI calls handler. If the function ID of the
hypercall wouldn't be supported by the PSCI code, a PSCI_RET_NOT_SUPPORTED
error code would be returned in x0.

This patch introduces a kvm_psci_is_call() check which is verified before
entering the PSCI calls handling code. The HVC is now only routed to the
PSCI code if its function ID is in the ranges of PSCI functions defined by
SMCCC (0x8400-0x841f and 0xc400-0xc41f).

If the function ID is not in those ranges, an Unknown Function Identifier
is returned in x0. This implements the behavior defined by SMCCC and paves
the way for other hvc handlers.

Signed-off-by: Florent Revest 
---
 arch/arm/include/asm/kvm_psci.h   |  1 +
 arch/arm64/include/asm/kvm_psci.h |  1 +
 arch/arm64/kvm/handle_exit.c  | 24 ++--
 include/uapi/linux/psci.h |  2 ++
 virt/kvm/arm/psci.c   | 21 +
 5 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/asm/kvm_psci.h b/arch/arm/include/asm/kvm_psci.h
index 6bda945..8dcd642 100644
--- a/arch/arm/include/asm/kvm_psci.h
+++ b/arch/arm/include/asm/kvm_psci.h
@@ -22,6 +22,7 @@
 #define KVM_ARM_PSCI_0_2   2

 int kvm_psci_version(struct kvm_vcpu *vcpu);
+bool kvm_psci_is_call(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);

 #endif /* __ARM_KVM_PSCI_H__ */
diff --git a/arch/arm64/include/asm/kvm_psci.h 
b/arch/arm64/include/asm/kvm_psci.h
index bc39e55..1a28809 100644
--- a/arch/arm64/include/asm/kvm_psci.h
+++ b/arch/arm64/include/asm/kvm_psci.h
@@ -22,6 +22,7 @@
 #define KVM_ARM_PSCI_0_2   2

 int kvm_psci_version(struct kvm_vcpu *vcpu);
+bool kvm_psci_is_call(struct kvm_vcpu *vcpu);
 int kvm_psci_call(struct kvm_vcpu *vcpu);

 #endif /* __ARM64_KVM_PSCI_H__ */
diff --git a/arch/arm64/kvm/handle_exit.c b/arch/arm64/kvm/handle_exit.c
index 17d8a16..bc7ade5 100644
--- a/arch/arm64/kvm/handle_exit.c
+++ b/arch/arm64/kvm/handle_exit.c
@@ -21,6 +21,7 @@

 #include 
 #include 
+#include 

 #include 
 #include 
@@ -34,19 +35,30 @@

 typedef int (*exit_handle_fn)(struct kvm_vcpu *, struct kvm_run *);

+/*
+ * handle_hvc - handle a guest hypercall
+ *
+ * @vcpu:  the vcpu pointer
+ * @run:   access to the kvm_run structure for results
+ *
+ * Route a given hypercall to its right HVC handler thanks to its function ID.
+ * If no corresponding handler is found, write an Unknown ID in x0 (cf. SMCCC).
+ *
+ * This function returns: > 0 (success), 0 (success but exit to user
+ * space), and < 0 (errors)
+ */
 static int handle_hvc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-   int ret;
+   int ret = 1;

trace_kvm_hvc_arm64(*vcpu_pc(vcpu), vcpu_get_reg(vcpu, 0),
kvm_vcpu_hvc_get_imm(vcpu));
vcpu->stat.hvc_exit_stat++;

-   ret = kvm_psci_call(vcpu);
-   if (ret < 0) {
-   kvm_inject_undefined(vcpu);
-   return 1;
-   }
+   if (kvm_psci_is_call(vcpu))
+   ret = kvm_psci_call(vcpu);
+   else
+   vcpu_set_reg(vcpu, 0, SMCCC_STD_RET_UNKNOWN_ID);

return ret;
 }
diff --git a/include/uapi/linux/psci.h b/include/uapi/linux/psci.h
index 3d7a0fc..79704fe 100644
--- a/include/uapi/linux/psci.h
+++ b/include/uapi/linux/psci.h
@@ -24,10 +24,12 @@
 /* PSCI v0.2 interface */
 #define PSCI_0_2_FN_BASE   0x8400
 #define PSCI_0_2_FN(n) (PSCI_0_2_FN_BASE + (n))
+#define PSCI_0_2_FN_ENDPSCI_0_2_FN(0x1F)
 #define PSCI_0_2_64BIT 0x4000
 #define PSCI_0_2_FN64_BASE \
(PSCI_0_2_FN_BASE + PSCI_0_2_64BIT)
 #define PSCI_0_2_FN64(n)   (PSCI_0_2_FN64_BASE + (n))
+#define PSCI_0_2_FN64_END  PSCI_0_2_FN64(0x1F)

 #define PSCI_0_2_FN_PSCI_VERSION   PSCI_0_2_FN(0)
 #define PSCI_0_2_FN_CPU_SUSPENDPSCI_0_2_FN(1)
diff --git a/virt/kvm/arm/psci.c b/virt/kvm/arm/psci.c
index f1e363b..9602894 100644
--- a/virt/kvm/arm/psci.c
+++ b/virt/kvm/arm/psci.c
@@ -332,3 +332,24 @@ int kvm_psci_call(struct kvm_vcpu *vcpu)
return -EINVAL;
};
 }
+
+/**
+ * kvm_psci_is_call - checks if a HVC function ID is in a PSCI range
+ * @vcpu: Pointer to the VCPU struct
+ *
+ * When a hypercall is received from a guest. The SMCCC defines a function ID
+ * as a value to be put in x0 to identify the destination of the call. The same
+ * document defines ranges of function IDs to be used by PSCI. This function
+ * checks whether a given vcpu is requesting a PSCI related handler.
+ *
+ * This function returns:
+ *  - true if this HVC should be handled by kvm_psci_call
+ *  - false if it shouldn't
+ */
+inline bool kvm_psci_is_call(struct kvm_vcpu *vcpu)
+{
+   unsigned long fn = vcpu_get_reg(

[RFC 05/11] KVM: Expose VM/VCPU creation functions

2017-08-25 Thread Florent Revest
Now that KVM is capable of creating internal virtual machines, the rest of
the kernel needs an API to access this capability.

This patch exposes two functions for VMs and VCPUs creation in kvm_host.h:
 - kvm_create_internal_vm: ensures that kvm->mm is kept NULL at VM creation
 - kvm_vm_create_vcpu: simple alias of kvm_vm_ioctl_create_vcpu for clarity

Signed-off-by: Florent Revest 
---
 include/linux/kvm_host.h |  3 +++
 virt/kvm/kvm_main.c  | 10 ++
 2 files changed, 13 insertions(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 21a6fd6..dd10d3b 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -565,6 +565,9 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned 
vcpu_align,
  struct module *module);
 void kvm_exit(void);

+struct kvm *kvm_create_internal_vm(unsigned long type);
+int kvm_vm_create_vcpu(struct kvm *kvm, u32 id);
+
 void kvm_get_kvm(struct kvm *kvm);
 void kvm_put_kvm(struct kvm *kvm);

diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 2e7af1a..c1c8bb6 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -733,6 +733,11 @@ static struct kvm *kvm_create_vm(unsigned long type, 
struct mm_struct *mm)
return ERR_PTR(r);
 }

+struct kvm *kvm_create_internal_vm(unsigned long type)
+{
+   return kvm_create_vm(type, NULL);
+}
+
 static void kvm_destroy_devices(struct kvm *kvm)
 {
struct kvm_device *dev, *tmp;
@@ -2549,6 +2554,11 @@ static int kvm_vm_ioctl_create_vcpu(struct kvm *kvm, u32 
id)
return r;
 }

+int kvm_vm_create_vcpu(struct kvm *kvm, u32 id)
+{
+   return kvm_vm_ioctl_create_vcpu(kvm, id);
+}
+
 static int kvm_vcpu_ioctl_set_sigmask(struct kvm_vcpu *vcpu, sigset_t *sigset)
 {
if (sigset) {
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 07/11] KVM: Allow initialization before the module target

2017-08-25 Thread Florent Revest
The kvm_init function has been designed to be executed during the
module_init target. It requires a struct module pointer to be used as
the owner of the /dev/* files and also tries to register /dev/kvm with a
function (misc_register) that can only be used late in the boot process.

This patch modifies kvm_init to execute this late initialization code
conditionally, only in the context of a module_init. It also offers a
kvm_set_module function to be used for /dev/kvm registration and device
files owning once the module target is reached.

As is, this patch does not change anything. However it could be used by
certain architectures to initialize the core of kvm earlier in the boot
(e.g: in a subsys_initcall) and then initialize the userspace facing files
in a module_init target. This can be useful to create internal VMs before
being able to offer the userspace APIs.

Signed-off-by: Florent Revest 
---
 include/linux/kvm_host.h |  1 +
 virt/kvm/kvm_main.c  | 28 
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index dd10d3b..15a0a8d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -563,6 +563,7 @@ static inline void kvm_irqfd_exit(void)
 #endif
 int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align,
  struct module *module);
+int kvm_set_module(struct module *module);
 void kvm_exit(void);

 struct kvm *kvm_create_internal_vm(unsigned long type);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index c1c8bb6..3c9cb00 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -4086,14 +4086,10 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned 
vcpu_align,
if (r)
goto out_free;

-   kvm_chardev_ops.owner = module;
-   kvm_vm_fops.owner = module;
-   kvm_vcpu_fops.owner = module;
-
-   r = misc_register(&kvm_dev);
-   if (r) {
-   pr_err("kvm: misc device register failed\n");
-   goto out_unreg;
+   if (module) {
+   r = kvm_set_module(module);
+   if (r)
+   goto out_unreg;
}

register_syscore_ops(&kvm_syscore_ops);
@@ -4136,6 +4132,22 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned 
vcpu_align,
 }
 EXPORT_SYMBOL_GPL(kvm_init);

+int kvm_set_module(struct module *module)
+{
+   int r;
+
+   kvm_chardev_ops.owner = module;
+   kvm_vm_fops.owner = module;
+   kvm_vcpu_fops.owner = module;
+
+   r = misc_register(&kvm_dev);
+   if (r)
+   pr_err("kvm: misc device register failed\n");
+
+   return r;
+}
+EXPORT_SYMBOL_GPL(kvm_set_module);
+
 void kvm_exit(void)
 {
debugfs_remove_recursive(kvm_debugfs_dir);
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 04/11] KVM, arm, arm64: Offer PAs to IPAs idmapping to internal VMs

2017-08-25 Thread Florent Revest
Usual KVM virtual machines map guest's physical addresses from a process
userspace memory. However, with the new concept of internal VMs, a virtual
machine can be created from the kernel, without any link to a userspace
context. Hence, some of the KVM's architecture-specific code needs to be
modified to take this kind of VMs into account.

The approach chosen with this patch is to let internal VMs idmap physical
addresses into intermediary physical addresses by calling
kvm_set_memory_region with a kvm_userspace_memory_region where the
guest_phys_addr field points both to the original PAs and to the IPAs. The
userspace_addr field of this struct is therefore ignored with internal VMs.

This patch extends the capabilities of the arm and arm64 stage2 MMU code
to handle internal VMs. Three things are changed:

- Various parts of the MMU code which are related to a userspace context
are now only executed if kvm->mm is present.

- When this pointer is NULL, struct kvm_userspace_memory_regions are
treated by internal_vm_prep_mem as idmaps of physical memory.

- A set of 256 additional private memslots is now reserved on arm64 for the
usage of internal VMs memory idmapping.

Note: this patch should have pretty much no performance impact on the
critical path of traditional VMs since only one unlikely branch had to be
added to the page fault handler.

Signed-off-by: Florent Revest 
---
 arch/arm64/include/asm/kvm_host.h |  1 +
 virt/kvm/arm/mmu.c| 76 +--
 2 files changed, 74 insertions(+), 3 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index d686300..65aab35 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -32,6 +32,7 @@
 #define __KVM_HAVE_ARCH_INTC_INITIALIZED

 #define KVM_USER_MEM_SLOTS 512
+#define KVM_PRIVATE_MEM_SLOTS 256
 #define KVM_HALT_POLL_NS_DEFAULT 50

 #include 
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 2ea21da..1d2d3df 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -772,6 +772,11 @@ static void stage2_unmap_memslot(struct kvm *kvm,
phys_addr_t size = PAGE_SIZE * memslot->npages;
hva_t reg_end = hva + size;

+   if (unlikely(!kvm->mm)) {
+   unmap_stage2_range(kvm, addr, size);
+   return;
+   }
+
/*
 * A memory region could potentially cover multiple VMAs, and any holes
 * between them, so iterate over all of them to find out if we should
@@ -819,7 +824,8 @@ void stage2_unmap_vm(struct kvm *kvm)
int idx;

idx = srcu_read_lock(&kvm->srcu);
-   down_read(¤t->mm->mmap_sem);
+   if (likely(kvm->mm))
+   down_read(¤t->mm->mmap_sem);
spin_lock(&kvm->mmu_lock);

slots = kvm_memslots(kvm);
@@ -827,7 +833,8 @@ void stage2_unmap_vm(struct kvm *kvm)
stage2_unmap_memslot(kvm, memslot);

spin_unlock(&kvm->mmu_lock);
-   up_read(¤t->mm->mmap_sem);
+   if (likely(kvm->mm))
+   up_read(¤t->mm->mmap_sem);
srcu_read_unlock(&kvm->srcu, idx);
 }

@@ -1303,6 +1310,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, 
phys_addr_t fault_ipa,
return -EFAULT;
}

+   if (unlikely(!kvm->mm)) {
+   kvm_err("Unexpected internal VM page fault\n");
+   kvm_inject_vabt(vcpu);
+   return 0;
+   }
+
/* Let's check if we will get back a huge page backed by hugetlbfs */
down_read(¤t->mm->mmap_sem);
vma = find_vma_intersection(current->mm, hva, hva + 1);
@@ -1850,6 +1863,54 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
kvm_mmu_wp_memory_region(kvm, mem->slot);
 }

+/*
+ * internal_vm_prep_mem - maps a range of hpa to gpa at stage2
+ *
+ * While userspace VMs manage gpas using hvas, internal virtual machines need a
+ * way to map physical addresses to a guest. In order to avoid code 
duplication,
+ * the kvm_set_memory_region call is kept for internal VMs, however it usually
+ * expects a struct kvm_userspace_memory_region with a userspace_addr field.
+ * With internal VMs, this field is ignored and physical memory memory pointed
+ * by guest_phys_addr can only be idmapped.
+ */
+static int internal_vm_prep_mem(struct kvm *kvm,
+   const struct kvm_userspace_memory_region *mem)
+{
+   phys_addr_t addr, end;
+   unsigned long pfn;
+   int ret;
+   struct kvm_mmu_memory_cache cache = { 0 };
+
+   end = mem->guest_phys_addr + mem->memory_size;
+   pfn = __phys_to_pfn(mem->guest_phys_addr);
+   addr = mem->guest_phys_addr;
+
+   for (; addr < end; addr += PAGE_SIZE) {
+   pte_t pte = pfn_pte(pfn, PAGE_S2);
+
+   pte = kvm_s2pte_mkwrite(pte);
+
+   ret = mmu_topup_memory_cache(&cache,
+KVM_MMU_CACHE_MIN_PAGES,
+ 

[RFC 08/11] KVM, arm, arm64: Initialize KVM's core earlier

2017-08-25 Thread Florent Revest
In order to use internal VMs early in the boot process, the arm_init
function, in charge of initializing KVM, is split in two parts:
 - A subsys_initcall target initializing KVM's core only
 - A module_init target initializing KVM's userspace facing files

An implicit dependency of VM execution on arm and arm64, the
initialization of KVM system registers, is also rescheduled to be
effective as soon as KVM's core is initialized.

Signed-off-by: Florent Revest 
---
 arch/arm/include/asm/kvm_coproc.h|  3 +++
 arch/arm/include/asm/kvm_host.h  |  1 +
 arch/arm/kvm/coproc.c|  6 ++
 arch/arm/kvm/coproc_a15.c|  3 +--
 arch/arm/kvm/coproc_a7.c |  3 +--
 arch/arm64/include/asm/kvm_host.h|  1 +
 arch/arm64/kvm/sys_regs_generic_v8.c |  8 ++--
 virt/kvm/arm/arm.c   | 13 +++--
 8 files changed, 30 insertions(+), 8 deletions(-)

diff --git a/arch/arm/include/asm/kvm_coproc.h 
b/arch/arm/include/asm/kvm_coproc.h
index e74ab0f..1502723 100644
--- a/arch/arm/include/asm/kvm_coproc.h
+++ b/arch/arm/include/asm/kvm_coproc.h
@@ -45,4 +45,7 @@ struct kvm_coproc_target_table {
 int kvm_arm_coproc_get_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 int kvm_arm_coproc_set_reg(struct kvm_vcpu *vcpu, const struct kvm_one_reg *);
 unsigned long kvm_arm_num_coproc_regs(struct kvm_vcpu *vcpu);
+
+int coproc_a15_init(void);
+int coproc_a7_init(void);
 #endif /* __ARM_KVM_COPROC_H__ */
diff --git a/arch/arm/include/asm/kvm_host.h b/arch/arm/include/asm/kvm_host.h
index 127e2dd..fb94666 100644
--- a/arch/arm/include/asm/kvm_host.h
+++ b/arch/arm/include/asm/kvm_host.h
@@ -287,6 +287,7 @@ static inline void kvm_arch_vcpu_uninit(struct kvm_vcpu 
*vcpu) {}
 static inline void kvm_arch_sched_in(struct kvm_vcpu *vcpu, int cpu) {}
 static inline void kvm_arch_vcpu_block_finish(struct kvm_vcpu *vcpu) {}

+void kvm_arm_init_sys_reg(void);
 static inline void kvm_arm_init_debug(void) {}
 static inline void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) {}
 static inline void kvm_arm_clear_debug(struct kvm_vcpu *vcpu) {}
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 6d1d2e2..28bc397 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -1369,3 +1369,9 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
if (vcpu_cp15(vcpu, num) == 0x42424242)
panic("Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
+
+void kvm_arm_init_sys_reg(void)
+{
+   coproc_a7_init();
+   coproc_a15_init();
+}
diff --git a/arch/arm/kvm/coproc_a15.c b/arch/arm/kvm/coproc_a15.c
index a713675..83102a3 100644
--- a/arch/arm/kvm/coproc_a15.c
+++ b/arch/arm/kvm/coproc_a15.c
@@ -43,9 +43,8 @@
.num = ARRAY_SIZE(a15_regs),
 };

-static int __init coproc_a15_init(void)
+int coproc_a15_init(void)
 {
kvm_register_target_coproc_table(&a15_target_table);
return 0;
 }
-late_initcall(coproc_a15_init);
diff --git a/arch/arm/kvm/coproc_a7.c b/arch/arm/kvm/coproc_a7.c
index b19e46d..b365ac0 100644
--- a/arch/arm/kvm/coproc_a7.c
+++ b/arch/arm/kvm/coproc_a7.c
@@ -46,9 +46,8 @@
.num = ARRAY_SIZE(a7_regs),
 };

-static int __init coproc_a7_init(void)
+int coproc_a7_init(void)
 {
kvm_register_target_coproc_table(&a7_target_table);
return 0;
 }
-late_initcall(coproc_a7_init);
diff --git a/arch/arm64/include/asm/kvm_host.h 
b/arch/arm64/include/asm/kvm_host.h
index 07b7460..e360bb3 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -374,6 +374,7 @@ static inline void kvm_arch_vcpu_block_finish(struct 
kvm_vcpu *vcpu) {}

 int kvm_arm_vcpu_init(struct kvm_vcpu *vcpu, struct kvm_vcpu_init *init);

+void kvm_arm_init_sys_reg(void);
 void kvm_arm_init_debug(void);
 void kvm_arm_setup_debug(struct kvm_vcpu *vcpu);
 void kvm_arm_clear_debug(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/sys_regs_generic_v8.c 
b/arch/arm64/kvm/sys_regs_generic_v8.c
index 969ade1..0fe755d 100644
--- a/arch/arm64/kvm/sys_regs_generic_v8.c
+++ b/arch/arm64/kvm/sys_regs_generic_v8.c
@@ -72,7 +72,7 @@ static void reset_actlr(struct kvm_vcpu *vcpu, const struct 
sys_reg_desc *r)
},
 };

-static int __init sys_reg_genericv8_init(void)
+static int sys_reg_genericv8_init(void)
 {
unsigned int i;

@@ -95,4 +95,8 @@ static int __init sys_reg_genericv8_init(void)

return 0;
 }
-late_initcall(sys_reg_genericv8_init);
+
+void kvm_arm_init_sys_reg(void)
+{
+   sys_reg_genericv8_init();
+}
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index aa29a5d..7d0aa4f 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -1451,6 +1451,8 @@ int kvm_arch_init(void *opaque)
int err;
int ret, cpu;

+   kvm_arm_init_sys_reg();
+
if (!is_hyp_mode_available()) {
kvm_err("HYP mode not available\n");
return -ENODEV;
@@ -1496,8 +1498,15 @@ void kvm_arch_exit(void)

 static int arm_init(void)
 {
-   int rc = kvm

[RFC 10/11] efi, arm64: Sandbox Runtime Services in a VM

2017-08-25 Thread Florent Revest
EFI Runtime Services are binary blobs currently executed in a special
memory context but with the privileges of the kernel. This can potentially
cause security or stability issues (registers corruption for example).

This patch adds a CONFIG_EFI_SANDBOX option that can be used on arm64 to
enclose the Runtime Services in a virtual machine and limit the impact they
can potentially have on the kernel. This sandboxing can also be useful for
debugging as exceptions caused by the firmware code can be recovered and
examined.

When booting the machine, an internal KVM virtual machine is created with
physical and virtual addresses mirroring the host's EFI context.

One page of code and at least 16K of data pages are kept in low memory for
the usage of an internal (in the VM) assembly function call wrapper
(efi_sandbox_wrapper). Calling this internal wrapper is done from external
C function wrappers (e.g: efi_sandbox_get_next_variable) filling the VCPU
registers with arguments and the data page with copies of memory buffers
first.

When a Runtime Service returns, the internal wrapper issues an HVC to let
the host know the efi status return value in x1. In case of exception,
an internal handler also sends an HVC with an EFI_ABORTED error code.

Details of the VCPU initialization, VM memory mapping and service call/ret
are extensively documented in arm-sandbox.c and arm-sandbox-payload.S.

Note: The current version of this patch could potentially cause problems of
arguments alignment when calling an EFI Runtime Service. Indeed, the
buffers arguments are just pushed onto a stack in a data page without any
regards to the ARM Calling Convention alignments.

Signed-off-by: Florent Revest 
---
 arch/arm/include/asm/efi.h |   5 +
 arch/arm64/include/asm/efi.h   |  69 
 arch/arm64/kernel/asm-offsets.c|   3 +
 arch/arm64/kvm/handle_exit.c   |   3 +
 drivers/firmware/efi/Kconfig   |  10 +
 drivers/firmware/efi/Makefile  |   1 +
 drivers/firmware/efi/arm-runtime.c |   2 +
 drivers/firmware/efi/arm-sandbox-payload.S |  96 +
 drivers/firmware/efi/arm-sandbox.c | 569 +
 include/linux/smccc_fn.h   |   3 +
 10 files changed, 761 insertions(+)
 create mode 100644 drivers/firmware/efi/arm-sandbox-payload.S
 create mode 100644 drivers/firmware/efi/arm-sandbox.c

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index ed575ae..524f0dd 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -35,6 +35,11 @@
__f(args);  \
 })

+struct kvm_vcpu;
+static inline void efi_arm_sandbox_init(struct mm_struct *efi_mm) { }
+static inline bool efi_sandbox_is_exit(struct kvm_vcpu *vcpu) { return false; }
+static inline int efi_sandbox_exit(struct kvm_vcpu *vcpu) { return -1; }
+
 int efi_arch_late_enable_runtime_services(void);

 #define ARCH_EFI_IRQ_FLAGS_MASK \
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 373d94d..f1c33cd 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -1,6 +1,8 @@
 #ifndef _ASM_EFI_H
 #define _ASM_EFI_H

+#include 
+
 #include 
 #include 
 #include 
@@ -18,6 +20,10 @@
 int efi_create_mapping(struct mm_struct *mm, efi_memory_desc_t *md);
 int efi_set_mapping_permissions(struct mm_struct *mm, efi_memory_desc_t *md);

+struct kvm_vcpu;
+
+#ifndef CONFIG_EFI_SANDBOX
+
 #define arch_efi_call_virt_setup() \
 ({ \
kernel_neon_begin();\
@@ -37,6 +43,69 @@
kernel_neon_end();  \
 })

+static inline void efi_arm_sandbox_init(struct mm_struct *efi_mm) { }
+static inline bool efi_sandbox_is_exit(struct kvm_vcpu *vcpu) { return false; }
+static inline int efi_sandbox_exit(struct kvm_vcpu *vcpu) { return -1; }
+
+#else
+
+void efi_arm_sandbox_init(struct mm_struct *efi_mm);
+bool efi_sandbox_is_exit(struct kvm_vcpu *vcpu);
+int efi_sandbox_exit(struct kvm_vcpu *vcpu);
+
+void efi_sandbox_excpt(void);
+void efi_sandbox_wrapper(void);
+void efi_sandbox_vectors(void);
+
+#define arch_efi_call_virt_setup() ({})
+#define arch_efi_call_virt(p, f, args...)  efi_sandbox_##f(args)
+#define arch_efi_call_virt_teardown() ({})
+
+/*
+ * The following function wrappers are needed in order to serialize the 
variadic
+ * macro's arguments (arch_efi_call_virt(p, f, args...)) in the vcpu's 
registers
+ * p is also ignored since it is available in the context of the virtual 
machine
+ */
+
+efi_status_t efi_sandbox_get_time(efi_time_t *tm,
+  efi_time_cap_t *tc);
+efi_status_t efi_sandbox_set_time(efi_time_t *tm);
+efi_status_t efi_sandbox_get_wakeup_time(efi_bool_t *enabled,
+efi_

[RFC 11/11] KVM, arm64: Don't trap internal VMs SMC calls

2017-08-25 Thread Florent Revest
Internal virtual machines can be used to sandbox code such as EFI Runtime
Services. However, some implementations of those Runtime Services rely on
handlers placed in the Secure World (e.g: SoftIron Overdrive 1000) and need
access to SMC calls.

This patch modifies the Hypervisor Configuration Register to avoid trapping
SMC calls of internal virtual machines. Normal userspace VMs are not
affected by this patch.

Note: Letting Runtime Services VMs access EL3 without control can
potentially be a security threat on its own. An alternative would be to
forward SMC calls selectively from inside handle_smc. However, this would
require some level of knowledge of the SMC calls arguments and EFI
Runtime Services implementations.

Signed-off-by: Florent Revest 
---
 arch/arm64/include/asm/kvm_emulate.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_emulate.h 
b/arch/arm64/include/asm/kvm_emulate.h
index fe39e68..4b46cd0 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -49,6 +49,9 @@ static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
vcpu->arch.hcr_el2 |= HCR_E2H;
if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
vcpu->arch.hcr_el2 &= ~HCR_RW;
+
+   if (!vcpu->kvm->mm)
+   vcpu->arch.hcr_el2 &= ~HCR_TSC;
 }

 static inline unsigned long vcpu_get_hcr(struct kvm_vcpu *vcpu)
--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 09/11] EFI, arm, arm64: Enable EFI Runtime Services later

2017-08-25 Thread Florent Revest
EFI Runtime Services on ARM are enabled very early in the boot process
although they aren't used until substantially later. This patch modifies
the efi initialization sequence on ARM to enable runtime services just
before they are effectively needed (in a subsys target instead of early).

The reason behind this change is that eventually, a late Runtime Services
initialization could take advantage of KVM's internal virtual machines to
sandbox firmware code execution. Since KVM's core is only available
starting from the subsys target, this reordering would be compulsory.

Signed-off-by: Florent Revest 
---
 arch/arm/include/asm/efi.h | 2 ++
 arch/arm64/include/asm/efi.h   | 2 ++
 arch/x86/include/asm/efi.h | 2 ++
 drivers/firmware/efi/arm-runtime.c | 3 +--
 drivers/firmware/efi/efi.c | 3 +++
 5 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/efi.h b/arch/arm/include/asm/efi.h
index 17f1f1a..ed575ae 100644
--- a/arch/arm/include/asm/efi.h
+++ b/arch/arm/include/asm/efi.h
@@ -35,6 +35,8 @@
__f(args);  \
 })

+int efi_arch_late_enable_runtime_services(void);
+
 #define ARCH_EFI_IRQ_FLAGS_MASK \
(PSR_J_BIT | PSR_E_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | \
 PSR_T_BIT | MODE_MASK)
diff --git a/arch/arm64/include/asm/efi.h b/arch/arm64/include/asm/efi.h
index 8f3043a..373d94d 100644
--- a/arch/arm64/include/asm/efi.h
+++ b/arch/arm64/include/asm/efi.h
@@ -37,6 +37,8 @@
kernel_neon_end();  \
 })

+int efi_arch_late_enable_runtime_services(void);
+
 #define ARCH_EFI_IRQ_FLAGS_MASK (PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT)

 /* arch specific definitions used by the stub code */
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 796ff6c..869efbb 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -233,6 +233,8 @@ static inline bool efi_is_64bit(void)

 extern bool efi_reboot_required(void);

+int __init efi_arch_late_enable_runtime_services(void) {}
+
 #else
 static inline void parse_efi_setup(u64 phys_addr, u32 data_len) {}
 static inline bool efi_reboot_required(void)
diff --git a/drivers/firmware/efi/arm-runtime.c 
b/drivers/firmware/efi/arm-runtime.c
index 1cc41c3..d94d240 100644
--- a/drivers/firmware/efi/arm-runtime.c
+++ b/drivers/firmware/efi/arm-runtime.c
@@ -115,7 +115,7 @@ static bool __init efi_virtmap_init(void)
  * non-early mapping of the UEFI system table and virtual mappings for all
  * EFI_MEMORY_RUNTIME regions.
  */
-static int __init arm_enable_runtime_services(void)
+int __init efi_arch_late_enable_runtime_services(void)
 {
u64 mapsize;

@@ -154,7 +154,6 @@ static int __init arm_enable_runtime_services(void)

return 0;
 }
-early_initcall(arm_enable_runtime_services);

 void efi_virtmap_load(void)
 {
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c
index 045d6d3..2b447b4 100644
--- a/drivers/firmware/efi/efi.c
+++ b/drivers/firmware/efi/efi.c
@@ -33,6 +33,7 @@
 #include 

 #include 
+#include 

 struct efi __read_mostly efi = {
.mps= EFI_INVALID_TABLE_ADDR,
@@ -304,6 +305,8 @@ static int __init efisubsys_init(void)
 {
int error;

+   efi_arch_late_enable_runtime_services();
+
if (!efi_enabled(EFI_BOOT))
return 0;

--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC 00/11] KVM, EFI, arm64: EFI Runtime Services Sandboxing

2017-08-25 Thread Florent Revest
Hi,

This series implements a mechanism to sandbox EFI Runtime Services on arm64.
It can be enabled with CONFIG_EFI_SANDBOX. At boot it spawns an internal KVM
virtual machine that is ran everytime an EFI Runtime Service is called. This
limits the possible security and stability impact of EFI runtime on the kernel.

The patch set is split as follow:
 - Patches 1 and 2: Give more control over HVC handling to KVM
 - Patches 3 to 6: Introduce the concept of KVM "internal VMs"
 - Patches 7 to 9: Reorder KVM and EFI initialization on ARM
 - Patch 10: Introduces the EFI sandboxing VM and wrappers
 - Patch 11: Workarounds some EFI Runtime Services relying on EL3

The sandboxing has been tested to work reliably (rtc and efivars) on a
SoftIron OverDrive 1000 box and on a ARMv8.3 model with VHE enabled. Normal
userspace KVM instance have also been tested to still work correctly.

Those patches apply cleanly on the Linus' v4.13-rc6 tag and have no other
dependencies.

Florent Revest (11):
  arm64: Add an SMCCC function IDs header
  KVM: arm64: Return an Unknown ID on unhandled HVC
  KVM: Allow VM lifecycle management without userspace
  KVM, arm, arm64: Offer PAs to IPAs idmapping to internal VMs
  KVM: Expose VM/VCPU creation functions
  KVM, arm64: Expose a VCPU initialization function
  KVM: Allow initialization before the module target
  KVM, arm, arm64: Initialize KVM's core earlier
  EFI, arm, arm64: Enable EFI Runtime Services later
  efi, arm64: Sandbox Runtime Services in a VM
  KVM, arm64: Don't trap internal VMs SMC calls

 arch/arm/include/asm/efi.h |   7 +
 arch/arm/include/asm/kvm_coproc.h  |   3 +
 arch/arm/include/asm/kvm_host.h|   1 +
 arch/arm/include/asm/kvm_psci.h|   1 +
 arch/arm/kvm/coproc.c  |   6 +
 arch/arm/kvm/coproc_a15.c  |   3 +-
 arch/arm/kvm/coproc_a7.c   |   3 +-
 arch/arm64/include/asm/efi.h   |  71 
 arch/arm64/include/asm/kvm_emulate.h   |   3 +
 arch/arm64/include/asm/kvm_host.h  |   4 +
 arch/arm64/include/asm/kvm_psci.h  |   1 +
 arch/arm64/kernel/asm-offsets.c|   3 +
 arch/arm64/kvm/handle_exit.c   |  27 +-
 arch/arm64/kvm/sys_regs_generic_v8.c   |   8 +-
 arch/x86/include/asm/efi.h |   2 +
 drivers/firmware/efi/Kconfig   |  10 +
 drivers/firmware/efi/Makefile  |   1 +
 drivers/firmware/efi/arm-runtime.c |   5 +-
 drivers/firmware/efi/arm-sandbox-payload.S |  96 +
 drivers/firmware/efi/arm-sandbox.c | 569 +
 drivers/firmware/efi/efi.c |   3 +
 include/linux/kvm_host.h   |   4 +
 include/linux/smccc_fn.h   |  53 +++
 include/uapi/linux/psci.h  |   2 +
 virt/kvm/arm/arm.c |  18 +-
 virt/kvm/arm/mmu.c |  76 +++-
 virt/kvm/arm/psci.c|  21 ++
 virt/kvm/kvm_main.c| 102 --
 28 files changed, 1050 insertions(+), 53 deletions(-)
 create mode 100644 drivers/firmware/efi/arm-sandbox-payload.S
 create mode 100644 drivers/firmware/efi/arm-sandbox.c
 create mode 100644 include/linux/smccc_fn.h

--
1.9.1

IMPORTANT NOTICE: The contents of this email and any attachments are 
confidential and may also be privileged. If you are not the intended recipient, 
please notify the sender immediately and do not disclose the contents to any 
other person, use it for any purpose, or store or copy the information in any 
medium. Thank you.
--
To unsubscribe from this list: send the line "unsubscribe linux-efi" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html