From 1cbf8f4b3c6c44446420f14d7b75ef8a1fbc2798 Mon Sep 17 00:00:00 2001 From: Travis Geiselbrecht Date: Mon, 19 Feb 2007 00:32:44 +0000 Subject: [PATCH] initial support for a commpage, which is a chunk of memory in high kernel space with user readonly permissions. The first use is to let the kernel decide what the preferred syscall mechanism is at boot time and copy the appropriate user space code there. Can be used for routines the kernel can decide best how to use (memcpy, some timing routines, etc). git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@20161 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/os/kernel/arch/x86/commpage.h | 23 +++++++ headers/private/kernel/arch/x86/commpage.h | 12 ++++ src/system/kernel/arch/x86/Jamfile | 2 + src/system/kernel/arch/x86/arch_cpu.c | 4 ++ src/system/kernel/arch/x86/commpage.c | 74 +++++++++++++++++++++ src/system/kernel/arch/x86/syscall.S | 19 ++++++ src/system/libroot/os/arch/x86/syscalls.inc | 11 ++- 7 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 headers/os/kernel/arch/x86/commpage.h create mode 100644 headers/private/kernel/arch/x86/commpage.h create mode 100644 src/system/kernel/arch/x86/commpage.c create mode 100644 src/system/kernel/arch/x86/syscall.S diff --git a/headers/os/kernel/arch/x86/commpage.h b/headers/os/kernel/arch/x86/commpage.h new file mode 100644 index 0000000000..a68ef23def --- /dev/null +++ b/headers/os/kernel/arch/x86/commpage.h @@ -0,0 +1,23 @@ +/* + * Copyright 2007, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef __OS_KERNEL_ARCH_x86_COMMPAGE_H +#define __OS_KERNEL_ARCH_x86_COMMPAGE_H + +/* some systemwide commpage constants, used in the kernel and libroot */ + +/* 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 + +#endif + diff --git a/headers/private/kernel/arch/x86/commpage.h b/headers/private/kernel/arch/x86/commpage.h new file mode 100644 index 0000000000..8a13d74354 --- /dev/null +++ b/headers/private/kernel/arch/x86/commpage.h @@ -0,0 +1,12 @@ +/* + * 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 + + +status_t commpage_init(void); + +#endif + diff --git a/src/system/kernel/arch/x86/Jamfile b/src/system/kernel/arch/x86/Jamfile index d8c9f3135a..d09d1409fb 100644 --- a/src/system/kernel/arch/x86/Jamfile +++ b/src/system/kernel/arch/x86/Jamfile @@ -31,6 +31,8 @@ KernelStaticLibrary libx86 : apm.cpp bios.cpp cpuid.S + commpage.c + syscall.S generic_vm_physical_page_mapper.cpp : diff --git a/src/system/kernel/arch/x86/arch_cpu.c b/src/system/kernel/arch/x86/arch_cpu.c index 8684db96b5..ff12cda9c4 100644 --- a/src/system/kernel/arch/x86/arch_cpu.c +++ b/src/system/kernel/arch/x86/arch_cpu.c @@ -17,6 +17,7 @@ #include #include #include +#include #include "interrupts.h" @@ -505,6 +506,9 @@ arch_cpu_init_post_vm(kernel_args *args) // setup SSE2/3 support init_sse(); + // initialize the commpage support + commpage_init(); + return B_OK; } diff --git a/src/system/kernel/arch/x86/commpage.c b/src/system/kernel/arch/x86/commpage.c new file mode 100644 index 0000000000..42cfb167d7 --- /dev/null +++ b/src/system/kernel/arch/x86/commpage.c @@ -0,0 +1,74 @@ +/* + * Copyright 2007, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#include +#include + +#include +#include + +#include + +static area_id comm_area; +static area_id user_comm_area; +static unsigned long *comm_ptr; +static unsigned long *user_comm_ptr; +static void *next_comm_addr; + +// user syscall assembly stub +extern void _user_syscall_int(void); +extern unsigned int _user_syscall_int_end; + +static inline +addr_t commpage_ptr_to_user_ptr(const void *ptr) +{ + return ((addr_t)ptr) + ((addr_t)user_comm_ptr - (addr_t)comm_ptr); +} + +static +status_t initialize_commpage_syscall(void) +{ + size_t len; + + // for now, we're hard coded to use the legacy method (int 99) + len = (size_t)((void *)&_user_syscall_int_end - (void *)&_user_syscall_int); + memcpy(next_comm_addr, &_user_syscall_int, len); + + // fill in the table entry + comm_ptr[COMMPAGE_ENTRY_SYSCALL] = commpage_ptr_to_user_ptr(next_comm_addr); + next_comm_addr = (void *)((addr_t)next_comm_addr + ROUNDUP(len, 4)); + + return B_OK; +} + +status_t +commpage_init(void) +{ + int i; + + // create a read/write kernel area + comm_area = create_area("commpage", (void **)&comm_ptr, B_ANY_ADDRESS, COMMPAGE_SIZE, B_FULL_LOCK, + B_KERNEL_WRITE_AREA | B_KERNEL_READ_AREA); + + // clone it at a fixed address with user read/only permissions + user_comm_ptr = (void *)USER_COMMPAGE_ADDR; + user_comm_area = clone_area("user_commpage", (void **)&user_comm_ptr, B_EXACT_ADDRESS, + B_READ_AREA | B_EXECUTE_AREA, comm_area); + + // zero it out + memset(comm_ptr, 0, COMMPAGE_SIZE); + + // fill in some of the table + comm_ptr[0] = COMMPAGE_SIGNATURE; + comm_ptr[1] = COMMPAGE_VERSION; + + // the next slot to allocate space is after the table + next_comm_addr = (void *)&comm_ptr[TABLE_ENTRIES]; + + // select the optimum syscall mechanism and patch the commpage + initialize_commpage_syscall(); + + return B_OK; +} + diff --git a/src/system/kernel/arch/x86/syscall.S b/src/system/kernel/arch/x86/syscall.S new file mode 100644 index 0000000000..2b359dfb7c --- /dev/null +++ b/src/system/kernel/arch/x86/syscall.S @@ -0,0 +1,19 @@ +/* + * Copyright 2007, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the MIT License. + */ + +#define FUNCTION(x) .global x; .type x,@function; x +#define SYM(x) .global x; x + +.text + +/* user space half of the syscall mechanism, to be copied into the commpage */ +FUNCTION(_user_syscall_int): + int $99 + ret +SYM(_user_syscall_int_end): + + + + diff --git a/src/system/libroot/os/arch/x86/syscalls.inc b/src/system/libroot/os/arch/x86/syscalls.inc index 87154ec695..4f8748cae6 100644 --- a/src/system/libroot/os/arch/x86/syscalls.inc +++ b/src/system/libroot/os/arch/x86/syscalls.inc @@ -1,3 +1,7 @@ +/* + * Copyright 2007, Travis Geiselbrecht. All rights reserved. + * Distributed under the terms of the MIT License. + */ /* ** Copyright 2001, Travis Geiselbrecht. All rights reserved. ** Distributed under the terms of the NewOS License. @@ -7,16 +11,18 @@ * syscall interface works as such: * eax has syscall # * esp + 4 points to the syscall parameters + * branch to the syscall vector in the commpage */ +#include + #define _SYSCALL(name, n) \ .globl name; \ .type name,@function; \ .align 8; \ name: \ movl $n,%eax; \ - int $99; \ - ret + jmp *(USER_COMMPAGE_ADDR + COMMPAGE_ENTRY_SYSCALL * 4) #define SYSCALL0(name, n) _SYSCALL(name, n) #define SYSCALL1(name, n) _SYSCALL(name, n) @@ -35,3 +41,4 @@ name: \ #define SYSCALL14(name, n) _SYSCALL(name, n) #define SYSCALL15(name, n) _SYSCALL(name, n) #define SYSCALL16(name, n) _SYSCALL(name, n) +