Merge branch 'master' of github.com:mmueller41/genode

This commit is contained in:
Michael Mueller
2022-10-14 14:31:37 +02:00
1561 changed files with 27337 additions and 15653 deletions

View File

@@ -21,6 +21,5 @@ content:
for spec in x86_32; do \
mv lib/mk/spec/$$spec/ld-fiasco.mk lib/mk/spec/$$spec/ld.mk; \
done;
sed -i "s/ld-fiasco/ld/" src/lib/ld/fiasco/target.mk
sed -i "s/fiasco_timer_drv/timer/" src/timer/fiasco/target.mk

View File

@@ -1 +1 @@
2022-05-24 1790ce242c001ed77aab9695f69923a44d1dc1d1
2022-10-11 1f0607de6493bad0e47b24e66d84474652e8b6be

View File

@@ -1,2 +0,0 @@
TARGET = ld-fiasco
LIBS = ld-fiasco

View File

@@ -1 +1 @@
2022-05-24 f7900083623a2009d35234c47d2475dea8f6cf53
2022-10-11 d258920f8664460c78eeea25fafb89eaa5e7adf5

View File

@@ -1 +1 @@
2022-05-24 f7d228f6419c2fc9b1b0faf4ba8d88862ba61e81
2022-10-11 1c94d29566bccccced246eeaf90702348e2b1a7f

View File

@@ -1 +1 @@
2022-05-24 391b798b7c1d1b44ff65d855980eb41a8f4a87c1
2022-10-11 2668fd23d5cbd45b8f632073fc7c155f96ecb848

View File

@@ -1 +1 @@
2022-05-24 79eab679e71dd70803b0e1647a23e2ba86c76f50
2022-10-11 8da054ff9e4c37895816fd30857b3c42d9e75eb0

View File

@@ -1 +1 @@
2022-05-24 7a16aeb081d1392c36d83f526936f17cc9560442
2022-10-11 f41df6b57d2c4b090a84427e02950df84fb385ad

View File

@@ -39,5 +39,4 @@ content:
for spec in x86_32 x86_64 arm arm_64; do \
mv lib/mk/spec/$$spec/ld-foc.mk lib/mk/spec/$$spec/ld.mk; \
done;
sed -i "s/ld-foc/ld/" src/lib/ld/foc/target.mk
sed -i "s/foc_timer_drv/timer/" src/timer/foc/target.mk

View File

@@ -1,2 +0,0 @@
TARGET = ld-foc
LIBS = ld-foc

View File

@@ -0,0 +1 @@
arm_v8a

View File

@@ -0,0 +1 @@
0x40000000

View File

@@ -1,6 +1,6 @@
REP_INC_DIR += src/bootstrap/board/virt_qemu
REP_INC_DIR += src/bootstrap/board/virt_qemu_arm_v7a
SRC_CC += bootstrap/board/virt_qemu/platform.cc
SRC_CC += bootstrap/board/virt_qemu_arm_v7a/platform.cc
SRC_CC += bootstrap/spec/arm/arm_v7_cpu.cc
SRC_CC += bootstrap/spec/arm/cortex_a15_cpu.cc
SRC_CC += bootstrap/spec/arm/gicv2.cc

View File

@@ -1,4 +1,4 @@
REP_INC_DIR += src/core/board/virt_qemu
REP_INC_DIR += src/core/board/virt_qemu_arm_v7a
REP_INC_DIR += src/core/spec/arm/virtualization
# add C++ sources

View File

@@ -1,8 +1,8 @@
REP_INC_DIR += src/bootstrap/board/virt_qemu_64
REP_INC_DIR += src/bootstrap/board/virt_qemu_arm_v8a
SRC_CC += bootstrap/spec/arm/gicv3.cc
SRC_CC += bootstrap/spec/arm_64/cortex_a53_mmu.cc
SRC_CC += bootstrap/board/virt_qemu_64/platform.cc
SRC_CC += bootstrap/board/virt_qemu_arm_v8a/platform.cc
SRC_CC += lib/base/arm_64/kernel/interface.cc
SRC_CC += spec/64bit/memory_map.cc
SRC_S += bootstrap/spec/arm_64/crt0.s

View File

@@ -1,4 +1,4 @@
REP_INC_DIR += src/core/board/virt_qemu_64
REP_INC_DIR += src/core/board/virt_qemu_arm_v8a
REP_INC_DIR += src/core/spec/arm/virtualization
# add C++ sources

View File

@@ -4,6 +4,6 @@ SRC_CC += timer_connection_time.cc
SRC_CC += hw/timer_connection_timestamp.cc
SRC_CC += duration.cc
INC_DIR += $(BASE_DIR)/src/include
REP_INC_DIR += src/include
vpath % $(BASE_DIR)/src/lib/timeout
vpath % $(call select_from_repositories,src/lib/timeout)

View File

@@ -1 +1 @@
2022-05-24 ab1cb582165e76bda4abf27870f44ad7d1ae5b6d
2022-10-11 50db06fe21eca6c46c9b4bf7fcbc81538ac74f32

View File

@@ -1,4 +1,6 @@
CONTENT += src/core/board/imx53_qsb \
src/bootstrap/board/imx53_qsb
src/bootstrap/board/imx53_qsb \
lib/mk/spec/arm_v7/core-hw-imx53_qsb.inc \
lib/mk/spec/arm_v7/bootstrap-hw-imx53_qsb.inc
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -1 +1 @@
2022-05-24 0fff6ce83b962b3fd54cf6eda0a157cb0cb0c9d5
2022-10-11 1377d3a2b7afaa265cc5ae6bbd515679be527c40

View File

@@ -1 +1 @@
2022-05-24 8c17512664a648eaed876c815ea678770eda3280
2022-10-11 c32cf899ce00bd69aff5bbd4f7b6b611d2bfa47d

View File

@@ -1 +1 @@
2022-05-24 edc396d9bc9a2ebf73590e70c1363020226909be
2022-10-11 39ff297bc573b8e8bf4f2e6e233bf0b1b21f13af

View File

@@ -1 +1 @@
2022-05-24 da90478c4c0b8993041bc59488eedb124e680e78
2022-10-11 f5456c3ed55b53ccaefee603fdb8d9b1e3ca84ab

View File

@@ -1 +1 @@
2022-05-24 1b34e317209c48bfc88af6118db32be261ce3e0c
2022-10-11 de2f50d9164952dbbf6ce76d29abad5d96da8512

View File

@@ -1 +1 @@
2022-05-24 46e9f88209bbc95228d3882cc0831770315402e4
2022-10-11 5d72eb4e34f582c06c086345b225cee91ce539cc

View File

@@ -1,4 +0,0 @@
CONTENT += src/core/board/virt_qemu_64 \
src/bootstrap/board/virt_qemu_64
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -1 +0,0 @@
2022-05-24 bb6c39c093a24d2ec4ff1d00e397529c51e95fa7

View File

@@ -0,0 +1,4 @@
CONTENT += src/core/board/virt_qemu_arm_v7a \
src/bootstrap/board/virt_qemu_arm_v7a
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -0,0 +1 @@
2022-10-11 70e53c98ef4b3215440efb2ea09e07ff7cd97c4f

View File

@@ -0,0 +1,4 @@
CONTENT += src/core/board/virt_qemu_arm_v8a \
src/bootstrap/board/virt_qemu_arm_v8a
include $(GENODE_DIR)/repos/base-hw/recipes/src/base-hw_content.inc

View File

@@ -0,0 +1 @@
2022-10-11 c146d70c9bde3f928110c868a54b8c800beffd79

View File

@@ -0,0 +1,2 @@
base-hw
base

View File

