Commit Graph

3327 Commits

Author SHA1 Message Date
Reto Buerki
c82f5e9269 hw_x86_64: Do not mask edge-triggered interrupts
Do not mask edge-triggered interrupts to avoid losing them while masked,
see Intel 82093AA I/O Advanced Programmable Interrupt Controller
(IOAPIC) specification, section 3.4.2, "Interrupt Mask":

"When this bit is 1, the interrupt signal is masked. Edge-sensitive
interrupts signaled on a masked interrupt pin are ignored (i.e., not
delivered or held pending)"

Or to quote Linus Torvalds on the subject:

"Now, edge-triggered interrupts are a _lot_ harder to mask, because the
Intel APIC is an unbelievable piece of sh*t, and has the edge-detect
logic _before_ the mask logic, so if a edge happens _while_ the device
is masked, you'll never ever see the edge ever again (unmasking will not
cause a new edge, so you simply lost the interrupt)."

So when you "mask" an edge-triggered IRQ, you can't really mask it at
all, because if you did that, you'd lose it forever if the IRQ comes in
while you masked it. Instead, we're supposed to leave it active, and set
a flag, and IF the IRQ comes in, we just remember it, and mask it at
that point instead, and then on unmasking, we have to replay it by
sending a self-IPI." [1]

[1] - http://yarchive.net/comp/linux/edge_triggered_interrupts.html

Ref #1448
2015-03-27 11:53:34 +01:00
Martin Stein
bfe1fac37c hw_x86_64: style fixes
Ref #1448
2015-03-27 11:53:34 +01:00
Stefan Kalkowski
49bffbfe7e os: enable PIT timer for hw_x86_64 platform 2015-03-27 11:53:34 +01:00
Adrian-Ken Rueegsegger
f4cb9101a4 hw: Fix format string for 64 bit platforms
Use the format specifier of the largest possible type and cast the value
to the chosen type. This avoids compiler warnings on x86_64.
2015-03-27 11:53:33 +01:00
Reto Buerki
92efc13a17 hw_x86_64: Add x86-specific IRQ session component
In order to match the I/O APIC configuration, a request for user timer
IRQ 0 is remapped to vector 50 (Board::TIMER_VECTOR_USER), all other
requests are transposed by adding the vector offset 48
(Board::VECTOR_REMAP_BASE).
2015-03-27 11:53:33 +01:00
Adrian-Ken Rueegsegger
f9f74d2930 hw_x86_64: Add VESA resources to x86 MMIO regions
The additional MMIO regions are necessary for emulated graphics devices
of QEMU and Bochs.
2015-03-27 11:53:33 +01:00
Adrian-Ken Rueegsegger
8b8e8c8270 hw_x86_64: Add various drivers to x86
Include PCI, PS2, VESA and Framebuffer drivers on x86_64 platform.
2015-03-27 11:53:33 +01:00
Adrian-Ken Rueegsegger
e5f26fa8db base: Raise RAM quota of signal session to 16K
On base-hw/x86_64 the quota of the signal session is not sufficient due to
the large size of the Signal_session_component. Increasing the quota to
16K avoids signal-context resource exhaustion messages as emmitted by the
run/launcher scenario:

  ...
  Quota exceeded! amount=4096, size=4096, consumed=4096
  failed to allocate signal-context resources
  upgrading quota donation for signal session
  C++ runtime: Genode::Parent::Quota_exceeded
  void* abort(): abort called
  ...

Note: This change increases the quota for all kernels even though it is
      strictly only required for base-hw/x86_64.
