How to figure out the interrupt source on I/O APIC? - operating-system

I understand that I/O APIC chip has 24 PINs, usually single chip system will map PIN 0~23 IRQ 32~55 respectively. Furthermore I could edit the related RTEs to allocate interrupt handler functions.
But how can I figure out the I/O APIC interrupt source on each PINs?
I understand that it is related to ACPI, but on detail how should I do this, is it mapped on some ACPI table? or I should use AML to check it??
Thank you very much!!

The general steps (for a modern OS) are:
Preparation
a) Parse the ACPI "APIC/MADT" table to determine if PIC chips exist (PCAT_COMPAT flag), how many IO APICs there are, and how many inputs each IO APIC has. If ACPI doesn't exist, you might want to try searching for/parsing older "MultiProcessor Spec." table and extracting the same information; however, if ACPI does exist it's possible that the "MultiProcessor Spec." table is designed to provide a "minimum stub" that's contains no real information (so you must check ACPI first and prefer using ACPI if it exists), and it may not be worth the hassle of supporting systems that don't support ACPI (especially if the operating system requires a 64-bit CPU, etc).
b) Parse the ACPI "FADT" to determine if MSI may (or must not) be enabled
c) Determine if the OS will use PIC alone, IO APICs alone, or IO APIC plus MSI. Note that this can (should?) take into account the operating system's own boot parameters and/or configuration (e.g. so if there's a compatibility problem the end user can work around the problem).
d) If PIC chips exist; mask all IRQs in the PIC chips, then reconfigure the PIC chips (to set whatever "base vector number" you want them to use - e.g. maybe so that the master PIC is interrupt vectors 32 to 39 and the slave is vectors 40 to 47). If IO APIC/s exist, mask all IRQs in each IO APIC. Note: if the PIC chips exist they both have a "spurious IRQ" that can't be masked, so if you don't want to use PIC chips it's still a good idea to reconfigure the PIC chips such that their spurious IRQs (and the interrupt handlers for them) aren't going to be in the way.
e) Use an ACPI AML interpreter to execute the _PIC object; to inform ACPI/AML that you will be using either IO APIC or PIC. Note that "OS uses PIC" is the default for backward compatibility, so this step could be skipped if you're not using IO APIC.
f) Configure the local APIC in each CPU (not covered here).
Devices
Before starting a device driver for a device:
a) Figure out the device's details (e.g. use "class, subclass and programming interface" fields from PCI configuration space to figure out what the device is) and check if you actually have a device driver for it; and decide if you want the device to use PCI IRQs or MSI.
b1) If the device will be using PCI IRQs and if the OS is using PIC chips (and not IO APICs); get the "Interrupt Line" field from the device's PCI configuration space and determine which interrupt vector it will be by adding the corresponding PIC chip's "base interrupt vector" to it.
b2) If the device will be using PCI IRQs (and not MSI) and if the OS is using IO APIC and not PIC; determine which "interrupt pin at the PCI slot" the device uses by reading the "Interupt Pin" field from the device's PCI configuration space. Then use an ACPI AML interpreter to execute the _PRT object and get a current (not forgetting that PCI-E supports "hot-plug") PCI IRQ routing table. Use this table (and the PCI device's "bus:device:function" address and which "interrupt pin" it uses) to determine where the PCI IRQ is connected (e.g. which global interrupt, which determines which input of which IO APIC). Then; if you haven't already (because the same interrupt line is shared by a different device) use some kind of "interrupt vector manager" to allocate an interrupt vector for the PCI IRQ, and configure the IO APIC input to generate that interrupt vector. Note that (for IO APIC and MSI) "interrupt vector" determines "IRQ priority", so so for high speed/latency sensitive devices (e.g. network card) you'll want interrupt vectors that imply "high IRQ priority" and for a slower/less latency sensitive devices (e.g. USB controller) you'll want to use interrupt vectors that imply "lower IRQ priority".
b3) If the device will be using MSI; determine how many consecutive interrupt vectors the device wants; then use some kind of "interrupt vector manager" to try allocate as many consecutive interrupt vectors as the device wants. Note that it is possible to give the device less interrupts than it wants.
c) Regardless of how it happened, you now know which interrupt vector/s the device will use. Start the device driver that's suitable for the device, and tell the device driver which interrupt vectors its device will use (and which MMIO regions, etc).
Note: There's more advanced ways to assign interrupt vectors than "first come first served"; and there's probably no technical reason why you can't re-evaluate/re-assign interrupt vectors later as some kind of dynamic optimization scheme (e.g. re-allocating interrupt vectors so they're given to frequently used PCI devices instead of idle/unused PCI devices).

Related