@@ -115,6 +115,12 @@ SRC_LIB_BASE += $(notdir $(wildcard $(BASE_HW_DIR)/src/lib/base/*.cc)) \
$(notdir $(wildcard $(BASE_DIR)/src/lib/base/*.cc)) \
${call selected_content,SRC_LIB_BASE_SPECS}
SRC_LIB_TIMEOUT += duration.cc \
hw/timer_connection_timestamp.cc \
timeout.cc \
timer_connection.cc \
timer_connection_time.cc
SRC_LIB_STARTUP += init_main_thread.cc _main.cc \
$(addprefix spec/,${call selected_content,SRC_LIB_STARTUP_SPECS})
@@ -125,15 +131,24 @@ SRC_CORE += $(notdir $(wildcard $(BASE_HW_DIR)/src/core/*.cc)) \
$(addprefix board/,$(BOARD)) \
version.inc target.inc include hw kernel
LIB_MK := base-hw-common.mk base-hw.mk bootstrap-hw.inc core-hw.inc \
timeout-hw.mk cxx.mk base.inc base-common.inc startup.inc \
$(addprefix spec/,${call selected_content,LIB_MK_SPECS})
# names of the lib/mk/ files to consider for inclusion in the src archive
LIB_MK_FILES := base-common.inc base-hw-common.mk \
base.inc base-hw.mk \
bootstrap-hw.inc bootstrap-hw-$(BOARD).inc bootstrap-hw-$(BOARD).mk \
core-hw.inc core-hw-$(BOARD).inc core-hw-$(BOARD).mk \
startup.inc startup-hw.mk \
timeout-hw.mk cxx.mk ld-hw.mk syscall-hw.mk
LIB_MK_DIRS := lib/mk $(addprefix lib/mk/spec/,${call selected_content,LIB_MK_SPECS})
CONTENT += $(foreach D,$(LIB_MK_DIRS),$(addprefix $D/,$(LIB_MK_FILES)))
CONTENT += $(addprefix src/timer/,$(SRC_TIMER)) \
$(addprefix src/include/hw/,$(SRC_INCLUDE_HW)) \
$(addprefix src/bootstrap/,$(SRC_BOOTSTRAP)) \
$(addprefix lib/mk/,$(LIB_MK)) \
$(addprefix src/lib/base/,$(SRC_LIB_BASE)) \
$(addprefix src/lib/timeout/,$(SRC_LIB_TIMEOUT)) \
$(addprefix src/lib/startup/,$(SRC_LIB_STARTUP)) \
$(addprefix src/core/,$(SRC_CORE)) \
src/lib/hw src/lib/ld src/lib/cxx \
@@ -180,7 +195,6 @@ generalize_target_names: $(CONTENT)
# apply kernel-agnostic convention of naming the timer and ld.lib.so
for subdir in ${call selected_content,LD_MK_DIRS}; do \
mv $$subdir/ld-hw.mk $$subdir/ld.mk; done
sed -i "s/ld-hw/ld/" src/lib/ld/hw/target.mk
sed -i "s/hw_timer_drv/timer/" src/timer/hw/target.mk
# supplement BOARD definition that normally comes form the build dir
sed -i "s/\?= unknown/:= $(BOARD)/" src/core/hw/target.mk
@@ -189,5 +203,4 @@ generalize_target_names: $(CONTENT)
sed -i "1aREQUIRES := $(ARCH)" src/core/hw/target.mk
sed -i "1aREQUIRES := $(ARCH)" src/bootstrap/hw/target.mk
sed -i "/REQUIRES/s/hw/hw $(ARCH)/" src/timer/hw/target.mk
sed -i "1aREQUIRES := $(ARCH)" src/lib/ld/hw/target.mk

View File

@@ -109,7 +109,8 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a
Cpu &cpu,
Pd &core_pd)
:
Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd, "idle" }
Thread { addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd,
Cpu_priority::min(), 0, "idle", Thread::IDLE }
{
regs->ip = (addr_t)&idle_thread_main;
@@ -120,14 +121,9 @@ Cpu::Idle_thread::Idle_thread(Board::Address_space_id_allocator &addr_space_id_a
void Cpu::schedule(Job * const job)
{
if (_id == executing_id())
_scheduler.ready(job->share());
else {
_scheduler.ready_check(job->share());
if (_scheduler.need_to_schedule())
trigger_ip_interrupt();
}
_scheduler.ready(job->share());
if (_id != executing_id() && _scheduler.need_to_schedule())
trigger_ip_interrupt();
}

View File

@@ -191,45 +191,17 @@ void Cpu_scheduler::update(time_t time)
}
void Cpu_scheduler::ready_check(Share &s1)
{
assert(_head);
ready(s1);
if (_need_to_schedule)
return;
Share * s2 = _head;
if (!s1._claim) {
_need_to_schedule = s2 == &_idle;
} else if (!_head_claims) {
_need_to_schedule = true;
} else if (s1._prio != s2->_prio) {
_need_to_schedule = s1._prio > s2->_prio;
} else {
for (
; s2 && s2 != &s1;
s2 =
Double_list<Cpu_share>::next(&s2->_claim_item) != nullptr ?
&Double_list<Cpu_share>::next(&s2->_claim_item)->payload() :
nullptr) ;
_need_to_schedule = !s2;
}
}
void Cpu_scheduler::ready(Share &s)
{
assert(!s._ready && &s != &_idle);
_need_to_schedule = true;
s._ready = 1;
s._fill = _fill;
_fills.insert_tail(&s._fill_item);
if (_head == &_idle)
_need_to_schedule = true;
if (!s._quota)
return;
@@ -239,6 +211,28 @@ void Cpu_scheduler::ready(Share &s)
_rcl[s._prio].insert_head(&s._claim_item);
else
_rcl[s._prio].insert_tail(&s._claim_item);
/*
* Check whether we need to re-schedule
*/
if (_need_to_schedule)
return;
/* current head has no quota left */
if (!_head_claims) {
_need_to_schedule = true;
return;
}
/* if current head has different priority */
if (s._prio != _head->_prio) {
_need_to_schedule = s._prio > _head->_prio;
return;
}
/* if current head has same priority, the ready share gets active */
if (s._claim)
_need_to_schedule = true;
}
@@ -246,7 +240,8 @@ void Cpu_scheduler::unready(Share &s)
{
assert(s._ready && &s != &_idle);
_need_to_schedule = true;
if (&s == _head)
_need_to_schedule = true;
s._ready = 0;
_fills.remove(&s._fill_item);
@@ -270,21 +265,15 @@ void Cpu_scheduler::remove(Share &s)
{
assert(&s != &_idle);
_need_to_schedule = true;
if (s._ready) unready(s);
if (&s == _head)
_head = nullptr;
if (s._ready)
_fills.remove(&s._fill_item);
if (!s._quota)
return;
if (s._ready)
_rcl[s._prio].remove(&s._claim_item);
else
_ucl[s._prio].remove(&s._claim_item);
_ucl[s._prio].remove(&s._claim_item);
}
@@ -292,8 +281,6 @@ void Cpu_scheduler::insert(Share &s)
{
assert(!s._ready);
_need_to_schedule = true;
if (!s._quota)
return;

View File

@@ -180,15 +180,10 @@ class Kernel::Cpu_scheduler
void timeout() { _need_to_schedule = true; }
/**
* Update head according to the consumed time
* Update head according to the current (absolute) time
*/
void update(time_t time);
/**
* Set 's1' ready and return wether this outdates current head
*/
void ready_check(Share &s1);
/**
* Set share 's' ready
*/

View File

@@ -329,6 +329,23 @@ void Thread::_call_start_thread()
/* join protection domain */
thread._pd = (Pd *) user_arg_3();
thread._ipc_init(*(Native_utcb *)user_arg_4(), *this);
/*
* Sanity check core threads!
*
* Currently, the model assumes that there is only one core
* entrypoint, which serves requests, and which can destroy
* threads and pds. If this changes, we have to inform all
* cpus about pd destructions to remove their page-tables
* from the hardware in case that a core-thread running with
* that same pd is currently active. Therefore, warn if the
* semantic changes, and additional core threads are started
* across cpu cores.
*/
if (thread._pd == &_core_pd && cpu.id() != _cpu_pool.primary_cpu().id())
Genode::raw("Error: do not start core threads"
" on CPU cores different than boot cpu");
thread._become_active();
}
@@ -369,7 +386,7 @@ void Thread::_call_restart_thread()
Thread &thread = *thread_ptr;
if (!_core && (&pd() != &thread.pd())) {
if (_type == USER && (&pd() != &thread.pd())) {
raw(*this, ": failed to lookup thread ", (unsigned)user_arg_1(),
" to restart it");
_die();
@@ -447,6 +464,18 @@ void Thread::_call_delete_thread()
}
void Thread::_call_delete_pd()
{
Genode::Kernel_object<Pd> & pd =
*(Genode::Kernel_object<Pd>*)user_arg_1();
if (_cpu->active(pd->mmu_regs))
_cpu->switch_to(_core_pd.mmu_regs);
_call_delete<Pd>();
}
void Thread::_call_await_request_msg()
{
if (_ipc_node.can_await_request()) {
@@ -793,7 +822,7 @@ void Thread::_call()
case call_id_pause_vm(): _call_pause_vm(); return;
default:
/* check wether this is a core thread */
if (!_core) {
if (_type != CORE) {
Genode::raw(*this, ": not entitled to do kernel call");
_die();
return;
@@ -805,7 +834,7 @@ void Thread::_call()
_call_new<Thread>(_addr_space_id_alloc, _user_irq_pool, _cpu_pool,
_core_pd, (unsigned) user_arg_2(),
(unsigned) _core_to_kernel_quota(user_arg_3()),
(char const *) user_arg_4());
(char const *) user_arg_4(), USER);
return;
case call_id_new_core_thread():
_call_new<Thread>(_addr_space_id_alloc, _user_irq_pool, _cpu_pool,
@@ -822,7 +851,7 @@ void Thread::_call()
*(Genode::Platform_pd *) user_arg_3(),
_addr_space_id_alloc);
return;
case call_id_delete_pd(): _call_delete<Pd>(); return;
case call_id_delete_pd(): _call_delete_pd(); return;
case call_id_new_signal_receiver(): _call_new<Signal_receiver>(); return;
case call_id_new_signal_context():
_call_new<Signal_context>(*(Signal_receiver*) user_arg_2(), user_arg_3());
@@ -857,7 +886,7 @@ void Thread::_mmu_exception()
return;
}
if (_core)
if (_type != USER)
Genode::raw(*this, " raised a fault, which should never happen ",
_fault);
@@ -874,7 +903,7 @@ Thread::Thread(Board::Address_space_id_allocator &addr_space_id_alloc,
unsigned const priority,
unsigned const quota,
char const *const label,
bool core)
Type type)
:
Kernel::Object { *this },
Cpu_job { priority, quota },
@@ -885,8 +914,8 @@ Thread::Thread(Board::Address_space_id_allocator &addr_space_id_alloc,
_ipc_node { *this },
_state { AWAITS_START },
_label { label },
_core { core },
regs { core }
_type { type },
regs { type != USER }
{ }

View File

@@ -57,6 +57,10 @@ struct Kernel::Thread_fault
*/
class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
{
public:
enum Type { USER, CORE, IDLE };
private:
/*
@@ -149,7 +153,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
capid_t _timeout_sigid { 0 };
bool _paused { false };
bool _cancel_next_await_signal { false };
bool const _core { false };
Type const _type;
Genode::Constructible<Tlb_invalidation> _tlb_invalidation {};
Genode::Constructible<Destroy> _destroy {};
@@ -230,6 +234,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
void _call_restart_thread();
void _call_yield_thread();
void _call_delete_thread();
void _call_delete_pd();
void _call_await_request_msg();
void _call_send_request_msg();
void _call_send_reply_msg();
@@ -301,7 +306,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
unsigned const priority,
unsigned const quota,
char const *const label,
bool core = false);
Type const type);
/**
* Constructor for core/kernel thread
@@ -315,7 +320,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
char const *const label)
:
Thread(addr_space_id_alloc, user_irq_pool, cpu_pool, core_pd,
Cpu_priority::min(), 0, label, true)
Cpu_priority::min(), 0, label, CORE)
{ }
~Thread();
@@ -432,6 +437,7 @@ class Kernel::Thread : private Kernel::Object, public Cpu_job, private Timeout
char const * label() const { return _label; }
Thread_fault fault() const { return _fault; }
Genode::Native_utcb *utcb() { return _utcb; }
Type type() const { return _type; }
Pd &pd() const
{

View File

@@ -77,6 +77,8 @@ class Kernel::Vm : private Kernel::Object, public Cpu_job
Kernel::Signal_context & context,
Identity & id);
~Vm();
/**
* Inject an interrupt to this VM
*

View File

@@ -22,13 +22,17 @@
using namespace Genode;
using namespace Kernel;
using Device = Board::Timer;
using Device = Board::Timer;
using counter_t = Board::Timer::Counter::access_t;
enum {
TICS_PER_MS =
Board::CORTEX_A9_PRIVATE_TIMER_CLK /
Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000
Board::CORTEX_A9_PRIVATE_TIMER_DIV / 1000,
MAX_COUNTER_VAL = ~(counter_t)0
};
@@ -79,12 +83,33 @@ time_t Timer::us_to_ticks(time_t const us) const {
time_t Timer::_duration() const
{
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;
counter_t const start_counter_val { (counter_t)_last_timeout_duration };
counter_t const curr_counter_val { _device.read<Device::Counter>() };
/*
* Calculate result depending on whether the counter already wrapped or
* not. See the comment in the implementation of '_max_value' for an
* explanation why this comparison is done instead of checking the IRQ
* status and why it is sufficient.
*/
if (curr_counter_val > start_counter_val)
return start_counter_val + (MAX_COUNTER_VAL - curr_counter_val);
return start_counter_val - curr_counter_val;
}
time_t Timer::_max_value() const { return 0xfffffffe; }
time_t Timer::_max_value() const
{
/*
* We propagate a max timeout value far lower than the one required
* by the hardware. This is because on some platforms (Qemu 4.2.1 PBXA9),
* the IRQ status register is not reliable. Sometimes, it indicates an IRQ
* too early, i.e., shortly before the counter wraps. Therefore we have to
* accomplish wrap detection via counter comparison only. Therefore, we
* have to make sure that we always read out the counter before it hits
* the max timout value again. And, therefore, the max timeout value has
* to be far away from the first value the counter has after wrapping.
*/
return MAX_COUNTER_VAL >> 1;
}

View File

@@ -87,24 +87,25 @@ void Arm_cpu::mmu_fault_status(Fsr::access_t fsr, Thread_fault & fault)
}
void Arm_cpu::switch_to(Arm_cpu::Context&, Arm_cpu::Mmu_context & o)
bool Arm_cpu::active(Arm_cpu::Mmu_context & ctx)
{
if (o.cidr == 0) return;
return (Cidr::read() == ctx.cidr);
}
Cidr::access_t cidr = Cidr::read();
if (cidr != o.cidr) {
/**
* First switch to global mappings only to prevent
* that wrong branch predicts result due to ASID
* and Page-Table not being in sync (see ARM RM B 3.10.4)
*/
Cidr::write(0);
Cpu::synchronization_barrier();
Ttbr0::write(o.ttbr0);
Cpu::synchronization_barrier();
Cidr::write(o.cidr);
Cpu::synchronization_barrier();
}
void Arm_cpu::switch_to(Arm_cpu::Mmu_context & ctx)
{
/**
* First switch to global mappings only to prevent
* that wrong branch predicts result due to ASID
* and Page-Table not being in sync (see ARM RM B 3.10.4)
*/
Cidr::write(0);
Cpu::synchronization_barrier();
Ttbr0::write(ctx.ttbr0);
Cpu::synchronization_barrier();
Cidr::write(ctx.cidr);
Cpu::synchronization_barrier();
}

View File

@@ -104,7 +104,8 @@ struct Genode::Arm_cpu : public Hw::Arm_cpu
else Tlbiall::write(0);
}
void switch_to(Context&, Mmu_context & o);
bool active(Mmu_context &);
void switch_to(Mmu_context &);
static void mmu_fault(Context & c, Kernel::Thread_fault & fault);
static void mmu_fault_status(Fsr::access_t fsr,

View File

@@ -67,7 +67,8 @@ void Kernel::Thread::Tlb_invalidation::execute() { };
void Thread::proceed(Cpu & cpu)
{
cpu.switch_to(*regs, pd().mmu_regs);
if (!cpu.active(pd().mmu_regs) && type() != CORE)
cpu.switch_to(pd().mmu_regs);
regs->cpu_exception = cpu.stack_start();
kernel_to_user_context_switch((static_cast<Cpu::Context*>(&*regs)),

View File

@@ -38,6 +38,9 @@ Vm::Vm(Irq::Pool & user_irq_pool,
}
Vm::~Vm() {}
void Vm::exception(Cpu & cpu)
{
switch(_state.cpu_exception) {

View File

@@ -15,7 +15,7 @@
push { r0 }
mrc p15, 4, r0, c1, c1, 0 /* read HCR register */
tst r0, #1 /* check VM bit */
beq _host_to_vm
beq _from_host
mov r0, #\exception_type
b _vm_to_host
.endm /* _vm_exit */
@@ -47,10 +47,27 @@ _vt_dab_entry: _vm_exit 5
_vt_irq_entry: _vm_exit 6
_vt_trp_entry: _vm_exit 8
_host_to_vm:
_from_host:
pop { r0 }
cmp r0, #0
beq _to_vm
cmp r0, #1
beq _invalidate_tlb
eret
_invalidate_tlb:
push { r3, r4 }
mrrc p15, 6, r3, r4, c2 /* save VTTBR */
mcrr p15, 6, r1, r2, c2 /* write VTTBR */
mcr p15, 0, r0, c8, c3, 0 /* TLBIALLIS */
mcrr p15, 6, r3, r4, c2 /* restore VTTBR */
eret
_to_vm:
push { r1 }
ldr r0, [sp, #1*4]
add r0, r0, #13*4
push { r2 }
add r0, r1, #13*4
ldmia r0!, { r1-r5 }
msr sp_usr, r1
mov lr, r2
@@ -115,6 +132,7 @@ _host_to_vm:
ldmia r0, {r0-r12} /* load vm's r0-r12 */
eret
_vm_to_host:
push { r0 } /* push cpu excep. */
ldr r0, [sp, #3*4] /* load vm state ptr */
@@ -218,6 +236,7 @@ _vm_to_host:
/* host kernel must jump to this point to switch to a vm */
.global hypervisor_enter_vm
hypervisor_enter_vm:
.global hypervisor_call
hypervisor_call:
hvc #0
bx lr

View File

@@ -0,0 +1,55 @@
/*
* \brief Interface between kernel and hypervisor
* \author Stefan Kalkowski
* \date 2022-06-13
*/
/*
* Copyright (C) 2022 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 _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_
#define _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_
#include <base/stdint.h>
#include <cpu/vm_state_virtualization.h>
namespace Hypervisor {
struct Host_context;
enum Call_number {
WORLD_SWITCH = 0,
TLB_INVALIDATE = 1,
};
using Call_arg = Genode::umword_t;
using Call_ret = Genode::umword_t;
extern "C"
Call_ret hypervisor_call(Call_arg call_id,
Call_arg arg0,
Call_arg arg1);
inline void invalidate_tlb(Genode::uint64_t vttbr)
{
hypervisor_call(TLB_INVALIDATE,
(vttbr & 0xffffffff),
((vttbr >> 32U) & 0xffffffff));
}
inline void switch_world(Genode::Vm_state & vm_state,
Host_context & host_state)
{
hypervisor_call(WORLD_SWITCH,
(Call_arg)&vm_state,
(Call_arg)&host_state);
}
}
#endif /* _SPEC__ARM_V7__VIRTUALIZATION_HYPERVISOR_H_ */

View File

@@ -19,6 +19,7 @@
#include <kernel/cpu.h>
#include <kernel/vm.h>
#include <kernel/main.h>
#include <spec/arm_v7/virtualization/hypervisor.h>
namespace Kernel {
@@ -41,7 +42,7 @@ namespace Kernel {
using namespace Kernel;
struct Host_context
struct Hypervisor::Host_context
{
Cpu::Ttbr_64bit::access_t vttbr;
Cpu::Hcr::access_t hcr;
@@ -61,15 +62,13 @@ struct Host_context
} vt_host_context;
extern "C" void hypervisor_enter_vm(Genode::Vm_state&, Host_context&);
static Host_context & host_context(Cpu & cpu)
static Hypervisor::Host_context & host_context(Cpu & cpu)
{
static Genode::Constructible<Host_context> host_context[NR_OF_CPUS];
static Genode::Constructible<Hypervisor::Host_context>
host_context[NR_OF_CPUS];
if (!host_context[cpu.id()].constructed()) {
host_context[cpu.id()].construct();
Host_context & c = *host_context[cpu.id()];
Hypervisor::Host_context & c = *host_context[cpu.id()];
c.sp = cpu.stack_start();
c.ttbr0 = Cpu::Ttbr0_64bit::read();
c.ttbr1 = Cpu::Ttbr1_64bit::read();
@@ -152,6 +151,15 @@ Kernel::Vm::Vm(Irq::Pool & user_irq_pool,
}
Kernel::Vm::~Vm()
{
Cpu::Ttbr_64bit::access_t vttbr =
Cpu::Ttbr_64bit::Ba::masked((Cpu::Ttbr_64bit::access_t)_id.table);
Cpu::Ttbr_64bit::Asid::set(vttbr, _id.id);
Hypervisor::invalidate_tlb(vttbr);
}
void Kernel::Vm::exception(Cpu & cpu)
{
switch(_state.cpu_exception) {
@@ -190,7 +198,7 @@ void Kernel::Vm::proceed(Cpu & cpu)
_state.esr_el2 = Cpu::Hstr::init();
_state.hpfar_el2 = Cpu::Hcr::init();
hypervisor_enter_vm(_state, host_context(cpu));
Hypervisor::switch_world(_state, host_context(cpu));
}

View File

@@ -26,12 +26,15 @@ Genode::Cpu::Context::Context(bool privileged)
}
void Genode::Cpu::switch_to(Context&, Mmu_context & mmu_context)
bool Genode::Cpu::active(Mmu_context & mmu_context)
{
if (mmu_context.id() == 0) return;
return (mmu_context.id() == Ttbr::Asid::get(Ttbr0_el1::read()));
}
if (mmu_context.id() != Ttbr::Asid::get(Ttbr0_el1::read()))
Ttbr0_el1::write(mmu_context.ttbr);
void Genode::Cpu::switch_to(Mmu_context & mmu_context)
{
Ttbr0_el1::write(mmu_context.ttbr);
}

View File

@@ -99,7 +99,8 @@ struct Genode::Cpu : Hw::Arm_64_cpu
return Ttbr::Asid::get(ttbr) & 0xffff; }
};
void switch_to(Context&, Mmu_context &);
bool active(Mmu_context &);
void switch_to(Mmu_context &);
static void mmu_fault(Context &, Kernel::Thread_fault &);

View File

@@ -55,6 +55,16 @@ void Thread::exception(Cpu & cpu)
" ISS=", Cpu::Esr::Iss::get(esr),
" ip=", (void*)regs->ip);
};
/*
* If the machine exception is caused by a non-privileged
* component, mark it dead, and continue execution.
*/
if (regs->exception_type == Cpu::SYNC_LEVEL_EL0) {
Genode::raw("Will freeze thread ", *this);
_become_inactive(DEAD);
return;
}
break;
}
default:
@@ -75,10 +85,14 @@ void Thread::exception(Cpu & cpu)
void Kernel::Thread::Tlb_invalidation::execute() { };
bool Kernel::Pd::invalidate_tlb(Cpu &, addr_t addr, size_t size)
bool Kernel::Pd::invalidate_tlb(Cpu & cpu, addr_t addr, size_t size)
{
using namespace Genode;
/* only apply to the active cpu */
if (cpu.id() != Cpu::executing_id())
return false;
/**
* The kernel part of the address space is mapped as global
* therefore we have to invalidate it differently
@@ -108,7 +122,9 @@ bool Kernel::Pd::invalidate_tlb(Cpu &, addr_t addr, size_t size)
void Thread::proceed(Cpu & cpu)
{
cpu.switch_to(*regs, pd().mmu_regs);
if (!cpu.active(pd().mmu_regs) && type() != CORE)
cpu.switch_to(pd().mmu_regs);
kernel_to_user_context_switch((static_cast<Cpu::Context*>(&*regs)),
(void*)cpu.stack_start());
}

View File

@@ -22,24 +22,34 @@
.global hypervisor_exception_vector
hypervisor_exception_vector:
.rept 16
add sp, sp, #-16 /* push x0, x1 to stack */
stp x0, x1, [sp]
mrs x1, hcr_el2 /* read HCR register */
tst x1, #1 /* check VM bit */
beq _host_to_vm /* if VM bit is not set, switch to VM */
ldr x0, [sp, #32] /* otherwise, load vm_state pointer */
adr x1, . /* hold exception vector offset in x1 */
and x1, x1, #0xf80
b _vm_to_host
add sp, sp, #-16 /* push x29, x30 to stack */
stp x29, x30, [sp]
mrs x30, hcr_el2 /* read HCR register */
tst x30, #1 /* check VM bit */
beq _from_host /* if VM bit is not set, its a host call */
ldr x29, [sp, #32] /* otherwise, load vm_state pointer */
adr x30, . /* hold exception vector offset in x30 */
and x30, x30, #0xf80
b _from_vm
.balign 128
.endr
_host_to_vm:
_from_host:
ldp x29, x30, [sp], #2*8 /* pop x29, x30 from stack */
cmp x0, #0
beq _to_vm
cmp x0, #1
beq _invalidate_tlb
eret
add sp, sp, #-16 /* push arg2 (vm pic state) to stack */
str x2, [sp]
_to_vm:
add sp, sp, #-16 /* push arg1/2 (vm/host state to stack */
stp x1, x2, [sp]
add sp, sp, #-16 /* push arg3 (vm pic state) to stack */
str x3, [sp]
msr vttbr_el2, x3 /* stage2 table pointer was arg3 */
msr vttbr_el2, x4 /* stage2 table pointer was arg4 */
mov x0, x1
add x0, x0, #31*8 /* skip x0...x30, loaded later */
@@ -179,27 +189,38 @@ _host_to_vm:
eret
_vm_to_host:
_invalidate_tlb:
msr vttbr_el2, x1
tlbi vmalle1is
msr vttbr_el2, xzr
eret
_from_vm:
/*********************
** Save vm context **
*********************/
/** general-purpose register **/
add x0, x0, #2*8 /* skip x0 and x1 for now */
stp x2, x3, [x0], #2*8
stp x4, x5, [x0], #2*8
stp x6, x7, [x0], #2*8
stp x8, x9, [x0], #2*8
stp x10, x11, [x0], #2*8
stp x12, x13, [x0], #2*8
stp x14, x15, [x0], #2*8
stp x16, x17, [x0], #2*8
stp x18, x19, [x0], #2*8
stp x20, x21, [x0], #2*8
stp x22, x23, [x0], #2*8
stp x24, x25, [x0], #2*8
stp x26, x27, [x0], #2*8
stp x0, x1, [x29], #2*8
stp x2, x3, [x29], #2*8
stp x4, x5, [x29], #2*8
stp x6, x7, [x29], #2*8
stp x8, x9, [x29], #2*8
stp x10, x11, [x29], #2*8
stp x12, x13, [x29], #2*8
stp x14, x15, [x29], #2*8
stp x16, x17, [x29], #2*8
stp x18, x19, [x29], #2*8
stp x20, x21, [x29], #2*8
stp x22, x23, [x29], #2*8
stp x24, x25, [x29], #2*8
stp x26, x27, [x29], #2*8
mov x0, x29
mov x1, x30
ldp x29, x30, [sp], #2*8 /* pop x29, x30 from stack */
stp x28, x29, [x0], #2*8
str x30, [x0], #1*8
@@ -284,11 +305,8 @@ _vm_to_host:
mov x0, #0b111
msr cnthctl_el2, x0
ldp x0, x1, [sp], #2*8 /* pop x0, x1 from stack */
ldr x29, [sp], #2*8 /* pop vm pic state from stack */
ldp x2, x30, [sp], #2*8 /* pop vm, and host state from stack */
stp x0, x1, [x2] /* save x0, x1 to vm state */
ldr x29, [sp], #2*8 /* pop vm pic state from stack */
ldp x2, x30, [sp], #2*8 /* pop vm, and host state from stack */
/**********************
@@ -364,6 +382,7 @@ _vm_to_host:
eret
/* host kernel must jump to this point to switch to a vm */
.global hypervisor_enter_vm
hypervisor_enter_vm:
.global hypervisor_call
hypervisor_call:
hvc #0
ret

View File

@@ -0,0 +1,52 @@
/*
* \brief Interface between kernel and hypervisor
* \author Stefan Kalkowski
* \date 2022-06-13
*/
/*
* Copyright (C) 2022 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 _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_
#define _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_
#include <base/stdint.h>
namespace Hypervisor {
enum Call_number {
WORLD_SWITCH = 0,
TLB_INVALIDATE = 1,
};
using Call_arg = Genode::umword_t;
using Call_ret = Genode::umword_t;
extern "C"
Call_ret hypervisor_call(Call_arg call_id,
Call_arg arg0,
Call_arg arg1,
Call_arg arg2,
Call_arg arg3);
inline void invalidate_tlb(Call_arg ttbr)
{
hypervisor_call(TLB_INVALIDATE, ttbr, 0, 0, 0);
}
inline void switch_world(Call_arg guest_state,
Call_arg host_state,
Call_arg pic_state,
Call_arg ttbr)
{
hypervisor_call(WORLD_SWITCH, guest_state, host_state, pic_state, ttbr);
}
}
#endif /* _SPEC__ARM_V8__VIRTUALIZATION_HYPERVISOR_H_ */

View File

@@ -23,14 +23,12 @@
#include <kernel/vm.h>
#include <kernel/main.h>
#include <spec/arm_v8/virtualization/hypervisor.h>
using Genode::addr_t;
using Kernel::Cpu;
using Kernel::Vm;
extern void * kernel_stack;
extern "C" void hypervisor_enter_vm(addr_t vm, addr_t host,
addr_t pic, addr_t guest_table);
static Genode::Vm_state & host_context(Cpu & cpu)
{
@@ -154,6 +152,15 @@ Vm::Vm(Irq::Pool & user_irq_pool,
}
Vm::~Vm()
{
Cpu::Vttbr_el2::access_t vttbr_el2 =
Cpu::Vttbr_el2::Ba::masked((Cpu::Vttbr_el2::access_t)_id.table);
Cpu::Vttbr_el2::Asid::set(vttbr_el2, _id.id);
Hypervisor::invalidate_tlb(vttbr_el2);
}
void Vm::exception(Cpu & cpu)
{
switch (_state.exception_type) {
@@ -197,7 +204,7 @@ void Vm::proceed(Cpu & cpu)
addr_t pic = Hw::Mm::el2_addr(&_vcpu_context.pic);
addr_t host = Hw::Mm::el2_addr(&host_context(cpu));
hypervisor_enter_vm(guest, host, pic, vttbr_el2);
Hypervisor::switch_world(guest, host, pic, vttbr_el2);
}

View File

@@ -115,11 +115,14 @@ class Genode::Cpu : public Arm_v7_cpu
*/
static unsigned executing_id() { return Mpidr::Aff_0::get(Mpidr::read()); }
void switch_to(Context &, Mmu_context & mmu_context)
bool active(Mmu_context & mmu_context)
{
if (mmu_context.id() && (Ttbr0_64bit::read() != mmu_context.ttbr0))
Ttbr0_64bit::write(mmu_context.ttbr0);
return (Ttbr0_64bit::read() == mmu_context.ttbr0);
}
void switch_to(Mmu_context & mmu_context)
{
Ttbr0_64bit::write(mmu_context.ttbr0);
}
};

View File

@@ -53,22 +53,16 @@ Mmu_context::~Mmu_context()
}
bool Genode::Cpu::active(Mmu_context & context)
{
return Satp::read() == context.satp;
}
void Genode::Cpu::switch_to(Mmu_context & context)
{
/*
* The sstatus register defines to which privilege level
* the machin returns when doing an exception return
*/
bool user = Satp::Asid::get(context.satp);
Sstatus::access_t v = Sstatus::read();
Sstatus::Spp::set(v, user ? 0 : 1);
Sstatus::write(v);
/* change the translation table when necessary */
if (user) {
Satp::write(context.satp);
sfence();
}
Satp::write(context.satp);
sfence();
}

View File

@@ -97,6 +97,7 @@ class Genode::Cpu : public Hw::Riscv_cpu
static void invalidate_tlb_by_pid(unsigned const /* pid */) { sfence(); }
bool active(Mmu_context & context);
void switch_to(Mmu_context & context);
static void mmu_fault(Context & c, Kernel::Thread_fault & f);

View File

@@ -100,7 +100,16 @@ void Kernel::Thread::_call_cache_invalidate_data_region() { }
void Kernel::Thread::proceed(Cpu & cpu)
{
cpu.switch_to(_pd->mmu_regs);
/*
* The sstatus register defines to which privilege level
* the machine returns when doing an exception return
*/
Cpu::Sstatus::access_t v = Cpu::Sstatus::read();
Cpu::Sstatus::Spp::set(v, (type() == USER) ? 0 : 1);
Cpu::Sstatus::write(v);
if (!cpu.active(pd().mmu_regs) && type() != CORE)
cpu.switch_to(_pd->mmu_regs);
asm volatile("csrw sscratch, %1 \n"
"mv x31, %0 \n"

View File

@@ -111,11 +111,20 @@ extern void const * const kernel_stack;
extern Genode::size_t const kernel_stack_size;
void Genode::Cpu::switch_to(Context & context, Mmu_context &mmu_context)
bool Genode::Cpu::active(Mmu_context &mmu_context)
{
if ((context.cs != 0x8) && (mmu_context.cr3 != Cr3::read()))
Cr3::write(mmu_context.cr3);
return (mmu_context.cr3 == Cr3::read());
}
void Genode::Cpu::switch_to(Mmu_context &mmu_context)
{
Cr3::write(mmu_context.cr3);
}
void Genode::Cpu::switch_to(Context & context)
{
tss.ist[0] = (addr_t)&context + sizeof(Genode::Cpu_state);
addr_t const stack_base = reinterpret_cast<addr_t>(&kernel_stack);

View File

@@ -126,7 +126,10 @@ class Genode::Cpu : public Hw::X86_64_cpu
*
* \param context next CPU context
*/
void switch_to(Context & context, Mmu_context &mmu_context);
void switch_to(Context & context);
bool active(Mmu_context &mmu_context);
void switch_to(Mmu_context &mmu_context);
static void mmu_fault(Context & regs, Kernel::Thread_fault & fault);

View File

@@ -43,7 +43,10 @@ void Kernel::Thread::_call_cache_invalidate_data_region() { }
void Kernel::Thread::proceed(Cpu & cpu)
{
cpu.switch_to(*regs, pd().mmu_regs);
if (!cpu.active(pd().mmu_regs) && type() != CORE)
cpu.switch_to(pd().mmu_regs);
cpu.switch_to(*regs);
asm volatile("fxrstor (%1) \n"
"mov %0, %%rsp \n"

View File

@@ -1,2 +0,0 @@
TARGET = ld-hw
LIBS = ld-hw

View File

@@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2014-2017 Genode Labs GmbH
* Copyright (C) 2014-2022 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.
@@ -18,125 +18,110 @@
/* core includes */
#include <kernel/cpu_scheduler.h>
/*
* Utilities
*/
using namespace Genode;
using namespace Kernel;
using Genode::size_t;
using Genode::addr_t;
using Genode::construct_at;
using Kernel::Cpu_share;
using Kernel::Cpu_scheduler;
struct Data
struct Main
{
Cpu_share idle;
Cpu_scheduler scheduler;
char shares[9][sizeof(Cpu_share)];
enum { MAX_SHARES = 10 };
Data() : idle(0, 0), scheduler(idle, 1000, 100) { }
Constructible<Cpu_share> shares[MAX_SHARES] {};
Cpu_scheduler scheduler;
time_t current_time { 0 };
Cpu_share & _idle()
{
if (!shares[0].constructed()) shares[0].construct(0, 0);
return *shares[0];
}
Main() : scheduler(_idle(), 1000, 100) { }
void done()
{
Genode::log("done");
while (1) ;
}
unsigned share_id(Cpu_share & share)
{
for (unsigned i = 0; i < MAX_SHARES; i++)
if (shares[i].constructed() && (&*shares[i] == &share))
return i;
return ~0U;
}
Cpu_share & share(unsigned const id)
{
return *shares[id];
}
void create(unsigned const id)
{
switch (id) {
case 1: shares[id].construct(2, 230); break;
case 2: shares[id].construct(0, 170); break;
case 3: shares[id].construct(3, 110); break;
case 4: shares[id].construct(1, 90); break;
case 5: shares[id].construct(3, 120); break;
case 6: shares[id].construct(3, 0); break;
case 7: shares[id].construct(2, 180); break;
case 8: shares[id].construct(2, 100); break;
case 9: shares[id].construct(2, 0); break;
default: return;
}
scheduler.insert(*shares[id]);
}
void destroy(unsigned const id)
{
if (!id || id >= MAX_SHARES)
return;
scheduler.remove(share(id));
shares[id].destruct();
}
unsigned time()
{
return scheduler.quota() - scheduler.residual();
}
void update_check(unsigned const l, unsigned const c, unsigned const t,
unsigned const s, unsigned const q)
{
current_time += c;
scheduler.update(current_time);
unsigned const st = time();
if (t != st) {
log("wrong time ", st, " in line ", l);
done();
}
Cpu_share & hs = scheduler.head();
unsigned const hq = scheduler.head_quota();
if (&hs != &share(s)) {
log("wrong share ", share_id(hs), " in line ", l);
done();
}
if (hq != q) {
log("wrong quota ", hq, " in line ", l);
done();
}
}
void ready_check(unsigned const l, unsigned const s, bool const x)
{
scheduler.ready(share(s));
if (scheduler.need_to_schedule() != x) {
log("wrong check result ", scheduler.need_to_schedule(), " in line ", l);
done();
}
}
void test();
};
Data * data()
{
static Data d;
return &d;
}
void done()
{
Genode::log("done");
while (1) ;
}
unsigned share_id(void * const pointer)
{
addr_t const address = (addr_t)pointer;
addr_t const base = (addr_t)data()->shares;
if (address < base || address >= base + sizeof(data()->shares)) {
return 0; }
return (unsigned)((address - base) / sizeof(Cpu_share) + 1);
}
Cpu_share * share(unsigned const id)
{
if (!id) { return &data()->idle; }
return reinterpret_cast<Cpu_share *>(&data()->shares[id - 1]);
}
void create(unsigned const id)
{
Cpu_share * const s = share(id);
void * const p = (void *)s;
switch (id) {
case 1: construct_at<Cpu_share>(p, 2, 230); break;
case 2: construct_at<Cpu_share>(p, 0, 170); break;
case 3: construct_at<Cpu_share>(p, 3, 110); break;
case 4: construct_at<Cpu_share>(p, 1, 90); break;
case 5: construct_at<Cpu_share>(p, 3, 120); break;
case 6: construct_at<Cpu_share>(p, 3, 0); break;
case 7: construct_at<Cpu_share>(p, 2, 180); break;
case 8: construct_at<Cpu_share>(p, 2, 100); break;
case 9: construct_at<Cpu_share>(p, 2, 0); break;
default: return;
}
data()->scheduler.insert(*s);
}
void destroy(unsigned const id)
{
Cpu_share * const s = share(id);
data()->scheduler.remove(*s);
s->~Cpu_share();
}
unsigned time()
{
return data()->scheduler.quota() -
data()->scheduler.residual();
}
void update_check(unsigned const l, unsigned const c, unsigned const t,
unsigned const s, unsigned const q)
{
data()->scheduler.update(c);
unsigned const st = time();
if (t != st) {
Genode::log("wrong time ", st, " in line ", l);
done();
}
Cpu_share &hs = data()->scheduler.head();
unsigned const hq = data()->scheduler.head_quota();
if (&hs != share(s)) {
unsigned const hi = share_id(&hs);
Genode::log("wrong share ", hi, " in line ", l);
done();
}
if (hq != q) {
Genode::log("wrong quota ", hq, " in line ", l);
done();
}
}
void ready_check(unsigned const l, unsigned const s, bool const x)
{
data()->scheduler.ready_check(*share(s));
if (data()->scheduler.need_to_schedule() != x) {
Genode::log("wrong check result ", data()->scheduler.need_to_schedule(), " in line ", l);
done();
}
}
/*
* Shortcuts for all basic operations that the test consists of
@@ -144,10 +129,10 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
#define C(s) create(s);
#define D(s) destroy(s);
#define A(s) data()->scheduler.ready(*share(s));
#define I(s) data()->scheduler.unready(*share(s));
#define Y data()->scheduler.yield();
#define Q(s, q) data()->scheduler.quota(*share(s), q);
#define A(s) scheduler.ready(share(s));
#define I(s) scheduler.unready(share(s));
#define Y scheduler.yield();
#define Q(s, q) scheduler.quota(share(s), q);
#define U(c, t, s, q) update_check(__LINE__, c, t, s, q);
#define O(s) ready_check(__LINE__, s, true);
#define N(s) ready_check(__LINE__, s, false);
@@ -157,6 +142,13 @@ void ready_check(unsigned const l, unsigned const s, bool const x)
* Main routine
*/
void Component::construct(Genode::Env &)
{
static Main main;
main.test();
}
void Main::test()
{
/*
* Step-by-step testing

View File

@@ -1,8 +1,7 @@
FROM_BASE_LINUX := etc src/lib/syscall src/lib/lx_hybrid lib/import include
FROM_BASE_LINUX_AND_BASE := lib/mk src/lib/base src/include
FROM_BASE := src/lib/timeout
FROM_BASE_LINUX_AND_BASE := src/lib/base src/include
content: $(FROM_BASE_LINUX) $(FROM_BASE_LINUX_AND_BASE) $(FROM_BASE) LICENSE
content: $(FROM_BASE_LINUX) $(FROM_BASE_LINUX_AND_BASE) LICENSE
$(FROM_BASE_LINUX):
mkdir -p $@
@@ -13,9 +12,30 @@ $(FROM_BASE_LINUX_AND_BASE):
cp -r $(GENODE_DIR)/repos/base/$@/* $@
cp -r $(REP_DIR)/$@/* $@
$(FROM_BASE):
BASE_LIB_MK_CONTENT := \
$(addprefix lib/mk/,base-common.inc timeout.mk)
content: $(BASE_LIB_MK_CONTENT)
$(BASE_LIB_MK_CONTENT):
mkdir -p $(dir $@)
cp $(GENODE_DIR)/repos/base/$@ $@
content: src/lib/timeout
src/lib/timeout:
mkdir -p $@
cp -r $(GENODE_DIR)/repos/base/$@/* $@
BASE_LINUX_LIB_MK_CONTENT := \
$(addprefix lib/mk/,lx_hybrid.mk base-linux.inc base-linux-common.mk) \
$(foreach S,arm arm_64 x86_32 x86_64,lib/mk/spec/$S/syscall-linux.mk)
content: $(BASE_LINUX_LIB_MK_CONTENT)
$(BASE_LINUX_LIB_MK_CONTENT):
mkdir -p $(dir $@)
cp $(REP_DIR)/$@ $@
LICENSE:
cp $(GENODE_DIR)/LICENSE $@

View File

@@ -1 +1 @@
2022-04-12 dcb2c9200b333adb17f9a8737620cbd84f641408
2022-10-11 4544924c73b2ee1d8d2717672320f14732807267

View File

@@ -10,7 +10,6 @@ content:
mv lib/mk/spec/$$spec/ld-linux.mk lib/mk/spec/$$spec/ld.mk; done;
sed -i "/TARGET/s/core-linux/core/" src/core/linux/target.mk
sed -i "s/BOARD.*unknown/BOARD := linux/" lib/mk/core-linux.inc
sed -i "s/ld-linux/ld/" src/lib/ld/linux/target.mk
sed -i "s/linux_timer_drv/timer/" src/timer/linux/target.mk
rm -rf src/lib/initramfs
rm -rf src/initramfs

View File

@@ -1 +1 @@
2022-05-24 4aea382035415c79bf5d551642ebfa64d42e4d21
2022-10-11 d7e12d81f12f081bb7c00233c18f3c8ac2f00d67

View File

@@ -5,14 +5,14 @@ REQUIRES = x86_64
INITRAMFS = initramfs
INITRAMFS_SRC_C = init.c
EXT_OBJECTS += $(BUILD_BASE_DIR)/lib/initramfs/$(INITRAMFS)
EXT_OBJECTS += $(BUILD_BASE_DIR)/initramfs/$(INITRAMFS)
$(TARGET): $(INITRAMFS)
$(INITRAMFS): $(INITRAMFS_SRC_C)
$(MSG_BUILD)$(INITRAMFS)
$(VERBOSE)gcc $^ -O0 $(CC_MARCH) -Wall -W -Wextra -Werror -std=gnu99 -o $@ -Wl,-O3 -Wl,--as-needed -static
$(VERBOSE)ln -sf $(BUILD_BASE_DIR)/lib/initramfs/$(INITRAMFS) $(BUILD_BASE_DIR)/bin/
$(VERBOSE)ln -sf $(BUILD_BASE_DIR)/initramfs/$(INITRAMFS) $(BUILD_BASE_DIR)/bin/
clean_initramfs:
$(VERBOSE)rm -rf $(INITRAMFS)

View File

@@ -172,6 +172,24 @@ void Region_map_mmap::_add_to_rmap(Region const &region)
}
/*
* Tracing must be inhibited in attach/detach as RPC trace points may trigger
* attachment of trace dataspaces, which would result in nested mutex
* acquisition.
*/
namespace Genode { extern bool inhibit_tracing; }
struct Inhibit_tracing_guard
{
bool old_value = inhibit_tracing;
Inhibit_tracing_guard() { inhibit_tracing = true; }
~Inhibit_tracing_guard() { inhibit_tracing = old_value; }
};
Region_map::Local_addr Region_map_mmap::attach(Dataspace_capability ds,
size_t size, off_t offset,
bool use_local_addr,
@@ -180,6 +198,8 @@ Region_map::Local_addr Region_map_mmap::attach(Dataspace_capability ds,
{
Mutex::Guard mutex_guard(mutex());
Inhibit_tracing_guard it_guard { };
/* only support attach_at for sub RM sessions */
if (_sub_rm && !use_local_addr) {
error("Region_map_mmap::attach: attaching w/o local addr not supported");
@@ -325,6 +345,8 @@ void Region_map_mmap::detach(Region_map::Local_addr local_addr)
{
Mutex::Guard mutex_guard(mutex());
Inhibit_tracing_guard it_guard { };
/*
* Cases
*

View File

@@ -1,4 +0,0 @@
TARGET = ld-linux.lib
LIBS = ld-linux
BUILD_ARTIFACTS := ld-linux.lib.so

View File

@@ -260,6 +260,30 @@ namespace Nova {
*/
enum Pd_op { TRANSFER_QUOTA = 0U, PD_DEBUG = 2U };
class Gsi_flags
{
private:
uint8_t _value { 0 };
public:
enum Mode { HIGH, LOW, EDGE };
Gsi_flags() { }
Gsi_flags(Mode m)
{
switch (m) {
case HIGH: _value = 0b110; break; /* level-high */
case LOW: _value = 0b111; break; /* level-low */
case EDGE: _value = 0b100; break; /* edge-triggered */
}
}
uint8_t value() const { return _value; }
};
class Descriptor
{

View File

@@ -457,12 +457,12 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
mword_t &msi_addr, mword_t &msi_data,
mword_t si = ~0UL)
mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
{
msi_addr = dev;
msi_data = cpu;
return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
}

View File

@@ -402,11 +402,11 @@ namespace Nova {
ALWAYS_INLINE
inline uint8_t assign_gsi(mword_t sm, mword_t dev, mword_t cpu,
mword_t &msi_addr, mword_t &msi_data,
mword_t si = ~0UL)
mword_t si = ~0UL, Gsi_flags flags = Gsi_flags())
{
msi_addr = dev;
msi_data = cpu;
return syscall_5(NOVA_ASSIGN_GSI, 0, sm, msi_addr, msi_data, si);
return syscall_5(NOVA_ASSIGN_GSI, flags.value(), sm, msi_addr, msi_data, si);
}
}
#endif /* _INCLUDE__SPEC__64BIT__NOVA__SYSCALLS_H_ */

View File

@@ -1 +1 @@
33a2fa953ec52b0f63b921f4d33d68891c0aada0
9ad770935115d201863fd83924e4684b14b8b56f

View File

@@ -4,7 +4,7 @@ DOWNLOADS := nova.git
# r10 branch
URL(nova) := https://github.com/alex-ab/NOVA.git
REV(nova) := 00dc49bc18e7f72a9c85487e8f94fd859511d89d
REV(nova) := a34076e7b8d48d08c2edee7754eadad8b6ea5312
DIR(nova) := src/kernel/nova
PATCHES := $(sort $(wildcard $(REP_DIR)/patches/*.patch))

View File

@@ -1,5 +1,8 @@
FROM_BASE_NOVA := etc include
FROM_BASE := lib/mk/timeout.mk src/lib/timeout
# base-nova.lib.a depends on timeout.lib.a, which includes base/internal/gloabls.h
FROM_BASE := lib/mk/timeout.mk src/lib/timeout \
src/include/base/internal/globals.h
content: $(FROM_BASE_NOVA) $(FROM_BASE) LICENSE

View File

@@ -1 +1 @@
2022-05-24 91bc8d51bbe703d56f5671019d14e4636f21bf1f
2022-10-11 4458ea63a69ae070e19a3cb09a403137755d2cb0

View File

@@ -15,8 +15,7 @@ src/kernel/nova: src/kernel
content:
for spec in x86_32 x86_64; do \
mv lib/mk/spec/$$spec/ld-nova.mk lib/mk/spec/$$spec/ld.mk; \
mv lib/mk/spec/$$spec/ld-nova.mk lib/mk/spec/$$spec/ld.mk; \
done;
sed -i "s/ld-nova/ld/" src/lib/ld/nova/target.mk
sed -i "s/nova_timer_drv/timer/" src/timer/nova/target.mk

View File

@@ -1 +1 @@
2022-05-24 8b59a28ade1392bae4aa772bbead1584a2dde1de
2022-10-11 574204b7d442811236bba60e4fe3f79e34fe9985

View File

@@ -13,7 +13,9 @@
#ifndef _CORE__INCLUDE__IRQ_OBJECT_H_
#define _CORE__INCLUDE__IRQ_OBJECT_H_
namespace Genode { class Irq_object; }
#include <nova/syscall-generic.h> /* Gsi_flags */
namespace Genode { class Irq_object; class Irq_args; }
class Genode::Irq_object
{
@@ -26,22 +28,24 @@ class Genode::Irq_object
addr_t _msi_data;
addr_t _device_phys = 0; /* PCI config extended address */
Nova::Gsi_flags _gsi_flags { };
enum { KERNEL_CAP_COUNT_LOG2 = 0 };
Genode::addr_t irq_sel() const { return _kernel_caps; }
addr_t irq_sel() const { return _kernel_caps; }
public:
Irq_object();
~Irq_object();
Genode::addr_t msi_address() const { return _msi_addr; }
Genode::addr_t msi_value() const { return _msi_data; }
addr_t msi_address() const { return _msi_addr; }
addr_t msi_value() const { return _msi_data; }
void sigh(Signal_context_capability cap);
void ack_irq();
void start(unsigned irq, Genode::addr_t);
void start(unsigned irq, addr_t, Irq_args const &);
};
#endif /* _CORE__INCLUDE__IRQ_OBJECT_H_ */

View File

@@ -18,6 +18,7 @@
/* core includes */
#include <irq_root.h>
#include <irq_args.h>
#include <platform.h>
/* NOVA includes */
@@ -27,13 +28,12 @@
using namespace Genode;
static bool irq_ctrl(Genode::addr_t irq_sel,
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
Genode::addr_t sig_sel, Genode::addr_t virt_addr = 0)
static bool irq_ctrl(addr_t irq_sel, addr_t &msi_addr, addr_t &msi_data,
addr_t sig_sel, Nova::Gsi_flags flags, addr_t virt_addr)
{
/* assign IRQ to CPU && request msi data to be used by driver */
uint8_t res = Nova::assign_gsi(irq_sel, virt_addr, boot_cpu(),
msi_addr, msi_data, sig_sel);
msi_addr, msi_data, sig_sel, flags);
if (res != Nova::NOVA_OK)
error("setting up MSI failed - error ", res);
@@ -46,30 +46,28 @@ static bool irq_ctrl(Genode::addr_t irq_sel,
}
static bool associate(Genode::addr_t irq_sel,
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
Genode::Signal_context_capability sig_cap,
Genode::addr_t virt_addr = 0)
{
return irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(),
virt_addr);
}
static void deassociate(Genode::addr_t irq_sel)
static bool associate_gsi(addr_t irq_sel, Signal_context_capability sig_cap,
Nova::Gsi_flags gsi_flags)
{
addr_t dummy1 = 0, dummy2 = 0;
if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel))
return irq_ctrl(irq_sel, dummy1, dummy2, sig_cap.local_name(), gsi_flags, 0);
}
static void deassociate(addr_t irq_sel)
{
addr_t dummy1 = 0, dummy2 = 0;
if (!irq_ctrl(irq_sel, dummy1, dummy2, irq_sel, Nova::Gsi_flags(), 0))
warning("Irq could not be de-associated");
}
static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
Genode::addr_t &msi_addr, Genode::addr_t &msi_data,
Genode::Signal_context_capability sig_cap)
static bool associate_msi(addr_t irq_sel, addr_t phys_mem, addr_t &msi_addr,
addr_t &msi_data, Signal_context_capability sig_cap)
{
return platform().region_alloc().alloc_aligned(4096, 12).convert<bool>(
return platform().region_alloc().alloc_aligned(4096, 12).convert<bool>(
[&] (void *virt_ptr) {
@@ -89,7 +87,7 @@ static bool msi(Genode::addr_t irq_sel, Genode::addr_t phys_mem,
}
/* try to assign MSI to device */
bool res = associate(irq_sel, msi_addr, msi_data, sig_cap, virt_addr);
bool res = irq_ctrl(irq_sel, msi_addr, msi_data, sig_cap.local_name(), Nova::Gsi_flags(), virt_addr);
unmap_local(Nova::Mem_crd(virt_addr >> 12, 0, Rights(true, true, true)));
platform().region_alloc().free(virt_ptr, 4096);
@@ -118,11 +116,12 @@ void Irq_object::sigh(Signal_context_capability cap)
return;
}
/* associate GSI or MSI to device belonging to device_phys */
bool ok = false;
if (_device_phys)
ok = msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
ok = associate_msi(irq_sel(), _device_phys, _msi_addr, _msi_data, cap);
else
ok = associate(irq_sel(), _msi_addr, _msi_data, cap);
ok = associate_gsi(irq_sel(), cap, _gsi_flags);
if (!ok) {
deassociate(irq_sel());
@@ -141,7 +140,7 @@ void Irq_object::ack_irq()
}
void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
void Irq_object::start(unsigned irq, addr_t const device_phys, Irq_args const &irq_args)
{
/* map IRQ SM cap from kernel to core at irq_sel selector */
using Nova::Obj_crd;
@@ -158,12 +157,29 @@ void Irq_object::start(unsigned irq, Genode::addr_t const device_phys)
throw Service_denied();
}
/* initialize GSI IRQ flags */
auto gsi_flags = [] (Irq_args const &args) {
if (args.trigger() == Irq_session::TRIGGER_UNCHANGED
|| args.polarity() == Irq_session::POLARITY_UNCHANGED)
return Nova::Gsi_flags();
if (args.trigger() == Irq_session::TRIGGER_EDGE)
return Nova::Gsi_flags(Nova::Gsi_flags::EDGE);
if (args.polarity() == Irq_session::POLARITY_HIGH)
return Nova::Gsi_flags(Nova::Gsi_flags::HIGH);
else
return Nova::Gsi_flags(Nova::Gsi_flags::LOW);
};
_gsi_flags = gsi_flags(irq_args);
/* associate GSI or MSI to device belonging to device_phys */
bool ok = false;
if (device_phys)
ok = msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
ok = associate_msi(irq_sel(), device_phys, _msi_addr, _msi_data, _sigh_cap);
else
ok = associate(irq_sel(), _msi_addr, _msi_data, _sigh_cap);
ok = associate_gsi(irq_sel(), _sigh_cap, _gsi_flags);
if (!ok)
throw Service_denied();
@@ -212,7 +228,9 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
:
_irq_number(~0U), _irq_alloc(irq_alloc), _irq_object()
{
long irq_number = Arg_string::find_arg(args, "irq_number").long_value(-1);
Irq_args const irq_args(args);
long irq_number = irq_args.irq_number();
long device_phys = Arg_string::find_arg(args, "device_config_phys").long_value(0);
if (device_phys) {
@@ -232,7 +250,7 @@ Irq_session_component::Irq_session_component(Range_allocator &irq_alloc,
_irq_number = (unsigned)irq_number;
_irq_object.start(_irq_number, device_phys);
_irq_object.start(_irq_number, device_phys, irq_args);
}
@@ -241,7 +259,7 @@ Irq_session_component::~Irq_session_component()
if (_irq_number == ~0U)
return;
Genode::addr_t free_irq = _irq_number;
addr_t free_irq = _irq_number;
_irq_alloc.free((void *)free_irq);
}
@@ -252,13 +270,13 @@ void Irq_session_component::ack_irq()
}
void Irq_session_component::sigh(Genode::Signal_context_capability cap)
void Irq_session_component::sigh(Signal_context_capability cap)
{
_irq_object.sigh(cap);
}
Genode::Irq_session::Info Irq_session_component::info()
Irq_session::Info Irq_session_component::info()
{
if (!_irq_object.msi_address() || !_irq_object.msi_value())
return { .type = Info::Type::INVALID, .address = 0, .value = 0 };

View File

@@ -1,2 +0,0 @@
TARGET = ld-nova
LIBS = ld-nova

View File

@@ -19,8 +19,7 @@ src/kernel/okl4: src/kernel
content:
for spec in x86_32; do \
mv lib/mk/spec/$$spec/ld-okl4.mk lib/mk/spec/$$spec/ld.mk; \
mv lib/mk/spec/$$spec/ld-okl4.mk lib/mk/spec/$$spec/ld.mk; \
done;
sed -i "s/ld-okl4/ld/" src/lib/ld/okl4/target.mk
sed -i "s/pit_timer_drv/timer/" src/timer/pit/target.inc

View File

@@ -1 +1 @@
2022-05-24 3b2acba4ebd649394e26217802598cf650a4b226
2022-10-11 b81b8b94731cda35017a740b0110ff4e8e233e07

View File

@@ -1,2 +0,0 @@
TARGET = ld-okl4
LIBS = ld-okl4

View File

@@ -21,6 +21,5 @@ content:
for spec in x86_32; do \
mv lib/mk/spec/$$spec/ld-pistachio.mk lib/mk/spec/$$spec/ld.mk; \
done;
sed -i "s/ld-pistachio/ld/" src/lib/ld/pistachio/target.mk
sed -i "s/pit_timer_drv/timer/" src/timer/pit/target.inc

View File

@@ -1 +1 @@
2022-05-24 ca2c90ebcbaa61ade7373d6ea48a608912cd2629
2022-10-11 b522663f9c8c779f255e2a5eb37f98b4301c5446

View File

@@ -1,2 +0,0 @@
TARGET = ld-pistachio
LIBS = ld-pistachio

View File

@@ -35,7 +35,6 @@ etc/board.conf:
content:
mv lib/mk/spec/arm/ld-sel4.mk lib/mk/spec/arm/ld.mk;
sed -i "s/ld-sel4/ld/" src/lib/ld/sel4/target.mk
sed -i "s/imx6_timer_drv/timer/" src/timer/epit/imx6/target.inc
find lib/mk/spec -name kernel-sel4-*.mk -o -name syscall-sel4-*.mk |\
grep -v "sel4-imx6q_sabrelite.mk" | xargs rm -rf

View File

@@ -1 +1 @@
2022-05-24 5d9558d34f4bd3f3e34d9b175fe3eb37be3561be
2022-10-11 6966c1e6595fec6e545ae729b9a5893e745a9fc9

View File

@@ -35,7 +35,6 @@ etc/board.conf:
content:
mv lib/mk/spec/arm/ld-sel4.mk lib/mk/spec/arm/ld.mk;
sed -i "s/ld-sel4/ld/" src/lib/ld/sel4/target.mk
sed -i "s/imx7_timer_drv/timer/" src/timer/gpt/imx7/target.inc
find lib/mk/spec -name kernel-sel4-*.mk -o -name syscall-sel4-*.mk |\
grep -v "sel4-imx7d_sabre.mk" | xargs rm -rf

Some files were not shown because too many files have changed in this diff Show More