Re: [PATCH v6 42/76] x86/sev-es: Setup early #VC handler

2021-09-05 Thread Juergen Gross via Virtualization

On 04.09.21 11:39, Lai Jiangshan wrote:

@@ -363,6 +370,33 @@ SYM_CODE_START_LOCAL(early_idt_handler_common)
 jmp restore_regs_and_return_to_kernel
  SYM_CODE_END(early_idt_handler_common)

+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * VC Exception handler used during very early boot. The
+ * early_idt_handler_array can't be used because it returns via the
+ * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early.


Hello Joerg, Juergen

The commit ae755b5a4548 ("x86/paravirt: Switch iret pvops to ALTERNATIVE")
( https://lore.kernel.org/lkml/20210311142319.4723-12-jgr...@suse.com/ )
had been merged and the paravirt_iret is deferenced based via %rip.

Can INTERRUPT_RETURN still be a problem if early_idt_handler_array
is used instead for bringup IDT?


Even before my patch the dereferencing was done via %rip.

I vaguely remember having discussed the pvops usage with Joerg when he
wrote the SEV support. I'm not sure why pvops shouldn't have worked, but
I'm sure its usage makes no sense at all, as long as we don't have SEV
support for Xen PV guests.


Juergen


OpenPGP_0xB0DE9DD628BF132F.asc
Description: OpenPGP public key


OpenPGP_signature
Description: OpenPGP digital signature
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

Re: [PATCH v6 42/76] x86/sev-es: Setup early #VC handler

2020-09-01 Thread Borislav Petkov
On Tue, Sep 01, 2020 at 02:59:22PM +0200, Joerg Roedel wrote:
> True, but having a separate function might be handy when support for #VE
> and #HV is developed. Those might also need to setup their early
> handlers here, no?

Ok.

-- 
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


Re: [PATCH v6 42/76] x86/sev-es: Setup early #VC handler

2020-09-01 Thread Joerg Roedel
On Mon, Aug 31, 2020 at 11:45:41AM +0200, Borislav Petkov wrote:
> On Mon, Aug 24, 2020 at 10:54:37AM +0200, Joerg Roedel wrote:
> > +#ifdef CONFIG_AMD_MEM_ENCRYPT
> > +   /* VMM Communication Exception */
> > +   handler = fixup_pointer(vc_no_ghcb, physbase);
> > +   set_early_idt_handler(idt, X86_TRAP_VC, handler);
> 
> This function is used only once AFAICT - you might just as well add its
> three-lined body here and save yourself the function definition and
> ifdeffery above...

True, but having a separate function might be handy when support for #VE
and #HV is developed. Those might also need to setup their early
handlers here, no?

Regards,

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


Re: [PATCH v6 42/76] x86/sev-es: Setup early #VC handler

2020-08-31 Thread Borislav Petkov
On Mon, Aug 24, 2020 at 10:54:37AM +0200, Joerg Roedel wrote:
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> +static void set_early_idt_handler(gate_desc *idt, int n, void *handler)
> +{
> + struct idt_data data;
> + gate_desc desc;
> +
> + init_idt_data(, n, handler);
> + idt_init_desc(, );
> + native_write_idt_entry(idt, n, );
> +}
> +#endif
> +
> +static struct desc_ptr early_idt_descr __initdata = {
> + .size   = IDT_TABLE_SIZE - 1,
> + .address= 0 /* Needs physical address of idt_table - 
> initialized at runtime. */,
> +};
> +
> +void __init early_idt_setup(unsigned long physbase)
> +{
> + void __maybe_unused *handler;
> + gate_desc *idt;
> +
> + idt = fixup_pointer(idt_table, physbase);
> +
> +#ifdef CONFIG_AMD_MEM_ENCRYPT
> + /* VMM Communication Exception */
> + handler = fixup_pointer(vc_no_ghcb, physbase);
> + set_early_idt_handler(idt, X86_TRAP_VC, handler);

This function is used only once AFAICT - you might just as well add its
three-lined body here and save yourself the function definition and
ifdeffery above...

> +#endif
> +
> + /* Initialize IDT descriptor and load IDT */
> + early_idt_descr.address = (unsigned long)idt;
> + native_load_idt(_idt_descr);
> +}
> -- 
> 2.28.0
> 

-- 
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization


[PATCH v6 42/76] x86/sev-es: Setup early #VC handler

2020-08-24 Thread Joerg Roedel
From: Joerg Roedel 

Setup an early handler for #VC exceptions. There is no GHCB mapped
yet, so just re-use the vc_no_ghcb_handler. It can only handle CPUID
exit-codes, but that should be enough to get the kernel through
verify_cpu() and __startup_64() until it runs on virtual addresses.

Signed-off-by: Joerg Roedel 
Link: https://lore.kernel.org/r/20200724160336.5435-42-j...@8bytes.org
---
 arch/x86/include/asm/setup.h  |  1 +
 arch/x86/include/asm/sev-es.h |  3 +++
 arch/x86/kernel/head64.c  |  1 +
 arch/x86/kernel/head_64.S | 34 +
 arch/x86/kernel/idt.c | 36 +++
 5 files changed, 75 insertions(+)

diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index cafae86813ae..0ce6453c9272 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -53,6 +53,7 @@ extern unsigned long __startup_secondary_64(void);
 extern void startup_64_setup_env(unsigned long physbase);
 extern void early_idt_setup_early_handler(unsigned long physaddr);
 extern void early_load_idt(void);
+extern void early_idt_setup(unsigned long physbase);
 extern void __init do_early_exception(struct pt_regs *regs, int trapnr);
 
 #ifdef CONFIG_X86_INTEL_MID
diff --git a/arch/x86/include/asm/sev-es.h b/arch/x86/include/asm/sev-es.h
index 7c0807b84546..ec0e112a742b 100644
--- a/arch/x86/include/asm/sev-es.h
+++ b/arch/x86/include/asm/sev-es.h
@@ -73,4 +73,7 @@ static inline u64 lower_bits(u64 val, unsigned int bits)
return (val & mask);
 }
 
+/* Early IDT entry points for #VC handler */
+extern void vc_no_ghcb(void);
+
 #endif
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 41514ec1e6f0..250fae33bf66 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -39,6 +39,7 @@
 #include 
 #include 
 #include 
+#include 
 
 /*
  * Manage page tables very early on.
diff --git a/arch/x86/kernel/head_64.S b/arch/x86/kernel/head_64.S
index 4622940134a5..12bf6f11fd83 100644
--- a/arch/x86/kernel/head_64.S
+++ b/arch/x86/kernel/head_64.S
@@ -95,6 +95,13 @@ SYM_CODE_START_NOALIGN(startup_64)
 .Lon_kernel_cs:
UNWIND_HINT_EMPTY
 
+   /* Setup IDT - Needed for SEV-ES */
+   pushq   %rsi
+   /* early_idt_setup - physbase as first parameter */
+   leaq_text(%rip), %rdi
+   callearly_idt_setup
+   popq%rsi
+
/* Sanitize CPU configuration */
call verify_cpu
 
@@ -363,6 +370,33 @@ SYM_CODE_START_LOCAL(early_idt_handler_common)
jmp restore_regs_and_return_to_kernel
 SYM_CODE_END(early_idt_handler_common)
 
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+/*
+ * VC Exception handler used during very early boot. The
+ * early_idt_handler_array can't be used because it returns via the
+ * paravirtualized INTERRUPT_RETURN and pv-ops don't work that early.
+ */
+SYM_CODE_START_NOALIGN(vc_no_ghcb)
+   UNWIND_HINT_IRET_REGS offset=8
+
+   /* Build pt_regs */
+   PUSH_AND_CLEAR_REGS
+
+   /* Call C handler */
+   movq%rsp, %rdi
+   movqORIG_RAX(%rsp), %rsi
+   calldo_vc_no_ghcb
+
+   /* Unwind pt_regs */
+   POP_REGS
+
+   /* Remove Error Code */
+   addq$8, %rsp
+
+   /* Pure iret required here - don't use INTERRUPT_RETURN */
+   iretq
+SYM_CODE_END(vc_no_ghcb)
+#endif
 
 #define SYM_DATA_START_PAGE_ALIGNED(name)  \
SYM_START(name, SYM_L_GLOBAL, .balign PAGE_SIZE)
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c
index e2777cc264f5..0d560a1218e1 100644
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -11,6 +11,7 @@
 #include 
 #include 
 #include 
+#include 
 
 struct idt_data {
unsigned intvector;
@@ -408,3 +409,38 @@ void early_load_idt(void)
 {
load_idt(_descr);
 }
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+static void set_early_idt_handler(gate_desc *idt, int n, void *handler)
+{
+   struct idt_data data;
+   gate_desc desc;
+
+   init_idt_data(, n, handler);
+   idt_init_desc(, );
+   native_write_idt_entry(idt, n, );
+}
+#endif
+
+static struct desc_ptr early_idt_descr __initdata = {
+   .size   = IDT_TABLE_SIZE - 1,
+   .address= 0 /* Needs physical address of idt_table - 
initialized at runtime. */,
+};
+
+void __init early_idt_setup(unsigned long physbase)
+{
+   void __maybe_unused *handler;
+   gate_desc *idt;
+
+   idt = fixup_pointer(idt_table, physbase);
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+   /* VMM Communication Exception */
+   handler = fixup_pointer(vc_no_ghcb, physbase);
+   set_early_idt_handler(idt, X86_TRAP_VC, handler);
+#endif
+
+   /* Initialize IDT descriptor and load IDT */
+   early_idt_descr.address = (unsigned long)idt;
+   native_load_idt(_idt_descr);
+}
-- 
2.28.0

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org