Linux PowerPC interruption Principle Analysis

Source: Internet
Author: User

Before learning about the Interrupt Processing Mechanism, let's take a look at the interrupt source of PowerPC. Here we use the e300c3 kernel. From the perspective of the e300 core, the interrupt source can be divided into exceptions and external interruptions, exceptions are generated by the e300 kernel, such as illegal commands or TLB Miss during memory access. This situation is too complicated. If we do not go into the details, the interruptions mentioned here are external interruptions. The so-called external interrupt is the interrupt caused by the e300 external pin. E300 has the following external interruptions: int #, CINT #, and MCP #. The three pins correspond to the general interrupt, critical interrupt, and machine respectively.
Check interrupted.

During device driving, you can use the request_irq function to mount peripheral interrupt service routines to the External Interrupt Processing Program. The external interrupt handler can directly handle hardware interruptions, but the request_irq function tries to mount the software interrupt number. Therefore, Linux must use some method to map hardware and software interruptions.

Here we need to understand the definition of the interrupt vector table, that is, it associates the software interrupt number with the hardware interrupt number. In the system, there are many interrupt sources. When a certain interruption occurs, the processor first enters the address of the processing function, that is, the interrupt vector. Each type corresponds to an interrupt vector number, and a series of Interrupt numbers constitute the interrupt vector table. For example, if the driver is concerned with external interruptions, when such interruptions occur, the processor kernel (e300) will go to the specified register to obtain the entry address of the interrupt handler function.

The hardware interrupt number is the value that the processor reads from the external PIC (programable Interrupt Controller) when the interrupt occurs. In PowerPC Linux, there is a concept of DTs. Driver programmers need to know how to write the interrupt item on the device node corresponding to the device that they are responsible, the number on interrupt is the hardware interrupt number. During Linux system initialization, you can configure the PIC to convert the hardware connection into the corresponding hardware interrupt number. For example, the disconnection irq0 ~ Irq7, you can use the PIC configuration to map the number of hardware interruptions to 10 ~ 18. When there is an interrupt request on irq0, the processor reads the PIC and obtains the hardware interrupt Number 10 corresponding to P1. These are hardware-based things. When drivers install their interrupt handlers, they are based on the software interrupt number, that is, the IRQ parameter in the kernel function request_irq is a software interrupt number.

