hw: move timer into board.h

Unify the generic timer implementation for ARMv7 and ARMv8.

Ref #3445
This commit is contained in:
Stefan Kalkowski 2019-07-10 16:12:21 +02:00 committed by Christian Helmuth
parent 5c7436bf10
commit 907de9d37f
48 changed files with 242 additions and 318 deletions

View File

@ -10,8 +10,8 @@ INC_DIR += $(REP_DIR)/src/core/spec/rpi
# add C++ sources
SRC_CC += platform_services.cc
SRC_CC += spec/arm/bcm2835_pic.cc
SRC_CC += spec/arm/bcm2835_system_timer.cc
SRC_CC += spec/arm/cpu.cc
SRC_CC += spec/rpi/timer.cc
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/arm_v6/core-hw.inc

View File

@ -9,8 +9,8 @@
INC_DIR += $(REP_DIR)/src/core/spec/imx53_qsb
INC_DIR += $(REP_DIR)/src/core/spec/imx53
SRC_CC += spec/arm/imx_epit.cc
SRC_CC += spec/arm/imx_tzic.cc
SRC_CC += spec/imx53/timer.cc
# include less specific configuration
include $(REP_DIR)/lib/mk/spec/cortex_a8/core-hw.inc

View File

@ -9,9 +9,9 @@ INC_DIR += $(REP_DIR)/src/core/spec/imx7d_sabre
INC_DIR += $(REP_DIR)/src/core/spec/arm_v7/virtualization
# add C++ sources
SRC_CC += spec/arm/generic_timer.cc
SRC_CC += spec/arm/gicv2.cc
SRC_CC += spec/arndale/platform_services.cc
SRC_CC += spec/imx7d_sabre/timer.cc
SRC_CC += kernel/vm_thread_on.cc
SRC_CC += spec/arm_v7/virtualization/kernel/vm.cc
SRC_CC += spec/arm_v7/vm_session_component.cc

View File

@ -16,8 +16,8 @@ SRC_CC += kernel/vm_thread_on.cc
SRC_CC += spec/arm_v7/trustzone/kernel/vm.cc
SRC_CC += spec/arm_v7/vm_session_component.cc
SRC_CC += spec/arm_v7/trustzone/vm_session_component.cc
SRC_CC += spec/arm/imx_epit.cc
SRC_CC += spec/arm/imx_tzic.cc
SRC_CC += spec/imx53/timer.cc
# add assembly sources
SRC_S += spec/arm_v7/trustzone/exception_vector.s

View File

@ -11,7 +11,7 @@ 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/rpi3/timer.cc
SRC_CC += spec/arm/generic_timer.cc
SRC_CC += spec/64bit/memory_map.cc
#add assembly sources

View File

@ -9,7 +9,7 @@ INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/cortex_a9
# add C++ sources
SRC_CC += spec/cortex_a9/board.cc
SRC_CC += spec/cortex_a9/timer.cc
SRC_CC += spec/arm/cortex_a9_private_timer.cc
SRC_CC += spec/arm/gicv2.cc
SRC_CC += spec/arm/kernel/lock.cc
SRC_CC += kernel/vm_thread_off.cc

View File

@ -8,7 +8,7 @@
INC_DIR += $(BASE_DIR)/../base-hw/src/core/spec/exynos5
# add C++ sources
SRC_CC += spec/exynos5/timer.cc
SRC_CC += spec/arm/exynos_mct.cc
# include less specific configuration
include $(BASE_DIR)/../base-hw/lib/mk/spec/cortex_a15/core-hw.inc

View File

@ -17,7 +17,7 @@ SRC_CC += kernel/cpu_mp.cc
SRC_CC += kernel/vm_thread_off.cc
SRC_CC += kernel/lock.cc
SRC_CC += spec/x86_64/pic.cc
SRC_CC += spec/x86_64/timer.cc
SRC_CC += spec/x86_64/pit.cc
SRC_CC += spec/x86_64/kernel/thread_exception.cc
SRC_CC += spec/x86_64/platform_support.cc
SRC_CC += spec/x86/platform_services.cc

View File

