Document internal machine/interrupt.h interface

Every platform has to implement a standard set of interrupt interfaces
that the kernel uses to interract with a machine's interrupt controller.
Providing a single header file for each of these functions provides a
single location to document their behavior.
This commit is contained in:
Kent McLeod 2019-05-29 21:19:01 +10:00
parent 94dcfce5c7
commit 2cd80a8c7e
21 changed files with 135 additions and 72 deletions

View file

@ -15,6 +15,7 @@
#include <autoconf.h>
#include <stdint.h>
#include <machine/interrupt.h>
/* Shift positions for GICD_SGIR register */
#define GICD_SGIR_SGIINTID_SHIFT 0
@ -62,11 +63,8 @@
#define IRQ_BIT(IRQ) ((IRQ) & 0x1f)
#define IS_IRQ_VALID(X) (((X) & IRQ_MASK) < SPECIAL_IRQ_START)
typedef uint16_t interrupt_t;
typedef uint16_t irq_t;
enum irqNumbers {
irqInvalid = (irq_t) - 1
irqInvalid = (uint16_t) -1
};
/*

View file

@ -160,7 +160,7 @@ static inline void dist_enable_set(irq_t irq)
gic_dist->enable_set[word] = BIT(bit);
}
static inline interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t irq;
if (!IS_IRQ_VALID(active_irq[CURRENT_CPU_INDEX()])) {
@ -186,7 +186,7 @@ static inline bool_t isIRQPending(void)
return IS_IRQ_VALID(gic_cpuiface->hi_pend);
}
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
#if defined ENABLE_SMP_SUPPORT && defined CONFIG_ARCH_ARM
assert(!(IRQ_IS_PPI(irq)) || (IDX_TO_CORE(irq) == getCurrentCPUIndex()));

View file

@ -233,7 +233,7 @@ static inline void gic_enable_set(irq_t irq)
}
static inline interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t irq;
@ -265,7 +265,7 @@ static inline bool_t isIRQPending(void)
return IS_IRQ_VALID(val);
}
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
#if defined ENABLE_SMP_SUPPORT
assert(!(IRQ_IS_PPI(irq)) || (IDX_TO_CORE(irq) == getCurrentCPUIndex()));

View file

@ -14,6 +14,7 @@
#include <types.h>
#include <api/failures.h>
#include <object/structures.h>
#include <machine/interrupt.h>
#include <plat/machine.h>
exception_t Arch_decodeIRQControlInvocation(word_t invLabel, word_t length,

View file

@ -222,11 +222,6 @@ int get_num_dev_p_regs(void);
p_region_t get_dev_p_reg(word_t i);
void map_kernel_devices(void);
typedef uint32_t irq_t;
void ackInterrupt(irq_t irq);
bool_t isIRQPending(void);
void maskInterrupt(bool_t enable, irq_t irq);
irq_t getActiveIRQ(void);
static inline void setInterruptMode(irq_t irq, bool_t levelTrigger, bool_t polarityLow) { }
/** MODIFIES: [*] */
void initTimer(void);
@ -236,8 +231,6 @@ void initLocalIRQController(void);
void initIRQController(void);
void setIRQTrigger(irq_t irq, bool_t trigger);
void handleSpuriousIRQ(void);
#ifdef ENABLE_SMP_SUPPORT
#define irq_remote_call_ipi (INTERRUPT_IPI_0)
#define irq_reschedule_ipi (INTERRUPT_IPI_1)

View file

@ -31,35 +31,34 @@
* gets to process the IRQ and subsequent HARTs won't receive a claim for the same IRQ.
*
* We require each platform to provide the following functions:
* interrupt_t plic_get_claim(void): If called when an IRQ is pending, returns
* irq_t plic_get_claim(void): If called when an IRQ is pending, returns
* the pending priority and starts a claim process. Will return irqInvalid
* if no IRQs are pending.
* void plic_complete_claim(interrupt_t irq): Complete a claim process for an
* void plic_complete_claim(irq_t irq): Complete a claim process for an
* interrupt.
* void plic_mask_irq(bool_t disable, interrupt_t irq): Disables or enables an
* void plic_mask_irq(bool_t disable, irq_t irq): Disables or enables an
* IRQ at the PLIC.
* void plic_irq_set_trigger(interrupt_t irq, bool_t edge_triggered): Configure
* void plic_irq_set_trigger(irq_t irq, bool_t edge_triggered): Configure
* an IRQ source on the PLIC to be edge or level triggered. This function does
* not need to be implemented if the PLIC doesn't support configuring this.
* void plic_init_controller(void): Perform PLIC initialisation during boot.
*/
typedef uint32_t interrupt_t;
static inline interrupt_t plic_get_claim(void)
static inline irq_t plic_get_claim(void)
{
return irqInvalid;
}
static inline void plic_complete_claim(interrupt_t irq)
static inline void plic_complete_claim(irq_t irq)
{
}
static inline void plic_mask_irq(bool_t disable, interrupt_t irq)
static inline void plic_mask_irq(bool_t disable, irq_t irq)
{
}
#ifdef HAVE_SET_TRIGGER
static inline void plic_irq_set_trigger(interrupt_t irq, bool_t edge_triggered);
static inline void plic_irq_set_trigger(irq_t irq, bool_t edge_triggered);
#endif
static inline void plic_init_controller(void)

