Re: [PATCH 18/62] x86/boot/compressed/64: Setup GHCB Based VC Exception handler

2020-02-12 Thread Joerg Roedel
On Tue, Feb 11, 2020 at 02:25:49PM -0800, Andy Lutomirski wrote:
> On Tue, Feb 11, 2020 at 5:53 AM Joerg Roedel  wrote:
> >
> > From: Joerg Roedel 
> >
> > Install an exception handler for #VC exception that uses a GHCB. Also
> > add the infrastructure for handling different exit-codes by decoding
> > the instruction that caused the exception and error handling.
> >
> 
> > diff --git a/arch/x86/boot/compressed/sev-es.c 
> > b/arch/x86/boot/compressed/sev-es.c
> > index 8d13121a8cf2..02fb6f57128b 100644
> > --- a/arch/x86/boot/compressed/sev-es.c
> > +++ b/arch/x86/boot/compressed/sev-es.c
> > @@ -8,12 +8,16 @@
> >  #include 
> >
> >  #include 
> > +#include 
> >  #include 
> >  #include 
> >  #include 
> >
> >  #include "misc.h"
> >
> > +struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
> > +struct ghcb *boot_ghcb;
> > +
> >  static inline u64 read_ghcb_msr(void)
> >  {
> > unsigned long low, high;
> > @@ -35,8 +39,95 @@ static inline void write_ghcb_msr(u64 val)
> > "a"(low), "d" (high) : "memory");
> >  }
> >
> > +static enum es_result es_fetch_insn_byte(struct es_em_ctxt *ctxt,
> > +unsigned int offset,
> > +char *buffer)
> > +{
> > +   char *rip = (char *)ctxt->regs->ip;
> > +
> > +   buffer[offset] = rip[offset];
> > +
> > +   return ES_OK;
> > +}
> > +
> > +static enum es_result es_write_mem(struct es_em_ctxt *ctxt,
> > +  void *dst, char *buf, size_t size)
> > +{
> > +   memcpy(dst, buf, size);
> > +
> > +   return ES_OK;
> > +}
> > +
> > +static enum es_result es_read_mem(struct es_em_ctxt *ctxt,
> > + void *src, char *buf, size_t size)
> > +{
> > +   memcpy(buf, src, size);
> > +
> > +   return ES_OK;
> > +}
> 
> 
> What are all these abstractions for?

They are needed for the code in arch/x86/kernel/sev-es-shared.c. This
file is used in the pre-decompression boot code and in the running
kernels SEV-ES support.

The running kernel needs these abstraction because it will get #VC
exceptions from user-space and MMIO exits touching user-space addresses.
These functions will implement the necessary security checks.

Regards,

Joerg
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [PATCH 18/62] x86/boot/compressed/64: Setup GHCB Based VC Exception handler

2020-02-11 Thread Andy Lutomirski
On Tue, Feb 11, 2020 at 5:53 AM Joerg Roedel  wrote:
>
> From: Joerg Roedel 
>
> Install an exception handler for #VC exception that uses a GHCB. Also
> add the infrastructure for handling different exit-codes by decoding
> the instruction that caused the exception and error handling.
>

> diff --git a/arch/x86/boot/compressed/sev-es.c 
> b/arch/x86/boot/compressed/sev-es.c
> index 8d13121a8cf2..02fb6f57128b 100644
> --- a/arch/x86/boot/compressed/sev-es.c
> +++ b/arch/x86/boot/compressed/sev-es.c
> @@ -8,12 +8,16 @@
>  #include 
>
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
>
>  #include "misc.h"
>
> +struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
> +struct ghcb *boot_ghcb;
> +
>  static inline u64 read_ghcb_msr(void)
>  {
> unsigned long low, high;
> @@ -35,8 +39,95 @@ static inline void write_ghcb_msr(u64 val)
> "a"(low), "d" (high) : "memory");
>  }
>
> +static enum es_result es_fetch_insn_byte(struct es_em_ctxt *ctxt,
> +unsigned int offset,
> +char *buffer)
> +{
> +   char *rip = (char *)ctxt->regs->ip;
> +
> +   buffer[offset] = rip[offset];
> +
> +   return ES_OK;
> +}
> +
> +static enum es_result es_write_mem(struct es_em_ctxt *ctxt,
> +  void *dst, char *buf, size_t size)
> +{
> +   memcpy(dst, buf, size);
> +
> +   return ES_OK;
> +}
> +
> +static enum es_result es_read_mem(struct es_em_ctxt *ctxt,
> + void *src, char *buf, size_t size)
> +{
> +   memcpy(buf, src, size);
> +
> +   return ES_OK;
> +}


What are all these abstractions for?
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH 18/62] x86/boot/compressed/64: Setup GHCB Based VC Exception handler

2020-02-11 Thread Joerg Roedel
From: Joerg Roedel 

Install an exception handler for #VC exception that uses a GHCB. Also
add the infrastructure for handling different exit-codes by decoding
the instruction that caused the exception and error handling.