@ -91,7 +91,7 @@ void Timer::process_timeouts()
Timer::Timer(Cpu & cpu)
: _driver(cpu.id()), _irq(interrupt_id(), cpu),
: _device(cpu.id()), _irq(interrupt_id(), cpu),
_last_timeout_duration(_max_value())
{
/*

View File

@ -21,8 +21,7 @@
/* Genode includes */
#include <util/list.h>
/* Core includes */
#include <timer_driver.h>
#include <board.h>
namespace Kernel
{
@ -74,9 +73,7 @@ class Kernel::Timer
void occurred() override;
};
using Driver = Timer_driver;
Driver _driver;
Board::Timer _device;
Irq _irq;
time_t _time = 0;
time_t _last_timeout_duration;

View File

@ -1,5 +1,5 @@
/*
* \brief Timer implementation specific to Rpi
* \brief Timer implementation specific to BCM2835 System Timer
* \author Norman Feske
* \author Stefan Kalkowski
* \author Martin Stein
@ -14,32 +14,37 @@
*/
/* core includes */
#include <board.h>
#include <platform.h>
#include <kernel/timer.h>
using namespace Genode;
using namespace Kernel;
using Device = Board::Timer;
Timer_driver::Timer_driver(unsigned)
Board::Timer::Timer(unsigned)
: Mmio(Platform::mmio_to_virt(Board::SYSTEM_TIMER_MMIO_BASE)) { }
void Timer::_start_one_shot(time_t const ticks)
{
_driver.write<Driver::Cs::M1>(1);
_driver.read<Driver::Cs>();
_driver.write<Driver::Cmp>(_driver.read<Driver::Clo>()
_device.write<Device::Cs::M1>(1);
_device.read<Device::Cs>();
_device.write<Device::Cmp>(_device.read<Device::Clo>()
+ (ticks < 2 ? 2 : ticks));
}
enum { TICS_PER_US = Board::SYSTEM_TIMER_CLOCK / 1000 / 1000 };
time_t Timer::ticks_to_us(time_t const ticks) const {
return ticks / Driver::TICS_PER_US; }
return ticks / TICS_PER_US; }
time_t Timer::us_to_ticks(time_t const us) const {
return us * Driver::TICS_PER_US; }
return us * TICS_PER_US; }
time_t Timer::_max_value() const {
@ -48,9 +53,9 @@ time_t Timer::_max_value() const {
time_t Timer::_duration() const
{
Driver::Clo::access_t const clo = _driver.read<Driver::Clo>();
Driver::Cmp::access_t const cmp = _driver.read<Driver::Cmp>();
Driver::Cs::access_t const irq = _driver.read<Driver::Cs::M1>();
Device::Clo::access_t const clo = _device.read<Device::Clo>();
Device::Cmp::access_t const cmp = _device.read<Device::Cmp>();
Device::Cs::access_t const irq = _device.read<Device::Cs::M1>();
uint32_t d = (irq) ? (uint32_t)_last_timeout_duration + (clo - cmp)
: clo - (cmp - _last_timeout_duration);
return d;

View File

@ -11,31 +11,26 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__BCM2835_SYSTEM_TIMER_H_
#define _SRC__CORE__SPEC__ARM__BCM2835_SYSTEM_TIMER_H_
/* Kernel includes */
#include <util/mmio.h>
/* core includes */
#include <board.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
/**
* Timer driver for core
*
* Timer channel 0 apparently doesn't work on the RPI, so we use channel 1
*/
struct Kernel::Timer_driver : Genode::Mmio
struct Board::Timer : Genode::Mmio
{
enum { TICS_PER_US = Board::SYSTEM_TIMER_CLOCK / 1000 / 1000 };
struct Cs : Register<0x0, 32> { struct M1 : Bitfield<1, 1> { }; };
struct Clo : Register<0x4, 32> { };
struct Cmp : Register<0x10, 32> { };
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__BCM2835_SYSTEM_TIMER_H_ */

View File

@ -23,7 +23,6 @@ class Board::Pic : Genode::Mmio
public:
enum {
TIMER_IRQ = 1,
NR_OF_IRQ = 64,
/*

View File

@ -22,9 +22,17 @@
using namespace Genode;
using namespace Kernel;
using Device = Board::Timer;
Timer_driver::Timer_driver(unsigned)
enum {
TICS_PER_MS =
Board::CORTEX_A9_PRIVATE_TIMER_CLK /
Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000
};
Board::Timer::Timer(unsigned)
: Mmio(Platform::mmio_to_virt(Board::Cpu_mmio::PRIVATE_TIMER_MMIO_BASE))
{
enum { PRESCALER = Board::CORTEX_A9_PRIVATE_TIMER_DIV - 1 };
@ -51,13 +59,13 @@ void Timer::_start_one_shot(time_t const ticks)
* First unset the interrupt flag,
* otherwise if the tick is small enough, we loose an interrupt
*/
_driver.write<Driver::Interrupt_status::Event>(1);
_driver.write<Driver::Counter>(ticks);
_device.write<Device::Interrupt_status::Event>(1);
_device.write<Device::Counter>(ticks);
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, Driver::TICS_PER_MS); }
return timer_ticks_to_us(ticks, TICS_PER_MS); }
unsigned Timer::interrupt_id() const {
@ -65,14 +73,14 @@ unsigned Timer::interrupt_id() const {
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * Driver::TICS_PER_MS; }
return (us / 1000) * TICS_PER_MS; }
time_t Timer::_duration() const
{
Driver::Counter::access_t last = _last_timeout_duration;
Driver::Counter::access_t cnt = _driver.read<Driver::Counter>();
Driver::Counter::access_t ret = (_driver.read<Driver::Interrupt_status::Event>())
Device::Counter::access_t last = _last_timeout_duration;
Device::Counter::access_t cnt = _device.read<Device::Counter>();
Device::Counter::access_t ret = (_device.read<Device::Interrupt_status::Event>())
? _max_value() - cnt + last : last - cnt;
return ret;
}

View File

@ -1,5 +1,5 @@
/*
* \brief Timer implementation specific to Cortex A9
* \brief Private Timer implementation specific to Cortex A9
* \author Martin stein
* \date 2011-12-13
*/
@ -11,28 +11,19 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_
#define _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_
/* Genode includes */
#include <util/mmio.h>
/* core includes */
#include <board.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
/**
* Timer driver for core
*/
struct Kernel::Timer_driver : Genode::Mmio
struct Board::Timer : Genode::Mmio
{
enum {
TICS_PER_MS =
Board::CORTEX_A9_PRIVATE_TIMER_CLK /
Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000
};
/**
* Load value register
*/
@ -62,7 +53,7 @@ struct Kernel::Timer_driver : Genode::Mmio
struct Event : Bitfield<0,1> { }; /* if counter hit zero */
};
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__CORTEX_A9_PRIVATE_TIMER_H_ */

View File

@ -25,7 +25,7 @@ using namespace Kernel;
unsigned Timer::interrupt_id() const
{
switch (_driver.cpu_id) {
switch (_device.cpu_id) {
case 0: return Board::MCT_IRQ_L0;
case 1: return Board::MCT_IRQ_L1;
default: return 0;
@ -33,7 +33,7 @@ unsigned Timer::interrupt_id() const
}
Timer_driver::Timer_driver(unsigned cpu_id)
Board::Timer::Timer(unsigned cpu_id)
:
Mmio(Platform::mmio_to_virt(Board::MCT_MMIO_BASE)),
local(Platform::mmio_to_virt(Board::MCT_MMIO_BASE)
@ -51,7 +51,7 @@ Timer_driver::Timer_driver(unsigned cpu_id)
}
Timer_driver::Local::Local(Genode::addr_t base)
Board::Timer::Local::Local(Genode::addr_t base)
: Mmio(base)
{
write<Int_enb>(Int_enb::Frceie::bits(1));
@ -68,27 +68,29 @@ Timer_driver::Local::Local(Genode::addr_t base)
void Timer::_start_one_shot(time_t const ticks)
{
_driver.local.cnt = _driver.local.read<Driver::Local::Tcnto>();
_driver.local.write<Driver::Local::Int_cstat::Frccnt>(1);
_driver.local.acked_write<Driver::Local::Frcntb,
Driver::Local::Wstat::Frcntb>(ticks);
using Device = Board::Timer;
_device.local.cnt = _device.local.read<Device::Local::Tcnto>();
_device.local.write<Device::Local::Int_cstat::Frccnt>(1);
_device.local.acked_write<Device::Local::Frcntb,
Device::Local::Wstat::Frcntb>(ticks);
}
time_t Timer::_duration() const
{
unsigned long ret = _driver.local.cnt - _driver.local.read<Driver::Local::Tcnto>();
using Tcnto = Board::Timer::Local::Tcnto;
unsigned long ret = _device.local.cnt - _device.local.read<Tcnto>();
return ret;
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
return timer_ticks_to_us(ticks, _device.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * _driver.ticks_per_ms; }
return (us / 1000) * _device.ticks_per_ms; }
time_t Timer::_max_value() const {

View File

@ -11,8 +11,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_
#define _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_
/* Kernel includes */
#include <util/mmio.h>
@ -20,10 +20,10 @@
/* base-hw includes */
#include <kernel/types.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
struct Kernel::Timer_driver : Genode::Mmio
struct Board::Timer : Genode::Mmio
{
enum {
PRESCALER = 1,
@ -108,14 +108,14 @@ struct Kernel::Timer_driver : Genode::Mmio
*
* \param clock input clock
*/
time_t static calc_ticks_per_ms(unsigned const clock) {
Kernel::time_t static calc_ticks_per_ms(unsigned const clock) {
return clock / (PRESCALER + 1) / (1 << DIV_MUX) / 1000; }
Local local;
unsigned const ticks_per_ms;
unsigned const cpu_id;
Timer_driver(unsigned cpu_id);
Timer(unsigned cpu_id);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__EXYNOS_MCT_H_ */

View File

@ -0,0 +1,60 @@
/*
* \brief Timer driver for core
* \author Stefan Kalkowski
* \date 2019-05-10
*/
/*
* Copyright (C) 2019 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.
*/
#include <drivers/timer/util.h>
#include <kernel/timer.h>
#include <kernel/cpu.h>
using namespace Kernel;
unsigned Timer::interrupt_id() const { return Board::TIMER_IRQ; }
unsigned long Board::Timer::_freq() { return Genode::Cpu::Cntfrq::read(); }
Board::Timer::Timer(unsigned) : ticks_per_ms(_freq() / 1000)
{
Cpu::Cntp_ctl::access_t ctl = 0;
Cpu::Cntp_ctl::Enable::set(ctl, 1);
Cpu::Cntp_ctl::write(ctl);
}
void Timer::_start_one_shot(time_t const ticks)
{
_device.last_time = Cpu::Cntpct::read();
Cpu::Cntp_tval::write(ticks);
Cpu::Cntp_ctl::access_t ctl = Cpu::Cntp_ctl::read();
Cpu::Cntp_ctl::Istatus::set(ctl, 0);
Cpu::Cntp_ctl::write(ctl);
}
time_t Timer::_duration() const
{
return Cpu::Cntpct::read() - _device.last_time;
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return Genode::timer_ticks_to_us(ticks, _device.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * _device.ticks_per_ms; }
time_t Timer::_max_value() const {
return _device.ticks_per_ms * 5000; }

View File

@ -11,24 +11,23 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__GENERIC_TIMER_H_
#define _SRC__CORE__SPEC__ARM__GENERIC_TIMER_H_
/* base-hw includes */
#include <kernel/types.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
struct Kernel::Timer_driver
struct Board::Timer
{
unsigned long _freq();
unsigned const ticks_per_ms;
time_t last_time { 0 };
Kernel::time_t last_time { 0 };
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__GENERIC_TIMER_H_ */

View File

@ -26,7 +26,7 @@ using namespace Kernel;
unsigned Timer::interrupt_id() const { return Board::EPIT_1_IRQ; }
Timer_driver::Timer_driver(unsigned)
Board::Timer::Timer(unsigned)
: Mmio(Platform::mmio_to_virt(Board::EPIT_1_MMIO_BASE))
{
reset();
@ -52,17 +52,17 @@ void Timer::_start_one_shot(time_t const ticks)
* First unset the interrupt flag,
* otherwise if the tick is small enough, we loose an interrupt
*/
_driver.write<Driver::Sr::Ocif>(1);
_driver.write<Driver::Lr>(ticks - 1);
_device.write<Board::Timer::Sr::Ocif>(1);
_device.write<Board::Timer::Lr>(ticks - 1);
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, Driver::TICS_PER_MS); }
return timer_ticks_to_us(ticks, Board::Timer::TICS_PER_MS); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000UL) * Driver::TICS_PER_MS; }
return (us / 1000UL) * Board::Timer::TICS_PER_MS; }
time_t Timer::_max_value() const {
@ -71,9 +71,10 @@ time_t Timer::_max_value() const {
time_t Timer::_duration() const
{
Driver::Cnt::access_t last = _last_timeout_duration;
Driver::Cnt::access_t cnt = _driver.read<Driver::Cnt>();
Driver::Cnt::access_t ret = (_driver.read<Driver::Sr::Ocif>())
using Device = Board::Timer;
Device::Cnt::access_t last = _last_timeout_duration;
Device::Cnt::access_t cnt = _device.read<Device::Cnt>();
Device::Cnt::access_t ret = (_device.read<Device::Sr::Ocif>())
? _max_value() - cnt + last : last - cnt;
return ret;
}

View File

@ -11,18 +11,18 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__IMX_EPIT_H_
#define _SRC__CORE__SPEC__ARM__IMX_EPIT_H_
/* Kernel includes */
#include <util/mmio.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
/**
* Timer driver for core
*/
struct Kernel::Timer_driver : Genode::Mmio
struct Board::Timer : Genode::Mmio
{
enum { TICS_PER_MS = 33333 };
@ -86,7 +86,7 @@ struct Kernel::Timer_driver : Genode::Mmio
write<Sr::Ocif>(1);
}
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__IMX_EPIT_H_ */

View File

@ -16,6 +16,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/arndale_board.h>
#include <spec/arm/exynos_mct.h>
namespace Board {
using namespace Hw::Arndale_board;

View File

@ -17,6 +17,7 @@
#include <hw/spec/arm/imx_tzic.h>
#include <hw/spec/arm/imx53_qsb_board.h>
#include <spec/arm/imx_epit.h>
namespace Board {
using namespace Hw::Imx53_qsb_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/imx6q_sabrelite_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {

View File

@ -16,11 +16,14 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/imx7d_sabre_board.h>
#include <spec/arm/generic_timer.h>
namespace Board {
using namespace Hw::Imx7d_sabre_board;
using Pic = Hw::Gicv2;
enum { TIMER_IRQ = 30 };
}
#endif /* _CORE__SPEC__IMX7_SABRELITE__BOARD_H_ */

View File

@ -1,75 +0,0 @@
/*
* \brief Timer driver for core
* \author Stefan Kalkowski
* \author Martin stein
* \date 2013-01-10
*/
/*
* Copyright (C) 2013-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.
*/
#include <drivers/timer/util.h>
#include <kernel/timer.h>
#include <board.h>
#include <platform.h>
using namespace Genode;
using namespace Kernel;
unsigned Timer::interrupt_id() const
{
return 30;
}
unsigned long Timer_driver::_freq()
{
unsigned long freq;
asm volatile("mrc p15, 0, %0, c14, c0, 0\n" : "=r" (freq));
return freq;
}
Timer_driver::Timer_driver(unsigned) : ticks_per_ms(_freq() / 1000)
{
unsigned long ctrl;
asm volatile("mrc p15, 0, %0, c14, c2, 1\n" : "=r" (ctrl));
asm volatile("mcr p15, 0, %0, c14, c2, 1\n" :: "r" (ctrl | 1));
}
void Timer::_start_one_shot(time_t const ticks)
{
unsigned long ctrl;
unsigned long v0, v1;
asm volatile("mrrc p15, 0, %0, %1, c14\n" : "=r" (v0), "=r" (v1));
_driver.last_time = (Genode::uint64_t)v0 | (Genode::uint64_t)v1 << 32;
asm volatile("mcr p15, 0, %0, c14, c2, 0\n" :: "r" (ticks));
asm volatile("mrc p15, 0, %0, c14, c2, 1\n" : "=r" (ctrl));
asm volatile("mcr p15, 0, %0, c14, c2, 1\n" :: "r" (ctrl & ~4UL));
}
time_t Timer::_duration() const
{
unsigned long v0, v1;
asm volatile("mrrc p15, 0, %0, %1, c14\n" : "=r" (v0), "=r" (v1));
Genode::uint64_t v = (Genode::uint64_t)v0 | (Genode::uint64_t)v1 << 32;
return v - _driver.last_time;
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * _driver.ticks_per_ms; }
time_t Timer::_max_value() const {
return _driver.ticks_per_ms * 5000; }

View File

@ -1,34 +0,0 @@
/*
* \brief Timer driver for core
* \author Martin stein
* \date 2013-01-10
*/
/*
* Copyright (C) 2013-2017 Genode Labs GmbH
*
* This file is part of the Kernel OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
/* base-hw includes */
#include <kernel/types.h>
namespace Kernel { class Timer_driver; }
struct Kernel::Timer_driver
{
unsigned long _freq();
unsigned const ticks_per_ms;
time_t last_time { 0 };
Timer_driver(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */

View File

@ -16,6 +16,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/nit6_solox_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {
using namespace Hw::Nit6_solox_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/odroid_xu_board.h>
#include <spec/arm/exynos_mct.h>
namespace Board {
using namespace Hw::Odroid_xu_board;

View File

@ -17,6 +17,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/panda_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {
using namespace Hw::Panda_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/pbxa9_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {
using namespace Hw::Pbxa9_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/riscv/board.h>
#include <spec/riscv/pic.h>
#include <spec/riscv/timer.h>
namespace Board { using namespace Hw::Riscv_board; }

View File

@ -19,28 +19,28 @@ using namespace Genode;
using namespace Kernel;
Timer_driver::Timer_driver(unsigned)
Board::Timer::Timer(unsigned)
{
/* enable timer interrupt */
enum { STIE = 0x20 };
asm volatile ("csrs sie, %0" : : "r"(STIE));
}
time_t Timer_driver::stime() const { return Hw::get_sys_timer(); }
time_t Board::Timer::stime() const { return Hw::get_sys_timer(); }
void Timer::_start_one_shot(time_t const ticks)
{
_driver.timeout = _driver.stime() + ticks;
Hw::set_sys_timer(_driver.timeout);
_device.timeout = _device.stime() + ticks;
Hw::set_sys_timer(_device.timeout);
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return ticks / Driver::TICS_PER_US; }
return ticks / Board::Timer::TICS_PER_US; }
time_t Timer::us_to_ticks(time_t const us) const {
return us * Driver::TICS_PER_MS; }
return us * Board::Timer::TICS_PER_MS; }
time_t Timer::_max_value() const {
@ -49,11 +49,10 @@ time_t Timer::_max_value() const {
time_t Timer::_duration() const
{
addr_t time = _driver.stime();
return time < _driver.timeout ? _driver.timeout - time
: _last_timeout_duration + (time - _driver.timeout);
addr_t time = _device.stime();
return time < _device.timeout ? _device.timeout - time
: _last_timeout_duration + (time - _device.timeout);
}
unsigned Timer::interrupt_id() const {
return 5; }
unsigned Timer::interrupt_id() const { return 5; }

View File

@ -11,19 +11,20 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_H_
#define _TIMER_H_
#ifndef _SRC__CORE__SPEC__RISCV__TIMER_H_
#define _SRC__CORE__SPEC__RISCV__TIMER_H_
/* Genode includes */
#include <base/stdint.h>
#include <kernel/types.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
/**
* Timer driver for core
*/
struct Kernel::Timer_driver
struct Board::Timer
{
enum {
SPIKE_TIMER_HZ = 1000000,
@ -31,11 +32,11 @@ struct Kernel::Timer_driver
TICS_PER_US = TICS_PER_MS / 1000,
};
time_t timeout = 0;
Kernel::time_t timeout = 0;
time_t stime() const;
Kernel::time_t stime() const;
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_H_ */
#endif /* _SRC__CORE__SPEC__RISCV__TIMER_H_ */

View File

@ -17,6 +17,7 @@
#include <hw/spec/arm/rpi_board.h>
#include <spec/arm/bcm2835_pic.h>
#include <spec/arm/bcm2835_system_timer.h>
namespace Board {
using namespace Hw::Rpi_board;

View File

@ -16,9 +16,12 @@
#include <hw/spec/arm_64/rpi3_board.h>
#include <spec/arm/bcm2837_pic.h>
#include <spec/arm/generic_timer.h>
namespace Board {
using namespace Hw::Rpi3_board;
enum { TIMER_IRQ = 1 };
};
#endif /* _CORE__SPEC__RPI3__BOARD_H_ */

View File

@ -1,60 +0,0 @@
/*
* \brief Timer driver for core
* \author Stefan Kalkowski
* \date 2019-05-10
*/
/*
* Copyright (C) 2019 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.
*/
#include <drivers/timer/util.h>
#include <kernel/timer.h>
#include <kernel/cpu.h>
using namespace Kernel;
unsigned Timer::interrupt_id() const { return Board::Pic::TIMER_IRQ; }
unsigned long Timer_driver::_freq() { return Genode::Cpu::Cntfrq_el0::read(); }
Timer_driver::Timer_driver(unsigned) : ticks_per_ms(_freq() / 1000)
{
Cpu::Cntp_ctl_el0::access_t ctl = 0;
Cpu::Cntp_ctl_el0::Enable::set(ctl, 1);
Cpu::Cntp_ctl_el0::write(ctl);
}
void Timer::_start_one_shot(time_t const ticks)
{
_driver.last_time = Cpu::Cntpct_el0::read();
Cpu::Cntp_tval_el0::write(ticks);
Cpu::Cntp_ctl_el0::access_t ctl = Cpu::Cntp_ctl_el0::read();
Cpu::Cntp_ctl_el0::Istatus::set(ctl, 0);
Cpu::Cntp_ctl_el0::write(ctl);
}
time_t Timer::_duration() const
{
return Cpu::Cntpct_el0::read() - _driver.last_time;
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return Genode::timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * _driver.ticks_per_ms; }
time_t Timer::_max_value() const {
return _driver.ticks_per_ms * 5000; }

View File

@ -17,6 +17,7 @@
#include <hw/spec/arm/imx_tzic.h>
#include <hw/spec/arm/usb_armory_board.h>
#include <spec/arm/imx_epit.h>
namespace Board {
using namespace Hw::Usb_armory_board;

View File

@ -17,6 +17,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/wand_quad_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {
using namespace Hw::Wand_quad_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/x86_64/pc_board.h>
#include <spec/x86_64/pic.h>
#include <spec/x86_64/pit.h>
namespace Board {
using namespace Hw::Pc_board;

View File

@ -16,6 +16,7 @@
#include <hw/spec/x86_64/pc_board.h>
#include <spec/x86_64/muen/pic.h>
#include <spec/x86_64/muen/timer.h>
namespace Board {
using namespace Hw::Pc_board;

View File

@ -26,7 +26,7 @@ using namespace Genode;
using namespace Kernel;
Timer_driver::Timer_driver(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz()), start(0)
Board::Timer::Timer(unsigned) : ticks_per_ms(sinfo()->get_tsc_khz()), start(0)
{
/* first sinfo instance, output status */
sinfo()->log_status();
@ -67,21 +67,21 @@ void Timer::_start_one_shot(time_t const ticks)
{
static const time_t MIN_TICKS = 10UL;
_driver.start = _driver.rdtsc();
uint64_t t = _driver.start + ((ticks > MIN_TICKS) ? ticks : MIN_TICKS);
_driver.event_page->tsc_trigger = t;
_device.start = _device.rdtsc();
uint64_t t = _device.start + ((ticks > MIN_TICKS) ? ticks : MIN_TICKS);
_device.event_page->tsc_trigger = t;
if (_driver.guest_event_page)
_driver.guest_event_page->tsc_trigger = t;
if (_device.guest_event_page)
_device.guest_event_page->tsc_trigger = t;
}
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
return timer_ticks_to_us(ticks, _device.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return us * (_driver.ticks_per_ms / 1000); }
return us * (_device.ticks_per_ms / 1000); }
time_t Timer::_max_value() const { return ~0UL; }
@ -89,5 +89,5 @@ time_t Timer::_max_value() const { return ~0UL; }
time_t Timer::_duration() const
{
return _driver.rdtsc() - _driver.start;
return _device.rdtsc() - _device.start;
}

View File

@ -17,10 +17,10 @@
/* Genode includes */
#include <base/stdint.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
struct Kernel::Timer_driver
struct Board::Timer
{
enum { TIMER_DISABLED = ~0ULL };
@ -45,7 +45,7 @@ struct Kernel::Timer_driver
class Invalid_region { };
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */

View File

@ -26,7 +26,7 @@ using namespace Genode;
using namespace Kernel;
uint32_t Timer_driver::pit_calc_timer_freq(void)
uint32_t Board::Timer::pit_calc_timer_freq(void)
{
uint32_t t_start, t_end;
@ -53,7 +53,7 @@ uint32_t Timer_driver::pit_calc_timer_freq(void)
}
Timer_driver::Timer_driver(unsigned)
Board::Timer::Timer(unsigned)
: Mmio(Platform::mmio_to_virt(Hw::Cpu_memory_map::lapic_phys_base()))
{
/* Enable LAPIC timer in one-shot mode */
@ -84,30 +84,30 @@ void Timer::init_cpu_local()
* Disable PIT timer channel. This is necessary since BIOS sets up
* channel 0 to fire periodically.
*/
outb(Driver::PIT_MODE, 0x30);
outb(Driver::PIT_CH0_DATA, 0);
outb(Driver::PIT_CH0_DATA, 0);
outb(Board::Timer::PIT_MODE, 0x30);
outb(Board::Timer::PIT_CH0_DATA, 0);
outb(Board::Timer::PIT_CH0_DATA, 0);
}
void Timer::_start_one_shot(time_t const ticks) {
_driver.write<Driver::Tmr_initial>(ticks); }
_device.write<Board::Timer::Tmr_initial>(ticks); }
time_t Timer::ticks_to_us(time_t const ticks) const {
return timer_ticks_to_us(ticks, _driver.ticks_per_ms); }
return timer_ticks_to_us(ticks, _device.ticks_per_ms); }
time_t Timer::us_to_ticks(time_t const us) const {
return (us / 1000) * _driver.ticks_per_ms; }
return (us / 1000) * _device.ticks_per_ms; }
time_t Timer::_max_value() const {
return (Driver::Tmr_initial::access_t)~0; }
return (Board::Timer::Tmr_initial::access_t)~0; }
time_t Timer::_duration() const {
return _last_timeout_duration - _driver.read<Driver::Tmr_current>(); }
return _last_timeout_duration - _device.read<Board::Timer::Tmr_current>(); }
unsigned Timer::interrupt_id() const {

View File

@ -12,8 +12,8 @@
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _TIMER_DRIVER_H_
#define _TIMER_DRIVER_H_
#ifndef _SRC__CORE__SPEC__ARM__PIT_H_
#define _SRC__CORE__SPEC__ARM__PIT_H_
/* Genode includes */
#include <util/mmio.h>
@ -23,12 +23,12 @@
#include <port_io.h>
#include <board.h>
namespace Kernel { class Timer_driver; }
namespace Board { class Timer; }
/**
* LAPIC-based timer driver for core
*/
struct Kernel::Timer_driver : Genode::Mmio
struct Board::Timer: Genode::Mmio
{
enum {
/* PIT constants */
@ -70,7 +70,7 @@ struct Kernel::Timer_driver : Genode::Mmio
/* Measure LAPIC timer frequency using PIT channel 2 */
Genode::uint32_t pit_calc_timer_freq(void);
Timer_driver(unsigned);
Timer(unsigned);
};
#endif /* _TIMER_DRIVER_H_ */
#endif /* _SRC__CORE__SPEC__ARM__PIT_H_ */

View File

@ -18,6 +18,7 @@
#include <hw/spec/arm/gicv2.h>
#include <hw/spec/arm/zynq_qemu_board.h>
#include <spec/arm/cortex_a9_private_timer.h>
namespace Board {
using namespace Hw::Zynq_qemu_board;

View File

@ -237,6 +237,18 @@ struct Hw::Arm_cpu
/* Counter Frequency register */
ARM_CP15_REGISTER_32BIT(Cntfrq, c14, c0, 0, 0);
/* Physical Timer Value register */
ARM_CP15_REGISTER_32BIT(Cntp_tval, c14, c2, 0, 0);
/* Physical Timer Control register */
ARM_CP15_REGISTER_32BIT(Cntp_ctl, c14, c2, 0, 1,
struct Enable : Bitfield<0, 1> {};
struct Istatus : Bitfield<2, 1> {};
);
/* Physical Count register */
ARM_CP15_REGISTER_64BIT(Cntpct, c14, 0);
/******************************
** Program status registers **
******************************/
@ -267,7 +279,6 @@ struct Hw::Arm_cpu
ARM_BANKED_REGISTER(Cpsr, cpsr);
/**********************************
** Cache maintainance functions **
**********************************/

View File

@ -40,8 +40,6 @@ struct Hw::Arm_64_cpu
struct El3 : Bitfield<8, 4> {};
);
SYSTEM_REGISTER(64, Cntfrq_el0, cntfrq_el0);
SYSTEM_REGISTER(64, Current_el, currentel,
enum Level { EL0, EL1, EL2, EL3 };
struct El : Bitfield<2, 2> {};
@ -164,6 +162,8 @@ struct Hw::Arm_64_cpu
** Generic timer interface **
*****************************/
SYSTEM_REGISTER(64, Cntfrq_el0, cntfrq_el0);
SYSTEM_REGISTER(32, Cntp_ctl_el0, cntp_ctl_el0,
struct Enable : Bitfield<0, 1> {};
struct Istatus : Bitfield<2, 1> {};
@ -171,6 +171,11 @@ struct Hw::Arm_64_cpu
SYSTEM_REGISTER(64, Cntpct_el0, cntpct_el0);
SYSTEM_REGISTER(32, Cntp_tval_el0, cntp_tval_el0);
using Cntfrq = Cntfrq_el0;
using Cntp_ctl = Cntp_ctl_el0;
using Cntpct = Cntpct_el0;
using Cntp_tval = Cntp_tval_el0;
};