parent
1cbd77c806
commit
87a6368ba1
|
@ -8,4 +8,6 @@ SRC_S += bootstrap/spec/arm_64/crt0.s
|
||||||
|
|
||||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||||
|
|
||||||
|
NR_OF_CPUS = 4
|
||||||
|
|
||||||
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
include $(BASE_DIR)/../base-hw/lib/mk/bootstrap-hw.inc
|
||||||
|
|
|
@ -2,17 +2,17 @@ INC_DIR += $(REP_DIR)/src/core/spec/rpi3
|
||||||
INC_DIR += $(REP_DIR)/src/core/spec/arm_v8
|
INC_DIR += $(REP_DIR)/src/core/spec/arm_v8
|
||||||
|
|
||||||
# add C++ sources
|
# add C++ sources
|
||||||
SRC_CC += platform_services.cc
|
SRC_CC += kernel/cpu_mp.cc
|
||||||
SRC_CC += kernel/vm_thread_off.cc
|
SRC_CC += kernel/vm_thread_off.cc
|
||||||
SRC_CC += kernel/cpu_up.cc
|
SRC_CC += platform_services.cc
|
||||||
SRC_CC += kernel/lock.cc
|
SRC_CC += spec/64bit/memory_map.cc
|
||||||
SRC_CC += spec/arm_v8/cpu.cc
|
|
||||||
SRC_CC += spec/arm_v8/kernel/thread.cc
|
|
||||||
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
|
||||||
SRC_CC += spec/arm/platform_support.cc
|
|
||||||
SRC_CC += spec/arm/bcm2837_pic.cc
|
SRC_CC += spec/arm/bcm2837_pic.cc
|
||||||
SRC_CC += spec/arm/generic_timer.cc
|
SRC_CC += spec/arm/generic_timer.cc
|
||||||
SRC_CC += spec/64bit/memory_map.cc
|
SRC_CC += spec/arm/kernel/lock.cc
|
||||||
|
SRC_CC += spec/arm/platform_support.cc
|
||||||
|
SRC_CC += spec/arm_v8/cpu.cc
|
||||||
|
SRC_CC += spec/arm_v8/kernel/cpu.cc
|
||||||
|
SRC_CC += spec/arm_v8/kernel/thread.cc
|
||||||
|
|
||||||
#add assembly sources
|
#add assembly sources
|
||||||
SRC_S += spec/arm_v8/exception_vector.s
|
SRC_S += spec/arm_v8/exception_vector.s
|
||||||
|
@ -20,5 +20,7 @@ SRC_S += spec/arm_v8/crt0.s
|
||||||
|
|
||||||
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
vpath spec/64bit/memory_map.cc $(BASE_DIR)/../base-hw/src/lib/hw
|
||||||
|
|
||||||
|
NR_OF_CPUS = 4
|
||||||
|
|
||||||
# include less specific configuration
|
# include less specific configuration
|
||||||
include $(REP_DIR)/lib/mk/core-hw.inc
|
include $(REP_DIR)/lib/mk/core-hw.inc
|
||||||
|
|
|
@ -23,7 +23,7 @@ namespace Board {
|
||||||
|
|
||||||
struct Cpu : Hw::Arm_64_cpu
|
struct Cpu : Hw::Arm_64_cpu
|
||||||
{
|
{
|
||||||
static void wake_up_all_cpus(void*) {}
|
static void wake_up_all_cpus(void*);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Pic { }; /* dummy object */
|
struct Pic { }; /* dummy object */
|
||||||
|
|
|
@ -26,3 +26,12 @@ Bootstrap::Platform::Board::Board()
|
||||||
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
::Board::LOCAL_IRQ_CONTROLLER_SIZE },
|
||||||
Memory_region { ::Board::IRQ_CONTROLLER_BASE,
|
Memory_region { ::Board::IRQ_CONTROLLER_BASE,
|
||||||
::Board::IRQ_CONTROLLER_SIZE }) {}
|
::Board::IRQ_CONTROLLER_SIZE }) {}
|
||||||
|
|
||||||
|
|
||||||
|
extern unsigned int _crt0_qemu_start_secondary_cpus;
|
||||||
|
|
||||||
|
void Board::Cpu::wake_up_all_cpus(void *)
|
||||||
|
{
|
||||||
|
_crt0_qemu_start_secondary_cpus = 1;
|
||||||
|
asm volatile("dsb #0; sev");
|
||||||
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <board.h>
|
#include <board.h>
|
||||||
|
#include <cpu.h>
|
||||||
#include <platform.h>
|
#include <platform.h>
|
||||||
|
|
||||||
|
|
||||||
|
@ -21,41 +22,109 @@ Board::Pic::Pic()
|
||||||
|
|
||||||
bool Board::Pic::take_request(unsigned & irq)
|
bool Board::Pic::take_request(unsigned & irq)
|
||||||
{
|
{
|
||||||
Core0_irq_source::access_t src = read<Core0_irq_source>();
|
unsigned cpu = Genode::Cpu::executing_id();
|
||||||
|
Core_irq_source<0>::access_t src = 0;
|
||||||
|
switch (cpu) {
|
||||||
|
case 0: src = read<Core_irq_source<0>>(); break;
|
||||||
|
case 1: src = read<Core_irq_source<1>>(); break;
|
||||||
|
case 2: src = read<Core_irq_source<2>>(); break;
|
||||||
|
case 3: src = read<Core_irq_source<3>>(); break;
|
||||||
|
}
|
||||||
|
|
||||||
if ((1 << TIMER_IRQ) & src) {
|
if ((1 << TIMER_IRQ) & src) {
|
||||||
irq = TIMER_IRQ;
|
irq = TIMER_IRQ;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (0xf0 & src) {
|
||||||
|
irq = IPI;
|
||||||
|
switch (cpu) {
|
||||||
|
case 0: write<Core_mailbox_clear<0>>(1); break;
|
||||||
|
case 1: write<Core_mailbox_clear<1>>(1); break;
|
||||||
|
case 2: write<Core_mailbox_clear<2>>(1); break;
|
||||||
|
case 3: write<Core_mailbox_clear<3>>(1); break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Pic::mask() { }
|
void Board::Pic::_timer_irq(unsigned cpu, bool enable)
|
||||||
|
{
|
||||||
|
unsigned v = enable ? 1 : 0;
|
||||||
|
switch (cpu) {
|
||||||
|
case 0:
|
||||||
|
write<Core_timer_irq_control<0>::Cnt_p_ns_irq>(v);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
write<Core_timer_irq_control<1>::Cnt_p_ns_irq>(v);
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
write<Core_timer_irq_control<2>::Cnt_p_ns_irq>(v);
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
write<Core_timer_irq_control<3>::Cnt_p_ns_irq>(v);
|
||||||
|
return;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Board::Pic::_ipi(unsigned cpu, bool enable)
|
||||||
|
{
|
||||||
|
unsigned v = enable ? 1 : 0;
|
||||||
|
switch (cpu) {
|
||||||
|
case 0:
|
||||||
|
write<Core_mailbox_irq_control<0>>(v);
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
write<Core_mailbox_irq_control<1>>(v);
|
||||||
|
return;
|
||||||
|
case 2:
|
||||||
|
write<Core_mailbox_irq_control<2>>(v);
|
||||||
|
return;
|
||||||
|
case 3:
|
||||||
|
write<Core_mailbox_irq_control<3>>(v);
|
||||||
|
return;
|
||||||
|
default: ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Pic::unmask(unsigned const i, unsigned cpu)
|
void Board::Pic::unmask(unsigned const i, unsigned cpu)
|
||||||
{
|
{
|
||||||
if (cpu > 0)
|
switch (i) {
|
||||||
Genode::raw("multi-core irq controller not implemented yet");
|
case TIMER_IRQ: _timer_irq(cpu, true); return;
|
||||||
|
case IPI: _ipi(cpu, true); return;
|
||||||
if (i == TIMER_IRQ) {
|
|
||||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Pic::mask(unsigned const i)
|
void Board::Pic::mask(unsigned const i)
|
||||||
{
|
{
|
||||||
if (i == TIMER_IRQ) {
|
unsigned cpu = Genode::Cpu::executing_id();
|
||||||
write<Core0_timer_irq_control::Cnt_p_ns_irq>(0);
|
switch (i) {
|
||||||
return;
|
case TIMER_IRQ: _timer_irq(cpu, false); return;
|
||||||
|
case IPI: _ipi(cpu, false); return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Genode::raw("irq of peripherals != timer not implemented yet!");
|
Genode::raw("irq of peripherals != timer not implemented yet! (irq=", i, ")");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { }
|
void Board::Pic::irq_mode(unsigned, unsigned, unsigned) { }
|
||||||
|
|
||||||
|
|
||||||
|
void Board::Pic::send_ipi(unsigned cpu_target)
|
||||||
|
{
|
||||||
|
switch (cpu_target) {
|
||||||
|
case 0: write<Core_mailbox_set<0>>(1); return;
|
||||||
|
case 1: write<Core_mailbox_set<1>>(1); return;
|
||||||
|
case 2: write<Core_mailbox_set<2>>(1); return;
|
||||||
|
case 3: write<Core_mailbox_set<3>>(1); return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -23,31 +23,34 @@ class Board::Pic : Genode::Mmio
|
||||||
public:
|
public:
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
IPI = 0,
|
||||||
NR_OF_IRQ = 64,
|
NR_OF_IRQ = 64,
|
||||||
|
|
||||||
/*
|
|
||||||
* dummy IPI value on non-SMP platform,
|
|
||||||
* only used in interrupt reservation within generic code
|
|
||||||
*/
|
|
||||||
IPI,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
struct Core0_timer_irq_control : Register<0x40, 32>
|
template <unsigned CPU_NUM>
|
||||||
|
struct Core_timer_irq_control : Register<0x40+CPU_NUM*0x4, 32>
|
||||||
{
|
{
|
||||||
struct Cnt_p_ns_irq : Bitfield<1, 1> {};
|
struct Cnt_p_ns_irq
|
||||||
|
: Register<0x40+CPU_NUM*0x4, 32>::template Bitfield<1, 1> {};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Core1_timer_irq_control : Register<0x44, 32> {};
|
template <unsigned CPU_NUM>
|
||||||
struct Core2_timer_irq_control : Register<0x48, 32> {};
|
struct Core_mailbox_irq_control : Register<0x50+CPU_NUM*0x4, 32> {};
|
||||||
struct Core3_timer_irq_control : Register<0x4c, 32> {};
|
|
||||||
|
|
||||||
struct Core0_irq_source : Register<0x60, 32> {};
|
template <unsigned CPU_NUM>
|
||||||
struct Core1_irq_source : Register<0x64, 32> {};
|
struct Core_irq_source : Register<0x60+CPU_NUM*0x4, 32> {};
|
||||||
struct Core2_irq_source : Register<0x68, 32> {};
|
|
||||||
struct Core3_irq_source : Register<0x6c, 32> {};
|
template <unsigned CPU_NUM>
|
||||||
|
struct Core_mailbox_set : Register<0x80+CPU_NUM*0x10, 32> {};
|
||||||
|
|
||||||
|
template <unsigned CPU_NUM>
|
||||||
|
struct Core_mailbox_clear : Register<0xc0+CPU_NUM*0x10, 32> {};
|
||||||
|
|
||||||
|
void _ipi(unsigned cpu, bool enable);
|
||||||
|
void _timer_irq(unsigned cpu, bool enable);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -55,10 +58,10 @@ class Board::Pic : Genode::Mmio
|
||||||
|
|
||||||
bool take_request(unsigned &irq);
|
bool take_request(unsigned &irq);
|
||||||
void finish_request() { }
|
void finish_request() { }
|
||||||
void mask();
|
|
||||||
void unmask(unsigned const i, unsigned);
|
void unmask(unsigned const i, unsigned);
|
||||||
void mask(unsigned const i);
|
void mask(unsigned const i);
|
||||||
void irq_mode(unsigned, unsigned, unsigned);
|
void irq_mode(unsigned, unsigned, unsigned);
|
||||||
|
void send_ipi(unsigned);
|
||||||
|
|
||||||
static constexpr bool fast_interrupts() { return false; }
|
static constexpr bool fast_interrupts() { return false; }
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue