kernel: +arch_get_thread_debug_cpu_state()
Similar to arch_get_debug_cpu_state(), but the thread whose CPU state to retrieve is specified. Works only for threads that aren't running, and on x86-64 we can get the FPU state only when the thread was interrupted in userland. Not implemented for the incomplete architecture ports.
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2011, Ingo Weinhold, [email protected].
|
* Copyright 2005-2016, Ingo Weinhold, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
#ifndef KERNEL_ARCH_USER_DEBUGGER_H
|
#ifndef KERNEL_ARCH_USER_DEBUGGER_H
|
||||||
@@ -19,6 +19,11 @@ extern "C" {
|
|||||||
struct arch_team_debug_info;
|
struct arch_team_debug_info;
|
||||||
struct arch_thread_debug_info;
|
struct arch_thread_debug_info;
|
||||||
|
|
||||||
|
namespace BKernel {
|
||||||
|
struct Thread;
|
||||||
|
}
|
||||||
|
using BKernel::Thread;
|
||||||
|
|
||||||
|
|
||||||
void arch_clear_team_debug_info(struct arch_team_debug_info *info);
|
void arch_clear_team_debug_info(struct arch_team_debug_info *info);
|
||||||
void arch_destroy_team_debug_info(struct arch_team_debug_info *info);
|
void arch_destroy_team_debug_info(struct arch_team_debug_info *info);
|
||||||
@@ -29,6 +34,8 @@ void arch_update_thread_single_step();
|
|||||||
|
|
||||||
void arch_set_debug_cpu_state(const debug_cpu_state *cpuState);
|
void arch_set_debug_cpu_state(const debug_cpu_state *cpuState);
|
||||||
void arch_get_debug_cpu_state(debug_cpu_state *cpuState);
|
void arch_get_debug_cpu_state(debug_cpu_state *cpuState);
|
||||||
|
status_t arch_get_thread_debug_cpu_state(Thread *thread,
|
||||||
|
debug_cpu_state *cpuState);
|
||||||
|
|
||||||
status_t arch_set_breakpoint(void *address);
|
status_t arch_set_breakpoint(void *address);
|
||||||
status_t arch_clear_breakpoint(void *address);
|
status_t arch_clear_breakpoint(void *address);
|
||||||
|
|||||||
@@ -60,6 +60,13 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_get_thread_debug_cpu_state(Thread *thread, debug_cpu_state *cpuState)
|
arch_get_thread_debug_cpu_state(Thread *thread, debug_cpu_state *cpuState)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -76,6 +76,13 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_breakpoint(void *address)
|
arch_set_breakpoint(void *address)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -54,6 +54,13 @@ arch_get_debug_cpu_state(debug_cpu_state *cpuState)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
status_t
|
||||||
|
arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
return B_UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
arch_set_breakpoint(void *address)
|
arch_set_breakpoint(void *address)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2005-2011, Ingo Weinhold, [email protected].
|
* Copyright 2005-2016, Ingo Weinhold, [email protected].
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -196,6 +196,51 @@ set_iframe_registers(iframe* frame, const debug_cpu_state* cpuState)
|
|||||||
#endif // __x86_64__
|
#endif // __x86_64__
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
get_cpu_state(Thread* thread, iframe* frame, debug_cpu_state* cpuState)
|
||||||
|
{
|
||||||
|
// For the floating point state to be correct the calling function must
|
||||||
|
// not use these registers (not even indirectly).
|
||||||
|
#ifdef __x86_64__
|
||||||
|
if (frame->fpu != nullptr) {
|
||||||
|
memcpy(&cpuState->extended_registers, frame->fpu,
|
||||||
|
sizeof(cpuState->extended_registers));
|
||||||
|
} else {
|
||||||
|
memset(&cpuState->extended_registers, 0,
|
||||||
|
sizeof(cpuState->extended_registers));
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
Thread* thisThread = thread_get_current_thread();
|
||||||
|
if (gHasSSE) {
|
||||||
|
if (thread == thisThread) {
|
||||||
|
// Since fxsave requires 16-byte alignment and this isn't guaranteed
|
||||||
|
// for the passed buffer, we use our thread's fpu_state field as
|
||||||
|
// temporary buffer. We need to disable interrupts to make use of
|
||||||
|
// it.
|
||||||
|
Thread* thread = thread_get_current_thread();
|
||||||
|
InterruptsLocker locker;
|
||||||
|
x86_fxsave(thread->arch_info.fpu_state);
|
||||||
|
// unlike fnsave, fxsave doesn't reinit the FPU state
|
||||||
|
}
|
||||||
|
memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
|
||||||
|
sizeof(cpuState->extended_registers));
|
||||||
|
} else {
|
||||||
|
if (thread == thisThread) {
|
||||||
|
x86_fnsave(&cpuState->extended_registers);
|
||||||
|
// fnsave reinits the FPU state after saving, so we need to
|
||||||
|
// load it again
|
||||||
|
x86_frstor(&cpuState->extended_registers);
|
||||||
|
} else {
|
||||||
|
memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
|
||||||
|
sizeof(cpuState->extended_registers));
|
||||||
|
}
|
||||||
|
// TODO: Convert to fxsave format!
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
get_iframe_registers(frame, cpuState);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
install_breakpoints(const arch_team_debug_info& teamInfo)
|
install_breakpoints(const arch_team_debug_info& teamInfo)
|
||||||
{
|
{
|
||||||
@@ -719,38 +764,28 @@ arch_set_debug_cpu_state(const debug_cpu_state* cpuState)
|
|||||||
void
|
void
|
||||||
arch_get_debug_cpu_state(debug_cpu_state* cpuState)
|
arch_get_debug_cpu_state(debug_cpu_state* cpuState)
|
||||||
{
|
{
|
||||||
if (iframe* frame = x86_get_user_iframe()) {
|
if (iframe* frame = x86_get_user_iframe())
|
||||||
// For the floating point state to be correct the calling function must
|
get_cpu_state(thread_get_current_thread(), frame, cpuState);
|
||||||
// not use these registers (not even indirectly).
|
}
|
||||||
#ifdef __x86_64__
|
|
||||||
if (frame->fpu != nullptr) {
|
|
||||||
memcpy(&cpuState->extended_registers, frame->fpu,
|
/*! \brief Retrieves the CPU state for the given thread.
|
||||||
sizeof(cpuState->extended_registers));
|
The thread must not be running and the thread's scheduler spinlock must be
|
||||||
} else {
|
held.
|
||||||
memset(&cpuState->extended_registers, 0,
|
\param thread The thread whose CPU state to retrieve.
|
||||||
sizeof(cpuState->extended_registers));
|
\param cpuState Pointer to pre-allocated storage for the CPU state.
|
||||||
}
|
\return \c B_OK, if everything goes fine, another error code, if the CPU
|
||||||
#else
|
state could not be retrieved.
|
||||||
if (gHasSSE) {
|
*/
|
||||||
// Since fxsave requires 16-byte alignment and this isn't guaranteed
|
status_t
|
||||||
// passed buffer, we use our thread's fpu_state field as temporary
|
arch_get_thread_debug_cpu_state(Thread* thread, debug_cpu_state* cpuState)
|
||||||
// buffer. We need to disable interrupts to make use of it.
|
{
|
||||||
Thread* thread = thread_get_current_thread();
|
iframe* frame = x86_get_thread_user_iframe(thread);
|
||||||
InterruptsLocker locker;
|
if (frame == NULL)
|
||||||
x86_fxsave(thread->arch_info.fpu_state);
|
return B_BAD_VALUE;
|
||||||
// unlike fnsave, fxsave doesn't reinit the FPU state
|
|
||||||
memcpy(&cpuState->extended_registers, thread->arch_info.fpu_state,
|
get_cpu_state(thread, frame, cpuState);
|
||||||
sizeof(cpuState->extended_registers));
|
return B_OK;
|
||||||
} else {
|
|
||||||
x86_fnsave(&cpuState->extended_registers);
|
|
||||||
x86_frstor(&cpuState->extended_registers);
|
|
||||||
// fnsave reinits the FPU state after saving, so we need to
|
|
||||||
// load it again
|
|
||||||
// TODO: Convert to fxsave format!
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
get_iframe_registers(frame, cpuState);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user