]>
git.proxmox.com Git - mirror_qemu.git/blob - target/mips/tcg/sysemu/mips-semi.c
f3735df7b9edbc01c57c459a0d79ee1cd937e797
2 * Unified Hosting Interface syscalls.
4 * Copyright (c) 2015 Imagination Technologies
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #include "qemu/osdep.h"
23 #include "gdbstub/syscalls.h"
24 #include "gdbstub/helpers.h"
25 #include "semihosting/softmmu-uaccess.h"
26 #include "semihosting/semihost.h"
27 #include "semihosting/console.h"
28 #include "semihosting/syscalls.h"
50 typedef struct UHIStat
{
54 uint16_t uhi_st_nlink
;
59 uint64_t uhi_st_atime
;
60 uint64_t uhi_st_spare1
;
61 uint64_t uhi_st_mtime
;
62 uint64_t uhi_st_spare2
;
63 uint64_t uhi_st_ctime
;
64 uint64_t uhi_st_spare3
;
65 uint64_t uhi_st_blksize
;
66 uint64_t uhi_st_blocks
;
67 uint64_t uhi_st_spare4
[2];
75 UHIOpen_CREAT
= 0x200,
76 UHIOpen_TRUNC
= 0x400,
96 UHI_ENAMETOOLONG
= 91,
98 UHI_ENETUNREACH
= 114,
116 UHI_EWOULDBLOCK
= 11,
120 static void report_fault(CPUMIPSState
*env
)
122 int op
= env
->active_tc
.gpr
[25];
123 error_report("Fault during UHI operation %d", op
);
127 static void uhi_cb(CPUState
*cs
, uint64_t ret
, int err
)
129 CPUMIPSState
*env
= cs
->env_ptr
;
131 #define E(N) case E##N: err = UHI_E##N; break
161 env
->active_tc
.gpr
[2] = ret
;
162 env
->active_tc
.gpr
[3] = err
;
165 static void uhi_fstat_cb(CPUState
*cs
, uint64_t ret
, int err
)
167 QEMU_BUILD_BUG_ON(sizeof(UHIStat
) < sizeof(struct gdb_stat
));
170 CPUMIPSState
*env
= cs
->env_ptr
;
171 target_ulong addr
= env
->active_tc
.gpr
[5];
172 UHIStat
*dst
= lock_user(VERIFY_WRITE
, addr
, sizeof(UHIStat
), 1);
179 memcpy(&s
, dst
, sizeof(struct gdb_stat
));
180 memset(dst
, 0, sizeof(UHIStat
));
182 dst
->uhi_st_dev
= tswap16(be32_to_cpu(s
.gdb_st_dev
));
183 dst
->uhi_st_ino
= tswap16(be32_to_cpu(s
.gdb_st_ino
));
184 dst
->uhi_st_mode
= tswap32(be32_to_cpu(s
.gdb_st_mode
));
185 dst
->uhi_st_nlink
= tswap16(be32_to_cpu(s
.gdb_st_nlink
));
186 dst
->uhi_st_uid
= tswap16(be32_to_cpu(s
.gdb_st_uid
));
187 dst
->uhi_st_gid
= tswap16(be32_to_cpu(s
.gdb_st_gid
));
188 dst
->uhi_st_rdev
= tswap16(be32_to_cpu(s
.gdb_st_rdev
));
189 dst
->uhi_st_size
= tswap64(be64_to_cpu(s
.gdb_st_size
));
190 dst
->uhi_st_atime
= tswap64(be32_to_cpu(s
.gdb_st_atime
));
191 dst
->uhi_st_mtime
= tswap64(be32_to_cpu(s
.gdb_st_mtime
));
192 dst
->uhi_st_ctime
= tswap64(be32_to_cpu(s
.gdb_st_ctime
));
193 dst
->uhi_st_blksize
= tswap64(be64_to_cpu(s
.gdb_st_blksize
));
194 dst
->uhi_st_blocks
= tswap64(be64_to_cpu(s
.gdb_st_blocks
));
196 unlock_user(dst
, addr
, sizeof(UHIStat
));
199 uhi_cb(cs
, ret
, err
);
202 void mips_semihosting(CPUMIPSState
*env
)
204 CPUState
*cs
= env_cpu(env
);
205 target_ulong
*gpr
= env
->active_tc
.gpr
;
206 const UHIOp op
= gpr
[25];
216 target_ulong fname
= gpr
[4];
219 p
= lock_user_string(fname
);
223 if (!strcmp("/dev/stdin", p
)) {
225 } else if (!strcmp("/dev/stdout", p
)) {
227 } else if (!strcmp("/dev/stderr", p
)) {
230 unlock_user(p
, fname
, 0);
232 /* FIXME: reusing a guest fd doesn't seem correct. */
238 semihost_sys_open(cs
, uhi_cb
, fname
, 0, gpr
[5], gpr
[6]);
243 semihost_sys_close(cs
, uhi_cb
, gpr
[4]);
246 semihost_sys_read(cs
, uhi_cb
, gpr
[4], gpr
[5], gpr
[6]);
249 semihost_sys_write(cs
, uhi_cb
, gpr
[4], gpr
[5], gpr
[6]);
252 semihost_sys_lseek(cs
, uhi_cb
, gpr
[4], gpr
[5], gpr
[6]);
255 semihost_sys_remove(cs
, uhi_cb
, gpr
[4], 0);
258 semihost_sys_fstat(cs
, uhi_fstat_cb
, gpr
[4], gpr
[5]);
262 gpr
[2] = semihosting_get_argc();
266 const char *s
= semihosting_get_arg(gpr
[4]);
267 gpr
[2] = s
? strlen(s
) : -1;
272 const char *s
= semihosting_get_arg(gpr
[4]);
282 p
= lock_user(VERIFY_WRITE
, addr
, len
, 0);
287 unlock_user(p
, addr
, len
);
294 target_ulong addr
= gpr
[4];
295 ssize_t len
= target_strlen(addr
);
302 p
= lock_user(VERIFY_READ
, addr
, len
, 1);
307 pct_d
= strstr(p
, "%d");
309 unlock_user(p
, addr
, 0);
310 semihost_sys_write(cs
, uhi_cb
, 2, addr
, len
);
314 str
= g_string_new_len(p
, pct_d
- p
);
315 g_string_append_printf(str
, "%d%s", (int)gpr
[5], pct_d
+ 2);
316 unlock_user(p
, addr
, 0);
319 * When we're using gdb, we need a guest address, so
320 * drop the string onto the stack below the stack pointer.
322 if (use_gdb_syscalls()) {
323 addr
= gpr
[29] - str
->len
;
324 p
= lock_user(VERIFY_WRITE
, addr
, str
->len
, 0);
328 memcpy(p
, str
->str
, str
->len
);
329 unlock_user(p
, addr
, str
->len
);
330 semihost_sys_write(cs
, uhi_cb
, 2, addr
, str
->len
);
332 gpr
[2] = qemu_semihosting_console_write(str
->str
, str
->len
);
334 g_string_free(str
, true);
340 const char *msg
, *file
;
342 msg
= lock_user_string(gpr
[4]);
346 file
= lock_user_string(gpr
[5]);
351 error_report("UHI assertion \"%s\": file \"%s\", line %d",
352 msg
, file
, (int)gpr
[6]);
357 error_report("Unknown UHI operation %d", op
);