View file

@ -12,13 +12,12 @@
#include <config.h>
#include <types.h>
#include <machine/interrupt.h>
#include <armv/machine.h>
typedef uint8_t interrupt_t;
enum irqNumbers {
irqInvalid = 255
};
typedef uint8_t irq_t;
#define CMPER_REG(base, off) ((volatile uint32_t *)((base) + (off)))
#define CMPER_TIMER3_CLKCTRL 0x84
@ -71,10 +70,10 @@ volatile struct INTC_map {
} *intc = (volatile void *)INTC_PPTR;
static inline interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t intcps_sir_irq = intc->intcps_sir_irq;
interrupt_t irq = (interrupt_t)(intcps_sir_irq & 0x7f);
irq_t irq = (irq_t)(intcps_sir_irq & 0x7f);
if ((intcps_sir_irq & INTCPS_SIR_IRQ_SPURIOUSIRQFLAG) == 0) {
assert((irq / 32) < (sizeof intc->intcps_n / sizeof intc->intcps_n[0]));
@ -92,7 +91,7 @@ static inline bool_t isIRQPending(void)
}
/* Enable or disable irq according to the 'disable' flag. */
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
if (likely(irq < maxIRQ)) {
if (disable) {

View file

@ -14,6 +14,7 @@
#define __DRIVERS_IRQ_BCM_H
#include <plat/machine/devices_gen.h>
#include <machine/io.h>
#include <machine/interrupt.h>
#define BASIC_IRQ_OFFSET 32
#define NORMAL_IRQ_OFFSET (BASIC_IRQ_OFFSET + 32)
@ -124,19 +125,10 @@ volatile struct core_regs {
#define LOCAL_TIMER_CTRL_EN_BIT 28
#define LOCAL_TIMER_CTRL_RL_MASK MASK(28)
typedef uint8_t interrupt_t;
typedef uint8_t irq_t;
enum irqNumbers {
irqInvalid = (irq_t) - 1
irqInvalid = 255
};
interrupt_t
getActiveIRQ(void);
void
maskInterrupt(bool_t disable, interrupt_t irq);
static inline bool_t isIRQPending(void)
{
uint32_t pending;

View file

@ -57,8 +57,6 @@
#endif
typedef uint32_t interrupt_t;
static inline void write_sie(word_t value)
{
asm volatile("csrw sie, %0" :: "r"(value));
@ -122,21 +120,21 @@ static inline word_t get_hart_id(void)
#endif
}
static inline interrupt_t plic_get_claim(void)
static inline irq_t plic_get_claim(void)
{
/* Read the claim register for our HART interrupt context */
word_t hart_id = get_hart_id();
return readl(PLIC_PPTR_BASE + plic_claim_offset(hart_id, PLIC_SVC_CONTEXT));
}
static inline void plic_complete_claim(interrupt_t irq)
static inline void plic_complete_claim(irq_t irq)
{
/* Complete the IRQ claim by writing back to the claim register. */
word_t hart_id = get_hart_id();
writel(irq, PLIC_PPTR_BASE + plic_claim_offset(hart_id, PLIC_SVC_CONTEXT));
}
static inline void plic_mask_irq(bool_t disable, interrupt_t irq)
static inline void plic_mask_irq(bool_t disable, irq_t irq)
{
uint64_t addr = 0;
uint32_t val = 0;

View file

@ -13,14 +13,12 @@
#include <config.h>
#include <basic_types.h>
#include <machine/interrupt.h>
enum irqNumbers {
irqInvalid = 255
};
typedef word_t interrupt_t;
typedef word_t irq_t;
/* Memory map for AVIC (Advanced Vectored Interrupt Controller). */
volatile struct avic_map {
uint32_t intctl;
@ -50,11 +48,11 @@ volatile struct avic_map {
* multiple times per interrupt received, we store the
* current active IRQ in a global variable.
*/
extern interrupt_t active_irq;
extern irq_t active_irq;
/* Get the active IRQ number from the AVIC. Returns 0xff if
* there isn't one. Note this is also known as irqInvalid */
static inline interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
if (active_irq == irqInvalid) {
/* Read the IRQ number from the IRQ controller.
@ -77,7 +75,7 @@ static inline bool_t isIRQPending(void)
}
/* Enable or disable irq according to the 'disable' flag. */
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
if (disable) {
avic->intdisnum = irq;

View file

@ -17,6 +17,7 @@
#include <arch/kernel/vspace.h>
#include <linker.h>
#include <armv/machine.h>
#include <machine/interrupt.h>
#define INTCPS_SIR_IRQ_SPURIOUSIRQFLAG 0xFF0000
@ -24,9 +25,6 @@ enum irqNumbers {
irqInvalid = 255
};
typedef uint8_t interrupt_t;
typedef uint8_t irq_t;
/*
* The struct below is used to discourage the compiler from generating literals
* for every single address we might access.
@ -60,10 +58,10 @@ volatile struct INTC_map {
uint32_t intcps_ilr[96];
} *intc = (volatile void *)INTC_PPTR;
static inline interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t intcps_sir_irq = intc->intcps_sir_irq;
interrupt_t irq = (interrupt_t)(intcps_sir_irq & 0x7f);
irq_t irq = (irq_t)(intcps_sir_irq & 0x7f);
/* Ignore spurious interrupts. */
if ((intcps_sir_irq & INTCPS_SIR_IRQ_SPURIOUSIRQFLAG) == 0) {
@ -84,7 +82,7 @@ static inline bool_t isIRQPending(void)
}
/* Enable or disable irq according to the 'disable' flag. */
static inline void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
if (likely(irq < maxIRQ)) {
if (disable) {

View file

@ -0,0 +1,87 @@
/*
* Copyright 2018, Data61
* Commonwealth Scientific and Industrial Research Organisation (CSIRO)
* ABN 41 687 119 230.
*
* This software may be distributed and modified according to the terms of
* the GNU General Public License version 2. Note that NO WARRANTY is provided.
* See "LICENSE_GPLv2.txt" for details.
*
* @TAG(DATA61_GPL)
*/
#ifndef __MACHINE_INTERRUPT_H
#define __MACHINE_INTERRUPT_H
#include <basic_types.h>
typedef word_t irq_t;
/**
* Return a currently pending IRQ.
*
* This function can be called multiple times and needs to return the same IRQ
* until ackInterrupt is called. getActiveIRQ returns irqInvalid if no interrupt
* is pending. It is assumed that if isIRQPending is true, then getActiveIRQ
* will not return irqInvalid. irqInvalid is a per platform constant that cannot
* correspond to an actual IRQ raised by the platform.
*
* @return The active IRQ. irqInvalid if no IRQ is pending.
*/
static inline irq_t getActiveIRQ(void);
/**
* Checks if an IRQ is currently pending in the hardware.
*
* isIRQPending is used to determine whether to preempt long running operations
* at various preemption points throughout the kernel. If this returns true, it
* means that if the Kernel were to return to user mode, it would then
* immediately take an interrupt.
*
* @return True if irq pending, False otherwise.
*/
static inline bool_t isIRQPending(void);
/**
* maskInterrupt disables and enables IRQs.
*
* When an IRQ is disabled, it should not raise an interrupt on the processor.
*
* @param[in] disable True to disable IRQ, False to enable IRQ
* @param[in] irq The irq to modify
*/
static inline void maskInterrupt(bool_t disable, irq_t irq);
/**
* Acks the interrupt
*
* ackInterrupt is used by the kernel to indicate it has processed the interrupt
* delivery and getActiveIRQ is now able to return a different IRQ number. Note
* that this is called after a notification has been signalled to user level,
* but before user level has handled the cause and does not imply that the cause
* of the interrupt has been handled.
*
* @param[in] irq irq to ack
*/
static inline void ackInterrupt(irq_t irq);
/**
* Called when getActiveIRQ returns irqInvalid while the kernel is handling an
* interrupt entry. An implementation is not required to do anything here, but
* can report the spurious IRQ or try prevent it from reoccuring.
*/
static inline void handleSpuriousIRQ(void);
/**
* Handle a platform-reserved IRQ.
*
* Platform specific implementation for handling IRQs for interrupts that are
* reserved and not made available to user-level. Will be called if getActiveIRQ
* returns an IRQ number that is reserved. After this function returns,
* ackInterrupt will likely be immediately called after.
*
* @param[in] irq The irq
*/
static inline void handleReservedIRQ(irq_t irq);
#endif /* __MACHINE_INTERRUPT_H */

View file

@ -11,6 +11,8 @@
#ifndef __PLAT_MACHINE_H
#define __PLAT_MACHINE_H
#include <machine/interrupt.h>
#define PIC_IRQ_LINES 16
#define IOAPIC_IRQ_LINES 24
@ -68,8 +70,6 @@ typedef enum _platform_irq_t {
irqInvalid = 255,
} platform_irq_t;
typedef uint8_t irq_t;
#define KERNEL_TIMER_IRQ irq_timer
#define BIOS_PADDR_START 0x0e0000
#define BIOS_PADDR_END 0x100000

View file

@ -18,6 +18,7 @@
#include <arch/object/structures.h>
#include <arch/model/statedata.h>
#include <arch/kernel/apic.h>
#include <machine/interrupt.h>
#include <plat/machine/acpi.h>
#include <plat/machine/ioapic.h>
#include <plat/machine/pic.h>

View file

@ -16,16 +16,16 @@
#define PLIC_MAX_NUM_INT 0
#define IRQ_CNODE_SLOT_BITS 1
static inline interrupt_t plic_get_claim(void)
static inline irq_t plic_get_claim(void)
{
return irqInvalid;
}
static inline void plic_complete_claim(interrupt_t irq)
static inline void plic_complete_claim(irq_t irq)
{
}
static inline void plic_mask_irq(bool_t disable, interrupt_t irq)
static inline void plic_mask_irq(bool_t disable, irq_t irq)
{
}

View file

@ -139,7 +139,7 @@ static uint32_t active_irq[CONFIG_MAX_NUM_NODES] = { irqInvalid };
*
* @return The active irq.
*/
irq_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t irq;
@ -182,7 +182,7 @@ void setIRQTrigger(irq_t irq, bool_t edge_triggered)
* core signalling which isn't currently supported.
* TODO: Add SSIP check when SMP support is added.
*/
bool_t isIRQPending(void)
static inline bool_t isIRQPending(void)
{
word_t sip = read_sip();
return (sip & (BIT(STIMER_IP) | BIT(SEXTERNAL_IP)));
@ -198,7 +198,7 @@ bool_t isIRQPending(void)
* @param[in] disable The disable
* @param[in] irq The irq
*/
void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
assert(IS_IRQ_VALID(irq));
if (irq == INTERRUPT_CORE_TIMER) {
@ -226,7 +226,7 @@ void maskInterrupt(bool_t disable, interrupt_t irq)
*
* @param[in] irq The irq
*/
void ackInterrupt(irq_t irq)
static inline void ackInterrupt(irq_t irq)
{
assert(IS_IRQ_VALID(irq));
active_irq[CURRENT_CPU_INDEX()] = irqInvalid;
@ -312,7 +312,7 @@ BOOT_CODE void initIRQController(void)
plic_init_controller();
}
void handleSpuriousIRQ(void)
static inline void handleSpuriousIRQ(void)
{
/* Do nothing */
printf("Superior IRQ!! SIP %lx\n", read_sip());

View file

@ -15,6 +15,7 @@
#include <config.h>
#define TIMER_CLOCK_HZ @CONFIGURE_TIMER_FREQUENCY@
#include <machine/interrupt.h>
/*
* seL4 assigns all IRQs global interrupt numbers that are used in interrupt

View file

@ -33,8 +33,6 @@ enum IPGConstants {
#define TIMER_CLOCK_SRC IPG_CLK_32K
interrupt_t active_irq = irqInvalid;
/* Configure EPIT1 as kernel preemption timer */
BOOT_CODE void initTimer(void)
{

View file

@ -34,8 +34,6 @@ enum IPGConstants {
IPG_CLK_32K = 3
};
interrupt_t active_irq = irqInvalid;
BOOT_CODE void initTimer(void)
{
/* reset the gpt */

View file

@ -30,7 +30,7 @@ BOOT_CODE void initIRQController(void)
BOOT_CODE void cpu_initLocalIRQController(void) {}
interrupt_t getActiveIRQ(void)
static inline irq_t getActiveIRQ(void)
{
uint32_t pending;
uint32_t irq;
@ -73,7 +73,7 @@ interrupt_t getActiveIRQ(void)
return irqInvalid;
}
void maskInterrupt(bool_t disable, interrupt_t irq)
static inline void maskInterrupt(bool_t disable, irq_t irq)
{
switch (irq) {
case INTERRUPT_CORE_CNTPSIRQ :

View file

@ -153,6 +153,8 @@ BOOT_CODE void initL2Cache(void)
#endif
}
irq_t active_irq = irqInvalid;
BOOT_CODE void initIRQController(void)
{
/* Do nothing */