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