What are IO ports, serial ports and what's the difference between them?

I'm confused.
I have recently started working on building an operating system while using bochs as an emulator and a certain manual online.
In the manual to move the vga framebuffer cursor I'm using the IO ports using the command 'out'. I get how to control it but I don't know what is it that I'm controlling, and after some reading it seems like everywhere it was addressed as an abstract thing that for example makes the cursor to change its position on the screen.
What I want to know: what are they physically? are they cables? if yes from where to where they are connected? can I input from them also as there name suggest? and why do I need the out command and cant write directly to their place in the memory?
If in your answer you can also include the serial ports and the difference between them and the IO ones it will be amazing,
with respect,
revolution
(btw the operating system is 32 bits)
An IO port is basically memory on the motherboard that you can write/read. The motherboard makes some memory available other than RAM. The CPU has a control bus which allows it to "tell" the motherboard that what it outputs on the data bus is to be written somewhere else than RAM. When you output to the VGA buffer, you write to video memory on the motherboard. The out/in instructions are used to write/read IO ports instead of writing to RAM. When you use out/in instructions, you instruct the CPU to set a certain line on its control bus to tell the motherboard to write/read a certain byte to an IO port instead of RAM.
Today, a lot of RAM memory is used for hardware mapping instead of IO ports. This is often called the PCI hole. It is memory mapped IO. So you will write to RAM and it will send the data to hardware like graphics memory. All of this is transparent to OS developers. You are simply using very abstract hardware interfaces which are either conventional (open source) or proprietary.
Serial ports in the meantime are simply ports which are serial in nature. A serial port is defined to be a port where data is transferred one bit at a time. USB is serial (universal serial bus). VGA is serial and others are too. These ports are not like IO ports. You can output to them indirectly using IO ports.
IO ports offer various hardware interfaces which allow to drive hardware. For example, if you have a VGA compatible screen and set text mode, the motherboard will make certain IO ports available and, when you write to these IO ports, video memory will vary depending on what you output to these ports. Eventually, the VGA screen will refresh when the video controller will output data written to video memory through the actual VGA port. I'm not totally aware of how all of this works since I'm not an electrical engineer and I never read about this stuff. To what I know, you can see the pins of the VGA port and what they do independently on wikipedia. VGA works with RGBHV. RGB stands for red, green and blue while HV stand for horizontal/vertical sync. As stated on wiki in the article on analog television:
Synchronizing pulses added to the video signal at the end of every scan line and video frame ensure that the sweep oscillators in the receiver remain locked in step with the transmitted signal so that the image can be reconstructed on the receiver screen. A sync separator circuit detects the sync voltage levels and sorts the pulses into horizontal and vertical sync.
The horizontal synchronization pulse (horizontal sync, or HSync), separates the scan lines. The horizontal sync signal is a single short pulse which indicates the start of every line. The rest of the scan line follows, with the signal ranging from 0.3 V (black) to 1 V (white), until the next horizontal or vertical synchronization pulse.
Memory in itself takes various forms in hardware. Video memory is often called VRAM (Video RAM) or the Frame Buffer as you can read in a Wikipedia article. So in itself video memory is an array of DRAM. DRAM today is one capacitor (which stores the data) and one mosfet transistor (which controls the flow of the data). So you have special wiring on the motherboard between the data bus of the processor and the VRAM. When you output data to video memory, you write to VRAM on the motherboard. Where you write and how just depends on the video mode you set up.
Most modern systems work with HDMI/Display port along with graphics card. These graphics card are other hardware interfaces which are often complex and they often cannot be known because the drivers for the cards are provided by the manufacturers. osdev.org has information on Intel HD Graphics which has a special interface to interact with. It can be used to gather info on the monitor and to determine what RAM address to use to write to the monitor.

Why does registers exists and how they work together with cpu?

