]> git.proxmox.com Git - mirror_qemu.git/blame - target/m68k/m68k-semi.c
Merge tag 'ui-pull-request' of https://gitlab.com/marcandre.lureau/qemu into staging
[mirror_qemu.git] / target / m68k / m68k-semi.c
CommitLineData
a87295e8
PB
1/*
2 * m68k/ColdFire Semihosting syscall interface
5fafdf24 3 *
a87295e8
PB
4 * Copyright (c) 2005-2007 CodeSourcery.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program 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
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
8167ee88 17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
a87295e8
PB
18 */
19
d8416665 20#include "qemu/osdep.h"
a87295e8
PB
21
22#include "cpu.h"
c566080c 23#include "gdbstub/syscalls.h"
4ea5fe99 24#include "gdbstub/helpers.h"
95027250 25#include "semihosting/syscalls.h"
c89a14ad 26#include "semihosting/softmmu-uaccess.h"
5601d241 27#include "hw/boards.h"
63c91552 28#include "qemu/log.h"
a87295e8
PB
29
30#define HOSTED_EXIT 0
31#define HOSTED_INIT_SIM 1
32#define HOSTED_OPEN 2
33#define HOSTED_CLOSE 3
34#define HOSTED_READ 4
35#define HOSTED_WRITE 5
36#define HOSTED_LSEEK 6
37#define HOSTED_RENAME 7
38#define HOSTED_UNLINK 8
39#define HOSTED_STAT 9
40#define HOSTED_FSTAT 10
41#define HOSTED_GETTIMEOFDAY 11
42#define HOSTED_ISATTY 12
43#define HOSTED_SYSTEM 13
44
7327e602
RH
45static int host_to_gdb_errno(int err)
46{
47#define E(X) case E##X: return GDB_E##X
48 switch (err) {
49 E(PERM);
50 E(NOENT);
51 E(INTR);
52 E(BADF);
53 E(ACCES);
54 E(FAULT);
55 E(BUSY);
56 E(EXIST);
57 E(NODEV);
58 E(NOTDIR);
59 E(ISDIR);
60 E(INVAL);
61 E(NFILE);
62 E(MFILE);
63 E(FBIG);
64 E(NOSPC);
65 E(SPIPE);
66 E(ROFS);
67 E(NAMETOOLONG);
68 default:
69 return GDB_EUNKNOWN;
70 }
71#undef E
72}
73
ab294b6c 74static void m68k_semi_u32_cb(CPUState *cs, uint64_t ret, int err)
1073bfd8 75{
ab294b6c
RH
76 M68kCPU *cpu = M68K_CPU(cs);
77 CPUM68KState *env = &cpu->env;
78
1073bfd8
PM
79 target_ulong args = env->dregs[1];
80 if (put_user_u32(ret, args) ||
7327e602 81 put_user_u32(host_to_gdb_errno(err), args + 4)) {
808d77bc
LMP
82 /*
83 * The m68k semihosting ABI does not provide any way to report this
1073bfd8
PM
84 * error to the guest, so the best we can do is log it in qemu.
85 * It is always a guest error not to pass us a valid argument block.
86 */
87 qemu_log_mask(LOG_GUEST_ERROR, "m68k-semihosting: return value "
88 "discarded because argument block not writable\n");
89 }
90}
91
ab294b6c 92static void m68k_semi_u64_cb(CPUState *cs, uint64_t ret, int err)
1073bfd8 93{
ab294b6c
RH
94 M68kCPU *cpu = M68K_CPU(cs);
95 CPUM68KState *env = &cpu->env;
96
1073bfd8
PM
97 target_ulong args = env->dregs[1];
98 if (put_user_u32(ret >> 32, args) ||
99 put_user_u32(ret, args + 4) ||
7327e602 100 put_user_u32(host_to_gdb_errno(err), args + 8)) {
1073bfd8
PM
101 /* No way to report this via m68k semihosting ABI; just log it */
102 qemu_log_mask(LOG_GUEST_ERROR, "m68k-semihosting: return value "
103 "discarded because argument block not writable\n");
104 }
105}
106
808d77bc
LMP
107/*
108 * Read the input value from the argument block; fail the semihosting
7ba6c104
PM
109 * call if the memory read fails.
110 */
111#define GET_ARG(n) do { \
112 if (get_user_ual(arg ## n, args + (n) * 4)) { \
7ba6c104
PM
113 goto failed; \
114 } \
115} while (0)
116
95027250
RH
117#define GET_ARG64(n) do { \
118 if (get_user_ual(arg ## n, args + (n) * 4)) { \
119 goto failed64; \
120 } \
121} while (0)
122
123
a87295e8
PB
124void do_m68k_semihosting(CPUM68KState *env, int nr)
125{
ab294b6c 126 CPUState *cs = env_cpu(env);
a87295e8 127 uint32_t args;
7ba6c104 128 target_ulong arg0, arg1, arg2, arg3;
a87295e8
PB
129
130 args = env->dregs[1];
131 switch (nr) {
132 case HOSTED_EXIT:
ad9dcb20 133 gdb_exit(env->dregs[0]);
a87295e8 134 exit(env->dregs[0]);
95027250 135
a87295e8 136 case HOSTED_OPEN:
7ba6c104
PM
137 GET_ARG(0);
138 GET_ARG(1);
139 GET_ARG(2);
140 GET_ARG(3);
95027250 141 semihost_sys_open(cs, m68k_semi_u32_cb, arg0, arg1, arg2, arg3);
a87295e8 142 break;
95027250 143
a87295e8 144 case HOSTED_CLOSE:
95027250
RH
145 GET_ARG(0);
146 semihost_sys_close(cs, m68k_semi_u32_cb, arg0);
147 break;
148
a87295e8 149 case HOSTED_READ:
7ba6c104
PM
150 GET_ARG(0);
151 GET_ARG(1);
152 GET_ARG(2);
95027250 153 semihost_sys_read(cs, m68k_semi_u32_cb, arg0, arg1, arg2);
a87295e8 154 break;
95027250 155
a87295e8 156 case HOSTED_WRITE:
7ba6c104
PM
157 GET_ARG(0);
158 GET_ARG(1);
159 GET_ARG(2);
95027250 160 semihost_sys_write(cs, m68k_semi_u32_cb, arg0, arg1, arg2);
a87295e8 161 break;
95027250 162
a87295e8 163 case HOSTED_LSEEK:
95027250
RH
164 GET_ARG64(0);
165 GET_ARG64(1);
166 GET_ARG64(2);
167 GET_ARG64(3);
168 semihost_sys_lseek(cs, m68k_semi_u64_cb, arg0,
8caaae73 169 deposit64(arg2, 32, 32, arg1), arg3);
95027250
RH
170 break;
171
a87295e8 172 case HOSTED_RENAME:
7ba6c104
PM
173 GET_ARG(0);
174 GET_ARG(1);
175 GET_ARG(2);
176 GET_ARG(3);
95027250 177 semihost_sys_rename(cs, m68k_semi_u32_cb, arg0, arg1, arg2, arg3);
a87295e8 178 break;
95027250 179
a87295e8 180 case HOSTED_UNLINK:
7ba6c104
PM
181 GET_ARG(0);
182 GET_ARG(1);
95027250 183 semihost_sys_remove(cs, m68k_semi_u32_cb, arg0, arg1);
a87295e8 184 break;
95027250 185
a87295e8 186 case HOSTED_STAT:
7ba6c104
PM
187 GET_ARG(0);
188 GET_ARG(1);
189 GET_ARG(2);
95027250 190 semihost_sys_stat(cs, m68k_semi_u32_cb, arg0, arg1, arg2);
a87295e8 191 break;
95027250 192
a87295e8 193 case HOSTED_FSTAT:
7ba6c104
PM
194 GET_ARG(0);
195 GET_ARG(1);
95027250 196 semihost_sys_fstat(cs, m68k_semi_u32_cb, arg0, arg1);
a87295e8 197 break;
95027250 198
a87295e8 199 case HOSTED_GETTIMEOFDAY:
7ba6c104
PM
200 GET_ARG(0);
201 GET_ARG(1);
95027250 202 semihost_sys_gettimeofday(cs, m68k_semi_u32_cb, arg0, arg1);
a87295e8 203 break;
95027250 204
a87295e8 205 case HOSTED_ISATTY:
7ba6c104 206 GET_ARG(0);
95027250 207 semihost_sys_isatty(cs, m68k_semi_u32_cb, arg0);
a87295e8 208 break;
95027250 209
a87295e8 210 case HOSTED_SYSTEM:
7ba6c104
PM
211 GET_ARG(0);
212 GET_ARG(1);
95027250 213 semihost_sys_system(cs, m68k_semi_u32_cb, arg0, arg1);
a87295e8 214 break;
95027250 215
a87295e8 216 case HOSTED_INIT_SIM:
808d77bc
LMP
217 /*
218 * FIXME: This is wrong for boards where RAM does not start at
219 * address zero.
220 */
5601d241
PB
221 env->dregs[1] = current_machine->ram_size;
222 env->aregs[7] = current_machine->ram_size;
a87295e8 223 return;
95027250 224
a87295e8 225 default:
a8d92fd8 226 cpu_abort(env_cpu(env), "Unsupported semihosting syscall %d\n", nr);
95027250
RH
227
228 failed:
229 m68k_semi_u32_cb(cs, -1, EFAULT);
230 break;
231 failed64:
232 m68k_semi_u64_cb(cs, -1, EFAULT);
233 break;
a87295e8 234 }
a87295e8 235}