Initial commit
49
chap/appendix_figures.tex
Normal file
@ -0,0 +1,49 @@
|
||||
\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}
|
360
chap/appendix_listings.tex
Normal file
@ -0,0 +1,360 @@
|
||||
\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
|
440
chap/appendix_tables.tex
Normal file
@ -0,0 +1,440 @@
|
||||
\chapter{Tables}
|
||||
\label{ch:tables}
|
||||
|
||||
This section lists all the registers and structures required to follow \autoref{ch:implementation}.
|
||||
|
||||
\clearpage
|
||||
|
||||
\renewcommand{\arraystretch}{1.2}
|
||||
|
||||
\section{Local APIC Registers}
|
||||
\label{sec:localapicregisters}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Register Name} & \textbf{Memory Offset} \\ \hline\hline
|
||||
Local APIC ID Register & 0x20 \\ \hline
|
||||
Local APIC Version Register & 0x30 \\ \hline
|
||||
Task Priority Register & 0x80 \\ \hline
|
||||
EOI Register & 0xB0 \\ \hline
|
||||
Spurious Interrupt Vector Register & 0xF0 \\ \hline
|
||||
Error Status Register & 0x280 \\ \hline
|
||||
Interrupt Command Register[0:31] & 0x300 \\ \hline
|
||||
Interrupt Command Register[32:63] & 0x310 \\ \hline
|
||||
LVT Timer Register & 0x320 \\ \hline
|
||||
LVT LINT1 Register & 0x360 \\ \hline
|
||||
LVT Error Register & 0x370 \\ \hline
|
||||
Timer Initial Count Register & 0x380 \\ \hline
|
||||
Timer Divide Configuration Register & 0x3E0 \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Registers used in this Implementation~\cite[sec.~3.11.4.1]{ia32}.}
|
||||
\label{tab:lapicregs}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:23 & Reserved \\ \hline
|
||||
24:31 & Local APIC ID \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC ID Register (xApic since Pentium 4)~\cite[sec.~3.11.4.6]{ia32}.}
|
||||
\label{tab:lapicregsid}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Local APIC Version \\ \hline
|
||||
8:15 & Reserved \\ \hline
|
||||
16:23 & Max LVT Entry \\ \hline
|
||||
24 & EOI Broadcast Suppression Support \\ \hline
|
||||
25:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Version Register~\cite[sec.~3.11.4.8]{ia32}.}
|
||||
\label{tab:lapicregsver}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:3 & Task-Priority Subclass \\ \hline
|
||||
4:7 & Task-Priority Class \\ \hline
|
||||
8:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Task Priority Register~\cite[sec.~3.11.8.3.1]{ia32}.}
|
||||
\label{tab:lapicregstpr}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Send EOI Signal \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC EOI Register~\cite[sec.~3.11.8.5]{ia32}.}
|
||||
\label{tab:lapicregseoi}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Spurious Interrupt Vector \\ \hline
|
||||
8 & APIC Software Enable/Disable \\ \hline
|
||||
9 & Focus Processor Checking \\ \hline
|
||||
10:11 & Reserved \\ \hline
|
||||
12 & EOI Broadcast Suppression \\ \hline
|
||||
13:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Spurious Interrupt Vector Register~\cite[sec.~3.11.9]{ia32}.}
|
||||
\label{tab:lapicregssvr}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:4 & Reserved \\ \hline
|
||||
5 & Send Illegal Vector \\ \hline
|
||||
6 & Receive Illegal Vector \\ \hline
|
||||
7 & Illegal Register Access \\ \hline
|
||||
8:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Error Status Register (Pentium 4)~\cite[sec.~3.11.5.3]{ia32}.}
|
||||
\label{tab:lapicregsesr}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Interrupt Vector \\ \hline
|
||||
8:10 & Delivery Mode \\ \hline
|
||||
11 & Destination Mode \\ \hline
|
||||
12 & Delivery Status \\ \hline
|
||||
13 & Reserved \\ \hline
|
||||
14 & Level \\ \hline
|
||||
15 & Trigger Mode \\ \hline
|
||||
16:17 & Reserved \\ \hline
|
||||
18:19 & Destination Shorthand \\ \hline
|
||||
20:55 & Reserved \\ \hline
|
||||
56:63 & Destination Field \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
||||
\label{tab:lapicregsicr}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Interrupt Vector \\ \hline
|
||||
8:11 & Reserved \\ \hline
|
||||
12 & Delivery Status \\ \hline
|
||||
13:15 & Reserved \\ \hline
|
||||
16 & Masked \\ \hline
|
||||
17:18 & Timer Mode \\ \hline
|
||||
19:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT Timer Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvtt}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Interrupt Vector \\ \hline
|
||||
8:11 & Reserved \\ \hline
|
||||
12 & Delivery Status \\ \hline
|
||||
13:15 & Reserved \\ \hline
|
||||
16 & Masked \\ \hline
|
||||
17:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT Error Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvterr}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Interrupt Vector \\ \hline
|
||||
8:10 & Delivery Mode \\ \hline
|
||||
11 & Reserved \\ \hline
|
||||
12 & Delivery Status \\ \hline
|
||||
13 & Pin Polarity \\ \hline
|
||||
14 & Remote IRR \\ \hline
|
||||
15 & Pin Polarity \\ \hline
|
||||
16 & Masked \\ \hline
|
||||
17:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT LINT1 Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvtlint}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Initial Count \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Timer Initial Count Register~\cite[sec.~3.11.5.4]{ia32}.}
|
||||
\label{tab:lapicregstimerinit}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & Divider \\ \hline
|
||||
2 & Reserved \\ \hline
|
||||
3 & Divider \\ \hline
|
||||
4:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Timer Divide Configuration Register~\cite[sec.~3.11.5.4]{ia32}.}
|
||||
\label{tab:lapicregstimerdiv}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Reserved \\ \hline
|
||||
8 & BSP Flag \\ \hline
|
||||
9 & Reserved \\ \hline
|
||||
10 & Enable x2Apic \\ \hline
|
||||
11 & Enable xApic \\ \hline
|
||||
12:35 & APIC Base Address \\ \hline
|
||||
36:63 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\cite[sec.~3.11.12.1]{ia32}.}
|
||||
\label{tab:lapicregsmsr}
|
||||
\end{table}
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{I/O APIC Registers}
|
||||
\label{sec:ioapicregs}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Register Name} & \textbf{Memory Offset} \\ \hline\hline
|
||||
Index Register & 0x00 \\ \hline
|
||||
Data Register & 0x10 \\ \hline\hline
|
||||
\textbf{Register Name} & \textbf{Index Offset} \\ \hline\hline
|
||||
I/O APIC ID Register & 0x00 \\ \hline
|
||||
I/O APIC Version Register & 0x01 \\ \hline
|
||||
Redirection Table & 0x10:0x3F \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Registers used in this Implementation~\cite[sec.~9.5]{ich5}.}
|
||||
\label{tab:ioapicregs}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Indirect Register Index \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Index Register~\cite[sec.~9.5.2]{ich5}.}
|
||||
\label{tab:ioapicregsidx}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Indirect Register Data \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Data Register~\cite[sec.~9.5.3]{ich5}.}
|
||||
\label{tab:ioapicregsdat}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:14 & Reserved \\ \hline
|
||||
15 & Scratchpad Bit \\ \hline
|
||||
16:23 & Reserved \\ \hline
|
||||
24:27 & I/O APIC ID \\ \hline
|
||||
28:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC ID Register~\cite[sec.~9.5.6]{ich5}.}
|
||||
\label{tab:ioapicregsid}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & I/O APIC Version \\ \hline
|
||||
8:14 & Reserved \\ \hline
|
||||
15 & PRQ \\ \hline
|
||||
16:23 & Maximum Redirection Entries \\ \hline
|
||||
24:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Version Register~\cite[sec.~9.5.7]{ich5}.}
|
||||
\label{tab:ioapicregsver}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Interrupt Vector \\ \hline
|
||||
8:10 & Delivery Mode \\ \hline
|
||||
11 & Destination Mode \\ \hline
|
||||
12 & Delivery Status \\ \hline
|
||||
13 & Pin Polarity \\ \hline
|
||||
14 & Remote IRR \\ \hline
|
||||
15 & Trigger Mode \\ \hline
|
||||
16 & Masked \\ \hline
|
||||
17:47 & Reserved \\ \hline
|
||||
48:55 & Extended Destination ID \\ \hline
|
||||
56:63 & Destination \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC REDTBL Register~\cite[sec.~9.5.8]{ich5}.}
|
||||
\label{tab:ioapicregsredtbl}
|
||||
\end{table}
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{System Description Tables}
|
||||
\label{sec:sdts}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:35 & MADT Header \\ \hline
|
||||
36:39 & Local APIC Base Address \\ \hline
|
||||
40:43 & Local APIC Flags \\ \hline
|
||||
44: & List of APIC Structures \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{ACPI MADT~\cite[sec.~5.2.8]{acpi1}.}
|
||||
\label{tab:madt}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & APIC Structure Header \\ \hline
|
||||
2 & ACPI Processor ID \\ \hline
|
||||
3 & APIC ID \\ \hline
|
||||
4:7 & Local APIC Flags (see \autoref{tab:madtlapicflags}) \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT Processor Local APIC Structure~\cite[sec.~5.2.8.1]{acpi1}.}
|
||||
\label{tab:madtlapic}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0 & Enabled \\ \hline
|
||||
1:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Flags~\cite[sec.~5.2.8.1]{acpi1}.}
|
||||
\label{tab:madtlapicflags}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & APIC Structure Header \\ \hline
|
||||
2 & I/O APIC ID \\ \hline
|
||||
3 & Reserved \\ \hline
|
||||
4:7 & I/O APIC Base Address \\ \hline
|
||||
8:11 & I/O APIC GSI Base \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT I/O APIC Structure~\cite[sec.~5.2.8.2]{acpi1}.}
|
||||
\label{tab:madtioapic}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & APIC Structure Header \\ \hline
|
||||
2 & Bus \\ \hline
|
||||
3 & Source \\ \hline
|
||||
4:7 & GSI \\ \hline
|
||||
8:9 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT Interrupt Source Override Structure~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\label{tab:madtirqoverride}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & Pin Polarity \\ \hline
|
||||
2:3 & Trigger Mode \\ \hline
|
||||
4:11 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Interrupt Input Flags~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\label{tab:madtintiflags}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & APIC Structure Header \\ \hline
|
||||
2:3 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
4:7 & GSI
|
||||
\end{tabularx}
|
||||
\caption{MADT I/O APIC NMI Source~\cite[sec.~5.2.8.3.2]{acpi1}.}
|
||||
\label{tab:madtionmi}
|
||||
\end{table}
|
||||
|
||||
\begin{table}[H]
|
||||
\centering
|
||||
\begin{tabularx}{1.0\textwidth}{| X | X |}
|
||||
\hline
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
0:1 & APIC Structure Header \\ \hline
|
||||
2 & ACPI Processor ID \\ \hline
|
||||
3:4 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
5 & Local APIC Interrupt Input \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT Local APIC NMI Source~\cite[sec.~5.2.8.3.3]{acpi1}.}
|
||||
\label{tab:madtlnmi}
|
||||
\end{table}
|
427
chap/background.tex
Normal file
@ -0,0 +1,427 @@
|
||||
\chapter{Background}
|
||||
\label{ch:background}
|
||||
|
||||
In this section, important domain specific concepts will be explained, to create the necessary
|
||||
foundation to follow \autoref{ch:implementation}. Important terms that are present in the glossary
|
||||
are marked in \textbf{bold} on their first occurrence.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Handling of External Events}
|
||||
\label{sec:eventhandling}
|
||||
|
||||
There are two different strategies to ``listen'' for external events: ``Polling'' and
|
||||
``Interrupts''.
|
||||
|
||||
The first strategy works by periodically \textit{polling} a device to check for changes. This could
|
||||
mean reading a register of the keyboard every 50 ms to determine if a key was pressed, or reading a
|
||||
sensor output even when the value remains unchanged. 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).
|
||||
|
||||
The second strategy are \textbf{\glspl{interrupt}}. Instead of the CPU actively ``looking'' for
|
||||
changes, the devices signal the events to the CPU themselves. 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.
|
||||
|
||||
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.
|
||||
|
||||
\section{Fundamental Concepts}
|
||||
\label{sec:fundamentals}
|
||||
|
||||
\subsection{Interrupt}
|
||||
\label{subsec:interrupt}
|
||||
|
||||
When a device signals an external event to the CPU, the current code execution gets
|
||||
\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
|
||||
via a network card. These interrupts from external hardware devices are called
|
||||
\textbf{\glspl{external interrupt}}.
|
||||
|
||||
Other types of interrupts mentioned in this thesis are \textbf{\glspl{ipi}}, \textbf{\glspl{msi}}
|
||||
and \textbf{\glspl{local interrupt}}:
|
||||
|
||||
\begin{itemize}
|
||||
\item IPIs: Interrupts sent between different processor cores in multiprocessor systems, for example to
|
||||
initialize different cores on system startup.
|
||||
\item MSIs: Interrupts sent in-band\footnote{In in-band signaling some control information (like an IRQ)
|
||||
is sent over the same channel as the data. This stands in contrast to out-of-band signaling, which
|
||||
uses a dedicated control line (like an interrupt line).}, for example over a PCI-bus\footnote{PCI
|
||||
supports MSIs since PCI 2.2~\cite[sec.~6.8]{pci22}.}.
|
||||
\item Local Interrupts: Some specific CPU-internal interrupts.
|
||||
\end{itemize}
|
||||
|
||||
Some interrupts are essential for continuous CPU operation. These \textbf{\glspl{nmi}} always have
|
||||
to be handled and cannot be ignored (usually\footnote{An example where NMIs should be disabled is
|
||||
the startup of additional processors in multiprocessor systems.}). Hardware error interrupts are a
|
||||
typical example for NMIs.
|
||||
|
||||
The existence of NMIs hints that it is possible to ignore regular interrupts. Marking an interrupt
|
||||
as ``ignored'' is called \textbf{\gls{masking}} an interrupt.
|
||||
|
||||
\subsection{Interrupt Controller}
|
||||
\label{subsec:controller}
|
||||
|
||||
A computer system has to process interrupts from many sources, so it is practical to have a
|
||||
designated \textbf{\gls{interrupt controller}}, that receives interrupts from different devices and
|
||||
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
|
||||
lines) to different devices. These signals can be represented in multiple ways through the level on
|
||||
the interrupt lines:
|
||||
|
||||
\textbf{\Gls{trigger mode}}:
|
||||
|
||||
\begin{itemize}
|
||||
\item Edge-triggered signal: 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
|
||||
\end{itemize}
|
||||
|
||||
\textbf{\Gls{pin polarity}}:
|
||||
|
||||
\begin{itemize}
|
||||
\item 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)
|
||||
\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}
|
||||
|
||||
A signal is represented through a combination of trigger mode and pin polarity, so there are a
|
||||
total of 4 combinations.
|
||||
|
||||
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. Because there are
|
||||
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
|
||||
\textbf{\gls{eoi}} notice from the OS\@.
|
||||
|
||||
Information on specific interrupt controllers follows in \autoref{sec:intelcontrollers}.
|
||||
|
||||
\subsection{Interrupt Handler}
|
||||
\label{subsec:handler}
|
||||
|
||||
When the CPU receives an IRQ, it pauses its current code execution to handle the interrupt. This is
|
||||
done by executing the \textbf{\gls{interrupt handler}} function, that is registered to the specific
|
||||
interrupt.
|
||||
|
||||
During interrupt servicing (execution of the interrupt handler), other interrupts can occur. When
|
||||
the execution of an interrupt handler is paused to handle another interrupt, this is called a
|
||||
\textbf{\gls{cascaded interrupt}}.
|
||||
|
||||
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. The interrupt handler addresses are
|
||||
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
|
||||
are usable for IRQs. In Intel's 32 bit IA-32 CPU architecture, this table is called the
|
||||
\textbf{\gls{idt}}. The \textbf{\gls{idtr}} keeps the location of the IDT, it is written by the
|
||||
\code{lidt}~\cite{x86isa} instruction.
|
||||
|
||||
\subsection{Interrupt Trigger Mode}
|
||||
\label{subsec:triggermode}
|
||||
|
||||
When an edge-triggered IRQ is received, its interrupt handler is called a single time, serviced,
|
||||
and marked as completed in the interrupt controller (completion does not require interacting with
|
||||
the device the interrupt originated from). The handler of an edge-triggered IRQ is called every
|
||||
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,
|
||||
the interrupt is signaled continuously. Servicing the interrupt thus requires not only signaling
|
||||
completion to the interrupt controller, but also to the device the interrupt originated from, to
|
||||
de-assert the interrupt line. Otherwise, the interrupt handler would be called again after
|
||||
completion.
|
||||
|
||||
\subsection{Spurious Interrupt}
|
||||
\label{subsec:spurious}
|
||||
|
||||
When an interrupt disappears while the interrupt controller is issuing the IRQ to the CPU, the
|
||||
interrupt controller sends a \textbf{\gls{spurious interrupt}}. The reason for this could be
|
||||
electrical noise on the interrupt line, masking of an interrupt through software at the same moment
|
||||
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}
|
||||
\label{sec:technologies}
|
||||
|
||||
\subsection{Advanced Configuration and Power Interface}
|
||||
\label{subsec:acpi}
|
||||
|
||||
\textbf{\gls{acpi}} allows the kernel to gather information about the system hardware during
|
||||
runtime. It also provides interactive functionality for power management, plug and play,
|
||||
hot-swapping or status monitoring. To interact with ACPI, the
|
||||
\textbf{\gls{aml}}~\cite[sec.~16]{acpi1}, a small language interpreted by the kernel, has to be
|
||||
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
|
||||
\textit{system description tables}. In this thesis, ACPI 1.0~\cite{acpi1} is used to read
|
||||
information about the system's interrupt hardware configuration, located in the ACPI
|
||||
\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
|
||||
through \textbf{\glspl{gsi}}~\cite[sec.~5.2.9]{acpi1}. 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{Additional information in \autoref{subsec:ioapicpcat}.}.
|
||||
|
||||
\subsection{CPU Identification}
|
||||
\label{subsec:cpuid}
|
||||
|
||||
\textbf{\gls{cpuid}} is used to gather information about a system's CPU. The x86 architecture
|
||||
provides the \code{cpuid}~\cite{x86isa} instruction, which allows the software to identify present
|
||||
CPU features at runtime, e.g.\ what instruction set extensions a processor implements\footnote{This
|
||||
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}
|
||||
\label{subsec:smp}
|
||||
|
||||
\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. SMP systems are
|
||||
controlled by a single OS, that treats all cores as individual, but equal processors. The shared
|
||||
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.
|
||||
|
||||
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.
|
||||
|
||||
% TODO: I think I could remove this section
|
||||
% \subsection{BIOS and UEFI}
|
||||
% \label{subsec:biosuefi}
|
||||
%
|
||||
% The \textbf{\gls{bios}} provides low-level control over a computer system's hardware, most commonly
|
||||
% used for booting an OS on system power-up. Its pre-boot environment is limited to the 16-bit
|
||||
% \textbf{\gls{real mode}} and 1 MB of addressable memory. BIOS originates from the IBM PC and has
|
||||
% been the default convention for computer system firmware until the \textbf{\gls{uefi}} standard.
|
||||
%
|
||||
% The UEFI standard is developed by the UEFI Forum, based on Intel's EFI. It improves on BIOS by
|
||||
% providing modularity, support for larger partitions, 32-bit or 64-bit environments before booting
|
||||
% and advanced features like networking capabilities, graphical user interfaces with mouse support or
|
||||
% security features\footnote{See \url{https://uefi.org/specifications} (visited on 22/02/2023).}.
|
||||
|
||||
\subsection{Model Specific Register}
|
||||
\label{subsec:msr}
|
||||
|
||||
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). MSRs that carried
|
||||
over to future generations and are now guaranteed to be included in future IA-32 or Intel 64 CPUs
|
||||
are called ``architectural'' MSRs. To interact with MSRs, the special instructions \code{rdmsr} and
|
||||
\code{wrmsr} are used~\cite{x86isa}. These instructions allow atomic read/write operations on
|
||||
MSRs\footnote{Detailed description in the IA-32 manual~\cite[sec.~4.2]{ia32}.}.
|
||||
|
||||
\subsection{Memory Mapped I/O}
|
||||
\label{subsec:mmio}
|
||||
|
||||
\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
|
||||
memory address can either be a location in physical memory, or belong to a device's register. Read
|
||||
and write operations are then performed by reading or writing the address the register is mapped
|
||||
to.
|
||||
|
||||
\subsection{Programmable Interval Timer}
|
||||
\label{subsec:pit}
|
||||
|
||||
The \textbf{\gls{pit}}\footnote{Specifically the Intel 8253/8254.} is a hardware timer from the
|
||||
original IBM PC. It consists of multiple decrementing counters and can generate a signal (for
|
||||
example an interrupt) once 0 is reached. This can be used to control a preemptive\footnote{A
|
||||
scheduler is called ``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.} scheduler or
|
||||
the integrated PC speaker.
|
||||
|
||||
\section{Intel's Interrupt Controllers}
|
||||
\label{sec:intelcontrollers}
|
||||
|
||||
Because it is logistically difficult to connect every external device directly to the CPU, this
|
||||
task is delegated to an interrupt controller, usually located in the system's chipset. Notable
|
||||
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}
|
||||
\label{subsec:intelpic}
|
||||
|
||||
The Intel 8259A PIC~\cite{pic} is the interrupt controller Intel used in the original Intel
|
||||
8086\footnote{The 8259 was used in the Intel 8080 and 8085, the 8259A is a revised version for the
|
||||
Intel 8086}, the ``father'' of the x86 processor architecture. A single PIC has 8 interrupt lines
|
||||
for external devices, but multiple PICs can be cascaded for a maximum of \(8 \cdot 8 = 64\)
|
||||
interrupt lines with 9 PICs. The most common PIC configuration supports 15 IRQs with two PICs: A
|
||||
slave, connected to interrupt line 2 of the master, which is connected to the CPU\footnote{This
|
||||
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]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.3\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/mp_spec_pic_configuration.svg}
|
||||
\end{subfigure}
|
||||
\caption{The PC/AT PIC architecture~\cite[sec.~1.13]{pcat}.}
|
||||
\label{fig:pcatpic}
|
||||
\end{figure}
|
||||
|
||||
If multiple interrupts get requested simultaneously, the PIC decides which one to service first
|
||||
based on its \textbf{\gls{interrupt priority}}. The PIC IRQ priorities are determined by the used
|
||||
interrupt lines, IRQ0 has the highest priority.
|
||||
|
||||
The PIC interrupt handling sequence can be briefly outlined as follows:
|
||||
|
||||
\begin{enumerate}
|
||||
\item When the PIC receives an interrupt from a device (PIC interrupts are edge-triggered with high pin
|
||||
polarity), it sets the corresponding bit in its \textbf{\gls{irr}}\footnote{Received IRQs that are
|
||||
requesting servicing are marked in the IRR.}
|
||||
\item If this interrupt is unmasked, an IRQ is sent to the CPU
|
||||
\item The CPU acknowledges the IRQ
|
||||
\item The PIC sets the corresponding bit in its \textbf{\gls{isr}}\footnote{IRQs that are being serviced
|
||||
are marked in the ISR. To reduce confusion, interrupt service routines will be denoted as
|
||||
``interrupt handler'' instead of ``ISR''.} and clears the previously set bit 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
|
||||
corresponding bit in the ISR\@.
|
||||
\end{enumerate}
|
||||
|
||||
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:
|
||||
|
||||
\begin{itemize}
|
||||
\item Multiple CPU cores require sending IPIs for initialization and coordination, which is not possible
|
||||
using the PIC\@.
|
||||
\item The PIC is hardwired to a single CPU core. It can be inefficient to handle the entire interrupt
|
||||
workload on a single core.
|
||||
\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 PIC does not support MSIs, which allow efficient handling of PCI interrupts.
|
||||
\end{itemize}
|
||||
|
||||
\subsection{Advanced Programmable Interrupt Controller}
|
||||
\label{subsec:intelapic}
|
||||
|
||||
The original Intel 82489DX discrete APIC was introduced with the Intel i486 processor. It consisted
|
||||
of two parts: A \textbf{\gls{local apic}}, responsible for receiving special \textbf{\glspl{local
|
||||
interrupt}}, and external interrupts from the second part, the \textbf{\gls{io apic}}. Unlike in
|
||||
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,
|
||||
the first Pentium processor.}, which contained an integrated local APIC for the first time, see
|
||||
\autoref{fig:integratedapic}\footnote{This is now the default configuration.}.
|
||||
|
||||
The APIC was designed to fix the shortcomings of the PIC, specifically regarding multiprocessor
|
||||
systems:
|
||||
|
||||
\begin{itemize}
|
||||
\item Each CPU core contains its own local APIC. It has the capabilities to issue IPIs and communicate
|
||||
with the chipset I/O APIC. Also, it includes the APIC timer, which can be used for per-core
|
||||
scheduling.
|
||||
\item The chipset I/O APIC allows configuration on a per-interrupt basis (priorities, destination,
|
||||
trigger mode or pin polarity are all configurable). Also, it is able to send interrupts to
|
||||
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 APIC architecture supports MSIs.
|
||||
\end{itemize}
|
||||
|
||||
To allow distributing the APIC hardware between local APICs of multiple CPU cores and I/O APICs,
|
||||
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
|
||||
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 PIC 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{The x2Apic architecture is backwards
|
||||
compatible to the xApic architecture, also, QEMU's TCG does not support the x2Apic architecture.}.
|
||||
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
|
||||
atomic register access to the 32- and 64-bit wide APIC control MSRs~\cite[sec.~3.11.12]{ia32}.
|
||||
|
||||
\section{PC/AT Compatibility}
|
||||
\label{sec:pcatcompat}
|
||||
|
||||
For compatibility to older computer systems, two cascaded PICs are usually present in current
|
||||
computer systems (see \autoref{fig:discreteapic}/\autoref{fig:integratedapic}). 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}}. It is possible to operate with both the PIC and I/O APIC as
|
||||
controllers for external interrupts in ``mixed mode'', but this is very uncommon. 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{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
|
||||
the relatively old MultiProcessor specification~\cite{mpspec}.} hardware\footnote{QEMU does not
|
||||
emulate the IMCR.} provides the \textbf{\gls{imcr}}, a special register that controls the physical
|
||||
connection of the PIC to the CPU. 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 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}.
|
||||
|
||||
\section{Interrupt Handling in hhuOS}
|
||||
\label{sec:currenthhuos}
|
||||
|
||||
In hhuOS, external interrupts are handled in two steps:
|
||||
|
||||
\begin{enumerate}
|
||||
\item After an IRQ is sent by an interrupt controller, the CPU looks up the interrupt handler address in
|
||||
the IDT. In hhuOS, every IDT entry contains the address of the \code{dispatch} function (see
|
||||
\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. In hhuOS, interrupt handlers are implemented through the
|
||||
\code{InterruptHandler} interface (see \autoref{lst:irqhandler}), that provides the \code{trigger}
|
||||
function, which contains the interrupt handling routine. 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. 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}
|
||||
|
||||
\begin{codeblock}[label=lst:irqhandler]{The InterruptHandler interface (InterruptHandler.h)~\cite{hhuos}}{C++}
|
||||
\cppfile{code/interrupthandler_def.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:irqassign]{Assigning an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_assign.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:irqdispatch]{Triggering an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_dispatch.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
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).
|
||||
|
||||
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.
|
107
chap/conclusion.tex
Normal file
@ -0,0 +1,107 @@
|
||||
\chapter{Conclusion}
|
||||
\label{ch:conclusion}
|
||||
|
||||
In this thesis, support for the APIC was integrated into hhuOS. The implementation supports usage
|
||||
of the local APIC in combination with the I/O APIC for regular interrupt handling without the
|
||||
PIC\@. 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. 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.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Comparing PIC and APIC Implementations}
|
||||
\label{sec:comparingpicapic}
|
||||
|
||||
Handling interrupts using the PIC is extremely simple, as seen in hhuOS' PIC implementation.
|
||||
Initialization and usage can be performed by using a total of only four different registers, two
|
||||
per PIC\footnote{Omitting the infrastructure that is required for both, PIC and APIC, like the IDT
|
||||
or dispatcher.}.
|
||||
|
||||
In comparison, the code complexity required to use the APIC is very high. 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. 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
|
||||
PC/AT architecture, the entire hardware interrupt configuration is known before boot. This is not
|
||||
the case when using the APIC, as the amount of interrupt controllers or even the number and order
|
||||
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
|
||||
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}
|
||||
\label{sec:futureimprov}
|
||||
|
||||
\subsection{Dependence on ACPI}
|
||||
\label{subsec:acpidependance}
|
||||
|
||||
The APIC system requires a supplier of system information during operation, but this must not
|
||||
necessarily be ACPI. Systems following Intel's ``MultiProcessor Specification''~\cite{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. This would
|
||||
increase the amount 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{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
|
||||
APIC's virtual wire mode~\cite[sec.~3.6.2.2]{mpspec}. The reliance on information provided in the
|
||||
MADT stems mostly from using the I/O APIC as the external interrupt controller. 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.
|
||||
|
||||
\subsection{Discrete APIC and x2Apic}
|
||||
\label{subsec:discretex2}
|
||||
|
||||
This implementation only supports the xApic architecture, as it's convenient to emulate and the
|
||||
x2Apic architecture is fully backwards compatible~\cite[sec.~3.11.12]{ia32}. The original, discrete
|
||||
local APIC (Intel 82489DX) is not supported explicitly, which reduces this implementation's
|
||||
compatibility to older systems\footnote{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~\cite[sec.~3.23.27]{ia32}.}. Supporting the x2Apic architecture does not increase
|
||||
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}
|
||||
\label{subsec:pcidevices}
|
||||
|
||||
The APIC is capable of handling MSIs, but this is not implemented in this thesis. 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. This is rather
|
||||
complicated, as it requires interacting with ACPI using AML~\cite[sec.~6.2.13]{acpi65}, which needs
|
||||
an according interpreter\footnote{There exist modular solutions that can be ported to the target
|
||||
OS~\cite{acpica}.}.
|
||||
|
||||
\subsection{Multiprocessor Systems}
|
||||
\label{subsec:multiprocessor}
|
||||
|
||||
This implementation demonstrates AP startup in SMP systems by using the APIC's IPI mechanism, but
|
||||
processors are only initialized to a spin-loop. 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 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,
|
||||
each I/O APIC redirects every received interrupt to the BSP's local APIC. Distributing interrupts
|
||||
to different CPU cores could improve interrupt handling performance, especially with frequent
|
||||
interrupts, like from network devices. This redirection could also happen dynamically
|
||||
(``IRQ-balancing''~\cite{irqbalance}), depending on interrupt workload measurements.
|
||||
|
||||
\subsection{UEFI Support}
|
||||
\label{subsec:uefisupport}
|
||||
|
||||
Currently, hhuOS' ACPI system only works with BIOS, so when booting an UEFI system, this
|
||||
implementation is disabled, because it requires ACPI. By supporting ACPI on UEFI systems, this
|
||||
implementation could also be used for those systems, which would improve compatibility with modern
|
||||
platforms.
|
645
chap/implementation.tex
Normal file
@ -0,0 +1,645 @@
|
||||
\chapter{Implementation}
|
||||
\label{ch:implementation}
|
||||
|
||||
This section will detail how and to what extent the APIC support was implemented. The steps
|
||||
performed in this implementation are described in a generally applicable way, concrete
|
||||
implementation details with hhuOS as an example are found in \autoref{ch:listings}.
|
||||
\autoref{sec:hhuosintegration} deals with the modifications done to the hhuOS system to integrate
|
||||
the APIC implementation.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Design Decisions and Scope}
|
||||
\label{sec:design}
|
||||
|
||||
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). 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 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
|
||||
components (see \autoref{fig:implarch}):
|
||||
|
||||
\begin{itemize}
|
||||
\item \code{LocalApic}: Provides functionality to interact with the local 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{Apic}: Condenses all the functionality above and exposes it to other parts
|
||||
of the OS\@.
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.5\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/Architecture.svg}
|
||||
\end{subfigure}
|
||||
\caption{Caller hierarchy of the main components.}
|
||||
\label{fig:implarch}
|
||||
\end{figure}
|
||||
|
||||
This implementation is targeted to support systems with a single I/O APIC\footnote{Operation with
|
||||
more than one I/O APIC is described further in the MultiProcessor
|
||||
specification~\cite[sec.~3.6.8]{mpspec}.}, because consumer hardware typically only uses a single
|
||||
one, and so does QEMU emulation. General information on implementing multiple I/O APIC support can
|
||||
be found in \autoref{subsec:multiioapic}.
|
||||
|
||||
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:
|
||||
|
||||
\begin{itemize}
|
||||
\item \code{GlobalSystemInterrupt}: ACPI's interrupt abstraction, detached from the hardware
|
||||
interrupt lines.
|
||||
\item \code{InterruptRequest}: Represents an IRQ, allowing the OS to address interrupts by
|
||||
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}. The dispatcher maps interrupt vectors to interrupt handlers.
|
||||
\end{itemize}
|
||||
|
||||
Both BIOS and UEFI are supported by hhuOS, but the hhuOS ACPI subsystem is currently only available
|
||||
with BIOS\footnote{State from 11/02/23.}, so when hhuOS is booted using UEFI, APIC support can't be
|
||||
enabled. 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
|
||||
hhuOS currently is a single-core OS and lacks some required infrastructure. All interrupts are
|
||||
handled using the BSP\@.
|
||||
|
||||
Summary of features that are outside the scope of this thesis:
|
||||
|
||||
\begin{itemize}
|
||||
\item Operation with a discrete APIC or x2Apic.
|
||||
\item Interrupts with logical destinations or custom priorities.
|
||||
\item Returning from APIC operation to PIC mode\footnote{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
|
||||
physical APIC base address to the IA32\textunderscore{}APIC\textunderscore{}BASE MSR.}.
|
||||
\item Distributing external interrupts to different APs in SMP enabled systems.
|
||||
\item Usage of the system's performance counter or monitoring interrupts.
|
||||
\item Meaningful APIC error handling.
|
||||
\item Handling of MSIs.
|
||||
\end{itemize}
|
||||
|
||||
To be able to easily extend an APIC implementation for single-core systems to SMP systems, some
|
||||
things have to be taken into account:
|
||||
|
||||
\begin{itemize}
|
||||
\item SMP systems need to manage multiple \code{LocalApic} and \code{ApicTimer} instances. This is
|
||||
handled by the \code{Apic} class.
|
||||
\item Initialization of the different components can no longer happen at the same ``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.
|
||||
\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
|
||||
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.
|
||||
\end{itemize}
|
||||
|
||||
\section{Code Style}
|
||||
\label{sec:codestyle}
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
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
|
||||
classes only selectively expose their interfaces (by using the \code{friend} declaration) for the
|
||||
same reason.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Local APIC}
|
||||
\label{sec:lapicinit}
|
||||
|
||||
The local APIC block diagram (see \autoref{fig:localapicblock}) shows a number of registers that
|
||||
are required for initialization:
|
||||
|
||||
\begin{itemize}
|
||||
\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{tpr}}: Decides the order in which interrupts are handled and a possible interrupt
|
||||
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{apr}}: Controls the priority in the APIC arbitration mechanism.
|
||||
\end{itemize}
|
||||
|
||||
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}
|
||||
\item LINT1: The local APIC's NMI source.
|
||||
\item 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
|
||||
in internal APIC communication).
|
||||
\end{itemize}
|
||||
|
||||
The LINT0 interrupt is unlisted, because it is mainly important for virtual wire mode (it can be
|
||||
triggered by external interrupts from the PIC). The performance and thermal monitoring interrupts
|
||||
also remain unused in this implementation.
|
||||
|
||||
Besides the local APIC's own registers, the IMCR and \textbf{\gls{ia32 apic base msr}} also require
|
||||
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}:
|
||||
|
||||
\begin{itemize}
|
||||
\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
|
||||
on power-up).
|
||||
\item The SVR is reset to \code{0x000000FF}.
|
||||
\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\@.
|
||||
\end{itemize}
|
||||
|
||||
The initialization sequence consists of these steps:
|
||||
|
||||
\begin{enumerate}
|
||||
\item Enable symmetric I/O mode and set the APIC operating mode.
|
||||
\item Initialize the LVT and NMI\@.
|
||||
\item Initialize the SVR\@.
|
||||
\item Clear outstanding signals.
|
||||
\item Initialize the TPR\@.
|
||||
\item Initialize the APIC timer and error handler.
|
||||
\item Startup the APs and initialize their respective local APICs.
|
||||
\item Synchronize the APRs.
|
||||
\end{enumerate}
|
||||
|
||||
\subsection{Accessing Local APIC Registers in xApic Mode}
|
||||
\label{subsec:xapicregacc}
|
||||
|
||||
Accessing registers in xApic mode is done via MMIO and requires a single page (4 KB) of memory,
|
||||
mapped to the ``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}). 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
|
||||
manual~\cite[sec.~3.11.4.1]{ia32} and in \autoref{tab:lapicregs}.
|
||||
|
||||
\subsection{Enabling the Local APIC}
|
||||
\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~\cite[sec.~3.6.2.1]{mpspec} to disconnect the PIC from the local APIC's LINT0 pin (see
|
||||
\autoref{fig:integratedapic}, for the example implementation see \autoref{sec:apxdisablepic}).
|
||||
|
||||
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~\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]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_apic_base_msr.svg}
|
||||
\end{subfigure}
|
||||
\caption{The IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\cite[sec.~3.11.4.4]{ia32}.}
|
||||
\label{fig:ia32apicbasemsr}
|
||||
\end{figure}
|
||||
|
||||
Because QEMU does not support x2Apic mode via its TCG\footnote{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
|
||||
the ``software enable/disable'' flag in the SVR, see \autoref{subsec:lapicsoftenable}.
|
||||
|
||||
\subsection{Handling Local Interrupts}
|
||||
\label{subsec:lapiclvtinit}
|
||||
|
||||
To configure how the local APIC handles the different local interrupts, the LVT registers are
|
||||
written (see \autoref{fig:localapiclvt}).
|
||||
|
||||
Local interrupts can be configured to use different delivery modes
|
||||
(excerpt)~\cite[sec.~3.11.5.1]{ia32}:
|
||||
|
||||
\begin{itemize}
|
||||
\item 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 ExtINT: The interrupt is treated as an external interrupt (instead of local interrupt), used e.g.\
|
||||
in virtual wire mode for LINT0.
|
||||
\end{itemize}
|
||||
|
||||
Initially, all local interrupts are initialized to PC/AT defaults: Masked, edge-triggered,
|
||||
active-high and with ``fixed'' delivery mode. Most importantly, the vector fields (bits 0:7 of an
|
||||
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
|
||||
\autoref{tab:lapicregslvtlint}), because it is the local APIC's NMI source\footnote{In older
|
||||
specifications~\cite{mpspec}, LINT1 is defined as NMI source (see \autoref{fig:integratedapic}). 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. It is also possible that
|
||||
ACPI reports information on the NMI source just for future-proofing.}. The delivery mode is set to
|
||||
``NMI'' and the interrupt vector to \code{0x00}. This information is also provided by ACPI in the
|
||||
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}
|
||||
\label{subsec:lapicsoftenable}
|
||||
|
||||
To complete a minimal local APIC initialization, the ``software enable/disable'' flag and the
|
||||
spurious interrupt vector (both contained in the SVR, see
|
||||
\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]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_apic_svr.svg}
|
||||
\end{subfigure}
|
||||
\caption{The local APIC SVR register~\cite[sec.~3.11.9]{ia32}.}
|
||||
\label{fig:ia32apicsvr}
|
||||
\end{figure}
|
||||
|
||||
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{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
|
||||
of all priorities. This is done by writing \code{0x00} to the TPR~\cite[sec.~3.11.8.3]{ia32} (see
|
||||
\autoref{tab:lapicregstpr}). 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.
|
||||
|
||||
\subsection{Local Interrupt EOI}
|
||||
\label{subsec:lapiceoi}
|
||||
|
||||
To notify the local APIC that a local interrupt has been handled, its EOI register (see
|
||||
\autoref{tab:lapicregseoi}) has to be written. Not all local interrupts require EOIs: NMI, SMI,
|
||||
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
|
||||
\autoref{subsec:ioapiceoi}.
|
||||
|
||||
\subsection{APIC Timer}
|
||||
\label{subsec:lapictimer}
|
||||
|
||||
The APIC timer is integrated into the local APIC, so it requires initialization of the latter. 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. Because the
|
||||
APIC timer doesn't tick with a fixed frequency, but at bus frequency, the initial counter has to be
|
||||
determined at runtime by using an external time source. 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. 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:
|
||||
|
||||
\begin{enumerate}
|
||||
\item 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
|
||||
initial value.
|
||||
\item TSC-Deadline: Trigger exactly one interrupt at an absolute time.
|
||||
\end{enumerate}
|
||||
|
||||
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}):
|
||||
|
||||
\begin{enumerate}
|
||||
\item Measure the timer frequency with an external time source.
|
||||
\item Configuration of the timer's divider register (see \autoref{tab:lapicregstimerdiv}).
|
||||
\item Setting the timer mode to periodic (see \autoref{tab:lapicregslvtt}).
|
||||
\item Initializing the counter register (see \autoref{tab:lapicregstimerinit}), depending on the measured
|
||||
timer frequency and the desired interval.
|
||||
\end{enumerate}
|
||||
|
||||
In this implementation, the APIC timer is calibrated by counting the amount of ticks in one
|
||||
millisecond using oneshot mode (see \autoref{sec:apxapictimer} for an example implementation). 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. 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
|
||||
\autoref{sec:apxapictimer} for an example implementation).
|
||||
|
||||
\subsection{APIC Error Interrupt}
|
||||
\label{subsec:lapicerror}
|
||||
|
||||
Errors can occur for example when the local APIC receives an invalid vector number, or an APIC
|
||||
message gets corrupted on the system bus. 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.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_error_status_register.svg}
|
||||
\end{subfigure}
|
||||
\caption{Error Status Register~\cite[sec.~3.11.5.3]{ia32}.}
|
||||
\label{fig:ia32esr}
|
||||
\end{figure}
|
||||
|
||||
The ESR is a ``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. Writing the ESR also
|
||||
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
|
||||
registering an interrupt handler for the appropriate vector (see \autoref{sec:apxhandlingerror} for
|
||||
an example implementation).
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{I/O APIC}
|
||||
\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~\cite[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}).
|
||||
|
||||
Additionally, for external interrupts a destination and destination mode can be specified. 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}). 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
|
||||
initialized correctly, external interrupts will be redirected to the local APIC and handled by the
|
||||
CPU\@.
|
||||
|
||||
Unlike the local APIC's registers, the REDTBL registers are accessed indirectly: Two registers, the
|
||||
``Index'' and ``Data'' register~\cite[sec.~9.5.1]{ich5}, are mapped to the main memory and can be
|
||||
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}
|
||||
\label{subsec:ioapicpcat}
|
||||
|
||||
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
|
||||
interrupt has to be determined by the OS at runtime, by using ACPI. ACPI provides ``Interrupt
|
||||
Source Override'' structures~\cite[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\@.
|
||||
|
||||
In addition to the interrupt input mapping, these structures also allow to customize the pin
|
||||
polarity and trigger mode of PC/AT compatible interrupts.
|
||||
|
||||
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}
|
||||
\label{subsec:ioapiceoi}
|
||||
|
||||
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{Because external interrupts are
|
||||
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
|
||||
the remote IRR bit:
|
||||
|
||||
\begin{enumerate}
|
||||
\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.
|
||||
\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. 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}
|
||||
|
||||
Because the first option is the only one supported by all APIC versions, it is used in this
|
||||
implementation\footnote{Disabling EOI broadcasting is not supported by all local
|
||||
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
|
||||
usable. External interrupts now have to be enabled/disabled by writing the ``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.
|
||||
|
||||
\subsection{Multiple I/O APICs}
|
||||
\label{subsec:multiioapic}
|
||||
|
||||
Most consumer hardware, for example all IA processors~\cite{ia32} and ICH hubs~\cite{ich5}, only
|
||||
provide a single I/O APIC, although technically multiple I/O APICs are supported by the
|
||||
MultiProcessor specification~\cite[sec.~3.6.8]{mpspec}.
|
||||
|
||||
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. 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~\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
|
||||
|
||||
\section{Symmetric Multiprocessing}
|
||||
\label{sec:smpinit}
|
||||
|
||||
Like single-core systems, SMP systems boot using only a single core, the BSP. By using the APIC's
|
||||
capabilities to send IPIs between cores, additional APs can be put into startup state and booted
|
||||
for system use.
|
||||
|
||||
To determine the amount 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
|
||||
\autoref{tab:madtlapicflags}).
|
||||
|
||||
\subsection{Inter-Processor Interrupts}
|
||||
\label{subsec:ipis}
|
||||
|
||||
Issuing IPIs works by writing the local APIC's ICR (see
|
||||
\autoref{fig:ia32icr}/\autoref{tab:lapicregsicr}). It allows specifying IPI type, destination
|
||||
(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
|
||||
a discrete APIC, and the \textbf{\gls{sipi}} for systems using the xApic or x2Apic architectures:
|
||||
|
||||
\begin{itemize}
|
||||
\item The INIT IPI causes an AP to reset its state and start executing at the address specified at its
|
||||
system reset vector. 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~\cite[sec.~B.4.1]{mpspec}.
|
||||
\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}
|
||||
|
||||
To wait until the IPI is sent, the ICR's delivery status bit can be polled.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_interrupt_command_register.svg}
|
||||
\end{subfigure}
|
||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
||||
\label{fig:ia32icr}
|
||||
\end{figure}
|
||||
|
||||
\subsection{Universal Startup Algorithm}
|
||||
\label{subsec:apstartup}
|
||||
|
||||
SMP initialization is performed differently on various processors. Intel's MultiProcessor
|
||||
specification defines a ``universal startup algorithm'' for multiprocessor
|
||||
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
|
||||
\autoref{subsec:apboot}) to lower memory, where the APs will start their execution. 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}~\cite[sec.~B.4]{mpspec}), because the INIT IPI
|
||||
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
|
||||
information on the importance of these timings or required precision. 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~\cite[lapic.c]{xv6}.
|
||||
|
||||
After preparation, the universal startup algorithm is now performed as follows, for each AP
|
||||
sequentially (see \autoref{sec:apxmpusa} for an example implementation):
|
||||
|
||||
\begin{enumerate}
|
||||
\item Assert and de-assert the level-triggered INIT IPI\@.
|
||||
\item Delay for 10 milliseconds.
|
||||
\item Send the SIPI\@.
|
||||
\item Delay for 200 microseconds.
|
||||
\item Send the SIPI again.
|
||||
\item Delay for 200 microseconds again.
|
||||
\item Wait until the AP has signaled boot completion, then continue to the next.
|
||||
\end{enumerate}
|
||||
|
||||
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\@.
|
||||
|
||||
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. This
|
||||
variable does not have to be synchronized across APs, because the startup is performed
|
||||
sequentially.
|
||||
|
||||
\subsection{Application Processor Boot Routine}
|
||||
\label{subsec:apboot}
|
||||
|
||||
After executing the ``INIT-SIPI-SIPI'' sequence, the targeted AP will start executing its boot
|
||||
routine in real mode. 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. The AP boot routine this implementation uses can be roughly described as
|
||||
follows (see \autoref{sec:apxapboot} for an example implementation):
|
||||
|
||||
\begin{enumerate}
|
||||
\item Load a temporary \textbf{\gls{gdt}}, used for switching to protected mode.
|
||||
\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
|
||||
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 IDT used by the BSP\@.
|
||||
\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 stack prepared for this AP\@.
|
||||
\item Call the (C++) AP entry function.
|
||||
\end{enumerate}
|
||||
|
||||
The APIC ID is used to determine which GDT and stack were prepared for a certain AP\@. It is
|
||||
necessary for each AP to have its own GDT, because each processor needs its own TSS for context
|
||||
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
|
||||
code has to be position independent. For this reason, absolute physical addresses have to be used
|
||||
when jumping, loading the IDTR and GDTR, or referencing variables. Also, any variables required
|
||||
during boot have to be available after relocation, this can be achieved by locating them inside the
|
||||
``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}
|
||||
\label{subsec:apsystementry}
|
||||
|
||||
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{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
|
||||
a certain local APIC receives multiple messages from different local APICs at a similar time. To
|
||||
decide the order of handling these messages, an arbitration mechanism based on the local APIC's ID
|
||||
is used~\cite[sec.~3.11.7]{ia32}. 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{This is not
|
||||
supported on Pentium 4 and Xeon processors.} (see \autoref{sec:apxappostboot} for an example
|
||||
implementation).
|
||||
|
||||
\clearpage
|
26
chap/introduction.tex
Normal file
@ -0,0 +1,26 @@
|
||||
\chapter{Introduction}
|
||||
\label{ch:introduction}
|
||||
|
||||
Computer systems are very useful, because they are able to interact with the ``outside world'', for
|
||||
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
|
||||
architecture, introduced by Intel for the Pentium 4 processor, will be implemented into hhuOS, ``A
|
||||
small operating system for learning purposes''~\cite{hhuos}. This support will cover a complete
|
||||
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
|
||||
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.
|
||||
|
||||
\clearpage
|
82
chap/verification.tex
Normal file
@ -0,0 +1,82 @@
|
||||
\chapter{Verification}
|
||||
\label{ch:verification}
|
||||
|
||||
Common techniques for testing software include component-based tests, like ``unit tests'', and
|
||||
``end-to-end tests'', where the complete functionality of a software system with all its parts is
|
||||
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
|
||||
developed during this thesis.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Methods of Verification}
|
||||
\label{sec:verificationmethods}
|
||||
|
||||
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{There is almost no logic that can be
|
||||
tested isolated or hardware independently.}.
|
||||
|
||||
This can be done in multiple ways:
|
||||
|
||||
\begin{itemize}
|
||||
\item When running hhuOS in an emulated environment, the current machine state can be inspected
|
||||
directly\footnote{QEMU offers the ``QEMU monitor'' to query information about specific hardware
|
||||
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 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\@.
|
||||
\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}
|
||||
|
||||
\section{Results}
|
||||
\label{sec:verificationresults}
|
||||
|
||||
QEMU was used as the main development platform, the implemented features were tested by using the
|
||||
QEMU monitor. 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:
|
||||
|
||||
\begin{itemize}
|
||||
\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 A working local APIC timer - verified by observing the APIC timer's registers.
|
||||
\end{itemize}
|
||||
|
||||
Although hhuOS is developed mainly for learning purposes, every OS' core task remains to be the
|
||||
management of computer hardware. For this reason this implementation was additionally tested on a
|
||||
``ThinkPad T60s'' with an Intel ``Core 2 Duo'' processor. 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.
|
||||
|
||||
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 amounts
|
||||
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}
|
||||
\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 Devices ``plugging in'' to the APIC instead of the PIC - verified by observing the LVT and
|
||||
REDTBL\@.
|
||||
\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 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{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. Also,
|
||||
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}
|
748
class/thesis.cls
Normal file
@ -0,0 +1,748 @@
|
||||
% @file thesis.cls
|
||||
%
|
||||
% @brief Document class for theses.
|
||||
%
|
||||
% @author Stefan Nothaas, Arbeitsgruppe Betriebssysteme, Institut für Informatik, HHU Düsseldorf
|
||||
% @author Filip Krakowski, Arbeitsgruppe Betriebssyteme, Institut für Informatik, HHU Düsseldorf
|
||||
%
|
||||
% @since 2021/04/29 (major refactoring, minted, university logo)
|
||||
% @since 2019/04/29 (bugfix, wrong page number for reference section)
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesClass{class/thesis}[2021/04/29 Template for theses]
|
||||
|
||||
% Use book class as base
|
||||
\LoadClass[12pt,twoside,a4paper]{book}
|
||||
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Packages
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\RequirePackage[left=3cm,right=2.5cm,top=3cm,bottom=2.5cm]{geometry}
|
||||
|
||||
\RequirePackage[utf8]{inputenc}
|
||||
\RequirePackage[T1]{fontenc}
|
||||
\RequirePackage[english,ngerman]{babel}
|
||||
\RequirePackage{mathtools}
|
||||
% \RequirePackage{amssymb} % Produces some errors I don't understand
|
||||
\RequirePackage[minted]{tcolorbox}
|
||||
% \RequirePackage{minted}
|
||||
\RequirePackage{fancyhdr} % For headers
|
||||
\RequirePackage{color}
|
||||
% \RequirePackage[usenames,dvipsnames]{xcolor} % Option Clash, already loaded by sth else
|
||||
\RequirePackage{graphicx}
|
||||
\RequirePackage{tikz}
|
||||
\RequirePackage{subcaption} % Floats in floats
|
||||
\RequirePackage{float}
|
||||
\RequirePackage{multirow} % For tables
|
||||
% \RequirePackage{todonotes}
|
||||
\RequirePackage{hyperref} % [hidelinks]
|
||||
\RequirePackage{algorithm2e}
|
||||
\RequirePackage{tocloft}
|
||||
\RequirePackage{listings}
|
||||
\RequirePackage{textcomp}
|
||||
\RequirePackage{ifthen}
|
||||
\RequirePackage{pgf} % Not sure if pgf was meant, but pgffor doesn't exist (at least not in my texlive?)
|
||||
\RequirePackage{enumitem}
|
||||
|
||||
% Some additions
|
||||
|
||||
% Borders around svg figures
|
||||
\RequirePackage{svg}
|
||||
\RequirePackage{float}
|
||||
\floatstyle{boxed}
|
||||
\restylefloat{figure}
|
||||
|
||||
\RequirePackage{csquotes}
|
||||
\RequirePackage{tabularx}
|
||||
|
||||
% Extra chapters
|
||||
\RequirePackage[acronym,automake,nonumberlist,nogroupskip]{glossaries} % Must be loaded after hyperref, [toc]
|
||||
\RequirePackage[page]{appendix} % [toc]
|
||||
% \RequirePackage{tocbibind} % Add lists to toc, still needs [heading=bibintoc] for some reason, [nottoc]?
|
||||
|
||||
% Font
|
||||
\RequirePackage{beton} % Computer Concrete font
|
||||
\DeclareFontSeriesDefault[rm]{bf}{sbc} % Computer Concrete does not have bold font
|
||||
\RequirePackage{eulerpx} % Math font
|
||||
\RequirePackage{inconsolata} % Code font
|
||||
|
||||
% Group listings by chapter, pretocmd prepends something to a command
|
||||
\RequirePackage{etoolbox}
|
||||
\pretocmd{\chapter}{\addtocontents{listings}{\protect\addvspace{10pt}}}{}{}
|
||||
|
||||
% Control lot/lof parskip
|
||||
\RequirePackage{tocloft}
|
||||
|
||||
% Allow referencing subsubsections (don't have those anymore)
|
||||
% \setcounter{secnumdepth}{3}
|
||||
% \setcounter{tocdepth}{3}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Package settings
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\tcbuselibrary{skins, breakable}
|
||||
\usetikzlibrary{shadings, backgrounds}
|
||||
|
||||
\fancypagestyle{plain}{%
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0pt}
|
||||
\fancyfoot[RO,LE]{\thepage}
|
||||
}
|
||||
|
||||
\fancypagestyle{thesis}{%
|
||||
\fancyhf{}
|
||||
\renewcommand{\headrulewidth}{0.4pt}
|
||||
\fancyfoot[RO,LE]{\thepage}
|
||||
\fancyhead[LO,RE]{\slshape \leftmark}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Bibliography
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\RequirePackage[style=ieee,backend=biber]{biblatex}
|
||||
\addbibresource{references.bib}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Translations
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\translatemastersthesis}{}
|
||||
\newcommand{\translatebachelorsthesis}{}
|
||||
\newcommand{\translateprojectwork}{}
|
||||
\newcommand{\translateprimaryreviewer}{}
|
||||
\newcommand{\translatesecondaryreviewer}{}
|
||||
\newcommand{\translatesupervisor}{}
|
||||
\newcommand{\translatesubmittedby}{}
|
||||
\newcommand{\translatefrom}{}
|
||||
\newcommand{\translateuniversityname}{}
|
||||
\newcommand{\translatedepartment}{}
|
||||
\newcommand{\translatedeclaration}{}
|
||||
\newcommand{\translatedeclarationtitle}{}
|
||||
|
||||
\addto\captionsenglish{
|
||||
\SetAlgorithmName{Algorithm}{Algorithm}{List of Algorithms}
|
||||
\renewcommand{\chaptername}{Chapter}
|
||||
\renewcommand{\translatemastersthesis}{Master's Thesis}
|
||||
\renewcommand{\translatebachelorsthesis}{Bachelor's Thesis}
|
||||
\renewcommand{\translateprojectwork}{Project Work}
|
||||
\renewcommand{\translateprimaryreviewer}{Primary Reviewer}
|
||||
\renewcommand{\translatesecondaryreviewer}{Secondary Reviewer}
|
||||
\renewcommand{\translatesupervisor}{Supervisor}
|
||||
\renewcommand{\translatesubmittedby}{submitted by}
|
||||
\renewcommand{\translatefrom}{from}
|
||||
\renewcommand{\translateuniversityname}{Heinrich Heine University Düsseldorf}
|
||||
\renewcommand{\translatedepartment}{Department Operating Systems}
|
||||
\renewcommand{\translatedeclarationtitle}{Statutory Declaration}
|
||||
\renewcommand{\translatedeclaration}{I hereby state that I have written this {\thesistypename} independently and that I have not used any sources or aids other than those declared. All passages taken from the literature have been marked as such. This thesis has not yet been submitted to any examination authority in the same or a similar form.}
|
||||
}
|
||||
|
||||
\addto\captionsngerman{
|
||||
\SetAlgorithmName{Algorithmus}{Algorithmus}{Algorithmenverzeichniss}
|
||||
\renewcommand{\chaptername}{Kapitel}
|
||||
\renewcommand{\translatemastersthesis}{Masterarbeit}
|
||||
\renewcommand{\translatebachelorsthesis}{Bachelorarbeit}
|
||||
\renewcommand{\translateprojectwork}{Projektarbeit}
|
||||
\renewcommand{\translateprimaryreviewer}{Erstgutachter}
|
||||
\renewcommand{\translatesecondaryreviewer}{Zweitgutachter}
|
||||
\renewcommand{\translatesupervisor}{Betreuer}
|
||||
\renewcommand{\translatesubmittedby}{vorgelegt von}
|
||||
\renewcommand{\translatefrom}{aus}
|
||||
\renewcommand{\translateuniversityname}{Heinrich-Heine-Universität Düsseldorf}
|
||||
\renewcommand{\translatedepartment}{Abteilung Betriebssysteme}
|
||||
\renewcommand{\translatedeclarationtitle}{Ehrenwörtliche Erklärung}
|
||||
\renewcommand{\translatedeclaration}{Hiermit versichere ich, die vorliegende {\thesistypename} selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt zu haben. Alle Stellen, die aus den Quellen entnommen wurden, sind als solche kenntlich gemacht worden. Diese Arbeit hat in gleicher oder ähnlicher Form noch keiner Prüfungsbehörde vorgelegen.}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Variables
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\thesistitle}[1]{\title{#1}}
|
||||
|
||||
\newcommand{\thesisauthor}[1]{\author{#1}}
|
||||
|
||||
\newcommand{\submissiondate}[1]{\date{#1}}
|
||||
|
||||
\def\@thesislanguage{}
|
||||
\newcommand{\thesislanguage}[1]{\def\@thesislanguage{#1}}
|
||||
|
||||
\def\@thesiskeywords{}
|
||||
\newcommand{\thesiskeywords}[1]{\def\@thesiskeywords{#1}}
|
||||
|
||||
\def\@authorbirthplace{}
|
||||
\newcommand{\authorbirthplace}[1]{\def\@authorbirthplace{#1}}
|
||||
|
||||
\def\@authorbirthname{}
|
||||
\newcommand{\authorbirthname}[1]{\def\@authorbirthname{#1}}
|
||||
|
||||
\def\@firstreviewer{}
|
||||
\newcommand{\firstreviewer}[1]{\def\@firstreviewer{#1}}
|
||||
|
||||
\def\@secondreviewer{}
|
||||
\newcommand{\secondreviewer}[1]{\def\@secondreviewer{#1}}
|
||||
|
||||
\def\@supervisor{}
|
||||
\newcommand{\supervisor}[1]{\def\@supervisor{#1}}
|
||||
|
||||
\def\@thesistype{}
|
||||
\newcommand{\thesistype}[1]{\def\@thesistype{#1}}
|
||||
|
||||
\def\@glossaryenabled{}
|
||||
\newcommand{\glossaryenabled}[1]{\def\@glossaryenabled{#1}}
|
||||
|
||||
\def\@listoffiguresenabled{}
|
||||
\newcommand{\listoffiguresenabled}[1]{\def\@listoffiguresenabled{#1}}
|
||||
|
||||
\def\@listoftablesenabled{}
|
||||
\newcommand{\listoftablesenabled}[1]{\def\@listoftablesenabled{#1}}
|
||||
|
||||
\def\@listofalgorithmsenabled{}
|
||||
\newcommand{\listofalgorithmsenabled}[1]{\def\@listofalgorithmsenabled{#1}}
|
||||
|
||||
\def\@hidefigures{}
|
||||
\newcommand{\hidefigures}[1]{\def\@hidefigures{#1}}
|
||||
|
||||
\def\@hidecode{}
|
||||
\newcommand{\hidecode}[1]{\def\@hidecode{#1}}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Colors
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% Primary
|
||||
\definecolor{hhuCorporateBlue}{HTML}{006AB3}
|
||||
\definecolor{hhuCorporateGrey}{HTML}{D9DADB}
|
||||
|
||||
% Secondary
|
||||
\definecolor{hhuCorporateGreen}{HTML}{97BF0D}
|
||||
\definecolor{hhuCorporateOrange}{HTML}{F29400}
|
||||
\definecolor{hhuCorporateRed}{HTML}{BE0A26}
|
||||
\definecolor{hhuCorporateDarkBlue}{HTML}{003865}
|
||||
\definecolor{hhuCorporateLightBlue}{HTML}{32B8C9}
|
||||
|
||||
% Code
|
||||
\colorlet{titlebg}{hhuCorporateGrey!80!white}
|
||||
\colorlet{titlecolor}{black}
|
||||
\colorlet{termbg}{hhuCorporateGrey!10!white}
|
||||
\colorlet{termfg}{hhuCorporateGrey!20!white}
|
||||
\colorlet{codebg}{white}
|
||||
\colorlet{numberbg}{hhuCorporateGrey!25!white}
|
||||
\colorlet{languagebg}{hhuCorporateGrey!20!white}
|
||||
\definecolor{mintedtext}{HTML}{F8F8F2}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Document settings
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\setlength{\marginparwidth}{2.1cm}
|
||||
|
||||
\AtBeginDocument{
|
||||
|
||||
\hypersetup{
|
||||
pdfauthor={\@author},
|
||||
pdftitle={\@title},
|
||||
pdfkeywords={\@thesiskeywords},
|
||||
pdfproducer={LaTeX with hyperref},
|
||||
pdfcreator={PDFLaTeX}
|
||||
}
|
||||
|
||||
\selectlanguage{\@thesislanguage}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Thesis environment
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newenvironment{thesis}
|
||||
{
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Global options
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\setlength{\parindent}{0pt}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Disable fancy headers
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\pagestyle{empty}
|
||||
\pagenumbering{gobble}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Title page
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\thesiscover
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Table of contents
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\tableofcontents
|
||||
\cleardoublepage
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Re-enable fancy headers
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% \pagenumbering{arabic} % Only number chapters
|
||||
\pagestyle{thesis}
|
||||
|
||||
\ifthenelse{\equal{\@glossaryenabled}{true}}
|
||||
{%
|
||||
\setacronymstyle{short-long}
|
||||
|
||||
\printglossary[type=\acronymtype]
|
||||
\cleardoublepage
|
||||
|
||||
\printglossary
|
||||
\cleardoublepage
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@hidefigures}{true}}
|
||||
{%
|
||||
\excludecomment{figure}
|
||||
\let\endfigure\relax
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@hidecode}{true}}
|
||||
{%
|
||||
\excludecomment{codeblock}
|
||||
\let\endcodeblock\relax
|
||||
}%
|
||||
{}
|
||||
|
||||
\pagenumbering{arabic}
|
||||
}
|
||||
{
|
||||
\pagenumbering{gobble}
|
||||
\printbibliography % [heading=bibintoc]
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
|
||||
\tcblistof[\chapter*]{listings}{List of Listings}
|
||||
% \addcontentsline{toc}{chapter}{List of Listings}
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
|
||||
% The lof/lot linespacing should match the lol linespacing
|
||||
\setlength{\cftparskip}{2pt}
|
||||
|
||||
\ifthenelse{\equal{\@listoftablesenabled}{true}}
|
||||
{%
|
||||
\listoftables
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@listoffiguresenabled}{true}}
|
||||
{%
|
||||
\listoffigures
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@listofalgorithmsenabled}{true}}
|
||||
{%
|
||||
\listofalgorithms
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
\declaration
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Title page
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\thesiscover}
|
||||
{
|
||||
\begin{titlepage}
|
||||
|
||||
\newgeometry{left=2.5cm,right=2.5cm,top=3cm}
|
||||
|
||||
\begin{center}
|
||||
|
||||
\includesvg[width=5cm]{img/hhu_color.svg}
|
||||
|
||||
\vspace{0.75cm}
|
||||
|
||||
{\Large \thesistypename}
|
||||
|
||||
\vspace{0.75cm}
|
||||
|
||||
% Thesis title
|
||||
\rule{\textwidth}{0.25mm}\\
|
||||
\vspace{-5pt}
|
||||
\rule{\textwidth}{0.8mm}\\
|
||||
|
||||
{\Huge \textsc{\@title\\}}
|
||||
|
||||
\rule{\textwidth}{0.8mm}\\
|
||||
\vspace{-5pt}
|
||||
\rule{\textwidth}{0.25mm}
|
||||
|
||||
\vspace{7.5em}
|
||||
|
||||
{\translatesubmittedby} \\[.5em]
|
||||
{\huge \@author} \\[.5em]
|
||||
{{\translatefrom} \@authorbirthplace}\\
|
||||
|
||||
\vfill
|
||||
|
||||
|
||||
% Department
|
||||
|
||||
|
||||
{\translatedepartment}\\
|
||||
Prof. Dr. Michael Schöttner\\
|
||||
{\translateuniversityname}\\
|
||||
|
||||
\vspace{1cm}
|
||||
|
||||
|
||||
% Date
|
||||
\vspace{0.5cm}
|
||||
\@date
|
||||
\vspace{0.5cm}
|
||||
|
||||
|
||||
% People
|
||||
\begin{tabular}{r l}
|
||||
{\translateprimaryreviewer}: & \@firstreviewer \\
|
||||
\ifthenelse{\equal{\@thesistype}{project}}{}{{\translatesecondaryreviewer}: & \@secondreviewer \\}
|
||||
{\translatesupervisor}: & \@supervisor \\
|
||||
\end{tabular}
|
||||
|
||||
|
||||
\end{center}
|
||||
|
||||
\end{titlepage}
|
||||
\clearpage{\pagestyle{empty}\cleardoublepage}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Literature
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\literature}
|
||||
{
|
||||
% Why is this here twice?
|
||||
% \bibliography{\literaturebibtexdatei}
|
||||
% \bibliographystyle{plain}
|
||||
|
||||
% \addcontentsline{toc}{chapter}{Literaturverzeichnis}
|
||||
% \cleardoublepage
|
||||
\bibliography{\literaturebibtexdatei}
|
||||
\bibliographystyle{plain}
|
||||
|
||||
\clearpage{\pagestyle{empty}\cleardoublepage}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Statutory Declaration
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\declaration}
|
||||
{
|
||||
\cleardoublepage
|
||||
\pagestyle{empty}
|
||||
\huge
|
||||
\noindent\textbf{\translatedeclarationtitle}
|
||||
|
||||
\large
|
||||
\vspace{3cm}
|
||||
{\noindent\translatedeclaration}
|
||||
|
||||
\vspace{4cm}
|
||||
\begin{center}
|
||||
\begin{tabular}{lc}
|
||||
Düsseldorf, \@date \hspace{1.5cm} & \hspace{7cm} \\[-10pt]
|
||||
& \hrulefill \\
|
||||
& \@author
|
||||
\\
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
|
||||
\clearpage{\pagestyle{empty}\cleardoublepage}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Miscellaneous
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newcommand{\thesistypename}{%
|
||||
\ifthenelse{\equal{\@thesistype}{bachelor}}
|
||||
{\translatebachelorsthesis}
|
||||
{%
|
||||
\ifthenelse{\equal{\@thesistype}{master}}
|
||||
{\translatemastersthesis}
|
||||
{\translateprojectwork}
|
||||
}%
|
||||
}
|
||||
|
||||
\newtcolorbox[auto counter,list inside=listings,number within=chapter]{codeblock}[3][]
|
||||
{%
|
||||
enhanced,
|
||||
colbacktitle=titlebg,
|
||||
coltitle=titlecolor,
|
||||
colframe=titlebg,
|
||||
interior style={%
|
||||
top color=codebg,
|
||||
bottom color=codebg
|
||||
},
|
||||
boxrule=.5pt,
|
||||
arc=0.6mm,
|
||||
width= (\linewidth),
|
||||
fonttitle=\footnotesize,
|
||||
adjusted title=\thetcbcounter\quad\texttt{#2},
|
||||
list entry=\thetcbcounter\quad\texttt{#2},
|
||||
after title={%
|
||||
\hfill\setlength{\fboxsep}{2pt}
|
||||
\codelang{#3}
|
||||
},
|
||||
overlay={%
|
||||
\begin{tcbclipinterior}\fill[numberbg] (frame.south west)
|
||||
rectangle ([xshift=5mm]frame.north west);
|
||||
\end{tcbclipinterior}
|
||||
},
|
||||
top=0mm,
|
||||
bottom=0mm,
|
||||
right=0mm,
|
||||
left=5mm,
|
||||
#1
|
||||
}
|
||||
|
||||
\newtcolorbox{terminalblock}
|
||||
{%
|
||||
enhanced,
|
||||
colbacktitle=titlebg,
|
||||
coltitle=titlecolor,
|
||||
colframe=titlebg,
|
||||
interior style={%
|
||||
top color=codebg,
|
||||
bottom color=codebg
|
||||
},
|
||||
boxrule=.5pt,
|
||||
arc=0.6mm,
|
||||
width= (\linewidth),
|
||||
fonttitle=\footnotesize,
|
||||
adjusted title={%
|
||||
\tikz\draw[hhuCorporateGrey!50!black,fill=hhuCorporateGrey!50!black] (0,0) circle (.5ex);
|
||||
\tikz\draw[hhuCorporateGrey!60!black,fill=hhuCorporateGrey!60!black] (0,0) circle (.5ex);
|
||||
\tikz\draw[hhuCorporateGrey!70!black,fill=hhuCorporateGrey!70!black] (0,0) circle (.5ex);
|
||||
},
|
||||
top=1mm,
|
||||
bottom=0mm,
|
||||
left=1mm,
|
||||
right=1mm
|
||||
}
|
||||
|
||||
\newtcbox{\codehighlight}{nobeforeafter,boxrule=.5pt,colback=black!5,colframe=black!35,
|
||||
arc=2pt,boxsep=0pt,left=2pt,right=2pt,top=2pt,bottom=1pt, tcbox raise base}
|
||||
|
||||
\newcommand{\code}[1]{\codehighlight{\texttt{#1}}}
|
||||
|
||||
\newtcbox{\languagehighlight}{nobeforeafter,boxrule=0pt,colback=black!5,arc=1pt,
|
||||
boxsep=0pt,left=2pt,right=2pt,top=2pt,bottom=2pt, tcbox raise base}
|
||||
|
||||
\newcommand{\codelang}[1]{\languagehighlight{\texttt{#1}}}
|
||||
|
||||
\newenvironment{noteblock}%
|
||||
{
|
||||
\setlength\topsep{4pt}
|
||||
\setlength\parskip{0pt}
|
||||
\begin{center}
|
||||
\begin{tabular}{|p{.95\linewidth}}
|
||||
}
|
||||
%
|
||||
{
|
||||
\end{tabular}
|
||||
\end{center}
|
||||
}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Code environments
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newminted{java}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{kotlin}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{scala}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{c}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newmintedfile[cppfile]{cpp}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newmintedfile[nasmfile]{nasm}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=0.8,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{rust}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=1.0,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{go}{
|
||||
linenos,
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=1.0,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
||||
|
||||
\newminted{text}{
|
||||
autogobble,
|
||||
breaklines=true,
|
||||
breaksymbol=,
|
||||
breakindent=4mm,
|
||||
breakbefore=.,
|
||||
breakbeforesymbolpre=,
|
||||
breakbeforesymbolpost=,
|
||||
baselinestretch=1.0,
|
||||
escapeinside=||,
|
||||
framesep=5mm,
|
||||
numbersep=7pt,
|
||||
% fontfamily=tt,
|
||||
fontsize=\footnotesize,
|
||||
% style=bw,
|
||||
escapeinside=||
|
||||
}
|
13
code/ap_boot_copy.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
// Allocate physical memory for copying the startup routine
|
||||
auto &memoryService = System::getService<MemoryService>();
|
||||
void *startupCodeMemory = memoryService.mapIO(0x8000, Util::PAGESIZE);
|
||||
|
||||
// Identity map the allocated physical memory to the kernel address space
|
||||
memoryService.unmap(reinterpret_cast<uint32_t>(startupCodeMemory));
|
||||
memoryService.mapPhysicalAddress(0x8000, 0x8000,
|
||||
Kernel::Paging::PRESENT | Kernel::Paging::READ_WRITE);
|
||||
|
||||
// Copy the startup routine and prepared variables to the identity mapped page
|
||||
auto startupCode = Util::Address<uint32_t>(reinterpret_cast<uint32_t>(&boot_ap));
|
||||
auto destination = Util::Address<uint32_t>(0x8000);
|
||||
destination.copyRange(startupCode, boot_ap_size);
|
4
code/ap_boot_post.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Excerpt from the smpEntry function
|
||||
Apic::initializeCurrentLocalApic();
|
||||
Apic::enableCurrentErrorHandler();
|
||||
Apic::startCurrentTimer();
|
25
code/ap_boot_protected_ap.asm
Normal file
@ -0,0 +1,25 @@
|
||||
; Continuing boot_ap_32:
|
||||
; Get the local APIC ID of this AP, to locate GDT and stack
|
||||
mov eax, 0x1
|
||||
cpuid
|
||||
shr ebx, 0x18
|
||||
mov edi, ebx ; Now the ID is in EDI
|
||||
|
||||
; Load the prepared AP GDT
|
||||
mov ebx, [boot_ap_gdts - boot_ap + startup_address]
|
||||
mov eax, [ebx + edi * 0x4]
|
||||
lgdt [eax]
|
||||
|
||||
; Load the TSS
|
||||
mov ax, 0x28
|
||||
ltr ax
|
||||
|
||||
; Load the correct stack for this AP
|
||||
mov ebx, [boot_ap_stacks - boot_ap + startup_address]
|
||||
mov esp, [ebx + edi * 0x4]
|
||||
add esp, stack_size ; Stack starts at the bottom
|
||||
mov ebp, esp
|
||||
|
||||
; Call the entry function
|
||||
push edi
|
||||
call [boot_ap_entry - boot_ap + startup_address]
|
12
code/ap_boot_protected_bsp.asm
Normal file
@ -0,0 +1,12 @@
|
||||
; This section has to be compiled for 32-bit protected mode
|
||||
boot_ap_32:
|
||||
; Set cr3, cr0 and cr4 to the BSP's values for paging
|
||||
mov eax, [boot_ap_cr3 - boot_ap + startup_address]
|
||||
mov cr3, eax
|
||||
mov eax, [boot_ap_cr0 - boot_ap + startup_address]
|
||||
mov cr0, eax
|
||||
mov eax, [boot_ap_cr4 - boot_ap + startup_address]
|
||||
mov cr4, eax
|
||||
|
||||
; Load the system IDT
|
||||
lidt [boot_ap_idtr - boot_ap + startup_address]
|
16
code/ap_boot_real.asm
Normal file
@ -0,0 +1,16 @@
|
||||
; Continuing boot_ap:
|
||||
; Enable Protected Mode, executed from an identity mapped page.
|
||||
mov eax, cr0
|
||||
or al, 0x1 ; Set PE bit
|
||||
mov cr0, eax
|
||||
|
||||
; Setup the protected mode segments
|
||||
mov ax, 0x10
|
||||
mov ds, ax ; Data segment register
|
||||
mov es, ax ; Extra segment register
|
||||
mov ss, ax ; Stack segment register
|
||||
mov fs, ax ; General purpose segment register
|
||||
mov gs, ax ; General purpose segment register
|
||||
|
||||
; Far jump to protected mode, set code segment register
|
||||
jmp dword 0x8:boot_ap_32 - boot_ap + 0x8000
|
13
code/ap_boot_real_prepare.asm
Normal file
@ -0,0 +1,13 @@
|
||||
; This section has to be compiled for 16-bit real mode
|
||||
boot_ap:
|
||||
; Disable interrupts
|
||||
cli
|
||||
|
||||
; Enable A20 address line
|
||||
in al, 0x92
|
||||
or al, 2
|
||||
out 0x92, al
|
||||
|
||||
; Load the temporary GDT required for the far jump into protected mode.
|
||||
lgdt [tmp_gdt_desc - boot_ap + 0x8000]
|
||||
|
19
code/ap_boot_usa.cpp
Normal file
@ -0,0 +1,19 @@
|
||||
// Excerpt from the Universal Startup Algorithm
|
||||
for (uint8_t cpu = 0; cpu < cpuCount; ++cpu) {
|
||||
if (cpu == LocalApic::getId()) { continue; } // Skip the BSP
|
||||
|
||||
LocalApic::clearErrors();
|
||||
LocalApic::sendInitIpi(cpu, ICREntry::Level::ASSERT);
|
||||
LocalApic::waitForIpiDispatch();
|
||||
LocalApic::sendInitIpi(cpu, ICREntry::Level::DEASSERT);
|
||||
LocalApic::waitForIpiDispatch();
|
||||
Pit::earlyDelay(10'000); // 10 milliseconds
|
||||
for (uint8_t i = 0; i < 2; ++i) {
|
||||
LocalApic::clearErrors();
|
||||
LocalApic::sendStartupIpi(cpu, apStartupAddress);
|
||||
LocalApic::waitForIpiDispatch();
|
||||
Pit::earlyDelay(200); // 200 microseconds
|
||||
}
|
||||
|
||||
while (!(runningAPs & (1 << cpu))) {} // Wait until the AP is running
|
||||
}
|
15
code/ap_boot_variables.cpp
Normal file
@ -0,0 +1,15 @@
|
||||
// These variables are located in the startup routine's TEXT section
|
||||
// and exported from smp_boot.asm.
|
||||
|
||||
// Use IDTR from the BSP
|
||||
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 %%cr3, %%eax;" : "=a"(boot_ap_cr3));
|
||||
asm volatile("mov %%cr4, %%eax;" : "=a"(boot_ap_cr4));
|
||||
|
||||
// Set the address of the pre-allocated GDTs, stacks and the entry function
|
||||
boot_ap_gdts = reinterpret_cast<uint32_t>(apGdts);
|
||||
boot_ap_stacks = reinterpret_cast<uint32_t>(apStacks);
|
||||
boot_ap_entry = reinterpret_cast<uint32_t>(&smpEntry);
|
10
code/apic_allow.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
void Apic::allow(InterruptRequest interruptRequest) {
|
||||
IoApic::IrqOverride *override = IoApic::getOverride(interruptRequest);
|
||||
if (override == nullptr) {
|
||||
// If no override is specified, the IRQ is identity mapped to the GSI
|
||||
IoApic::allow(static_cast<GlobalSystemInterrupt>(interruptRequest));
|
||||
} else {
|
||||
// If an override is specified, lookup which GSI the IRQ is mapped to
|
||||
IoApic::allow(override->target);
|
||||
}
|
||||
}
|
8
code/apicerror_trigger.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
void ApicErrorHandler::trigger(const InterruptFrame &frame) {
|
||||
// Write/read register: Write first, then read
|
||||
// Writing the ESR updates its contents and arms the interrupt again
|
||||
LocalApic::writeDoubleWord(LocalApic::ESR, 0);
|
||||
uint32_t errors = LocalApic::readDoubleWord(LocalApic::ESR);
|
||||
|
||||
log.error("APIC error on core [%d]: [0x%x]!", LocalApic::getId(), errors);
|
||||
}
|
11
code/apictimer_calibrate.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// Excerpt from the ApicTimer::calibrate function
|
||||
uint32_t ApicTimer::calibrate() {
|
||||
// Start the timer with a large counter
|
||||
LocalApic::writeDoubleWord(LocalApic::TIMER_INITIAL, 0xFFFFFFFF);
|
||||
|
||||
// Wait a little
|
||||
Pit::earlyDelay(10'000);
|
||||
|
||||
// Calculate how often the timer ticked in one millisecond
|
||||
return (0xFFFFFFFF - LocalApic::readDoubleWord(LocalApic::TIMER_CURRENT)) / 10;
|
||||
}
|
10
code/apictimer_trigger.cpp
Normal file
@ -0,0 +1,10 @@
|
||||
// Excerpt from the APIC timer interrupt handler
|
||||
void ApicTimer::trigger(const InterruptFrame &frame) {
|
||||
if (cpuId != LocalApic::getId()) {
|
||||
// Abort if the handler doesn't belong to the current CPU
|
||||
return;
|
||||
}
|
||||
|
||||
// Increase the "core-local" time
|
||||
time.addNanoseconds(timerInterval * 1'000'000); // Interval is in milliseconds
|
||||
}
|
8
code/interruptdispatcher_assign.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// Excerpt from the "InterruptDispatcher" class
|
||||
void InterruptDispatcher::assign(uint8_t slot, InterruptHandler &isr) {
|
||||
if (handler[slot] == nullptr) {
|
||||
handler[slot] = new Util::ArrayList<InterruptHandler*>;
|
||||
}
|
||||
|
||||
handler[slot]->add(&isr); // Register an interrupt handler to an interrupt vector
|
||||
}
|
4
code/interruptdispatcher_check_spurious.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Excerpt from the "checkSpuriousInterrupt" function
|
||||
bool InterruptService::checkSpuriousInterrupt(InterruptVector interrupt) {
|
||||
return interrupt == InterruptVector::SPURIOUS;
|
||||
}
|
12
code/interruptdispatcher_dispatch.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Excerpt from the "dispatch" function
|
||||
interruptDepthWrapper.inc();
|
||||
interruptService.sendEndOfInterrupt(slot); // Signal interrupt servicing
|
||||
asm volatile("sti"); // Allow cascaded interrupts
|
||||
|
||||
uint32_t size = handlerList->size();
|
||||
for (uint32_t i = 0; i < size; i++) {
|
||||
handlerList->get(i)->trigger(frame); // Call registered interrupt handlers
|
||||
}
|
||||
|
||||
asm volatile("cli");
|
||||
interruptDepthWrapper.dec();
|
5
code/interruptdispatcher_ignore_spurious.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
// Excerpt from the "dispatch" function
|
||||
if (interruptService.checkSpuriousInterrupt(slot)) {
|
||||
spuriousCounterWrapper.inc();
|
||||
return; // Early return to skip the calling of any handlers
|
||||
}
|
4
code/interrupthandler_def.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Excerpt from the "InterruptHandler" class definition
|
||||
public:
|
||||
virtual void plugin() = 0; // Register the handler
|
||||
virtual void trigger(const InterruptFrame &frame) = 0; // Handle an interrupt
|
7
code/interruptservice_after.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
void InterruptService::allowHardwareInterrupt(InterruptRequest interrupt) {
|
||||
if (Apic::isEnabled()) {
|
||||
Apic::allow(interrupt);
|
||||
} else {
|
||||
Pic::allow(interrupt);
|
||||
}
|
||||
}
|
6
code/ioapic_irqoverride.cpp
Normal file
@ -0,0 +1,6 @@
|
||||
struct IrqOverride {
|
||||
InterruptRequest source;
|
||||
GlobalSystemInterrupt target;
|
||||
REDTBLEntry::PinPolarity polarity;
|
||||
REDTBLEntry::TriggerMode trigger;
|
||||
};
|
13
code/ioapic_redtbl_entry.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
struct REDTBLEntry {
|
||||
InterruptVector vector;
|
||||
DeliveryMode deliveryMode;
|
||||
DestinationMode destinationMode;
|
||||
DeliveryStatus deliveryStatus;
|
||||
PinPolarity pinPolarity;
|
||||
TriggerMode triggerMode;
|
||||
bool isMasked;
|
||||
uint8_t destination;
|
||||
|
||||
explicit REDTBLEntry(uint64_t registerValue);
|
||||
explicit operator uint64_t() const;
|
||||
};
|
26
code/ioapic_redtbl_example.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// Excerpt from the IoAPic::initializeREDTBL function
|
||||
void IoApic::initializeREDTBL() {
|
||||
// GSI2 belongs to the PIT in many systems
|
||||
auto gsi = GlobalSystemInterrupt(2);
|
||||
IrqOverride *override = getOverride(gsi);
|
||||
|
||||
REDTBLEntry redtblEntry{};
|
||||
redtblEntry.deliveryMode = REDTBLEntry::DeliveryMode::FIXED;
|
||||
redtblEntry.destinationMode = REDTBLEntry::DestinationMode::PHYSICAL;
|
||||
redtblEntry.isMasked = true;
|
||||
redtblEntry.destination = LocalApic::getId(); // Redirect to BSP
|
||||
|
||||
if (override != nullptr) {
|
||||
// Apply any information provided by an interrupt override
|
||||
redtblEntry.vector = override->source + 32;
|
||||
redtblEntry.pinPolarity = override->polarity;
|
||||
redtblEntry.triggerMode = override->trigger;
|
||||
} else {
|
||||
// Apply PC/AT compatible ISA bus defaults
|
||||
redtblEntry.vector = gsi + 32;
|
||||
redtblEntry.pinPolarity = REDTBLEntry::PinPolarity::HIGH;
|
||||
redtblEntry.triggerMode = REDTBLEntry::TriggerMode::EDGE;
|
||||
}
|
||||
|
||||
writeREDTBL(gsi, redtblEntry);
|
||||
}
|
4
code/ioapic_write_indirect.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
void IoApic::writeIndirectRegister(uint32_t reg, uint32_t val) {
|
||||
writeMMIORegister<uint8_t>(0x00, reg); // Write the index register
|
||||
writeMMIORegister<uint32_t>(0x10, val); // Write the data register
|
||||
}
|
4
code/ioapic_write_mmio.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
template<typename T>
|
||||
void IoApic::writeMMIORegister(uint32_t reg, T val) {
|
||||
*reinterpret_cast<volatile T *>(mmioAddress + reg) = val;
|
||||
}
|
7
code/ioapic_write_redtbl.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
void IoApic::writeREDTBL(GlobalSystemInterrupt gsi, const REDTBLEntry &redtbl) {
|
||||
auto val = static_cast<uint64_t>(redtbl);
|
||||
redtblLock.acquire(); // Synchronized in case of multiple APs
|
||||
writeIndirectRegister(0x10 + 2 * gsi, val & 0xFFFFFFFF); // Low DW
|
||||
writeIndirectRegister(0x10 + 2 * gsi + 1, val >> 32); // High DW
|
||||
redtblLock.release();
|
||||
}
|
12
code/lapic_apr_example.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
void LocalApic::synchronizeArbitrationIds() {
|
||||
ICREntry icrEntry{};
|
||||
icrEntry.vector = 0;
|
||||
icrEntry.deliveryMode = ICREntry::DeliveryMode::INIT;
|
||||
icrEntry.destinationMode = ICREntry::DestinationMode::PHYSICAL;
|
||||
icrEntry.level = ICREntry::Level::DEASSERT;
|
||||
icrEntry.triggerMode = ICREntry::TriggerMode::LEVEL;
|
||||
icrEntry.destinationShorthand = ICREntry::DestinationShorthand::ALL;
|
||||
icrEntry.destination = 0;
|
||||
writeICR(icrEntry);
|
||||
waitForIpiDispatch();
|
||||
}
|
13
code/lapic_icr_entry.cpp
Normal file
@ -0,0 +1,13 @@
|
||||
struct ICREntry {
|
||||
InterruptVector vector;
|
||||
DeliveryMode deliveryMode;
|
||||
DestinationMode destinationMode;
|
||||
DeliveryStatus deliveryStatus;
|
||||
Level level;
|
||||
TriggerMode triggerMode;
|
||||
DestinationShorthand destinationShorthand;
|
||||
uint8_t destination;
|
||||
|
||||
explicit ICREntry(uint64_t registerValue);
|
||||
explicit operator uint64_t() const;
|
||||
};
|
7
code/lapic_imcr.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
void LocalApic::disablePicMode() {
|
||||
IoPort registerSelectorPort = IoPort(0x22);
|
||||
IoPort registerDataPort = IoPort(0x23);
|
||||
|
||||
registerSelectorPort.writeByte(0x70); // IMCR address is 0x70
|
||||
registerDataPort.writeByte(0x01); // 0x01 disconnects PIC
|
||||
}
|
11
code/lapic_initipi_example.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
void LocalApic::issueINIT(uint8_t cpuId, ICREntry::Level level) {
|
||||
ICREntry icrEntry{};
|
||||
icrEntry.vector = 0;
|
||||
icrEntry.deliveryMode = ICREntry::DeliveryMode::INIT;
|
||||
icrEntry.destinationMode = ICREntry::DestinationMode::PHYSICAL;
|
||||
icrEntry.level = level; // ASSERT or DEASSERT
|
||||
icrEntry.triggerMode = ICREntry::TriggerMode::LEVEL;
|
||||
icrEntry.destinationShorthand = ICREntry::DestinationShorthand::NO;
|
||||
icrEntry.destination = cpuId;
|
||||
writeICR(icrEntry); // Writing the ICR issues IPI
|
||||
}
|
12
code/lapic_lvt_entry.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
struct LVTEntry {
|
||||
InterruptVector vector;
|
||||
DeliveryMode deliveryMode;
|
||||
DeliveryStatus deliveryStatus;
|
||||
PinPolarity pinPolarity;
|
||||
TriggerMode triggerMode;
|
||||
bool isMasked;
|
||||
TimerMode timerMode;
|
||||
|
||||
explicit LVTEntry(uint32_t registerValue);
|
||||
explicit operator uint32_t() const;
|
||||
};
|
7
code/lapic_lvt_example.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
LVTEntry lvtEntry{};
|
||||
lvtEntry.deliveryMode = LVTEntry::DeliveryMode::FIXED;
|
||||
lvtEntry.pinPolarity = LVTEntry::PinPolarity::HIGH;
|
||||
lvtEntry.triggerMode = LVTEntry::TriggerMode::EDGE;
|
||||
lvtEntry.isMasked = true;
|
||||
lvtEntry.vector = InterruptVector::LINT0;
|
||||
writeLVT(LINT0, lvtEntry);
|
9
code/lapic_mmio_alloc.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
uint32_t allocateMMIORegion() {
|
||||
// The apicBaseAddress is obtained via ACPI
|
||||
auto &memoryService = System::getService<MemoryService>();
|
||||
void *virtAddressPtr = memoryService.mapIO(apicBaseAddress, Util::PAGESIZE);
|
||||
|
||||
// Account for possible misalignment, as mapIO returns a page-aligned pointer
|
||||
uint32_t pageOffset = apicBaseAddress % Util::PAGESIZE;
|
||||
return reinterpret_cast<uint32_t>(virtAddressPtr) + pageOffset;
|
||||
}
|
4
code/lapic_mmio_write.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
void LocalApic::writeDoubleWord(uint32_t reg, uint32_t val) {
|
||||
// Use volatile to prevent compiletime caching and code elimination
|
||||
*reinterpret_cast<volatile uint32_t *>(virtAddress + reg) = val;
|
||||
}
|
9
code/lapic_msr_entry.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
struct BaseMSREntry {
|
||||
bool isBSP;
|
||||
bool isX2Apic;
|
||||
bool isXApic;
|
||||
uint32_t baseField;
|
||||
|
||||
explicit BaseMSREntry(uint64_t registerValue);
|
||||
explicit operator uint64_t() const;
|
||||
};
|
11
code/lapic_sipi_example.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
void LocalApic::issueSIPI(uint8_t cpuId, uint32_t page) {
|
||||
ICREntry icrEntry{};
|
||||
icrEntry.vector = page;
|
||||
icrEntry.deliveryMode = ICREntry::DeliveryMode::STARTUP;
|
||||
icrEntry.destinationMode = ICREntry::DestinationMode::PHYSICAL;
|
||||
icrEntry.level = ICREntry::Level::ASSERT;
|
||||
icrEntry.triggerMode = ICREntry::TriggerMode::EDGE;
|
||||
icrEntry.destinationShorthand = ICREntry::DestinationShorthand::NO;
|
||||
icrEntry.destination = cpuId;
|
||||
writeICR(icrEntry); // Writing the ICR issues an IPI
|
||||
}
|
9
code/lapic_svr_entry.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
struct SVREntry {
|
||||
InterruptVector vector;
|
||||
bool isSWEnabled;
|
||||
bool hasFocusProcessorChecking;
|
||||
bool suppressEoiBroadcasting;
|
||||
|
||||
explicit SVREntry(uint32_t registerValue);
|
||||
explicit operator uint32_t() const;
|
||||
};
|
4
code/lapic_svr_example.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
SVREntry svrEntry{};
|
||||
svrEntry.vector = InterruptVector::SPURIOUS;
|
||||
svrEntry.isSWEnabled = true; // Keep the APIC software enabled
|
||||
writeSVR(svrEntry);
|
7
code/lapic_write_icr.cpp
Normal file
@ -0,0 +1,7 @@
|
||||
void LocalApic::writeICR(const ICREntry &icrEntry) {
|
||||
auto val = static_cast<uint64_t>(icrEntry);
|
||||
icrLock.acquire(); // Synchronized in case of multiple APs
|
||||
writeDoubleWord(0x310, val >> 32);
|
||||
writeDoubleWord(0x300, val & 0xFFFFFFFF); // Writing the low DW sends the IPI
|
||||
icrLock.release();
|
||||
}
|
3
code/lapic_write_lvt.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
void LocalApic::writeLVT(uint32_t reg, const LVTEntry &lvtEntry) {
|
||||
writeDoubleWord(reg, static_cast<uint32_t>(lvtEntry));
|
||||
}
|
4
code/lapic_write_msr.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
void LocalApic::writeBaseMSR(const MSREntry &msrEntry) {
|
||||
ModelSpecificRegister baseMSR = ModelSpecificRegister(0x1B);
|
||||
baseMSR.writeQuadWord(static_cast<uint64_t>(msrEntry)); // Atomic write
|
||||
}
|
3
code/lapic_write_svr.cpp
Normal file
@ -0,0 +1,3 @@
|
||||
void LocalApic::writeSVR(const SVREntry &svrEntry) {
|
||||
writeDoubleWord(0xF0, static_cast<uint32_t>(svrEntry));
|
||||
}
|
12
code/pit_after.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
void Pit::trigger(const InterruptFrame &frame) {
|
||||
time.addNanoseconds(timerInterval); // Increase system time
|
||||
|
||||
// Don't use PIT for scheduling when the APIC timer is enabled
|
||||
if (Apic::isEnabled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||
System::getService<SchedulerService>().yield(); // Trigger preemption
|
||||
}
|
||||
}
|
8
code/pit_trigger.cpp
Normal file
@ -0,0 +1,8 @@
|
||||
// Excerpt from the "Pit" interrupt handler
|
||||
void Pit::trigger(const InterruptFrame &frame) {
|
||||
time.addNanoseconds(timerInterval); // Increase system time
|
||||
|
||||
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||
System::getService<SchedulerService>().yield(); // Trigger preemption
|
||||
}
|
||||
}
|
4
code/smp_entry.cpp
Normal file
@ -0,0 +1,4 @@
|
||||
// Excerpt from the smpEntry function
|
||||
void smpEntry(uint8_t cpuId) {
|
||||
runningAPs |= (1 << cpuId); // Mark that this AP is running
|
||||
}
|
9
code/system_after.cpp
Normal file
@ -0,0 +1,9 @@
|
||||
// Excerpt from System::initializeSystem(). Located before interrupts
|
||||
// are enabled and any devices have registered their handlers.
|
||||
if (Apic::isSupported()) {
|
||||
Apic::enable();
|
||||
|
||||
if (Apic::isSmpSupported()) {
|
||||
Apic::startupSmp();
|
||||
}
|
||||
}
|
243
glossary.tex
Normal file
@ -0,0 +1,243 @@
|
||||
\makeglossaries
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Acronyms
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newacronym{acpi}{ACPI}{\gls{advanced configuration and power interface}}
|
||||
\newacronym{aml}{AML}{acpi machine language}
|
||||
\newacronym{ap}{AP}{\gls{application processor}}
|
||||
\newacronym{apr}{APR}{arbitration priority register}
|
||||
\newacronym{apic}{APIC}{advanced programmable interrupt controller}
|
||||
\newacronym{bios}{BIOS}{basic input/output system}
|
||||
\newacronym{bsp}{BSP}{\gls{bootstrap processor}}
|
||||
\newacronym{cpuid}{CPUID}{cpu identification}
|
||||
\newacronym{eoi}{EOI}{\gls{end-of-interrupt}}
|
||||
\newacronym{esr}{ESR}{error status register}
|
||||
\newacronym{gdt}{GDT}{global descriptor table}
|
||||
\newacronym{gdtr}{GDTR}{global descriptor table register}
|
||||
\newacronym{gsi}{GSI}{\gls{global system interrupt}}
|
||||
\newacronym{ich}{ICH}{intel input/output controller hub}
|
||||
\newacronym{icr}{ICR}{\gls{interrupt command register}}
|
||||
\newacronym{idt}{IDT}{interrupt descriptor table}
|
||||
\newacronym{idtr}{IDTR}{interrupt descriptor table register}
|
||||
\newacronym{imcr}{IMCR}{\gls{interrupt mode control register}}
|
||||
\newacronym{imr}{IMR}{interrupt mask register}
|
||||
\newacronym{inti}{INTI}{interrupt input}
|
||||
\newacronym{ipi}{IPI}{inter-processor interrupt}
|
||||
\newacronym{irq}{IRQ}{interrupt request}
|
||||
\newacronym{irr}{IRR}{\gls{interrupt request register}}
|
||||
\newacronym{isa}{ISA}{industry standard architecture}
|
||||
\newacronym{isr}{ISR}{\gls{in-service register}}
|
||||
\newacronym{lvt}{LVT}{\gls{local vector table}}
|
||||
\newacronym{madt}{MADT}{multiple apic descriptor table}
|
||||
\newacronym{mmio}{MMIO}{memory mapped input/output}
|
||||
\newacronym{msr}{MSR}{model specific register}
|
||||
\newacronym{msi}{MSI}{\gls{message-signaled interrupt}}
|
||||
\newacronym{nmi}{NMI}{\gls{non-maskable interrupt}}
|
||||
\newacronym{pci}{PCI}{peripheral component interconnect}
|
||||
\newacronym{pic}{PIC}{programmable interrupt controller}
|
||||
\newacronym{pit}{PIT}{\gls{programmable interval timer}}
|
||||
\newacronym{redtbl}{REDTBL}{redirection table}
|
||||
\newacronym{sipi}{SIPI}{startup inter-processor interrupt}
|
||||
\newacronym{smi}{SMI}{system management interrupt}
|
||||
\newacronym{smp}{SMP}{\gls{symmetric multiprocessing}}
|
||||
\newacronym{svr}{SVR}{\gls{spurious interrupt vector register}}
|
||||
\newacronym{tmr}{TMR}{trigger-mode register}
|
||||
\newacronym{tpr}{TPR}{\gls{task-priority register}}
|
||||
\newacronym{tss}{TSS}{task state segment}
|
||||
\newacronym{uefi}{UEFI}{unified extensible firmware interface}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Glossary Entries
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
% \newglossaryentry{}{
|
||||
% name={},
|
||||
% description={}
|
||||
% }
|
||||
|
||||
\newglossaryentry{advanced configuration and power interface}{
|
||||
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},
|
||||
description={a hardware timer that can trigger periodic interrupts by using a counter, integrated into the local APIC}
|
||||
}
|
||||
\newglossaryentry{application processor}{
|
||||
name={application processor},
|
||||
description={a processor inside an SMP system, e.g. a CPU core}
|
||||
}
|
||||
\newglossaryentry{bootstrap processor}{
|
||||
name={bootstrap processor},
|
||||
description={the application processor used to boot an SMP system}
|
||||
}
|
||||
\newglossaryentry{cascaded interrupt}{
|
||||
name={cascaded interrupt},
|
||||
description={an interrupt, serviced during another interrupt handler}
|
||||
}
|
||||
\newglossaryentry{end-of-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},
|
||||
description={an abstraction used by ACPI to decouple interrupts from hardware interrupt lines}
|
||||
}
|
||||
\newglossaryentry{ia32 apic base msr}{
|
||||
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},
|
||||
description={a part of the APIC architecture inside the chipset, responsible for receiving external interrupts}
|
||||
}
|
||||
\newglossaryentry{init ipi}{
|
||||
name={INIT IPI},
|
||||
description={an interprocessor interrupt sent from the BSP to the APs, to begin the AP initialization process}
|
||||
}
|
||||
\newglossaryentry{inter-processor interrupt}{
|
||||
name={inter-processor interrupt},
|
||||
description={an interrupt sent between CPU cores}
|
||||
}
|
||||
\newglossaryentry{interrupt}{
|
||||
name={interrupt},
|
||||
description={a request for the CPU to handle an event}
|
||||
}
|
||||
\newglossaryentry{interrupt command register}{
|
||||
name={interrupt command register},
|
||||
description={a register of the local APIC used to issue interprocessor interrupts}
|
||||
}
|
||||
\newglossaryentry{interrupt controller}{
|
||||
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},
|
||||
description={a register present in some systems to choose the physically connected interrupt controller}
|
||||
}
|
||||
\newglossaryentry{interrupt priority}{
|
||||
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},
|
||||
description={a register, part of the PIC and local APIC, which keeps track of received interrupts}
|
||||
}
|
||||
\newglossaryentry{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}
|
||||
}
|
||||
\newglossaryentry{irq override}{
|
||||
name={IRQ override},
|
||||
description={information from ACPI, that describes how interrupt lines correspond to global system interrupts}
|
||||
}
|
||||
\newglossaryentry{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}
|
||||
}
|
||||
\newglossaryentry{local interrupt}{
|
||||
name={local interrupt},
|
||||
description={an CPU internal interrupt handled by the local APIC, like the APIC timer interrupt}
|
||||
}
|
||||
\newglossaryentry{local vector table}{
|
||||
name={local vector table},
|
||||
description={a set of registers, part of the local APIC, that configure how local interrupts are handled}
|
||||
}
|
||||
\newglossaryentry{masking}{
|
||||
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},
|
||||
description={an interrupt sent in-band over a PCI-bus}
|
||||
}
|
||||
\newglossaryentry{non-maskable interrupt}{
|
||||
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},
|
||||
description={only use the PIC for interrupt handling, like the PC/AT}
|
||||
}
|
||||
\newglossaryentry{pin polarity}{
|
||||
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},
|
||||
description={a set of registers, part of the I/O APIC, that configure how external interrupts are handled}
|
||||
}
|
||||
\newglossaryentry{spurious interrupt}{
|
||||
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},
|
||||
description={a register of the local APIC which contains the APIC software enable flag and the spurious interrupt vector}
|
||||
}
|
||||
\newglossaryentry{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}
|
||||
}
|
||||
\newglossaryentry{symmetric io mode}{
|
||||
name={symmetric I/O mode},
|
||||
description={use the I/O APIC in combination with the local APIC for interrupt handling in multiprocessor systems}
|
||||
}
|
||||
\newglossaryentry{symmetric multiprocessing}{
|
||||
name={symmetric multiprocessing},
|
||||
description={a computer architecture where multiple CPUs operate on a shared main memory}
|
||||
}
|
||||
\newglossaryentry{task-priority register}{
|
||||
name={task-priority register},
|
||||
description={a register of the local APIC which determines interrupt handling order and priority theshold}
|
||||
}
|
||||
\newglossaryentry{trigger 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},
|
||||
description={use the local APIC in combination with the PIC as external interrupt controller}
|
||||
}
|
||||
\newglossaryentry{xapic}{
|
||||
name={xApic},
|
||||
description={a revision of the APIC architecture, register access is handled through MMIO}
|
||||
}
|
||||
\newglossaryentry{x2apic}{
|
||||
name={x2Apic},
|
||||
description={a revision of the APIC architecture, register access is handled through MSRs}
|
||||
}
|
859
img/Architecture.svg
Normal file
@ -0,0 +1,859 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="331.91998pt"
|
||||
height="274.07999pt"
|
||||
viewBox="0 0 331.91998 274.07999"
|
||||
version="1.1"
|
||||
id="svg288"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg" content="%3Cmxfile%20host%3D%22app.diagrams.net%22%20modified%3D%222023-02-22T21%3A36%3A30.923Z%22%20agent%3D%225.0%20(X11)%22%20version%3D%2220.8.23%22%20etag%3D%22rvZp2vNKKJioHv2OAW5W%22%3E%3Cdiagram%20name%3D%22Page-1%22%20id%3D%22HYT1I5f8udhBxdHM_BtV%22%3E7Vldb5swFP01PG7iKyR5zNfWap1UKZPWPnrggifAzJgA%2B%2FUz4RpCSCSWNjiV%2BhTu8fXXuT5H4GjWKiq%2BMpQE36mHQ83UvUKz1pppGlPbFD8VUgKizwHxGfEAa4Et%2BYtlIqAZ8XDaSeSUhpwkXdClcYxd3sEQYzTvpr3QsDtrgnzcA7YuCvvoT%2BLxoEZnE73F7zDxAzmzoUNLhGQyAGmAPJofQNZGs1aMUl4%2FRcUKhxV7kpe635czrc3CGI75kA7A%2Bw6FGext8Xi%2FEsgdYl4uhoFl8lLundEs9nDV3dCsZR4QjrcJcqvWXJRbYAGPQmh%2BoTGH8hkzEcNsmHFcnF2x0fAgThCmEeasFCnQwZLUweGZOhDnbSUMmRMcVEHmISi%2B3wzd8iMegKLTdFk9OrAnTgaElPGA%2BjRG4aZFly1huojanAdKE6DpN%2Ba8BJ5QxukQEquJOxSmNGMuQDaIAjEf806lBxDNcIg42XVHfw1rdu%2BQaaYTikUsPbLr0On8yaqTv9%2Fyp3S%2F54VIMGZJsd%2B4bBdPfvX7QIUoFwlx5YBiKfsx6%2Ba3mmYVojQ9N8VZfeg3oQ9nTH1MbkEfgihWPsF4%2B%2BC5Cj5PZLguDhvXpYwKwp%2FaTBE9wwzVc9upCmSfAVqcjqJF6PpIiRixOQzmsVnOj4pcrwp6HdW5Wcag0jsqSn9pqS%2Bw1BNltNVZ6vRqlnpPR%2FbTX%2BxVY70TWzYchbY8U6LNC%2By00XMj7mF6HqBf%2Be1wI%2B9Ec6V2%2BZ%2F0XmCXp%2BhW6JdyOVcwzMouf5AIsw%2FPfGPPtGcKPdMwenyMoNAhyjrxcTdVqCzzHfGk0oGU3B1cyJOhKyTqetcFH2%2B2I1w4TEZ1aSU3DkNU5ZxQlUr7cXqq%2BoZZXN3M3%2FgFr33F8yTC9q69vvRo%2F7KwNv8A%3C%2Fdiagram%3E%3C%2Fmxfile%3E">
|
||||
<defs
|
||||
id="defs74">
|
||||
<g
|
||||
id="g66">
|
||||
<g
|
||||
id="glyph-0-0" />
|
||||
<g
|
||||
id="glyph-0-1">
|
||||
<path
|
||||
d="M -0.015625 0 L 3.6875 -9.65625 L 5.0625 -9.65625 L 9.015625 0 L 7.5625 0 L 6.4375 -2.921875 L 2.390625 -2.921875 L 1.34375 0 Z M 2.765625 -3.96875 L 6.03125 -3.96875 L 5.03125 -6.640625 C 4.71875 -7.453125 4.488281 -8.117188 4.34375 -8.640625 C 4.21875 -8.015625 4.046875 -7.398438 3.828125 -6.796875 Z M 2.765625 -3.96875 "
|
||||
id="path3" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-2">
|
||||
<path
|
||||
d="M 1.046875 0 L 1.046875 -9.65625 L 4.6875 -9.65625 C 5.320313 -9.65625 5.8125 -9.625 6.15625 -9.5625 C 6.625 -9.476563 7.019531 -9.328125 7.34375 -9.109375 C 7.664063 -8.890625 7.921875 -8.578125 8.109375 -8.171875 C 8.304688 -7.773438 8.40625 -7.335938 8.40625 -6.859375 C 8.40625 -6.035156 8.144531 -5.335938 7.625 -4.765625 C 7.101563 -4.203125 6.160156 -3.921875 4.796875 -3.921875 L 2.3125 -3.921875 L 2.3125 0 Z M 2.3125 -5.0625 L 4.8125 -5.0625 C 5.632813 -5.0625 6.21875 -5.210938 6.5625 -5.515625 C 6.914063 -5.828125 7.09375 -6.265625 7.09375 -6.828125 C 7.09375 -7.222656 6.988281 -7.566406 6.78125 -7.859375 C 6.582031 -8.148438 6.316406 -8.335938 5.984375 -8.421875 C 5.765625 -8.484375 5.363281 -8.515625 4.78125 -8.515625 L 2.3125 -8.515625 Z M 2.3125 -5.0625 "
|
||||
id="path6" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-3">
|
||||
<path
|
||||
d="M 1.25 0 L 1.25 -9.65625 L 2.53125 -9.65625 L 2.53125 0 Z M 1.25 0 "
|
||||
id="path9" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-4">
|
||||
<path
|
||||
d="M 7.921875 -3.390625 L 9.203125 -3.0625 C 8.929688 -2.007813 8.445313 -1.207031 7.75 -0.65625 C 7.0625 -0.101563 6.210938 0.171875 5.203125 0.171875 C 4.160156 0.171875 3.3125 -0.0390625 2.65625 -0.46875 C 2.007813 -0.894531 1.515625 -1.507813 1.171875 -2.3125 C 0.835938 -3.113281 0.671875 -3.976563 0.671875 -4.90625 C 0.671875 -5.90625 0.863281 -6.78125 1.25 -7.53125 C 1.632813 -8.28125 2.179688 -8.847656 2.890625 -9.234375 C 3.597656 -9.617188 4.378906 -9.8125 5.234375 -9.8125 C 6.191406 -9.8125 7 -9.566406 7.65625 -9.078125 C 8.320313 -8.585938 8.785156 -7.894531 9.046875 -7 L 7.78125 -6.703125 C 7.5625 -7.410156 7.238281 -7.921875 6.8125 -8.234375 C 6.382813 -8.554688 5.847656 -8.71875 5.203125 -8.71875 C 4.460938 -8.71875 3.84375 -8.539063 3.34375 -8.1875 C 2.84375 -7.832031 2.488281 -7.351563 2.28125 -6.75 C 2.082031 -6.15625 1.984375 -5.539063 1.984375 -4.90625 C 1.984375 -4.082031 2.101563 -3.363281 2.34375 -2.75 C 2.582031 -2.144531 2.953125 -1.6875 3.453125 -1.375 C 3.960938 -1.070313 4.515625 -0.921875 5.109375 -0.921875 C 5.816406 -0.921875 6.414063 -1.128906 6.90625 -1.546875 C 7.40625 -1.960938 7.742188 -2.578125 7.921875 -3.390625 Z M 7.921875 -3.390625 "
|
||||
id="path12" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-5">
|
||||
<path
|
||||
d="M 1.078125 0 L 1.078125 -9.65625 L 2.359375 -9.65625 L 2.359375 -5.6875 L 7.375 -5.6875 L 7.375 -9.65625 L 8.65625 -9.65625 L 8.65625 0 L 7.375 0 L 7.375 -4.546875 L 2.359375 -4.546875 L 2.359375 0 Z M 1.078125 0 "
|
||||
id="path15" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-6">
|
||||
<path
|
||||
d="M 5.453125 -0.859375 C 5.015625 -0.484375 4.59375 -0.21875 4.1875 -0.0625 C 3.78125 0.0820313 3.34375 0.15625 2.875 0.15625 C 2.101563 0.15625 1.507813 -0.03125 1.09375 -0.40625 C 0.6875 -0.78125 0.484375 -1.257813 0.484375 -1.84375 C 0.484375 -2.1875 0.5625 -2.5 0.71875 -2.78125 C 0.875 -3.0625 1.078125 -3.285156 1.328125 -3.453125 C 1.585938 -3.628906 1.875 -3.765625 2.1875 -3.859375 C 2.414063 -3.910156 2.765625 -3.96875 3.234375 -4.03125 C 4.191406 -4.144531 4.898438 -4.28125 5.359375 -4.4375 C 5.359375 -4.601563 5.359375 -4.707031 5.359375 -4.75 C 5.359375 -5.226563 5.25 -5.566406 5.03125 -5.765625 C 4.71875 -6.035156 4.265625 -6.171875 3.671875 -6.171875 C 3.117188 -6.171875 2.707031 -6.070313 2.4375 -5.875 C 2.175781 -5.675781 1.976563 -5.332031 1.84375 -4.84375 L 0.6875 -5 C 0.789063 -5.488281 0.960938 -5.882813 1.203125 -6.1875 C 1.453125 -6.5 1.800781 -6.738281 2.25 -6.90625 C 2.707031 -7.070313 3.238281 -7.15625 3.84375 -7.15625 C 4.4375 -7.15625 4.921875 -7.082031 5.296875 -6.9375 C 5.671875 -6.800781 5.945313 -6.625 6.125 -6.40625 C 6.300781 -6.195313 6.421875 -5.929688 6.484375 -5.609375 C 6.523438 -5.398438 6.546875 -5.035156 6.546875 -4.515625 L 6.546875 -2.9375 C 6.546875 -1.832031 6.570313 -1.132813 6.625 -0.84375 C 6.675781 -0.550781 6.773438 -0.269531 6.921875 0 L 5.6875 0 C 5.5625 -0.25 5.484375 -0.535156 5.453125 -0.859375 Z M 5.359375 -3.515625 C 4.921875 -3.335938 4.273438 -3.1875 3.421875 -3.0625 C 2.929688 -2.988281 2.582031 -2.90625 2.375 -2.8125 C 2.175781 -2.726563 2.019531 -2.601563 1.90625 -2.4375 C 1.800781 -2.269531 1.75 -2.082031 1.75 -1.875 C 1.75 -1.5625 1.867188 -1.296875 2.109375 -1.078125 C 2.347656 -0.867188 2.695313 -0.765625 3.15625 -0.765625 C 3.613281 -0.765625 4.019531 -0.863281 4.375 -1.0625 C 4.726563 -1.269531 4.988281 -1.546875 5.15625 -1.890625 C 5.289063 -2.160156 5.359375 -2.554688 5.359375 -3.078125 Z M 5.359375 -3.515625 "
|
||||
id="path18" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-7">
|
||||
<path
|
||||
d="M 0.875 0 L 0.875 -7 L 1.9375 -7 L 1.9375 -5.9375 C 2.207031 -6.425781 2.457031 -6.75 2.6875 -6.90625 C 2.925781 -7.070313 3.179688 -7.15625 3.453125 -7.15625 C 3.859375 -7.15625 4.265625 -7.023438 4.671875 -6.765625 L 4.265625 -5.671875 C 3.972656 -5.835938 3.679688 -5.921875 3.390625 -5.921875 C 3.140625 -5.921875 2.910156 -5.84375 2.703125 -5.6875 C 2.492188 -5.53125 2.347656 -5.316406 2.265625 -5.046875 C 2.128906 -4.617188 2.0625 -4.15625 2.0625 -3.65625 L 2.0625 0 Z M 0.875 0 "
|
||||
id="path21" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-8">
|
||||
<path
|
||||
d="M 5.421875 0 L 5.421875 -0.875 C 4.984375 -0.1875 4.332031 0.15625 3.46875 0.15625 C 2.914063 0.15625 2.40625 0.00390625 1.9375 -0.296875 C 1.46875 -0.609375 1.101563 -1.039063 0.84375 -1.59375 C 0.582031 -2.144531 0.453125 -2.773438 0.453125 -3.484375 C 0.453125 -4.179688 0.566406 -4.8125 0.796875 -5.375 C 1.035156 -5.945313 1.382813 -6.382813 1.84375 -6.6875 C 2.3125 -7 2.835938 -7.15625 3.421875 -7.15625 C 3.835938 -7.15625 4.207031 -7.0625 4.53125 -6.875 C 4.863281 -6.695313 5.132813 -6.46875 5.34375 -6.1875 L 5.34375 -9.65625 L 6.53125 -9.65625 L 6.53125 0 Z M 1.671875 -3.484375 C 1.671875 -2.585938 1.859375 -1.914063 2.234375 -1.46875 C 2.617188 -1.03125 3.066406 -0.8125 3.578125 -0.8125 C 4.097656 -0.8125 4.535156 -1.023438 4.890625 -1.453125 C 5.253906 -1.878906 5.4375 -2.523438 5.4375 -3.390625 C 5.4375 -4.347656 5.253906 -5.050781 4.890625 -5.5 C 4.523438 -5.945313 4.070313 -6.171875 3.53125 -6.171875 C 3 -6.171875 2.554688 -5.953125 2.203125 -5.515625 C 1.847656 -5.085938 1.671875 -4.410156 1.671875 -3.484375 Z M 1.671875 -3.484375 "
|
||||
id="path24" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-9">
|
||||
<path
|
||||
d="M 2.171875 0 L 0.046875 -7 L 1.265625 -7 L 2.375 -2.953125 L 2.796875 -1.453125 C 2.804688 -1.523438 2.925781 -2.003906 3.15625 -2.890625 L 4.265625 -7 L 5.484375 -7 L 6.53125 -2.9375 L 6.875 -1.59375 L 7.28125 -2.953125 L 8.484375 -7 L 9.625 -7 L 7.453125 0 L 6.21875 0 L 5.109375 -4.1875 L 4.828125 -5.375 L 3.421875 0 Z M 2.171875 0 "
|
||||
id="path27" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-10">
|
||||
<path
|
||||
d="M 5.671875 -2.25 L 6.90625 -2.09375 C 6.707031 -1.382813 6.347656 -0.832031 5.828125 -0.4375 C 5.304688 -0.0390625 4.640625 0.15625 3.828125 0.15625 C 2.804688 0.15625 1.992188 -0.15625 1.390625 -0.78125 C 0.796875 -1.414063 0.5 -2.300781 0.5 -3.4375 C 0.5 -4.613281 0.800781 -5.523438 1.40625 -6.171875 C 2.007813 -6.828125 2.796875 -7.15625 3.765625 -7.15625 C 4.691406 -7.15625 5.453125 -6.832031 6.046875 -6.1875 C 6.640625 -5.550781 6.9375 -4.660156 6.9375 -3.515625 C 6.9375 -3.441406 6.9375 -3.332031 6.9375 -3.1875 L 1.71875 -3.1875 C 1.757813 -2.425781 1.972656 -1.835938 2.359375 -1.421875 C 2.753906 -1.015625 3.242188 -0.8125 3.828125 -0.8125 C 4.265625 -0.8125 4.632813 -0.925781 4.9375 -1.15625 C 5.25 -1.382813 5.492188 -1.75 5.671875 -2.25 Z M 1.78125 -4.171875 L 5.6875 -4.171875 C 5.632813 -4.753906 5.484375 -5.191406 5.234375 -5.484375 C 4.859375 -5.941406 4.367188 -6.171875 3.765625 -6.171875 C 3.222656 -6.171875 2.765625 -5.988281 2.390625 -5.625 C 2.023438 -5.257813 1.820313 -4.773438 1.78125 -4.171875 Z M 1.78125 -4.171875 "
|
||||
id="path30" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-11">
|
||||
<path
|
||||
d="M 0.984375 0 L 0.984375 -9.65625 L 2.265625 -9.65625 L 2.265625 -1.140625 L 7.015625 -1.140625 L 7.015625 0 Z M 0.984375 0 "
|
||||
id="path33" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-12">
|
||||
<path
|
||||
d="M 0.453125 -3.5 C 0.453125 -4.789063 0.8125 -5.75 1.53125 -6.375 C 2.125 -6.894531 2.859375 -7.15625 3.734375 -7.15625 C 4.691406 -7.15625 5.472656 -6.835938 6.078125 -6.203125 C 6.691406 -5.578125 7 -4.707031 7 -3.59375 C 7 -2.695313 6.863281 -1.988281 6.59375 -1.46875 C 6.320313 -0.957031 5.925781 -0.554688 5.40625 -0.265625 C 4.894531 0.015625 4.335938 0.15625 3.734375 0.15625 C 2.753906 0.15625 1.960938 -0.15625 1.359375 -0.78125 C 0.753906 -1.40625 0.453125 -2.3125 0.453125 -3.5 Z M 1.671875 -3.5 C 1.671875 -2.601563 1.863281 -1.929688 2.25 -1.484375 C 2.644531 -1.035156 3.140625 -0.8125 3.734375 -0.8125 C 4.316406 -0.8125 4.800781 -1.035156 5.1875 -1.484375 C 5.582031 -1.929688 5.78125 -2.613281 5.78125 -3.53125 C 5.78125 -4.394531 5.582031 -5.050781 5.1875 -5.5 C 4.800781 -5.945313 4.316406 -6.171875 3.734375 -6.171875 C 3.140625 -6.171875 2.644531 -5.945313 2.25 -5.5 C 1.863281 -5.0625 1.671875 -4.394531 1.671875 -3.5 Z M 1.671875 -3.5 "
|
||||
id="path36" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-13">
|
||||
<path
|
||||
d="M 5.453125 -2.5625 L 6.609375 -2.40625 C 6.484375 -1.601563 6.160156 -0.972656 5.640625 -0.515625 C 5.117188 -0.0664063 4.472656 0.15625 3.703125 0.15625 C 2.742188 0.15625 1.972656 -0.15625 1.390625 -0.78125 C 0.816406 -1.40625 0.53125 -2.300781 0.53125 -3.46875 C 0.53125 -4.226563 0.65625 -4.890625 0.90625 -5.453125 C 1.15625 -6.015625 1.535156 -6.4375 2.046875 -6.71875 C 2.554688 -7.007813 3.113281 -7.15625 3.71875 -7.15625 C 4.476563 -7.15625 5.097656 -6.960938 5.578125 -6.578125 C 6.054688 -6.191406 6.363281 -5.644531 6.5 -4.9375 L 5.359375 -4.765625 C 5.242188 -5.234375 5.046875 -5.582031 4.765625 -5.8125 C 4.492188 -6.050781 4.160156 -6.171875 3.765625 -6.171875 C 3.160156 -6.171875 2.671875 -5.957031 2.296875 -5.53125 C 1.929688 -5.101563 1.75 -4.425781 1.75 -3.5 C 1.75 -2.5625 1.925781 -1.878906 2.28125 -1.453125 C 2.644531 -1.023438 3.113281 -0.8125 3.6875 -0.8125 C 4.15625 -0.8125 4.546875 -0.953125 4.859375 -1.234375 C 5.171875 -1.523438 5.367188 -1.96875 5.453125 -2.5625 Z M 5.453125 -2.5625 "
|
||||
id="path39" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-14">
|
||||
<path
|
||||
d="M 0.859375 0 L 0.859375 -9.65625 L 2.046875 -9.65625 L 2.046875 0 Z M 0.859375 0 "
|
||||
id="path42" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-15">
|
||||
<path
|
||||
d="M 0.890625 2.6875 L 0.890625 -7 L 1.96875 -7 L 1.96875 -6.078125 C 2.21875 -6.429688 2.503906 -6.695313 2.828125 -6.875 C 3.148438 -7.0625 3.539063 -7.15625 4 -7.15625 C 4.59375 -7.15625 5.117188 -7 5.578125 -6.6875 C 6.035156 -6.382813 6.378906 -5.953125 6.609375 -5.390625 C 6.835938 -4.828125 6.953125 -4.210938 6.953125 -3.546875 C 6.953125 -2.828125 6.820313 -2.179688 6.5625 -1.609375 C 6.3125 -1.035156 5.941406 -0.597656 5.453125 -0.296875 C 4.960938 0.00390625 4.445313 0.15625 3.90625 0.15625 C 3.507813 0.15625 3.15625 0.0703125 2.84375 -0.09375 C 2.53125 -0.257813 2.273438 -0.46875 2.078125 -0.71875 L 2.078125 2.6875 Z M 1.96875 -3.453125 C 1.96875 -2.554688 2.148438 -1.890625 2.515625 -1.453125 C 2.878906 -1.023438 3.316406 -0.8125 3.828125 -0.8125 C 4.359375 -0.8125 4.8125 -1.035156 5.1875 -1.484375 C 5.5625 -1.929688 5.75 -2.625 5.75 -3.5625 C 5.75 -4.445313 5.5625 -5.109375 5.1875 -5.546875 C 4.820313 -5.992188 4.390625 -6.21875 3.890625 -6.21875 C 3.378906 -6.21875 2.929688 -5.984375 2.546875 -5.515625 C 2.160156 -5.046875 1.96875 -4.359375 1.96875 -3.453125 Z M 1.96875 -3.453125 "
|
||||
id="path45" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-16">
|
||||
<path
|
||||
d="M 0.890625 -8.296875 L 0.890625 -9.65625 L 2.078125 -9.65625 L 2.078125 -8.296875 Z M 0.890625 0 L 0.890625 -7 L 2.078125 -7 L 2.078125 0 Z M 0.890625 0 "
|
||||
id="path48" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-17">
|
||||
<path
|
||||
d="M 0.421875 -2.09375 L 1.59375 -2.265625 C 1.65625 -1.796875 1.835938 -1.4375 2.140625 -1.1875 C 2.441406 -0.9375 2.859375 -0.8125 3.390625 -0.8125 C 3.941406 -0.8125 4.347656 -0.921875 4.609375 -1.140625 C 4.867188 -1.367188 5 -1.628906 5 -1.921875 C 5 -2.191406 4.882813 -2.40625 4.65625 -2.5625 C 4.488281 -2.664063 4.082031 -2.800781 3.4375 -2.96875 C 2.570313 -3.1875 1.96875 -3.375 1.625 -3.53125 C 1.289063 -3.6875 1.035156 -3.90625 0.859375 -4.1875 C 0.691406 -4.476563 0.609375 -4.796875 0.609375 -5.140625 C 0.609375 -5.453125 0.679688 -5.738281 0.828125 -6 C 0.972656 -6.269531 1.164063 -6.488281 1.40625 -6.65625 C 1.59375 -6.800781 1.84375 -6.921875 2.15625 -7.015625 C 2.476563 -7.109375 2.820313 -7.15625 3.1875 -7.15625 C 3.738281 -7.15625 4.21875 -7.070313 4.625 -6.90625 C 5.039063 -6.75 5.347656 -6.535156 5.546875 -6.265625 C 5.742188 -5.992188 5.878906 -5.632813 5.953125 -5.1875 L 4.796875 -5.03125 C 4.742188 -5.382813 4.59375 -5.660156 4.34375 -5.859375 C 4.09375 -6.066406 3.734375 -6.171875 3.265625 -6.171875 C 2.722656 -6.171875 2.335938 -6.082031 2.109375 -5.90625 C 1.878906 -5.726563 1.765625 -5.519531 1.765625 -5.28125 C 1.765625 -5.125 1.8125 -4.984375 1.90625 -4.859375 C 2 -4.734375 2.148438 -4.628906 2.359375 -4.546875 C 2.472656 -4.503906 2.820313 -4.398438 3.40625 -4.234375 C 4.238281 -4.015625 4.820313 -3.832031 5.15625 -3.6875 C 5.488281 -3.539063 5.75 -3.332031 5.9375 -3.0625 C 6.125 -2.789063 6.21875 -2.453125 6.21875 -2.046875 C 6.21875 -1.660156 6.101563 -1.289063 5.875 -0.9375 C 5.644531 -0.59375 5.3125 -0.320313 4.875 -0.125 C 4.445313 0.0625 3.957031 0.15625 3.40625 0.15625 C 2.5 0.15625 1.804688 -0.03125 1.328125 -0.40625 C 0.847656 -0.78125 0.546875 -1.34375 0.421875 -2.09375 Z M 0.421875 -2.09375 "
|
||||
id="path51" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-18">
|
||||
<path
|
||||
d="M 3.5 0 L 3.5 -8.515625 L 0.3125 -8.515625 L 0.3125 -9.65625 L 7.96875 -9.65625 L 7.96875 -8.515625 L 4.78125 -8.515625 L 4.78125 0 Z M 3.5 0 "
|
||||
id="path54" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-19">
|
||||
<path
|
||||
d="M 0.890625 0 L 0.890625 -7 L 1.953125 -7 L 1.953125 -6.015625 C 2.171875 -6.359375 2.460938 -6.632813 2.828125 -6.84375 C 3.191406 -7.050781 3.601563 -7.15625 4.0625 -7.15625 C 4.582031 -7.15625 5.007813 -7.046875 5.34375 -6.828125 C 5.675781 -6.609375 5.910156 -6.304688 6.046875 -5.921875 C 6.597656 -6.742188 7.316406 -7.15625 8.203125 -7.15625 C 8.898438 -7.15625 9.429688 -6.960938 9.796875 -6.578125 C 10.171875 -6.191406 10.359375 -5.597656 10.359375 -4.796875 L 10.359375 0 L 9.1875 0 L 9.1875 -4.40625 C 9.1875 -4.875 9.144531 -5.210938 9.0625 -5.421875 C 8.988281 -5.628906 8.847656 -5.796875 8.640625 -5.921875 C 8.441406 -6.054688 8.207031 -6.125 7.9375 -6.125 C 7.445313 -6.125 7.039063 -5.957031 6.71875 -5.625 C 6.394531 -5.300781 6.234375 -4.78125 6.234375 -4.0625 L 6.234375 0 L 5.046875 0 L 5.046875 -4.546875 C 5.046875 -5.066406 4.945313 -5.457031 4.75 -5.71875 C 4.5625 -5.988281 4.25 -6.125 3.8125 -6.125 C 3.476563 -6.125 3.164063 -6.035156 2.875 -5.859375 C 2.59375 -5.679688 2.390625 -5.421875 2.265625 -5.078125 C 2.140625 -4.742188 2.078125 -4.257813 2.078125 -3.625 L 2.078125 0 Z M 0.890625 0 "
|
||||
id="path57" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-20">
|
||||
<path
|
||||
d="M 0.984375 0 L 0.984375 -9.65625 L 2.265625 -9.65625 L 2.265625 -4.859375 L 7.0625 -9.65625 L 8.796875 -9.65625 L 4.734375 -5.734375 L 8.96875 0 L 7.28125 0 L 3.84375 -4.890625 L 2.265625 -3.34375 L 2.265625 0 Z M 0.984375 0 "
|
||||
id="path60" />
|
||||
</g>
|
||||
<g
|
||||
id="glyph-0-21">
|
||||
<path
|
||||
d="M 0.890625 0 L 0.890625 -7 L 1.953125 -7 L 1.953125 -6 C 2.460938 -6.769531 3.207031 -7.15625 4.1875 -7.15625 C 4.601563 -7.15625 4.988281 -7.078125 5.34375 -6.921875 C 5.695313 -6.773438 5.960938 -6.578125 6.140625 -6.328125 C 6.316406 -6.078125 6.4375 -5.785156 6.5 -5.453125 C 6.550781 -5.234375 6.578125 -4.847656 6.578125 -4.296875 L 6.578125 0 L 5.390625 0 L 5.390625 -4.25 C 5.390625 -4.738281 5.34375 -5.097656 5.25 -5.328125 C 5.15625 -5.566406 4.988281 -5.757813 4.75 -5.90625 C 4.519531 -6.050781 4.25 -6.125 3.9375 -6.125 C 3.425781 -6.125 2.988281 -5.960938 2.625 -5.640625 C 2.257813 -5.316406 2.078125 -4.707031 2.078125 -3.8125 L 2.078125 0 Z M 0.890625 0 "
|
||||
id="path63" />
|
||||
</g>
|
||||
</g>
|
||||
<clipPath
|
||||
id="clip-0">
|
||||
<path
|
||||
clip-rule="nonzero"
|
||||
d="M 116 221 L 216 221 L 216 272.046875 L 116 272.046875 Z M 116 221 "
|
||||
id="path68" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
id="clip-1">
|
||||
<path
|
||||
clip-rule="nonzero"
|
||||
d="M 240 150 L 331.921875 150 L 331.921875 197 L 240 197 Z M 240 150 "
|
||||
id="path71" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
d="M 127.777344 225.953125 L 204.222656 225.953125 C 204.664063 225.953125 205.101563 225.996094 205.535156 226.085938 C 205.972656 226.171875 206.394531 226.296875 206.800781 226.46875 C 207.210938 226.636719 207.601563 226.84375 207.96875 227.089844 C 208.335938 227.335938 208.675781 227.617188 208.992188 227.929688 C 209.304688 228.242188 209.582031 228.585938 209.828125 228.953125 C 210.074219 229.320313 210.28125 229.710938 210.453125 230.117188 C 210.621094 230.527344 210.75 230.949219 210.835938 231.382813 C 210.921875 231.816406 210.964844 232.257813 210.964844 232.699219 L 210.964844 264.175781 C 210.964844 264.617188 210.921875 265.058594 210.835938 265.492188 C 210.75 265.925781 210.621094 266.347656 210.453125 266.757813 C 210.28125 267.167969 210.074219 267.554688 209.828125 267.921875 C 209.582031 268.292969 209.304688 268.632813 208.992188 268.945313 C 208.675781 269.257813 208.335938 269.539063 207.96875 269.785156 C 207.601563 270.03125 207.210938 270.238281 206.800781 270.40625 C 206.394531 270.578125 205.972656 270.703125 205.535156 270.792969 C 205.101563 270.878906 204.664063 270.921875 204.222656 270.921875 L 127.777344 270.921875 C 127.335938 270.921875 126.898438 270.878906 126.460938 270.792969 C 126.027344 270.703125 125.605469 270.578125 125.199219 270.40625 C 124.789063 270.238281 124.398438 270.03125 124.03125 269.785156 C 123.664063 269.539063 123.324219 269.257813 123.007813 268.945313 C 122.695313 268.632813 122.417969 268.292969 122.171875 267.921875 C 121.925781 267.554688 121.714844 267.167969 121.546875 266.757813 C 121.378906 266.347656 121.25 265.925781 121.164063 265.492188 C 121.078125 265.058594 121.035156 264.617188 121.035156 264.175781 L 121.035156 232.699219 C 121.035156 232.257813 121.078125 231.816406 121.164063 231.382813 C 121.25 230.949219 121.378906 230.527344 121.546875 230.117188 C 121.714844 229.710938 121.925781 229.320313 122.171875 228.953125 C 122.417969 228.585938 122.695313 228.242188 123.007813 227.929688 C 123.324219 227.617188 123.664063 227.335938 124.03125 227.089844 C 124.398438 226.84375 124.789063 226.636719 125.199219 226.46875 C 125.605469 226.296875 126.027344 226.171875 126.460938 226.085938 C 126.898438 225.996094 127.335938 225.953125 127.777344 225.953125 Z M 127.777344 225.953125 "
|
||||
id="path76" />
|
||||
<g
|
||||
clip-path="url(#clip-0)"
|
||||
id="g80">
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="#000000"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="m 169.99809,300.99772 h 102.00385 c 0.58898,0 1.17276,0.0573 1.75132,0.17721 0.58377,0.11467 1.14669,0.28146 1.68877,0.51081 0.54728,0.22412 1.06851,0.50037 1.55846,0.82874 0.48995,0.32837 0.94342,0.70366 1.36561,1.12064 0.41698,0.41698 0.78705,0.87566 1.11542,1.36561 0.32838,0.48995 0.60463,1.01118 0.83397,1.55325 0.22412,0.54729 0.39613,1.11021 0.5108,1.68877 0.11467,0.57856 0.172,1.16755 0.172,1.75653 v 42.00036 c 0,0.58898 -0.0573,1.17797 -0.172,1.75653 -0.11467,0.57856 -0.28668,1.14148 -0.5108,1.68877 -0.22934,0.54729 -0.50559,1.0633 -0.83397,1.55325 -0.32837,0.49517 -0.69844,0.94863 -1.11542,1.36561 -0.42219,0.41698 -0.87566,0.79227 -1.36561,1.12064 -0.48995,0.32837 -1.01118,0.60462 -1.55846,0.82875 -0.54208,0.22934 -1.105,0.39613 -1.68877,0.51601 -0.57856,0.11467 -1.16234,0.172 -1.75132,0.172 H 169.99809 c -0.58898,0 -1.17275,-0.0573 -1.75653,-0.172 -0.57856,-0.11988 -1.14148,-0.28667 -1.68355,-0.51601 -0.54729,-0.22413 -1.06852,-0.50038 -1.55847,-0.82875 -0.48995,-0.32837 -0.94342,-0.70366 -1.36561,-1.12064 -0.41698,-0.41698 -0.78705,-0.87044 -1.11542,-1.36561 -0.32837,-0.48995 -0.60984,-1.00596 -0.83396,-1.55325 -0.22413,-0.54729 -0.39613,-1.11021 -0.5108,-1.68877 -0.11467,-0.57856 -0.17201,-1.16755 -0.17201,-1.75653 v -42.00036 c 0,-0.58898 0.0573,-1.17797 0.17201,-1.75653 0.11467,-0.57856 0.28667,-1.14148 0.5108,-1.68877 0.22412,-0.54207 0.50559,-1.0633 0.83396,-1.55325 0.32837,-0.48995 0.69844,-0.94863 1.11542,-1.36561 0.42219,-0.41698 0.87566,-0.79227 1.36561,-1.12064 0.48995,-0.32837 1.01118,-0.60462 1.55847,-0.82874 0.54207,-0.22935 1.10499,-0.39614 1.68355,-0.51081 0.58378,-0.11988 1.16755,-0.17721 1.75653,-0.17721 z m 0,0"
|
||||
transform="matrix(0.749436,0,0,0.749436,0.374718,0.374718)"
|
||||
id="path78" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g90">
|
||||
<use
|
||||
xlink:href="#glyph-0-1"
|
||||
x="149.87541"
|
||||
y="244.31601"
|
||||
id="use82" />
|
||||
<use
|
||||
xlink:href="#glyph-0-2"
|
||||
x="158.87303"
|
||||
y="244.31601"
|
||||
id="use84" />
|
||||
<use
|
||||
xlink:href="#glyph-0-3"
|
||||
x="167.87065"
|
||||
y="244.31601"
|
||||
id="use86" />
|
||||
<use
|
||||
xlink:href="#glyph-0-4"
|
||||
x="171.61856"
|
||||
y="244.31601"
|
||||
id="use88" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g108">
|
||||
<use
|
||||
xlink:href="#glyph-0-5"
|
||||
x="136.38557"
|
||||
y="260.80359"
|
||||
id="use92" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="146.1275"
|
||||
y="260.80359"
|
||||
id="use94" />
|
||||
<use
|
||||
xlink:href="#glyph-0-7"
|
||||
x="153.62991"
|
||||
y="260.80359"
|
||||
id="use96" />
|
||||
<use
|
||||
xlink:href="#glyph-0-8"
|
||||
x="158.12213"
|
||||
y="260.80359"
|
||||
id="use98" />
|
||||
<use
|
||||
xlink:href="#glyph-0-9"
|
||||
x="165.62454"
|
||||
y="260.80359"
|
||||
id="use100" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="175.36647"
|
||||
y="260.80359"
|
||||
id="use102" />
|
||||
<use
|
||||
xlink:href="#glyph-0-7"
|
||||
x="182.86888"
|
||||
y="260.80359"
|
||||
id="use104" />
|
||||
<use
|
||||
xlink:href="#glyph-0-10"
|
||||
x="187.3611"
|
||||
y="260.80359"
|
||||
id="use106" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 260.998867 L 221.000017 294.62834 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path110" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 299.882294 L 217.502593 292.882235 L 221.000017 294.62834 L 224.49744 292.882235 Z M 221.000017 299.882294 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path112" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="M 161.001742 201.000592 L 280.998292 201.000592 L 280.998292 260.998867 L 161.001742 260.998867 Z M 161.001742 201.000592 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path114" />
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g134">
|
||||
<use
|
||||
xlink:href="#glyph-0-11"
|
||||
x="136.37386"
|
||||
y="169.37245"
|
||||
id="use116" />
|
||||
<use
|
||||
xlink:href="#glyph-0-12"
|
||||
x="143.87627"
|
||||
y="169.37245"
|
||||
id="use118" />
|
||||
<use
|
||||
xlink:href="#glyph-0-13"
|
||||
x="151.37868"
|
||||
y="169.37245"
|
||||
id="use120" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="158.1236"
|
||||
y="169.37245"
|
||||
id="use122" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="165.62601"
|
||||
y="169.37245"
|
||||
id="use124" />
|
||||
<use
|
||||
xlink:href="#glyph-0-1"
|
||||
x="168.62302"
|
||||
y="169.37245"
|
||||
id="use126" />
|
||||
<use
|
||||
xlink:href="#glyph-0-15"
|
||||
x="177.62064"
|
||||
y="169.37245"
|
||||
id="use128" />
|
||||
<use
|
||||
xlink:href="#glyph-0-16"
|
||||
x="185.12303"
|
||||
y="169.37245"
|
||||
id="use130" />
|
||||
<use
|
||||
xlink:href="#glyph-0-13"
|
||||
x="188.12004"
|
||||
y="169.37245"
|
||||
id="use132" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g146">
|
||||
<use
|
||||
xlink:href="#glyph-0-4"
|
||||
x="148.75127"
|
||||
y="185.86003"
|
||||
id="use136" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="158.49319"
|
||||
y="185.86003"
|
||||
id="use138" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="161.4902"
|
||||
y="185.86003"
|
||||
id="use140" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="168.99261"
|
||||
y="185.86003"
|
||||
id="use142" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="175.73753"
|
||||
y="185.86003"
|
||||
id="use144" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 60.999405 260.998867 L 60.999405 330.999461 L 154.632365 330.999461 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path148" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 159.881107 330.999461 L 152.881048 334.502096 L 154.632365 330.999461 L 152.881048 327.502037 Z M 159.881107 330.999461 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path150" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 120.99768 231.002336 L 154.632365 231.002336 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path152" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 159.881107 231.002336 L 152.881048 234.499759 L 154.632365 231.002336 L 152.881048 227.4997 Z M 159.881107 231.002336 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path154" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="M 1.00113 201.000592 L 120.99768 201.000592 L 120.99768 260.998867 L 1.00113 260.998867 Z M 1.00113 201.000592 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path156" />
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g170">
|
||||
<use
|
||||
xlink:href="#glyph-0-3"
|
||||
x="26.967972"
|
||||
y="169.37245"
|
||||
id="use158" />
|
||||
<use
|
||||
xlink:href="#glyph-0-12"
|
||||
x="30.715881"
|
||||
y="169.37245"
|
||||
id="use160" />
|
||||
<use
|
||||
xlink:href="#glyph-0-1"
|
||||
x="38.218288"
|
||||
y="169.37245"
|
||||
id="use162" />
|
||||
<use
|
||||
xlink:href="#glyph-0-15"
|
||||
x="47.215908"
|
||||
y="169.37245"
|
||||
id="use164" />
|
||||
<use
|
||||
xlink:href="#glyph-0-16"
|
||||
x="54.718315"
|
||||
y="169.37245"
|
||||
id="use166" />
|
||||
<use
|
||||
xlink:href="#glyph-0-13"
|
||||
x="57.715324"
|
||||
y="169.37245"
|
||||
id="use168" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g182">
|
||||
<use
|
||||
xlink:href="#glyph-0-4"
|
||||
x="28.84156"
|
||||
y="185.86003"
|
||||
id="use172" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="38.583492"
|
||||
y="185.86003"
|
||||
id="use174" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="41.580502"
|
||||
y="185.86003"
|
||||
id="use176" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="49.082909"
|
||||
y="185.86003"
|
||||
id="use178" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="55.827831"
|
||||
y="185.86003"
|
||||
id="use180" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 381.000629 260.998867 L 381.000629 330.999461 L 287.367668 330.999461 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path184" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 282.118927 330.999461 L 289.118986 327.502037 L 287.367668 330.999461 L 289.118986 334.502096 Z M 282.118927 330.999461 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path186" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 321.002354 231.002336 L 287.367668 231.002336 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path188" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 282.118927 231.002336 L 289.118986 227.4997 L 287.367668 231.002336 L 289.118986 234.499759 Z M 282.118927 231.002336 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path190" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
d="M 240.945313 151.011719 L 330.875 151.011719 L 330.875 195.976563 L 240.945313 195.976563 Z M 240.945313 151.011719 "
|
||||
id="path192" />
|
||||
<g
|
||||
clip-path="url(#clip-1)"
|
||||
id="g196">
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="#000000"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="M 321.00235,201.00059 H 440.9989 v 59.99828 H 321.00235 Z m 0,0"
|
||||
transform="matrix(0.749436,0,0,0.749436,0.374718,0.374718)"
|
||||
id="path194" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g208">
|
||||
<use
|
||||
xlink:href="#glyph-0-1"
|
||||
x="255.42874"
|
||||
y="169.37245"
|
||||
id="use198" />
|
||||
<use
|
||||
xlink:href="#glyph-0-15"
|
||||
x="264.42636"
|
||||
y="169.37245"
|
||||
id="use200" />
|
||||
<use
|
||||
xlink:href="#glyph-0-16"
|
||||
x="271.92877"
|
||||
y="169.37245"
|
||||
id="use202" />
|
||||
<use
|
||||
xlink:href="#glyph-0-13"
|
||||
x="274.92578"
|
||||
y="169.37245"
|
||||
id="use204" />
|
||||
<use
|
||||
xlink:href="#glyph-0-18"
|
||||
x="281.67068"
|
||||
y="169.37245"
|
||||
id="use206" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g218">
|
||||
<use
|
||||
xlink:href="#glyph-0-16"
|
||||
x="289.41022"
|
||||
y="169.37245"
|
||||
id="use210" />
|
||||
<use
|
||||
xlink:href="#glyph-0-19"
|
||||
x="292.40723"
|
||||
y="169.37245"
|
||||
id="use212" />
|
||||
<use
|
||||
xlink:href="#glyph-0-10"
|
||||
x="303.64438"
|
||||
y="169.37245"
|
||||
id="use214" />
|
||||
<use
|
||||
xlink:href="#glyph-0-7"
|
||||
x="311.14679"
|
||||
y="169.37245"
|
||||
id="use216" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g230">
|
||||
<use
|
||||
xlink:href="#glyph-0-4"
|
||||
x="268.66095"
|
||||
y="185.86003"
|
||||
id="use220" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="278.40289"
|
||||
y="185.86003"
|
||||
id="use222" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="281.3999"
|
||||
y="185.86003"
|
||||
id="use224" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="288.90231"
|
||||
y="185.86003"
|
||||
id="use226" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="295.64722"
|
||||
y="185.86003"
|
||||
id="use228" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 161.001742 130.999998 L 60.999405 130.999998 L 60.999405 194.631215 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path232" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 60.999405 199.879957 L 57.501981 192.879898 L 60.999405 194.631215 L 64.50204 192.879898 Z M 60.999405 199.879957 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path234" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 161.001742 L 221.000017 194.631215 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path236" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 199.879957 L 217.502593 192.879898 L 221.000017 194.631215 L 224.49744 192.879898 Z M 221.000017 199.879957 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path238" />
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 280.998292 130.999998 L 381.000629 130.999998 L 381.000629 194.631215 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path240" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 381.000629 199.879957 L 377.497993 192.879898 L 381.000629 194.631215 L 384.498053 192.879898 Z M 381.000629 199.879957 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path242" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="M 161.001742 100.998255 L 280.998292 100.998255 L 280.998292 161.001742 L 161.001742 161.001742 Z M 161.001742 100.998255 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path244" />
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g254">
|
||||
<use
|
||||
xlink:href="#glyph-0-1"
|
||||
x="152.49844"
|
||||
y="94.428886"
|
||||
id="use246" />
|
||||
<use
|
||||
xlink:href="#glyph-0-15"
|
||||
x="161.49606"
|
||||
y="94.428886"
|
||||
id="use248" />
|
||||
<use
|
||||
xlink:href="#glyph-0-16"
|
||||
x="168.99846"
|
||||
y="94.428886"
|
||||
id="use250" />
|
||||
<use
|
||||
xlink:href="#glyph-0-13"
|
||||
x="171.99548"
|
||||
y="94.428886"
|
||||
id="use252" />
|
||||
</g>
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g266">
|
||||
<use
|
||||
xlink:href="#glyph-0-4"
|
||||
x="148.75127"
|
||||
y="110.91647"
|
||||
id="use256" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="158.49319"
|
||||
y="110.91647"
|
||||
id="use258" />
|
||||
<use
|
||||
xlink:href="#glyph-0-6"
|
||||
x="161.4902"
|
||||
y="110.91647"
|
||||
id="use260" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="168.99261"
|
||||
y="110.91647"
|
||||
id="use262" />
|
||||
<use
|
||||
xlink:href="#glyph-0-17"
|
||||
x="175.73753"
|
||||
y="110.91647"
|
||||
id="use264" />
|
||||
</g>
|
||||
<path
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 60.999405 L 221.000017 94.628878 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path268" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(0%, 0%, 0%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="10"
|
||||
d="M 221.000017 99.87762 L 217.502593 92.87756 L 221.000017 94.628878 L 224.49744 92.87756 Z M 221.000017 99.87762 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path270" />
|
||||
<path
|
||||
fill-rule="nonzero"
|
||||
fill="rgb(100%, 100%, 100%)"
|
||||
fill-opacity="1"
|
||||
stroke-width="1"
|
||||
stroke-linecap="butt"
|
||||
stroke-linejoin="miter"
|
||||
stroke="rgb(0%, 0%, 0%)"
|
||||
stroke-opacity="1"
|
||||
stroke-miterlimit="4"
|
||||
d="M 169.998095 1.00113 L 272.001939 1.00113 C 272.590923 1.00113 273.174696 1.058464 273.753257 1.173134 C 274.337029 1.287804 274.899953 1.459808 275.442027 1.683935 C 275.989314 1.913274 276.51054 2.189524 277.000492 2.517896 C 277.490444 2.846268 277.94391 3.216338 278.366103 3.638531 C 278.783083 4.055511 279.153153 4.508978 279.481525 4.99893 C 279.809898 5.488882 280.086147 6.010107 280.315486 6.557394 C 280.539613 7.099469 280.711618 7.662392 280.826287 8.246165 C 280.940957 8.824725 280.998292 9.408498 280.998292 9.997483 L 280.998292 51.997839 C 280.998292 52.592036 280.940957 53.175809 280.826287 53.754369 C 280.711618 54.33293 280.539613 54.895853 280.315486 55.44314 C 280.086147 55.990427 279.809898 56.50644 279.481525 57.001605 C 279.153153 57.491557 278.783083 57.945023 278.366103 58.362003 C 277.94391 58.784196 277.490444 59.154266 277.000492 59.482638 C 276.51054 59.81101 275.989314 60.08726 275.442027 60.316599 C 274.899953 60.540726 274.337029 60.712731 273.753257 60.8274 C 273.174696 60.94207 272.590923 60.999405 272.001939 60.999405 L 169.998095 60.999405 C 169.40911 60.999405 168.825338 60.94207 168.241565 60.8274 C 167.663005 60.712731 167.100081 60.540726 166.558006 60.316599 C 166.01072 60.08726 165.489494 59.81101 164.999542 59.482638 C 164.50959 59.154266 164.056124 58.784196 163.633931 58.362003 C 163.216951 57.945023 162.84688 57.491557 162.518508 57.001605 C 162.190136 56.50644 161.908674 55.990427 161.684547 55.44314 C 161.46042 54.895853 161.288416 54.33293 161.173746 53.754369 C 161.059077 53.175809 161.001742 52.592036 161.001742 51.997839 L 161.001742 9.997483 C 161.001742 9.408498 161.059077 8.824725 161.173746 8.246165 C 161.288416 7.662392 161.46042 7.099469 161.684547 6.557394 C 161.908674 6.010107 162.190136 5.488882 162.518508 4.99893 C 162.84688 4.508978 163.216951 4.055511 163.633931 3.638531 C 164.056124 3.216338 164.50959 2.846268 164.999542 2.517896 C 165.489494 2.189524 166.01072 1.913274 166.558006 1.683935 C 167.100081 1.459808 167.663005 1.287804 168.241565 1.173134 C 168.825338 1.058464 169.40911 1.00113 169.998095 1.00113 Z M 169.998095 1.00113 "
|
||||
transform="matrix(0.749436, 0, 0, 0.749436, 0.374718, 0.374718)"
|
||||
id="path272" />
|
||||
<g
|
||||
fill="#000000"
|
||||
fill-opacity="1"
|
||||
id="g286">
|
||||
<use
|
||||
xlink:href="#glyph-0-20"
|
||||
x="146.12823"
|
||||
y="27.729118"
|
||||
id="use274" />
|
||||
<use
|
||||
xlink:href="#glyph-0-10"
|
||||
x="155.12585"
|
||||
y="27.729118"
|
||||
id="use276" />
|
||||
<use
|
||||
xlink:href="#glyph-0-7"
|
||||
x="162.62827"
|
||||
y="27.729118"
|
||||
id="use278" />
|
||||
<use
|
||||
xlink:href="#glyph-0-21"
|
||||
x="167.12048"
|
||||
y="27.729118"
|
||||
id="use280" />
|
||||
<use
|
||||
xlink:href="#glyph-0-10"
|
||||
x="174.62289"
|
||||
y="27.729118"
|
||||
id="use282" />
|
||||
<use
|
||||
xlink:href="#glyph-0-14"
|
||||
x="182.12531"
|
||||
y="27.729118"
|
||||
id="use284" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 42 KiB |
94
img/hhu_color.svg
Normal file
After Width: | Height: | Size: 25 KiB |
3297
img/ia32_apic_base_msr.svg
Normal file
After Width: | Height: | Size: 301 KiB |
4730
img/ia32_apic_svr.svg
Normal file
After Width: | Height: | Size: 281 KiB |
5116
img/ia32_error_status_register.svg
Normal file
After Width: | Height: | Size: 265 KiB |
5852
img/ia32_interrupt_command_register.svg
Normal file
After Width: | Height: | Size: 332 KiB |
7178
img/ia32_lvt.svg
Normal file
After Width: | Height: | Size: 300 KiB |
10631
img/ia32_manual_local_apic_blockdiagram.svg
Normal file
After Width: | Height: | Size: 404 KiB |
4275
img/ia32_manual_system_vs_apic_bus.svg
Normal file
After Width: | Height: | Size: 264 KiB |
5269
img/mp_spec_discrete_apic_configuration.svg
Normal file
After Width: | Height: | Size: 186 KiB |
5259
img/mp_spec_integrated_apic_configuration.svg
Normal file
After Width: | Height: | Size: 205 KiB |
2346
img/mp_spec_pic_configuration.svg
Normal file
After Width: | Height: | Size: 125 KiB |
69
properties.tex
Normal file
@ -0,0 +1,69 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Titel der Arbeit %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesistitle{Interrupt Handling using the x86 APIC}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Schlüsselwörter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesiskeywords{Interrupt,APIC,hhuOS}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Sprache der Arbeit %
|
||||
% %
|
||||
% ngerman - Deutsch (neue Rechtschreibung) %
|
||||
% english - Englisch %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesislanguage{english}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Art der Arbeit %
|
||||
% %
|
||||
% bachelor - Bachelorarbeit %
|
||||
% master - Masterarbeit %
|
||||
% project - Projektarbeit %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesistype{bachelor}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Ausgabe von Verzeichnissen %
|
||||
% %
|
||||
% true - Aktiviert %
|
||||
% false - Deaktiviert %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\glossaryenabled{true}
|
||||
\listofalgorithmsenabled{false}
|
||||
\listoffiguresenabled{true}
|
||||
\listoftablesenabled{true}
|
||||
\hidefigures{false}
|
||||
\hidecode{false}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Vollständiger Name %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesisauthor{Christoph Urlacher}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Geburtsort %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\authorbirthplace{Ratingen}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Datum der Abgabe %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\submissiondate{March 15th, 2023}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Erstgutachter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\firstreviewer{Prof. Dr. Michael Schöttner}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Zweitgutachter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\secondreviewer{Prof. Dr. Stefan Conrad}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Betreuer %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\supervisor{M.Sc. Fabian Ruhland}
|
270
references.bib
Normal file
@ -0,0 +1,270 @@
|
||||
@Manual{pic,
|
||||
month = jun,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel 8259A Datasheet}},
|
||||
url = {https://pdos.csail.mit.edu/6.828/2017/readings/hardware/8259A.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1978},
|
||||
note = {Rev 3},
|
||||
comment = {Datasheet for Intel's Programmable Interrupt Controller},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel 8259A Datasheet.pdf:PDF},
|
||||
keywords = {PIC},
|
||||
}
|
||||
|
||||
@Manual{ia32,
|
||||
month = dec,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel 64 and IA-32 Architectures Software Developer's Manual}},
|
||||
url = {https://cdrdv2.intel.com/v1/dl/getContent/671200},
|
||||
urldate = {2023-02-08},
|
||||
year = {2022},
|
||||
abstract = {The general manual for Intel's 32 bit and 64 bit architectures},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel 64 and IA-32 Manual.pdf:PDF},
|
||||
keywords = {x86, Intel 64, Intel IA-32},
|
||||
}
|
||||
|
||||
@Manual{ioapic,
|
||||
month = may,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel 82093AA Datasheet}},
|
||||
url = {https://pdos.csail.mit.edu/6.828/2017/readings/ia32/ioapic.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1996},
|
||||
comment = {Datasheet of Intel's external I/O APIC},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel 82093AA Datasheet.pdf:PDF},
|
||||
keywords = {I/O APIC},
|
||||
}
|
||||
|
||||
@Manual{acpi1,
|
||||
month = feb,
|
||||
organization = {UEFI Forum},
|
||||
title = {{Advanced Configuration and Power Interface Specification}},
|
||||
url = {http://uefi.org/sites/default/files/resources/ACPI_1_Errata_B.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1999},
|
||||
note = {Rev 1.0b},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/ACPI 1 Specification.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{acpi2,
|
||||
month = aug,
|
||||
organization = {UEFI Forum},
|
||||
title = {{Advanced Configuration and Power Interface Specification}},
|
||||
url = {http://uefi.org/sites/default/files/resources/ACPI_2_Errata_C.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2003},
|
||||
note = {Rev 2.0c},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/ACPI 2 Specification.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{acpi65,
|
||||
month = aug,
|
||||
organization = {UEFI Forum},
|
||||
title = {{Advanced Configuration and Power Interface Specification}},
|
||||
url = {https://uefi.org/sites/default/files/resources/ACPI_Spec_6_5_Aug29.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2022},
|
||||
note = {Rev 6.5},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/ACPI 6_5 Specification.pdf:PDF},
|
||||
keywords = {ACPI Specification, UEFI},
|
||||
}
|
||||
|
||||
@Manual{cpp20draft,
|
||||
month = oct,
|
||||
organization = {ISO/IEC JTC and SC22 WG21 and N4860},
|
||||
title = {{C++20 International Standard Draft}},
|
||||
url = {https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/n4868.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2020},
|
||||
note = {N4860},
|
||||
abstract = {C++ Draft International Standard},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/C++20 Standard Draft.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{c99draft,
|
||||
month = sep,
|
||||
organization = {ISO/IEC JTC SC22 WG14},
|
||||
title = {{C99 International Standard Draft}},
|
||||
url = {https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1999},
|
||||
note = {N1256},
|
||||
abstract = {Programming languages - C},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/C99 Standard Draft.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{ich2,
|
||||
month = oct,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel ICH2 Datasheet}},
|
||||
url = {https://www.intel.com/content/dam/doc/datasheet/82801ba-i-o-controller-hub-2-82801bam-i-o-controller-hub-2-mobile-datasheet.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2000},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel ICH2 Datasheet.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{ich5,
|
||||
month = apr,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel ICH5 Datasheet}},
|
||||
url = {https://www.intel.com/content/dam/doc/datasheet/82801eb-82801er-io-controller-hub-datasheet.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2003},
|
||||
note = {Rev 001},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel ICH5 Datasheet.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{mpspec,
|
||||
month = may,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel MultiProcessor Specification}},
|
||||
url = {https://web.archive.org/web/20121002210153/http://download.intel.com/design/archives/processors/pro/docs/24201606.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1997},
|
||||
note = {Rev 1.4},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel MultiProcessor Specification.pdf:PDF},
|
||||
}
|
||||
|
||||
@TechReport{msilatency,
|
||||
author = {Coleman, James},
|
||||
institution = {Intel Corporation},
|
||||
title = {{Reducing Interrupt Latency Through the Use of Message Signalled Interrupts}},
|
||||
year = {2009},
|
||||
month = jan,
|
||||
type = {techreport},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel Reducing Interrupt Latency through the Use of MSIs Whitepaper.pdf:PDF},
|
||||
url = {https://www.intel.com/content/dam/www/public/us/en/documents/white-papers/msg-signaled-interrupts-paper.pdf},
|
||||
}
|
||||
|
||||
@Manual{cpuid,
|
||||
month = may,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel Processor Identification and the CPUID Instruction}},
|
||||
url = {https://www.scss.tcd.ie/~jones/CS4021/processor-identification-cpuid-instruction-note.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {2012},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel CPUID Application Note.pdf:PDF},
|
||||
}
|
||||
|
||||
@Misc{hhuos,
|
||||
author = {Akguel, Burak and Gesse, Christian and Ruhland, Fabian and Krakowski, Filip and Schoettner, Michael and others},
|
||||
howpublished = {GitHub},
|
||||
note = {Branch "experimental"},
|
||||
title = {{hhuOS - A small operating system}},
|
||||
url = {https://github.com/hhuOS/hhuOS/tree/experimental},
|
||||
urldate = {2023-02-08},
|
||||
}
|
||||
|
||||
@Manual{pci22,
|
||||
month = dec,
|
||||
organization = {PCI Special Interest Group},
|
||||
title = {{PCI 2.2 Local Bus Specification}},
|
||||
url = {https://www.ics.uci.edu/~harris/ics216/pci/PCI_22.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1998},
|
||||
note = {Rev 2.2},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/PCI 2_2 Specification.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{pcat,
|
||||
month = mar,
|
||||
organization = {IBM},
|
||||
title = {{PC/AT Technical Reference}},
|
||||
url = {http://bitsavers.informatik.uni-stuttgart.de/pdf/ibm/pc/at/6183355_PC_AT_Technical_Reference_Mar86.pdf},
|
||||
urldate = {2023-02-08},
|
||||
year = {1986},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/PC_AT Technical Reference.pdf:PDF},
|
||||
}
|
||||
|
||||
@Manual{80386,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel 80386 Manual}},
|
||||
url = {https://bitsavers.org/components/intel/80386/230985-001_80386_Programmers_Reference_Manual_1986.pdf},
|
||||
urldate = {2023-02-10},
|
||||
year = {1986},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel 80386 Manual.pdf:PDF},
|
||||
}
|
||||
|
||||
@Misc{x86isa,
|
||||
author = {Félix Cloutier},
|
||||
month = sep,
|
||||
title = {{x86 and amd64 instruction reference}},
|
||||
year = {2022},
|
||||
url = {https://www.felixcloutier.com/x86/index.html},
|
||||
urldate = {2023-02-10},
|
||||
}
|
||||
|
||||
@Misc{linux,
|
||||
author = {Torvalds, Linus and others},
|
||||
month = feb,
|
||||
title = {{Linux 6.1.11}},
|
||||
year = {2023},
|
||||
url = {https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/tree/?h=v6.1.11},
|
||||
urldate = {2023-02-10},
|
||||
}
|
||||
|
||||
@Misc{xv6,
|
||||
author = {Kaashoek, Frans and Morris, Robert and Cox, Russ},
|
||||
title = {{xv6 OS}},
|
||||
url = {https://github.com/mit-pdos/xv6-public},
|
||||
urldate = {2023-02-10},
|
||||
}
|
||||
|
||||
@Misc{osdev,
|
||||
title = {{OSDev}},
|
||||
url = {https://wiki.osdev.org/},
|
||||
urldate = {2023-02-10},
|
||||
}
|
||||
|
||||
@Misc{serenity,
|
||||
author = {Kling, Andreas and others},
|
||||
title = {{SerenityOS}},
|
||||
url = {https://github.com/SerenityOS/serenity},
|
||||
urldate = {2023-02-10},
|
||||
}
|
||||
|
||||
@Manual{acpipre,
|
||||
month = dec,
|
||||
organization = {UEFI Forum},
|
||||
title = {{Advanced Configuration and Power Interface Specification}},
|
||||
url = {https://uefi.org/sites/default/files/resources/ACPI_1.pdf},
|
||||
urldate = {2023-02-21},
|
||||
year = {1996},
|
||||
note = {Rev 1.0},
|
||||
}
|
||||
|
||||
@Manual{mpspecpre,
|
||||
month = oct,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel MultiProcessor Specification}},
|
||||
year = {1993},
|
||||
note = {Rev 1.0},
|
||||
}
|
||||
|
||||
@Misc{irqbalance,
|
||||
author = {Horman, Neil and Waskiewicz, P. J. and Arapov, Anton and others},
|
||||
title = {Irqbalance},
|
||||
url = {https://github.com/Irqbalance/irqbalance},
|
||||
urldate = {2023-02-23},
|
||||
}
|
||||
|
||||
@Misc{acpica,
|
||||
title = {{ACPICA}},
|
||||
organization = {Intel Corporation},
|
||||
url = {https://acpica.org/},
|
||||
urldate = {2023-02-23},
|
||||
}
|
||||
|
||||
@Manual{pit,
|
||||
month = sep,
|
||||
organization = {Intel Corporation},
|
||||
title = {{Intel 8254 Datasheet}},
|
||||
url = {https://www.scs.stanford.edu/10wi-cs140/pintos/specs/8254.pdf},
|
||||
urldate = {2023-02-26},
|
||||
year = {1993},
|
||||
note = {Rev 5},
|
||||
abstract = {DATASHEET SEARCH, DATABOOK, COMPONENT, FREE DOWNLOAD SITE},
|
||||
file = {:/home/christoph/Notes/HHU/Bachelorarbeit/literature/Intel 8254 Datasheet.pdf:PDF},
|
||||
}
|
||||
|
||||
@Comment{jabref-meta: databaseType:bibtex;}
|
45
thesis.tex
Normal file
@ -0,0 +1,45 @@
|
||||
% !TeX document-id = {631e44a8-cd91-47da-bf82-1571f8787194}
|
||||
% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
|
||||
|
||||
\documentclass{class/thesis}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Bitte ergänzen Sie Ihre persönlichen Daten innerhalb %
|
||||
% der im Folgenden inkludierten Datei properties.tex %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\include{properties}
|
||||
\include{glossary}
|
||||
|
||||
\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}
|
||||
|
||||
\include{chap/introduction}
|
||||
\include{chap/background}
|
||||
\include{chap/implementation}
|
||||
\include{chap/verification}
|
||||
\include{chap/conclusion}
|
||||
|
||||
% \pagenumbering{gobble} % Don't number appendix?
|
||||
\begin{appendices}
|
||||
\include{chap/appendix_listings}
|
||||
% \raggedbottom % The figures/tables shouldn't have huge vspace between them
|
||||
\include{chap/appendix_tables}
|
||||
\include{chap/appendix_figures}
|
||||
\end{appendices}
|
||||
|
||||
\end{thesis}
|
||||
|
||||
\end{document}
|