This patch extends the protection domain framework with an additional
plugin to use Task-State Segment (TSS) structures to offload much of
the work of switching protection domains to the CPU. This can save
space compared to paging, since paging requires two 4KiB page tables
and one 32-byte page table plus one whole-system TSS and an additional
32-byte data structure for each protection domain, whereas the
approach implemented by this patch just requires a 128-byte data
structure for each protection domain. Only a small number of
protection domains will typically be used, so
n * 128 < 8328 + (n * 32).
For additional information, please refer to cpu/x86/mm/README.md.
GCC 6 is introducing named address spaces for the FS and GS segments
[1]. LLVM Clang also provides address spaces for the FS and GS
segments [2]. This patch also adds support to the multi-segment X86
memory management subsystem for using these features instead of inline
assembly blocks, which enables type checking to detect some address
space mismatches.
[1] https://gcc.gnu.org/onlinedocs/gcc/Named-Address-Spaces.html
[2] http://llvm.org/releases/3.3/tools/clang/docs/LanguageExtensions.html#target-specific-extensions
This patch implements a simple, lightweight form of protection domains
using a pluggable framework. Currently, the following plugin is
available:
- Flat memory model with paging.
The overall goal of a protection domain implementation within this
framework is to define a set of resources that should be accessible to
each protection domain and to prevent that protection domain from
accessing other resources. The details of each implementation of
protection domains may differ substantially, but they should all be
guided by the principle of least privilege. However, that idealized
principle is balanced against the practical objectives of limiting the
number of relatively time-consuming context switches and minimizing
changes to existing code.
For additional information, please refer to cpu/x86/mm/README.md.
This patch also causes the C compiler to be used as the default linker
and assembler.
This patch permits interrupts to be generated by both the I2C and GPIO
controllers for simultaneously-executing applications. The controllers
share a single interrupt pin, INTC. Prior to this patch,
quarkX1000_gpio_init() routed INTA to PIRQC and IRQ 10 (due to an
incorrect assumption that INTA is connected to the GPIO controller),
and quarkX1000_i2c_init() routed INTC to PIRQC and IRQ 9. The I2C
controller initialization is a prerequisite for GPIO initialization,
so the final configuration was that INTA and INTC were both routed to
PIRQC and IRQ 10. Thus, only the GPIO ISR was being invoked, even if
the I2C controller was actually responsible for the interrupt.
This patch refactors the I2C and GPIO ISR setup and handler code so
that the shared portions are combined in
cpu/x86/drivers/legacy_pc/shared-isr.[ch]. The I2C and GPIO drivers
communicate their interrupt information to the shared component by
placing structures in a specific section of the binary.
The SET_INTERRUPT_HANDLER macro in interrupt.h used an inline assembly
feature to cause GCC to generate a unique number for a trampoline
label. Clang compiled the code using that feature without generating
any compile-time errors, but it always generated the number 0,
resulting in all interrupt trampolines having the same label names.
This patch replaces the usage of that feature with local labels, which
are supported by both GCC and Clang. See
https://sourceware.org/binutils/docs/as/Symbol-Names.html for an
explanation of local labels.
The SET_INTERRUPT_HANDLER macro defines and registers an interrupt
handler. It outputs a trampoline for the interrupt handler using a
block of inline assembly, and the address of that trampoline is what
is actually placed in the IDT. That trampoline invokes the main body
of the interrupt handler.
This patch adds a missing clobber list to the inline assembly block.
It simply lists the caller-saved registers defined by the cdecl
calling convention: EAX, ECX, and EDX. This is necessary, because the
inline assembly block invokes idt_set_intr_gate_desc using a call
instruction at the time the function containing the
SET_INTERRUPT_HANDLER instance is executed. The
idt_set_intr_gate_desc function is free to clobber EAX, ECX, and EDX
according to cdecl. A Clang-generated implementation of
idt_set_intr_gate_desc did in fact clobber those registers, resulting
in incorrect operation of the code following an instance of
SET_INTERRUPT_HANDLER. The change in this patch informs the compiler
that those registers may be clobbered so that it can adjust the code
that it outputs around the inline assembly block accordingly.
This commit turns cpu_init() into a SoC-agnostic function by
removing any SoC specific calls and isolating them into their
own SoC implementation.
We start this by isolating all IRQs initialization code from
the legacy-pc target, pic_init() and spurious IRQ7 registration,
into a new interface: irq_init() from irq.h. Future SoCs will have
to provide their own implementation of this interface.
This model is to be followed by future initialization code that
we may need to add and which is not common to all x86 SoCs.
The x86/init/common/ folder holds all cpu initialization
code - idt and gdt setup, interrupts and cpu initialization.
On this folder will also sit any SoC specific implementation of
the functions called from cpu_init().