The software interrupt number is a concept in Linux. To support the relationship between multiple platforms, Linux does not directly use the hardware interrupt number index irq_desc. Therefore, when an external interrupt occurs, the function of the External Interrupt entry reads the PIC to obtain the hardware interrupt Number of the interrupt. After obtaining the hardware interrupt number, it is mapped to the corresponding software interrupt number to index the irq_desc array to obtain the interrupt handler function on the software interrupt number. Obviously, the ing between the hardware interrupt number and the software interrupt number should be established before the device can handle the interrupt. In Linux PowerPC, this ing relationship is determined by the irq_of_parse_and_map (struct
Device_node * Dev, int index.

Note: In 8315, You can query the MSI hardware interrupt number in the system global interrupt vector register sivcr. In addition, if there is no software interrupt number, the device driver can also use the hardware interrupt number as the index mounting handler. In terms of functionality, there is no problem. The software interrupt number is introduced to make the hardware interrupt number transparent to OS. This can reduce OS dependencies on the hardware platform.

Next, paste some kernel code to facilitate detailed analysis:

In Linux, the struct irq_map_entry irq_map [nr_irqs] is used to map the interrupt numbers of software and hardware. Generally, the system automatically finds available software numbers to correspond to the hardware interrupt numbers of the requests.

In the system where open firmware is used, the driver must map the hardware and software interrupt numbers before executing ruquest_irq. The specific function is used:
Irq_of_parse_and_map (struct device_node * Dev, int index );
The specific function call process is as follows:
Irq_create_of_mapping (struct device_node * controller, u32 * inspec, unsigned int intsize );
Irq_create_mapping (struct irq_host * Host, irq_hw_number_t hwirq );
In addition to the ing of software and hardware interrupt numbers, the program also needs the initial structure.
Next we will look at several other major data structures related to interruptions:
1. struct: struct irq_desc (include/Linux/IRQ. h)

struct irq_desc {unsigned intirq;struct timer_rand_state *timer_rand_state;unsigned int            *kstat_irqs;#ifdef CONFIG_INTR_REMAPstruct irq_2_iommu      *irq_2_iommu;#endifirq_flow_handler_thandle_irq;struct irq_chip*chip;struct msi_desc*msi_desc;void*handler_data;void*chip_data;struct irqaction*action;/* IRQ action list */unsigned intstatus;/* IRQ status */unsigned intdepth;/* nested irq disables */unsigned intwake_depth;/* nested wake enables */unsigned intirq_count;/* For detecting broken IRQs */unsigned longlast_unhandled;/* Aging timer for unhandled count */unsigned intirqs_unhandled;raw_spinlock_tlock;#ifdef CONFIG_SMPcpumask_var_taffinity;const struct cpumask*affinity_hint;unsigned intnode;#ifdef CONFIG_GENERIC_PENDING_IRQcpumask_var_tpending_mask;#endif#endifatomic_tthreads_active;wait_queue_head_t       wait_for_threads;#ifdef CONFIG_PROC_FSstruct proc_dir_entry*dir;#endifconst char*name;} ____cacheline_internodealigned_in_smp;

This struct is used to describe the interrupt source, which is used to connect the hardware interrupt and the bridge between the interrupt processing functions registered through request_irq in the driver. In the array irq_desc [nr_irqs] (nr_irqs = 225), each item corresponds to a corresponding interrupt source, and each item corresponds to an item in the interrupt vector table, that is, the first item in the array corresponds to 32nd items in the interrupt vector table (the interrupt vector number is 0x20), and corresponds to each other in sequence. The interrupt vector table contains 256 Items.
Some member explanations:
Status: either 0 or a flag extracted from a specific set (not clear ). These flags indicate the status of IRQ-whether it is disabled or whether the IRQ device is being automatically detected.
Chip: a pointer to hw_interrupt_type (or irq_chip. The defined functions are platform-related (more specifically, interrupt controller-related). Obviously, interrupt controllers on different platforms have different operation functions, such as enable, disable, and mask, unmask an interrupted operation. From the perspective of platform transplantation, chip shields underlying hardware from being different, making some code in the kernel platform irrelevant. However, for Linux on different platforms, BSP must initialize the chip variable in irq_desc.

Action: A pointer to the header of a one-way linked list composed of irqaction struct. If an IRQ is used by only one interrupt source, the length of the linked list is 1. When multiple devices share one interrupt source, the linked list is composed of multiple irqaction struct, this is described below.
Depth: the number of current users of irq_desc_t, which is mainly used to ensure that IRQ will not be disabled while the event is being processed.

From the driver developer's point of view, you do not need to directly call functions in chip. However, when the driver request_irq needs to install the interrupt handler in one of irq_desc, the following is a prototype of the request_irq function:
Int request_irq (unsigned int IRQ, irq_handler_t handler, unsigned long irqflags, const char * devname, void * dev_id)

The third parameter irqflags affects kernel calls to functions in chip. Therefore, learning about Chip-related interruptions enable/disable/mask/unmask is helpful to driver programmers.
2. struct: struct irqaction (include/Linux/interrupt. h)

struct irqaction {irq_handler_t handler;unsigned long flags;const char *name;void *dev_id;struct irqaction *next;int irq;struct proc_dir_entry *dir;irq_handler_t thread_fn;struct task_struct *thread;unsigned long thread_flags;};

This struct contains the information required to process an interrupt. It represents the operations that the kernel should take after receiving a specific IRQ.
Main members:
Handler-the pointer points to a function that interrupts the service program. When the interrupt occurs, the kernel calls the function pointed to by the pointer.
Flags: the flag can be 0 or sa_interrupt (indicating that the interrupt handler is a fast interrupt handler, which is not found in 2.6 by default) sa_sample_random (indicating that the interrupt contributes to the kernel pool. I understand that some random numbers are generated during the interrupt. These random numbers are used as encryption keys because the interrupt occurs randomly, if an interruption occurs at a frequency, do not set this flag, or set this flag for a device that is vulnerable to attacks) sa_shirq (this flag indicates that multiple interrupt service programs are allowed to share one interrupt number. If not set, one program corresponds to one disconnection ).
Mask: not used on x86.
Name: name of the hardware that causes the interruption.
Dev_id: this flag is mainly used when the interrupt number is shared. That is, when you set flags = sa_shirq, when multiple interrupt service programs share one interrupt number, the kernel needs to know that the interrupt service program should be deleted after the interrupt program is used up. This member is null if it is not shared.
Next: If flags = sa_shirq, This is the pointer to the next struct irqaction struct in the column; otherwise, it is null.
IRQ: Needless to say, this is the interrupt number.
3 struct: struct hw_interrupt_type (include/Linux/IRQ. h)

struct irq_chip {const char*name;unsigned int(*startup)(unsigned int irq);void(*shutdown)(unsigned int irq);void(*enable)(unsigned int irq);void(*disable)(unsigned int irq);void(*ack)(unsigned int irq);void(*mask)(unsigned int irq);void(*mask_ack)(unsigned int irq);void(*unmask)(unsigned int irq);void(*eoi)(unsigned int irq);void(*end)(unsigned int irq);int(*set_affinity)(unsigned int irq,const struct cpumask *dest);int(*retrigger)(unsigned int irq);int(*set_type)(unsigned int irq, unsigned int flow_type);int(*set_wake)(unsigned int irq, unsigned int on);void(*bus_lock)(unsigned int irq);void(*bus_sync_unlock)(unsigned int irq);/* Currently used only by UML, might disappear one day.*/#ifdef CONFIG_IRQ_RELEASE_METHODvoid(*release)(unsigned int irq, void *dev_id);#endif/* * For compatibility, ->typename is copied into ->name. * Will disappear. */const char*typename;};

It is used to describe the interrupt controller, that is, an abstract interrupt controller. Its members are a series of pointers to functions.
Typename: Give the corresponding controller a name that is easy to understand.
Startup: events that can be generated from the IRQ of a given controller. (Basically the same as enable)
Shutdown: disables events generated from IRQ of a given controller. (Basically the same as disable)
The relationship between the above three struct types can be illustrated in the following figure:

 

The array irq_desc_t is used to describe the interrupt information. It has 225 items. Each item represents an interrupt source, and the field IRQ (note that this field is the handler field in ), this struct is used to describe the interrupt controller, and the action field is used to describe the information required to process an interrupt. It represents the operation that the kernel should take after receiving a specific IRQ.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.