aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/dumpstack_64.c82
1 files changed, 51 insertions, 31 deletions
diff --git a/arch/x86/kernel/dumpstack_64.c b/arch/x86/kernel/dumpstack_64.c
index fca97bd3d8ae..f356d3ea0c70 100644
--- a/arch/x86/kernel/dumpstack_64.c
+++ b/arch/x86/kernel/dumpstack_64.c
@@ -50,52 +50,72 @@ const char *stack_type_name(enum stack_type type)
50 return NULL; 50 return NULL;
51} 51}
52 52
53struct estack_layout { 53/**
54 unsigned int begin; 54 * struct estack_pages - Page descriptor for exception stacks
55 unsigned int end; 55 * @offs: Offset from the start of the exception stack area
56 * @size: Size of the exception stack
57 * @type: Type to store in the stack_info struct
58 */
59struct estack_pages {
60 u32 offs;
61 u16 size;
62 u16 type;
56}; 63};
57 64
58#define ESTACK_ENTRY(x) { \ 65#define EPAGERANGE(st) \
59 .begin = offsetof(struct cea_exception_stacks, x## _stack), \ 66 [PFN_DOWN(CEA_ESTACK_OFFS(st)) ... \
60 .end = offsetof(struct cea_exception_stacks, x## _stack_guard) \ 67 PFN_DOWN(CEA_ESTACK_OFFS(st) + CEA_ESTACK_SIZE(st) - 1)] = { \
61 } 68 .offs = CEA_ESTACK_OFFS(st), \
69 .size = CEA_ESTACK_SIZE(st), \
70 .type = STACK_TYPE_EXCEPTION + ESTACK_ ##st, }
62 71
63static const struct estack_layout layout[] = { 72/*
64 [ ESTACK_DF ] = ESTACK_ENTRY(DF), 73 * Array of exception stack page descriptors. If the stack is larger than
65 [ ESTACK_NMI ] = ESTACK_ENTRY(NMI), 74 * PAGE_SIZE, all pages covering a particular stack will have the same
66 [ ESTACK_DB2 ] = { .begin = 0, .end = 0}, 75 * info. The guard pages including the not mapped DB2 stack are zeroed
67 [ ESTACK_DB1 ] = ESTACK_ENTRY(DB1), 76 * out.
68 [ ESTACK_DB ] = ESTACK_ENTRY(DB), 77 */
69 [ ESTACK_MCE ] = ESTACK_ENTRY(MCE), 78static const
79struct estack_pages estack_pages[CEA_ESTACK_PAGES] ____cacheline_aligned = {
80 EPAGERANGE(DF),
81 EPAGERANGE(NMI),
82 EPAGERANGE(DB1),
83 EPAGERANGE(DB),
84 EPAGERANGE(MCE),
70}; 85};
71 86
72static bool in_exception_stack(unsigned long *stack, struct stack_info *info) 87static bool in_exception_stack(unsigned long *stack, struct stack_info *info)
73{ 88{
74 unsigned long estacks, begin, end, stk = (unsigned long)stack; 89 unsigned long begin, end, stk = (unsigned long)stack;
90 const struct estack_pages *ep;
75 struct pt_regs *regs; 91 struct pt_regs *regs;
76 unsigned int k; 92 unsigned int k;
77 93
78 BUILD_BUG_ON(N_EXCEPTION_STACKS != 6); 94 BUILD_BUG_ON(N_EXCEPTION_STACKS != 6);
79 95
80 estacks = (unsigned long)__this_cpu_read(cea_exception_stacks); 96 begin = (unsigned long)__this_cpu_read(cea_exception_stacks);
81 97 end = begin + sizeof(struct cea_exception_stacks);
82 for (k = 0; k < N_EXCEPTION_STACKS; k++) { 98 /* Bail if @stack is outside the exception stack area. */
83 begin = estacks + layout[k].begin; 99 if (stk < begin || stk >= end)
84 end = estacks + layout[k].end; 100 return false;
85 regs = (struct pt_regs *)end - 1;
86 101
87 if (stk < begin || stk >= end) 102 /* Calc page offset from start of exception stacks */
88 continue; 103 k = (stk - begin) >> PAGE_SHIFT;
104 /* Lookup the page descriptor */
105 ep = &estack_pages[k];
106 /* Guard page? */
107 if (!ep->size)
108 return false;
89 109
90 info->type = STACK_TYPE_EXCEPTION + k; 110 begin += (unsigned long)ep->offs;
91 info->begin = (unsigned long *)begin; 111 end = begin + (unsigned long)ep->size;
92 info->end = (unsigned long *)end; 112 regs = (struct pt_regs *)end - 1;
93 info->next_sp = (unsigned long *)regs->sp;
94 113
95 return true; 114 info->type = ep->type;
96 } 115 info->begin = (unsigned long *)begin;
97 116 info->end = (unsigned long *)end;
98 return false; 117 info->next_sp = (unsigned long *)regs->sp;
118 return true;
99} 119}
100 120
101static bool in_irq_stack(unsigned long *stack, struct stack_info *info) 121static bool in_irq_stack(unsigned long *stack, struct stack_info *info)