So I am currently learning Operating Systems and Programming.
I want how the registers work in detail.
All I know is there is the main memory and our CPU which takes address and instruction from the main memory by the help of the address bus.
And also there is something MCC (Memory Controller Chip which helps in fetching the memory location from RAM.)
On the internet, it shows register is temporary storage and data can be accessed faster than ram for registers.
But I want to really understand the deep-down process on how they work. As they are also of 32 bits and 16 bits something like that. I am really confused.!!!
I'm not a native english speaker, pardon me for some perhaps incorrect terminology. Hope this will be a little bit helpful.
Why does registers exists
When user program is running on CPU, it works in a 'dynamic' sense. That is, we should store incoming source data or any intermediate data, and do specific calculation upon them. Memory devices are needed. We have a choice among flip-flop, on-chip RAM/ROM, and off-chip RAM/ROM.
The term register for programmer's model is actually a D flip-flop in the physical circuit, which is a memory device and can hold a single bit. An IC design consists of standard cell part (including the register mentioned before, and and/or/etc. gates) and hard macro (like SRAM). As the technology node advances, the standard cells' delay are getting smaller and smaller. Auto Place-n-Route tool will place the register and the related surrounding logic nearby, to make sure the logic can run at the specified 3.0/4.0GHz speed target. For some practical reasons (which I'm not quite sure because I don't do layout), we tend to place hard macros around, leading to much longer metal wire. This plus SRAM's own characteristics, on-chip SRAM is normally slower than D flip-flop. If the memory device is off the chip, say an external Flash chip or KGD (known good die), it will be further slower since the signals should traverse through 2 more IO devices which have much larger delay.
how they work together with cpu
Each register is assigned a different 'address' (which maybe not open to programmer). That is implemented by adding address decode logic. For instance, when CPU is going to execute an instruction mov R1, 0x12, the address decode logic sees the binary code of R1, and selects only those flip-flops corresponding to R1. Then data 0x12 is stored (written) into those flip-flops. Same for read process.
Regarding "they are also of 32 bits and 16 bits something like that", the bit width is not a problem. Both flip-flops and a word in RAM can have a bit width of N, as long as the same address can select N flip-flops or N bits in RAM at one time.
Registers are small memories which resides inside the processor (what you called CPU). Their role is to hold the operands for fast processor calculations and to store the results. A register is usually designated by a name (AL, BX, ECX, RDX, cr3, RIP, R0, R8, R15, etc.) and has a size which is the number of bits it can store (4, 8, 16, 32, 64, 128 bits). Other registers have special meanings, and their bits control the state or provide information about the state of the processor.
There are not many registers (because they are very expensive). All of them have a capacity of only a few kilobytes, so they can't store all the code and data of your program, which can go up to gigabytes. This is the role of the central memory (what you call RAM). This big memory can hold gigabytes of data and each byte has its address. However, it only holds data when the computer is turned on. The RAM reside outside of the CPU Chip and interacts with him via Memory Controller Chip which stands as interface between CPU and RAM.
On top of that, there is the hard drive that stores your data when you turn off your computer.
That is a very simple view to get you started.

How is CR8 register used to prioritize interrupts in an x86-64 CPU?