Signed-off-by: Joerg Roedel 
---
 arch/x86/Kconfig   |   1 +
 arch/x86/boot/compressed/idt_64.c  |   4 +
 arch/x86/boot/compressed/idt_handlers_64.S |   1 +
 arch/x86/boot/compressed/misc.h|   1 +
 arch/x86/boot/compressed/sev-es.c  |  91 +++
 arch/x86/include/asm/sev-es.h  |  33 
 arch/x86/include/uapi/asm/svm.h|   1 +
 arch/x86/kernel/sev-es-shared.c| 171 +
 8 files changed, 303 insertions(+)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index beea77046f9b..c12347492589 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1526,6 +1526,7 @@ config AMD_MEM_ENCRYPT
select DYNAMIC_PHYSICAL_MASK
select ARCH_USE_MEMREMAP_PROT
select ARCH_HAS_FORCE_DMA_UNENCRYPTED
+   select INSTRUCTION_DECODER
---help---
  Say yes to enable support for the encryption of system memory.
  This requires an AMD processor that supports Secure Memory
diff --git a/arch/x86/boot/compressed/idt_64.c 
b/arch/x86/boot/compressed/idt_64.c
index bdd20dfd1fd0..eebb2f857dac 100644
--- a/arch/x86/boot/compressed/idt_64.c
+++ b/arch/x86/boot/compressed/idt_64.c
@@ -45,5 +45,9 @@ void load_stage2_idt(void)
 
set_idt_entry(X86_TRAP_PF, boot_pf_handler);
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+   set_idt_entry(X86_TRAP_VC, boot_stage2_vc_handler);
+#endif
+
load_boot_idt(_idt_desc);
 }
diff --git a/arch/x86/boot/compressed/idt_handlers_64.S 
b/arch/x86/boot/compressed/idt_handlers_64.S
index 330eb4e5c8b3..3c71a11beee0 100644
--- a/arch/x86/boot/compressed/idt_handlers_64.S
+++ b/arch/x86/boot/compressed/idt_handlers_64.S
@@ -74,4 +74,5 @@ EXCEPTION_HANDLER boot_pf_handler do_boot_page_fault 
error_code=1
 
 #ifdef CONFIG_AMD_MEM_ENCRYPT
 EXCEPTION_HANDLER  boot_stage1_vc_handler no_ghcb_vc_handler error_code=1
+EXCEPTION_HANDLER  boot_stage2_vc_handler boot_vc_handler error_code=1
 #endif
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index 42f68a858a35..567d71ab5ed9 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -143,5 +143,6 @@ extern struct desc_ptr boot_idt_desc;
 /* IDT Entry Points */
 void boot_pf_handler(void);
 void boot_stage1_vc_handler(void);
+void boot_stage2_vc_handler(void);
 
 #endif /* BOOT_COMPRESSED_MISC_H */
diff --git a/arch/x86/boot/compressed/sev-es.c 
b/arch/x86/boot/compressed/sev-es.c
index 8d13121a8cf2..02fb6f57128b 100644
--- a/arch/x86/boot/compressed/sev-es.c
+++ b/arch/x86/boot/compressed/sev-es.c
@@ -8,12 +8,16 @@
 #include 
 
 #include 
+#include 
 #include 
 #include 
 #include 
 
 #include "misc.h"
 
+struct ghcb boot_ghcb_page __aligned(PAGE_SIZE);
+struct ghcb *boot_ghcb;
+
 static inline u64 read_ghcb_msr(void)
 {
unsigned long low, high;
@@ -35,8 +39,95 @@ static inline void write_ghcb_msr(u64 val)
"a"(low), "d" (high) : "memory");
 }
 
+static enum es_result es_fetch_insn_byte(struct es_em_ctxt *ctxt,
+unsigned int offset,
+char *buffer)
+{
+   char *rip = (char *)ctxt->regs->ip;
+
+   buffer[offset] = rip[offset];
+
+   return ES_OK;
+}
+
+static enum es_result es_write_mem(struct es_em_ctxt *ctxt,
+  void *dst, char *buf, size_t size)
+{
+   memcpy(dst, buf, size);
+
+   return ES_OK;
+}
+
+static enum es_result es_read_mem(struct es_em_ctxt *ctxt,
+ void *src, char *buf, size_t size)
+{
+   memcpy(buf, src, size);
+
+   return ES_OK;
+}
+
 #undef __init
+#undef __pa
 #define __init
+#define __pa(x)((unsigned long)(x))
+
+#define __BOOT_COMPRESSED
+
+/* Basic instruction decoding support needed */
+#include "../../lib/inat.c"
+#include "../../lib/insn.c"
 
 /* Include code for early handlers */
 #include "../../kernel/sev-es-shared.c"
+
+static bool setup_ghcb(void)
+{
+   if (!sev_es_negotiate_protocol())
+   terminate(GHCB_SEV_ES_REASON_PROTOCOL_UNSUPPORTED);
+
+   if (set_page_decrypted((unsigned long)_ghcb_page))
+   return false;
+
+   /* Page is now mapped decrypted, clear it */
+   memset(_ghcb_page, 0, sizeof(boot_ghcb_page));
+
+   boot_ghcb = _ghcb_page;
+
+   /* Initialize lookup tables for the instruction decoder */
+   inat_init_tables();
+
+   return true;
+}
+
+void boot_vc_handler(struct pt_regs *regs)
+{
+   unsigned long exit_code = regs->orig_ax;
+   struct es_em_ctxt ctxt;
+   enum es_result result;
+
+   if (!boot_ghcb && !setup_ghcb())
+   terminate(GHCB_SEV_ES_REASON_GENERAL_REQUEST);
+
+