From: Andrew Cooper <andrew.cooper3@citrix.com>
Subject: x86: document how stub exception recovery works

Describe how it is meant to work, even if one aspect of it will only be
taken care of subsequently.

Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
Reviewed-by: Jan Beulich <jbeulich@suse.com>

--- a/xen/arch/x86/extable.c
+++ b/xen/arch/x86/extable.c
@@ -94,6 +94,22 @@ search_exception_table(const struct cpu_
     if ( region && region->ex )
         return search_one_extable(region->ex, region->ex_end, regs->rip);
 
+    /*
+     * Emulation stubs (which are per-CPU) are constructed with a RET at the
+     * end, and are CALLed by the invoking code.
+     *
+     * An exception in the stubs may occur anywhere, so we first match any
+     * %rip in the correct stub, with a sanity check on %rsp too.  But, an
+     * entry in ex_table[] needs to be compile-time constant, so we register
+     * the fixup address using the invoking CALL's return address.
+     *
+     * To recover, we:
+     * 1) Emulate a pseudo-RET to get out of the stub.  We POP the return
+     *    address off the stack(s), use it to look up the fixup address, and
+     *    JMP there, then
+     * 2) Emulate a PUSH of 'token' onto the data stack to pass information
+     *    about the exception back to the invoking code.
+     */
     if ( regs->rip >= stub + STUB_BUF_SIZE / 2 &&
          regs->rip < stub + STUB_BUF_SIZE &&
          regs->rsp > (unsigned long)regs &&
