In 32bit, if not stack switch occurs, this information isn't present in an
exception frame. As a result, regs->sp and regs->ss may actually alias the
interrupted stack frame. To avoid accidental incorrect use, prefix the names
in cpu_regs with an underscore.
Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
return true;
}
+unsigned long cpu_regs_sp(const struct cpu_regs *regs)
+{
+#ifdef __x86_64__
+ return regs->_sp;
+#else
+ unsigned int cs = read_cs();
+
+ if ( (regs->cs & 3) > (cs & 3) )
+ return regs->_sp;
+
+ return (unsigned long)regs + offsetof(struct cpu_regs, _sp);
+#endif
+}
+
+unsigned int cpu_regs_ss(const struct cpu_regs *regs)
+{
+#ifdef __x86_64__
+ return regs->_ss;
+#else
+ unsigned int cs = read_cs();
+
+ if ( (regs->cs & 3) > (cs & 3) )
+ return regs->_ss;
+
+ return read_ss();
+#endif
+}
+
/*
* C entry-point for exceptions, after the per-environment stubs have suitably
* adjusted the stack.
#define DECL_REG(n) \
union { uint32_t e ## n; unsigned long n; }
+#define _DECL_REG(n) \
+ union { uint32_t _e ## n; unsigned long _ ## n; }
struct cpu_regs {
DECL_REG(bp);
DECL_REG(ip);
uint16_t cs, _pad1[1];
DECL_REG(flags);
- DECL_REG(sp); /* Won't be valid if stack */
- uint16_t ss, _pad0[1]; /* switch didn't occur. */
+ _DECL_REG(sp); /* Won't be valid if stack */
+ uint16_t _ss, _pad0[1]; /* switch didn't occur. */
/* Top of stack. */
};
#define DECL_REG(n) \
union { uint64_t r ## n; uint32_t e ## n; unsigned long n; }
+#define _DECL_REG(n) \
+ union { uint64_t _r ## n; uint32_t _e ## n; unsigned long _ ## n; }
struct cpu_regs {
uint64_t r15;
DECL_REG(ip);
uint16_t cs, _pad1[3];
DECL_REG(flags);
- DECL_REG(sp);
- uint16_t ss, _pad0[3];
+ _DECL_REG(sp);
+ uint16_t _ss, _pad0[3];
/* Top of stack. */
};
*/
void __noreturn arch_crash_hard(void);
+/*
+ * Return the correct %ss/%esp from an exception. In 32bit if no stack switch
+ * occurs, an exception frame doesn't contain this information.
+ */
+unsigned long cpu_regs_sp(const struct cpu_regs *regs);
+unsigned int cpu_regs_ss(const struct cpu_regs *regs);
+
extern uint8_t boot_stack[2 * PAGE_SIZE];
#if defined(CONFIG_PV)