2015-03-27 11:53:33 +01:00
Adrian-Ken Rueegsegger
96a3eabe16 hw_x86_64: Log additional information on unknown exception
Provide more information in the log message when an unknown exception
occurs.
2015-03-27 11:53:32 +01:00
Adrian-Ken Rueegsegger
544148bc24 hw_x86_64: Add I/O port allocator to platform
Add the entire I/O port range to the I/O port allocator on x86. Do nothing
on ARM platforms since there are no I/O port resources.
2015-03-27 11:53:32 +01:00
Reto Buerki
5765398741 hw_x86_64: Add x86 platform services to core
Use the x86-specific platform_services.cc file and register the I/O port
session component.
2015-03-27 11:53:32 +01:00
Reto Buerki
28b5e67a8c Update or add hw_x86_64 copyright headers 2015-03-27 11:53:32 +01:00
Adrian-Ken Rueegsegger
ace61c54d6 hw_x86_64: Zero-fill BSS segment in x86_64 crt0.s
Make sure all content of the BSS segment is initialized to zero.
2015-03-27 11:53:32 +01:00
Reto Buerki
69a58c4bd5 hw_x86_64: Set EFLAGS IF, IOPL bits in Cpu::init_thread
Enable interrupts for all threads, set I/O privilege level (IOPL) to 3
for core threads to allow UART access.
2015-03-27 11:53:32 +01:00
Adrian-Ken Rueegsegger
7ce8464b3a hw_x86_64: Enable FPU support
* Enable the use of the FXSAVE and FXRSTOR instructions, see Intel SDM
  Vol. 3C, section 2.5.
* The state of the x87 floating point unit (FPU) is loaded and saved on
  demand.
* Make the cr0 control register accessible in the Cpu class. This is in
  preparation of the upcoming FPU management.
* Access to the FPU is disabled by setting the Task Switch flag in the cr0
  register.
* Access to the FPU is enabled by clearing the Task Switch flag in the cr0
  register.
* Implement FPU initialization
* Add is_fpu_enabled helper function
* Add pointer to CPU lazy state to CPU class
* Init FPU when finishing kernel initialization
* Add function to retry FPU instruction:
    Similar to the ARM mechanism to retry undefined instructions, implement a
    function for retrying an FPU instruction. If a floating-point instruction
    causes an #NM exception due to the FPU being disabled, it can be retried
    after the correct FPU state is restored, saving the current state and
    enabling the FPU in the process.
* Disable FPU when switching to different user context:
    This enables lazy save/restore of the FPU since trying to execute a
    floating point instruction when the FPU is disabled will cause a #NM
    exception.
* Declare constant for #NM exception
* Retry FPU instruction on #NM exception
* Assure alignment of FXSAVE area:
    The FXSAVE area is 512-byte memory region that must be 16-byte aligned. As
    it turns out the alignment attribute is not honored in all cases so add a
    workaround to assure the alignment constraint is met by manually rounding
    the start of the FXSAVE area to the next 16-byte boundary if necessary.
2015-03-27 11:53:31 +01:00
Reto Buerki
c14898703d hw_x86_64: Implement Cpu_idle::exception function
Forward external interrupts during the CPU idle thread to the
_interrupt function.
2015-03-27 11:53:31 +01:00
Reto Buerki
e443b859e6 base: Add x86 RESET pseudo-exception
Define RESET as exception 0xfe. The reset state is only used initially
in the CPU idle exception function.
2015-03-27 11:53:31 +01:00
Reto Buerki
c9c84dd751 base: Move Cpu_exception enum to x86_64 cpu_state.h 2015-03-27 11:53:31 +01:00
Reto Buerki
4e259f7b1e hw_x86_64: Implement LAPIC-based kernel timer
The LAPIC timer is programmed in one-shot mode with vector 32
(Board::TIMER_VECTOR_KERNEL). The timer frequency is measured using PIT
channel 2 as reference (50ms delay).

Disable PIT timer channel 0 since BIOS programs it to fire periodically.
This avoids potential spurious timer interrupts.
2015-03-27 11:53:31 +01:00
Reto Buerki
a21959fc26 hw_x86_64: Implement APIC-based PIC driver
The implementation initializes the Local APIC (LAPIC) of CPU 0 in xapic
mode (mmio register access) and uses the I/O APIC to remap, mask and
unmask hardware IRQs. The remapping offset of IRQs is 48.

