hw: instantiate pic object per cpu

Ref #3520
This commit is contained in:
Stefan Kalkowski 2019-10-09 14:40:30 +02:00 committed by Christian Helmuth
parent d4a3db22bd
commit e3f82b09d7
34 changed files with 105 additions and 115 deletions

View File

@ -47,7 +47,6 @@ class Bootstrap::Platform
Mmio_space const core_mmio;
unsigned cpus { NR_OF_CPUS };
::Board::Boot_info info { };
::Board::Pic pic { };
Board();
};

View File

@ -15,6 +15,7 @@
unsigned Bootstrap::Platform::enable_mmu()
{
::Board::Pic pic { };
::Board::Cpu::Sctlr::init();
::Board::Cpu::enable_mmu_and_caches((addr_t)core_pd->table_base);

View File

@ -118,7 +118,7 @@ unsigned Bootstrap::Platform::enable_mmu()
Actlr::disable_smp();
/* locally initialize interrupt controller */
board.pic.init_cpu_local();
::Board::Pic pic { };
Cpu::invalidate_data_cache();
data_cache_invalidated.inc();

View File

@ -13,8 +13,41 @@
#include <board.h>
void Board::Pic::init_cpu_local()
Hw::Gicv2::Gicv2()
: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
_cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE),
_last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)),
_max_irq(_distr.max_irq())
{
static bool distributor_initialized = false;
if (!distributor_initialized) {
distributor_initialized = true;
/* disable device */
_distr.write<Distributor::Ctlr>(0);
/* configure every shared peripheral interrupt */
for (unsigned i = min_spi; i <= _max_irq; i++) {
if (Board::NON_SECURE) {
_distr.write<Distributor::Igroupr::Group_status>(1, i);
}
_distr.write<Distributor::Icfgr::Edge_triggered>(0, i);
_distr.write<Distributor::Ipriorityr::Priority>(0, i);
_distr.write<Distributor::Icenabler::Clear_enable>(1, i);
}
/* enable device */
Distributor::Ctlr::access_t v = 0;
if (Board::NON_SECURE) {
Distributor::Ctlr::Enable_grp0::set(v, 1);
Distributor::Ctlr::Enable_grp1::set(v, 1);
} else {
Distributor::Ctlr::Enable::set(v, 1);
}
_distr.write<Distributor::Ctlr>(v);
}
if (Board::NON_SECURE) {
_cpui.write<Cpu_interface::Ctlr>(0);
@ -40,34 +73,3 @@ void Board::Pic::init_cpu_local()
}
_cpui.write<Cpu_interface::Ctlr>(v);
}
Hw::Gicv2::Gicv2()
: _distr(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE),
_cpui (Board::Cpu_mmio::IRQ_CONTROLLER_CPU_BASE),
_last_iar(Cpu_interface::Iar::Irq_id::bits(spurious_id)),
_max_irq(_distr.max_irq())
{
/* disable device */
_distr.write<Distributor::Ctlr>(0);
/* configure every shared peripheral interrupt */
for (unsigned i = min_spi; i <= _max_irq; i++) {
if (Board::NON_SECURE) {
_distr.write<Distributor::Igroupr::Group_status>(1, i);
}
_distr.write<Distributor::Icfgr::Edge_triggered>(0, i);
_distr.write<Distributor::Ipriorityr::Priority>(0, i);
_distr.write<Distributor::Icenabler::Clear_enable>(1, i);
}
/* enable device */
Distributor::Ctlr::access_t v = 0;
if (Board::NON_SECURE) {
Distributor::Ctlr::Enable_grp0::set(v, 1);
Distributor::Ctlr::Enable_grp1::set(v, 1);
} else {
Distributor::Ctlr::Enable::set(v, 1);
}
_distr.write<Distributor::Ctlr>(v);
}

View File

@ -1,26 +0,0 @@
/*
* \brief Interrupt controller definitions for ARM
* \author Stefan Kalkowski
* \date 2017-02-22
*/
/*
* Copyright (C) 2017 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__BOOTSTRAP__SPEC__ARM__GICV2_H_
#define _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_
#include <hw/spec/arm/gicv2.h>
namespace Board { struct Pic; }
struct Board::Pic : Hw::Gicv2
{
void init_cpu_local();
};
#endif /* _SRC__BOOTSTRAP__SPEC__ARM__GICV2_H_ */

View File

