Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:10

0001 /* SPDX-License-Identifier: BSD-2-Clause */
0002 
0003 /**
0004  * @file
0005  *
0006  * @ingroup RTEMSBSPsX8664AMD64
0007  *
0008  * @brief Interrupts support
0009  */
0010 
0011 /*
0012  * Copyright (c) 2018 Amaan Cheval <amaan.cheval@gmail.com>
0013  *
0014  * Redistribution and use in source and binary forms, with or without
0015  * modification, are permitted provided that the following conditions
0016  * are met:
0017  * 1. Redistributions of source code must retain the above copyright
0018  *    notice, this list of conditions and the following disclaimer.
0019  * 2. Redistributions in binary form must reproduce the above copyright
0020  *    notice, this list of conditions and the following disclaimer in the
0021  *    documentation and/or other materials provided with the distribution.
0022  *
0023  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
0024  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
0025  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
0026  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
0027  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
0028  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
0029  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
0030  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
0031  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
0032  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0033  * SUCH DAMAGE.
0034  */
0035 
0036 #include <apic.h>
0037 #include <bsp/fatal.h>
0038 #include <bsp/irq-generic.h>
0039 #include <rtems.h>
0040 #include <rtems/score/idt.h>
0041 #include <rtems/score/basedefs.h>
0042 #include <rtems/score/x86_64.h>
0043 #include <rtems/score/cpuimpl.h>
0044 #include <rtems/score/processormaskimpl.h>
0045 
0046 #include <stdint.h>
0047 
0048 /*
0049  * The IDT maps every interrupt vector to an interrupt_descriptor based on the
0050  * vector number.
0051  */
0052 interrupt_descriptor amd64_idt[IDT_SIZE] RTEMS_ALIGNED(8) = { { 0 } };
0053 
0054 struct idt_record amd64_idtr = {
0055   .limit = (IDT_SIZE * 16) - 1,
0056   .base = (uintptr_t) amd64_idt
0057 };
0058 
0059 /**
0060  * IRQs that the RTEMS Interrupt Manager will manage
0061  * @see DISTINCT_INTERRUPT_ENTRY
0062  */
0063 static uintptr_t rtemsIRQs[BSP_IRQ_VECTOR_NUMBER] = {
0064   (uintptr_t) rtems_irq_prologue_0,
0065   (uintptr_t) rtems_irq_prologue_1,
0066   (uintptr_t) rtems_irq_prologue_2,
0067   (uintptr_t) rtems_irq_prologue_3,
0068   (uintptr_t) rtems_irq_prologue_4,
0069   (uintptr_t) rtems_irq_prologue_5,
0070   (uintptr_t) rtems_irq_prologue_6,
0071   (uintptr_t) rtems_irq_prologue_7,
0072   (uintptr_t) rtems_irq_prologue_8,
0073   (uintptr_t) rtems_irq_prologue_9,
0074   (uintptr_t) rtems_irq_prologue_10,
0075   (uintptr_t) rtems_irq_prologue_11,
0076   (uintptr_t) rtems_irq_prologue_12,
0077   (uintptr_t) rtems_irq_prologue_13,
0078   (uintptr_t) rtems_irq_prologue_14,
0079   (uintptr_t) rtems_irq_prologue_15,
0080   (uintptr_t) rtems_irq_prologue_16,
0081   (uintptr_t) rtems_irq_prologue_17,
0082   (uintptr_t) rtems_irq_prologue_18,
0083   (uintptr_t) rtems_irq_prologue_19,
0084   (uintptr_t) rtems_irq_prologue_20,
0085   (uintptr_t) rtems_irq_prologue_21,
0086   (uintptr_t) rtems_irq_prologue_22,
0087   (uintptr_t) rtems_irq_prologue_23,
0088   (uintptr_t) rtems_irq_prologue_24,
0089   (uintptr_t) rtems_irq_prologue_25,
0090   (uintptr_t) rtems_irq_prologue_26,
0091   (uintptr_t) rtems_irq_prologue_27,
0092   (uintptr_t) rtems_irq_prologue_28,
0093   (uintptr_t) rtems_irq_prologue_29,
0094   (uintptr_t) rtems_irq_prologue_30,
0095   (uintptr_t) rtems_irq_prologue_31,
0096   (uintptr_t) rtems_irq_prologue_32,
0097   (uintptr_t) rtems_irq_prologue_33
0098 };
0099 
0100 void lidt(struct idt_record *ptr)
0101 {
0102   __asm__ volatile ("lidt %0" :: "m"(*ptr));
0103 }
0104 
0105 interrupt_descriptor amd64_create_interrupt_descriptor(
0106   uintptr_t handler, uint8_t types_and_attributes
0107 )
0108 {
0109   interrupt_descriptor entry = {
0110     .offset_0 = handler & 0xffff,
0111     .segment_selector = amd64_get_cs(),
0112     .interrupt_stack_table = 0,
0113     .type_and_attributes = types_and_attributes,
0114     .offset_1 = (handler >> 16) & 0xffff,
0115     .offset_2 = handler >> 32,
0116     .reserved_zero = 0,
0117   };
0118   return entry;
0119 }
0120 
0121 uintptr_t amd64_get_handler_from_idt(uint32_t vector)
0122 {
0123   interrupt_descriptor entry = amd64_idt[vector];
0124   uintptr_t handler = entry.offset_0 | (entry.offset_1 << 16) |
0125     ((uint64_t) entry.offset_2 << 32);
0126   return handler;
0127 }
0128 
0129 void amd64_install_raw_interrupt(
0130   uint32_t vector, uintptr_t new_handler, uintptr_t *old_handler
0131 )
0132 {
0133   *old_handler = amd64_get_handler_from_idt(vector);
0134   interrupt_descriptor new_desc = amd64_create_interrupt_descriptor(
0135     new_handler,
0136     IDT_INTERRUPT_GATE | IDT_PRESENT
0137   );
0138   amd64_idt[vector] = new_desc;
0139 }
0140 
0141 void amd64_dispatch_isr(rtems_vector_number vector)
0142 {
0143   bsp_interrupt_handler_dispatch(vector);
0144 }
0145 
0146 void bsp_interrupt_facility_initialize(void)
0147 {
0148   uintptr_t old;
0149   for (uint32_t i = 0; i < BSP_IRQ_VECTOR_NUMBER; i++) {
0150     amd64_install_raw_interrupt(i, rtemsIRQs[i], &old);
0151   }
0152 
0153   lidt(&amd64_idtr);
0154 
0155   if (lapic_initialize() == false) {
0156     bsp_fatal(BSP_FATAL_INTERRUPT_INITIALIZATION);
0157   }
0158 }
0159 
0160 rtems_status_code bsp_interrupt_vector_disable(rtems_vector_number vector)
0161 {
0162   /* XXX: Should be implemented once I/O APIC support is added */
0163   return RTEMS_SUCCESSFUL;
0164 }
0165 
0166 rtems_status_code bsp_interrupt_set_priority(
0167   rtems_vector_number vector,
0168   uint32_t priority
0169 )
0170 {
0171   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0172   return RTEMS_UNSATISFIED;
0173 }
0174 
0175 rtems_status_code bsp_interrupt_get_priority(
0176   rtems_vector_number vector,
0177   uint32_t *priority
0178 )
0179 {
0180   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0181   bsp_interrupt_assert(priority != NULL);
0182   return RTEMS_UNSATISFIED;
0183 }
0184 
0185 rtems_status_code bsp_interrupt_get_attributes(
0186   rtems_vector_number         vector,
0187   rtems_interrupt_attributes *attributes
0188 )
0189 {
0190   return RTEMS_SUCCESSFUL;
0191 }
0192 
0193 rtems_status_code bsp_interrupt_is_pending(
0194   rtems_vector_number vector,
0195   bool               *pending
0196 )
0197 {
0198   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0199   bsp_interrupt_assert(pending != NULL);
0200   *pending = false;
0201   return RTEMS_UNSATISFIED;
0202 }
0203 
0204 rtems_status_code bsp_interrupt_raise(rtems_vector_number vector)
0205 {
0206   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0207   return RTEMS_UNSATISFIED;
0208 }
0209 
0210 rtems_status_code bsp_interrupt_clear(rtems_vector_number vector)
0211 {
0212   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0213   return RTEMS_UNSATISFIED;
0214 }
0215 
0216 rtems_status_code bsp_interrupt_vector_is_enabled(
0217   rtems_vector_number vector,
0218   bool               *enabled
0219 )
0220 {
0221   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0222   bsp_interrupt_assert(enabled != NULL);
0223   *enabled = false;
0224   return RTEMS_UNSATISFIED;
0225 }
0226 
0227 rtems_status_code bsp_interrupt_vector_enable(rtems_vector_number vector)
0228 {
0229   /* XXX: Should be implemented once I/O APIC support is added */
0230   return RTEMS_SUCCESSFUL;
0231 }
0232 
0233 #ifdef RTEMS_SMP
0234 /* TODO: See #5121 */
0235 rtems_status_code bsp_interrupt_get_affinity(
0236   rtems_vector_number  vector,
0237   Processor_mask      *affinity
0238 )
0239 {
0240   (void) vector;
0241   _Processor_mask_From_index( affinity, 0 );
0242   return RTEMS_UNSATISFIED;
0243 }
0244 
0245 /* TODO: See #5121 */
0246 rtems_status_code bsp_interrupt_set_affinity(
0247   rtems_vector_number   vector,
0248   const Processor_mask *affinity
0249 )
0250 {
0251   (void) vector;
0252   (void) affinity;
0253   return RTEMS_UNSATISFIED;
0254 }
0255 
0256 rtems_status_code bsp_interrupt_raise_on(
0257   rtems_vector_number vector,
0258   uint32_t            cpu_index
0259 )
0260 {
0261   bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
0262   return RTEMS_UNSATISFIED;
0263 }
0264 #endif