Statistics
| Branch: | Revision:

root / xtensa-semi.c @ 19ac36b5

History | View | Annotate | Download (6.7 kB)

1 1ddeaa5d Max Filippov
/*
2 1ddeaa5d Max Filippov
 * Copyright (c) 2011, Max Filippov, Open Source and Linux Lab.
3 1ddeaa5d Max Filippov
 * All rights reserved.
4 1ddeaa5d Max Filippov
 *
5 1ddeaa5d Max Filippov
 * Redistribution and use in source and binary forms, with or without
6 1ddeaa5d Max Filippov
 * modification, are permitted provided that the following conditions are met:
7 1ddeaa5d Max Filippov
 *     * Redistributions of source code must retain the above copyright
8 1ddeaa5d Max Filippov
 *       notice, this list of conditions and the following disclaimer.
9 1ddeaa5d Max Filippov
 *     * Redistributions in binary form must reproduce the above copyright
10 1ddeaa5d Max Filippov
 *       notice, this list of conditions and the following disclaimer in the
11 1ddeaa5d Max Filippov
 *       documentation and/or other materials provided with the distribution.
12 1ddeaa5d Max Filippov
 *     * Neither the name of the Open Source and Linux Lab nor the
13 1ddeaa5d Max Filippov
 *       names of its contributors may be used to endorse or promote products
14 1ddeaa5d Max Filippov
 *       derived from this software without specific prior written permission.
15 1ddeaa5d Max Filippov
 *
16 1ddeaa5d Max Filippov
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
17 1ddeaa5d Max Filippov
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 1ddeaa5d Max Filippov
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 1ddeaa5d Max Filippov
 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
20 1ddeaa5d Max Filippov
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 1ddeaa5d Max Filippov
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 1ddeaa5d Max Filippov
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 1ddeaa5d Max Filippov
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 1ddeaa5d Max Filippov
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 1ddeaa5d Max Filippov
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 1ddeaa5d Max Filippov
 */
