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:
parent
da3b64d8bc
commit
c5b309ff07
99 changed files with 3594 additions and 851 deletions
|
@ -1027,11 +1027,11 @@ int pci_func;
|
|||
u32_t u32;
|
||||
message m;
|
||||
|
||||
r= ds_retrieve_u32("amddev", &u32);
|
||||
r= ds_retrieve_label_num("amddev", &u32);
|
||||
if (r != OK)
|
||||
{
|
||||
#if 0
|
||||
printf("tell_dev: ds_retrieve_u32 failed for 'amddev': %d\n",
|
||||
printf("tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
|
||||
r);
|
||||
#endif
|
||||
return;
|
||||
|
|
|
@ -157,9 +157,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
memset(e1000_table, 0, sizeof(e1000_table));
|
||||
|
||||
/* Perform calibration. */
|
||||
if((r = micro_delay_calibrate()) != OK)
|
||||
if((r = tsc_calibrate()) != OK)
|
||||
{
|
||||
panic("e1000", "rmicro_delay_calibrate failed", r);
|
||||
panic("e1000", "tsc_calibrate failed", r);
|
||||
}
|
||||
/* Try to notify inet that we are present (again) */
|
||||
if ((r = ds_retrieve_u32("inet", &tasknr)) == OK)
|
||||
|
|
|
@ -414,15 +414,15 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
|
||||
memset(fxp_table, 0, ft);
|
||||
|
||||
if((r=micro_delay_calibrate()) != OK)
|
||||
panic("FXP","rmicro_delay_calibrate failed", r);
|
||||
if((r=tsc_calibrate()) != OK)
|
||||
panic("FXP","tsc_calibrate failed", r);
|
||||
|
||||
/* Try to notify inet that we are present (again) */
|
||||
r= ds_retrieve_u32("inet", &tasknr);
|
||||
r= ds_retrieve_label_num("inet", &tasknr);
|
||||
if (r == OK)
|
||||
notify(tasknr);
|
||||
else if (r != ESRCH)
|
||||
printf("fxp: ds_retrieve_u32 failed for 'inet': %d\n", r);
|
||||
printf("fxp: ds_retrieve_label_num failed for 'inet': %d\n", r);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
@ -3013,12 +3013,12 @@ int pci_func;
|
|||
u32_t u32;
|
||||
message m;
|
||||
|
||||
r= ds_retrieve_u32("amddev", &u32);
|
||||
r= ds_retrieve_label_num("amddev", &u32);
|
||||
if (r != OK)
|
||||
{
|
||||
#if 0
|
||||
printf(
|
||||
"fxp`tell_dev: ds_retrieve_u32 failed for 'amddev': %d\n",
|
||||
"fxp`tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
|
||||
r);
|
||||
#endif
|
||||
return;
|
||||
|
|
|
@ -367,11 +367,11 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
/* Try to notify INET that we are present (again). If INET cannot
|
||||
* be found, assume this is the first time we started and INET is
|
||||
* not yet alive. */
|
||||
r = ds_retrieve_u32("inet", &inet_proc_nr);
|
||||
r = ds_retrieve_label_num("inet", &inet_proc_nr);
|
||||
if (r == OK)
|
||||
notify(inet_proc_nr);
|
||||
else if (r != ESRCH)
|
||||
printf("orinoco: ds_retrieve_u32 failed for 'inet': %d\n", r);
|
||||
printf("orinoco: ds_retrieve_label_num failed for 'inet': %d\n", r);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
|
|
@ -336,11 +336,11 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
* be found, assume this is the first time we started and INET is
|
||||
* not yet alive.
|
||||
*/
|
||||
r= ds_retrieve_u32("inet", &inet_proc_nr);
|
||||
r= ds_retrieve_label_num("inet", &inet_proc_nr);
|
||||
if (r == OK)
|
||||
notify(inet_proc_nr);
|
||||
else if (r != ESRCH)
|
||||
printf("rtl8139: ds_retrieve_u32 failed for 'inet': %d\n", r);
|
||||
printf("rtl8139: ds_retrieve_label_num failed for 'inet': %d\n", r);
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
@ -3017,12 +3017,12 @@ int pci_func;
|
|||
u32_t u32;
|
||||
message m;
|
||||
|
||||
r= ds_retrieve_u32("amddev", &u32);
|
||||
r= ds_retrieve_label_num("amddev", &u32);
|
||||
if (r != OK)
|
||||
{
|
||||
#if 0
|
||||
printf(
|
||||
"rtl8139`tell_dev: ds_retrieve_u32 failed for 'amddev': %d\n",
|
||||
"rtl8139`tell_dev: ds_retrieve_label_num failed for 'amddev': %d\n",
|
||||
r);
|
||||
#endif
|
||||
return;
|
||||
|
|
|
@ -117,8 +117,8 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
(progname=strrchr(env_argv[0],'/')) ? progname++
|
||||
: (progname=env_argv[0]);
|
||||
|
||||
if((r=micro_delay_calibrate()) != OK)
|
||||
panic("ti1225", "micro_delay_calibrate failed", r);
|
||||
if((r=tsc_calibrate()) != OK)
|
||||
panic("ti1225", "tsc_calibrate failed", r);
|
||||
|
||||
debug= 0;
|
||||
while (c= getopt(env_argc, env_argv, "d?"), c != -1)
|
||||
|
|
|
@ -350,8 +350,11 @@
|
|||
|
||||
# define SYS_VTIMER (KERNEL_CALL + 45) /* sys_vtimer() */
|
||||
# define SYS_RUNCTL (KERNEL_CALL + 46) /* sys_runctl() */
|
||||
# define SYS_SAFEMAP (KERNEL_CALL + 47) /* sys_safemap() */
|
||||
# define SYS_SAFEREVMAP (KERNEL_CALL + 48) /* sys_saferevmap() sys_saferevmap2() */
|
||||
# define SYS_SAFEUNMAP (KERNEL_CALL + 49) /* sys_safeunmap() */
|
||||
|
||||
#define NR_SYS_CALLS 47 /* number of system calls */
|
||||
#define NR_SYS_CALLS 50 /* number of system calls */
|
||||
#define SYS_CALL_MASK_SIZE BITMAP_CHUNKS(NR_SYS_CALLS)
|
||||
|
||||
/* Field names for SYS_MEMSET. */
|
||||
|
@ -536,6 +539,15 @@
|
|||
#define VSCP_VEC_ADDR m2_p1 /* start of vector */
|
||||
#define VSCP_VEC_SIZE m2_l2 /* elements in vector */
|
||||
|
||||
/* Field names for SYS_SAFEMAPs */
|
||||
#define SMAP_EP m2_i1
|
||||
#define SMAP_GID m2_i2
|
||||
#define SMAP_OFFSET m2_i3
|
||||
#define SMAP_SEG m2_p1
|
||||
#define SMAP_ADDRESS m2_l1
|
||||
#define SMAP_BYTES m2_l2
|
||||
#define SMAP_FLAG m2_s1
|
||||
|
||||
/* Field names for SYS_SPROF, _CPROF, _PROFBUF. */
|
||||
#define PROF_ACTION m7_i1 /* start/stop/reset/get */
|
||||
#define PROF_MEM_SIZE m7_i2 /* available memory for data */
|
||||
|
@ -556,11 +568,13 @@
|
|||
#define SVMCTL_PF_WHO m1_i1 /* GET_PAGEFAULT reply: process ep */
|
||||
#define SVMCTL_PF_I386_CR2 m1_i2 /* GET_PAGEFAULT reply: CR2 */
|
||||
#define SVMCTL_PF_I386_ERR m1_i3 /* GET_PAGEFAULT reply: error code */
|
||||
#define SVMCTL_MRG_ADDR m1_p1 /* MEMREQ_GET reply: address */
|
||||
#define SVMCTL_MRG_LEN m1_i1 /* MEMREQ_GET reply: length */
|
||||
#define SVMCTL_MRG_WRITE m1_i2 /* MEMREQ_GET reply: writeflag */
|
||||
#define SVMCTL_MRG_EP m1_i3 /* MEMREQ_GET reply: process */
|
||||
#define SVMCTL_MRG_REQUESTOR m1_p2 /* MEMREQ_GET reply: requestor */
|
||||
#define SVMCTL_MRG_TARGET m2_i1 /* MEMREQ_GET reply: target process */
|
||||
#define SVMCTL_MRG_ADDR m2_i2 /* MEMREQ_GET reply: address */
|
||||
#define SVMCTL_MRG_LENGTH m2_i3 /* MEMREQ_GET reply: length */
|
||||
#define SVMCTL_MRG_FLAG m2_s1 /* MEMREQ_GET reply: flag */
|
||||
#define SVMCTL_MRG_EP2 m2_l1 /* MEMREQ_GET reply: source process */
|
||||
#define SVMCTL_MRG_ADDR2 m2_l2 /* MEMREQ_GET reply: source address */
|
||||
#define SVMCTL_MRG_REQUESTOR m2_p1 /* MEMREQ_GET reply: requestor */
|
||||
#define SVMCTL_MAP_VIR_ADDR m1_p1
|
||||
|
||||
/* Reply message for VMCTL_KERN_PHYSMAP */
|
||||
|
@ -654,19 +668,23 @@
|
|||
|
||||
#define DS_RQ_BASE 0x800
|
||||
|
||||
#define DS_PUBLISH (DS_RQ_BASE + 0) /* publish information */
|
||||
#define DS_SUBSCRIBE (DS_RQ_BASE + 1) /* subscribe to information */
|
||||
#define DS_RETRIEVE (DS_RQ_BASE + 2) /* retrieve information by name */
|
||||
#define DS_CHECK (DS_RQ_BASE + 3) /* retrieve updated information */
|
||||
#define DS_PUBLISH (DS_RQ_BASE + 0) /* publish data */
|
||||
#define DS_RETRIEVE (DS_RQ_BASE + 1) /* retrieve data by name */
|
||||
#define DS_SUBSCRIBE (DS_RQ_BASE + 2) /* subscribe to data updates */
|
||||
#define DS_CHECK (DS_RQ_BASE + 3) /* retrieve updated data */
|
||||
#define DS_DELETE (DS_RQ_BASE + 4) /* delete data */
|
||||
#define DS_SNAPSHOT (DS_RQ_BASE + 5) /* take a snapshot */
|
||||
#define DS_RETRIEVE_LABEL (DS_RQ_BASE + 6) /* retrieve label's name */
|
||||
|
||||
/* DS field names: DS_SUBSCRIBE, DS_PUBLISH, DS_RETRIEVE */
|
||||
# define DS_KEY_GRANT m2_p1 /* key for the information */
|
||||
# define DS_KEY_LEN m2_i1 /* length of key incl. '\0' */
|
||||
/* DS field names */
|
||||
# define DS_KEY_GRANT m2_i1 /* key for the data */
|
||||
# define DS_KEY_LEN m2_s1 /* length of key incl. '\0' */
|
||||
# define DS_FLAGS m2_i2 /* flags provided by caller */
|
||||
|
||||
/* DS_PUBLISH, DS_RETRIEVE */
|
||||
# define DS_VAL m2_l1 /* data (u32, char *, etc.) */
|
||||
# define DS_VAL_LEN m2_l2 /* data length */
|
||||
# define DS_NR_SNAPSHOT m2_i3 /* number of snapshot */
|
||||
# define DS_STRING m2_i3 /* inline string */
|
||||
|
||||
/*===========================================================================*
|
||||
* Miscellaneous messages used by TTY *
|
||||
|
|
|
@ -79,6 +79,10 @@
|
|||
#define CLICK_SHIFT 12 /* log2 of CLICK_SIZE */
|
||||
#endif
|
||||
|
||||
/* Click alignment macros. */
|
||||
#define CLICK_FLOOR(n) (((vir_bytes)(n) / CLICK_SIZE) * CLICK_SIZE)
|
||||
#define CLICK_CEIL(n) CLICK_FLOOR((vir_bytes)(n) + CLICK_SIZE-1)
|
||||
|
||||
/* Sizes of memory tables. The boot monitor distinguishes three memory areas,
|
||||
* namely low mem below 1M, 1M-16M, and mem after 16M. More chunks are needed
|
||||
* for DOS MINIX.
|
||||
|
|
|
@ -5,34 +5,68 @@
|
|||
|
||||
#include <minix/types.h>
|
||||
|
||||
/* DS Flag values. */
|
||||
#define DS_IN_USE 0x0001 /* Internal use only. */
|
||||
#define DS_PUBLIC 0x0002 /* Publically retrievable value. */
|
||||
#define DS_INITIAL 0x0004 /* On subscription, send initial contents. */
|
||||
/* Flags. */
|
||||
#define DSF_IN_USE 0x001 /* entry is in use */
|
||||
#define DSF_PRIV_RETRIEVE 0x002 /* only owner can retrieve */
|
||||
#define DSF_PRIV_OVERWRITE 0x004 /* only owner can overwrite */
|
||||
#define DSF_PRIV_SNAPSHOT 0x004 /* only owner can take a snapshot */
|
||||
#define DSF_PRIV_SUBSCRIBE 0x008 /* only owner can subscribe */
|
||||
#define DSF_TYPE_U32 0x010 /* u32 data type */
|
||||
#define DSF_TYPE_STR 0x020 /* string data type */
|
||||
#define DSF_TYPE_MEM 0x040 /* memory range data type */
|
||||
#define DSF_TYPE_MAP 0x080 /* mapped memory range data type */
|
||||
#define DSF_TYPE_LABEL 0x100 /* label data type */
|
||||
|
||||
/* These type flags are mutually exclusive. Give as args to ds_subscribe. */
|
||||
#define DS_TYPE_U32 0x0100
|
||||
#define DS_TYPE_STR 0x0200
|
||||
#define DS_TYPE_MASK 0xff00 /* All type info. */
|
||||
#define DSF_MASK_TYPE 0xFF0 /* mask for type flags. */
|
||||
#define DSF_MASK_INTERNAL 0xFFF /* mask for internal flags. */
|
||||
|
||||
#define DSF_OVERWRITE 0x01000 /* overwrite if entry exists */
|
||||
#define DSF_INITIAL 0x02000 /* check subscriptions immediately */
|
||||
|
||||
#define DSMF_MAP_MAPPED 0x10000 /* map mapped memory range */
|
||||
#define DSMF_COPY_MAPPED 0x20000 /* copy mapped memory range */
|
||||
#define DSMF_COPY_SNAPSHOT 0x40000 /* copy snapshot */
|
||||
|
||||
/* DS constants. */
|
||||
#define DS_MAX_KEYLEN 80 /* Max length for a key, including '\0'. */
|
||||
#define DS_MAX_VALLEN 100 /* Max legnth for a str value, incl '\0'. */
|
||||
#define DS_MAX_KEYLEN 80 /* Max length of a key, including '\0'. */
|
||||
#define DS_MAX_STRLEN 16 /* Max length of string, including '\0'. */
|
||||
|
||||
/* ds.c */
|
||||
_PROTOTYPE( int ds_subscribe, (char *name_regexp, int type, int flags));
|
||||
|
||||
/* publish/update item */
|
||||
_PROTOTYPE( int ds_publish_u32, (char *name, u32_t val));
|
||||
_PROTOTYPE( int ds_publish_str, (char *name, char *val));
|
||||
/* U32 */
|
||||
_PROTOTYPE( int ds_publish_u32, (const char *name, u32_t val, int flags));
|
||||
_PROTOTYPE( int ds_retrieve_u32, (const char *name, u32_t *val));
|
||||
_PROTOTYPE( int ds_delete_u32, (const char *ds_name));
|
||||
|
||||
/* retrieve item by name + type */
|
||||
_PROTOTYPE( int ds_retrieve_u32, (char *name, u32_t *val) );
|
||||
_PROTOTYPE( int ds_retrieve_str, (char *name, char *val, size_t len));
|
||||
/* STRING */
|
||||
_PROTOTYPE( int ds_publish_str, (const char *name, char *val, int flags));
|
||||
_PROTOTYPE( int ds_retrieve_str, (const char *name, char *val, size_t len));
|
||||
_PROTOTYPE( int ds_delete_str, (const char *ds_name));
|
||||
|
||||
/* retrieve updates for item */
|
||||
_PROTOTYPE( int ds_check_u32, (char *n, size_t namelen, u32_t *val));
|
||||
_PROTOTYPE( int ds_check_str, (char *n, size_t namelen, char *v, size_t vlen));
|
||||
/* MEM */
|
||||
_PROTOTYPE( int ds_publish_mem, (const char *ds_name, void *vaddr,
|
||||
size_t length, int flags));
|
||||
_PROTOTYPE( int ds_retrieve_mem, (const char *ds_name, char *vaddr,
|
||||
size_t *length));
|
||||
_PROTOTYPE( int ds_delete_mem, (const char *ds_name));
|
||||
|
||||
/* MAP */
|
||||
_PROTOTYPE( int ds_publish_map, (const char *ds_name, void *vaddr,
|
||||
size_t length, int flags));
|
||||
_PROTOTYPE( int ds_snapshot_map, (const char *ds_name, int *nr_snapshot));
|
||||
_PROTOTYPE( int ds_retrieve_map, (const char *ds_name, char *vaddr,
|
||||
size_t *length, int nr_snapshot, int flags));
|
||||
_PROTOTYPE( int ds_delete_map, (const char *ds_name));
|
||||
|
||||
/* LABEL */
|
||||
_PROTOTYPE( int ds_publish_label, (const char *ds_name, u32_t value,int flags));
|
||||
_PROTOTYPE( int ds_retrieve_label_name, (char *ds_name, u32_t num));
|
||||
_PROTOTYPE( int ds_retrieve_label_num, (const char *ds_name, u32_t *value));
|
||||
_PROTOTYPE( int ds_delete_label, (const char *ds_name));
|
||||
|
||||
/* Subscribe and check. */
|
||||
_PROTOTYPE( int ds_subscribe, (const char *regex, int flags));
|
||||
_PROTOTYPE( int ds_check, (char *ds_name, int *type));
|
||||
|
||||
#endif /* _MINIX_DS_H */
|
||||
|
||||
|
|
|
@ -49,6 +49,13 @@ struct vscp_vec {
|
|||
size_t v_bytes; /* no. of bytes */
|
||||
};
|
||||
|
||||
/* Types on VM invocation. */
|
||||
#define VMPTYPE_NONE 0
|
||||
#define VMPTYPE_CHECK 1
|
||||
#define VMPTYPE_COWMAP 2
|
||||
#define VMPTYPE_SMAP 3
|
||||
#define VMPTYPE_SUNMAP 4
|
||||
|
||||
/* Invalid grant number. */
|
||||
#define GRANT_INVALID -1
|
||||
#define GRANT_VALID(g) ((g) > GRANT_INVALID)
|
||||
|
@ -56,6 +63,7 @@ struct vscp_vec {
|
|||
/* Operations: any combination is ok. */
|
||||
#define CPF_READ 0x000001 /* Granted process may read. */
|
||||
#define CPF_WRITE 0x000002 /* Granted process may write. */
|
||||
#define CPF_MAP 0x000004 /* Granted process may map. */
|
||||
|
||||
/* Internal flags. */
|
||||
#define CPF_USED 0x000100 /* Grant slot in use. */
|
||||
|
|
|
@ -62,7 +62,8 @@ _PROTOTYPE( int sys_vmctl, (endpoint_t who, int param, u32_t value));
|
|||
_PROTOTYPE( int sys_vmctl_get_pagefault_i386, (endpoint_t *who, u32_t *cr2, u32_t *err));
|
||||
_PROTOTYPE( int sys_vmctl_get_cr3_i386, (endpoint_t who, u32_t *cr3) );
|
||||
_PROTOTYPE( int sys_vmctl_get_memreq, (endpoint_t *who, vir_bytes *mem,
|
||||
vir_bytes *len, int *wrflag, endpoint_t *) );
|
||||
vir_bytes *len, int *wrflag, endpoint_t *who_s, vir_bytes *mem_s,
|
||||
endpoint_t *) );
|
||||
_PROTOTYPE( int sys_vmctl_enable_paging, (struct mem_map *));
|
||||
|
||||
_PROTOTYPE( int sys_readbios, (phys_bytes address, void *buf, size_t size));
|
||||
|
@ -149,6 +150,14 @@ _PROTOTYPE(int sys_vsafecopy, (struct vscp_vec *copyvec, int elements));
|
|||
_PROTOTYPE(int sys_memset, (unsigned long pattern,
|
||||
phys_bytes base, phys_bytes bytes));
|
||||
|
||||
/* Grant-based map functions. */
|
||||
_PROTOTYPE(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));
|
||||
_PROTOTYPE(int sys_saferevmap_gid, (cp_grant_id_t grant));
|
||||
_PROTOTYPE(int sys_saferevmap_addr, (vir_bytes addr));
|
||||
_PROTOTYPE(int sys_safeunmap, (int my_seg, vir_bytes my_address));
|
||||
|
||||
_PROTOTYPE(int sys_umap, (endpoint_t proc_ep, int seg, vir_bytes vir_addr,
|
||||
vir_bytes bytes, phys_bytes *phys_addr));
|
||||
_PROTOTYPE(int sys_umap_data_fb, (endpoint_t proc_ep, vir_bytes vir_addr,
|
||||
|
|
|
@ -49,13 +49,15 @@ _PROTOTYPE( void panic, (char *who, char *mess, int num));
|
|||
_PROTOTYPE( int getuptime, (clock_t *ticks));
|
||||
_PROTOTYPE( int getuptime2, (clock_t *ticks, time_t *boottime));
|
||||
_PROTOTYPE( int tickdelay, (clock_t ticks));
|
||||
_PROTOTYPE( int micro_delay_calibrate, (void));
|
||||
_PROTOTYPE( int tsc_calibrate, (void));
|
||||
_PROTOTYPE( u32_t sys_hz, (void));
|
||||
_PROTOTYPE( double getidle, (void));
|
||||
_PROTOTYPE( void util_stacktrace, (void));
|
||||
_PROTOTYPE( void util_nstrcat, (char *str, unsigned long n) );
|
||||
_PROTOTYPE( void util_stacktrace_strcat, (char *));
|
||||
_PROTOTYPE( int micro_delay, (u32_t micros));
|
||||
_PROTOTYPE( u32_t tsc_64_to_micros, (u64_t tsc));
|
||||
_PROTOTYPE( u32_t tsc_to_micros, (u32_t low, u32_t high));
|
||||
_PROTOTYPE( u32_t micros_to_ticks, (u32_t micros));
|
||||
_PROTOTYPE( void ser_putc, (char c));
|
||||
_PROTOTYPE( void get_randomness, (struct k_randomness *, int));
|
||||
|
|
|
@ -44,12 +44,13 @@
|
|||
#define SI_PROC_TAB 2 /* copy of entire process table */
|
||||
#define SI_DMAP_TAB 3 /* get device <-> driver mappings */
|
||||
#define SI_MEM_ALLOC 4 /* get memory allocation data */
|
||||
#define SI_DATA_STORE 5 /* get copy of data store */
|
||||
#define SI_LOADINFO 6 /* get copy of load average structure */
|
||||
#define SI_KPROC_TAB 7 /* copy of kernel process table */
|
||||
#define SI_CALL_STATS 8 /* system call statistics */
|
||||
#define SI_PCI_INFO 9 /* get kernel info via PM */
|
||||
#define SI_PROCPUB_TAB 10 /* copy of public entries of process table */
|
||||
#define SI_DATA_STORE 5 /* get copy of data store mappings */
|
||||
#define SI_SUBSCRIPTION 6 /* get copy of data store subscriptions */
|
||||
#define SI_LOADINFO 7 /* get copy of load average structure */
|
||||
#define SI_KPROC_TAB 8 /* copy of kernel process table */
|
||||
#define SI_CALL_STATS 9 /* system call statistics */
|
||||
#define SI_PCI_INFO 10 /* get kernel info via PM */
|
||||
#define SI_PROCPUB_TAB 11 /* copy of public entries of process table */
|
||||
|
||||
/* NULL must be defined in <unistd.h> according to POSIX Sec. 2.7.1. */
|
||||
#define NULL ((void *)0)
|
||||
|
|
|
@ -613,10 +613,11 @@ PUBLIC int vm_suspend(struct proc *caller, struct proc *target,
|
|||
util_stacktrace_strcat(caller->p_vmrequest.stacktrace);
|
||||
#endif
|
||||
|
||||
caller->p_vmrequest.writeflag = 1;
|
||||
caller->p_vmrequest.start = linaddr;
|
||||
caller->p_vmrequest.length = len;
|
||||
caller->p_vmrequest.who = target->p_endpoint;
|
||||
caller->p_vmrequest.req_type = VMPTYPE_CHECK;
|
||||
caller->p_vmrequest.target = target->p_endpoint;
|
||||
caller->p_vmrequest.params.check.start = linaddr;
|
||||
caller->p_vmrequest.params.check.length = len;
|
||||
caller->p_vmrequest.params.check.writeflag = 1;
|
||||
caller->p_vmrequest.type = type;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
|
|
|
@ -137,12 +137,7 @@ PUBLIC void prot_init(void)
|
|||
/* Click-round kernel. */
|
||||
if(kinfo.data_base % CLICK_SIZE)
|
||||
minix_panic("kinfo.data_base not aligned", NO_NUM);
|
||||
kinfo.data_size = ((kinfo.data_size+CLICK_SIZE-1)/CLICK_SIZE) * CLICK_SIZE;
|
||||
|
||||
/* Click-round kernel. */
|
||||
if(kinfo.data_base % CLICK_SIZE)
|
||||
minix_panic("kinfo.data_base not aligned", NO_NUM);
|
||||
kinfo.data_size = ((kinfo.data_size+CLICK_SIZE-1)/CLICK_SIZE) * CLICK_SIZE;
|
||||
kinfo.data_size = (phys_bytes) (CLICK_CEIL(kinfo.data_size));
|
||||
|
||||
/* Build gdt and idt pointers in GDT where the BIOS expects them. */
|
||||
dtp= (struct desctableptr_s *) &gdt[GDT_INDEX];
|
||||
|
|
|
@ -154,13 +154,14 @@ PUBLIC void main()
|
|||
|
||||
/* Convert addresses to clicks and build process memory map */
|
||||
text_base = e_hdr.a_syms >> CLICK_SHIFT;
|
||||
text_clicks = (e_hdr.a_text + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
data_clicks = (e_hdr.a_data+e_hdr.a_bss + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
st_clicks= (e_hdr.a_total + CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
text_clicks = (vir_clicks) (CLICK_CEIL(e_hdr.a_text) >> CLICK_SHIFT);
|
||||
data_clicks = (vir_clicks) (CLICK_CEIL(e_hdr.a_data
|
||||
+ e_hdr.a_bss) >> CLICK_SHIFT);
|
||||
st_clicks = (vir_clicks) (CLICK_CEIL(e_hdr.a_total) >> CLICK_SHIFT);
|
||||
if (!(e_hdr.a_flags & A_SEP))
|
||||
{
|
||||
data_clicks= (e_hdr.a_text+e_hdr.a_data+e_hdr.a_bss +
|
||||
CLICK_SIZE-1) >> CLICK_SHIFT;
|
||||
data_clicks = (vir_clicks) (CLICK_CEIL(e_hdr.a_text +
|
||||
e_hdr.a_data + e_hdr.a_bss) >> CLICK_SHIFT);
|
||||
text_clicks = 0; /* common I&D */
|
||||
}
|
||||
rp->p_memmap[T].mem_phys = text_base;
|
||||
|
|
|
@ -61,7 +61,7 @@ struct proc {
|
|||
* memory that isn't present, VM has to fix it. Until it has asked
|
||||
* what needs to be done and fixed it, save necessary state here.
|
||||
*
|
||||
* The requester gets a copy of its request message in reqmsg and gets
|
||||
* The requestor gets a copy of its request message in reqmsg and gets
|
||||
* VMREQUEST set.
|
||||
*/
|
||||
struct {
|
||||
|
@ -70,6 +70,8 @@ struct proc {
|
|||
#define VMSTYPE_SYS_NONE 0
|
||||
#define VMSTYPE_KERNELCALL 1
|
||||
#define VMSTYPE_DELIVERMSG 2
|
||||
#define VMSTYPE_MAP 3
|
||||
|
||||
int type; /* suspended operation */
|
||||
union {
|
||||
/* VMSTYPE_SYS_MESSAGE */
|
||||
|
@ -77,10 +79,20 @@ struct proc {
|
|||
} saved;
|
||||
|
||||
/* Parameters of request to VM */
|
||||
vir_bytes start, length; /* memory range */
|
||||
u8_t writeflag; /* nonzero for write access */
|
||||
endpoint_t who;
|
||||
|
||||
int req_type;
|
||||
endpoint_t target;
|
||||
union {
|
||||
struct {
|
||||
vir_bytes start, length; /* memory range */
|
||||
u8_t writeflag; /* nonzero for write access */
|
||||
} check;
|
||||
struct {
|
||||
char writeflag;
|
||||
endpoint_t ep_s;
|
||||
vir_bytes vir_s, vir_d;
|
||||
vir_bytes length;
|
||||
} map;
|
||||
} params;
|
||||
/* VM result when available */
|
||||
int vmresult;
|
||||
|
||||
|
|
|
@ -89,6 +89,12 @@ _PROTOTYPE( void check_runqueues_f, (char *file, int line) );
|
|||
_PROTOTYPE( char *rtsflagstr, (int flags) );
|
||||
_PROTOTYPE( char *miscflagstr, (int flags) );
|
||||
|
||||
/* system/do_safemap.c */
|
||||
_PROTOTYPE( int map_invoke_vm, (int req_type,
|
||||
endpoint_t end_d, int seg_d, vir_bytes off_d,
|
||||
endpoint_t end_s, int seg_s, vir_bytes off_s,
|
||||
size_t size, int flag));
|
||||
|
||||
/* system/do_safecopy.c */
|
||||
_PROTOTYPE( int verify_grant, (endpoint_t, endpoint_t, cp_grant_id_t, vir_bytes,
|
||||
int, vir_bytes, vir_bytes *, endpoint_t *));
|
||||
|
|
|
@ -208,6 +208,11 @@ PRIVATE void initialize(void)
|
|||
map(SYS_SAFECOPYTO, do_safecopy); /* copy with pre-granted permission */
|
||||
map(SYS_VSAFECOPY, do_vsafecopy); /* vectored safecopy */
|
||||
|
||||
/* Mapping. */
|
||||
map(SYS_SAFEMAP, do_safemap); /* map pages from other process */
|
||||
map(SYS_SAFEREVMAP, do_saferevmap); /* grantor revokes the map grant */
|
||||
map(SYS_SAFEUNMAP, do_safeunmap); /* requestor unmaps the mapped pages */
|
||||
|
||||
/* Clock functionality. */
|
||||
map(SYS_TIMES, do_times); /* get uptime and process times */
|
||||
map(SYS_SETALARM, do_setalarm); /* schedule a synchronous alarm */
|
||||
|
@ -263,10 +268,6 @@ int priv_id; /* privilege id */
|
|||
rc->p_priv = sp; /* assign new slot */
|
||||
rc->p_priv->s_proc_nr = proc_nr(rc); /* set association */
|
||||
|
||||
/* Clear some fields */
|
||||
sp->s_asyntab= -1;
|
||||
sp->s_asynsize= 0;
|
||||
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
@ -482,9 +483,11 @@ register struct proc *rc; /* slot of process to clean up */
|
|||
if (priv(rc)->s_flags & SYS_PROC)
|
||||
{
|
||||
if (priv(rc)->s_asynsize) {
|
||||
#if 0
|
||||
kprintf("clear_endpoint: clearing s_asynsize of %s / %d\n",
|
||||
rc->p_name, rc->p_endpoint);
|
||||
proc_stacktrace(rc);
|
||||
#endif
|
||||
}
|
||||
priv(rc)->s_asynsize= 0;
|
||||
}
|
||||
|
|
|
@ -181,6 +181,10 @@ _PROTOTYPE( int do_setgrant, (message *m_ptr) );
|
|||
_PROTOTYPE( int do_readbios, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_mapdma, (message *m_ptr) );
|
||||
|
||||
_PROTOTYPE( int do_safemap, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_saferevmap, (message *m_ptr) );
|
||||
_PROTOTYPE( int do_safeunmap, (message *m_ptr) );
|
||||
|
||||
_PROTOTYPE( int do_sprofile, (message *m_ptr) );
|
||||
#if ! SPROFILE
|
||||
#define do_sprofile do_unused
|
||||
|
|
|
@ -44,6 +44,7 @@ OBJECTS = \
|
|||
$(SYSTEM)(do_privctl.o) \
|
||||
$(SYSTEM)(do_segctl.o) \
|
||||
$(SYSTEM)(do_safecopy.o) \
|
||||
$(SYSTEM)(do_safemap.o) \
|
||||
$(SYSTEM)(do_sysctl.o) \
|
||||
$(SYSTEM)(do_getksig.o) \
|
||||
$(SYSTEM)(do_endksig.o) \
|
||||
|
@ -155,6 +156,9 @@ $(SYSTEM)(do_privctl.o): do_privctl.c
|
|||
$(SYSTEM)(do_safecopy.o): do_safecopy.c
|
||||
$(CC) do_safecopy.c
|
||||
|
||||
$(SYSTEM)(do_safemap.o): do_safemap.c
|
||||
$(CC) do_safemap.c
|
||||
|
||||
$(SYSTEM)(do_sysctl.o): do_sysctl.c
|
||||
$(CC) do_sysctl.c
|
||||
|
||||
|
|
|
@ -49,12 +49,6 @@ register message *m_ptr; /* pointer to request message */
|
|||
return EINVAL;
|
||||
}
|
||||
|
||||
/* memory becomes readonly */
|
||||
if (priv(rpp)->s_asynsize > 0) {
|
||||
printf("kernel: process with waiting asynsend table can't fork\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
map_ptr= (struct mem_map *) m_ptr->PR_MEM_PTR;
|
||||
|
||||
/* Copy parent 'proc' struct to child. And reinitialize some fields. */
|
||||
|
|
|
@ -101,6 +101,8 @@ message *m_ptr; /* pointer to request message */
|
|||
priv(rp)->s_notify_pending.chunk[i] = 0; /* - notifications */
|
||||
priv(rp)->s_int_pending = 0; /* - interrupts */
|
||||
sigemptyset(&priv(rp)->s_sig_pending); /* - signals */
|
||||
priv(rp)->s_asyntab= -1; /* - asynsends */
|
||||
priv(rp)->s_asynsize= 0;
|
||||
|
||||
/* Set defaults for privilege bitmaps. */
|
||||
priv(rp)->s_flags= DEF_SYS_F; /* privilege flags */
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
|
||||
#define MEM_TOP 0xFFFFFFFFUL
|
||||
|
||||
#define USE_COW_SAFECOPY 0
|
||||
|
||||
FORWARD _PROTOTYPE(int safecopy, (endpoint_t, endpoint_t, cp_grant_id_t, int, int, size_t, vir_bytes, vir_bytes, int));
|
||||
|
||||
#define HASGRANTTABLE(gr) \
|
||||
|
@ -229,9 +231,10 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE
|
|||
{
|
||||
static struct vir_addr v_src, v_dst;
|
||||
static vir_bytes v_offset;
|
||||
int r;
|
||||
endpoint_t new_granter, *src, *dst;
|
||||
struct proc *granter_p;
|
||||
vir_bytes size;
|
||||
int r;
|
||||
|
||||
/* See if there is a reasonable grant table. */
|
||||
if(!(granter_p = endpoint_lookup(granter))) return EINVAL;
|
||||
|
@ -279,8 +282,48 @@ int access; /* CPF_READ for a copy from granter to grantee, CPF_WRITE
|
|||
}
|
||||
|
||||
/* Do the regular copy. */
|
||||
return virtual_copy_vmcheck(&v_src, &v_dst, bytes);
|
||||
#if USE_COW_SAFECOPY
|
||||
if(v_offset % CLICK_SIZE != addr % CLICK_SIZE || bytes < CLICK_SIZE) {
|
||||
/* Give up on COW immediately when offsets are not aligned
|
||||
* or we are copying less than a page.
|
||||
*/
|
||||
return virtual_copy_vmcheck(&v_src, &v_dst, bytes);
|
||||
}
|
||||
|
||||
if((size = v_offset % CLICK_SIZE) != 0) {
|
||||
/* Normal copy for everything before the first page boundary. */
|
||||
size = CLICK_SIZE - size;
|
||||
r = virtual_copy_vmcheck(&v_src, &v_dst, size);
|
||||
if(r != OK)
|
||||
return r;
|
||||
v_src.offset += size;
|
||||
v_dst.offset += size;
|
||||
bytes -= size;
|
||||
}
|
||||
if((size = bytes / CLICK_SIZE) != 0) {
|
||||
/* Use COW optimization when copying entire pages. */
|
||||
size *= CLICK_SIZE;
|
||||
r = map_invoke_vm(VMPTYPE_COWMAP,
|
||||
v_dst.proc_nr_e, v_dst.segment, v_dst.offset,
|
||||
v_src.proc_nr_e, v_src.segment, v_src.offset,
|
||||
size, 0);
|
||||
if(r != OK)
|
||||
return r;
|
||||
v_src.offset += size;
|
||||
v_dst.offset += size;
|
||||
bytes -= size;
|
||||
}
|
||||
if(bytes != 0) {
|
||||
/* Normal copy for everything after the last page boundary. */
|
||||
r = virtual_copy_vmcheck(&v_src, &v_dst, bytes);
|
||||
if(r != OK)
|
||||
return r;
|
||||
}
|
||||
|
||||
return OK;
|
||||
#else
|
||||
return virtual_copy_vmcheck(&v_src, &v_dst, bytes);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
285
kernel/system/do_safemap.c
Normal file
285
kernel/system/do_safemap.c
Normal file
|
@ -0,0 +1,285 @@
|
|||
/* The kernel call implemented in this file:
|
||||
* m_type: SYS_SAFEMAP or SYS_SAFEREVMAP or SYS_SAFEUNMAP
|
||||
*
|
||||
* The parameters for this kernel call are:
|
||||
* SMAP_EP endpoint of the grantor
|
||||
* SMAP_GID grant id
|
||||
* SMAP_OFFSET offset of the grant space
|
||||
* SMAP_SEG segment
|
||||
* SMAP_ADDRESS address
|
||||
* SMAP_BYTES bytes to be copied
|
||||
* SMAP_FLAG access, writable map or not?
|
||||
*/
|
||||
|
||||
#include <minix/type.h>
|
||||
#include <minix/safecopies.h>
|
||||
|
||||
#include "../system.h"
|
||||
#include "../vm.h"
|
||||
|
||||
|
||||
struct map_info_s {
|
||||
int flag;
|
||||
|
||||
/* Grantor. */
|
||||
endpoint_t grantor;
|
||||
int gid;
|
||||
vir_bytes offset;
|
||||
vir_bytes address_Dseg; /* seg always is D */
|
||||
|
||||
/* Grantee. */
|
||||
endpoint_t grantee;
|
||||
int seg;
|
||||
vir_bytes address;
|
||||
|
||||
/* Length. */
|
||||
vir_bytes bytes;
|
||||
};
|
||||
|
||||
#define MAX_MAP_INFO 20
|
||||
static struct map_info_s map_info[MAX_MAP_INFO];
|
||||
|
||||
/*===========================================================================*
|
||||
* add_info *
|
||||
*===========================================================================*/
|
||||
static int add_info(endpoint_t grantor, endpoint_t grantee, int gid,
|
||||
vir_bytes offset, vir_bytes address_Dseg,
|
||||
int seg, vir_bytes address, vir_bytes bytes)
|
||||
{
|
||||
int i;
|
||||
|
||||
for(i = 0; i < MAX_MAP_INFO; i++) {
|
||||
if(map_info[i].flag == 0)
|
||||
break;
|
||||
}
|
||||
if(i == MAX_MAP_INFO)
|
||||
return EBUSY;
|
||||
|
||||
map_info[i].flag = 1;
|
||||
map_info[i].grantor = grantor;
|
||||
map_info[i].grantee = grantee;
|
||||
map_info[i].gid = gid;
|
||||
map_info[i].address_Dseg = address_Dseg;
|
||||
map_info[i].offset = offset;
|
||||
map_info[i].seg = seg;
|
||||
map_info[i].address = address;
|
||||
map_info[i].bytes = bytes;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_revoke_info *
|
||||
*===========================================================================*/
|
||||
static struct map_info_s *get_revoke_info(endpoint_t grantor, int flag, int arg)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < MAX_MAP_INFO; i++) {
|
||||
if(map_info[i].flag == 1
|
||||
&& map_info[i].grantor == grantor
|
||||
&& (flag ? (map_info[i].gid == arg)
|
||||
: (map_info[i].address_Dseg == arg)))
|
||||
return &map_info[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_unmap_info *
|
||||
*===========================================================================*/
|
||||
static struct map_info_s *get_unmap_info(endpoint_t grantee, int seg,
|
||||
vir_bytes address)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < MAX_MAP_INFO; i++) {
|
||||
if(map_info[i].flag == 1
|
||||
&& map_info[i].grantee == grantee
|
||||
&& map_info[i].seg == seg
|
||||
&& map_info[i].address == address)
|
||||
return &map_info[i];
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* clear_info *
|
||||
*===========================================================================*/
|
||||
static int clear_info(struct map_info_s *p)
|
||||
{
|
||||
p->flag = 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* map_invoke_vm *
|
||||
*===========================================================================*/
|
||||
PUBLIC int map_invoke_vm(int req_type, /* VMPTYPE_... COWMAP, SMAP, SUNMAP */
|
||||
endpoint_t end_d, int seg_d, vir_bytes off_d,
|
||||
endpoint_t end_s, int seg_s, vir_bytes off_s,
|
||||
size_t size, int flag)
|
||||
{
|
||||
struct proc *caller, *src, *dst;
|
||||
vir_bytes lin_src, lin_dst;
|
||||
|
||||
src = endpoint_lookup(end_s);
|
||||
dst = endpoint_lookup(end_d);
|
||||
caller = endpoint_lookup(who_e);
|
||||
|
||||
lin_src = umap_local(src, seg_s, off_s, size);
|
||||
lin_dst = umap_local(dst, seg_d, off_d, size);
|
||||
if(lin_src == 0 || lin_dst == 0) {
|
||||
kprintf("map_invoke_vm: error in umap_local.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
/* Make sure the linear addresses are both page aligned. */
|
||||
if(lin_src % CLICK_SIZE != 0
|
||||
|| lin_dst % CLICK_SIZE != 0) {
|
||||
kprintf("map_invoke_vm: linear addresses not page aligned.\n");
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
vmassert(!RTS_ISSET(caller, RTS_VMREQUEST));
|
||||
vmassert(!RTS_ISSET(caller, RTS_VMREQTARGET));
|
||||
vmassert(!RTS_ISSET(dst, RTS_VMREQUEST));
|
||||
vmassert(!RTS_ISSET(dst, RTS_VMREQTARGET));
|
||||
RTS_LOCK_SET(caller, RTS_VMREQUEST);
|
||||
RTS_LOCK_SET(dst, RTS_VMREQTARGET);
|
||||
|
||||
/* Map to the destination. */
|
||||
caller->p_vmrequest.req_type = req_type;
|
||||
caller->p_vmrequest.target = end_d; /* destination proc */
|
||||
caller->p_vmrequest.params.map.vir_d = lin_dst; /* destination addr */
|
||||
caller->p_vmrequest.params.map.ep_s = end_s; /* source process */
|
||||
caller->p_vmrequest.params.map.vir_s = lin_src; /* source address */
|
||||
caller->p_vmrequest.params.map.length = size;
|
||||
caller->p_vmrequest.params.map.writeflag = flag;
|
||||
|
||||
caller->p_vmrequest.type = VMSTYPE_MAP;
|
||||
|
||||
/* Connect caller on vmrequest wait queue. */
|
||||
if(!(caller->p_vmrequest.nextrequestor = vmrequest))
|
||||
lock_notify(SYSTEM, VM_PROC_NR);
|
||||
vmrequest = caller;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_safemap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_safemap(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
endpoint_t grantor = m_ptr->SMAP_EP;
|
||||
cp_grant_id_t gid = m_ptr->SMAP_GID;
|
||||
vir_bytes offset = m_ptr->SMAP_OFFSET;
|
||||
int seg = (int)m_ptr->SMAP_SEG;
|
||||
vir_bytes address = m_ptr->SMAP_ADDRESS;
|
||||
vir_bytes bytes = m_ptr->SMAP_BYTES;
|
||||
int flag = m_ptr->SMAP_FLAG;
|
||||
|
||||
vir_bytes offset_result;
|
||||
endpoint_t new_grantor;
|
||||
int r;
|
||||
int access = CPF_MAP | CPF_READ;
|
||||
|
||||
/* Check the grant. We currently support safemap with both direct and
|
||||
* indirect grants, as verify_grant() stores the original grantor
|
||||
* transparently in new_grantor below. However, we maintain the original
|
||||
* semantics associated to indirect grants only here at safemap time.
|
||||
* After the mapping has been set up, if a process part of the chain
|
||||
* of trust crashes or exits without revoking the mapping, the mapping
|
||||
* can no longer be manually or automatically revoked for any of the
|
||||
* processes lower in the chain. This solution reduces complexity but
|
||||
* could be improved if we make the assumption that only one process in
|
||||
* the chain of trust can effectively map the original memory region.
|
||||
*/
|
||||
if(flag != 0)
|
||||
access |= CPF_WRITE;
|
||||
r = verify_grant(grantor, who_e, gid, bytes, access,
|
||||
offset, &offset_result, &new_grantor);
|
||||
if(r != OK) {
|
||||
kprintf("verify_grant for gid %d from %d to %d failed: %d\n",
|
||||
gid, grantor, who_e, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Add map info. */
|
||||
r = add_info(new_grantor, who_e, gid, offset, offset_result, seg,
|
||||
address, bytes);
|
||||
if(r != OK)
|
||||
return r;
|
||||
|
||||
/* Invoke VM. */
|
||||
return map_invoke_vm(VMPTYPE_SMAP,
|
||||
who_e, seg, address, new_grantor, D, offset_result, bytes,flag);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* safeunmap *
|
||||
*===========================================================================*/
|
||||
PRIVATE int safeunmap(struct map_info_s *p)
|
||||
{
|
||||
vir_bytes offset_result;
|
||||
endpoint_t new_grantor;
|
||||
int r;
|
||||
|
||||
r = verify_grant(p->grantor, p->grantee, p->gid, p->bytes, CPF_MAP,
|
||||
p->offset, &offset_result, &new_grantor);
|
||||
if(r != OK) {
|
||||
kprintf("safeunmap: error in verify_grant.\n");
|
||||
return r;
|
||||
}
|
||||
|
||||
r = map_invoke_vm(VMPTYPE_SUNMAP,
|
||||
p->grantee, p->seg, p->address,
|
||||
new_grantor, D, offset_result,
|
||||
p->bytes, 0);
|
||||
clear_info(p);
|
||||
if(r != OK) {
|
||||
kprintf("safeunmap: error in map_invoke_vm.\n");
|
||||
return r;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_saferevmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_saferevmap(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
struct map_info_s *p;
|
||||
int flag = m_ptr->SMAP_FLAG;
|
||||
int arg = m_ptr->SMAP_GID; /* gid or address_Dseg */
|
||||
int r;
|
||||
|
||||
while((p = get_revoke_info(who_e, flag, arg)) != NULL) {
|
||||
if((r = safeunmap(p)) != OK)
|
||||
return r;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_safeunmap *
|
||||
*===========================================================================*/
|
||||
PUBLIC int do_safeunmap(m_ptr)
|
||||
register message *m_ptr;
|
||||
{
|
||||
vir_bytes address = m_ptr->SMAP_ADDRESS;
|
||||
int seg = (int)m_ptr->SMAP_SEG;
|
||||
struct map_info_s *p;
|
||||
int r;
|
||||
|
||||
while((p = get_unmap_info(who_e, seg, address)) != NULL) {
|
||||
if((r = safeunmap(p)) != OK)
|
||||
return r;
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -65,21 +65,51 @@ register message *m_ptr; /* pointer to request message */
|
|||
#endif
|
||||
|
||||
/* Reply with request fields. */
|
||||
m_ptr->SVMCTL_MRG_ADDR = (char *) rp->p_vmrequest.start;
|
||||
m_ptr->SVMCTL_MRG_LEN = rp->p_vmrequest.length;
|
||||
m_ptr->SVMCTL_MRG_WRITE = rp->p_vmrequest.writeflag;
|
||||
m_ptr->SVMCTL_MRG_EP = rp->p_vmrequest.who;
|
||||
m_ptr->SVMCTL_MRG_REQUESTOR = (void *) rp->p_endpoint;
|
||||
switch(rp->p_vmrequest.req_type) {
|
||||
case VMPTYPE_CHECK:
|
||||
m_ptr->SVMCTL_MRG_TARGET =
|
||||
rp->p_vmrequest.target;
|
||||
m_ptr->SVMCTL_MRG_ADDR =
|
||||
rp->p_vmrequest.params.check.start;
|
||||
m_ptr->SVMCTL_MRG_LENGTH =
|
||||
rp->p_vmrequest.params.check.length;
|
||||
m_ptr->SVMCTL_MRG_FLAG =
|
||||
rp->p_vmrequest.params.check.writeflag;
|
||||
m_ptr->SVMCTL_MRG_REQUESTOR =
|
||||
(void *) rp->p_endpoint;
|
||||
break;
|
||||
case VMPTYPE_COWMAP:
|
||||
case VMPTYPE_SMAP:
|
||||
case VMPTYPE_SUNMAP:
|
||||
m_ptr->SVMCTL_MRG_TARGET =
|
||||
rp->p_vmrequest.target;
|
||||
m_ptr->SVMCTL_MRG_ADDR =
|
||||
rp->p_vmrequest.params.map.vir_d;
|
||||
m_ptr->SVMCTL_MRG_EP2 =
|
||||
rp->p_vmrequest.params.map.ep_s;
|
||||
m_ptr->SVMCTL_MRG_ADDR2 =
|
||||
rp->p_vmrequest.params.map.vir_s;
|
||||
m_ptr->SVMCTL_MRG_LENGTH =
|
||||
rp->p_vmrequest.params.map.length;
|
||||
m_ptr->SVMCTL_MRG_FLAG =
|
||||
rp->p_vmrequest.params.map.writeflag;
|
||||
m_ptr->SVMCTL_MRG_REQUESTOR =
|
||||
(void *) rp->p_endpoint;
|
||||
break;
|
||||
default:
|
||||
minix_panic("VMREQUEST wrong type", NO_NUM);
|
||||
}
|
||||
|
||||
rp->p_vmrequest.vmresult = VMSUSPEND;
|
||||
|
||||
/* Remove from request chain. */
|
||||
vmrequest = vmrequest->p_vmrequest.nextrequestor;
|
||||
|
||||
return OK;
|
||||
return rp->p_vmrequest.req_type;
|
||||
case VMCTL_MEMREQ_REPLY:
|
||||
vmassert(RTS_ISSET(p, RTS_VMREQUEST));
|
||||
vmassert(p->p_vmrequest.vmresult == VMSUSPEND);
|
||||
okendpt(p->p_vmrequest.who, &proc_nr);
|
||||
okendpt(p->p_vmrequest.target, &proc_nr);
|
||||
target = proc_addr(proc_nr);
|
||||
p->p_vmrequest.vmresult = m_ptr->SVMCTL_VALUE;
|
||||
vmassert(p->p_vmrequest.vmresult != VMSUSPEND);
|
||||
|
@ -94,21 +124,28 @@ register message *m_ptr; /* pointer to request message */
|
|||
p->p_vmrequest.start + p->p_vmrequest.length,
|
||||
p->p_vmrequest.writeflag, p->p_vmrequest.stacktrace);
|
||||
printf("type %d\n", p->p_vmrequest.type);
|
||||
#endif
|
||||
|
||||
vmassert(RTS_ISSET(target, RTS_VMREQTARGET));
|
||||
RTS_LOCK_UNSET(target, RTS_VMREQTARGET);
|
||||
#endif
|
||||
|
||||
if(p->p_vmrequest.type == VMSTYPE_KERNELCALL) {
|
||||
switch(p->p_vmrequest.type) {
|
||||
case VMSTYPE_KERNELCALL:
|
||||
/* Put on restart chain. */
|
||||
p->p_vmrequest.nextrestart = vmrestart;
|
||||
vmrestart = p;
|
||||
} else if(p->p_vmrequest.type == VMSTYPE_DELIVERMSG) {
|
||||
break;
|
||||
case VMSTYPE_DELIVERMSG:
|
||||
vmassert(p->p_misc_flags & MF_DELIVERMSG);
|
||||
vmassert(p == target);
|
||||
vmassert(RTS_ISSET(p, RTS_VMREQUEST));
|
||||
RTS_LOCK_UNSET(p, RTS_VMREQUEST);
|
||||
} else {
|
||||
break;
|
||||
case VMSTYPE_MAP:
|
||||
vmassert(RTS_ISSET(p, RTS_VMREQUEST));
|
||||
RTS_LOCK_UNSET(p, RTS_VMREQUEST);
|
||||
break;
|
||||
default:
|
||||
#if DEBUG_VMASSERT
|
||||
printf("suspended with stack: %s\n",
|
||||
p->p_vmrequest.stacktrace);
|
||||
|
|
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;
|
||||
}
|
||||
|
|
@ -7,12 +7,14 @@
|
|||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <regex.h>
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/ds.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/keymap.h>
|
||||
|
@ -27,5 +29,4 @@
|
|||
|
||||
#include "proto.h"
|
||||
#include "glo.h"
|
||||
#include "store.h"
|
||||
|
||||
|
|
|
@ -71,12 +71,21 @@ PUBLIC int main(int argc, char **argv)
|
|||
case DS_RETRIEVE:
|
||||
result = do_retrieve(&m);
|
||||
break;
|
||||
case DS_RETRIEVE_LABEL:
|
||||
result = do_retrieve_label(&m);
|
||||
break;
|
||||
case DS_DELETE:
|
||||
result = do_delete(&m);
|
||||
break;
|
||||
case DS_SUBSCRIBE:
|
||||
result = do_subscribe(&m);
|
||||
break;
|
||||
case DS_CHECK:
|
||||
result = do_check(&m);
|
||||
break;
|
||||
case DS_SNAPSHOT:
|
||||
result = do_snapshot(&m);
|
||||
break;
|
||||
case GETSYSINFO:
|
||||
result = do_getsysinfo(&m);
|
||||
break;
|
||||
|
|
|
@ -6,8 +6,11 @@ _PROTOTYPE(int main, (int argc, char **argv));
|
|||
/* store.c */
|
||||
_PROTOTYPE(int do_publish, (message *m_ptr));
|
||||
_PROTOTYPE(int do_retrieve, (message *m_ptr));
|
||||
_PROTOTYPE(int do_retrieve_label, (message *m_ptr));
|
||||
_PROTOTYPE(int do_subscribe, (message *m_ptr));
|
||||
_PROTOTYPE(int do_check, (message *m_ptr));
|
||||
_PROTOTYPE(int do_delete, (message *m_ptr));
|
||||
_PROTOTYPE(int do_snapshot, (message *m_ptr));
|
||||
_PROTOTYPE(int do_getsysinfo, (message *m_ptr));
|
||||
_PROTOTYPE(int sef_cb_init_fresh, (int type, sef_init_info_t *info));
|
||||
_PROTOTYPE(int map_service, (struct rprocpub *rpub));
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,33 +1,46 @@
|
|||
/* Type definitions for the Data Store Server. */
|
||||
#ifndef _DS_STORE_H_
|
||||
#define _DS_STORE_H_
|
||||
|
||||
/* Type definitions for the Data Store Server. */
|
||||
#include <sys/types.h>
|
||||
#include <minix/sys_config.h>
|
||||
#include <minix/ds.h>
|
||||
#include <minix/bitmap.h>
|
||||
#include <regex.h>
|
||||
|
||||
/* Constants for the Data Store Server. */
|
||||
#define NR_DS_KEYS 64 /* reserve space for so many items */
|
||||
#define NR_DS_SUBS (4*_NR_SYS_PROCS) /* .. and so many subscriptions */
|
||||
|
||||
/* Types. */
|
||||
#define NR_DS_KEYS 64 /* number of entries */
|
||||
#define NR_DS_SUBS (4*_NR_SYS_PROCS) /* number of subscriptions */
|
||||
#define NR_DS_SNAPSHOT 5 /* number of snapshots */
|
||||
|
||||
/* Base 'class' for the following 3 structs. */
|
||||
struct data_store {
|
||||
int ds_flags; /* flags for this store, includes type info */
|
||||
char ds_key[DS_MAX_KEYLEN]; /* key to lookup information */
|
||||
union {
|
||||
u32_t ds_val_u32; /* u32 data (DS_TYPE_U32) */
|
||||
char ds_val_str[DS_MAX_VALLEN]; /* string data (DS_TYPE_STR) */
|
||||
} ds_val;
|
||||
int flags;
|
||||
char key[DS_MAX_KEYLEN]; /* key to lookup information */
|
||||
char owner[DS_MAX_KEYLEN];
|
||||
|
||||
/* out of date subscribers. */
|
||||
bitchunk_t ds_old_subs[BITMAP_CHUNKS(NR_DS_SUBS)];
|
||||
union {
|
||||
unsigned u32;
|
||||
char string[DS_MAX_STRLEN];
|
||||
struct {
|
||||
void *data;
|
||||
size_t length;
|
||||
size_t reallen;
|
||||
} mem;
|
||||
struct dsi_map {
|
||||
void *data;
|
||||
size_t length;
|
||||
void *realpointer;
|
||||
void *snapshots[NR_DS_SNAPSHOT];
|
||||
int sindex;
|
||||
} map;
|
||||
} u;
|
||||
};
|
||||
|
||||
struct subscription {
|
||||
int sub_flags; /* flags for this subscription */
|
||||
regex_t sub_regex; /* regular expression agains keys */
|
||||
endpoint_t sub_owner; /* who is subscribed */
|
||||
int flags;
|
||||
char owner[DS_MAX_KEYLEN];
|
||||
regex_t regex;
|
||||
bitchunk_t old_subs[BITMAP_CHUNKS(NR_DS_KEYS)];
|
||||
};
|
||||
|
||||
|
||||
#endif /* _DS_STORE_H_ */
|
||||
|
|
|
@ -257,9 +257,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
|
|||
init_rand256(randbits);
|
||||
|
||||
/* Our new identity as a server. */
|
||||
r= ds_retrieve_u32("inet", &tasknr);
|
||||
r= ds_retrieve_label_num("inet", &tasknr);
|
||||
if (r != OK)
|
||||
ip_panic(("inet: ds_retrieve_u32 failed for 'inet': %d", r));
|
||||
ip_panic(("inet: ds_retrieve_label_num failed for 'inet': %d", r));
|
||||
this_proc= tasknr;
|
||||
|
||||
/* Register the device group. */
|
||||
|
|
|
@ -99,10 +99,10 @@ PUBLIC void osdep_eth_init()
|
|||
}
|
||||
eth_port->etp_osdep.etp_rd_vec_grant= gid;
|
||||
|
||||
r= ds_retrieve_u32(ecp->ec_task, &tasknr);
|
||||
r= ds_retrieve_label_num(ecp->ec_task, &tasknr);
|
||||
if (r != OK && r != ESRCH)
|
||||
{
|
||||
printf("inet: ds_retrieve_u32 failed for '%s': %d\n",
|
||||
printf("inet: ds_retrieve_label_num failed for '%s': %d\n",
|
||||
ecp->ec_task, r);
|
||||
}
|
||||
if (r != OK)
|
||||
|
|
|
@ -1,66 +1,54 @@
|
|||
/* This file contains procedures to dump DS data structures.
|
||||
*
|
||||
* The entry points into this file are
|
||||
* data_store_dmp: display DS data store contents
|
||||
*
|
||||
* Created:
|
||||
* Oct 18, 2005: by Jorrit N. Herder
|
||||
*/
|
||||
|
||||
#include "inc.h"
|
||||
#include "../ds/store.h"
|
||||
|
||||
PUBLIC struct data_store store[NR_DS_KEYS];
|
||||
PRIVATE struct data_store ds_store[NR_DS_KEYS];
|
||||
|
||||
FORWARD _PROTOTYPE( char *s_flags_str, (int flags) );
|
||||
|
||||
/*===========================================================================*
|
||||
* data_store_dmp *
|
||||
*===========================================================================*/
|
||||
PUBLIC void data_store_dmp()
|
||||
{
|
||||
struct data_store *dsp;
|
||||
int i,j, n=0, s;
|
||||
static int prev_i=0;
|
||||
struct data_store *p;
|
||||
static int prev_i = 0;
|
||||
int r, i, n = 0;
|
||||
|
||||
|
||||
printf("Data Store (DS) contents dump\n");
|
||||
|
||||
if((s=getsysinfo(DS_PROC_NR, SI_DATA_STORE, store)) != OK) {
|
||||
printf("Couldn't talk to DS: %d.\n", s);
|
||||
if((r=getsysinfo(DS_PROC_NR, SI_DATA_STORE, ds_store)) != OK) {
|
||||
printf("Couldn't talk to DS: %d.\n", r);
|
||||
return;
|
||||
}
|
||||
|
||||
printf("slot key type value\n");
|
||||
printf("Data store contents:\n");
|
||||
printf("-slot- ------key------ -----owner----- ---type--- ----value---\n");
|
||||
for(i = prev_i; i < NR_DS_KEYS; i++) {
|
||||
p = &ds_store[i];
|
||||
if(!(p->flags & DSF_IN_USE))
|
||||
continue;
|
||||
|
||||
for (i=prev_i; i<NR_DS_KEYS; i++) {
|
||||
dsp = &store[i];
|
||||
if (! dsp->ds_flags & DS_IN_USE) continue;
|
||||
if (++n > 22) break;
|
||||
printf("%3d %-20s ",
|
||||
i, dsp->ds_key);
|
||||
if(dsp->ds_flags & DS_TYPE_U32) {
|
||||
printf("u32 %lu\n", dsp->ds_val.ds_val_u32);
|
||||
} else if(dsp->ds_flags & DS_TYPE_STR) {
|
||||
printf("str \"%s\"\n", dsp->ds_val.ds_val_str);
|
||||
} else {
|
||||
printf("Bogus type\n");
|
||||
printf("%6d %-15s %-15s ", i, p->key, p->owner);
|
||||
switch(p->flags & DSF_MASK_TYPE) {
|
||||
case DSF_TYPE_U32:
|
||||
printf("%-10s %12u\n", "U32", p->u.u32);
|
||||
break;
|
||||
case DSF_TYPE_STR:
|
||||
printf("%-10s %12s\n", "STR", p->u.string);
|
||||
break;
|
||||
case DSF_TYPE_MEM:
|
||||
printf("%-10s %12u\n", "MEM", p->u.mem.length);
|
||||
break;
|
||||
case DSF_TYPE_MAP:
|
||||
printf("%-10s %9u/%3u\n", "MAP", p->u.map.length,
|
||||
p->u.map.sindex);
|
||||
break;
|
||||
case DSF_TYPE_LABEL:
|
||||
printf("%-10s %12u\n", "LABEL", p->u.u32);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(n++ == 21)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i >= NR_DS_KEYS) i = 0;
|
||||
else printf("--more--\r");
|
||||
prev_i = i;
|
||||
}
|
||||
|
||||
|
||||
PRIVATE char *s_flags_str(int flags)
|
||||
{
|
||||
static char str[5];
|
||||
str[0] = (flags & DS_IN_USE) ? 'U' : '-';
|
||||
str[1] = (flags & DS_PUBLIC) ? 'P' : '-';
|
||||
str[2] = '-';
|
||||
str[3] = '\0';
|
||||
|
||||
return(str);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,11 +49,12 @@ PUBLIC int fs_readsuper()
|
|||
return(EINVAL);
|
||||
}
|
||||
|
||||
r = ds_retrieve_u32(fs_dev_label, &tasknr);
|
||||
if (r != OK) {
|
||||
printf("%s:%d fs_readsuper: ds_retrieve_u32 failed for '%s': %d\n",
|
||||
__FILE__, __LINE__, fs_dev_label, r);
|
||||
return(EINVAL);
|
||||
r= ds_retrieve_label_num(fs_dev_label, &tasknr);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("mfs:fs_readsuper: ds_retrieve_label_num failed for '%s': %d\n",
|
||||
fs_dev_label, r);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
driver_e = tasknr;
|
||||
|
|
|
@ -45,8 +45,8 @@ PRIVATE int check_mem_available(char *new_brksize)
|
|||
mem_sp = &proc.p_memmap[S]; /* pointer to stack segment map */
|
||||
|
||||
/* Compute how many clicks the data segment is to become. */
|
||||
data_clicks = (vir_clicks) ( ((long) new_brksize + CLICK_SIZE - 1) >>
|
||||
CLICK_SHIFT) - mem_dp->mem_vir;
|
||||
data_clicks = (vir_clicks) (CLICK_CEIL(new_brksize) >> CLICK_SHIFT)
|
||||
- mem_dp->mem_vir;
|
||||
|
||||
/* See if stack size has gone negative (i.e., sp too close to 0xFFFF...) */
|
||||
base_of_stack = (long) mem_sp->mem_vir + (long) mem_sp->mem_len;
|
||||
|
@ -62,7 +62,7 @@ PRIVATE int check_mem_available(char *new_brksize)
|
|||
|
||||
/* Add a safety margin for future stack growth. Impossible to do right. */
|
||||
#define SAFETY_BYTES (384 * sizeof(char *))
|
||||
#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
|
||||
#define SAFETY_CLICKS ((vir_clicks) (CLICK_CEIL(SAFETY_BYTES) >> CLICK_SHIFT))
|
||||
gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
|
||||
if (sp_lower < gap_base)
|
||||
{
|
||||
|
|
|
@ -112,7 +112,7 @@ PRIVATE void print_usage(char *app_name, char *problem)
|
|||
fprintf(stderr, "Warning, %s\n", problem);
|
||||
fprintf(stderr, "Usage:\n");
|
||||
fprintf(stderr,
|
||||
" %s [-c] (up|run) <binary> [%s <args>] [%s <special>] [%s <ticks>]\n",
|
||||
" %s [-c -r] (up|run) <binary> [%s <args>] [%s <special>] [%s <ticks>]\n",
|
||||
app_name, ARG_ARGS, ARG_DEV, ARG_PERIOD);
|
||||
fprintf(stderr, " %s down label\n", app_name);
|
||||
fprintf(stderr, " %s refresh label\n", app_name);
|
||||
|
@ -729,6 +729,9 @@ struct
|
|||
{ "GETINFO", SYS_GETINFO },
|
||||
{ "SAFECOPYFROM", SYS_SAFECOPYFROM },
|
||||
{ "SAFECOPYTO", SYS_SAFECOPYTO },
|
||||
{ "SAFEMAP", SYS_SAFEMAP },
|
||||
{ "SAFEREVMAP", SYS_SAFEREVMAP },
|
||||
{ "SAFEUNMAP", SYS_SAFEUNMAP },
|
||||
{ "VSAFECOPY", SYS_VSAFECOPY },
|
||||
{ "SETGRANT", SYS_SETGRANT },
|
||||
{ "READBIOS", SYS_READBIOS },
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
*/
|
||||
#define FS_KC SYS_KILL, SYS_VIRCOPY, SYS_SAFECOPYFROM, SYS_SAFECOPYTO, \
|
||||
SYS_UMAP, SYS_GETINFO, SYS_EXIT, SYS_TIMES, SYS_SETALARM, \
|
||||
SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
|
||||
SYS_PRIVCTL, SYS_TRACE , SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL, \
|
||||
SYS_SAFEMAP, SYS_SAFEREVMAP, SYS_SAFEUNMAP
|
||||
#define DRV_KC FS_KC, SYS_SEGCTL, SYS_IRQCTL, SYS_INT86, SYS_DEVIO, \
|
||||
SYS_SDEVIO, SYS_VDEVIO, SYS_SETGRANT, SYS_PROFBUF, SYS_SYSCTL
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ struct rproc *rp; /* pointer to process slot */
|
|||
rpub = rp->r_pub;
|
||||
|
||||
/* Register its label with DS. */
|
||||
s= ds_publish_u32(rpub->label, rpub->endpoint);
|
||||
s= ds_publish_label(rpub->label, rpub->endpoint, DSF_OVERWRITE);
|
||||
if (s != OK) {
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ PUBLIC int do_mapdriver()
|
|||
|
||||
label[label_len]= '\0';
|
||||
|
||||
r= ds_retrieve_u32(label, &tasknr);
|
||||
r= ds_retrieve_label_num(label, &tasknr);
|
||||
if (r != OK)
|
||||
{
|
||||
printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
|
||||
|
|
|
@ -96,7 +96,7 @@ PUBLIC int do_mount()
|
|||
|
||||
mount_label[sizeof(mount_label)-1] = 0;
|
||||
|
||||
r = ds_retrieve_u32(mount_label, &fs_e);
|
||||
r = ds_retrieve_label_num(mount_label, &fs_e);
|
||||
if (r != OK) return(r);
|
||||
|
||||
if (isokendpt(fs_e, &proc_nr) != OK) return(EINVAL);
|
||||
|
|
|
@ -5,7 +5,7 @@ include /etc/make.conf
|
|||
|
||||
OBJ = main.o alloc.o utility.o exec.o exit.o fork.o break.o \
|
||||
signal.o vfs.o mmap.o slaballoc.o region.o pagefaults.o addravl.o \
|
||||
physravl.o rs.o queryexit.o
|
||||
physravl.o rs.o queryexit.o map_mem.o
|
||||
ARCHOBJ = $(ARCH)/vm.o $(ARCH)/pagetable.o $(ARCH)/arch_pagefaults.o $(ARCH)/util.o
|
||||
|
||||
CPPFLAGS=-I../../kernel/arch/$(ARCH)/include -I$(ARCH)
|
||||
|
|
|
@ -96,7 +96,7 @@ vir_bytes sp; /* new value of sp */
|
|||
|
||||
/* Add a safety margin for future stack growth. Impossible to do right. */
|
||||
#define SAFETY_BYTES (384 * sizeof(char *))
|
||||
#define SAFETY_CLICKS ((SAFETY_BYTES + CLICK_SIZE - 1) / CLICK_SIZE)
|
||||
#define SAFETY_CLICKS ((vir_clicks) (CLICK_CEIL(SAFETY_BYTES) >> CLICK_SHIFT))
|
||||
gap_base = mem_dp->mem_vir + data_clicks + SAFETY_CLICKS;
|
||||
if (sp_lower < gap_base)
|
||||
{
|
||||
|
@ -165,7 +165,7 @@ vir_bytes v;
|
|||
vir_clicks new_clicks;
|
||||
int r;
|
||||
|
||||
new_clicks = (vir_clicks) ( ((long) v + CLICK_SIZE - 1) >> CLICK_SHIFT);
|
||||
new_clicks = (vir_clicks) (CLICK_CEIL(v) >> CLICK_SHIFT);
|
||||
if (new_clicks < vmp->vm_arch.vm_seg[D].mem_vir) {
|
||||
printf("VM: real_brk failed because new_clicks too high: %d\n",
|
||||
new_clicks);
|
||||
|
|
|
@ -110,10 +110,10 @@ SANITYCHECK(SCL_DETAIL);
|
|||
}
|
||||
|
||||
/* Check to see if segment sizes are feasible. */
|
||||
tc = ((unsigned long) args.text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
dc = (args.data_bytes+args.bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
totc = (args.tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
sc = (args.args_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
tc = (vir_clicks) (CLICK_CEIL(args.text_bytes) >> CLICK_SHIFT);
|
||||
dc = (vir_clicks) (CLICK_CEIL(args.data_bytes+args.bss_bytes) >> CLICK_SHIFT);
|
||||
totc = (vir_clicks) (CLICK_CEIL(args.tot_bytes) >> CLICK_SHIFT);
|
||||
sc = (vir_clicks) (CLICK_CEIL(args.args_bytes) >> CLICK_SHIFT);
|
||||
if (dc >= totc) {
|
||||
printf("VM: newmem: no stack?\n");
|
||||
return(ENOEXEC); /* stack must be at least 1 click */
|
||||
|
@ -204,10 +204,10 @@ vir_bytes *stack_top; /* top of process stack */
|
|||
* and stack occupies an integral number of clicks, starting at click
|
||||
* boundary. The data and bss parts are run together with no space.
|
||||
*/
|
||||
text_clicks = ((unsigned long) text_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
data_clicks = (data_bytes + bss_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
stack_clicks = (stk_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
tot_clicks = (tot_bytes + CLICK_SIZE - 1) >> CLICK_SHIFT;
|
||||
text_clicks = (vir_clicks) (CLICK_CEIL(text_bytes) >> CLICK_SHIFT);
|
||||
data_clicks = (vir_clicks) (CLICK_CEIL(data_bytes + bss_bytes) >> CLICK_SHIFT);
|
||||
stack_clicks = (vir_clicks) (CLICK_CEIL(stk_bytes) >> CLICK_SHIFT);
|
||||
tot_clicks = (vir_clicks) (CLICK_CEIL(tot_bytes) >> CLICK_SHIFT);
|
||||
gap_clicks = tot_clicks - data_clicks - stack_clicks;
|
||||
if ( (int) gap_clicks < 0) {
|
||||
printf("VM: new_mem: no gap?\n");
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
#define _SYSTEM 1
|
||||
#define _POSIX_SOURCE 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
330
servers/vm/map_mem.c
Normal file
330
servers/vm/map_mem.c
Normal file
|
@ -0,0 +1,330 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#include <minix/com.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/config.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <minix/syslib.h>
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
|
||||
#include "vm.h"
|
||||
#include "proto.h"
|
||||
#include "util.h"
|
||||
#include "glo.h"
|
||||
#include "region.h"
|
||||
#include "sanitycheck.h"
|
||||
|
||||
/*===========================================================================*
|
||||
* split_phys *
|
||||
*===========================================================================*/
|
||||
PRIVATE int split_phys(struct phys_region *pr, vir_bytes point)
|
||||
{
|
||||
struct phys_region *newpr, *q, *prev;
|
||||
struct phys_block *newpb;
|
||||
struct phys_block *pb = pr->ph;
|
||||
/* Split the phys region into 2 parts by @point. */
|
||||
|
||||
if(pr->offset >= point || pr->offset + pb->length <= point)
|
||||
return OK;
|
||||
if(!SLABALLOC(newpb))
|
||||
return ENOMEM;
|
||||
|
||||
/* Split phys block. */
|
||||
*newpb = *pb;
|
||||
pb->length = point - pr->offset;
|
||||
newpb->length -= pb->length;
|
||||
newpb->phys += pb->length;
|
||||
|
||||
/* Split phys regions in a list. */
|
||||
for(q = pb->firstregion; q; q = q->next_ph_list) {
|
||||
if(!SLABALLOC(newpr))
|
||||
return ENOMEM;
|
||||
|
||||
*newpr = *q;
|
||||
newpr->ph = newpb;
|
||||
newpr->offset += pb->length;
|
||||
|
||||
/* Link to the vir region's phys region list. */
|
||||
physr_insert(newpr->parent->phys, newpr);
|
||||
|
||||
/* Link to the next_ph_list. */
|
||||
if(q == pb->firstregion) {
|
||||
newpb->firstregion = newpr;
|
||||
prev = newpr;
|
||||
} else {
|
||||
prev->next_ph_list = newpr;
|
||||
prev = newpr;
|
||||
}
|
||||
}
|
||||
prev->next_ph_list = NULL;
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* rm_phys_regions *
|
||||
*===========================================================================*/
|
||||
PRIVATE void rm_phys_regions(struct vir_region *region,
|
||||
vir_bytes begin, vir_bytes length)
|
||||
{
|
||||
/* Remove all phys regions between @begin and @begin+length.
|
||||
*
|
||||
* Don't update the page table, because we will update it at map_memory()
|
||||
* later.
|
||||
*/
|
||||
struct phys_region *pr;
|
||||
physr_iter iter;
|
||||
|
||||
physr_start_iter(region->phys, &iter, begin, AVL_GREATER_EQUAL);
|
||||
while((pr = physr_get_iter(&iter)) && pr->offset < begin + length) {
|
||||
pb_unreferenced(region, pr);
|
||||
physr_remove(region->phys, pr->offset);
|
||||
physr_start_iter(region->phys, &iter, begin,
|
||||
AVL_GREATER_EQUAL);
|
||||
SLABFREE(pr);
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* clean_phys_regions *
|
||||
*===========================================================================*/
|
||||
PRIVATE void clean_phys_regions(struct vir_region *region,
|
||||
vir_bytes offset, vir_bytes length)
|
||||
{
|
||||
/* Consider @offset as the start address and @offset+length as the end address.
|
||||
* If there are phys regions crossing the start address or the end address,
|
||||
* split them into 2 parts.
|
||||
*
|
||||
* We assume that the phys regions are listed in order and don't overlap.
|
||||
*/
|
||||
struct phys_region *pr;
|
||||
physr_iter iter;
|
||||
|
||||
physr_start_iter_least(region->phys, &iter);
|
||||
while((pr = physr_get_iter(&iter))) {
|
||||
/* If this phys region crosses the start address, split it. */
|
||||
if(pr->offset < offset
|
||||
&& pr->offset + pr->ph->length > offset) {
|
||||
split_phys(pr, offset);
|
||||
physr_start_iter_least(region->phys, &iter);
|
||||
}
|
||||
/* If this phys region crosses the end address, split it. */
|
||||
else if(pr->offset < offset + length
|
||||
&& pr->offset + pr->ph->length > offset + length) {
|
||||
split_phys(pr, offset + length);
|
||||
physr_start_iter_least(region->phys, &iter);
|
||||
}
|
||||
else {
|
||||
physr_incr_iter(&iter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_map_memory *
|
||||
*===========================================================================*/
|
||||
PRIVATE int do_map_memory(struct vmproc *vms, struct vmproc *vmd,
|
||||
struct vir_region *vrs, struct vir_region *vrd,
|
||||
vir_bytes offset_s, vir_bytes offset_d,
|
||||
vir_bytes length, int flag)
|
||||
{
|
||||
struct phys_region *prs;
|
||||
struct phys_region *newphysr;
|
||||
struct phys_block *pb;
|
||||
physr_iter iter;
|
||||
u32_t pt_flag = PTF_PRESENT | PTF_USER;
|
||||
vir_bytes end;
|
||||
|
||||
/* Search for the first phys region in the source process. */
|
||||
physr_start_iter(vrs->phys, &iter, offset_s, AVL_EQUAL);
|
||||
prs = physr_get_iter(&iter);
|
||||
if(!prs)
|
||||
vm_panic("map_memory: no aligned phys region.", 0);
|
||||
|
||||
/* flag: 0 -> read-only
|
||||
* 1 -> writable
|
||||
* -1 -> share as COW, so read-only
|
||||
*/
|
||||
if(flag > 0)
|
||||
pt_flag |= PTF_WRITE;
|
||||
|
||||
/* Map phys blocks in the source process to the destination process. */
|
||||
end = offset_d + length;
|
||||
while((prs = physr_get_iter(&iter)) && offset_d < end) {
|
||||
/* If a SMAP share was requested but the phys block has already
|
||||
* been shared as COW, copy the block for the source phys region
|
||||
* first.
|
||||
*/
|
||||
pb = prs->ph;
|
||||
if(flag >= 0 && pb->refcount > 1
|
||||
&& pb->share_flag == PBSH_COW) {
|
||||
map_copy_ph_block(vms, vrs, prs);
|
||||
pb = prs->ph;
|
||||
}
|
||||
|
||||
/* Allocate a new phys region. */
|
||||
if(!SLABALLOC(newphysr))
|
||||
return ENOMEM;
|
||||
|
||||
/* Set and link the new phys region to the block. */
|
||||
newphysr->ph = pb;
|
||||
newphysr->offset = offset_d;
|
||||
newphysr->parent = vrd;
|
||||
newphysr->next_ph_list = pb->firstregion;
|
||||
pb->firstregion = newphysr;
|
||||
physr_insert(newphysr->parent->phys, newphysr);
|
||||
pb->refcount++;
|
||||
|
||||
/* If a COW share was requested but the phys block has already
|
||||
* been shared as SMAP, give up on COW and copy the block for
|
||||
* the destination phys region now.
|
||||
*/
|
||||
if(flag < 0 && pb->refcount > 1
|
||||
&& pb->share_flag == PBSH_SMAP) {
|
||||
map_copy_ph_block(vmd, vrd, newphysr);
|
||||
}
|
||||
else {
|
||||
/* See if this is a COW share or SMAP share. */
|
||||
if(flag < 0) { /* COW share */
|
||||
pb->share_flag = PBSH_COW;
|
||||
/* Update the page table for the src process. */
|
||||
pt_writemap(&vms->vm_pt, offset_s + vrs->vaddr,
|
||||
pb->phys, pb->length,
|
||||
pt_flag, WMF_OVERWRITE);
|
||||
}
|
||||
else { /* SMAP share */
|
||||
pb->share_flag = PBSH_SMAP;
|
||||
}
|
||||
/* Update the page table for the destination process. */
|
||||
pt_writemap(&vmd->vm_pt, offset_d + vrd->vaddr,
|
||||
pb->phys, pb->length, pt_flag, WMF_OVERWRITE);
|
||||
}
|
||||
|
||||
physr_incr_iter(&iter);
|
||||
offset_d += pb->length;
|
||||
offset_s += pb->length;
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* map_memory *
|
||||
*===========================================================================*/
|
||||
PUBLIC int map_memory(endpoint_t sour, endpoint_t dest,
|
||||
vir_bytes virt_s, vir_bytes virt_d, vir_bytes length, int flag)
|
||||
{
|
||||
/* This is the entry point. This function will be called by handle_memory() when
|
||||
* VM recieves a map-memory request.
|
||||
*/
|
||||
struct vmproc *vms, *vmd;
|
||||
struct vir_region *vrs, *vrd;
|
||||
struct phys_region *prs, *prd;
|
||||
physr_iter iters, iterd;
|
||||
vir_bytes offset_s, offset_d;
|
||||
int p;
|
||||
|
||||
if(vm_isokendpt(sour, &p) != OK)
|
||||
vm_panic("handle_memory: endpoint wrong", sour);
|
||||
vms = &vmproc[p];
|
||||
if(vm_isokendpt(dest, &p) != OK)
|
||||
vm_panic("handle_memory: endpoint wrong", dest);
|
||||
vmd = &vmproc[p];
|
||||
|
||||
vrs = map_lookup(vms, virt_s);
|
||||
vm_assert(vrs);
|
||||
vrd = map_lookup(vmd, virt_d);
|
||||
vm_assert(vrd);
|
||||
|
||||
/* Linear address -> offset from start of vir region. */
|
||||
offset_s = virt_s - vrs->vaddr;
|
||||
offset_d = virt_d - vrd->vaddr;
|
||||
|
||||
/* Make sure that the range in the source process has been mapped
|
||||
* to physical memory.
|
||||
*/
|
||||
map_handle_memory(vms, vrs, offset_s, length, 0);
|
||||
|
||||
/* Prepare work. */
|
||||
#define map_printregion(x, y) (x = x)
|
||||
#define printf(x, y, z) (z = z)
|
||||
printf("before clean with offset, length: %d, %d\n", offset_s, length);
|
||||
map_printregion(vms, vrs);
|
||||
clean_phys_regions(vrs, offset_s, length);
|
||||
printf("after clean with offset, length: %d, %d\n", offset_s, length);
|
||||
map_printregion(vms, vrs);
|
||||
|
||||
printf("before clean with offset, length: %d, %d\n", offset_d, length);
|
||||
map_printregion(vmd, vrd);
|
||||
clean_phys_regions(vrd, offset_d, length);
|
||||
printf("after clean with offset, length: %d, %d\n", offset_d, length);
|
||||
map_printregion(vmd, vrd);
|
||||
|
||||
rm_phys_regions(vrd, offset_d, length);
|
||||
printf("after rm with offset, length: %d, %d\n", offset_d, length);
|
||||
map_printregion(vmd, vrd);
|
||||
|
||||
/* Map memory. */
|
||||
do_map_memory(vms, vmd, vrs, vrd, offset_s, offset_d, length, flag);
|
||||
printf("after map (dst) with offset, length: %d, %d\n", offset_d, length);
|
||||
map_printregion(vmd, vrd);
|
||||
#undef map_printregion
|
||||
#undef printf
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* unmap_memory *
|
||||
*===========================================================================*/
|
||||
PUBLIC int unmap_memory(endpoint_t sour, endpoint_t dest,
|
||||
vir_bytes virt_s, vir_bytes virt_d, vir_bytes length, int flag)
|
||||
{
|
||||
struct vmproc *vmd;
|
||||
struct vir_region *vrd;
|
||||
struct phys_region *pr;
|
||||
struct phys_block *pb;
|
||||
physr_iter iter;
|
||||
vir_bytes off, end;
|
||||
int p;
|
||||
|
||||
/* Use information on the destination process to unmap. */
|
||||
if(vm_isokendpt(dest, &p) != OK)
|
||||
vm_panic("handle_memory: endpoint wrong", dest);
|
||||
vmd = &vmproc[p];
|
||||
|
||||
vrd = map_lookup(vmd, virt_d);
|
||||
vm_assert(vrd);
|
||||
|
||||
/* Search for the first phys region in the destination process. */
|
||||
off = virt_d - vrd->vaddr;
|
||||
physr_start_iter(vrd->phys, &iter, off, AVL_EQUAL);
|
||||
pr = physr_get_iter(&iter);
|
||||
if(!pr)
|
||||
vm_panic("map_memory: no aligned phys region.", 0);
|
||||
|
||||
/* Copy the phys block now rather than doing COW. */
|
||||
end = off + length;
|
||||
while((pr = physr_get_iter(&iter)) && off < end) {
|
||||
pb = pr->ph;
|
||||
vm_assert(pb->refcount > 1);
|
||||
vm_assert(pb->share_flag == PBSH_SMAP);
|
||||
|
||||
map_copy_ph_block(vmd, vrd, pr);
|
||||
|
||||
physr_incr_iter(&iter);
|
||||
off += pb->length;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
|
@ -127,26 +127,42 @@ PUBLIC void do_pagefaults(void)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* do_memory *
|
||||
* do_memory *
|
||||
*===========================================================================*/
|
||||
PUBLIC void do_memory(void)
|
||||
{
|
||||
int r, s;
|
||||
endpoint_t who, requestor;
|
||||
vir_bytes mem;
|
||||
endpoint_t who, who_s, requestor;
|
||||
vir_bytes mem, mem_s;
|
||||
vir_bytes len;
|
||||
int wrflag;
|
||||
|
||||
while((r=sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &requestor))
|
||||
== OK) {
|
||||
while(1) {
|
||||
int p, r = OK;
|
||||
struct vmproc *vmp;
|
||||
|
||||
if(vm_isokendpt(who, &p) != OK)
|
||||
vm_panic("do_memory: endpoint wrong", who);
|
||||
vmp = &vmproc[p];
|
||||
r = sys_vmctl_get_memreq(&who, &mem, &len, &wrflag, &who_s,
|
||||
&mem_s, &requestor);
|
||||
|
||||
r = handle_memory(vmp, mem, len, wrflag);
|
||||
switch(r) {
|
||||
case VMPTYPE_CHECK:
|
||||
if(vm_isokendpt(who, &p) != OK)
|
||||
vm_panic("do_memory: bad endpoint", who);
|
||||
vmp = &vmproc[p];
|
||||
|
||||
r = handle_memory(vmp, mem, len, wrflag);
|
||||
break;
|
||||
case VMPTYPE_COWMAP:
|
||||
r = map_memory(who_s, who, mem_s, mem, len, -1);
|
||||
break;
|
||||
case VMPTYPE_SMAP:
|
||||
r = map_memory(who_s, who, mem_s, mem, len, wrflag);
|
||||
break;
|
||||
case VMPTYPE_SUNMAP:
|
||||
r = unmap_memory(who_s, who, mem_s, mem, len, wrflag);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if(sys_vmctl(requestor, VMCTL_MEMREQ_REPLY, r) != OK)
|
||||
vm_panic("do_memory: sys_vmctl failed", r);
|
||||
|
|
|
@ -4,6 +4,8 @@ struct vmproc;
|
|||
struct stat;
|
||||
struct mem_map;
|
||||
struct memory;
|
||||
struct vir_region;
|
||||
struct phys_region;
|
||||
|
||||
#include <minix/ipc.h>
|
||||
#include <minix/endpoint.h>
|
||||
|
@ -76,6 +78,12 @@ _PROTOTYPE( int vfs_open, (struct vmproc *for_who, callback_t callback,
|
|||
_PROTOTYPE( int vfs_close, (struct vmproc *for_who, callback_t callback,
|
||||
int fd));
|
||||
|
||||
/* map_mem.c */
|
||||
_PROTOTYPE( int map_memory, (endpoint_t sour, endpoint_t dest,
|
||||
vir_bytes virt_s, vir_bytes virt_d, vir_bytes length, int flag));
|
||||
_PROTOTYPE( int unmap_memory, (endpoint_t sour, endpoint_t dest,
|
||||
vir_bytes virt_s, vir_bytes virt_d, vir_bytes length, int flag));
|
||||
|
||||
/* mmap.c */
|
||||
_PROTOTYPE(int do_mmap, (message *msg) );
|
||||
_PROTOTYPE(int do_munmap, (message *msg) );
|
||||
|
@ -156,6 +164,10 @@ _PROTOTYPE(int map_remap, (struct vmproc *dvmp, vir_bytes da, size_t size,
|
|||
_PROTOTYPE(int map_get_phys, (struct vmproc *vmp, vir_bytes addr, phys_bytes *r));
|
||||
_PROTOTYPE(int map_get_ref, (struct vmproc *vmp, vir_bytes addr, u8_t *cnt));
|
||||
|
||||
_PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp,
|
||||
struct vir_region *region, struct phys_region *ph));
|
||||
_PROTOTYPE(void pb_unreferenced, (struct vir_region *region,
|
||||
struct phys_region *pr));
|
||||
#if SANITYCHECKS
|
||||
_PROTOTYPE(void map_sanitycheck,(char *file, int line));
|
||||
#endif
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
|
@ -40,8 +40,6 @@ FORWARD _PROTOTYPE(struct phys_region *map_new_physblock, (struct vmproc *vmp,
|
|||
FORWARD _PROTOTYPE(int map_ph_writept, (struct vmproc *vmp, struct vir_region *vr,
|
||||
struct phys_region *pr));
|
||||
|
||||
FORWARD _PROTOTYPE(int map_copy_ph_block, (struct vmproc *vmp, struct vir_region *region, struct phys_region *ph));
|
||||
|
||||
FORWARD _PROTOTYPE(struct vir_region *map_copy_region, (struct vmproc *vmp, struct vir_region *vr));
|
||||
|
||||
PRIVATE char *map_name(struct vir_region *vr)
|
||||
|
@ -422,7 +420,7 @@ USE(newregion,
|
|||
/*===========================================================================*
|
||||
* pb_unreferenced *
|
||||
*===========================================================================*/
|
||||
void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
||||
PUBLIC void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
||||
{
|
||||
struct phys_block *pb;
|
||||
int remap = 0;
|
||||
|
@ -460,20 +458,6 @@ void pb_unreferenced(struct vir_region *region, struct phys_region *pr)
|
|||
vm_panic("strange phys flags", NO_NUM);
|
||||
}
|
||||
SLABFREE(pb);
|
||||
} else if(WRITABLE(region, pb)) {
|
||||
/* If a writable piece of physical memory is now only
|
||||
* referenced once, map it writable right away instead of
|
||||
* waiting for a page fault.
|
||||
*/
|
||||
vm_assert(pb);
|
||||
vm_assert(pb->firstregion);
|
||||
vm_assert(!pb->firstregion->next_ph_list);
|
||||
vm_assert(pb->firstregion->ph == pb);
|
||||
vm_assert(pb->firstregion->ph == pb);
|
||||
if(map_ph_writept(pb->firstregion->parent->parent,
|
||||
pb->firstregion->parent, pb->firstregion) != OK) {
|
||||
vm_panic("pb_unreferenced: writept", NO_NUM);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -709,7 +693,7 @@ phys_bytes what_mem;
|
|||
/*===========================================================================*
|
||||
* map_copy_ph_block *
|
||||
*===========================================================================*/
|
||||
PRIVATE int map_copy_ph_block(vmp, region, ph)
|
||||
PUBLIC int map_copy_ph_block(vmp, region, ph)
|
||||
struct vmproc *vmp;
|
||||
struct vir_region *region;
|
||||
struct phys_region *ph;
|
||||
|
@ -816,9 +800,13 @@ int write;
|
|||
if(r != OK)
|
||||
printf("map_ph_writept failed\n");
|
||||
} else {
|
||||
r = map_copy_ph_block(vmp, region, ph);
|
||||
if(r != OK)
|
||||
printf("map_copy_ph_block failed\n");
|
||||
if(ph->ph->refcount > 0
|
||||
&& ph->ph->share_flag != PBSH_COW) {
|
||||
printf("VM: write RO mapped pages.\n");
|
||||
return EFAULT;
|
||||
} else {
|
||||
r = map_copy_ph_block(vmp, region, ph);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* Pagefault in non-existing block. Map in new block. */
|
||||
|
@ -959,9 +947,12 @@ int write;
|
|||
SANITYCHECK(SCL_FUNCTIONS);
|
||||
|
||||
if(changes < 1) {
|
||||
#if VERBOSE
|
||||
printf("region start at 0x%lx offset 0x%lx len 0x%lx write %d\n",
|
||||
region->vaddr, offset, length, write);
|
||||
vm_panic("no changes in map_handle_memory", NO_NUM);
|
||||
printf("no changes in map_handle_memory\n");
|
||||
#endif
|
||||
return EFAULT;
|
||||
}
|
||||
|
||||
#if SANITYCHECKS
|
||||
|
@ -1065,11 +1056,19 @@ PUBLIC int map_writept(struct vmproc *vmp)
|
|||
physr_iter iter;
|
||||
physr_start_iter_least(vr->phys, &iter);
|
||||
while((ph = physr_get_iter(&iter))) {
|
||||
physr_incr_iter(&iter);
|
||||
|
||||
/* If this phys block is shared as SMAP, then do
|
||||
* not update the page table. */
|
||||
if(ph->ph->refcount > 1
|
||||
&& ph->ph->share_flag == PBSH_SMAP) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if((r=map_ph_writept(vmp, vr, ph)) != OK) {
|
||||
printf("VM: map_writept: failed\n");
|
||||
return r;
|
||||
}
|
||||
physr_incr_iter(&iter);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1125,6 +1124,14 @@ struct vmproc *src;
|
|||
USE(pb, pb->refcount++;);
|
||||
vm_assert(pb->refcount > 1);
|
||||
|
||||
/* If the phys block has been shared as SMAP,
|
||||
* do the regular copy. */
|
||||
if(pb->refcount > 2 && pb->share_flag == PBSH_SMAP) {
|
||||
map_copy_ph_block(dst, newvr, new_ph);
|
||||
} else {
|
||||
pb->share_flag = PBSH_COW;
|
||||
}
|
||||
|
||||
/* Get next new physregion */
|
||||
physr_incr_iter(&iter_orig);
|
||||
physr_incr_iter(&iter_new);
|
||||
|
|
|
@ -23,6 +23,9 @@ struct phys_block {
|
|||
vir_bytes length; /* no. of contiguous bytes */
|
||||
phys_bytes phys; /* physical memory */
|
||||
u8_t refcount; /* Refcount of these pages */
|
||||
#define PBSH_COW 1
|
||||
#define PBSH_SMAP 2
|
||||
u8_t share_flag; /* PBSH_COW or PBSH_SMAP */
|
||||
|
||||
/* first in list of phys_regions that reference this block */
|
||||
struct phys_region *firstregion;
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
|
@ -76,8 +76,8 @@ struct memory *mem_chunks; /* store mem chunks here */
|
|||
base = mem_chunks[i].base;
|
||||
size = mem_chunks[i].size;
|
||||
limit = base + size;
|
||||
base = (base + CLICK_SIZE-1) & ~(long)(CLICK_SIZE-1);
|
||||
limit &= ~(long)(CLICK_SIZE-1);
|
||||
base = (phys_bytes) (CLICK_CEIL(base));
|
||||
limit = (phys_bytes) (CLICK_FLOOR(limit));
|
||||
if (limit <= base) {
|
||||
memp->base = memp->size = 0;
|
||||
} else {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#define VERBOSE 0
|
||||
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/config.h>
|
||||
|
|
18
test/ds/Makefile
Normal file
18
test/ds/Makefile
Normal file
|
@ -0,0 +1,18 @@
|
|||
all: dstest subs
|
||||
chmod +x down run
|
||||
|
||||
dstest: dstest.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
subs: subs.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
run: all
|
||||
sh run
|
||||
|
||||
kill:
|
||||
sh down
|
||||
|
||||
clean:
|
||||
rm -f dstest subs
|
||||
|
23
test/ds/README
Normal file
23
test/ds/README
Normal file
|
@ -0,0 +1,23 @@
|
|||
Test Program for DataServer
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
1. Type `make run` to prepare and run test.
|
||||
2. When done testing, type `make clean` to clean up.
|
||||
|
||||
How the test works
|
||||
==================
|
||||
|
||||
`dstest` tests the new DS API (excluding ds_subscribe() and ds_check()).
|
||||
test_u32, test_str, test_mem, test_label, and test_map test U32, STR, MEM, LABEL
|
||||
and MAP type respectively.
|
||||
|
||||
Invalid invokation is tested as well. Erroneous conditions are tested only once.
|
||||
For example, publishing an entry with same label name, but without
|
||||
DSF_OVERWRITE set, is tested in test_u32 and nowhere else again.
|
||||
Type-specific features are always tested.
|
||||
|
||||
`subs` tests ds_subscribe() and ds_check(). The server subscribes
|
||||
to a U32 type. When `dstest` runs, `subs` catches all the updates.
|
||||
|
4
test/ds/down
Normal file
4
test/ds/down
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
service down dstest
|
||||
service down subs
|
230
test/ds/dstest.c
Normal file
230
test/ds/dstest.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
#include "inc.h"
|
||||
|
||||
char *key_u32 = "test_u32";
|
||||
char *key_str = "test_str";
|
||||
char *key_mem = "test_mem";
|
||||
char *key_map = "test_map";
|
||||
char *key_label = "test_label";
|
||||
|
||||
/*===========================================================================*
|
||||
* test_u32 *
|
||||
*===========================================================================*/
|
||||
void test_u32(void)
|
||||
{
|
||||
int r;
|
||||
unsigned long value;
|
||||
|
||||
/* Publish and retrieve. */
|
||||
r = ds_publish_u32(key_u32, 1234, 0);
|
||||
assert(r == OK);
|
||||
r = ds_retrieve_u32(key_u32, &value);
|
||||
assert(r == OK && value == 1234);
|
||||
|
||||
/* If dstest deletes 'test_u32' immediately after publishing it,
|
||||
* subs will catch the event, but it can't check it immediately.
|
||||
* So dstest will sleep 2 seconds to wait for subs to complete. */
|
||||
sleep(2);
|
||||
|
||||
/* Publish again without DSF_OVERWRITE. */
|
||||
r = ds_publish_u32(key_u32, 4321, 0);
|
||||
assert(r == EEXIST);
|
||||
|
||||
/* Publish again with DSF_OVERWRITE to overwrite it. */
|
||||
r = ds_publish_u32(key_u32, 4321, DSF_OVERWRITE);
|
||||
assert(r == OK);
|
||||
r = ds_retrieve_u32(key_u32, &value);
|
||||
assert(r == OK && value == 4321);
|
||||
|
||||
/* Delete. */
|
||||
r = ds_delete_u32(key_u32);
|
||||
assert(r == OK);
|
||||
r = ds_retrieve_u32(key_u32, &value);
|
||||
assert(r == ESRCH);
|
||||
|
||||
printf("DSTEST: U32 test successful!\n");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* test_str *
|
||||
*===========================================================================*/
|
||||
void test_str(void)
|
||||
{
|
||||
int r;
|
||||
char *string = "little";
|
||||
char *longstring = "verylooooooongstring";
|
||||
char buf[17];
|
||||
|
||||
r = ds_publish_str(key_str, string, 0);
|
||||
assert(r == OK);
|
||||
|
||||
r = ds_retrieve_str(key_str, buf, 0);
|
||||
assert(r == OK && strcmp(string, buf) == 0);
|
||||
|
||||
r = ds_delete_str(key_str);
|
||||
assert(r == OK);
|
||||
|
||||
/* Publish a long string. */
|
||||
r = ds_publish_str(key_str, longstring, 0);
|
||||
assert(r == EINVAL);
|
||||
|
||||
printf("DSTEST: STRING test successful!\n");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* test_mem *
|
||||
*===========================================================================*/
|
||||
void test_mem(void)
|
||||
{
|
||||
char *string1 = "ok, this is a string";
|
||||
char *string2 = "ok, this is a very looooong string";
|
||||
size_t len1 = strlen(string1) + 1;
|
||||
size_t len2 = strlen(string2) + 1;
|
||||
char buf[100];
|
||||
size_t get_len;
|
||||
int r;
|
||||
|
||||
/* Publish and retrieve. */
|
||||
r = ds_publish_mem(key_mem, string1, len1, 0);
|
||||
assert(r == OK);
|
||||
get_len = 100;
|
||||
r = ds_retrieve_mem(key_mem, buf, &get_len);
|
||||
assert(r == OK && strcmp(string1, buf) == 0);
|
||||
assert(get_len == len1);
|
||||
|
||||
/* Let get_len=8, which is less than strlen(string1). */
|
||||
get_len = 8;
|
||||
r = ds_retrieve_mem(key_mem, buf, &get_len);
|
||||
assert(r == OK && get_len == 8);
|
||||
|
||||
/* Publish again to overwrite with a bigger memory range. */
|
||||
r = ds_publish_mem(key_mem, string2, len2, DSF_OVERWRITE);
|
||||
assert(r == OK);
|
||||
|
||||
get_len = 100;
|
||||
r = ds_retrieve_mem(key_mem, buf, &get_len);
|
||||
assert(r == OK && strcmp(string2, buf) == 0);
|
||||
assert(get_len == len2);
|
||||
|
||||
r = ds_delete_mem(key_mem);
|
||||
assert(r == OK);
|
||||
|
||||
printf("DSTEST: MEM test successful!\n");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* test_label *
|
||||
*===========================================================================*/
|
||||
void test_label(void)
|
||||
{
|
||||
int r;
|
||||
char get_label[DS_MAX_KEYLEN];
|
||||
unsigned long num;
|
||||
|
||||
/* Publish and retrieve. */
|
||||
r = ds_publish_label(key_label, 1234, 0);
|
||||
assert(r == OK);
|
||||
r = ds_retrieve_label_num(key_label, &num);
|
||||
assert(r == OK && num == 1234);
|
||||
|
||||
/* Here are the differences w.r.t. U32. */
|
||||
r = ds_publish_label("hello", 1234, 0);
|
||||
assert(r == EEXIST);
|
||||
r = ds_retrieve_label_name(get_label, 1234);
|
||||
assert(r == OK && strcmp(key_label, get_label) == 0);
|
||||
|
||||
r = ds_delete_label(key_label);
|
||||
assert(r == OK);
|
||||
|
||||
printf("DSTEST: LABEL test successful!\n");
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* test_map *
|
||||
*===========================================================================*/
|
||||
void test_map(void)
|
||||
{
|
||||
char buf_buf[CLICK_SIZE * 2];
|
||||
char buf_buf2[CLICK_SIZE * 2];
|
||||
char *buf, *buf2;
|
||||
char get_buf[CLICK_SIZE];
|
||||
int *p;
|
||||
volatile int *p2;
|
||||
int *get_p;
|
||||
size_t get_len;
|
||||
int is;
|
||||
int r;
|
||||
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
buf2 = (char*) CLICK_CEIL(buf_buf2);
|
||||
|
||||
p = (int *)buf;
|
||||
p2 = (int *)buf2;
|
||||
get_p = (int *)get_buf;
|
||||
|
||||
*p = 1;
|
||||
r = ds_publish_map(key_map, buf, CLICK_SIZE, 0);
|
||||
assert(r == OK);
|
||||
|
||||
r = ds_snapshot_map(key_map, &is);
|
||||
assert(r == OK);
|
||||
|
||||
/* Copy the mapped memory range.
|
||||
* Set *p=2, then the mapped memory range should change too
|
||||
* and *get_p should be 2.
|
||||
*/
|
||||
*p = 2;
|
||||
get_len = CLICK_SIZE;
|
||||
r = ds_retrieve_map(key_map, get_buf, &get_len, 0, DSMF_COPY_MAPPED);
|
||||
assert(r == OK && get_len == CLICK_SIZE && *get_p == 2);
|
||||
|
||||
/* Copy snapshot, where *get_p should still be 1. */
|
||||
get_len = CLICK_SIZE;
|
||||
r = ds_retrieve_map(key_map, get_buf, &get_len, is, DSMF_COPY_SNAPSHOT);
|
||||
assert(r == OK && get_len == CLICK_SIZE && *get_p == 1);
|
||||
|
||||
/* Map the mapped memory range to @buf2, then set *p=3, which
|
||||
* in turn should let *p2=3.
|
||||
*/
|
||||
get_len = CLICK_SIZE;
|
||||
r = ds_retrieve_map(key_map, buf2, &get_len, 0, DSMF_MAP_MAPPED);
|
||||
assert(r == OK && get_len == CLICK_SIZE);
|
||||
*p = 3;
|
||||
assert(*p2 == 3);
|
||||
|
||||
r = ds_delete_map(key_map);
|
||||
assert(r == OK);
|
||||
|
||||
printf("DSTEST: MAP test successful!\n");
|
||||
}
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(void)
|
||||
{
|
||||
/* SEF local startup. */
|
||||
sef_local_startup();
|
||||
|
||||
/* Run all the tests. */
|
||||
test_u32();
|
||||
test_str();
|
||||
test_mem();
|
||||
test_map();
|
||||
test_label();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
15
test/ds/inc.h
Normal file
15
test/ds/inc.h
Normal file
|
@ -0,0 +1,15 @@
|
|||
#define _MINIX
|
||||
#define _SYSTEM
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/ds.h>
|
||||
#include <minix/syslib.h>
|
6
test/ds/run
Normal file
6
test/ds/run
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
PWD=`pwd`
|
||||
|
||||
service up ${PWD}/subs -config ${PWD}/system.conf -script ${PWD}/down
|
||||
service up ${PWD}/dstest -config ${PWD}/system.conf -script ${PWD}/down
|
93
test/ds/subs.c
Normal file
93
test/ds/subs.c
Normal file
|
@ -0,0 +1,93 @@
|
|||
#include "inc.h"
|
||||
|
||||
char *key_u32 = "test_u32";
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(void)
|
||||
{
|
||||
int r;
|
||||
message mess;
|
||||
char key[DS_MAX_KEYLEN];
|
||||
int type;
|
||||
unsigned long num;
|
||||
char string[17];
|
||||
char buf[1000];
|
||||
size_t length = 1000;
|
||||
|
||||
/* SEF local startup. */
|
||||
sef_local_startup();
|
||||
|
||||
/* Subscribe. */
|
||||
r = ds_subscribe(key_u32, DSF_INITIAL);
|
||||
if(r != OK && r != EEXIST) {
|
||||
printf("SUBSCRIBER: error in ds_subscribe: %d\n", r);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while(1) {
|
||||
/* Wait for a message. */
|
||||
r = sef_receive(ANY, &mess);
|
||||
if(r != OK) {
|
||||
printf("SUBSCRIBER: sef_receive failed.\n");
|
||||
return 1;
|
||||
}
|
||||
/* Only handle notifications from DS. */
|
||||
if(mess.m_source != DS_PROC_NR)
|
||||
continue;
|
||||
|
||||
/* Check which one was changed. */
|
||||
r = ds_check(key, &type);
|
||||
if(r == ENOENT) {
|
||||
printf("SUBSCRIBER: the key %s was deleted.\n",
|
||||
key);
|
||||
continue;
|
||||
}
|
||||
if(r != OK) {
|
||||
printf("SUBSCRIBER: error in ds_check.\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Retrieve the entry. */
|
||||
printf("SUBSCRIBER: key: %s, ", key);
|
||||
switch(type) {
|
||||
case DSF_TYPE_U32:
|
||||
r = ds_retrieve_u32(key, &num);
|
||||
if(r != OK)
|
||||
printf("error in ds_retrieve_u32.\n");
|
||||
printf("U32: %d\n", num);
|
||||
break;
|
||||
case DSF_TYPE_STR:
|
||||
r = ds_retrieve_str(key, string, 0);
|
||||
if(r != OK)
|
||||
printf("error in ds_retrieve_str.\n");
|
||||
printf("STR: %s\n", string);
|
||||
break;
|
||||
case DSF_TYPE_MEM:
|
||||
r = ds_retrieve_mem(key, buf, &length);
|
||||
if(r != OK)
|
||||
printf("error in ds_retrieve_mem.\n");
|
||||
break;
|
||||
case DSF_TYPE_MAP:
|
||||
break;
|
||||
default:
|
||||
printf("error in type! %d\n", type);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
25
test/ds/system.conf
Normal file
25
test/ds/system.conf
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
service dstest
|
||||
{
|
||||
system
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SAFEMAP
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
||||
|
||||
service subs
|
||||
{
|
||||
system
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
21
test/safecopy/Makefile
Normal file
21
test/safecopy/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
all: requestor grantor 1fifo 2fifo
|
||||
chmod +x down run
|
||||
|
||||
requestor: requestor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
grantor: grantor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
1fifo 2fifo:
|
||||
mkfifo $@
|
||||
|
||||
run: all
|
||||
sh run
|
||||
|
||||
kill:
|
||||
sh down
|
||||
|
||||
clean:
|
||||
rm -f grantor requestor 1fifo 2fifo
|
||||
|
19
test/safecopy/README
Normal file
19
test/safecopy/README
Normal file
|
@ -0,0 +1,19 @@
|
|||
Test Program for Safecopy with or without COW
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
Test safecopy with COW:
|
||||
1. Set USE_COW_SAFECOPY to 1 in /usr/src/kernel/system/do_safecopy.c
|
||||
2. Type `make run` to prepare and run test.
|
||||
3. When done testing, type `make clean` to clean up.
|
||||
|
||||
Test safecopy without COW:
|
||||
1. Set USE_COW_SAFECOPY to 0 in /usr/src/kernel/system/do_safecopy.c
|
||||
2. Type `make run` to prepare and run test.
|
||||
3. When done testing, type `make clean` to clean up.
|
||||
|
||||
If you want to modify the test buffer size:
|
||||
1. Modify TEST_PAGE_NUM in inc.h
|
||||
2. Modify TEST_PAGE_SHIFT in inc.h
|
||||
|
5
test/safecopy/down
Normal file
5
test/safecopy/down
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
service down grantor
|
||||
service down requestor
|
||||
|
59
test/safecopy/grantor.c
Normal file
59
test/safecopy/grantor.c
Normal file
|
@ -0,0 +1,59 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self, ep_requestor;
|
||||
int fid_send, fid_get;
|
||||
cp_grant_id_t gid;
|
||||
char *buf;
|
||||
int i;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_send = open(FIFO_GRANTOR, O_WRONLY);
|
||||
fid_get = open(FIFO_REQUESTOR, O_RDONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("GRANTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
buf[0] = BUF_START;
|
||||
|
||||
/* Get the requestor's endpoint. */
|
||||
read(fid_get, &ep_requestor, sizeof(ep_requestor));
|
||||
dprint("GRANTOR: getting requestor's endpoint: %d\n", ep_requestor);
|
||||
|
||||
/* Grant. */
|
||||
gid = cpf_grant_direct(ep_requestor, (long)buf, BUF_SIZE,
|
||||
CPF_READ | CPF_WRITE);
|
||||
ep_self = getprocnr();
|
||||
dprint("GRANTOR: sending my endpoint %d and gid %d\n", ep_self, gid);
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
write(fid_send, &gid, sizeof(gid));
|
||||
|
||||
/* Wait till requestor is done. */
|
||||
FIFO_WAIT(fid_get);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
50
test/safecopy/inc.h
Normal file
50
test/safecopy/inc.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#define _SYSTEM
|
||||
#define _MINIX
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/safecopies.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <errno.h>
|
||||
|
||||
/* TEST_PAGE_SHIFT =
|
||||
* log2(CLICK_SIZE * TEST_PAGE_NUM) = CLICK_SHIFT + log2(TEST_PAGE_NUM)
|
||||
*/
|
||||
#define TEST_PAGE_NUM 8
|
||||
#define TEST_PAGE_SHIFT 15
|
||||
|
||||
#define BUF_SIZE (TEST_PAGE_NUM * CLICK_SIZE)
|
||||
#define BUF_START 100
|
||||
|
||||
#define FIFO_REQUESTOR "/usr/src/test/safecopy/1fifo"
|
||||
#define FIFO_GRANTOR "/usr/src/test/safecopy/2fifo"
|
||||
|
||||
#define FIFO_WAIT(fid) { \
|
||||
int a; \
|
||||
if(read(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_WAIT failed", NO_NUM); \
|
||||
}
|
||||
#define FIFO_NOTIFY(fid) { \
|
||||
int a = 1; \
|
||||
if(write(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_NOTIFY failed", NO_NUM); \
|
||||
}
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
# define dprint printf
|
||||
#else
|
||||
# define dprint (void)
|
||||
#endif
|
||||
|
96
test/safecopy/requestor.c
Normal file
96
test/safecopy/requestor.c
Normal file
|
@ -0,0 +1,96 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
endpoint_t ep_granter;
|
||||
int gid;
|
||||
char *buf;
|
||||
|
||||
/*===========================================================================*
|
||||
* test *
|
||||
*===========================================================================*/
|
||||
int test(size_t size)
|
||||
{
|
||||
u32_t low1, high1;
|
||||
u32_t low2, high2;
|
||||
int r;
|
||||
|
||||
/* Timing. */
|
||||
read_tsc(&high1, &low1);
|
||||
r = sys_safecopyfrom(ep_granter, gid, 0, (long)buf, size, D);
|
||||
read_tsc(&high2, &low2);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in safecopy: %d\n", r);
|
||||
return r;
|
||||
}
|
||||
printf("REQUESTOR: SAFECOPY 0x%-8x - %d\n", size, low2 - low1);
|
||||
|
||||
/* Test. */
|
||||
if(buf[0] != BUF_START) {
|
||||
printf("REQUESTOR: error in safecopy!\n");
|
||||
printf(" size, value: %d, %d\n", size, buf[0]);
|
||||
return r;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self;
|
||||
int fid_send, fid_get;
|
||||
int i;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_get = open(FIFO_GRANTOR, O_RDONLY);
|
||||
fid_send = open(FIFO_REQUESTOR, O_WRONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("REQUESTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Sending the endpoint to the granter, in order to let him
|
||||
* create the grant.
|
||||
*/
|
||||
ep_self = getprocnr();
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
dprint("REQUESTOR: sending my endpoint: %d\n", ep_self);
|
||||
|
||||
/* Getting the granter's endpoint and gid. */
|
||||
read(fid_get, &ep_granter, sizeof(ep_granter));
|
||||
read(fid_get, &gid, sizeof(gid));
|
||||
dprint("REQUESTOR: getting granter's endpoint %d and gid %d\n",
|
||||
ep_granter, gid);
|
||||
|
||||
/* Test SAFECOPY. */
|
||||
for(i = 0; i <= TEST_PAGE_SHIFT; i++) {
|
||||
if(test(1 << i) != OK)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Notify grantor we are done. */
|
||||
FIFO_NOTIFY(fid_send);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
7
test/safecopy/run
Normal file
7
test/safecopy/run
Normal file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/sh
|
||||
|
||||
PWD=`pwd`
|
||||
|
||||
service up ${PWD}/grantor -config ${PWD}/system.conf -script ${PWD}/down
|
||||
service up ${PWD}/requestor -config ${PWD}/system.conf -script ${PWD}/down
|
||||
|
34
test/safecopy/system.conf
Normal file
34
test/safecopy/system.conf
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
service requestor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
||||
|
||||
service grantor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
21
test/safemap/Makefile
Normal file
21
test/safemap/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
all: requestor grantor 1fifo 2fifo
|
||||
chmod +x down run
|
||||
|
||||
requestor: requestor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
grantor: grantor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
1fifo 2fifo:
|
||||
mkfifo $@
|
||||
|
||||
run: all
|
||||
sh run
|
||||
|
||||
kill:
|
||||
sh down
|
||||
|
||||
clean:
|
||||
rm -f grantor requestor 1fifo 2fifo
|
||||
|
8
test/safemap/README
Normal file
8
test/safemap/README
Normal file
|
@ -0,0 +1,8 @@
|
|||
Test Program for Safemap
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
1. Type `make run` to prepare and run test.
|
||||
2. When done testing, type `make clean` to clean up.
|
||||
|
4
test/safemap/down
Normal file
4
test/safemap/down
Normal file
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
|
||||
service down grantor
|
||||
service down requestor
|
129
test/safemap/grantor.c
Normal file
129
test/safemap/grantor.c
Normal file
|
@ -0,0 +1,129 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
int fid_send, fid_get;
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self, ep_requestor, ep_child;
|
||||
cp_grant_id_t gid;
|
||||
int i, r, pid;
|
||||
char *buf;
|
||||
int status;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_send = open(FIFO_GRANTOR, O_WRONLY);
|
||||
fid_get = open(FIFO_REQUESTOR, O_RDONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("GRANTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the requestor's endpoint. */
|
||||
read(fid_get, &ep_requestor, sizeof(ep_requestor));
|
||||
dprint("GRANTOR: getting requestor's endpoint: %d\n", ep_requestor);
|
||||
|
||||
/* Grant. */
|
||||
gid = cpf_grant_direct(ep_requestor, (long)buf, BUF_SIZE,
|
||||
CPF_READ | CPF_WRITE | CPF_MAP);
|
||||
ep_self = getprocnr();
|
||||
dprint("GRANTOR: sending my endpoint %d and gid %d\n", ep_self, gid);
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
write(fid_send, &gid, sizeof(gid));
|
||||
|
||||
/* Test MAP. */
|
||||
buf[0] = BUF_START_GRANTOR;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_REQUESTOR, "MAP");
|
||||
|
||||
/* Test UNMAP. */
|
||||
buf[0] = BUF_START_GRANTOR;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_GRANTOR, "UNMAP");
|
||||
|
||||
/* Test REVOKE. */
|
||||
r = sys_saferevmap_gid(gid);
|
||||
if(r != OK) {
|
||||
printf("GRANTOR: error in sys_saferevmap_gid: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
buf[0] = BUF_START_GRANTOR+1;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_GRANTOR+1, "REVOKE");
|
||||
|
||||
/* Test SMAP_COW. */
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
buf[0] = BUF_START_GRANTOR;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_GRANTOR, "SMAP_COW");
|
||||
|
||||
/* Test COW_SMAP. */
|
||||
r = sys_saferevmap_gid(gid);
|
||||
if(r != OK) {
|
||||
printf("GRANTOR: error in sys_saferevmap_gid: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
buf[0] = BUF_START_GRANTOR+1;
|
||||
pid = fork();
|
||||
if(pid < 0) {
|
||||
printf("GRANTOR: error in fork.\n");
|
||||
return 1;
|
||||
}
|
||||
if(pid == 0) {
|
||||
buf[0] = BUF_START_GRANTOR+2;
|
||||
exit(0);
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
ep_child = getnprocnr(pid);
|
||||
if ((r = sys_privctl(ep_child, SYS_PRIV_SET_USER, NULL)) != OK) {
|
||||
printf("GRANTOR: unable to set privileges: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
if ((r = sys_privctl(ep_child, SYS_PRIV_ALLOW, NULL)) != OK) {
|
||||
printf("GRANTOR: child process can't run: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
wait(&status);
|
||||
FIFO_NOTIFY(fid_send);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_GRANTOR+1, "COW_SMAP");
|
||||
|
||||
/* Test COW_SMAP2 (with COW safecopy). */
|
||||
r = sys_saferevmap_gid(gid);
|
||||
if(r != OK) {
|
||||
printf("GRANTOR: error in sys_saferevmap_gid: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("GRANTOR", buf[0], BUF_START_REQUESTOR, "COW_SMAP2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
54
test/safemap/inc.h
Normal file
54
test/safemap/inc.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#define _SYSTEM
|
||||
#define _MINIX
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/safecopies.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define TEST_PAGE_NUM 4
|
||||
#define BUF_SIZE (TEST_PAGE_NUM * CLICK_SIZE)
|
||||
#define BUF_START_REQUESTOR 10
|
||||
#define BUF_START_GRANTOR 20
|
||||
|
||||
#define FIFO_REQUESTOR "/usr/src/test/safemap/1fifo"
|
||||
#define FIFO_GRANTOR "/usr/src/test/safemap/2fifo"
|
||||
|
||||
#define FIFO_WAIT(fid) { \
|
||||
int a; \
|
||||
if(read(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_WAIT failed", NO_NUM); \
|
||||
}
|
||||
#define FIFO_NOTIFY(fid) { \
|
||||
int a = 1; \
|
||||
if(write(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_NOTIFY failed", NO_NUM); \
|
||||
}
|
||||
|
||||
#define CHECK_TEST(who, result, expected, test_name) { \
|
||||
printf("%-9s: test %s %s\n", who, test_name, \
|
||||
(expected == result ? "succeeded" : "failed")); \
|
||||
if(expected != result) { \
|
||||
exit(1); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
# define dprint printf
|
||||
#else
|
||||
# define dprint (void)
|
||||
#endif
|
||||
|
153
test/safemap/requestor.c
Normal file
153
test/safemap/requestor.c
Normal file
|
@ -0,0 +1,153 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
endpoint_t ep_granter;
|
||||
cp_grant_id_t gid;
|
||||
char *buf;
|
||||
int fid_send, fid_get;
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self, ep_child;
|
||||
size_t size = BUF_SIZE;
|
||||
int i, r, pid;
|
||||
int status;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_get = open(FIFO_GRANTOR, O_RDONLY);
|
||||
fid_send = open(FIFO_REQUESTOR, O_WRONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("REQUESTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send the endpoint to the granter, in order to let him to
|
||||
* create the grant.
|
||||
*/
|
||||
ep_self = getprocnr();
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
dprint("REQUESTOR: sending my endpoint: %d\n", ep_self);
|
||||
|
||||
/* Get the granter's endpoint and gid. */
|
||||
read(fid_get, &ep_granter, sizeof(ep_granter));
|
||||
read(fid_get, &gid, sizeof(gid));
|
||||
dprint("REQUESTOR: getting granter's endpoint %d and gid %d\n",
|
||||
ep_granter, gid);
|
||||
|
||||
/* Test MAP. */
|
||||
FIFO_WAIT(fid_get);
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf, size, D, 1);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safemap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_GRANTOR, "MAP");
|
||||
buf[0] = BUF_START_REQUESTOR;
|
||||
r = sys_safeunmap(D, (long)buf);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safeunmap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
|
||||
/* Test UNMAP. */
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_REQUESTOR, "UNMAP");
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf, size, D, 1);
|
||||
if(r != 0) {
|
||||
printf("REQUESTOR: error in sys_safemap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
|
||||
/* Test REVOKE. */
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_GRANTOR, "REVOKE");
|
||||
buf[0] = BUF_START_REQUESTOR;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
|
||||
/* Test SMAP_COW. */
|
||||
FIFO_WAIT(fid_get);
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf, size, D, 1);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safemap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
buf[0] = BUF_START_REQUESTOR;
|
||||
pid = fork();
|
||||
if(pid < 0) {
|
||||
printf("REQUESTOR: error in fork\n");
|
||||
return 1;
|
||||
}
|
||||
if(pid == 0) {
|
||||
exit(buf[0] != BUF_START_REQUESTOR);
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
ep_child = getnprocnr(pid);
|
||||
if ((r = sys_privctl(ep_child, SYS_PRIV_SET_USER, NULL)) != OK) {
|
||||
printf("REQUESTOR: unable to set privileges: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
if ((r = sys_privctl(ep_child, SYS_PRIV_ALLOW, NULL)) != OK) {
|
||||
printf("REQUESTOR: child process can't run: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
wait(&status);
|
||||
FIFO_NOTIFY(fid_send);
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_GRANTOR, "SMAP_COW");
|
||||
CHECK_TEST("REQUESTOR", 1, WIFEXITED(status)
|
||||
&& (WEXITSTATUS(status) == 0), "SMAP_COW child");
|
||||
|
||||
/* Test COW_SMAP. */
|
||||
FIFO_WAIT(fid_get);
|
||||
buf[0] = BUF_START_REQUESTOR;
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf, size, D, 1);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safemap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_GRANTOR+1, "COW_SMAP");
|
||||
|
||||
/* Test COW_SMAP2 (with COW safecopy). */
|
||||
FIFO_WAIT(fid_get);
|
||||
buf[0] = BUF_START_REQUESTOR;
|
||||
r = sys_safecopyto(ep_granter, gid, 0, (long)buf, size, D);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safecopyto: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf, size, D, 1);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: error in sys_safemap: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
FIFO_NOTIFY(fid_send);
|
||||
CHECK_TEST("REQUESTOR", buf[0], BUF_START_REQUESTOR, "COW_SMAP2");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
6
test/safemap/run
Normal file
6
test/safemap/run
Normal file
|
@ -0,0 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
PWD=`pwd`
|
||||
|
||||
service up ${PWD}/grantor -config ${PWD}/system.conf -script ${PWD}/down
|
||||
service up ${PWD}/requestor -config ${PWD}/system.conf -script ${PWD}/down
|
34
test/safemap/system.conf
Normal file
34
test/safemap/system.conf
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
service requestor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
||||
|
||||
service grantor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
21
test/safeperf/Makefile
Normal file
21
test/safeperf/Makefile
Normal file
|
@ -0,0 +1,21 @@
|
|||
all: requestor grantor 1fifo 2fifo
|
||||
chmod +x down run
|
||||
|
||||
requestor: requestor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
grantor: grantor.c inc.h
|
||||
cc -o $@ $< -lsys
|
||||
|
||||
1fifo 2fifo:
|
||||
mkfifo $@
|
||||
|
||||
run: all
|
||||
sh run
|
||||
|
||||
kill:
|
||||
sh down
|
||||
|
||||
clean:
|
||||
rm -f grantor requestor 1fifo 2fifo
|
||||
|
11
test/safeperf/README
Normal file
11
test/safeperf/README
Normal file
|
@ -0,0 +1,11 @@
|
|||
Performance Test Program for Safecopy and Safemap
|
||||
|
||||
How to run
|
||||
==========
|
||||
|
||||
1. Set USE_COW_SAFECOPY to 1 or 0 in kernel/system/do_safecopy.c
|
||||
to run safecopy tests with or without COW optimization.
|
||||
2. Type `make run` to prepare and run tests. Configuration parameters
|
||||
for performance tests are in ./run.
|
||||
3. When done testing, type `make clean` to clean up.
|
||||
|
5
test/safeperf/down
Normal file
5
test/safeperf/down
Normal file
|
@ -0,0 +1,5 @@
|
|||
#!/bin/sh
|
||||
|
||||
service down grantor
|
||||
service down requestor
|
||||
|
62
test/safeperf/grantor.c
Normal file
62
test/safeperf/grantor.c
Normal file
|
@ -0,0 +1,62 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
int fid_send, fid_get;
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self, ep_requestor, ep_child;
|
||||
cp_grant_id_t gid;
|
||||
int i, r, pid;
|
||||
char *buf;
|
||||
int status;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_send = open(FIFO_GRANTOR, O_WRONLY);
|
||||
fid_get = open(FIFO_REQUESTOR, O_RDONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("GRANTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Get the requestor's endpoint. */
|
||||
read(fid_get, &ep_requestor, sizeof(ep_requestor));
|
||||
dprint("GRANTOR: getting requestor's endpoint: %d\n", ep_requestor);
|
||||
|
||||
/* Grant. */
|
||||
gid = cpf_grant_direct(ep_requestor, (long)buf, BUF_SIZE,
|
||||
CPF_READ | CPF_WRITE | CPF_MAP);
|
||||
ep_self = getprocnr();
|
||||
dprint("GRANTOR: sending my endpoint %d and gid %d\n", ep_self, gid);
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
write(fid_send, &gid, sizeof(gid));
|
||||
|
||||
/* Test safemap. */
|
||||
buf[0] = 0;
|
||||
FIFO_NOTIFY(fid_send);
|
||||
FIFO_WAIT(fid_get);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
51
test/safeperf/inc.h
Normal file
51
test/safeperf/inc.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
#define _SYSTEM
|
||||
#define _MINIX
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <minix/com.h>
|
||||
#include <minix/type.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/safecopies.h>
|
||||
#include <minix/syslib.h>
|
||||
#include <minix/sysutil.h>
|
||||
#include <errno.h>
|
||||
|
||||
#define TEST_PAGE_NUM 50
|
||||
#define BUF_SIZE (TEST_PAGE_NUM * CLICK_SIZE)
|
||||
|
||||
#define NR_TEST_ITERATIONS 100
|
||||
|
||||
#define FIFO_REQUESTOR "/usr/src/test/safeperf/1fifo"
|
||||
#define FIFO_GRANTOR "/usr/src/test/safeperf/2fifo"
|
||||
|
||||
#define FIFO_WAIT(fid) { \
|
||||
int a; \
|
||||
if(read(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_WAIT failed", NO_NUM); \
|
||||
}
|
||||
#define FIFO_NOTIFY(fid) { \
|
||||
int a = 1; \
|
||||
if(write(fid, &a, sizeof(a)) != sizeof(a)) \
|
||||
panic(__FILE__, "FIFO_NOTIFY failed", NO_NUM); \
|
||||
}
|
||||
|
||||
#define REPORT_TEST(who, test_name, diff) { \
|
||||
printf("%-9s: test %s took an average of %d.%dus per page\n", \
|
||||
who, test_name, (int)diff, ((int)(diff*1000))%1000); \
|
||||
}
|
||||
|
||||
#define DEBUG 0
|
||||
#if DEBUG
|
||||
# define dprint printf
|
||||
#else
|
||||
# define dprint (void)
|
||||
#endif
|
||||
|
166
test/safeperf/requestor.c
Normal file
166
test/safeperf/requestor.c
Normal file
|
@ -0,0 +1,166 @@
|
|||
#include "inc.h"
|
||||
|
||||
char buf_buf[BUF_SIZE + CLICK_SIZE];
|
||||
|
||||
endpoint_t ep_granter;
|
||||
cp_grant_id_t gid;
|
||||
char *buf;
|
||||
int fid_send, fid_get;
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
||||
/*===========================================================================*
|
||||
* read_write_buff *
|
||||
*===========================================================================*/
|
||||
void read_write_buff(char* buff, int size, int is_write)
|
||||
{
|
||||
int i;
|
||||
char c;
|
||||
|
||||
if(size % CLICK_SIZE != 0) {
|
||||
panic("REQUESTOR", "buff_size not page aligned", NO_NUM);
|
||||
}
|
||||
if(is_write) {
|
||||
for(i=0;i<size;i+=CLICK_SIZE) buff[i] = 1;
|
||||
}
|
||||
else {
|
||||
for(i=0;i<size;i+=CLICK_SIZE) c = buff[i];
|
||||
}
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* exit_usage *
|
||||
*===========================================================================*/
|
||||
void exit_usage(void)
|
||||
{
|
||||
printf("Usage: requestor pages=<nr_pages> map=<0|1> write=<0|1>\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* main *
|
||||
*===========================================================================*/
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
endpoint_t ep_self, ep_child;
|
||||
size_t size = BUF_SIZE;
|
||||
int i, r, pid;
|
||||
int status;
|
||||
u64_t start, end, diff;
|
||||
double micros;
|
||||
char nr_pages_str[10], is_map_str[2], is_write_str[2];
|
||||
int nr_pages, is_map, is_write;
|
||||
|
||||
/* SEF local startup. */
|
||||
env_setargs(argc, argv);
|
||||
sef_local_startup();
|
||||
|
||||
/* Parse the command line. */
|
||||
r = env_get_param("pages", nr_pages_str, sizeof(nr_pages_str));
|
||||
errno = 0;
|
||||
nr_pages = atoi(nr_pages_str);
|
||||
if (r != OK || errno || nr_pages <=0) {
|
||||
exit_usage();
|
||||
}
|
||||
if(nr_pages > TEST_PAGE_NUM) {
|
||||
printf("REQUESTOR: too many pages. Max allowed: %d\n",
|
||||
TEST_PAGE_NUM);
|
||||
exit_usage();
|
||||
}
|
||||
r = env_get_param("map", is_map_str, sizeof(is_map_str));
|
||||
errno = 0;
|
||||
is_map = atoi(is_map_str);
|
||||
if (r != OK || errno || (is_map!=0 && is_map!=1)) {
|
||||
exit_usage();
|
||||
}
|
||||
r = env_get_param("write", is_write_str, sizeof(is_write_str));
|
||||
errno = 0;
|
||||
is_write = atoi(is_write_str);
|
||||
if (r != OK || errno || (is_write!=0 && is_write!=1)) {
|
||||
exit_usage();
|
||||
}
|
||||
printf("REQUESTOR: Running tests with pages=%d map=%d write=%d...\n",
|
||||
nr_pages, is_map, is_write);
|
||||
|
||||
/* Prepare work. */
|
||||
buf = (char*) CLICK_CEIL(buf_buf);
|
||||
fid_get = open(FIFO_GRANTOR, O_RDONLY);
|
||||
fid_send = open(FIFO_REQUESTOR, O_WRONLY);
|
||||
if(fid_get < 0 || fid_send < 0) {
|
||||
printf("REQUESTOR: can't open fifo files.\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Send the endpoint to the granter, in order to let him to
|
||||
* create the grant.
|
||||
*/
|
||||
ep_self = getprocnr();
|
||||
write(fid_send, &ep_self, sizeof(ep_self));
|
||||
dprint("REQUESTOR: sending my endpoint: %d\n", ep_self);
|
||||
|
||||
/* Get the granter's endpoint and gid. */
|
||||
read(fid_get, &ep_granter, sizeof(ep_granter));
|
||||
read(fid_get, &gid, sizeof(gid));
|
||||
dprint("REQUESTOR: getting granter's endpoint %d and gid %d\n",
|
||||
ep_granter, gid);
|
||||
|
||||
FIFO_WAIT(fid_get);
|
||||
diff = make64(0, 0);
|
||||
|
||||
if(is_map) {
|
||||
/* Test safemap. */
|
||||
for(i=0;i<NR_TEST_ITERATIONS;i++) {
|
||||
read_tsc_64(&start);
|
||||
r = sys_safemap(ep_granter, gid, 0, (long)buf,
|
||||
nr_pages*CLICK_SIZE, D, 1);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: safemap error: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
read_write_buff(buf, nr_pages*CLICK_SIZE, is_write);
|
||||
read_tsc_64(&end);
|
||||
diff = add64(diff, (sub64(end, start)));
|
||||
r = sys_safeunmap(D, (long)buf);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: safeunmap error: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
micros = ((double)tsc_64_to_micros(diff))
|
||||
/ (NR_TEST_ITERATIONS*nr_pages);
|
||||
REPORT_TEST("REQUESTOR", "SAFEMAP", micros);
|
||||
}
|
||||
else {
|
||||
/* Test safecopy. */
|
||||
for(i=0;i<NR_TEST_ITERATIONS;i++) {
|
||||
read_tsc_64(&start);
|
||||
r = sys_safecopyfrom(ep_granter, gid, 0, (long)buf,
|
||||
nr_pages*CLICK_SIZE, D);
|
||||
if(r != OK) {
|
||||
printf("REQUESTOR: safecopy error: %d\n", r);
|
||||
return 1;
|
||||
}
|
||||
read_write_buff(buf, nr_pages*CLICK_SIZE, is_write);
|
||||
read_tsc_64(&end);
|
||||
diff = add64(diff, (sub64(end, start)));
|
||||
}
|
||||
micros = ((double)tsc_64_to_micros(diff))
|
||||
/ (NR_TEST_ITERATIONS*nr_pages);
|
||||
REPORT_TEST("REQUESTOR", "SAFECOPY", micros);
|
||||
}
|
||||
|
||||
FIFO_NOTIFY(fid_send);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* sef_local_startup *
|
||||
*===========================================================================*/
|
||||
PRIVATE void sef_local_startup()
|
||||
{
|
||||
/* Let SEF perform startup. */
|
||||
sef_startup();
|
||||
}
|
||||
|
16
test/safeperf/run
Normal file
16
test/safeperf/run
Normal file
|
@ -0,0 +1,16 @@
|
|||
#!/bin/sh
|
||||
|
||||
PAGES="1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50"
|
||||
MAP=0
|
||||
WRITE=1
|
||||
|
||||
PWD=`pwd`
|
||||
|
||||
for P in `echo $PAGES`
|
||||
do
|
||||
service up ${PWD}/grantor -config ${PWD}/system.conf -script ${PWD}/down
|
||||
service up ${PWD}/requestor -config ${PWD}/system.conf -script ${PWD}/down \
|
||||
-args pages=${P}\ map=${MAP}\ write=${WRITE}
|
||||
sleep 2
|
||||
done
|
||||
|
34
test/safeperf/system.conf
Normal file
34
test/safeperf/system.conf
Normal file
|
@ -0,0 +1,34 @@
|
|||
|
||||
service requestor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
||||
|
||||
service grantor
|
||||
{
|
||||
system
|
||||
SAFECOPYFROM
|
||||
SAFECOPYTO
|
||||
SAFEMAP
|
||||
SAFEREVMAP
|
||||
SAFEUNMAP
|
||||
UMAP
|
||||
PRIVCTL
|
||||
SETGRANT
|
||||
GETINFO
|
||||
SYSCTL
|
||||
;
|
||||
uid 0;
|
||||
};
|
Loading…
Reference in a new issue