@ -15,6 +15,7 @@
using Board::Cpu;
extern "C" void * _crt0_enable_fpu;
static inline void prepare_non_secure_world()
{
@ -82,6 +83,12 @@ static inline void prepare_hypervisor()
unsigned Bootstrap::Platform::enable_mmu()
{
static volatile bool primary_cpu = true;
bool primary = primary_cpu;
if (primary) primary_cpu = false;
::Board::Pic pic __attribute__((unused)) {};
while (Cpu::current_privilege_level() > Cpu::Current_el::EL1) {
if (Cpu::current_privilege_level() == Cpu::Current_el::EL3)
prepare_non_secure_world();
@ -89,6 +96,9 @@ unsigned Bootstrap::Platform::enable_mmu()
prepare_hypervisor();
}
/* primary cpu wakes up all others */
if (primary && NR_OF_CPUS > 1) Cpu::wake_up_all_cpus(&_crt0_enable_fpu);
/* enable performance counter for user-land */
Cpu::Pmuserenr_el0::write(0b1111);

View File

@ -17,11 +17,11 @@
#include <hw/spec/arm/arndale_board.h>
#include <hw/spec/arm/lpae.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Arndale_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = true;
}

View File

@ -155,7 +155,9 @@ unsigned Bootstrap::Platform::enable_mmu()
using namespace ::Board;
static volatile bool primary_cpu = true;
board.pic.init_cpu_local();
/* locally initialize interrupt controller */
::Board::Pic pic { };
prepare_nonsecure_world();
prepare_hypervisor((addr_t)core_pd->table_base);

View File

@ -18,11 +18,11 @@
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Imx6q_sabrelite_board;
using Pic = Hw::Gicv2;
struct L2_cache;
static constexpr bool NON_SECURE = false;

View File

@ -17,11 +17,11 @@
#include <hw/spec/arm/imx7d_sabre_board.h>
#include <hw/spec/arm/lpae.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Imx7d_sabre_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = true;
}

View File

@ -287,7 +287,9 @@ unsigned Bootstrap::Platform::enable_mmu()
{
static volatile bool primary_cpu = true;
static unsigned long timer_freq = Cpu::Cntfrq::read();
board.pic.init_cpu_local();
/* locally initialize interrupt controller */
::Board::Pic pic { };
prepare_nonsecure_world(timer_freq);
prepare_hypervisor((addr_t)core_pd->table_base);

View File

@ -24,4 +24,7 @@ Bootstrap::Platform::Board::Board()
Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE,
::Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_SIZE },
Memory_region { ::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE,
::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE }) {}
::Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE })
{
::Board::Pic pic {};
}

View File

@ -18,11 +18,11 @@
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Nit6_solox_board;
using Pic = Hw::Gicv2;
struct L2_cache;
static constexpr bool NON_SECURE = false;

View File

@ -17,10 +17,11 @@
#include <hw/spec/arm/odroid_xu_board.h>
#include <hw/spec/arm/lpae.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Odroid_xu_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = false;
}

View File

@ -25,7 +25,9 @@ Bootstrap::Platform::Board::Board()
unsigned Bootstrap::Platform::enable_mmu()
{
board.pic.init_cpu_local();
/* locally initialize interrupt controller */
::Board::Pic pic { };
Cpu::Sctlr::init();
Cpu::Cpsr::init();
Cpu::invalidate_data_cache();

View File

@ -17,11 +17,11 @@
#include <hw/spec/arm/panda_board.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Panda_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = false;
class L2_cache;

View File

@ -19,11 +19,13 @@
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Pbxa9_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = false;
}

View File

@ -16,10 +16,7 @@
#include <hw/spec/riscv/board.h>
namespace Board {
using namespace Hw::Riscv_board;
struct Pic {};
}
namespace Board { using namespace Hw::Riscv_board; }
template <typename E, unsigned B, unsigned S>
void Sv39::Level_x_translation_table<E, B, S>::_translation_added(addr_t, size_t)

View File