27 1ddeaa5d Max Filippov
28 1ddeaa5d Max Filippov
#include <errno.h>
29 1ddeaa5d Max Filippov
#include <unistd.h>
30 1ddeaa5d Max Filippov
#include <string.h>
31 1ddeaa5d Max Filippov
#include <stddef.h>
32 1ddeaa5d Max Filippov
#include "cpu.h"
33 1ddeaa5d Max Filippov
#include "dyngen-exec.h"
34 16c1deae Lluís Vilanova
#include "helper.h"
35 1ddeaa5d Max Filippov
#include "qemu-log.h"
36 1ddeaa5d Max Filippov
37 1ddeaa5d Max Filippov
enum {
38 1ddeaa5d Max Filippov
    TARGET_SYS_exit = 1,
39 1ddeaa5d Max Filippov
    TARGET_SYS_read = 3,
40 1ddeaa5d Max Filippov
    TARGET_SYS_write = 4,
41 1ddeaa5d Max Filippov
    TARGET_SYS_open = 5,
42 1ddeaa5d Max Filippov
    TARGET_SYS_close = 6,
43 1ddeaa5d Max Filippov
    TARGET_SYS_lseek = 19,
44 1ddeaa5d Max Filippov
    TARGET_SYS_select_one = 29,
45 1ddeaa5d Max Filippov
46 1ddeaa5d Max Filippov
    TARGET_SYS_argc = 1000,
47 1ddeaa5d Max Filippov
    TARGET_SYS_argv_sz = 1001,
48 1ddeaa5d Max Filippov
    TARGET_SYS_argv = 1002,
49 1ddeaa5d Max Filippov
    TARGET_SYS_memset = 1004,
50 1ddeaa5d Max Filippov
};
51 1ddeaa5d Max Filippov
52 1ddeaa5d Max Filippov
enum {
53 1ddeaa5d Max Filippov
    SELECT_ONE_READ   = 1,
54 1ddeaa5d Max Filippov
    SELECT_ONE_WRITE  = 2,
55 1ddeaa5d Max Filippov
    SELECT_ONE_EXCEPT = 3,
56 1ddeaa5d Max Filippov
};
57 1ddeaa5d Max Filippov
58 d4a5b622 Andreas Färber
void HELPER(simcall)(CPUXtensaState *env)
59 1ddeaa5d Max Filippov
{
60 1ddeaa5d Max Filippov
    uint32_t *regs = env->regs;
61 1ddeaa5d Max Filippov
62 1ddeaa5d Max Filippov
    switch (regs[2]) {
63 1ddeaa5d Max Filippov
    case TARGET_SYS_exit:
64 1ddeaa5d Max Filippov
        qemu_log("exit(%d) simcall\n", regs[3]);
65 1ddeaa5d Max Filippov
        exit(regs[3]);
66 1ddeaa5d Max Filippov
        break;
67 1ddeaa5d Max Filippov
68 1ddeaa5d Max Filippov
    case TARGET_SYS_read:
69 1ddeaa5d Max Filippov
    case TARGET_SYS_write:
70 1ddeaa5d Max Filippov
        {
71 1ddeaa5d Max Filippov
            bool is_write = regs[2] == TARGET_SYS_write;
72 1ddeaa5d Max Filippov
            uint32_t fd = regs[3];
73 1ddeaa5d Max Filippov
            uint32_t vaddr = regs[4];
74 1ddeaa5d Max Filippov
            uint32_t len = regs[5];
75 1ddeaa5d Max Filippov
76 1ddeaa5d Max Filippov
            while (len > 0) {
77 1ddeaa5d Max Filippov
                target_phys_addr_t paddr =
78 1ddeaa5d Max Filippov
                    cpu_get_phys_page_debug(env, vaddr);
79 1ddeaa5d Max Filippov
                uint32_t page_left =
80 1ddeaa5d Max Filippov
                    TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
81 1ddeaa5d Max Filippov
                uint32_t io_sz = page_left < len ? page_left : len;
82 1ddeaa5d Max Filippov
                target_phys_addr_t sz = io_sz;
83 1ddeaa5d Max Filippov
                void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
84 1ddeaa5d Max Filippov
85 1ddeaa5d Max Filippov
                if (buf) {
86 1ddeaa5d Max Filippov
                    vaddr += io_sz;
87 1ddeaa5d Max Filippov
                    len -= io_sz;
88 1ddeaa5d Max Filippov
                    regs[2] = is_write ?
89 1ddeaa5d Max Filippov
                        write(fd, buf, io_sz) :
90 1ddeaa5d Max Filippov
                        read(fd, buf, io_sz);
91 1ddeaa5d Max Filippov
                    regs[3] = errno;
92 1ddeaa5d Max Filippov
                    cpu_physical_memory_unmap(buf, sz, is_write, sz);
93 1ddeaa5d Max Filippov
                    if (regs[2] == -1) {
94 1ddeaa5d Max Filippov
                        break;
95 1ddeaa5d Max Filippov
                    }
96 1ddeaa5d Max Filippov
                } else {
97 1ddeaa5d Max Filippov
                    regs[2] = -1;
98 1ddeaa5d Max Filippov
                    regs[3] = EINVAL;
99 1ddeaa5d Max Filippov
                    break;
100 1ddeaa5d Max Filippov
                }
101 1ddeaa5d Max Filippov
            }
102 1ddeaa5d Max Filippov
        }
103 1ddeaa5d Max Filippov
        break;
104 1ddeaa5d Max Filippov
105 1ddeaa5d Max Filippov
    case TARGET_SYS_open:
106 1ddeaa5d Max Filippov
        {
107 1ddeaa5d Max Filippov
            char name[1024];
108 1ddeaa5d Max Filippov
            int rc;
109 1ddeaa5d Max Filippov
            int i;
110 1ddeaa5d Max Filippov
111 1ddeaa5d Max Filippov
            for (i = 0; i < ARRAY_SIZE(name); ++i) {
112 1ddeaa5d Max Filippov
                rc = cpu_memory_rw_debug(
113 1ddeaa5d Max Filippov
                        env, regs[3] + i, (uint8_t *)name + i, 1, 0);
114 1ddeaa5d Max Filippov
                if (rc != 0 || name[i] == 0) {
115 1ddeaa5d Max Filippov
                    break;
116 1ddeaa5d Max Filippov
                }
117 1ddeaa5d Max Filippov
            }
118 1ddeaa5d Max Filippov
119 1ddeaa5d Max Filippov
            if (rc == 0 && i < ARRAY_SIZE(name)) {
120 1ddeaa5d Max Filippov
                regs[2] = open(name, regs[4], regs[5]);
121 1ddeaa5d Max Filippov
                regs[3] = errno;
122 1ddeaa5d Max Filippov
            } else {
123 1ddeaa5d Max Filippov
                regs[2] = -1;
124 1ddeaa5d Max Filippov
                regs[3] = EINVAL;
125 1ddeaa5d Max Filippov
            }
126 1ddeaa5d Max Filippov
        }
127 1ddeaa5d Max Filippov
        break;
128 1ddeaa5d Max Filippov
129 1ddeaa5d Max Filippov
    case TARGET_SYS_close:
130 1ddeaa5d Max Filippov
        if (regs[3] < 3) {
131 1ddeaa5d Max Filippov
            regs[2] = regs[3] = 0;
132 1ddeaa5d Max Filippov
        } else {
133 1ddeaa5d Max Filippov
            regs[2] = close(regs[3]);
134 1ddeaa5d Max Filippov
            regs[3] = errno;
135 1ddeaa5d Max Filippov
        }
136 1ddeaa5d Max Filippov
        break;
137 1ddeaa5d Max Filippov
138 1ddeaa5d Max Filippov
    case TARGET_SYS_lseek:
139 1ddeaa5d Max Filippov
        regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
140 1ddeaa5d Max Filippov
        regs[3] = errno;
141 1ddeaa5d Max Filippov
        break;
142 1ddeaa5d Max Filippov
143 1ddeaa5d Max Filippov
    case TARGET_SYS_select_one:
144 1ddeaa5d Max Filippov
        {
145 1ddeaa5d Max Filippov
            uint32_t fd = regs[3];
146 1ddeaa5d Max Filippov
            uint32_t rq = regs[4];
147 1ddeaa5d Max Filippov
            uint32_t target_tv = regs[5];
148 1ddeaa5d Max Filippov
            uint32_t target_tvv[2];
149 1ddeaa5d Max Filippov
150 1ddeaa5d Max Filippov
            struct timeval tv = {0};
151 1ddeaa5d Max Filippov
            fd_set fdset;
152 1ddeaa5d Max Filippov
153 1ddeaa5d Max Filippov
            FD_ZERO(&fdset);
154 1ddeaa5d Max Filippov
            FD_SET(fd, &fdset);
155 1ddeaa5d Max Filippov
156 1ddeaa5d Max Filippov
            if (target_tv) {
157 1ddeaa5d Max Filippov
                cpu_memory_rw_debug(env, target_tv,
158 1ddeaa5d Max Filippov
                        (uint8_t *)target_tvv, sizeof(target_tvv), 0);
159 1ddeaa5d Max Filippov
                tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
160 1ddeaa5d Max Filippov
                tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
161 1ddeaa5d Max Filippov
            }
162 1ddeaa5d Max Filippov
            regs[2] = select(fd + 1,
163 1ddeaa5d Max Filippov
                    rq == SELECT_ONE_READ   ? &fdset : NULL,
164 1ddeaa5d Max Filippov
                    rq == SELECT_ONE_WRITE  ? &fdset : NULL,
165 1ddeaa5d Max Filippov
                    rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
166 1ddeaa5d Max Filippov
                    target_tv ? &tv : NULL);
167 1ddeaa5d Max Filippov
            regs[3] = errno;
168 1ddeaa5d Max Filippov
        }
169 1ddeaa5d Max Filippov
        break;
170 1ddeaa5d Max Filippov
171 1ddeaa5d Max Filippov
    case TARGET_SYS_argc:
172 1ddeaa5d Max Filippov
        regs[2] = 1;
173 1ddeaa5d Max Filippov
        regs[3] = 0;
174 1ddeaa5d Max Filippov
        break;
175 1ddeaa5d Max Filippov
176 1ddeaa5d Max Filippov
    case TARGET_SYS_argv_sz:
177 1ddeaa5d Max Filippov
        regs[2] = 128;
178 1ddeaa5d Max Filippov
        regs[3] = 0;
179 1ddeaa5d Max Filippov
        break;
180 1ddeaa5d Max Filippov
181 1ddeaa5d Max Filippov
    case TARGET_SYS_argv:
182 1ddeaa5d Max Filippov
        {
183 1ddeaa5d Max Filippov
            struct Argv {
184 1ddeaa5d Max Filippov
                uint32_t argptr[2];
185 1ddeaa5d Max Filippov
                char text[120];
186 1ddeaa5d Max Filippov
            } argv = {
187 1ddeaa5d Max Filippov
                {0, 0},
188 1ddeaa5d Max Filippov
                "test"
189 1ddeaa5d Max Filippov
            };
190 1ddeaa5d Max Filippov
191 1ddeaa5d Max Filippov
            argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
192 1ddeaa5d Max Filippov
            cpu_memory_rw_debug(
193 1ddeaa5d Max Filippov
                    env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
194 1ddeaa5d Max Filippov
        }
195 1ddeaa5d Max Filippov
        break;
196 1ddeaa5d Max Filippov
197 1ddeaa5d Max Filippov
    case TARGET_SYS_memset:
198 1ddeaa5d Max Filippov
        {
199 1ddeaa5d Max Filippov
            uint32_t base = regs[3];
200 1ddeaa5d Max Filippov
            uint32_t sz = regs[5];
201 1ddeaa5d Max Filippov
202 1ddeaa5d Max Filippov
            while (sz) {
203 1ddeaa5d Max Filippov
                target_phys_addr_t len = sz;
204 1ddeaa5d Max Filippov
                void *buf = cpu_physical_memory_map(base, &len, 1);
205 1ddeaa5d Max Filippov
206 1ddeaa5d Max Filippov
                if (buf && len) {
207 1ddeaa5d Max Filippov
                    memset(buf, regs[4], len);
208 1ddeaa5d Max Filippov
                    cpu_physical_memory_unmap(buf, len, 1, len);
209 1ddeaa5d Max Filippov
                } else {
210 1ddeaa5d Max Filippov
                    len = 1;
211 1ddeaa5d Max Filippov
                }
212 1ddeaa5d Max Filippov
                base += len;
213 1ddeaa5d Max Filippov
                sz -= len;
214 1ddeaa5d Max Filippov
            }
215 1ddeaa5d Max Filippov
            regs[2] = regs[3];
216 1ddeaa5d Max Filippov
            regs[3] = 0;
217 1ddeaa5d Max Filippov
        }
218 1ddeaa5d Max Filippov
        break;
219 1ddeaa5d Max Filippov
220 1ddeaa5d Max Filippov
    default:
221 1ddeaa5d Max Filippov
        qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
222 1ddeaa5d Max Filippov
        break;
223 1ddeaa5d Max Filippov
    }
224 1ddeaa5d Max Filippov
}