diff options
Diffstat (limited to 'include/user')
-rw-r--r-- | include/user/abitypes.h | 7 | ||||
-rw-r--r-- | include/user/cpu_loop.h | 88 | ||||
-rw-r--r-- | include/user/guest-host.h | 76 | ||||
-rw-r--r-- | include/user/mmap.h | 32 | ||||
-rw-r--r-- | include/user/page-protection.h | 96 | ||||
-rw-r--r-- | include/user/signal.h | 25 |
6 files changed, 317 insertions, 7 deletions
diff --git a/include/user/abitypes.h b/include/user/abitypes.h index 5c9a955..7528124 100644 --- a/include/user/abitypes.h +++ b/include/user/abitypes.h @@ -21,13 +21,6 @@ #define ABI_LLONG_ALIGNMENT 2 #endif -#ifdef TARGET_CRIS -#define ABI_SHORT_ALIGNMENT 1 -#define ABI_INT_ALIGNMENT 1 -#define ABI_LONG_ALIGNMENT 1 -#define ABI_LLONG_ALIGNMENT 1 -#endif - #if (defined(TARGET_I386) && !defined(TARGET_X86_64)) \ || defined(TARGET_SH4) \ || defined(TARGET_OPENRISC) \ diff --git a/include/user/cpu_loop.h b/include/user/cpu_loop.h new file mode 100644 index 0000000..ad8a1d7 --- /dev/null +++ b/include/user/cpu_loop.h @@ -0,0 +1,88 @@ +/* + * qemu user cpu loop + * + * Copyright (c) 2003-2008 Fabrice Bellard + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#ifndef USER_CPU_LOOP_H +#define USER_CPU_LOOP_H + +#include "exec/vaddr.h" +#include "exec/mmu-access-type.h" + + +/** + * adjust_signal_pc: + * @pc: raw pc from the host signal ucontext_t. + * @is_write: host memory operation was write, or read-modify-write. + * + * Alter @pc as required for unwinding. Return the type of the + * guest memory access -- host reads may be for guest execution. + */ +MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write); + +/** + * handle_sigsegv_accerr_write: + * @cpu: the cpu context + * @old_set: the sigset_t from the signal ucontext_t + * @host_pc: the host pc, adjusted for the signal + * @host_addr: the host address of the fault + * + * Return true if the write fault has been handled, and should be re-tried. + */ +bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set, + uintptr_t host_pc, vaddr guest_addr); + +/** + * cpu_loop_exit_sigsegv: + * @cpu: the cpu context + * @addr: the guest address of the fault + * @access_type: access was read/write/execute + * @maperr: true for invalid page, false for permission fault + * @ra: host pc for unwinding + * + * Use the TCGCPUOps hook to record cpu state, do guest operating system + * specific things to raise SIGSEGV, and jump to the main cpu loop. + */ +G_NORETURN void cpu_loop_exit_sigsegv(CPUState *cpu, vaddr addr, + MMUAccessType access_type, + bool maperr, uintptr_t ra); + +/** + * cpu_loop_exit_sigbus: + * @cpu: the cpu context + * @addr: the guest address of the alignment fault + * @access_type: access was read/write/execute + * @ra: host pc for unwinding + * + * Use the TCGCPUOps hook to record cpu state, do guest operating system + * specific things to raise SIGBUS, and jump to the main cpu loop. + */ +G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, vaddr addr, + MMUAccessType access_type, + uintptr_t ra); + +G_NORETURN void cpu_loop(CPUArchState *env); + +void target_exception_dump(CPUArchState *env, const char *fmt, int code); +#define EXCP_DUMP(env, fmt, code) \ + target_exception_dump(env, fmt, code) + +typedef struct target_pt_regs target_pt_regs; + +void target_cpu_copy_regs(CPUArchState *env, target_pt_regs *regs); + +#endif diff --git a/include/user/guest-host.h b/include/user/guest-host.h new file mode 100644 index 0000000..8f7ef75 --- /dev/null +++ b/include/user/guest-host.h @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +/* + * guest <-> host helpers. + * + * Copyright (c) 2003 Fabrice Bellard + */ + +#ifndef USER_GUEST_HOST_H +#define USER_GUEST_HOST_H + +#include "exec/vaddr.h" +#include "user/guest-base.h" +#include "accel/tcg/cpu-ops.h" + +/* + * If non-zero, the guest virtual address space is a contiguous subset + * of the host virtual address space, i.e. '-R reserved_va' is in effect + * either from the command-line or by default. The value is the last + * byte of the guest address space e.g. UINT32_MAX. + * + * If zero, the host and guest virtual address spaces are intermingled. + */ +extern unsigned long reserved_va; + +/* + * The last byte of the guest address space. + * If reserved_va is non-zero, guest_addr_max matches. + * If reserved_va is zero, guest_addr_max equals the full guest space. + */ +extern unsigned long guest_addr_max; + +static inline vaddr cpu_untagged_addr(CPUState *cs, vaddr x) +{ + const TCGCPUOps *tcg_ops = cs->cc->tcg_ops; + if (tcg_ops->untagged_addr) { + return tcg_ops->untagged_addr(cs, x); + } + return x; +} + +/* All direct uses of g2h and h2g need to go away for usermode softmmu. */ +static inline void *g2h_untagged(vaddr x) +{ + return (void *)((uintptr_t)(x) + guest_base); +} + +static inline void *g2h(CPUState *cs, vaddr x) +{ + return g2h_untagged(cpu_untagged_addr(cs, x)); +} + +static inline bool guest_addr_valid_untagged(vaddr x) +{ + return x <= guest_addr_max; +} + +static inline bool guest_range_valid_untagged(vaddr start, vaddr len) +{ + return len - 1 <= guest_addr_max && start <= guest_addr_max - len + 1; +} + +#define h2g_valid(x) \ + ((uintptr_t)(x) - guest_base <= guest_addr_max) + +#define h2g_nocheck(x) ({ \ + uintptr_t __ret = (uintptr_t)(x) - guest_base; \ + (vaddr)__ret; \ +}) + +#define h2g(x) ({ \ + /* Check if given address fits target address space */ \ + assert(h2g_valid(x)); \ + h2g_nocheck(x); \ +}) + +#endif diff --git a/include/user/mmap.h b/include/user/mmap.h new file mode 100644 index 0000000..4d5e9aa --- /dev/null +++ b/include/user/mmap.h @@ -0,0 +1,32 @@ +/* + * MMAP declarations for QEMU user emulation + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef USER_MMAP_H +#define USER_MMAP_H + +#include "user/abitypes.h" + +/* + * mmap_next_start: The base address for the next mmap without hint, + * increased after each successful map, starting at task_unmapped_base. + * This is an optimization within QEMU and not part of ADDR_COMPAT_LAYOUT. + */ +extern abi_ulong mmap_next_start; + +int target_mprotect(abi_ulong start, abi_ulong len, int prot); + +abi_long target_mmap(abi_ulong start, abi_ulong len, int prot, + int flags, int fd, off_t offset); +int target_munmap(abi_ulong start, abi_ulong len); +abi_long target_mremap(abi_ulong old_addr, abi_ulong old_size, + abi_ulong new_size, unsigned long flags, + abi_ulong new_addr); + +abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment); + +void TSA_NO_TSA mmap_fork_start(void); +void TSA_NO_TSA mmap_fork_end(int child); + +#endif diff --git a/include/user/page-protection.h b/include/user/page-protection.h new file mode 100644 index 0000000..4bde664 --- /dev/null +++ b/include/user/page-protection.h @@ -0,0 +1,96 @@ +/* + * QEMU page protection declarations. + * + * Copyright (c) 2003 Fabrice Bellard + * + * SPDX-License-Identifier: LGPL-2.1+ + */ +#ifndef USER_PAGE_PROTECTION_H +#define USER_PAGE_PROTECTION_H + +#ifndef CONFIG_USER_ONLY +#error Cannot include this header from system emulation +#endif + +#include "exec/vaddr.h" +#include "exec/translation-block.h" + +int page_unprotect(CPUState *cpu, tb_page_addr_t address, uintptr_t pc); + +int page_get_flags(vaddr address); + +/** + * page_set_flags: + * @start: first byte of range + * @last: last byte of range + * @flags: flags to set + * Context: holding mmap lock + * + * Modify the flags of a page and invalidate the code if necessary. + * The flag PAGE_WRITE_ORG is positioned automatically depending + * on PAGE_WRITE. The mmap_lock should already be held. + */ +void page_set_flags(vaddr start, vaddr last, int flags); + +void page_reset_target_data(vaddr start, vaddr last); + +/** + * page_check_range + * @start: first byte of range + * @len: length of range + * @flags: flags required for each page + * + * Return true if every page in [@start, @start+@len) has @flags set. + * Return false if any page is unmapped. Thus testing flags == 0 is + * equivalent to testing for flags == PAGE_VALID. + */ +bool page_check_range(vaddr start, vaddr last, int flags); + +/** + * page_check_range_empty: + * @start: first byte of range + * @last: last byte of range + * Context: holding mmap lock + * + * Return true if the entire range [@start, @last] is unmapped. + * The memory lock must be held so that the caller will can ensure + * the result stays true until a new mapping can be installed. + */ +bool page_check_range_empty(vaddr start, vaddr last); + +/** + * page_find_range_empty + * @min: first byte of search range + * @max: last byte of search range + * @len: size of the hole required + * @align: alignment of the hole required (power of 2) + * + * If there is a range [x, x+@len) within [@min, @max] such that + * x % @align == 0, then return x. Otherwise return -1. + * The memory lock must be held, as the caller will want to ensure + * the returned range stays empty until a new mapping can be installed. + */ +vaddr page_find_range_empty(vaddr min, vaddr max, vaddr len, vaddr align); + +/** + * page_get_target_data + * @address: guest virtual address + * @size: per-page size + * + * Return @size bytes of out-of-band data to associate + * with the guest page at @address, allocating it if necessary. The + * caller should already have verified that the address is valid. + * The value of @size must be the same for every call. + * + * The memory will be freed when the guest page is deallocated, + * e.g. with the munmap system call. + */ +__attribute__((returns_nonnull)) +void *page_get_target_data(vaddr address, size_t size); + +typedef int (*walk_memory_regions_fn)(void *, vaddr, vaddr, int); +int walk_memory_regions(void *, walk_memory_regions_fn); + +void page_dump(FILE *f); + +#endif diff --git a/include/user/signal.h b/include/user/signal.h new file mode 100644 index 0000000..7fa33b0 --- /dev/null +++ b/include/user/signal.h @@ -0,0 +1,25 @@ +/* + * Signal-related declarations. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#ifndef USER_SIGNAL_H +#define USER_SIGNAL_H + +#ifndef CONFIG_USER_ONLY +#error Cannot include this header from system emulation +#endif + +/** + * target_to_host_signal: + * @sig: target signal. + * + * On success, return the host signal between 0 (inclusive) and NSIG + * (exclusive) corresponding to the target signal @sig. Return any other value + * on failure. + */ +int target_to_host_signal(int sig); + +extern int host_interrupt_signal; + +#endif |