File:  [Qemu by Fabrice Bellard] / qemu / xtensa-semi.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 19:17:18 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, HEAD
qemu 1.0.1

    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 "dyngen-exec.h"
   34: #include "helpers.h"
   35: #include "qemu-log.h"
   36: 
   37: enum {
   38:     TARGET_SYS_exit = 1,
   39:     TARGET_SYS_read = 3,
   40:     TARGET_SYS_write = 4,
   41:     TARGET_SYS_open = 5,
   42:     TARGET_SYS_close = 6,
   43:     TARGET_SYS_lseek = 19,
   44:     TARGET_SYS_select_one = 29,
   45: 
   46:     TARGET_SYS_argc = 1000,
   47:     TARGET_SYS_argv_sz = 1001,
   48:     TARGET_SYS_argv = 1002,
   49:     TARGET_SYS_memset = 1004,
   50: };
   51: 
   52: enum {
   53:     SELECT_ONE_READ   = 1,
   54:     SELECT_ONE_WRITE  = 2,
   55:     SELECT_ONE_EXCEPT = 3,
   56: };
   57: 
   58: void HELPER(simcall)(CPUState *env)
   59: {
   60:     uint32_t *regs = env->regs;
   61: 
   62:     switch (regs[2]) {
   63:     case TARGET_SYS_exit:
   64:         qemu_log("exit(%d) simcall\n", regs[3]);
   65:         exit(regs[3]);
   66:         break;
   67: 
   68:     case TARGET_SYS_read:
   69:     case TARGET_SYS_write:
   70:         {
   71:             bool is_write = regs[2] == TARGET_SYS_write;
   72:             uint32_t fd = regs[3];
   73:             uint32_t vaddr = regs[4];
   74:             uint32_t len = regs[5];
   75: 
   76:             while (len > 0) {
   77:                 target_phys_addr_t paddr =
   78:                     cpu_get_phys_page_debug(env, vaddr);
   79:                 uint32_t page_left =
   80:                     TARGET_PAGE_SIZE - (vaddr & (TARGET_PAGE_SIZE - 1));
   81:                 uint32_t io_sz = page_left < len ? page_left : len;
   82:                 target_phys_addr_t sz = io_sz;
   83:                 void *buf = cpu_physical_memory_map(paddr, &sz, is_write);
   84: 
   85:                 if (buf) {
   86:                     vaddr += io_sz;
   87:                     len -= io_sz;
   88:                     regs[2] = is_write ?
   89:                         write(fd, buf, io_sz) :
   90:                         read(fd, buf, io_sz);
   91:                     regs[3] = errno;
   92:                     cpu_physical_memory_unmap(buf, sz, is_write, sz);
   93:                     if (regs[2] == -1) {
   94:                         break;
   95:                     }
   96:                 } else {
   97:                     regs[2] = -1;
   98:                     regs[3] = EINVAL;
   99:                     break;
  100:                 }
  101:             }
  102:         }
  103:         break;
  104: 
  105:     case TARGET_SYS_open:
  106:         {
  107:             char name[1024];
  108:             int rc;
  109:             int i;
  110: 
  111:             for (i = 0; i < ARRAY_SIZE(name); ++i) {
  112:                 rc = cpu_memory_rw_debug(
  113:                         env, regs[3] + i, (uint8_t *)name + i, 1, 0);
  114:                 if (rc != 0 || name[i] == 0) {
  115:                     break;
  116:                 }
  117:             }
  118: 
  119:             if (rc == 0 && i < ARRAY_SIZE(name)) {
  120:                 regs[2] = open(name, regs[4], regs[5]);
  121:                 regs[3] = errno;
  122:             } else {
  123:                 regs[2] = -1;
  124:                 regs[3] = EINVAL;
  125:             }
  126:         }
  127:         break;
  128: 
  129:     case TARGET_SYS_close:
  130:         if (regs[3] < 3) {
  131:             regs[2] = regs[3] = 0;
  132:         } else {
  133:             regs[2] = close(regs[3]);
  134:             regs[3] = errno;
  135:         }
  136:         break;
  137: 
  138:     case TARGET_SYS_lseek:
  139:         regs[2] = lseek(regs[3], (off_t)(int32_t)regs[4], regs[5]);
  140:         regs[3] = errno;
  141:         break;
  142: 
  143:     case TARGET_SYS_select_one:
  144:         {
  145:             uint32_t fd = regs[3];
  146:             uint32_t rq = regs[4];
  147:             uint32_t target_tv = regs[5];
  148:             uint32_t target_tvv[2];
  149: 
  150:             struct timeval tv = {0};
  151:             fd_set fdset;
  152: 
  153:             FD_ZERO(&fdset);
  154:             FD_SET(fd, &fdset);
  155: 
  156:             if (target_tv) {
  157:                 cpu_memory_rw_debug(env, target_tv,
  158:                         (uint8_t *)target_tvv, sizeof(target_tvv), 0);
  159:                 tv.tv_sec = (int32_t)tswap32(target_tvv[0]);
  160:                 tv.tv_usec = (int32_t)tswap32(target_tvv[1]);
  161:             }
  162:             regs[2] = select(fd + 1,
  163:                     rq == SELECT_ONE_READ   ? &fdset : NULL,
  164:                     rq == SELECT_ONE_WRITE  ? &fdset : NULL,
  165:                     rq == SELECT_ONE_EXCEPT ? &fdset : NULL,
  166:                     target_tv ? &tv : NULL);
  167:             regs[3] = errno;
  168:         }
  169:         break;
  170: 
  171:     case TARGET_SYS_argc:
  172:         regs[2] = 1;
  173:         regs[3] = 0;
  174:         break;
  175: 
  176:     case TARGET_SYS_argv_sz:
  177:         regs[2] = 128;
  178:         regs[3] = 0;
  179:         break;
  180: 
  181:     case TARGET_SYS_argv:
  182:         {
  183:             struct Argv {
  184:                 uint32_t argptr[2];
  185:                 char text[120];
  186:             } argv = {
  187:                 {0, 0},
  188:                 "test"
  189:             };
  190: 
  191:             argv.argptr[0] = tswap32(regs[3] + offsetof(struct Argv, text));
  192:             cpu_memory_rw_debug(
  193:                     env, regs[3], (uint8_t *)&argv, sizeof(argv), 1);
  194:         }
  195:         break;
  196: 
  197:     case TARGET_SYS_memset:
  198:         {
  199:             uint32_t base = regs[3];
  200:             uint32_t sz = regs[5];
  201: 
  202:             while (sz) {
  203:                 target_phys_addr_t len = sz;
  204:                 void *buf = cpu_physical_memory_map(base, &len, 1);
  205: 
  206:                 if (buf && len) {
  207:                     memset(buf, regs[4], len);
  208:                     cpu_physical_memory_unmap(buf, len, 1, len);
  209:                 } else {
  210:                     len = 1;
  211:                 }
  212:                 base += len;
  213:                 sz -= len;
  214:             }
  215:             regs[2] = regs[3];
  216:             regs[3] = 0;
  217:         }
  218:         break;
  219: 
  220:     default:
  221:         qemu_log("%s(%d): not implemented\n", __func__, regs[2]);
  222:         break;
  223:     }
  224: }

unix.superglobalmegacorp.com