Also initialize the legacy PIC and mask all interrupts in order to
disable it.

For more information about LAPIC and I/O APIC see Intel SDM Vol. 3A,
chapter 10 and the Intel 82093AA I/O Advanced Programmable Interrupt
Controller (IOAPIC) specification

Set bit 9 in the RFLAGS register of user CPU context to enable
interrupts on kernel- to usermode switch.
2015-03-27 11:53:31 +01:00
Reto Buerki
557c96a9cb hw_x86_64: Add APIC MMIO to native regions 2015-03-27 11:53:30 +01:00
Reto Buerki
cf100f96af hw_x86_64: Add x86-specific board.h file
The file specifies constants for the LAPIC, I/O APIC MMIO regions plus
the interrupt remapping offset and timer vectors.
2015-03-27 11:53:30 +01:00
Adrian-Ken Rueegsegger
42987a7b2f hw_x86_64: Add mapping for I/O APIC MMIO to initial pt
Make the I/O APIC accessible via its MMIO region by adding a 2 MB large
page mapping at 0xfec00000 with memory type UC.
2015-03-27 11:53:30 +01:00
Adrian-Ken Rueegsegger
c06c21e472 hw_x86_64: Add mapping for APIC MMIO to initial pt
Make the local APIC accessible via its MMIO region by adding a 2 MB
large page mapping at 0xfee00000 with memory type UC.

Note: The mapping is added to the initial page tables to make the APIC
      usable prior to the activation of core's page tables, e.g. in the
      constructor of the timer class.
