LCOV - code coverage report
Current view: top level - arch/x86/kernel - idt.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 65 74 87.8 %
Date: 2022-03-28 16:04:14 Functions: 10 12 83.3 %
Branches: 15 22 68.2 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Interrupt descriptor table related code
       4                 :            :  */
       5                 :            : #include <linux/interrupt.h>
       6                 :            : 
       7                 :            : #include <asm/traps.h>
       8                 :            : #include <asm/proto.h>
       9                 :            : #include <asm/desc.h>
      10                 :            : #include <asm/hw_irq.h>
      11                 :            : 
      12                 :            : struct idt_data {
      13                 :            :         unsigned int    vector;
      14                 :            :         unsigned int    segment;
      15                 :            :         struct idt_bits bits;
      16                 :            :         const void      *addr;
      17                 :            : };
      18                 :            : 
      19                 :            : #define DPL0            0x0
      20                 :            : #define DPL3            0x3
      21                 :            : 
      22                 :            : #define DEFAULT_STACK   0
      23                 :            : 
      24                 :            : #define G(_vector, _addr, _ist, _type, _dpl, _segment)  \
      25                 :            :         {                                               \
      26                 :            :                 .vector         = _vector,              \
      27                 :            :                 .bits.ist       = _ist,                 \
      28                 :            :                 .bits.type      = _type,                \
      29                 :            :                 .bits.dpl       = _dpl,                 \
      30                 :            :                 .bits.p         = 1,                    \
      31                 :            :                 .addr           = _addr,                \
      32                 :            :                 .segment        = _segment,             \
      33                 :            :         }
      34                 :            : 
      35                 :            : /* Interrupt gate */
      36                 :            : #define INTG(_vector, _addr)                            \
      37                 :            :         G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL0, __KERNEL_CS)
      38                 :            : 
      39                 :            : /* System interrupt gate */
      40                 :            : #define SYSG(_vector, _addr)                            \
      41                 :            :         G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL3, __KERNEL_CS)
      42                 :            : 
      43                 :            : /*
      44                 :            :  * Interrupt gate with interrupt stack. The _ist index is the index in
      45                 :            :  * the tss.ist[] array, but for the descriptor it needs to start at 1.
      46                 :            :  */
      47                 :            : #define ISTG(_vector, _addr, _ist)                      \
      48                 :            :         G(_vector, _addr, _ist + 1, GATE_INTERRUPT, DPL0, __KERNEL_CS)
      49                 :            : 
      50                 :            : /* Task gate */
      51                 :            : #define TSKG(_vector, _gdt)                             \
      52                 :            :         G(_vector, NULL, DEFAULT_STACK, GATE_TASK, DPL0, _gdt << 3)
      53                 :            : 
      54                 :            : /*
      55                 :            :  * Early traps running on the DEFAULT_STACK because the other interrupt
      56                 :            :  * stacks work only after cpu_init().
      57                 :            :  */
      58                 :            : static const __initconst struct idt_data early_idts[] = {
      59                 :            :         INTG(X86_TRAP_DB,               debug),
      60                 :            :         SYSG(X86_TRAP_BP,               int3),
      61                 :            : #ifdef CONFIG_X86_32
      62                 :            :         INTG(X86_TRAP_PF,               page_fault),
      63                 :            : #endif
      64                 :            : };
      65                 :            : 
      66                 :            : /*
      67                 :            :  * The default IDT entries which are set up in trap_init() before
      68                 :            :  * cpu_init() is invoked. Interrupt stacks cannot be used at that point and
      69                 :            :  * the traps which use them are reinitialized with IST after cpu_init() has
      70                 :            :  * set up TSS.
      71                 :            :  */
      72                 :            : static const __initconst struct idt_data def_idts[] = {
      73                 :            :         INTG(X86_TRAP_DE,               divide_error),
      74                 :            :         INTG(X86_TRAP_NMI,              nmi),
      75                 :            :         INTG(X86_TRAP_BR,               bounds),
      76                 :            :         INTG(X86_TRAP_UD,               invalid_op),
      77                 :            :         INTG(X86_TRAP_NM,               device_not_available),
      78                 :            :         INTG(X86_TRAP_OLD_MF,           coprocessor_segment_overrun),
      79                 :            :         INTG(X86_TRAP_TS,               invalid_TSS),
      80                 :            :         INTG(X86_TRAP_NP,               segment_not_present),
      81                 :            :         INTG(X86_TRAP_SS,               stack_segment),
      82                 :            :         INTG(X86_TRAP_GP,               general_protection),
      83                 :            :         INTG(X86_TRAP_SPURIOUS,         spurious_interrupt_bug),
      84                 :            :         INTG(X86_TRAP_MF,               coprocessor_error),
      85                 :            :         INTG(X86_TRAP_AC,               alignment_check),
      86                 :            :         INTG(X86_TRAP_XF,               simd_coprocessor_error),
      87                 :            : 
      88                 :            : #ifdef CONFIG_X86_32
      89                 :            :         TSKG(X86_TRAP_DF,               GDT_ENTRY_DOUBLEFAULT_TSS),
      90                 :            : #else
      91                 :            :         INTG(X86_TRAP_DF,               double_fault),
      92                 :            : #endif
      93                 :            :         INTG(X86_TRAP_DB,               debug),
      94                 :            : 
      95                 :            : #ifdef CONFIG_X86_MCE
      96                 :            :         INTG(X86_TRAP_MC,               &machine_check),
      97                 :            : #endif
      98                 :            : 
      99                 :            :         SYSG(X86_TRAP_OF,               overflow),
     100                 :            : #if defined(CONFIG_IA32_EMULATION)
     101                 :            :         SYSG(IA32_SYSCALL_VECTOR,       entry_INT80_compat),
     102                 :            : #elif defined(CONFIG_X86_32)
     103                 :            :         SYSG(IA32_SYSCALL_VECTOR,       entry_INT80_32),
     104                 :            : #endif
     105                 :            : };
     106                 :            : 
     107                 :            : /*
     108                 :            :  * The APIC and SMP idt entries
     109                 :            :  */
     110                 :            : static const __initconst struct idt_data apic_idts[] = {
     111                 :            : #ifdef CONFIG_SMP
     112                 :            :         INTG(RESCHEDULE_VECTOR,         reschedule_interrupt),
     113                 :            :         INTG(CALL_FUNCTION_VECTOR,      call_function_interrupt),
     114                 :            :         INTG(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt),
     115                 :            :         INTG(IRQ_MOVE_CLEANUP_VECTOR,   irq_move_cleanup_interrupt),
     116                 :            :         INTG(REBOOT_VECTOR,             reboot_interrupt),
     117                 :            : #endif
     118                 :            : 
     119                 :            : #ifdef CONFIG_X86_THERMAL_VECTOR
     120                 :            :         INTG(THERMAL_APIC_VECTOR,       thermal_interrupt),
     121                 :            : #endif
     122                 :            : 
     123                 :            : #ifdef CONFIG_X86_MCE_THRESHOLD
     124                 :            :         INTG(THRESHOLD_APIC_VECTOR,     threshold_interrupt),
     125                 :            : #endif
     126                 :            : 
     127                 :            : #ifdef CONFIG_X86_MCE_AMD
     128                 :            :         INTG(DEFERRED_ERROR_VECTOR,     deferred_error_interrupt),
     129                 :            : #endif
     130                 :            : 
     131                 :            : #ifdef CONFIG_X86_LOCAL_APIC
     132                 :            :         INTG(LOCAL_TIMER_VECTOR,        apic_timer_interrupt),
     133                 :            :         INTG(X86_PLATFORM_IPI_VECTOR,   x86_platform_ipi),
     134                 :            : # ifdef CONFIG_HAVE_KVM
     135                 :            :         INTG(POSTED_INTR_VECTOR,        kvm_posted_intr_ipi),
     136                 :            :         INTG(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi),
     137                 :            :         INTG(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi),
     138                 :            : # endif
     139                 :            : # ifdef CONFIG_IRQ_WORK
     140                 :            :         INTG(IRQ_WORK_VECTOR,           irq_work_interrupt),
     141                 :            : # endif
     142                 :            : #ifdef CONFIG_X86_UV
     143                 :            :         INTG(UV_BAU_MESSAGE,            uv_bau_message_intr1),
     144                 :            : #endif
     145                 :            :         INTG(SPURIOUS_APIC_VECTOR,      spurious_interrupt),
     146                 :            :         INTG(ERROR_APIC_VECTOR,         error_interrupt),
     147                 :            : #endif
     148                 :            : };
     149                 :            : 
     150                 :            : #ifdef CONFIG_X86_64
     151                 :            : /*
     152                 :            :  * Early traps running on the DEFAULT_STACK because the other interrupt
     153                 :            :  * stacks work only after cpu_init().
     154                 :            :  */
     155                 :            : static const __initconst struct idt_data early_pf_idts[] = {
     156                 :            :         INTG(X86_TRAP_PF,               page_fault),
     157                 :            : };
     158                 :            : 
     159                 :            : /*
     160                 :            :  * Override for the debug_idt. Same as the default, but with interrupt
     161                 :            :  * stack set to DEFAULT_STACK (0). Required for NMI trap handling.
     162                 :            :  */
     163                 :            : static const __initconst struct idt_data dbg_idts[] = {
     164                 :            :         INTG(X86_TRAP_DB,       debug),
     165                 :            : };
     166                 :            : #endif
     167                 :            : 
     168                 :            : /* Must be page-aligned because the real IDT is used in a fixmap. */
     169                 :            : gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss;
     170                 :            : 
     171                 :            : struct desc_ptr idt_descr __ro_after_init = {
     172                 :            :         .size           = (IDT_ENTRIES * 2 * sizeof(unsigned long)) - 1,
     173                 :            :         .address        = (unsigned long) idt_table,
     174                 :            : };
     175                 :            : 
     176                 :            : #ifdef CONFIG_X86_64
     177                 :            : /* No need to be aligned, but done to keep all IDTs defined the same way. */
     178                 :            : gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
     179                 :            : 
     180                 :            : /*
     181                 :            :  * The exceptions which use Interrupt stacks. They are setup after
     182                 :            :  * cpu_init() when the TSS has been initialized.
     183                 :            :  */
     184                 :            : static const __initconst struct idt_data ist_idts[] = {
     185                 :            :         ISTG(X86_TRAP_DB,       debug,          IST_INDEX_DB),
     186                 :            :         ISTG(X86_TRAP_NMI,      nmi,            IST_INDEX_NMI),
     187                 :            :         ISTG(X86_TRAP_DF,       double_fault,   IST_INDEX_DF),
     188                 :            : #ifdef CONFIG_X86_MCE
     189                 :            :         ISTG(X86_TRAP_MC,       &machine_check,     IST_INDEX_MCE),
     190                 :            : #endif
     191                 :            : };
     192                 :            : 
     193                 :            : /*
     194                 :            :  * Override for the debug_idt. Same as the default, but with interrupt
     195                 :            :  * stack set to DEFAULT_STACK (0). Required for NMI trap handling.
     196                 :            :  */
     197                 :            : const struct desc_ptr debug_idt_descr = {
     198                 :            :         .size           = IDT_ENTRIES * 16 - 1,
     199                 :            :         .address        = (unsigned long) debug_idt_table,
     200                 :            : };
     201                 :            : #endif
     202                 :            : 
     203                 :       3679 : static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d)
     204                 :            : {
     205                 :       3679 :         unsigned long addr = (unsigned long) d->addr;
     206                 :            : 
     207                 :       3679 :         gate->offset_low     = (u16) addr;
     208                 :       3679 :         gate->segment                = (u16) d->segment;
     209                 :       3679 :         gate->bits           = d->bits;
     210                 :       3679 :         gate->offset_middle  = (u16) (addr >> 16);
     211                 :            : #ifdef CONFIG_X86_64
     212                 :       3679 :         gate->offset_high    = (u32) (addr >> 32);
     213                 :       3679 :         gate->reserved               = 0;
     214                 :            : #endif
     215                 :            : }
     216                 :            : 
     217                 :            : static void
     218                 :       3198 : idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size, bool sys)
     219                 :            : {
     220                 :       3198 :         gate_desc desc;
     221                 :            : 
     222         [ +  + ]:       6877 :         for (; size > 0; t++, size--) {
     223                 :       3679 :                 idt_init_desc(&desc, t);
     224         [ +  + ]:       3679 :                 write_idt_entry(idt, t->vector, &desc);
     225         [ +  + ]:       3679 :                 if (sys)
     226                 :        546 :                         set_bit(t->vector, system_vectors);
     227                 :            :         }
     228                 :       3198 : }
     229                 :            : 
     230                 :       3120 : static void set_intr_gate(unsigned int n, const void *addr)
     231                 :            : {
     232                 :       3120 :         struct idt_data data;
     233                 :            : 
     234         [ -  + ]:       3120 :         BUG_ON(n > 0xFF);
     235                 :            : 
     236                 :       3120 :         memset(&data, 0, sizeof(data));
     237                 :       3120 :         data.vector     = n;
     238                 :       3120 :         data.addr       = addr;
     239                 :       3120 :         data.segment    = __KERNEL_CS;
     240                 :       3120 :         data.bits.type  = GATE_INTERRUPT;
     241                 :       3120 :         data.bits.p     = 1;
     242                 :            : 
     243                 :       3120 :         idt_setup_from_table(idt_table, &data, 1, false);
     244                 :       3120 : }
     245                 :            : 
     246                 :            : /**
     247                 :            :  * idt_setup_early_traps - Initialize the idt table with early traps
     248                 :            :  *
     249                 :            :  * On X8664 these traps do not use interrupt stacks as they can't work
     250                 :            :  * before cpu_init() is invoked and sets up TSS. The IST variants are
     251                 :            :  * installed after that.
     252                 :            :  */
     253                 :         13 : void __init idt_setup_early_traps(void)
     254                 :            : {
     255                 :         13 :         idt_setup_from_table(idt_table, early_idts, ARRAY_SIZE(early_idts),
     256                 :            :                              true);
     257                 :         13 :         load_idt(&idt_descr);
     258                 :         13 : }
     259                 :            : 
     260                 :            : /**
     261                 :            :  * idt_setup_traps - Initialize the idt table with default traps
     262                 :            :  */
     263                 :         13 : void __init idt_setup_traps(void)
     264                 :            : {
     265                 :         13 :         idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true);
     266                 :         13 : }
     267                 :            : 
     268                 :            : #ifdef CONFIG_X86_64
     269                 :            : /**
     270                 :            :  * idt_setup_early_pf - Initialize the idt table with early pagefault handler
     271                 :            :  *
     272                 :            :  * On X8664 this does not use interrupt stacks as they can't work before
     273                 :            :  * cpu_init() is invoked and sets up TSS. The IST variant is installed
     274                 :            :  * after that.
     275                 :            :  *
     276                 :            :  * FIXME: Why is 32bit and 64bit installing the PF handler at different
     277                 :            :  * places in the early setup code?
     278                 :            :  */
     279                 :         13 : void __init idt_setup_early_pf(void)
     280                 :            : {
     281                 :         13 :         idt_setup_from_table(idt_table, early_pf_idts,
     282                 :            :                              ARRAY_SIZE(early_pf_idts), true);
     283                 :         13 : }
     284                 :            : 
     285                 :            : /**
     286                 :            :  * idt_setup_ist_traps - Initialize the idt table with traps using IST
     287                 :            :  */
     288                 :         13 : void __init idt_setup_ist_traps(void)
     289                 :            : {
     290                 :         13 :         idt_setup_from_table(idt_table, ist_idts, ARRAY_SIZE(ist_idts), true);
     291                 :         13 : }
     292                 :            : 
     293                 :            : /**
     294                 :            :  * idt_setup_debugidt_traps - Initialize the debug idt table with debug traps
     295                 :            :  */
     296                 :         13 : void __init idt_setup_debugidt_traps(void)
     297                 :            : {
     298                 :         13 :         memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16);
     299                 :            : 
     300                 :         13 :         idt_setup_from_table(debug_idt_table, dbg_idts, ARRAY_SIZE(dbg_idts), false);
     301                 :         13 : }
     302                 :            : #endif
     303                 :            : 
     304                 :            : /**
     305                 :            :  * idt_setup_apic_and_irq_gates - Setup APIC/SMP and normal interrupt gates
     306                 :            :  */
     307                 :         13 : void __init idt_setup_apic_and_irq_gates(void)
     308                 :            : {
     309                 :         13 :         int i = FIRST_EXTERNAL_VECTOR;
     310                 :         13 :         void *entry;
     311                 :            : 
     312                 :         13 :         idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true);
     313                 :            : 
     314         [ +  + ]:       2639 :         for_each_clear_bit_from(i, system_vectors, FIRST_SYSTEM_VECTOR) {
     315                 :       2626 :                 entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR);
     316                 :       2626 :                 set_intr_gate(i, entry);
     317                 :            :         }
     318                 :            : 
     319                 :            : #ifdef CONFIG_X86_LOCAL_APIC
     320         [ +  + ]:         78 :         for_each_clear_bit_from(i, system_vectors, NR_VECTORS) {
     321                 :         65 :                 set_bit(i, system_vectors);
     322                 :         65 :                 entry = spurious_entries_start + 8 * (i - FIRST_SYSTEM_VECTOR);
     323                 :         65 :                 set_intr_gate(i, entry);
     324                 :            :         }
     325                 :            : #endif
     326                 :         13 : }
     327                 :            : 
     328                 :            : /**
     329                 :            :  * idt_setup_early_handler - Initializes the idt table with early handlers
     330                 :            :  */
     331                 :         13 : void __init idt_setup_early_handler(void)
     332                 :            : {
     333                 :         13 :         int i;
     334                 :            : 
     335         [ +  + ]:        429 :         for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
     336                 :        416 :                 set_intr_gate(i, early_idt_handler_array[i]);
     337                 :            : #ifdef CONFIG_X86_32
     338                 :            :         for ( ; i < NR_VECTORS; i++)
     339                 :            :                 set_intr_gate(i, early_ignore_irq);
     340                 :            : #endif
     341                 :         13 :         load_idt(&idt_descr);
     342                 :         13 : }
     343                 :            : 
     344                 :            : /**
     345                 :            :  * idt_invalidate - Invalidate interrupt descriptor table
     346                 :            :  * @addr:       The virtual address of the 'invalid' IDT
     347                 :            :  */
     348                 :          0 : void idt_invalidate(void *addr)
     349                 :            : {
     350                 :          0 :         struct desc_ptr idt = { .address = (unsigned long) addr, .size = 0 };
     351                 :            : 
     352                 :          0 :         load_idt(&idt);
     353                 :          0 : }
     354                 :            : 
     355                 :         13 : void __init update_intr_gate(unsigned int n, const void *addr)
     356                 :            : {
     357   [ -  +  +  - ]:         13 :         if (WARN_ON_ONCE(!test_bit(n, system_vectors)))
     358                 :            :                 return;
     359                 :         13 :         set_intr_gate(n, addr);
     360                 :            : }
     361                 :            : 
     362                 :          0 : void alloc_intr_gate(unsigned int n, const void *addr)
     363                 :            : {
     364         [ #  # ]:          0 :         BUG_ON(n < FIRST_SYSTEM_VECTOR);
     365         [ #  # ]:          0 :         if (!test_and_set_bit(n, system_vectors))
     366                 :          0 :                 set_intr_gate(n, addr);
     367                 :          0 : }

Generated by: LCOV version 1.14