 f14eced5ac
			
		
	
	
		f14eced5ac
		
	
	
	
	
		
			
			Add a check in 'softmmu-uaccess.h' that the header is only include in system emulation, and rename it as 'uaccess.h'. Rename the API methods: - softmmu_[un]lock_user*() -> uaccess_[un]lock_user*() - softmmu_strlen_user() -> uaccess_strlen_user(). Update a pair of comments. Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org> Message-ID: <20231004090629.37473-9-philmd@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
		
			
				
	
	
		
			92 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			92 lines
		
	
	
		
			2.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * Helper routines to provide target memory access for semihosting
 | |
|  * syscalls in system emulation mode.
 | |
|  *
 | |
|  * Copyright (c) 2007 CodeSourcery.
 | |
|  *
 | |
|  * This code is licensed under the GPL
 | |
|  */
 | |
| 
 | |
| #include "qemu/osdep.h"
 | |
| #include "exec/exec-all.h"
 | |
| #include "semihosting/uaccess.h"
 | |
| 
 | |
| void *uaccess_lock_user(CPUArchState *env, target_ulong addr,
 | |
|                         target_ulong len, bool copy)
 | |
| {
 | |
|     void *p = malloc(len);
 | |
|     if (p && copy) {
 | |
|         if (cpu_memory_rw_debug(env_cpu(env), addr, p, len, 0)) {
 | |
|             free(p);
 | |
|             p = NULL;
 | |
|         }
 | |
|     }
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| ssize_t uaccess_strlen_user(CPUArchState *env, target_ulong addr)
 | |
| {
 | |
|     int mmu_idx = cpu_mmu_index(env, false);
 | |
|     size_t len = 0;
 | |
| 
 | |
|     while (1) {
 | |
|         size_t left_in_page;
 | |
|         int flags;
 | |
|         void *h;
 | |
| 
 | |
|         /* Find the number of bytes remaining in the page. */
 | |
|         left_in_page = TARGET_PAGE_SIZE - (addr & ~TARGET_PAGE_MASK);
 | |
| 
 | |
|         flags = probe_access_flags(env, addr, 0, MMU_DATA_LOAD,
 | |
|                                    mmu_idx, true, &h, 0);
 | |
|         if (flags & TLB_INVALID_MASK) {
 | |
|             return -1;
 | |
|         }
 | |
|         if (flags & TLB_MMIO) {
 | |
|             do {
 | |
|                 uint8_t c;
 | |
|                 if (cpu_memory_rw_debug(env_cpu(env), addr, &c, 1, 0)) {
 | |
|                     return -1;
 | |
|                 }
 | |
|                 if (c == 0) {
 | |
|                     return len;
 | |
|                 }
 | |
|                 addr++;
 | |
|                 len++;
 | |
|                 if (len > INT32_MAX) {
 | |
|                     return -1;
 | |
|                 }
 | |
|             } while (--left_in_page != 0);
 | |
|         } else {
 | |
|             char *p = memchr(h, 0, left_in_page);
 | |
|             if (p) {
 | |
|                 len += p - (char *)h;
 | |
|                 return len <= INT32_MAX ? (ssize_t)len : -1;
 | |
|             }
 | |
|             addr += left_in_page;
 | |
|             len += left_in_page;
 | |
|             if (len > INT32_MAX) {
 | |
|                 return -1;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| char *uaccess_lock_user_string(CPUArchState *env, target_ulong addr)
 | |
| {
 | |
|     ssize_t len = uaccess_strlen_user(env, addr);
 | |
|     if (len < 0) {
 | |
|         return NULL;
 | |
|     }
 | |
|     return uaccess_lock_user(env, addr, len + 1, true);
 | |
| }
 | |
| 
 | |
| void uaccess_unlock_user(CPUArchState *env, void *p,
 | |
|                          target_ulong addr, target_ulong len)
 | |
| {
 | |
|     if (len) {
 | |
|         cpu_memory_rw_debug(env_cpu(env), addr, p, len, 1);
 | |
|     }
 | |
|     free(p);
 | |
| }
 |