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:
Ingo Weinhold
2008-01-11 00:36:44 +00:00
parent 5a69bb2730
commit 34b3b26b3b
50 changed files with 1641 additions and 722 deletions
+3
View File
@@ -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 */
+53
View File
@@ -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 */
+1 -1
View File
@@ -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;
+4 -1
View File
@@ -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);
+18
View File
@@ -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 */
+2
View File
@@ -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);