From 9c881ab372010b46655dfed0a3c5cd78b3ff8fa0 Mon Sep 17 00:00:00 2001 From: Alexey Makhalov Date: Mon, 30 Nov 2020 09:48:29 -0800 Subject: [PATCH 01/13] x86_64: VC exception stack support Linux 5.10 has introduced SEV-ES support. New (5th) exception stack was added: 'VC_stack'. 'struct exception_stacks' cannot be used to obtain the size of VC stack, as the size of VC stack is zero there. Try another structure 'struct cea_exception_stacks' first as it represents actual CPU entry area with valid stack sizes and guard pages. Handled the case if VC stack is not mapped (present). It happens when SEV-ES is not active or not supported. Signed-off-by: Alexey Makhalov Signed-off-by: Lianbo Jiang --- defs.h | 1 + x86_64.c | 48 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/defs.h b/defs.h index e1a18e9d0b4d..e468b1d99fcf 100644 --- a/defs.h +++ b/defs.h @@ -5938,6 +5938,7 @@ struct x86_64_pt_regs_offsets { struct x86_64_stkinfo { ulong ebase[NR_CPUS][MAX_EXCEPTION_STACKS]; int esize[MAX_EXCEPTION_STACKS]; + char available[NR_CPUS][MAX_EXCEPTION_STACKS]; ulong ibase[NR_CPUS]; int isize; int NMI_stack_index; diff --git a/x86_64.c b/x86_64.c index 939c8a9fddd4..23a40a04bbc4 100644 --- a/x86_64.c +++ b/x86_64.c @@ -1369,6 +1369,7 @@ x86_64_ist_init(void) ulong init_tss; struct machine_specific *ms; struct syment *boot_sp, *tss_sp, *ist_sp; + char *exc_stack_struct_name = NULL; ms = machdep->machspec; if (!(tss_sp = per_cpu_symbol_search("per_cpu__init_tss"))) { @@ -1444,25 +1445,40 @@ x86_64_ist_init(void) return; } - if (MEMBER_EXISTS("exception_stacks", "NMI_stack")) { + if (MEMBER_EXISTS("cea_exception_stacks", "NMI_stack")) { + /* The effective cpu entry area mapping with guard pages. */ + exc_stack_struct_name = "cea_exception_stacks"; + } else if (MEMBER_EXISTS("exception_stacks", "NMI_stack")) { + /* The exception stacks' physical storage. No guard pages and no VC stack. */ + exc_stack_struct_name = "exception_stacks"; + } + if (exc_stack_struct_name) { for (i = 0; i < MAX_EXCEPTION_STACKS; i++) { if (STREQ(ms->stkinfo.exception_stacks[i], "DEBUG")) - ms->stkinfo.esize[i] = MEMBER_SIZE("exception_stacks", "DB_stack"); + ms->stkinfo.esize[i] = MEMBER_SIZE(exc_stack_struct_name, "DB_stack"); else if (STREQ(ms->stkinfo.exception_stacks[i], "NMI")) - ms->stkinfo.esize[i] = MEMBER_SIZE("exception_stacks", "NMI_stack"); + ms->stkinfo.esize[i] = MEMBER_SIZE(exc_stack_struct_name, "NMI_stack"); else if (STREQ(ms->stkinfo.exception_stacks[i], "DOUBLEFAULT")) - ms->stkinfo.esize[i] = MEMBER_SIZE("exception_stacks", "DF_stack"); + ms->stkinfo.esize[i] = MEMBER_SIZE(exc_stack_struct_name, "DF_stack"); else if (STREQ(ms->stkinfo.exception_stacks[i], "MCE")) - ms->stkinfo.esize[i] = MEMBER_SIZE("exception_stacks", "MCE_stack"); + ms->stkinfo.esize[i] = MEMBER_SIZE(exc_stack_struct_name, "MCE_stack"); + else if (STREQ(ms->stkinfo.exception_stacks[i], "VC")) + ms->stkinfo.esize[i] = MEMBER_SIZE(exc_stack_struct_name, "VC_stack"); } /* - * Adjust the top-of-stack addresses down to the base stack address. + * Adjust the top-of-stack addresses down to the base stack address + * and set stack page availabilituy flag. */ for (c = 0; c < kt->cpus; c++) { for (i = 0; i < MAX_EXCEPTION_STACKS; i++) { - if (ms->stkinfo.ebase[c][i] == 0) - continue; - ms->stkinfo.ebase[c][i] -= ms->stkinfo.esize[i]; + if (ms->stkinfo.ebase[c][i]) + ms->stkinfo.ebase[c][i] -= ms->stkinfo.esize[i]; + + ms->stkinfo.available[c][i] = TRUE; + /* VC stack can be unmapped if SEV-ES is disabled or not supported. */ + if (STREQ(ms->stkinfo.exception_stacks[i], "VC") && + !accessible(ms->stkinfo.ebase[c][i])) + ms->stkinfo.available[c][i] = FALSE; } } @@ -1487,6 +1503,7 @@ x86_64_ist_init(void) else ms->stkinfo.esize[i] = esize; ms->stkinfo.ebase[c][i] -= ms->stkinfo.esize[i]; + ms->stkinfo.available[c][i] = TRUE; } } @@ -2842,7 +2859,8 @@ x86_64_eframe_search(struct bt_info *bt) !(NUM_IN_BITMAP(bt->cpumask, c))) continue; for (i = 0; i < MAX_EXCEPTION_STACKS; i++) { - if (ms->stkinfo.ebase[c][i] == 0) + if (ms->stkinfo.ebase[c][i] == 0 || + !ms->stkinfo.available[c][i]) break; bt->hp->esp = ms->stkinfo.ebase[c][i]; fprintf(fp, "CPU %d %s EXCEPTION STACK:", @@ -3288,7 +3306,8 @@ x86_64_in_exception_stack(struct bt_info *bt, int *estack_index) for (c = 0; !estack && (c < kt->cpus); c++) { for (i = 0; i < MAX_EXCEPTION_STACKS; i++) { - if (ms->stkinfo.ebase[c][i] == 0) + if (ms->stkinfo.ebase[c][i] == 0 || + !ms->stkinfo.available[c][i]) break; if ((rsp >= ms->stkinfo.ebase[c][i]) && (rsp < (ms->stkinfo.ebase[c][i] + @@ -5097,7 +5116,7 @@ skip_stage: ms->stkinfo.esize[estack]; console("x86_64_get_dumpfile_stack_frame: searching %s estack at %lx\n", ms->stkinfo.exception_stacks[estack], bt->stackbase); - if (!(bt->stackbase)) + if (!(bt->stackbase && ms->stkinfo.available[bt->tc->processor][estack])) goto skip_stage; bt->stackbuf = ms->irqstack; alter_stackbuf(bt); @@ -5380,6 +5399,8 @@ x86_64_exception_stacks_init(void) ms->stkinfo.exception_stacks[ist-1] = "DOUBLEFAULT"; if (strstr(buf, "machine")) ms->stkinfo.exception_stacks[ist-1] = "MCE"; + if (strstr(buf, "vmm")) + ms->stkinfo.exception_stacks[ist-1] = "VC"; } } @@ -5737,6 +5758,9 @@ x86_64_display_machine_stats(void) fprintf(fp, "%22s: %016lx", buf, machdep->machspec->stkinfo.ebase[c][i]); + if (!machdep->machspec->stkinfo.available[c][i]) + fprintf(fp, " [unavailable]"); + if (hide_offline_cpu(c)) fprintf(fp, " [OFFLINE]\n"); else -- 2.17.1