qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

uaccess.c (2393B)


      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"
     11 #include "exec/exec-all.h"
     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 
     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 
     75 char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
     76 {
     77     ssize_t len = softmmu_strlen_user(env, addr);
     78     if (len < 0) {
     79         return NULL;
     80     }
     81     return softmmu_lock_user(env, addr, len + 1, true);
     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 }