]>
Commit | Line | Data |
---|---|---|
0a922181 RH |
1 | /* |
2 | * Helper routines to provide target memory access for semihosting | |
3 | * syscalls in system emulation mode. | |
4 | * | |
5 | * Copyright (c) 2007 CodeSourcery. | |
6 | * | |
7 | * This code is licensed under the GPL | |
8 | */ | |
9 | ||
10 | #include "qemu/osdep.h" | |
5f9ca6f3 | 11 | #include "exec/exec-all.h" |
0a922181 RH |
12 | #include "semihosting/softmmu-uaccess.h" |
13 | ||
14 | void *softmmu_lock_user(CPUArchState *env, target_ulong addr, | |
15 | target_ulong len, bool copy) | |
16 | { | |
17 | void *p = malloc(len); | |
18 | if (p && copy) { | |
19 | if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) { | |
20 | free(p); | |
21 | p = NULL; | |
22 | } | |
23 | } | |
24 | return p; | |
25 | } | |
26 | ||
5f9ca6f3 RH |
27 | ssize_t softmmu_strlen_user(CPUArchState *env, target_ulong addr) |
28 | { | |
29 | int mmu_idx = cpu_mmu_index(env, false); | |
30 | size_t len = 0; | |
31 | ||
32 | while (1) { | |
33 | size_t left_in_page; | |
34 | int flags; | |
35 | void *h; | |
36 | ||
37 | /* Find the number of bytes remaining in the page. */ | |
38 | left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK); | |
39 | ||
40 | flags = probe_access_flags(env, addr, MMU_DATA_LOAD, | |
41 | mmu_idx, true, &h, 0); | |
42 | if (flags & TLB_INVALID_MASK) { | |
43 | return -1; | |
44 | } | |
45 | if (flags & TLB_MMIO) { | |
46 | do { | |
47 | uint8_t c; | |
48 | if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) { | |
49 | return -1; | |
50 | } | |
51 | if (c == 0) { | |
52 | return len; | |
53 | } | |
54 | addr++; | |
55 | len++; | |
56 | if (len > INT32_MAX) { | |
57 | return -1; | |
58 | } | |
59 | } while (--left_in_page != 0); | |
60 | } else { | |
61 | char *p = memchr(h, 0, left_in_page); | |
62 | if (p) { | |
63 | len += p - (char *)h; | |
64 | return len <= INT32_MAX ? (ssize_t)len : -1; | |
65 | } | |
66 | addr += left_in_page; | |
67 | len += left_in_page; | |
68 | if (len > INT32_MAX) { | |
69 | return -1; | |
70 | } | |
71 | } | |
72 | } | |
73 | } | |
74 | ||
0a922181 RH |
75 | char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr) |
76 | { | |
3d5e2b4f RH |
77 | ssize_t len = softmmu_strlen_user(env, addr); |
78 | if (len < 0) { | |
0a922181 RH |
79 | return NULL; |
80 | } | |
3d5e2b4f | 81 | return softmmu_lock_user(env, addr, len + 1, true); |
0a922181 RH |
82 | } |
83 | ||
84 | void softmmu_unlock_user(CPUArchState *env, void *p, | |
85 | target_ulong addr, target_ulong len) | |
86 | { | |
87 | if (len) { | |
88 | cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1); | |
89 | } | |
90 | free(p); | |
91 | } |