2015-03-27 11:53:30 +01:00
Reto Buerki
b75b1902f2 hw_x86_64: Provide inb and outb functions for port I/O
The port_io.h file provides the inb and outb functions to perform port
I/O operations.
2015-03-27 11:53:30 +01:00
Reto Buerki
1b3871a3f0 hw_x86_64: Move exception_entry to 0xffff0000
The location in memory is arbitrary but we use the same address as the
ARM architecture. Adjust references to virtual addresses in the mode
transition pages to cope with 64-bit values.
2015-03-27 11:53:30 +01:00
Reto Buerki
147b1ec2b1 hw_x86_64: Adjust parameter type of Message_tpl::prepare_send
Change the type of the local name parameter from unsigned to unsigned
long. Otherwise only 4 bytes are copied on x86_64, leaving 4 bytes of
garbage.
2015-03-27 11:53:29 +01:00
Reto Buerki
16a51b317a hw_x86_64: Implement Cpu_idle::Cpu_idle function
The function is a copy of the ARM version.
2015-03-27 11:53:29 +01:00
Reto Buerki
2ecdf4f729 hw_x86_64: Forward interrupts to _interrupt function
Extend the Thread::exception function to forward external interrupts to
the _interrupt function for processing.
2015-03-27 11:53:29 +01:00
Reto Buerki
d0024e1893 hw_x86_64: Fill _fault_addr from cr2 in _mmu_exception
Use the Cpu::Cr2 register to read the linear page fault address in the
Thread::_mmu_exception function.
2015-03-27 11:53:29 +01:00
Reto Buerki
d553d38ecf hw_x86_64: Model cr2 register in CPU state
Make the cr2 control register accessible in the Cpu class. The register
is needed to retrieve the linear address that caused a page fault.
2015-03-27 11:53:29 +01:00
Reto Buerki
466ad3aed4 hw_x86_64: Implement Thread::_mmu_exception() for x86_64
The function is a copy of the ARM version minus the in_fault
distinction.
2015-03-27 11:53:29 +01:00
Reto Buerki
0992c233bd hw_x86_64: Forward page faults to the _mmu_exception function 2015-03-27 11:53:28 +01:00
Reto Buerki
112ff2609a hw_x86_64: Add Thread::_event implementation
It is an exact copy of the ARM version.
2015-03-27 11:53:28 +01:00
Reto Buerki
83a1b826a3 hw_x86_64: Add supervisor call handling to Thread::exception
Forward supervisor calls to the Thread::_call function for dispatching.
2015-03-27 11:53:28 +01:00
Reto Buerki
0568dcc875 hw_x86_64: Implement Thread::_reg function 2015-03-27 11:53:28 +01:00
Reto Buerki
e5be376f57 hw_x86_64: Declare Thread_reg_id enum for x86_64
Only define IDs of registers which are actually accessed by threads.
2015-03-27 11:53:28 +01:00
Reto Buerki
472c3b6502 hw_x86_64: Use mtc relative addressing for master context 2015-03-27 11:53:28 +01:00
Reto Buerki
080d7d5f8b hw_x86_64: Use mtc relative addressing for _mt_buffer in crt0.s
Until the kernel page tables are active, labels can't be used directly
because the associated pages are not mapped for non-core threads.
2015-03-27 11:53:28 +01:00
Reto Buerki
09c90e5751 hw_x86_64: Set interrupt stack in Tss::Setup 2015-03-27 11:53:27 +01:00
Reto Buerki
9af9dcc02c hw_x86_64: Reserve space for interrupt stack in mtc region
The interrupt stack must reside in the mtc region in order to use it for
non-core threads. The size of the stack is set to 56 bytes in order to
hold the interrupt stack frame plus the additional vector number that is
pushed onto the stack by the ISR.
2015-03-27 11:53:27 +01:00
Reto Buerki
9c44d32dd9 hw_x86_64: Add virt_base paramater to Tss::setup function
The stack pointers (RSP) for privilege levels 0-2 must be setup using an
address in the mtc region to make stack switching work for non-core
threads.
2015-03-27 11:53:27 +01:00
Reto Buerki
15d131b723 hw_x86_64: Use _virt_mtc_addr to calculate ISR base
Call the _virt_mtc_addr function with the _mt_isrs label to calculate
the ISR base address in Idt::setup. Again, assume the address to be
below 0x10000.
2015-03-27 11:53:27 +01:00
Reto Buerki
a5efe04656 hw_x86_64: Add virt_base paramater to Idt::setup function
Use parameter instead of class member variable because it would get
stored into the mtc region otherwise. In a further iteration only the
actual IDT should be saved into the mtc, not the complete class
instance. Currently the class instance size is equal to the IDT table
size.
2015-03-27 11:53:27 +01:00
Reto Buerki
1102b2b562 hw_x86_64: Calculate limit using _mt_gdt_end in Gdt::load 2015-03-27 11:53:27 +01:00
Reto Buerki
6f5ea78a51 hw_x86_64: Prefix gdt labels with _mt
Streamline the naming by prepending the _mt prefix to the gdt labels.
2015-03-27 11:53:26 +01:00
Reto Buerki
69e820e4e3 hw_x86_64: Reload GDTR in Genode::Cpu::init_thread
The GDT reload must happen after the page tables mapping the mtc region
is active, that's why it cannot be done in the Genode::Cpu ctor.
2015-03-27 11:53:26 +01:00
Reto Buerki
968ab15bbb hw_x86_64: Add Genode::Gdt class
The class provides the load() function which reloads the GDTR with the
GDT address in the mtc region. This is needed to make the segments
accessible to non-core threads.

Make the _gdt_start label global to use it in the call to
_virt_mtc_addr().
2015-03-27 11:53:26 +01:00
Reto Buerki
251b270e4b hw_x86_64: Factor out _virt_mtc_addr to mtc_util.h header 2015-03-27 11:53:26 +01:00
Reto Buerki
cfe89996e8 hw_x86_64: Factor out pseudo descriptor class to own header 2015-03-27 11:53:26 +01:00