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:
Cristiano Giuffrida 2010-01-14 15:24:16 +00:00
parent da3b64d8bc
commit c5b309ff07
99 changed files with 3594 additions and 851 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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;

View file

@ -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);
}

View file

@ -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;

View file

@ -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)

View file

@ -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 *

View file

@ -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.

View file

@ -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 */

View file

@ -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. */

View file

@ -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,

View file

@ -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));

View file

@ -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)

View file

@ -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. */

View file

@ -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];

View file

@ -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;

View file

@ -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;

View file

@ -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 *));

View file

@ -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 */
@ -262,10 +267,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;
}

View file

@ -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

View file

@ -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

View file

@ -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. */

View file

@ -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 */

View file

@ -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
View 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;
}

View file

@ -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);

View file

@ -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

View file

@ -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 \

View file

@ -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;
}

View file

@ -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__,

View 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;

View file

@ -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;

View file

@ -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
View 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, &copy_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, &copy_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, &copy_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, &copy_mess));
}

View file

@ -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;

View file

@ -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 \

View file

@ -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;
}

View file

@ -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"

View file

@ -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;

View file

@ -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

View file

@ -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_ */

View file

@ -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. */

View file

@ -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)

View file

@ -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);
}

View file

@ -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;

View file

@ -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)
{

View file

@ -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 },

View file

@ -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

View file

@ -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;
}

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -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);

View file

@ -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");

View file

@ -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>

View file

@ -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
View 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;
}

View file

@ -1,8 +1,6 @@
#define _SYSTEM 1
#define VERBOSE 0
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>

View file

@ -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);

View file

@ -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

View file

@ -1,8 +1,6 @@
#define _SYSTEM 1
#define VERBOSE 0
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>

View file

@ -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);

View file

@ -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;

View file

@ -1,8 +1,6 @@
#define _SYSTEM 1
#define VERBOSE 0
#include <minix/callnr.h>
#include <minix/com.h>
#include <minix/config.h>

View file

@ -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 {

View file

@ -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
View 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
View 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
View file

@ -0,0 +1,4 @@
#!/bin/sh
service down dstest
service down subs

230
test/ds/dstest.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,5 @@
#!/bin/sh
service down grantor
service down requestor

59
test/safecopy/grantor.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,4 @@
#!/bin/sh
service down grantor
service down requestor

129
test/safemap/grantor.c Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View file

@ -0,0 +1,5 @@
#!/bin/sh
service down grantor
service down requestor

62
test/safeperf/grantor.c Normal file
View 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
View 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
View 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
View 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
View 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;
};