@ -18,11 +18,7 @@
#include <hw/spec/arm/page_table.h>
#include <spec/arm/cpu.h>
namespace Board {
using namespace Hw::Rpi_board;
struct Pic {};
}
namespace Board { using namespace Hw::Rpi_board; }
constexpr unsigned Hw::Page_table::Descriptor_base::_device_tex() {

View File

@ -20,8 +20,13 @@
namespace Board {
using namespace Hw::Rpi3_board;
using Cpu = Hw::Arm_64_cpu;
struct Pic {};
struct Cpu : Hw::Arm_64_cpu
{
static void wake_up_all_cpus(void*);
};
struct Pic { }; /* dummy object */
};
#endif /* _BOOTSTRAP__SPEC__RPI3__BOARD_H_ */

View File

@ -38,6 +38,8 @@ Bootstrap::Platform::Board::Board()
Aipstz aipstz_1(AIPS_1_MMIO_BASE);
Aipstz aipstz_2(AIPS_2_MMIO_BASE);
Pic pic {};
/* set monitor mode exception vector entry */
Cpu::Mvbar::write(Hw::Mm::system_exception_vector().base);

View File

@ -18,11 +18,13 @@
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Wand_quad_board;
using Pic = Hw::Gicv2;
struct L2_cache;
static constexpr bool NON_SECURE = false;

View File

@ -22,7 +22,6 @@
namespace Board {
using namespace Hw::Pc_board;
using Cpu = Hw::X86_64_cpu;
struct Pic {};
}
#endif /* _SRC__BOOTSTRAP__SPEC__X86_64__BOARD_H_ */

View File

@ -18,10 +18,11 @@
#include <spec/arm/cortex_a9_actlr.h>
#include <spec/arm/cortex_a9_page_table.h>
#include <spec/arm/cpu.h>
#include <spec/arm/gicv2.h>
#include <hw/spec/arm/gicv2.h>
namespace Board {
using namespace Hw::Zynq_qemu_board;
using Pic = Hw::Gicv2;
static constexpr bool NON_SECURE = false;
}

View File

@ -157,10 +157,10 @@ addr_t Cpu::stack_start() {
return (addr_t)&kernel_stack + KERNEL_STACK_SIZE * (_id+1); }
Cpu::Cpu(unsigned const id, Board::Pic & pic,
Cpu::Cpu(unsigned const id,
Inter_processor_work_list & global_work_list)
:
_id(id), _pic(pic), _timer(*this),
_id(id), _timer(*this),
_scheduler(&_idle, _quota(), _fill()), _idle(*this),
_ipi_irq(*this),
_global_work_list(global_work_list)
@ -174,7 +174,7 @@ Cpu::Cpu(unsigned const id, Board::Pic & pic,
bool Cpu_pool::initialize()
{
unsigned id = Cpu::executing_id();
_cpus[id].construct(id, _pic, _global_work_list);
_cpus[id].construct(id, _global_work_list);
return --_initialized == 0;
}

View File

@ -112,7 +112,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
unsigned const _id;
Board::Pic &_pic;
Board::Pic _pic {};
Timer _timer;
Cpu_scheduler _scheduler;
Idle_thread _idle;
@ -132,7 +132,7 @@ class Kernel::Cpu : public Genode::Cpu, private Irq::Pool, private Timeout
/**
* Construct object for CPU 'id'
*/
Cpu(unsigned const id, Board::Pic & pic,
Cpu(unsigned const id,
Inter_processor_work_list & global_work_list);
static inline unsigned primary_id() { return 0; }
@ -191,7 +191,6 @@ class Kernel::Cpu_pool
{
private:
Board::Pic _pic {};
Inter_processor_work_list _global_work_list {};
unsigned _count;
unsigned _initialized { _count };

View File

@ -105,8 +105,6 @@ class Kernel::Timer
unsigned interrupt_id() const;
static void init_cpu_local();
time_t time() const { return _time + _duration(); }
};

View File

@ -53,7 +53,6 @@ class Board::Pic : Genode::Mmio
Pic();
void init_cpu_local();
bool take_request(unsigned &irq);
void finish_request() { }
void mask();

View File

@ -17,11 +17,16 @@
using namespace Genode;
static inline Genode::addr_t redistributor_addr()
{
return Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE
+ (Cpu::executing_id() * 0x20000));
};
Hw::Pic::Pic()
: _distr(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_DISTR_BASE)),
_redistr(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE)),
_redistr_sgi(Platform::mmio_to_virt(Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_BASE)
+ Board::Cpu_mmio::IRQ_CONTROLLER_REDIST_SIZE / 2),
_redistr(redistributor_addr()),
_redistr_sgi(redistributor_addr() + 0x10000),
_max_irq(_distr.max_irq())
{
_redistributor_init();

View File

@ -22,8 +22,6 @@ void Kernel::Cpu::_arch_init()
Idt::init();
Tss::init();
Timer::init_cpu_local();
/* enable timer interrupt */
_pic.store_apic_id(id());
_pic.unmask(_timer.interrupt_id(), id());

View File

@ -56,9 +56,6 @@ Board::Timer::Timer(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz()), start(0)
}
void Timer::init_cpu_local() { }
unsigned Timer::interrupt_id() const {
return Board::TIMER_VECTOR_KERNEL; }

View File

@ -75,11 +75,7 @@ Board::Timer::Timer(unsigned)
/* Calculate timer frequency */
ticks_per_ms = pit_calc_timer_freq();
}
}
void Timer::init_cpu_local()
{
/**
* Disable PIT timer channel. This is necessary since BIOS sets up
* channel 0 to fire periodically.

View File

@ -168,9 +168,7 @@ class Hw::Gicv2
Distributor _distr;
Cpu_interface _cpui;
Cpu_interface::Iar::access_t _last_iar;
unsigned const _max_irq;
void _init();
unsigned const _max_irq;
bool _valid(unsigned const irq_id) const { return irq_id <= _max_irq; }

View File

@ -36,7 +36,7 @@ namespace Hw::Imx8q_evk_board {
IRQ_CONTROLLER_DISTR_BASE = 0x38800000,
IRQ_CONTROLLER_DISTR_SIZE = 0x10000,
IRQ_CONTROLLER_REDIST_BASE = 0x38880000,
IRQ_CONTROLLER_REDIST_SIZE = 0x20000, /* per core */
IRQ_CONTROLLER_REDIST_SIZE = 0xc0000,
};
};
};