2 * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the Open Source and Linux Lab nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 TARGET_SYS_lseek
= 19,
43 TARGET_SYS_select_one
= 29,
45 TARGET_SYS_argc
= 1000,
46 TARGET_SYS_argv_sz
= 1001,
47 TARGET_SYS_argv
= 1002,
48 TARGET_SYS_memset
= 1004,
54 SELECT_ONE_EXCEPT
= 3,
96 static uint32_t errno_h2g(int host_errno
)
98 static const uint32_t guest_errno
[] = {
99 [EPERM
] = TARGET_EPERM
,
100 [ENOENT
] = TARGET_ENOENT
,
101 [ESRCH
] = TARGET_ESRCH
,
102 [EINTR
] = TARGET_EINTR
,
104 [ENXIO
] = TARGET_ENXIO
,
105 [E2BIG
] = TARGET_E2BIG
,
106 [ENOEXEC
] = TARGET_ENOEXEC
,
107 [EBADF
] = TARGET_EBADF
,
108 [ECHILD
] = TARGET_ECHILD
,
109 [EAGAIN
] = TARGET_EAGAIN
,
110 [ENOMEM
] = TARGET_ENOMEM
,
111 [EACCES
] = TARGET_EACCES
,
112 [EFAULT
] = TARGET_EFAULT
,
114 [ENOTBLK
] = TARGET_ENOTBLK
,
116 [EBUSY
] = TARGET_EBUSY
,
117 [EEXIST
] = TARGET_EEXIST
,
118 [EXDEV
] = TARGET_EXDEV
,
119 [ENODEV
] = TARGET_ENODEV
,
120 [ENOTDIR
] = TARGET_ENOTDIR
,
121 [EISDIR
] = TARGET_EISDIR
,
122 [EINVAL
] = TARGET_EINVAL
,
123 [ENFILE
] = TARGET_ENFILE
,
124 [EMFILE
] = TARGET_EMFILE
,
125 [ENOTTY
] = TARGET_ENOTTY
,
127 [ETXTBSY
] = TARGET_ETXTBSY
,
129 [EFBIG
] = TARGET_EFBIG
,
130 [ENOSPC
] = TARGET_ENOSPC
,
131 [ESPIPE
] = TARGET_ESPIPE
,
132 [EROFS
] = TARGET_EROFS
,
133 [EMLINK
] = TARGET_EMLINK
,
134 [EPIPE
] = TARGET_EPIPE
,
135 [EDOM
] = TARGET_EDOM
,
136 [ERANGE
] = TARGET_ERANGE
,
137 [ENOSYS
] = TARGET_ENOSYS
,
139 [ELOOP
] = TARGET_ELOOP
,
143 if (host_errno
== 0) {
145 } else if (host_errno
> 0 && host_errno
< ARRAY_SIZE(guest_errno
) &&
146 guest_errno
[host_errno
]) {
147 return guest_errno
[host_errno
];
149 return TARGET_EINVAL
;
153 void HELPER(simcall
)(CPUXtensaState
*env
)
155 uint32_t *regs
= env
->regs
;
158 case TARGET_SYS_exit
:
159 qemu_log("exit(%d) simcall\n", regs
[3]);
163 case TARGET_SYS_read
:
164 case TARGET_SYS_write
:
166 bool is_write
= regs
[2] == TARGET_SYS_write
;
167 uint32_t fd
= regs
[3];
168 uint32_t vaddr
= regs
[4];
169 uint32_t len
= regs
[5];
172 target_phys_addr_t paddr
=
173 cpu_get_phys_page_debug(env
, vaddr
);
175 TARGET_PAGE_SIZE
- (vaddr
& (TARGET_PAGE_SIZE
- 1));
176 uint32_t io_sz
= page_left
< len
? page_left
: len
;
177 target_phys_addr_t sz
= io_sz
;
178 void *buf
= cpu_physical_memory_map(paddr
, &sz
, is_write
);
184 write(fd
, buf
, io_sz
) :
185 read(fd
, buf
, io_sz
);
186 regs
[3] = errno_h2g(errno
);
187 cpu_physical_memory_unmap(buf
, sz
, is_write
, sz
);
193 regs
[3] = TARGET_EINVAL
;
200 case TARGET_SYS_open
:
206 for (i
= 0; i
< ARRAY_SIZE(name
); ++i
) {
207 rc
= cpu_memory_rw_debug(
208 env
, regs
[3] + i
, (uint8_t *)name
+ i
, 1, 0);
209 if (rc
!= 0 || name
[i
] == 0) {
214 if (rc
== 0 && i
< ARRAY_SIZE(name
)) {
215 regs
[2] = open(name
, regs
[4], regs
[5]);
216 regs
[3] = errno_h2g(errno
);
219 regs
[3] = TARGET_EINVAL
;
224 case TARGET_SYS_close
:
226 regs
[2] = regs
[3] = 0;
228 regs
[2] = close(regs
[3]);
229 regs
[3] = errno_h2g(errno
);
233 case TARGET_SYS_lseek
:
234 regs
[2] = lseek(regs
[3], (off_t
)(int32_t)regs
[4], regs
[5]);
235 regs
[3] = errno_h2g(errno
);
238 case TARGET_SYS_select_one
:
240 uint32_t fd
= regs
[3];
241 uint32_t rq
= regs
[4];
242 uint32_t target_tv
= regs
[5];
243 uint32_t target_tvv
[2];
245 struct timeval tv
= {0};
252 cpu_memory_rw_debug(env
, target_tv
,
253 (uint8_t *)target_tvv
, sizeof(target_tvv
), 0);
254 tv
.tv_sec
= (int32_t)tswap32(target_tvv
[0]);
255 tv
.tv_usec
= (int32_t)tswap32(target_tvv
[1]);
257 regs
[2] = select(fd
+ 1,
258 rq
== SELECT_ONE_READ
? &fdset
: NULL
,
259 rq
== SELECT_ONE_WRITE
? &fdset
: NULL
,
260 rq
== SELECT_ONE_EXCEPT
? &fdset
: NULL
,
261 target_tv
? &tv
: NULL
);
262 regs
[3] = errno_h2g(errno
);
266 case TARGET_SYS_argc
:
271 case TARGET_SYS_argv_sz
:
276 case TARGET_SYS_argv
:
286 argv
.argptr
[0] = tswap32(regs
[3] + offsetof(struct Argv
, text
));
288 env
, regs
[3], (uint8_t *)&argv
, sizeof(argv
), 1);
292 case TARGET_SYS_memset
:
294 uint32_t base
= regs
[3];
295 uint32_t sz
= regs
[5];
298 target_phys_addr_t len
= sz
;
299 void *buf
= cpu_physical_memory_map(base
, &len
, 1);
302 memset(buf
, regs
[4], len
);
303 cpu_physical_memory_unmap(buf
, len
, 1, len
);
316 qemu_log("%s(%d): not implemented\n", __func__
, regs
[2]);
318 regs
[3] = TARGET_ENOSYS
;