FreeNOS
RaspberryKernel.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2025 Ivan Tan
3 * Copyright (C) 2019 Niek Linnenbank
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <FreeNOS/System.h>
20#include <FreeNOS/ProcessManager.h>
21#include <Log.h>
22#include <SplitAllocator.h>
23#include <CoreInfo.h>
25#include <arm64/ARM64Constant.h>
26#include <arm64/ARM64Control.h>
29#include "RaspberryKernel.h"
30
32 : ARM64Kernel(info)
33 , m_bcm(info->coreId)
34{
35 NOTICE("");
36
37 // Setup interrupt callbacks
38 m_intControl = &m_bcmIntr;
39 m_exception.install(ARM64Exception::IRQ_SP_ELx, interrupt);
40 m_exception.install(ARM64Exception::IRQ_Lower_EL, interrupt);
41
42 // Configure clocks and irqs. For BCM2836, only use the generic ARM timer
43 // when running under Qemu. Unfortunately, Qemu dropped support for the
44 // broadcom timer in recent versions. On hardware, use the broadcom timer.
45#ifdef BCM2836
47 NOTICE("sysfreq = " << system_frequency);
48 //if (system_frequency == 62500000)
49 {
50 // Use ARM generic timer
51 m_timer = &m_armTimer;
52 m_timerIrq = ARMTIMER_IRQ;
53 m_armTimer.setFrequency(100);
54
55 // Setup IRQ routing
56 m_bcm.setCoreTimerIrq(Broadcom2836::NonSecurePhysicalTimer, false);
57 }
58#endif /* BCM2836 */
59 /* Default to broadcom timer and interrupt handling */
60}
61
62void RaspberryKernel::interrupt(volatile CPUState state)
63{
66 bool tick, is_uart0 = false;
67
68 DEBUG("procId = " << proc->getID());
69#ifdef BCM2836
70 if (kernel->m_timer == &kernel->m_armTimer)
71 {
73 }
74 else
75#endif /* BCM2836 */
76 {
78 }
79
80 if (tick)
81 {
82 kernel->m_timer->tick();
83 kernel->getProcessManager()->schedule();
84 }
85 for (uint i = kernel->m_timerIrq + 1; i < 64; i++)
86 {
87 if (kernel->m_intControl->isTriggered(i))
88 {
89 is_uart0 = i == UART0_IRQ;
90 kernel->executeIntVector(i, (CPUState *)&state);
91 }
92 }
93
94 //FIXME: it is just a walkaround when timer interrupt doesn't work
95 if (is_uart0)
96 kernel->getProcessManager()->schedule();
97
98 next = (ARM64Process *) kernel->getProcessManager()->current();
99 if (next != proc)
100 {
101 proc->setCpuState((const CPUState *)&state);
102 MemoryBlock::copy((void *)&state, next->cpuState(), sizeof(state));
103 }
104}
u8 coreId
Definition IntelACPI.h:1
Represents the ARM64 kernel implementation.
Definition ARM64Kernel.h:39
ARM64 specific process implementation.
void setCpuState(const CPUState *cpuState)
Overwrite the saved CPU registers for this task.
bool getCoreTimerIrqStatus(Timer timer) const
Get core timer interrupt status.
virtual bool isTriggered(uint irq)
Check if an IRQ vector is set.
virtual void executeIntVector(u32 vec, CPUState *state)
Execute an interrupt handler.
Definition Kernel.cpp:210
IntController * m_intControl
Interrupt Controller.
Definition Kernel.h:242
Timer * m_timer
Timer device.
Definition Kernel.h:245
ProcessManager * getProcessManager()
Get process manager.
Definition Kernel.cpp:143
static Size copy(void *dest, const void *src, Size count)
Copy memory from one place to another.
Result schedule()
Schedule next process to run.
Process * current()
Current process running.
ProcessID getID() const
Retrieve our ID number.
Definition Process.cpp:60
Represents the Raspberry Pi kernel implementation.
Broadcom2836 m_bcm
Broadcom specific registers.
u8 m_timerIrq
Interrupt number for the timer.
ARM64Timer m_armTimer
ARM generic timer.
static void interrupt(CPUState state)
Interrupt handler routine.
RaspberryKernel(CoreInfo *info)
Constructor function.
virtual Result tick()
Process timer tick.
Definition Timer.cpp:74
static Kernel * instance()
Retrieve the instance.
Definition Singleton.h:86
#define BCM_IRQ_SYSTIMERM1
Triggered when the system timer matches the C1 register.
unsigned int u32
Unsigned 32-bit number.
Definition Types.h:53
#define NOTICE(msg)
Output a notice message.
Definition Log.h:75
unsigned int uint
Unsigned integer number.
Definition Types.h:44
#define DEBUG(msg)
Output a debug message to standard output.
Definition Log.h:89
u64 read(Register reg)
Read a register from the CP15.
Contains all the CPU registers.
Definition ARMCore.h:244
Per-Core information structure.
Definition CoreInfo.h:61