[PATCH v3 45/75] x86/dumpstack/64: Handle #VC exception stacks

Joerg Roedel
2020-04-28T15:21:35Z

From: Joerg Roedel <jroedel@suse.de>

Make the stack unwinder aware of the IST stacks for the #VC exception
handler.

Signed-off-by: Joerg Roedel <jroedel@suse.de>
---
arch/x86/include/asm/cpu_entry_area.h | 1 +
arch/x86/include/asm/sev-es.h | 13 ++++++++
arch/x86/include/asm/stacktrace.h | 4 +++
arch/x86/kernel/dumpstack_64.c | 47 +++++++++++++++++++++++++++
arch/x86/kernel/sev-es.c | 26 +++++++++++++++
5 files changed, 91 insertions(+)

diff --git a/arch/x86/include/asm/cpu_entry_area.h b/arch/x86/include/asm/cpu_entry_area.h
index 85aac6c63653..e4216caad01a 100644
--- a/arch/x86/include/asm/cpu_entry_area.h
+++ b/arch/x86/include/asm/cpu_entry_area.h
@@ -192,6 +192,7 @@ struct cpu_entry_area {

DECLARE_PER_CPU(struct cpu_entry_area *, cpu_entry_area);
DECLARE_PER_CPU(struct cea_exception_stacks *, cea_exception_stacks);
+DECLARE_PER_CPU(struct cea_vmm_exception_stacks *, cea_vmm_exception_stacks);

extern void setup_cpu_entry_areas(void);
extern void cea_set_pte(void *cea_vaddr, phys_addr_t pa, pgprot_t flags);
diff --git a/arch/x86/include/asm/sev-es.h b/arch/x86/include/asm/sev-es.h
index e1ed963a57ec..265da8351475 100644
--- a/arch/x86/include/asm/sev-es.h
+++ b/arch/x86/include/asm/sev-es.h
@@ -9,6 +9,8 @@
#define __ASM_ENCRYPTED_STATE_H

#include <linux/types.h>
+
+#include <asm/stacktrace.h>
#include <asm/insn.h>

#define GHCB_SEV_INFO 0x001UL
@@ -76,4 +78,15 @@ static inline u64 lower_bits(u64 val, unsigned int bits)
extern void vc_no_ghcb(void);
extern bool vc_boot_ghcb(struct pt_regs *regs);

+enum stack_type;
+
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+const char *vc_stack_name(enum stack_type type);
+#else /* CONFIG_AMD_MEM_ENCRYPT */
+static inline const char *vc_stack_name(enum stack_type type)
+{
+ return NULL;
+}
+#endif /* CONFIG_AMD_MEM_ENCRYPT*/
+
#endif
diff --git a/arch/x86/include/asm/stacktrace.h b/arch/x86/include/asm/stacktrace.h
index 14db05086bbf..2f3534ef4b5f 100644
--- a/arch/x86/include/asm/stacktrace.h
+++ b/arch/x86/include/asm/stacktrace.h
@@ -21,6 +21,10 @@ enum stack_type {
STACK_TYPE_ENTRY,
STACK_TYPE_EXCEPTION,
STACK_TYPE_EXCEPTION_LAST = STACK_TYPE_EXCEPTION + N_EXCEPTION_STACKS-1,
+#ifdef CONFIG_X86_64
+ STACK_TYPE_VC,
+ STACK_TYPE_VC_LAST = STACK_TYPE_VC + N_VC_STACKS - 1,
+#endif
};

struct stack_info {
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index 87b97897a881..2468963c1424 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -18,6 +18,7 @@

#include <asm/cpu_entry_area.h>
#include <asm/stacktrace.h>
+#include <asm/sev-es.h>

static const char * const exception_stack_names[] = {
[ ESTACK_DF ] = "#DF",
@@ -47,6 +48,9 @@ const char *stack_type_name(enum stack_type type)
if (type >= STACK_TYPE_EXCEPTION && type <= STACK_TYPE_EXCEPTION_LAST)
return exception_stack_names[type - STACK_TYPE_EXCEPTION];

+ if (type >= STACK_TYPE_VC && type <= STACK_TYPE_VC_LAST)
+ return vc_stack_name(type);
+
return NULL;
}

@@ -84,6 +88,46 @@ struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = {
EPAGERANGE(MCE),
};

+static bool in_vc_exception_stack(unsigned long *stack, struct stack_info *info)
+{
+#ifdef CONFIG_AMD_MEM_ENCRYPT
+ unsigned long begin, end, stk = (unsigned long)stack;
+ struct cea_vmm_exception_stacks *vc_stacks;
+ struct pt_regs *regs;
+ enum stack_type type;
+ int i;
+
+ vc_stacks = __this_cpu_read(cea_vmm_exception_stacks);
+
+ /* Already initialized? */
+ if (!vc_stacks)
+ return false;
+
+ for (i = 0; i < N_VC_STACKS; i++) {
+ type = STACK_TYPE_VC_LAST - i;
+ begin = (unsigned long)vc_stacks->stacks[i].stack;
+ end = begin + sizeof(vc_stacks->stacks[i].stack);
+
+ if (stk >= begin && stk < end)
+ goto found;
+ }
+
+ return false;
+
+found:
+
+ regs = (struct pt_regs *)end - 1;
+ info->type = type;
+ info->begin = (unsigned long *)begin;
+ info->end = (unsigned long *)end;
+ info->next_sp = (unsigned long *)regs->sp;
+
+ return true;
+#else
+ return false;
+#endif
+}
+
static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
{
unsigned long begin, end, stk = (unsigned long)stack;
@@ -173,6 +217,9 @@ int get_stack_info(unsigned long *stack, struct task_struct *task,
if (in_entry_stack(stack, info))
goto recursion_check;

+ if (in_vc_exception_stack(stack, info))
+ goto recursion_check;
+
goto unknown;

recursion_check:
diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c
index e5d87f2af357..dd60d24db3d0 100644
--- a/arch/x86/kernel/sev-es.c
+++ b/arch/x86/kernel/sev-es.c
@@ -18,6 +18,7 @@
#include <linux/mm.h>

#include <asm/cpu_entry_area.h>
+#include <asm/stacktrace.h>
#include <asm/trap_defs.h>
#include <asm/sev-es.h>
#include <asm/insn-eval.h>
@@ -34,6 +35,9 @@ static struct ghcb boot_ghcb_page __bss_decrypted __aligned(PAGE_SIZE);
* cleared
*/
static struct ghcb __initdata *boot_ghcb;
+DEFINE_PER_CPU(struct cea_vmm_exception_stacks *, cea_vmm_exception_stacks);
+
+static char vc_stack_names[N_VC_STACKS][8];

/* #VC handler runtime per-cpu data */
struct sev_es_runtime_data {
@@ -240,6 +244,16 @@ static void __init sev_es_init_ghcb(int cpu)
memset(&data->ghcb_page, 0, sizeof(data->ghcb_page));
}

+static void __init init_vc_stack_names(void)
+{
+ int i;
+
+ for (i = 0; i < N_VC_STACKS; i++) {
+ snprintf(vc_stack_names[i], sizeof(vc_stack_names[i]),
+ "#VC%d", i);
+ }
+}
+
static void __init sev_es_setup_vc_stack(int cpu)
{
struct vmm_exception_stacks *stack;
@@ -272,6 +286,8 @@ static void __init sev_es_setup_vc_stack(int cpu)
tss = per_cpu_ptr(&cpu_tss_rw, cpu);

tss->x86_tss.ist[IST_INDEX_VC] = (unsigned long)first_stack + size;
+
+ per_cpu(cea_vmm_exception_stacks, cpu) = &cea->vc_stacks;
}

void __init sev_es_init_vc_handling(void)
@@ -290,6 +306,16 @@ void __init sev_es_init_vc_handling(void)
sev_es_init_ghcb(cpu);
sev_es_setup_vc_stack(cpu);
}
+
+ init_vc_stack_names();
+}
+
+const char *vc_stack_name(enum stack_type type)
+{
+ if (type < STACK_TYPE_VC || type > STACK_TYPE_VC_LAST)
+ return NULL;
+
+ return vc_stack_names[type - STACK_TYPE_VC];
}

static void __init vc_early_vc_forward_exception(struct es_em_ctxt *ctxt)
--
2.17.1