Final pre-release
This commit is contained in:
@ -1,49 +0,0 @@
|
|||||||
\chapter{Figures}
|
|
||||||
\label{ch:figures}
|
|
||||||
|
|
||||||
\clearpage
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
|
||||||
\begin{subfigure}[b]{1.0\textwidth}
|
|
||||||
\includesvg[width=1.0\linewidth]{img/mp_spec_discrete_apic_configuration.svg}
|
|
||||||
\end{subfigure}
|
|
||||||
\caption{The discrete APIC architecture~\cite[sec.~5.1]{mpspec}.}
|
|
||||||
\label{fig:discreteapic}
|
|
||||||
\end{figure}
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
|
||||||
\begin{subfigure}[b]{1.0\textwidth}
|
|
||||||
\includesvg[width=1.0\linewidth]{img/mp_spec_integrated_apic_configuration.svg}
|
|
||||||
\end{subfigure}
|
|
||||||
\caption{The integrated APIC architecture~\cite[sec.~5.2]{mpspec}.}
|
|
||||||
\label{fig:integratedapic}
|
|
||||||
\end{figure}
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
|
||||||
\begin{subfigure}[b]{0.7\textwidth}
|
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_system_vs_apic_bus.svg}
|
|
||||||
\end{subfigure}
|
|
||||||
\caption{System vs APIC bus~\cite[sec.~3.11.1]{ia32}.}
|
|
||||||
\label{fig:systemvsapicbus}
|
|
||||||
\end{figure}
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
|
||||||
\begin{subfigure}[b]{1.0\textwidth}
|
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_local_apic_blockdiagram.svg}
|
|
||||||
\end{subfigure}
|
|
||||||
\caption{The local APIC block diagram~\cite[sec.~3.11.4.1]{ia32}.}
|
|
||||||
\label{fig:localapicblock}
|
|
||||||
\end{figure}
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
|
||||||
\centering
|
|
||||||
\begin{subfigure}[b]{1.0\textwidth}
|
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_lvt.svg}
|
|
||||||
\end{subfigure}
|
|
||||||
\caption{The Local Vector Table~\cite[sec.~3.11.5.1]{ia32}.}
|
|
||||||
\label{fig:localapiclvt}
|
|
||||||
\end{figure}
|
|
@ -1,360 +0,0 @@
|
|||||||
\chapter{Listings}
|
|
||||||
\label{ch:listings}
|
|
||||||
|
|
||||||
This chapter contains concrete implementation examples for concepts mentioned in
|
|
||||||
\autoref{ch:implementation}, demonstrated on the example of hhuOS\@.
|
|
||||||
|
|
||||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Accessing Local APIC Registers in xApic Mode}
|
|
||||||
\label{sec:apxxapicregacc}
|
|
||||||
|
|
||||||
The xApic register access requires a single page of strong uncachable memory, but since this
|
|
||||||
requires setting attributes in the ``Page Attribute Table''\footnote{See
|
|
||||||
\url{https://docs.kernel.org/x86/pat.html} (visited on 12/02/2023).}, this implementation only uses
|
|
||||||
hhuOS' \code{mapIO} function\cite[MemoryService.cpp]{hhuos}, which maps a physical address to the
|
|
||||||
kernel heap, with hhuOS' ``CACHE\textunderscore{}DISABLE'' flag set in the kernel page table:
|
|
||||||
|
|
||||||
\begin{codeblock}{Allocating the Local APIC's MMIO Region (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_mmio_alloc.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
A register can now be written as follows:
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:lapicmmiowrite]{Writing a Local APIC MMIO Register (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_mmio_write.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
To reduce the usage of manual bit-shifting and -masking, this implementation provides structures
|
|
||||||
for some commonly used registers, that implement conversion operators to the register format:
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:msrentry]{The MSREntry Structure (LocalApicRegisters.h)}{C++}
|
|
||||||
\cppfile{code/lapic_msr_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:svrentry]{The SVREntry Structure (LocalApicRegisters.h)}{C++}
|
|
||||||
\cppfile{code/lapic_svr_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:lvtentry]{The LVTEntry Structure (LocalApicRegisters.h)}{C++}
|
|
||||||
\cppfile{code/lapic_lvt_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:icrentry]{The ICREntry Structure (LocalApicRegisters.h)}{C++}
|
|
||||||
\cppfile{code/lapic_icr_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
These can be used in combination with some convenience functions:
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_write_msr.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing the SVR (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_write_svr.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing the LVT (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_write_lvt.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing the ICR (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_write_icr.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Disabling PIC-Mode}
|
|
||||||
\label{sec:apxdisablepic}
|
|
||||||
|
|
||||||
Setting the IMCR\footnote{Writing the IMCR is detailed in the MultiProcessor
|
|
||||||
specification~\cite[sec. 3.6.2.1]{mpspec}.} using hhuOS' \code{IoPort} class:
|
|
||||||
|
|
||||||
\begin{codeblock}{Disabling PIC-Mode (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_imcr.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Initializing the LVT}
|
|
||||||
\label{sec:apxlvtinit}
|
|
||||||
|
|
||||||
The interrupt vectors are set as defined by the \code{InterruptVector} enum. This implementation
|
|
||||||
configures the LVT by using the \code{LVTEntry} struct (see \autoref{lst:lvtentry}):
|
|
||||||
|
|
||||||
\begin{codeblock}{Configuring the LINT0 Local Interrupt (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_lvt_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
This process is repeated for each local interrupt.
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Handling the Spurious Interrupt}
|
|
||||||
\label{sec:apxsvr}
|
|
||||||
|
|
||||||
This implementation sets the SVR by using the \code{SVREntry} struct (see \autoref{lst:svrentry}):
|
|
||||||
|
|
||||||
\begin{codeblock}{Setting the Spurious Interrupt Vector (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_svr_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Because hhuOS uses a two-stage interrupt handling approach (described in
|
|
||||||
\autoref{sec:currenthhuos}), the spurious interrupt does not receive its own interrupt handler.
|
|
||||||
Instead, it is ignored in the \code{dispatch} function, hhuOS' ``first-stage'' interrupt handler:
|
|
||||||
|
|
||||||
\begin{codeblock}{Checking for Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
|
||||||
\cppfile{code/interruptdispatcher_check_spurious.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}{Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
|
||||||
\cppfile{code/interruptdispatcher_ignore_spurious.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Using the APIC Timer}
|
|
||||||
\label{sec:apxapictimer}
|
|
||||||
|
|
||||||
The timer frequency is determined by counting the ticks in one millisecond, using the PIT as
|
|
||||||
calibration source:
|
|
||||||
|
|
||||||
\begin{codeblock}{Calibrating the APIC Timer (ApicTimer.cpp)}{C++}
|
|
||||||
\cppfile{code/apictimer_calibrate.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
This calibration is performed before the interrupts get enabled, so it is not possible to use
|
|
||||||
hhuOS' \code{TimeService} for the delay. Instead, the \code{PIT::earlyDelay} function is used,
|
|
||||||
which configures the PIT for mode 0 on channel 0 and polls the channel's output status~\cite{pit}].
|
|
||||||
Furthermore, the calibration is only performed once, even if multiple APIC timers are used. This
|
|
||||||
removes the possibility of using multiple timers with different dividers.
|
|
||||||
|
|
||||||
To handle the APIC timer interrupt on multiple cores, \(n\) \code{ApicTimer} instances are
|
|
||||||
registered to the appropriate interrupt vector, where \(n\) is the number of CPUs. Because this
|
|
||||||
means, that each APIC timer interrupt on any CPU core triggers all \(n\) interrupt handlers, the
|
|
||||||
handler has to determine if it belongs to the calling CPU:
|
|
||||||
|
|
||||||
\begin{codeblock}{Handling the APIC Timer Interrupt (ApicTimer.cpp)}{C++}
|
|
||||||
\cppfile{code/apictimer_trigger.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Handling local APIC Errors}
|
|
||||||
\label{sec:apxhandlingerror}
|
|
||||||
|
|
||||||
The error interrupt handler obtains the ESR's contents by writing to it first:
|
|
||||||
|
|
||||||
\begin{codeblock}{The local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}{C++}
|
|
||||||
\cppfile{code/apicerror_trigger.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Because every CPU core can only access its own local APIC's registers, a single instance of this
|
|
||||||
interrupt handler can be used for each AP in the system.
|
|
||||||
|
|
||||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Accessing I/O APIC Registers}
|
|
||||||
\label{sec:iolistings}
|
|
||||||
|
|
||||||
The I/O APIC's indirect register access requires two MMIO registers, that can be written similar to
|
|
||||||
the local APIC's registers:
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing an I/O APIC MMIO Register (IoApic.h)}{C++}
|
|
||||||
\cppfile{code/ioapic_write_mmio.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Using the ``Index'' and ``Data'' registers to access the I/O APIC's indirect registers:
|
|
||||||
|
|
||||||
\begin{codeblock}{Writing an I/O APIC indirect Register (IoApic.cpp)}{C++}
|
|
||||||
\cppfile{code/ioapic_write_indirect.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
To reduce the manual bit-shifting and -masking, the same approach is used as for the local APIC:
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:redtblentry]{The REDTBLEntry Structure (IoApicRegisters.h)}{C++}
|
|
||||||
\cppfile{code/ioapic_redtbl_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:writeredtbl]{Writing the REDTBL (IoApic.cpp)}{C++}
|
|
||||||
\cppfile{code/ioapic_write_redtbl.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{I/O APIC Interrupt Overrides}
|
|
||||||
\label{sec:apxirqoverrides}
|
|
||||||
|
|
||||||
This implementation represents an interrupt override using the following structure:
|
|
||||||
|
|
||||||
\begin{codeblock}{The External Interrupt Override Structure (IoApic.h)}{C++}
|
|
||||||
\cppfile{code/ioapic_irqoverride.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
During initialization, they are used to set the correct interrupt vectors, polarities and trigger
|
|
||||||
modes for each REDTBL entry. The \code{REDTBLEntry} struct (see \autoref{lst:redtblentry}) is used
|
|
||||||
to write the REDTBL:
|
|
||||||
|
|
||||||
\begin{codeblock}{Initializing the REDTBL (IoApic.cpp)}{C++}
|
|
||||||
\cppfile{code/ioapic_redtbl_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
During regular OS operation, they are used to determine the correct REDTBL entries for e.g.\
|
|
||||||
unmasking an interrupt:
|
|
||||||
|
|
||||||
\begin{codeblock}{Unmasking an IRQ (Apic.cpp)}{C++}
|
|
||||||
\cppfile{code/apic_allow.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
To convey this deviation between GSIs and PC/AT compatible IRQs very clearly, the internal
|
|
||||||
\code{IoApic::allow} function only accepts a \code{GlobalSystemInterrupt} as argument, while the
|
|
||||||
public \code{Apic::allow} function accepts an \code{InterruptRequest}, that allows addressing the
|
|
||||||
interrupt by name.
|
|
||||||
|
|
||||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Issuing Inter-Processor Interrupts}
|
|
||||||
\label{sec:apxipis}
|
|
||||||
|
|
||||||
To issue an IPI, the ICR is written by using the \code{ICREntry} struct (see
|
|
||||||
\autoref{lst:icrentry}):
|
|
||||||
|
|
||||||
\begin{codeblock}{Issuing an INIT IPI (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_initipi_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}{Issuing a SIPI (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_sipi_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Preparing Symmetric Multiprocessing Startup}
|
|
||||||
\label{sec:apxpreparesmp}
|
|
||||||
|
|
||||||
Before executing the ``Universal Startup Algorithm'', the boot code has to be relocated to physical
|
|
||||||
lower memory. The memory region used for this copy has to be identity mapped to the virtual kernel
|
|
||||||
address space, so the effective addresses don't change after enabling paging in protected mode. To
|
|
||||||
keep required variables available to the startup code, these are located in the routines ``TEXT''
|
|
||||||
section and initialized during runtime. This approach was taken from~\cite[APIC.cpp]{serenity}:
|
|
||||||
|
|
||||||
\begin{codeblock}{Preparing the Boot Routine's Variables (ApicSmp.cpp)}{C++}
|
|
||||||
\cppfile{code/ap_boot_variables.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Now, the initialized startup routine can be copied to \code{0x8000}:
|
|
||||||
|
|
||||||
\begin{codeblock}{Relocating the Boot Routine (ApicSmp.cpp)}{C++}
|
|
||||||
\cppfile{code/ap_boot_copy.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
The \code{boot\textunderscore{}ap} function is the entry of the startup routine, it is described
|
|
||||||
further in \autoref{sec:apxapboot}.
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Universal Startup Algorithm}
|
|
||||||
\label{sec:apxmpusa}
|
|
||||||
|
|
||||||
The ``INIT-SIPI-SIPI'' sequence, or ``Universal Startup Algorithm'' is performed by issuing IPIs as
|
|
||||||
described in \autoref{sec:apxipis} and using the PIT as time source (see
|
|
||||||
\autoref{sec:apxapictimer}):
|
|
||||||
|
|
||||||
\begin{codeblock}{The Universal Startup Algorithm (ApicSmp.cpp)}{C++}
|
|
||||||
\cppfile{code/ap_boot_usa.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Boot completion is signaled in the AP's entry function:
|
|
||||||
|
|
||||||
\begin{codeblock}{Signaling AP Boot Completion (smp\textunderscore{}entry.cpp)}{C++}
|
|
||||||
\cppfile{code/smp_entry.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Application Processor Boot Routine}
|
|
||||||
\label{sec:apxapboot}
|
|
||||||
|
|
||||||
Because like the BSP, every AP is initialized in real mode, it has to be switched to protected mode
|
|
||||||
first:
|
|
||||||
|
|
||||||
\begin{codeblock}{Preparing the Switch to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
|
||||||
\nasmfile{code/ap_boot_real_prepare.asm}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Then, by enabling protected mode, setting the segment registers and far-jumping to the 32-bit code
|
|
||||||
segment, the switch is performed:
|
|
||||||
|
|
||||||
\begin{codeblock}{Switching from Real Mode to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
|
||||||
\nasmfile{code/ap_boot_real.asm}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
In 32-bit protected mode, paging is enabled and interrupt processing is prepared by reusing the
|
|
||||||
control register values and the IDT from the BSP:
|
|
||||||
|
|
||||||
\begin{codeblock}{Loading Registers from the BSP (smp\textunderscore{}boot.asm)}{nasm}
|
|
||||||
\nasmfile{code/ap_boot_protected_bsp.asm}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Finally, to call the AP entry function, the AP requires its own GDT and stack:
|
|
||||||
|
|
||||||
\begin{codeblock}{Calling the Entry Function (smp\textunderscore{}boot.asm)}{nasm}
|
|
||||||
\nasmfile{code/ap_boot_protected_ap.asm}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
The rest of the AP's initialization is performed from the entry function.
|
|
||||||
|
|
||||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Application Processor Post-Boot Routine}
|
|
||||||
\label{sec:apxappostboot}
|
|
||||||
|
|
||||||
When the AP has booted, it initializes its own APIC, including the APIC timer and error handler:
|
|
||||||
|
|
||||||
\begin{codeblock}{Initializing the Core's Local APIC (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/ap_boot_post.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Because this added another possible recipient to internal APIC messages, the arbitration IDs are
|
|
||||||
synchronized by issuing an ``INIT-level-deassert IPI'' using the \code{ICREntry} struct (see
|
|
||||||
\autoref{lst:icrentry}):
|
|
||||||
|
|
||||||
\begin{codeblock}{Synchronizing the Arbitration IDs (LocalApic.cpp)}{C++}
|
|
||||||
\cppfile{code/lapic_apr_example.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
Because hhuOS' paging is not designed for multiple processors, the booted AP remains in a busy loop
|
|
||||||
and does not enable its interrupts.
|
|
||||||
|
|
||||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
|
||||||
|
|
||||||
\section{Integration into hhuOS}
|
|
||||||
\label{sec:hhuosintegration}
|
|
||||||
|
|
||||||
To integrate the APIC implementation into hhuOS, some preexisting components of its interrupt
|
|
||||||
infrastructure (described in \autoref{sec:currenthhuos}) have to be modified:
|
|
||||||
|
|
||||||
\begin{enumerate}
|
|
||||||
\item The \code{InterruptService} has to forward calls to allow or forbid a hardware interrupt to the
|
|
||||||
\code{Apic} class instead of the \code{Pic} class, depending on if the APIC system is enabled - to
|
|
||||||
keep the option of running the OS on hardware that does not support the APIC (see
|
|
||||||
\autoref{lst:interruptserviceafter}).
|
|
||||||
\item The \code{Pit} interrupt handler may no longer trigger the scheduler preemption if the APIC timer
|
|
||||||
is enabled (see \autoref{lst:pithandlerafter}).
|
|
||||||
\item The \code{System::initializeSystem} function needs to enable the APIC system if it is available
|
|
||||||
(see \autoref{lst:systemafter}).
|
|
||||||
\end{enumerate}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:interruptserviceafter]{Using the correct interrupt controller (InterruptService.cpp)}{C++}
|
|
||||||
\cppfile{code/interruptservice_after.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:pithandlerafter]{Disable preemption if necessary (Pit.cpp)}{C++}
|
|
||||||
\cppfile{code/pit_after.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:systemafter]{Enabling the APIC system (System.cpp)}{C++}
|
|
||||||
\cppfile{code/system_after.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\cleardoublepage
|
|
236
chap/background.aux
Normal file
236
chap/background.aux
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {2}Background}{3}{chapter.2}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:background}{{2}{3}{Background}{chapter.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.1}Handling of External Events}{4}{section.2.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:eventhandling}{{2.1}{4}{Handling of External Events}{section.2.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.2}Fundamental Concepts}{4}{section.2.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:fundamentals}{{2.2}{4}{Fundamental Concepts}{section.2.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.1}Interrupt}{4}{subsection.2.2.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:interrupt}{{2.2.1}{4}{Interrupt}{subsection.2.2.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.2}Interrupt Controller}{5}{subsection.2.2.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:controller}{{2.2.2}{5}{Interrupt Controller}{subsection.2.2.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.3}Interrupt Handler}{5}{subsection.2.2.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:handler}{{2.2.3}{5}{Interrupt Handler}{subsection.2.2.3}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2.1}{\ignorespaces Interrupt Handler Execution.\relax }}{6}{figure.2.1}\protected@file@percent }
|
||||||
|
\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
|
||||||
|
\newlabel{fig:interruptexecution}{{2.1}{6}{Interrupt Handler Execution.\relax }{figure.2.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.4}Interrupt Trigger Mode}{6}{subsection.2.2.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:triggermode}{{2.2.4}{6}{Interrupt Trigger Mode}{subsection.2.2.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.5}Spurious Interrupt}{6}{subsection.2.2.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:spurious}{{2.2.5}{6}{Spurious Interrupt}{subsection.2.2.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.3}Used Technologies}{7}{section.2.3}\protected@file@percent }
|
||||||
|
\newlabel{sec:technologies}{{2.3}{7}{Used Technologies}{section.2.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.1}Advanced Configuration and Power Interface}{7}{subsection.2.3.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:acpi}{{2.3.1}{7}{Advanced Configuration and Power Interface}{subsection.2.3.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.2}CPU Identification}{7}{subsection.2.3.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:cpuid}{{2.3.2}{7}{CPU Identification}{subsection.2.3.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.3}Symmetric Multiprocessing}{7}{subsection.2.3.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:smp}{{2.3.3}{7}{Symmetric Multiprocessing}{subsection.2.3.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.4}Model Specific Register}{8}{subsection.2.3.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:msr}{{2.3.4}{8}{Model Specific Register}{subsection.2.3.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.5}Memory Mapped I/O}{8}{subsection.2.3.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:mmio}{{2.3.5}{8}{Memory Mapped I/O}{subsection.2.3.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.6}Programmable Interval Timer}{8}{subsection.2.3.6}\protected@file@percent }
|
||||||
|
\newlabel{subsec:pit}{{2.3.6}{8}{Programmable Interval Timer}{subsection.2.3.6}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.4}Intel's Interrupt Controllers}{8}{section.2.4}\protected@file@percent }
|
||||||
|
\newlabel{sec:intelcontrollers}{{2.4}{8}{Intel's Interrupt Controllers}{section.2.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.1}Programmable Interrupt Controller}{8}{subsection.2.4.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:intelpic}{{2.4.1}{8}{Programmable Interrupt Controller}{subsection.2.4.1}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2.2}{\ignorespaces The PC/AT PIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~1.13]{pcat}.\relax }}{9}{figure.2.2}\protected@file@percent }
|
||||||
|
\newlabel{fig:pcatpic}{{2.2}{9}{The PC/AT PIC Architecture~\autocite [sec.~1.13]{pcat}.\relax }{figure.2.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.2}Advanced Programmable Interrupt Controller}{10}{subsection.2.4.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:intelapic}{{2.4.2}{10}{Advanced Programmable Interrupt Controller}{subsection.2.4.2}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2.3}{\ignorespaces The Discrete APIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~5.1]{mpspec}.\relax }}{11}{figure.2.3}\protected@file@percent }
|
||||||
|
\newlabel{fig:discreteapic}{{2.3}{11}{The Discrete APIC Architecture~\autocite [sec.~5.1]{mpspec}.\relax }{figure.2.3}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2.4}{\ignorespaces The Integrated APIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~5.2]{mpspec}.\relax }}{12}{figure.2.4}\protected@file@percent }
|
||||||
|
\newlabel{fig:integratedapic}{{2.4}{12}{The Integrated APIC Architecture~\autocite [sec.~5.2]{mpspec}.\relax }{figure.2.4}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {2.5}{\ignorespaces System Bus vs APIC Bus~\blx@tocontentsinit {0}\autocite [sec.~3.11.1]{ia32}.\relax }}{13}{figure.2.5}\protected@file@percent }
|
||||||
|
\newlabel{fig:systemvsapicbus}{{2.5}{13}{System Bus vs APIC Bus~\autocite [sec.~3.11.1]{ia32}.\relax }{figure.2.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.5}PC/AT Compatibility}{13}{section.2.5}\protected@file@percent }
|
||||||
|
\newlabel{sec:pcatcompat}{{2.5}{13}{PC/AT Compatibility}{section.2.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {2.6}Interrupt Handling in HhuOS}{14}{section.2.6}\protected@file@percent }
|
||||||
|
\newlabel{sec:currenthhuos}{{2.6}{14}{Interrupt Handling in HhuOS}{section.2.6}{}}
|
||||||
|
\@setckpt{chap/background}{
|
||||||
|
\setcounter{page}{15}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{2}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{17}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{2}
|
||||||
|
\setcounter{section}{6}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{5}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{15}
|
||||||
|
\setcounter{FancyVerbLine}{0}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{22}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{0}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{0}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{1}
|
||||||
|
\setcounter{Item}{12}
|
||||||
|
\setcounter{Hfootnote}{17}
|
||||||
|
\setcounter{bookmark@seq@number}{21}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{0}
|
||||||
|
\setcounter{@ppsavesec}{0}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{26}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{6}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -1,31 +1,25 @@
|
|||||||
\chapter{Background}
|
\chapter{Background}
|
||||||
\label{ch:background}
|
\label{ch:background}
|
||||||
|
|
||||||
In this section, important domain specific concepts will be explained, to create the necessary
|
In this section, important domain-specific concepts will be explained, to create the necessary foundation to follow \autoref{ch:implementation}.
|
||||||
foundation to follow \autoref{ch:implementation}. Important terms that are present in the glossary
|
Important terms present in the glossary are marked in \textbf{bold} on their first occurrence.
|
||||||
are marked in \textbf{bold} on their first occurrence.
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Handling of External Events}
|
\section{Handling of External Events}
|
||||||
\label{sec:eventhandling}
|
\label{sec:eventhandling}
|
||||||
|
|
||||||
There are two different strategies to ``listen'' for external events: ``Polling'' and
|
There are two different strategies to \textquote{listen} for external events: \textquote{Polling} and \textquote{Interrupts}.
|
||||||
``Interrupts''.
|
|
||||||
|
|
||||||
The first strategy works by periodically \textit{polling} a device to check for changes. This could
|
The first strategy works by periodically \textit{polling} a device to check for changes.
|
||||||
mean reading a register of the keyboard every 50 ms to determine if a key was pressed, or reading a
|
This could mean reading a register of the keyboard every \SI{50}{\milli\second} to determine if a key was pressed, or reading a sensor output even when the value remains unchanged.
|
||||||
sensor output even when the value remains unchanged. Because every device would have to be polled
|
Because every device would have to be polled constantly, no matter if any change actually occurred, this method is computationally inefficient (although easy to implement without extra hardware).
|
||||||
constantly, no matter if any change actually occurred, this method is computationally inefficient
|
|
||||||
(although easy to implement without extra hardware).
|
|
||||||
|
|
||||||
The second strategy are \textbf{\glspl{interrupt}}. Instead of the CPU actively ``looking'' for
|
The second strategy are \textit{interrupts}.
|
||||||
changes, the devices signal the events to the CPU themselves. Every time the CPU is notified of an
|
Instead of the CPU actively \textquote{looking} for changes, the devices signal the events to the CPU themselves.
|
||||||
external event, it pauses the current code execution and calls a function designated to handle this
|
Every time the CPU is notified of an external event, it pauses the current code execution and calls a function designated to handle this specific event.
|
||||||
specific event.
|
|
||||||
|
|
||||||
This approach is much more efficient than the polling strategy, because the CPU does not have to
|
This approach is much more efficient than the polling strategy, because the CPU does not have to waste its processing power to check for events when none are occurring.
|
||||||
waste its processing power to check for events when none are occurring.
|
|
||||||
|
|
||||||
\section{Fundamental Concepts}
|
\section{Fundamental Concepts}
|
||||||
\label{sec:fundamentals}
|
\label{sec:fundamentals}
|
||||||
@ -33,119 +27,101 @@ waste its processing power to check for events when none are occurring.
|
|||||||
\subsection{Interrupt}
|
\subsection{Interrupt}
|
||||||
\label{subsec:interrupt}
|
\label{subsec:interrupt}
|
||||||
|
|
||||||
When a device signals an external event to the CPU, the current code execution gets
|
When a device signals an external event to the CPU, the current code execution gets \textit{interrupted}, to handle the event.
|
||||||
\textit{interrupted}, to handle the event. Thus, the process of signaling and handling an external
|
|
||||||
event is called ``interrupt''.
|
|
||||||
|
|
||||||
Interrupts can be caused by all sorts of events, like key presses on a keyboard or packets received
|
Interrupts can be caused by all sorts of events, like key presses on a keyboard or packets received via a network card.
|
||||||
via a network card. These interrupts from external hardware devices are called
|
These interrupts from external hardware devices are called \textit{external interrupts}.
|
||||||
\textbf{\glspl{external interrupt}}.
|
|
||||||
|
|
||||||
Other types of interrupts mentioned in this thesis are \textbf{\glspl{ipi}}, \textbf{\glspl{msi}}
|
Other types of interrupts mentioned in this thesis are \textbf{\glspl{ipi}}, \textbf{\glspl{msi}} and \textbf{\glspl{local interrupt}}:
|
||||||
and \textbf{\glspl{local interrupt}}:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item IPIs: Interrupts sent between different processor cores in multiprocessor systems, for example to
|
\item IPIs: Interrupts sent between different processor cores in multiprocessor systems, e.g.\ to initialize different cores on system startup or synchronize caches.
|
||||||
initialize different cores on system startup.
|
\item MSIs: Interrupts sent in-band\footnote{
|
||||||
\item MSIs: Interrupts sent in-band\footnote{In in-band signaling some control information (like an IRQ)
|
In in-band signaling, control information is sent over the same channel as the data, while out-of-band signaling uses a dedicated control line.},
|
||||||
is sent over the same channel as the data. This stands in contrast to out-of-band signaling, which
|
\ e.g.\ over a PCI-bus\footnote{
|
||||||
uses a dedicated control line (like an interrupt line).}, for example over a PCI-bus\footnote{PCI
|
PCI supports MSIs since PCI 2.2~\autocite[sec.~6.8]{pci22}.}.
|
||||||
supports MSIs since PCI 2.2~\cite[sec.~6.8]{pci22}.}.
|
\item Local Interrupts: Some specific CPU-internal interrupts, e.g.\ for performance monitoring.
|
||||||
\item Local Interrupts: Some specific CPU-internal interrupts.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Some interrupts are essential for continuous CPU operation. These \textbf{\glspl{nmi}} always have
|
Some interrupts are essential for CPU operation.
|
||||||
to be handled and cannot be ignored (usually\footnote{An example where NMIs should be disabled is
|
These \textbf{\glspl{nmi}} always have to be handled and cannot be ignored (except in some special cases, like booting).
|
||||||
the startup of additional processors in multiprocessor systems.}). Hardware error interrupts are a
|
Hardware error interrupts are a typical example for NMIs.
|
||||||
typical example for NMIs.
|
|
||||||
|
|
||||||
The existence of NMIs hints that it is possible to ignore regular interrupts. Marking an interrupt
|
The existence of NMIs hints that it is possible to ignore regular interrupts.
|
||||||
as ``ignored'' is called \textbf{\gls{masking}} an interrupt.
|
Marking an interrupt as \textquote{ignored} is called \textit{masking} an interrupt.
|
||||||
|
|
||||||
\subsection{Interrupt Controller}
|
\subsection{Interrupt Controller}
|
||||||
\label{subsec:controller}
|
\label{subsec:controller}
|
||||||
|
|
||||||
A computer system has to process interrupts from many sources, so it is practical to have a
|
A computer system has to process interrupts from many sources, so it is practical to have a designated \textit{interrupt controller}, that receives interrupts from different devices and forwards them to the CPU\@.
|
||||||
designated \textbf{\gls{interrupt controller}}, that receives interrupts from different devices and
|
The masking functionality is integrated into the interrupt controller, so masked interrupts do not reach the CPU at all.
|
||||||
forwards them to the CPU. The masking functionality is integrated into the interrupt controller, so
|
|
||||||
masked interrupts don't reach the CPU at all.
|
|
||||||
|
|
||||||
The interrupt controller receives interrupts through signals over physical connections (interrupt
|
The interrupt controller receives interrupts through signals over physical connections (\textit{interrupt lines}) to different devices.
|
||||||
lines) to different devices. These signals can be represented in multiple ways through the level on
|
These signals can be represented in multiple ways through the level on the interrupt lines:
|
||||||
the interrupt lines:
|
|
||||||
|
|
||||||
\textbf{\Gls{trigger mode}}:
|
\textit{Trigger mode}:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Edge-triggered signal: A signal is received when the interrupt line level changes
|
\item Edge-triggered: A signal is received when the interrupt line level changes.
|
||||||
\item Level-triggered signal: A signal is received when the interrupt line reaches a certain level
|
\item Level-triggered: A signal is received when the interrupt line reaches a certain level.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
\textbf{\Gls{pin polarity}}:
|
\textit{Pin polarity}:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item High: A signal is received when the interrupt line level changes from either low to high (in
|
\item Active-high: A signal is received when the interrupt line level changes from either low to high (in edge-triggered mode) or reaches a level above a threshold (in level-triggered mode).
|
||||||
edge-triggered mode) or reaches a level above a threshold (in level-triggered mode)
|
\item Active-low: A signal is received when the interrupt line level changes from either high to low (in edge-triggered mode) or reaches a level below a threshold (in level-triggered mode).
|
||||||
\item Low: A signal is received when the interrupt line level changes from either high to low (in
|
|
||||||
edge-triggered mode) or reaches a level below a threshold (in level-triggered mode)
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
A signal is represented through a combination of trigger mode and pin polarity, so there are a
|
A signal is represented through a combination of trigger mode and pin polarity, so there are a total of four combinations.
|
||||||
total of 4 combinations.
|
|
||||||
|
|
||||||
When the interrupt controller receives an interrupt signal, it requests the CPU to handle the
|
When the interrupt controller receives an interrupt signal, it requests the CPU to handle the specific event: The interrupt controller sends an \textbf{\gls{irq}} to the CPU\@.
|
||||||
specific event: The interrupt controller sends an \textbf{\gls{irq}} to the CPU. Because there are
|
Because there are multiple devices that can signal interrupts, an IRQ is usually indexed by its \textbf{\gls{inti}} on the interrupt controller: If a keyboard is connected to the interrupt controller on INTI1, the CPU receives an IRQ1.
|
||||||
multiple devices that can signal interrupts, an IRQ is usually indexed by its hardware pin on the
|
|
||||||
interrupt controller: If a keyboard is connected to the interrupt controller on pin 1, the CPU
|
|
||||||
receives an IRQ1.
|
|
||||||
|
|
||||||
To signal that an interrupt has been handled by the software, the interrupt controller receives an
|
To signal that an interrupt is being handled by the software, the interrupt controller receives an \textbf{\gls{eoi}} notice from the OS\@.
|
||||||
\textbf{\gls{eoi}} notice from the OS\@.
|
|
||||||
|
|
||||||
Information on specific interrupt controllers follows in \autoref{sec:intelcontrollers}.
|
Information on specific interrupt controllers follows in \autoref{sec:intelcontrollers}.
|
||||||
|
|
||||||
\subsection{Interrupt Handler}
|
\subsection{Interrupt Handler}
|
||||||
\label{subsec:handler}
|
\label{subsec:handler}
|
||||||
|
|
||||||
When the CPU receives an IRQ, it pauses its current code execution to handle the interrupt. This is
|
When the CPU receives an IRQ, it pauses its current code execution to handle the interrupt (see \autoref{fig:interruptexecution}).
|
||||||
done by executing the \textbf{\gls{interrupt handler}} function, that is registered to the specific
|
This is done by executing the \textit{interrupt handler} function, that is registered to the specific interrupt.
|
||||||
interrupt.
|
|
||||||
|
|
||||||
During interrupt servicing (execution of the interrupt handler), other interrupts can occur. When
|
\begin{figure}[h]
|
||||||
the execution of an interrupt handler is paused to handle another interrupt, this is called a
|
\centering
|
||||||
\textbf{\gls{cascaded interrupt}}.
|
\begin{subfigure}[b]{0.5\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{diagrams/interrupt_seq.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{Interrupt Handler Execution.}
|
||||||
|
\label{fig:interruptexecution}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
Interrupt handlers have to be registered to different IRQs, so the CPU can locate and execute the
|
During interrupt servicing (execution of the interrupt handler), other interrupts can occur.
|
||||||
specific code that is designated to handle a certain interrupt. The interrupt handler addresses are
|
When the execution of an interrupt handler is paused to handle another interrupt, this is called a \textit{cascaded interrupt}.
|
||||||
stored in an \textit{interrupt vector table}: Each address corresponds to an \textbf{\gls{interrupt
|
|
||||||
vector}} number, interrupt vectors 0 to 31 are reserved for the CPU, interrupt vectors 32 to 255
|
Interrupt handlers have to be registered to different IRQs, so the CPU can locate and execute the specific code that is designated to handle a certain interrupt.
|
||||||
are usable for IRQs. In Intel's 32 bit IA-32 CPU architecture, this table is called the
|
The interrupt handler addresses are stored in an \textit{interrupt vector table}: Each address corresponds to an \textit{interrupt vector} number, interrupt vectors 0--31 are reserved for the CPU, interrupt vectors 32--255 are usable for IRQs.
|
||||||
\textbf{\gls{idt}}. The \textbf{\gls{idtr}} keeps the location of the IDT, it is written by the
|
In Intel's x86 IA-32 CPU architecture, this table is called the \textbf{\gls{idt}}.
|
||||||
\code{lidt}~\cite{x86isa} instruction.
|
The \textbf{\gls{idtr}} keeps the location of the IDT, it is written by the \code{lidt}~\autocite{x86isa} instruction.
|
||||||
|
|
||||||
\subsection{Interrupt Trigger Mode}
|
\subsection{Interrupt Trigger Mode}
|
||||||
\label{subsec:triggermode}
|
\label{subsec:triggermode}
|
||||||
|
|
||||||
When an edge-triggered IRQ is received, its interrupt handler is called a single time, serviced,
|
When an edge-triggered IRQ is received, its interrupt handler is called a single time to service the interrupt, which does not require interacting with the device the interrupt originated from.
|
||||||
and marked as completed in the interrupt controller (completion does not require interacting with
|
The handler of an edge-triggered IRQ is called every time the interrupt line changes its level (low-to-high or high-to-low, as specified by the pin polarity).
|
||||||
the device the interrupt originated from). The handler of an edge-triggered IRQ is called every
|
This could lead to problems if \textquote{glitches} occur on the interrupt line.
|
||||||
time the interrupt line changes its level. This could lead to problems if ``glitches'' occur on the
|
|
||||||
interrupt line.
|
|
||||||
|
|
||||||
An alternative is the level-triggered IRQ: When the interrupt line is above/below a certain level,
|
An alternative is the level-triggered IRQ\@: When the interrupt line is above/below a certain level, the interrupt is signaled continuously.
|
||||||
the interrupt is signaled continuously. Servicing the interrupt thus requires not only signaling
|
Servicing the interrupt thus requires not only notifying the interrupt controller (EOI), but also interaction with the device the interrupt originated from, to deassert the interrupt line.
|
||||||
completion to the interrupt controller, but also to the device the interrupt originated from, to
|
Otherwise, the interrupt handler would be called again after completion.
|
||||||
de-assert the interrupt line. Otherwise, the interrupt handler would be called again after
|
|
||||||
completion.
|
|
||||||
|
|
||||||
\subsection{Spurious Interrupt}
|
\subsection{Spurious Interrupt}
|
||||||
\label{subsec:spurious}
|
\label{subsec:spurious}
|
||||||
|
|
||||||
When an interrupt disappears while the interrupt controller is issuing the IRQ to the CPU, the
|
When an interrupt \textquote{disappears} while the interrupt controller is issuing the IRQ, the interrupt controller sends a \textit{spurious interrupt}.
|
||||||
interrupt controller sends a \textbf{\gls{spurious interrupt}}. The reason for this could be
|
The reason for this could be electrical noise on the interrupt line, masking of an interrupt through software at the same moment the IRQ was dispatched, or incorrectly sent EOIs.
|
||||||
electrical noise on the interrupt line, masking of an interrupt through software at the same moment
|
Thus, before an interrupt handler is called, the OS has to check the validity of the occurred interrupt and ignore it, if it is deemed spurious.
|
||||||
this interrupt was received, or incorrectly sent EOIs. Thus, before an interrupt handler is called,
|
|
||||||
the OS has to check the validity of the occurred interrupt and ignore it, if it is deemed spurious.
|
|
||||||
|
|
||||||
\section{Used Technologies}
|
\section{Used Technologies}
|
||||||
\label{sec:technologies}
|
\label{sec:technologies}
|
||||||
@ -153,43 +129,33 @@ the OS has to check the validity of the occurred interrupt and ignore it, if it
|
|||||||
\subsection{Advanced Configuration and Power Interface}
|
\subsection{Advanced Configuration and Power Interface}
|
||||||
\label{subsec:acpi}
|
\label{subsec:acpi}
|
||||||
|
|
||||||
\textbf{\gls{acpi}} allows the kernel to gather information about the system hardware during
|
\textbf{\gls{acpi}} allows the kernel to gather information about the system hardware during runtime.
|
||||||
runtime. It also provides interactive functionality for power management, plug and play,
|
It also provides interactive functionality for power management, plug and play, hot-swapping or status monitoring.
|
||||||
hot-swapping or status monitoring. To interact with ACPI, the
|
To interact with ACPI, the \textbf{\gls{aml}}~\autocite[sec.~16]{acpi1}, a small language interpreted by the kernel, has to be used\footnote{
|
||||||
\textbf{\gls{aml}}~\cite[sec.~16]{acpi1}, a small language interpreted by the kernel, has to be
|
In this thesis, information from ACPI is only read, so AML is not required.}.
|
||||||
used\footnote{In this thesis, information from ACPI is only read, so AML is not required.}.
|
|
||||||
|
|
||||||
ACPI defines abstractions for different types of hardware, that are organized in multiple
|
ACPI defines abstractions for different types of hardware, that are organized in multiple \textit{system description tables}.
|
||||||
\textit{system description tables}. In this thesis, ACPI 1.0~\cite{acpi1} is used to read
|
In this thesis, ACPI 1.0~\autocite{acpi1} is used to read information about the system's interrupt hardware configuration, located in the ACPI \textbf{\gls{madt}}~\autocite[sec.~5.2.8]{acpi1}.
|
||||||
information about the system's interrupt hardware configuration, located in the ACPI
|
The MADT contains information on used interrupt controllers (version, physical memory addresses to access registers, etc.), available CPU cores in multiprocessor systems and specific interrupt configuration (trigger mode and pin polarity).
|
||||||
\textbf{\gls{madt}}~\cite[sec.~5.2.8]{acpi1}. The MADT contains information on used interrupt
|
|
||||||
controllers (version, physical memory addresses to access registers, etc.), available CPU cores in
|
|
||||||
multiprocessor systems and specific interrupt configuration (trigger mode and pin polarity).
|
|
||||||
|
|
||||||
To allow compatibility to different interrupt controllers, ACPI abstracts external interrupts
|
To allow compatibility to different interrupt controllers, ACPI abstracts external interrupts through \textbf{\glspl{gsi}}~\autocite[sec.~5.2.9]{acpi1}.
|
||||||
through \textbf{\glspl{gsi}}~\cite[sec.~5.2.9]{acpi1}. Different interrupt controllers may have the
|
Different interrupt controllers may have the same devices connected to different interrupt lines, maintaining a mapping between actual hardware interrupt lines and GSIs allows the OS to operate on different interrupt controllers\footnote{
|
||||||
same devices connected to different interrupt lines, maintaining a mapping between actual hardware
|
Additional information in \autoref{subsec:ioapicpcat}.}.
|
||||||
interrupt lines and GSIs allows the OS to operate on different interrupt
|
|
||||||
controllers\footnote{Additional information in \autoref{subsec:ioapicpcat}.}.
|
|
||||||
|
|
||||||
\subsection{CPU Identification}
|
\subsection{CPU Identification}
|
||||||
\label{subsec:cpuid}
|
\label{subsec:cpuid}
|
||||||
|
|
||||||
\textbf{\gls{cpuid}} is used to gather information about a system's CPU. The x86 architecture
|
\textbf{\gls{cpuid}} is used to gather information about a system's CPU\@.
|
||||||
provides the \code{cpuid}~\cite{x86isa} instruction, which allows the software to identify present
|
The x86 architecture provides the \code{cpuid}~\autocite{x86isa} instruction, which allows the software to identify present CPU features at runtime, e.g.\ what instruction set extensions a processor implements\footnote{
|
||||||
CPU features at runtime, e.g.\ what instruction set extensions a processor implements\footnote{This
|
This thesis uses CPUID to determine what APIC feature set is supported, see \textquote{APIC} and \textquote{x2APIC} features in the CPUID application note~\autocite[sec.~5.1.2]{cpuid}.}.
|
||||||
thesis uses CPUID to determine what APIC feature set is supported, see ``APIC'' and ``x2APIC''
|
|
||||||
features in the CPUID application note~\cite[sec.~5.1.2]{cpuid}.}.
|
|
||||||
|
|
||||||
\subsection{Symmetric Multiprocessing}
|
\subsection{Symmetric Multiprocessing}
|
||||||
\label{subsec:smp}
|
\label{subsec:smp}
|
||||||
|
|
||||||
\textbf{\gls{smp}} is a form of multiprocessing, where a system consists of multiple, homogeneous
|
\textbf{\gls{smp}} is a form of multiprocessing, where a system consists of multiple, homogeneous CPU cores, that all have access to a shared main memory and the I/O devices.
|
||||||
CPU cores, that all have access to a shared main memory and the I/O devices. SMP systems are
|
SMP systems are controlled by a single OS, that treats all cores as individual, but equal processors.
|
||||||
controlled by a single OS, that treats all cores as individual, but equal processors. The shared
|
The shared main memory allows every core to work on an arbitrary task, independent of its memory location.
|
||||||
main memory allows every core to work on an arbitrary task, independent of its memory location.
|
Programming for SMP systems requires the usage of multithreading, to allow for an efficient distribution of tasks to multiple CPU cores.
|
||||||
Programming for SMP systems requires the usage of multithreading, to allow for an efficient
|
|
||||||
distribution of tasks to multiple CPU cores.
|
|
||||||
|
|
||||||
In SMP systems, a single CPU core is active initially, this core is called the \textbf{\gls{bsp}}.
|
In SMP systems, a single CPU core is active initially, this core is called the \textbf{\gls{bsp}}.
|
||||||
Other cores, called \textbf{\glspl{ap}}, will be initialized by this core.
|
Other cores, called \textbf{\glspl{ap}}, will be initialized by this core.
|
||||||
@ -211,90 +177,77 @@ Other cores, called \textbf{\glspl{ap}}, will be initialized by this core.
|
|||||||
\subsection{Model Specific Register}
|
\subsection{Model Specific Register}
|
||||||
\label{subsec:msr}
|
\label{subsec:msr}
|
||||||
|
|
||||||
A \textbf{\gls{msr}} is a special control register in an IA-32 CPU, that is not guaranteed to be
|
A \textbf{\gls{msr}} is a special control register in an IA-32 CPU, that is not guaranteed to be present in future CPU generations (it is not part of the architectural standard).
|
||||||
present in future CPU generations (it is not part of the architectural standard). MSRs that carried
|
MSRs that carried over to future generations and are now guaranteed to be included in future IA-32 or Intel 64 CPUs are called \textquote{architectural} MSRs.
|
||||||
over to future generations and are now guaranteed to be included in future IA-32 or Intel 64 CPUs
|
To interact with MSRs, the special instructions \code{rdmsr} and \code{wrmsr} are used~\autocite{x86isa}.
|
||||||
are called ``architectural'' MSRs. To interact with MSRs, the special instructions \code{rdmsr} and
|
These instructions allow atomic read/write operations on MSRs\footnote{
|
||||||
\code{wrmsr} are used~\cite{x86isa}. These instructions allow atomic read/write operations on
|
Detailed description in the IA-32 manual~\autocite[sec.~4.2]{ia32}.}.
|
||||||
MSRs\footnote{Detailed description in the IA-32 manual~\cite[sec.~4.2]{ia32}.}.
|
|
||||||
|
|
||||||
\subsection{Memory Mapped I/O}
|
\subsection{Memory Mapped I/O}
|
||||||
\label{subsec:mmio}
|
\label{subsec:mmio}
|
||||||
|
|
||||||
\textbf{\gls{mmio}} is a way for the CPU to perform I/O operations with an external device.
|
\textbf{\gls{mmio}} is a way for the CPU to perform I/O operations with an external device.
|
||||||
Registers of external devices are mapped to the same address space as the main memory, thus a
|
Registers of external devices are mapped to the same address space as the main memory, thus a memory address can either be a location in physical memory, or belong to a device's register.
|
||||||
memory address can either be a location in physical memory, or belong to a device's register. Read
|
Read and write operations are then performed by reading or writing the address the register is mapped to.
|
||||||
and write operations are then performed by reading or writing the address the register is mapped
|
|
||||||
to.
|
|
||||||
|
|
||||||
\subsection{Programmable Interval Timer}
|
\subsection{Programmable Interval Timer}
|
||||||
\label{subsec:pit}
|
\label{subsec:pit}
|
||||||
|
|
||||||
The \textbf{\gls{pit}}\footnote{Specifically the Intel 8253/8254.} is a hardware timer from the
|
The \textbf{\gls{pit}}~\autocite{pit} is a hardware timer from the original IBM PC\@.
|
||||||
original IBM PC. It consists of multiple decrementing counters and can generate a signal (for
|
It consists of multiple decrementing counters and can generate a signal (e.g.\ an interrupt) once 0 is reached.
|
||||||
example an interrupt) once 0 is reached. This can be used to control a preemptive\footnote{A
|
This can be used to control a preemptive\footnote{
|
||||||
scheduler is called ``preemptive'', when it is able to forcefully take away the CPU from the
|
A scheduler is called \textquote{preemptive}, when it is able to forcefully take away the CPU from the currently working thread, even when the thread did not signal any form of completion.}
|
||||||
currently working thread, even when the thread did not signal any form of completion.} scheduler or
|
\ scheduler or the integrated PC speaker.
|
||||||
the integrated PC speaker.
|
|
||||||
|
|
||||||
\section{Intel's Interrupt Controllers}
|
\section{Intel's Interrupt Controllers}
|
||||||
\label{sec:intelcontrollers}
|
\label{sec:intelcontrollers}
|
||||||
|
|
||||||
Because it is logistically difficult to connect every external device directly to the CPU, this
|
Because it is logistically difficult to connect every external device directly to the CPU, this task is delegated to a dedicated interrupt controller.
|
||||||
task is delegated to an interrupt controller, usually located in the system's chipset. Notable
|
Notable interrupt controllers (and the only ones considered in this thesis) are the Intel \textbf{\gls{pic}} and Intel \textbf{\gls{apic}}.
|
||||||
interrupt controllers (and the only ones considered in this thesis) are the Intel
|
|
||||||
\textbf{\gls{pic}} and Intel \textbf{\gls{apic}}.
|
|
||||||
|
|
||||||
\subsection{Programmable Interrupt Controller}
|
\subsection{Programmable Interrupt Controller}
|
||||||
\label{subsec:intelpic}
|
\label{subsec:intelpic}
|
||||||
|
|
||||||
The Intel 8259A PIC~\cite{pic} is the interrupt controller Intel used in the original Intel
|
The Intel \textquote{8259A} PIC~\autocite{pic} is the interrupt controller Intel used in the original Intel \textquote{8086}\footnote{
|
||||||
8086\footnote{The 8259 was used in the Intel 8080 and 8085, the 8259A is a revised version for the
|
The 8259 was used in the Intel \textquote{8080} and \textquote{8085}, the 8259A is a revised version for the Intel 8086},
|
||||||
Intel 8086}, the ``father'' of the x86 processor architecture. A single PIC has 8 interrupt lines
|
\ the \textquote{father} of the x86 processor architecture.
|
||||||
for external devices, but multiple PICs can be cascaded for a maximum of \(8 \cdot 8 = 64\)
|
A single PIC has eight interrupt lines for external devices, but multiple PICs can be cascaded for a maximum of \(8 \cdot 8 = 64\) interrupt lines with nine PICs.
|
||||||
interrupt lines with 9 PICs. The most common PIC configuration supports 15 IRQs with two PICs: A
|
The most common PIC configuration supports 15 IRQs with two PICs (see \autoref{fig:pcatpic}): A slave, connected to INTI2 of the master, which is connected to the CPU\footnote{
|
||||||
slave, connected to interrupt line 2 of the master, which is connected to the CPU\footnote{This
|
This configuration is called the \textquote{PC/AT PIC Architecture}, as it was used in the IBM PC/AT~\autocite[sec.~1.13]{pcat}.}.
|
||||||
configuration is called the \textbf{\gls{pcat pic architecture}}, as it was used in the IBM
|
|
||||||
PC/AT~\cite[sec.~1.13]{pcat}.}.
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
\begin{figure}[h]
|
||||||
\centering
|
\centering
|
||||||
\begin{subfigure}[b]{0.3\textwidth}
|
\begin{subfigure}[b]{0.3\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/mp_spec_pic_configuration.svg}
|
\includesvg[width=1.0\linewidth]{img/mp_spec_pic_configuration.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{The PC/AT PIC architecture~\cite[sec.~1.13]{pcat}.}
|
\caption{The PC/AT PIC Architecture~\autocite[sec.~1.13]{pcat}.}
|
||||||
\label{fig:pcatpic}
|
\label{fig:pcatpic}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
If multiple interrupts get requested simultaneously, the PIC decides which one to service first
|
If multiple interrupts get requested simultaneously, the PIC decides which one to service first based on its \textit{interrupt priority}.
|
||||||
based on its \textbf{\gls{interrupt priority}}. The PIC IRQ priorities are determined by the used
|
The PIC IRQ priorities are determined by the used interrupt lines, IRQ0 has the highest priority.
|
||||||
interrupt lines, IRQ0 has the highest priority.
|
|
||||||
|
|
||||||
The PIC interrupt handling sequence can be briefly outlined as follows:
|
The PIC interrupt handling sequence can be briefly outlined as follows:
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item When the PIC receives an interrupt from a device (PIC interrupts are edge-triggered with high pin
|
\item When the PIC receives an unmasked interrupt from a device (PIC interrupts are edge-triggered with high pin polarity), it sets the corresponding bit in its \textbf{\gls{irr}}\footnote{
|
||||||
polarity), it sets the corresponding bit in its \textbf{\gls{irr}}\footnote{Received IRQs that are
|
Received IRQs that are requesting servicing are marked in the IRR.}.
|
||||||
requesting servicing are marked in the IRR.}
|
\item The IRQ is dispatched to the CPU\@.
|
||||||
\item If this interrupt is unmasked, an IRQ is sent to the CPU
|
\item The CPU acknowledges the IRQ\@.
|
||||||
\item The CPU acknowledges the IRQ
|
\item The PIC sets the corresponding bit in its \textbf{\gls{isr}}\footnote{
|
||||||
\item The PIC sets the corresponding bit in its \textbf{\gls{isr}}\footnote{IRQs that are being serviced
|
IRQs that are being serviced are marked in the ISR\@.
|
||||||
are marked in the ISR. To reduce confusion, interrupt service routines will be denoted as
|
To reduce confusion, interrupt service routines will be denoted as \textquote{interrupt handler} instead of \textquote{ISR}.}
|
||||||
``interrupt handler'' instead of ``ISR''.} and clears the previously set bit in the IRR. If the
|
and clears the previously set bit in the IRR\@.
|
||||||
same interrupt occurs again, it can now be queued a single time in the IRR\@.
|
If the same interrupt occurs again, it can now be queued a single time in the IRR\@.
|
||||||
\item When the interrupt has been handled by the OS, it sends an EOI to the PIC, which clears the
|
\item When the interrupt is being handled by the OS, it sends an EOI to the PIC, which clears the corresponding bit in the ISR\@.
|
||||||
corresponding bit in the ISR\@.
|
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
With the introduction of multiprocessor systems and devices with an ever-increasing need for large
|
With the introduction of multiprocessor systems and devices with an ever-increasing need for large amounts of interrupts (like high-performance networking hardware), the PIC reached its architectural limits:
|
||||||
amounts of interrupts (like high-performance networking hardware), the PIC reached its
|
|
||||||
architectural limits:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Multiple CPU cores require sending IPIs for initialization and coordination, which is not possible
|
\item Multiple CPU cores require sending IPIs for initialization and coordination, which is not possible using the PIC\@.
|
||||||
using the PIC\@.
|
\item The PIC is hardwired to a single CPU core.
|
||||||
\item The PIC is hardwired to a single CPU core. It can be inefficient to handle the entire interrupt
|
It can be inefficient to handle the entire interrupt workload on a single core.
|
||||||
workload on a single core.
|
|
||||||
\item The IRQ priorities depend on how the devices are physically wired to the PIC\@.
|
\item The IRQ priorities depend on how the devices are physically wired to the PIC\@.
|
||||||
\item The PC/AT PIC architecture only has a very limited number of interrupt lines.
|
\item The PC/AT PIC architecture only has a very limited number of interrupt lines.
|
||||||
\item The PIC does not support MSIs, which allow efficient handling of PCI interrupts.
|
\item The PIC does not support MSIs, which allow efficient handling of PCI interrupts.
|
||||||
@ -303,125 +256,116 @@ architectural limits:
|
|||||||
\subsection{Advanced Programmable Interrupt Controller}
|
\subsection{Advanced Programmable Interrupt Controller}
|
||||||
\label{subsec:intelapic}
|
\label{subsec:intelapic}
|
||||||
|
|
||||||
The original Intel 82489DX discrete APIC was introduced with the Intel i486 processor. It consisted
|
The original Intel \textquote{82489DX} \textbf{\gls{discrete apic}} was introduced with the Intel \textquote{i486} processor.
|
||||||
of two parts: A \textbf{\gls{local apic}}, responsible for receiving special \textbf{\glspl{local
|
It consisted of two parts: A \textbf{\gls{local apic}}, responsible for receiving special \textbf{\glspl{local interrupt}}, and the \textbf{\gls{io apic}}, responsible for receiving external interrupts (and forwarding them to the local APIC).
|
||||||
interrupt}}, and external interrupts from the second part, the \textbf{\gls{io apic}}. Unlike in
|
Unlike in modern systems, the i486's local APIC was not integrated into the CPU core (hence \textquote{discrete}), see \autoref{fig:discreteapic}.
|
||||||
modern systems, the i486's local APIC was not integrated into the CPU core (hence ``discrete''),
|
|
||||||
see \autoref{fig:discreteapic}.
|
|
||||||
|
|
||||||
The i486 was superseded by the Intel P54C\footnote{The Intel P54C is the successor of the Intel P5,
|
\begin{figure}[h]
|
||||||
the first Pentium processor.}, which contained an integrated local APIC for the first time, see
|
\centering
|
||||||
\autoref{fig:integratedapic}\footnote{This is now the default configuration.}.
|
\begin{subfigure}[b]{0.75\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{img/mp_spec_discrete_apic_configuration.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{The Discrete APIC Architecture~\autocite[sec.~5.1]{mpspec}.}
|
||||||
|
\label{fig:discreteapic}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
The APIC was designed to fix the shortcomings of the PIC, specifically regarding multiprocessor
|
The i486 was superseded by the Intel \textquote{P54C}\footnote{
|
||||||
systems:
|
The Intel P54C is the successor of the Intel P5, the first Pentium processor.},
|
||||||
|
\ which contained an \textit{integrated APIC} for the first time (see \autoref{fig:integratedapic}), which is now the default configuration.
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{subfigure}[b]{0.75\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{img/mp_spec_integrated_apic_configuration.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{The Integrated APIC Architecture~\autocite[sec.~5.2]{mpspec}.}
|
||||||
|
\label{fig:integratedapic}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
The APIC was designed to fix the shortcomings of the PIC, specifically regarding multiprocessor systems:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Each CPU core contains its own local APIC. It has the capabilities to issue IPIs and communicate
|
\item Each CPU core contains its own local APIC\@.
|
||||||
with the chipset I/O APIC. Also, it includes the APIC timer, which can be used for per-core
|
It has the capabilities to handle local interrupts and IPIs, and communicate with the chipset I/O APIC\@.
|
||||||
scheduling.
|
\item The chipset I/O APIC allows configuration on a per-interrupt basis (priorities, destination, trigger mode or pin polarity are all configurable).
|
||||||
\item The chipset I/O APIC allows configuration on a per-interrupt basis (priorities, destination,
|
Also, it is able to distributes interrupts to different CPU cores, allowing the efficient processing of large amounts of interrupts\footnote{
|
||||||
trigger mode or pin polarity are all configurable). Also, it is able to send interrupts to
|
There are tools that dynamically reprogram the I/O APIC to distribute interrupts to available CPU cores, depending on heuristics of past interrupts (IRQ-balancing).}.
|
||||||
different CPU cores, allowing the efficient processing of large amounts of
|
|
||||||
interrupts\footnote{There are tools that dynamically reprogram the I/O APIC to distribute
|
|
||||||
interrupts to available CPU cores, depending on heuristics of past interrupts (IRQ-balancing).}.
|
|
||||||
\item The order in which external devices are connected to the I/O APIC is flexible.
|
\item The order in which external devices are connected to the I/O APIC is flexible.
|
||||||
\item The APIC architecture supports MSIs.
|
\item The APIC architecture supports MSIs.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
To allow distributing the APIC hardware between local APICs of multiple CPU cores and I/O APICs,
|
In comparison to the PIC, the external interrupt handling sequence changed:
|
||||||
the APIC system sends messages over a bus. In the Intel P6 and original Pentium processors a
|
|
||||||
dedicated APIC bus is used, but since the Intel Pentium 4 and Xeon processors the chipset's system
|
|
||||||
bus is used instead (see \autoref{fig:systemvsapicbus})\footnote{The Intel Core microarchitecture
|
|
||||||
is based on the P6 architecture (replacing the Pentium 4's NetBurst architecture), but still uses
|
|
||||||
the system bus instead of a discrete bus.}. Using the system bus is considered the default in this
|
|
||||||
document.
|
|
||||||
|
|
||||||
Because the order in which external devices are connected to the interrupt controller is flexible
|
\begin{enumerate}
|
||||||
in the APIC architecture, but fixed in the PC/AT PIC architecture, there can be deviations in
|
\item An external interrupt arrives at the I/O APIC\@.
|
||||||
device-to-IRQ mappings between the PIC and APIC interrupt controllers. To handle this, ACPI
|
\item The I/O APIC redirects the interrupt to the local APIC, which sets the corresponding IRR bit.
|
||||||
provides information about how the PIC compatible interrupts (IRQ0 to IRQ15) map to ACPI's GSIs in
|
\item The local APIC dispatches the IRQ\@.
|
||||||
the MADT, which has to be taken into account by the os when operating with an APIC. The mapping
|
\item The CPU acknowledges the IRQ and the local APIC sets the corresponding ISR bit.
|
||||||
information for a single interrupt will be called \textbf{\gls{irq override}}.
|
\item When the interrupt is being handled by the OS, it sends an EOI to the local APIC\footnote{
|
||||||
|
In case of edge-triggered interrupts. For level-triggered interrupts see \autoref{subsec:ioapiceoi}.},
|
||||||
|
\ which clears the corresponding bit in the ISR\@.
|
||||||
|
Note how the OS only interacts directly with the local APIC, not the I/O APIC.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
There have been different revisions on the APIC architecture after the original, discrete APIC,
|
To allow splitting the APIC architecture into local APICs of multiple CPU cores and I/O APICs, the individual components communicate over a bus.
|
||||||
notably the \textbf{\gls{xapic}} and \textbf{\gls{x2apic}} architectures. This thesis is mostly
|
In the Intel \textquote{P6} and \textquote{Pentium} processors a dedicated \textit{APIC bus} is used, but since the Intel \textquote{Pentium 4} and \textquote{Xeon} processors the \textit{system bus} is used instead (see \autoref{fig:systemvsapicbus})\footnote{
|
||||||
concerned about the older xApic architecture\footnote{The x2Apic architecture is backwards
|
The Intel \textquote{Core} microarchitecture is based on the P6 architecture and replaces the Pentium 4's \textquote{NetBurst} architecture, but still uses the system bus instead of a discrete bus~\autocite[sec.~3.11.2]{ia32}.}.
|
||||||
compatible to the xApic architecture, also, QEMU's TCG does not support the x2Apic architecture.}.
|
Using the system bus is considered the default in this document.
|
||||||
A notable difference between xApic and x2Apic architectures is the register access: xApic uses
|
|
||||||
32-bit MMIO based register access, while x2Apic uses an MSR based register access, which allows
|
\begin{figure}[h]
|
||||||
atomic register access to the 32- and 64-bit wide APIC control MSRs~\cite[sec.~3.11.12]{ia32}.
|
\centering
|
||||||
|
\begin{subfigure}[b]{0.6\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{img/ia32_manual_system_vs_apic_bus.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{System Bus vs APIC Bus~\autocite[sec.~3.11.1]{ia32}.}
|
||||||
|
\label{fig:systemvsapicbus}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Because the order in which external devices are connected to the interrupt controller is flexible in the APIC architecture, but fixed in the PC/AT PIC architecture, there can be deviations in device-to-IRQ mappings between the PIC and APIC interrupt controllers.
|
||||||
|
To handle this, ACPI provides information about how the PC/AT compatible interrupts (IRQ0 to IRQ15) map to ACPI's GSIs in the MADT, which has to be taken into account by the OS when operating with an APIC\@.
|
||||||
|
The mapping information for a single interrupt will be called \textbf{\gls{irq override}}.
|
||||||
|
|
||||||
|
There have been different revisions on the APIC architecture after the original, discrete APIC, notably the \textbf{\gls{xapic}} and \textbf{\gls{x2apic}} architectures.
|
||||||
|
This thesis is mostly concerned about the older xApic architecture\footnote{
|
||||||
|
This does not present a compatibility issue, as the x2Apic architecture is backwards compatible to the xApic architecture.}.
|
||||||
|
A notable difference between xApic and x2Apic architectures is the register access: xApic uses \SI{32}{\bit} MMIO based register access, while x2Apic uses an MSR based register access, which allows atomic register access to the \SI{64}{\bit} wide APIC control MSRs~\autocite[sec.~3.11.12]{ia32}.
|
||||||
|
|
||||||
\section{PC/AT Compatibility}
|
\section{PC/AT Compatibility}
|
||||||
\label{sec:pcatcompat}
|
\label{sec:pcatcompat}
|
||||||
|
|
||||||
For compatibility to older computer systems, two cascaded PICs are usually present in current
|
For compatibility with older computer systems, two cascaded PICs are usually present in current computer systems (see \autoref{fig:discreteapic}/\autoref{fig:integratedapic}).
|
||||||
computer systems (see \autoref{fig:discreteapic}/\autoref{fig:integratedapic}). The local APIC can
|
The local APIC can be initialized to operate with these PICs instead of the I/O APIC, this is called \textbf{\gls{virtual wire mode}}.
|
||||||
be initialized to operate with these PICs instead of the I/O APIC, this is called
|
It is possible to operate with both the PIC and I/O APIC as controllers for external interrupts in \textit{mixed mode}, but this is very uncommon.
|
||||||
\textbf{\gls{virtual wire mode}}. It is possible to operate with both the PIC and I/O APIC as
|
Because the presence of a local APIC usually guarantees the presence of an I/O APIC, this thesis only focuses on interrupt handling with either two PICs (\textbf{\gls{pic mode}}), in case no APIC is available, or the full APIC architecture (local APIC and I/O APIC in \textbf{\gls{symmetric io mode}})\footnote{
|
||||||
controllers for external interrupts in ``mixed mode'', but this is very uncommon. Because the
|
For more information on operating modes, consult the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.2.1]{mpspec}.}.
|
||||||
presence of a local APIC usually guarantees the presence of an I/O APIC, this thesis only focuses
|
|
||||||
on interrupt handling with either two PICs (\textbf{\gls{pic mode}}), in case no APIC is available,
|
|
||||||
or the full APIC architecture (local APIC and I/O APIC in \textbf{\gls{symmetric io
|
|
||||||
mode}})\footnote{For more information on operating modes, consult the MultiProcessor
|
|
||||||
specification~\cite[sec.~3.6.2.1]{mpspec}.}.
|
|
||||||
|
|
||||||
To switch from PIC to symmetric I/O mode, some\footnote{References to the IMCR are only found in
|
To switch from PIC to symmetric I/O mode, some (older) hardware provides the \textbf{\gls{imcr}}, a special register that controls the physical connection of the PIC to the CPU\@.
|
||||||
the relatively old MultiProcessor specification~\cite{mpspec}.} hardware\footnote{QEMU does not
|
In the original discrete APIC architecture, the IMCR can choose if either the PIC or local APIC is connected to the CPU (see \autoref{fig:discreteapic}), since the xApic architecture the IMCR only connects or disconnects the PIC to the local APIC's LINT0 INTI (see \autoref{fig:integratedapic}).
|
||||||
emulate the IMCR.} provides the \textbf{\gls{imcr}}, a special register that controls the physical
|
When the IMCR is set to connect the PIC, and the xApic \textquote{global enable/disable} flag is unset (see \autoref{subsec:lapicenable}), the system is functionally equivalent to an IA-32 CPU without an integrated local APIC~\autocite[sec.~3.11.4.3]{ia32}.
|
||||||
connection of the PIC to the CPU. In the original discrete APIC architecture, the IMCR can choose
|
Modern systems (and QEMU) do not support PIC Mode and thus do not have the IMCR\@.
|
||||||
if either the PIC or local APIC is connected to the CPU (see \autoref{fig:discreteapic}), since the
|
PC/AT compatibility is usually achieved in these systems by connecting two PICs to the first external interrupt input of the I/O APIC (see \autoref{fig:integratedapic}).
|
||||||
xApic architecture the IMCR only connects or disconnects the PIC to the local APIC's LINT0 pin (see
|
|
||||||
\autoref{fig:integratedapic}). When the IMCR is set to connect the PIC, and the xApic ``global
|
|
||||||
enable/disable'' flag is unset (see \autoref{subsec:lapicenable}), the system is functionally
|
|
||||||
equivalent to an IA-32 CPU without an integrated local APIC~\cite[sec.~3.11.4.3]{ia32}.
|
|
||||||
|
|
||||||
Specifics on handling PC/AT compatible external interrupts follow in \autoref{subsec:ioapicpcat}.
|
Specifics on handling PC/AT compatible external interrupts follow in \autoref{subsec:ioapicpcat}.
|
||||||
|
|
||||||
\section{Interrupt Handling in hhuOS}
|
\section{Interrupt Handling in HhuOS}
|
||||||
\label{sec:currenthhuos}
|
\label{sec:currenthhuos}
|
||||||
|
|
||||||
In hhuOS, external interrupts are handled in two steps:
|
In hhuOS, external interrupts are handled in two stages (see \autoref{subsec:apxcurrenthhuos} for code examples):
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item After an IRQ is sent by an interrupt controller, the CPU looks up the interrupt handler address in
|
\item After an IRQ is sent by an interrupt controller, the CPU looks up the interrupt handler address in the IDT\@.
|
||||||
the IDT. In hhuOS, every IDT entry contains the address of the \code{dispatch} function (see
|
In hhuOS, every IDT entry contains the address of the \code{dispatch} function, which is invoked with the vector number of the interrupt.
|
||||||
\autoref{lst:irqdispatch}), which is invoked with the vector number of the interrupt.
|
\item The \code{dispatch} function determines which interrupt handler will be called, based on the supplied vector number.
|
||||||
\item The \code{dispatch} function determines which interrupt handler will be called, based on the
|
In hhuOS, interrupt handlers are implemented through the \code{InterruptHandler} interface, that provides the \code{trigger} function, which contains the interrupt handling routine.
|
||||||
supplied vector number. In hhuOS, interrupt handlers are implemented through the
|
To allow the \code{dispatch} function to find the desired interrupt handler, it has to be registered to a vector number by the OS beforehand.
|
||||||
\code{InterruptHandler} interface (see \autoref{lst:irqhandler}), that provides the \code{trigger}
|
This process is handled by the \code{plugin} function of the interrupt handler interface, which uses the interrupt dispatcher's \code{assign} function to register itself to the correct vector number.
|
||||||
function, which contains the interrupt handling routine. To allow the \code{dispatch} function to
|
HhuOS supports assigning multiple interrupt handlers to a single interrupt vector and cascading interrupts.
|
||||||
find the desired interrupt handler, it has to be registered to a vector number by the OS
|
|
||||||
beforehand. This process is handled by the \code{plugin} function of the interrupt handler
|
|
||||||
interface, which uses the interrupt dispatcher's \code{assign} function (see
|
|
||||||
\autoref{lst:irqassign}) to register itself to the correct vector number. HhuOS supports assigning
|
|
||||||
multiple interrupt handlers to a single interrupt vector and cascading interrupts.
|
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:irqhandler]{The InterruptHandler interface (InterruptHandler.h)~\cite{hhuos}}{C++}
|
To prevent the need of interacting with a specific interrupt controller implementation (e.g. \code{Pic} class) or the dispatcher, a system service (the \code{InterruptService}) is implemented to expose this functionality to other parts of the OS (it allows e.g.\ registering interrupt handlers or masking and unmasking interrupts).
|
||||||
\cppfile{code/interrupthandler_def.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:irqassign]{Assigning an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
Currently, hhuOS utilizes the PIT to manage the global system time, which in turn is used to trigger hhuOS' preemptive round-robin scheduler (the \code{Scheduler} class).
|
||||||
\cppfile{code/interruptdispatcher_assign.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:irqdispatch]{Triggering an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
The PIT and other devices are initialized before the system entry point, in the \code{System::initializeSystem} function.
|
||||||
\cppfile{code/interruptdispatcher_dispatch.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
To prevent the need of interacting with a specific interrupt controller implementation (e.g.
|
\cleardoublepage
|
||||||
\code{Pic} class) or the dispatcher, a system service (the \code{InterruptService}) is implemented
|
|
||||||
to expose this functionality to other parts of the OS (it allows e.g.\ registering interrupt
|
|
||||||
handlers or masking and unmasking interrupts).
|
|
||||||
|
|
||||||
Currently, hhuOS utilizes the PIT to manage the global system time (see \autoref{lst:pithandler}),
|
|
||||||
which in turn is used to trigger hhuOS's preemptive round-robin scheduler (the \code{Scheduler}
|
|
||||||
class).
|
|
||||||
|
|
||||||
\begin{codeblock}[label=lst:pithandler]{The PIT interrupt handler (Pit.cpp)~\cite{hhuos}}{C++}
|
|
||||||
\cppfile{code/pit_trigger.cpp}
|
|
||||||
\end{codeblock}
|
|
||||||
|
|
||||||
The PIT and other devices are initialized before the system entry point, in the
|
|
||||||
\code{System::initializeSystem} function.
|
|
201
chap/conclusion.aux
Normal file
201
chap/conclusion.aux
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {5}Conclusion}{37}{chapter.5}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:conclusion}{{5}{37}{Conclusion}{chapter.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {5.1}Comparing PIC and APIC Implementations}{38}{section.5.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:comparingpicapic}{{5.1}{38}{Comparing PIC and APIC Implementations}{section.5.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {5.2}Future Improvements}{38}{section.5.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:futureimprov}{{5.2}{38}{Future Improvements}{section.5.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.1}Dependence on ACPI}{38}{subsection.5.2.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:acpidependance}{{5.2.1}{38}{Dependence on ACPI}{subsection.5.2.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.2}Discrete APIC and x2Apic}{39}{subsection.5.2.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:discretex2}{{5.2.2}{39}{Discrete APIC and x2Apic}{subsection.5.2.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.3}PCI Devices}{39}{subsection.5.2.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:pcidevices}{{5.2.3}{39}{PCI Devices}{subsection.5.2.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.4}Multiprocessor Systems}{39}{subsection.5.2.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:multiprocessor}{{5.2.4}{39}{Multiprocessor Systems}{subsection.5.2.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.5}UEFI Support}{40}{subsection.5.2.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:uefisupport}{{5.2.5}{40}{UEFI Support}{subsection.5.2.5}{}}
|
||||||
|
\@setckpt{chap/conclusion}{
|
||||||
|
\setcounter{page}{41}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{9}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{5}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{5}
|
||||||
|
\setcounter{section}{2}
|
||||||
|
\setcounter{subsection}{5}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{0}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{59}
|
||||||
|
\setcounter{FancyVerbLine}{0}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{48}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{0}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{0}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{2}
|
||||||
|
\setcounter{Item}{46}
|
||||||
|
\setcounter{Hfootnote}{43}
|
||||||
|
\setcounter{bookmark@seq@number}{51}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{0}
|
||||||
|
\setcounter{@ppsavesec}{0}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{89}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{19}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -1,41 +1,29 @@
|
|||||||
\chapter{Conclusion}
|
\chapter{Conclusion}
|
||||||
\label{ch:conclusion}
|
\label{ch:conclusion}
|
||||||
|
|
||||||
In this thesis, support for the APIC was integrated into hhuOS. The implementation supports usage
|
In this thesis, support for the APIC was integrated into hhuOS\@.
|
||||||
of the local APIC in combination with the I/O APIC for regular interrupt handling without the
|
The implementation supports usage of the local APIC in combination with the I/O APIC for regular interrupt handling without the PIC\@.
|
||||||
PIC\@. Also, the APIC's included timer is used to trigger hhuOS' scheduler, and it is demonstrated
|
Also, the APIC's included timer is used to trigger hhuOS' scheduler, and it is demonstrated how to initialize a multiprocessor system using the APIC's IPI capabilities.
|
||||||
how to initialize a multiprocessor system using the APIC's IPI capabilities. All of this is
|
All of this is implemented with real hardware in mind, so ACPI is used to gather system information during runtime and adapt the initialization and usage accordingly.
|
||||||
implemented with real hardware in mind, so ACPI is used to gather system information during runtime
|
|
||||||
and adapt the initialization and usage accordingly.
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Comparing PIC and APIC Implementations}
|
\section{Comparing PIC and APIC Implementations}
|
||||||
\label{sec:comparingpicapic}
|
\label{sec:comparingpicapic}
|
||||||
|
|
||||||
Handling interrupts using the PIC is extremely simple, as seen in hhuOS' PIC implementation.
|
Handling interrupts using the PIC is simple, as seen in hhuOS' PIC implementation.
|
||||||
Initialization and usage can be performed by using a total of only four different registers, two
|
Initialization and usage can be performed by using a total of only four different registers, two per PIC\footnote{
|
||||||
per PIC\footnote{Omitting the infrastructure that is required for both, PIC and APIC, like the IDT
|
Omitting the infrastructure that is required for both, PIC and APIC, like the IDT or dispatcher.}.
|
||||||
or dispatcher.}.
|
|
||||||
|
|
||||||
In comparison, the code complexity required to use the APIC is very high. The most obvious reason
|
In comparison, the code complexity required to use the APIC is very high.
|
||||||
is its significantly increased set of features: Local interrupts are special to the APIC, also the
|
The most obvious reason is its significantly increased set of features: Local interrupts are special to the APIC, also the APIC system is made up of multiple components that require internal communication and individual initialization.
|
||||||
APIC system is made up of multiple components that require internal communication and individual
|
Additionally, the APIC supports advanced processor topologies with large numbers of cores and offers increased flexibility by allowing to configure individual interrupts' vectors, destinations, signals and priorities, which results in additional setup.
|
||||||
initialization. Additionally, the APIC supports advanced processor topologies with large amounts of
|
|
||||||
cores and offers increased flexibility by allowing to configure individual interrupt's vectors,
|
|
||||||
destinations, signals and priorities, which results in additional setup.
|
|
||||||
|
|
||||||
Another source of complexity that is not present with the PIC is the APIC's variability: With the
|
Another source of complexity that is not present with the PIC is the APIC's variability: With the PC/AT architecture, the entire hardware interrupt configuration is known before boot.
|
||||||
PC/AT architecture, the entire hardware interrupt configuration is known before boot. This is not
|
This is not the case when using the APIC, as the number of interrupt controllers or even the number and order of connected devices is only known while the system is running.
|
||||||
the case when using the APIC, as the amount of interrupt controllers or even the number and order
|
Parsing this information from ACPI tables and allowing the implementation to adapt to different hardware configurations, all while maintaining PC/AT compatibility, increases the amount of code by a large margin.
|
||||||
of connected devices is only known while the system is running. Parsing this information from ACPI
|
|
||||||
tables and allowing the implementation to adapt to different hardware configurations, all while
|
|
||||||
maintaining PC/AT compatibility, increases the amount of code by a large margin.
|
|
||||||
|
|
||||||
In general, all of this effort results in a much more powerful and future-proof system: It is not
|
In general, all of this effort results in a much more powerful and future-proof system: It is not limited to specific hardware configurations, allows scaling to a large amount of interrupts or processors, and is required for multiprocessor machines, which equals almost all modern computer systems.
|
||||||
limited to specific hardware configurations, allows scaling to a large amount of interrupts or
|
|
||||||
processors, and is required for multiprocessor machines, which equals to almost all modern computer
|
|
||||||
systems.
|
|
||||||
|
|
||||||
\section{Future Improvements}
|
\section{Future Improvements}
|
||||||
\label{sec:futureimprov}
|
\label{sec:futureimprov}
|
||||||
@ -43,65 +31,48 @@ systems.
|
|||||||
\subsection{Dependence on ACPI}
|
\subsection{Dependence on ACPI}
|
||||||
\label{subsec:acpidependance}
|
\label{subsec:acpidependance}
|
||||||
|
|
||||||
The APIC system requires a supplier of system information during operation, but this must not
|
The APIC system requires a supplier of system information during operation, but this must not necessarily be ACPI\@.
|
||||||
necessarily be ACPI. Systems following Intel's ``MultiProcessor Specification''~\cite{mpspec} can
|
Systems following Intel's \textquote{MultiProcessor Specification}~\autocite{mpspec} can acquire the required information by parsing configuration tables similar to ACPI's system description tables, but provided in accordance to the MultiProcessor Specification.
|
||||||
acquire the required information by parsing configuration tables similar to ACPI's system
|
This would increase the number of systems supported by this APIC implementation, but the general compatibility improvement is difficult to quantize, as single-core systems are still supported by the old PIC implementation\footnote{
|
||||||
description tables, but provided in accordance to the MultiProcessor Specification. This would
|
The \textquote{MultiProcessor Specification} was (pre-) released in 1993~\autocite{mpspecpre}, the first ACPI release was in 1996~\autocite{acpipre}.
|
||||||
increase the amount of systems supported by this APIC implementation, but the general compatibility
|
Multiprocessor systems between these years could be affected.}.
|
||||||
improvement is difficult to quantize, as single-core systems are still supported by the old PIC
|
|
||||||
implementation\footnote{The MultiProcessor Specification was (pre-) released in
|
|
||||||
1993~\cite{mpspecpre}, the first ACPI release was in 1996~\cite{acpipre}. Multiprocessor systems
|
|
||||||
between these years would be affected.}.
|
|
||||||
|
|
||||||
Alternatively, systems that do not support ACPI could be supported partially by utilizing the local
|
Alternatively, systems that do not support ACPI could be supported partially by utilizing the local APIC's virtual wire mode~\autocite[sec.~3.6.2.2]{mpspec}.
|
||||||
APIC's virtual wire mode~\cite[sec.~3.6.2.2]{mpspec}. The reliance on information provided in the
|
The reliance on information provided in the MADT stems mostly from using the I/O APIC as the external interrupt controller.
|
||||||
MADT stems mostly from using the I/O APIC as the external interrupt controller. By using the local
|
By using the local APIC for its local interrupt and multiprocessor functionality, but keeping the PC/AT compatible PIC as the external interrupt controller, multiprocessor systems without ACPI could be supported.
|
||||||
APIC for its local interrupt and multiprocessor functionality, but keeping the PC/AT compatible PIC
|
|
||||||
as the external interrupt controller, multiprocessor systems without ACPI could be supported.
|
|
||||||
|
|
||||||
\subsection{Discrete APIC and x2Apic}
|
\subsection{Discrete APIC and x2Apic}
|
||||||
\label{subsec:discretex2}
|
\label{subsec:discretex2}
|
||||||
|
|
||||||
This implementation only supports the xApic architecture, as it's convenient to emulate and the
|
This implementation only supports the xApic architecture, as it is convenient to emulate and the x2Apic architecture is fully backwards compatible~\autocite[sec.~3.11.12]{ia32}.
|
||||||
x2Apic architecture is fully backwards compatible~\cite[sec.~3.11.12]{ia32}. The original, discrete
|
The original, discrete local APIC (Intel 82489DX) is not supported explicitly, which reduces this implementation's compatibility to older systems\footnote{
|
||||||
local APIC (Intel 82489DX) is not supported explicitly, which reduces this implementation's
|
Although it is possible that no or only very few modifications are necessary, as this implementation does not utilize many of the xApic's exclusive features~\autocite[sec.~3.23.27]{ia32}.}.
|
||||||
compatibility to older systems\footnote{Although it is possible that no or only very few
|
Supporting the x2Apic architecture does not increase compatibility, but using the x2Apic's MSR-based atomic register access is beneficial in multiprocessor systems.
|
||||||
modifications are necessary, as this implementation does not utilize many of the xApic's exclusive
|
Newer ACPI versions provide separate x2Apic specific structures in the MADT~\autocite[sec.~5.2.12.12]{acpi65}, so supporting x2Apic also requires supporting modern ACPI versions\footnote{
|
||||||
features~\cite[sec.~3.23.27]{ia32}.}. Supporting the x2Apic architecture does not increase
|
Currently (on 27/02/2023), hhuOS supports ACPI 1.0b~\autocite{acpi1}.}.
|
||||||
compatibility, but using the x2Apic's MSR-based atomic register access is beneficial in
|
|
||||||
multiprocessor systems. Newer ACPI versions provide separate x2Apic specific structures in the
|
|
||||||
MADT~\cite[sec.~5.2.12.12]{acpi65}, so supporting x2Apic also requires supporting modern ACPI
|
|
||||||
versions\footnote{Currently, hhuOS supports ACPI 1.0b~\cite{acpi1}.}.
|
|
||||||
|
|
||||||
\subsection{PCI Devices}
|
\subsection{PCI Devices}
|
||||||
\label{subsec:pcidevices}
|
\label{subsec:pcidevices}
|
||||||
|
|
||||||
The APIC is capable of handling MSIs, but this is not implemented in this thesis. To support PCI
|
The APIC is capable of handling MSIs, but this is not implemented in this thesis.
|
||||||
devices using the APIC instead of the PIC, either support for MSIs has to be implemented, or ACPI
|
To support PCI devices using the APIC instead of the PIC, either support for MSIs has to be implemented, or ACPI has to be used to determine the corresponding I/O APIC interrupt inputs.
|
||||||
has to be used to determine the corresponding I/O APIC interrupt inputs. This is rather
|
This is rather complicated, as it requires interacting with ACPI using AML~\autocite[sec.~6.2.13]{acpi65}, which needs an according interpreter\footnote{
|
||||||
complicated, as it requires interacting with ACPI using AML~\cite[sec.~6.2.13]{acpi65}, which needs
|
There exist modular solutions that can be ported to the target OS~\autocite{acpica}.}.
|
||||||
an according interpreter\footnote{There exist modular solutions that can be ported to the target
|
|
||||||
OS~\cite{acpica}.}.
|
|
||||||
|
|
||||||
\subsection{Multiprocessor Systems}
|
\subsection{Multiprocessor Systems}
|
||||||
\label{subsec:multiprocessor}
|
\label{subsec:multiprocessor}
|
||||||
|
|
||||||
This implementation demonstrates AP startup in SMP systems by using the APIC's IPI mechanism, but
|
This implementation demonstrates AP startup in SMP systems by using the APIC's IPI mechanism, but processors are only initialized to a spin-loop.
|
||||||
processors are only initialized to a spin-loop. Because the APIC is a prerequisite for more
|
Because the APIC is a prerequisite for more in-depth SMP support, this implementation enables more substantial improvements in this area, like distributing tasks to different CPU cores and using the cores' local APIC timers to manage core-local schedulers.
|
||||||
in-depth SMP support, this implementation enables more substantial improvements in this area, like
|
|
||||||
distributing tasks to different CPU cores and using the core's local APIC timer to manage a
|
|
||||||
core-local scheduler.
|
|
||||||
|
|
||||||
Another possible area of improvement is the execution of the interrupt handlers: At the moment,
|
Another possible area of improvement is the execution of the interrupt handlers: At the moment, each I/O APIC redirects every received interrupt to the BSP's local APIC\@.
|
||||||
each I/O APIC redirects every received interrupt to the BSP's local APIC. Distributing interrupts
|
Distributing interrupts to different CPU cores could improve interrupt handling performance, especially with frequent interrupts, like from network devices.
|
||||||
to different CPU cores could improve interrupt handling performance, especially with frequent
|
This redirection could be implemented statically for each interrupt or based on priorities, but could also happen dynamically (\textquote{IRQ-balancing}~\autocite{irqbalance}), based on interrupt workload measurements.
|
||||||
interrupts, like from network devices. This redirection could also happen dynamically
|
|
||||||
(``IRQ-balancing''~\cite{irqbalance}), depending on interrupt workload measurements.
|
|
||||||
|
|
||||||
\subsection{UEFI Support}
|
\subsection{UEFI Support}
|
||||||
\label{subsec:uefisupport}
|
\label{subsec:uefisupport}
|
||||||
|
|
||||||
Currently, hhuOS' ACPI system only works with BIOS, so when booting an UEFI system, this
|
Currently, hhuOS' ACPI system only works with BIOS, so when booting an UEFI system, this implementation is disabled, because it requires ACPI\@.
|
||||||
implementation is disabled, because it requires ACPI. By supporting ACPI on UEFI systems, this
|
By supporting ACPI on UEFI systems, this implementation could also be used for those systems, which would improve compatibility with modern platforms.
|
||||||
implementation could also be used for those systems, which would improve compatibility with modern
|
|
||||||
platforms.
|
\cleardoublepage
|
191
chap/figures.aux
Normal file
191
chap/figures.aux
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {B}Figures}{59}{appendix.1.B}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:figures}{{B}{59}{Figures}{appendix.1.B}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {B.1}{\ignorespaces Enabling the APIC Subsystem.\relax }}{60}{figure.1.B.1}\protected@file@percent }
|
||||||
|
\newlabel{fig:apicenable}{{B.1}{60}{Enabling the APIC Subsystem.\relax }{figure.1.B.1}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {B.2}{\ignorespaces Starting SMP Operation.\relax }}{61}{figure.1.B.2}\protected@file@percent }
|
||||||
|
\newlabel{fig:smpenable}{{B.2}{61}{Starting SMP Operation.\relax }{figure.1.B.2}{}}
|
||||||
|
\@setckpt{chap/figures}{
|
||||||
|
\setcounter{page}{63}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{4}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{0}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{2}
|
||||||
|
\setcounter{section}{0}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{2}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{184}
|
||||||
|
\setcounter{FancyVerbLine}{12}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{70}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{1}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{47}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{2}
|
||||||
|
\setcounter{Item}{50}
|
||||||
|
\setcounter{Hfootnote}{45}
|
||||||
|
\setcounter{bookmark@seq@number}{73}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{1}
|
||||||
|
\setcounter{@ppsavesec}{5}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{96}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{20}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
24
chap/figures.tex
Normal file
24
chap/figures.tex
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
\chapter{Figures}
|
||||||
|
\label{ch:figures}
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{subfigure}[b]{0.85\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{diagrams/apic_enable_seq.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{Enabling the APIC Subsystem.}
|
||||||
|
\label{fig:apicenable}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
\begin{figure}[h]
|
||||||
|
\centering
|
||||||
|
\begin{subfigure}[b]{0.85\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{diagrams/apic_smp_enable_seq.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{Starting SMP Operation.}
|
||||||
|
\label{fig:smpenable}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Note that this diagram is slightly misleading, because the application processor runs in parallel and is not susceptible to delays on the BSP\@.
|
||||||
|
|
||||||
|
\cleardoublepage
|
237
chap/implementation.aux
Normal file
237
chap/implementation.aux
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {3}Implementation}{15}{chapter.3}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:implementation}{{3}{15}{Implementation}{chapter.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.1}Design Decisions and Scope}{16}{section.3.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:design}{{3.1}{16}{Design Decisions and Scope}{section.3.1}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.1}{\ignorespaces Caller Hierarchy of the Main Components.\relax }}{16}{figure.3.1}\protected@file@percent }
|
||||||
|
\newlabel{fig:implarch}{{3.1}{16}{Caller Hierarchy of the Main Components.\relax }{figure.3.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Local APIC}{19}{section.3.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:lapicinit}{{3.2}{19}{Local APIC}{section.3.2}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.2}{\ignorespaces The Local APIC Block Diagram~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.1]{ia32}.\relax }}{20}{figure.3.2}\protected@file@percent }
|
||||||
|
\newlabel{fig:localapicblock}{{3.2}{20}{The Local APIC Block Diagram~\autocite [sec.~3.11.4.1]{ia32}.\relax }{figure.3.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Accessing Local APIC Registers in xApic Mode}{21}{subsection.3.2.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:xapicregacc}{{3.2.1}{21}{Accessing Local APIC Registers in xApic Mode}{subsection.3.2.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Enabling the Local APIC}{21}{subsection.3.2.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapicenable}{{3.2.2}{21}{Enabling the Local APIC}{subsection.3.2.2}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.3}{\ignorespaces The IA32\textunderscore {}APIC\textunderscore {}BASE MSR~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.4]{ia32}.\relax }}{21}{figure.3.3}\protected@file@percent }
|
||||||
|
\newlabel{fig:ia32apicbasemsr}{{3.3}{21}{The IA32\textunderscore {}APIC\textunderscore {}BASE MSR~\autocite [sec.~3.11.4.4]{ia32}.\relax }{figure.3.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Handling Local Interrupts}{22}{subsection.3.2.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapiclvtinit}{{3.2.3}{22}{Handling Local Interrupts}{subsection.3.2.3}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.4}{\ignorespaces The Local Vector Table~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{22}{figure.3.4}\protected@file@percent }
|
||||||
|
\newlabel{fig:localapiclvt}{{3.4}{22}{The Local Vector Table~\autocite [sec.~3.11.5.1]{ia32}.\relax }{figure.3.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.4}Allowing Interrupt Processing}{23}{subsection.3.2.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapicsoftenable}{{3.2.4}{23}{Allowing Interrupt Processing}{subsection.3.2.4}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.5}{\ignorespaces The Local APIC SVR Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.9]{ia32}.\relax }}{23}{figure.3.5}\protected@file@percent }
|
||||||
|
\newlabel{fig:ia32apicsvr}{{3.5}{23}{The Local APIC SVR Register~\autocite [sec.~3.11.9]{ia32}.\relax }{figure.3.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.5}Local Interrupt EOI}{24}{subsection.3.2.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapiceoi}{{3.2.5}{24}{Local Interrupt EOI}{subsection.3.2.5}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.6}APIC Timer}{24}{subsection.3.2.6}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapictimer}{{3.2.6}{24}{APIC Timer}{subsection.3.2.6}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.7}APIC Error Interrupt}{25}{subsection.3.2.7}\protected@file@percent }
|
||||||
|
\newlabel{subsec:lapicerror}{{3.2.7}{25}{APIC Error Interrupt}{subsection.3.2.7}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.6}{\ignorespaces Error Status Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.3]{ia32}.\relax }}{25}{figure.3.6}\protected@file@percent }
|
||||||
|
\newlabel{fig:ia32esr}{{3.6}{25}{Error Status Register~\autocite [sec.~3.11.5.3]{ia32}.\relax }{figure.3.6}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.3}I/O APIC}{26}{section.3.3}\protected@file@percent }
|
||||||
|
\newlabel{sec:ioapicinit}{{3.3}{26}{I/O APIC}{section.3.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Interrupt Overrides}{26}{subsection.3.3.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:ioapicpcat}{{3.3.1}{26}{Interrupt Overrides}{subsection.3.3.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}External Interrupt EOI}{27}{subsection.3.3.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:ioapiceoi}{{3.3.2}{27}{External Interrupt EOI}{subsection.3.3.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.3}Multiple I/O APICs}{28}{subsection.3.3.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:multiioapic}{{3.3.3}{28}{Multiple I/O APICs}{subsection.3.3.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {3.4}Symmetric Multiprocessing}{29}{section.3.4}\protected@file@percent }
|
||||||
|
\newlabel{sec:smpinit}{{3.4}{29}{Symmetric Multiprocessing}{section.3.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.1}Inter-Processor Interrupts}{29}{subsection.3.4.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:ipis}{{3.4.1}{29}{Inter-Processor Interrupts}{subsection.3.4.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.2}Universal Startup Algorithm}{29}{subsection.3.4.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apstartup}{{3.4.2}{29}{Universal Startup Algorithm}{subsection.3.4.2}{}}
|
||||||
|
\@writefile{lof}{\contentsline {figure}{\numberline {3.7}{\ignorespaces Interrupt Command Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.6.1]{ia32}.\relax }}{30}{figure.3.7}\protected@file@percent }
|
||||||
|
\newlabel{fig:ia32icr}{{3.7}{30}{Interrupt Command Register~\autocite [sec.~3.11.6.1]{ia32}.\relax }{figure.3.7}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.3}Application Processor Boot Routine}{31}{subsection.3.4.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apboot}{{3.4.3}{31}{Application Processor Boot Routine}{subsection.3.4.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.4}Application Processor Post-Boot Routine}{32}{subsection.3.4.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apsystementry}{{3.4.4}{32}{Application Processor Post-Boot Routine}{subsection.3.4.4}{}}
|
||||||
|
\@setckpt{chap/implementation}{
|
||||||
|
\setcounter{page}{33}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{9}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{18}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{3}
|
||||||
|
\setcounter{section}{4}
|
||||||
|
\setcounter{subsection}{4}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{7}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{53}
|
||||||
|
\setcounter{FancyVerbLine}{0}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{40}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{0}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{0}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{2}
|
||||||
|
\setcounter{Item}{46}
|
||||||
|
\setcounter{Hfootnote}{35}
|
||||||
|
\setcounter{bookmark@seq@number}{40}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{0}
|
||||||
|
\setcounter{@ppsavesec}{0}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{77}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{6}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -1,35 +1,26 @@
|
|||||||
\chapter{Implementation}
|
\chapter{Implementation}
|
||||||
\label{ch:implementation}
|
\label{ch:implementation}
|
||||||
|
|
||||||
This section will detail how and to what extent the APIC support was implemented. The steps
|
This section will detail how and to what extent the APIC support was implemented.
|
||||||
performed in this implementation are described in a generally applicable way, concrete
|
The steps performed in this implementation are described in a generally applicable way, details on the implementation source code are found in \autoref{ch:listings}.
|
||||||
implementation details with hhuOS as an example are found in \autoref{ch:listings}.
|
\autoref{subsec:hhuosintegration} deals with the modifications done to the hhuOS system to integrate the APIC implementation.
|
||||||
\autoref{sec:hhuosintegration} deals with the modifications done to the hhuOS system to integrate
|
|
||||||
the APIC implementation.
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Design Decisions and Scope}
|
\section{Design Decisions and Scope}
|
||||||
\label{sec:design}
|
\label{sec:design}
|
||||||
|
|
||||||
The APIC interrupt architecture is split into multiple hardware components and tasks: The
|
The APIC interrupt architecture is split into multiple hardware components and tasks: The (potentially multiple) local APICs, the (usually single) I/O APIC and the APIC timer (part of each local APIC).
|
||||||
(potentially multiple) local APICs, the (usually single) I/O APIC and the APIC timer (part of each
|
Furthermore, the APIC system needs to interact with its memory mapped registers and the hhuOS ACPI subsystem, to gather information about the CPU topology and interrupt overrides.
|
||||||
local APIC). Furthermore, the APIC system needs to interact with its memory mapped registers and
|
Also, the OS should be able to interact with the APIC system in a simple and easy manner, without needing to know all of its individual parts.
|
||||||
the hhuOS ACPI subsystem, to gather information about the CPU topology and IRQ overrides. Also, the
|
|
||||||
OS should be able to interact with the APIC system in a simple and easy manner, without needing to
|
|
||||||
know all of its individual parts.
|
|
||||||
|
|
||||||
To keep the whole system structured and simple, the implementation is split into the following main
|
To keep the whole system structured and simple, the implementation is split into the following main components (see \autoref{fig:implarch}):
|
||||||
components (see \autoref{fig:implarch}):
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \code{LocalApic}: Provides functionality to interact with the local APIC
|
\item \code{LocalApic}: Provides functionality to interact with the local APIC (masking and unmasking, register access, etc.).
|
||||||
(masking and unmasking, register access, etc.).
|
\item \code{IoApic}: Provides functionality to interact with the I/O APIC (masking and unmasking, register access, etc.)
|
||||||
\item \code{IoApic}: Provides functionality to interact with the I/O APIC (masking and
|
|
||||||
unmasking, register access, etc.)
|
|
||||||
\item \code{ApicTimer}: Provides functionality to calibrate the APIC timer and handle its interrupts.
|
\item \code{ApicTimer}: Provides functionality to calibrate the APIC timer and handle its interrupts.
|
||||||
\item \code{Apic}: Condenses all the functionality above and exposes it to other parts
|
\item \code{Apic}: Condenses all the functionality above and exposes it to other parts of the OS\@.
|
||||||
of the OS\@.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
\begin{figure}[h]
|
\begin{figure}[h]
|
||||||
@ -37,494 +28,387 @@ components (see \autoref{fig:implarch}):
|
|||||||
\begin{subfigure}[b]{0.5\textwidth}
|
\begin{subfigure}[b]{0.5\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/Architecture.svg}
|
\includesvg[width=1.0\linewidth]{img/Architecture.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{Caller hierarchy of the main components.}
|
\caption{Caller Hierarchy of the Main Components.}
|
||||||
\label{fig:implarch}
|
\label{fig:implarch}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
This implementation is targeted to support systems with a single I/O APIC\footnote{Operation with
|
This implementation is targeted to support systems with a single I/O APIC\footnote{
|
||||||
more than one I/O APIC is described further in the MultiProcessor
|
Operation with more than one I/O APIC is described further in the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.8]{mpspec}.},
|
||||||
specification~\cite[sec.~3.6.8]{mpspec}.}, because consumer hardware typically only uses a single
|
\ because consumer hardware typically only uses a single one, and so does QEMU emulation.
|
||||||
one, and so does QEMU emulation. General information on implementing multiple I/O APIC support can
|
General information on implementing multiple I/O APIC support can be found in \autoref{subsec:multiioapic}.
|
||||||
be found in \autoref{subsec:multiioapic}.
|
|
||||||
|
|
||||||
With the introduction of ACPI's GSIs to the OS, new types are introduced to clearly differentiate
|
With the introduction of ACPI's GSIs to the OS, new types are introduced to clearly differentiate different representations of interrupts and prevent unintentional conversions:
|
||||||
different representations of interrupts and prevent unintentional conversions:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \code{GlobalSystemInterrupt}: ACPI's interrupt abstraction, detached from the hardware
|
\item \code{GlobalSystemInterrupt}: ACPI's interrupt abstraction, detached from the hardware interrupt lines.
|
||||||
interrupt lines.
|
\item \code{InterruptRequest}: Represents an \textbf{\gls{isa}} IRQ, allowing the OS to address interrupts by the name of the device that triggers it.
|
||||||
\item \code{InterruptRequest}: Represents an IRQ, allowing the OS to address interrupts by
|
When the APIC is used, interrupt overrides map IRQs to GSIs.
|
||||||
the name of the device that triggers it. When the APIC is used, IRQ overrides map IRQs to GSIs.
|
\item \code{InterruptVector}: Represents an interrupt's vector number, as used by the \code{InterruptDispatcher}.
|
||||||
\item \code{InterruptVector}: Represents an interrupt's vector number, as used by the
|
The dispatcher maps interrupt vectors to interrupt handlers.
|
||||||
\code{InterruptDispatcher}. The dispatcher maps interrupt vectors to interrupt handlers.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Both BIOS and UEFI are supported by hhuOS, but the hhuOS ACPI subsystem is currently only available
|
Both BIOS and UEFI are supported by hhuOS, but the hhuOS ACPI subsystem is currently only available with BIOS\footnote{
|
||||||
with BIOS\footnote{State from 11/02/23.}, so when hhuOS is booted using UEFI, APIC support can't be
|
State from 11/02/2023.},
|
||||||
enabled. Also, the APIC can handle MSIs, but they are not included in this implementation, as hhuOS
|
\ so when hhuOS is booted using UEFI, APIC support cannot be enabled.
|
||||||
currently does not utilize them.
|
Also, the APIC can handle MSIs, but they are not included in this implementation, as hhuOS currently does not utilize them.
|
||||||
|
|
||||||
SMP systems are partially supported: The APs are initialized, but only to a busy-looping state, as
|
SMP systems are partially supported: The APs are initialized, but only to a busy-looping state, as hhuOS currently is a single-core OS and lacks some required infrastructure.
|
||||||
hhuOS currently is a single-core OS and lacks some required infrastructure. All interrupts are
|
All interrupts are handled using the BSP\@.
|
||||||
handled using the BSP\@.
|
|
||||||
|
|
||||||
Summary of features that are outside the scope of this thesis:
|
A summary of features that are outside the scope of this thesis:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Operation with a discrete APIC or x2Apic.
|
\item Operation with a discrete APIC or x2Apic.
|
||||||
\item Interrupts with logical destinations or custom priorities.
|
\item Interrupts with logical destinations or custom priorities.
|
||||||
\item Returning from APIC operation to PIC mode\footnote{This would be theoretically possible with
|
\item Returning from APIC operation to PIC mode\footnote{
|
||||||
single-core hardware, but probably useless.}.
|
This would be theoretically possible with single-core hardware, but probably useless.}.
|
||||||
\item Relocation of a local APIC's MMIO memory region\footnote{Relocation is possible by writing a new
|
\item Relocation of a local APIC's MMIO memory region\footnote{
|
||||||
physical APIC base address to the IA32\textunderscore{}APIC\textunderscore{}BASE MSR.}.
|
Relocation is possible by writing a new physical APIC base address to the IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.4.5]{ia32}.}.
|
||||||
\item Distributing external interrupts to different APs in SMP enabled systems.
|
\item Distributing external interrupts to different APs in SMP enabled systems.
|
||||||
\item Usage of the system's performance counter or monitoring interrupts.
|
\item Usage of the system's performance counter or monitoring interrupts.
|
||||||
\item Meaningful APIC error handling.
|
\item Meaningful treatment of APIC errors.
|
||||||
\item Handling of MSIs.
|
\item Handling of MSIs.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
To be able to easily extend an APIC implementation for single-core systems to SMP systems, some
|
To be able to easily extend an APIC implementation for single-core systems to SMP systems, some things have to be taken into account:
|
||||||
things have to be taken into account:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item SMP systems need to manage multiple \code{LocalApic} and \code{ApicTimer} instances. This is
|
\item SMP systems need to manage multiple \code{LocalApic} and \code{ApicTimer} instances.
|
||||||
handled by the \code{Apic} class.
|
This is handled by the \code{Apic} class.
|
||||||
\item Initialization of the different components can no longer happen at the same ``location'': The local
|
\item Initialization of the different components can no longer happen at the same \textquote{location}: The local APICs and APIC timers of additional APs have to be initialized by the APs themselves, because the BSP can not access an AP's registers.
|
||||||
APICs and APIC timers of additional APs have to be initialized by the APs themselves, because the
|
|
||||||
BSP can not access an AP's registers.
|
|
||||||
\item APs are only allowed to access instances of APIC classes that belong to them.
|
\item APs are only allowed to access instances of APIC classes that belong to them.
|
||||||
\item Interrupt handlers that get called on multiple APs may need to take the current processor into
|
\item Interrupt handlers that get called on multiple APs may need to take the current processor into account (for example the APIC timer interrupt handler).
|
||||||
account (for example the APIC timer interrupt handler).
|
\item Register access has to be synchronized, if it is performed in multiple operations on the same address space.
|
||||||
\item Register access has to be synchronized, if it is performed in multiple operations on the same
|
|
||||||
address space.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
\section{Code Style}
|
% \section{Code Style}
|
||||||
\label{sec:codestyle}
|
% \label{sec:codestyle}
|
||||||
|
%
|
||||||
Individual state of local and I/O APICs is managed through instances of their respective classes.
|
% Individual state of local and I/O APICs is managed through instances of their respective classes.
|
||||||
Because each CPU core can only access the local APIC contained in itself, this can create a
|
% Because each CPU core can only access the local APIC contained in itself, this can create a
|
||||||
misconception: It is not possible to (e.g.) allow an interrupt in a certain local APIC by calling a
|
% misconception: It is not possible to (e.g.) allow an interrupt in a certain local APIC by calling a
|
||||||
function on a certain \code{LocalApic} instance. This is communicated through code by declaring a
|
% function on a certain \code{LocalApic} instance. This is communicated through code by declaring a
|
||||||
range of functions as \code{static}. It is also in direct contrast to the \code{IoApic} class: I/O
|
% range of functions as \code{static}. It is also in direct contrast to the \code{IoApic} class: I/O
|
||||||
APICs can be addressed by instances, because they are not part of the CPU core: Each core can
|
% APICs can be addressed by instances, because they are not part of the CPU core: Each core can
|
||||||
always access all I/O APICs (if there are multiple).
|
% always access all I/O APICs (if there are multiple).
|
||||||
|
%
|
||||||
Error checking is done to a small extent in this implementation: Publicly exposed functions (from
|
% Error checking is done to a small extent in this implementation: Publicly exposed functions (from
|
||||||
the \code{Apic} class) do check for invalid invocations, but the internally used classes do not
|
% the \code{Apic} class) do check for invalid invocations, but the internally used classes do not
|
||||||
protect their invariants, because they are not used directly by other parts of the OS. These
|
% protect their invariants, because they are not used directly by other parts of the OS. These
|
||||||
classes only selectively expose their interfaces (by using the \code{friend} declaration) for the
|
% classes only selectively expose their interfaces (by using the \code{friend} declaration) for the
|
||||||
same reason.
|
% same reason.
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Local APIC}
|
\section{Local APIC}
|
||||||
\label{sec:lapicinit}
|
\label{sec:lapicinit}
|
||||||
|
|
||||||
The local APIC block diagram (see \autoref{fig:localapicblock}) shows a number of registers that
|
The local APIC block diagram (see \autoref{fig:localapicblock}) shows a number of registers that are required for initialization\footnote{
|
||||||
are required for initialization:
|
Registers like the \textquote{Trigger Mode Register}, \textquote{Logical Destination Register} or \textquote{Destination Format Register} remain unused in this thesis.}:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item \textbf{\gls{lvt}}: Used to configure how local interrupts are handled.
|
\item \textbf{\gls{lvt}}: Used to configure how local interrupts are handled.
|
||||||
\item \textbf{\gls{svr}}: Contains the software-enable flag and the spurious interrupt vector number.
|
\item \textbf{\gls{svr}}: Contains the software-enable flag and the spurious interrupt vector number.
|
||||||
\item \textbf{\gls{tpr}}: Decides the order in which interrupts are handled and a possible interrupt
|
\item \textbf{\gls{tpr}}: Decides the order in which interrupts are handled and a possible interrupt priority threshold, to ignore low priority interrupts.
|
||||||
priority threshold, to ignore low priority interrupts.
|
|
||||||
\item \textbf{\gls{icr}}: Controls the sending of IPIs for starting up APs in SMP enabled systems.
|
\item \textbf{\gls{icr}}: Controls the sending of IPIs for starting up APs in SMP enabled systems.
|
||||||
\item \textbf{\gls{apr}}: Controls the priority in the APIC arbitration mechanism.
|
\item \textbf{\gls{apr}}: Controls the priority in the APIC arbitration mechanism.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
There are multiple registers associated with the LVT, those belong to the different local
|
\begin{figure}[h]
|
||||||
interrupts the local APIC can handle. Local interrupts this implementation is concerned about are
|
\centering
|
||||||
listed below:
|
\begin{subfigure}[b]{0.9\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{img/ia32_manual_local_apic_blockdiagram.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{The Local APIC Block Diagram~\autocite[sec.~3.11.4.1]{ia32}.}
|
||||||
|
\label{fig:localapicblock}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
There are multiple registers associated with the LVT, those belong to the different local interrupts the local APIC can handle.
|
||||||
|
Local interrupts this implementation is concerned about are listed below:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item LINT1: The local APIC's NMI source.
|
\item \textit{LINT1}: The local APIC's NMI source.
|
||||||
\item Timer: Periodic interrupt triggered by the APIC timer.
|
\item \textit{Timer}: Periodic interrupt triggered by the APIC timer.
|
||||||
\item Error: Triggered by errors in the APIC system (e.g.\ invalid vector numbers or corrupted messages
|
\item \textit{Error}: Triggered by errors in the APIC system (e.g.\ invalid vector numbers or corrupted messages in internal APIC communication).
|
||||||
in internal APIC communication).
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
The LINT0 interrupt is unlisted, because it is mainly important for virtual wire mode (it can be
|
The LINT0 interrupt is unlisted, because it is mainly important for virtual wire mode (it can be triggered by external interrupts from the PIC).
|
||||||
triggered by external interrupts from the PIC). The performance and thermal monitoring interrupts
|
The performance and thermal monitoring interrupts also remain unused in this implementation.
|
||||||
also remain unused in this implementation.
|
|
||||||
|
|
||||||
Besides the local APIC's own registers, the IMCR and \textbf{\gls{ia32 apic base msr}} also require
|
Besides the local APIC's own registers, the IMCR and IA32\textunderscore{}APIC\textunderscore{}BASE MSR also requires initialization (described in \autoref{subsec:lapicenable}).
|
||||||
initialization (described in \autoref{subsec:lapicenable}).
|
|
||||||
|
|
||||||
After system power-up, the local APIC is in the following state~\cite[sec.~3.11.4.7]{ia32}:
|
After system power-up, the local APIC is in the following state~\autocite[sec.~3.11.4.7]{ia32}:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item IRR, ISR and TPR are reset to \code{0x00000000}.
|
\item IRR, ISR and TPR are reset to \code{0x00000000}.
|
||||||
\item The LVT is reset to \code{0x00000000}, except for the masking bits (all local interrupts are masked
|
\item The LVT is reset to \code{0x00000000}, except for the masking bits (all local interrupts are masked on power-up).
|
||||||
on power-up).
|
|
||||||
\item The SVR is reset to \code{0x000000FF}.
|
\item The SVR is reset to \code{0x000000FF}.
|
||||||
\item The APIC is in xApic mode, even if x2Apic support is present.
|
\item The APIC is in xApic mode, even if x2Apic support is present.
|
||||||
\item Only the BSP is enabled, other APs have to be enabled by the BSP's local APIC\@.
|
\item Only the BSP is enabled, other APs have to be enabled by the BSP's local APIC\@.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
The initialization sequence consists of these steps:
|
The initialization sequence consists of these steps, all performed before interrupt handling is enabled (see \autoref{fig:apicenable}):
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Enable symmetric I/O mode and set the APIC operating mode.
|
\item Enable symmetric I/O mode and set the APIC operating mode.
|
||||||
\item Initialize the LVT and NMI\@.
|
\item Initialize the LVT and NMI\@.
|
||||||
\item Initialize the SVR\@.
|
\item Initialize the SVR\@.
|
||||||
\item Clear outstanding signals.
|
|
||||||
\item Initialize the TPR\@.
|
\item Initialize the TPR\@.
|
||||||
\item Initialize the APIC timer and error handler.
|
\item Initialize the APIC timer and error handler.
|
||||||
\item Startup the APs and initialize their respective local APICs.
|
\item Startup the APs and initialize their respective local APICs.
|
||||||
\item Synchronize the APRs.
|
\item Synchronize the APRs.
|
||||||
|
\item Enable interrupts for the BSP and APs.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
\subsection{Accessing Local APIC Registers in xApic Mode}
|
\subsection{Accessing Local APIC Registers in xApic Mode}
|
||||||
\label{subsec:xapicregacc}
|
\label{subsec:xapicregacc}
|
||||||
|
|
||||||
Accessing registers in xApic mode is done via MMIO and requires a single page (4 KB) of memory,
|
Accessing registers in xApic mode is done via MMIO and requires a single page (\SI{4}{\kilo\byte}) of memory, mapped to the \textquote{APIC Base} address, which can be obtained by reading the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) or parsing the MADT (see \autoref{tab:madt}).
|
||||||
mapped to the ``APIC Base'' address, which can be obtained by reading the
|
The IA-32 manual specifies a caching strategy of \textquote{strong uncachable}\footnote{
|
||||||
IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see
|
See IA-32 manual for information on this caching strategy~\autocite[sec.~3.12.3]{ia32}.}
|
||||||
\autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) or parsing the MADT (see
|
~\autocite[sec.~3.11.4.1]{ia32} for this region (see \autoref{subsec:apxxapicregacc} for the example implementation).
|
||||||
\autoref{tab:madt}). The IA-32 manual specifies a caching strategy of ``strong
|
|
||||||
uncachable''\footnote{See IA-32 manual for information on this caching
|
|
||||||
strategy~\cite[sec.~3.12.3]{ia32}.}~\cite[sec.~3.11.4.1]{ia32} for this region (see
|
|
||||||
\autoref{sec:apxxapicregacc} for the example implementation).
|
|
||||||
|
|
||||||
The address offsets (from the base address) for the local APIC registers are listed in the IA-32
|
The address offsets (from the base address) for the local APIC registers are listed in the IA-32 manual~\autocite[sec.~3.11.4.1]{ia32} and in \autoref{tab:lapicregs}.
|
||||||
manual~\cite[sec.~3.11.4.1]{ia32} and in \autoref{tab:lapicregs}.
|
|
||||||
|
|
||||||
\subsection{Enabling the Local APIC}
|
\subsection{Enabling the Local APIC}
|
||||||
\label{subsec:lapicenable}
|
\label{subsec:lapicenable}
|
||||||
|
|
||||||
The following steps have to be executed before any interrupt handling has been enabled by the OS\@.
|
Because the system boots in PIC mode, \code{0x01} should be written to the IMCR~\autocite[sec.~3.6.2.1]{mpspec} to disconnect the PIC from the local APIC's LINT0 INTI (see \autoref{fig:integratedapic}, for the example implementation see \autoref{subsec:apxdisablepic}).
|
||||||
|
|
||||||
Because the system boots in PIC mode, \code{0x01} should be written to the
|
To set the operating mode, it is first determined which modes are supported by executing the \code{cpuid} instruction with \code{eax=1}: If bit 9 of the \code{edx} register is set, xApic mode is supported, if bit 21 of the \code{ecx} register is set, x2Apic mode is supported~\autocite[sec.~5.1.2]{cpuid}.
|
||||||
IMCR~\cite[sec.~3.6.2.1]{mpspec} to disconnect the PIC from the local APIC's LINT0 pin (see
|
If xApic mode is supported (if the local APIC is an integrated APIC), it will be in that mode already.
|
||||||
\autoref{fig:integratedapic}, for the example implementation see \autoref{sec:apxdisablepic}).
|
The \textquote{global enable/disable} (\textquote{EN}) bit in the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) allows disabling xApic mode, and thus the entire local APIC, globally\footnote{
|
||||||
|
If the system uses the discrete APIC bus, xApic mode cannot be re-enabled without a system reset~\autocite[sec.~3.11.4.3]{ia32}.}.
|
||||||
To set the operating mode, it is first determined which modes are supported by executing the
|
Enabling x2Apic mode is done by setting the \textquote{EXTD} bit (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) of the IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.4.3]{ia32}.
|
||||||
\code{cpuid} instruction with \code{eax=1}: If bit 9 of the \code{edx} register is set, xApic mode
|
|
||||||
is supported, if bit 21 of the \code{ecx} register is set, x2Apic mode is
|
|
||||||
supported~\cite[sec.~5.1.2]{cpuid}.
|
|
||||||
|
|
||||||
If xApic mode is supported (if the local APIC is an integrated APIC), it will be in that mode
|
|
||||||
already. The ``global enable/disable'' (``EN'') bit in the
|
|
||||||
IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see
|
|
||||||
\autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) allows disabling xApic mode, and thus the
|
|
||||||
entire local APIC, globally\footnote{If the system uses the discrete APIC bus, xApic mode cannot be
|
|
||||||
re-enabled without a system reset~\cite[sec.~3.11.4.3]{ia32}.}.
|
|
||||||
|
|
||||||
Enabling x2Apic mode is done by setting the ``EXTD'' bit (see
|
|
||||||
\autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) of the
|
|
||||||
IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\cite[sec.~3.11.4.3]{ia32}.
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
\begin{figure}[h]
|
||||||
\centering
|
\centering
|
||||||
\begin{subfigure}[b]{0.7\textwidth}
|
\begin{subfigure}[b]{0.7\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_apic_base_msr.svg}
|
\includesvg[width=1.0\linewidth]{img/ia32_apic_base_msr.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{The IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\cite[sec.~3.11.4.4]{ia32}.}
|
\caption{The IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.4.4]{ia32}.}
|
||||||
\label{fig:ia32apicbasemsr}
|
\label{fig:ia32apicbasemsr}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
Because QEMU does not support x2Apic mode via its TCG\footnote{QEMU Tiny Code Generator transforms
|
Because QEMU does not support x2Apic mode via its TCG\footnote{
|
||||||
target instructions to instructions for the host CPU.}, this implementation only uses xApic mode.
|
QEMU Tiny Code Generator transforms target instructions to instructions for the host CPU.},
|
||||||
|
\ this implementation only uses xApic mode.
|
||||||
|
|
||||||
Besides the ``global enable/disable'' (``EN'') flag, the APIC can also be enabled/disabled by using
|
Besides the \textquote{global enable/disable} flag, the APIC can also be enabled/disabled by using the \textquote{software enable/disable} flag in the SVR, see \autoref{subsec:lapicsoftenable}.
|
||||||
the ``software enable/disable'' flag in the SVR, see \autoref{subsec:lapicsoftenable}.
|
|
||||||
|
|
||||||
\subsection{Handling Local Interrupts}
|
\subsection{Handling Local Interrupts}
|
||||||
\label{subsec:lapiclvtinit}
|
\label{subsec:lapiclvtinit}
|
||||||
|
|
||||||
To configure how the local APIC handles the different local interrupts, the LVT registers are
|
To configure how the local APIC handles the different local interrupts, the LVT registers are written (see \autoref{fig:localapiclvt}).
|
||||||
written (see \autoref{fig:localapiclvt}).
|
|
||||||
|
|
||||||
Local interrupts can be configured to use different delivery modes
|
\begin{figure}[h]
|
||||||
(excerpt)~\cite[sec.~3.11.5.1]{ia32}:
|
\centering
|
||||||
|
\begin{subfigure}[b]{0.7\textwidth}
|
||||||
|
\includesvg[width=1.0\linewidth]{img/ia32_lvt.svg}
|
||||||
|
\end{subfigure}
|
||||||
|
\caption{The Local Vector Table~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||||
|
\label{fig:localapiclvt}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
Local interrupts can be configured to use different delivery modes (excerpt)~\autocite[sec.~3.11.5.1]{ia32}:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Fixed: Simply delivers the interrupt vector stored in the LVT register.
|
\item \textit{Fixed}: Simply delivers the interrupt vector stored in the LVT register.
|
||||||
\item NMI: Configures this interrupt as non-maskable, this ignores the stored vector number.
|
\item \textit{NMI}: Configures this interrupt as non-maskable, this ignores the stored vector number.
|
||||||
\item ExtINT: The interrupt is treated as an external interrupt (instead of local interrupt), used e.g.\
|
\item \textit{ExtINT}: The interrupt is treated as an external interrupt (instead of local interrupt), used e.g.\ in virtual wire mode for LINT0\@.
|
||||||
in virtual wire mode for LINT0.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Initially, all local interrupts are initialized to PC/AT defaults: Masked, edge-triggered,
|
Initially, all local interrupts are initialized to PC/AT defaults: Masked, edge-triggered, active-high and with \textit{fixed} delivery mode.
|
||||||
active-high and with ``fixed'' delivery mode. Most importantly, the vector fields (bits 0:7 of an
|
Most importantly, the vector fields (bits 0:7 of each LVT register) are set to their corresponding interrupt vector (see \autoref{subsec:apxlvtinit} for an example implementation).
|
||||||
LVT register) are set to their corresponding interrupt vector (see \autoref{sec:apxlvtinit} for an
|
|
||||||
example implementation).
|
|
||||||
|
|
||||||
After default-initializing the local interrupts, LINT1 has to be configured separately (see
|
After default-initializing the local interrupts, LINT1 has to be configured separately (see \autoref{tab:lapicregslvtlint}), because it is the local APIC's NMI source\footnote{
|
||||||
\autoref{tab:lapicregslvtlint}), because it is the local APIC's NMI source\footnote{In older
|
In older specifications~\autocite{mpspec}, LINT1 is defined as NMI source (see \autoref{fig:integratedapic}).
|
||||||
specifications~\cite{mpspec}, LINT1 is defined as NMI source (see \autoref{fig:integratedapic}). It
|
It is possible that this changed with newer architectures, so for increased compatibility this implementation configures the local APIC NMI source as reported by ACPI\@.
|
||||||
is possible that this changed with newer architectures, so for increased compatibility this
|
It is also possible that ACPI reports information on the NMI source just for future-proofing.}.
|
||||||
implementation configures the local APIC NMI source as reported by ACPI. It is also possible that
|
The delivery mode is set to \textquote{NMI} and the interrupt vector to \code{0x00}.
|
||||||
ACPI reports information on the NMI source just for future-proofing.}. The delivery mode is set to
|
This information is also provided by ACPI in the MADT (see \autoref{tab:madtlnmi}).
|
||||||
``NMI'' and the interrupt vector to \code{0x00}. This information is also provided by ACPI in the
|
Other local interrupts (APIC timer and the error interrupt) will be configured later (see \autoref{subsec:lapictimer} and \autoref{subsec:lapicerror}).
|
||||||
MADT (see \autoref{tab:madtlnmi}). Other local interrupts (APIC timer and the error interrupt) will
|
|
||||||
be configured later (see \autoref{subsec:lapictimer} and \autoref{subsec:lapicerror}).
|
|
||||||
|
|
||||||
\subsection{Allowing Interrupt Processing}
|
\subsection{Allowing Interrupt Processing}
|
||||||
\label{subsec:lapicsoftenable}
|
\label{subsec:lapicsoftenable}
|
||||||
|
|
||||||
To complete a minimal local APIC initialization, the ``software enable/disable'' flag and the
|
To complete a minimal local APIC initialization, the \textquote{software enable/disable} flag and the spurious interrupt vector (see \autoref{fig:ia32apicsvr}/\autoref{tab:lapicregssvr}), are set.
|
||||||
spurious interrupt vector (both contained in the SVR, see
|
It makes sense to choose \code{0xFF} for the spurious interrupt vector, as on P6 and Pentium processors, the lowest four bits must be set (see \autoref{fig:ia32apicsvr}).
|
||||||
\autoref{fig:ia32apicsvr}/\autoref{tab:lapicregssvr}), are set. It makes sense to choose
|
|
||||||
\code{0xFF} for the spurious interrupt vector, as on P6 and Pentium processors, the lowest 4 bits
|
|
||||||
must be set (see \autoref{fig:ia32apicsvr}).
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
\begin{figure}[h]
|
||||||
\centering
|
\centering
|
||||||
\begin{subfigure}[b]{0.7\textwidth}
|
\begin{subfigure}[b]{0.7\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_apic_svr.svg}
|
\includesvg[width=1.0\linewidth]{img/ia32_apic_svr.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{The local APIC SVR register~\cite[sec.~3.11.9]{ia32}.}
|
\caption{The Local APIC SVR Register~\autocite[sec.~3.11.9]{ia32}.}
|
||||||
\label{fig:ia32apicsvr}
|
\label{fig:ia32apicsvr}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
Because the APIC's spurious interrupt has a dedicated interrupt vector (unlike the PIC's spurious
|
Because the APIC's spurious interrupt has a dedicated interrupt vector (unlike the PIC's spurious interrupt), it can be ignored easily by registering a stub interrupt handler for the appropriate vector (see \autoref{subsec:apxsvr} for an implementation example).
|
||||||
interrupt), it can be ignored easily by registering a stub interrupt handler for the appropriate
|
|
||||||
vector (see \autoref{sec:apxsvr} for an implementation example).
|
|
||||||
|
|
||||||
The final step to initialize the BSP's local APIC is to allow the local APIC to receive interrupts
|
The final step to initialize the BSP's local APIC is to allow the local APIC to receive interrupts of all priorities.
|
||||||
of all priorities. This is done by writing \code{0x00} to the TPR~\cite[sec.~3.11.8.3]{ia32} (see
|
This is done by writing \code{0x00} to the TPR~\autocite[sec.~3.11.8.3]{ia32} (see \autoref{tab:lapicregstpr}).
|
||||||
\autoref{tab:lapicregstpr}). By configuring the TPRs of different local APICs to different
|
By configuring the TPRs of different local APICs to different priorities or priority classes, distribution of external interrupts to CPUs can be controlled, but this is not used in this thesis.
|
||||||
priorities or priority classes, distribution of external interrupts to CPUs can be controlled, but
|
|
||||||
this is not used in this thesis.
|
|
||||||
|
|
||||||
\subsection{Local Interrupt EOI}
|
\subsection{Local Interrupt EOI}
|
||||||
\label{subsec:lapiceoi}
|
\label{subsec:lapiceoi}
|
||||||
|
|
||||||
To notify the local APIC that a local interrupt has been handled, its EOI register (see
|
To notify the local APIC that a local interrupt is being handled, its EOI register (see \autoref{tab:lapicregseoi}) has to be written.
|
||||||
\autoref{tab:lapicregseoi}) has to be written. Not all local interrupts require EOIs: NMI, SMI,
|
Not all local interrupts require EOIs: NMI, SMI, INIT, ExtINT, SIPI, or INIT-Deassert interrupts are excluded~\autocite[sec.~3.11.8.5]{ia32}.
|
||||||
INIT, ExtINT, STARTUP, or INIT-Deassert interrupts are excluded~\cite[sec.~3.11.8.5]{ia32}.
|
|
||||||
|
|
||||||
EOIs for external interrupts are also handled by the local APIC, this is described in
|
EOIs for external interrupts are also handled by the local APIC, further described in \autoref{subsec:ioapiceoi}.
|
||||||
\autoref{subsec:ioapiceoi}.
|
|
||||||
|
|
||||||
\subsection{APIC Timer}
|
\subsection{APIC Timer}
|
||||||
\label{subsec:lapictimer}
|
\label{subsec:lapictimer}
|
||||||
|
|
||||||
The APIC timer is integrated into the local APIC, so it requires initialization of the latter. Like
|
The APIC timer is integrated into the local APIC, so it requires initialization of the latter.
|
||||||
the PIT, the APIC timer can generate periodic interrupts in a specified interval by using a
|
Like the PIT, the APIC timer can generate periodic interrupts in a specified interval by using a counter, that is initialized with a starting value depending on the desired interval.
|
||||||
counter, that is initialized with a starting value depending on the desired interval. Because the
|
Because the APIC timer does not tick with a fixed frequency, but at bus frequency, the initial counter has to be determined at runtime by using an external time source.
|
||||||
APIC timer doesn't tick with a fixed frequency, but at bus frequency, the initial counter has to be
|
In addition to the counter register, the APIC timer interval is influenced by a divider: Instead of decrementing the counter at every bus clock, it will be decremented every \(n\)-th bus clock, where \(n\) is the divider.
|
||||||
determined at runtime by using an external time source. In addition to the counter register, the
|
This is useful to allow for long intervals (with decreased precision), that would require a larger counter register otherwise.
|
||||||
APIC timer interval is influenced by a divider: Instead of decrementing the counter at every bus
|
|
||||||
clock, it will be decremented every \(n\)-th bus clock, where \(n\) is the divider. This is useful
|
|
||||||
to allow for long intervals (with decreased precision), that would require a larger counter
|
|
||||||
register otherwise.
|
|
||||||
|
|
||||||
The APIC timer supports three different timer modes, that can be set in the timer's LVT register:
|
The APIC timer supports three different timer modes, that can be set in the timer's LVT register:
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Oneshot: Trigger exactly one interrupt when the counter reaches zero.
|
\item \textit{Oneshot}: Trigger exactly one interrupt when the counter reaches zero.
|
||||||
\item Periodic: Trigger an interrupt each time the counter reaches zero, on zero the counter reloads its
|
\item \textit{Periodic}: Trigger an interrupt each time the counter reaches zero, on zero the counter reloads its initial value.
|
||||||
initial value.
|
\item \textit{TSC-Deadline}: Trigger exactly one interrupt at an absolute time.
|
||||||
\item TSC-Deadline: Trigger exactly one interrupt at an absolute time.
|
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
This implementation uses the APIC timer in periodic mode, to trigger the scheduler preemption.
|
This implementation uses the APIC timer in periodic mode, to trigger the scheduler preemption.
|
||||||
Initialization requires the following steps (order recommended by OSDev~\cite{osdev}):
|
Initialization requires the following steps (order recommended by OSDev~\autocite{osdev}):
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Measure the timer frequency with an external time source.
|
\item Measure the timer frequency with an external time source.
|
||||||
\item Configuration of the timer's divider register (see \autoref{tab:lapicregstimerdiv}).
|
\item Configuration of the timer's divider register (see \autoref{tab:lapicregstimerdiv}).
|
||||||
\item Setting the timer mode to periodic (see \autoref{tab:lapicregslvtt}).
|
\item Setting the timer mode to periodic (see \autoref{tab:lapicregslvtt}).
|
||||||
\item Initializing the counter register (see \autoref{tab:lapicregstimerinit}), depending on the measured
|
\item Initializing the counter register (see \autoref{tab:lapicregstimerinit}), depending on the measured timer frequency and the desired interval.
|
||||||
timer frequency and the desired interval.
|
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
In this implementation, the APIC timer is calibrated by counting the amount of ticks in one
|
In this implementation, the APIC timer is calibrated by counting the amount of ticks in one millisecond using oneshot mode (see \autoref{subsec:apxapictimer} for an example implementation).
|
||||||
millisecond using oneshot mode (see \autoref{sec:apxapictimer} for an example implementation). The
|
The measured amount of timer ticks can then be used to calculate the required counter for an arbitrary millisecond interval, although very large intervals could require the use of a larger divider, while very small intervals (in micro- or nanosecond scale) could require the opposite, to provide the necessary precision.
|
||||||
measured amount of timer ticks can then be used to calculate the required counter for an arbitrary
|
For this approach it is important that the timer is initialized with the same divider that was used during calibration.
|
||||||
millisecond interval, although very large intervals could require the use of a larger divider,
|
|
||||||
while very small intervals (in micro- or nanosecond scale) could require the opposite, to provide
|
|
||||||
the necessary precision. For this approach it is important that the timer is initialized with the
|
|
||||||
same divider that was used during calibration.
|
|
||||||
|
|
||||||
To use the timer, an interrupt handler has to be registered to its interrupt vector (see
|
To use the timer, an interrupt handler has to be registered to its interrupt vector (see \autoref{subsec:apxapictimer} for an example implementation).
|
||||||
\autoref{sec:apxapictimer} for an example implementation).
|
|
||||||
|
|
||||||
\subsection{APIC Error Interrupt}
|
\subsection{APIC Error Interrupt}
|
||||||
\label{subsec:lapicerror}
|
\label{subsec:lapicerror}
|
||||||
|
|
||||||
Errors can occur for example when the local APIC receives an invalid vector number, or an APIC
|
Errors can occur e.g.\ when the local APIC receives an invalid vector number, or an APIC message gets corrupted on the system bus.
|
||||||
message gets corrupted on the system bus. To handle these cases, the local APIC provides the local
|
To handle these cases, the local APIC provides the local error interrupt, whose interrupt handler can read the error status from the local APIC's \textbf{\gls{esr}} (see \autoref{fig:ia32esr}/\autoref{tab:lapicregsesr}) and take appropriate action.
|
||||||
error interrupt, whose interrupt handler can read the error status from the local APIC's
|
|
||||||
\textbf{\gls{esr}} (see \autoref{fig:ia32esr}/\autoref{tab:lapicregsesr}) and take appropriate
|
|
||||||
action.
|
|
||||||
|
|
||||||
\begin{figure}[h]
|
\begin{figure}[h]
|
||||||
\centering
|
\centering
|
||||||
\begin{subfigure}[b]{0.7\textwidth}
|
\begin{subfigure}[b]{0.7\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_error_status_register.svg}
|
\includesvg[width=1.0\linewidth]{img/ia32_error_status_register.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{Error Status Register~\cite[sec.~3.11.5.3]{ia32}.}
|
\caption{Error Status Register~\autocite[sec.~3.11.5.3]{ia32}.}
|
||||||
\label{fig:ia32esr}
|
\label{fig:ia32esr}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
The ESR is a ``write/read'' register: Before reading a value from the ESR, it has to be written,
|
The ESR is a \textquote{write/read} register: Before reading a value from the ESR, it has to be written, which updates the ESR's contents to the error status since the last write.
|
||||||
which updates the ESR's contents to the error status since the last write. Writing the ESR also
|
Writing the ESR also arms the local error interrupt, which doesn't happen automatically~\autocite[sec.~3.11.5.3]{ia32}.
|
||||||
arms the local error interrupt again~\cite[sec.~3.11.5.3]{ia32}.
|
|
||||||
|
|
||||||
Enabling the local error interrupt is now as simple as enabling it in the local APIC's LVT and
|
Enabling the local error interrupt is now as simple as enabling it in the local APIC's LVT and registering an interrupt handler for the appropriate vector (see \autoref{subsec:apxhandlingerror} for an example implementation).
|
||||||
registering an interrupt handler for the appropriate vector (see \autoref{sec:apxhandlingerror} for
|
|
||||||
an example implementation).
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{I/O APIC}
|
\section{I/O APIC}
|
||||||
\label{sec:ioapicinit}
|
\label{sec:ioapicinit}
|
||||||
|
|
||||||
% TODO: Continue moving code to the appendix from here on
|
To fully replace the PIC and handle external interrupts using the APIC, the I/O APIC, located in the system chipset, has to be initialized by setting its \textbf{\gls{redtbl}} registers~\autocite[sec.~9.5.8]{ich5} (see \autoref{tab:ioapicregsredtbl}).
|
||||||
|
Like the local APIC's LVT, the REDTBL allows configuration of interrupt vectors, masking bits, interrupt delivery modes, pin polarities and trigger modes (see \autoref{subsec:lapiclvtinit}).
|
||||||
|
|
||||||
To fully replace the PIC and handle external interrupts using the APIC, the I/O APIC, located in
|
Additionally, for external interrupts a destination and destination mode can be specified.
|
||||||
the system chipset, has to be initialized by setting its \textbf{\gls{redtbl}}
|
This is required because the I/O APIC is able to forward external interrupts to different local APICs over the system bus (see \autoref{fig:integratedapic}).
|
||||||
registers~\cite[sec.~9.5.8]{ich5} (see \autoref{tab:ioapicregsredtbl}). Like the local APIC's LVT,
|
SMP systems use this mechanism to distribute external interrupts to different CPU cores for performance benefits.
|
||||||
the REDTBL allows configuration of interrupt vectors, masking bits, interrupt delivery modes, pin
|
Because this implementation's focus is not on SMP, all external interrupts are default initialized to \textit{physical} destination mode\footnote{
|
||||||
polarities and trigger modes (see \autoref{subsec:lapiclvtinit}).
|
The alternative is \textit{logical} destination mode, which allows addressing individual or clusters of local APIC's in a larger volume of processors~\autocite[sec.~3.11.6.2.2]{ia32}.}
|
||||||
|
~\autocite[sec.~3.11.6.2.1]{ia32} and are sent to the BSP for servicing, by using the BSP's local APIC ID as the destination.
|
||||||
|
The other fields are set to ISA bus defaults\footnote{
|
||||||
|
Edge-triggered, active-high.},
|
||||||
|
\ with \textit{fixed} delivery mode, masked, and the corresponding interrupt vector, as defined by the \code{InterruptVector} enum.
|
||||||
|
|
||||||
Additionally, for external interrupts a destination and destination mode can be specified. This is
|
The I/O APIC does not have to be enabled explicitly, if the local APIC is enabled and the REDTBL is initialized correctly, external interrupts will be redirected to the local APIC and handled by the CPU\@.
|
||||||
required because the I/O APIC is able to forward external interrupts to different local APICs over
|
|
||||||
the system bus (see \autoref{fig:integratedapic}). SMP systems use this mechanism to distribute
|
|
||||||
external interrupts to different CPU cores for performance benefits. Because this implementation's
|
|
||||||
focus is not on SMP, all external interrupts are default initialized to ``physical'' destination
|
|
||||||
mode\footnote{The alternative is "logical" destination mode, which allows addressing individual or
|
|
||||||
clusters of local APIC's in a larger volume of
|
|
||||||
processors~\cite[sec.~3.11.6.2.2]{ia32}.}~\cite[sec.~3.11.6.2.1]{ia32} and are sent to the BSP for
|
|
||||||
servicing, by using the BSP's local APIC ID as the destination. The other fields are set to
|
|
||||||
\textbf{\gls{isa}} bus defaults\footnote{Edge-triggered, active-high.}, with ``fixed'' delivery
|
|
||||||
mode, masked, and the corresponding interrupt vector, as defined by the \code{InterruptVector}
|
|
||||||
enum.
|
|
||||||
|
|
||||||
The I/O APIC does not have to be enabled explicitly, if the local APIC is enabled and the REDTBL is
|
Unlike the local APIC's registers, the REDTBL registers are accessed indirectly: Two registers, the \textquote{Index} and \textquote{Data} register~\autocite[sec.~9.5.1]{ich5}, are mapped to the main memory and can be used analogous to the local APIC's registers.
|
||||||
initialized correctly, external interrupts will be redirected to the local APIC and handled by the
|
The MMIO base address can be parsed from the MADT (see \autoref{tab:madtioapic}).
|
||||||
CPU\@.
|
Writing an offset to the index register exposes an indirectly accessible I/O APIC register through the data register (see \autoref{subsec:iolistings} for an example implementation).
|
||||||
|
This indirect addressing scheme is useful, because the number of external interrupts an I/O APIC supports, and in turn the number of REDTBL registers, can vary\footnote{
|
||||||
|
Intel's consumer \textbf{\glspl{ich}} always support a fixed amount of 24 external interrupts though~\autocite[sec.~9.5.7]{ich5}.}.
|
||||||
|
|
||||||
Unlike the local APIC's registers, the REDTBL registers are accessed indirectly: Two registers, the
|
It is possible that one or multiple of the I/O APIC's interrupt inputs act as an NMI source.
|
||||||
``Index'' and ``Data'' register~\cite[sec.~9.5.1]{ich5}, are mapped to the main memory and can be
|
If this is the case is reported in the MADT (see \autoref{tab:madtionmi}), so when necessary, the corresponding REDTBL entries are initialized like the local APIC's NMI source (see \autoref{subsec:lapiclvtinit}), and using these interrupt inputs for external interrupts is forbidden.
|
||||||
used analogous to the local APIC's registers. The MMIO base address can be parsed from the MADT
|
|
||||||
(see \autoref{tab:madtioapic}). Writing an offset to the index register exposes an indirectly
|
|
||||||
accessible I/O APIC register through the data register (see \autoref{sec:iolistings} for an example
|
|
||||||
implementation). This indirect addressing scheme is useful, because the number of external
|
|
||||||
interrupts an I/O APIC supports, and in turn the number of REDTBL registers, can
|
|
||||||
vary\footnote{Intel's consumer \textbf{\glspl{ich}} always support a fixed amount of 24 external
|
|
||||||
interrupts though~\cite[sec.~9.5.7]{ich5}.}.
|
|
||||||
|
|
||||||
It is possible that one or multiple of the I/O APIC's interrupt inputs act as an NMI source. If
|
|
||||||
this is the case is reported in the MADT (see \autoref{tab:madtionmi}), so when necessary, the
|
|
||||||
corresponding REDTBL entries are initialized like the local APIC's NMI source (see
|
|
||||||
\autoref{subsec:lapiclvtinit}), and using these interrupt inputs for external interrupts is
|
|
||||||
forbidden.
|
|
||||||
|
|
||||||
\subsection{Interrupt Overrides}
|
\subsection{Interrupt Overrides}
|
||||||
\label{subsec:ioapicpcat}
|
\label{subsec:ioapicpcat}
|
||||||
|
|
||||||
In every PC/AT compatible system, external devices are hardwired to the PIC in the same order.
|
In every PC/AT compatible system, external devices are hardwired to the PIC in the same order.
|
||||||
Because this is not the case for the I/O APIC, the interrupt line used by each PC/AT compatible
|
Because this is not the case for the I/O APIC, the INTIs used by each PC/AT compatible interrupt has to be determined by the OS at runtime, by using ACPI\@.
|
||||||
interrupt has to be determined by the OS at runtime, by using ACPI. ACPI provides ``Interrupt
|
ACPI provides \textquote{Interrupt Source Override} structures~\autocite[sec.~5.2.8.3.1]{acpi1} inside the MADT (see \autoref{tab:madtirqoverride}) for each PC/AT compatible interrupt that is mapped differently to the I/O APIC than to the PIC\@.
|
||||||
Source Override'' structures~\cite[sec.~5.2.8.3.1]{acpi1} inside the MADT (see
|
In addition to the interrupt input mapping, these structures also allow customizing the pin polarity and trigger mode of PC/AT compatible interrupts.
|
||||||
\autoref{tab:madtirqoverride}) for each PC/AT compatible interrupt that is mapped differently to
|
|
||||||
the I/O APIC than to the PIC\@.
|
|
||||||
|
|
||||||
In addition to the interrupt input mapping, these structures also allow to customize the pin
|
This information does not only apply to the REDTBL initialization, but it has to be taken into account every time an action is performed on a PC/AT compatible interrupt, like masking or unmasking: If \code{IRQ0} (PIT) should be unmasked, it has to be determined what GSI (or in other words, I/O APIC interrupt input) it belongs to.
|
||||||
polarity and trigger mode of PC/AT compatible interrupts.
|
In many systems \code{IRQ0} is mapped to \code{GSI2}, because the PC/AT compatible PICs are connected to \code{GSI0} (see \autoref{fig:integratedapic}).
|
||||||
|
Thus, to allow the PIT interrupt in those systems, the REDTBL entry belonging to \code{GSI2} instead of \code{GSI0} has to be written (see \autoref{subsec:apxirqoverrides} for an example implementation).
|
||||||
This information does not only apply to the REDTBL initialization, but it has to be taken into
|
|
||||||
account every time an action is performed on a PC/AT compatible interrupt, like masking or
|
|
||||||
unmasking: If \code{IRQ0} (PIT) should be unmasked, it has to be determined what GSI (or in other
|
|
||||||
words, I/O APIC interrupt input) it belongs to. In many systems \code{IRQ0} is mapped to
|
|
||||||
\code{GSI2}, because the PC/AT compatible PICs are connected to \code{GSI0}. Thus, to allow the PIT
|
|
||||||
interrupt in those systems, the REDTBL entry belonging to \code{GSI2} instead of \code{GSI0} has to
|
|
||||||
be written (see \autoref{sec:apxirqoverrides} for an example implementation).
|
|
||||||
|
|
||||||
\subsection{External Interrupt EOI}
|
\subsection{External Interrupt EOI}
|
||||||
\label{subsec:ioapiceoi}
|
\label{subsec:ioapiceoi}
|
||||||
|
|
||||||
Notifying the I/O APIC that an external interrupt has been handled differs depending on the
|
Notifying the I/O APIC that an external interrupt has been handled differs depending on the interrupt trigger mode: Edge-triggered external interrupts are completed by writing the local APIC's EOI register (see \autoref{subsec:lapiceoi})\footnote{
|
||||||
interrupt trigger mode: Edge-triggered external interrupts are completed by writing the local
|
Because external interrupts are forwarded to the local APIC, the local APIC is responsible for tracking them in its IRR and ISR.}.
|
||||||
APIC's EOI register (see \autoref{subsec:lapiceoi})\footnote{Because external interrupts are
|
Level-triggered interrupts are treated separately: Upon registering a level-triggered external interrupt, the I/O APIC sets an internal \textquote{Remote IRR} bit in the corresponding REDTBL entry~\autocite[sec.~9.5.8]{ich5} (see \autoref{tab:ioapicregsredtbl}).
|
||||||
forwarded to the local APIC, the local APIC is responsible for tracking them in its IRR and ISR.}.
|
|
||||||
Level-triggered interrupts are treated separately: Upon registering a level-triggered external
|
|
||||||
interrupt, the I/O APIC sets an internal ``Remote IRR'' bit in the corresponding REDTBL
|
|
||||||
entry~\cite[sec.~9.5.8]{ich5} (see \autoref{tab:ioapicregsredtbl}).
|
|
||||||
|
|
||||||
There are three possible ways to signal completion of a level-triggered external interrupt to clear
|
There are three possible ways to signal completion of a level-triggered external interrupt to clear the remote IRR bit:
|
||||||
the remote IRR bit:
|
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Using the local APIC's EOI broadcasting feature: If EOI broadcasting is enabled, writing the local
|
\item Using the local APIC's EOI broadcasting feature: If EOI broadcasting is enabled, writing the local APIC's EOI register also triggers EOIs for each I/O APIC (for the appropriate interrupt), which clears the remote IRR bit.
|
||||||
APIC's EOI register also triggers EOIs for each I/O APIC (for the appropriate interrupt), which
|
\item Sending a directed EOI to an I/O APIC\@: I/O APICs with versions greater than \code{0x20} include an I/O EOI register~\autocite[sec.~9.5.5]{ich5}.
|
||||||
clears the remote IRR bit.
|
Writing the vector number of the handled interrupt to this register clears the remote IRR bit.
|
||||||
\item Sending a directed EOI to an I/O APIC: I/O APICs with versions greater than \code{0x20} include an
|
\item Simulating a directed EOI for I/O APICs with versions smaller than \code{0x20}: Temporarily masking and setting a completed interrupt as edge-triggered clears the remote IRR bit~\autocite[io\textunderscore{}apic.c]{linux}.
|
||||||
I/O EOI register. Writing the vector number of the handled interrupt to this register clears the
|
|
||||||
remote IRR bit.
|
|
||||||
\item Simulating a directed EOI for I/O APICs with versions smaller than \code{0x20}: Temporarily masking
|
|
||||||
and setting a completed interrupt as edge-triggered clears the remote IRR
|
|
||||||
bit~\cite[io\textunderscore{}apic.c]{linux}.
|
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
Because the first option is the only one supported by all APIC versions, it is used in this
|
Because the first option is the only one supported by all APIC versions, it is used in this implementation\footnote{
|
||||||
implementation\footnote{Disabling EOI broadcasting is not supported by all local
|
Disabling EOI broadcasting is not supported by all local APICs~\autocite[sec.~3.11.8.5]{ia32}.}.
|
||||||
APICs~\cite[sec.~3.11.8.5]{ia32}.}.
|
|
||||||
|
|
||||||
At this point, after initializing the local and I/O APIC for the BSP, the APIC system is fully
|
At this point, after initializing the local and I/O APIC for the BSP, the APIC system is fully usable.
|
||||||
usable. External interrupts now have to be enabled/disabled by writing the ``masked'' bit in these
|
External interrupts now have to be enabled/disabled by writing the \textquote{masked} bit in these interrupts' REDTBL entries, interrupt handler completion is signaled by writing the local APIC's EOI register, and spurious interrupts are detected by using the local APIC's spurious interrupt vector.
|
||||||
interrupts' REDTBL entries, interrupt handler completion is signaled by writing the local APIC's
|
|
||||||
EOI register, and spurious interrupts are detected by using the local APIC's spurious interrupt
|
|
||||||
vector.
|
|
||||||
|
|
||||||
\subsection{Multiple I/O APICs}
|
\subsection{Multiple I/O APICs}
|
||||||
\label{subsec:multiioapic}
|
\label{subsec:multiioapic}
|
||||||
|
|
||||||
Most consumer hardware, for example all IA processors~\cite{ia32} and ICH hubs~\cite{ich5}, only
|
Most consumer hardware, for example all IA processors~\autocite{ia32} and ICH hubs~\autocite{ich5}, only provide a single I/O APIC, although technically multiple I/O APICs are supported by the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.8]{mpspec}.
|
||||||
provide a single I/O APIC, although technically multiple I/O APICs are supported by the
|
If ACPI reports multiple I/O APICs (by supplying multiple MADT I/O APIC structures, see \autoref{tab:madtioapic}), the previously described initialization has to be performed for each I/O APIC individually.
|
||||||
MultiProcessor specification~\cite[sec.~3.6.8]{mpspec}.
|
Additionally, the I/O APIC's ID, also reported by ACPI, has to be written to the corresponding I/O APIC's ID register (see \autoref{tab:ioapicregsid}), because this register is always initialized to zero~\autocite[sec.~9.5.6]{ich5}.
|
||||||
|
|
||||||
If ACPI reports multiple I/O APICs (by supplying multiple MADT I/O APIC structures, see
|
Using a variable number of I/O APICs requires determining the target I/O APIC for each operation that concerns a GSI, like masking or unmasking.
|
||||||
\autoref{tab:madtioapic}), the previously described initialization has to be performed for each I/O
|
For this reason, ACPI provides the \textquote{GSI Base}~\autocite[sec.~5.2.8.2]{acpi1} for each available I/O APIC, the number of GSIs a single I/O APIC can handle can be determined by reading the I/O APIC's version register~\autocite[sec.~9.5.7]{ich5} (see \autoref{tab:ioapicregsver})\footnote{
|
||||||
APIC individually. Additionally, the I/O APIC's ID, also reported by ACPI, has to be written to the
|
This approach was previously used in this implementation, but removed for simplicity.}.
|
||||||
corresponding I/O APIC's ID register (see \autoref{tab:ioapicregsid}), because this register is
|
|
||||||
always initialized to zero~\cite[sec.~9.5.6]{ich5}.
|
|
||||||
|
|
||||||
Using a variable number of I/O APICs requires determining the target I/O APIC for each operation
|
|
||||||
that concerns a GSI, like masking or unmasking. For this reason, ACPI provides the ``GSI
|
|
||||||
Base''~\cite[sec.~5.2.8.2]{acpi1} for each available I/O APIC, the number of GSIs a single I/O APIC
|
|
||||||
can handle can be determined by reading the I/O APIC's version register~\cite[sec.~9.5.7]{ich5}
|
|
||||||
(see \autoref{tab:ioapicregsver})\footnote{This approach was previously used in this
|
|
||||||
implementation, but removed for simplicity.}.
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Symmetric Multiprocessing}
|
\section{Symmetric Multiprocessing}
|
||||||
\label{sec:smpinit}
|
\label{sec:smpinit}
|
||||||
|
|
||||||
Like single-core systems, SMP systems boot using only a single core, the BSP. By using the APIC's
|
Like single-core systems, SMP systems boot using only a single core, the BSP\@.
|
||||||
capabilities to send IPIs between cores, additional APs can be put into startup state and booted
|
By using the APIC's capabilities to send IPIs between cores, additional APs can be put into startup state and booted for system use.
|
||||||
for system use.
|
|
||||||
|
|
||||||
To determine the amount of usable processors, the MADT is parsed (see \autoref{tab:madtlapic}).
|
To determine the number of usable processors, the MADT is parsed (see \autoref{tab:madtlapic}).
|
||||||
Note, that some processors may be reported as disabled, those may not be used by the OS (see
|
Note, that some processors may be reported as disabled, those may not be used by the OS (see \autoref{tab:madtlapicflags}).
|
||||||
\autoref{tab:madtlapicflags}).
|
|
||||||
|
|
||||||
\subsection{Inter-Processor Interrupts}
|
\subsection{Inter-Processor Interrupts}
|
||||||
\label{subsec:ipis}
|
\label{subsec:ipis}
|
||||||
|
|
||||||
Issuing IPIs works by writing the local APIC's ICR (see
|
Issuing IPIs works by writing the local APIC's ICR (see \autoref{fig:ia32icr}/\autoref{tab:lapicregsicr}).
|
||||||
\autoref{fig:ia32icr}/\autoref{tab:lapicregsicr}). It allows specifying IPI type, destination
|
It allows specifying IPI type, destination (analogous to REDTBL destinations, see \autoref{sec:ioapicinit}) and vector (see \autoref{subsec:apxipis} for an example implementation).
|
||||||
(analogous to REDTBL destinations, see \autoref{sec:ioapicinit}) and vector (see
|
|
||||||
\autoref{sec:apxipis} for an example implementation).
|
|
||||||
|
|
||||||
Depending on the APIC architecture, two different IPIs are required: The INIT IPI for systems using
|
Depending on the APIC architecture, two different IPIs are required: The \textit{INIT IPI} for systems using a discrete APIC, and the \textbf{\gls{sipi}} for systems using the xApic or x2Apic architectures:
|
||||||
a discrete APIC, and the \textbf{\gls{sipi}} for systems using the xApic or x2Apic architectures:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item The INIT IPI causes an AP to reset its state and start executing at the address specified at its
|
\item The INIT IPI causes an AP to reset its state and start executing at the address specified at its system reset vector.
|
||||||
system reset vector. If paired with a system warm-reset, the AP can be instructed to start
|
If paired with a system warm-reset, the AP can be instructed to start executing the AP boot sequence by writing the appropriate address to the warm-reset vector~\autocite[sec.~B.4.1]{mpspec}.
|
||||||
executing the AP boot sequence by writing the appropriate address to the warm-reset
|
\item Since the xApic architecture, the SIPI is used for AP startup: It causes the AP to start executing code in real mode, at a page specified in the IPIs interrupt vector~\autocite[sec.~B.4.2]{mpspec}.
|
||||||
vector~\cite[sec.~B.4.1]{mpspec}.
|
By copying the AP boot routine to a page in lower physical memory, and sending the SIPI with the correct page number, an AP can be booted.
|
||||||
\item Since the xApic architecture, the SIPI is used for AP startup: It causes the AP to start executing
|
|
||||||
code in real mode, at a page specified in the IPIs interrupt vector~\cite[sec.~B.4.2]{mpspec}. By
|
|
||||||
copying the AP boot routine to a page in lower physical memory, and sending the SIPI with the
|
|
||||||
correct page number, an AP can be booted.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
To wait until the IPI is sent, the ICR's delivery status bit can be polled.
|
To wait until the IPI is sent, the ICR's delivery status bit can be polled.
|
||||||
@ -534,77 +418,54 @@ To wait until the IPI is sent, the ICR's delivery status bit can be polled.
|
|||||||
\begin{subfigure}[b]{0.7\textwidth}
|
\begin{subfigure}[b]{0.7\textwidth}
|
||||||
\includesvg[width=1.0\linewidth]{img/ia32_interrupt_command_register.svg}
|
\includesvg[width=1.0\linewidth]{img/ia32_interrupt_command_register.svg}
|
||||||
\end{subfigure}
|
\end{subfigure}
|
||||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
\caption{Interrupt Command Register~\autocite[sec.~3.11.6.1]{ia32}.}
|
||||||
\label{fig:ia32icr}
|
\label{fig:ia32icr}
|
||||||
\end{figure}
|
\end{figure}
|
||||||
|
|
||||||
\subsection{Universal Startup Algorithm}
|
\subsection{Universal Startup Algorithm}
|
||||||
\label{subsec:apstartup}
|
\label{subsec:apstartup}
|
||||||
|
|
||||||
SMP initialization is performed differently on various processors. Intel's MultiProcessor
|
SMP initialization is performed differently on various processors.
|
||||||
specification defines a ``universal startup algorithm'' for multiprocessor
|
Intel's \textquote{MultiProcessor Specification} defines a \textquote{Universal Startup Algorithm} for multiprocessor systems~\autocite[sec.~B.4]{mpspec}, which can be used to boot SMP systems with either discrete APIC, xApic or x2Apic, as it issues both, INIT IPI and SIPI\@.
|
||||||
systems~\cite[sec.~B.4]{mpspec}, which can be used to boot SMP systems with either discrete APIC,
|
|
||||||
xApic or x2Apic, as it issues both, INIT IPI and SIPI\footnote{Technically, it always issues the
|
|
||||||
INIT IPI, and the SIPI only for xApic or x2Apic, but since the SIPI is ignored by discrete APICs,
|
|
||||||
it can be sent either way. This ``INIT-SIPI-SIPI'' sequence is also stated in the IA-32
|
|
||||||
manual~\cite[sec.~3.9.4]{ia32}.}.
|
|
||||||
|
|
||||||
This algorithm has some prerequisites: It is required to copy the AP boot routine (detailed in
|
This algorithm has some prerequisites: It is required to copy the AP boot routine (detailed in \autoref{subsec:apboot}) to lower memory, where the APs will start their execution.
|
||||||
\autoref{subsec:apboot}) to lower memory, where the APs will start their execution. Also, the APs
|
Also, the APs need allocated stack memory to call the entry function, and in case of a discrete APIC that uses the INIT IPI, the system needs to be configured for a warm-reset (by writing \code{0xAH} to the CMOS shutdown status byte, located at \code{0xF}~\autocite[sec.~B.4]{mpspec}), because the INIT IPI does not support supplying the address where AP execution should begin, unlike the SIPI\@.
|
||||||
need allocated stack memory to call the entry function, and in case of a discrete APIC that uses
|
The warm-reset vector (a \SI{32}{\bit} field, located at physical address \code{40:67}~\autocite[sec.~B.4]{mpspec}) needs to be set to the physical address the AP startup routine was copied to.
|
||||||
the INIT IPI, the system needs to be configured for a warm-reset (by writing \code{0xAH} to the
|
Additionally, the entire AP startup procedure has to be performed with all sources of interrupts disabled, which offers a small challenge, since some timings need to be taken into account\footnote{
|
||||||
CMOS shutdown status byte, located at \code{0xF}~\cite[sec.~B.4]{mpspec}), because the INIT IPI
|
This implementation uses the PIT's mode 0 on channel 0 for timekeeping, see \autoref{subsec:apxapictimer}.}.
|
||||||
does not support supplying the address where AP execution should begin, unlike the SIPI. The
|
|
||||||
warm-reset vector (a 32-bit field, located at physical address
|
|
||||||
\code{40:67}~\cite[sec.~B.4]{mpspec}) needs to be set to the physical address the AP startup
|
|
||||||
routine was copied to. Additionally, the entire AP startup procedure has to be performed with all
|
|
||||||
sources of interrupts disabled, which offers a small challenge, since some timings need to be taken
|
|
||||||
into account\footnote{This implementation uses the PIT's mode 0 on channel 0 for timekeeping.}.
|
|
||||||
|
|
||||||
The usage of delays in the algorithm is quite specific, but the specification provides no further
|
The usage of delays in the algorithm is quite specific, but the specification provides no further information on the importance of these timings or required precision.
|
||||||
information on the importance of these timings or required precision. The algorithm allowed for
|
The algorithm allowed for successful startup of additional APs when tested in QEMU (with and without KVM) and on certain real hardware, although for different processors or emulators (like Bochs), different timings might be required~\autocite[lapic.c]{xv6}.
|
||||||
successful startup of additional APs when tested in QEMU (with and without KVM) and on certain real
|
|
||||||
hardware, although for different processors or emulators (like Bochs), different timings might be
|
|
||||||
required~\cite[lapic.c]{xv6}.
|
|
||||||
|
|
||||||
After preparation, the universal startup algorithm is now performed as follows, for each AP
|
After preparation, the universal startup algorithm is now performed as follows, for each AP sequentially (see \autoref{subsec:apxmpusa} for an example implementation and \autoref{fig:smpenable}):
|
||||||
sequentially (see \autoref{sec:apxmpusa} for an example implementation):
|
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Assert and de-assert the level-triggered INIT IPI\@.
|
\item Assert and de-assert the level-triggered INIT IPI\@.
|
||||||
\item Delay for 10 milliseconds.
|
\item Delay for \SI{10}{\milli\second}.
|
||||||
\item Send the SIPI\@.
|
\item Send the SIPI\@.
|
||||||
\item Delay for 200 microseconds.
|
\item Delay for \SI{200}{\micro\second}.
|
||||||
\item Send the SIPI again.
|
\item Send the SIPI again.
|
||||||
\item Delay for 200 microseconds again.
|
\item Delay for \SI{200}{\micro\second} again.
|
||||||
\item Wait until the AP has signaled boot completion, then continue to the next.
|
\item Wait until the AP has signaled boot completion, then continue to the next.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
If the system uses a discrete APIC, the APs will reach the boot routine by starting execution at
|
If the system uses a discrete APIC, the APs will reach the boot routine by starting execution at the location specified in the warm-reset vector, if the system uses the xApic or x2Apic architecture, the APs will reach the boot routine because its location was specified in the SIPI\@.
|
||||||
the location specified in the warm-reset vector, if the system uses the xApic or x2Apic
|
|
||||||
architecture, the APs will reach the boot routine because its location was specified in the SIPI\@.
|
|
||||||
|
|
||||||
Signaling boot completion from the APs entry function can be done by using a global bitmap
|
Signaling boot completion from the APs entry function can be done by using a global bitmap variable, where the \(n\)-th bit indicates the running state of the \(n\)-th processor.
|
||||||
variable, where the \(n\)-th bit indicates the running state of the \(n\)-th processor. This
|
This variable does not have to be synchronized across APs, because the startup is performed sequentially.
|
||||||
variable does not have to be synchronized across APs, because the startup is performed
|
|
||||||
sequentially.
|
|
||||||
|
|
||||||
\subsection{Application Processor Boot Routine}
|
\subsection{Application Processor Boot Routine}
|
||||||
\label{subsec:apboot}
|
\label{subsec:apboot}
|
||||||
|
|
||||||
After executing the ``INIT-SIPI-SIPI'' sequence, the targeted AP will start executing its boot
|
After executing the \textquote{INIT-SIPI-SIPI} sequence, the targeted AP will start executing its boot routine in real mode.
|
||||||
routine in real mode. The general steps required are similar to those required when booting a
|
The general steps required are similar to those required when booting a single-core system, but since the BSP in SMP systems is already fully operational at this point, much can be recycled.
|
||||||
single-core system, but since the BSP in SMP systems is already fully operational at this point,
|
The AP boot routine this implementation uses can be roughly described as follows (see \autoref{subsec:apxapboot} for an example implementation):
|
||||||
much can be recycled. The AP boot routine this implementation uses can be roughly described as
|
|
||||||
follows (see \autoref{sec:apxapboot} for an example implementation):
|
|
||||||
|
|
||||||
\begin{enumerate}
|
\begin{enumerate}
|
||||||
\item Load a temporary \textbf{\gls{gdt}}, used for switching to protected mode.
|
\item Load a temporary \textbf{\gls{gdt}}, used for switching to protected mode.
|
||||||
\item Enable protected mode by writing \code{cr0}.
|
\item Enable protected mode by writing \code{cr0}.
|
||||||
\item Far jump to switch to protected mode and reload the code-segment register, set up the other
|
\item Far jump to switch to protected mode and reload the code-segment register, set up the other segments manually.
|
||||||
segments manually.
|
\item Load the \code{cr3}, \code{cr0} and \code{cr4} values used by the BSP to enable paging (in that order).
|
||||||
\item Load the \code{cr3}, \code{cr0} and \code{cr4} values used by the BSP to enable paging (in that
|
|
||||||
order).
|
|
||||||
\item Load the IDT used by the BSP\@.
|
\item Load the IDT used by the BSP\@.
|
||||||
\item Determine the AP's APIC ID by using CPUID\@.
|
\item Determine the AP's APIC ID by using CPUID\@.
|
||||||
\item Load the GDT and \textbf{\gls{tss}} prepared for this AP\@.
|
\item Load the GDT and \textbf{\gls{tss}} prepared for this AP\@.
|
||||||
@ -612,34 +473,25 @@ follows (see \autoref{sec:apxapboot} for an example implementation):
|
|||||||
\item Call the (C++) AP entry function.
|
\item Call the (C++) AP entry function.
|
||||||
\end{enumerate}
|
\end{enumerate}
|
||||||
|
|
||||||
The APIC ID is used to determine which GDT and stack were prepared for a certain AP\@. It is
|
The APIC ID is used to determine which GDT and stack were prepared for a certain AP\@.
|
||||||
necessary for each AP to have its own GDT, because each processor needs its own TSS for context
|
It is necessary for each AP to have its own GDT, because each processor needs its own TSS for hardware context switching, e.g.\ when interrupt-based system calls are used on all CPUs.
|
||||||
switching, for example when interrupt-based system calls are used on all CPUs.
|
|
||||||
|
|
||||||
Because it is relocated into lower physical memory (in this implementation to \code{0x8000}), this
|
Because it is relocated into lower physical memory, this code has to be position independent.
|
||||||
code has to be position independent. For this reason, absolute physical addresses have to be used
|
For this reason, absolute physical addresses have to be used when jumping, loading the IDTR and GDTR, or referencing variables.
|
||||||
when jumping, loading the IDTR and GDTR, or referencing variables. Also, any variables required
|
Also, any variables required during boot have to be available after relocation, this can be achieved by locating them inside the \textquote{TEXT} section of the routine, so they stay with the rest of the instructions when copying.
|
||||||
during boot have to be available after relocation, this can be achieved by locating them inside the
|
These variables have to be initialized during runtime, before the routine is copied (see \autoref{subsec:apxpreparesmp} for an example implementation).
|
||||||
``TEXT'' section of the routine, so they stay with the rest of the instructions when copying. These
|
|
||||||
variables have to be initialized during runtime, before the routine is copied (see
|
|
||||||
\autoref{sec:apxpreparesmp} for an example implementation).
|
|
||||||
|
|
||||||
\subsection{Application Processor Post-Boot Routine}
|
\subsection{Application Processor Post-Boot Routine}
|
||||||
\label{subsec:apsystementry}
|
\label{subsec:apsystementry}
|
||||||
|
|
||||||
In the entry function, called at the end of the boot routine, the AP signals boot completion as
|
In the entry function, called at the end of the boot routine, the AP signals boot completion as described in \autoref{subsec:apstartup} and initializes its local APIC by repeating the necessary steps from \autoref{subsec:lapiclvtinit}, \autoref{subsec:lapicsoftenable}, \autoref{subsec:lapictimer} and \autoref{subsec:lapicerror}\footnote{
|
||||||
described in \autoref{subsec:apstartup} and initializes its local APIC by repeating the necessary
|
MMIO memory does not have to be allocated again, as all local APICs use the same memory region in this implementation.
|
||||||
steps from \autoref{subsec:lapiclvtinit}, \autoref{subsec:lapicsoftenable},
|
Also, the initial value for the APIC timer's counter can be reused, if already calibrated.}.
|
||||||
\autoref{subsec:lapictimer} and \autoref{subsec:lapicerror}\footnote{MMIO memory does not have to
|
|
||||||
be allocated again, as all local APICs use the same memory region in this implementation. Also, the
|
|
||||||
initial value for the APIC timer's counter can be reused, if already calibrated.}.
|
|
||||||
|
|
||||||
Because multiple local APICs are present and active in the system now, the possibility arises that
|
Because multiple local APICs are present and active in the system now, the possibility arises that a certain local APIC receives multiple messages from different local APICs at a similar time.
|
||||||
a certain local APIC receives multiple messages from different local APICs at a similar time. To
|
To decide the order of handling these messages, an arbitration mechanism based on the local APIC's ID is used~\autocite[sec.~3.11.7]{ia32}.
|
||||||
decide the order of handling these messages, an arbitration mechanism based on the local APIC's ID
|
To make sure the arbitration priority matches the local APIC's ID, the ARPs can be synchronized by issuing an INIT-level-deassert IPI\footnote{
|
||||||
is used~\cite[sec.~3.11.7]{ia32}. To make sure the arbitration priority matches the local APIC's
|
This is not supported on Pentium 4 and Xeon processors.}
|
||||||
ID, the ARPs can be synchronized by issuing an INIT-level-deassert IPI\footnote{This is not
|
\ (see \autoref{subsec:apxappostboot} for an example implementation).
|
||||||
supported on Pentium 4 and Xeon processors.} (see \autoref{sec:apxappostboot} for an example
|
|
||||||
implementation).
|
|
||||||
|
|
||||||
\clearpage
|
\cleardoublepage
|
187
chap/introduction.aux
Normal file
187
chap/introduction.aux
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:introduction}{{1}{1}{Introduction}{chapter.1}{}}
|
||||||
|
\@setckpt{chap/introduction}{
|
||||||
|
\setcounter{page}{3}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{0}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{0}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{1}
|
||||||
|
\setcounter{section}{0}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{0}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{0}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{0}
|
||||||
|
\setcounter{FancyVerbLine}{0}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{10}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{0}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{0}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{0}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{0}
|
||||||
|
\setcounter{Item}{0}
|
||||||
|
\setcounter{Hfootnote}{0}
|
||||||
|
\setcounter{bookmark@seq@number}{1}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{0}
|
||||||
|
\setcounter{@ppsavesec}{0}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{1}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{1}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -1,26 +1,20 @@
|
|||||||
\chapter{Introduction}
|
\chapter{Introduction}
|
||||||
\label{ch:introduction}
|
\label{ch:introduction}
|
||||||
|
|
||||||
Computer systems are very useful, because they are able to interact with the ``outside world'', for
|
\clearpage
|
||||||
instance by reading values from sensors, controlling external appliances or interacting with a user
|
|
||||||
through human interface devices. In each of these scenarios, the system's CPU has to react to
|
|
||||||
``external changes'', like a key press or sensor reading. An efficient hardware solution to this
|
|
||||||
problem are ``interrupts''.
|
|
||||||
|
|
||||||
In this thesis, support for the ``APIC'', a modern and widely used interrupt controller
|
Computer systems need to interact with their surroundings, for instance by reading values from sensors, controlling external appliances or interacting with a user through human interface devices.
|
||||||
architecture, introduced by Intel for the Pentium 4 processor, will be implemented into hhuOS, ``A
|
In each of these scenarios, the system's CPU has to react to \textquote{external changes}, like a key press or sensor reading.
|
||||||
small operating system for learning purposes''~\cite{hhuos}. This support will cover a complete
|
An efficient hardware solution to this problem are \textquote{interrupts}.
|
||||||
replacement of the older ``PIC'' interrupt controller, introduction of an alternative timer - a
|
|
||||||
part of the APIC architecture - for scheduling, and utilizing the APIC to boot multiprocessor
|
|
||||||
systems.
|
|
||||||
|
|
||||||
The following chapter explains important background concepts, in \autoref{ch:implementation} the
|
Through the past, interrupt hardware went through different iterations: Intel introduced the \textquote{Programmable Interrupt Controller} for the \textquote{8085} processor in 1976, with a revised version for the \textquote{8086} processor.
|
||||||
required steps to use the APIC and their implementation are explained in general,
|
With modern standards like multicore processors, peripheral extendability, greater flexibility or higher performance, the Programmable Interrupt Controller could no longer meet its requirements.
|
||||||
\autoref{ch:verification} deals with the verification process of the developed software on emulated
|
|
||||||
and real hardware, and \autoref{ch:conclusion} draws conclusions regarding the previous
|
|
||||||
implementation and future improvements.
|
|
||||||
|
|
||||||
Specific details on the code created during this thesis are given in \autoref{ch:listings},
|
In this thesis, support for the \textquote{Advanced Programmable Interrupt Controller}, a modern, multiprocessing capable and widely used interrupt controller architecture, introduced by Intel for the x86 \textquote{i486} processor, will be implemented into hhuOS, \textquote{A small operating system for learning purposes}~\autocite{hhuos}.
|
||||||
separated from the main body.
|
This support will cover a complete replacement of the older Programmable Interrupt Controller, introduction of an alternative timer -- a part of the APIC architecture -- for scheduling, and utilizing the APIC to boot multiprocessor systems.
|
||||||
|
|
||||||
\clearpage
|
The following chapter explains important background concepts, in \autoref{ch:implementation} the required steps to use the APIC and their implementation are explained in general, \autoref{ch:verification} deals with the verification process of the developed software on emulated and real hardware, and \autoref{ch:conclusion} draws conclusions regarding the previous implementation and future improvements.
|
||||||
|
|
||||||
|
Specific details on the code created during this thesis are given in \autoref{ch:listings}, separated from the main body.
|
||||||
|
|
||||||
|
\cleardoublepage
|
284
chap/listings.aux
Normal file
284
chap/listings.aux
Normal file
@ -0,0 +1,284 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {A}Listings}{43}{appendix.1.A}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:listings}{{A}{43}{Listings}{appendix.1.A}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {A.1}Integration into HhuOS}{44}{section.1.A.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:apxhhuos}{{A.1}{44}{Integration into HhuOS}{section.1.A.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.1}Interrupt Handling in HhuOS}{44}{subsection.1.A.1.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxcurrenthhuos}{{A.1.1}{44}{Interrupt Handling in HhuOS}{subsection.1.A.1.1}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.1\hskip 1em\relax \texttt {The InterruptHandler Interface (InterruptHandler.h)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.1}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.2\hskip 1em\relax \texttt {Assigning an Interrupt Handler (InterruptDispatcher.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.2}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.3\hskip 1em\relax \texttt {Triggering an Interrupt Handler (InterruptDispatcher.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.3}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.4\hskip 1em\relax \texttt {The PIT Interrupt Handler (Pit.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.4}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.2}Necessary Modifications to HhuOS}{45}{subsection.1.A.1.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:hhuosintegration}{{A.1.2}{45}{Necessary Modifications to HhuOS}{subsection.1.A.1.2}{}}
|
||||||
|
\newlabel{lst:interruptserviceafter}{{A.5}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.5}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.5\hskip 1em\relax \texttt {Using the Correct Interrupt Controller (InterruptService.cpp)}}{45}{tcb@cnt@codeblock.1.A.5}\protected@file@percent }
|
||||||
|
\newlabel{lst:pithandlerafter}{{A.6}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.6}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.6\hskip 1em\relax \texttt {Disabling PIT Preemption (Pit.cpp)}}{45}{tcb@cnt@codeblock.1.A.6}\protected@file@percent }
|
||||||
|
\newlabel{lst:systemafter}{{A.7}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.7}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.7\hskip 1em\relax \texttt {Enabling the APIC System (System.cpp)}}{45}{tcb@cnt@codeblock.1.A.7}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.3}Public Interface of the APIC Subsystem}{46}{subsection.1.A.1.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:hhuospublicinterface}{{A.1.3}{46}{Public Interface of the APIC Subsystem}{subsection.1.A.1.3}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.8\hskip 1em\relax \texttt {The APIC Public Interface (Apic.h)}}{46}{tcb@cnt@codeblock.1.A.8}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {A.2}Local APIC}{47}{section.1.A.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:apxlocalapic}{{A.2}{47}{Local APIC}{section.1.A.2}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.1}Accessing Local APIC Registers in xApic Mode}{47}{subsection.1.A.2.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxxapicregacc}{{A.2.1}{47}{Accessing Local APIC Registers in xApic Mode}{subsection.1.A.2.1}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.9\hskip 1em\relax \texttt {Allocating the Local APIC's MMIO Region (LocalApic.cpp)}}{47}{tcb@cnt@codeblock.1.A.9}\protected@file@percent }
|
||||||
|
\newlabel{lst:lapicmmiowrite}{{A.10}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.10}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.10\hskip 1em\relax \texttt {Writing a Local APIC MMIO Register (LocalApic.cpp)}}{47}{tcb@cnt@codeblock.1.A.10}\protected@file@percent }
|
||||||
|
\newlabel{lst:msrentry}{{A.11}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.11}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.11\hskip 1em\relax \texttt {The MSREntry Structure (LocalApicRegisters.h)}}{47}{tcb@cnt@codeblock.1.A.11}\protected@file@percent }
|
||||||
|
\newlabel{lst:svrentry}{{A.12}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.12}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.12\hskip 1em\relax \texttt {The SVREntry Structure (LocalApicRegisters.h)}}{47}{tcb@cnt@codeblock.1.A.12}\protected@file@percent }
|
||||||
|
\newlabel{lst:lvtentry}{{A.13}{48}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.13}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.13\hskip 1em\relax \texttt {The LVTEntry Structure (LocalApicRegisters.h)}}{48}{tcb@cnt@codeblock.1.A.13}\protected@file@percent }
|
||||||
|
\newlabel{lst:icrentry}{{A.14}{48}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.14}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.14\hskip 1em\relax \texttt {The ICREntry Structure (LocalApicRegisters.h)}}{48}{tcb@cnt@codeblock.1.A.14}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.15\hskip 1em\relax \texttt {Writing the IA32\textunderscore {}APIC\textunderscore {}BASE MSR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.15}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.16\hskip 1em\relax \texttt {Writing the SVR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.16}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.17\hskip 1em\relax \texttt {Writing the LVT (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.17}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.18\hskip 1em\relax \texttt {Writing the ICR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.18}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.2}Disabling PIC Mode}{49}{subsection.1.A.2.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxdisablepic}{{A.2.2}{49}{Disabling PIC Mode}{subsection.1.A.2.2}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.19\hskip 1em\relax \texttt {Disabling PIC Mode (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.19}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.3}Initializing the LVT}{49}{subsection.1.A.2.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxlvtinit}{{A.2.3}{49}{Initializing the LVT}{subsection.1.A.2.3}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.20\hskip 1em\relax \texttt {Configuring the LINT0 Local Interrupt (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.20}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.4}Handling the Spurious Interrupt}{49}{subsection.1.A.2.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxsvr}{{A.2.4}{49}{Handling the Spurious Interrupt}{subsection.1.A.2.4}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.21\hskip 1em\relax \texttt {Setting the Spurious Interrupt Vector (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.21}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.22\hskip 1em\relax \texttt {Checking for Spurious Interrupts (InterruptDispatcher.cpp)}}{49}{tcb@cnt@codeblock.1.A.22}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.23\hskip 1em\relax \texttt {Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}}{50}{tcb@cnt@codeblock.1.A.23}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.5}Using the APIC Timer}{50}{subsection.1.A.2.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxapictimer}{{A.2.5}{50}{Using the APIC Timer}{subsection.1.A.2.5}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.24\hskip 1em\relax \texttt {Calibrating the APIC Timer (ApicTimer.cpp)}}{50}{tcb@cnt@codeblock.1.A.24}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.25\hskip 1em\relax \texttt {Microsecond Delay without Interrupts (Pit.cpp)}}{50}{tcb@cnt@codeblock.1.A.25}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.26\hskip 1em\relax \texttt {Handling the APIC Timer Interrupt (ApicTimer.cpp)}}{51}{tcb@cnt@codeblock.1.A.26}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.6}Handling Local APIC Errors}{51}{subsection.1.A.2.6}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxhandlingerror}{{A.2.6}{51}{Handling Local APIC Errors}{subsection.1.A.2.6}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.27\hskip 1em\relax \texttt {The Local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}}{51}{tcb@cnt@codeblock.1.A.27}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {A.3}I/O APIC}{52}{section.1.A.3}\protected@file@percent }
|
||||||
|
\newlabel{sec:apxioapic}{{A.3}{52}{I/O APIC}{section.1.A.3}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.3.1}Accessing I/O APIC Registers}{52}{subsection.1.A.3.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:iolistings}{{A.3.1}{52}{Accessing I/O APIC Registers}{subsection.1.A.3.1}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.28\hskip 1em\relax \texttt {Writing an I/O APIC MMIO Register (IoApic.h)}}{52}{tcb@cnt@codeblock.1.A.28}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.29\hskip 1em\relax \texttt {Writing an I/O APIC Indirect Register (IoApic.cpp)}}{52}{tcb@cnt@codeblock.1.A.29}\protected@file@percent }
|
||||||
|
\newlabel{lst:redtblentry}{{A.30}{52}{Accessing I/O APIC Registers}{tcb@cnt@codeblock.1.A.30}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.30\hskip 1em\relax \texttt {The REDTBLEntry Structure (IoApicRegisters.h)}}{52}{tcb@cnt@codeblock.1.A.30}\protected@file@percent }
|
||||||
|
\newlabel{lst:writeredtbl}{{A.31}{52}{Accessing I/O APIC Registers}{tcb@cnt@codeblock.1.A.31}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.31\hskip 1em\relax \texttt {Writing the REDTBL (IoApic.cpp)}}{52}{tcb@cnt@codeblock.1.A.31}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.3.2}Interrupt Overrides}{52}{subsection.1.A.3.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxirqoverrides}{{A.3.2}{52}{Interrupt Overrides}{subsection.1.A.3.2}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.32\hskip 1em\relax \texttt {The External Interrupt Override Structure (IoApic.h)}}{53}{tcb@cnt@codeblock.1.A.32}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.33\hskip 1em\relax \texttt {Initializing the REDTBL (IoApic.cpp)}}{53}{tcb@cnt@codeblock.1.A.33}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.34\hskip 1em\relax \texttt {Unmasking an IRQ (Apic.cpp)}}{53}{tcb@cnt@codeblock.1.A.34}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.35\hskip 1em\relax \texttt {Unmasking an IRQ Internally (IoApic.cpp)}}{54}{tcb@cnt@codeblock.1.A.35}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {A.4}Symmetric Multiprocessing}{55}{section.1.A.4}\protected@file@percent }
|
||||||
|
\newlabel{sec:apxsymmetric}{{A.4}{55}{Symmetric Multiprocessing}{section.1.A.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.1}Issuing Inter-Processor Interrupts}{55}{subsection.1.A.4.1}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxipis}{{A.4.1}{55}{Issuing Inter-Processor Interrupts}{subsection.1.A.4.1}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.36\hskip 1em\relax \texttt {Issuing an INIT IPI (LocalApic.cpp)}}{55}{tcb@cnt@codeblock.1.A.36}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.37\hskip 1em\relax \texttt {Issuing a SIPI (LocalApic.cpp)}}{55}{tcb@cnt@codeblock.1.A.37}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.2}Preparing Symmetric Multiprocessing Startup}{55}{subsection.1.A.4.2}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxpreparesmp}{{A.4.2}{55}{Preparing Symmetric Multiprocessing Startup}{subsection.1.A.4.2}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.38\hskip 1em\relax \texttt {Preparing the Boot Routine's Variables (ApicSmp.cpp)}}{55}{tcb@cnt@codeblock.1.A.38}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.39\hskip 1em\relax \texttt {Relocating the Boot Routine (ApicSmp.cpp)}}{56}{tcb@cnt@codeblock.1.A.39}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.3}Universal Startup Algorithm}{56}{subsection.1.A.4.3}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxmpusa}{{A.4.3}{56}{Universal Startup Algorithm}{subsection.1.A.4.3}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.40\hskip 1em\relax \texttt {The Universal Startup Algorithm (ApicSmp.cpp)}}{56}{tcb@cnt@codeblock.1.A.40}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.41\hskip 1em\relax \texttt {Signaling AP Boot Completion (smp\textunderscore {}entry.cpp)}}{56}{tcb@cnt@codeblock.1.A.41}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.4}Application Processor Boot Routine}{57}{subsection.1.A.4.4}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxapboot}{{A.4.4}{57}{Application Processor Boot Routine}{subsection.1.A.4.4}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.42\hskip 1em\relax \texttt {Preparing the Switch to Protected Mode (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.42}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.43\hskip 1em\relax \texttt {Switching from Real Mode to Protected Mode (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.43}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.44\hskip 1em\relax \texttt {Reusing Values from the BSP (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.44}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.45\hskip 1em\relax \texttt {Calling the Entry Function (smp\textunderscore {}boot.asm)}}{58}{tcb@cnt@codeblock.1.A.45}\protected@file@percent }
|
||||||
|
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.5}Application Processor Post-Boot Routine}{58}{subsection.1.A.4.5}\protected@file@percent }
|
||||||
|
\newlabel{subsec:apxappostboot}{{A.4.5}{58}{Application Processor Post-Boot Routine}{subsection.1.A.4.5}{}}
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.46\hskip 1em\relax \texttt {Initializing the Core's Local APIC (LocalApic.cpp)}}{58}{tcb@cnt@codeblock.1.A.46}\protected@file@percent }
|
||||||
|
\@writefile{listings}{\contentsline {tcolorbox}{A.47\hskip 1em\relax \texttt {Synchronizing the Arbitration IDs (LocalApic.cpp)}}{58}{tcb@cnt@codeblock.1.A.47}\protected@file@percent }
|
||||||
|
\@setckpt{chap/listings}{
|
||||||
|
\setcounter{page}{59}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{4}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{2}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{1}
|
||||||
|
\setcounter{section}{4}
|
||||||
|
\setcounter{subsection}{5}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{0}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{184}
|
||||||
|
\setcounter{FancyVerbLine}{12}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{66}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{1}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{47}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{2}
|
||||||
|
\setcounter{Item}{50}
|
||||||
|
\setcounter{Hfootnote}{45}
|
||||||
|
\setcounter{bookmark@seq@number}{72}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{1}
|
||||||
|
\setcounter{@ppsavesec}{5}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{96}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{20}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{47}
|
||||||
|
}
|
378
chap/listings.tex
Normal file
378
chap/listings.tex
Normal file
@ -0,0 +1,378 @@
|
|||||||
|
\chapter{Listings}
|
||||||
|
\label{ch:listings}
|
||||||
|
|
||||||
|
This chapter contains concrete implementation examples for concepts mentioned in \autoref{ch:implementation}, demonstrated on the example of hhuOS\@.
|
||||||
|
The code is simplified and not necessarily identical to the actual implementation, to allow for a self-contained demonstration.
|
||||||
|
Names and namespaces were adjusted especially.
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\section{Integration into HhuOS}
|
||||||
|
\label{sec:apxhhuos}
|
||||||
|
|
||||||
|
\subsection{Interrupt Handling in HhuOS}
|
||||||
|
\label{subsec:apxcurrenthhuos}
|
||||||
|
|
||||||
|
Devices that provide interrupts implement the \code{InterruptHandler} interface:
|
||||||
|
|
||||||
|
\begin{codeblock}{The InterruptHandler Interface (InterruptHandler.h)~\autocite{hhuos}}{C++}
|
||||||
|
\cppfile{code/interrupthandler_def.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
These interrupt handlers have to be registered to the appropriate interrupt vector:
|
||||||
|
|
||||||
|
\begin{codeblock}{Assigning an Interrupt Handler (InterruptDispatcher.cpp)~\autocite{hhuos}}{C++}
|
||||||
|
\cppfile{code/interruptdispatcher_assign.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Multiple interrupt handlers can be registered to the same interrupt vector.
|
||||||
|
For every interrupt that arrives at a CPU, the first-stage interrupt handler (registered in the IDT for every vector) is called, which in turn calls the device-specific handlers:
|
||||||
|
|
||||||
|
\begin{codeblock}{Triggering an Interrupt Handler (InterruptDispatcher.cpp)~\autocite{hhuos}}{C++}
|
||||||
|
\cppfile{code/interruptdispatcher_dispatch.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
The PIT interrupt handler manages the system time and the scheduler:
|
||||||
|
|
||||||
|
\begin{codeblock}{The PIT Interrupt Handler (Pit.cpp)~\autocite{hhuos}}{C++}
|
||||||
|
\cppfile{code/pit_trigger.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\subsection{Necessary Modifications to HhuOS}
|
||||||
|
\label{subsec:hhuosintegration}
|
||||||
|
|
||||||
|
To integrate the APIC implementation into hhuOS, some preexisting components of its interrupt infrastructure (see \autoref{sec:apxhhuos}) have to be modified:
|
||||||
|
|
||||||
|
\begin{enumerate}
|
||||||
|
\item The \code{InterruptService} has to forward calls to the \code{Apic} class instead of the \code{Pic} class, depending on if the APIC system is enabled -- to keep the option of running the OS on hardware that does not support the APIC (see \autoref{lst:interruptserviceafter}).
|
||||||
|
\item The \code{Pit} interrupt handler may no longer trigger the scheduler preemption if the APIC timer is enabled (see \autoref{lst:pithandlerafter}).
|
||||||
|
\item The \code{System::initializeSystem} function needs to enable the APIC system if it is available (see \autoref{lst:systemafter}).
|
||||||
|
\item The existing devices using interrupts need to use the new \code{InterruptVector} and \code{InterruptRequest} enums.
|
||||||
|
\end{enumerate}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:interruptserviceafter]{Using the Correct Interrupt Controller (InterruptService.cpp)}{C++}
|
||||||
|
\cppfile{code/interruptservice_after.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:pithandlerafter]{Disabling PIT Preemption (Pit.cpp)}{C++}
|
||||||
|
\cppfile{code/pit_after.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:systemafter]{Enabling the APIC System (System.cpp)}{C++}
|
||||||
|
\cppfile{code/system_after.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Public Interface of the APIC Subsystem}
|
||||||
|
\label{subsec:hhuospublicinterface}
|
||||||
|
|
||||||
|
To interact with the APIC subsystem from the \textquote{outside}, the \code{Apic} class is used, which exposes the necessary functionality:
|
||||||
|
|
||||||
|
\begin{codeblock}{The APIC Public Interface (Apic.h)}{C++}
|
||||||
|
\cppfile{code/apic_def.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Enabling the APIC subsystem is done by the \code{enable} function (see \autoref{fig:apicenable}).
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\section{Local APIC}
|
||||||
|
\label{sec:apxlocalapic}
|
||||||
|
|
||||||
|
\subsection{Accessing Local APIC Registers in xApic Mode}
|
||||||
|
\label{subsec:apxxapicregacc}
|
||||||
|
|
||||||
|
The xApic register access requires a single page of strong uncachable memory, but since this requires setting attributes in the \textquote{Page Attribute Table}\footnote{
|
||||||
|
See \url{https://docs.kernel.org/x86/pat.html} (visited on 12/02/2023).},
|
||||||
|
\ this implementation only uses hhuOS' \code{mapIO} function, which maps a physical address to the kernel heap, with hhuOS' \textquote{CACHE\textunderscore{}DISABLE} flag set in the kernel page table:
|
||||||
|
|
||||||
|
\begin{codeblock}{Allocating the Local APIC's MMIO Region (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_mmio_alloc.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
A register can now be written as follows:
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:lapicmmiowrite]{Writing a Local APIC MMIO Register (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_mmio_write.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
To reduce the usage of manual bit-shifting and -masking, this implementation provides structures for some commonly used registers, that implement conversion operators to the register format:
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:msrentry]{The MSREntry Structure (LocalApicRegisters.h)}{C++}
|
||||||
|
\cppfile{code/lapic_msr_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:svrentry]{The SVREntry Structure (LocalApicRegisters.h)}{C++}
|
||||||
|
\cppfile{code/lapic_svr_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:lvtentry]{The LVTEntry Structure (LocalApicRegisters.h)}{C++}
|
||||||
|
\cppfile{code/lapic_lvt_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:icrentry]{The ICREntry Structure (LocalApicRegisters.h)}{C++}
|
||||||
|
\cppfile{code/lapic_icr_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
These can be used in combination with some convenience functions:
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_write_msr.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing the SVR (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_write_svr.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing the LVT (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_write_lvt.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing the ICR (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_write_icr.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Disabling PIC Mode}
|
||||||
|
\label{subsec:apxdisablepic}
|
||||||
|
|
||||||
|
Setting the IMCR\footnote{
|
||||||
|
Writing the IMCR is detailed in the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.2.1]{mpspec}.}
|
||||||
|
\ using hhuOS' \code{IoPort} class:
|
||||||
|
|
||||||
|
\begin{codeblock}{Disabling PIC Mode (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_imcr.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Initializing the LVT}
|
||||||
|
\label{subsec:apxlvtinit}
|
||||||
|
|
||||||
|
The interrupt vectors are set as defined by the \code{InterruptVector} enum.
|
||||||
|
This implementation configures the LVT by using the \code{LVTEntry} struct (see \autoref{lst:lvtentry}):
|
||||||
|
|
||||||
|
\begin{codeblock}{Configuring the LINT0 Local Interrupt (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_lvt_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
This process is repeated for each local interrupt.
|
||||||
|
|
||||||
|
\subsection{Handling the Spurious Interrupt}
|
||||||
|
\label{subsec:apxsvr}
|
||||||
|
|
||||||
|
This implementation sets the SVR by using the \code{SVREntry} struct (see \autoref{lst:svrentry}):
|
||||||
|
|
||||||
|
\begin{codeblock}{Setting the Spurious Interrupt Vector (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_svr_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Because hhuOS uses a two-stage interrupt handling approach (described in \autoref{sec:currenthhuos}), the spurious interrupt does not receive its own interrupt handler.
|
||||||
|
Instead, it is ignored in the \code{dispatch} function, hhuOS' \textquote{first-stage} interrupt handler:
|
||||||
|
|
||||||
|
\begin{codeblock}{Checking for Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||||
|
\cppfile{code/interruptdispatcher_check_spurious.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||||
|
\cppfile{code/interruptdispatcher_ignore_spurious.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Using the APIC Timer}
|
||||||
|
\label{subsec:apxapictimer}
|
||||||
|
|
||||||
|
The timer frequency is determined by counting the ticks in one millisecond, using the PIT as calibration source:
|
||||||
|
|
||||||
|
\begin{codeblock}{Calibrating the APIC Timer (ApicTimer.cpp)}{C++}
|
||||||
|
\cppfile{code/apictimer_calibrate.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
This calibration is performed before the interrupts get enabled, so it is not possible to use hhuOS' \code{TimeService} for the delay.
|
||||||
|
Instead, the \code{PIT::earlyDelay} function is used, which configures the PIT for mode \textquote{Interrupt on Terminal Count} on channel zero and polls the channel's output status~\autocite{pit}:
|
||||||
|
|
||||||
|
\begin{codeblock}{Microsecond Delay without Interrupts (Pit.cpp)}{C++}
|
||||||
|
\cppfile{code/pit_early_delay.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Furthermore, the calibration is only performed once, even if multiple APIC timers are used.
|
||||||
|
This removes the possibility of using multiple timers with different dividers.
|
||||||
|
|
||||||
|
To handle the APIC timer interrupt on multiple cores, \(n\) \code{ApicTimer} instances are registered to the appropriate interrupt vector, where \(n\) is the number of CPUs.
|
||||||
|
Because this means, that each APIC timer interrupt on any CPU core triggers all \(n\) interrupt handlers, the handler has to determine if it belongs to the calling CPU\@.
|
||||||
|
The handler belonging to the BSP's APIC timer also triggers the scheduler preemption (instead of the PIT):
|
||||||
|
|
||||||
|
\begin{codeblock}{Handling the APIC Timer Interrupt (ApicTimer.cpp)}{C++}
|
||||||
|
\cppfile{code/apictimer_trigger.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Handling Local APIC Errors}
|
||||||
|
\label{subsec:apxhandlingerror}
|
||||||
|
|
||||||
|
The error interrupt handler obtains the ESR's contents by writing to it first:
|
||||||
|
|
||||||
|
\begin{codeblock}{The Local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}{C++}
|
||||||
|
\cppfile{code/apicerror_trigger.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Because every CPU core can only access its own local APIC's registers, a single instance of this interrupt handler can be used for each AP in the system.
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\section{I/O APIC}
|
||||||
|
\label{sec:apxioapic}
|
||||||
|
|
||||||
|
\subsection{Accessing I/O APIC Registers}
|
||||||
|
\label{subsec:iolistings}
|
||||||
|
|
||||||
|
The I/O APIC's indirect register access requires two MMIO registers, that can be written similar to the local APIC's registers:
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing an I/O APIC MMIO Register (IoApic.h)}{C++}
|
||||||
|
\cppfile{code/ioapic_write_mmio.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Using the \textquote{Index} and \textquote{Data} registers to access the I/O APIC's indirect registers:
|
||||||
|
|
||||||
|
\begin{codeblock}{Writing an I/O APIC Indirect Register (IoApic.cpp)}{C++}
|
||||||
|
\cppfile{code/ioapic_write_indirect.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
To reduce the manual bit-shifting and -masking, the same approach is used as for the local APIC\@:
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:redtblentry]{The REDTBLEntry Structure (IoApicRegisters.h)}{C++}
|
||||||
|
\cppfile{code/ioapic_redtbl_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}[label=lst:writeredtbl]{Writing the REDTBL (IoApic.cpp)}{C++}
|
||||||
|
\cppfile{code/ioapic_write_redtbl.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Interrupt Overrides}
|
||||||
|
\label{subsec:apxirqoverrides}
|
||||||
|
|
||||||
|
This implementation represents an interrupt override using the following structure:
|
||||||
|
|
||||||
|
\begin{codeblock}{The External Interrupt Override Structure (IoApic.h)}{C++}
|
||||||
|
\cppfile{code/ioapic_irqoverride.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
During initialization, the overrides are used to set the correct interrupt vectors, polarities and trigger modes for each REDTBL entry.
|
||||||
|
The \code{REDTBLEntry} struct (see \autoref{lst:redtblentry}) is used to write the REDTBL\@:
|
||||||
|
|
||||||
|
\begin{codeblock}{Initializing the REDTBL (IoApic.cpp)}{C++}
|
||||||
|
\cppfile{code/ioapic_redtbl_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
During regular operation, the overrides are used to determine the correct REDTBL entries for e.g.\ unmasking an interrupt:
|
||||||
|
|
||||||
|
\begin{codeblock}{Unmasking an IRQ (Apic.cpp)}{C++}
|
||||||
|
\cppfile{code/apic_allow.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
To convey this deviation between GSIs and PC/AT compatible IRQs very clearly, the public \code{Apic::allow} function accepts an \code{InterruptRequest} as an argument (that allows addressing the interrupt by name), while the internal \code{IoApic::allow} function only accepts a \code{GlobalSystemInterrupt} as argument:
|
||||||
|
|
||||||
|
\begin{codeblock}{Unmasking an IRQ Internally (IoApic.cpp)}{C++}
|
||||||
|
\cppfile{code/ioapic_allow.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
The internal \code{IoApic::allow} function is hidden (\code{private}) from the OS, and gets only called by the exposed \code{Apic::allow} function.
|
||||||
|
This prevents accidentally setting the wrong REDTBL entry by not taking possible interrupt overrides into account.
|
||||||
|
The same principle is applied to the other operations concerning GSIs.
|
||||||
|
|
||||||
|
\clearpage
|
||||||
|
|
||||||
|
\section{Symmetric Multiprocessing}
|
||||||
|
\label{sec:apxsymmetric}
|
||||||
|
|
||||||
|
An overview of the complete SMP startup process can be found in \autoref{fig:smpenable}.
|
||||||
|
|
||||||
|
\subsection{Issuing Inter-Processor Interrupts}
|
||||||
|
\label{subsec:apxipis}
|
||||||
|
|
||||||
|
To issue an IPI, the ICR is written by using the \code{ICREntry} struct (see \autoref{lst:icrentry}):
|
||||||
|
|
||||||
|
\begin{codeblock}{Issuing an INIT IPI (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_initipi_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\begin{codeblock}{Issuing a SIPI (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_sipi_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Preparing Symmetric Multiprocessing Startup}
|
||||||
|
\label{subsec:apxpreparesmp}
|
||||||
|
|
||||||
|
Before executing the \textquote{Universal Startup Algorithm}, the boot code has to be relocated to physical lower memory.
|
||||||
|
The memory region used for this copy has to be identity-mapped to the virtual kernel address space, so the effective addresses do not change after enabling paging in protected mode.
|
||||||
|
To keep the required variables available to the startup code, these are located in the routines \textquote{TEXT} section and initialized during runtime.
|
||||||
|
This approach was taken from SerenityOS~\autocite[APIC.cpp]{serenity}:
|
||||||
|
|
||||||
|
\begin{codeblock}{Preparing the Boot Routine's Variables (ApicSmp.cpp)}{C++}
|
||||||
|
\cppfile{code/ap_boot_variables.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Now, the initialized startup routine can be copied to \code{0x8000}:
|
||||||
|
|
||||||
|
\begin{codeblock}{Relocating the Boot Routine (ApicSmp.cpp)}{C++}
|
||||||
|
\cppfile{code/ap_boot_copy.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
The \code{boot\textunderscore{}ap} function is the entry of the startup routine, it is described further in \autoref{subsec:apxapboot}.
|
||||||
|
|
||||||
|
\subsection{Universal Startup Algorithm}
|
||||||
|
\label{subsec:apxmpusa}
|
||||||
|
|
||||||
|
The \textquote{INIT-SIPI-SIPI} sequence, or \textquote{Universal Startup Algorithm} is performed by issuing IPIs as described in \autoref{subsec:apxipis} and using the PIT as time source (see \autoref{subsec:apxapictimer}):
|
||||||
|
|
||||||
|
\begin{codeblock}{The Universal Startup Algorithm (ApicSmp.cpp)}{C++}
|
||||||
|
\cppfile{code/ap_boot_usa.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Boot completion is signaled in the AP's entry function:
|
||||||
|
|
||||||
|
\begin{codeblock}{Signaling AP Boot Completion (smp\textunderscore{}entry.cpp)}{C++}
|
||||||
|
\cppfile{code/smp_entry.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Application Processor Boot Routine}
|
||||||
|
\label{subsec:apxapboot}
|
||||||
|
|
||||||
|
Because like the BSP, every AP is initialized in real mode, it has to be switched to protected mode first:
|
||||||
|
|
||||||
|
\begin{codeblock}{Preparing the Switch to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||||
|
\nasmfile{code/ap_boot_real_prepare.asm}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Then, by enabling protected mode, setting the segment registers and far-jumping to the \SI{32}{\bit} code segment, the switch is performed:
|
||||||
|
|
||||||
|
\begin{codeblock}{Switching from Real Mode to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||||
|
\nasmfile{code/ap_boot_real.asm}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
In \SI{32}{\bit} protected mode, paging is enabled and interrupt processing is prepared by reusing the control register values and the IDT from the BSP\@:
|
||||||
|
|
||||||
|
\begin{codeblock}{Reusing Values from the BSP (smp\textunderscore{}boot.asm)}{nasm}
|
||||||
|
\nasmfile{code/ap_boot_protected_bsp.asm}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Finally, to call the AP entry function, the AP requires its own stack. If hardware context switching is to be used, the AP additionally requires its own GDT and TSS\@:
|
||||||
|
|
||||||
|
\begin{codeblock}{Calling the Entry Function (smp\textunderscore{}boot.asm)}{nasm}
|
||||||
|
\nasmfile{code/ap_boot_protected_ap.asm}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
\subsection{Application Processor Post-Boot Routine}
|
||||||
|
\label{subsec:apxappostboot}
|
||||||
|
|
||||||
|
When the AP has booted, it initializes its own APIC, including the APIC timer and error handler:
|
||||||
|
|
||||||
|
\begin{codeblock}{Initializing the Core's Local APIC (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/ap_boot_post.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Because this added another possible recipient to internal APIC messages, the arbitration IDs are synchronized by issuing an \textquote{INIT-level-deassert IPI} using the \code{ICREntry} struct (see \autoref{lst:icrentry}):
|
||||||
|
|
||||||
|
\begin{codeblock}{Synchronizing the Arbitration IDs (LocalApic.cpp)}{C++}
|
||||||
|
\cppfile{code/lapic_apr_example.cpp}
|
||||||
|
\end{codeblock}
|
||||||
|
|
||||||
|
Because hhuOS' paging is not designed for multiple processors, the booted AP remains in a busy loop and does not enable its interrupts.
|
||||||
|
|
||||||
|
\cleardoublepage
|
249
chap/tables.aux
Normal file
249
chap/tables.aux
Normal file
@ -0,0 +1,249 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {C}Tables}{63}{appendix.1.C}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:tables}{{C}{63}{Tables}{appendix.1.C}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {C.1}Local APIC Registers}{64}{section.1.C.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:localapicregisters}{{C.1}{64}{Local APIC Registers}{section.1.C.1}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.1}{\ignorespaces Local APIC Registers used in this Implementation~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.1]{ia32}.\relax }}{64}{table.caption.5}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregs}{{C.1}{64}{Local APIC Registers used in this Implementation~\autocite [sec.~3.11.4.1]{ia32}.\relax }{table.caption.5}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.2}{\ignorespaces Local APIC ID Register (xApic since Pentium 4)~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.6]{ia32}.\relax }}{64}{table.caption.6}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregsid}{{C.2}{64}{Local APIC ID Register (xApic since Pentium 4)~\autocite [sec.~3.11.4.6]{ia32}.\relax }{table.caption.6}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.3}{\ignorespaces Local APIC Version Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.8]{ia32}.\relax }}{64}{table.caption.7}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregsver}{{C.3}{64}{Local APIC Version Register~\autocite [sec.~3.11.4.8]{ia32}.\relax }{table.caption.7}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.4}{\ignorespaces Task Priority Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.8.3.1]{ia32}.\relax }}{65}{table.caption.8}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregstpr}{{C.4}{65}{Task Priority Register~\autocite [sec.~3.11.8.3.1]{ia32}.\relax }{table.caption.8}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.5}{\ignorespaces Local APIC EOI Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.8.5]{ia32}.\relax }}{65}{table.caption.9}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregseoi}{{C.5}{65}{Local APIC EOI Register~\autocite [sec.~3.11.8.5]{ia32}.\relax }{table.caption.9}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.6}{\ignorespaces Spurious Interrupt Vector Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.9]{ia32}.\relax }}{65}{table.caption.10}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregssvr}{{C.6}{65}{Spurious Interrupt Vector Register~\autocite [sec.~3.11.9]{ia32}.\relax }{table.caption.10}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.7}{\ignorespaces Error Status Register (Pentium 4)~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.3]{ia32}.\relax }}{65}{table.caption.11}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregsesr}{{C.7}{65}{Error Status Register (Pentium 4)~\autocite [sec.~3.11.5.3]{ia32}.\relax }{table.caption.11}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.8}{\ignorespaces Interrupt Command Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.6.1]{ia32}.\relax }}{66}{table.caption.12}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregsicr}{{C.8}{66}{Interrupt Command Register~\autocite [sec.~3.11.6.1]{ia32}.\relax }{table.caption.12}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.9}{\ignorespaces LVT Timer Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{66}{table.caption.13}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregslvtt}{{C.9}{66}{LVT Timer Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.13}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.10}{\ignorespaces LVT Error Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{66}{table.caption.14}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregslvterr}{{C.10}{66}{LVT Error Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.14}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.11}{\ignorespaces LVT LINT1 Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{67}{table.caption.15}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregslvtlint}{{C.11}{67}{LVT LINT1 Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.15}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.12}{\ignorespaces Timer Initial Count Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.4]{ia32}.\relax }}{67}{table.caption.16}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregstimerinit}{{C.12}{67}{Timer Initial Count Register~\autocite [sec.~3.11.5.4]{ia32}.\relax }{table.caption.16}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.13}{\ignorespaces Timer Divide Configuration Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.4]{ia32}.\relax }}{67}{table.caption.17}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregstimerdiv}{{C.13}{67}{Timer Divide Configuration Register~\autocite [sec.~3.11.5.4]{ia32}.\relax }{table.caption.17}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.14}{\ignorespaces IA32\textunderscore {} APIC\textunderscore {}BASE MSR~\blx@tocontentsinit {0}\autocite [sec.~3.11.12.1]{ia32}. \relax }}{67}{table.caption.18}\protected@file@percent }
|
||||||
|
\newlabel{tab:lapicregsmsr}{{C.14}{67}{IA32\textunderscore {} APIC\textunderscore {}BASE MSR~\autocite [sec.~3.11.12.1]{ia32}. \relax }{table.caption.18}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {C.2}I/O APIC Registers}{68}{section.1.C.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:ioapicregs}{{C.2}{68}{I/O APIC Registers}{section.1.C.2}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.15}{\ignorespaces I/O APIC Registers used in this Implementation~\blx@tocontentsinit {0}\autocite [sec.~9.5]{ich5}.\relax }}{68}{table.caption.19}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregs}{{C.15}{68}{I/O APIC Registers used in this Implementation~\autocite [sec.~9.5]{ich5}.\relax }{table.caption.19}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.16}{\ignorespaces I/O APIC Index Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.2]{ich5}.\relax }}{68}{table.caption.20}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregsidx}{{C.16}{68}{I/O APIC Index Register~\autocite [sec.~9.5.2]{ich5}.\relax }{table.caption.20}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.17}{\ignorespaces I/O APIC Data Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.3]{ich5}.\relax }}{68}{table.caption.21}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregsdat}{{C.17}{68}{I/O APIC Data Register~\autocite [sec.~9.5.3]{ich5}.\relax }{table.caption.21}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.18}{\ignorespaces I/O APIC ID Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.6]{ich5}.\relax }}{68}{table.caption.22}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregsid}{{C.18}{68}{I/O APIC ID Register~\autocite [sec.~9.5.6]{ich5}.\relax }{table.caption.22}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.19}{\ignorespaces I/O APIC Version Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.7]{ich5}.\relax }}{69}{table.caption.23}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregsver}{{C.19}{69}{I/O APIC Version Register~\autocite [sec.~9.5.7]{ich5}.\relax }{table.caption.23}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.20}{\ignorespaces I/O APIC REDTBL Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.8]{ich5}.\relax }}{69}{table.caption.24}\protected@file@percent }
|
||||||
|
\newlabel{tab:ioapicregsredtbl}{{C.20}{69}{I/O APIC REDTBL Register~\autocite [sec.~9.5.8]{ich5}.\relax }{table.caption.24}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {C.3}System Description Tables}{70}{section.1.C.3}\protected@file@percent }
|
||||||
|
\newlabel{sec:sdts}{{C.3}{70}{System Description Tables}{section.1.C.3}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.21}{\ignorespaces ACPI MADT~\blx@tocontentsinit {0}\autocite [sec.~5.2.8]{acpi1}.\relax }}{70}{table.caption.25}\protected@file@percent }
|
||||||
|
\newlabel{tab:madt}{{C.21}{70}{ACPI MADT~\autocite [sec.~5.2.8]{acpi1}.\relax }{table.caption.25}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.22}{\ignorespaces MADT Processor Local APIC Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.1]{acpi1}.\relax }}{70}{table.caption.26}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtlapic}{{C.22}{70}{MADT Processor Local APIC Structure~\autocite [sec.~5.2.8.1]{acpi1}.\relax }{table.caption.26}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.23}{\ignorespaces Local APIC Flags~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.1]{acpi1}.\relax }}{70}{table.caption.27}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtlapicflags}{{C.23}{70}{Local APIC Flags~\autocite [sec.~5.2.8.1]{acpi1}.\relax }{table.caption.27}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.24}{\ignorespaces MADT I/O APIC Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.2]{acpi1}.\relax }}{70}{table.caption.28}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtioapic}{{C.24}{70}{MADT I/O APIC Structure~\autocite [sec.~5.2.8.2]{acpi1}.\relax }{table.caption.28}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.25}{\ignorespaces MADT Interrupt Source Override Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }}{71}{table.caption.29}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtirqoverride}{{C.25}{71}{MADT Interrupt Source Override Structure~\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }{table.caption.29}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.26}{\ignorespaces INTI Flags~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }}{71}{table.caption.30}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtintiflags}{{C.26}{71}{INTI Flags~\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }{table.caption.30}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.27}{\ignorespaces MADT I/O APIC NMI Source~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.2]{acpi1}.\relax }}{71}{table.caption.31}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtionmi}{{C.27}{71}{MADT I/O APIC NMI Source~\autocite [sec.~5.2.8.3.2]{acpi1}.\relax }{table.caption.31}{}}
|
||||||
|
\@writefile{lot}{\contentsline {table}{\numberline {C.28}{\ignorespaces MADT Local APIC NMI Source~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.3]{acpi1}.\relax }}{71}{table.caption.32}\protected@file@percent }
|
||||||
|
\newlabel{tab:madtlnmi}{{C.28}{71}{MADT Local APIC NMI Source~\autocite [sec.~5.2.8.3.3]{acpi1}.\relax }{table.caption.32}{}}
|
||||||
|
\@setckpt{chap/tables}{
|
||||||
|
\setcounter{page}{73}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{4}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{0}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{3}
|
||||||
|
\setcounter{section}{3}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{0}
|
||||||
|
\setcounter{table}{28}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{184}
|
||||||
|
\setcounter{FancyVerbLine}{12}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{80}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{1}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{47}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{2}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{1}
|
||||||
|
\setcounter{Item}{50}
|
||||||
|
\setcounter{Hfootnote}{45}
|
||||||
|
\setcounter{bookmark@seq@number}{77}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{1}
|
||||||
|
\setcounter{@ppsavesec}{5}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{152}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{4}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -5,7 +5,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\renewcommand{\arraystretch}{1.2}
|
\renewcommand{\arraystretch}{1.2} % Slightly larger row spacing
|
||||||
|
|
||||||
\section{Local APIC Registers}
|
\section{Local APIC Registers}
|
||||||
\label{sec:localapicregisters}
|
\label{sec:localapicregisters}
|
||||||
@ -29,7 +29,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
Timer Initial Count Register & 0x380 \\ \hline
|
Timer Initial Count Register & 0x380 \\ \hline
|
||||||
Timer Divide Configuration Register & 0x3E0 \\ \hline
|
Timer Divide Configuration Register & 0x3E0 \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Local APIC Registers used in this Implementation~\cite[sec.~3.11.4.1]{ia32}.}
|
\caption{Local APIC Registers used in this Implementation~\autocite[sec.~3.11.4.1]{ia32}.}
|
||||||
\label{tab:lapicregs}
|
\label{tab:lapicregs}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -41,7 +41,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
0:23 & Reserved \\ \hline
|
0:23 & Reserved \\ \hline
|
||||||
24:31 & Local APIC ID \\ \hline
|
24:31 & Local APIC ID \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Local APIC ID Register (xApic since Pentium 4)~\cite[sec.~3.11.4.6]{ia32}.}
|
\caption{Local APIC ID Register (xApic since Pentium 4)~\autocite[sec.~3.11.4.6]{ia32}.}
|
||||||
\label{tab:lapicregsid}
|
\label{tab:lapicregsid}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
24 & EOI Broadcast Suppression Support \\ \hline
|
24 & EOI Broadcast Suppression Support \\ \hline
|
||||||
25:31 & Reserved \\ \hline
|
25:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Local APIC Version Register~\cite[sec.~3.11.4.8]{ia32}.}
|
\caption{Local APIC Version Register~\autocite[sec.~3.11.4.8]{ia32}.}
|
||||||
\label{tab:lapicregsver}
|
\label{tab:lapicregsver}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
4:7 & Task-Priority Class \\ \hline
|
4:7 & Task-Priority Class \\ \hline
|
||||||
8:31 & Reserved \\ \hline
|
8:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Task Priority Register~\cite[sec.~3.11.8.3.1]{ia32}.}
|
\caption{Task Priority Register~\autocite[sec.~3.11.8.3.1]{ia32}.}
|
||||||
\label{tab:lapicregstpr}
|
\label{tab:lapicregstpr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -80,7 +80,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:31 & Send EOI Signal \\ \hline
|
0:31 & Send EOI Signal \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Local APIC EOI Register~\cite[sec.~3.11.8.5]{ia32}.}
|
\caption{Local APIC EOI Register~\autocite[sec.~3.11.8.5]{ia32}.}
|
||||||
\label{tab:lapicregseoi}
|
\label{tab:lapicregseoi}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -96,7 +96,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
12 & EOI Broadcast Suppression \\ \hline
|
12 & EOI Broadcast Suppression \\ \hline
|
||||||
13:31 & Reserved \\ \hline
|
13:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Spurious Interrupt Vector Register~\cite[sec.~3.11.9]{ia32}.}
|
\caption{Spurious Interrupt Vector Register~\autocite[sec.~3.11.9]{ia32}.}
|
||||||
\label{tab:lapicregssvr}
|
\label{tab:lapicregssvr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
7 & Illegal Register Access \\ \hline
|
7 & Illegal Register Access \\ \hline
|
||||||
8:31 & Reserved \\ \hline
|
8:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Error Status Register (Pentium 4)~\cite[sec.~3.11.5.3]{ia32}.}
|
\caption{Error Status Register (Pentium 4)~\autocite[sec.~3.11.5.3]{ia32}.}
|
||||||
\label{tab:lapicregsesr}
|
\label{tab:lapicregsesr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -132,7 +132,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
20:55 & Reserved \\ \hline
|
20:55 & Reserved \\ \hline
|
||||||
56:63 & Destination Field \\ \hline
|
56:63 & Destination Field \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
\caption{Interrupt Command Register~\autocite[sec.~3.11.6.1]{ia32}.}
|
||||||
\label{tab:lapicregsicr}
|
\label{tab:lapicregsicr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -149,7 +149,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
17:18 & Timer Mode \\ \hline
|
17:18 & Timer Mode \\ \hline
|
||||||
19:31 & Reserved \\ \hline
|
19:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{LVT Timer Register~\cite[sec.~3.11.5.1]{ia32}.}
|
\caption{LVT Timer Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||||
\label{tab:lapicregslvtt}
|
\label{tab:lapicregslvtt}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
16 & Masked \\ \hline
|
16 & Masked \\ \hline
|
||||||
17:31 & Reserved \\ \hline
|
17:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{LVT Error Register~\cite[sec.~3.11.5.1]{ia32}.}
|
\caption{LVT Error Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||||
\label{tab:lapicregslvterr}
|
\label{tab:lapicregslvterr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
16 & Masked \\ \hline
|
16 & Masked \\ \hline
|
||||||
17:31 & Reserved \\ \hline
|
17:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{LVT LINT1 Register~\cite[sec.~3.11.5.1]{ia32}.}
|
\caption{LVT LINT1 Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||||
\label{tab:lapicregslvtlint}
|
\label{tab:lapicregslvtlint}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -195,7 +195,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:31 & Initial Count \\ \hline
|
0:31 & Initial Count \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Timer Initial Count Register~\cite[sec.~3.11.5.4]{ia32}.}
|
\caption{Timer Initial Count Register~\autocite[sec.~3.11.5.4]{ia32}.}
|
||||||
\label{tab:lapicregstimerinit}
|
\label{tab:lapicregstimerinit}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -209,7 +209,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
3 & Divider \\ \hline
|
3 & Divider \\ \hline
|
||||||
4:31 & Reserved \\ \hline
|
4:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Timer Divide Configuration Register~\cite[sec.~3.11.5.4]{ia32}.}
|
\caption{Timer Divide Configuration Register~\autocite[sec.~3.11.5.4]{ia32}.}
|
||||||
\label{tab:lapicregstimerdiv}
|
\label{tab:lapicregstimerdiv}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -226,7 +226,9 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
12:35 & APIC Base Address \\ \hline
|
12:35 & APIC Base Address \\ \hline
|
||||||
36:63 & Reserved \\ \hline
|
36:63 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\cite[sec.~3.11.12.1]{ia32}.}
|
\caption{IA32\textunderscore{}
|
||||||
|
APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.12.1]{ia32}.
|
||||||
|
}
|
||||||
\label{tab:lapicregsmsr}
|
\label{tab:lapicregsmsr}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -247,7 +249,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
I/O APIC Version Register & 0x01 \\ \hline
|
I/O APIC Version Register & 0x01 \\ \hline
|
||||||
Redirection Table & 0x10:0x3F \\ \hline
|
Redirection Table & 0x10:0x3F \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC Registers used in this Implementation~\cite[sec.~9.5]{ich5}.}
|
\caption{I/O APIC Registers used in this Implementation~\autocite[sec.~9.5]{ich5}.}
|
||||||
\label{tab:ioapicregs}
|
\label{tab:ioapicregs}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -258,7 +260,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:7 & Indirect Register Index \\ \hline
|
0:7 & Indirect Register Index \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC Index Register~\cite[sec.~9.5.2]{ich5}.}
|
\caption{I/O APIC Index Register~\autocite[sec.~9.5.2]{ich5}.}
|
||||||
\label{tab:ioapicregsidx}
|
\label{tab:ioapicregsidx}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -269,7 +271,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:31 & Indirect Register Data \\ \hline
|
0:31 & Indirect Register Data \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC Data Register~\cite[sec.~9.5.3]{ich5}.}
|
\caption{I/O APIC Data Register~\autocite[sec.~9.5.3]{ich5}.}
|
||||||
\label{tab:ioapicregsdat}
|
\label{tab:ioapicregsdat}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -284,7 +286,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
24:27 & I/O APIC ID \\ \hline
|
24:27 & I/O APIC ID \\ \hline
|
||||||
28:31 & Reserved \\ \hline
|
28:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC ID Register~\cite[sec.~9.5.6]{ich5}.}
|
\caption{I/O APIC ID Register~\autocite[sec.~9.5.6]{ich5}.}
|
||||||
\label{tab:ioapicregsid}
|
\label{tab:ioapicregsid}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -299,7 +301,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
16:23 & Maximum Redirection Entries \\ \hline
|
16:23 & Maximum Redirection Entries \\ \hline
|
||||||
24:31 & Reserved \\ \hline
|
24:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC Version Register~\cite[sec.~9.5.7]{ich5}.}
|
\caption{I/O APIC Version Register~\autocite[sec.~9.5.7]{ich5}.}
|
||||||
\label{tab:ioapicregsver}
|
\label{tab:ioapicregsver}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -320,7 +322,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
48:55 & Extended Destination ID \\ \hline
|
48:55 & Extended Destination ID \\ \hline
|
||||||
56:63 & Destination \\ \hline
|
56:63 & Destination \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{I/O APIC REDTBL Register~\cite[sec.~9.5.8]{ich5}.}
|
\caption{I/O APIC REDTBL Register~\autocite[sec.~9.5.8]{ich5}.}
|
||||||
\label{tab:ioapicregsredtbl}
|
\label{tab:ioapicregsredtbl}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -339,7 +341,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
40:43 & Local APIC Flags \\ \hline
|
40:43 & Local APIC Flags \\ \hline
|
||||||
44: & List of APIC Structures \\ \hline
|
44: & List of APIC Structures \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{ACPI MADT~\cite[sec.~5.2.8]{acpi1}.}
|
\caption{ACPI MADT~\autocite[sec.~5.2.8]{acpi1}.}
|
||||||
\label{tab:madt}
|
\label{tab:madt}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -353,7 +355,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
3 & APIC ID \\ \hline
|
3 & APIC ID \\ \hline
|
||||||
4:7 & Local APIC Flags (see \autoref{tab:madtlapicflags}) \\ \hline
|
4:7 & Local APIC Flags (see \autoref{tab:madtlapicflags}) \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{MADT Processor Local APIC Structure~\cite[sec.~5.2.8.1]{acpi1}.}
|
\caption{MADT Processor Local APIC Structure~\autocite[sec.~5.2.8.1]{acpi1}.}
|
||||||
\label{tab:madtlapic}
|
\label{tab:madtlapic}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -365,7 +367,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
0 & Enabled \\ \hline
|
0 & Enabled \\ \hline
|
||||||
1:31 & Reserved \\ \hline
|
1:31 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Local APIC Flags~\cite[sec.~5.2.8.1]{acpi1}.}
|
\caption{Local APIC Flags~\autocite[sec.~5.2.8.1]{acpi1}.}
|
||||||
\label{tab:madtlapicflags}
|
\label{tab:madtlapicflags}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -380,7 +382,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
4:7 & I/O APIC Base Address \\ \hline
|
4:7 & I/O APIC Base Address \\ \hline
|
||||||
8:11 & I/O APIC GSI Base \\ \hline
|
8:11 & I/O APIC GSI Base \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{MADT I/O APIC Structure~\cite[sec.~5.2.8.2]{acpi1}.}
|
\caption{MADT I/O APIC Structure~\autocite[sec.~5.2.8.2]{acpi1}.}
|
||||||
\label{tab:madtioapic}
|
\label{tab:madtioapic}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -393,9 +395,9 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
2 & Bus \\ \hline
|
2 & Bus \\ \hline
|
||||||
3 & Source \\ \hline
|
3 & Source \\ \hline
|
||||||
4:7 & GSI \\ \hline
|
4:7 & GSI \\ \hline
|
||||||
8:9 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
8:9 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{MADT Interrupt Source Override Structure~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
\caption{MADT Interrupt Source Override Structure~\autocite[sec.~5.2.8.3.1]{acpi1}.}
|
||||||
\label{tab:madtirqoverride}
|
\label{tab:madtirqoverride}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -408,7 +410,7 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
2:3 & Trigger Mode \\ \hline
|
2:3 & Trigger Mode \\ \hline
|
||||||
4:11 & Reserved \\ \hline
|
4:11 & Reserved \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{Interrupt Input Flags~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
\caption{INTI Flags~\autocite[sec.~5.2.8.3.1]{acpi1}.}
|
||||||
\label{tab:madtintiflags}
|
\label{tab:madtintiflags}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -418,10 +420,10 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\hline
|
\hline
|
||||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:1 & APIC Structure Header \\ \hline
|
0:1 & APIC Structure Header \\ \hline
|
||||||
2:3 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
2:3 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||||
4:7 & GSI
|
4:7 & GSI \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{MADT I/O APIC NMI Source~\cite[sec.~5.2.8.3.2]{acpi1}.}
|
\caption{MADT I/O APIC NMI Source~\autocite[sec.~5.2.8.3.2]{acpi1}.}
|
||||||
\label{tab:madtionmi}
|
\label{tab:madtionmi}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
@ -432,9 +434,11 @@ This section lists all the registers and structures required to follow \autoref{
|
|||||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||||
0:1 & APIC Structure Header \\ \hline
|
0:1 & APIC Structure Header \\ \hline
|
||||||
2 & ACPI Processor ID \\ \hline
|
2 & ACPI Processor ID \\ \hline
|
||||||
3:4 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
3:4 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||||
5 & Local APIC Interrupt Input \\ \hline
|
5 & Local APIC INTI \\ \hline
|
||||||
\end{tabularx}
|
\end{tabularx}
|
||||||
\caption{MADT Local APIC NMI Source~\cite[sec.~5.2.8.3.3]{acpi1}.}
|
\caption{MADT Local APIC NMI Source~\autocite[sec.~5.2.8.3.3]{acpi1}.}
|
||||||
\label{tab:madtlnmi}
|
\label{tab:madtlnmi}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
|
\cleardoublepage
|
191
chap/verification.aux
Normal file
191
chap/verification.aux
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
\relax
|
||||||
|
\providecommand{\transparent@use}[1]{}
|
||||||
|
\providecommand\hyper@newdestlabel[2]{}
|
||||||
|
\@writefile{listings}{\addvspace {10pt}}
|
||||||
|
\@writefile{toc}{\contentsline {chapter}{\numberline {4}Verification}{33}{chapter.4}\protected@file@percent }
|
||||||
|
\@writefile{lof}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{lot}{\addvspace {10\p@ }}
|
||||||
|
\@writefile{loa}{\addvspace {10\p@ }}
|
||||||
|
\newlabel{ch:verification}{{4}{33}{Verification}{chapter.4}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.1}Methods of Verification}{34}{section.4.1}\protected@file@percent }
|
||||||
|
\newlabel{sec:verificationmethods}{{4.1}{34}{Methods of Verification}{section.4.1}{}}
|
||||||
|
\@writefile{toc}{\contentsline {section}{\numberline {4.2}Results}{34}{section.4.2}\protected@file@percent }
|
||||||
|
\newlabel{sec:verificationresults}{{4.2}{34}{Results}{section.4.2}{}}
|
||||||
|
\@setckpt{chap/verification}{
|
||||||
|
\setcounter{page}{37}
|
||||||
|
\setcounter{equation}{0}
|
||||||
|
\setcounter{enumi}{9}
|
||||||
|
\setcounter{enumii}{0}
|
||||||
|
\setcounter{enumiii}{0}
|
||||||
|
\setcounter{enumiv}{0}
|
||||||
|
\setcounter{footnote}{3}
|
||||||
|
\setcounter{mpfootnote}{0}
|
||||||
|
\setcounter{part}{0}
|
||||||
|
\setcounter{chapter}{4}
|
||||||
|
\setcounter{section}{2}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\setcounter{subsubsection}{0}
|
||||||
|
\setcounter{paragraph}{0}
|
||||||
|
\setcounter{subparagraph}{0}
|
||||||
|
\setcounter{figure}{0}
|
||||||
|
\setcounter{table}{0}
|
||||||
|
\setcounter{parentequation}{0}
|
||||||
|
\setcounter{tcbbreakpart}{1}
|
||||||
|
\setcounter{tcblayer}{0}
|
||||||
|
\setcounter{tcolorbox@number}{59}
|
||||||
|
\setcounter{FancyVerbLine}{0}
|
||||||
|
\setcounter{linenumber}{1}
|
||||||
|
\setcounter{LN@truepage}{44}
|
||||||
|
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||||
|
\setcounter{FV@TrueTabCounter}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStart}{0}
|
||||||
|
\setcounter{FV@HighlightLinesStop}{0}
|
||||||
|
\setcounter{FancyVerbLineBreakLast}{0}
|
||||||
|
\setcounter{FV@BreakBufferDepth}{0}
|
||||||
|
\setcounter{float@type}{16}
|
||||||
|
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||||
|
\setcounter{minted@pygmentizecounter}{0}
|
||||||
|
\setcounter{listing}{0}
|
||||||
|
\setcounter{tcblisting}{0}
|
||||||
|
\setcounter{caption@flags}{6}
|
||||||
|
\setcounter{continuedfloat}{0}
|
||||||
|
\setcounter{subfigure}{0}
|
||||||
|
\setcounter{subtable}{0}
|
||||||
|
\setcounter{section@level}{1}
|
||||||
|
\setcounter{Item}{46}
|
||||||
|
\setcounter{Hfootnote}{38}
|
||||||
|
\setcounter{bookmark@seq@number}{43}
|
||||||
|
\setcounter{AlgoLine}{0}
|
||||||
|
\setcounter{algocfline}{0}
|
||||||
|
\setcounter{algocfproc}{0}
|
||||||
|
\setcounter{algocf}{0}
|
||||||
|
\setcounter{lofdepth}{1}
|
||||||
|
\setcounter{lotdepth}{1}
|
||||||
|
\setcounter{svg@param@lastpage}{0}
|
||||||
|
\setcounter{svg@param@currpage}{-1}
|
||||||
|
\setcounter{su@anzahl}{0}
|
||||||
|
\setcounter{LT@tables}{0}
|
||||||
|
\setcounter{LT@chunks}{0}
|
||||||
|
\setcounter{@pps}{0}
|
||||||
|
\setcounter{@ppsavesec}{0}
|
||||||
|
\setcounter{@ppsaveapp}{0}
|
||||||
|
\setcounter{tabx@nest}{0}
|
||||||
|
\setcounter{listtotal}{0}
|
||||||
|
\setcounter{listcount}{0}
|
||||||
|
\setcounter{liststart}{0}
|
||||||
|
\setcounter{liststop}{0}
|
||||||
|
\setcounter{citecount}{0}
|
||||||
|
\setcounter{citetotal}{0}
|
||||||
|
\setcounter{multicitecount}{0}
|
||||||
|
\setcounter{multicitetotal}{0}
|
||||||
|
\setcounter{instcount}{78}
|
||||||
|
\setcounter{maxnames}{3}
|
||||||
|
\setcounter{minnames}{3}
|
||||||
|
\setcounter{maxitems}{3}
|
||||||
|
\setcounter{minitems}{1}
|
||||||
|
\setcounter{citecounter}{0}
|
||||||
|
\setcounter{maxcitecounter}{0}
|
||||||
|
\setcounter{savedcitecounter}{0}
|
||||||
|
\setcounter{uniquelist}{0}
|
||||||
|
\setcounter{uniquename}{0}
|
||||||
|
\setcounter{refsection}{0}
|
||||||
|
\setcounter{refsegment}{0}
|
||||||
|
\setcounter{maxextratitle}{0}
|
||||||
|
\setcounter{maxextratitleyear}{0}
|
||||||
|
\setcounter{maxextraname}{0}
|
||||||
|
\setcounter{maxextradate}{0}
|
||||||
|
\setcounter{maxextraalpha}{0}
|
||||||
|
\setcounter{abbrvpenalty}{50}
|
||||||
|
\setcounter{highnamepenalty}{50}
|
||||||
|
\setcounter{lownamepenalty}{25}
|
||||||
|
\setcounter{maxparens}{3}
|
||||||
|
\setcounter{parenlevel}{0}
|
||||||
|
\setcounter{blx@maxsection}{0}
|
||||||
|
\setcounter{mincomprange}{10}
|
||||||
|
\setcounter{maxcomprange}{100000}
|
||||||
|
\setcounter{mincompwidth}{1}
|
||||||
|
\setcounter{afterword}{0}
|
||||||
|
\setcounter{savedafterword}{0}
|
||||||
|
\setcounter{annotator}{0}
|
||||||
|
\setcounter{savedannotator}{0}
|
||||||
|
\setcounter{author}{0}
|
||||||
|
\setcounter{savedauthor}{0}
|
||||||
|
\setcounter{bookauthor}{0}
|
||||||
|
\setcounter{savedbookauthor}{0}
|
||||||
|
\setcounter{commentator}{0}
|
||||||
|
\setcounter{savedcommentator}{0}
|
||||||
|
\setcounter{editor}{0}
|
||||||
|
\setcounter{savededitor}{0}
|
||||||
|
\setcounter{editora}{0}
|
||||||
|
\setcounter{savededitora}{0}
|
||||||
|
\setcounter{editorb}{0}
|
||||||
|
\setcounter{savededitorb}{0}
|
||||||
|
\setcounter{editorc}{0}
|
||||||
|
\setcounter{savededitorc}{0}
|
||||||
|
\setcounter{foreword}{0}
|
||||||
|
\setcounter{savedforeword}{0}
|
||||||
|
\setcounter{holder}{0}
|
||||||
|
\setcounter{savedholder}{0}
|
||||||
|
\setcounter{introduction}{0}
|
||||||
|
\setcounter{savedintroduction}{0}
|
||||||
|
\setcounter{namea}{0}
|
||||||
|
\setcounter{savednamea}{0}
|
||||||
|
\setcounter{nameb}{0}
|
||||||
|
\setcounter{savednameb}{0}
|
||||||
|
\setcounter{namec}{0}
|
||||||
|
\setcounter{savednamec}{0}
|
||||||
|
\setcounter{translator}{0}
|
||||||
|
\setcounter{savedtranslator}{0}
|
||||||
|
\setcounter{shortauthor}{0}
|
||||||
|
\setcounter{savedshortauthor}{0}
|
||||||
|
\setcounter{shorteditor}{0}
|
||||||
|
\setcounter{savedshorteditor}{0}
|
||||||
|
\setcounter{labelname}{0}
|
||||||
|
\setcounter{savedlabelname}{0}
|
||||||
|
\setcounter{institution}{0}
|
||||||
|
\setcounter{savedinstitution}{0}
|
||||||
|
\setcounter{lista}{0}
|
||||||
|
\setcounter{savedlista}{0}
|
||||||
|
\setcounter{listb}{0}
|
||||||
|
\setcounter{savedlistb}{0}
|
||||||
|
\setcounter{listc}{0}
|
||||||
|
\setcounter{savedlistc}{0}
|
||||||
|
\setcounter{listd}{0}
|
||||||
|
\setcounter{savedlistd}{0}
|
||||||
|
\setcounter{liste}{0}
|
||||||
|
\setcounter{savedliste}{0}
|
||||||
|
\setcounter{listf}{0}
|
||||||
|
\setcounter{savedlistf}{0}
|
||||||
|
\setcounter{location}{0}
|
||||||
|
\setcounter{savedlocation}{0}
|
||||||
|
\setcounter{organization}{0}
|
||||||
|
\setcounter{savedorganization}{0}
|
||||||
|
\setcounter{origlocation}{0}
|
||||||
|
\setcounter{savedoriglocation}{0}
|
||||||
|
\setcounter{origpublisher}{0}
|
||||||
|
\setcounter{savedorigpublisher}{0}
|
||||||
|
\setcounter{publisher}{0}
|
||||||
|
\setcounter{savedpublisher}{0}
|
||||||
|
\setcounter{language}{0}
|
||||||
|
\setcounter{savedlanguage}{0}
|
||||||
|
\setcounter{origlanguage}{0}
|
||||||
|
\setcounter{savedoriglanguage}{0}
|
||||||
|
\setcounter{pageref}{0}
|
||||||
|
\setcounter{savedpageref}{0}
|
||||||
|
\setcounter{textcitecount}{0}
|
||||||
|
\setcounter{textcitetotal}{0}
|
||||||
|
\setcounter{textcitemaxnames}{0}
|
||||||
|
\setcounter{biburlbigbreakpenalty}{100}
|
||||||
|
\setcounter{biburlbreakpenalty}{200}
|
||||||
|
\setcounter{biburlnumpenalty}{0}
|
||||||
|
\setcounter{biburlucpenalty}{0}
|
||||||
|
\setcounter{biburllcpenalty}{0}
|
||||||
|
\setcounter{smartand}{1}
|
||||||
|
\setcounter{bbx:relatedcount}{0}
|
||||||
|
\setcounter{bbx:relatedtotal}{0}
|
||||||
|
\setcounter{cbx@tempcnta}{0}
|
||||||
|
\setcounter{cbx@tempcntb}{13}
|
||||||
|
\setcounter{cbx@tempcntc}{0}
|
||||||
|
\setcounter{cbx@tempcntd}{-1}
|
||||||
|
\setcounter{tcb@cnt@codeblock}{0}
|
||||||
|
}
|
@ -1,82 +1,64 @@
|
|||||||
\chapter{Verification}
|
\chapter{Verification}
|
||||||
\label{ch:verification}
|
\label{ch:verification}
|
||||||
|
|
||||||
Common techniques for testing software include component-based tests, like ``unit tests'', and
|
Common techniques for testing software include component-based tests, like \textquote{unit tests}, and \textquote{end-to-end tests}, where the complete functionality of a software system with all its parts is tested.
|
||||||
``end-to-end tests'', where the complete functionality of a software system with all its parts is
|
As unit testing is mostly suitable for independent slices of a system's application logic, it is not very useful for testing low-level software designed to run directly on hardware devices.
|
||||||
tested. As unit testing is mostly suitable for independent slices of a system's application logic,
|
|
||||||
it is not very useful for testing low-level software designed to run directly on hardware devices.
|
|
||||||
|
|
||||||
This chapter deals with the process and results of testing hhuOS with the APIC implementation
|
This chapter deals with the process and results of testing hhuOS with the APIC implementation developed during this thesis.
|
||||||
developed during this thesis.
|
|
||||||
|
|
||||||
\clearpage
|
\clearpage
|
||||||
|
|
||||||
\section{Methods of Verification}
|
\section{Methods of Verification}
|
||||||
\label{sec:verificationmethods}
|
\label{sec:verificationmethods}
|
||||||
|
|
||||||
This application can be tested by running the entire hhuOS operating system on both emulated and
|
This application can be tested by running the entire hhuOS operating system on both emulated and real hardware, and monitoring its state of operation\footnote{
|
||||||
real hardware, and monitoring its state of operation\footnote{There is almost no logic that can be
|
There is almost no logic that can be tested isolated or hardware independently.}.
|
||||||
tested isolated or hardware independently.}.
|
|
||||||
|
|
||||||
This can be done in multiple ways:
|
This can be done in multiple ways:
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item When running hhuOS in an emulated environment, the current machine state can be inspected
|
\item When running hhuOS in an emulated environment, the current machine state can be inspected directly\footnote{
|
||||||
directly\footnote{QEMU offers the ``QEMU monitor'' to query information about specific hardware
|
QEMU offers the \textquote{QEMU monitor} to query information about specific hardware components, like the local or I/O APIC (\code{info lapic} and \code{info pic}).}.
|
||||||
components, like the local or I/O APIC (\code{info lapic} and \code{info pic}).}.
|
\item To test the functionality of an interrupt controller specifically, stub interrupt handlers can be used to verify that a specific interrupt (like an IPI) has been registered.
|
||||||
\item To test the functionality of an interrupt controller specifically, stub interrupt handlers can be
|
\item By attaching a debugger (very simple for emulated hardware), it can be observed that e.g.\ the timer interrupt is correctly increasing the timestamp for each running CPU\@.
|
||||||
used to verify that a specific interrupt (like an IPI) has been registered.
|
\item By exposing some of the APIC's internal data through hhuOS' virtual file system, end-to-end verification can be performed from the system itself, as debugging and monitoring is significantly more difficult when running on real hardware.
|
||||||
\item By attaching a debugger (very simple for emulated hardware), it can be observed that e.g.\ the
|
\item Because the interrupt controller is a vital part for many components of an operating system, observing a successful boot is already a significant indicator for a correct implementation.
|
||||||
timer interrupt is correctly increasing the timestamp for each running CPU\@.
|
|
||||||
\item By exposing some of the APIC's internal data through hhuOS' virtual file system, end-to-end
|
|
||||||
verification can be performed from the system itself, as debugging and monitoring is significantly
|
|
||||||
more difficult when running on real hardware.
|
|
||||||
\item Because the interrupt controller is a vital part for many components of an operating system,
|
|
||||||
observing a successful boot is already a significant indicator for a correct implementation.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
\section{Results}
|
\section{Results}
|
||||||
\label{sec:verificationresults}
|
\label{sec:verificationresults}
|
||||||
|
|
||||||
QEMU was used as the main development platform, the implemented features were tested by using the
|
QEMU was used as the main development platform, the implemented features were tested by using the QEMU monitor.
|
||||||
QEMU monitor. Specifically, QEMU provides the current register state of all local and I/O APICs, by
|
Specifically, QEMU provides the current register state of all local and I/O APICs, by attaching a debugger to the running operating system correct behavior was observed on the emulated hardware level:
|
||||||
attaching a debugger to the running operating system correct behavior was observed on the emulated
|
|
||||||
hardware level:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item Working local interrupts - verified by observing the local APIC's IRR\@.
|
\item Working local interrupts -- verified by observing the local APIC's IRR\@.
|
||||||
\item Propagation of interrupts to the CPU - verified by observing the local APIC's ISR\@.
|
\item Propagation of interrupts to the CPU -- verified by observing the local APIC's ISR\@.
|
||||||
\item A working local APIC timer - verified by observing the APIC timer's registers.
|
\item A working local APIC timer -- verified by observing the APIC timer's registers.
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
Although hhuOS is developed mainly for learning purposes, every OS' core task remains to be the
|
Although hhuOS is developed mainly for learning purposes, every OS' core task remains to be the management of computer hardware.
|
||||||
management of computer hardware. For this reason this implementation was additionally tested on a
|
For this reason, this implementation was additionally tested on a \textquote{ThinkPad T60s} with an Intel \textquote{Core 2 Duo} processor.
|
||||||
``ThinkPad T60s'' with an Intel ``Core 2 Duo'' processor. By providing internal status data through
|
By providing internal status data through the virtual file system, implemented features (including booting additional APs) were verified on this very specific set of hardware.
|
||||||
the virtual file system, implemented features (including booting additional APs) were verified on
|
|
||||||
this very specific set of hardware.
|
|
||||||
|
|
||||||
More specifically, information about detected and enabled local APICs and the I/O APIC, register
|
More specifically, information about detected and enabled local APICs and the I/O APIC, register values from the BSP's LVT and the REDTBL, the contents of the PIC's \textbf{\gls{imr}}, and the number of occurred interrupts by core (similar to \code{/proc/interrupts} in Linux~\autocite{linux}) are exposed on the path \code{/device/apic/}.
|
||||||
values from the BSP's LVT and the REDTBL, the contents of the PIC's \textbf{\gls{imr}}, and amounts
|
This way, the following things could be verified on real hardware:
|
||||||
of occurred interrupts by core (similar to \code{/proc/interrupts} in Linux~\cite{linux}]) are
|
|
||||||
exposed on the path \code{/device/apic/}. This way, the following things could be verified on real
|
|
||||||
hardware:
|
|
||||||
|
|
||||||
\begin{itemize}
|
\begin{itemize}
|
||||||
\item The APIC is indeed used instead of the PIC - verified by observing the PIC's IMR\@.
|
\item The APIC is indeed used instead of the PIC -- verified by observing the PIC's IMR\@.
|
||||||
\item Successful MMIO for local and I/O APIC - verified by observing the LVT and REDTBL\@.
|
\item Successful MMIO for local and I/O APIC -- verified by observing the LVT and REDTBL\@.
|
||||||
\item Devices ``plugging in'' to the APIC instead of the PIC - verified by observing the LVT and
|
\item Devices \textquote{plugging in} to the APIC instead of the PIC -- verified by observing the LVT and REDTBL\@.
|
||||||
REDTBL\@.
|
\item Interrupt handlers are called correctly -- verified by using the keyboard.
|
||||||
\item Interrupt handlers are called correctly - verified by using the keyboard.
|
\item Working startup of additional APs -- verified by checking the state of the AP's local APICs and observing the system log.
|
||||||
\item Working startup of additional APs - verified by checking the state of the AP's local APICs and
|
\item Handling interrupts on another AP -- verified by redirecting the keyboard interrupt to another processor and observing the number of occurred keyboard interrupts on this processor\footnote{
|
||||||
observing the system log.
|
Interestingly, this was easier to verify on real hardware than in QEMU, because QEMU usually instantly crashes when interrupts are enabled on an AP beside the BSP\@.
|
||||||
\item Handling interrupts on another AP - verified by redirecting the keyboard interrupt to another
|
Also, redirecting the keyboard interrupt in QEMU significantly changes the behavior of any key press and renders the keyboard unusable.
|
||||||
processor and observing the number of occurred keyboard interrupts on this
|
This is expected, as hhuOS' paging is not designed for multiple processors.
|
||||||
processor\footnote{Interestingly, this was easier to verify on real hardware than in QEMU, because
|
On the ThinkPad T60s though, it was possible (surprisingly) to use the redirected keyboard interrupt to \code{cat} the \code{/device/apic/irqs} file to observe the interrupt statistics, which showed the keyboard interrupts indeed arriving at a different core than the BSP\@.
|
||||||
QEMU usually instantly crashes when interrupts are enabled on an AP beside the BSP. Also,
|
After a certain time, the system crashes on the ThinkPad as well.}.
|
||||||
redirecting the keyboard interrupt in QEMU significantly changes the behaviour of any key press and
|
|
||||||
renders the keyboard unusable. This is expected, as hhuOS' paging is not designed for multiple
|
|
||||||
processors. On the ThinkPad T60s though, it was possible (surprisingly) to use the redirected
|
|
||||||
keyboard interrupt to \code{cat} the \code{/device/apic/irqs} file to observe the interrupt
|
|
||||||
statistics, which showed the keyboard interrupts arriving on a different core than the BSP. After a
|
|
||||||
certain time, the system crashes on the ThinkPad aswell.}.
|
|
||||||
\end{itemize}
|
\end{itemize}
|
||||||
|
|
||||||
|
It should be noted, that e.g.\ the REDTBL observation requires the same MMIO registers as the functionality that is to be verified, which would allow for wrong conclusions if the MMIO mechanism was faulty.
|
||||||
|
It is very unlikely though that all the correct values are provided accidentally.
|
||||||
|
|
||||||
|
\cleardoublepage
|
130
class/thesis.cls
130
class/thesis.cls
@ -20,65 +20,63 @@
|
|||||||
% Packages
|
% Packages
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
|
\RequirePackage{silence} % Silence some warnings
|
||||||
|
\WarningFilter{latexfont}{Font shape}
|
||||||
|
\WarningFilter{latexfont}{Some font shapres were not available}
|
||||||
|
\WarningFilter{latexfont}{Size substitutions with differences}
|
||||||
|
\WarningFilter{latex}{`h' float specifier}
|
||||||
|
\WarningFilter{latex}{\include should only be used after}
|
||||||
|
\WarningFilter{fancyhdr}{\headheight}
|
||||||
|
|
||||||
\RequirePackage[left=3cm,right=2.5cm,top=3cm,bottom=2.5cm]{geometry}
|
\RequirePackage[left=3cm,right=2.5cm,top=3cm,bottom=2.5cm]{geometry}
|
||||||
|
|
||||||
\RequirePackage[utf8]{inputenc}
|
\RequirePackage[utf8]{inputenc}
|
||||||
\RequirePackage[T1]{fontenc}
|
\RequirePackage[T1]{fontenc}
|
||||||
\RequirePackage[english,ngerman]{babel}
|
\RequirePackage[english]{babel} % ngerman
|
||||||
\RequirePackage{mathtools}
|
|
||||||
% \RequirePackage{amssymb} % Produces some errors I don't understand
|
|
||||||
\RequirePackage[minted]{tcolorbox}
|
|
||||||
% \RequirePackage{minted}
|
|
||||||
\RequirePackage{fancyhdr} % For headers
|
\RequirePackage{fancyhdr} % For headers
|
||||||
\RequirePackage{color}
|
\RequirePackage{color}
|
||||||
% \RequirePackage[usenames,dvipsnames]{xcolor} % Option Clash, already loaded by sth else
|
\RequirePackage[usenames,dvipsnames]{xcolor}
|
||||||
\RequirePackage{graphicx}
|
% \RequirePackage{amssymb}
|
||||||
|
\RequirePackage{amsmath} % tcolorbox should load this anyway, but results in errors?
|
||||||
|
\RequirePackage[minted]{tcolorbox} % Load after xcolor, [minted]
|
||||||
|
% \RequirePackage{minted}
|
||||||
|
% \RequirePackage{graphicx}
|
||||||
\RequirePackage{tikz}
|
\RequirePackage{tikz}
|
||||||
\RequirePackage{subcaption} % Floats in floats
|
\RequirePackage{subcaption} % Floats in floats
|
||||||
\RequirePackage{float}
|
\RequirePackage{float}
|
||||||
\RequirePackage{multirow} % For tables
|
% \RequirePackage{multirow} % For tables
|
||||||
% \RequirePackage{todonotes}
|
% \RequirePackage{todonotes}
|
||||||
\RequirePackage{hyperref} % [hidelinks]
|
\RequirePackage[hidelinks]{hyperref} % [hidelinks]
|
||||||
\RequirePackage{algorithm2e}
|
\RequirePackage{algorithm2e}
|
||||||
\RequirePackage{tocloft}
|
\RequirePackage{tocloft}
|
||||||
\RequirePackage{listings}
|
% \RequirePackage{listings}
|
||||||
\RequirePackage{textcomp}
|
\RequirePackage{textcomp}
|
||||||
\RequirePackage{ifthen}
|
\RequirePackage{ifthen}
|
||||||
\RequirePackage{pgf} % Not sure if pgf was meant, but pgffor doesn't exist (at least not in my texlive?)
|
% \RequirePackage{pgffor}
|
||||||
\RequirePackage{enumitem}
|
\RequirePackage{enumitem}
|
||||||
|
|
||||||
% Some additions
|
% Some additions
|
||||||
|
\RequirePackage[inkscapelatex=false]{svg} % Autoconvert to pdf, don't let latex touch the fonts
|
||||||
% Borders around svg figures
|
\RequirePackage{csquotes} % \textquote{}
|
||||||
\RequirePackage{svg}
|
|
||||||
\RequirePackage{float}
|
|
||||||
\floatstyle{boxed}
|
|
||||||
\restylefloat{figure}
|
|
||||||
|
|
||||||
\RequirePackage{csquotes}
|
|
||||||
\RequirePackage{tabularx}
|
\RequirePackage{tabularx}
|
||||||
|
|
||||||
% Extra chapters
|
|
||||||
\RequirePackage[acronym,automake,nonumberlist,nogroupskip]{glossaries} % Must be loaded after hyperref, [toc]
|
\RequirePackage[acronym,automake,nonumberlist,nogroupskip]{glossaries} % Must be loaded after hyperref, [toc]
|
||||||
\RequirePackage[page]{appendix} % [toc]
|
\RequirePackage[page]{appendix} % [toc]
|
||||||
% \RequirePackage{tocbibind} % Add lists to toc, still needs [heading=bibintoc] for some reason, [nottoc]?
|
% \RequirePackage{tocbibind} % Add lists to toc, still needs [heading=bibintoc] for some reason, [nottoc]?
|
||||||
|
|
||||||
% Font
|
|
||||||
\RequirePackage{beton} % Computer Concrete font
|
\RequirePackage{beton} % Computer Concrete font
|
||||||
\DeclareFontSeriesDefault[rm]{bf}{sbc} % Computer Concrete does not have bold font
|
\RequirePackage{eulerpx} % Math font (have no math :()
|
||||||
\RequirePackage{eulerpx} % Math font
|
|
||||||
\RequirePackage{inconsolata} % Code font
|
\RequirePackage{inconsolata} % Code font
|
||||||
|
\RequirePackage[activate={true,nocompatibility},final,expansion=false,tracking=true,kerning=true,factor=1100,stretch=10,shrink=10]{microtype} % Sadly, expansion does not work with concrete, as they are not scalable
|
||||||
% Group listings by chapter, pretocmd prepends something to a command
|
|
||||||
\RequirePackage{etoolbox}
|
\RequirePackage{etoolbox}
|
||||||
\pretocmd{\chapter}{\addtocontents{listings}{\protect\addvspace{10pt}}}{}{}
|
\RequirePackage{siunitx}
|
||||||
|
\RequirePackage{setspace}
|
||||||
|
|
||||||
% Control lot/lof parskip
|
% Options
|
||||||
\RequirePackage{tocloft}
|
\floatstyle{boxed} % boxes around figures
|
||||||
|
\restylefloat{figure}
|
||||||
% Allow referencing subsubsections (don't have those anymore)
|
\DeclareFontSeriesDefault[rm]{bf}{sbc} % beton Computer Concrete does not have bold font
|
||||||
% \setcounter{secnumdepth}{3}
|
\pretocmd{\chapter}{\addtocontents{listings}{\protect\addvspace{10pt}}}{}{} % Group listings by chap
|
||||||
% \setcounter{tocdepth}{3}
|
\sisetup{detect-all}
|
||||||
|
% \renewcommand{\baselinestretch}{0.95}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Package settings
|
% Package settings
|
||||||
@ -192,9 +190,6 @@
|
|||||||
\def\@thesistype{}
|
\def\@thesistype{}
|
||||||
\newcommand{\thesistype}[1]{\def\@thesistype{#1}}
|
\newcommand{\thesistype}[1]{\def\@thesistype{#1}}
|
||||||
|
|
||||||
\def\@glossaryenabled{}
|
|
||||||
\newcommand{\glossaryenabled}[1]{\def\@glossaryenabled{#1}}
|
|
||||||
|
|
||||||
\def\@listoffiguresenabled{}
|
\def\@listoffiguresenabled{}
|
||||||
\newcommand{\listoffiguresenabled}[1]{\def\@listoffiguresenabled{#1}}
|
\newcommand{\listoffiguresenabled}[1]{\def\@listoffiguresenabled{#1}}
|
||||||
|
|
||||||
@ -204,12 +199,6 @@
|
|||||||
\def\@listofalgorithmsenabled{}
|
\def\@listofalgorithmsenabled{}
|
||||||
\newcommand{\listofalgorithmsenabled}[1]{\def\@listofalgorithmsenabled{#1}}
|
\newcommand{\listofalgorithmsenabled}[1]{\def\@listofalgorithmsenabled{#1}}
|
||||||
|
|
||||||
\def\@hidefigures{}
|
|
||||||
\newcommand{\hidefigures}[1]{\def\@hidefigures{#1}}
|
|
||||||
|
|
||||||
\def\@hidecode{}
|
|
||||||
\newcommand{\hidecode}[1]{\def\@hidecode{#1}}
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Colors
|
% Colors
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
@ -284,8 +273,12 @@
|
|||||||
% Table of contents
|
% Table of contents
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
\tableofcontents
|
\microtypesetup{protrusion=false}
|
||||||
|
\begin{spacing}{0.94} % Hamburger the TOC into two pages really unprofessionally
|
||||||
|
\tableofcontents
|
||||||
|
\end{spacing}
|
||||||
\cleardoublepage
|
\cleardoublepage
|
||||||
|
\microtypesetup{protrusion=true}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Re-enable fancy headers
|
% Re-enable fancy headers
|
||||||
@ -294,34 +287,16 @@
|
|||||||
% \pagenumbering{arabic} % Only number chapters
|
% \pagenumbering{arabic} % Only number chapters
|
||||||
\pagestyle{thesis}
|
\pagestyle{thesis}
|
||||||
|
|
||||||
\ifthenelse{\equal{\@glossaryenabled}{true}}
|
% Print Glossary
|
||||||
{%
|
\setacronymstyle{short-long}
|
||||||
\setacronymstyle{short-long}
|
\printglossary[type=\acronymtype]
|
||||||
|
\cleardoublepage
|
||||||
\printglossary[type=\acronymtype]
|
\printglossary
|
||||||
\cleardoublepage
|
|
||||||
|
|
||||||
\printglossary
|
|
||||||
\cleardoublepage
|
|
||||||
}%
|
|
||||||
{}
|
|
||||||
|
|
||||||
\ifthenelse{\equal{\@hidefigures}{true}}
|
|
||||||
{%
|
|
||||||
\excludecomment{figure}
|
|
||||||
\let\endfigure\relax
|
|
||||||
}%
|
|
||||||
{}
|
|
||||||
|
|
||||||
\ifthenelse{\equal{\@hidecode}{true}}
|
|
||||||
{%
|
|
||||||
\excludecomment{codeblock}
|
|
||||||
\let\endcodeblock\relax
|
|
||||||
}%
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
\cleardoublepage
|
||||||
\pagenumbering{arabic}
|
\pagenumbering{arabic}
|
||||||
}
|
}
|
||||||
|
% Document Content
|
||||||
{
|
{
|
||||||
\pagenumbering{gobble}
|
\pagenumbering{gobble}
|
||||||
\printbibliography % [heading=bibintoc]
|
\printbibliography % [heading=bibintoc]
|
||||||
@ -330,8 +305,8 @@
|
|||||||
|
|
||||||
\tcblistof[\chapter*]{listings}{List of Listings}
|
\tcblistof[\chapter*]{listings}{List of Listings}
|
||||||
% \addcontentsline{toc}{chapter}{List of Listings}
|
% \addcontentsline{toc}{chapter}{List of Listings}
|
||||||
%\cleardoublepage
|
\cleardoublepage
|
||||||
\clearpage
|
% \clearpage
|
||||||
|
|
||||||
% The lof/lot linespacing should match the lol linespacing
|
% The lof/lot linespacing should match the lol linespacing
|
||||||
\setlength{\cftparskip}{2pt}
|
\setlength{\cftparskip}{2pt}
|
||||||
@ -339,24 +314,24 @@
|
|||||||
\ifthenelse{\equal{\@listoftablesenabled}{true}}
|
\ifthenelse{\equal{\@listoftablesenabled}{true}}
|
||||||
{%
|
{%
|
||||||
\listoftables
|
\listoftables
|
||||||
%\cleardoublepage
|
\cleardoublepage
|
||||||
\clearpage
|
% \clearpage
|
||||||
}%
|
}%
|
||||||
{}
|
{}
|
||||||
|
|
||||||
\ifthenelse{\equal{\@listoffiguresenabled}{true}}
|
\ifthenelse{\equal{\@listoffiguresenabled}{true}}
|
||||||
{%
|
{%
|
||||||
\listoffigures
|
\listoffigures
|
||||||
%\cleardoublepage
|
\cleardoublepage
|
||||||
\clearpage
|
% \clearpage
|
||||||
}%
|
}%
|
||||||
{}
|
{}
|
||||||
|
|
||||||
\ifthenelse{\equal{\@listofalgorithmsenabled}{true}}
|
\ifthenelse{\equal{\@listofalgorithmsenabled}{true}}
|
||||||
{%
|
{%
|
||||||
\listofalgorithms
|
\listofalgorithms
|
||||||
%\cleardoublepage
|
\cleardoublepage
|
||||||
\clearpage
|
% \clearpage
|
||||||
}%
|
}%
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -439,7 +414,6 @@
|
|||||||
|
|
||||||
\newcommand{\literature}
|
\newcommand{\literature}
|
||||||
{
|
{
|
||||||
% Why is this here twice?
|
|
||||||
% \bibliography{\literaturebibtexdatei}
|
% \bibliography{\literaturebibtexdatei}
|
||||||
% \bibliographystyle{plain}
|
% \bibliographystyle{plain}
|
||||||
|
|
||||||
|
@ -5,12 +5,10 @@
|
|||||||
shr ebx, 0x18
|
shr ebx, 0x18
|
||||||
mov edi, ebx ; Now the ID is in EDI
|
mov edi, ebx ; Now the ID is in EDI
|
||||||
|
|
||||||
; Load the prepared AP GDT
|
; Load the AP's prepared GDT and TSS
|
||||||
mov ebx, [boot_ap_gdts - boot_ap + startup_address]
|
mov ebx, [boot_ap_gdts - boot_ap + startup_address]
|
||||||
mov eax, [ebx + edi * 0x4]
|
mov eax, [ebx + edi * 0x4]
|
||||||
lgdt [eax]
|
lgdt [eax]
|
||||||
|
|
||||||
; Load the TSS
|
|
||||||
mov ax, 0x28
|
mov ax, 0x28
|
||||||
ltr ax
|
ltr ax
|
||||||
|
|
||||||
|
@ -1,10 +1,5 @@
|
|||||||
// These variables are located in the startup routine's TEXT section
|
// Recycle values from the BSP
|
||||||
// and exported from smp_boot.asm.
|
|
||||||
|
|
||||||
// Use IDTR from the BSP
|
|
||||||
asm volatile("sidt %0" : "=m"(boot_ap_idtr));
|
asm volatile("sidt %0" : "=m"(boot_ap_idtr));
|
||||||
|
|
||||||
// Use cr0, cr3 and cr4 from the BSP
|
|
||||||
asm volatile("mov %%cr0, %%eax;" : "=a"(boot_ap_cr0));
|
asm volatile("mov %%cr0, %%eax;" : "=a"(boot_ap_cr0));
|
||||||
asm volatile("mov %%cr3, %%eax;" : "=a"(boot_ap_cr3));
|
asm volatile("mov %%cr3, %%eax;" : "=a"(boot_ap_cr3));
|
||||||
asm volatile("mov %%cr4, %%eax;" : "=a"(boot_ap_cr4));
|
asm volatile("mov %%cr4, %%eax;" : "=a"(boot_ap_cr4));
|
||||||
|
35
code/apic_def.cpp
Normal file
35
code/apic_def.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
// Excerpt from the Apic class definition
|
||||||
|
class Apic {
|
||||||
|
public:
|
||||||
|
// Enabling the APIC subsystem
|
||||||
|
static bool isSupported();
|
||||||
|
static bool isEnabled();
|
||||||
|
static void enable();
|
||||||
|
|
||||||
|
// Enabling SMP
|
||||||
|
static bool isSmpSupported();
|
||||||
|
static void startupSmp();
|
||||||
|
|
||||||
|
// Controlling the current core's local APIC
|
||||||
|
static void initializeCurrentLocalApic();
|
||||||
|
static uint8_t getCpuCount();
|
||||||
|
static LocalApic &getCurrentLocalApic();
|
||||||
|
static void enableCurrentErrorHandler();
|
||||||
|
|
||||||
|
// Controlling the current core's APIC timer
|
||||||
|
static bool isCurrentTimerRunning();
|
||||||
|
static void startCurrentTimer();
|
||||||
|
static ApicTimer &getCurrentTimer();
|
||||||
|
|
||||||
|
// Controlling the current core's interrupts
|
||||||
|
static void allow(InterruptRequest interruptRequest);
|
||||||
|
static void forbid(InterruptRequest interruptRequest);
|
||||||
|
static bool status(InterruptRequest interruptRequest);
|
||||||
|
static void sendEndOfInterrupt(InterruptVector vector);
|
||||||
|
static bool isLocalInterrupt(InterruptVector vector);
|
||||||
|
static bool isExternalInterrupt(InterruptVector vector);
|
||||||
|
|
||||||
|
// Tracking interrupt statistics
|
||||||
|
static void mountVirtualFilesystemNodes();
|
||||||
|
static void countInterrupt(InterruptVector vector);
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
void ApicErrorHandler::trigger(const InterruptFrame &frame) {
|
void ApicErrorHandler::trigger() {
|
||||||
// Write/read register: Write first, then read
|
|
||||||
// Writing the ESR updates its contents and arms the interrupt again
|
// Writing the ESR updates its contents and arms the interrupt again
|
||||||
LocalApic::writeDoubleWord(LocalApic::ESR, 0);
|
LocalApic::writeDoubleWord(LocalApic::ESR, 0);
|
||||||
uint32_t errors = LocalApic::readDoubleWord(LocalApic::ESR);
|
uint32_t errors = LocalApic::readDoubleWord(LocalApic::ESR);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// Excerpt from the APIC timer interrupt handler
|
// Excerpt from the ApicTimer interrupt handler
|
||||||
void ApicTimer::trigger(const InterruptFrame &frame) {
|
void ApicTimer::trigger(const InterruptFrame &frame) {
|
||||||
if (cpuId != LocalApic::getId()) {
|
if (cpuId != LocalApic::getId()) {
|
||||||
// Abort if the handler doesn't belong to the current CPU
|
// Abort if the handler doesn't belong to the current CPU
|
||||||
@ -7,4 +7,14 @@ void ApicTimer::trigger(const InterruptFrame &frame) {
|
|||||||
|
|
||||||
// Increase the "core-local" time
|
// Increase the "core-local" time
|
||||||
time.addNanoseconds(timerInterval * 1'000'000); // Interval is in milliseconds
|
time.addNanoseconds(timerInterval * 1'000'000); // Interval is in milliseconds
|
||||||
|
|
||||||
|
// Only the BSP may continue
|
||||||
|
if (cpuId != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trigger preemption
|
||||||
|
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||||
|
System::getService<SchedulerService>().yield();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,9 @@
|
|||||||
// Excerpt from the "InterruptDispatcher" class
|
// Excerpt from the "assign" function
|
||||||
void InterruptDispatcher::assign(uint8_t slot, InterruptHandler &isr) {
|
void InterruptDispatcher::assign(InterruptVector vec, InterruptHandler &handler) {
|
||||||
if (handler[slot] == nullptr) {
|
if (handlers[vec] == nullptr) {
|
||||||
handler[slot] = new Util::ArrayList<InterruptHandler*>;
|
// Make space for multiple possible interrupt handlers
|
||||||
|
handlers[vec] = new Util::ArrayList<InterruptHandler *>;
|
||||||
}
|
}
|
||||||
|
|
||||||
handler[slot]->add(&isr); // Register an interrupt handler to an interrupt vector
|
handlers[vec]->add(&handler); // Register a handler to a vector
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
// Excerpt from the "dispatch" function
|
// Excerpt from the "dispatch" function
|
||||||
interruptDepthWrapper.inc();
|
void InterruptDispatcher::dispatch(InterruptVector vec) {
|
||||||
interruptService.sendEndOfInterrupt(slot); // Signal interrupt servicing
|
interruptService.sendEndOfInterrupt(vec); // Signal interrupt servicing
|
||||||
asm volatile("sti"); // Allow cascaded interrupts
|
asm volatile("sti"); // Allow cascaded interrupts
|
||||||
|
|
||||||
uint32_t size = handlerList->size();
|
auto *handlerList = handlers[vec];
|
||||||
for (uint32_t i = 0; i < size; i++) {
|
for (uint32_t i = 0; i < handlerList->size(); i++) {
|
||||||
handlerList->get(i)->trigger(frame); // Call registered interrupt handlers
|
handlerList->get(i)->trigger(); // Call registered interrupt handlers
|
||||||
}
|
}
|
||||||
|
|
||||||
asm volatile("cli");
|
asm volatile("cli");
|
||||||
interruptDepthWrapper.dec();
|
}
|
@ -1,5 +1,7 @@
|
|||||||
// Excerpt from the "dispatch" function
|
// Excerpt from the "dispatch" function
|
||||||
if (interruptService.checkSpuriousInterrupt(slot)) {
|
void InterruptDispatcher::dispatch(InterruptVector vec) {
|
||||||
spuriousCounterWrapper.inc();
|
if (interruptService.checkSpuriousInterrupt(slot)) {
|
||||||
return; // Early return to skip the calling of any handlers
|
spuriousCounterWrapper.inc();
|
||||||
|
return; // Early return to skip the calling of any handlers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
// Excerpt from the "InterruptHandler" class definition
|
// Excerpt from the "InterruptHandler" interface
|
||||||
|
class InterruptHandler {
|
||||||
public:
|
public:
|
||||||
virtual void plugin() = 0; // Register the handler
|
virtual void plugin() = 0; // Register the handler
|
||||||
virtual void trigger(const InterruptFrame &frame) = 0; // Handle an interrupt
|
virtual void trigger(const InterruptFrame &frame) = 0; // Handle an interrupt
|
||||||
|
};
|
||||||
|
5
code/ioapic_allow.cpp
Normal file
5
code/ioapic_allow.cpp
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
void IoApic::allow(GlobalSystemInterrupt gsi) {
|
||||||
|
REDTBLEntry redtblEntry = readREDTBL(gsi);
|
||||||
|
redtblEntry.isMasked = false;
|
||||||
|
writeREDTBL(gsi, redtblEntry);
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
struct IrqOverride {
|
struct IrqOverride {
|
||||||
InterruptRequest source;
|
InterruptRequest source;
|
||||||
GlobalSystemInterrupt target;
|
GlobalSystemInterrupt target;
|
||||||
REDTBLEntry::PinPolarity polarity;
|
REDTBLEntry::PinPolarity polarity;
|
||||||
REDTBLEntry::TriggerMode trigger;
|
REDTBLEntry::TriggerMode trigger;
|
||||||
};
|
};
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
void Pit::trigger(const InterruptFrame &frame) {
|
void Pit::trigger() {
|
||||||
time.addNanoseconds(timerInterval); // Increase system time
|
time.addNanoseconds(timerInterval); // Increase system time
|
||||||
|
|
||||||
// Don't use PIT for scheduling when the APIC timer is enabled
|
// Don't use PIT for scheduling when the APIC timer is enabled
|
||||||
|
12
code/pit_early_delay.cpp
Normal file
12
code/pit_early_delay.cpp
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
// Excerpt from the "earlyDelay" function
|
||||||
|
void Pit::earlyDelay(uint16_t us) {
|
||||||
|
uint32_t counter = (static_cast<double>(BASE_FREQUENCY) / 1'000'000) * us;
|
||||||
|
|
||||||
|
controlPort.writeByte(0b110000); // Channel 0, mode 0
|
||||||
|
dataPort0.writeByte(static_cast<uint8_t>(counter & 0xFF)); // Low byte
|
||||||
|
dataPort0.writeByte(static_cast<uint8_t>((counter >> 8) & 0xFF)); // High byte
|
||||||
|
|
||||||
|
do {
|
||||||
|
controlPort.writeByte(0b11100010); // Readback channel 0
|
||||||
|
} while (!(dataPort0.readByte() & (1 << 7))); // Bit 7 is the output pin state
|
||||||
|
}
|
@ -1,7 +1,8 @@
|
|||||||
// Excerpt from the "Pit" interrupt handler
|
// Excerpt from the "Pit" interrupt handler
|
||||||
void Pit::trigger(const InterruptFrame &frame) {
|
void Pit::trigger() {
|
||||||
time.addNanoseconds(timerInterval); // Increase system time
|
time.addNanoseconds(timerInterval); // Increase system time
|
||||||
|
|
||||||
|
// Trigger preemption
|
||||||
if (time.toMilliseconds() % yieldInterval == 0) {
|
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||||
System::getService<SchedulerService>().yield(); // Trigger preemption
|
System::getService<SchedulerService>().yield(); // Trigger preemption
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
// Excerpt from System::initializeSystem(). Located before interrupts
|
// Excerpt from the "initializeSystem" function
|
||||||
// are enabled and any devices have registered their handlers.
|
void System::initializeSystem() {
|
||||||
if (Apic::isSupported()) {
|
if (Apic::isSupported()) {
|
||||||
Apic::enable();
|
Apic::enable();
|
||||||
|
|
||||||
if (Apic::isSmpSupported()) {
|
if (Apic::isSmpSupported()) {
|
||||||
Apic::startupSmp();
|
Apic::startupSmp();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
Cpu::enableInterrupts();
|
||||||
|
}
|
||||||
|
58
diagrams/apic_enable_seq.puml
Normal file
58
diagrams/apic_enable_seq.puml
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
@startuml
|
||||||
|
'https://plantuml.com/sequence-diagram
|
||||||
|
|
||||||
|
title Apic::enable()
|
||||||
|
|
||||||
|
participant Apic
|
||||||
|
participant Acpi
|
||||||
|
participant LocalApic
|
||||||
|
participant IoApic
|
||||||
|
participant ApicErrorHandler
|
||||||
|
participant ApicTimer
|
||||||
|
|
||||||
|
==Prepare Initialization==
|
||||||
|
|
||||||
|
group Create Devices
|
||||||
|
Apic -[hidden]> ApicTimer
|
||||||
|
Apic -> Acpi: Request system information
|
||||||
|
Apic <- Acpi: Provide MADT structures
|
||||||
|
Apic -> LocalApic ++: Instantiate LocalApic
|
||||||
|
Apic -> IoApic ++: Instantiate IoApic
|
||||||
|
end
|
||||||
|
|
||||||
|
group Initialize Local APIC
|
||||||
|
Apic -[hidden]> ApicTimer
|
||||||
|
Apic -> LocalApic: Enable xApic mode
|
||||||
|
LocalApic -> LocalApic: Set IMCR
|
||||||
|
LocalApic -> LocalApic: MMIO allocation
|
||||||
|
==Actual Component Initialization==
|
||||||
|
Apic -> LocalApic: Initialize current local APIC
|
||||||
|
LocalApic -> LocalApic: Set LVT and NMI
|
||||||
|
LocalApic -> LocalApic: Set spurious vector
|
||||||
|
LocalApic -> LocalApic: Synchronize APR
|
||||||
|
LocalApic -> LocalApic: Allow all priorities
|
||||||
|
end
|
||||||
|
|
||||||
|
group Initialize I/O APIC
|
||||||
|
Apic -[hidden]> ApicTimer
|
||||||
|
Apic -> IoApic: Initialize I/O APIC
|
||||||
|
IoApic -> IoApic: MMIO allocation
|
||||||
|
IoApic -> IoApic: Set REDTBL, NMI
|
||||||
|
end
|
||||||
|
|
||||||
|
group Initialize APIC error handler
|
||||||
|
Apic -[hidden]> ApicTimer
|
||||||
|
Apic -> ApicErrorHandler ++: Instantiate handler
|
||||||
|
Apic -> ApicErrorHandler: Register the interrupt handler
|
||||||
|
Apic -> LocalApic: Allow current error interrupt
|
||||||
|
Apic -> LocalApic: Arm error interrupt
|
||||||
|
end
|
||||||
|
|
||||||
|
group Initialize APIC timer
|
||||||
|
Apic -[hidden]> ApicTimer
|
||||||
|
Apic -> ApicTimer: Calibrate the timer
|
||||||
|
Apic -> ApicTimer ++: Instantiate current timer
|
||||||
|
Apic -> ApicTimer: Register current interrupt handler
|
||||||
|
LocalApic <- ApicTimer: Allow current timer interrupt
|
||||||
|
end
|
||||||
|
@enduml
|
1
diagrams/apic_enable_seq.svg
Normal file
1
diagrams/apic_enable_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 20 KiB |
44
diagrams/apic_smp_enable_seq.puml
Normal file
44
diagrams/apic_smp_enable_seq.puml
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
@startuml
|
||||||
|
'https://plantuml.com/sequence-diagram
|
||||||
|
|
||||||
|
title Apic::startupSmp() for a single AP
|
||||||
|
footer The Application Processor lifetime symbolizes the AP's expected online state for the xApic architecture.
|
||||||
|
|
||||||
|
participant Apic
|
||||||
|
participant GDT as "AP GDT"
|
||||||
|
participant Stack as "AP Stack"
|
||||||
|
participant 0x8000 as "AP Boot Routine"
|
||||||
|
participant LocalApic
|
||||||
|
participant smp_entry as "Application Processor"
|
||||||
|
|
||||||
|
Apic -> GDT ++: Prepare AP GDT
|
||||||
|
Apic -> Stack ++: Allocate AP stack
|
||||||
|
|
||||||
|
group Prepare AP Boot Routine
|
||||||
|
Apic -[hidden]> smp_entry
|
||||||
|
Apic -> 0x8000 ++: Allocate physical memory at 0x8000
|
||||||
|
Apic -> Apic: Initialize smp_boot variables
|
||||||
|
Apic -> 0x8000: Copy smp_boot to 0x8000
|
||||||
|
end
|
||||||
|
|
||||||
|
Apic -> Apic: Prepare warm reset
|
||||||
|
|
||||||
|
group Universal Startup Algorithm
|
||||||
|
Apic -> LocalApic: Send INIT IPI
|
||||||
|
LocalApic -> smp_entry: INIT
|
||||||
|
...10 ms...
|
||||||
|
Apic -> LocalApic: Send SIPI
|
||||||
|
LocalApic -> smp_entry ++: STARTUP
|
||||||
|
...200 us...
|
||||||
|
Apic -> LocalApic: Send SIPI
|
||||||
|
LocalApic -> smp_entry: STARTUP
|
||||||
|
...200 us...
|
||||||
|
end
|
||||||
|
|
||||||
|
Apic <- smp_entry: Initialize AP's local APIC
|
||||||
|
Apic <- smp_entry: Initialize AP's APIC timer
|
||||||
|
Apic <- smp_entry: Initialize AP's APIC error handler
|
||||||
|
Apic <- smp_entry: Signal boot completion
|
||||||
|
Apic -> 0x8000 !!: Free physical memory at 0x8000
|
||||||
|
|
||||||
|
@enduml
|
1
diagrams/apic_smp_enable_seq.svg
Normal file
1
diagrams/apic_smp_enable_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 28 KiB |
19
diagrams/interrupt_seq.puml
Normal file
19
diagrams/interrupt_seq.puml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
@startuml
|
||||||
|
'https://plantuml.com/sequence-diagram
|
||||||
|
|
||||||
|
title Interrupt Handler Execution
|
||||||
|
footer The lifetimes symbolize the current code execution by the CPU.
|
||||||
|
|
||||||
|
participant main as "Main Thread"
|
||||||
|
participant handler as "Interrupt Handler"
|
||||||
|
|
||||||
|
==Interrupt Request==
|
||||||
|
activate main
|
||||||
|
main -> handler --: Switch context to interrupt handler
|
||||||
|
activate handler
|
||||||
|
handler -> handler: Handle the interrupt
|
||||||
|
main <- handler --: Switch back to previous context
|
||||||
|
activate main
|
||||||
|
==Interrupt Handled==
|
||||||
|
|
||||||
|
@enduml
|
1
diagrams/interrupt_seq.svg
Normal file
1
diagrams/interrupt_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.4 KiB |
152
glossary.tex
152
glossary.tex
@ -1,10 +1,10 @@
|
|||||||
\makeglossaries
|
\makeglossaries{}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Acronyms
|
% Acronyms
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
\newacronym{acpi}{ACPI}{\gls{advanced configuration and power interface}}
|
\newacronym{acpi}{ACPI}{advanced configuration and power interface}
|
||||||
\newacronym{aml}{AML}{acpi machine language}
|
\newacronym{aml}{AML}{acpi machine language}
|
||||||
\newacronym{ap}{AP}{\gls{application processor}}
|
\newacronym{ap}{AP}{\gls{application processor}}
|
||||||
\newacronym{apr}{APR}{arbitration priority register}
|
\newacronym{apr}{APR}{arbitration priority register}
|
||||||
@ -12,7 +12,7 @@
|
|||||||
\newacronym{bios}{BIOS}{basic input/output system}
|
\newacronym{bios}{BIOS}{basic input/output system}
|
||||||
\newacronym{bsp}{BSP}{\gls{bootstrap processor}}
|
\newacronym{bsp}{BSP}{\gls{bootstrap processor}}
|
||||||
\newacronym{cpuid}{CPUID}{cpu identification}
|
\newacronym{cpuid}{CPUID}{cpu identification}
|
||||||
\newacronym{eoi}{EOI}{\gls{end-of-interrupt}}
|
\newacronym{eoi}{EOI}{end of interrupt}
|
||||||
\newacronym{esr}{ESR}{error status register}
|
\newacronym{esr}{ESR}{error status register}
|
||||||
\newacronym{gdt}{GDT}{global descriptor table}
|
\newacronym{gdt}{GDT}{global descriptor table}
|
||||||
\newacronym{gdtr}{GDTR}{global descriptor table register}
|
\newacronym{gdtr}{GDTR}{global descriptor table register}
|
||||||
@ -34,14 +34,14 @@
|
|||||||
\newacronym{mmio}{MMIO}{memory mapped input/output}
|
\newacronym{mmio}{MMIO}{memory mapped input/output}
|
||||||
\newacronym{msr}{MSR}{model specific register}
|
\newacronym{msr}{MSR}{model specific register}
|
||||||
\newacronym{msi}{MSI}{\gls{message-signaled interrupt}}
|
\newacronym{msi}{MSI}{\gls{message-signaled interrupt}}
|
||||||
\newacronym{nmi}{NMI}{\gls{non-maskable interrupt}}
|
\newacronym{nmi}{NMI}{non-maskable interrupt}
|
||||||
\newacronym{pci}{PCI}{peripheral component interconnect}
|
\newacronym{pci}{PCI}{peripheral component interconnect}
|
||||||
\newacronym{pic}{PIC}{programmable interrupt controller}
|
\newacronym{pic}{PIC}{programmable interrupt controller}
|
||||||
\newacronym{pit}{PIT}{\gls{programmable interval timer}}
|
\newacronym{pit}{PIT}{programmable interval timer}
|
||||||
\newacronym{redtbl}{REDTBL}{redirection table}
|
\newacronym{redtbl}{REDTBL}{redirection table}
|
||||||
\newacronym{sipi}{SIPI}{startup inter-processor interrupt}
|
\newacronym{sipi}{SIPI}{startup inter-processor interrupt}
|
||||||
\newacronym{smi}{SMI}{system management interrupt}
|
\newacronym{smi}{SMI}{system management interrupt}
|
||||||
\newacronym{smp}{SMP}{\gls{symmetric multiprocessing}}
|
\newacronym{smp}{SMP}{symmetric multiprocessing}
|
||||||
\newacronym{svr}{SVR}{\gls{spurious interrupt vector register}}
|
\newacronym{svr}{SVR}{\gls{spurious interrupt vector register}}
|
||||||
\newacronym{tmr}{TMR}{trigger-mode register}
|
\newacronym{tmr}{TMR}{trigger-mode register}
|
||||||
\newacronym{tpr}{TPR}{\gls{task-priority register}}
|
\newacronym{tpr}{TPR}{\gls{task-priority register}}
|
||||||
@ -57,187 +57,107 @@
|
|||||||
% description={}
|
% description={}
|
||||||
% }
|
% }
|
||||||
|
|
||||||
\newglossaryentry{advanced configuration and power interface}{
|
\newglossaryentry{apic timer}{%
|
||||||
name={advanced configuration and power interface},
|
|
||||||
description={a standard for operating systems to allow software to query information about the system hardware configuration}
|
|
||||||
}
|
|
||||||
\newglossaryentry{apic timer}{
|
|
||||||
name={APIC timer},
|
name={APIC timer},
|
||||||
description={a hardware timer that can trigger periodic interrupts by using a counter, integrated into the local APIC}
|
description={a hardware timer that can trigger periodic interrupts by using a counter, integrated into the local APIC}
|
||||||
}
|
}
|
||||||
\newglossaryentry{application processor}{
|
\newglossaryentry{application processor}{%
|
||||||
name={application processor},
|
name={application processor},
|
||||||
description={a processor inside an SMP system, e.g. a CPU core}
|
description={a processor inside an SMP system, e.g.\ a CPU core}
|
||||||
}
|
}
|
||||||
\newglossaryentry{bootstrap processor}{
|
\newglossaryentry{bootstrap processor}{%
|
||||||
name={bootstrap processor},
|
name={bootstrap processor},
|
||||||
description={the application processor used to boot an SMP system}
|
description={the application processor used to boot an SMP system}
|
||||||
}
|
}
|
||||||
\newglossaryentry{cascaded interrupt}{
|
\newglossaryentry{discrete apic}{%
|
||||||
name={cascaded interrupt},
|
name={discrete APIC},
|
||||||
description={an interrupt, serviced during another interrupt handler}
|
description={the predecessor of the xApic architecture where the local APIC was not integrated into the CPU core, register access is handled through MMIO}
|
||||||
}
|
}
|
||||||
\newglossaryentry{end-of-interrupt}{
|
\newglossaryentry{global system interrupt}{%
|
||||||
name={end-of-interrupt},
|
|
||||||
description={a notification to an interrupt controller that an interrupt has been handled}
|
|
||||||
}
|
|
||||||
\newglossaryentry{external interrupt}{
|
|
||||||
name={external interrupt},
|
|
||||||
description={an interrupt from an external hardware device}
|
|
||||||
}
|
|
||||||
\newglossaryentry{global system interrupt}{
|
|
||||||
name={global system interrupt},
|
name={global system interrupt},
|
||||||
description={an abstraction used by ACPI to decouple interrupts from hardware interrupt lines}
|
description={an abstraction used by ACPI to decouple interrupts from hardware interrupt lines}
|
||||||
}
|
}
|
||||||
\newglossaryentry{ia32 apic base msr}{
|
\newglossaryentry{io apic}{%
|
||||||
name={IA32\textunderscore{}APIC\textunderscore{}BASE MSR},
|
|
||||||
description={an x86 architectural MSR that contains the local APIC's physical MMIO address and the xApic global enable/disable flag}
|
|
||||||
}
|
|
||||||
\newglossaryentry{io apic}{
|
|
||||||
name={I/O APIC},
|
name={I/O APIC},
|
||||||
description={a part of the APIC architecture inside the chipset, responsible for receiving external interrupts}
|
description={a part of the APIC architecture inside the chipset, responsible for receiving external interrupts}
|
||||||
}
|
}
|
||||||
\newglossaryentry{init ipi}{
|
\newglossaryentry{init ipi}{%
|
||||||
name={INIT IPI},
|
name={INIT IPI},
|
||||||
description={an interprocessor interrupt sent from the BSP to the APs, to begin the AP initialization process}
|
description={an interprocessor interrupt sent from the BSP to the APs, to begin the AP initialization process}
|
||||||
}
|
}
|
||||||
\newglossaryentry{inter-processor interrupt}{
|
\newglossaryentry{inter-processor interrupt}{%
|
||||||
name={inter-processor interrupt},
|
name={inter-processor interrupt},
|
||||||
description={an interrupt sent between CPU cores}
|
description={an interrupt sent between CPU cores}
|
||||||
}
|
}
|
||||||
\newglossaryentry{interrupt}{
|
\newglossaryentry{interrupt command register}{%
|
||||||
name={interrupt},
|
|
||||||
description={a request for the CPU to handle an event}
|
|
||||||
}
|
|
||||||
\newglossaryentry{interrupt command register}{
|
|
||||||
name={interrupt command register},
|
name={interrupt command register},
|
||||||
description={a register of the local APIC used to issue interprocessor interrupts}
|
description={a register of the local APIC used to issue interprocessor interrupts}
|
||||||
}
|
}
|
||||||
\newglossaryentry{interrupt controller}{
|
\newglossaryentry{interrupt mode control register}{%
|
||||||
name={interrupt controller},
|
|
||||||
description={a hardware component designated to receive interrupts and forward them to the CPU}
|
|
||||||
}
|
|
||||||
\newglossaryentry{interrupt handler}{
|
|
||||||
name={interrupt handler},
|
|
||||||
description={a function designated to handle a specific interrupt}
|
|
||||||
}
|
|
||||||
\newglossaryentry{interrupt mode control register}{
|
|
||||||
name={interrupt mode control register},
|
name={interrupt mode control register},
|
||||||
description={a register present in some systems to choose the physically connected interrupt controller}
|
description={a register present in some systems to choose the physically connected interrupt controller}
|
||||||
}
|
}
|
||||||
\newglossaryentry{interrupt priority}{
|
\newglossaryentry{interrupt request register}{%
|
||||||
name={interrupt priority},
|
|
||||||
description={the interrupt priority decides the order, in which multiple, simultaneously arriving interrupts, are forwarded to the CPU}
|
|
||||||
}
|
|
||||||
\newglossaryentry{interrupt vector}{
|
|
||||||
name={interrupt vector},
|
|
||||||
description={a slot of an interrupt handler in the IDT}
|
|
||||||
}
|
|
||||||
\newglossaryentry{interrupt request register}{
|
|
||||||
name={interrupt request register},
|
name={interrupt request register},
|
||||||
description={a register, part of the PIC and local APIC, which keeps track of received interrupts}
|
description={a register, part of the PIC and local APIC, which keeps track of received interrupts}
|
||||||
}
|
}
|
||||||
\newglossaryentry{in-service register}{
|
\newglossaryentry{in-service register}{%
|
||||||
name={in-service register},
|
name={in-service register},
|
||||||
description={a register, part of the PIC and local APIC, which keeps track of interrupts that are being serviced}
|
description={a register, part of the PIC and local APIC, which keeps track of interrupts that are being serviced}
|
||||||
}
|
}
|
||||||
\newglossaryentry{irq override}{
|
\newglossaryentry{irq override}{%
|
||||||
name={IRQ override},
|
name={interrupt override},
|
||||||
description={information from ACPI, that describes how interrupt lines correspond to global system interrupts}
|
description={information from ACPI, that describes how interrupt lines correspond to global system interrupts}
|
||||||
}
|
}
|
||||||
\newglossaryentry{local apic}{
|
\newglossaryentry{local apic}{%
|
||||||
name={local APIC},
|
name={local APIC},
|
||||||
description={a part of the APIC architecture inside a CPU core, responsible for receiving local interrupts and communication with the I/O APIC}
|
description={a part of the APIC architecture inside a CPU core, responsible for receiving local interrupts and communication with the I/O APIC}
|
||||||
}
|
}
|
||||||
\newglossaryentry{local interrupt}{
|
\newglossaryentry{local interrupt}{%
|
||||||
name={local interrupt},
|
name={local interrupt},
|
||||||
description={an CPU internal interrupt handled by the local APIC, like the APIC timer interrupt}
|
description={an CPU internal interrupt handled by the local APIC, like the APIC timer interrupt}
|
||||||
}
|
}
|
||||||
\newglossaryentry{local vector table}{
|
\newglossaryentry{local vector table}{%
|
||||||
name={local vector table},
|
name={local vector table},
|
||||||
description={a set of registers, part of the local APIC, that configure how local interrupts are handled}
|
description={a set of registers, part of the local APIC, that configure how local interrupts are handled}
|
||||||
}
|
}
|
||||||
\newglossaryentry{masking}{
|
\newglossaryentry{message-signaled interrupt}{%
|
||||||
name={masking},
|
|
||||||
description={marking an interrupt as ignored}
|
|
||||||
}
|
|
||||||
\newglossaryentry{memory-mapped io}{
|
|
||||||
name={memory-mapped I/O},
|
|
||||||
description={a way to access a devices registers by mapping them to addresses in the main memory}
|
|
||||||
}
|
|
||||||
\newglossaryentry{message-signaled interrupt}{
|
|
||||||
name={message-signaled interrupt},
|
name={message-signaled interrupt},
|
||||||
description={an interrupt sent in-band over a PCI-bus}
|
description={an interrupt sent in-band over a PCI-bus}
|
||||||
}
|
}
|
||||||
\newglossaryentry{non-maskable interrupt}{
|
\newglossaryentry{pic mode}{%
|
||||||
name={non-maskable interrupt},
|
|
||||||
description={a system critical interrupt that cannot be masked}
|
|
||||||
}
|
|
||||||
\newglossaryentry{pcat pic architecture}{
|
|
||||||
name={PC/AT PIC architecture},
|
|
||||||
description={an interrupt controller configuration using two cascaded PICs for a total of 15 interrupt lines}
|
|
||||||
}
|
|
||||||
\newglossaryentry{pic mode}{
|
|
||||||
name={PIC mode},
|
name={PIC mode},
|
||||||
description={only use the PIC for interrupt handling, like the PC/AT}
|
description={only use the PIC for interrupt handling, like the PC/AT}
|
||||||
}
|
}
|
||||||
\newglossaryentry{pin polarity}{
|
\newglossaryentry{redirection table}{%
|
||||||
name={pin polarity},
|
|
||||||
description={describes if a signal is represented by either a high or low level change or theshold}
|
|
||||||
}
|
|
||||||
\newglossaryentry{programmable interval timer}{
|
|
||||||
name={programmable interval timer},
|
|
||||||
description={a hardware timer that can trigger periodic interrupts by using a counter}
|
|
||||||
}
|
|
||||||
\newglossaryentry{protected mode}{
|
|
||||||
name={protected mode},
|
|
||||||
description={the 32-bit operating mode of x86 CPUs which includes security features such as paging}
|
|
||||||
}
|
|
||||||
\newglossaryentry{real mode}{
|
|
||||||
name={real mode},
|
|
||||||
description={an operating mode of x86 CPUs with 16-bit segmented memory addressing, resulting in 1 MB of usable memory with 20-bit address width}
|
|
||||||
}
|
|
||||||
\newglossaryentry{redirection table}{
|
|
||||||
name={redirection table},
|
name={redirection table},
|
||||||
description={a set of registers, part of the I/O APIC, that configure how external interrupts are handled}
|
description={a set of registers, part of the I/O APIC, that configure how external interrupts are handled}
|
||||||
}
|
}
|
||||||
\newglossaryentry{spurious interrupt}{
|
\newglossaryentry{spurious interrupt vector register}{%
|
||||||
name={spurious interrupt},
|
|
||||||
description={an interrupt that is triggered in case an original interrupt is no longer valid on delivery}
|
|
||||||
}
|
|
||||||
\newglossaryentry{spurious interrupt vector register}{
|
|
||||||
name={spurious interrupt vector register},
|
name={spurious interrupt vector register},
|
||||||
description={a register of the local APIC which contains the APIC software enable flag and the spurious interrupt vector}
|
description={a register of the local APIC which contains the APIC software enable flag and the spurious interrupt vector}
|
||||||
}
|
}
|
||||||
\newglossaryentry{startup ipi}{
|
\newglossaryentry{startup ipi}{%
|
||||||
name={STARTUP IPI},
|
name={STARTUP IPI},
|
||||||
description={an interprocessor interrupt sent from the BSP to the APs, to load the AP startup routine and finish AP initialization}
|
description={an interprocessor interrupt sent from the BSP to the APs, to load the AP startup routine and finish AP initialization}
|
||||||
}
|
}
|
||||||
\newglossaryentry{symmetric io mode}{
|
\newglossaryentry{symmetric io mode}{%
|
||||||
name={symmetric I/O mode},
|
name={symmetric I/O mode},
|
||||||
description={use the I/O APIC in combination with the local APIC for interrupt handling in multiprocessor systems}
|
description={use the I/O APIC in combination with the local APIC for interrupt handling in multiprocessor systems}
|
||||||
}
|
}
|
||||||
\newglossaryentry{symmetric multiprocessing}{
|
\newglossaryentry{task-priority register}{%
|
||||||
name={symmetric multiprocessing},
|
|
||||||
description={a computer architecture where multiple CPUs operate on a shared main memory}
|
|
||||||
}
|
|
||||||
\newglossaryentry{task-priority register}{
|
|
||||||
name={task-priority register},
|
name={task-priority register},
|
||||||
description={a register of the local APIC which determines interrupt handling order and priority theshold}
|
description={a register of the local APIC which determines interrupt handling order and priority theshold}
|
||||||
}
|
}
|
||||||
\newglossaryentry{trigger mode}{
|
\newglossaryentry{virtual wire mode}{%
|
||||||
name={trigger mode},
|
|
||||||
description={describes if a signal is represented by either a change in level or a level theshold}
|
|
||||||
}
|
|
||||||
\newglossaryentry{virtual wire mode}{
|
|
||||||
name={virtual wire mode},
|
name={virtual wire mode},
|
||||||
description={use the local APIC in combination with the PIC as external interrupt controller}
|
description={use the local APIC in combination with the PIC as external interrupt controller}
|
||||||
}
|
}
|
||||||
\newglossaryentry{xapic}{
|
\newglossaryentry{xapic}{%
|
||||||
name={xApic},
|
name={xApic},
|
||||||
description={a revision of the APIC architecture, register access is handled through MMIO}
|
description={a revision of the APIC architecture, register access is handled through MMIO}
|
||||||
}
|
}
|
||||||
\newglossaryentry{x2apic}{
|
\newglossaryentry{x2apic}{%
|
||||||
name={x2Apic},
|
name={x2Apic},
|
||||||
description={a revision of the APIC architecture, register access is handled through MSRs}
|
description={a revision of the APIC architecture, register access is handled through MSRs}
|
||||||
}
|
}
|
||||||
|
1
img/ApicTimerHandler.drawio
Normal file
1
img/ApicTimerHandler.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2023-03-01T15:38:29.975Z" agent="5.0 (X11)" etag="lMw5qLzuehWTyToD7hYz" version="20.8.23"><diagram name="Page-1" id="GcggYPQxszAjPQo6ng4k">7Vlbk5owFP41Pm6Hm0gfV9deZmzHGbrT7r5FOEJaIGwIiv31TTAR2VSHzlahnX0RzpeT2/nO+Qg4smdp9Z6iPP5EQkhGlhFWI/tuZFnmxLH4RSA7iRiOs0ciikOJNYCPf4JylGiJQyhajoyQhOG8DQYkyyBgLQxRSrZttzVJ2rPmKAIN8AOU6OhXHLJ4j3pjo8E/AI5iNbNpyJYUKWcJFDEKyfYIsucje0YJYfu7tJpBIqKn4rLv9+5E62FhFDLWpcN8+fS4cJeeT9Z2Wr1d3htT/0aSUbCd2jCEfP/SJJTFJCIZSuYNOqWkzEIQoxrcanwWhOQcNDn4HRjbSTJRyQiHYpYmspUvmO6+if5vxsp8kMPVxl3VsnbSWpOMyUFNj9v7tYsFnwyJhApS0gDOxEGlFqIRsDN+1oE4nvJAUuDr4/0oJIjhTXsdSKZedPBr2OE3kqA/IEuOu0FJKWcaWW7ClzsN8abFovtUirSqI3ZT1CG75Q6ml1d13FQ7v4vEdUF4xov94xSoWEbGgNIyZ2qCFVWuCuE7qGdV6LM0apJEML6NMQM/RzUHWy4V7YT4PbEboAyq89TqVMgOlqpDJTyutLdNFZuqNOOjClZ+f529ycXY+0w6knLV2m5VdlPo169tq2Ntu73WtqGlxwN/7r2UweIHsCD+r6S6K51en3RaGptfpLSuICFZVNTnGP4zW96f0U5jENpp9a6drhbO2xXP5sE9dZzBRc60eteQC2qB11ELzBO0XUcMPC17P2YBhVRsV7y5ULgRB6/B68Ahu/vLZkcLpTj8DOYhOZgzj9n1hca0ez316ML+eup5IaHjXgnV31FPHHym/nLwgjfuX/Dsf/TkM4DQea86ckoeuujIpFcdGes6QnEU1UqSU4A0Z5hkg1cQ1+m9DPTvTsNUkOehm1wwdNxsPrzXbUf/X9jzXw==</diagram></mxfile>
|
1224
img/ApicTimerHandler.svg
Normal file
1224
img/ApicTimerHandler.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 62 KiB |
1
img/Architecture.drawio
Normal file
1
img/Architecture.drawio
Normal file
@ -0,0 +1 @@
|
|||||||
|
<mxfile host="app.diagrams.net" modified="2023-03-02T13:45:01.329Z" agent="5.0 (X11)" etag="-uXxVCLlOb1aSAnoL_Ac" version="20.8.23" type="device"><diagram name="Page-1" id="GcggYPQxszAjPQo6ng4k">7VlNc5swEP01HNNBCGN6xB9JPE2bdpJJm95kUIAOICKEgfz6CiwZGGzXTW1DOjnBvl2k1Vu9xcgKnIb5FUWx95k4OFA01ckVOFM0DYx1jV9KpBCIqutrxKW+I7AauPNfsAwUaOo7OGkFMkIC5sdt0CZRhG3WwhClJGuHPZGgPWuMXNwB7mwUdNHvvsO8NWqO1Bq/xr7ryZmBKjwhksECSDzkkKwBwbkCp5QQtr4L8ykOSvYkL+vnLnd4N4lRHLFDHpgby2/3S+MhTyd+oYfP1s/i4UKMskJBKhZ8Q/jiOWR9XUz55RpRJ+NziDWwQhJDSRo5uBwbKHCSeT7DdzGyS2/G9wLHPBYGwv1EIiZqC0xud3OXiWDKcN6AxFquMAkxowUPEV4oeRU7a2wIO6vLBGSM1yiRjENiZ7iboWvy+I3g72+4HHdIwg7fTMIklHnEJREK5jU6qWlUuVXH3BASC/J+YcYKwR5KGXkltQlJqY335C+kyhB1MfvzninXtrdQFAeI+au2kI7OutbZwYpmBDz/ieOvWtUwntNSaxVjF0lFmcUDgBnnFW/Sz+/c8lopwYp9Ww7I86vGXLuPNc00QEmya4qdolMHITqjf9F97EN0nEFa/BDPV8ZjaXwYSXOWN52zQljHEys8UKxaX2J1LevFhSGyUHybe5emk8MvMpu+ilXX57FVnu3F2src0aq1lZ9eOyk8WSddkDO30SX9p7HeSDcGxtC68ea3bj8CB0pP3Vgfejfel/UJBF/K/d4PMX3X/JE1r5tD03wvP8BeL1XzQKnCQUkV9NJYT8/ysBoiAP8ny/qgWDZP+tp5f+Oc+Jt/1PsbB8C3JVNw6MmaOSidyrQbQv2EaVSe8A/8LFg/5xbd/SHfom7Bx7lVznKu3iFuC70Hf1Se8lydm/X/H5Wv8TcSnP8G</diagram></mxfile>
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 49 KiB |
@ -6,7 +6,7 @@
|
|||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Schlüsselwörter %
|
% Schlüsselwörter %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\thesiskeywords{Interrupt,APIC,hhuOS}
|
\thesiskeywords{x86, Interrupt, APIC, hhuOS}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Sprache der Arbeit %
|
% Sprache der Arbeit %
|
||||||
@ -31,12 +31,9 @@
|
|||||||
% true - Aktiviert %
|
% true - Aktiviert %
|
||||||
% false - Deaktiviert %
|
% false - Deaktiviert %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\glossaryenabled{true}
|
|
||||||
\listofalgorithmsenabled{false}
|
\listofalgorithmsenabled{false}
|
||||||
\listoffiguresenabled{true}
|
\listoffiguresenabled{true}
|
||||||
\listoftablesenabled{true}
|
\listoftablesenabled{true}
|
||||||
\hidefigures{false}
|
|
||||||
\hidecode{false}
|
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Vollständiger Name %
|
% Vollständiger Name %
|
||||||
@ -51,19 +48,19 @@
|
|||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Datum der Abgabe %
|
% Datum der Abgabe %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\submissiondate{March 15th, 2023}
|
\submissiondate{March 3rd, 2023}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Erstgutachter %
|
% Erstgutachter %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\firstreviewer{Prof. Dr. Michael Schöttner}
|
\firstreviewer{Prof.\ Dr.\ Michael Schöttner}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Zweitgutachter %
|
% Zweitgutachter %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\secondreviewer{Prof. Dr. Stefan Conrad}
|
\secondreviewer{Prof.\ Dr.\ Stefan Conrad}
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Betreuer %
|
% Betreuer %
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
\supervisor{M.Sc. Fabian Ruhland}
|
\supervisor{M.Sc.\ Fabian Ruhland}
|
||||||
|
41
thesis.tex
41
thesis.tex
@ -1,7 +1,7 @@
|
|||||||
% !TeX document-id = {631e44a8-cd91-47da-bf82-1571f8787194}
|
% !TeX document-id = {631e44a8-cd91-47da-bf82-1571f8787194}
|
||||||
% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
|
% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
|
||||||
|
|
||||||
\documentclass{class/thesis}
|
\documentclass{class/thesis} % [draft]
|
||||||
|
|
||||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
% Bitte ergänzen Sie Ihre persönlichen Daten innerhalb %
|
% Bitte ergänzen Sie Ihre persönlichen Daten innerhalb %
|
||||||
@ -12,34 +12,33 @@
|
|||||||
\include{glossary}
|
\include{glossary}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
|
||||||
% Capitalize all the names
|
|
||||||
\renewcommand{\figureautorefname}{Figure}
|
|
||||||
\renewcommand{\tableautorefname}{Table}
|
|
||||||
\renewcommand{\partautorefname}{Part} \renewcommand{\appendixautorefname}{Appendix}
|
|
||||||
\renewcommand{\chapterautorefname}{Chapter} \renewcommand{\sectionautorefname}{Section}
|
|
||||||
\renewcommand{\subsectionautorefname}{Section} \renewcommand{\subsubsectionautorefname}{Section}
|
|
||||||
\makeatletter\newcommand{\tcb@cnt@codeblockautorefname}{Listing}\makeatother
|
|
||||||
|
|
||||||
% \renewcommand{\clearpage}{}
|
|
||||||
% \renewcommand{\cleardoublepage}{}
|
|
||||||
|
|
||||||
\begin{thesis}
|
\begin{thesis}
|
||||||
|
|
||||||
|
% Detect overfull boxes % TODO: Should probably disable this before submitting
|
||||||
|
% \overfullrule=2cm
|
||||||
|
|
||||||
|
% Capitalize all the section names
|
||||||
|
\renewcommand{\figureautorefname}{Figure}
|
||||||
|
\renewcommand{\tableautorefname}{Table}
|
||||||
|
\renewcommand{\partautorefname}{Part}
|
||||||
|
\renewcommand{\appendixautorefname}{Appendix}
|
||||||
|
\renewcommand{\chapterautorefname}{Chapter}
|
||||||
|
\renewcommand{\sectionautorefname}{Section}
|
||||||
|
\renewcommand{\subsectionautorefname}{Section}
|
||||||
|
\renewcommand{\subsubsectionautorefname}{Section}
|
||||||
|
\makeatletter\newcommand{\tcb@cnt@codeblockautorefname}{Listing}\makeatother
|
||||||
|
|
||||||
|
% Chapters
|
||||||
\include{chap/introduction}
|
\include{chap/introduction}
|
||||||
\include{chap/background}
|
\include{chap/background}
|
||||||
\include{chap/implementation}
|
\include{chap/implementation}
|
||||||
\include{chap/verification}
|
\include{chap/verification}
|
||||||
\include{chap/conclusion}
|
\include{chap/conclusion}
|
||||||
|
|
||||||
% \pagenumbering{gobble} % Don't number appendix?
|
|
||||||
\begin{appendices}
|
\begin{appendices}
|
||||||
\include{chap/appendix_listings}
|
\include{chap/listings}
|
||||||
% \raggedbottom % The figures/tables shouldn't have huge vspace between them
|
\include{chap/figures}
|
||||||
\include{chap/appendix_tables}
|
\include{chap/tables}
|
||||||
\include{chap/appendix_figures}
|
|
||||||
\end{appendices}
|
\end{appendices}
|
||||||
|
|
||||||
\end{thesis}
|
\end{thesis}
|
||||||
|
\end{document}
|
||||||
\end{document}
|
|
Reference in New Issue
Block a user