Merged branch haiku/branches/developer/bonefish/optimization revision
23139 into trunk, with roughly the following changes (for details svn log the branch): * The int 99 syscall handler is now fully in assembly. * Added a sysenter/sysexit handler and use it on Pentiums that support it (via commpage). * Got rid of i386_handle_trap(). A bit of functionality was moved into the assembly handler which now uses a jump table to call C functions handling the respective interrupt. * Some optimizations to get user debugger support code out of the interrupt handling path. * Introduced a thread::flags fields which allows to skip handling of rare events (signals, user debug enabling/disabling) on the common interrupt handling path. * Got rid of the explicit iframe stack. The iframes can still be retrieved by iterating through the stack frames. * Made the commpage an architecture independent feature. It's used for the real time data stuff (instead of creating a separate area). * The x86 CPU modules can now provide processor optimized versions for common functions (currently memcpy() only). They are used in the kernel and are provided to the userland via commpage entries. * Introduced build system feature allowing easy use of C structure member offsets in assembly code. Changes after merging: * Fixed merge conflict in src/system/kernel/arch/x86/arch_debug.cpp (caused by refactoring and introduction of "call" debugger command). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23370 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
@@ -46,6 +46,9 @@ void arch_check_syscall_restart(struct thread *t);
|
||||
void arch_store_fork_frame(struct arch_fork_arg *arg);
|
||||
void arch_restore_fork_frame(struct arch_fork_arg *arg);
|
||||
|
||||
#define arch_syscall_64_bit_return_value()
|
||||
// overridden by architectures that need special handling
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -22,6 +22,8 @@ void arch_destroy_team_debug_info(struct arch_team_debug_info *info);
|
||||
void arch_clear_thread_debug_info(struct arch_thread_debug_info *info);
|
||||
void arch_destroy_thread_debug_info(struct arch_thread_debug_info *info);
|
||||
|
||||
void arch_update_thread_single_step();
|
||||
|
||||
void arch_set_debug_cpu_state(const struct debug_cpu_state *cpuState);
|
||||
void arch_get_debug_cpu_state(struct debug_cpu_state *cpuState);
|
||||
|
||||
@@ -29,6 +31,7 @@ status_t arch_set_breakpoint(void *address);
|
||||
status_t arch_clear_breakpoint(void *address);
|
||||
status_t arch_set_watchpoint(void *address, uint32 type, int32 length);
|
||||
status_t arch_clear_watchpoint(void *address);
|
||||
bool arch_has_breakpoints(struct arch_team_debug_info *info);
|
||||
|
||||
#if KERNEL_BREAKPOINTS
|
||||
status_t arch_set_kernel_breakpoint(void *address);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_ARCH_x86_COMMPAGE_H
|
||||
#define _KERNEL_ARCH_x86_COMMPAGE_H
|
||||
|
||||
#ifndef _KERNEL_COMMPAGE_H
|
||||
# error Must not be included directly. Include <commpage.h> instead!
|
||||
#endif
|
||||
|
||||
#define COMMPAGE_ENTRY_X86_SYSCALL (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 0)
|
||||
#define COMMPAGE_ENTRY_X86_MEMCPY (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 1)
|
||||
|
||||
#define ARCH_USER_COMMPAGE_ADDR (0xffff0000)
|
||||
|
||||
#endif /* _KERNEL_ARCH_x86_COMMPAGE_H */
|
||||
@@ -9,14 +9,21 @@
|
||||
#define _KERNEL_ARCH_x86_CPU_H
|
||||
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
|
||||
#include <module.h>
|
||||
#include <arch/x86/descriptors.h>
|
||||
|
||||
#endif // !_ASSEMBLER
|
||||
|
||||
|
||||
// MSR registers (possibly Intel specific)
|
||||
#define IA32_MSR_APIC_BASE 0x1b
|
||||
|
||||
#define IA32_MSR_MTRR_CAPABILITIES 0xfe
|
||||
#define IA32_MSR_SYSENTER_CS 0x174
|
||||
#define IA32_MSR_SYSENTER_ESP 0x175
|
||||
#define IA32_MSR_SYSENTER_EIP 0x176
|
||||
#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff
|
||||
#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200
|
||||
#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201
|
||||
@@ -81,6 +88,20 @@
|
||||
#define IA32_MTR_WRITE_PROTECTED 5
|
||||
#define IA32_MTR_WRITE_BACK 6
|
||||
|
||||
|
||||
// iframe types
|
||||
#define IFRAME_TYPE_SYSCALL 0x1
|
||||
#define IFRAME_TYPE_OTHER 0x2
|
||||
#define IFRAME_TYPE_MASK 0xf
|
||||
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
|
||||
typedef struct x86_optimized_functions {
|
||||
void (*memcpy)(void* dest, const void* source, size_t count);
|
||||
void* memcpy_end;
|
||||
} x86_optimized_functions;
|
||||
|
||||
typedef struct x86_cpu_module_info {
|
||||
module_info info;
|
||||
uint32 (*count_mtrrs)(void);
|
||||
@@ -89,6 +110,8 @@ typedef struct x86_cpu_module_info {
|
||||
void (*set_mtrr)(uint32 index, uint64 base, uint64 length, uint8 type);
|
||||
status_t (*get_mtrr)(uint32 index, uint64 *_base, uint64 *_length,
|
||||
uint8 *_type);
|
||||
|
||||
void (*get_optimized_functions)(x86_optimized_functions* functions);
|
||||
} x86_cpu_module_info;
|
||||
|
||||
|
||||
@@ -110,6 +133,7 @@ struct tss {
|
||||
};
|
||||
|
||||
struct iframe {
|
||||
uint32 type; // iframe type
|
||||
uint32 gs;
|
||||
uint32 fs;
|
||||
uint32 es;
|
||||
@@ -277,5 +301,6 @@ extern segment_descriptor *gGDT;
|
||||
} // extern "C" {
|
||||
#endif
|
||||
|
||||
#endif // !_ASSEMBLER
|
||||
|
||||
#endif /* _KERNEL_ARCH_x86_CPU_H */
|
||||
|
||||
@@ -5,7 +5,9 @@
|
||||
#ifndef _KERNEL_ARCH_x86_KERNEL_H
|
||||
#define _KERNEL_ARCH_x86_KERNEL_H
|
||||
|
||||
#include <arch/cpu.h>
|
||||
#ifndef _ASSEMBLER
|
||||
# include <arch/cpu.h>
|
||||
#endif
|
||||
|
||||
// memory layout
|
||||
#define KERNEL_BASE 0x80000000
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void x86_push_iframe(struct iframe_stack *stack, struct iframe *frame);
|
||||
void x86_pop_iframe(struct iframe_stack *stack);
|
||||
struct iframe *i386_get_user_iframe(void);
|
||||
void *x86_next_page_directory(struct thread *from, struct thread *to);
|
||||
|
||||
void i386_return_from_signal();
|
||||
void i386_end_return_from_signal();
|
||||
|
||||
// override empty macro
|
||||
#undef arch_syscall_64_bit_return_value
|
||||
void arch_syscall_64_bit_return_value();
|
||||
|
||||
|
||||
static
|
||||
inline struct thread *
|
||||
|
||||
@@ -19,13 +19,6 @@ struct farcall {
|
||||
uint32 *ss;
|
||||
};
|
||||
|
||||
#define IFRAME_TRACE_DEPTH 4
|
||||
|
||||
struct iframe_stack {
|
||||
struct iframe *frames[IFRAME_TRACE_DEPTH];
|
||||
int32 index;
|
||||
};
|
||||
|
||||
// architecture specific thread info
|
||||
struct arch_thread {
|
||||
struct farcall current_stack;
|
||||
@@ -33,9 +26,6 @@ struct arch_thread {
|
||||
|
||||
// 512 byte floating point save point - this must be 16 byte aligned
|
||||
uint8 fpu_state[512];
|
||||
|
||||
// used to track interrupts on this thread
|
||||
struct iframe_stack iframes;
|
||||
} _ALIGNED(16);
|
||||
|
||||
struct arch_team {
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#ifndef _KERNEL_ARCH_X86_USER_DEBUGGER_H
|
||||
#define _KERNEL_ARCH_X86_USER_DEBUGGER_H
|
||||
|
||||
#define ARCH_INIT_USER_DEBUG i386_init_user_debug
|
||||
#define ARCH_INIT_USER_DEBUG x86_init_user_debug
|
||||
|
||||
// number of breakpoints the CPU supports
|
||||
// Actually it supports 4, but DR3 is used to hold the struct thread*.
|
||||
@@ -94,11 +94,6 @@ enum {
|
||||
X86_BREAKPOINT_LENGTH_4 = 0x3,
|
||||
};
|
||||
|
||||
// thread debug flags
|
||||
enum {
|
||||
X86_THREAD_DEBUG_DR7_SET = 0x01,
|
||||
};
|
||||
|
||||
struct arch_breakpoint {
|
||||
void *address; // NULL, if deactivated
|
||||
uint32 type; // one of the architecture types above
|
||||
@@ -122,14 +117,13 @@ extern "C" {
|
||||
struct iframe;
|
||||
struct thread;
|
||||
|
||||
extern void i386_init_user_debug_at_kernel_exit(struct iframe *frame);
|
||||
extern void i386_exit_user_debug_at_kernel_entry();
|
||||
extern void i386_reinit_user_debug_after_context_switch(struct thread *thread);
|
||||
extern void x86_init_user_debug_at_kernel_exit(struct iframe *frame);
|
||||
extern void x86_exit_user_debug_at_kernel_entry();
|
||||
|
||||
extern int i386_handle_debug_exception(struct iframe *frame);
|
||||
extern int i386_handle_breakpoint_exception(struct iframe *frame);
|
||||
extern void x86_handle_debug_exception(struct iframe *frame);
|
||||
extern void x86_handle_breakpoint_exception(struct iframe *frame);
|
||||
|
||||
extern void i386_init_user_debug();
|
||||
extern void x86_init_user_debug();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
/*
|
||||
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_ARCH_x86_COMMPAGE_H
|
||||
#define _KERNEL_ARCH_x86_COMMPAGE_H
|
||||
|
||||
/*! Some systemwide commpage constants, used in the kernel and libroot */
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
# include <SupportDefs.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* be careful what you put here, this file is included from assembly */
|
||||
#define COMMPAGE_ENTRY_MAGIC 0
|
||||
#define COMMPAGE_ENTRY_VERSION 1
|
||||
#define COMMPAGE_ENTRY_SYSCALL 2
|
||||
|
||||
#define USER_COMMPAGE_ADDR (0xffff0000)
|
||||
#define COMMPAGE_SIZE (0x8000)
|
||||
#define TABLE_ENTRIES 64
|
||||
|
||||
#define COMMPAGE_SIGNATURE 'COMM'
|
||||
#define COMMPAGE_VERSION 1
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
status_t commpage_init(void);
|
||||
#endif
|
||||
|
||||
#endif /* _KERNEL_ARCH_x86_COMMPAGE_H */
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2007, Travis Geiselbrecht. All rights reserved.
|
||||
* Distributed under the terms of the MIT License.
|
||||
*/
|
||||
#ifndef _KERNEL_COMMPAGE_H
|
||||
#define _KERNEL_COMMPAGE_H
|
||||
|
||||
/*! Some systemwide commpage constants, used in the kernel and libroot */
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
# include <SupportDefs.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* be careful what you put here, this file is included from assembly */
|
||||
#define COMMPAGE_ENTRY_MAGIC 0
|
||||
#define COMMPAGE_ENTRY_VERSION 1
|
||||
#define COMMPAGE_ENTRY_REAL_TIME_DATA 2
|
||||
#define COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC 3
|
||||
|
||||
#define COMMPAGE_SIZE (0x8000)
|
||||
#define COMMPAGE_TABLE_ENTRIES 64
|
||||
|
||||
#define COMMPAGE_SIGNATURE 'COMM'
|
||||
#define COMMPAGE_VERSION 1
|
||||
|
||||
#define USER_COMMPAGE_ADDR ARCH_USER_COMMPAGE_ADDR
|
||||
// set by the architecture specific implementation
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
|
||||
#define USER_COMMPAGE_TABLE ((void**)(USER_COMMPAGE_ADDR))
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
status_t commpage_init(void);
|
||||
void* allocate_commpage_entry(int entry, size_t size);
|
||||
void* fill_commpage_entry(int entry, const void* copyFrom, size_t size);
|
||||
|
||||
status_t arch_commpage_init(void);
|
||||
// implemented in the architecture specific part
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // ! _ASSEMBLER
|
||||
|
||||
#include <arch_commpage.h>
|
||||
|
||||
#endif /* _KERNEL_COMMPAGE_H */
|
||||
@@ -9,7 +9,7 @@
|
||||
#include <SupportDefs.h>
|
||||
|
||||
|
||||
typedef struct {
|
||||
typedef struct syscall_info {
|
||||
void *function; // pointer to the syscall function
|
||||
int parameter_size; // summed up parameter size
|
||||
} syscall_info;
|
||||
|
||||
@@ -26,9 +26,10 @@ struct thread *thread_lookat_queue(struct thread_queue *q);
|
||||
struct thread *thread_dequeue(struct thread_queue *q);
|
||||
struct thread *thread_dequeue_id(struct thread_queue *q, thread_id id);
|
||||
|
||||
void thread_at_kernel_entry(void);
|
||||
void thread_at_kernel_entry(bigtime_t now);
|
||||
// called when the thread enters the kernel on behalf of the thread
|
||||
void thread_at_kernel_exit(void);
|
||||
void thread_at_kernel_exit_no_signals(void);
|
||||
void thread_reset_for_exec(void);
|
||||
|
||||
status_t thread_init(struct kernel_args *args);
|
||||
@@ -69,6 +70,8 @@ status_t wait_for_thread_etc(thread_id id, uint32 flags, bigtime_t timeout,
|
||||
status_t select_thread(int32 object, struct select_info *info, bool kernel);
|
||||
status_t deselect_thread(int32 object, struct select_info *info, bool kernel);
|
||||
|
||||
#define syscall_64_bit_return_value() arch_syscall_64_bit_return_value()
|
||||
|
||||
// used in syscalls.c
|
||||
status_t _user_set_thread_priority(thread_id thread, int32 newPriority);
|
||||
status_t _user_rename_thread(thread_id thread, const char *name);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#ifndef _KERNEL_THREAD_TYPES_H
|
||||
#define _KERNEL_THREAD_TYPES_H
|
||||
|
||||
#ifndef _ASSEMBLER
|
||||
|
||||
#include <cbuf.h>
|
||||
#include <smp.h>
|
||||
@@ -182,6 +183,9 @@ struct team {
|
||||
typedef int32 (*thread_entry_func)(thread_func, void *);
|
||||
|
||||
struct thread {
|
||||
int32 flags; // summary of events relevant in interrupt
|
||||
// handlers (signals pending, user debugging
|
||||
// enabled, etc.)
|
||||
struct thread *all_next;
|
||||
struct thread *team_next;
|
||||
struct thread *queue_next; /* i.e. run queue, release queue, etc. */
|
||||
@@ -246,6 +250,7 @@ struct thread {
|
||||
// stack
|
||||
area_id kernel_stack_area;
|
||||
addr_t kernel_stack_base;
|
||||
addr_t kernel_stack_top;
|
||||
area_id user_stack_area;
|
||||
addr_t user_stack_base;
|
||||
size_t user_stack_size;
|
||||
@@ -268,4 +273,17 @@ struct thread_queue {
|
||||
struct thread *tail;
|
||||
};
|
||||
|
||||
|
||||
#endif // !_ASSEMBLER
|
||||
|
||||
|
||||
// bits for the thread::flags field
|
||||
#define THREAD_FLAGS_SIGNALS_PENDING 0x01
|
||||
#define THREAD_FLAGS_DEBUG_THREAD 0x02
|
||||
#define THREAD_FLAGS_DEBUGGER_INSTALLED 0x04
|
||||
#define THREAD_FLAGS_BREAKPOINTS_DEFINED 0x08
|
||||
#define THREAD_FLAGS_BREAKPOINTS_INSTALLED 0x10
|
||||
#define THREAD_FLAGS_64_BIT_SYSCALL_RETURN 0x20
|
||||
|
||||
|
||||
#endif /* _KERNEL_THREAD_TYPES_H */
|
||||
|
||||
@@ -144,6 +144,7 @@ void user_debug_finish_after_exec();
|
||||
|
||||
void init_user_debug();
|
||||
|
||||
|
||||
// debug event callbacks
|
||||
|
||||
void user_debug_pre_syscall(uint32 syscall, void *args);
|
||||
@@ -155,6 +156,7 @@ bool user_debug_handle_signal(int signal, struct sigaction *handler,
|
||||
void user_debug_stop_thread();
|
||||
void user_debug_team_created(team_id teamID);
|
||||
void user_debug_team_deleted(team_id teamID, port_id debuggerPort);
|
||||
void user_debug_update_new_thread_flags(thread_id threadID);
|
||||
void user_debug_thread_created(thread_id threadID);
|
||||
void user_debug_thread_deleted(team_id teamID, thread_id threadID);
|
||||
void user_debug_image_created(const image_info *imageInfo);
|
||||
|
||||
Reference in New Issue
Block a user