hw: remove duplicated definition of x86 local APIC

Ref genodelabs/genode#5310
This commit is contained in:
Stefan Kalkowski 2024-04-25 13:40:57 +02:00 committed by Christian Helmuth
parent 6889959f59
commit 7770285aed
4 changed files with 90 additions and 83 deletions

View File

@ -20,6 +20,7 @@
#include <multiboot2.h>
#include <hw/spec/x86_64/acpi.h>
#include <hw/spec/x86_64/apic.h>
using namespace Genode;
@ -274,57 +275,28 @@ Bootstrap::Platform::Board::Board()
}
struct Lapic : Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
static inline
void ipi_to_all(Hw::Local_apic &lapic, unsigned const boot_frame,
Hw::Local_apic::Icr_low::Delivery_mode::Mode const mode)
{
struct Svr : Register<0x0f0, 32>
{
struct APIC_enable : Bitfield<8, 1> { };
};
using Icr_low = Hw::Local_apic::Icr_low;
struct Icr_low : Register<0x300, 32>
{
struct Vector : Bitfield< 0, 8> { };
struct Delivery_mode : Bitfield< 8, 3>
{
enum Mode { INIT = 5, SIPI = 6 };
};
struct Delivery_status : Bitfield<12, 1> { };
struct Level_assert : Bitfield<14, 1> { };
struct Dest_shorthand : Bitfield<18, 2>
{
enum { ALL_OTHERS = 3 };
};
};
struct Icr_high : Register<0x310, 32>
{
struct Destination : Bitfield<24, 8> { };
};
Lapic(addr_t const addr) : Mmio({(char *)addr, Mmio::SIZE}) { }
};
static inline void ipi_to_all(Lapic &lapic, unsigned const boot_frame,
Lapic::Icr_low::Delivery_mode::Mode const mode)
{
/* wait until ready */
while (lapic.read<Lapic::Icr_low::Delivery_status>())
while (lapic.read<Icr_low::Delivery_status>())
asm volatile ("pause":::"memory");
unsigned const apic_cpu_id = 0; /* unused for IPI to all */
Lapic::Icr_low::access_t icr_low = 0;
Lapic::Icr_low::Vector::set(icr_low, boot_frame);
Lapic::Icr_low::Delivery_mode::set(icr_low, mode);
Lapic::Icr_low::Level_assert::set(icr_low);
Lapic::Icr_low::Level_assert::set(icr_low);
Lapic::Icr_low::Dest_shorthand::set(icr_low, Lapic::Icr_low::Dest_shorthand::ALL_OTHERS);
Icr_low::access_t icr_low = 0;
Icr_low::Vector::set(icr_low, boot_frame);
Icr_low::Delivery_mode::set(icr_low, mode);
Icr_low::Level_assert::set(icr_low);
Icr_low::Level_assert::set(icr_low);
Icr_low::Dest_shorthand::set(icr_low, Icr_low::Dest_shorthand::ALL_OTHERS);
/* program */
lapic.write<Lapic::Icr_high::Destination>(apic_cpu_id);
lapic.write<Lapic::Icr_low>(icr_low);
lapic.write<Hw::Local_apic::Icr_high::Destination>(apic_cpu_id);
lapic.write<Icr_low>(icr_low);
}
@ -356,11 +328,11 @@ unsigned Bootstrap::Platform::enable_mmu()
Cpu::IA32_apic_base::Lapic::set(lapic_msr);
Cpu::IA32_apic_base::write(lapic_msr);
Lapic lapic(board.core_mmio.virt_addr(Hw::Cpu_memory_map::lapic_phys_base()));
Hw::Local_apic lapic(board.core_mmio.virt_addr(Hw::Cpu_memory_map::lapic_phys_base()));
/* enable local APIC if required */
if (!lapic.read<Lapic::Svr::APIC_enable>())
lapic.write<Lapic::Svr::APIC_enable>(true);
if (!lapic.read<Hw::Local_apic::Svr::APIC_enable>())
lapic.write<Hw::Local_apic::Svr::APIC_enable>(true);
/* reset assembly counter (crt0.s) by last booted CPU, required for resume */
if (__cpus_booted >= board.cpus)
@ -377,12 +349,15 @@ unsigned Bootstrap::Platform::enable_mmu()
/* BSP - we're primary CPU - wake now all other CPUs */
/* see Intel Multiprocessor documentation - we need to do INIT-SIPI-SIPI */
ipi_to_all(lapic, 0 /* unused */, Lapic::Icr_low::Delivery_mode::INIT);
ipi_to_all(lapic, 0 /* unused */,
Hw::Local_apic::Icr_low::Delivery_mode::INIT);
/* wait 10 ms - debates ongoing whether this is still required */
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI);
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12,
Hw::Local_apic::Icr_low::Delivery_mode::SIPI);
/* wait 200 us - debates ongoing whether this is still required */
/* debates ongoing whether the second SIPI is still required */
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12, Lapic::Icr_low::Delivery_mode::SIPI);
ipi_to_all(lapic, AP_BOOT_CODE_PAGE >> 12,
Hw::Local_apic::Icr_low::Delivery_mode::SIPI);
return (unsigned)cpu_id;
}