I'm reading the Intel documentation on control registers, but I'm struggling to understand how CR8 register is used. To quote the docs (2-18 Vol. 3A):
Task Priority Level (bit 3:0 of CR8) — This sets the threshold value
corresponding to the highest- priority interrupt to be blocked. A
value of 0 means all interrupts are enabled. This field is available
in 64- bit mode. A value of 15 means all interrupts will be disabled.
I have 3 quick questions, if you don't mind:
So bits 3 thru 0 of CR8 make up those 16 levels of priority values. But priority of what? A running "thread", I assume, correct?
But what is that priority value in CR8 compared to when an interrupt is received to see if it has to be blocked or not?
When an interrupt is blocked, what does it mean? Is it "delayed" until later time, or is it just discarded, i.e. lost?
CR8 indicates the current priority of the CPU. When an interrupt is pending, bits 7:4 of the interrupt vector number is compared to CR8. If the vector is greater, it is serviced, otherwise it is held pending until CR8 is set to a lower value.
Assuming the APIC is in use, it has an IRR (Interrupt Request Register) with one bit per interrupt vector number. When that bit is set, the interrupt is pending. It can stay that way forever.
When an interrupt arrives, it is ORed into the IRR. If the interrupt is already pending (that is, the IRR bit for that vector is already set), the new interrupt is merged with the prior one. (You could say it is dropped, but I don't think of it that way; instead, I say the two are combined into one.) Because of this merging, interrupt service routines must be designed to process all the work that is ready, rather than expecting a distinct interrupt for each unit of work.
Another related point is that Windows (and I assume Linux) tries to keep the IRQ level of a CPU as low as possible at all times. Interrupt service routines do as little work as possible at their elevated hardware interrupt level and then cue a deferred procedure call to do the rest of their work at DPC IRQ level. The DPC will normally be serviced immediately unless another IRQ has arrived because they are at a higher priority than normal processes.
Once a CPU starts executing a DPC it will then execute all the DPC's in its per CPU DPC cue before returning the CPU IRQL to zero to allow normal threads to resume.
The advantage of doing it this way is that an incoming hardware IRQ of any priority can interrupt a DPC and get its own DPC on the cue almost immediately, so it never gets missed.
I should also try and explain ( as I think it is 😁) the difference between the IRQ level of a CPU and the priority of an IRQ .
Before Control Register 8 became available with x64 the CPU had no notion of an IRQ level.
The designers of windows NT decided that every logical processor in a system should have a NOTIONAL IRQ Level that would be stored in a data structure called a processor control block for each CPU. They decided there should be 32 levels for no reason I know of 😁.
Software and hardware interrupts are also assigned a level so if they are above the level that the CPU has assigned then they are allowed to continue.
Windows does NOT make use of the interrupt priority assigned by the PIC/APIC hardware, instead it uses the interrupt mask bits in them. The various pins are assigned a vector number and then they get a level.
When Windows raises the LRQL of a CPU in its PCB it also reprograms the interrupt mask of the PIC/APIC. But not straight away.
Every interrupt that occurs causes the Windows trap dispatcher to execute and compare the IRQ level with the CPU IRQL and if the IRQ level is higher the interrupt goes ahead, if not THEN Windows reprograms the mask and returns to the executing thread instead.
The reason for that is that reprogramming the PIC takes time and if no lower level IRQ comes in then windows can save its self a job.
On x64 there IS CR8 and I am still looking at how that works.

Zilog z80 I, R registers purpose

There are I and R registers in the Control section of the Z80 cpu, what is their purpose and usage?
The R register is the memory refresh register. It's used to refresh dynamic RAM. Essentially, it is incremented on each instruction and placed on the address bus (when not in use for fetching or storing data) so that dynamic RAM chips can be refreshed.
You can ignore the R register, although people did use it as a source of semi random numbers.
The I register is the interrupt vector base register. In interrupt mode 2, the Z80 has a table of 128 interrupt vectors. The I register tells you the page in RAM where that table is.

Interrupt Vector. Location / Who sets it? [closed]

Closed. This question is off-topic. It is not currently accepting answers.
Want to improve this question? Update the question so it's on-topic for Stack Overflow.
Closed 10 years ago.
Improve this question
Knowing that An interrupt vector is the memory address of an interrupt handler, or an index into an array called an interrupt vector table that contains the memory addresses of interrupt handlers. When an interrupt is generated, the Operating System saves its execution state via a context switch, and begins execution of the interrupt handler at the interrupt vector.
I have some question, i have been searching hardly but no answer yet.
Is the interrupt vector stored at RAM? and if it is stored at RAM, who sets it to ram? the OS?
interrupt vector is the memory address of an interrupt handler
memory is synonym to RAM, so yes interrupt vector in stored in the RAM.If a device driver wants to register a interrupt handler function, you need to call appropriate OS calls(incase of linux it is request_irqs), and it would create a entry in the Interrupt vector table. This entry would point to wherever you interrupt handler function resides in memory/RAM. It's the OS that holds the responsibility to manage the interrupt vector table.
So, whenever that specific interrupt occurs, your interrupt handler function would be called.
It is in the FLASH. Not in the RAM. The registers are in the RAM. Cause the RAM is to store all the data. But the FLASH is to store all the program. And the interrupt vectors are generated by Compiler.
It depends on the hardware.
If there's only one address that the CPU can jump to on an interrupt then whether that's ROM or RAM depends on the memory map that the system has built around the CPU. Ditto for a predefined interrupt vector table. If the CPU allows a base address to be set for the interrupt table then it's obviously up to the OS.
Generally speaking, an OS that loads completely from disk — like Windows — will obviously keep it in RAM.
OSes that are stored partly or wholly in ROM generally keep the vector table in RAM so that it can be modified at runtime. On very constrained and well-defined systems like the 8-bit Acorn MOS that's because software might conceivably want to take full control of the hardware — if memory serves then that specific system has the hardware vector in ROM because of the fundamentals of the memory map but puts a routine there that then soft vectors through RAM. So it was a very deliberate decision.
On relatively more spacious systems like the classic Mac OS that's because it allows the ROM to be patched after the fact. If a bug is found in a particular interrupt routine after a machine has shipped then an OS update could be issued that would load a RAM replacement for the routine and just change the vector table. That's especially useful in Mac OS because all calls into the system use a trap mechanism that's analogous to an interrupt.
On the PC under modern windows OS's , the interrupt vectors are stored in the Interrupt Descriptor Table (IDT). You can find out where this table is located using the LIDT instruction (Load Interrupt Descriptor Table). But you cannot change a value there, unless you can get your code to run in Priviledge Level Zero (ring o), and Microsoft and Intel have conspired to make that almost impossible under Windows, as all instructions which would change the Code Segment Register (CS) to ring 0 are blocked to user programs. That's why WINTEL, like Australopithicus, might prove to be a dead-end in evolutionary terms (I hope).
Basically, PCs are nothing more than a smart terminal; you have to use them just as a terminal on your own machine to do REAL work, like controlling something.