bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] x86_64: install emergency handler for double fault


From: Samuel Thibault
Subject: Re: [PATCH v2] x86_64: install emergency handler for double fault
Date: Fri, 4 Aug 2023 23:34:24 +0200
User-agent: NeoMutt/20170609 (1.8.3)

Applied, thanks!

Luca Dariz, le sam. 29 juil. 2023 19:45:14 +0200, a ecrit:
> * i386/i386/idt.c: add selector for the interrupt-specific stack
> * i386/i386/ktss.c: configure ist1 to use a dedicated stack
> * i386/i386/trap.c: add double fault handler, which just prints the
>   state and panics. There is not much else to do in this case but it's
>   useful for troubleshooting
> * x86_64/idt_inittab.S: allow to specify an interrupt stack for custom
>   handlers
> * x86_64/locore.S: add double fault handler
> ---
>  i386/i386/idt.c      | 12 +++++++++++-
>  i386/i386/ktss.c     |  4 +++-
>  i386/i386/trap.c     |  6 ++++++
>  x86_64/idt_inittab.S | 25 +++++++++++++------------
>  x86_64/locore.S      | 15 +++++++++++++++
>  5 files changed, 48 insertions(+), 14 deletions(-)
> 
> diff --git a/i386/i386/idt.c b/i386/i386/idt.c
> index cdfb9a88..caa44d71 100644
> --- a/i386/i386/idt.c
> +++ b/i386/i386/idt.c
> @@ -34,6 +34,10 @@ struct idt_init_entry
>       unsigned long entrypoint;
>       unsigned short vector;
>       unsigned short type;
> +#ifdef __x86_64__
> +     unsigned short ist;
> +     unsigned short pad_0;
> +#endif
>  };
>  extern struct idt_init_entry idt_inittab[];
>  
> @@ -49,7 +53,13 @@ idt_fill(struct real_gate *myidt)
>       /* Initialize the exception vectors from the idt_inittab.  */
>       while (iie->entrypoint)
>       {
> -             fill_idt_gate(myidt, iie->vector, iie->entrypoint, KERNEL_CS, 
> iie->type, 0);
> +             fill_idt_gate(myidt, iie->vector, iie->entrypoint, KERNEL_CS, 
> iie->type,
> +#ifdef __x86_64__
> +                           iie->ist
> +#else
> +                           0
> +#endif
> +                 );
>               iie++;
>       }
>  
> diff --git a/i386/i386/ktss.c b/i386/i386/ktss.c
> index 1d880167..34cb6df2 100644
> --- a/i386/i386/ktss.c
> +++ b/i386/i386/ktss.c
> @@ -43,9 +43,10 @@ struct task_tss ktss;
>  void
>  ktss_fill(struct task_tss *myktss, struct real_descriptor *mygdt)
>  {
> -     /* XXX temporary exception stack */
> +     /* XXX temporary exception stacks */
>       /* FIXME: make it per-processor */
>       static int exception_stack[1024];
> +     static int double_fault_stack[1024];
>  
>  #ifdef       MACH_RING1
>       /* Xen won't allow us to do any I/O by default anyway, just register
> @@ -61,6 +62,7 @@ ktss_fill(struct task_tss *myktss, struct real_descriptor 
> *mygdt)
>       /* Initialize the master TSS.  */
>  #ifdef __x86_64__
>       myktss->tss.rsp0 = (unsigned long)(exception_stack+1024);
> +     myktss->tss.ist1 = (unsigned long)(double_fault_stack+1024);
>  #else /* ! __x86_64__ */
>       myktss->tss.ss0 = KERNEL_DS;
>       myktss->tss.esp0 = (unsigned long)(exception_stack+1024);
> diff --git a/i386/i386/trap.c b/i386/i386/trap.c
> index f7bd8e38..b3689c9a 100644
> --- a/i386/i386/trap.c
> +++ b/i386/i386/trap.c
> @@ -666,3 +666,9 @@ db_debug_all_traps (boolean_t enable)
>  }
>  
>  #endif       /* MACH_KDB */
> +
> +void handle_double_fault(struct i386_saved_state *regs)
> +{
> +  dump_ss(regs);
> +  panic("DOUBLE FAULT! This is critical\n");
> +}
> diff --git a/x86_64/idt_inittab.S b/x86_64/idt_inittab.S
> index f021b56d..fc1df0c7 100644
> --- a/x86_64/idt_inittab.S
> +++ b/x86_64/idt_inittab.S
> @@ -50,12 +50,13 @@ ENTRY(idt_inittab)
>       .quad   entry           ;\
>       .text
>  #else        /* MACH_PV_DESCRIPTORS */
> -#define      IDT_ENTRY(n,entry,type) \
> +#define      IDT_ENTRY(n,entry,type,ist) \
>       .data   2               ;\
>       .quad   entry           ;\
>       .word   n               ;\
>       .word   type            ;\
> -     .long   0       /*pad*/ ;\
> +     .word   ist             ;\
> +     .word   0       /*pad*/ ;\
>       .text
>  #endif       /* MACH_PV_DESCRIPTORS */
>  
> @@ -63,7 +64,7 @@ ENTRY(idt_inittab)
>   * No error code.  Clear error code and push trap number.
>   */
>  #define      EXCEPTION(n,name) \
> -     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_TRAP_GATE);\
> +     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_TRAP_GATE, 0);\
>  ENTRY(name)                          ;\
>       INT_FIX                         ;\
>       pushq   $(0)                    ;\
> @@ -74,7 +75,7 @@ ENTRY(name)                         ;\
>   * User-accessible exception.  Otherwise, same as above.
>   */
>  #define      EXCEP_USR(n,name) \
> -     IDT_ENTRY(n,EXT(name),ACC_PL_U|ACC_TRAP_GATE);\
> +     IDT_ENTRY(n,EXT(name),ACC_PL_U|ACC_TRAP_GATE, 0);\
>  ENTRY(name)                          ;\
>       INT_FIX                         ;\
>       pushq   $(0)                    ;\
> @@ -85,7 +86,7 @@ ENTRY(name)                         ;\
>   * Error code has been pushed.  Just push trap number.
>   */
>  #define      EXCEP_ERR(n,name) \
> -     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_INTR_GATE);\
> +     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_INTR_GATE, 0);\
>  ENTRY(name)                          ;\
>       INT_FIX                         ;\
>       pushq   $(n)                    ;\
> @@ -95,25 +96,25 @@ ENTRY(name)                               ;\
>   * Special interrupt code: dispatches to a unique entrypoint,
>   * not defined automatically here.
>   */
> -#define      EXCEP_SPC(n,name)  \
> -     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_TRAP_GATE)
> +#define      EXCEP_SPC(n,name, ist)  \
> +     IDT_ENTRY(n,EXT(name),ACC_PL_K|ACC_TRAP_GATE, ist)
>  
>  
>  EXCEPTION(0x00,t_zero_div)
> -EXCEP_SPC(0x01,t_debug)
> +EXCEP_SPC(0x01,t_debug, 0)
>  /* skip NMI interrupt - let more specific code figure that out.  */
>  EXCEP_USR(0x03,t_int3)
>  EXCEP_USR(0x04,t_into)
>  EXCEP_USR(0x05,t_bounds)
>  EXCEPTION(0x06,t_invop)
>  EXCEPTION(0x07,t_nofpu)
> -EXCEPTION(0x08,a_dbl_fault)
> +EXCEP_SPC(0x08,t_dbl_fault, 1)
>  EXCEPTION(0x09,a_fpu_over)
>  EXCEPTION(0x0a,a_inv_tss)
> -EXCEP_SPC(0x0b,t_segnp)
> +EXCEP_SPC(0x0b,t_segnp, 0)
>  EXCEP_ERR(0x0c,t_stack_fault)
> -EXCEP_SPC(0x0d,t_gen_prot)
> -EXCEP_SPC(0x0e,t_page_fault)
> +EXCEP_SPC(0x0d,t_gen_prot, 0)
> +EXCEP_SPC(0x0e,t_page_fault, 0)
>  #ifdef MACH_PV_DESCRIPTORS
>  EXCEP_ERR(0x0f,t_trap_0f)
>  #else
> diff --git a/x86_64/locore.S b/x86_64/locore.S
> index 2938e430..16b0dde5 100644
> --- a/x86_64/locore.S
> +++ b/x86_64/locore.S
> @@ -345,6 +345,21 @@ ENTRY(start_timer)
>   *
>   */
>  
> +/* Try to save/show some information when a double fault happens
> + * We can't recover to a working state, so if we have a debugger wait for it,
> + * otherwise reset */
> +ENTRY(t_dbl_fault)
> +     INT_FIX
> +     cli     /* disable interrupts that might corrupt the state*/
> +     pusha
> +     movq    %cr2,%rax
> +     movq    %rax,R_CR2-R_R15(%rsp)  /* CR2 might contain the faulting 
> address */
> +     subq    $48,%rsp        // FIXME remove when segments are cleaned up
> +     movq    %rsp,%rdi               /* pass the saved state */
> +     call    handle_double_fault
> +     jmp     cpu_shutdown    /* reset */
> +END(t_dbl_fault)
> +
>  /*
>   * General protection or segment-not-present fault.
>   * Check for a GP/NP fault in the kernel_return
> -- 
> 2.39.2
> 
> 

-- 
Samuel
---
Pour une évaluation indépendante, transparente et rigoureuse !
Je soutiens la Commission d'Évaluation de l'Inria.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]