Merge of Wu's GSOC 09 branch (src.20090525.r4372.wu)
Main changes: - COW optimization for safecopy. - safemap, a grant-based interface for sharing memory regions between processes. - Integration with safemap and complete rework of DS, supporting new data types natively (labels, memory ranges, memory mapped ranges). - For further information: http://wiki.minix3.org/en/SummerOfCode2009/MemoryGrants Additional changes not included in the original Wu's branch: - Fixed unhandled case in VM when using COW optimization for safecopy in case of a block that has already been shared as SMAP. - Better interface and naming scheme for sys_saferevmap and ds_retrieve_map calls. - Better input checking in syslib: check for page alignment when creating memory mapping grants. - DS notifies subscribers when an entry is deleted. - Documented the behavior of indirect grants in case of memory mapping. - Test suite in /usr/src/test/safeperf|safecopy|safemap|ds/* reworked and extended. - Minor fixes and general cleanup. - TO-DO: Grant ids should be generated and managed the way endpoints are to make sure grant slots are never misreused.
This commit is contained in:
92
lib/Makefile
92
lib/Makefile
@@ -6,10 +6,10 @@ all-gnu:
|
||||
|
||||
makefiles: Makefile
|
||||
Makedepend-ack Makedepend-gnu:
|
||||
sh generate.sh . obj-ack/ obj-gnu
|
||||
sh ./generate.sh . obj-ack obj-gnu
|
||||
|
||||
Makefile: Makefile.in Makedepend-ack Makedepend-gnu
|
||||
sh generate.sh . obj-ack/ obj-gnu
|
||||
sh ./generate.sh . obj-ack obj-gnu
|
||||
@echo
|
||||
@echo *Attention*
|
||||
@echo Makefile is regenerated... rerun command to see changes
|
||||
@@ -17,47 +17,47 @@ Makefile: Makefile.in Makedepend-ack Makedepend-gnu
|
||||
@echo
|
||||
|
||||
all-ack: makefiles
|
||||
mkdir -p obj-ack//./ansi
|
||||
mkdir -p obj-ack/./ansi
|
||||
cd ansi && $(MAKE) $@
|
||||
mkdir -p obj-ack//./curses
|
||||
mkdir -p obj-ack/./curses
|
||||
cd curses && $(MAKE) $@
|
||||
mkdir -p obj-ack//./dummy
|
||||
mkdir -p obj-ack/./dummy
|
||||
cd dummy && $(MAKE) $@
|
||||
mkdir -p obj-ack//./editline
|
||||
mkdir -p obj-ack/./editline
|
||||
cd editline && $(MAKE) $@
|
||||
mkdir -p obj-ack//./end
|
||||
mkdir -p obj-ack/./end
|
||||
cd end && $(MAKE) $@
|
||||
mkdir -p obj-ack//./ip
|
||||
mkdir -p obj-ack/./ip
|
||||
cd ip && $(MAKE) $@
|
||||
mkdir -p obj-ack//./math
|
||||
mkdir -p obj-ack/./math
|
||||
cd math && $(MAKE) $@
|
||||
mkdir -p obj-ack//./other
|
||||
mkdir -p obj-ack/./other
|
||||
cd other && $(MAKE) $@
|
||||
mkdir -p obj-ack//./posix
|
||||
mkdir -p obj-ack/./posix
|
||||
cd posix && $(MAKE) $@
|
||||
mkdir -p obj-ack//./regex
|
||||
mkdir -p obj-ack/./regex
|
||||
cd regex && $(MAKE) $@
|
||||
mkdir -p obj-ack//./stdio
|
||||
mkdir -p obj-ack/./stdio
|
||||
cd stdio && $(MAKE) $@
|
||||
mkdir -p obj-ack//./stdtime
|
||||
mkdir -p obj-ack/./stdtime
|
||||
cd stdtime && $(MAKE) $@
|
||||
mkdir -p obj-ack//./syscall
|
||||
mkdir -p obj-ack/./syscall
|
||||
cd syscall && $(MAKE) $@
|
||||
mkdir -p obj-ack//./syslib
|
||||
mkdir -p obj-ack/./syslib
|
||||
cd syslib && $(MAKE) $@
|
||||
mkdir -p obj-ack//./util
|
||||
mkdir -p obj-ack/./util
|
||||
cd util && $(MAKE) $@
|
||||
mkdir -p obj-ack//./sysutil
|
||||
mkdir -p obj-ack/./sysutil
|
||||
cd sysutil && $(MAKE) $@
|
||||
mkdir -p obj-ack//./sysvipc
|
||||
mkdir -p obj-ack/./sysvipc
|
||||
cd sysvipc && $(MAKE) $@
|
||||
mkdir -p obj-ack//./timers
|
||||
mkdir -p obj-ack/./timers
|
||||
cd timers && $(MAKE) $@
|
||||
mkdir -p obj-ack//./i386
|
||||
mkdir -p obj-ack/./i386
|
||||
cd i386 && $(MAKE) $@
|
||||
mkdir -p obj-ack//./ack
|
||||
mkdir -p obj-ack/./ack
|
||||
cd ack && $(MAKE) $@
|
||||
mkdir -p obj-ack//./gnu
|
||||
mkdir -p obj-ack/./gnu
|
||||
cd gnu && $(MAKE) $@
|
||||
|
||||
all-gnu: makefiles
|
||||
@@ -150,56 +150,56 @@ makefiles: ack/Makefile
|
||||
makefiles: gnu/Makefile
|
||||
|
||||
ansi/Makefile: ansi/Makefile.in
|
||||
cd ansi && sh ../generate.sh ./ansi ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd ansi && sh .././generate.sh ./ansi ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
curses/Makefile: curses/Makefile.in
|
||||
cd curses && sh ../generate.sh ./curses ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd curses && sh .././generate.sh ./curses ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
dummy/Makefile: dummy/Makefile.in
|
||||
cd dummy && sh ../generate.sh ./dummy ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd dummy && sh .././generate.sh ./dummy ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
editline/Makefile: editline/Makefile.in
|
||||
cd editline && sh ../generate.sh ./editline ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd editline && sh .././generate.sh ./editline ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
end/Makefile: end/Makefile.in
|
||||
cd end && sh ../generate.sh ./end ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd end && sh .././generate.sh ./end ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
ip/Makefile: ip/Makefile.in
|
||||
cd ip && sh ../generate.sh ./ip ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd ip && sh .././generate.sh ./ip ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
math/Makefile: math/Makefile.in
|
||||
cd math && sh ../generate.sh ./math ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd math && sh .././generate.sh ./math ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
other/Makefile: other/Makefile.in
|
||||
cd other && sh ../generate.sh ./other ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd other && sh .././generate.sh ./other ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
posix/Makefile: posix/Makefile.in
|
||||
cd posix && sh ../generate.sh ./posix ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd posix && sh .././generate.sh ./posix ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
regex/Makefile: regex/Makefile.in
|
||||
cd regex && sh ../generate.sh ./regex ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd regex && sh .././generate.sh ./regex ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
stdio/Makefile: stdio/Makefile.in
|
||||
cd stdio && sh ../generate.sh ./stdio ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd stdio && sh .././generate.sh ./stdio ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
stdtime/Makefile: stdtime/Makefile.in
|
||||
cd stdtime && sh ../generate.sh ./stdtime ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd stdtime && sh .././generate.sh ./stdtime ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
syscall/Makefile: syscall/Makefile.in
|
||||
cd syscall && sh ../generate.sh ./syscall ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd syscall && sh .././generate.sh ./syscall ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
syslib/Makefile: syslib/Makefile.in
|
||||
cd syslib && sh ../generate.sh ./syslib ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd syslib && sh .././generate.sh ./syslib ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
util/Makefile: util/Makefile.in
|
||||
cd util && sh ../generate.sh ./util ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd util && sh .././generate.sh ./util ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
sysutil/Makefile: sysutil/Makefile.in
|
||||
cd sysutil && sh ../generate.sh ./sysutil ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd sysutil && sh .././generate.sh ./sysutil ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
sysvipc/Makefile: sysvipc/Makefile.in
|
||||
cd sysvipc && sh ../generate.sh ./sysvipc ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd sysvipc && sh .././generate.sh ./sysvipc ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
timers/Makefile: timers/Makefile.in
|
||||
cd timers && sh ../generate.sh ./timers ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd timers && sh .././generate.sh ./timers ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
i386/Makefile: i386/Makefile.in
|
||||
cd i386 && sh ../generate.sh ./i386 ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd i386 && sh .././generate.sh ./i386 ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
ack/Makefile: ack/Makefile.in
|
||||
cd ack && sh ../generate.sh ./ack ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd ack && sh .././generate.sh ./ack ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
gnu/Makefile: gnu/Makefile.in
|
||||
cd gnu && sh ../generate.sh ./gnu ../obj-ack/ ../obj-gnu && $(MAKE) makefiles
|
||||
cd gnu && sh .././generate.sh ./gnu ../obj-ack ../obj-gnu && $(MAKE) makefiles
|
||||
|
||||
clean::
|
||||
rm -f obj-ack//./*
|
||||
rm -f obj-ack/./*
|
||||
rm -f obj-gnu/./*
|
||||
|
||||
install: install-ack
|
||||
|
||||
install-ack: all-ack
|
||||
cp obj-ack//*.[ao] /usr/lib/i386
|
||||
cp obj-ack/*.[ao] /usr/lib/i386
|
||||
|
||||
install-gnu: all-gnu
|
||||
cp obj-gnu/*.[ao] /usr/gnu/lib
|
||||
|
||||
@@ -52,6 +52,7 @@ libsys_FILES=" \
|
||||
sys_readbios.c \
|
||||
sys_runctl.c \
|
||||
sys_safecopy.c \
|
||||
sys_safemap.c \
|
||||
sys_sysctl.c \
|
||||
sys_vsafecopy.c \
|
||||
sys_profbuf.c \
|
||||
|
||||
421
lib/syslib/ds.c
421
lib/syslib/ds.c
@@ -4,260 +4,257 @@
|
||||
|
||||
#include "syslib.h"
|
||||
|
||||
#define GRANTBAD -1001
|
||||
static message m;
|
||||
|
||||
int
|
||||
ds_subscribe(ds_name_regexp, type, flags)
|
||||
char *ds_name_regexp;
|
||||
int type;
|
||||
int flags;
|
||||
PRIVATE int do_invoke_ds(int type, const char *ds_name)
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g;
|
||||
size_t len;
|
||||
cp_grant_id_t g_key;
|
||||
size_t len_key;
|
||||
int access, r;
|
||||
|
||||
len = strlen(ds_name_regexp)+1;
|
||||
g = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_name_regexp, len, CPF_READ);
|
||||
if(type == DS_CHECK || type == DS_RETRIEVE_LABEL) {
|
||||
len_key = DS_MAX_KEYLEN;
|
||||
access = CPF_WRITE;
|
||||
} else {
|
||||
len_key = strlen(ds_name)+1;
|
||||
access = CPF_READ;
|
||||
}
|
||||
|
||||
if(!GRANT_VALID(g))
|
||||
return GRANTBAD;
|
||||
/* Grant for key. */
|
||||
g_key = cpf_grant_direct(DS_PROC_NR, (vir_bytes) ds_name,
|
||||
len_key, access);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return errno;
|
||||
|
||||
flags &= DS_INITIAL;
|
||||
m.DS_KEY_GRANT = g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
|
||||
m.DS_KEY_GRANT = (char *) g;
|
||||
m.DS_KEY_LEN = len;
|
||||
m.DS_FLAGS = flags | (type & DS_TYPE_MASK);
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_SUBSCRIBE, &m);
|
||||
|
||||
cpf_revoke(g);
|
||||
r = _taskcall(DS_PROC_NR, type, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_publish_u32(ds_name, value)
|
||||
char *ds_name;
|
||||
u32_t value;
|
||||
int ds_publish_label(const char *ds_name, u32_t value, int flags)
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g;
|
||||
size_t len;
|
||||
|
||||
len = strlen(ds_name)+1;
|
||||
g = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_name, len, CPF_READ);
|
||||
|
||||
if(!GRANT_VALID(g))
|
||||
return GRANTBAD;
|
||||
|
||||
m.DS_KEY_GRANT = (char *) g;
|
||||
m.DS_KEY_LEN = len;
|
||||
m.DS_FLAGS = DS_TYPE_U32;
|
||||
m.DS_VAL = value;
|
||||
m.DS_VAL_LEN = sizeof(value);
|
||||
m.DS_FLAGS = DSF_TYPE_LABEL | flags;
|
||||
return do_invoke_ds(DS_PUBLISH, ds_name);
|
||||
}
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_PUBLISH, &m);
|
||||
int ds_publish_u32(const char *ds_name, u32_t value, int flags)
|
||||
{
|
||||
m.DS_VAL = value;
|
||||
m.DS_FLAGS = DSF_TYPE_U32 | flags;
|
||||
return do_invoke_ds(DS_PUBLISH, ds_name);
|
||||
}
|
||||
|
||||
cpf_revoke(g);
|
||||
int ds_publish_str(const char *ds_name, char *value, int flags)
|
||||
{
|
||||
if(strlen(value) >= DS_MAX_STRLEN)
|
||||
return EINVAL;
|
||||
strcpy((char *)(&m.DS_STRING), value);
|
||||
m.DS_FLAGS = DSF_TYPE_STR | flags;
|
||||
return do_invoke_ds(DS_PUBLISH, ds_name);
|
||||
}
|
||||
|
||||
int ds_publish_mem(const char *ds_name, void *vaddr, size_t length, int flags)
|
||||
{
|
||||
cp_grant_id_t gid;
|
||||
int r;
|
||||
|
||||
/* Grant for memory range. */
|
||||
gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, length, CPF_READ);
|
||||
if(!GRANT_VALID(gid))
|
||||
return errno;
|
||||
|
||||
m.DS_VAL = gid;
|
||||
m.DS_VAL_LEN = length;
|
||||
m.DS_FLAGS = DSF_TYPE_MEM | flags;
|
||||
|
||||
r = do_invoke_ds(DS_PUBLISH, ds_name);
|
||||
cpf_revoke(gid);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_publish_str(ds_name, value)
|
||||
char *ds_name;
|
||||
char *value;
|
||||
int ds_publish_map(const char *ds_name, void *vaddr, size_t length, int flags)
|
||||
{
|
||||
cp_grant_id_t gid;
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g_key, g_str;
|
||||
size_t len_key, len_str;
|
||||
|
||||
/* Grant for key. */
|
||||
len_key = strlen(ds_name)+1;
|
||||
g_key = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_name, len_key, CPF_READ);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return GRANTBAD;
|
||||
if(((vir_bytes)vaddr % CLICK_SIZE != 0) || (length % CLICK_SIZE != 0))
|
||||
return EINVAL;
|
||||
|
||||
/* Grant for value. */
|
||||
len_str = strlen(value)+1;
|
||||
g_str = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) value, len_str, CPF_READ);
|
||||
/* Grant for mapped memory range. */
|
||||
gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, length,
|
||||
CPF_READ | CPF_MAP);
|
||||
if(!GRANT_VALID(gid))
|
||||
return errno;
|
||||
|
||||
if(!GRANT_VALID(g_str)) {
|
||||
cpf_revoke(g_key);
|
||||
return GRANTBAD;
|
||||
}
|
||||
m.DS_VAL = gid;
|
||||
m.DS_VAL_LEN = length;
|
||||
m.DS_FLAGS = DSF_TYPE_MAP | flags;
|
||||
|
||||
m.DS_KEY_GRANT = (char *) g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
m.DS_FLAGS = DS_TYPE_STR;
|
||||
m.DS_VAL = g_str;
|
||||
m.DS_VAL_LEN = len_str;
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_PUBLISH, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
cpf_revoke(g_str);
|
||||
r = do_invoke_ds(DS_PUBLISH, ds_name);
|
||||
cpf_revoke(gid);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_u32(ds_name, value)
|
||||
char *ds_name;
|
||||
u32_t *value;
|
||||
int ds_snapshot_map(const char *ds_name, int *nr_snapshot)
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g_key;
|
||||
size_t len_key;
|
||||
|
||||
/* Grant for key. */
|
||||
len_key = strlen(ds_name)+1;
|
||||
g_key = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_name, len_key, CPF_READ);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return GRANTBAD;
|
||||
|
||||
/* Do request. */
|
||||
m.DS_KEY_GRANT = (char *) g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
m.DS_FLAGS = DS_TYPE_U32;
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
|
||||
if(r == OK) {
|
||||
/* Assign u32 value. */
|
||||
*value = m.DS_VAL;
|
||||
}
|
||||
|
||||
r = do_invoke_ds(DS_SNAPSHOT, ds_name);
|
||||
*nr_snapshot = m.DS_NR_SNAPSHOT;
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_str(ds_name, value, len_str)
|
||||
char *ds_name;
|
||||
char *value;
|
||||
size_t len_str;
|
||||
int ds_retrieve_label_name(char *ds_name, u32_t num)
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g_key, g_str;
|
||||
size_t len_key;
|
||||
|
||||
/* Grant for key. */
|
||||
len_key = strlen(ds_name)+1;
|
||||
g_key = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_name, len_key, CPF_READ);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return GRANTBAD;
|
||||
|
||||
/* Grant for value. */
|
||||
g_str = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) value, len_str, CPF_WRITE);
|
||||
|
||||
if(!GRANT_VALID(g_str)) {
|
||||
cpf_revoke(g_key);
|
||||
return GRANTBAD;
|
||||
}
|
||||
|
||||
/* Do request. */
|
||||
|
||||
m.DS_KEY_GRANT = (char *) g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
m.DS_FLAGS = DS_TYPE_STR;
|
||||
m.DS_VAL = g_str;
|
||||
m.DS_VAL_LEN = len_str;
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
cpf_revoke(g_str);
|
||||
|
||||
m.DS_VAL = num;
|
||||
r = do_invoke_ds(DS_RETRIEVE_LABEL, ds_name);
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_check_str(ds_key, len_key, value, len_str)
|
||||
char *ds_key;
|
||||
size_t len_key;
|
||||
char *value;
|
||||
size_t len_str;
|
||||
int ds_retrieve_label_num(const char *ds_name, u32_t *value)
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g_key, g_str;
|
||||
|
||||
if(len_key < 1 || len_str < 1) return -1002;
|
||||
|
||||
/* Grant for key. */
|
||||
g_key = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_key, len_key, CPF_WRITE);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return GRANTBAD;
|
||||
|
||||
/* Grant for value. */
|
||||
g_str = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) value, len_str, CPF_WRITE);
|
||||
|
||||
if(!GRANT_VALID(g_str)) {
|
||||
cpf_revoke(g_key);
|
||||
return GRANTBAD;
|
||||
}
|
||||
|
||||
/* Do request. */
|
||||
|
||||
m.DS_KEY_GRANT = (char *) g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
m.DS_FLAGS = DS_TYPE_STR;
|
||||
m.DS_VAL = g_str;
|
||||
m.DS_VAL_LEN = len_str;
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_CHECK, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
cpf_revoke(g_str);
|
||||
|
||||
ds_key[len_key-1] = '\0';
|
||||
value[len_str-1] = '\0';
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_check_u32(ds_key, len_key, value)
|
||||
char *ds_key;
|
||||
size_t len_key;
|
||||
u32_t *value;
|
||||
{
|
||||
int r;
|
||||
message m;
|
||||
cp_grant_id_t g_key;
|
||||
|
||||
if(len_key < 1) return -1;
|
||||
|
||||
/* Grant for key. */
|
||||
g_key = cpf_grant_direct(DS_PROC_NR,
|
||||
(vir_bytes) ds_key, len_key, CPF_WRITE);
|
||||
if(!GRANT_VALID(g_key))
|
||||
return GRANTBAD;
|
||||
|
||||
/* Do request. */
|
||||
m.DS_KEY_GRANT = (char *) g_key;
|
||||
m.DS_KEY_LEN = len_key;
|
||||
m.DS_FLAGS = DS_TYPE_U32;
|
||||
|
||||
r = _taskcall(DS_PROC_NR, DS_CHECK, &m);
|
||||
|
||||
cpf_revoke(g_key);
|
||||
|
||||
ds_key[len_key-1] = '\0';
|
||||
|
||||
/* Assign u32 value. */
|
||||
m.DS_FLAGS = DSF_TYPE_LABEL;
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
*value = m.DS_VAL;
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_u32(const char *ds_name, u32_t *value)
|
||||
{
|
||||
int r;
|
||||
m.DS_FLAGS = DSF_TYPE_U32;
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
*value = m.DS_VAL;
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_str(const char *ds_name, char *value, size_t len_str)
|
||||
{
|
||||
int r;
|
||||
m.DS_FLAGS = DSF_TYPE_STR;
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
strncpy(value, (char *)(&m.DS_STRING), DS_MAX_STRLEN);
|
||||
value[DS_MAX_STRLEN - 1] = '\0';
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_mem(const char *ds_name, char *vaddr, size_t *length)
|
||||
{
|
||||
cp_grant_id_t gid;
|
||||
int r;
|
||||
|
||||
/* Grant for memory range. */
|
||||
gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr, *length, CPF_WRITE);
|
||||
if(!GRANT_VALID(gid))
|
||||
return errno;
|
||||
|
||||
m.DS_VAL = gid;
|
||||
m.DS_VAL_LEN = *length;
|
||||
m.DS_FLAGS = DSF_TYPE_MEM;
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
*length = m.DS_VAL_LEN;
|
||||
cpf_revoke(gid);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_retrieve_map(const char *ds_name, char *vaddr, size_t *length,
|
||||
int nr_snapshot, int flags)
|
||||
{
|
||||
cp_grant_id_t gid;
|
||||
int r;
|
||||
|
||||
/* Map a mapped memory range. */
|
||||
if(flags & DSMF_MAP_MAPPED) {
|
||||
/* Request DS to grant. */
|
||||
m.DS_FLAGS = DSF_TYPE_MAP | DSMF_MAP_MAPPED;
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
if(r != OK)
|
||||
return r;
|
||||
|
||||
/* Do the safemap. */
|
||||
if(*length > m.DS_VAL_LEN)
|
||||
*length = m.DS_VAL_LEN;
|
||||
*length = (size_t) CLICK_FLOOR(*length);
|
||||
r = sys_safemap(DS_PROC_NR, m.DS_VAL, 0,
|
||||
(vir_bytes)vaddr, *length, D, 0);
|
||||
|
||||
/* Copy mapped memory range or a snapshot. */
|
||||
} else if(flags & (DSMF_COPY_MAPPED|DSMF_COPY_SNAPSHOT)) {
|
||||
/* Grant for memory range first. */
|
||||
gid = cpf_grant_direct(DS_PROC_NR, (vir_bytes)vaddr,
|
||||
*length, CPF_WRITE);
|
||||
if(!GRANT_VALID(gid))
|
||||
return errno;
|
||||
|
||||
m.DS_VAL = gid;
|
||||
m.DS_VAL_LEN = *length;
|
||||
if(flags & DSMF_COPY_MAPPED) {
|
||||
m.DS_FLAGS = DSF_TYPE_MAP | DSMF_COPY_MAPPED;
|
||||
}
|
||||
else {
|
||||
m.DS_NR_SNAPSHOT = nr_snapshot;
|
||||
m.DS_FLAGS = DSF_TYPE_MAP | DSMF_COPY_SNAPSHOT;
|
||||
}
|
||||
r = do_invoke_ds(DS_RETRIEVE, ds_name);
|
||||
*length = m.DS_VAL_LEN;
|
||||
cpf_revoke(gid);
|
||||
}
|
||||
else {
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
int ds_delete_u32(const char *ds_name)
|
||||
{
|
||||
m.DS_FLAGS = DSF_TYPE_U32;
|
||||
return do_invoke_ds(DS_DELETE, ds_name);
|
||||
}
|
||||
|
||||
int ds_delete_str(const char *ds_name)
|
||||
{
|
||||
m.DS_FLAGS = DSF_TYPE_STR;
|
||||
return do_invoke_ds(DS_DELETE, ds_name);
|
||||
}
|
||||
|
||||
int ds_delete_mem(const char *ds_name)
|
||||
{
|
||||
m.DS_FLAGS = DSF_TYPE_MEM;
|
||||
return do_invoke_ds(DS_DELETE, ds_name);
|
||||
}
|
||||
|
||||
int ds_delete_map(const char *ds_name)
|
||||
{
|
||||
m.DS_FLAGS = DSF_TYPE_MAP;
|
||||
return do_invoke_ds(DS_DELETE, ds_name);
|
||||
}
|
||||
|
||||
int ds_delete_label(const char *ds_name)
|
||||
{
|
||||
m.DS_FLAGS = DSF_TYPE_LABEL;
|
||||
return do_invoke_ds(DS_DELETE, ds_name);
|
||||
}
|
||||
|
||||
int ds_subscribe(const char *regexp, int flags)
|
||||
{
|
||||
m.DS_FLAGS = flags;
|
||||
return do_invoke_ds(DS_SUBSCRIBE, regexp);
|
||||
}
|
||||
|
||||
int ds_check(char *ds_key, int *type)
|
||||
{
|
||||
int r;
|
||||
r = do_invoke_ds(DS_CHECK, ds_key);
|
||||
*type = m.DS_FLAGS;
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ endpoint_t proc_ep;
|
||||
|
||||
if (pci_procnr == ANY)
|
||||
{
|
||||
r= ds_retrieve_u32("pci", &u32);
|
||||
r= ds_retrieve_label_num("pci", &u32);
|
||||
if (r != 0)
|
||||
{
|
||||
panic("syslib/" __FILE__,
|
||||
|
||||
@@ -22,9 +22,9 @@ char *name;
|
||||
size_t len;
|
||||
message m;
|
||||
|
||||
r= ds_retrieve_u32("pci", &u32);
|
||||
r= ds_retrieve_label_num("pci", &u32);
|
||||
if (r != 0)
|
||||
panic("syslib/" __FILE__, "pci_init1: ds_retrieve_u32 failed for 'pci'", r);
|
||||
panic("syslib/" __FILE__, "pci_init1: ds_retrieve_label_num failed for 'pci'", r);
|
||||
pci_procnr= u32;
|
||||
|
||||
m.m_type= BUSC_PCI_INIT;
|
||||
|
||||
@@ -22,11 +22,11 @@ struct rs_pci *rs_pci;
|
||||
|
||||
if (pci_procnr == ANY)
|
||||
{
|
||||
r= ds_retrieve_u32("pci", &u32);
|
||||
r= ds_retrieve_label_num("pci", &u32);
|
||||
if (r != 0)
|
||||
{
|
||||
panic("syslib/" __FILE__,
|
||||
"pci_set_acl: ds_retrieve_u32 failed for 'pci'",
|
||||
"pci_set_acl: ds_retrieve_label_num failed for 'pci'",
|
||||
r);
|
||||
}
|
||||
pci_procnr = u32;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#define ACCESS_CHECK(a) { \
|
||||
if((a) & ~(CPF_READ|CPF_WRITE)) { \
|
||||
if((a) & ~(CPF_READ|CPF_WRITE|CPF_MAP)) { \
|
||||
errno = EINVAL; \
|
||||
return -1; \
|
||||
} \
|
||||
@@ -37,6 +37,13 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define CLICK_ALIGNMENT_CHECK(addr, bytes) { \
|
||||
if(((vir_bytes)(addr) % CLICK_SIZE != 0) \
|
||||
|| ((vir_bytes)(bytes) % CLICK_SIZE != 0)) { \
|
||||
return EINVAL; \
|
||||
} \
|
||||
}
|
||||
|
||||
#define NR_STATIC_GRANTS 2
|
||||
PRIVATE cp_grant_t static_grants[NR_STATIC_GRANTS];
|
||||
PRIVATE cp_grant_t *grants = NULL;
|
||||
@@ -206,8 +213,16 @@ PUBLIC int
|
||||
cpf_revoke(cp_grant_id_t g)
|
||||
{
|
||||
/* Revoke previously granted access, identified by grant id. */
|
||||
int r;
|
||||
GID_CHECK_USED(g);
|
||||
|
||||
/* If this grant is for memory mapping, revoke the mapping first. */
|
||||
if(grants[g].cp_flags & CPF_MAP) {
|
||||
r = sys_saferevmap_gid(g);
|
||||
if(r != 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Make grant invalid by setting flags to 0, clearing CPF_USED.
|
||||
* This invalidates the grant.
|
||||
*/
|
||||
@@ -262,6 +277,12 @@ int access;
|
||||
GID_CHECK(gid);
|
||||
ACCESS_CHECK(access);
|
||||
|
||||
/* Check click alignment in case of memory mapping grant. */
|
||||
if(access & CPF_MAP) {
|
||||
CLICK_ALIGNMENT_CHECK(addr, bytes);
|
||||
}
|
||||
|
||||
/* Fill in new slot data. */
|
||||
grants[gid].cp_flags = access | CPF_DIRECT | CPF_USED | CPF_VALID;
|
||||
grants[gid].cp_u.cp_direct.cp_who_to = who;
|
||||
grants[gid].cp_u.cp_direct.cp_start = addr;
|
||||
@@ -298,6 +319,11 @@ int access;
|
||||
GID_CHECK(gid);
|
||||
ACCESS_CHECK(access);
|
||||
|
||||
/* Check click alignment in case of memory mapping grant. */
|
||||
if(access & CPF_MAP) {
|
||||
CLICK_ALIGNMENT_CHECK(addr, bytes);
|
||||
}
|
||||
|
||||
/* Fill in new slot data. */
|
||||
grants[gid].cp_flags = CPF_USED | CPF_MAGIC | CPF_VALID | access;
|
||||
grants[gid].cp_u.cp_magic.cp_who_to = who_to;
|
||||
|
||||
72
lib/syslib/sys_safemap.c
Normal file
72
lib/syslib/sys_safemap.c
Normal file
@@ -0,0 +1,72 @@
|
||||
|
||||
#include "syslib.h"
|
||||
|
||||
#include <minix/safecopies.h>
|
||||
|
||||
/*===========================================================================*
|
||||
* sys_safemap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int sys_safemap(endpoint_t grantor, cp_grant_id_t grant,
|
||||
vir_bytes grant_offset, vir_bytes my_address,
|
||||
size_t bytes, int my_seg, int writable)
|
||||
{
|
||||
/* Map a block of data for which the other process has previously
|
||||
* granted permission.
|
||||
*/
|
||||
|
||||
message copy_mess;
|
||||
|
||||
copy_mess.SMAP_EP = grantor;
|
||||
copy_mess.SMAP_GID = grant;
|
||||
copy_mess.SMAP_OFFSET = grant_offset;
|
||||
copy_mess.SMAP_SEG = (void*) my_seg;
|
||||
copy_mess.SMAP_ADDRESS = my_address;
|
||||
copy_mess.SMAP_BYTES = bytes;
|
||||
copy_mess.SMAP_FLAG = writable;
|
||||
|
||||
return(_taskcall(SYSTASK, SYS_SAFEMAP, ©_mess));
|
||||
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sys_saferevmap_gid *
|
||||
*===========================================================================*/
|
||||
PUBLIC int sys_saferevmap_gid(cp_grant_id_t grant)
|
||||
{
|
||||
/* Grantor revokes safemap by grant id. */
|
||||
message copy_mess;
|
||||
|
||||
copy_mess.SMAP_FLAG = 1;
|
||||
copy_mess.SMAP_GID = grant;
|
||||
|
||||
return(_taskcall(SYSTASK, SYS_SAFEREVMAP, ©_mess));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sys_saferevmap_addr *
|
||||
*===========================================================================*/
|
||||
PUBLIC int sys_saferevmap_addr(vir_bytes addr)
|
||||
{
|
||||
/* Grantor revokes safemap by address. */
|
||||
message copy_mess;
|
||||
|
||||
copy_mess.SMAP_FLAG = 0;
|
||||
copy_mess.SMAP_GID = addr;
|
||||
|
||||
return(_taskcall(SYSTASK, SYS_SAFEREVMAP, ©_mess));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sys_safeunmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int sys_safeunmap(int my_seg, vir_bytes my_address)
|
||||
{
|
||||
/* Requestor unmaps safemap. */
|
||||
message copy_mess;
|
||||
|
||||
copy_mess.SMAP_SEG = (void*) my_seg;
|
||||
copy_mess.SMAP_ADDRESS = my_address;
|
||||
|
||||
return(_taskcall(SYSTASK, SYS_SAFEUNMAP, ©_mess));
|
||||
}
|
||||
|
||||
@@ -43,7 +43,8 @@ PUBLIC int sys_vmctl_get_cr3_i386(endpoint_t who, u32_t *cr3)
|
||||
}
|
||||
|
||||
PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
|
||||
vir_bytes *len, int *wrflag, endpoint_t *requestor)
|
||||
vir_bytes *len, int *wrflag, endpoint_t *who_s, vir_bytes *mem_s,
|
||||
endpoint_t *requestor)
|
||||
{
|
||||
message m;
|
||||
int r;
|
||||
@@ -51,11 +52,13 @@ PUBLIC int sys_vmctl_get_memreq(endpoint_t *who, vir_bytes *mem,
|
||||
m.SVMCTL_WHO = SELF;
|
||||
m.SVMCTL_PARAM = VMCTL_MEMREQ_GET;
|
||||
r = _taskcall(SYSTASK, SYS_VMCTL, &m);
|
||||
if(r == OK) {
|
||||
*who = m.SVMCTL_MRG_EP;
|
||||
*mem = (vir_bytes) m.SVMCTL_MRG_ADDR;
|
||||
*len = m.SVMCTL_MRG_LEN;
|
||||
*wrflag = m.SVMCTL_MRG_WRITE;
|
||||
if(r >= 0) {
|
||||
*who = m.SVMCTL_MRG_TARGET;
|
||||
*mem = m.SVMCTL_MRG_ADDR;
|
||||
*len = m.SVMCTL_MRG_LENGTH;
|
||||
*wrflag = m.SVMCTL_MRG_FLAG;
|
||||
*who_s = m.SVMCTL_MRG_EP2;
|
||||
*mem_s = m.SVMCTL_MRG_ADDR2;
|
||||
*requestor = (endpoint_t) m.SVMCTL_MRG_REQUESTOR;
|
||||
}
|
||||
return r;
|
||||
|
||||
@@ -18,7 +18,7 @@ libsys_FILES=" \
|
||||
env_panic.c \
|
||||
env_prefix.c \
|
||||
fkey_ctl.c \
|
||||
micro_delay.c \
|
||||
tsc_util.c \
|
||||
report.c \
|
||||
taskcall.c \
|
||||
read_tsc.s \
|
||||
|
||||
@@ -17,15 +17,15 @@
|
||||
#define CALIBRATE \
|
||||
if(!calibrated) { \
|
||||
int r; \
|
||||
if((r=micro_delay_calibrate()) != OK) \
|
||||
panic(__FILE__, "micro_delay: calibrate failed\n", r); \
|
||||
if((r=tsc_calibrate()) != OK) \
|
||||
panic(__FILE__, "calibrate failed\n", r); \
|
||||
}
|
||||
|
||||
static u32_t calib_tsc, Hz = 0;
|
||||
static int calibrated = 0;
|
||||
|
||||
int
|
||||
micro_delay_calibrate(void)
|
||||
tsc_calibrate(void)
|
||||
{
|
||||
u64_t start, end, diff;
|
||||
struct tms tms;
|
||||
@@ -50,11 +50,11 @@ micro_delay_calibrate(void)
|
||||
diff = sub64(end, start);
|
||||
if(ex64hi(diff) != 0)
|
||||
panic(__FILE__,
|
||||
"micro_delay_calibrate: CALIBRATE_TICKS too high "
|
||||
"tsc_calibrate: CALIBRATE_TICKS too high "
|
||||
"for TSC frequency\n", NO_NUM);
|
||||
calib_tsc = ex64lo(diff);
|
||||
#if 0
|
||||
printf("micro_delay_calibrate: "
|
||||
printf("tsc_calibrate: "
|
||||
"%lu cycles/%d ticks of %d Hz; %lu cycles/s\n",
|
||||
calib_tsc, CALIBRATE_TICKS(Hz), Hz,
|
||||
div64u(mul64u(calib_tsc, Hz), CALIBRATE_TICKS(Hz)));
|
||||
@@ -94,3 +94,23 @@ micro_delay(u32_t micros)
|
||||
return OK;
|
||||
}
|
||||
|
||||
u32_t tsc_64_to_micros(u64_t tsc)
|
||||
{
|
||||
return tsc_to_micros(ex64lo(tsc), ex64hi(tsc));
|
||||
}
|
||||
|
||||
u32_t tsc_to_micros(u32_t low, u32_t high)
|
||||
{
|
||||
u32_t micros;
|
||||
|
||||
if(high) {
|
||||
return 0;
|
||||
}
|
||||
CALIBRATE;
|
||||
|
||||
micros = (div64u(mul64u(low, MICROHZ * CALIBRATE_TICKS(Hz)),
|
||||
calib_tsc)/Hz);
|
||||
|
||||
return micros;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user