View File

@ -39,7 +39,7 @@ enum {
Local_interrupt_controller::
Local_interrupt_controller(Global_interrupt_controller &global_irq_ctrl)
:
Mmio { {(char *)Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()), Mmio::SIZE} },
Local_apic({Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base())}),
_global_irq_ctrl { global_irq_ctrl }
{
init();

View File

@ -17,6 +17,7 @@
/* Genode includes */
#include <util/mmio.h>
#include <hw/spec/x86_64/apic.h>
#include <hw/spec/x86_64/x86_64.h>
namespace Board {
@ -148,43 +149,10 @@ class Board::Global_interrupt_controller : public Genode::Mmio<Hw::Cpu_memory_ma
};
class Board::Local_interrupt_controller : public Genode::Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
class Board::Local_interrupt_controller : private Hw::Local_apic
{
private:
/*
* Registers
*/
struct Id : Register<0x020, 32> { };
struct EOI : Register<0x0b0, 32, true> { };
struct Svr : Register<0x0f0, 32>
{
struct APIC_enable : Bitfield<8, 1> { };
};
/*
* ISR register, see Intel SDM Vol. 3A, section 10.8.4.
*
* Each of the 8 32-bit ISR values is followed by 12 bytes of padding.
*/
struct Isr : Register_array<0x100, 32, 8 * 4, 32> { };
/*
* Interrupt control register
*/
struct Icr_low : Register<0x300, 32, true>
{
struct Vector : Bitfield< 0, 8> { };
struct Delivery_status : Bitfield<12, 1> { };
struct Level_assert : Bitfield<14, 1> { };
};
struct Icr_high : Register<0x310, 32, true>
{
struct Destination : Bitfield<24, 8> { };
};
Global_interrupt_controller &_global_irq_ctrl;
/**

View File

@ -0,0 +1,64 @@
/*
* \brief APIC definitions
* \author Stefan Kalkowski
* \date 2024-04-25
*/
/*
* Copyright (C) 2024 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_
#define _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_
namespace Hw { class Local_apic; }
#include <hw/spec/x86_64/x86_64.h>
struct Hw::Local_apic : Genode::Mmio<Hw::Cpu_memory_map::LAPIC_SIZE>
{
struct Id : Register<0x020, 32> { };
struct EOI : Register<0x0b0, 32, true> { };
struct Svr : Register<0x0f0, 32>
{
struct APIC_enable : Bitfield<8, 1> { };
};
/*
* ISR register, see Intel SDM Vol. 3A, section 10.8.4.
*
* Each of the 8 32-bit ISR values is followed by 12 bytes of padding.
*/
struct Isr : Register_array<0x100, 32, 8 * 4, 32> { };
/*
* Interrupt control register
*/
struct Icr_low : Register<0x300, 32, true>
{
struct Vector : Bitfield< 0, 8> { };
struct Delivery_mode : Bitfield< 8, 3>
{
enum Mode { INIT = 5, SIPI = 6 };
};
struct Delivery_status : Bitfield<12, 1> { };
struct Level_assert : Bitfield<14, 1> { };
struct Dest_shorthand : Bitfield<18, 2>
{
enum { ALL_OTHERS = 3 };
};
};
struct Icr_high : Register<0x310, 32, true>
{
struct Destination : Bitfield<24, 8> { };
};
Local_apic(addr_t const addr) : Mmio({(char*)addr, Mmio::SIZE}) {}
};
#endif /* _SRC__INCLUDE__HW__SPEC__X86_64__APIC_H_ */