aboutsummaryrefslogtreecommitdiff
path: root/linux-user/qemu.h
blob: c176a58aa46fe52ade5ad6523062446da1db7d86 (plain)
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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#ifndef QEMU_H
#define QEMU_H

#include "thunk.h"

#include <signal.h>
#include <string.h>
#include "syscall_defs.h"

#include "cpu.h"
#include "syscall.h"

/* This struct is used to hold certain information about the image.
 * Basically, it replicates in user space what would be certain
 * task_struct fields in the kernel
 */
struct image_info {
	unsigned long	start_code;
	unsigned long	end_code;
	unsigned long	end_data;
	unsigned long	start_brk;
	unsigned long	brk;
	unsigned long	start_mmap;
	unsigned long	mmap;
	unsigned long	rss;
	unsigned long	start_stack;
	unsigned long	arg_start;
	unsigned long	arg_end;
	unsigned long	env_start;
	unsigned long	env_end;
	unsigned long	entry;
	int		personality;
};

#ifdef TARGET_I386
/* Information about the current linux thread */
struct vm86_saved_state {
    uint32_t eax; /* return code */
    uint32_t ebx;
    uint32_t ecx;
    uint32_t edx;
    uint32_t esi;
    uint32_t edi;
    uint32_t ebp;
    uint32_t esp;
    uint32_t eflags;
    uint32_t eip;
    uint16_t cs, ss, ds, es, fs, gs;
};
#endif

#ifdef TARGET_ARM
/* FPU emulator */
#include "nwfpe/fpa11.h"
#endif

/* NOTE: we force a big alignment so that the stack stored after is
   aligned too */
typedef struct TaskState {
    struct TaskState *next;
#ifdef TARGET_ARM
    /* FPA state */
    FPA11 fpa;
#endif
#ifdef TARGET_I386
    struct target_vm86plus_struct *target_v86;
    struct vm86_saved_state vm86_saved_regs;
    struct target_vm86plus_struct vm86plus;
    uint32_t v86flags;
    uint32_t v86mask;
#endif
    int used; /* non zero if used */
    uint8_t stack[0];
} __attribute__((aligned(16))) TaskState;

extern TaskState *first_task_state;

int elf_exec(const char * filename, char ** argv, char ** envp, 
             struct target_pt_regs * regs, struct image_info *infop);

void target_set_brk(char *new_brk);
void syscall_init(void);
long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, 
                long arg4, long arg5, long arg6);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
extern CPUState *global_env;
void cpu_loop(CPUState *env);
void init_paths(const char *prefix);
const char *path(const char *pathname);

extern int loglevel;
extern FILE *logfile;

/* signal.c */
void process_pending_signals(void *cpu_env);
void signal_init(void);
int queue_signal(int sig, target_siginfo_t *info);
void host_to_target_siginfo(target_siginfo_t *tinfo, const siginfo_t *info);
void target_to_host_siginfo(siginfo_t *info, const target_siginfo_t *tinfo);
long do_sigreturn(CPUState *env);
long do_rt_sigreturn(CPUState *env);

#ifdef TARGET_I386
/* vm86.c */
void save_v86_state(CPUX86State *env);
void handle_vm86_trap(CPUX86State *env, int trapno);
void handle_vm86_fault(CPUX86State *env);
int do_vm86(CPUX86State *env, long subfunction, 
            struct target_vm86plus_struct * target_v86);
#endif

/* mmap.c */
int target_mprotect(unsigned long start, unsigned long len, int prot);
long target_mmap(unsigned long start, unsigned long len, int prot, 
                 int flags, int fd, unsigned long offset);
int target_munmap(unsigned long start, unsigned long len);
long target_mremap(unsigned long old_addr, unsigned long old_size, 
                   unsigned long new_size, unsigned long flags,
                   unsigned long new_addr);
int target_msync(unsigned long start, unsigned long len, int flags);

/* user access */

#define VERIFY_READ 0
#define VERIFY_WRITE 1

#define access_ok(type,addr,size) (1)

#define __put_user(x,ptr)\
({\
    int size = sizeof(*ptr);\
    switch(size) {\
    case 1:\
        stb(ptr, (typeof(*ptr))(x));\
        break;\
    case 2:\
        stw(ptr, (typeof(*ptr))(x));\
        break;\
    case 4:\
        stl(ptr, (typeof(*ptr))(x));\
        break;\
    case 8:\
        stq(ptr, (typeof(*ptr))(x));\
        break;\
    default:\
        abort();\
    }\
    0;\
})

#define __get_user(x, ptr) \
({\
    int size = sizeof(*ptr);\
    switch(size) {\
    case 1:\
        x = (typeof(*ptr))ldub((void *)ptr);\
        break;\
    case 2:\
        x = (typeof(*ptr))lduw((void *)ptr);\
        break;\
    case 4:\
        x = (typeof(*ptr))ldl((void *)ptr);\
        break;\
    case 8:\
        x = (typeof(*ptr))ldq((void *)ptr);\
        break;\
    default:\
        abort();\
    }\
    0;\
})

static inline unsigned long __copy_to_user(void *dst, const void *src, 
                                           unsigned long size)
{
    memcpy(dst, src, size);
    return 0;
}

static inline unsigned long __copy_from_user(void *dst, const void *src, 
                                             unsigned long size)
{
    memcpy(dst, src, size);
    return 0;
}

static inline unsigned long __clear_user(void *dst, unsigned long size)
{
    memset(dst, 0, size);
    return 0;
}

#define put_user(x,ptr)\
({\
    int __ret;\
    if (access_ok(VERIFY_WRITE, ptr, sizeof(*ptr)))\
        __ret = __put_user(x, ptr);\
    else\
        __ret = -EFAULT;\
    __ret;\
})

#define get_user(x,ptr)\
({\
    int __ret;\
    if (access_ok(VERIFY_READ, ptr, sizeof(*ptr)))\
        __ret = __get_user(x, ptr);\
    else\
        __ret = -EFAULT;\
    __ret;\
})

static inline unsigned long copy_to_user(void *dst, const void *src, 
                                         unsigned long size)
{
    if (access_ok(VERIFY_WRITE, dst, size))
        return __copy_to_user(dst, src, size);
    else
        return size;
}

static inline unsigned long copy_from_user(void *dst, const void *src, 
                                             unsigned long size)
{
    if (access_ok(VERIFY_READ, src, size))
        return __copy_from_user(dst, src, size);
    else
        return size;
}

static inline unsigned long clear_user(void *dst, unsigned long size)
{
    if (access_ok(VERIFY_WRITE, dst, size))
        return __clear_user(dst, size);
    else
        return size;
}

#endif /* QEMU_H */