* allow to specify PROT_READ/PROT_WRITE when mmapping a file * add msyncdiff -r1.19 -r1.20 src/sys/rump/include/rump/rumpuser.h
(pooka)
--- src/sys/rump/include/rump/rumpuser.h 2009/02/28 15:49:12 1.19
+++ src/sys/rump/include/rump/rumpuser.h 2009/03/18 15:32:27 1.20
@@ -1,172 +1,177 @@ | @@ -1,172 +1,177 @@ | |||
1 | /* $NetBSD: rumpuser.h,v 1.19 2009/02/28 15:49:12 pooka Exp $ */ | 1 | /* $NetBSD: rumpuser.h,v 1.20 2009/03/18 15:32:27 pooka Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2007 Antti Kantee. All Rights Reserved. | 4 | * Copyright (c) 2007 Antti Kantee. All Rights Reserved. | |
5 | * | 5 | * | |
6 | * Development of this software was supported by Google Summer of Code. | 6 | * Development of this software was supported by Google Summer of Code. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | |
18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | #ifndef _RUMP_RUMPUSER_H_ | 30 | #ifndef _RUMP_RUMPUSER_H_ | |
31 | #define _RUMP_RUMPUSER_H_ | 31 | #define _RUMP_RUMPUSER_H_ | |
32 | 32 | |||
33 | #include <sys/stdint.h> | 33 | #include <sys/stdint.h> | |
34 | 34 | |||
35 | struct msghdr; | 35 | struct msghdr; | |
36 | struct pollfd; | 36 | struct pollfd; | |
37 | struct sockaddr; | 37 | struct sockaddr; | |
38 | 38 | |||
39 | typedef void (*kernel_lockfn)(int); | 39 | typedef void (*kernel_lockfn)(int); | |
40 | typedef void (*kernel_unlockfn)(int, int *); | 40 | typedef void (*kernel_unlockfn)(int, int *); | |
41 | 41 | |||
42 | int rumpuser_getfileinfo(const char *, uint64_t *, int *, int *); | 42 | int rumpuser_getfileinfo(const char *, uint64_t *, int *, int *); | |
43 | #define RUMPUSER_FT_DIR 1 | 43 | #define RUMPUSER_FT_DIR 1 | |
44 | #define RUMPUSER_FT_REG 2 | 44 | #define RUMPUSER_FT_REG 2 | |
45 | #define RUMPUSER_FT_BLK 3 | 45 | #define RUMPUSER_FT_BLK 3 | |
46 | #define RUMPUSER_FT_OTHER 4 | 46 | #define RUMPUSER_FT_OTHER 4 | |
47 | int rumpuser_nanosleep(uint64_t *, uint64_t *, int *); | 47 | int rumpuser_nanosleep(uint64_t *, uint64_t *, int *); | |
48 | 48 | |||
49 | #define rumpuser_malloc(a,b) rumpuser__malloc(a,b,__func__,__LINE__); | 49 | #define rumpuser_malloc(a,b) rumpuser__malloc(a,b,__func__,__LINE__); | |
50 | #define rumpuser_realloc(a,b,c) rumpuser__realloc(a,b,c,__func__,__LINE__); | 50 | #define rumpuser_realloc(a,b,c) rumpuser__realloc(a,b,c,__func__,__LINE__); | |
51 | 51 | |||
52 | void *rumpuser__malloc(size_t, int, const char *, int); | 52 | void *rumpuser__malloc(size_t, int, const char *, int); | |
53 | void *rumpuser__realloc(void *, size_t, int, const char *, int); | 53 | void *rumpuser__realloc(void *, size_t, int, const char *, int); | |
54 | void rumpuser_free(void *); | 54 | void rumpuser_free(void *); | |
55 | 55 | |||
56 | void *rumpuser_anonmmap(size_t, int, int, int *); | 56 | void *rumpuser_anonmmap(size_t, int, int, int *); | |
57 | void *rumpuser_filemmap(int fd, off_t, size_t, int, int, int *); | 57 | #define RUMPUSER_FILEMMAP_READ 0x01 | |
58 | #define RUMPUSER_FILEMMAP_WRITE 0x02 | |||
59 | #define RUMPUSER_FILEMMAP_TRUNCATE 0x04 | |||
60 | #define RUMPUSER_FILEMMAP_SHARED 0x08 | |||
61 | void *rumpuser_filemmap(int fd, off_t, size_t, int, int *); | |||
58 | void rumpuser_unmap(void *, size_t); | 62 | void rumpuser_unmap(void *, size_t); | |
63 | int rumpuser_memsync(void *, size_t, int *); | |||
59 | 64 | |||
60 | int rumpuser_open(const char *, int, int *); | 65 | int rumpuser_open(const char *, int, int *); | |
61 | int rumpuser_ioctl(int, u_long, void *, int *); | 66 | int rumpuser_ioctl(int, u_long, void *, int *); | |
62 | int rumpuser_close(int, int *); | 67 | int rumpuser_close(int, int *); | |
63 | int rumpuser_fsync(int, int *); | 68 | int rumpuser_fsync(int, int *); | |
64 | 69 | |||
65 | typedef void (*rump_biodone_fn)(void *, size_t, int); | 70 | typedef void (*rump_biodone_fn)(void *, size_t, int); | |
66 | 71 | |||
67 | ssize_t rumpuser_read(int, void *, size_t, int *); | 72 | ssize_t rumpuser_read(int, void *, size_t, int *); | |
68 | ssize_t rumpuser_pread(int, void *, size_t, off_t, int *); | 73 | ssize_t rumpuser_pread(int, void *, size_t, off_t, int *); | |
69 | ssize_t rumpuser_write(int, const void *, size_t, int *); | 74 | ssize_t rumpuser_write(int, const void *, size_t, int *); | |
70 | ssize_t rumpuser_pwrite(int, const void *, size_t, off_t, int *); | 75 | ssize_t rumpuser_pwrite(int, const void *, size_t, off_t, int *); | |
71 | void rumpuser_read_bio(int, void *, size_t, off_t, rump_biodone_fn, void *); | 76 | void rumpuser_read_bio(int, void *, size_t, off_t, rump_biodone_fn, void *); | |
72 | void rumpuser_write_bio(int, const void *, size_t, off_t,rump_biodone_fn,void*); | 77 | void rumpuser_write_bio(int, const void *, size_t, off_t,rump_biodone_fn,void*); | |
73 | 78 | |||
74 | struct rumpuser_iovec { | 79 | struct rumpuser_iovec { | |
75 | void *iov_base; | 80 | void *iov_base; | |
76 | uint64_t iov_len; | 81 | uint64_t iov_len; | |
77 | }; | 82 | }; | |
78 | ssize_t rumpuser_readv(int, const struct rumpuser_iovec *, int, int *); | 83 | ssize_t rumpuser_readv(int, const struct rumpuser_iovec *, int, int *); | |
79 | ssize_t rumpuser_writev(int, const struct rumpuser_iovec *, int, int *); | 84 | ssize_t rumpuser_writev(int, const struct rumpuser_iovec *, int, int *); | |
80 | 85 | |||
81 | int rumpuser_gettime(uint64_t *, uint64_t *, int *); | 86 | int rumpuser_gettime(uint64_t *, uint64_t *, int *); | |
82 | int rumpuser_getenv(const char *, char *, size_t, int *); | 87 | int rumpuser_getenv(const char *, char *, size_t, int *); | |
83 | 88 | |||
84 | int rumpuser_gethostname(char *, size_t, int *); | 89 | int rumpuser_gethostname(char *, size_t, int *); | |
85 | 90 | |||
86 | char *rumpuser_realpath(const char *, char *, int *); | 91 | char *rumpuser_realpath(const char *, char *, int *); | |
87 | 92 | |||
88 | int rumpuser_poll(struct pollfd *, int, int, int *); | 93 | int rumpuser_poll(struct pollfd *, int, int, int *); | |
89 | 94 | |||
90 | int rumpuser_putchar(int, int *); | 95 | int rumpuser_putchar(int, int *); | |
91 | 96 | |||
92 | void rumpuser_panic(void); | 97 | void rumpuser_panic(void); | |
93 | 98 | |||
94 | void rumpuser_seterrno(int); | 99 | void rumpuser_seterrno(int); | |
95 | 100 | |||
96 | int rumpuser_writewatchfile_setup(int, int, intptr_t, int *); | 101 | int rumpuser_writewatchfile_setup(int, int, intptr_t, int *); | |
97 | int rumpuser_writewatchfile_wait(int, intptr_t *, int *); | 102 | int rumpuser_writewatchfile_wait(int, intptr_t *, int *); | |
98 | 103 | |||
99 | /* rumpuser_pth */ | 104 | /* rumpuser_pth */ | |
100 | void rumpuser_thrinit(kernel_lockfn, kernel_unlockfn, int); | 105 | void rumpuser_thrinit(kernel_lockfn, kernel_unlockfn, int); | |
101 | int rumpuser_bioinit(rump_biodone_fn); | 106 | int rumpuser_bioinit(rump_biodone_fn); | |
102 | 107 | |||
103 | int rumpuser_thread_create(void *(*f)(void *), void *, const char *); | 108 | int rumpuser_thread_create(void *(*f)(void *), void *, const char *); | |
104 | void rumpuser_thread_exit(void); | 109 | void rumpuser_thread_exit(void); | |
105 | 110 | |||
106 | struct rumpuser_mtx; | 111 | struct rumpuser_mtx; | |
107 | 112 | |||
108 | void rumpuser_mutex_init(struct rumpuser_mtx **); | 113 | void rumpuser_mutex_init(struct rumpuser_mtx **); | |
109 | void rumpuser_mutex_recursive_init(struct rumpuser_mtx **); | 114 | void rumpuser_mutex_recursive_init(struct rumpuser_mtx **); | |
110 | void rumpuser_mutex_enter(struct rumpuser_mtx *); | 115 | void rumpuser_mutex_enter(struct rumpuser_mtx *); | |
111 | int rumpuser_mutex_tryenter(struct rumpuser_mtx *); | 116 | int rumpuser_mutex_tryenter(struct rumpuser_mtx *); | |
112 | void rumpuser_mutex_exit(struct rumpuser_mtx *); | 117 | void rumpuser_mutex_exit(struct rumpuser_mtx *); | |
113 | void rumpuser_mutex_destroy(struct rumpuser_mtx *); | 118 | void rumpuser_mutex_destroy(struct rumpuser_mtx *); | |
114 | int rumpuser_mutex_held(struct rumpuser_mtx *); | 119 | int rumpuser_mutex_held(struct rumpuser_mtx *); | |
115 | 120 | |||
116 | struct rumpuser_rw; | 121 | struct rumpuser_rw; | |
117 | 122 | |||
118 | void rumpuser_rw_init(struct rumpuser_rw **); | 123 | void rumpuser_rw_init(struct rumpuser_rw **); | |
119 | void rumpuser_rw_enter(struct rumpuser_rw *, int); | 124 | void rumpuser_rw_enter(struct rumpuser_rw *, int); | |
120 | int rumpuser_rw_tryenter(struct rumpuser_rw *, int); | 125 | int rumpuser_rw_tryenter(struct rumpuser_rw *, int); | |
121 | void rumpuser_rw_exit(struct rumpuser_rw *); | 126 | void rumpuser_rw_exit(struct rumpuser_rw *); | |
122 | void rumpuser_rw_destroy(struct rumpuser_rw *); | 127 | void rumpuser_rw_destroy(struct rumpuser_rw *); | |
123 | int rumpuser_rw_held(struct rumpuser_rw *); | 128 | int rumpuser_rw_held(struct rumpuser_rw *); | |
124 | int rumpuser_rw_rdheld(struct rumpuser_rw *); | 129 | int rumpuser_rw_rdheld(struct rumpuser_rw *); | |
125 | int rumpuser_rw_wrheld(struct rumpuser_rw *); | 130 | int rumpuser_rw_wrheld(struct rumpuser_rw *); | |
126 | 131 | |||
127 | struct rumpuser_cv; | 132 | struct rumpuser_cv; | |
128 | 133 | |||
129 | void rumpuser_cv_init(struct rumpuser_cv **); | 134 | void rumpuser_cv_init(struct rumpuser_cv **); | |
130 | void rumpuser_cv_destroy(struct rumpuser_cv *); | 135 | void rumpuser_cv_destroy(struct rumpuser_cv *); | |
131 | void rumpuser_cv_wait(struct rumpuser_cv *, struct rumpuser_mtx *); | 136 | void rumpuser_cv_wait(struct rumpuser_cv *, struct rumpuser_mtx *); | |
132 | int rumpuser_cv_timedwait(struct rumpuser_cv *, struct rumpuser_mtx *, | 137 | int rumpuser_cv_timedwait(struct rumpuser_cv *, struct rumpuser_mtx *, | |
133 | struct timespec *); | 138 | struct timespec *); | |
134 | void rumpuser_cv_signal(struct rumpuser_cv *); | 139 | void rumpuser_cv_signal(struct rumpuser_cv *); | |
135 | void rumpuser_cv_broadcast(struct rumpuser_cv *); | 140 | void rumpuser_cv_broadcast(struct rumpuser_cv *); | |
136 | int rumpuser_cv_has_waiters(struct rumpuser_cv *); | 141 | int rumpuser_cv_has_waiters(struct rumpuser_cv *); | |
137 | 142 | |||
138 | struct lwp; | 143 | struct lwp; | |
139 | 144 | |||
140 | void rumpuser_set_curlwp(struct lwp *); | 145 | void rumpuser_set_curlwp(struct lwp *); | |
141 | struct lwp *rumpuser_get_curlwp(void); | 146 | struct lwp *rumpuser_get_curlwp(void); | |
142 | 147 | |||
143 | /* "aio" stuff for being able to fire of a B_ASYNC I/O and continue */ | 148 | /* "aio" stuff for being able to fire of a B_ASYNC I/O and continue */ | |
144 | struct rumpuser_aio { | 149 | struct rumpuser_aio { | |
145 | int rua_fd; | 150 | int rua_fd; | |
146 | uint8_t *rua_data; | 151 | uint8_t *rua_data; | |
147 | size_t rua_dlen; | 152 | size_t rua_dlen; | |
148 | off_t rua_off; | 153 | off_t rua_off; | |
149 | void *rua_bp; | 154 | void *rua_bp; | |
150 | int rua_op; | 155 | int rua_op; | |
151 | }; | 156 | }; | |
152 | 157 | |||
153 | #define N_AIOS 128 | 158 | #define N_AIOS 128 | |
154 | extern struct rumpuser_mtx rumpuser_aio_mtx; | 159 | extern struct rumpuser_mtx rumpuser_aio_mtx; | |
155 | extern struct rumpuser_cv rumpuser_aio_cv; | 160 | extern struct rumpuser_cv rumpuser_aio_cv; | |
156 | extern struct rumpuser_aio rumpuser_aios[N_AIOS]; | 161 | extern struct rumpuser_aio rumpuser_aios[N_AIOS]; | |
157 | extern int rumpuser_aio_head, rumpuser_aio_tail; | 162 | extern int rumpuser_aio_head, rumpuser_aio_tail; | |
158 | 163 | |||
159 | /* rumpuser_net */ | 164 | /* rumpuser_net */ | |
160 | 165 | |||
161 | int rumpuser_net_socket(int, int, int, int *); | 166 | int rumpuser_net_socket(int, int, int, int *); | |
162 | int rumpuser_net_sendmsg(int, const struct msghdr *, int, int *); | 167 | int rumpuser_net_sendmsg(int, const struct msghdr *, int, int *); | |
163 | int rumpuser_net_recvmsg(int, struct msghdr *, int, int *); | 168 | int rumpuser_net_recvmsg(int, struct msghdr *, int, int *); | |
164 | int rumpuser_net_connect(int, const struct sockaddr *, int, int *); | 169 | int rumpuser_net_connect(int, const struct sockaddr *, int, int *); | |
165 | int rumpuser_net_bind(int, const struct sockaddr *, int, int *); | 170 | int rumpuser_net_bind(int, const struct sockaddr *, int, int *); | |
166 | int rumpuser_net_accept(int, struct sockaddr *, int *, int *); | 171 | int rumpuser_net_accept(int, struct sockaddr *, int *, int *); | |
167 | int rumpuser_net_listen(int, int, int *); | 172 | int rumpuser_net_listen(int, int, int *); | |
168 | enum rumpuser_getnametype { RUMPUSER_SOCKNAME, RUMPUSER_PEERNAME }; | 173 | enum rumpuser_getnametype { RUMPUSER_SOCKNAME, RUMPUSER_PEERNAME }; | |
169 | int rumpuser_net_getname(int, struct sockaddr *, int *, | 174 | int rumpuser_net_getname(int, struct sockaddr *, int *, | |
170 | enum rumpuser_getnametype, int *); | 175 | enum rumpuser_getnametype, int *); | |
171 | 176 | |||
172 | #endif /* _RUMP_RUMPUSER_H_ */ | 177 | #endif /* _RUMP_RUMPUSER_H_ */ |
--- src/sys/rump/librump/rumpuser/Attic/rumpuser.c 2009/03/18 10:22:45 1.36
+++ src/sys/rump/librump/rumpuser/Attic/rumpuser.c 2009/03/18 15:32:27 1.37
@@ -1,484 +1,496 @@ | @@ -1,484 +1,496 @@ | |||
1 | /* $NetBSD: rumpuser.c,v 1.36 2009/03/18 10:22:45 cegger Exp $ */ | 1 | /* $NetBSD: rumpuser.c,v 1.37 2009/03/18 15:32:27 pooka Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2007 Antti Kantee. All Rights Reserved. | 4 | * Copyright (c) 2007 Antti Kantee. All Rights Reserved. | |
5 | * | 5 | * | |
6 | * Development of this software was supported by Google Summer of Code | 6 | * Development of this software was supported by Google Summer of Code | |
7 | * and the Finnish Cultural Foundation. | 7 | * and the Finnish Cultural Foundation. | |
8 | * | 8 | * | |
9 | * Redistribution and use in source and binary forms, with or without | 9 | * Redistribution and use in source and binary forms, with or without | |
10 | * modification, are permitted provided that the following conditions | 10 | * modification, are permitted provided that the following conditions | |
11 | * are met: | 11 | * are met: | |
12 | * 1. Redistributions of source code must retain the above copyright | 12 | * 1. Redistributions of source code must retain the above copyright | |
13 | * notice, this list of conditions and the following disclaimer. | 13 | * notice, this list of conditions and the following disclaimer. | |
14 | * 2. Redistributions in binary form must reproduce the above copyright | 14 | * 2. Redistributions in binary form must reproduce the above copyright | |
15 | * notice, this list of conditions and the following disclaimer in the | 15 | * notice, this list of conditions and the following disclaimer in the | |
16 | * documentation and/or other materials provided with the distribution. | 16 | * documentation and/or other materials provided with the distribution. | |
17 | * | 17 | * | |
18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | 18 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | |
19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 19 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 20 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 21 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 22 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 23 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 24 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 25 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 26 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 27 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
28 | * SUCH DAMAGE. | 28 | * SUCH DAMAGE. | |
29 | */ | 29 | */ | |
30 | 30 | |||
31 | #include <sys/cdefs.h> | 31 | #include <sys/cdefs.h> | |
32 | #if !defined(lint) | 32 | #if !defined(lint) | |
33 | __RCSID("$NetBSD: rumpuser.c,v 1.36 2009/03/18 10:22:45 cegger Exp $"); | 33 | __RCSID("$NetBSD: rumpuser.c,v 1.37 2009/03/18 15:32:27 pooka Exp $"); | |
34 | #endif /* !lint */ | 34 | #endif /* !lint */ | |
35 | 35 | |||
36 | /* thank the maker for this */ | 36 | /* thank the maker for this */ | |
37 | #ifdef __linux__ | 37 | #ifdef __linux__ | |
38 | #define _XOPEN_SOURCE 500 | 38 | #define _XOPEN_SOURCE 500 | |
39 | #define _BSD_SOURCE | 39 | #define _BSD_SOURCE | |
40 | #define _FILE_OFFSET_BITS 64 | 40 | #define _FILE_OFFSET_BITS 64 | |
41 | #include <features.h> | 41 | #include <features.h> | |
42 | #endif | 42 | #endif | |
43 | 43 | |||
44 | #include <sys/param.h> | 44 | #include <sys/param.h> | |
45 | #include <sys/event.h> | 45 | #include <sys/event.h> | |
46 | #include <sys/ioctl.h> | 46 | #include <sys/ioctl.h> | |
47 | #include <sys/mman.h> | 47 | #include <sys/mman.h> | |
48 | #include <sys/uio.h> | 48 | #include <sys/uio.h> | |
49 | 49 | |||
50 | #include <assert.h> | 50 | #include <assert.h> | |
51 | #include <err.h> | 51 | #include <err.h> | |
52 | #include <errno.h> | 52 | #include <errno.h> | |
53 | #include <fcntl.h> | 53 | #include <fcntl.h> | |
54 | #include <poll.h> | 54 | #include <poll.h> | |
55 | #include <stdint.h> | 55 | #include <stdint.h> | |
56 | #include <stdio.h> | 56 | #include <stdio.h> | |
57 | #include <stdlib.h> | 57 | #include <stdlib.h> | |
58 | #include <string.h> | 58 | #include <string.h> | |
59 | #include <time.h> | 59 | #include <time.h> | |
60 | #include <unistd.h> | 60 | #include <unistd.h> | |
61 | 61 | |||
62 | #include <rump/rumpuser.h> | 62 | #include <rump/rumpuser.h> | |
63 | 63 | |||
64 | #include "rumpuser_int.h" | 64 | #include "rumpuser_int.h" | |
65 | 65 | |||
66 | int | 66 | int | |
67 | rumpuser_getfileinfo(const char *path, uint64_t *size, int *ft, int *error) | 67 | rumpuser_getfileinfo(const char *path, uint64_t *size, int *ft, int *error) | |
68 | { | 68 | { | |
69 | struct stat sb; | 69 | struct stat sb; | |
70 | int rv; | 70 | int rv; | |
71 | 71 | |||
72 | rv = stat(path, &sb); | 72 | rv = stat(path, &sb); | |
73 | if (rv == -1) { | 73 | if (rv == -1) { | |
74 | *error = errno; | 74 | *error = errno; | |
75 | return rv; | 75 | return rv; | |
76 | } | 76 | } | |
77 | 77 | |||
78 | *size = sb.st_size; | 78 | *size = sb.st_size; | |
79 | switch (sb.st_mode & S_IFMT) { | 79 | switch (sb.st_mode & S_IFMT) { | |
80 | case S_IFDIR: | 80 | case S_IFDIR: | |
81 | *ft = RUMPUSER_FT_DIR; | 81 | *ft = RUMPUSER_FT_DIR; | |
82 | break; | 82 | break; | |
83 | case S_IFREG: | 83 | case S_IFREG: | |
84 | *ft = RUMPUSER_FT_REG; | 84 | *ft = RUMPUSER_FT_REG; | |
85 | break; | 85 | break; | |
86 | case S_IFBLK: | 86 | case S_IFBLK: | |
87 | *ft = RUMPUSER_FT_BLK; | 87 | *ft = RUMPUSER_FT_BLK; | |
88 | break; | 88 | break; | |
89 | default: | 89 | default: | |
90 | *ft = RUMPUSER_FT_OTHER; | 90 | *ft = RUMPUSER_FT_OTHER; | |
91 | break; | 91 | break; | |
92 | } | 92 | } | |
93 | 93 | |||
94 | return rv; | 94 | return rv; | |
95 | } | 95 | } | |
96 | 96 | |||
97 | int | 97 | int | |
98 | rumpuser_nanosleep(uint64_t *sec, uint64_t *nsec, int *error) | 98 | rumpuser_nanosleep(uint64_t *sec, uint64_t *nsec, int *error) | |
99 | { | 99 | { | |
100 | struct timespec rqt, rmt; | 100 | struct timespec rqt, rmt; | |
101 | int rv; | 101 | int rv; | |
102 | 102 | |||
103 | /*LINTED*/ | 103 | /*LINTED*/ | |
104 | rqt.tv_sec = *sec; | 104 | rqt.tv_sec = *sec; | |
105 | /*LINTED*/ | 105 | /*LINTED*/ | |
106 | rqt.tv_nsec = *nsec; | 106 | rqt.tv_nsec = *nsec; | |
107 | 107 | |||
108 | KLOCK_WRAP(rv = nanosleep(&rqt, &rmt)); | 108 | KLOCK_WRAP(rv = nanosleep(&rqt, &rmt)); | |
109 | if (rv == -1) | 109 | if (rv == -1) | |
110 | *error = errno; | 110 | *error = errno; | |
111 | 111 | |||
112 | *sec = rmt.tv_sec; | 112 | *sec = rmt.tv_sec; | |
113 | *nsec = rmt.tv_nsec; | 113 | *nsec = rmt.tv_nsec; | |
114 | 114 | |||
115 | return rv; | 115 | return rv; | |
116 | } | 116 | } | |
117 | 117 | |||
118 | void * | 118 | void * | |
119 | rumpuser__malloc(size_t howmuch, int canfail, const char *func, int line) | 119 | rumpuser__malloc(size_t howmuch, int canfail, const char *func, int line) | |
120 | { | 120 | { | |
121 | void *rv; | 121 | void *rv; | |
122 | 122 | |||
123 | rv = malloc(howmuch); | 123 | rv = malloc(howmuch); | |
124 | if (rv == NULL && canfail == 0) { | 124 | if (rv == NULL && canfail == 0) { | |
125 | warn("malloc failed %s (%d)", func, line); | 125 | warn("malloc failed %s (%d)", func, line); | |
126 | abort(); | 126 | abort(); | |
127 | } | 127 | } | |
128 | 128 | |||
129 | if (rv) | 129 | if (rv) | |
130 | memset(rv, 0, howmuch); | 130 | memset(rv, 0, howmuch); | |
131 | 131 | |||
132 | return rv; | 132 | return rv; | |
133 | } | 133 | } | |
134 | 134 | |||
135 | void * | 135 | void * | |
136 | rumpuser__realloc(void *ptr, size_t howmuch, int canfail, | 136 | rumpuser__realloc(void *ptr, size_t howmuch, int canfail, | |
137 | const char *func, int line) | 137 | const char *func, int line) | |
138 | { | 138 | { | |
139 | void *rv; | 139 | void *rv; | |
140 | 140 | |||
141 | rv = realloc(ptr, howmuch); | 141 | rv = realloc(ptr, howmuch); | |
142 | if (rv == NULL && canfail == 0) { | 142 | if (rv == NULL && canfail == 0) { | |
143 | warn("realloc failed %s (%d)", func, line); | 143 | warn("realloc failed %s (%d)", func, line); | |
144 | abort(); | 144 | abort(); | |
145 | } | 145 | } | |
146 | 146 | |||
147 | return rv; | 147 | return rv; | |
148 | } | 148 | } | |
149 | 149 | |||
150 | void | 150 | void | |
151 | rumpuser_free(void *ptr) | 151 | rumpuser_free(void *ptr) | |
152 | { | 152 | { | |
153 | 153 | |||
154 | free(ptr); | 154 | free(ptr); | |
155 | } | 155 | } | |
156 | 156 | |||
157 | void * | 157 | void * | |
158 | rumpuser_anonmmap(size_t size, int alignbit, int exec, int *error) | 158 | rumpuser_anonmmap(size_t size, int alignbit, int exec, int *error) | |
159 | { | 159 | { | |
160 | void *rv; | 160 | void *rv; | |
161 | int prot; | 161 | int prot; | |
162 | 162 | |||
163 | prot = PROT_READ|PROT_WRITE; | 163 | prot = PROT_READ|PROT_WRITE; | |
164 | if (exec) | 164 | if (exec) | |
165 | prot |= PROT_EXEC; | 165 | prot |= PROT_EXEC; | |
166 | /* XXX: MAP_ALIGNED() is not portable */ | 166 | /* XXX: MAP_ALIGNED() is not portable */ | |
167 | rv = mmap(NULL, size, prot, MAP_ANON | MAP_ALIGNED(alignbit), -1, 0); | 167 | rv = mmap(NULL, size, prot, MAP_ANON | MAP_ALIGNED(alignbit), -1, 0); | |
168 | if (rv == MAP_FAILED) { | 168 | if (rv == MAP_FAILED) { | |
169 | *error = errno; | 169 | *error = errno; | |
170 | return NULL; | 170 | return NULL; | |
171 | } | 171 | } | |
172 | return rv; | 172 | return rv; | |
173 | } | 173 | } | |
174 | 174 | |||
175 | void | 175 | void | |
176 | rumpuser_unmap(void *addr, size_t len) | 176 | rumpuser_unmap(void *addr, size_t len) | |
177 | { | 177 | { | |
178 | int rv; | 178 | int rv; | |
179 | 179 | |||
180 | rv = munmap(addr, len); | 180 | rv = munmap(addr, len); | |
181 | assert(rv == 0); | 181 | assert(rv == 0); | |
182 | } | 182 | } | |
183 | 183 | |||
184 | void * | 184 | void * | |
185 | rumpuser_filemmap(int fd, off_t offset, size_t len, int shared, | 185 | rumpuser_filemmap(int fd, off_t offset, size_t len, int flags, int *error) | |
186 | int dotruncate, int *error) | |||
187 | { | 186 | { | |
188 | void *rv; | 187 | void *rv; | |
189 | int flags; | 188 | int mmflags, prot; | |
190 | 189 | |||
191 | if (dotruncate) | 190 | if (flags & RUMPUSER_FILEMMAP_TRUNCATE) | |
192 | ftruncate(fd, offset + len); | 191 | ftruncate(fd, offset + len); | |
193 | 192 | |||
194 | flags = MAP_FILE; | 193 | mmflags = MAP_FILE; | |
195 | if (shared) | 194 | if (flags & RUMPUSER_FILEMMAP_SHARED) | |
196 | flags |= MAP_SHARED; | 195 | mmflags |= MAP_SHARED; | |
197 | else | 196 | else | |
198 | flags |= MAP_PRIVATE; | 197 | mmflags |= MAP_PRIVATE; | |
199 | 198 | |||
200 | rv = mmap(NULL, len, PROT_READ|PROT_WRITE, flags, fd, offset); | 199 | prot = 0; | |
200 | if (flags & RUMPUSER_FILEMMAP_READ) | |||
201 | prot |= PROT_READ; | |||
202 | if (flags & RUMPUSER_FILEMMAP_WRITE) | |||
203 | prot |= PROT_WRITE; | |||
204 | ||||
205 | rv = mmap(NULL, len, PROT_READ|PROT_WRITE, mmflags, fd, offset); | |||
201 | if (rv == MAP_FAILED) { | 206 | if (rv == MAP_FAILED) { | |
202 | *error = errno; | 207 | *error = errno; | |
203 | return NULL; | 208 | return NULL; | |
204 | } | 209 | } | |
205 | 210 | |||
206 | *error = 0; | 211 | *error = 0; | |
207 | return rv; | 212 | return rv; | |
208 | } | 213 | } | |
209 | 214 | |||
210 | int | 215 | int | |
216 | rumpuser_memsync(void *addr, size_t len, int *error) | |||
217 | { | |||
218 | ||||
219 | DOCALL_KLOCK(int, (msync(addr, len, MS_SYNC))); | |||
220 | } | |||
221 | ||||
222 | int | |||
211 | rumpuser_open(const char *path, int flags, int *error) | 223 | rumpuser_open(const char *path, int flags, int *error) | |
212 | { | 224 | { | |
213 | 225 | |||
214 | DOCALL(int, (open(path, flags, 0644))); | 226 | DOCALL(int, (open(path, flags, 0644))); | |
215 | } | 227 | } | |
216 | 228 | |||
217 | int | 229 | int | |
218 | rumpuser_ioctl(int fd, u_long cmd, void *data, int *error) | 230 | rumpuser_ioctl(int fd, u_long cmd, void *data, int *error) | |
219 | { | 231 | { | |
220 | 232 | |||
221 | DOCALL_KLOCK(int, (ioctl(fd, cmd, data))); | 233 | DOCALL_KLOCK(int, (ioctl(fd, cmd, data))); | |
222 | } | 234 | } | |
223 | 235 | |||
224 | int | 236 | int | |
225 | rumpuser_close(int fd, int *error) | 237 | rumpuser_close(int fd, int *error) | |
226 | { | 238 | { | |
227 | 239 | |||
228 | DOCALL(int, close(fd)); | 240 | DOCALL(int, close(fd)); | |
229 | } | 241 | } | |
230 | 242 | |||
231 | int | 243 | int | |
232 | rumpuser_fsync(int fd, int *error) | 244 | rumpuser_fsync(int fd, int *error) | |
233 | { | 245 | { | |
234 | 246 | |||
235 | DOCALL_KLOCK(int, fsync(fd)); | 247 | DOCALL_KLOCK(int, fsync(fd)); | |
236 | } | 248 | } | |
237 | 249 | |||
238 | ssize_t | 250 | ssize_t | |
239 | rumpuser_read(int fd, void *data, size_t size, int *error) | 251 | rumpuser_read(int fd, void *data, size_t size, int *error) | |
240 | { | 252 | { | |
241 | ssize_t rv; | 253 | ssize_t rv; | |
242 | 254 | |||
243 | KLOCK_WRAP(rv = read(fd, data, size)); | 255 | KLOCK_WRAP(rv = read(fd, data, size)); | |
244 | if (rv == -1) | 256 | if (rv == -1) | |
245 | *error = errno; | 257 | *error = errno; | |
246 | 258 | |||
247 | return rv; | 259 | return rv; | |
248 | } | 260 | } | |
249 | 261 | |||
250 | ssize_t | 262 | ssize_t | |
251 | rumpuser_pread(int fd, void *data, size_t size, off_t offset, int *error) | 263 | rumpuser_pread(int fd, void *data, size_t size, off_t offset, int *error) | |
252 | { | 264 | { | |
253 | ssize_t rv; | 265 | ssize_t rv; | |
254 | 266 | |||
255 | KLOCK_WRAP(rv = pread(fd, data, size, offset)); | 267 | KLOCK_WRAP(rv = pread(fd, data, size, offset)); | |
256 | if (rv == -1) | 268 | if (rv == -1) | |
257 | *error = errno; | 269 | *error = errno; | |
258 | 270 | |||
259 | return rv; | 271 | return rv; | |
260 | } | 272 | } | |
261 | 273 | |||
262 | void | 274 | void | |
263 | rumpuser_read_bio(int fd, void *data, size_t size, off_t offset, | 275 | rumpuser_read_bio(int fd, void *data, size_t size, off_t offset, | |
264 | rump_biodone_fn biodone, void *biodonecookie) | 276 | rump_biodone_fn biodone, void *biodonecookie) | |
265 | { | 277 | { | |
266 | ssize_t rv; | 278 | ssize_t rv; | |
267 | int error = 0; | 279 | int error = 0; | |
268 | 280 | |||
269 | KLOCK_WRAP(rv = rumpuser_pread(fd, data, size, offset, &error)); | 281 | KLOCK_WRAP(rv = rumpuser_pread(fd, data, size, offset, &error)); | |
270 | /* check against <0 instead of ==-1 to get typing below right */ | 282 | /* check against <0 instead of ==-1 to get typing below right */ | |
271 | if (rv < 0) | 283 | if (rv < 0) | |
272 | rv = 0; | 284 | rv = 0; | |
273 | 285 | |||
274 | /* LINTED: see above */ | 286 | /* LINTED: see above */ | |
275 | biodone(biodonecookie, rv, error); | 287 | biodone(biodonecookie, rv, error); | |
276 | } | 288 | } | |
277 | 289 | |||
278 | ssize_t | 290 | ssize_t | |
279 | rumpuser_write(int fd, const void *data, size_t size, int *error) | 291 | rumpuser_write(int fd, const void *data, size_t size, int *error) | |
280 | { | 292 | { | |
281 | ssize_t rv; | 293 | ssize_t rv; | |
282 | 294 | |||
283 | KLOCK_WRAP(rv = write(fd, data, size)); | 295 | KLOCK_WRAP(rv = write(fd, data, size)); | |
284 | if (rv == -1) | 296 | if (rv == -1) | |
285 | *error = errno; | 297 | *error = errno; | |
286 | 298 | |||
287 | return rv; | 299 | return rv; | |
288 | } | 300 | } | |
289 | 301 | |||
290 | ssize_t | 302 | ssize_t | |
291 | rumpuser_pwrite(int fd, const void *data, size_t size, off_t offset, int *error) | 303 | rumpuser_pwrite(int fd, const void *data, size_t size, off_t offset, int *error) | |
292 | { | 304 | { | |
293 | ssize_t rv; | 305 | ssize_t rv; | |
294 | 306 | |||
295 | KLOCK_WRAP(rv = pwrite(fd, data, size, offset)); | 307 | KLOCK_WRAP(rv = pwrite(fd, data, size, offset)); | |
296 | if (rv == -1) | 308 | if (rv == -1) | |
297 | *error = errno; | 309 | *error = errno; | |
298 | 310 | |||
299 | return rv; | 311 | return rv; | |
300 | } | 312 | } | |
301 | 313 | |||
302 | void | 314 | void | |
303 | rumpuser_write_bio(int fd, const void *data, size_t size, off_t offset, | 315 | rumpuser_write_bio(int fd, const void *data, size_t size, off_t offset, | |
304 | rump_biodone_fn biodone, void *biodonecookie) | 316 | rump_biodone_fn biodone, void *biodonecookie) | |
305 | { | 317 | { | |
306 | ssize_t rv; | 318 | ssize_t rv; | |
307 | int error = 0; | 319 | int error = 0; | |
308 | 320 | |||
309 | KLOCK_WRAP(rv = rumpuser_pwrite(fd, data, size, offset, &error)); | 321 | KLOCK_WRAP(rv = rumpuser_pwrite(fd, data, size, offset, &error)); | |
310 | /* check against <0 instead of ==-1 to get typing below right */ | 322 | /* check against <0 instead of ==-1 to get typing below right */ | |
311 | if (rv < 0) | 323 | if (rv < 0) | |
312 | rv = 0; | 324 | rv = 0; | |
313 | 325 | |||
314 | /* LINTED: see above */ | 326 | /* LINTED: see above */ | |
315 | biodone(biodonecookie, rv, error); | 327 | biodone(biodonecookie, rv, error); | |
316 | } | 328 | } | |
317 | 329 | |||
318 | ssize_t | 330 | ssize_t | |
319 | rumpuser_readv(int fd, const struct rumpuser_iovec *riov, int iovcnt, | 331 | rumpuser_readv(int fd, const struct rumpuser_iovec *riov, int iovcnt, | |
320 | int *error) | 332 | int *error) | |
321 | { | 333 | { | |
322 | struct iovec *iovp; | 334 | struct iovec *iovp; | |
323 | ssize_t rv; | 335 | ssize_t rv; | |
324 | int i; | 336 | int i; | |
325 | 337 | |||
326 | iovp = malloc(iovcnt * sizeof(struct iovec)); | 338 | iovp = malloc(iovcnt * sizeof(struct iovec)); | |
327 | if (iovp == NULL) { | 339 | if (iovp == NULL) { | |
328 | *error = ENOMEM; | 340 | *error = ENOMEM; | |
329 | return -1; | 341 | return -1; | |
330 | } | 342 | } | |
331 | for (i = 0; i < iovcnt; i++) { | 343 | for (i = 0; i < iovcnt; i++) { | |
332 | iovp[i].iov_base = riov[i].iov_base; | 344 | iovp[i].iov_base = riov[i].iov_base; | |
333 | /*LINTED*/ | 345 | /*LINTED*/ | |
334 | iovp[i].iov_len = riov[i].iov_len; | 346 | iovp[i].iov_len = riov[i].iov_len; | |
335 | } | 347 | } | |
336 | 348 | |||
337 | KLOCK_WRAP(rv = readv(fd, iovp, iovcnt)); | 349 | KLOCK_WRAP(rv = readv(fd, iovp, iovcnt)); | |
338 | if (rv == -1) | 350 | if (rv == -1) | |
339 | *error = errno; | 351 | *error = errno; | |
340 | free(iovp); | 352 | free(iovp); | |
341 | 353 | |||
342 | return rv; | 354 | return rv; | |
343 | } | 355 | } | |
344 | 356 | |||
345 | ssize_t | 357 | ssize_t | |
346 | rumpuser_writev(int fd, const struct rumpuser_iovec *riov, int iovcnt, | 358 | rumpuser_writev(int fd, const struct rumpuser_iovec *riov, int iovcnt, | |
347 | int *error) | 359 | int *error) | |
348 | { | 360 | { | |
349 | struct iovec *iovp; | 361 | struct iovec *iovp; | |
350 | ssize_t rv; | 362 | ssize_t rv; | |
351 | int i; | 363 | int i; | |
352 | 364 | |||
353 | iovp = malloc(iovcnt * sizeof(struct iovec)); | 365 | iovp = malloc(iovcnt * sizeof(struct iovec)); | |
354 | if (iovp == NULL) { | 366 | if (iovp == NULL) { | |
355 | *error = ENOMEM; | 367 | *error = ENOMEM; | |
356 | return -1; | 368 | return -1; | |
357 | } | 369 | } | |
358 | for (i = 0; i < iovcnt; i++) { | 370 | for (i = 0; i < iovcnt; i++) { | |
359 | iovp[i].iov_base = riov[i].iov_base; | 371 | iovp[i].iov_base = riov[i].iov_base; | |
360 | /*LINTED*/ | 372 | /*LINTED*/ | |
361 | iovp[i].iov_len = riov[i].iov_len; | 373 | iovp[i].iov_len = riov[i].iov_len; | |
362 | } | 374 | } | |
363 | 375 | |||
364 | KLOCK_WRAP(rv = writev(fd, iovp, iovcnt)); | 376 | KLOCK_WRAP(rv = writev(fd, iovp, iovcnt)); | |
365 | if (rv == -1) | 377 | if (rv == -1) | |
366 | *error = errno; | 378 | *error = errno; | |
367 | free(iovp); | 379 | free(iovp); | |
368 | 380 | |||
369 | return rv; | 381 | return rv; | |
370 | } | 382 | } | |
371 | 383 | |||
372 | int | 384 | int | |
373 | rumpuser_gettime(uint64_t *sec, uint64_t *nsec, int *error) | 385 | rumpuser_gettime(uint64_t *sec, uint64_t *nsec, int *error) | |
374 | { | 386 | { | |
375 | struct timeval tv; | 387 | struct timeval tv; | |
376 | int rv; | 388 | int rv; | |
377 | 389 | |||
378 | rv = gettimeofday(&tv, NULL); | 390 | rv = gettimeofday(&tv, NULL); | |
379 | if (rv == -1) { | 391 | if (rv == -1) { | |
380 | *error = errno; | 392 | *error = errno; | |
381 | return rv; | 393 | return rv; | |
382 | } | 394 | } | |
383 | 395 | |||
384 | *sec = tv.tv_sec; | 396 | *sec = tv.tv_sec; | |
385 | *nsec = tv.tv_usec * 1000; | 397 | *nsec = tv.tv_usec * 1000; | |
386 | 398 | |||
387 | return 0; | 399 | return 0; | |
388 | } | 400 | } | |
389 | 401 | |||
390 | int | 402 | int | |
391 | rumpuser_getenv(const char *name, char *buf, size_t blen, int *error) | 403 | rumpuser_getenv(const char *name, char *buf, size_t blen, int *error) | |
392 | { | 404 | { | |
393 | 405 | |||
394 | DOCALL(int, getenv_r(name, buf, blen)); | 406 | DOCALL(int, getenv_r(name, buf, blen)); | |
395 | } | 407 | } | |
396 | 408 | |||
397 | int | 409 | int | |
398 | rumpuser_gethostname(char *name, size_t namelen, int *error) | 410 | rumpuser_gethostname(char *name, size_t namelen, int *error) | |
399 | { | 411 | { | |
400 | 412 | |||
401 | DOCALL(int, (gethostname(name, namelen))); | 413 | DOCALL(int, (gethostname(name, namelen))); | |
402 | } | 414 | } | |
403 | 415 | |||
404 | char * | 416 | char * | |
405 | rumpuser_realpath(const char *path, char resolvedname[MAXPATHLEN], int *error) | 417 | rumpuser_realpath(const char *path, char resolvedname[MAXPATHLEN], int *error) | |
406 | { | 418 | { | |
407 | char *rv; | 419 | char *rv; | |
408 | 420 | |||
409 | rv = realpath(path, resolvedname); | 421 | rv = realpath(path, resolvedname); | |
410 | if (rv == NULL) | 422 | if (rv == NULL) | |
411 | *error = errno; | 423 | *error = errno; | |
412 | else | 424 | else | |
413 | *error = 0; | 425 | *error = 0; | |
414 | 426 | |||
415 | return rv; | 427 | return rv; | |
416 | } | 428 | } | |
417 | 429 | |||
418 | int | 430 | int | |
419 | rumpuser_poll(struct pollfd *fds, int nfds, int timeout, int *error) | 431 | rumpuser_poll(struct pollfd *fds, int nfds, int timeout, int *error) | |
420 | { | 432 | { | |
421 | 433 | |||
422 | DOCALL_KLOCK(int, (poll(fds, (nfds_t)nfds, timeout))); | 434 | DOCALL_KLOCK(int, (poll(fds, (nfds_t)nfds, timeout))); | |
423 | } | 435 | } | |
424 | 436 | |||
425 | int | 437 | int | |
426 | rumpuser_putchar(int c, int *error) | 438 | rumpuser_putchar(int c, int *error) | |
427 | { | 439 | { | |
428 | 440 | |||
429 | DOCALL(int, (putchar(c))); | 441 | DOCALL(int, (putchar(c))); | |
430 | } | 442 | } | |
431 | 443 | |||
432 | void | 444 | void | |
433 | rumpuser_panic(void) | 445 | rumpuser_panic(void) | |
434 | { | 446 | { | |
435 | 447 | |||
436 | abort(); | 448 | abort(); | |
437 | } | 449 | } | |
438 | 450 | |||
439 | void | 451 | void | |
440 | rumpuser_seterrno(int error) | 452 | rumpuser_seterrno(int error) | |
441 | { | 453 | { | |
442 | 454 | |||
443 | errno = error; | 455 | errno = error; | |
444 | } | 456 | } | |
445 | 457 | |||
446 | int | 458 | int | |
447 | rumpuser_writewatchfile_setup(int kq, int fd, intptr_t opaque, int *error) | 459 | rumpuser_writewatchfile_setup(int kq, int fd, intptr_t opaque, int *error) | |
448 | { | 460 | { | |
449 | struct kevent kev; | 461 | struct kevent kev; | |
450 | 462 | |||
451 | if (kq == -1) { | 463 | if (kq == -1) { | |
452 | kq = kqueue(); | 464 | kq = kqueue(); | |
453 | if (kq == -1) { | 465 | if (kq == -1) { | |
454 | *error = errno; | 466 | *error = errno; | |
455 | return -1; | 467 | return -1; | |
456 | } | 468 | } | |
457 | } | 469 | } | |
458 | 470 | |||
459 | EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR, | 471 | EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_ENABLE|EV_CLEAR, | |
460 | NOTE_WRITE, 0, opaque); | 472 | NOTE_WRITE, 0, opaque); | |
461 | if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) { | 473 | if (kevent(kq, &kev, 1, NULL, 0, NULL) == -1) { | |
462 | *error = errno; | 474 | *error = errno; | |
463 | return -1; | 475 | return -1; | |
464 | } | 476 | } | |
465 | 477 | |||
466 | return kq; | 478 | return kq; | |
467 | } | 479 | } | |
468 | 480 | |||
469 | int | 481 | int | |
470 | rumpuser_writewatchfile_wait(int kq, intptr_t *opaque, int *error) | 482 | rumpuser_writewatchfile_wait(int kq, intptr_t *opaque, int *error) | |
471 | { | 483 | { | |
472 | struct kevent kev; | 484 | struct kevent kev; | |
473 | int rv; | 485 | int rv; | |
474 | 486 | |||
475 | KLOCK_WRAP(rv = kevent(kq, NULL, 0, &kev, 1, NULL)); | 487 | KLOCK_WRAP(rv = kevent(kq, NULL, 0, &kev, 1, NULL)); | |
476 | if (rv == -1) { | 488 | if (rv == -1) { | |
477 | *error = errno; | 489 | *error = errno; | |
478 | return -1; | 490 | return -1; | |
479 | } | 491 | } | |
480 | 492 | |||
481 | if (opaque) | 493 | if (opaque) | |
482 | *opaque = kev.udata; | 494 | *opaque = kev.udata; | |
483 | return rv; | 495 | return rv; | |
484 | } | 496 | } |
--- src/sys/rump/net/lib/libshmif/if_shmem.c 2009/03/01 20:50:04 1.4
+++ src/sys/rump/net/lib/libshmif/if_shmem.c 2009/03/18 15:32:27 1.5
@@ -1,377 +1,378 @@ | @@ -1,377 +1,378 @@ | |||
1 | /* $NetBSD: if_shmem.c,v 1.4 2009/03/01 20:50:04 pooka Exp $ */ | 1 | /* $NetBSD: if_shmem.c,v 1.5 2009/03/18 15:32:27 pooka Exp $ */ | |
2 | 2 | |||
3 | /* | 3 | /* | |
4 | * Copyright (c) 2009 Antti Kantee. All Rights Reserved. | 4 | * Copyright (c) 2009 Antti Kantee. All Rights Reserved. | |
5 | * | 5 | * | |
6 | * Development of this software was supported by The Nokia Foundation. | 6 | * Development of this software was supported by The Nokia Foundation. | |
7 | * | 7 | * | |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without | |
9 | * modification, are permitted provided that the following conditions | 9 | * modification, are permitted provided that the following conditions | |
10 | * are met: | 10 | * are met: | |
11 | * 1. Redistributions of source code must retain the above copyright | 11 | * 1. Redistributions of source code must retain the above copyright | |
12 | * notice, this list of conditions and the following disclaimer. | 12 | * notice, this list of conditions and the following disclaimer. | |
13 | * 2. Redistributions in binary form must reproduce the above copyright | 13 | * 2. Redistributions in binary form must reproduce the above copyright | |
14 | * notice, this list of conditions and the following disclaimer in the | 14 | * notice, this list of conditions and the following disclaimer in the | |
15 | * documentation and/or other materials provided with the distribution. | 15 | * documentation and/or other materials provided with the distribution. | |
16 | * | 16 | * | |
17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | 17 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS | |
18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | 18 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | |
20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | 20 | * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 21 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 22 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | 23 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | 24 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | 25 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | 26 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 | * SUCH DAMAGE. | 27 | * SUCH DAMAGE. | |
28 | */ | 28 | */ | |
29 | 29 | |||
30 | #include <sys/cdefs.h> | 30 | #include <sys/cdefs.h> | |
31 | __KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.4 2009/03/01 20:50:04 pooka Exp $"); | 31 | __KERNEL_RCSID(0, "$NetBSD: if_shmem.c,v 1.5 2009/03/18 15:32:27 pooka Exp $"); | |
32 | 32 | |||
33 | #include <sys/param.h> | 33 | #include <sys/param.h> | |
34 | #include <sys/fcntl.h> | 34 | #include <sys/fcntl.h> | |
35 | #include <sys/kmem.h> | 35 | #include <sys/kmem.h> | |
36 | #include <sys/kthread.h> | 36 | #include <sys/kthread.h> | |
37 | #include <sys/lock.h> | 37 | #include <sys/lock.h> | |
38 | #include <sys/atomic.h> | 38 | #include <sys/atomic.h> | |
39 | 39 | |||
40 | #include <net/if.h> | 40 | #include <net/if.h> | |
41 | #include <net/if_ether.h> | 41 | #include <net/if_ether.h> | |
42 | 42 | |||
43 | #include <netinet/in.h> | 43 | #include <netinet/in.h> | |
44 | #include <netinet/in_var.h> | 44 | #include <netinet/in_var.h> | |
45 | 45 | |||
46 | #include <rump/rump.h> | 46 | #include <rump/rump.h> | |
47 | #include <rump/rumpuser.h> | 47 | #include <rump/rumpuser.h> | |
48 | 48 | |||
49 | #include "rump_private.h" | 49 | #include "rump_private.h" | |
50 | 50 | |||
51 | /* | 51 | /* | |
52 | * A virtual ethernet interface which uses shared memory from a | 52 | * A virtual ethernet interface which uses shared memory from a | |
53 | * memory mapped file as the bus. | 53 | * memory mapped file as the bus. | |
54 | */ | 54 | */ | |
55 | 55 | |||
56 | static int shmif_init(struct ifnet *); | 56 | static int shmif_init(struct ifnet *); | |
57 | static int shmif_ioctl(struct ifnet *, u_long, void *); | 57 | static int shmif_ioctl(struct ifnet *, u_long, void *); | |
58 | static void shmif_start(struct ifnet *); | 58 | static void shmif_start(struct ifnet *); | |
59 | static void shmif_stop(struct ifnet *, int); | 59 | static void shmif_stop(struct ifnet *, int); | |
60 | 60 | |||
61 | struct shmif_sc { | 61 | struct shmif_sc { | |
62 | struct ethercom sc_ec; | 62 | struct ethercom sc_ec; | |
63 | uint8_t sc_myaddr[6]; | 63 | uint8_t sc_myaddr[6]; | |
64 | uint8_t *sc_busmem; | 64 | uint8_t *sc_busmem; | |
65 | int sc_memfd; | 65 | int sc_memfd; | |
66 | int sc_kq; | 66 | int sc_kq; | |
67 | 67 | |||
68 | uint32_t sc_nextpacket; | 68 | uint32_t sc_nextpacket; | |
69 | uint32_t sc_prevgen; | 69 | uint32_t sc_prevgen; | |
70 | }; | 70 | }; | |
71 | #define IFMEM_LOCK (0) | 71 | #define IFMEM_LOCK (0) | |
72 | #define IFMEM_GENERATION (8) | 72 | #define IFMEM_GENERATION (8) | |
73 | #define IFMEM_LASTPACKET (12) | 73 | #define IFMEM_LASTPACKET (12) | |
74 | #define IFMEM_WAKEUP (16) | 74 | #define IFMEM_WAKEUP (16) | |
75 | #define IFMEM_DATA (20) | 75 | #define IFMEM_DATA (20) | |
76 | 76 | |||
77 | #define BUSCTRL_ATOFF(sc, off) ((uint32_t *)(sc->sc_busmem+(off))) | 77 | #define BUSCTRL_ATOFF(sc, off) ((uint32_t *)(sc->sc_busmem+(off))) | |
78 | 78 | |||
79 | #define BUSMEM_SIZE 65536 /* enough? */ | 79 | #define BUSMEM_SIZE 65536 /* enough? */ | |
80 | 80 | |||
81 | static void shmif_rcv(void *); | 81 | static void shmif_rcv(void *); | |
82 | 82 | |||
83 | static uint32_t numif; | 83 | static uint32_t numif; | |
84 | 84 | |||
85 | /* | 85 | /* | |
86 | * This locking needs work and will misbehave severely if: | 86 | * This locking needs work and will misbehave severely if: | |
87 | * 1) the backing memory has to be paged in | 87 | * 1) the backing memory has to be paged in | |
88 | * 2) some lockholder exits while holding the lock | 88 | * 2) some lockholder exits while holding the lock | |
89 | */ | 89 | */ | |
90 | static void | 90 | static void | |
91 | lockbus(struct shmif_sc *sc) | 91 | lockbus(struct shmif_sc *sc) | |
92 | { | 92 | { | |
93 | 93 | |||
94 | __cpu_simple_lock((__cpu_simple_lock_t *)sc->sc_busmem); | 94 | __cpu_simple_lock((__cpu_simple_lock_t *)sc->sc_busmem); | |
95 | } | 95 | } | |
96 | 96 | |||
97 | static void | 97 | static void | |
98 | unlockbus(struct shmif_sc *sc) | 98 | unlockbus(struct shmif_sc *sc) | |
99 | { | 99 | { | |
100 | 100 | |||
101 | __cpu_simple_unlock((__cpu_simple_lock_t *)sc->sc_busmem); | 101 | __cpu_simple_unlock((__cpu_simple_lock_t *)sc->sc_busmem); | |
102 | } | 102 | } | |
103 | 103 | |||
104 | static uint32_t | 104 | static uint32_t | |
105 | busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len) | 105 | busread(struct shmif_sc *sc, void *dest, uint32_t off, size_t len) | |
106 | { | 106 | { | |
107 | size_t chunk; | 107 | size_t chunk; | |
108 | 108 | |||
109 | KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); | 109 | KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); | |
110 | chunk = MIN(len, BUSMEM_SIZE - off); | 110 | chunk = MIN(len, BUSMEM_SIZE - off); | |
111 | memcpy(dest, sc->sc_busmem + off, chunk); | 111 | memcpy(dest, sc->sc_busmem + off, chunk); | |
112 | len -= chunk; | 112 | len -= chunk; | |
113 | 113 | |||
114 | if (len == 0) | 114 | if (len == 0) | |
115 | return off + chunk; | 115 | return off + chunk; | |
116 | 116 | |||
117 | /* else, wraps around */ | 117 | /* else, wraps around */ | |
118 | off = IFMEM_DATA; | 118 | off = IFMEM_DATA; | |
119 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | 119 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | |
120 | 120 | |||
121 | /* finish reading */ | 121 | /* finish reading */ | |
122 | memcpy((uint8_t *)dest + chunk, sc->sc_busmem + off, len); | 122 | memcpy((uint8_t *)dest + chunk, sc->sc_busmem + off, len); | |
123 | return off + len; | 123 | return off + len; | |
124 | } | 124 | } | |
125 | 125 | |||
126 | static uint32_t | 126 | static uint32_t | |
127 | buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len) | 127 | buswrite(struct shmif_sc *sc, uint32_t off, void *data, size_t len) | |
128 | { | 128 | { | |
129 | size_t chunk; | 129 | size_t chunk; | |
130 | 130 | |||
131 | KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); | 131 | KASSERT(len < (BUSMEM_SIZE - IFMEM_DATA) && off <= BUSMEM_SIZE); | |
132 | 132 | |||
133 | chunk = MIN(len, BUSMEM_SIZE - off); | 133 | chunk = MIN(len, BUSMEM_SIZE - off); | |
134 | memcpy(sc->sc_busmem + off, data, chunk); | 134 | memcpy(sc->sc_busmem + off, data, chunk); | |
135 | len -= chunk; | 135 | len -= chunk; | |
136 | 136 | |||
137 | if (len == 0) | 137 | if (len == 0) | |
138 | return off + chunk; | 138 | return off + chunk; | |
139 | 139 | |||
140 | DPRINTF(("buswrite wrap: wrote %d bytes to %d, left %d to %d", | 140 | DPRINTF(("buswrite wrap: wrote %d bytes to %d, left %d to %d", | |
141 | chunk, off, len, IFMEM_DATA)); | 141 | chunk, off, len, IFMEM_DATA)); | |
142 | 142 | |||
143 | /* else, wraps around */ | 143 | /* else, wraps around */ | |
144 | off = IFMEM_DATA; | 144 | off = IFMEM_DATA; | |
145 | (*BUSCTRL_ATOFF(sc, IFMEM_GENERATION))++; | 145 | (*BUSCTRL_ATOFF(sc, IFMEM_GENERATION))++; | |
146 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | 146 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | |
147 | 147 | |||
148 | /* finish writing */ | 148 | /* finish writing */ | |
149 | memcpy(sc->sc_busmem + off, (uint8_t *)data + chunk, len); | 149 | memcpy(sc->sc_busmem + off, (uint8_t *)data + chunk, len); | |
150 | return off + len; | 150 | return off + len; | |
151 | } | 151 | } | |
152 | 152 | |||
153 | static inline uint32_t | 153 | static inline uint32_t | |
154 | advance(uint32_t oldoff, uint32_t delta) | 154 | advance(uint32_t oldoff, uint32_t delta) | |
155 | { | 155 | { | |
156 | uint32_t newoff; | 156 | uint32_t newoff; | |
157 | 157 | |||
158 | newoff = oldoff + delta; | 158 | newoff = oldoff + delta; | |
159 | if (newoff >= BUSMEM_SIZE) | 159 | if (newoff >= BUSMEM_SIZE) | |
160 | newoff -= (BUSMEM_SIZE - IFMEM_DATA); | 160 | newoff -= (BUSMEM_SIZE - IFMEM_DATA); | |
161 | return newoff; | 161 | return newoff; | |
162 | 162 | |||
163 | } | 163 | } | |
164 | 164 | |||
165 | static uint32_t | 165 | static uint32_t | |
166 | nextpktoff(struct shmif_sc *sc, uint32_t oldoff) | 166 | nextpktoff(struct shmif_sc *sc, uint32_t oldoff) | |
167 | { | 167 | { | |
168 | uint32_t oldlen; | 168 | uint32_t oldlen; | |
169 | 169 | |||
170 | busread(sc, &oldlen, oldoff, 4); | 170 | busread(sc, &oldlen, oldoff, 4); | |
171 | KASSERT(oldlen < BUSMEM_SIZE - IFMEM_DATA); | 171 | KASSERT(oldlen < BUSMEM_SIZE - IFMEM_DATA); | |
172 | 172 | |||
173 | return advance(oldoff, 4 + oldlen); | 173 | return advance(oldoff, 4 + oldlen); | |
174 | } | 174 | } | |
175 | 175 | |||
176 | int rump_shmif_create(const char *, int *); /* XXX */ | 176 | int rump_shmif_create(const char *, int *); /* XXX */ | |
177 | 177 | |||
178 | int | 178 | int | |
179 | rump_shmif_create(const char *path, int *ifnum) | 179 | rump_shmif_create(const char *path, int *ifnum) | |
180 | { | 180 | { | |
181 | struct shmif_sc *sc; | 181 | struct shmif_sc *sc; | |
182 | struct ifnet *ifp; | 182 | struct ifnet *ifp; | |
183 | uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 }; | 183 | uint8_t enaddr[ETHER_ADDR_LEN] = { 0xb2, 0xa0, 0x00, 0x00, 0x00, 0x00 }; | |
184 | uint32_t randnum; | 184 | uint32_t randnum; | |
185 | unsigned mynum; | 185 | unsigned mynum; | |
186 | int error; | 186 | int error; | |
187 | 187 | |||
188 | randnum = arc4random(); | 188 | randnum = arc4random(); | |
189 | memcpy(&enaddr[2], &randnum, 4); | 189 | memcpy(&enaddr[2], &randnum, 4); | |
190 | mynum = atomic_inc_uint_nv(&numif)-1; | 190 | mynum = atomic_inc_uint_nv(&numif)-1; | |
191 | 191 | |||
192 | sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); | 192 | sc = kmem_zalloc(sizeof(*sc), KM_SLEEP); | |
193 | ifp = &sc->sc_ec.ec_if; | 193 | ifp = &sc->sc_ec.ec_if; | |
194 | memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr)); | 194 | memcpy(sc->sc_myaddr, enaddr, sizeof(enaddr)); | |
195 | 195 | |||
196 | sc->sc_memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error); | 196 | sc->sc_memfd = rumpuser_open(path, O_RDWR | O_CREAT, &error); | |
197 | if (sc->sc_memfd == -1) | 197 | if (sc->sc_memfd == -1) | |
198 | goto fail; | 198 | goto fail; | |
199 | sc->sc_busmem = rumpuser_filemmap(sc->sc_memfd, 0, BUSMEM_SIZE, | 199 | sc->sc_busmem = rumpuser_filemmap(sc->sc_memfd, 0, BUSMEM_SIZE, | |
200 | 1, 1, &error); | 200 | RUMPUSER_FILEMMAP_TRUNCATE | RUMPUSER_FILEMMAP_SHARED | |
201 | | RUMPUSER_FILEMMAP_READ | RUMPUSER_FILEMMAP_WRITE, &error); | |||
201 | if (error) | 202 | if (error) | |
202 | goto fail; | 203 | goto fail; | |
203 | 204 | |||
204 | lockbus(sc); | 205 | lockbus(sc); | |
205 | if (*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) == 0) | 206 | if (*BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) == 0) | |
206 | *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = IFMEM_DATA; | 207 | *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = IFMEM_DATA; | |
207 | sc->sc_nextpacket = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | 208 | sc->sc_nextpacket = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | |
208 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | 209 | sc->sc_prevgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | |
209 | unlockbus(sc); | 210 | unlockbus(sc); | |
210 | 211 | |||
211 | sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error); | 212 | sc->sc_kq = rumpuser_writewatchfile_setup(-1, sc->sc_memfd, 0, &error); | |
212 | if (sc->sc_kq == -1) | 213 | if (sc->sc_kq == -1) | |
213 | goto fail; | 214 | goto fail; | |
214 | 215 | |||
215 | sprintf(ifp->if_xname, "shmif%d", mynum); | 216 | sprintf(ifp->if_xname, "shmif%d", mynum); | |
216 | ifp->if_softc = sc; | 217 | ifp->if_softc = sc; | |
217 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | 218 | ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; | |
218 | ifp->if_init = shmif_init; | 219 | ifp->if_init = shmif_init; | |
219 | ifp->if_ioctl = shmif_ioctl; | 220 | ifp->if_ioctl = shmif_ioctl; | |
220 | ifp->if_start = shmif_start; | 221 | ifp->if_start = shmif_start; | |
221 | ifp->if_stop = shmif_stop; | 222 | ifp->if_stop = shmif_stop; | |
222 | ifp->if_mtu = 1518; | 223 | ifp->if_mtu = 1518; | |
223 | 224 | |||
224 | if_attach(ifp); | 225 | if_attach(ifp); | |
225 | ether_ifattach(ifp, enaddr); | 226 | ether_ifattach(ifp, enaddr); | |
226 | 227 | |||
227 | if (ifnum) | 228 | if (ifnum) | |
228 | *ifnum = mynum; | 229 | *ifnum = mynum; | |
229 | return 0; | 230 | return 0; | |
230 | 231 | |||
231 | fail: | 232 | fail: | |
232 | panic("rump_shmemif_create: fixme"); | 233 | panic("rump_shmemif_create: fixme"); | |
233 | } | 234 | } | |
234 | 235 | |||
235 | static int | 236 | static int | |
236 | shmif_init(struct ifnet *ifp) | 237 | shmif_init(struct ifnet *ifp) | |
237 | { | 238 | { | |
238 | int error = 0; | 239 | int error = 0; | |
239 | 240 | |||
240 | if (rump_threads) { | 241 | if (rump_threads) { | |
241 | error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, | 242 | error = kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, | |
242 | shmif_rcv, ifp, NULL, "shmif"); | 243 | shmif_rcv, ifp, NULL, "shmif"); | |
243 | } else { | 244 | } else { | |
244 | printf("WARNING: threads not enabled, shmif NOT working\n"); | 245 | printf("WARNING: threads not enabled, shmif NOT working\n"); | |
245 | } | 246 | } | |
246 | 247 | |||
247 | ifp->if_flags |= IFF_RUNNING; | 248 | ifp->if_flags |= IFF_RUNNING; | |
248 | return error; | 249 | return error; | |
249 | } | 250 | } | |
250 | 251 | |||
251 | static int | 252 | static int | |
252 | shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data) | 253 | shmif_ioctl(struct ifnet *ifp, u_long cmd, void *data) | |
253 | { | 254 | { | |
254 | int s, rv; | 255 | int s, rv; | |
255 | 256 | |||
256 | s = splnet(); | 257 | s = splnet(); | |
257 | rv = ether_ioctl(ifp, cmd, data); | 258 | rv = ether_ioctl(ifp, cmd, data); | |
258 | splx(s); | 259 | splx(s); | |
259 | 260 | |||
260 | return rv; | 261 | return rv; | |
261 | } | 262 | } | |
262 | 263 | |||
263 | /* send everything in-context */ | 264 | /* send everything in-context */ | |
264 | static void | 265 | static void | |
265 | shmif_start(struct ifnet *ifp) | 266 | shmif_start(struct ifnet *ifp) | |
266 | { | 267 | { | |
267 | struct shmif_sc *sc = ifp->if_softc; | 268 | struct shmif_sc *sc = ifp->if_softc; | |
268 | struct mbuf *m, *m0; | 269 | struct mbuf *m, *m0; | |
269 | uint32_t lastoff, dataoff, npktlenoff; | 270 | uint32_t lastoff, dataoff, npktlenoff; | |
270 | uint32_t pktsize = 0; | 271 | uint32_t pktsize = 0; | |
271 | bool wrote = false; | 272 | bool wrote = false; | |
272 | int error; | 273 | int error; | |
273 | 274 | |||
274 | for (;;) { | 275 | for (;;) { | |
275 | IF_DEQUEUE(&ifp->if_snd, m0); | 276 | IF_DEQUEUE(&ifp->if_snd, m0); | |
276 | if (m0 == NULL) { | 277 | if (m0 == NULL) { | |
277 | break; | 278 | break; | |
278 | } | 279 | } | |
279 | 280 | |||
280 | lockbus(sc); | 281 | lockbus(sc); | |
281 | lastoff = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | 282 | lastoff = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | |
282 | 283 | |||
283 | npktlenoff = nextpktoff(sc, lastoff); | 284 | npktlenoff = nextpktoff(sc, lastoff); | |
284 | dataoff = advance(npktlenoff, 4); | 285 | dataoff = advance(npktlenoff, 4); | |
285 | 286 | |||
286 | for (m = m0; m != NULL; m = m->m_next) { | 287 | for (m = m0; m != NULL; m = m->m_next) { | |
287 | pktsize += m->m_len; | 288 | pktsize += m->m_len; | |
288 | dataoff = buswrite(sc, dataoff, mtod(m, void *), | 289 | dataoff = buswrite(sc, dataoff, mtod(m, void *), | |
289 | m->m_len); | 290 | m->m_len); | |
290 | } | 291 | } | |
291 | buswrite(sc, npktlenoff, &pktsize, 4); | 292 | buswrite(sc, npktlenoff, &pktsize, 4); | |
292 | *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = npktlenoff; | 293 | *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET) = npktlenoff; | |
293 | unlockbus(sc); | 294 | unlockbus(sc); | |
294 | 295 | |||
295 | m_freem(m0); | 296 | m_freem(m0); | |
296 | wrote = true; | 297 | wrote = true; | |
297 | 298 | |||
298 | DPRINTF(("shmif_start: send %d bytes at off %d\n", | 299 | DPRINTF(("shmif_start: send %d bytes at off %d\n", | |
299 | pktsize, npktlenoff)); | 300 | pktsize, npktlenoff)); | |
300 | } | 301 | } | |
301 | /* wakeup */ | 302 | /* wakeup */ | |
302 | if (wrote) | 303 | if (wrote) | |
303 | rumpuser_pwrite(sc->sc_memfd, &error, 4, IFMEM_WAKEUP, &error); | 304 | rumpuser_pwrite(sc->sc_memfd, &error, 4, IFMEM_WAKEUP, &error); | |
304 | } | 305 | } | |
305 | 306 | |||
306 | static void | 307 | static void | |
307 | shmif_stop(struct ifnet *ifp, int disable) | 308 | shmif_stop(struct ifnet *ifp, int disable) | |
308 | { | 309 | { | |
309 | 310 | |||
310 | panic("%s: unimpl", __func__); | 311 | panic("%s: unimpl", __func__); | |
311 | } | 312 | } | |
312 | 313 | |||
313 | static void | 314 | static void | |
314 | shmif_rcv(void *arg) | 315 | shmif_rcv(void *arg) | |
315 | { | 316 | { | |
316 | struct ifnet *ifp = arg; | 317 | struct ifnet *ifp = arg; | |
317 | struct shmif_sc *sc = ifp->if_softc; | 318 | struct shmif_sc *sc = ifp->if_softc; | |
318 | struct mbuf *m = NULL; | 319 | struct mbuf *m = NULL; | |
319 | struct ether_header *eth; | 320 | struct ether_header *eth; | |
320 | uint32_t nextpkt, pktlen, lastpkt, busgen, lastnext; | 321 | uint32_t nextpkt, pktlen, lastpkt, busgen, lastnext; | |
321 | int error; | 322 | int error; | |
322 | 323 | |||
323 | for (;;) { | 324 | for (;;) { | |
324 | if (m == NULL) { | 325 | if (m == NULL) { | |
325 | m = m_gethdr(M_WAIT, MT_DATA); | 326 | m = m_gethdr(M_WAIT, MT_DATA); | |
326 | MCLGET(m, M_WAIT); | 327 | MCLGET(m, M_WAIT); | |
327 | } | 328 | } | |
328 | 329 | |||
329 | DPRINTF(("waiting %d/%d\n", sc->sc_nextpacket, sc->sc_prevgen)); | 330 | DPRINTF(("waiting %d/%d\n", sc->sc_nextpacket, sc->sc_prevgen)); | |
330 | 331 | |||
331 | KASSERT(m->m_flags & M_EXT); | 332 | KASSERT(m->m_flags & M_EXT); | |
332 | lockbus(sc); | 333 | lockbus(sc); | |
333 | lastpkt = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | 334 | lastpkt = *BUSCTRL_ATOFF(sc, IFMEM_LASTPACKET); | |
334 | busgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | 335 | busgen = *BUSCTRL_ATOFF(sc, IFMEM_GENERATION); | |
335 | lastnext = nextpktoff(sc, lastpkt); | 336 | lastnext = nextpktoff(sc, lastpkt); | |
336 | if ((lastnext > sc->sc_nextpacket && busgen > sc->sc_prevgen) | 337 | if ((lastnext > sc->sc_nextpacket && busgen > sc->sc_prevgen) | |
337 | || (busgen > sc->sc_prevgen+1)) { | 338 | || (busgen > sc->sc_prevgen+1)) { | |
338 | nextpkt = lastpkt; | 339 | nextpkt = lastpkt; | |
339 | sc->sc_prevgen = busgen; | 340 | sc->sc_prevgen = busgen; | |
340 | printf("DROPPING\n"); | 341 | printf("DROPPING\n"); | |
341 | } else { | 342 | } else { | |
342 | nextpkt = sc->sc_nextpacket; | 343 | nextpkt = sc->sc_nextpacket; | |
343 | } | 344 | } | |
344 | 345 | |||
345 | /* need more data? */ | 346 | /* need more data? */ | |
346 | if (lastnext == nextpkt && sc->sc_prevgen == busgen){ | 347 | if (lastnext == nextpkt && sc->sc_prevgen == busgen){ | |
347 | unlockbus(sc); | 348 | unlockbus(sc); | |
348 | error = 0; | 349 | error = 0; | |
349 | rumpuser_writewatchfile_wait(sc->sc_kq, NULL, &error); | 350 | rumpuser_writewatchfile_wait(sc->sc_kq, NULL, &error); | |
350 | if (__predict_false(error)) | 351 | if (__predict_false(error)) | |
351 | printf("shmif_rcv: wait failed %d\n", error); | 352 | printf("shmif_rcv: wait failed %d\n", error); | |
352 | continue; | 353 | continue; | |
353 | } | 354 | } | |
354 | 355 | |||
355 | busread(sc, &pktlen, nextpkt, 4); | 356 | busread(sc, &pktlen, nextpkt, 4); | |
356 | busread(sc, mtod(m, void *), advance(nextpkt, 4), pktlen); | 357 | busread(sc, mtod(m, void *), advance(nextpkt, 4), pktlen); | |
357 | 358 | |||
358 | DPRINTF(("shmif_rcv: read packet of length %d at %d\n", | 359 | DPRINTF(("shmif_rcv: read packet of length %d at %d\n", | |
359 | pktlen, nextpkt)); | 360 | pktlen, nextpkt)); | |
360 | 361 | |||
361 | sc->sc_nextpacket = nextpktoff(sc, nextpkt); | 362 | sc->sc_nextpacket = nextpktoff(sc, nextpkt); | |
362 | sc->sc_prevgen = busgen; | 363 | sc->sc_prevgen = busgen; | |
363 | unlockbus(sc); | 364 | unlockbus(sc); | |
364 | 365 | |||
365 | m->m_len = m->m_pkthdr.len = pktlen; | 366 | m->m_len = m->m_pkthdr.len = pktlen; | |
366 | m->m_pkthdr.rcvif = ifp; | 367 | m->m_pkthdr.rcvif = ifp; | |
367 | 368 | |||
368 | /* if it's to us, don't pass up and reuse storage space */ | 369 | /* if it's to us, don't pass up and reuse storage space */ | |
369 | eth = mtod(m, struct ether_header *); | 370 | eth = mtod(m, struct ether_header *); | |
370 | if (memcmp(eth->ether_shost, sc->sc_myaddr, 6) != 0) { | 371 | if (memcmp(eth->ether_shost, sc->sc_myaddr, 6) != 0) { | |
371 | ifp->if_input(ifp, m); | 372 | ifp->if_input(ifp, m); | |
372 | m = NULL; | 373 | m = NULL; | |
373 | } | 374 | } | |
374 | } | 375 | } | |
375 | 376 | |||
376 | panic("shmif_worker is a lazy boy %d\n", error); | 377 | panic("shmif_worker is a lazy boy %d\n", error); | |
377 | } | 378 | } |