From 4dadd6a4379cce585e56a96e5f64451558698140 Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 12 Nov 2012 16:52:12 +0100 Subject: [PATCH] base-hw: Read and write whole thread states. By now there is no use case for read/write a single register of a thread state. Thus the new syscalls 'read_thread_state' and 'write_thread_state' replace the old ones 'read_register' and 'write_register'. --- base-hw/include/kernel/syscalls.h | 36 ++++------ base-hw/src/core/include/arm/cpu.h | 106 +++++++++++++---------------- base-hw/src/core/kernel.cc | 33 ++++----- 3 files changed, 71 insertions(+), 104 deletions(-) diff --git a/base-hw/include/kernel/syscalls.h b/base-hw/include/kernel/syscalls.h index fa061d56c..ee91f8622 100644 --- a/base-hw/include/kernel/syscalls.h +++ b/base-hw/include/kernel/syscalls.h @@ -43,8 +43,8 @@ namespace Kernel GET_THREAD = 5, CURRENT_THREAD_ID = 6, YIELD_THREAD = 7, - READ_REGISTER = 18, - WRITE_REGISTER = 19, + READ_THREAD_STATE = 18, + WRITE_THREAD_STATE = 19, /* interprocess communication */ REQUEST_AND_WAIT = 8, @@ -380,41 +380,31 @@ namespace Kernel /** - * Get the current value of a register of a specific CPU context + * Copy the current state of a thread to the callers UTCB * - * \param thread_id ID of the thread that owns the targeted context - * \param reg_id platform-specific ID of the targeted register + * \param thread_id ID of the targeted thread * * Restricted to core threads. One can also read from its own context, * or any thread that is active in the meantime. In these cases - * be aware of the fact, that the result reflects the context + * be aware of the fact, that the result reflects the thread * state that were backed at the last kernel entry of the thread. + * The copy might be incoherent when this function returns because + * the caller might get scheduled away before then. */ - inline unsigned long read_register(unsigned long const thread_id, - unsigned long const reg_id) - { - return syscall(READ_REGISTER, (Syscall_arg)thread_id, - (Syscall_arg)reg_id); - } + inline void read_thread_state(unsigned const thread_id) { + syscall(READ_THREAD_STATE, (Syscall_arg)thread_id); } /** - * Write a value to a register of a specific CPU context + * Override the state of a thread with the callers UTCB content * - * \param thread_id ID of the thread that owns the targeted context - * \param reg_id platform-specific ID of the targeted register - * \param value value that shall be written to the register + * \param thread_id ID of the targeted thread * * Restricted to core threads. One can also write to its own context, or * to that of a thread that is active in the meantime. */ - inline void write_register(unsigned long const thread_id, - unsigned long const reg_id, - unsigned long const value) - { - syscall(WRITE_REGISTER, (Syscall_arg)thread_id, (Syscall_arg)reg_id, - (Syscall_arg)value); - } + inline void write_thread_state(unsigned const thread_id) { + syscall(WRITE_THREAD_STATE, (Syscall_arg)thread_id); } /** diff --git a/base-hw/src/core/include/arm/cpu.h b/base-hw/src/core/include/arm/cpu.h index 8111bbd8e..6a301afbe 100644 --- a/base-hw/src/core/include/arm/cpu.h +++ b/base-hw/src/core/include/arm/cpu.h @@ -480,6 +480,52 @@ namespace Arm addr_t tlb() const { return section_table; } void protection_domain(unsigned const id) { cidr = id; } + + /** + * Copy CPU state data to 'c' + */ + void read_cpu_state(Cpu_state * const s) + { + s->r0 = r0; + s->r1 = r1; + s->r2 = r2; + s->r3 = r3; + s->r4 = r4; + s->r5 = r5; + s->r6 = r6; + s->r7 = r7; + s->r8 = r8; + s->r9 = r9; + s->r10 = r10; + s->r11 = r11; + s->r12 = r12; + s->sp = sp; + s->lr = lr; + s->ip = ip; + } + + /** + * Override CPU state with data from 'c' + */ + void write_cpu_state(Cpu_state * const s) + { + r0 = s->r0; + r1 = s->r1; + r2 = s->r2; + r3 = s->r3; + r4 = s->r4; + r5 = s->r5; + r6 = s->r6; + r7 = s->r7; + r8 = s->r8; + r9 = s->r9; + r10 = s->r10; + r11 = s->r11; + r12 = s->r12; + sp = s->sp; + lr = s->lr; + ip = s->ip; + } }; /** @@ -513,66 +559,6 @@ namespace Arm unsigned user_arg_6() const { return r6; } unsigned user_arg_7() const { return r7; } - /** - * Read a general purpose register - * - * \param id ID of the targeted register - * \param v Holds register value if this returns 1 - */ - bool get_gpr(unsigned id, unsigned & v) const - { - switch(id) - { - case 0: v = r0; return 1; - case 1: v = r1; return 1; - case 2: v = r2; return 1; - case 3: v = r3; return 1; - case 4: v = r4; return 1; - case 5: v = r5; return 1; - case 6: v = r6; return 1; - case 7: v = r7; return 1; - case 8: v = r8; return 1; - case 9: v = r9; return 1; - case 10: v = r10; return 1; - case 11: v = r11; return 1; - case 12: v = r12; return 1; - case 13: v = sp; return 1; - case 14: v = lr; return 1; - case 15: v = ip; return 1; - } - return 0; - } - - /** - * Override a general purpose register - * - * \param id ID of the targeted register - * \param v Has been written to register if this returns 1 - */ - bool set_gpr(unsigned id, unsigned const v) - { - switch(id) - { - case 0: r0 = v; return 1; - case 1: r1 = v; return 1; - case 2: r2 = v; return 1; - case 3: r3 = v; return 1; - case 4: r4 = v; return 1; - case 5: r5 = v; return 1; - case 6: r6 = v; return 1; - case 7: r7 = v; return 1; - case 8: r8 = v; return 1; - case 9: r9 = v; return 1; - case 10: r10 = v; return 1; - case 11: r11 = v; return 1; - case 12: r12 = v; return 1; - case 13: sp = v; return 1; - case 14: lr = v; return 1; - case 15: ip = v; return 1; - } - return 0; - } - /** * Check if a pagefault has occured due to a translation miss * diff --git a/base-hw/src/core/kernel.cc b/base-hw/src/core/kernel.cc index 7d6357f47..82020ae4c 100644 --- a/base-hw/src/core/kernel.cc +++ b/base-hw/src/core/kernel.cc @@ -27,6 +27,7 @@ #include #include #include +#include /* core includes */ #include @@ -54,6 +55,7 @@ extern Genode::addr_t _mt_master_context_end; namespace Kernel { /* import Genode types */ + typedef Genode::Thread_state Thread_state; typedef Genode::size_t size_t; typedef Genode::addr_t addr_t; typedef Genode::umword_t umword_t; @@ -1899,37 +1901,26 @@ namespace Kernel /** * Do specific syscall for 'user', for details see 'syscall.h' */ - void do_read_register(Thread * const user) + void do_read_thread_state(Thread * const user) { - /* check permissions */ assert(user->pd_id() == core_id()); - - /* get targeted thread */ Thread * const t = Thread::pool()->object(user->user_arg_1()); - assert(t); - - /* return requested register */ - unsigned gpr; - assert(t->get_gpr(user->user_arg_2(), gpr)); - user->user_arg_0(gpr); + if (!t) PDBG("Targeted thread unknown"); + Thread_state * const ts = (Thread_state *)user->phys_utcb()->base(); + t->Cpu::Context::read_cpu_state(ts); } /** * Do specific syscall for 'user', for details see 'syscall.h' */ - void do_write_register(Thread * const user) + void do_write_thread_state(Thread * const user) { - /* check permissions */ assert(user->pd_id() == core_id()); - - /* get targeted thread */ Thread * const t = Thread::pool()->object(user->user_arg_1()); - assert(t); - - /* write to requested register */ - unsigned const gpr = user->user_arg_3(); - assert(t->set_gpr(user->user_arg_2(), gpr)); + if (!t) PDBG("Targeted thread unknown"); + Thread_state * const ts = (Thread_state *)user->phys_utcb()->base(); + t->Cpu::Context::write_cpu_state(ts); } @@ -2090,8 +2081,8 @@ namespace Kernel /* 15 */ do_await_irq, /* 16 */ do_free_irq, /* 17 */ do_print_char, - /* 18 */ do_read_register, - /* 19 */ do_write_register, + /* 18 */ do_read_thread_state, + /* 19 */ do_write_thread_state, /* 20 */ do_new_signal_receiver, /* 21 */ do_new_signal_context, /* 22 */ do_await_signal,