Final pre-release
This commit is contained in:
@ -1,49 +0,0 @@
|
||||
\chapter{Figures}
|
||||
\label{ch:figures}
|
||||
|
||||
\clearpage
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{1.0\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/mp_spec_discrete_apic_configuration.svg}
|
||||
\end{subfigure}
|
||||
\caption{The discrete APIC architecture~\cite[sec.~5.1]{mpspec}.}
|
||||
\label{fig:discreteapic}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{1.0\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/mp_spec_integrated_apic_configuration.svg}
|
||||
\end{subfigure}
|
||||
\caption{The integrated APIC architecture~\cite[sec.~5.2]{mpspec}.}
|
||||
\label{fig:integratedapic}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_system_vs_apic_bus.svg}
|
||||
\end{subfigure}
|
||||
\caption{System vs APIC bus~\cite[sec.~3.11.1]{ia32}.}
|
||||
\label{fig:systemvsapicbus}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{1.0\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_local_apic_blockdiagram.svg}
|
||||
\end{subfigure}
|
||||
\caption{The local APIC block diagram~\cite[sec.~3.11.4.1]{ia32}.}
|
||||
\label{fig:localapicblock}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{1.0\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_lvt.svg}
|
||||
\end{subfigure}
|
||||
\caption{The Local Vector Table~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{fig:localapiclvt}
|
||||
\end{figure}
|
@ -1,360 +0,0 @@
|
||||
\chapter{Listings}
|
||||
\label{ch:listings}
|
||||
|
||||
This chapter contains concrete implementation examples for concepts mentioned in
|
||||
\autoref{ch:implementation}, demonstrated on the example of hhuOS\@.
|
||||
|
||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Accessing Local APIC Registers in xApic Mode}
|
||||
\label{sec:apxxapicregacc}
|
||||
|
||||
The xApic register access requires a single page of strong uncachable memory, but since this
|
||||
requires setting attributes in the ``Page Attribute Table''\footnote{See
|
||||
\url{https://docs.kernel.org/x86/pat.html} (visited on 12/02/2023).}, this implementation only uses
|
||||
hhuOS' \code{mapIO} function\cite[MemoryService.cpp]{hhuos}, which maps a physical address to the
|
||||
kernel heap, with hhuOS' ``CACHE\textunderscore{}DISABLE'' flag set in the kernel page table:
|
||||
|
||||
\begin{codeblock}{Allocating the Local APIC's MMIO Region (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_mmio_alloc.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
A register can now be written as follows:
|
||||
|
||||
\begin{codeblock}[label=lst:lapicmmiowrite]{Writing a Local APIC MMIO Register (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_mmio_write.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To reduce the usage of manual bit-shifting and -masking, this implementation provides structures
|
||||
for some commonly used registers, that implement conversion operators to the register format:
|
||||
|
||||
\begin{codeblock}[label=lst:msrentry]{The MSREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_msr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:svrentry]{The SVREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_svr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:lvtentry]{The LVTEntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_lvt_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:icrentry]{The ICREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_icr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
These can be used in combination with some convenience functions:
|
||||
|
||||
\begin{codeblock}{Writing the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_msr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the SVR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_svr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the LVT (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_lvt.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the ICR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_icr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Disabling PIC-Mode}
|
||||
\label{sec:apxdisablepic}
|
||||
|
||||
Setting the IMCR\footnote{Writing the IMCR is detailed in the MultiProcessor
|
||||
specification~\cite[sec. 3.6.2.1]{mpspec}.} using hhuOS' \code{IoPort} class:
|
||||
|
||||
\begin{codeblock}{Disabling PIC-Mode (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_imcr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Initializing the LVT}
|
||||
\label{sec:apxlvtinit}
|
||||
|
||||
The interrupt vectors are set as defined by the \code{InterruptVector} enum. This implementation
|
||||
configures the LVT by using the \code{LVTEntry} struct (see \autoref{lst:lvtentry}):
|
||||
|
||||
\begin{codeblock}{Configuring the LINT0 Local Interrupt (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_lvt_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
This process is repeated for each local interrupt.
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Handling the Spurious Interrupt}
|
||||
\label{sec:apxsvr}
|
||||
|
||||
This implementation sets the SVR by using the \code{SVREntry} struct (see \autoref{lst:svrentry}):
|
||||
|
||||
\begin{codeblock}{Setting the Spurious Interrupt Vector (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_svr_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because hhuOS uses a two-stage interrupt handling approach (described in
|
||||
\autoref{sec:currenthhuos}), the spurious interrupt does not receive its own interrupt handler.
|
||||
Instead, it is ignored in the \code{dispatch} function, hhuOS' ``first-stage'' interrupt handler:
|
||||
|
||||
\begin{codeblock}{Checking for Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||
\cppfile{code/interruptdispatcher_check_spurious.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||
\cppfile{code/interruptdispatcher_ignore_spurious.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Using the APIC Timer}
|
||||
\label{sec:apxapictimer}
|
||||
|
||||
The timer frequency is determined by counting the ticks in one millisecond, using the PIT as
|
||||
calibration source:
|
||||
|
||||
\begin{codeblock}{Calibrating the APIC Timer (ApicTimer.cpp)}{C++}
|
||||
\cppfile{code/apictimer_calibrate.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
This calibration is performed before the interrupts get enabled, so it is not possible to use
|
||||
hhuOS' \code{TimeService} for the delay. Instead, the \code{PIT::earlyDelay} function is used,
|
||||
which configures the PIT for mode 0 on channel 0 and polls the channel's output status~\cite{pit}].
|
||||
Furthermore, the calibration is only performed once, even if multiple APIC timers are used. This
|
||||
removes the possibility of using multiple timers with different dividers.
|
||||
|
||||
To handle the APIC timer interrupt on multiple cores, \(n\) \code{ApicTimer} instances are
|
||||
registered to the appropriate interrupt vector, where \(n\) is the number of CPUs. Because this
|
||||
means, that each APIC timer interrupt on any CPU core triggers all \(n\) interrupt handlers, the
|
||||
handler has to determine if it belongs to the calling CPU:
|
||||
|
||||
\begin{codeblock}{Handling the APIC Timer Interrupt (ApicTimer.cpp)}{C++}
|
||||
\cppfile{code/apictimer_trigger.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Handling local APIC Errors}
|
||||
\label{sec:apxhandlingerror}
|
||||
|
||||
The error interrupt handler obtains the ESR's contents by writing to it first:
|
||||
|
||||
\begin{codeblock}{The local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}{C++}
|
||||
\cppfile{code/apicerror_trigger.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because every CPU core can only access its own local APIC's registers, a single instance of this
|
||||
interrupt handler can be used for each AP in the system.
|
||||
|
||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Accessing I/O APIC Registers}
|
||||
\label{sec:iolistings}
|
||||
|
||||
The I/O APIC's indirect register access requires two MMIO registers, that can be written similar to
|
||||
the local APIC's registers:
|
||||
|
||||
\begin{codeblock}{Writing an I/O APIC MMIO Register (IoApic.h)}{C++}
|
||||
\cppfile{code/ioapic_write_mmio.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Using the ``Index'' and ``Data'' registers to access the I/O APIC's indirect registers:
|
||||
|
||||
\begin{codeblock}{Writing an I/O APIC indirect Register (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_write_indirect.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To reduce the manual bit-shifting and -masking, the same approach is used as for the local APIC:
|
||||
|
||||
\begin{codeblock}[label=lst:redtblentry]{The REDTBLEntry Structure (IoApicRegisters.h)}{C++}
|
||||
\cppfile{code/ioapic_redtbl_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:writeredtbl]{Writing the REDTBL (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_write_redtbl.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{I/O APIC Interrupt Overrides}
|
||||
\label{sec:apxirqoverrides}
|
||||
|
||||
This implementation represents an interrupt override using the following structure:
|
||||
|
||||
\begin{codeblock}{The External Interrupt Override Structure (IoApic.h)}{C++}
|
||||
\cppfile{code/ioapic_irqoverride.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
During initialization, they are used to set the correct interrupt vectors, polarities and trigger
|
||||
modes for each REDTBL entry. The \code{REDTBLEntry} struct (see \autoref{lst:redtblentry}) is used
|
||||
to write the REDTBL:
|
||||
|
||||
\begin{codeblock}{Initializing the REDTBL (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_redtbl_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
During regular OS operation, they are used to determine the correct REDTBL entries for e.g.\
|
||||
unmasking an interrupt:
|
||||
|
||||
\begin{codeblock}{Unmasking an IRQ (Apic.cpp)}{C++}
|
||||
\cppfile{code/apic_allow.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To convey this deviation between GSIs and PC/AT compatible IRQs very clearly, the internal
|
||||
\code{IoApic::allow} function only accepts a \code{GlobalSystemInterrupt} as argument, while the
|
||||
public \code{Apic::allow} function accepts an \code{InterruptRequest}, that allows addressing the
|
||||
interrupt by name.
|
||||
|
||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Issuing Inter-Processor Interrupts}
|
||||
\label{sec:apxipis}
|
||||
|
||||
To issue an IPI, the ICR is written by using the \code{ICREntry} struct (see
|
||||
\autoref{lst:icrentry}):
|
||||
|
||||
\begin{codeblock}{Issuing an INIT IPI (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_initipi_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Issuing a SIPI (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_sipi_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Preparing Symmetric Multiprocessing Startup}
|
||||
\label{sec:apxpreparesmp}
|
||||
|
||||
Before executing the ``Universal Startup Algorithm'', the boot code has to be relocated to physical
|
||||
lower memory. The memory region used for this copy has to be identity mapped to the virtual kernel
|
||||
address space, so the effective addresses don't change after enabling paging in protected mode. To
|
||||
keep required variables available to the startup code, these are located in the routines ``TEXT''
|
||||
section and initialized during runtime. This approach was taken from~\cite[APIC.cpp]{serenity}:
|
||||
|
||||
\begin{codeblock}{Preparing the Boot Routine's Variables (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_variables.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Now, the initialized startup routine can be copied to \code{0x8000}:
|
||||
|
||||
\begin{codeblock}{Relocating the Boot Routine (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_copy.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The \code{boot\textunderscore{}ap} function is the entry of the startup routine, it is described
|
||||
further in \autoref{sec:apxapboot}.
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Universal Startup Algorithm}
|
||||
\label{sec:apxmpusa}
|
||||
|
||||
The ``INIT-SIPI-SIPI'' sequence, or ``Universal Startup Algorithm'' is performed by issuing IPIs as
|
||||
described in \autoref{sec:apxipis} and using the PIT as time source (see
|
||||
\autoref{sec:apxapictimer}):
|
||||
|
||||
\begin{codeblock}{The Universal Startup Algorithm (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_usa.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Boot completion is signaled in the AP's entry function:
|
||||
|
||||
\begin{codeblock}{Signaling AP Boot Completion (smp\textunderscore{}entry.cpp)}{C++}
|
||||
\cppfile{code/smp_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Application Processor Boot Routine}
|
||||
\label{sec:apxapboot}
|
||||
|
||||
Because like the BSP, every AP is initialized in real mode, it has to be switched to protected mode
|
||||
first:
|
||||
|
||||
\begin{codeblock}{Preparing the Switch to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_real_prepare.asm}
|
||||
\end{codeblock}
|
||||
|
||||
Then, by enabling protected mode, setting the segment registers and far-jumping to the 32-bit code
|
||||
segment, the switch is performed:
|
||||
|
||||
\begin{codeblock}{Switching from Real Mode to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_real.asm}
|
||||
\end{codeblock}
|
||||
|
||||
In 32-bit protected mode, paging is enabled and interrupt processing is prepared by reusing the
|
||||
control register values and the IDT from the BSP:
|
||||
|
||||
\begin{codeblock}{Loading Registers from the BSP (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_protected_bsp.asm}
|
||||
\end{codeblock}
|
||||
|
||||
Finally, to call the AP entry function, the AP requires its own GDT and stack:
|
||||
|
||||
\begin{codeblock}{Calling the Entry Function (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_protected_ap.asm}
|
||||
\end{codeblock}
|
||||
|
||||
The rest of the AP's initialization is performed from the entry function.
|
||||
|
||||
% \clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Application Processor Post-Boot Routine}
|
||||
\label{sec:apxappostboot}
|
||||
|
||||
When the AP has booted, it initializes its own APIC, including the APIC timer and error handler:
|
||||
|
||||
\begin{codeblock}{Initializing the Core's Local APIC (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_post.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because this added another possible recipient to internal APIC messages, the arbitration IDs are
|
||||
synchronized by issuing an ``INIT-level-deassert IPI'' using the \code{ICREntry} struct (see
|
||||
\autoref{lst:icrentry}):
|
||||
|
||||
\begin{codeblock}{Synchronizing the Arbitration IDs (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_apr_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because hhuOS' paging is not designed for multiple processors, the booted AP remains in a busy loop
|
||||
and does not enable its interrupts.
|
||||
|
||||
\clearpage %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\section{Integration into hhuOS}
|
||||
\label{sec:hhuosintegration}
|
||||
|
||||
To integrate the APIC implementation into hhuOS, some preexisting components of its interrupt
|
||||
infrastructure (described in \autoref{sec:currenthhuos}) have to be modified:
|
||||
|
||||
\begin{enumerate}
|
||||
\item The \code{InterruptService} has to forward calls to allow or forbid a hardware interrupt to the
|
||||
\code{Apic} class instead of the \code{Pic} class, depending on if the APIC system is enabled - to
|
||||
keep the option of running the OS on hardware that does not support the APIC (see
|
||||
\autoref{lst:interruptserviceafter}).
|
||||
\item The \code{Pit} interrupt handler may no longer trigger the scheduler preemption if the APIC timer
|
||||
is enabled (see \autoref{lst:pithandlerafter}).
|
||||
\item The \code{System::initializeSystem} function needs to enable the APIC system if it is available
|
||||
(see \autoref{lst:systemafter}).
|
||||
\end{enumerate}
|
||||
|
||||
\begin{codeblock}[label=lst:interruptserviceafter]{Using the correct interrupt controller (InterruptService.cpp)}{C++}
|
||||
\cppfile{code/interruptservice_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:pithandlerafter]{Disable preemption if necessary (Pit.cpp)}{C++}
|
||||
\cppfile{code/pit_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:systemafter]{Enabling the APIC system (System.cpp)}{C++}
|
||||
\cppfile{code/system_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\cleardoublepage
|
236
chap/background.aux
Normal file
236
chap/background.aux
Normal file
@ -0,0 +1,236 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {2}Background}{3}{chapter.2}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:background}{{2}{3}{Background}{chapter.2}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.1}Handling of External Events}{4}{section.2.1}\protected@file@percent }
|
||||
\newlabel{sec:eventhandling}{{2.1}{4}{Handling of External Events}{section.2.1}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.2}Fundamental Concepts}{4}{section.2.2}\protected@file@percent }
|
||||
\newlabel{sec:fundamentals}{{2.2}{4}{Fundamental Concepts}{section.2.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.1}Interrupt}{4}{subsection.2.2.1}\protected@file@percent }
|
||||
\newlabel{subsec:interrupt}{{2.2.1}{4}{Interrupt}{subsection.2.2.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.2}Interrupt Controller}{5}{subsection.2.2.2}\protected@file@percent }
|
||||
\newlabel{subsec:controller}{{2.2.2}{5}{Interrupt Controller}{subsection.2.2.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.3}Interrupt Handler}{5}{subsection.2.2.3}\protected@file@percent }
|
||||
\newlabel{subsec:handler}{{2.2.3}{5}{Interrupt Handler}{subsection.2.2.3}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2.1}{\ignorespaces Interrupt Handler Execution.\relax }}{6}{figure.2.1}\protected@file@percent }
|
||||
\providecommand*\caption@xref[2]{\@setref\relax\@undefined{#1}}
|
||||
\newlabel{fig:interruptexecution}{{2.1}{6}{Interrupt Handler Execution.\relax }{figure.2.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.4}Interrupt Trigger Mode}{6}{subsection.2.2.4}\protected@file@percent }
|
||||
\newlabel{subsec:triggermode}{{2.2.4}{6}{Interrupt Trigger Mode}{subsection.2.2.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.2.5}Spurious Interrupt}{6}{subsection.2.2.5}\protected@file@percent }
|
||||
\newlabel{subsec:spurious}{{2.2.5}{6}{Spurious Interrupt}{subsection.2.2.5}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.3}Used Technologies}{7}{section.2.3}\protected@file@percent }
|
||||
\newlabel{sec:technologies}{{2.3}{7}{Used Technologies}{section.2.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.1}Advanced Configuration and Power Interface}{7}{subsection.2.3.1}\protected@file@percent }
|
||||
\newlabel{subsec:acpi}{{2.3.1}{7}{Advanced Configuration and Power Interface}{subsection.2.3.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.2}CPU Identification}{7}{subsection.2.3.2}\protected@file@percent }
|
||||
\newlabel{subsec:cpuid}{{2.3.2}{7}{CPU Identification}{subsection.2.3.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.3}Symmetric Multiprocessing}{7}{subsection.2.3.3}\protected@file@percent }
|
||||
\newlabel{subsec:smp}{{2.3.3}{7}{Symmetric Multiprocessing}{subsection.2.3.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.4}Model Specific Register}{8}{subsection.2.3.4}\protected@file@percent }
|
||||
\newlabel{subsec:msr}{{2.3.4}{8}{Model Specific Register}{subsection.2.3.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.5}Memory Mapped I/O}{8}{subsection.2.3.5}\protected@file@percent }
|
||||
\newlabel{subsec:mmio}{{2.3.5}{8}{Memory Mapped I/O}{subsection.2.3.5}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.3.6}Programmable Interval Timer}{8}{subsection.2.3.6}\protected@file@percent }
|
||||
\newlabel{subsec:pit}{{2.3.6}{8}{Programmable Interval Timer}{subsection.2.3.6}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.4}Intel's Interrupt Controllers}{8}{section.2.4}\protected@file@percent }
|
||||
\newlabel{sec:intelcontrollers}{{2.4}{8}{Intel's Interrupt Controllers}{section.2.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.1}Programmable Interrupt Controller}{8}{subsection.2.4.1}\protected@file@percent }
|
||||
\newlabel{subsec:intelpic}{{2.4.1}{8}{Programmable Interrupt Controller}{subsection.2.4.1}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2.2}{\ignorespaces The PC/AT PIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~1.13]{pcat}.\relax }}{9}{figure.2.2}\protected@file@percent }
|
||||
\newlabel{fig:pcatpic}{{2.2}{9}{The PC/AT PIC Architecture~\autocite [sec.~1.13]{pcat}.\relax }{figure.2.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {2.4.2}Advanced Programmable Interrupt Controller}{10}{subsection.2.4.2}\protected@file@percent }
|
||||
\newlabel{subsec:intelapic}{{2.4.2}{10}{Advanced Programmable Interrupt Controller}{subsection.2.4.2}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2.3}{\ignorespaces The Discrete APIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~5.1]{mpspec}.\relax }}{11}{figure.2.3}\protected@file@percent }
|
||||
\newlabel{fig:discreteapic}{{2.3}{11}{The Discrete APIC Architecture~\autocite [sec.~5.1]{mpspec}.\relax }{figure.2.3}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2.4}{\ignorespaces The Integrated APIC Architecture~\blx@tocontentsinit {0}\autocite [sec.~5.2]{mpspec}.\relax }}{12}{figure.2.4}\protected@file@percent }
|
||||
\newlabel{fig:integratedapic}{{2.4}{12}{The Integrated APIC Architecture~\autocite [sec.~5.2]{mpspec}.\relax }{figure.2.4}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {2.5}{\ignorespaces System Bus vs APIC Bus~\blx@tocontentsinit {0}\autocite [sec.~3.11.1]{ia32}.\relax }}{13}{figure.2.5}\protected@file@percent }
|
||||
\newlabel{fig:systemvsapicbus}{{2.5}{13}{System Bus vs APIC Bus~\autocite [sec.~3.11.1]{ia32}.\relax }{figure.2.5}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.5}PC/AT Compatibility}{13}{section.2.5}\protected@file@percent }
|
||||
\newlabel{sec:pcatcompat}{{2.5}{13}{PC/AT Compatibility}{section.2.5}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {2.6}Interrupt Handling in HhuOS}{14}{section.2.6}\protected@file@percent }
|
||||
\newlabel{sec:currenthhuos}{{2.6}{14}{Interrupt Handling in HhuOS}{section.2.6}{}}
|
||||
\@setckpt{chap/background}{
|
||||
\setcounter{page}{15}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{2}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{17}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{2}
|
||||
\setcounter{section}{6}
|
||||
\setcounter{subsection}{0}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{5}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{15}
|
||||
\setcounter{FancyVerbLine}{0}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{22}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{0}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{0}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{1}
|
||||
\setcounter{Item}{12}
|
||||
\setcounter{Hfootnote}{17}
|
||||
\setcounter{bookmark@seq@number}{21}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{0}
|
||||
\setcounter{@ppsavesec}{0}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{26}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{6}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -1,31 +1,25 @@
|
||||
\chapter{Background}
|
||||
\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.
|
||||
In this section, important domain-specific concepts will be explained, to create the necessary foundation to follow \autoref{ch:implementation}.
|
||||
Important terms 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''.
|
||||
There are two different strategies to \textquote{listen} for external events: \textquote{Polling} and \textquote{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 first strategy works by periodically \textit{polling} a device to check for changes.
|
||||
This could mean reading a register of the keyboard every \SI{50}{\milli\second} to determine if a key was pressed, or reading a sensor output even when the value remains unchanged.
|
||||
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.
|
||||
The second strategy are \textit{interrupts}.
|
||||
Instead of the CPU actively \textquote{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.
|
||||
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}
|
||||
@ -33,119 +27,101 @@ waste its processing power to check for events when none are occurring.
|
||||
\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''.
|
||||
When a device signals an external event to the CPU, the current code execution gets \textit{interrupted}, to handle the event.
|
||||
|
||||
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}}.
|
||||
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 \textit{external interrupts}.
|
||||
|
||||
Other types of interrupts mentioned in this thesis are \textbf{\glspl{ipi}}, \textbf{\glspl{msi}}
|
||||
and \textbf{\glspl{local 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.
|
||||
\item IPIs: Interrupts sent between different processor cores in multiprocessor systems, e.g.\ to initialize different cores on system startup or synchronize caches.
|
||||
\item MSIs: Interrupts sent in-band\footnote{
|
||||
In in-band signaling, control information is sent over the same channel as the data, while out-of-band signaling uses a dedicated control line.},
|
||||
\ e.g.\ over a PCI-bus\footnote{
|
||||
PCI supports MSIs since PCI 2.2~\autocite[sec.~6.8]{pci22}.}.
|
||||
\item Local Interrupts: Some specific CPU-internal interrupts, e.g.\ for performance monitoring.
|
||||
\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.
|
||||
Some interrupts are essential for CPU operation.
|
||||
These \textbf{\glspl{nmi}} always have to be handled and cannot be ignored (except in some special cases, like booting).
|
||||
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.
|
||||
The existence of NMIs hints that it is possible to ignore regular interrupts.
|
||||
Marking an interrupt as \textquote{ignored} is called \textit{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.
|
||||
A computer system has to process interrupts from many sources, so it is practical to have a designated \textit{interrupt controller}, that receives interrupts from different devices and forwards them to the CPU\@.
|
||||
The masking functionality is integrated into the interrupt controller, so masked interrupts do not 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:
|
||||
The interrupt controller receives interrupts through signals over physical connections (\textit{interrupt lines}) to different devices.
|
||||
These signals can be represented in multiple ways through the level on the interrupt lines:
|
||||
|
||||
\textbf{\Gls{trigger mode}}:
|
||||
\textit{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
|
||||
\item Edge-triggered: A signal is received when the interrupt line level changes.
|
||||
\item Level-triggered: A signal is received when the interrupt line reaches a certain level.
|
||||
\end{itemize}
|
||||
|
||||
\textbf{\Gls{pin polarity}}:
|
||||
\textit{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)
|
||||
\item Active-high: A signal is received when the interrupt line level changes from either low to high (in edge-triggered mode) or reaches a level above a threshold (in level-triggered mode).
|
||||
\item Active-low: A signal is received when the interrupt line level changes from either high to low (in edge-triggered mode) or reaches a level below a threshold (in level-triggered mode).
|
||||
\end{itemize}
|
||||
|
||||
A signal is represented through a combination of trigger mode and pin polarity, so there are a
|
||||
total of 4 combinations.
|
||||
A signal is represented through a combination of trigger mode and pin polarity, so there are a total of four 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.
|
||||
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 \textbf{\gls{inti}} on the interrupt controller: If a keyboard is connected to the interrupt controller on INTI1, 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\@.
|
||||
To signal that an interrupt is being 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.
|
||||
When the CPU receives an IRQ, it pauses its current code execution to handle the interrupt (see \autoref{fig:interruptexecution}).
|
||||
This is done by executing the \textit{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}}.
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.5\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{diagrams/interrupt_seq.svg}
|
||||
\end{subfigure}
|
||||
\caption{Interrupt Handler Execution.}
|
||||
\label{fig:interruptexecution}
|
||||
\end{figure}
|
||||
|
||||
Interrupt handlers have to be registered to different IRQs, so the CPU can locate and execute the
|
||||
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.
|
||||
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 \textit{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 \textit{interrupt vector} number, interrupt vectors 0--31 are reserved for the CPU, interrupt vectors 32--255 are usable for IRQs.
|
||||
In Intel's x86 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}~\autocite{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.
|
||||
When an edge-triggered IRQ is received, its interrupt handler is called a single time to service the interrupt, which does not require interacting with the device the interrupt originated from.
|
||||
The handler of an edge-triggered IRQ is called every time the interrupt line changes its level (low-to-high or high-to-low, as specified by the pin polarity).
|
||||
This could lead to problems if \textquote{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.
|
||||
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 notifying the interrupt controller (EOI), but also interaction with the device the interrupt originated from, to deassert 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.
|
||||
When an interrupt \textquote{disappears} while the interrupt controller is issuing the IRQ, the interrupt controller sends a \textit{spurious interrupt}.
|
||||
The reason for this could be electrical noise on the interrupt line, masking of an interrupt through software at the same moment the IRQ was dispatched, or incorrectly sent EOIs.
|
||||
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}
|
||||
@ -153,43 +129,33 @@ the OS has to check the validity of the occurred interrupt and ignore it, if it
|
||||
\subsection{Advanced Configuration and Power Interface}
|
||||
\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.}.
|
||||
\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}}~\autocite[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).
|
||||
ACPI defines abstractions for different types of hardware, that are organized in multiple \textit{system description tables}.
|
||||
In this thesis, ACPI 1.0~\autocite{acpi1} is used to read information about the system's interrupt hardware configuration, located in the ACPI \textbf{\gls{madt}}~\autocite[sec.~5.2.8]{acpi1}.
|
||||
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}.}.
|
||||
To allow compatibility to different interrupt controllers, ACPI abstracts external interrupts through \textbf{\glspl{gsi}}~\autocite[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}.}.
|
||||
\textbf{\gls{cpuid}} is used to gather information about a system's CPU\@.
|
||||
The x86 architecture provides the \code{cpuid}~\autocite{x86isa} instruction, which allows the software to identify present CPU features at runtime, e.g.\ what instruction set extensions a processor implements\footnote{
|
||||
This thesis uses CPUID to determine what APIC feature set is supported, see \textquote{APIC} and \textquote{x2APIC} features in the CPUID application note~\autocite[sec.~5.1.2]{cpuid}.}.
|
||||
|
||||
\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.
|
||||
\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.
|
||||
@ -211,90 +177,77 @@ Other cores, called \textbf{\glspl{ap}}, will be initialized by this core.
|
||||
\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}.}.
|
||||
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 \textquote{architectural} MSRs.
|
||||
To interact with MSRs, the special instructions \code{rdmsr} and \code{wrmsr} are used~\autocite{x86isa}.
|
||||
These instructions allow atomic read/write operations on MSRs\footnote{
|
||||
Detailed description in the IA-32 manual~\autocite[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.
|
||||
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.
|
||||
The \textbf{\gls{pit}}~\autocite{pit} is a hardware timer from the original IBM PC\@.
|
||||
It consists of multiple decrementing counters and can generate a signal (e.g.\ an interrupt) once 0 is reached.
|
||||
This can be used to control a preemptive\footnote{
|
||||
A scheduler is called \textquote{preemptive}, when it is able to forcefully take away the CPU from the currently working thread, even when the thread did not signal any form of completion.}
|
||||
\ 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}}.
|
||||
Because it is logistically difficult to connect every external device directly to the CPU, this task is delegated to a dedicated interrupt controller.
|
||||
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}.}.
|
||||
The Intel \textquote{8259A} PIC~\autocite{pic} is the interrupt controller Intel used in the original Intel \textquote{8086}\footnote{
|
||||
The 8259 was used in the Intel \textquote{8080} and \textquote{8085}, the 8259A is a revised version for the Intel 8086},
|
||||
\ the \textquote{father} of the x86 processor architecture.
|
||||
A single PIC has eight interrupt lines for external devices, but multiple PICs can be cascaded for a maximum of \(8 \cdot 8 = 64\) interrupt lines with nine PICs.
|
||||
The most common PIC configuration supports 15 IRQs with two PICs (see \autoref{fig:pcatpic}): A slave, connected to INTI2 of the master, which is connected to the CPU\footnote{
|
||||
This configuration is called the \textquote{PC/AT PIC Architecture}, as it was used in the IBM PC/AT~\autocite[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}.}
|
||||
\caption{The PC/AT PIC Architecture~\autocite[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.
|
||||
If multiple interrupts get requested simultaneously, the PIC decides which one to service first based on its \textit{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\@.
|
||||
\item When the PIC receives an unmasked interrupt from a device (PIC interrupts are edge-triggered with high pin polarity), it sets the corresponding bit in its \textbf{\gls{irr}}\footnote{
|
||||
Received IRQs that are requesting servicing are marked in the IRR.}.
|
||||
\item The IRQ is dispatched 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 \textquote{interrupt handler} instead of \textquote{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 is being 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:
|
||||
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 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.
|
||||
@ -303,125 +256,116 @@ architectural limits:
|
||||
\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 original Intel \textquote{82489DX} \textbf{\gls{discrete apic}} was introduced with the Intel \textquote{i486} processor.
|
||||
It consisted of two parts: A \textbf{\gls{local apic}}, responsible for receiving special \textbf{\glspl{local interrupt}}, and the \textbf{\gls{io apic}}, responsible for receiving external interrupts (and forwarding them to the local APIC).
|
||||
Unlike in modern systems, the i486's local APIC was not integrated into the CPU core (hence \textquote{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.}.
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.75\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/mp_spec_discrete_apic_configuration.svg}
|
||||
\end{subfigure}
|
||||
\caption{The Discrete APIC Architecture~\autocite[sec.~5.1]{mpspec}.}
|
||||
\label{fig:discreteapic}
|
||||
\end{figure}
|
||||
|
||||
The APIC was designed to fix the shortcomings of the PIC, specifically regarding multiprocessor
|
||||
systems:
|
||||
The i486 was superseded by the Intel \textquote{P54C}\footnote{
|
||||
The Intel P54C is the successor of the Intel P5, the first Pentium processor.},
|
||||
\ which contained an \textit{integrated APIC} for the first time (see \autoref{fig:integratedapic}), which is now the default configuration.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.75\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/mp_spec_integrated_apic_configuration.svg}
|
||||
\end{subfigure}
|
||||
\caption{The Integrated APIC Architecture~\autocite[sec.~5.2]{mpspec}.}
|
||||
\label{fig:integratedapic}
|
||||
\end{figure}
|
||||
|
||||
The APIC was designed to fix the shortcomings of the PIC, specifically regarding multiprocessor systems:
|
||||
|
||||
\begin{itemize}
|
||||
\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 Each CPU core contains its own local APIC\@.
|
||||
It has the capabilities to handle local interrupts and IPIs, and communicate with the chipset I/O APIC\@.
|
||||
\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 distributes 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.
|
||||
In comparison to the PIC, the external interrupt handling sequence changed:
|
||||
|
||||
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}}.
|
||||
\begin{enumerate}
|
||||
\item An external interrupt arrives at the I/O APIC\@.
|
||||
\item The I/O APIC redirects the interrupt to the local APIC, which sets the corresponding IRR bit.
|
||||
\item The local APIC dispatches the IRQ\@.
|
||||
\item The CPU acknowledges the IRQ and the local APIC sets the corresponding ISR bit.
|
||||
\item When the interrupt is being handled by the OS, it sends an EOI to the local APIC\footnote{
|
||||
In case of edge-triggered interrupts. For level-triggered interrupts see \autoref{subsec:ioapiceoi}.},
|
||||
\ which clears the corresponding bit in the ISR\@.
|
||||
Note how the OS only interacts directly with the local APIC, not the I/O APIC.
|
||||
\end{enumerate}
|
||||
|
||||
There have been different revisions on the APIC architecture after the original, discrete APIC,
|
||||
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}.
|
||||
To allow splitting the APIC architecture into local APICs of multiple CPU cores and I/O APICs, the individual components communicate over a bus.
|
||||
In the Intel \textquote{P6} and \textquote{Pentium} processors a dedicated \textit{APIC bus} is used, but since the Intel \textquote{Pentium 4} and \textquote{Xeon} processors the \textit{system bus} is used instead (see \autoref{fig:systemvsapicbus})\footnote{
|
||||
The Intel \textquote{Core} microarchitecture is based on the P6 architecture and replaces the Pentium 4's \textquote{NetBurst} architecture, but still uses the system bus instead of a discrete bus~\autocite[sec.~3.11.2]{ia32}.}.
|
||||
Using the system bus is considered the default in this document.
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.6\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_system_vs_apic_bus.svg}
|
||||
\end{subfigure}
|
||||
\caption{System Bus vs APIC Bus~\autocite[sec.~3.11.1]{ia32}.}
|
||||
\label{fig:systemvsapicbus}
|
||||
\end{figure}
|
||||
|
||||
Because the order in which external devices are connected to the interrupt controller is flexible in the APIC architecture, but fixed in the PC/AT PIC architecture, there can be deviations in device-to-IRQ mappings between the PIC and APIC interrupt controllers.
|
||||
To handle this, ACPI provides information about how the PC/AT compatible interrupts (IRQ0 to IRQ15) map to ACPI's GSIs in the MADT, which has to be taken into account by the OS when operating with an APIC\@.
|
||||
The mapping information for a single interrupt will be called \textbf{\gls{irq override}}.
|
||||
|
||||
There have been different revisions on the APIC architecture after the original, discrete APIC, notably the \textbf{\gls{xapic}} and \textbf{\gls{x2apic}} architectures.
|
||||
This thesis is mostly concerned about the older xApic architecture\footnote{
|
||||
This does not present a compatibility issue, as the x2Apic architecture is backwards compatible to the xApic architecture.}.
|
||||
A notable difference between xApic and x2Apic architectures is the register access: xApic uses \SI{32}{\bit} MMIO based register access, while x2Apic uses an MSR based register access, which allows atomic register access to the \SI{64}{\bit} wide APIC control MSRs~\autocite[sec.~3.11.12]{ia32}.
|
||||
|
||||
\section{PC/AT Compatibility}
|
||||
\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}.}.
|
||||
For compatibility with 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 \textit{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 \textquote{MultiProcessor Specification}~\autocite[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}.
|
||||
To switch from PIC to symmetric I/O mode, some (older) hardware provides the \textbf{\gls{imcr}}, a special register that controls the physical connection of the PIC to the CPU\@.
|
||||
In the original discrete APIC architecture, the IMCR can choose if either the PIC or local APIC is connected to the CPU (see \autoref{fig:discreteapic}), since the xApic architecture the IMCR only connects or disconnects the PIC to the local APIC's LINT0 INTI (see \autoref{fig:integratedapic}).
|
||||
When the IMCR is set to connect the PIC, and the xApic \textquote{global enable/disable} flag is unset (see \autoref{subsec:lapicenable}), the system is functionally equivalent to an IA-32 CPU without an integrated local APIC~\autocite[sec.~3.11.4.3]{ia32}.
|
||||
Modern systems (and QEMU) do not support PIC Mode and thus do not have the IMCR\@.
|
||||
PC/AT compatibility is usually achieved in these systems by connecting two PICs to the first external interrupt input of the I/O APIC (see \autoref{fig:integratedapic}).
|
||||
|
||||
Specifics on handling PC/AT compatible external interrupts follow in \autoref{subsec:ioapicpcat}.
|
||||
|
||||
\section{Interrupt Handling in hhuOS}
|
||||
\section{Interrupt Handling in HhuOS}
|
||||
\label{sec:currenthhuos}
|
||||
|
||||
In hhuOS, external interrupts are handled in two steps:
|
||||
In hhuOS, external interrupts are handled in two stages (see \autoref{subsec:apxcurrenthhuos} for code examples):
|
||||
|
||||
\begin{enumerate}
|
||||
\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.
|
||||
\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, 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, 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 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}
|
||||
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).
|
||||
|
||||
\begin{codeblock}[label=lst:irqassign]{Assigning an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_assign.cpp}
|
||||
\end{codeblock}
|
||||
Currently, hhuOS utilizes the PIT to manage the global system time, which in turn is used to trigger hhuOS' preemptive round-robin scheduler (the \code{Scheduler} class).
|
||||
|
||||
\begin{codeblock}[label=lst:irqdispatch]{Triggering an interrupt handler (InterruptDispatcher.cpp)~\cite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_dispatch.cpp}
|
||||
\end{codeblock}
|
||||
The PIT and other devices are initialized before the system entry point, in the \code{System::initializeSystem} function.
|
||||
|
||||
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.
|
||||
\cleardoublepage
|
201
chap/conclusion.aux
Normal file
201
chap/conclusion.aux
Normal file
@ -0,0 +1,201 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {5}Conclusion}{37}{chapter.5}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:conclusion}{{5}{37}{Conclusion}{chapter.5}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {5.1}Comparing PIC and APIC Implementations}{38}{section.5.1}\protected@file@percent }
|
||||
\newlabel{sec:comparingpicapic}{{5.1}{38}{Comparing PIC and APIC Implementations}{section.5.1}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {5.2}Future Improvements}{38}{section.5.2}\protected@file@percent }
|
||||
\newlabel{sec:futureimprov}{{5.2}{38}{Future Improvements}{section.5.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.1}Dependence on ACPI}{38}{subsection.5.2.1}\protected@file@percent }
|
||||
\newlabel{subsec:acpidependance}{{5.2.1}{38}{Dependence on ACPI}{subsection.5.2.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.2}Discrete APIC and x2Apic}{39}{subsection.5.2.2}\protected@file@percent }
|
||||
\newlabel{subsec:discretex2}{{5.2.2}{39}{Discrete APIC and x2Apic}{subsection.5.2.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.3}PCI Devices}{39}{subsection.5.2.3}\protected@file@percent }
|
||||
\newlabel{subsec:pcidevices}{{5.2.3}{39}{PCI Devices}{subsection.5.2.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.4}Multiprocessor Systems}{39}{subsection.5.2.4}\protected@file@percent }
|
||||
\newlabel{subsec:multiprocessor}{{5.2.4}{39}{Multiprocessor Systems}{subsection.5.2.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {5.2.5}UEFI Support}{40}{subsection.5.2.5}\protected@file@percent }
|
||||
\newlabel{subsec:uefisupport}{{5.2.5}{40}{UEFI Support}{subsection.5.2.5}{}}
|
||||
\@setckpt{chap/conclusion}{
|
||||
\setcounter{page}{41}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{9}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{5}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{5}
|
||||
\setcounter{section}{2}
|
||||
\setcounter{subsection}{5}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{0}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{59}
|
||||
\setcounter{FancyVerbLine}{0}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{48}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{0}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{0}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{2}
|
||||
\setcounter{Item}{46}
|
||||
\setcounter{Hfootnote}{43}
|
||||
\setcounter{bookmark@seq@number}{51}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{0}
|
||||
\setcounter{@ppsavesec}{0}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{89}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{19}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -1,41 +1,29 @@
|
||||
\chapter{Conclusion}
|
||||
\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.
|
||||
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.}.
|
||||
Handling interrupts using the PIC is simple, as seen in hhuOS' PIC implementation.
|
||||
Initialization and usage can be performed by using a total of only four different registers, two 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.
|
||||
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 numbers of cores and offers increased flexibility by allowing to configure individual interrupts' 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.
|
||||
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 number 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.
|
||||
In general, all of this effort results in a much more powerful and future-proof system: It is not limited to specific hardware configurations, allows scaling to a large amount of interrupts or processors, and is required for multiprocessor machines, which equals almost all modern computer systems.
|
||||
|
||||
\section{Future Improvements}
|
||||
\label{sec:futureimprov}
|
||||
@ -43,65 +31,48 @@ systems.
|
||||
\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.}.
|
||||
The APIC system requires a supplier of system information during operation, but this must not necessarily be ACPI\@.
|
||||
Systems following Intel's \textquote{MultiProcessor Specification}~\autocite{mpspec} can acquire the required information by parsing configuration tables similar to ACPI's system description tables, but provided in accordance to the MultiProcessor Specification.
|
||||
This would increase the number of systems supported by this APIC implementation, but the general compatibility improvement is difficult to quantize, as single-core systems are still supported by the old PIC implementation\footnote{
|
||||
The \textquote{MultiProcessor Specification} was (pre-) released in 1993~\autocite{mpspecpre}, the first ACPI release was in 1996~\autocite{acpipre}.
|
||||
Multiprocessor systems between these years could 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.
|
||||
Alternatively, systems that do not support ACPI could be supported partially by utilizing the local APIC's virtual wire mode~\autocite[sec.~3.6.2.2]{mpspec}.
|
||||
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}.}.
|
||||
This implementation only supports the xApic architecture, as it is convenient to emulate and the x2Apic architecture is fully backwards compatible~\autocite[sec.~3.11.12]{ia32}.
|
||||
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~\autocite[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~\autocite[sec.~5.2.12.12]{acpi65}, so supporting x2Apic also requires supporting modern ACPI versions\footnote{
|
||||
Currently (on 27/02/2023), hhuOS supports ACPI 1.0b~\autocite{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}.}.
|
||||
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~\autocite[sec.~6.2.13]{acpi65}, which needs an according interpreter\footnote{
|
||||
There exist modular solutions that can be ported to the target OS~\autocite{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.
|
||||
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 cores' local APIC timers to manage core-local schedulers.
|
||||
|
||||
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.
|
||||
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 be implemented statically for each interrupt or based on priorities, but could also happen dynamically (\textquote{IRQ-balancing}~\autocite{irqbalance}), based on interrupt workload measurements.
|
||||
|
||||
\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.
|
||||
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.
|
||||
|
||||
\cleardoublepage
|
191
chap/figures.aux
Normal file
191
chap/figures.aux
Normal file
@ -0,0 +1,191 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {B}Figures}{59}{appendix.1.B}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:figures}{{B}{59}{Figures}{appendix.1.B}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {B.1}{\ignorespaces Enabling the APIC Subsystem.\relax }}{60}{figure.1.B.1}\protected@file@percent }
|
||||
\newlabel{fig:apicenable}{{B.1}{60}{Enabling the APIC Subsystem.\relax }{figure.1.B.1}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {B.2}{\ignorespaces Starting SMP Operation.\relax }}{61}{figure.1.B.2}\protected@file@percent }
|
||||
\newlabel{fig:smpenable}{{B.2}{61}{Starting SMP Operation.\relax }{figure.1.B.2}{}}
|
||||
\@setckpt{chap/figures}{
|
||||
\setcounter{page}{63}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{4}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{0}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{2}
|
||||
\setcounter{section}{0}
|
||||
\setcounter{subsection}{0}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{2}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{184}
|
||||
\setcounter{FancyVerbLine}{12}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{70}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{1}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{47}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{2}
|
||||
\setcounter{Item}{50}
|
||||
\setcounter{Hfootnote}{45}
|
||||
\setcounter{bookmark@seq@number}{73}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{1}
|
||||
\setcounter{@ppsavesec}{5}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{96}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{20}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
24
chap/figures.tex
Normal file
24
chap/figures.tex
Normal file
@ -0,0 +1,24 @@
|
||||
\chapter{Figures}
|
||||
\label{ch:figures}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.85\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{diagrams/apic_enable_seq.svg}
|
||||
\end{subfigure}
|
||||
\caption{Enabling the APIC Subsystem.}
|
||||
\label{fig:apicenable}
|
||||
\end{figure}
|
||||
|
||||
\begin{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.85\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{diagrams/apic_smp_enable_seq.svg}
|
||||
\end{subfigure}
|
||||
\caption{Starting SMP Operation.}
|
||||
\label{fig:smpenable}
|
||||
\end{figure}
|
||||
|
||||
Note that this diagram is slightly misleading, because the application processor runs in parallel and is not susceptible to delays on the BSP\@.
|
||||
|
||||
\cleardoublepage
|
237
chap/implementation.aux
Normal file
237
chap/implementation.aux
Normal file
@ -0,0 +1,237 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {3}Implementation}{15}{chapter.3}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:implementation}{{3}{15}{Implementation}{chapter.3}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {3.1}Design Decisions and Scope}{16}{section.3.1}\protected@file@percent }
|
||||
\newlabel{sec:design}{{3.1}{16}{Design Decisions and Scope}{section.3.1}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.1}{\ignorespaces Caller Hierarchy of the Main Components.\relax }}{16}{figure.3.1}\protected@file@percent }
|
||||
\newlabel{fig:implarch}{{3.1}{16}{Caller Hierarchy of the Main Components.\relax }{figure.3.1}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {3.2}Local APIC}{19}{section.3.2}\protected@file@percent }
|
||||
\newlabel{sec:lapicinit}{{3.2}{19}{Local APIC}{section.3.2}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.2}{\ignorespaces The Local APIC Block Diagram~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.1]{ia32}.\relax }}{20}{figure.3.2}\protected@file@percent }
|
||||
\newlabel{fig:localapicblock}{{3.2}{20}{The Local APIC Block Diagram~\autocite [sec.~3.11.4.1]{ia32}.\relax }{figure.3.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.1}Accessing Local APIC Registers in xApic Mode}{21}{subsection.3.2.1}\protected@file@percent }
|
||||
\newlabel{subsec:xapicregacc}{{3.2.1}{21}{Accessing Local APIC Registers in xApic Mode}{subsection.3.2.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.2}Enabling the Local APIC}{21}{subsection.3.2.2}\protected@file@percent }
|
||||
\newlabel{subsec:lapicenable}{{3.2.2}{21}{Enabling the Local APIC}{subsection.3.2.2}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.3}{\ignorespaces The IA32\textunderscore {}APIC\textunderscore {}BASE MSR~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.4]{ia32}.\relax }}{21}{figure.3.3}\protected@file@percent }
|
||||
\newlabel{fig:ia32apicbasemsr}{{3.3}{21}{The IA32\textunderscore {}APIC\textunderscore {}BASE MSR~\autocite [sec.~3.11.4.4]{ia32}.\relax }{figure.3.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.3}Handling Local Interrupts}{22}{subsection.3.2.3}\protected@file@percent }
|
||||
\newlabel{subsec:lapiclvtinit}{{3.2.3}{22}{Handling Local Interrupts}{subsection.3.2.3}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.4}{\ignorespaces The Local Vector Table~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{22}{figure.3.4}\protected@file@percent }
|
||||
\newlabel{fig:localapiclvt}{{3.4}{22}{The Local Vector Table~\autocite [sec.~3.11.5.1]{ia32}.\relax }{figure.3.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.4}Allowing Interrupt Processing}{23}{subsection.3.2.4}\protected@file@percent }
|
||||
\newlabel{subsec:lapicsoftenable}{{3.2.4}{23}{Allowing Interrupt Processing}{subsection.3.2.4}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.5}{\ignorespaces The Local APIC SVR Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.9]{ia32}.\relax }}{23}{figure.3.5}\protected@file@percent }
|
||||
\newlabel{fig:ia32apicsvr}{{3.5}{23}{The Local APIC SVR Register~\autocite [sec.~3.11.9]{ia32}.\relax }{figure.3.5}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.5}Local Interrupt EOI}{24}{subsection.3.2.5}\protected@file@percent }
|
||||
\newlabel{subsec:lapiceoi}{{3.2.5}{24}{Local Interrupt EOI}{subsection.3.2.5}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.6}APIC Timer}{24}{subsection.3.2.6}\protected@file@percent }
|
||||
\newlabel{subsec:lapictimer}{{3.2.6}{24}{APIC Timer}{subsection.3.2.6}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.2.7}APIC Error Interrupt}{25}{subsection.3.2.7}\protected@file@percent }
|
||||
\newlabel{subsec:lapicerror}{{3.2.7}{25}{APIC Error Interrupt}{subsection.3.2.7}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.6}{\ignorespaces Error Status Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.3]{ia32}.\relax }}{25}{figure.3.6}\protected@file@percent }
|
||||
\newlabel{fig:ia32esr}{{3.6}{25}{Error Status Register~\autocite [sec.~3.11.5.3]{ia32}.\relax }{figure.3.6}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {3.3}I/O APIC}{26}{section.3.3}\protected@file@percent }
|
||||
\newlabel{sec:ioapicinit}{{3.3}{26}{I/O APIC}{section.3.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.1}Interrupt Overrides}{26}{subsection.3.3.1}\protected@file@percent }
|
||||
\newlabel{subsec:ioapicpcat}{{3.3.1}{26}{Interrupt Overrides}{subsection.3.3.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.2}External Interrupt EOI}{27}{subsection.3.3.2}\protected@file@percent }
|
||||
\newlabel{subsec:ioapiceoi}{{3.3.2}{27}{External Interrupt EOI}{subsection.3.3.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.3.3}Multiple I/O APICs}{28}{subsection.3.3.3}\protected@file@percent }
|
||||
\newlabel{subsec:multiioapic}{{3.3.3}{28}{Multiple I/O APICs}{subsection.3.3.3}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {3.4}Symmetric Multiprocessing}{29}{section.3.4}\protected@file@percent }
|
||||
\newlabel{sec:smpinit}{{3.4}{29}{Symmetric Multiprocessing}{section.3.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.1}Inter-Processor Interrupts}{29}{subsection.3.4.1}\protected@file@percent }
|
||||
\newlabel{subsec:ipis}{{3.4.1}{29}{Inter-Processor Interrupts}{subsection.3.4.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.2}Universal Startup Algorithm}{29}{subsection.3.4.2}\protected@file@percent }
|
||||
\newlabel{subsec:apstartup}{{3.4.2}{29}{Universal Startup Algorithm}{subsection.3.4.2}{}}
|
||||
\@writefile{lof}{\contentsline {figure}{\numberline {3.7}{\ignorespaces Interrupt Command Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.6.1]{ia32}.\relax }}{30}{figure.3.7}\protected@file@percent }
|
||||
\newlabel{fig:ia32icr}{{3.7}{30}{Interrupt Command Register~\autocite [sec.~3.11.6.1]{ia32}.\relax }{figure.3.7}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.3}Application Processor Boot Routine}{31}{subsection.3.4.3}\protected@file@percent }
|
||||
\newlabel{subsec:apboot}{{3.4.3}{31}{Application Processor Boot Routine}{subsection.3.4.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {3.4.4}Application Processor Post-Boot Routine}{32}{subsection.3.4.4}\protected@file@percent }
|
||||
\newlabel{subsec:apsystementry}{{3.4.4}{32}{Application Processor Post-Boot Routine}{subsection.3.4.4}{}}
|
||||
\@setckpt{chap/implementation}{
|
||||
\setcounter{page}{33}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{9}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{18}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{3}
|
||||
\setcounter{section}{4}
|
||||
\setcounter{subsection}{4}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{7}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{53}
|
||||
\setcounter{FancyVerbLine}{0}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{40}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{0}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{0}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{2}
|
||||
\setcounter{Item}{46}
|
||||
\setcounter{Hfootnote}{35}
|
||||
\setcounter{bookmark@seq@number}{40}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{0}
|
||||
\setcounter{@ppsavesec}{0}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{77}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{6}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -1,35 +1,26 @@
|
||||
\chapter{Implementation}
|
||||
\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.
|
||||
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, details on the implementation source code are found in \autoref{ch:listings}.
|
||||
\autoref{subsec: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.
|
||||
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 interrupt 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}):
|
||||
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{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\@.
|
||||
\item \code{Apic}: Condenses all the functionality above and exposes it to other parts of the OS\@.
|
||||
\end{itemize}
|
||||
|
||||
\begin{figure}[h]
|
||||
@ -37,494 +28,387 @@ components (see \autoref{fig:implarch}):
|
||||
\begin{subfigure}[b]{0.5\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/Architecture.svg}
|
||||
\end{subfigure}
|
||||
\caption{Caller hierarchy of the main components.}
|
||||
\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}.
|
||||
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 \textquote{MultiProcessor Specification}~\autocite[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:
|
||||
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.
|
||||
\item \code{GlobalSystemInterrupt}: ACPI's interrupt abstraction, detached from the hardware interrupt lines.
|
||||
\item \code{InterruptRequest}: Represents an \textbf{\gls{isa}} IRQ, allowing the OS to address interrupts by the name of the device that triggers it.
|
||||
When the APIC is used, interrupt 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.
|
||||
Both BIOS and UEFI are supported by hhuOS, but the hhuOS ACPI subsystem is currently only available with BIOS\footnote{
|
||||
State from 11/02/2023.},
|
||||
\ so when hhuOS is booted using UEFI, APIC support cannot 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\@.
|
||||
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:
|
||||
A 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 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~\autocite[sec.~3.11.4.5]{ia32}.}.
|
||||
\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 Meaningful treatment of APIC errors.
|
||||
\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:
|
||||
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 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 \textquote{location}: The local APICs and APIC timers of additional APs have to be initialized by the APs themselves, because the BSP can not access an AP's registers.
|
||||
\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.
|
||||
\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.
|
||||
% \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:
|
||||
The local APIC block diagram (see \autoref{fig:localapicblock}) shows a number of registers that are required for initialization\footnote{
|
||||
Registers like the \textquote{Trigger Mode Register}, \textquote{Logical Destination Register} or \textquote{Destination Format Register} remain unused in this thesis.}:
|
||||
|
||||
\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{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{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.9\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_manual_local_apic_blockdiagram.svg}
|
||||
\end{subfigure}
|
||||
\caption{The Local APIC Block Diagram~\autocite[sec.~3.11.4.1]{ia32}.}
|
||||
\label{fig:localapicblock}
|
||||
\end{figure}
|
||||
|
||||
There are multiple registers associated with the LVT, those belong to the different local interrupts the local APIC can handle.
|
||||
Local interrupts this implementation is concerned about are listed below:
|
||||
|
||||
\begin{itemize}
|
||||
\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).
|
||||
\item \textit{LINT1}: The local APIC's NMI source.
|
||||
\item \textit{Timer}: Periodic interrupt triggered by the APIC timer.
|
||||
\item \textit{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.
|
||||
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}).
|
||||
Besides the local APIC's own registers, the IMCR and IA32\textunderscore{}APIC\textunderscore{}BASE MSR also requires initialization (described in \autoref{subsec:lapicenable}).
|
||||
|
||||
After system power-up, the local APIC is in the following state~\cite[sec.~3.11.4.7]{ia32}:
|
||||
After system power-up, the local APIC is in the following state~\autocite[sec.~3.11.4.7]{ia32}:
|
||||
|
||||
\begin{itemize}
|
||||
\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 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:
|
||||
The initialization sequence consists of these steps, all performed before interrupt handling is enabled (see \autoref{fig:apicenable}):
|
||||
|
||||
\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.
|
||||
\item Enable interrupts for the BSP and APs.
|
||||
\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).
|
||||
Accessing registers in xApic mode is done via MMIO and requires a single page (\SI{4}{\kilo\byte}) of memory, mapped to the \textquote{APIC Base} address, which can be obtained by reading the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) or parsing the MADT (see \autoref{tab:madt}).
|
||||
The IA-32 manual specifies a caching strategy of \textquote{strong uncachable}\footnote{
|
||||
See IA-32 manual for information on this caching strategy~\autocite[sec.~3.12.3]{ia32}.}
|
||||
~\autocite[sec.~3.11.4.1]{ia32} for this region (see \autoref{subsec: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}.
|
||||
The address offsets (from the base address) for the local APIC registers are listed in the IA-32 manual~\autocite[sec.~3.11.4.1]{ia32} and in \autoref{tab:lapicregs}.
|
||||
|
||||
\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~\autocite[sec.~3.6.2.1]{mpspec} to disconnect the PIC from the local APIC's LINT0 INTI (see \autoref{fig:integratedapic}, for the example implementation see \autoref{subsec:apxdisablepic}).
|
||||
|
||||
Because the system boots in PIC mode, \code{0x01} should be written to the
|
||||
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}.
|
||||
To set the operating mode, it is first determined which modes are supported by executing the \code{cpuid} instruction with \code{eax=1}: If bit 9 of the \code{edx} register is set, xApic mode is supported, if bit 21 of the \code{ecx} register is set, x2Apic mode is supported~\autocite[sec.~5.1.2]{cpuid}.
|
||||
If xApic mode is supported (if the local APIC is an integrated APIC), it will be in that mode already.
|
||||
The \textquote{global enable/disable} (\textquote{EN}) bit in the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) allows disabling xApic mode, and thus the entire local APIC, globally\footnote{
|
||||
If the system uses the discrete APIC bus, xApic mode cannot be re-enabled without a system reset~\autocite[sec.~3.11.4.3]{ia32}.}.
|
||||
Enabling x2Apic mode is done by setting the \textquote{EXTD} bit (see \autoref{fig:ia32apicbasemsr}/\autoref{tab:lapicregsmsr}) of the IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.4.3]{ia32}.
|
||||
|
||||
\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}.}
|
||||
\caption{The IA32\textunderscore{}APIC\textunderscore{}BASE MSR~\autocite[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.
|
||||
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}.
|
||||
Besides the \textquote{global enable/disable} flag, the APIC can also be enabled/disabled by using the \textquote{software enable/disable} flag in the SVR, see \autoref{subsec:lapicsoftenable}.
|
||||
|
||||
\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}).
|
||||
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{figure}[h]
|
||||
\centering
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_lvt.svg}
|
||||
\end{subfigure}
|
||||
\caption{The Local Vector Table~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{fig:localapiclvt}
|
||||
\end{figure}
|
||||
|
||||
Local interrupts can be configured to use different delivery modes (excerpt)~\autocite[sec.~3.11.5.1]{ia32}:
|
||||
|
||||
\begin{itemize}
|
||||
\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.
|
||||
\item \textit{Fixed}: Simply delivers the interrupt vector stored in the LVT register.
|
||||
\item \textit{NMI}: Configures this interrupt as non-maskable, this ignores the stored vector number.
|
||||
\item \textit{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).
|
||||
Initially, all local interrupts are initialized to PC/AT defaults: Masked, edge-triggered, active-high and with \textit{fixed} delivery mode.
|
||||
Most importantly, the vector fields (bits 0:7 of each LVT register) are set to their corresponding interrupt vector (see \autoref{subsec:apxlvtinit} for an example implementation).
|
||||
|
||||
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}).
|
||||
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~\autocite{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 \textquote{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}).
|
||||
To complete a minimal local APIC initialization, the \textquote{software enable/disable} flag and the spurious interrupt vector (see \autoref{fig:ia32apicsvr}/\autoref{tab:lapicregssvr}), are set.
|
||||
It makes sense to choose \code{0xFF} for the spurious interrupt vector, as on P6 and Pentium processors, the lowest four bits must be set (see \autoref{fig:ia32apicsvr}).
|
||||
|
||||
\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}.}
|
||||
\caption{The Local APIC SVR Register~\autocite[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).
|
||||
Because the APIC's spurious interrupt has a dedicated interrupt vector (unlike the PIC's spurious interrupt), it can be ignored easily by registering a stub interrupt handler for the appropriate vector (see \autoref{subsec:apxsvr} for an implementation example).
|
||||
|
||||
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.
|
||||
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~\autocite[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}.
|
||||
To notify the local APIC that a local interrupt is being handled, its EOI register (see \autoref{tab:lapicregseoi}) has to be written.
|
||||
Not all local interrupts require EOIs: NMI, SMI, INIT, ExtINT, SIPI, or INIT-Deassert interrupts are excluded~\autocite[sec.~3.11.8.5]{ia32}.
|
||||
|
||||
EOIs for external interrupts are also handled by the local APIC, this is described in
|
||||
\autoref{subsec:ioapiceoi}.
|
||||
EOIs for external interrupts are also handled by the local APIC, further 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 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 does not tick with a fixed frequency, but at bus frequency, the initial counter has to be determined at runtime by using an external time source.
|
||||
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.
|
||||
\item \textit{Oneshot}: Trigger exactly one interrupt when the counter reaches zero.
|
||||
\item \textit{Periodic}: Trigger an interrupt each time the counter reaches zero, on zero the counter reloads its initial value.
|
||||
\item \textit{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}):
|
||||
Initialization requires the following steps (order recommended by OSDev~\autocite{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.
|
||||
\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.
|
||||
In this implementation, the APIC timer is calibrated by counting the amount of ticks in one millisecond using oneshot mode (see \autoref{subsec:apxapictimer} for an example implementation).
|
||||
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).
|
||||
To use the timer, an interrupt handler has to be registered to its interrupt vector (see \autoref{subsec: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.
|
||||
Errors can occur e.g.\ 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}.}
|
||||
\caption{Error Status Register~\autocite[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}.
|
||||
The ESR is a \textquote{write/read} register: Before reading a value from the ESR, it has to be written, which updates the ESR's contents to the error status since the last write.
|
||||
Writing the ESR also arms the local error interrupt, which doesn't happen automatically~\autocite[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).
|
||||
Enabling the local error interrupt is now as simple as enabling it in the local APIC's LVT and registering an interrupt handler for the appropriate vector (see \autoref{subsec:apxhandlingerror} for an example implementation).
|
||||
|
||||
\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~\autocite[sec.~9.5.8]{ich5} (see \autoref{tab:ioapicregsredtbl}).
|
||||
Like the local APIC's LVT, the REDTBL allows configuration of interrupt vectors, masking bits, interrupt delivery modes, pin polarities and trigger modes (see \autoref{subsec:lapiclvtinit}).
|
||||
|
||||
To fully replace the PIC and handle external interrupts using the APIC, the I/O APIC, located in
|
||||
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 \textit{physical} destination mode\footnote{
|
||||
The alternative is \textit{logical} destination mode, which allows addressing individual or clusters of local APIC's in a larger volume of processors~\autocite[sec.~3.11.6.2.2]{ia32}.}
|
||||
~\autocite[sec.~3.11.6.2.1]{ia32} and are sent to the BSP for servicing, by using the BSP's local APIC ID as the destination.
|
||||
The other fields are set to ISA bus defaults\footnote{
|
||||
Edge-triggered, active-high.},
|
||||
\ with \textit{fixed} delivery mode, masked, and the corresponding interrupt vector, as defined by the \code{InterruptVector} enum.
|
||||
|
||||
Additionally, for external interrupts a destination and destination mode can be specified. This is
|
||||
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\@.
|
||||
|
||||
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 \textquote{Index} and \textquote{Data} register~\autocite[sec.~9.5.1]{ich5}, are mapped to the main memory and can be used analogous to the local APIC's registers.
|
||||
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{subsec:iolistings} for an example implementation).
|
||||
This indirect addressing scheme is useful, because the number of external interrupts an I/O APIC supports, and in turn the number of REDTBL registers, can vary\footnote{
|
||||
Intel's consumer \textbf{\glspl{ich}} always support a fixed amount of 24 external interrupts though~\autocite[sec.~9.5.7]{ich5}.}.
|
||||
|
||||
Unlike the local APIC's registers, the REDTBL registers are accessed indirectly: Two registers, the
|
||||
``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.
|
||||
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\@.
|
||||
Because this is not the case for the I/O APIC, the INTIs used by each PC/AT compatible interrupt has to be determined by the OS at runtime, by using ACPI\@.
|
||||
ACPI provides \textquote{Interrupt Source Override} structures~\autocite[sec.~5.2.8.3.1]{acpi1} inside the MADT (see \autoref{tab:madtirqoverride}) for each PC/AT compatible interrupt that is mapped differently to the I/O APIC than to the PIC\@.
|
||||
In addition to the interrupt input mapping, these structures also allow customizing the pin polarity and trigger mode of PC/AT compatible interrupts.
|
||||
|
||||
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).
|
||||
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} (see \autoref{fig:integratedapic}).
|
||||
Thus, to allow the PIT interrupt in those systems, the REDTBL entry belonging to \code{GSI2} instead of \code{GSI0} has to be written (see \autoref{subsec:apxirqoverrides} for an example implementation).
|
||||
|
||||
\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}).
|
||||
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 \textquote{Remote IRR} bit in the corresponding REDTBL entry~\autocite[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:
|
||||
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}.
|
||||
\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~\autocite[sec.~9.5.5]{ich5}.
|
||||
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~\autocite[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}.}.
|
||||
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~\autocite[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.
|
||||
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 \textquote{masked} bit in these interrupts' REDTBL entries, interrupt handler completion is signaled by writing the local APIC's EOI register, and spurious interrupts are detected by using the local APIC's spurious interrupt vector.
|
||||
|
||||
\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}.
|
||||
Most consumer hardware, for example all IA processors~\autocite{ia32} and ICH hubs~\autocite{ich5}, only provide a single I/O APIC, although technically multiple I/O APICs are supported by the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.8]{mpspec}.
|
||||
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~\autocite[sec.~9.5.6]{ich5}.
|
||||
|
||||
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.}.
|
||||
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 \textquote{GSI Base}~\autocite[sec.~5.2.8.2]{acpi1} for each available I/O APIC, the number of GSIs a single I/O APIC can handle can be determined by reading the I/O APIC's version register~\autocite[sec.~9.5.7]{ich5} (see \autoref{tab:ioapicregsver})\footnote{
|
||||
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.
|
||||
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}).
|
||||
To determine the number of usable processors, the MADT is parsed (see \autoref{tab:madtlapic}).
|
||||
Note, that some processors may be reported as disabled, those may not be used by the OS (see \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).
|
||||
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{subsec: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:
|
||||
Depending on the APIC architecture, two different IPIs are required: The \textit{INIT IPI} for systems using a discrete APIC, and the \textbf{\gls{sipi}} for systems using the xApic or x2Apic architectures:
|
||||
|
||||
\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.
|
||||
\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~\autocite[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~\autocite[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.
|
||||
@ -534,77 +418,54 @@ To wait until the IPI is sent, the ICR's delivery status bit can be polled.
|
||||
\begin{subfigure}[b]{0.7\textwidth}
|
||||
\includesvg[width=1.0\linewidth]{img/ia32_interrupt_command_register.svg}
|
||||
\end{subfigure}
|
||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
||||
\caption{Interrupt Command Register~\autocite[sec.~3.11.6.1]{ia32}.}
|
||||
\label{fig:ia32icr}
|
||||
\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}.}.
|
||||
SMP initialization is performed differently on various processors.
|
||||
Intel's \textquote{MultiProcessor Specification} defines a \textquote{Universal Startup Algorithm} for multiprocessor systems~\autocite[sec.~B.4]{mpspec}, which can be used to boot SMP systems with either discrete APIC, xApic or x2Apic, as it issues both, INIT IPI and SIPI\@.
|
||||
|
||||
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.}.
|
||||
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}~\autocite[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 \SI{32}{\bit} field, located at physical address \code{40:67}~\autocite[sec.~B.4]{mpspec}) needs to be set to the physical address the AP startup routine was copied to.
|
||||
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, see \autoref{subsec:apxapictimer}.}.
|
||||
|
||||
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}.
|
||||
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~\autocite[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):
|
||||
After preparation, the universal startup algorithm is now performed as follows, for each AP sequentially (see \autoref{subsec:apxmpusa} for an example implementation and \autoref{fig:smpenable}):
|
||||
|
||||
\begin{enumerate}
|
||||
\item Assert and de-assert the level-triggered INIT IPI\@.
|
||||
\item Delay for 10 milliseconds.
|
||||
\item Delay for \SI{10}{\milli\second}.
|
||||
\item Send the SIPI\@.
|
||||
\item Delay for 200 microseconds.
|
||||
\item Delay for \SI{200}{\micro\second}.
|
||||
\item Send the SIPI again.
|
||||
\item Delay for 200 microseconds again.
|
||||
\item Delay for \SI{200}{\micro\second} again.
|
||||
\item Wait until the AP has signaled boot completion, then continue to the next.
|
||||
\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\@.
|
||||
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.
|
||||
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):
|
||||
After executing the \textquote{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{subsec: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 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\@.
|
||||
@ -612,34 +473,25 @@ follows (see \autoref{sec:apxapboot} for an example implementation):
|
||||
\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.
|
||||
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 hardware context switching, e.g.\ 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).
|
||||
Because it is relocated into lower physical memory, 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 \textquote{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{subsec: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.}.
|
||||
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).
|
||||
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~\autocite[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{subsec:apxappostboot} for an example implementation).
|
||||
|
||||
\clearpage
|
||||
\cleardoublepage
|
187
chap/introduction.aux
Normal file
187
chap/introduction.aux
Normal file
@ -0,0 +1,187 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {1}Introduction}{1}{chapter.1}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:introduction}{{1}{1}{Introduction}{chapter.1}{}}
|
||||
\@setckpt{chap/introduction}{
|
||||
\setcounter{page}{3}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{0}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{0}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{1}
|
||||
\setcounter{section}{0}
|
||||
\setcounter{subsection}{0}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{0}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{0}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{0}
|
||||
\setcounter{FancyVerbLine}{0}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{10}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{0}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{0}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{0}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{0}
|
||||
\setcounter{Item}{0}
|
||||
\setcounter{Hfootnote}{0}
|
||||
\setcounter{bookmark@seq@number}{1}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{0}
|
||||
\setcounter{@ppsavesec}{0}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{1}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{1}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -1,26 +1,20 @@
|
||||
\chapter{Introduction}
|
||||
\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''.
|
||||
\clearpage
|
||||
|
||||
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.
|
||||
Computer systems need to interact with their surroundings, for instance by reading values from sensors, controlling external appliances or interacting with a user through human interface devices.
|
||||
In each of these scenarios, the system's CPU has to react to \textquote{external changes}, like a key press or sensor reading.
|
||||
An efficient hardware solution to this problem are \textquote{interrupts}.
|
||||
|
||||
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.
|
||||
Through the past, interrupt hardware went through different iterations: Intel introduced the \textquote{Programmable Interrupt Controller} for the \textquote{8085} processor in 1976, with a revised version for the \textquote{8086} processor.
|
||||
With modern standards like multicore processors, peripheral extendability, greater flexibility or higher performance, the Programmable Interrupt Controller could no longer meet its requirements.
|
||||
|
||||
Specific details on the code created during this thesis are given in \autoref{ch:listings},
|
||||
separated from the main body.
|
||||
In this thesis, support for the \textquote{Advanced Programmable Interrupt Controller}, a modern, multiprocessing capable and widely used interrupt controller architecture, introduced by Intel for the x86 \textquote{i486} processor, will be implemented into hhuOS, \textquote{A small operating system for learning purposes}~\autocite{hhuos}.
|
||||
This support will cover a complete replacement of the older Programmable Interrupt Controller, introduction of an alternative timer -- a part of the APIC architecture -- for scheduling, and utilizing the APIC to boot multiprocessor systems.
|
||||
|
||||
\clearpage
|
||||
The following chapter explains important background concepts, in \autoref{ch:implementation} the required steps to use the APIC and their implementation are explained in general, \autoref{ch:verification} deals with the verification process of the developed software on emulated and real hardware, and \autoref{ch:conclusion} draws conclusions regarding the previous implementation and future improvements.
|
||||
|
||||
Specific details on the code created during this thesis are given in \autoref{ch:listings}, separated from the main body.
|
||||
|
||||
\cleardoublepage
|
284
chap/listings.aux
Normal file
284
chap/listings.aux
Normal file
@ -0,0 +1,284 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {A}Listings}{43}{appendix.1.A}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:listings}{{A}{43}{Listings}{appendix.1.A}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {A.1}Integration into HhuOS}{44}{section.1.A.1}\protected@file@percent }
|
||||
\newlabel{sec:apxhhuos}{{A.1}{44}{Integration into HhuOS}{section.1.A.1}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.1}Interrupt Handling in HhuOS}{44}{subsection.1.A.1.1}\protected@file@percent }
|
||||
\newlabel{subsec:apxcurrenthhuos}{{A.1.1}{44}{Interrupt Handling in HhuOS}{subsection.1.A.1.1}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.1\hskip 1em\relax \texttt {The InterruptHandler Interface (InterruptHandler.h)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.1}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.2\hskip 1em\relax \texttt {Assigning an Interrupt Handler (InterruptDispatcher.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.2}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.3\hskip 1em\relax \texttt {Triggering an Interrupt Handler (InterruptDispatcher.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.3}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.4\hskip 1em\relax \texttt {The PIT Interrupt Handler (Pit.cpp)~\blx@tocontentsinit {0}\autocite {hhuos}}}{44}{tcb@cnt@codeblock.1.A.4}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.2}Necessary Modifications to HhuOS}{45}{subsection.1.A.1.2}\protected@file@percent }
|
||||
\newlabel{subsec:hhuosintegration}{{A.1.2}{45}{Necessary Modifications to HhuOS}{subsection.1.A.1.2}{}}
|
||||
\newlabel{lst:interruptserviceafter}{{A.5}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.5}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.5\hskip 1em\relax \texttt {Using the Correct Interrupt Controller (InterruptService.cpp)}}{45}{tcb@cnt@codeblock.1.A.5}\protected@file@percent }
|
||||
\newlabel{lst:pithandlerafter}{{A.6}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.6}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.6\hskip 1em\relax \texttt {Disabling PIT Preemption (Pit.cpp)}}{45}{tcb@cnt@codeblock.1.A.6}\protected@file@percent }
|
||||
\newlabel{lst:systemafter}{{A.7}{45}{Necessary Modifications to HhuOS}{tcb@cnt@codeblock.1.A.7}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.7\hskip 1em\relax \texttt {Enabling the APIC System (System.cpp)}}{45}{tcb@cnt@codeblock.1.A.7}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.1.3}Public Interface of the APIC Subsystem}{46}{subsection.1.A.1.3}\protected@file@percent }
|
||||
\newlabel{subsec:hhuospublicinterface}{{A.1.3}{46}{Public Interface of the APIC Subsystem}{subsection.1.A.1.3}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.8\hskip 1em\relax \texttt {The APIC Public Interface (Apic.h)}}{46}{tcb@cnt@codeblock.1.A.8}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {A.2}Local APIC}{47}{section.1.A.2}\protected@file@percent }
|
||||
\newlabel{sec:apxlocalapic}{{A.2}{47}{Local APIC}{section.1.A.2}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.1}Accessing Local APIC Registers in xApic Mode}{47}{subsection.1.A.2.1}\protected@file@percent }
|
||||
\newlabel{subsec:apxxapicregacc}{{A.2.1}{47}{Accessing Local APIC Registers in xApic Mode}{subsection.1.A.2.1}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.9\hskip 1em\relax \texttt {Allocating the Local APIC's MMIO Region (LocalApic.cpp)}}{47}{tcb@cnt@codeblock.1.A.9}\protected@file@percent }
|
||||
\newlabel{lst:lapicmmiowrite}{{A.10}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.10}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.10\hskip 1em\relax \texttt {Writing a Local APIC MMIO Register (LocalApic.cpp)}}{47}{tcb@cnt@codeblock.1.A.10}\protected@file@percent }
|
||||
\newlabel{lst:msrentry}{{A.11}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.11}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.11\hskip 1em\relax \texttt {The MSREntry Structure (LocalApicRegisters.h)}}{47}{tcb@cnt@codeblock.1.A.11}\protected@file@percent }
|
||||
\newlabel{lst:svrentry}{{A.12}{47}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.12}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.12\hskip 1em\relax \texttt {The SVREntry Structure (LocalApicRegisters.h)}}{47}{tcb@cnt@codeblock.1.A.12}\protected@file@percent }
|
||||
\newlabel{lst:lvtentry}{{A.13}{48}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.13}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.13\hskip 1em\relax \texttt {The LVTEntry Structure (LocalApicRegisters.h)}}{48}{tcb@cnt@codeblock.1.A.13}\protected@file@percent }
|
||||
\newlabel{lst:icrentry}{{A.14}{48}{Accessing Local APIC Registers in xApic Mode}{tcb@cnt@codeblock.1.A.14}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.14\hskip 1em\relax \texttt {The ICREntry Structure (LocalApicRegisters.h)}}{48}{tcb@cnt@codeblock.1.A.14}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.15\hskip 1em\relax \texttt {Writing the IA32\textunderscore {}APIC\textunderscore {}BASE MSR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.15}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.16\hskip 1em\relax \texttt {Writing the SVR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.16}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.17\hskip 1em\relax \texttt {Writing the LVT (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.17}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.18\hskip 1em\relax \texttt {Writing the ICR (LocalApic.cpp)}}{48}{tcb@cnt@codeblock.1.A.18}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.2}Disabling PIC Mode}{49}{subsection.1.A.2.2}\protected@file@percent }
|
||||
\newlabel{subsec:apxdisablepic}{{A.2.2}{49}{Disabling PIC Mode}{subsection.1.A.2.2}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.19\hskip 1em\relax \texttt {Disabling PIC Mode (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.19}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.3}Initializing the LVT}{49}{subsection.1.A.2.3}\protected@file@percent }
|
||||
\newlabel{subsec:apxlvtinit}{{A.2.3}{49}{Initializing the LVT}{subsection.1.A.2.3}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.20\hskip 1em\relax \texttt {Configuring the LINT0 Local Interrupt (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.20}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.4}Handling the Spurious Interrupt}{49}{subsection.1.A.2.4}\protected@file@percent }
|
||||
\newlabel{subsec:apxsvr}{{A.2.4}{49}{Handling the Spurious Interrupt}{subsection.1.A.2.4}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.21\hskip 1em\relax \texttt {Setting the Spurious Interrupt Vector (LocalApic.cpp)}}{49}{tcb@cnt@codeblock.1.A.21}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.22\hskip 1em\relax \texttt {Checking for Spurious Interrupts (InterruptDispatcher.cpp)}}{49}{tcb@cnt@codeblock.1.A.22}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.23\hskip 1em\relax \texttt {Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}}{50}{tcb@cnt@codeblock.1.A.23}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.5}Using the APIC Timer}{50}{subsection.1.A.2.5}\protected@file@percent }
|
||||
\newlabel{subsec:apxapictimer}{{A.2.5}{50}{Using the APIC Timer}{subsection.1.A.2.5}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.24\hskip 1em\relax \texttt {Calibrating the APIC Timer (ApicTimer.cpp)}}{50}{tcb@cnt@codeblock.1.A.24}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.25\hskip 1em\relax \texttt {Microsecond Delay without Interrupts (Pit.cpp)}}{50}{tcb@cnt@codeblock.1.A.25}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.26\hskip 1em\relax \texttt {Handling the APIC Timer Interrupt (ApicTimer.cpp)}}{51}{tcb@cnt@codeblock.1.A.26}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.2.6}Handling Local APIC Errors}{51}{subsection.1.A.2.6}\protected@file@percent }
|
||||
\newlabel{subsec:apxhandlingerror}{{A.2.6}{51}{Handling Local APIC Errors}{subsection.1.A.2.6}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.27\hskip 1em\relax \texttt {The Local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}}{51}{tcb@cnt@codeblock.1.A.27}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {A.3}I/O APIC}{52}{section.1.A.3}\protected@file@percent }
|
||||
\newlabel{sec:apxioapic}{{A.3}{52}{I/O APIC}{section.1.A.3}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.3.1}Accessing I/O APIC Registers}{52}{subsection.1.A.3.1}\protected@file@percent }
|
||||
\newlabel{subsec:iolistings}{{A.3.1}{52}{Accessing I/O APIC Registers}{subsection.1.A.3.1}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.28\hskip 1em\relax \texttt {Writing an I/O APIC MMIO Register (IoApic.h)}}{52}{tcb@cnt@codeblock.1.A.28}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.29\hskip 1em\relax \texttt {Writing an I/O APIC Indirect Register (IoApic.cpp)}}{52}{tcb@cnt@codeblock.1.A.29}\protected@file@percent }
|
||||
\newlabel{lst:redtblentry}{{A.30}{52}{Accessing I/O APIC Registers}{tcb@cnt@codeblock.1.A.30}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.30\hskip 1em\relax \texttt {The REDTBLEntry Structure (IoApicRegisters.h)}}{52}{tcb@cnt@codeblock.1.A.30}\protected@file@percent }
|
||||
\newlabel{lst:writeredtbl}{{A.31}{52}{Accessing I/O APIC Registers}{tcb@cnt@codeblock.1.A.31}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.31\hskip 1em\relax \texttt {Writing the REDTBL (IoApic.cpp)}}{52}{tcb@cnt@codeblock.1.A.31}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.3.2}Interrupt Overrides}{52}{subsection.1.A.3.2}\protected@file@percent }
|
||||
\newlabel{subsec:apxirqoverrides}{{A.3.2}{52}{Interrupt Overrides}{subsection.1.A.3.2}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.32\hskip 1em\relax \texttt {The External Interrupt Override Structure (IoApic.h)}}{53}{tcb@cnt@codeblock.1.A.32}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.33\hskip 1em\relax \texttt {Initializing the REDTBL (IoApic.cpp)}}{53}{tcb@cnt@codeblock.1.A.33}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.34\hskip 1em\relax \texttt {Unmasking an IRQ (Apic.cpp)}}{53}{tcb@cnt@codeblock.1.A.34}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.35\hskip 1em\relax \texttt {Unmasking an IRQ Internally (IoApic.cpp)}}{54}{tcb@cnt@codeblock.1.A.35}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {A.4}Symmetric Multiprocessing}{55}{section.1.A.4}\protected@file@percent }
|
||||
\newlabel{sec:apxsymmetric}{{A.4}{55}{Symmetric Multiprocessing}{section.1.A.4}{}}
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.1}Issuing Inter-Processor Interrupts}{55}{subsection.1.A.4.1}\protected@file@percent }
|
||||
\newlabel{subsec:apxipis}{{A.4.1}{55}{Issuing Inter-Processor Interrupts}{subsection.1.A.4.1}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.36\hskip 1em\relax \texttt {Issuing an INIT IPI (LocalApic.cpp)}}{55}{tcb@cnt@codeblock.1.A.36}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.37\hskip 1em\relax \texttt {Issuing a SIPI (LocalApic.cpp)}}{55}{tcb@cnt@codeblock.1.A.37}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.2}Preparing Symmetric Multiprocessing Startup}{55}{subsection.1.A.4.2}\protected@file@percent }
|
||||
\newlabel{subsec:apxpreparesmp}{{A.4.2}{55}{Preparing Symmetric Multiprocessing Startup}{subsection.1.A.4.2}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.38\hskip 1em\relax \texttt {Preparing the Boot Routine's Variables (ApicSmp.cpp)}}{55}{tcb@cnt@codeblock.1.A.38}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.39\hskip 1em\relax \texttt {Relocating the Boot Routine (ApicSmp.cpp)}}{56}{tcb@cnt@codeblock.1.A.39}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.3}Universal Startup Algorithm}{56}{subsection.1.A.4.3}\protected@file@percent }
|
||||
\newlabel{subsec:apxmpusa}{{A.4.3}{56}{Universal Startup Algorithm}{subsection.1.A.4.3}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.40\hskip 1em\relax \texttt {The Universal Startup Algorithm (ApicSmp.cpp)}}{56}{tcb@cnt@codeblock.1.A.40}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.41\hskip 1em\relax \texttt {Signaling AP Boot Completion (smp\textunderscore {}entry.cpp)}}{56}{tcb@cnt@codeblock.1.A.41}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.4}Application Processor Boot Routine}{57}{subsection.1.A.4.4}\protected@file@percent }
|
||||
\newlabel{subsec:apxapboot}{{A.4.4}{57}{Application Processor Boot Routine}{subsection.1.A.4.4}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.42\hskip 1em\relax \texttt {Preparing the Switch to Protected Mode (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.42}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.43\hskip 1em\relax \texttt {Switching from Real Mode to Protected Mode (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.43}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.44\hskip 1em\relax \texttt {Reusing Values from the BSP (smp\textunderscore {}boot.asm)}}{57}{tcb@cnt@codeblock.1.A.44}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.45\hskip 1em\relax \texttt {Calling the Entry Function (smp\textunderscore {}boot.asm)}}{58}{tcb@cnt@codeblock.1.A.45}\protected@file@percent }
|
||||
\@writefile{toc}{\contentsline {subsection}{\numberline {A.4.5}Application Processor Post-Boot Routine}{58}{subsection.1.A.4.5}\protected@file@percent }
|
||||
\newlabel{subsec:apxappostboot}{{A.4.5}{58}{Application Processor Post-Boot Routine}{subsection.1.A.4.5}{}}
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.46\hskip 1em\relax \texttt {Initializing the Core's Local APIC (LocalApic.cpp)}}{58}{tcb@cnt@codeblock.1.A.46}\protected@file@percent }
|
||||
\@writefile{listings}{\contentsline {tcolorbox}{A.47\hskip 1em\relax \texttt {Synchronizing the Arbitration IDs (LocalApic.cpp)}}{58}{tcb@cnt@codeblock.1.A.47}\protected@file@percent }
|
||||
\@setckpt{chap/listings}{
|
||||
\setcounter{page}{59}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{4}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{2}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{1}
|
||||
\setcounter{section}{4}
|
||||
\setcounter{subsection}{5}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{0}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{184}
|
||||
\setcounter{FancyVerbLine}{12}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{66}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{1}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{47}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{2}
|
||||
\setcounter{Item}{50}
|
||||
\setcounter{Hfootnote}{45}
|
||||
\setcounter{bookmark@seq@number}{72}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{1}
|
||||
\setcounter{@ppsavesec}{5}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{96}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{20}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{47}
|
||||
}
|
378
chap/listings.tex
Normal file
378
chap/listings.tex
Normal file
@ -0,0 +1,378 @@
|
||||
\chapter{Listings}
|
||||
\label{ch:listings}
|
||||
|
||||
This chapter contains concrete implementation examples for concepts mentioned in \autoref{ch:implementation}, demonstrated on the example of hhuOS\@.
|
||||
The code is simplified and not necessarily identical to the actual implementation, to allow for a self-contained demonstration.
|
||||
Names and namespaces were adjusted especially.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Integration into HhuOS}
|
||||
\label{sec:apxhhuos}
|
||||
|
||||
\subsection{Interrupt Handling in HhuOS}
|
||||
\label{subsec:apxcurrenthhuos}
|
||||
|
||||
Devices that provide interrupts implement the \code{InterruptHandler} interface:
|
||||
|
||||
\begin{codeblock}{The InterruptHandler Interface (InterruptHandler.h)~\autocite{hhuos}}{C++}
|
||||
\cppfile{code/interrupthandler_def.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
These interrupt handlers have to be registered to the appropriate interrupt vector:
|
||||
|
||||
\begin{codeblock}{Assigning an Interrupt Handler (InterruptDispatcher.cpp)~\autocite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_assign.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Multiple interrupt handlers can be registered to the same interrupt vector.
|
||||
For every interrupt that arrives at a CPU, the first-stage interrupt handler (registered in the IDT for every vector) is called, which in turn calls the device-specific handlers:
|
||||
|
||||
\begin{codeblock}{Triggering an Interrupt Handler (InterruptDispatcher.cpp)~\autocite{hhuos}}{C++}
|
||||
\cppfile{code/interruptdispatcher_dispatch.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The PIT interrupt handler manages the system time and the scheduler:
|
||||
|
||||
\begin{codeblock}{The PIT Interrupt Handler (Pit.cpp)~\autocite{hhuos}}{C++}
|
||||
\cppfile{code/pit_trigger.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\clearpage
|
||||
|
||||
\subsection{Necessary Modifications to HhuOS}
|
||||
\label{subsec:hhuosintegration}
|
||||
|
||||
To integrate the APIC implementation into hhuOS, some preexisting components of its interrupt infrastructure (see \autoref{sec:apxhhuos}) have to be modified:
|
||||
|
||||
\begin{enumerate}
|
||||
\item The \code{InterruptService} has to forward calls to the \code{Apic} class instead of the \code{Pic} class, depending on if the APIC system is enabled -- to keep the option of running the OS on hardware that does not support the APIC (see \autoref{lst:interruptserviceafter}).
|
||||
\item The \code{Pit} interrupt handler may no longer trigger the scheduler preemption if the APIC timer is enabled (see \autoref{lst:pithandlerafter}).
|
||||
\item The \code{System::initializeSystem} function needs to enable the APIC system if it is available (see \autoref{lst:systemafter}).
|
||||
\item The existing devices using interrupts need to use the new \code{InterruptVector} and \code{InterruptRequest} enums.
|
||||
\end{enumerate}
|
||||
|
||||
\begin{codeblock}[label=lst:interruptserviceafter]{Using the Correct Interrupt Controller (InterruptService.cpp)}{C++}
|
||||
\cppfile{code/interruptservice_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:pithandlerafter]{Disabling PIT Preemption (Pit.cpp)}{C++}
|
||||
\cppfile{code/pit_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:systemafter]{Enabling the APIC System (System.cpp)}{C++}
|
||||
\cppfile{code/system_after.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Public Interface of the APIC Subsystem}
|
||||
\label{subsec:hhuospublicinterface}
|
||||
|
||||
To interact with the APIC subsystem from the \textquote{outside}, the \code{Apic} class is used, which exposes the necessary functionality:
|
||||
|
||||
\begin{codeblock}{The APIC Public Interface (Apic.h)}{C++}
|
||||
\cppfile{code/apic_def.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Enabling the APIC subsystem is done by the \code{enable} function (see \autoref{fig:apicenable}).
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Local APIC}
|
||||
\label{sec:apxlocalapic}
|
||||
|
||||
\subsection{Accessing Local APIC Registers in xApic Mode}
|
||||
\label{subsec:apxxapicregacc}
|
||||
|
||||
The xApic register access requires a single page of strong uncachable memory, but since this requires setting attributes in the \textquote{Page Attribute Table}\footnote{
|
||||
See \url{https://docs.kernel.org/x86/pat.html} (visited on 12/02/2023).},
|
||||
\ this implementation only uses hhuOS' \code{mapIO} function, which maps a physical address to the kernel heap, with hhuOS' \textquote{CACHE\textunderscore{}DISABLE} flag set in the kernel page table:
|
||||
|
||||
\begin{codeblock}{Allocating the Local APIC's MMIO Region (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_mmio_alloc.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
A register can now be written as follows:
|
||||
|
||||
\begin{codeblock}[label=lst:lapicmmiowrite]{Writing a Local APIC MMIO Register (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_mmio_write.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To reduce the usage of manual bit-shifting and -masking, this implementation provides structures for some commonly used registers, that implement conversion operators to the register format:
|
||||
|
||||
\begin{codeblock}[label=lst:msrentry]{The MSREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_msr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:svrentry]{The SVREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_svr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:lvtentry]{The LVTEntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_lvt_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:icrentry]{The ICREntry Structure (LocalApicRegisters.h)}{C++}
|
||||
\cppfile{code/lapic_icr_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
These can be used in combination with some convenience functions:
|
||||
|
||||
\begin{codeblock}{Writing the IA32\textunderscore{}APIC\textunderscore{}BASE MSR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_msr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the SVR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_svr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the LVT (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_lvt.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Writing the ICR (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_write_icr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Disabling PIC Mode}
|
||||
\label{subsec:apxdisablepic}
|
||||
|
||||
Setting the IMCR\footnote{
|
||||
Writing the IMCR is detailed in the \textquote{MultiProcessor Specification}~\autocite[sec.~3.6.2.1]{mpspec}.}
|
||||
\ using hhuOS' \code{IoPort} class:
|
||||
|
||||
\begin{codeblock}{Disabling PIC Mode (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_imcr.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Initializing the LVT}
|
||||
\label{subsec:apxlvtinit}
|
||||
|
||||
The interrupt vectors are set as defined by the \code{InterruptVector} enum.
|
||||
This implementation configures the LVT by using the \code{LVTEntry} struct (see \autoref{lst:lvtentry}):
|
||||
|
||||
\begin{codeblock}{Configuring the LINT0 Local Interrupt (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_lvt_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
This process is repeated for each local interrupt.
|
||||
|
||||
\subsection{Handling the Spurious Interrupt}
|
||||
\label{subsec:apxsvr}
|
||||
|
||||
This implementation sets the SVR by using the \code{SVREntry} struct (see \autoref{lst:svrentry}):
|
||||
|
||||
\begin{codeblock}{Setting the Spurious Interrupt Vector (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_svr_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because hhuOS uses a two-stage interrupt handling approach (described in \autoref{sec:currenthhuos}), the spurious interrupt does not receive its own interrupt handler.
|
||||
Instead, it is ignored in the \code{dispatch} function, hhuOS' \textquote{first-stage} interrupt handler:
|
||||
|
||||
\begin{codeblock}{Checking for Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||
\cppfile{code/interruptdispatcher_check_spurious.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Ignoring Spurious Interrupts (InterruptDispatcher.cpp)}{C++}
|
||||
\cppfile{code/interruptdispatcher_ignore_spurious.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Using the APIC Timer}
|
||||
\label{subsec:apxapictimer}
|
||||
|
||||
The timer frequency is determined by counting the ticks in one millisecond, using the PIT as calibration source:
|
||||
|
||||
\begin{codeblock}{Calibrating the APIC Timer (ApicTimer.cpp)}{C++}
|
||||
\cppfile{code/apictimer_calibrate.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
This calibration is performed before the interrupts get enabled, so it is not possible to use hhuOS' \code{TimeService} for the delay.
|
||||
Instead, the \code{PIT::earlyDelay} function is used, which configures the PIT for mode \textquote{Interrupt on Terminal Count} on channel zero and polls the channel's output status~\autocite{pit}:
|
||||
|
||||
\begin{codeblock}{Microsecond Delay without Interrupts (Pit.cpp)}{C++}
|
||||
\cppfile{code/pit_early_delay.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Furthermore, the calibration is only performed once, even if multiple APIC timers are used.
|
||||
This removes the possibility of using multiple timers with different dividers.
|
||||
|
||||
To handle the APIC timer interrupt on multiple cores, \(n\) \code{ApicTimer} instances are registered to the appropriate interrupt vector, where \(n\) is the number of CPUs.
|
||||
Because this means, that each APIC timer interrupt on any CPU core triggers all \(n\) interrupt handlers, the handler has to determine if it belongs to the calling CPU\@.
|
||||
The handler belonging to the BSP's APIC timer also triggers the scheduler preemption (instead of the PIT):
|
||||
|
||||
\begin{codeblock}{Handling the APIC Timer Interrupt (ApicTimer.cpp)}{C++}
|
||||
\cppfile{code/apictimer_trigger.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Handling Local APIC Errors}
|
||||
\label{subsec:apxhandlingerror}
|
||||
|
||||
The error interrupt handler obtains the ESR's contents by writing to it first:
|
||||
|
||||
\begin{codeblock}{The Local APIC Error Interrupt Handler (ApicErrorHandler.cpp)}{C++}
|
||||
\cppfile{code/apicerror_trigger.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because every CPU core can only access its own local APIC's registers, a single instance of this interrupt handler can be used for each AP in the system.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{I/O APIC}
|
||||
\label{sec:apxioapic}
|
||||
|
||||
\subsection{Accessing I/O APIC Registers}
|
||||
\label{subsec:iolistings}
|
||||
|
||||
The I/O APIC's indirect register access requires two MMIO registers, that can be written similar to the local APIC's registers:
|
||||
|
||||
\begin{codeblock}{Writing an I/O APIC MMIO Register (IoApic.h)}{C++}
|
||||
\cppfile{code/ioapic_write_mmio.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Using the \textquote{Index} and \textquote{Data} registers to access the I/O APIC's indirect registers:
|
||||
|
||||
\begin{codeblock}{Writing an I/O APIC Indirect Register (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_write_indirect.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To reduce the manual bit-shifting and -masking, the same approach is used as for the local APIC\@:
|
||||
|
||||
\begin{codeblock}[label=lst:redtblentry]{The REDTBLEntry Structure (IoApicRegisters.h)}{C++}
|
||||
\cppfile{code/ioapic_redtbl_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}[label=lst:writeredtbl]{Writing the REDTBL (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_write_redtbl.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Interrupt Overrides}
|
||||
\label{subsec:apxirqoverrides}
|
||||
|
||||
This implementation represents an interrupt override using the following structure:
|
||||
|
||||
\begin{codeblock}{The External Interrupt Override Structure (IoApic.h)}{C++}
|
||||
\cppfile{code/ioapic_irqoverride.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
During initialization, the overrides are used to set the correct interrupt vectors, polarities and trigger modes for each REDTBL entry.
|
||||
The \code{REDTBLEntry} struct (see \autoref{lst:redtblentry}) is used to write the REDTBL\@:
|
||||
|
||||
\begin{codeblock}{Initializing the REDTBL (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_redtbl_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
During regular operation, the overrides are used to determine the correct REDTBL entries for e.g.\ unmasking an interrupt:
|
||||
|
||||
\begin{codeblock}{Unmasking an IRQ (Apic.cpp)}{C++}
|
||||
\cppfile{code/apic_allow.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
To convey this deviation between GSIs and PC/AT compatible IRQs very clearly, the public \code{Apic::allow} function accepts an \code{InterruptRequest} as an argument (that allows addressing the interrupt by name), while the internal \code{IoApic::allow} function only accepts a \code{GlobalSystemInterrupt} as argument:
|
||||
|
||||
\begin{codeblock}{Unmasking an IRQ Internally (IoApic.cpp)}{C++}
|
||||
\cppfile{code/ioapic_allow.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The internal \code{IoApic::allow} function is hidden (\code{private}) from the OS, and gets only called by the exposed \code{Apic::allow} function.
|
||||
This prevents accidentally setting the wrong REDTBL entry by not taking possible interrupt overrides into account.
|
||||
The same principle is applied to the other operations concerning GSIs.
|
||||
|
||||
\clearpage
|
||||
|
||||
\section{Symmetric Multiprocessing}
|
||||
\label{sec:apxsymmetric}
|
||||
|
||||
An overview of the complete SMP startup process can be found in \autoref{fig:smpenable}.
|
||||
|
||||
\subsection{Issuing Inter-Processor Interrupts}
|
||||
\label{subsec:apxipis}
|
||||
|
||||
To issue an IPI, the ICR is written by using the \code{ICREntry} struct (see \autoref{lst:icrentry}):
|
||||
|
||||
\begin{codeblock}{Issuing an INIT IPI (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_initipi_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\begin{codeblock}{Issuing a SIPI (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_sipi_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Preparing Symmetric Multiprocessing Startup}
|
||||
\label{subsec:apxpreparesmp}
|
||||
|
||||
Before executing the \textquote{Universal Startup Algorithm}, the boot code has to be relocated to physical lower memory.
|
||||
The memory region used for this copy has to be identity-mapped to the virtual kernel address space, so the effective addresses do not change after enabling paging in protected mode.
|
||||
To keep the required variables available to the startup code, these are located in the routines \textquote{TEXT} section and initialized during runtime.
|
||||
This approach was taken from SerenityOS~\autocite[APIC.cpp]{serenity}:
|
||||
|
||||
\begin{codeblock}{Preparing the Boot Routine's Variables (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_variables.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Now, the initialized startup routine can be copied to \code{0x8000}:
|
||||
|
||||
\begin{codeblock}{Relocating the Boot Routine (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_copy.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
The \code{boot\textunderscore{}ap} function is the entry of the startup routine, it is described further in \autoref{subsec:apxapboot}.
|
||||
|
||||
\subsection{Universal Startup Algorithm}
|
||||
\label{subsec:apxmpusa}
|
||||
|
||||
The \textquote{INIT-SIPI-SIPI} sequence, or \textquote{Universal Startup Algorithm} is performed by issuing IPIs as described in \autoref{subsec:apxipis} and using the PIT as time source (see \autoref{subsec:apxapictimer}):
|
||||
|
||||
\begin{codeblock}{The Universal Startup Algorithm (ApicSmp.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_usa.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Boot completion is signaled in the AP's entry function:
|
||||
|
||||
\begin{codeblock}{Signaling AP Boot Completion (smp\textunderscore{}entry.cpp)}{C++}
|
||||
\cppfile{code/smp_entry.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Application Processor Boot Routine}
|
||||
\label{subsec:apxapboot}
|
||||
|
||||
Because like the BSP, every AP is initialized in real mode, it has to be switched to protected mode first:
|
||||
|
||||
\begin{codeblock}{Preparing the Switch to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_real_prepare.asm}
|
||||
\end{codeblock}
|
||||
|
||||
Then, by enabling protected mode, setting the segment registers and far-jumping to the \SI{32}{\bit} code segment, the switch is performed:
|
||||
|
||||
\begin{codeblock}{Switching from Real Mode to Protected Mode (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_real.asm}
|
||||
\end{codeblock}
|
||||
|
||||
In \SI{32}{\bit} protected mode, paging is enabled and interrupt processing is prepared by reusing the control register values and the IDT from the BSP\@:
|
||||
|
||||
\begin{codeblock}{Reusing Values from the BSP (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_protected_bsp.asm}
|
||||
\end{codeblock}
|
||||
|
||||
Finally, to call the AP entry function, the AP requires its own stack. If hardware context switching is to be used, the AP additionally requires its own GDT and TSS\@:
|
||||
|
||||
\begin{codeblock}{Calling the Entry Function (smp\textunderscore{}boot.asm)}{nasm}
|
||||
\nasmfile{code/ap_boot_protected_ap.asm}
|
||||
\end{codeblock}
|
||||
|
||||
\subsection{Application Processor Post-Boot Routine}
|
||||
\label{subsec:apxappostboot}
|
||||
|
||||
When the AP has booted, it initializes its own APIC, including the APIC timer and error handler:
|
||||
|
||||
\begin{codeblock}{Initializing the Core's Local APIC (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/ap_boot_post.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because this added another possible recipient to internal APIC messages, the arbitration IDs are synchronized by issuing an \textquote{INIT-level-deassert IPI} using the \code{ICREntry} struct (see \autoref{lst:icrentry}):
|
||||
|
||||
\begin{codeblock}{Synchronizing the Arbitration IDs (LocalApic.cpp)}{C++}
|
||||
\cppfile{code/lapic_apr_example.cpp}
|
||||
\end{codeblock}
|
||||
|
||||
Because hhuOS' paging is not designed for multiple processors, the booted AP remains in a busy loop and does not enable its interrupts.
|
||||
|
||||
\cleardoublepage
|
249
chap/tables.aux
Normal file
249
chap/tables.aux
Normal file
@ -0,0 +1,249 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {C}Tables}{63}{appendix.1.C}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:tables}{{C}{63}{Tables}{appendix.1.C}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {C.1}Local APIC Registers}{64}{section.1.C.1}\protected@file@percent }
|
||||
\newlabel{sec:localapicregisters}{{C.1}{64}{Local APIC Registers}{section.1.C.1}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.1}{\ignorespaces Local APIC Registers used in this Implementation~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.1]{ia32}.\relax }}{64}{table.caption.5}\protected@file@percent }
|
||||
\newlabel{tab:lapicregs}{{C.1}{64}{Local APIC Registers used in this Implementation~\autocite [sec.~3.11.4.1]{ia32}.\relax }{table.caption.5}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.2}{\ignorespaces Local APIC ID Register (xApic since Pentium 4)~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.6]{ia32}.\relax }}{64}{table.caption.6}\protected@file@percent }
|
||||
\newlabel{tab:lapicregsid}{{C.2}{64}{Local APIC ID Register (xApic since Pentium 4)~\autocite [sec.~3.11.4.6]{ia32}.\relax }{table.caption.6}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.3}{\ignorespaces Local APIC Version Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.4.8]{ia32}.\relax }}{64}{table.caption.7}\protected@file@percent }
|
||||
\newlabel{tab:lapicregsver}{{C.3}{64}{Local APIC Version Register~\autocite [sec.~3.11.4.8]{ia32}.\relax }{table.caption.7}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.4}{\ignorespaces Task Priority Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.8.3.1]{ia32}.\relax }}{65}{table.caption.8}\protected@file@percent }
|
||||
\newlabel{tab:lapicregstpr}{{C.4}{65}{Task Priority Register~\autocite [sec.~3.11.8.3.1]{ia32}.\relax }{table.caption.8}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.5}{\ignorespaces Local APIC EOI Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.8.5]{ia32}.\relax }}{65}{table.caption.9}\protected@file@percent }
|
||||
\newlabel{tab:lapicregseoi}{{C.5}{65}{Local APIC EOI Register~\autocite [sec.~3.11.8.5]{ia32}.\relax }{table.caption.9}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.6}{\ignorespaces Spurious Interrupt Vector Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.9]{ia32}.\relax }}{65}{table.caption.10}\protected@file@percent }
|
||||
\newlabel{tab:lapicregssvr}{{C.6}{65}{Spurious Interrupt Vector Register~\autocite [sec.~3.11.9]{ia32}.\relax }{table.caption.10}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.7}{\ignorespaces Error Status Register (Pentium 4)~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.3]{ia32}.\relax }}{65}{table.caption.11}\protected@file@percent }
|
||||
\newlabel{tab:lapicregsesr}{{C.7}{65}{Error Status Register (Pentium 4)~\autocite [sec.~3.11.5.3]{ia32}.\relax }{table.caption.11}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.8}{\ignorespaces Interrupt Command Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.6.1]{ia32}.\relax }}{66}{table.caption.12}\protected@file@percent }
|
||||
\newlabel{tab:lapicregsicr}{{C.8}{66}{Interrupt Command Register~\autocite [sec.~3.11.6.1]{ia32}.\relax }{table.caption.12}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.9}{\ignorespaces LVT Timer Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{66}{table.caption.13}\protected@file@percent }
|
||||
\newlabel{tab:lapicregslvtt}{{C.9}{66}{LVT Timer Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.13}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.10}{\ignorespaces LVT Error Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{66}{table.caption.14}\protected@file@percent }
|
||||
\newlabel{tab:lapicregslvterr}{{C.10}{66}{LVT Error Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.14}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.11}{\ignorespaces LVT LINT1 Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.1]{ia32}.\relax }}{67}{table.caption.15}\protected@file@percent }
|
||||
\newlabel{tab:lapicregslvtlint}{{C.11}{67}{LVT LINT1 Register~\autocite [sec.~3.11.5.1]{ia32}.\relax }{table.caption.15}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.12}{\ignorespaces Timer Initial Count Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.4]{ia32}.\relax }}{67}{table.caption.16}\protected@file@percent }
|
||||
\newlabel{tab:lapicregstimerinit}{{C.12}{67}{Timer Initial Count Register~\autocite [sec.~3.11.5.4]{ia32}.\relax }{table.caption.16}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.13}{\ignorespaces Timer Divide Configuration Register~\blx@tocontentsinit {0}\autocite [sec.~3.11.5.4]{ia32}.\relax }}{67}{table.caption.17}\protected@file@percent }
|
||||
\newlabel{tab:lapicregstimerdiv}{{C.13}{67}{Timer Divide Configuration Register~\autocite [sec.~3.11.5.4]{ia32}.\relax }{table.caption.17}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.14}{\ignorespaces IA32\textunderscore {} APIC\textunderscore {}BASE MSR~\blx@tocontentsinit {0}\autocite [sec.~3.11.12.1]{ia32}. \relax }}{67}{table.caption.18}\protected@file@percent }
|
||||
\newlabel{tab:lapicregsmsr}{{C.14}{67}{IA32\textunderscore {} APIC\textunderscore {}BASE MSR~\autocite [sec.~3.11.12.1]{ia32}. \relax }{table.caption.18}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {C.2}I/O APIC Registers}{68}{section.1.C.2}\protected@file@percent }
|
||||
\newlabel{sec:ioapicregs}{{C.2}{68}{I/O APIC Registers}{section.1.C.2}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.15}{\ignorespaces I/O APIC Registers used in this Implementation~\blx@tocontentsinit {0}\autocite [sec.~9.5]{ich5}.\relax }}{68}{table.caption.19}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregs}{{C.15}{68}{I/O APIC Registers used in this Implementation~\autocite [sec.~9.5]{ich5}.\relax }{table.caption.19}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.16}{\ignorespaces I/O APIC Index Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.2]{ich5}.\relax }}{68}{table.caption.20}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregsidx}{{C.16}{68}{I/O APIC Index Register~\autocite [sec.~9.5.2]{ich5}.\relax }{table.caption.20}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.17}{\ignorespaces I/O APIC Data Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.3]{ich5}.\relax }}{68}{table.caption.21}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregsdat}{{C.17}{68}{I/O APIC Data Register~\autocite [sec.~9.5.3]{ich5}.\relax }{table.caption.21}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.18}{\ignorespaces I/O APIC ID Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.6]{ich5}.\relax }}{68}{table.caption.22}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregsid}{{C.18}{68}{I/O APIC ID Register~\autocite [sec.~9.5.6]{ich5}.\relax }{table.caption.22}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.19}{\ignorespaces I/O APIC Version Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.7]{ich5}.\relax }}{69}{table.caption.23}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregsver}{{C.19}{69}{I/O APIC Version Register~\autocite [sec.~9.5.7]{ich5}.\relax }{table.caption.23}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.20}{\ignorespaces I/O APIC REDTBL Register~\blx@tocontentsinit {0}\autocite [sec.~9.5.8]{ich5}.\relax }}{69}{table.caption.24}\protected@file@percent }
|
||||
\newlabel{tab:ioapicregsredtbl}{{C.20}{69}{I/O APIC REDTBL Register~\autocite [sec.~9.5.8]{ich5}.\relax }{table.caption.24}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {C.3}System Description Tables}{70}{section.1.C.3}\protected@file@percent }
|
||||
\newlabel{sec:sdts}{{C.3}{70}{System Description Tables}{section.1.C.3}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.21}{\ignorespaces ACPI MADT~\blx@tocontentsinit {0}\autocite [sec.~5.2.8]{acpi1}.\relax }}{70}{table.caption.25}\protected@file@percent }
|
||||
\newlabel{tab:madt}{{C.21}{70}{ACPI MADT~\autocite [sec.~5.2.8]{acpi1}.\relax }{table.caption.25}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.22}{\ignorespaces MADT Processor Local APIC Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.1]{acpi1}.\relax }}{70}{table.caption.26}\protected@file@percent }
|
||||
\newlabel{tab:madtlapic}{{C.22}{70}{MADT Processor Local APIC Structure~\autocite [sec.~5.2.8.1]{acpi1}.\relax }{table.caption.26}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.23}{\ignorespaces Local APIC Flags~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.1]{acpi1}.\relax }}{70}{table.caption.27}\protected@file@percent }
|
||||
\newlabel{tab:madtlapicflags}{{C.23}{70}{Local APIC Flags~\autocite [sec.~5.2.8.1]{acpi1}.\relax }{table.caption.27}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.24}{\ignorespaces MADT I/O APIC Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.2]{acpi1}.\relax }}{70}{table.caption.28}\protected@file@percent }
|
||||
\newlabel{tab:madtioapic}{{C.24}{70}{MADT I/O APIC Structure~\autocite [sec.~5.2.8.2]{acpi1}.\relax }{table.caption.28}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.25}{\ignorespaces MADT Interrupt Source Override Structure~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }}{71}{table.caption.29}\protected@file@percent }
|
||||
\newlabel{tab:madtirqoverride}{{C.25}{71}{MADT Interrupt Source Override Structure~\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }{table.caption.29}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.26}{\ignorespaces INTI Flags~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }}{71}{table.caption.30}\protected@file@percent }
|
||||
\newlabel{tab:madtintiflags}{{C.26}{71}{INTI Flags~\autocite [sec.~5.2.8.3.1]{acpi1}.\relax }{table.caption.30}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.27}{\ignorespaces MADT I/O APIC NMI Source~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.2]{acpi1}.\relax }}{71}{table.caption.31}\protected@file@percent }
|
||||
\newlabel{tab:madtionmi}{{C.27}{71}{MADT I/O APIC NMI Source~\autocite [sec.~5.2.8.3.2]{acpi1}.\relax }{table.caption.31}{}}
|
||||
\@writefile{lot}{\contentsline {table}{\numberline {C.28}{\ignorespaces MADT Local APIC NMI Source~\blx@tocontentsinit {0}\autocite [sec.~5.2.8.3.3]{acpi1}.\relax }}{71}{table.caption.32}\protected@file@percent }
|
||||
\newlabel{tab:madtlnmi}{{C.28}{71}{MADT Local APIC NMI Source~\autocite [sec.~5.2.8.3.3]{acpi1}.\relax }{table.caption.32}{}}
|
||||
\@setckpt{chap/tables}{
|
||||
\setcounter{page}{73}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{4}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{0}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{3}
|
||||
\setcounter{section}{3}
|
||||
\setcounter{subsection}{0}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{0}
|
||||
\setcounter{table}{28}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{184}
|
||||
\setcounter{FancyVerbLine}{12}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{80}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{1}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{47}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{2}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{1}
|
||||
\setcounter{Item}{50}
|
||||
\setcounter{Hfootnote}{45}
|
||||
\setcounter{bookmark@seq@number}{77}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{1}
|
||||
\setcounter{@ppsavesec}{5}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{152}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{4}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -5,7 +5,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
|
||||
\clearpage
|
||||
|
||||
\renewcommand{\arraystretch}{1.2}
|
||||
\renewcommand{\arraystretch}{1.2} % Slightly larger row spacing
|
||||
|
||||
\section{Local APIC Registers}
|
||||
\label{sec:localapicregisters}
|
||||
@ -29,7 +29,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
Timer Initial Count Register & 0x380 \\ \hline
|
||||
Timer Divide Configuration Register & 0x3E0 \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Registers used in this Implementation~\cite[sec.~3.11.4.1]{ia32}.}
|
||||
\caption{Local APIC Registers used in this Implementation~\autocite[sec.~3.11.4.1]{ia32}.}
|
||||
\label{tab:lapicregs}
|
||||
\end{table}
|
||||
|
||||
@ -41,7 +41,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
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}.}
|
||||
\caption{Local APIC ID Register (xApic since Pentium 4)~\autocite[sec.~3.11.4.6]{ia32}.}
|
||||
\label{tab:lapicregsid}
|
||||
\end{table}
|
||||
|
||||
@ -56,7 +56,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
24 & EOI Broadcast Suppression Support \\ \hline
|
||||
25:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Version Register~\cite[sec.~3.11.4.8]{ia32}.}
|
||||
\caption{Local APIC Version Register~\autocite[sec.~3.11.4.8]{ia32}.}
|
||||
\label{tab:lapicregsver}
|
||||
\end{table}
|
||||
|
||||
@ -69,7 +69,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
4:7 & Task-Priority Class \\ \hline
|
||||
8:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Task Priority Register~\cite[sec.~3.11.8.3.1]{ia32}.}
|
||||
\caption{Task Priority Register~\autocite[sec.~3.11.8.3.1]{ia32}.}
|
||||
\label{tab:lapicregstpr}
|
||||
\end{table}
|
||||
|
||||
@ -80,7 +80,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Send EOI Signal \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC EOI Register~\cite[sec.~3.11.8.5]{ia32}.}
|
||||
\caption{Local APIC EOI Register~\autocite[sec.~3.11.8.5]{ia32}.}
|
||||
\label{tab:lapicregseoi}
|
||||
\end{table}
|
||||
|
||||
@ -96,7 +96,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
12 & EOI Broadcast Suppression \\ \hline
|
||||
13:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Spurious Interrupt Vector Register~\cite[sec.~3.11.9]{ia32}.}
|
||||
\caption{Spurious Interrupt Vector Register~\autocite[sec.~3.11.9]{ia32}.}
|
||||
\label{tab:lapicregssvr}
|
||||
\end{table}
|
||||
|
||||
@ -111,7 +111,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
7 & Illegal Register Access \\ \hline
|
||||
8:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Error Status Register (Pentium 4)~\cite[sec.~3.11.5.3]{ia32}.}
|
||||
\caption{Error Status Register (Pentium 4)~\autocite[sec.~3.11.5.3]{ia32}.}
|
||||
\label{tab:lapicregsesr}
|
||||
\end{table}
|
||||
|
||||
@ -132,7 +132,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
20:55 & Reserved \\ \hline
|
||||
56:63 & Destination Field \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Interrupt Command Register~\cite[sec.~3.11.6.1]{ia32}.}
|
||||
\caption{Interrupt Command Register~\autocite[sec.~3.11.6.1]{ia32}.}
|
||||
\label{tab:lapicregsicr}
|
||||
\end{table}
|
||||
|
||||
@ -149,7 +149,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
17:18 & Timer Mode \\ \hline
|
||||
19:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT Timer Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\caption{LVT Timer Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvtt}
|
||||
\end{table}
|
||||
|
||||
@ -165,7 +165,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
16 & Masked \\ \hline
|
||||
17:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT Error Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\caption{LVT Error Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvterr}
|
||||
\end{table}
|
||||
|
||||
@ -184,7 +184,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
16 & Masked \\ \hline
|
||||
17:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{LVT LINT1 Register~\cite[sec.~3.11.5.1]{ia32}.}
|
||||
\caption{LVT LINT1 Register~\autocite[sec.~3.11.5.1]{ia32}.}
|
||||
\label{tab:lapicregslvtlint}
|
||||
\end{table}
|
||||
|
||||
@ -195,7 +195,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Initial Count \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Timer Initial Count Register~\cite[sec.~3.11.5.4]{ia32}.}
|
||||
\caption{Timer Initial Count Register~\autocite[sec.~3.11.5.4]{ia32}.}
|
||||
\label{tab:lapicregstimerinit}
|
||||
\end{table}
|
||||
|
||||
@ -209,7 +209,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
3 & Divider \\ \hline
|
||||
4:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Timer Divide Configuration Register~\cite[sec.~3.11.5.4]{ia32}.}
|
||||
\caption{Timer Divide Configuration Register~\autocite[sec.~3.11.5.4]{ia32}.}
|
||||
\label{tab:lapicregstimerdiv}
|
||||
\end{table}
|
||||
|
||||
@ -226,7 +226,9 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
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}.}
|
||||
\caption{IA32\textunderscore{}
|
||||
APIC\textunderscore{}BASE MSR~\autocite[sec.~3.11.12.1]{ia32}.
|
||||
}
|
||||
\label{tab:lapicregsmsr}
|
||||
\end{table}
|
||||
|
||||
@ -247,7 +249,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
I/O APIC Version Register & 0x01 \\ \hline
|
||||
Redirection Table & 0x10:0x3F \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Registers used in this Implementation~\cite[sec.~9.5]{ich5}.}
|
||||
\caption{I/O APIC Registers used in this Implementation~\autocite[sec.~9.5]{ich5}.}
|
||||
\label{tab:ioapicregs}
|
||||
\end{table}
|
||||
|
||||
@ -258,7 +260,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:7 & Indirect Register Index \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Index Register~\cite[sec.~9.5.2]{ich5}.}
|
||||
\caption{I/O APIC Index Register~\autocite[sec.~9.5.2]{ich5}.}
|
||||
\label{tab:ioapicregsidx}
|
||||
\end{table}
|
||||
|
||||
@ -269,7 +271,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\textbf{Bit Number} & \textbf{Description} \\ \hline\hline
|
||||
0:31 & Indirect Register Data \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Data Register~\cite[sec.~9.5.3]{ich5}.}
|
||||
\caption{I/O APIC Data Register~\autocite[sec.~9.5.3]{ich5}.}
|
||||
\label{tab:ioapicregsdat}
|
||||
\end{table}
|
||||
|
||||
@ -284,7 +286,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
24:27 & I/O APIC ID \\ \hline
|
||||
28:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC ID Register~\cite[sec.~9.5.6]{ich5}.}
|
||||
\caption{I/O APIC ID Register~\autocite[sec.~9.5.6]{ich5}.}
|
||||
\label{tab:ioapicregsid}
|
||||
\end{table}
|
||||
|
||||
@ -299,7 +301,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
16:23 & Maximum Redirection Entries \\ \hline
|
||||
24:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC Version Register~\cite[sec.~9.5.7]{ich5}.}
|
||||
\caption{I/O APIC Version Register~\autocite[sec.~9.5.7]{ich5}.}
|
||||
\label{tab:ioapicregsver}
|
||||
\end{table}
|
||||
|
||||
@ -320,7 +322,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
48:55 & Extended Destination ID \\ \hline
|
||||
56:63 & Destination \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{I/O APIC REDTBL Register~\cite[sec.~9.5.8]{ich5}.}
|
||||
\caption{I/O APIC REDTBL Register~\autocite[sec.~9.5.8]{ich5}.}
|
||||
\label{tab:ioapicregsredtbl}
|
||||
\end{table}
|
||||
|
||||
@ -339,7 +341,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
40:43 & Local APIC Flags \\ \hline
|
||||
44: & List of APIC Structures \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{ACPI MADT~\cite[sec.~5.2.8]{acpi1}.}
|
||||
\caption{ACPI MADT~\autocite[sec.~5.2.8]{acpi1}.}
|
||||
\label{tab:madt}
|
||||
\end{table}
|
||||
|
||||
@ -353,7 +355,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
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}.}
|
||||
\caption{MADT Processor Local APIC Structure~\autocite[sec.~5.2.8.1]{acpi1}.}
|
||||
\label{tab:madtlapic}
|
||||
\end{table}
|
||||
|
||||
@ -365,7 +367,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
0 & Enabled \\ \hline
|
||||
1:31 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Local APIC Flags~\cite[sec.~5.2.8.1]{acpi1}.}
|
||||
\caption{Local APIC Flags~\autocite[sec.~5.2.8.1]{acpi1}.}
|
||||
\label{tab:madtlapicflags}
|
||||
\end{table}
|
||||
|
||||
@ -380,7 +382,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
4:7 & I/O APIC Base Address \\ \hline
|
||||
8:11 & I/O APIC GSI Base \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT I/O APIC Structure~\cite[sec.~5.2.8.2]{acpi1}.}
|
||||
\caption{MADT I/O APIC Structure~\autocite[sec.~5.2.8.2]{acpi1}.}
|
||||
\label{tab:madtioapic}
|
||||
\end{table}
|
||||
|
||||
@ -393,9 +395,9 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
2 & Bus \\ \hline
|
||||
3 & Source \\ \hline
|
||||
4:7 & GSI \\ \hline
|
||||
8:9 & Interrupt Input Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
8:9 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT Interrupt Source Override Structure~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\caption{MADT Interrupt Source Override Structure~\autocite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\label{tab:madtirqoverride}
|
||||
\end{table}
|
||||
|
||||
@ -408,7 +410,7 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
2:3 & Trigger Mode \\ \hline
|
||||
4:11 & Reserved \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{Interrupt Input Flags~\cite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\caption{INTI Flags~\autocite[sec.~5.2.8.3.1]{acpi1}.}
|
||||
\label{tab:madtintiflags}
|
||||
\end{table}
|
||||
|
||||
@ -418,10 +420,10 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\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
|
||||
2:3 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
4:7 & GSI \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT I/O APIC NMI Source~\cite[sec.~5.2.8.3.2]{acpi1}.}
|
||||
\caption{MADT I/O APIC NMI Source~\autocite[sec.~5.2.8.3.2]{acpi1}.}
|
||||
\label{tab:madtionmi}
|
||||
\end{table}
|
||||
|
||||
@ -432,9 +434,11 @@ This section lists all the registers and structures required to follow \autoref{
|
||||
\textbf{Byte Number} & \textbf{Description} \\ \hline\hline
|
||||
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
|
||||
3:4 & INTI Flags (see \autoref{tab:madtintiflags}) \\ \hline
|
||||
5 & Local APIC INTI \\ \hline
|
||||
\end{tabularx}
|
||||
\caption{MADT Local APIC NMI Source~\cite[sec.~5.2.8.3.3]{acpi1}.}
|
||||
\caption{MADT Local APIC NMI Source~\autocite[sec.~5.2.8.3.3]{acpi1}.}
|
||||
\label{tab:madtlnmi}
|
||||
\end{table}
|
||||
|
||||
\cleardoublepage
|
191
chap/verification.aux
Normal file
191
chap/verification.aux
Normal file
@ -0,0 +1,191 @@
|
||||
\relax
|
||||
\providecommand{\transparent@use}[1]{}
|
||||
\providecommand\hyper@newdestlabel[2]{}
|
||||
\@writefile{listings}{\addvspace {10pt}}
|
||||
\@writefile{toc}{\contentsline {chapter}{\numberline {4}Verification}{33}{chapter.4}\protected@file@percent }
|
||||
\@writefile{lof}{\addvspace {10\p@ }}
|
||||
\@writefile{lot}{\addvspace {10\p@ }}
|
||||
\@writefile{loa}{\addvspace {10\p@ }}
|
||||
\newlabel{ch:verification}{{4}{33}{Verification}{chapter.4}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {4.1}Methods of Verification}{34}{section.4.1}\protected@file@percent }
|
||||
\newlabel{sec:verificationmethods}{{4.1}{34}{Methods of Verification}{section.4.1}{}}
|
||||
\@writefile{toc}{\contentsline {section}{\numberline {4.2}Results}{34}{section.4.2}\protected@file@percent }
|
||||
\newlabel{sec:verificationresults}{{4.2}{34}{Results}{section.4.2}{}}
|
||||
\@setckpt{chap/verification}{
|
||||
\setcounter{page}{37}
|
||||
\setcounter{equation}{0}
|
||||
\setcounter{enumi}{9}
|
||||
\setcounter{enumii}{0}
|
||||
\setcounter{enumiii}{0}
|
||||
\setcounter{enumiv}{0}
|
||||
\setcounter{footnote}{3}
|
||||
\setcounter{mpfootnote}{0}
|
||||
\setcounter{part}{0}
|
||||
\setcounter{chapter}{4}
|
||||
\setcounter{section}{2}
|
||||
\setcounter{subsection}{0}
|
||||
\setcounter{subsubsection}{0}
|
||||
\setcounter{paragraph}{0}
|
||||
\setcounter{subparagraph}{0}
|
||||
\setcounter{figure}{0}
|
||||
\setcounter{table}{0}
|
||||
\setcounter{parentequation}{0}
|
||||
\setcounter{tcbbreakpart}{1}
|
||||
\setcounter{tcblayer}{0}
|
||||
\setcounter{tcolorbox@number}{59}
|
||||
\setcounter{FancyVerbLine}{0}
|
||||
\setcounter{linenumber}{1}
|
||||
\setcounter{LN@truepage}{44}
|
||||
\setcounter{FV@TrueTabGroupLevel}{0}
|
||||
\setcounter{FV@TrueTabCounter}{0}
|
||||
\setcounter{FV@HighlightLinesStart}{0}
|
||||
\setcounter{FV@HighlightLinesStop}{0}
|
||||
\setcounter{FancyVerbLineBreakLast}{0}
|
||||
\setcounter{FV@BreakBufferDepth}{0}
|
||||
\setcounter{float@type}{16}
|
||||
\setcounter{minted@FancyVerbLineTemp}{0}
|
||||
\setcounter{minted@pygmentizecounter}{0}
|
||||
\setcounter{listing}{0}
|
||||
\setcounter{tcblisting}{0}
|
||||
\setcounter{caption@flags}{6}
|
||||
\setcounter{continuedfloat}{0}
|
||||
\setcounter{subfigure}{0}
|
||||
\setcounter{subtable}{0}
|
||||
\setcounter{section@level}{1}
|
||||
\setcounter{Item}{46}
|
||||
\setcounter{Hfootnote}{38}
|
||||
\setcounter{bookmark@seq@number}{43}
|
||||
\setcounter{AlgoLine}{0}
|
||||
\setcounter{algocfline}{0}
|
||||
\setcounter{algocfproc}{0}
|
||||
\setcounter{algocf}{0}
|
||||
\setcounter{lofdepth}{1}
|
||||
\setcounter{lotdepth}{1}
|
||||
\setcounter{svg@param@lastpage}{0}
|
||||
\setcounter{svg@param@currpage}{-1}
|
||||
\setcounter{su@anzahl}{0}
|
||||
\setcounter{LT@tables}{0}
|
||||
\setcounter{LT@chunks}{0}
|
||||
\setcounter{@pps}{0}
|
||||
\setcounter{@ppsavesec}{0}
|
||||
\setcounter{@ppsaveapp}{0}
|
||||
\setcounter{tabx@nest}{0}
|
||||
\setcounter{listtotal}{0}
|
||||
\setcounter{listcount}{0}
|
||||
\setcounter{liststart}{0}
|
||||
\setcounter{liststop}{0}
|
||||
\setcounter{citecount}{0}
|
||||
\setcounter{citetotal}{0}
|
||||
\setcounter{multicitecount}{0}
|
||||
\setcounter{multicitetotal}{0}
|
||||
\setcounter{instcount}{78}
|
||||
\setcounter{maxnames}{3}
|
||||
\setcounter{minnames}{3}
|
||||
\setcounter{maxitems}{3}
|
||||
\setcounter{minitems}{1}
|
||||
\setcounter{citecounter}{0}
|
||||
\setcounter{maxcitecounter}{0}
|
||||
\setcounter{savedcitecounter}{0}
|
||||
\setcounter{uniquelist}{0}
|
||||
\setcounter{uniquename}{0}
|
||||
\setcounter{refsection}{0}
|
||||
\setcounter{refsegment}{0}
|
||||
\setcounter{maxextratitle}{0}
|
||||
\setcounter{maxextratitleyear}{0}
|
||||
\setcounter{maxextraname}{0}
|
||||
\setcounter{maxextradate}{0}
|
||||
\setcounter{maxextraalpha}{0}
|
||||
\setcounter{abbrvpenalty}{50}
|
||||
\setcounter{highnamepenalty}{50}
|
||||
\setcounter{lownamepenalty}{25}
|
||||
\setcounter{maxparens}{3}
|
||||
\setcounter{parenlevel}{0}
|
||||
\setcounter{blx@maxsection}{0}
|
||||
\setcounter{mincomprange}{10}
|
||||
\setcounter{maxcomprange}{100000}
|
||||
\setcounter{mincompwidth}{1}
|
||||
\setcounter{afterword}{0}
|
||||
\setcounter{savedafterword}{0}
|
||||
\setcounter{annotator}{0}
|
||||
\setcounter{savedannotator}{0}
|
||||
\setcounter{author}{0}
|
||||
\setcounter{savedauthor}{0}
|
||||
\setcounter{bookauthor}{0}
|
||||
\setcounter{savedbookauthor}{0}
|
||||
\setcounter{commentator}{0}
|
||||
\setcounter{savedcommentator}{0}
|
||||
\setcounter{editor}{0}
|
||||
\setcounter{savededitor}{0}
|
||||
\setcounter{editora}{0}
|
||||
\setcounter{savededitora}{0}
|
||||
\setcounter{editorb}{0}
|
||||
\setcounter{savededitorb}{0}
|
||||
\setcounter{editorc}{0}
|
||||
\setcounter{savededitorc}{0}
|
||||
\setcounter{foreword}{0}
|
||||
\setcounter{savedforeword}{0}
|
||||
\setcounter{holder}{0}
|
||||
\setcounter{savedholder}{0}
|
||||
\setcounter{introduction}{0}
|
||||
\setcounter{savedintroduction}{0}
|
||||
\setcounter{namea}{0}
|
||||
\setcounter{savednamea}{0}
|
||||
\setcounter{nameb}{0}
|
||||
\setcounter{savednameb}{0}
|
||||
\setcounter{namec}{0}
|
||||
\setcounter{savednamec}{0}
|
||||
\setcounter{translator}{0}
|
||||
\setcounter{savedtranslator}{0}
|
||||
\setcounter{shortauthor}{0}
|
||||
\setcounter{savedshortauthor}{0}
|
||||
\setcounter{shorteditor}{0}
|
||||
\setcounter{savedshorteditor}{0}
|
||||
\setcounter{labelname}{0}
|
||||
\setcounter{savedlabelname}{0}
|
||||
\setcounter{institution}{0}
|
||||
\setcounter{savedinstitution}{0}
|
||||
\setcounter{lista}{0}
|
||||
\setcounter{savedlista}{0}
|
||||
\setcounter{listb}{0}
|
||||
\setcounter{savedlistb}{0}
|
||||
\setcounter{listc}{0}
|
||||
\setcounter{savedlistc}{0}
|
||||
\setcounter{listd}{0}
|
||||
\setcounter{savedlistd}{0}
|
||||
\setcounter{liste}{0}
|
||||
\setcounter{savedliste}{0}
|
||||
\setcounter{listf}{0}
|
||||
\setcounter{savedlistf}{0}
|
||||
\setcounter{location}{0}
|
||||
\setcounter{savedlocation}{0}
|
||||
\setcounter{organization}{0}
|
||||
\setcounter{savedorganization}{0}
|
||||
\setcounter{origlocation}{0}
|
||||
\setcounter{savedoriglocation}{0}
|
||||
\setcounter{origpublisher}{0}
|
||||
\setcounter{savedorigpublisher}{0}
|
||||
\setcounter{publisher}{0}
|
||||
\setcounter{savedpublisher}{0}
|
||||
\setcounter{language}{0}
|
||||
\setcounter{savedlanguage}{0}
|
||||
\setcounter{origlanguage}{0}
|
||||
\setcounter{savedoriglanguage}{0}
|
||||
\setcounter{pageref}{0}
|
||||
\setcounter{savedpageref}{0}
|
||||
\setcounter{textcitecount}{0}
|
||||
\setcounter{textcitetotal}{0}
|
||||
\setcounter{textcitemaxnames}{0}
|
||||
\setcounter{biburlbigbreakpenalty}{100}
|
||||
\setcounter{biburlbreakpenalty}{200}
|
||||
\setcounter{biburlnumpenalty}{0}
|
||||
\setcounter{biburlucpenalty}{0}
|
||||
\setcounter{biburllcpenalty}{0}
|
||||
\setcounter{smartand}{1}
|
||||
\setcounter{bbx:relatedcount}{0}
|
||||
\setcounter{bbx:relatedtotal}{0}
|
||||
\setcounter{cbx@tempcnta}{0}
|
||||
\setcounter{cbx@tempcntb}{13}
|
||||
\setcounter{cbx@tempcntc}{0}
|
||||
\setcounter{cbx@tempcntd}{-1}
|
||||
\setcounter{tcb@cnt@codeblock}{0}
|
||||
}
|
@ -1,82 +1,64 @@
|
||||
\chapter{Verification}
|
||||
\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.
|
||||
Common techniques for testing software include component-based tests, like \textquote{unit tests}, and \textquote{end-to-end tests}, where the complete functionality of a software system with all its parts is tested.
|
||||
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.
|
||||
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 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.
|
||||
\item When running hhuOS in an emulated environment, the current machine state can be inspected directly\footnote{
|
||||
QEMU offers the \textquote{QEMU monitor} to query information about specific hardware components, like the local or I/O APIC (\code{info lapic} and \code{info pic}).}.
|
||||
\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:
|
||||
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.
|
||||
\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.
|
||||
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 \textquote{ThinkPad T60s} with an Intel \textquote{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:
|
||||
More specifically, information about detected and enabled local APICs and the I/O APIC, register values from the BSP's LVT and the REDTBL, the contents of the PIC's \textbf{\gls{imr}}, and the number of occurred interrupts by core (similar to \code{/proc/interrupts} in Linux~\autocite{linux}) are exposed on the path \code{/device/apic/}.
|
||||
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.}.
|
||||
\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 \textquote{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 behavior 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 indeed arriving at a different core than the BSP\@.
|
||||
After a certain time, the system crashes on the ThinkPad as well.}.
|
||||
\end{itemize}
|
||||
|
||||
It should be noted, that e.g.\ the REDTBL observation requires the same MMIO registers as the functionality that is to be verified, which would allow for wrong conclusions if the MMIO mechanism was faulty.
|
||||
It is very unlikely though that all the correct values are provided accidentally.
|
||||
|
||||
\cleardoublepage
|
130
class/thesis.cls
130
class/thesis.cls
@ -20,65 +20,63 @@
|
||||
% Packages
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\RequirePackage{silence} % Silence some warnings
|
||||
\WarningFilter{latexfont}{Font shape}
|
||||
\WarningFilter{latexfont}{Some font shapres were not available}
|
||||
\WarningFilter{latexfont}{Size substitutions with differences}
|
||||
\WarningFilter{latex}{`h' float specifier}
|
||||
\WarningFilter{latex}{\include should only be used after}
|
||||
\WarningFilter{fancyhdr}{\headheight}
|
||||
|
||||
\RequirePackage[left=3cm,right=2.5cm,top=3cm,bottom=2.5cm]{geometry}
|
||||
|
||||
\RequirePackage[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[english]{babel} % ngerman
|
||||
\RequirePackage{fancyhdr} % For headers
|
||||
\RequirePackage{color}
|
||||
% \RequirePackage[usenames,dvipsnames]{xcolor} % Option Clash, already loaded by sth else
|
||||
\RequirePackage{graphicx}
|
||||
\RequirePackage[usenames,dvipsnames]{xcolor}
|
||||
% \RequirePackage{amssymb}
|
||||
\RequirePackage{amsmath} % tcolorbox should load this anyway, but results in errors?
|
||||
\RequirePackage[minted]{tcolorbox} % Load after xcolor, [minted]
|
||||
% \RequirePackage{minted}
|
||||
% \RequirePackage{graphicx}
|
||||
\RequirePackage{tikz}
|
||||
\RequirePackage{subcaption} % Floats in floats
|
||||
\RequirePackage{float}
|
||||
\RequirePackage{multirow} % For tables
|
||||
% \RequirePackage{multirow} % For tables
|
||||
% \RequirePackage{todonotes}
|
||||
\RequirePackage{hyperref} % [hidelinks]
|
||||
\RequirePackage[hidelinks]{hyperref} % [hidelinks]
|
||||
\RequirePackage{algorithm2e}
|
||||
\RequirePackage{tocloft}
|
||||
\RequirePackage{listings}
|
||||
% \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{pgffor}
|
||||
\RequirePackage{enumitem}
|
||||
|
||||
% Some additions
|
||||
|
||||
% Borders around svg figures
|
||||
\RequirePackage{svg}
|
||||
\RequirePackage{float}
|
||||
\floatstyle{boxed}
|
||||
\restylefloat{figure}
|
||||
|
||||
\RequirePackage{csquotes}
|
||||
\RequirePackage[inkscapelatex=false]{svg} % Autoconvert to pdf, don't let latex touch the fonts
|
||||
\RequirePackage{csquotes} % \textquote{}
|
||||
\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{eulerpx} % Math font (have no math :()
|
||||
\RequirePackage{inconsolata} % Code font
|
||||
|
||||
% Group listings by chapter, pretocmd prepends something to a command
|
||||
\RequirePackage[activate={true,nocompatibility},final,expansion=false,tracking=true,kerning=true,factor=1100,stretch=10,shrink=10]{microtype} % Sadly, expansion does not work with concrete, as they are not scalable
|
||||
\RequirePackage{etoolbox}
|
||||
\pretocmd{\chapter}{\addtocontents{listings}{\protect\addvspace{10pt}}}{}{}
|
||||
\RequirePackage{siunitx}
|
||||
\RequirePackage{setspace}
|
||||
|
||||
% Control lot/lof parskip
|
||||
\RequirePackage{tocloft}
|
||||
|
||||
% Allow referencing subsubsections (don't have those anymore)
|
||||
% \setcounter{secnumdepth}{3}
|
||||
% \setcounter{tocdepth}{3}
|
||||
% Options
|
||||
\floatstyle{boxed} % boxes around figures
|
||||
\restylefloat{figure}
|
||||
\DeclareFontSeriesDefault[rm]{bf}{sbc} % beton Computer Concrete does not have bold font
|
||||
\pretocmd{\chapter}{\addtocontents{listings}{\protect\addvspace{10pt}}}{}{} % Group listings by chap
|
||||
\sisetup{detect-all}
|
||||
% \renewcommand{\baselinestretch}{0.95}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Package settings
|
||||
@ -192,9 +190,6 @@
|
||||
\def\@thesistype{}
|
||||
\newcommand{\thesistype}[1]{\def\@thesistype{#1}}
|
||||
|
||||
\def\@glossaryenabled{}
|
||||
\newcommand{\glossaryenabled}[1]{\def\@glossaryenabled{#1}}
|
||||
|
||||
\def\@listoffiguresenabled{}
|
||||
\newcommand{\listoffiguresenabled}[1]{\def\@listoffiguresenabled{#1}}
|
||||
|
||||
@ -204,12 +199,6 @@
|
||||
\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
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
@ -284,8 +273,12 @@
|
||||
% Table of contents
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\tableofcontents
|
||||
\microtypesetup{protrusion=false}
|
||||
\begin{spacing}{0.94} % Hamburger the TOC into two pages really unprofessionally
|
||||
\tableofcontents
|
||||
\end{spacing}
|
||||
\cleardoublepage
|
||||
\microtypesetup{protrusion=true}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Re-enable fancy headers
|
||||
@ -294,34 +287,16 @@
|
||||
% \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
|
||||
}%
|
||||
{}
|
||||
% Print Glossary
|
||||
\setacronymstyle{short-long}
|
||||
\printglossary[type=\acronymtype]
|
||||
\cleardoublepage
|
||||
\printglossary
|
||||
|
||||
\cleardoublepage
|
||||
\pagenumbering{arabic}
|
||||
}
|
||||
% Document Content
|
||||
{
|
||||
\pagenumbering{gobble}
|
||||
\printbibliography % [heading=bibintoc]
|
||||
@ -330,8 +305,8 @@
|
||||
|
||||
\tcblistof[\chapter*]{listings}{List of Listings}
|
||||
% \addcontentsline{toc}{chapter}{List of Listings}
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
\cleardoublepage
|
||||
% \clearpage
|
||||
|
||||
% The lof/lot linespacing should match the lol linespacing
|
||||
\setlength{\cftparskip}{2pt}
|
||||
@ -339,24 +314,24 @@
|
||||
\ifthenelse{\equal{\@listoftablesenabled}{true}}
|
||||
{%
|
||||
\listoftables
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
\cleardoublepage
|
||||
% \clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@listoffiguresenabled}{true}}
|
||||
{%
|
||||
\listoffigures
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
\cleardoublepage
|
||||
% \clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
\ifthenelse{\equal{\@listofalgorithmsenabled}{true}}
|
||||
{%
|
||||
\listofalgorithms
|
||||
%\cleardoublepage
|
||||
\clearpage
|
||||
\cleardoublepage
|
||||
% \clearpage
|
||||
}%
|
||||
{}
|
||||
|
||||
@ -439,7 +414,6 @@
|
||||
|
||||
\newcommand{\literature}
|
||||
{
|
||||
% Why is this here twice?
|
||||
% \bibliography{\literaturebibtexdatei}
|
||||
% \bibliographystyle{plain}
|
||||
|
||||
|
@ -5,12 +5,10 @@
|
||||
shr ebx, 0x18
|
||||
mov edi, ebx ; Now the ID is in EDI
|
||||
|
||||
; Load the prepared AP GDT
|
||||
; Load the AP's prepared GDT and TSS
|
||||
mov ebx, [boot_ap_gdts - boot_ap + startup_address]
|
||||
mov eax, [ebx + edi * 0x4]
|
||||
lgdt [eax]
|
||||
|
||||
; Load the TSS
|
||||
mov ax, 0x28
|
||||
ltr ax
|
||||
|
||||
|
@ -1,10 +1,5 @@
|
||||
// These variables are located in the startup routine's TEXT section
|
||||
// and exported from smp_boot.asm.
|
||||
|
||||
// Use IDTR from the BSP
|
||||
// Recycle values 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));
|
||||
|
35
code/apic_def.cpp
Normal file
35
code/apic_def.cpp
Normal file
@ -0,0 +1,35 @@
|
||||
// Excerpt from the Apic class definition
|
||||
class Apic {
|
||||
public:
|
||||
// Enabling the APIC subsystem
|
||||
static bool isSupported();
|
||||
static bool isEnabled();
|
||||
static void enable();
|
||||
|
||||
// Enabling SMP
|
||||
static bool isSmpSupported();
|
||||
static void startupSmp();
|
||||
|
||||
// Controlling the current core's local APIC
|
||||
static void initializeCurrentLocalApic();
|
||||
static uint8_t getCpuCount();
|
||||
static LocalApic &getCurrentLocalApic();
|
||||
static void enableCurrentErrorHandler();
|
||||
|
||||
// Controlling the current core's APIC timer
|
||||
static bool isCurrentTimerRunning();
|
||||
static void startCurrentTimer();
|
||||
static ApicTimer &getCurrentTimer();
|
||||
|
||||
// Controlling the current core's interrupts
|
||||
static void allow(InterruptRequest interruptRequest);
|
||||
static void forbid(InterruptRequest interruptRequest);
|
||||
static bool status(InterruptRequest interruptRequest);
|
||||
static void sendEndOfInterrupt(InterruptVector vector);
|
||||
static bool isLocalInterrupt(InterruptVector vector);
|
||||
static bool isExternalInterrupt(InterruptVector vector);
|
||||
|
||||
// Tracking interrupt statistics
|
||||
static void mountVirtualFilesystemNodes();
|
||||
static void countInterrupt(InterruptVector vector);
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
void ApicErrorHandler::trigger(const InterruptFrame &frame) {
|
||||
// Write/read register: Write first, then read
|
||||
void ApicErrorHandler::trigger() {
|
||||
// Writing the ESR updates its contents and arms the interrupt again
|
||||
LocalApic::writeDoubleWord(LocalApic::ESR, 0);
|
||||
uint32_t errors = LocalApic::readDoubleWord(LocalApic::ESR);
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Excerpt from the APIC timer interrupt handler
|
||||
// Excerpt from the ApicTimer interrupt handler
|
||||
void ApicTimer::trigger(const InterruptFrame &frame) {
|
||||
if (cpuId != LocalApic::getId()) {
|
||||
// Abort if the handler doesn't belong to the current CPU
|
||||
@ -7,4 +7,14 @@ void ApicTimer::trigger(const InterruptFrame &frame) {
|
||||
|
||||
// Increase the "core-local" time
|
||||
time.addNanoseconds(timerInterval * 1'000'000); // Interval is in milliseconds
|
||||
|
||||
// Only the BSP may continue
|
||||
if (cpuId != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Trigger preemption
|
||||
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||
System::getService<SchedulerService>().yield();
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
// Excerpt from the "InterruptDispatcher" class
|
||||
void InterruptDispatcher::assign(uint8_t slot, InterruptHandler &isr) {
|
||||
if (handler[slot] == nullptr) {
|
||||
handler[slot] = new Util::ArrayList<InterruptHandler*>;
|
||||
// Excerpt from the "assign" function
|
||||
void InterruptDispatcher::assign(InterruptVector vec, InterruptHandler &handler) {
|
||||
if (handlers[vec] == nullptr) {
|
||||
// Make space for multiple possible interrupt handlers
|
||||
handlers[vec] = new Util::ArrayList<InterruptHandler *>;
|
||||
}
|
||||
|
||||
handler[slot]->add(&isr); // Register an interrupt handler to an interrupt vector
|
||||
handlers[vec]->add(&handler); // Register a handler to a vector
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
// Excerpt from the "dispatch" function
|
||||
interruptDepthWrapper.inc();
|
||||
interruptService.sendEndOfInterrupt(slot); // Signal interrupt servicing
|
||||
asm volatile("sti"); // Allow cascaded interrupts
|
||||
void InterruptDispatcher::dispatch(InterruptVector vec) {
|
||||
interruptService.sendEndOfInterrupt(vec); // 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
|
||||
}
|
||||
auto *handlerList = handlers[vec];
|
||||
for (uint32_t i = 0; i < handlerList->size(); i++) {
|
||||
handlerList->get(i)->trigger(); // Call registered interrupt handlers
|
||||
}
|
||||
|
||||
asm volatile("cli");
|
||||
interruptDepthWrapper.dec();
|
||||
asm volatile("cli");
|
||||
}
|
@ -1,5 +1,7 @@
|
||||
// Excerpt from the "dispatch" function
|
||||
if (interruptService.checkSpuriousInterrupt(slot)) {
|
||||
spuriousCounterWrapper.inc();
|
||||
return; // Early return to skip the calling of any handlers
|
||||
void InterruptDispatcher::dispatch(InterruptVector vec) {
|
||||
if (interruptService.checkSpuriousInterrupt(slot)) {
|
||||
spuriousCounterWrapper.inc();
|
||||
return; // Early return to skip the calling of any handlers
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,6 @@
|
||||
// Excerpt from the "InterruptHandler" class definition
|
||||
// Excerpt from the "InterruptHandler" interface
|
||||
class InterruptHandler {
|
||||
public:
|
||||
virtual void plugin() = 0; // Register the handler
|
||||
virtual void trigger(const InterruptFrame &frame) = 0; // Handle an interrupt
|
||||
virtual void trigger(const InterruptFrame &frame) = 0; // Handle an interrupt
|
||||
};
|
||||
|
5
code/ioapic_allow.cpp
Normal file
5
code/ioapic_allow.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
void IoApic::allow(GlobalSystemInterrupt gsi) {
|
||||
REDTBLEntry redtblEntry = readREDTBL(gsi);
|
||||
redtblEntry.isMasked = false;
|
||||
writeREDTBL(gsi, redtblEntry);
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
struct IrqOverride {
|
||||
InterruptRequest source;
|
||||
GlobalSystemInterrupt target;
|
||||
InterruptRequest source;
|
||||
GlobalSystemInterrupt target;
|
||||
REDTBLEntry::PinPolarity polarity;
|
||||
REDTBLEntry::TriggerMode trigger;
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
void Pit::trigger(const InterruptFrame &frame) {
|
||||
void Pit::trigger() {
|
||||
time.addNanoseconds(timerInterval); // Increase system time
|
||||
|
||||
// Don't use PIT for scheduling when the APIC timer is enabled
|
||||
|
12
code/pit_early_delay.cpp
Normal file
12
code/pit_early_delay.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// Excerpt from the "earlyDelay" function
|
||||
void Pit::earlyDelay(uint16_t us) {
|
||||
uint32_t counter = (static_cast<double>(BASE_FREQUENCY) / 1'000'000) * us;
|
||||
|
||||
controlPort.writeByte(0b110000); // Channel 0, mode 0
|
||||
dataPort0.writeByte(static_cast<uint8_t>(counter & 0xFF)); // Low byte
|
||||
dataPort0.writeByte(static_cast<uint8_t>((counter >> 8) & 0xFF)); // High byte
|
||||
|
||||
do {
|
||||
controlPort.writeByte(0b11100010); // Readback channel 0
|
||||
} while (!(dataPort0.readByte() & (1 << 7))); // Bit 7 is the output pin state
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
// Excerpt from the "Pit" interrupt handler
|
||||
void Pit::trigger(const InterruptFrame &frame) {
|
||||
void Pit::trigger() {
|
||||
time.addNanoseconds(timerInterval); // Increase system time
|
||||
|
||||
// Trigger preemption
|
||||
if (time.toMilliseconds() % yieldInterval == 0) {
|
||||
System::getService<SchedulerService>().yield(); // Trigger preemption
|
||||
}
|
||||
|
@ -1,9 +1,12 @@
|
||||
// Excerpt from System::initializeSystem(). Located before interrupts
|
||||
// are enabled and any devices have registered their handlers.
|
||||
if (Apic::isSupported()) {
|
||||
Apic::enable();
|
||||
// Excerpt from the "initializeSystem" function
|
||||
void System::initializeSystem() {
|
||||
if (Apic::isSupported()) {
|
||||
Apic::enable();
|
||||
|
||||
if (Apic::isSmpSupported()) {
|
||||
Apic::startupSmp();
|
||||
if (Apic::isSmpSupported()) {
|
||||
Apic::startupSmp();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Cpu::enableInterrupts();
|
||||
}
|
||||
|
58
diagrams/apic_enable_seq.puml
Normal file
58
diagrams/apic_enable_seq.puml
Normal file
@ -0,0 +1,58 @@
|
||||
@startuml
|
||||
'https://plantuml.com/sequence-diagram
|
||||
|
||||
title Apic::enable()
|
||||
|
||||
participant Apic
|
||||
participant Acpi
|
||||
participant LocalApic
|
||||
participant IoApic
|
||||
participant ApicErrorHandler
|
||||
participant ApicTimer
|
||||
|
||||
==Prepare Initialization==
|
||||
|
||||
group Create Devices
|
||||
Apic -[hidden]> ApicTimer
|
||||
Apic -> Acpi: Request system information
|
||||
Apic <- Acpi: Provide MADT structures
|
||||
Apic -> LocalApic ++: Instantiate LocalApic
|
||||
Apic -> IoApic ++: Instantiate IoApic
|
||||
end
|
||||
|
||||
group Initialize Local APIC
|
||||
Apic -[hidden]> ApicTimer
|
||||
Apic -> LocalApic: Enable xApic mode
|
||||
LocalApic -> LocalApic: Set IMCR
|
||||
LocalApic -> LocalApic: MMIO allocation
|
||||
==Actual Component Initialization==
|
||||
Apic -> LocalApic: Initialize current local APIC
|
||||
LocalApic -> LocalApic: Set LVT and NMI
|
||||
LocalApic -> LocalApic: Set spurious vector
|
||||
LocalApic -> LocalApic: Synchronize APR
|
||||
LocalApic -> LocalApic: Allow all priorities
|
||||
end
|
||||
|
||||
group Initialize I/O APIC
|
||||
Apic -[hidden]> ApicTimer
|
||||
Apic -> IoApic: Initialize I/O APIC
|
||||
IoApic -> IoApic: MMIO allocation
|
||||
IoApic -> IoApic: Set REDTBL, NMI
|
||||
end
|
||||
|
||||
group Initialize APIC error handler
|
||||
Apic -[hidden]> ApicTimer
|
||||
Apic -> ApicErrorHandler ++: Instantiate handler
|
||||
Apic -> ApicErrorHandler: Register the interrupt handler
|
||||
Apic -> LocalApic: Allow current error interrupt
|
||||
Apic -> LocalApic: Arm error interrupt
|
||||
end
|
||||
|
||||
group Initialize APIC timer
|
||||
Apic -[hidden]> ApicTimer
|
||||
Apic -> ApicTimer: Calibrate the timer
|
||||
Apic -> ApicTimer ++: Instantiate current timer
|
||||
Apic -> ApicTimer: Register current interrupt handler
|
||||
LocalApic <- ApicTimer: Allow current timer interrupt
|
||||
end
|
||||
@enduml
|
1
diagrams/apic_enable_seq.svg
Normal file
1
diagrams/apic_enable_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 20 KiB |
44
diagrams/apic_smp_enable_seq.puml
Normal file
44
diagrams/apic_smp_enable_seq.puml
Normal file
@ -0,0 +1,44 @@
|
||||
@startuml
|
||||
'https://plantuml.com/sequence-diagram
|
||||
|
||||
title Apic::startupSmp() for a single AP
|
||||
footer The Application Processor lifetime symbolizes the AP's expected online state for the xApic architecture.
|
||||
|
||||
participant Apic
|
||||
participant GDT as "AP GDT"
|
||||
participant Stack as "AP Stack"
|
||||
participant 0x8000 as "AP Boot Routine"
|
||||
participant LocalApic
|
||||
participant smp_entry as "Application Processor"
|
||||
|
||||
Apic -> GDT ++: Prepare AP GDT
|
||||
Apic -> Stack ++: Allocate AP stack
|
||||
|
||||
group Prepare AP Boot Routine
|
||||
Apic -[hidden]> smp_entry
|
||||
Apic -> 0x8000 ++: Allocate physical memory at 0x8000
|
||||
Apic -> Apic: Initialize smp_boot variables
|
||||
Apic -> 0x8000: Copy smp_boot to 0x8000
|
||||
end
|
||||
|
||||
Apic -> Apic: Prepare warm reset
|
||||
|
||||
group Universal Startup Algorithm
|
||||
Apic -> LocalApic: Send INIT IPI
|
||||
LocalApic -> smp_entry: INIT
|
||||
...10 ms...
|
||||
Apic -> LocalApic: Send SIPI
|
||||
LocalApic -> smp_entry ++: STARTUP
|
||||
...200 us...
|
||||
Apic -> LocalApic: Send SIPI
|
||||
LocalApic -> smp_entry: STARTUP
|
||||
...200 us...
|
||||
end
|
||||
|
||||
Apic <- smp_entry: Initialize AP's local APIC
|
||||
Apic <- smp_entry: Initialize AP's APIC timer
|
||||
Apic <- smp_entry: Initialize AP's APIC error handler
|
||||
Apic <- smp_entry: Signal boot completion
|
||||
Apic -> 0x8000 !!: Free physical memory at 0x8000
|
||||
|
||||
@enduml
|
1
diagrams/apic_smp_enable_seq.svg
Normal file
1
diagrams/apic_smp_enable_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 28 KiB |
19
diagrams/interrupt_seq.puml
Normal file
19
diagrams/interrupt_seq.puml
Normal file
@ -0,0 +1,19 @@
|
||||
@startuml
|
||||
'https://plantuml.com/sequence-diagram
|
||||
|
||||
title Interrupt Handler Execution
|
||||
footer The lifetimes symbolize the current code execution by the CPU.
|
||||
|
||||
participant main as "Main Thread"
|
||||
participant handler as "Interrupt Handler"
|
||||
|
||||
==Interrupt Request==
|
||||
activate main
|
||||
main -> handler --: Switch context to interrupt handler
|
||||
activate handler
|
||||
handler -> handler: Handle the interrupt
|
||||
main <- handler --: Switch back to previous context
|
||||
activate main
|
||||
==Interrupt Handled==
|
||||
|
||||
@enduml
|
1
diagrams/interrupt_seq.svg
Normal file
1
diagrams/interrupt_seq.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.4 KiB |
152
glossary.tex
152
glossary.tex
@ -1,10 +1,10 @@
|
||||
\makeglossaries
|
||||
\makeglossaries{}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Acronyms
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
|
||||
\newacronym{acpi}{ACPI}{\gls{advanced configuration and power interface}}
|
||||
\newacronym{acpi}{ACPI}{advanced configuration and power interface}
|
||||
\newacronym{aml}{AML}{acpi machine language}
|
||||
\newacronym{ap}{AP}{\gls{application processor}}
|
||||
\newacronym{apr}{APR}{arbitration priority register}
|
||||
@ -12,7 +12,7 @@
|
||||
\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{eoi}{EOI}{end of interrupt}
|
||||
\newacronym{esr}{ESR}{error status register}
|
||||
\newacronym{gdt}{GDT}{global descriptor table}
|
||||
\newacronym{gdtr}{GDTR}{global descriptor table register}
|
||||
@ -34,14 +34,14 @@
|
||||
\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{nmi}{NMI}{non-maskable interrupt}
|
||||
\newacronym{pci}{PCI}{peripheral component interconnect}
|
||||
\newacronym{pic}{PIC}{programmable interrupt controller}
|
||||
\newacronym{pit}{PIT}{\gls{programmable interval timer}}
|
||||
\newacronym{pit}{PIT}{programmable interval timer}
|
||||
\newacronym{redtbl}{REDTBL}{redirection table}
|
||||
\newacronym{sipi}{SIPI}{startup inter-processor interrupt}
|
||||
\newacronym{smi}{SMI}{system management interrupt}
|
||||
\newacronym{smp}{SMP}{\gls{symmetric multiprocessing}}
|
||||
\newacronym{smp}{SMP}{symmetric multiprocessing}
|
||||
\newacronym{svr}{SVR}{\gls{spurious interrupt vector register}}
|
||||
\newacronym{tmr}{TMR}{trigger-mode register}
|
||||
\newacronym{tpr}{TPR}{\gls{task-priority register}}
|
||||
@ -57,187 +57,107 @@
|
||||
% 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}{
|
||||
\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}{
|
||||
\newglossaryentry{application processor}{%
|
||||
name={application processor},
|
||||
description={a processor inside an SMP system, e.g. a CPU core}
|
||||
description={a processor inside an SMP system, e.g.\ a CPU core}
|
||||
}
|
||||
\newglossaryentry{bootstrap processor}{
|
||||
\newglossaryentry{bootstrap processor}{%
|
||||
name={bootstrap processor},
|
||||
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{discrete apic}{%
|
||||
name={discrete APIC},
|
||||
description={the predecessor of the xApic architecture where the local APIC was not integrated into the CPU core, register access is handled through MMIO}
|
||||
}
|
||||
\newglossaryentry{end-of-interrupt}{
|
||||
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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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},
|
||||
\newglossaryentry{irq override}{%
|
||||
name={interrupt override},
|
||||
description={information from ACPI, that describes how interrupt lines correspond to global system interrupts}
|
||||
}
|
||||
\newglossaryentry{local apic}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\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}{
|
||||
\newglossaryentry{virtual wire mode}{%
|
||||
name={virtual wire mode},
|
||||
description={use the local APIC in combination with the PIC as external interrupt controller}
|
||||
}
|
||||
\newglossaryentry{xapic}{
|
||||
\newglossaryentry{xapic}{%
|
||||
name={xApic},
|
||||
description={a revision of the APIC architecture, register access is handled through MMIO}
|
||||
}
|
||||
\newglossaryentry{x2apic}{
|
||||
\newglossaryentry{x2apic}{%
|
||||
name={x2Apic},
|
||||
description={a revision of the APIC architecture, register access is handled through MSRs}
|
||||
}
|
||||
|
1
img/ApicTimerHandler.drawio
Normal file
1
img/ApicTimerHandler.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2023-03-01T15:38:29.975Z" agent="5.0 (X11)" etag="lMw5qLzuehWTyToD7hYz" version="20.8.23"><diagram name="Page-1" id="GcggYPQxszAjPQo6ng4k">7Vlbk5owFP41Pm6Hm0gfV9deZmzHGbrT7r5FOEJaIGwIiv31TTAR2VSHzlahnX0RzpeT2/nO+Qg4smdp9Z6iPP5EQkhGlhFWI/tuZFnmxLH4RSA7iRiOs0ciikOJNYCPf4JylGiJQyhajoyQhOG8DQYkyyBgLQxRSrZttzVJ2rPmKAIN8AOU6OhXHLJ4j3pjo8E/AI5iNbNpyJYUKWcJFDEKyfYIsucje0YJYfu7tJpBIqKn4rLv9+5E62FhFDLWpcN8+fS4cJeeT9Z2Wr1d3htT/0aSUbCd2jCEfP/SJJTFJCIZSuYNOqWkzEIQoxrcanwWhOQcNDn4HRjbSTJRyQiHYpYmspUvmO6+if5vxsp8kMPVxl3VsnbSWpOMyUFNj9v7tYsFnwyJhApS0gDOxEGlFqIRsDN+1oE4nvJAUuDr4/0oJIjhTXsdSKZedPBr2OE3kqA/IEuOu0FJKWcaWW7ClzsN8abFovtUirSqI3ZT1CG75Q6ml1d13FQ7v4vEdUF4xov94xSoWEbGgNIyZ2qCFVWuCuE7qGdV6LM0apJEML6NMQM/RzUHWy4V7YT4PbEboAyq89TqVMgOlqpDJTyutLdNFZuqNOOjClZ+f529ycXY+0w6knLV2m5VdlPo169tq2Ntu73WtqGlxwN/7r2UweIHsCD+r6S6K51en3RaGptfpLSuICFZVNTnGP4zW96f0U5jENpp9a6drhbO2xXP5sE9dZzBRc60eteQC2qB11ELzBO0XUcMPC17P2YBhVRsV7y5ULgRB6/B68Ahu/vLZkcLpTj8DOYhOZgzj9n1hca0ez316ML+eup5IaHjXgnV31FPHHym/nLwgjfuX/Dsf/TkM4DQea86ckoeuujIpFcdGes6QnEU1UqSU4A0Z5hkg1cQ1+m9DPTvTsNUkOehm1wwdNxsPrzXbUf/X9jzXw==</diagram></mxfile>
|
1224
img/ApicTimerHandler.svg
Normal file
1224
img/ApicTimerHandler.svg
Normal file
File diff suppressed because it is too large
Load Diff
After Width: | Height: | Size: 62 KiB |
1
img/Architecture.drawio
Normal file
1
img/Architecture.drawio
Normal file
@ -0,0 +1 @@
|
||||
<mxfile host="app.diagrams.net" modified="2023-03-02T13:45:01.329Z" agent="5.0 (X11)" etag="-uXxVCLlOb1aSAnoL_Ac" version="20.8.23" type="device"><diagram name="Page-1" id="GcggYPQxszAjPQo6ng4k">7VlNc5swEP01HNNBCGN6xB9JPE2bdpJJm95kUIAOICKEgfz6CiwZGGzXTW1DOjnBvl2k1Vu9xcgKnIb5FUWx95k4OFA01ckVOFM0DYx1jV9KpBCIqutrxKW+I7AauPNfsAwUaOo7OGkFMkIC5sdt0CZRhG3WwhClJGuHPZGgPWuMXNwB7mwUdNHvvsO8NWqO1Bq/xr7ryZmBKjwhksECSDzkkKwBwbkCp5QQtr4L8ykOSvYkL+vnLnd4N4lRHLFDHpgby2/3S+MhTyd+oYfP1s/i4UKMskJBKhZ8Q/jiOWR9XUz55RpRJ+NziDWwQhJDSRo5uBwbKHCSeT7DdzGyS2/G9wLHPBYGwv1EIiZqC0xud3OXiWDKcN6AxFquMAkxowUPEV4oeRU7a2wIO6vLBGSM1yiRjENiZ7iboWvy+I3g72+4HHdIwg7fTMIklHnEJREK5jU6qWlUuVXH3BASC/J+YcYKwR5KGXkltQlJqY335C+kyhB1MfvzninXtrdQFAeI+au2kI7OutbZwYpmBDz/ieOvWtUwntNSaxVjF0lFmcUDgBnnFW/Sz+/c8lopwYp9Ww7I86vGXLuPNc00QEmya4qdolMHITqjf9F97EN0nEFa/BDPV8ZjaXwYSXOWN52zQljHEys8UKxaX2J1LevFhSGyUHybe5emk8MvMpu+ilXX57FVnu3F2src0aq1lZ9eOyk8WSddkDO30SX9p7HeSDcGxtC68ea3bj8CB0pP3Vgfejfel/UJBF/K/d4PMX3X/JE1r5tD03wvP8BeL1XzQKnCQUkV9NJYT8/ysBoiAP8ny/qgWDZP+tp5f+Oc+Jt/1PsbB8C3JVNw6MmaOSidyrQbQv2EaVSe8A/8LFg/5xbd/SHfom7Bx7lVznKu3iFuC70Hf1Se8lydm/X/H5Wv8TcSnP8G</diagram></mxfile>
|
File diff suppressed because it is too large
Load Diff
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 49 KiB |
@ -6,7 +6,7 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Schlüsselwörter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\thesiskeywords{Interrupt,APIC,hhuOS}
|
||||
\thesiskeywords{x86, Interrupt, APIC, hhuOS}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Sprache der Arbeit %
|
||||
@ -31,12 +31,9 @@
|
||||
% true - Aktiviert %
|
||||
% false - Deaktiviert %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\glossaryenabled{true}
|
||||
\listofalgorithmsenabled{false}
|
||||
\listoffiguresenabled{true}
|
||||
\listoftablesenabled{true}
|
||||
\hidefigures{false}
|
||||
\hidecode{false}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Vollständiger Name %
|
||||
@ -51,19 +48,19 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Datum der Abgabe %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\submissiondate{March 15th, 2023}
|
||||
\submissiondate{March 3rd, 2023}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Erstgutachter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\firstreviewer{Prof. Dr. Michael Schöttner}
|
||||
\firstreviewer{Prof.\ Dr.\ Michael Schöttner}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Zweitgutachter %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\secondreviewer{Prof. Dr. Stefan Conrad}
|
||||
\secondreviewer{Prof.\ Dr.\ Stefan Conrad}
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Betreuer %
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
\supervisor{M.Sc. Fabian Ruhland}
|
||||
\supervisor{M.Sc.\ Fabian Ruhland}
|
||||
|
41
thesis.tex
41
thesis.tex
@ -1,7 +1,7 @@
|
||||
% !TeX document-id = {631e44a8-cd91-47da-bf82-1571f8787194}
|
||||
% !TeX TXS-program:compile = txs:///pdflatex/[--shell-escape]
|
||||
|
||||
\documentclass{class/thesis}
|
||||
\documentclass{class/thesis} % [draft]
|
||||
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
% Bitte ergänzen Sie Ihre persönlichen Daten innerhalb %
|
||||
@ -12,34 +12,33 @@
|
||||
\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}
|
||||
|
||||
% Detect overfull boxes % TODO: Should probably disable this before submitting
|
||||
% \overfullrule=2cm
|
||||
|
||||
% Capitalize all the section names
|
||||
\renewcommand{\figureautorefname}{Figure}
|
||||
\renewcommand{\tableautorefname}{Table}
|
||||
\renewcommand{\partautorefname}{Part}
|
||||
\renewcommand{\appendixautorefname}{Appendix}
|
||||
\renewcommand{\chapterautorefname}{Chapter}
|
||||
\renewcommand{\sectionautorefname}{Section}
|
||||
\renewcommand{\subsectionautorefname}{Section}
|
||||
\renewcommand{\subsubsectionautorefname}{Section}
|
||||
\makeatletter\newcommand{\tcb@cnt@codeblockautorefname}{Listing}\makeatother
|
||||
|
||||
% Chapters
|
||||
\include{chap/introduction}
|
||||
\include{chap/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}
|
||||
\include{chap/listings}
|
||||
\include{chap/figures}
|
||||
\include{chap/tables}
|
||||
\end{appendices}
|
||||
|
||||
\end{thesis}
|
||||
|
||||
\end{document}
|
||||
\end{document}
|
Reference in New Issue
Block a user