Import QEMU upstream snapshot d2e570c
Upstream: https://gitlab.com/qemu-project/qemu.git Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
commit
cf256aa081
11315 files changed
+3598369
No files matched your search
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QEMU abi_ptr type definitions
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
#ifndef EXEC_ABI_PTR_H
|
||||
#define EXEC_ABI_PTR_H
|
||||
|
||||
#include "cpu-param.h"
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/*
|
||||
* sparc32plus has 64bit long but 32bit space address
|
||||
* this can make bad result with g2h() and h2g()
|
||||
*/
|
||||
#if TARGET_VIRT_ADDR_SPACE_BITS <= 32
|
||||
typedef uint32_t abi_ptr;
|
||||
#define TARGET_ABI_FMT_ptr "%x"
|
||||
#else
|
||||
typedef uint64_t abi_ptr;
|
||||
#define TARGET_ABI_FMT_ptr "%"PRIx64
|
||||
#endif
|
||||
|
||||
#else /* !CONFIG_USER_ONLY */
|
||||
|
||||
#include "exec/target_long.h"
|
||||
|
||||
typedef target_ulong abi_ptr;
|
||||
#define TARGET_ABI_FMT_ptr TARGET_FMT_lx
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* QEMU breakpoint & watchpoint definitions
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef EXEC_BREAKPOINT_H
|
||||
#define EXEC_BREAKPOINT_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "exec/vaddr.h"
|
||||
#include "exec/memattrs.h"
|
||||
|
||||
/* Breakpoint/watchpoint flags */
|
||||
#define BP_MEM_READ 0x01
|
||||
#define BP_MEM_WRITE 0x02
|
||||
#define BP_MEM_ACCESS (BP_MEM_READ | BP_MEM_WRITE)
|
||||
#define BP_STOP_BEFORE_ACCESS 0x04
|
||||
/* 0x08 currently unused */
|
||||
#define BP_GDB 0x10
|
||||
#define BP_CPU 0x20
|
||||
#define BP_ANY (BP_GDB | BP_CPU)
|
||||
#define BP_HIT_SHIFT 6
|
||||
#define BP_WATCHPOINT_HIT_READ (BP_MEM_READ << BP_HIT_SHIFT)
|
||||
#define BP_WATCHPOINT_HIT_WRITE (BP_MEM_WRITE << BP_HIT_SHIFT)
|
||||
#define BP_WATCHPOINT_HIT (BP_MEM_ACCESS << BP_HIT_SHIFT)
|
||||
|
||||
typedef struct CPUBreakpoint {
|
||||
vaddr pc;
|
||||
int flags; /* BP_* */
|
||||
QTAILQ_ENTRY(CPUBreakpoint) entry;
|
||||
} CPUBreakpoint;
|
||||
|
||||
typedef struct CPUWatchpoint {
|
||||
vaddr vaddr;
|
||||
vaddr len;
|
||||
vaddr hitaddr;
|
||||
MemTxAttrs hitattrs;
|
||||
int flags; /* BP_* */
|
||||
QTAILQ_ENTRY(CPUWatchpoint) entry;
|
||||
} CPUWatchpoint;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* CPU interfaces that are target independent.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
#ifndef CPU_COMMON_H
|
||||
#define CPU_COMMON_H
|
||||
|
||||
#include "qemu/thread.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
#define EXCP_INTERRUPT 0x10000 /* async interruption */
|
||||
#define EXCP_HLT 0x10001 /* hlt instruction reached */
|
||||
#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
|
||||
#define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */
|
||||
#define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */
|
||||
#define EXCP_ATOMIC 0x10005 /* stop-the-world and emulate atomic */
|
||||
|
||||
#define REAL_HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_real_host_page_size())
|
||||
|
||||
/* The CPU list lock nests outside page_(un)lock or mmap_(un)lock */
|
||||
extern QemuMutex qemu_cpu_list_lock;
|
||||
void qemu_init_cpu_list(void);
|
||||
void cpu_list_lock(void);
|
||||
void cpu_list_unlock(void);
|
||||
unsigned int cpu_list_generation_id_get(void);
|
||||
|
||||
int cpu_get_free_index(void);
|
||||
|
||||
/**
|
||||
* cpu_address_space_init:
|
||||
* @cpu: CPU to add this address space to
|
||||
* @asidx: integer index of this address space
|
||||
* @prefix: prefix to be used as name of address space
|
||||
* @mr: the root memory region of address space
|
||||
*
|
||||
* Add the specified address space to the CPU's cpu_ases list.
|
||||
* The address space added with @asidx 0 is the one used for the
|
||||
* convenience pointer cpu->as.
|
||||
* The target-specific code which registers ASes is responsible
|
||||
* for defining what semantics address space 0, 1, 2, etc have.
|
||||
*
|
||||
* Note that with KVM only one address space is supported.
|
||||
*/
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr);
|
||||
/**
|
||||
* cpu_destroy_address_spaces:
|
||||
* @cpu: CPU for which address spaces need to be destroyed
|
||||
*
|
||||
* Destroy all address spaces associated with this CPU; this
|
||||
* is called as part of unrealizing the CPU.
|
||||
*/
|
||||
void cpu_destroy_address_spaces(CPUState *cpu);
|
||||
|
||||
/* vl.c */
|
||||
void list_cpus(void);
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
#include "qemu/atomic.h"
|
||||
|
||||
/**
|
||||
* cpu_loop_exit_requested:
|
||||
* @cpu: The CPU state to be tested
|
||||
*
|
||||
* Indicate if somebody asked for a return of the CPU to the main loop
|
||||
* (e.g., via cpu_exit() or cpu_interrupt()).
|
||||
*
|
||||
* This is helpful for architectures that support interruptible
|
||||
* instructions. After writing back all state to registers/memory, this
|
||||
* call can be used to check if it makes sense to return to the main loop
|
||||
* or to continue executing the interruptible instruction.
|
||||
*/
|
||||
static inline bool cpu_loop_exit_requested(const CPUState *cpu)
|
||||
{
|
||||
return (int32_t)qatomic_read(&cpu->neg.icount_decr.u32) < 0;
|
||||
}
|
||||
#endif /* CONFIG_TCG */
|
||||
|
||||
/**
|
||||
* env_archcpu(env)
|
||||
* @env: The architecture environment
|
||||
*
|
||||
* Return the ArchCPU associated with the environment.
|
||||
*/
|
||||
static inline ArchCPU *env_archcpu(CPUArchState *env)
|
||||
{
|
||||
return (void *)env - sizeof(CPUState);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_cpu_const(env)
|
||||
* @env: The architecture environment
|
||||
*
|
||||
* Return the CPUState associated with the environment.
|
||||
*/
|
||||
static inline const CPUState *env_cpu_const(const CPUArchState *env)
|
||||
{
|
||||
return (void *)env - sizeof(CPUState);
|
||||
}
|
||||
|
||||
/**
|
||||
* env_cpu(env)
|
||||
* @env: The architecture environment
|
||||
*
|
||||
* Return the CPUState associated with the environment.
|
||||
*/
|
||||
static inline CPUState *env_cpu(CPUArchState *env)
|
||||
{
|
||||
return (CPUState *)env_cpu_const(env);
|
||||
}
|
||||
|
||||
#endif /* CPU_COMMON_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* common defines for all CPUs
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef CPU_DEFS_H
|
||||
#define CPU_DEFS_H
|
||||
|
||||
#ifndef COMPILING_PER_TARGET
|
||||
#error cpu.h included from common code
|
||||
#endif
|
||||
|
||||
#include "cpu-param.h"
|
||||
|
||||
#ifndef TARGET_LONG_BITS
|
||||
# error TARGET_LONG_BITS must be defined in cpu-param.h
|
||||
#endif
|
||||
#ifndef TARGET_VIRT_ADDR_SPACE_BITS
|
||||
# error TARGET_VIRT_ADDR_SPACE_BITS must be defined in cpu-param.h
|
||||
#endif
|
||||
#if !defined(TARGET_PAGE_BITS) && !defined(TARGET_PAGE_BITS_VARY)
|
||||
# error TARGET_PAGE_BITS must be defined in cpu-param.h
|
||||
#endif
|
||||
|
||||
#include "exec/target_long.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Flags for use with cpu_interrupt()
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef CPU_INTERRUPT_H
|
||||
#define CPU_INTERRUPT_H
|
||||
|
||||
/*
|
||||
* The numbers assigned here are non-sequential in order to preserve binary
|
||||
* compatibility with the vmstate dump. Bit 0 (0x0001) was previously used
|
||||
* for CPU_INTERRUPT_EXIT, and is cleared when loading the vmstate dump.
|
||||
*/
|
||||
|
||||
/*
|
||||
* External hardware interrupt pending.
|
||||
* This is typically used for interrupts from devices.
|
||||
*/
|
||||
#define CPU_INTERRUPT_HARD 0x0002
|
||||
|
||||
/*
|
||||
* Exit the current TB. This is typically used when some system-level device
|
||||
* makes some change to the memory mapping. E.g. the a20 line change.
|
||||
*/
|
||||
#define CPU_INTERRUPT_EXITTB 0x0004
|
||||
|
||||
/* Halt the CPU. */
|
||||
#define CPU_INTERRUPT_HALT 0x0020
|
||||
|
||||
/* Debug event pending. */
|
||||
#define CPU_INTERRUPT_DEBUG 0x0080
|
||||
|
||||
/* Reset signal. */
|
||||
#define CPU_INTERRUPT_RESET 0x0400
|
||||
|
||||
/*
|
||||
* Several target-specific external hardware interrupts. Each target/cpu.h
|
||||
* should define proper names based on these defines.
|
||||
*/
|
||||
#define CPU_INTERRUPT_TGT_EXT_0 0x0008
|
||||
#define CPU_INTERRUPT_TGT_EXT_1 0x0010
|
||||
#define CPU_INTERRUPT_TGT_EXT_2 0x0040
|
||||
#define CPU_INTERRUPT_TGT_EXT_3 0x0200
|
||||
#define CPU_INTERRUPT_TGT_EXT_4 0x1000
|
||||
|
||||
/*
|
||||
* Several target-specific internal interrupts. These differ from the
|
||||
* preceding target-specific interrupts in that they are intended to
|
||||
* originate from within the cpu itself, typically in response to some
|
||||
* instruction being executed. These, therefore, are not masked while
|
||||
* single-stepping within the debugger.
|
||||
*/
|
||||
#define CPU_INTERRUPT_TGT_INT_0 0x0100
|
||||
#define CPU_INTERRUPT_TGT_INT_1 0x0800
|
||||
#define CPU_INTERRUPT_TGT_INT_2 0x2000
|
||||
|
||||
/* First unused bit: 0x4000. */
|
||||
|
||||
/* The set of all bits that should be masked when single-stepping. */
|
||||
#define CPU_INTERRUPT_SSTEP_MASK \
|
||||
(CPU_INTERRUPT_HARD \
|
||||
| CPU_INTERRUPT_TGT_EXT_0 \
|
||||
| CPU_INTERRUPT_TGT_EXT_1 \
|
||||
| CPU_INTERRUPT_TGT_EXT_2 \
|
||||
| CPU_INTERRUPT_TGT_EXT_3 \
|
||||
| CPU_INTERRUPT_TGT_EXT_4)
|
||||
|
||||
#endif /* CPU_INTERRUPT_H */
|
||||
@@ -0,0 +1,283 @@
|
||||
/*
|
||||
* Common CPU TLB handling
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef CPUTLB_H
|
||||
#define CPUTLB_H
|
||||
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "exec/memattrs.h"
|
||||
#include "exec/vaddr.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "system/ram_addr.h"
|
||||
|
||||
void tlb_reset_dirty(CPUState *cpu, uintptr_t start, uintptr_t length);
|
||||
void tlb_reset_dirty_range_all(ram_addr_t start, ram_addr_t length);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* tlb_set_page_full:
|
||||
* @cpu: CPU context
|
||||
* @mmu_idx: mmu index of the tlb to modify
|
||||
* @addr: virtual address of the entry to add
|
||||
* @full: the details of the tlb entry
|
||||
*
|
||||
* Add an entry to @cpu tlb index @mmu_idx. All of the fields of
|
||||
* @full must be filled, except for xlat_offset & section, and
|
||||
* constitute the complete description of the translated page.
|
||||
*
|
||||
* This is generally called by the target tlb_fill function after
|
||||
* having performed a successful page table walk to find the physical
|
||||
* address and attributes for the translation.
|
||||
*
|
||||
* At most one entry for a given virtual address is permitted. Only a
|
||||
* single TARGET_PAGE_SIZE region is mapped; @full->lg_page_size is only
|
||||
* used by tlb_flush_page.
|
||||
*/
|
||||
void tlb_set_page_full(CPUState *cpu, int mmu_idx, vaddr addr,
|
||||
CPUTLBEntryFull *full);
|
||||
|
||||
/**
|
||||
* tlb_set_page_with_attrs:
|
||||
* @cpu: CPU to add this TLB entry for
|
||||
* @addr: virtual address of page to add entry for
|
||||
* @paddr: physical address of the page
|
||||
* @attrs: memory transaction attributes
|
||||
* @prot: access permissions (PAGE_READ/PAGE_WRITE/PAGE_EXEC bits)
|
||||
* @mmu_idx: MMU index to insert TLB entry for
|
||||
* @size: size of the page in bytes
|
||||
*
|
||||
* Add an entry to this CPU's TLB (a mapping from virtual address
|
||||
* @addr to physical address @paddr) with the specified memory
|
||||
* transaction attributes. This is generally called by the target CPU
|
||||
* specific code after it has been called through the tlb_fill()
|
||||
* entry point and performed a successful page table walk to find
|
||||
* the physical address and attributes for the virtual address
|
||||
* which provoked the TLB miss.
|
||||
*
|
||||
* At most one entry for a given virtual address is permitted. Only a
|
||||
* single TARGET_PAGE_SIZE region is mapped; the supplied @size is only
|
||||
* used by tlb_flush_page.
|
||||
*/
|
||||
void tlb_set_page_with_attrs(CPUState *cpu, vaddr addr,
|
||||
hwaddr paddr, MemTxAttrs attrs,
|
||||
int prot, int mmu_idx, vaddr size);
|
||||
|
||||
/**
|
||||
* tlb_set_page:
|
||||
*
|
||||
* This function is equivalent to calling tlb_set_page_with_attrs()
|
||||
* with an @attrs argument of MEMTXATTRS_UNSPECIFIED. It's provided
|
||||
* as a convenience for CPUs which don't use memory transaction attributes.
|
||||
*/
|
||||
void tlb_set_page(CPUState *cpu, vaddr addr,
|
||||
hwaddr paddr, int prot,
|
||||
int mmu_idx, vaddr size);
|
||||
|
||||
#if defined(CONFIG_TCG) && !defined(CONFIG_USER_ONLY)
|
||||
/**
|
||||
* tlb_flush_page:
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @addr: virtual address of page to be flushed
|
||||
*
|
||||
* Flush one page from the TLB of the specified CPU, for all
|
||||
* MMU indexes.
|
||||
*/
|
||||
void tlb_flush_page(CPUState *cpu, vaddr addr);
|
||||
|
||||
/**
|
||||
* tlb_flush_page_all_cpus_synced:
|
||||
* @cpu: src CPU of the flush
|
||||
* @addr: virtual address of page to be flushed
|
||||
*
|
||||
* Flush one page from the TLB of all CPUs, for all
|
||||
* MMU indexes.
|
||||
*
|
||||
* When this function returns, no CPUs will subsequently perform
|
||||
* translations using the flushed TLBs.
|
||||
*/
|
||||
void tlb_flush_page_all_cpus_synced(CPUState *src, vaddr addr);
|
||||
|
||||
/**
|
||||
* tlb_flush:
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
*
|
||||
* Flush the entire TLB for the specified CPU. Most CPU architectures
|
||||
* allow the implementation to drop entries from the TLB at any time
|
||||
* so this is generally safe. If more selective flushing is required
|
||||
* use one of the other functions for efficiency.
|
||||
*/
|
||||
void tlb_flush(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* tlb_flush_all_cpus_synced:
|
||||
* @cpu: src CPU of the flush
|
||||
*
|
||||
* Flush the entire TLB for all CPUs, for all MMU indexes.
|
||||
*
|
||||
* When this function returns, no CPUs will subsequently perform
|
||||
* translations using the flushed TLBs.
|
||||
*/
|
||||
void tlb_flush_all_cpus_synced(CPUState *src_cpu);
|
||||
|
||||
/**
|
||||
* tlb_flush_page_by_mmuidx:
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @addr: virtual address of page to be flushed
|
||||
* @idxmap: bitmap of MMU indexes to flush
|
||||
*
|
||||
* Flush one page from the TLB of the specified CPU, for the specified
|
||||
* MMU indexes.
|
||||
*/
|
||||
void tlb_flush_page_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
MMUIdxMap idxmap);
|
||||
|
||||
/**
|
||||
* tlb_flush_page_by_mmuidx_all_cpus_synced:
|
||||
* @cpu: Originating CPU of the flush
|
||||
* @addr: virtual address of page to be flushed
|
||||
* @idxmap: bitmap of MMU indexes to flush
|
||||
*
|
||||
* Flush one page from the TLB of all CPUs, for the specified
|
||||
* MMU indexes.
|
||||
*
|
||||
* When this function returns, no CPUs will subsequently perform
|
||||
* translations using the flushed TLBs.
|
||||
*/
|
||||
void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
|
||||
MMUIdxMap idxmap);
|
||||
|
||||
/**
|
||||
* tlb_flush_by_mmuidx:
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @wait: If true ensure synchronisation by exiting the cpu_loop
|
||||
* @idxmap: bitmap of MMU indexes to flush
|
||||
*
|
||||
* Flush all entries from the TLB of the specified CPU, for the specified
|
||||
* MMU indexes.
|
||||
*/
|
||||
void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap);
|
||||
|
||||
/**
|
||||
* tlb_flush_by_mmuidx_all_cpus_synced:
|
||||
* @cpu: Originating CPU of the flush
|
||||
* @idxmap: bitmap of MMU indexes to flush
|
||||
*
|
||||
* Flush all entries from the TLB of all CPUs, for the specified
|
||||
* MMU indexes.
|
||||
*
|
||||
* When this function returns, no CPUs will subsequently perform
|
||||
* translations using the flushed TLBs.
|
||||
*/
|
||||
void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, MMUIdxMap idxmap);
|
||||
|
||||
/**
|
||||
* tlb_flush_page_bits_by_mmuidx
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @addr: virtual address of page to be flushed
|
||||
* @idxmap: bitmap of mmu indexes to flush
|
||||
* @bits: number of significant bits in address
|
||||
*
|
||||
* Similar to tlb_flush_page_mask, but with a bitmap of indexes.
|
||||
*/
|
||||
void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
MMUIdxMap idxmap, unsigned bits);
|
||||
|
||||
/* Similarly, with broadcast and syncing. */
|
||||
void tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
|
||||
MMUIdxMap idxmap,
|
||||
unsigned bits);
|
||||
|
||||
/**
|
||||
* tlb_flush_range_by_mmuidx
|
||||
* @cpu: CPU whose TLB should be flushed
|
||||
* @addr: virtual address of the start of the range to be flushed
|
||||
* @len: length of range to be flushed
|
||||
* @idxmap: bitmap of mmu indexes to flush
|
||||
* @bits: number of significant bits in address
|
||||
*
|
||||
* For each mmuidx in @idxmap, flush all pages within [@addr,@addr+@len),
|
||||
* comparing only the low @bits worth of each virtual page.
|
||||
*/
|
||||
void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
vaddr len, MMUIdxMap idxmap,
|
||||
unsigned bits);
|
||||
|
||||
/* Similarly, with broadcast and syncing. */
|
||||
void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
vaddr addr,
|
||||
vaddr len,
|
||||
MMUIdxMap idxmap,
|
||||
unsigned bits);
|
||||
#else
|
||||
static inline void tlb_flush_page(CPUState *cpu, vaddr addr)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_page_all_cpus_synced(CPUState *src, vaddr addr)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush(CPUState *cpu)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_all_cpus_synced(CPUState *src_cpu)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_page_by_mmuidx(CPUState *cpu,
|
||||
vaddr addr, MMUIdxMap idxmap)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tlb_flush_by_mmuidx(CPUState *cpu, MMUIdxMap idxmap)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_page_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
vaddr addr,
|
||||
MMUIdxMap idxmap)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
MMUIdxMap idxmap)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_page_bits_by_mmuidx(CPUState *cpu,
|
||||
vaddr addr,
|
||||
MMUIdxMap idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void
|
||||
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
|
||||
MMUIdxMap idxmap, unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
|
||||
vaddr len, MMUIdxMap idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
vaddr addr,
|
||||
vaddr len,
|
||||
MMUIdxMap idxmap,
|
||||
unsigned bits)
|
||||
{
|
||||
}
|
||||
#endif /* CONFIG_TCG && !CONFIG_USER_ONLY */
|
||||
#endif /* CPUTLB_H */
|
||||
@@ -0,0 +1,161 @@
|
||||
#ifndef GDBSTUB_H
|
||||
#define GDBSTUB_H
|
||||
|
||||
typedef struct GDBFeature {
|
||||
const char *xmlname;
|
||||
const char *xml;
|
||||
const char *name;
|
||||
const char * const *regs;
|
||||
int base_reg;
|
||||
int num_regs;
|
||||
} GDBFeature;
|
||||
|
||||
typedef struct GDBFeatureBuilder {
|
||||
GDBFeature *feature;
|
||||
GPtrArray *xml;
|
||||
GPtrArray *regs;
|
||||
int base_reg;
|
||||
} GDBFeatureBuilder;
|
||||
|
||||
|
||||
/* Get or set a register. Returns the size of the register. */
|
||||
typedef int (*gdb_get_reg_cb)(CPUState *cpu, GByteArray *buf, int reg);
|
||||
typedef int (*gdb_set_reg_cb)(CPUState *cpu, uint8_t *buf, int reg);
|
||||
|
||||
/**
|
||||
* gdb_init_cpu(): Initialize the CPU for gdbstub.
|
||||
* @cpu: The CPU to be initialized.
|
||||
*/
|
||||
void gdb_init_cpu(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* gdb_register_coprocessor() - register a supplemental set of registers
|
||||
* @cpu - the CPU associated with registers
|
||||
* @get_reg - get function (gdb reading)
|
||||
* @set_reg - set function (gdb modifying)
|
||||
* @num_regs - number of registers in set
|
||||
* @xml - xml name of set
|
||||
*/
|
||||
void gdb_register_coprocessor(CPUState *cpu,
|
||||
gdb_get_reg_cb get_reg, gdb_set_reg_cb set_reg,
|
||||
const GDBFeature *feature);
|
||||
|
||||
/**
|
||||
* gdb_unregister_coprocessor_all() - unregisters supplemental set of registers
|
||||
* @cpu - the CPU associated with registers
|
||||
*/
|
||||
void gdb_unregister_coprocessor_all(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* gdbserver_start: start the gdb server
|
||||
* @port_or_device: connection spec for gdb
|
||||
* @errp: error handle
|
||||
*
|
||||
* For CONFIG_USER this is either a tcp port or a path to a fifo. For
|
||||
* system emulation you can use a full chardev spec for your gdbserver
|
||||
* port.
|
||||
*
|
||||
* Returns true when server successfully started.
|
||||
*/
|
||||
bool gdbserver_start(const char *port_or_device, Error **errp);
|
||||
|
||||
/**
|
||||
* gdb_feature_builder_init() - Initialize GDBFeatureBuilder.
|
||||
* @builder: The builder to be initialized.
|
||||
* @feature: The feature to be filled.
|
||||
* @name: The name of the feature.
|
||||
* @xmlname: The name of the XML.
|
||||
* @base_reg: The base number of the register ID.
|
||||
*/
|
||||
void gdb_feature_builder_init(GDBFeatureBuilder *builder, GDBFeature *feature,
|
||||
const char *name, const char *xmlname,
|
||||
int base_reg);
|
||||
|
||||
/**
|
||||
* gdb_feature_builder_append_tag() - Append a tag.
|
||||
* @builder: The builder.
|
||||
* @format: The format of the tag.
|
||||
* @...: The values to be formatted.
|
||||
*/
|
||||
void G_GNUC_PRINTF(2, 3)
|
||||
gdb_feature_builder_append_tag(const GDBFeatureBuilder *builder,
|
||||
const char *format, ...);
|
||||
|
||||
/**
|
||||
* gdb_feature_builder_append_reg() - Append a register.
|
||||
* @builder: The builder.
|
||||
* @name: The register's name; it must be unique within a CPU.
|
||||
* @bitsize: The register's size, in bits.
|
||||
* @regnum: The offset of the register's number in the feature.
|
||||
* @type: The type of the register.
|
||||
* @group: The register group to which this register belongs; it can be NULL.
|
||||
*/
|
||||
void gdb_feature_builder_append_reg(const GDBFeatureBuilder *builder,
|
||||
const char *name,
|
||||
int bitsize,
|
||||
int regnum,
|
||||
const char *type,
|
||||
const char *group);
|
||||
|
||||
/**
|
||||
* gdb_feature_builder_end() - End building GDBFeature.
|
||||
* @builder: The builder.
|
||||
*/
|
||||
void gdb_feature_builder_end(const GDBFeatureBuilder *builder);
|
||||
|
||||
/**
|
||||
* gdb_find_static_feature() - Find a static feature.
|
||||
* @xmlname: The name of the XML.
|
||||
*
|
||||
* Return: The static feature.
|
||||
*/
|
||||
const GDBFeature *gdb_find_static_feature(const char *xmlname);
|
||||
|
||||
/**
|
||||
* gdb_read_register() - Read a register associated with a CPU.
|
||||
* @cpu: The CPU associated with the register.
|
||||
* @buf: The buffer that the read register will be appended to.
|
||||
* @reg: The register's number returned by gdb_find_feature_register().
|
||||
*
|
||||
* Return: The number of read bytes.
|
||||
*/
|
||||
int gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
|
||||
|
||||
/**
|
||||
* gdb_write_register() - Write a register associated with a CPU.
|
||||
* @cpu: The CPU associated with the register.
|
||||
* @buf: The buffer that the register contents will be set to.
|
||||
* @reg: The register's number returned by gdb_find_feature_register().
|
||||
*
|
||||
* The size of @buf must be at least the size of the register being
|
||||
* written.
|
||||
*
|
||||
* Return: The number of written bytes, or 0 if an error occurred (for
|
||||
* example, an unknown register was provided).
|
||||
*/
|
||||
int gdb_write_register(CPUState *cpu, uint8_t *mem_buf, int reg);
|
||||
|
||||
/**
|
||||
* typedef GDBRegDesc - a register description from gdbstub
|
||||
*/
|
||||
typedef struct {
|
||||
int gdb_reg;
|
||||
const char *name;
|
||||
const char *feature_name;
|
||||
} GDBRegDesc;
|
||||
|
||||
/**
|
||||
* gdb_get_register_list() - Return list of all registers for CPU
|
||||
* @cpu: The CPU being searched
|
||||
*
|
||||
* Returns a GArray of GDBRegDesc, caller frees array but not the
|
||||
* const strings.
|
||||
*/
|
||||
GArray *gdb_get_register_list(CPUState *cpu);
|
||||
|
||||
void gdb_set_stop_cpu(CPUState *cpu);
|
||||
|
||||
/* in gdbstub-xml.c, generated by scripts/feature_to_c.py */
|
||||
extern const GDBFeature gdb_static_features[];
|
||||
|
||||
#endif /* GDBSTUB_H */
|
||||
@@ -0,0 +1,14 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands generation functions for tcg opcodes.
|
||||
*/
|
||||
|
||||
#ifndef HELPER_GEN_COMMON_H
|
||||
#define HELPER_GEN_COMMON_H
|
||||
|
||||
#define HELPER_H "accel/tcg/tcg-runtime.h"
|
||||
#include "exec/helper-gen.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#endif /* HELPER_GEN_COMMON_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands generation functions for tcg opcodes.
|
||||
*/
|
||||
|
||||
#ifndef HELPER_GEN_H
|
||||
#define HELPER_GEN_H
|
||||
|
||||
#include "exec/helper-gen-common.h"
|
||||
|
||||
#define HELPER_H "helper.h"
|
||||
#include "exec/helper-gen.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#endif /* HELPER_GEN_H */
|
||||
@@ -0,0 +1,110 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands generation functions for tcg opcodes.
|
||||
* Define HELPER_H for the header file to be expanded,
|
||||
* and static inline to change from global file scope.
|
||||
*/
|
||||
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/helper-info.h"
|
||||
#include "exec/helper-head.h.inc"
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl0(ret)) \
|
||||
{ \
|
||||
tcg_gen_call0(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1)) \
|
||||
{ \
|
||||
tcg_gen_call1(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
|
||||
{ \
|
||||
tcg_gen_call2(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
|
||||
{ \
|
||||
tcg_gen_call3(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
|
||||
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
|
||||
{ \
|
||||
tcg_gen_call4(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), \
|
||||
dh_arg(t3, 3), dh_arg(t4, 4)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5)) \
|
||||
{ \
|
||||
tcg_gen_call5(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6)) \
|
||||
{ \
|
||||
tcg_gen_call6(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6)); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7)\
|
||||
extern TCGHelperInfo glue(helper_info_, name); \
|
||||
static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3), \
|
||||
dh_arg_decl(t4, 4), dh_arg_decl(t5, 5), dh_arg_decl(t6, 6), \
|
||||
dh_arg_decl(t7, 7)) \
|
||||
{ \
|
||||
tcg_gen_call7(glue(helper_info_,name).func, \
|
||||
&glue(helper_info_,name), dh_retvar(ret), \
|
||||
dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5), dh_arg(t6, 6), \
|
||||
dh_arg(t7, 7)); \
|
||||
}
|
||||
|
||||
#include HELPER_H
|
||||
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
#undef DEF_HELPER_FLAGS_1
|
||||
#undef DEF_HELPER_FLAGS_2
|
||||
#undef DEF_HELPER_FLAGS_3
|
||||
#undef DEF_HELPER_FLAGS_4
|
||||
#undef DEF_HELPER_FLAGS_5
|
||||
#undef DEF_HELPER_FLAGS_6
|
||||
#undef DEF_HELPER_FLAGS_7
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* Used by other helper files.
|
||||
*/
|
||||
|
||||
#ifndef EXEC_HELPER_HEAD_H
|
||||
#define EXEC_HELPER_HEAD_H
|
||||
|
||||
#include "fpu/softfloat-types.h"
|
||||
|
||||
#define HELPER(name) glue(helper_, name)
|
||||
|
||||
/* Some types that make sense in C, but not for TCG. */
|
||||
#define dh_alias_i32 i32
|
||||
#define dh_alias_s32 i32
|
||||
#define dh_alias_int i32
|
||||
#define dh_alias_i64 i64
|
||||
#define dh_alias_s64 i64
|
||||
#define dh_alias_i128 i128
|
||||
#define dh_alias_f16 i32
|
||||
#define dh_alias_f32 i32
|
||||
#define dh_alias_f64 i64
|
||||
#define dh_alias_ptr ptr
|
||||
#define dh_alias_cptr ptr
|
||||
#define dh_alias_env ptr
|
||||
#define dh_alias_fpst ptr
|
||||
#define dh_alias_void void
|
||||
#define dh_alias_noreturn noreturn
|
||||
#define dh_alias(t) glue(dh_alias_, t)
|
||||
|
||||
#define dh_ctype_i32 uint32_t
|
||||
#define dh_ctype_s32 int32_t
|
||||
#define dh_ctype_int int
|
||||
#define dh_ctype_i64 uint64_t
|
||||
#define dh_ctype_s64 int64_t
|
||||
#define dh_ctype_i128 Int128
|
||||
#define dh_ctype_f16 uint32_t
|
||||
#define dh_ctype_f32 float32
|
||||
#define dh_ctype_f64 float64
|
||||
#define dh_ctype_ptr void *
|
||||
#define dh_ctype_cptr const void *
|
||||
#define dh_ctype_env CPUArchState *
|
||||
#define dh_ctype_fpst float_status *
|
||||
#define dh_ctype_void void
|
||||
#define dh_ctype_noreturn G_NORETURN void
|
||||
#define dh_ctype(t) dh_ctype_##t
|
||||
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
# include "exec/target_long.h"
|
||||
# if TARGET_LONG_BITS == 32
|
||||
# define dh_alias_tl i32
|
||||
# define dh_typecode_tl dh_typecode_i32
|
||||
# else
|
||||
# define dh_alias_tl i64
|
||||
# define dh_typecode_tl dh_typecode_i64
|
||||
# endif
|
||||
# define dh_ctype_tl target_ulong
|
||||
#endif /* COMPILING_PER_TARGET */
|
||||
|
||||
#if __SIZEOF_POINTER__ == 4
|
||||
# define dh_alias_vaddr i32
|
||||
# define dh_typecode_vaddr dh_typecode_i32
|
||||
#elif __SIZEOF_POINTER__ == 8
|
||||
# define dh_alias_vaddr i64
|
||||
# define dh_typecode_vaddr dh_typecode_i64
|
||||
#else
|
||||
# error "sizeof pointer is different from {4,8}"
|
||||
#endif /* __SIZEOF_POINTER__ */
|
||||
# define dh_ctype_vaddr uintptr_t
|
||||
|
||||
/* We can't use glue() here because it falls foul of C preprocessor
|
||||
recursive expansion rules. */
|
||||
#define dh_retvar_decl0_void void
|
||||
#define dh_retvar_decl0_noreturn void
|
||||
#define dh_retvar_decl0_i32 TCGv_i32 retval
|
||||
#define dh_retvar_decl0_i64 TCGv_i64 retval
|
||||
#define dh_retval_decl0_i128 TCGv_i128 retval
|
||||
#define dh_retvar_decl0_ptr TCGv_ptr retval
|
||||
#define dh_retvar_decl0(t) glue(dh_retvar_decl0_, dh_alias(t))
|
||||
|
||||
#define dh_retvar_decl_void
|
||||
#define dh_retvar_decl_noreturn
|
||||
#define dh_retvar_decl_i32 TCGv_i32 retval,
|
||||
#define dh_retvar_decl_i64 TCGv_i64 retval,
|
||||
#define dh_retvar_decl_i128 TCGv_i128 retval,
|
||||
#define dh_retvar_decl_ptr TCGv_ptr retval,
|
||||
#define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
|
||||
|
||||
#define dh_retvar_void NULL
|
||||
#define dh_retvar_noreturn NULL
|
||||
#define dh_retvar_i32 tcgv_i32_temp(retval)
|
||||
#define dh_retvar_i64 tcgv_i64_temp(retval)
|
||||
#define dh_retvar_i128 tcgv_i128_temp(retval)
|
||||
#define dh_retvar_ptr tcgv_ptr_temp(retval)
|
||||
#define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
|
||||
|
||||
#define dh_typecode_void 0
|
||||
#define dh_typecode_noreturn 0
|
||||
#define dh_typecode_i32 2
|
||||
#define dh_typecode_s32 3
|
||||
#define dh_typecode_i64 4
|
||||
#define dh_typecode_s64 5
|
||||
#define dh_typecode_ptr 6
|
||||
#define dh_typecode_i128 7
|
||||
#define dh_typecode_int dh_typecode_s32
|
||||
#define dh_typecode_f16 dh_typecode_i32
|
||||
#define dh_typecode_f32 dh_typecode_i32
|
||||
#define dh_typecode_f64 dh_typecode_i64
|
||||
#define dh_typecode_cptr dh_typecode_ptr
|
||||
#define dh_typecode_env dh_typecode_ptr
|
||||
#define dh_typecode_fpst dh_typecode_ptr
|
||||
#define dh_typecode(t) dh_typecode_##t
|
||||
|
||||
#define dh_callflag_i32 0
|
||||
#define dh_callflag_i64 0
|
||||
#define dh_callflag_i128 0
|
||||
#define dh_callflag_ptr 0
|
||||
#define dh_callflag_void 0
|
||||
#define dh_callflag_noreturn TCG_CALL_NO_RETURN
|
||||
#define dh_callflag(t) glue(dh_callflag_, dh_alias(t))
|
||||
|
||||
#define dh_typemask(t, n) (dh_typecode(t) << (n * 3))
|
||||
|
||||
#define dh_arg(t, n) \
|
||||
glue(glue(tcgv_, dh_alias(t)), _temp)(glue(arg, n))
|
||||
|
||||
#define dh_arg_decl(t, n) glue(TCGv_, dh_alias(t)) glue(arg, n)
|
||||
|
||||
#define DEF_HELPER_0(name, ret) \
|
||||
DEF_HELPER_FLAGS_0(name, 0, ret)
|
||||
#define DEF_HELPER_1(name, ret, t1) \
|
||||
DEF_HELPER_FLAGS_1(name, 0, ret, t1)
|
||||
#define DEF_HELPER_2(name, ret, t1, t2) \
|
||||
DEF_HELPER_FLAGS_2(name, 0, ret, t1, t2)
|
||||
#define DEF_HELPER_3(name, ret, t1, t2, t3) \
|
||||
DEF_HELPER_FLAGS_3(name, 0, ret, t1, t2, t3)
|
||||
#define DEF_HELPER_4(name, ret, t1, t2, t3, t4) \
|
||||
DEF_HELPER_FLAGS_4(name, 0, ret, t1, t2, t3, t4)
|
||||
#define DEF_HELPER_5(name, ret, t1, t2, t3, t4, t5) \
|
||||
DEF_HELPER_FLAGS_5(name, 0, ret, t1, t2, t3, t4, t5)
|
||||
#define DEF_HELPER_6(name, ret, t1, t2, t3, t4, t5, t6) \
|
||||
DEF_HELPER_FLAGS_6(name, 0, ret, t1, t2, t3, t4, t5, t6)
|
||||
#define DEF_HELPER_7(name, ret, t1, t2, t3, t4, t5, t6, t7) \
|
||||
DEF_HELPER_FLAGS_7(name, 0, ret, t1, t2, t3, t4, t5, t6, t7)
|
||||
|
||||
/* MAX_CALL_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
|
||||
|
||||
#endif /* EXEC_HELPER_HEAD_H */
|
||||
@@ -0,0 +1,96 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands info structures for tcg helpers.
|
||||
* Define HELPER_H for the header file to be expanded.
|
||||
*/
|
||||
|
||||
#include "tcg/tcg.h"
|
||||
#include "tcg/helper-info.h"
|
||||
#include "exec/helper-head.h.inc"
|
||||
|
||||
/*
|
||||
* Need one more level of indirection before stringification
|
||||
* to get all the macros expanded first.
|
||||
*/
|
||||
#define str(s) #s
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, RET) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, RET, T1) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, RET, T1, T2) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, RET, T1, T2, T3) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, RET, T1, T2, T3, T4) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||
| dh_typemask(T4, 4) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, RET, T1, T2, T3, T4, T5) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_6(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||
| dh_typemask(T6, 6) \
|
||||
};
|
||||
|
||||
#define DEF_HELPER_FLAGS_7(NAME, FLAGS, RET, T1, T2, T3, T4, T5, T6, T7) \
|
||||
TCGHelperInfo glue(helper_info_, NAME) = { \
|
||||
.func = HELPER(NAME), .name = str(NAME), \
|
||||
.flags = FLAGS | dh_callflag(RET), \
|
||||
.typemask = dh_typemask(RET, 0) | dh_typemask(T1, 1) \
|
||||
| dh_typemask(T2, 2) | dh_typemask(T3, 3) \
|
||||
| dh_typemask(T4, 4) | dh_typemask(T5, 5) \
|
||||
| dh_typemask(T6, 6) | dh_typemask(T7, 7) \
|
||||
};
|
||||
|
||||
#include HELPER_H
|
||||
|
||||
#undef str
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
#undef DEF_HELPER_FLAGS_1
|
||||
#undef DEF_HELPER_FLAGS_2
|
||||
#undef DEF_HELPER_FLAGS_3
|
||||
#undef DEF_HELPER_FLAGS_4
|
||||
#undef DEF_HELPER_FLAGS_5
|
||||
#undef DEF_HELPER_FLAGS_6
|
||||
#undef DEF_HELPER_FLAGS_7
|
||||
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands prototypes for the helper functions.
|
||||
*/
|
||||
|
||||
#ifndef HELPER_PROTO_COMMON_H
|
||||
#define HELPER_PROTO_COMMON_H
|
||||
|
||||
#include "qemu/atomic128.h" /* for HAVE_CMPXCHG128 */
|
||||
|
||||
#define HELPER_H "accel/tcg/tcg-runtime.h"
|
||||
#include "exec/helper-proto.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#include "accel/tcg/getpc.h"
|
||||
|
||||
#endif /* HELPER_PROTO_COMMON_H */
|
||||
@@ -0,0 +1,16 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands prototypes for the helper functions.
|
||||
*/
|
||||
|
||||
#ifndef HELPER_PROTO_H
|
||||
#define HELPER_PROTO_H
|
||||
|
||||
#include "exec/helper-proto-common.h"
|
||||
|
||||
#define HELPER_H "helper.h"
|
||||
#include "exec/helper-proto.h.inc"
|
||||
#undef HELPER_H
|
||||
|
||||
#endif /* HELPER_PROTO_H */
|
||||
@@ -0,0 +1,68 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* Helper file for declaring TCG helper functions.
|
||||
* This one expands prototypes for the helper functions.
|
||||
* Define HELPER_H for the header file to be expanded.
|
||||
*/
|
||||
|
||||
#include "exec/helper-head.h.inc"
|
||||
|
||||
/*
|
||||
* Work around an issue with --enable-lto, in which GCC's ipa-split pass
|
||||
* decides to split out the noreturn code paths that raise an exception,
|
||||
* taking the __builtin_return_address() along into the new function,
|
||||
* where it no longer computes a value that returns to TCG generated code.
|
||||
* Despite the name, the noinline attribute affects splitter, so this
|
||||
* prevents the optimization in question. Given that helpers should not
|
||||
* otherwise be called directly, this should not have any other visible effect.
|
||||
*
|
||||
* See https://gitlab.com/qemu-project/qemu/-/issues/1454
|
||||
*/
|
||||
#define DEF_HELPER_ATTR __attribute__((noinline))
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
||||
dh_ctype(ret) HELPER(name) (void) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), \
|
||||
dh_ctype(t3)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_6(name, flags, ret, t1, t2, t3, t4, t5, t6) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5), \
|
||||
dh_ctype(t6)) DEF_HELPER_ATTR;
|
||||
|
||||
#define DEF_HELPER_FLAGS_7(name, flags, ret, t1, t2, t3, t4, t5, t6, t7) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
dh_ctype(t4), dh_ctype(t5), dh_ctype(t6), \
|
||||
dh_ctype(t7)) DEF_HELPER_ATTR;
|
||||
|
||||
#define IN_HELPER_PROTO
|
||||
|
||||
#include HELPER_H
|
||||
|
||||
#undef IN_HELPER_PROTO
|
||||
|
||||
#undef DEF_HELPER_FLAGS_0
|
||||
#undef DEF_HELPER_FLAGS_1
|
||||
#undef DEF_HELPER_FLAGS_2
|
||||
#undef DEF_HELPER_FLAGS_3
|
||||
#undef DEF_HELPER_FLAGS_4
|
||||
#undef DEF_HELPER_FLAGS_5
|
||||
#undef DEF_HELPER_FLAGS_6
|
||||
#undef DEF_HELPER_FLAGS_7
|
||||
#undef DEF_HELPER_ATTR
|
||||
@@ -0,0 +1,26 @@
|
||||
/* Define hwaddr if it exists. */
|
||||
|
||||
#ifndef HWADDR_H
|
||||
#define HWADDR_H
|
||||
|
||||
|
||||
#define HWADDR_BITS 64
|
||||
/* hwaddr is the type of a physical address (its size can
|
||||
be different from 'target_ulong'). */
|
||||
|
||||
typedef uint64_t hwaddr;
|
||||
#define HWADDR_MAX UINT64_MAX
|
||||
#define HWADDR_FMT_plx "%016" PRIx64
|
||||
#define HWADDR_PRId PRId64
|
||||
#define HWADDR_PRIi PRIi64
|
||||
#define HWADDR_PRIo PRIo64
|
||||
#define HWADDR_PRIu PRIu64
|
||||
#define HWADDR_PRIx PRIx64
|
||||
#define HWADDR_PRIX PRIX64
|
||||
|
||||
typedef struct MemMapEntry {
|
||||
hwaddr base;
|
||||
hwaddr size;
|
||||
} MemMapEntry;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* icount - Instruction Counter API
|
||||
* CPU timers state API
|
||||
*
|
||||
* Copyright 2020 SUSE LLC
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef EXEC_ICOUNT_H
|
||||
#define EXEC_ICOUNT_H
|
||||
|
||||
/**
|
||||
* ICountMode: icount enablement state:
|
||||
*
|
||||
* @ICOUNT_DISABLED: Disabled - Do not count executed instructions.
|
||||
* @ICOUNT_PRECISE: Enabled - Fixed conversion of insn to ns via "shift" option
|
||||
* @ICOUNT_ADAPTATIVE: Enabled - Runtime adaptive algorithm to compute shift
|
||||
*/
|
||||
typedef enum {
|
||||
ICOUNT_DISABLED = 0,
|
||||
ICOUNT_PRECISE,
|
||||
ICOUNT_ADAPTATIVE,
|
||||
} ICountMode;
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
extern ICountMode use_icount;
|
||||
#define icount_enabled() (use_icount)
|
||||
#else
|
||||
#define icount_enabled() ICOUNT_DISABLED
|
||||
#endif
|
||||
|
||||
/* Protect the CONFIG_USER_ONLY test vs poisoning. */
|
||||
#if defined(COMPILING_PER_TARGET) || defined(COMPILING_SYSTEM_VS_USER)
|
||||
# ifdef CONFIG_USER_ONLY
|
||||
# undef icount_enabled
|
||||
# define icount_enabled() ICOUNT_DISABLED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update the icount with the executed instructions. Called by
|
||||
* cpus-tcg vCPU thread so the main-loop can see time has moved forward.
|
||||
*/
|
||||
void icount_update(CPUState *cpu);
|
||||
|
||||
/* get raw icount value */
|
||||
int64_t icount_get_raw(void);
|
||||
|
||||
/* return the virtual CPU time in ns, based on the instruction counter. */
|
||||
int64_t icount_get(void);
|
||||
/*
|
||||
* convert an instruction counter value to ns, based on the icount shift.
|
||||
* This shift is set as a fixed value with the icount "shift" option
|
||||
* (precise mode), or it is constantly approximated and corrected at
|
||||
* runtime in adaptive mode.
|
||||
*/
|
||||
int64_t icount_to_ns(int64_t icount);
|
||||
|
||||
/**
|
||||
* icount_configure: configure the icount options, including "shift"
|
||||
* @opts: Options to parse
|
||||
* @errp: pointer to a NULL-initialized error object
|
||||
*
|
||||
* Return: true on success, else false setting @errp with error
|
||||
*/
|
||||
bool icount_configure(QemuOpts *opts, Error **errp);
|
||||
|
||||
/* used by tcg vcpu thread to calc icount budget */
|
||||
int64_t icount_round(int64_t count);
|
||||
|
||||
/* if the CPUs are idle, start accounting real time to virtual clock. */
|
||||
void icount_start_warp_timer(void);
|
||||
void icount_account_warp_timer(void);
|
||||
void icount_notify_exit(void);
|
||||
|
||||
#endif /* EXEC_ICOUNT_H */
|
||||
@@ -0,0 +1,40 @@
|
||||
#ifndef QEMU_EXEC_LOG_H
|
||||
#define QEMU_EXEC_LOG_H
|
||||
|
||||
#include "qemu/log.h"
|
||||
#include "hw/core/cpu.h"
|
||||
#include "disas/disas.h"
|
||||
|
||||
/* cpu_dump_state() logging functions: */
|
||||
/**
|
||||
* log_cpu_state:
|
||||
* @cpu: The CPU whose state is to be logged.
|
||||
* @flags: Flags what to log.
|
||||
*
|
||||
* Logs the output of cpu_dump_state().
|
||||
*/
|
||||
static inline void log_cpu_state(CPUState *cpu, int flags)
|
||||
{
|
||||
FILE *f = qemu_log_trylock();
|
||||
if (f) {
|
||||
cpu_dump_state(cpu, f, flags);
|
||||
qemu_log_unlock(f);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* log_cpu_state_mask:
|
||||
* @mask: Mask when to log.
|
||||
* @cpu: The CPU whose state is to be logged.
|
||||
* @flags: Flags what to log.
|
||||
*
|
||||
* Logs the output of cpu_dump_state() if loglevel includes @mask.
|
||||
*/
|
||||
static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
|
||||
{
|
||||
if (qemu_loglevel & mask) {
|
||||
log_cpu_state(cpu, flags);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Memory transaction attributes
|
||||
*
|
||||
* Copyright (c) 2015 Linaro Limited.
|
||||
*
|
||||
* Authors:
|
||||
* Peter Maydell <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEMATTRS_H
|
||||
#define MEMATTRS_H
|
||||
|
||||
/* Every memory transaction has associated with it a set of
|
||||
* attributes. Some of these are generic (such as the ID of
|
||||
* the bus master); some are specific to a particular kind of
|
||||
* bus (such as the ARM Secure/NonSecure bit). We define them
|
||||
* all as non-overlapping bitfields in a single struct to avoid
|
||||
* confusion if different parts of QEMU used the same bit for
|
||||
* different semantics.
|
||||
*/
|
||||
typedef struct MemTxAttrs {
|
||||
/*
|
||||
* ARM/AMBA: TrustZone Secure access
|
||||
* x86: System Management Mode access
|
||||
*/
|
||||
unsigned int secure:1;
|
||||
/*
|
||||
* ARM: ArmSecuritySpace. This partially overlaps secure, but it is
|
||||
* easier to have both fields to assist code that does not understand
|
||||
* ARMv9 RME, or no specific knowledge of ARM at all (e.g. pflash).
|
||||
*/
|
||||
unsigned int space:2;
|
||||
/* Memory access is usermode (unprivileged) */
|
||||
unsigned int user:1;
|
||||
/*
|
||||
* Bus interconnect and peripherals can access anything (memories,
|
||||
* devices) by default. By setting the 'memory' bit, bus transaction
|
||||
* are restricted to "normal" memories (per the AMBA documentation)
|
||||
* versus devices. Access to devices will be logged and rejected
|
||||
* (see MEMTX_ACCESS_ERROR).
|
||||
*/
|
||||
unsigned int memory:1;
|
||||
/* Debug access that can even write to ROM. */
|
||||
unsigned int debug:1;
|
||||
/* Requester ID (for MSI for example) */
|
||||
unsigned int requester_id:16;
|
||||
|
||||
/*
|
||||
* PID (PCI PASID) support: Limited to 8 bits process identifier.
|
||||
*/
|
||||
unsigned int pid:8;
|
||||
|
||||
/* PCI - IOMMU operations, see PCIAddressType */
|
||||
unsigned int address_type:1;
|
||||
|
||||
/*
|
||||
* Bus masters which don't specify any attributes will get this
|
||||
* (via the MEMTXATTRS_UNSPECIFIED constant), so that we can
|
||||
* distinguish "all attributes deliberately clear" from
|
||||
* "didn't specify" if necessary. "debug" can be set alongside
|
||||
* "unspecified".
|
||||
*/
|
||||
bool unspecified;
|
||||
|
||||
uint8_t _reserved1;
|
||||
uint16_t _reserved2;
|
||||
} MemTxAttrs;
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(MemTxAttrs) > 8);
|
||||
|
||||
/* Bus masters which don't specify any attributes will get this,
|
||||
* which has all attribute bits clear except the topmost one
|
||||
* (so that we can distinguish "all attributes deliberately clear"
|
||||
* from "didn't specify" if necessary).
|
||||
*/
|
||||
#define MEMTXATTRS_UNSPECIFIED ((MemTxAttrs) { .unspecified = true })
|
||||
|
||||
/* New-style MMIO accessors can indicate that the transaction failed.
|
||||
* A zero (MEMTX_OK) response means success; anything else is a failure
|
||||
* of some kind. The memory subsystem will bitwise-OR together results
|
||||
* if it is synthesizing an operation from multiple smaller accesses.
|
||||
*/
|
||||
#define MEMTX_OK 0
|
||||
#define MEMTX_ERROR (1U << 0) /* device returned an error */
|
||||
#define MEMTX_DECODE_ERROR (1U << 1) /* nothing at that address */
|
||||
#define MEMTX_ACCESS_ERROR (1U << 2) /* access denied */
|
||||
typedef uint32_t MemTxResult;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Constants for memory operations
|
||||
*
|
||||
* Authors:
|
||||
* Richard Henderson <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEMOP_H
|
||||
#define MEMOP_H
|
||||
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
typedef enum MemOp {
|
||||
MO_8 = 0,
|
||||
MO_16 = 1,
|
||||
MO_32 = 2,
|
||||
MO_64 = 3,
|
||||
MO_128 = 4,
|
||||
MO_256 = 5,
|
||||
MO_512 = 6,
|
||||
MO_1024 = 7,
|
||||
MO_SIZE = 0x07, /* Mask for the above. */
|
||||
|
||||
MO_SIGN = 0x08, /* Sign-extended, otherwise zero-extended. */
|
||||
|
||||
MO_BSWAP = 0x10, /* Host reverse endian. */
|
||||
#if HOST_BIG_ENDIAN
|
||||
MO_LE = MO_BSWAP,
|
||||
MO_BE = 0,
|
||||
#else
|
||||
MO_LE = 0,
|
||||
MO_BE = MO_BSWAP,
|
||||
#endif
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
#ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
|
||||
#if TARGET_BIG_ENDIAN
|
||||
MO_TE = MO_BE,
|
||||
#else
|
||||
MO_TE = MO_LE,
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* MO_UNALN accesses are never checked for alignment.
|
||||
* MO_ALIGN accesses will result in a call to the CPU's
|
||||
* do_unaligned_access hook if the guest address is not aligned.
|
||||
*
|
||||
* Some architectures (e.g. ARMv8) need the address which is aligned
|
||||
* to a size more than the size of the memory access.
|
||||
* Some architectures (e.g. SPARCv9) need an address which is aligned,
|
||||
* but less strictly than the natural alignment.
|
||||
*
|
||||
* MO_ALIGN supposes the alignment size is the size of a memory access.
|
||||
*
|
||||
* There are three options:
|
||||
* - unaligned access permitted (MO_UNALN).
|
||||
* - an alignment to the size of an access (MO_ALIGN);
|
||||
* - an alignment to a specified size, which may be more or less than
|
||||
* the access size (MO_ALIGN_x where 'x' is a size in bytes);
|
||||
*/
|
||||
MO_ASHIFT = 5,
|
||||
MO_AMASK = 0x7 << MO_ASHIFT,
|
||||
MO_UNALN = 0,
|
||||
MO_ALIGN_2 = 1 << MO_ASHIFT,
|
||||
MO_ALIGN_4 = 2 << MO_ASHIFT,
|
||||
MO_ALIGN_8 = 3 << MO_ASHIFT,
|
||||
MO_ALIGN_16 = 4 << MO_ASHIFT,
|
||||
MO_ALIGN_32 = 5 << MO_ASHIFT,
|
||||
MO_ALIGN_64 = 6 << MO_ASHIFT,
|
||||
MO_ALIGN = MO_AMASK,
|
||||
|
||||
/*
|
||||
* MO_ALIGN_TLB_ONLY:
|
||||
* Apply MO_AMASK only along the TCG slow path if TLB_CHECK_ALIGNED
|
||||
* is set; otherwise unaligned access is permitted.
|
||||
* This is used by target/arm, where unaligned accesses are
|
||||
* permitted for pages marked Normal but aligned accesses are
|
||||
* required for pages marked Device.
|
||||
*/
|
||||
MO_ALIGN_TLB_ONLY = 1 << 8,
|
||||
|
||||
/*
|
||||
* MO_ATOM_* describes the atomicity requirements of the operation:
|
||||
* MO_ATOM_IFALIGN: the operation must be single-copy atomic if it
|
||||
* is aligned; if unaligned there is no atomicity.
|
||||
* MO_ATOM_IFALIGN_PAIR: the entire operation may be considered to
|
||||
* be a pair of half-sized operations which are packed together
|
||||
* for convenience, with single-copy atomicity on each half if
|
||||
* the half is aligned.
|
||||
* This is the atomicity e.g. of Arm pre-FEAT_LSE2 LDP.
|
||||
* MO_ATOM_WITHIN16: the operation is single-copy atomic, even if it
|
||||
* is unaligned, so long as it does not cross a 16-byte boundary;
|
||||
* if it crosses a 16-byte boundary there is no atomicity.
|
||||
* This is the atomicity e.g. of Arm FEAT_LSE2 LDR.
|
||||
* MO_ATOM_WITHIN16_PAIR: the entire operation is single-copy atomic,
|
||||
* if it happens to be within a 16-byte boundary, otherwise it
|
||||
* devolves to a pair of half-sized MO_ATOM_WITHIN16 operations.
|
||||
* Depending on alignment, one or both will be single-copy atomic.
|
||||
* This is the atomicity e.g. of Arm FEAT_LSE2 LDP.
|
||||
* MO_ATOM_SUBALIGN: the operation is single-copy atomic by parts
|
||||
* by the alignment. E.g. if an 8-byte value is accessed at an
|
||||
* address which is 0 mod 8, then the whole 8-byte access is
|
||||
* single-copy atomic; otherwise, if it is accessed at 0 mod 4
|
||||
* then each 4-byte subobject is single-copy atomic; otherwise
|
||||
* if it is accessed at 0 mod 2 then the four 2-byte subobjects
|
||||
* are single-copy atomic.
|
||||
* This is the atomicity e.g. of IBM Power.
|
||||
* MO_ATOM_NONE: the operation has no atomicity requirements.
|
||||
*
|
||||
* Note the default (i.e. 0) value is single-copy atomic to the
|
||||
* size of the operation, if aligned. This retains the behaviour
|
||||
* from before this field was introduced.
|
||||
*/
|
||||
MO_ATOM_SHIFT = 9,
|
||||
MO_ATOM_IFALIGN = 0 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_IFALIGN_PAIR = 1 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_WITHIN16 = 2 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_WITHIN16_PAIR = 3 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_SUBALIGN = 4 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_NONE = 5 << MO_ATOM_SHIFT,
|
||||
MO_ATOM_MASK = 7 << MO_ATOM_SHIFT,
|
||||
|
||||
/* Combinations of the above, for ease of use. */
|
||||
MO_UB = MO_8,
|
||||
MO_UW = MO_16,
|
||||
MO_UL = MO_32,
|
||||
MO_UQ = MO_64,
|
||||
MO_UO = MO_128,
|
||||
MO_SB = MO_SIGN | MO_8,
|
||||
MO_SW = MO_SIGN | MO_16,
|
||||
MO_SL = MO_SIGN | MO_32,
|
||||
MO_SQ = MO_SIGN | MO_64,
|
||||
MO_SO = MO_SIGN | MO_128,
|
||||
|
||||
MO_LEUW = MO_LE | MO_UW,
|
||||
MO_LEUL = MO_LE | MO_UL,
|
||||
MO_LEUQ = MO_LE | MO_UQ,
|
||||
MO_LESW = MO_LE | MO_SW,
|
||||
MO_LESL = MO_LE | MO_SL,
|
||||
MO_LESQ = MO_LE | MO_SQ,
|
||||
|
||||
MO_BEUW = MO_BE | MO_UW,
|
||||
MO_BEUL = MO_BE | MO_UL,
|
||||
MO_BEUQ = MO_BE | MO_UQ,
|
||||
MO_BESW = MO_BE | MO_SW,
|
||||
MO_BESL = MO_BE | MO_SL,
|
||||
MO_BESQ = MO_BE | MO_SQ,
|
||||
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
#ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
|
||||
MO_TEUW = MO_TE | MO_UW,
|
||||
MO_TEUL = MO_TE | MO_UL,
|
||||
MO_TEUQ = MO_TE | MO_UQ,
|
||||
MO_TEUO = MO_TE | MO_UO,
|
||||
MO_TESW = MO_TE | MO_SW,
|
||||
MO_TESL = MO_TE | MO_SL,
|
||||
MO_TESQ = MO_TE | MO_SQ,
|
||||
#endif
|
||||
#endif
|
||||
|
||||
MO_SSIZE = MO_SIZE | MO_SIGN,
|
||||
} MemOp;
|
||||
|
||||
/* MemOp to size in bytes. */
|
||||
static inline unsigned memop_size(MemOp op)
|
||||
{
|
||||
return 1 << (op & MO_SIZE);
|
||||
}
|
||||
|
||||
/* Size in bytes to MemOp. */
|
||||
static inline MemOp size_memop(unsigned size)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
/* Power of 2 up to 1024 */
|
||||
assert(is_power_of_2(size) && size >= 1 && size <= (1 << MO_SIZE));
|
||||
#endif
|
||||
return (MemOp)ctz32(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* memop_tlb_alignment_bits:
|
||||
* @memop: MemOp value
|
||||
*
|
||||
* Extract the alignment size for use with TLB_CHECK_ALIGNED.
|
||||
*/
|
||||
static inline unsigned memop_tlb_alignment_bits(MemOp memop, bool tlb_check)
|
||||
{
|
||||
unsigned a = memop & MO_AMASK;
|
||||
|
||||
if (a == MO_UNALN || (!tlb_check && (memop & MO_ALIGN_TLB_ONLY))) {
|
||||
/* No alignment required. */
|
||||
a = 0;
|
||||
} else if (a == MO_ALIGN) {
|
||||
/* A natural alignment requirement. */
|
||||
a = memop & MO_SIZE;
|
||||
} else {
|
||||
/* A specific alignment requirement. */
|
||||
a = a >> MO_ASHIFT;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* memop_alignment_bits:
|
||||
* @memop: MemOp value
|
||||
*
|
||||
* Extract the alignment size from the memop.
|
||||
*/
|
||||
static inline unsigned memop_alignment_bits(MemOp memop)
|
||||
{
|
||||
return memop_tlb_alignment_bits(memop, false);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Combine the MemOp and mmu_idx parameters into a single value.
|
||||
*
|
||||
* Authors:
|
||||
* Richard Henderson <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef EXEC_MEMOPIDX_H
|
||||
#define EXEC_MEMOPIDX_H
|
||||
|
||||
#include "exec/memop.h"
|
||||
|
||||
typedef uint32_t MemOpIdx;
|
||||
|
||||
/**
|
||||
* make_memop_idx
|
||||
* @op: memory operation
|
||||
* @idx: mmu index
|
||||
*
|
||||
* Encode these values into a single parameter.
|
||||
*/
|
||||
static inline MemOpIdx make_memop_idx(MemOp op, unsigned idx)
|
||||
{
|
||||
#ifdef CONFIG_DEBUG_TCG
|
||||
assert(idx <= 31);
|
||||
assert(clz32(op) >= 5);
|
||||
#endif
|
||||
return (op << 5) | idx;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_memop
|
||||
* @oi: combined op/idx parameter
|
||||
*
|
||||
* Extract the memory operation from the combined value.
|
||||
*/
|
||||
static inline MemOp get_memop(MemOpIdx oi)
|
||||
{
|
||||
return oi >> 5;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_mmuidx
|
||||
* @oi: combined op/idx parameter
|
||||
*
|
||||
* Extract the mmu index from the combined value.
|
||||
*/
|
||||
static inline unsigned get_mmuidx(MemOpIdx oi)
|
||||
{
|
||||
return oi & 31;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* QEMU user-only mmap lock, with stubs for system mode
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
#ifndef EXEC_MMAP_LOCK_H
|
||||
#define EXEC_MMAP_LOCK_H
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
||||
void TSA_NO_TSA mmap_lock(void);
|
||||
void TSA_NO_TSA mmap_unlock(void);
|
||||
bool have_mmap_lock(void);
|
||||
|
||||
static inline void mmap_unlock_guard(void *unused)
|
||||
{
|
||||
mmap_unlock();
|
||||
}
|
||||
|
||||
#define WITH_MMAP_LOCK_GUARD() \
|
||||
for (int _mmap_lock_iter __attribute__((cleanup(mmap_unlock_guard))) \
|
||||
= (mmap_lock(), 0); _mmap_lock_iter == 0; _mmap_lock_iter = 1)
|
||||
|
||||
#else
|
||||
|
||||
static inline void mmap_lock(void) {}
|
||||
static inline void mmap_unlock(void) {}
|
||||
#define WITH_MMAP_LOCK_GUARD()
|
||||
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
#endif /* EXEC_MMAP_LOCK_H */
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* QEMU MMU Access type definitions
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef EXEC_MMU_ACCESS_TYPE_H
|
||||
#define EXEC_MMU_ACCESS_TYPE_H
|
||||
|
||||
typedef enum MMUAccessType {
|
||||
MMU_DATA_LOAD = 0,
|
||||
MMU_DATA_STORE = 1,
|
||||
MMU_INST_FETCH = 2
|
||||
#define MMU_ACCESS_COUNT 3
|
||||
} MMUAccessType;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* QEMU page protection definitions.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1+
|
||||
*/
|
||||
#ifndef EXEC_PAGE_PROT_COMMON_H
|
||||
#define EXEC_PAGE_PROT_COMMON_H
|
||||
|
||||
/* same as PROT_xxx */
|
||||
#define PAGE_READ 0x0001
|
||||
#define PAGE_WRITE 0x0002
|
||||
#define PAGE_EXEC 0x0004
|
||||
#define PAGE_RWX (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
|
||||
#define PAGE_VALID 0x0008
|
||||
/*
|
||||
* Original state of the write flag (used when tracking self-modifying code)
|
||||
*/
|
||||
#define PAGE_WRITE_ORG 0x0010
|
||||
/*
|
||||
* Invalidate the TLB entry immediately, helpful for s390x
|
||||
* Low-Address-Protection. Used with PAGE_WRITE in tlb_set_page_with_attrs()
|
||||
*/
|
||||
#define PAGE_WRITE_INV 0x0020
|
||||
/*
|
||||
* For linux-user, indicates that the page is mapped with the same semantics
|
||||
* in both guest and host.
|
||||
*/
|
||||
#define PAGE_PASSTHROUGH 0x40
|
||||
/* For linux-user, indicates that the page is MAP_ANON. */
|
||||
#define PAGE_ANON 0x0080
|
||||
/*
|
||||
* For linux-user, indicates that the page should not be
|
||||
* included in a core dump.
|
||||
*/
|
||||
#define PAGE_DONTDUMP 0x0100
|
||||
/* Target-specific bits that will be used via page_get_flags(). */
|
||||
#define PAGE_TARGET_1 0x0200
|
||||
#define PAGE_TARGET_2 0x0400
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Definitions for cpus with variable page sizes.
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef EXEC_PAGE_VARY_H
|
||||
#define EXEC_PAGE_VARY_H
|
||||
|
||||
/*
|
||||
* For system mode, the minimum comes from the number of bits
|
||||
* required for maximum alignment (6) and the number of bits
|
||||
* required for TLB_FLAGS_MASK (3).
|
||||
*
|
||||
* For user mode, TARGET_PAGE_BITS_VARY is a hack to allow the target
|
||||
* page size to match the host page size. Mostly, this reduces the
|
||||
* ordinary target page size to run on a host with 4KiB pages (i.e. x86).
|
||||
* There is no true minimum required by the implementation, but keep the
|
||||
* same minimum as for system mode for sanity.
|
||||
* See linux-user/mmap.c, mmap_h_lt_g and mmap_h_gt_g.
|
||||
*/
|
||||
#define TARGET_PAGE_BITS_MIN 9
|
||||
|
||||
typedef struct {
|
||||
bool decided;
|
||||
int bits;
|
||||
uint64_t mask;
|
||||
} TargetPageBits;
|
||||
|
||||
/**
|
||||
* set_preferred_target_page_bits:
|
||||
* @bits: number of bits needed to represent an address within the page
|
||||
*
|
||||
* Set the preferred target page size (the actual target page
|
||||
* size may be smaller than any given CPU's preference).
|
||||
* Returns true on success, false on failure (which can only happen
|
||||
* if this is called after the system has already finalized its
|
||||
* choice of page size and the requested page size is smaller than that).
|
||||
*/
|
||||
bool set_preferred_target_page_bits(int bits);
|
||||
|
||||
/**
|
||||
* finalize_target_page_bits:
|
||||
* Commit the final value set by set_preferred_target_page_bits.
|
||||
*/
|
||||
void finalize_target_page_bits(void);
|
||||
|
||||
/**
|
||||
* migration_legacy_page_bits
|
||||
*
|
||||
* For migration compatibility with qemu v2.9, prior to the introduction
|
||||
* of the configuration/target-page-bits section, return the value of
|
||||
* TARGET_PAGE_BITS that the target had then.
|
||||
*/
|
||||
int migration_legacy_page_bits(void);
|
||||
|
||||
#endif /* EXEC_PAGE_VARY_H */
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (C) 2017, Emilio G. Cota <[email protected]>
|
||||
*
|
||||
* License: GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*
|
||||
* plugin-gen.h - TCG-dependent definitions for generating plugin code
|
||||
*
|
||||
* This header should be included only from plugin.c and C files that emit
|
||||
* TCG code.
|
||||
*/
|
||||
#ifndef QEMU_PLUGIN_GEN_H
|
||||
#define QEMU_PLUGIN_GEN_H
|
||||
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
struct DisasContextBase;
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db);
|
||||
void plugin_gen_tb_end(CPUState *cpu, size_t num_insns);
|
||||
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
|
||||
void plugin_gen_insn_end(void);
|
||||
|
||||
void plugin_gen_disable_mem_helpers(void);
|
||||
|
||||
#else /* !CONFIG_PLUGIN */
|
||||
|
||||
static inline
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
static inline
|
||||
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db)
|
||||
{ }
|
||||
|
||||
static inline void plugin_gen_insn_end(void)
|
||||
{ }
|
||||
|
||||
static inline void plugin_gen_tb_end(CPUState *cpu, size_t num_insns)
|
||||
{ }
|
||||
|
||||
static inline void plugin_gen_disable_mem_helpers(void)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_PLUGIN */
|
||||
|
||||
#endif /* QEMU_PLUGIN_GEN_H */
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
/* Poison identifiers that should not be used when building
|
||||
target independent device code. */
|
||||
|
||||
#ifndef HW_POISON_H
|
||||
#define HW_POISON_H
|
||||
|
||||
#include "config-poison.h"
|
||||
|
||||
#pragma GCC poison TARGET_I386
|
||||
#pragma GCC poison TARGET_X86_64
|
||||
#pragma GCC poison TARGET_AARCH64
|
||||
#pragma GCC poison TARGET_ALPHA
|
||||
#pragma GCC poison TARGET_ARM
|
||||
#pragma GCC poison TARGET_HEXAGON
|
||||
#pragma GCC poison TARGET_HPPA
|
||||
#pragma GCC poison TARGET_LOONGARCH64
|
||||
#pragma GCC poison TARGET_M68K
|
||||
#pragma GCC poison TARGET_MICROBLAZE
|
||||
#pragma GCC poison TARGET_MIPS
|
||||
#pragma GCC poison TARGET_ABI_MIPSN32
|
||||
#pragma GCC poison TARGET_ABI_MIPSO32
|
||||
#pragma GCC poison TARGET_MIPS64
|
||||
#pragma GCC poison TARGET_ABI_MIPSN64
|
||||
#pragma GCC poison TARGET_OR1K
|
||||
#pragma GCC poison TARGET_PPC
|
||||
#pragma GCC poison TARGET_PPC64
|
||||
#pragma GCC poison TARGET_ABI32
|
||||
#pragma GCC poison TARGET_RX
|
||||
#pragma GCC poison TARGET_S390X
|
||||
#pragma GCC poison TARGET_SH4
|
||||
#pragma GCC poison TARGET_SPARC
|
||||
#pragma GCC poison TARGET_SPARC64
|
||||
#pragma GCC poison TARGET_TRICORE
|
||||
#pragma GCC poison TARGET_XTENSA
|
||||
|
||||
#pragma GCC poison TARGET_HAS_BFLT
|
||||
#pragma GCC poison TARGET_NAME
|
||||
#pragma GCC poison TARGET_BIG_ENDIAN
|
||||
#pragma GCC poison TCG_GUEST_DEFAULT_MO
|
||||
|
||||
#pragma GCC poison TARGET_LONG_BITS
|
||||
#pragma GCC poison TARGET_FMT_lx
|
||||
#pragma GCC poison TARGET_FMT_ld
|
||||
#pragma GCC poison TARGET_FMT_lu
|
||||
|
||||
#pragma GCC poison TARGET_PHYS_ADDR_SPACE_BITS
|
||||
|
||||
#pragma GCC poison CONFIG_ALPHA_DIS
|
||||
#pragma GCC poison CONFIG_HPPA_DIS
|
||||
#pragma GCC poison CONFIG_I386_DIS
|
||||
#pragma GCC poison CONFIG_HEXAGON_DIS
|
||||
#pragma GCC poison CONFIG_LOONGARCH_DIS
|
||||
#pragma GCC poison CONFIG_M68K_DIS
|
||||
#pragma GCC poison CONFIG_MICROBLAZE_DIS
|
||||
#pragma GCC poison CONFIG_MIPS_DIS
|
||||
#pragma GCC poison CONFIG_PPC_DIS
|
||||
#pragma GCC poison CONFIG_RISCV_DIS
|
||||
#pragma GCC poison CONFIG_S390_DIS
|
||||
#pragma GCC poison CONFIG_SH4_DIS
|
||||
#pragma GCC poison CONFIG_SPARC_DIS
|
||||
#pragma GCC poison CONFIG_XTENSA_DIS
|
||||
|
||||
#pragma GCC poison CONFIG_HVF
|
||||
#pragma GCC poison CONFIG_LINUX_USER
|
||||
#pragma GCC poison CONFIG_KVM
|
||||
#pragma GCC poison CONFIG_WHPX
|
||||
#pragma GCC poison CONFIG_XEN
|
||||
|
||||
#ifndef COMPILING_SYSTEM_VS_USER
|
||||
#pragma GCC poison CONFIG_USER_ONLY
|
||||
#pragma GCC poison CONFIG_SOFTMMU
|
||||
#endif
|
||||
|
||||
#pragma GCC poison KVM_HAVE_MCE_INJECTION
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* QEMU replay core API
|
||||
*
|
||||
* Copyright (c) 2010-2015 Institute for System Programming
|
||||
* of the Russian Academy of Sciences.
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef EXEC_REPLAY_H
|
||||
#define EXEC_REPLAY_H
|
||||
|
||||
#include "qapi/qapi-types-replay.h"
|
||||
|
||||
extern ReplayMode replay_mode;
|
||||
|
||||
/* Replay process control functions */
|
||||
|
||||
/* Enables recording or saving event log with specified parameters */
|
||||
void replay_configure(struct QemuOpts *opts);
|
||||
/* Initializes timers used for snapshotting and enables events recording */
|
||||
void replay_start(void);
|
||||
/* Closes replay log file and frees other resources. */
|
||||
void replay_finish(void);
|
||||
/* Adds replay blocker with the specified error description */
|
||||
void replay_add_blocker(const char *feature);
|
||||
/* Returns name of the replay log file */
|
||||
const char *replay_get_filename(void);
|
||||
|
||||
/*
|
||||
* Start making one step in backward direction.
|
||||
* Used by gdbstub for backwards debugging.
|
||||
* Returns true on success.
|
||||
*/
|
||||
bool replay_reverse_step(void);
|
||||
/*
|
||||
* Start searching the last breakpoint/watchpoint.
|
||||
* Used by gdbstub for backwards debugging.
|
||||
* Returns true if the process successfully started.
|
||||
*/
|
||||
bool replay_reverse_continue(void);
|
||||
/*
|
||||
* Returns true if replay module is processing
|
||||
* reverse_continue or reverse_step request
|
||||
*/
|
||||
bool replay_running_debug(void);
|
||||
/* Called in reverse debugging mode to collect breakpoint information */
|
||||
void replay_breakpoint(void);
|
||||
/* Called when gdb is attached to gdbstub */
|
||||
void replay_gdb_attached(void);
|
||||
|
||||
/* Interrupts and exceptions */
|
||||
|
||||
/* Called by exception handler to write or read exception processing events */
|
||||
bool replay_exception(void);
|
||||
/*
|
||||
* Used to determine that exception is pending.
|
||||
* Does not proceed to the next event in the log.
|
||||
*/
|
||||
bool replay_has_exception(void);
|
||||
/*
|
||||
* Called by interrupt handlers to write or read interrupt processing events.
|
||||
* Returns true if interrupt should be processed.
|
||||
*/
|
||||
bool replay_interrupt(void);
|
||||
/*
|
||||
* Tries to read interrupt event from the file.
|
||||
* Returns true, when interrupt request is pending.
|
||||
*/
|
||||
bool replay_has_interrupt(void);
|
||||
|
||||
/* Processing data from random generators */
|
||||
|
||||
/* Saves the values from the random number generator */
|
||||
void replay_save_random(int ret, void *buf, size_t len);
|
||||
/* Loads the saved values for the random number generator */
|
||||
int replay_read_random(void *buf, size_t len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Target Long Definitions
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
* Copyright (c) 2023 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _TARGET_LONG_H_
|
||||
#define _TARGET_LONG_H_
|
||||
|
||||
/*
|
||||
* Usually this should only be included via cpu-defs.h however for
|
||||
* certain cases where we want to build only two versions of a binary
|
||||
* object we can include directly. However the build-system must
|
||||
* ensure TARGET_LONG_BITS is defined directly.
|
||||
*/
|
||||
#ifndef TARGET_LONG_BITS
|
||||
#error TARGET_LONG_BITS not defined
|
||||
#endif
|
||||
|
||||
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
|
||||
|
||||
/* target_ulong is the type of a virtual address */
|
||||
#if TARGET_LONG_SIZE == 4
|
||||
typedef int32_t target_long;
|
||||
typedef uint32_t target_ulong;
|
||||
#define TARGET_FMT_lx "%08x"
|
||||
#define TARGET_FMT_ld "%d"
|
||||
#define TARGET_FMT_lu "%u"
|
||||
#define MO_TL MO_32
|
||||
#elif TARGET_LONG_SIZE == 8
|
||||
typedef int64_t target_long;
|
||||
typedef uint64_t target_ulong;
|
||||
#define TARGET_FMT_lx "%016" PRIx64
|
||||
#define TARGET_FMT_ld "%" PRId64
|
||||
#define TARGET_FMT_lu "%" PRIu64
|
||||
#define MO_TL MO_64
|
||||
#else
|
||||
#error TARGET_LONG_SIZE undefined
|
||||
#endif
|
||||
|
||||
#endif /* _TARGET_LONG_H_ */
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Target page sizes and friends for non target files
|
||||
*
|
||||
* Copyright (c) 2017 Red Hat Inc
|
||||
*
|
||||
* Authors:
|
||||
* David Alan Gilbert <[email protected]>
|
||||
* Juan Quintela <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef EXEC_TARGET_PAGE_H
|
||||
#define EXEC_TARGET_PAGE_H
|
||||
|
||||
/*
|
||||
* If compiling per-target, get the real values.
|
||||
* For generic code, reuse the mechanism for variable page size.
|
||||
*/
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
#include "cpu-param.h"
|
||||
#include "exec/target_long.h"
|
||||
#define TARGET_PAGE_TYPE target_long
|
||||
#else
|
||||
#define TARGET_PAGE_BITS_VARY
|
||||
#define TARGET_PAGE_TYPE int
|
||||
#endif
|
||||
|
||||
#ifdef TARGET_PAGE_BITS_VARY
|
||||
# include "exec/page-vary.h"
|
||||
extern const TargetPageBits target_page;
|
||||
# ifdef CONFIG_DEBUG_TCG
|
||||
# define TARGET_PAGE_BITS ({ assert(target_page.decided); \
|
||||
target_page.bits; })
|
||||
# define TARGET_PAGE_MASK ({ assert(target_page.decided); \
|
||||
(TARGET_PAGE_TYPE)target_page.mask; })
|
||||
# else
|
||||
# define TARGET_PAGE_BITS target_page.bits
|
||||
# define TARGET_PAGE_MASK ((TARGET_PAGE_TYPE)target_page.mask)
|
||||
# endif
|
||||
# define TARGET_PAGE_SIZE (-(int)TARGET_PAGE_MASK)
|
||||
#else
|
||||
# define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
|
||||
# define TARGET_PAGE_MASK ((TARGET_PAGE_TYPE)-1 << TARGET_PAGE_BITS)
|
||||
#endif
|
||||
|
||||
#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
|
||||
|
||||
static inline size_t qemu_target_page_size(void)
|
||||
{
|
||||
return TARGET_PAGE_SIZE;
|
||||
}
|
||||
|
||||
static inline int qemu_target_page_mask(void)
|
||||
{
|
||||
return TARGET_PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline int qemu_target_page_bits(void)
|
||||
{
|
||||
return TARGET_PAGE_BITS;
|
||||
}
|
||||
|
||||
/* Convert target pages to MiB (2**20). */
|
||||
static inline size_t qemu_target_pages_to_MiB(size_t pages)
|
||||
{
|
||||
int page_bits = TARGET_PAGE_BITS;
|
||||
|
||||
/* So far, the largest (non-huge) page size is 64k, i.e. 16 bits. */
|
||||
g_assert(page_bits < 20);
|
||||
|
||||
return pages >> (20 - page_bits);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* tb-flush prototype for use by the rest of the system.
|
||||
*
|
||||
* Copyright (c) 2022 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
#ifndef _TB_FLUSH_H_
|
||||
#define _TB_FLUSH_H_
|
||||
|
||||
/**
|
||||
* tb_flush__exclusive_or_serial()
|
||||
*
|
||||
* Used to flush all the translation blocks in the system. Mostly this is
|
||||
* used to empty the code generation buffer after it is full. Sometimes it
|
||||
* is used when it is simpler to flush everything than work out which
|
||||
* individual translations are now invalid.
|
||||
*
|
||||
* Must be called from an exclusive or serial context, e.g. start_exclusive,
|
||||
* vm_stop, or when there is only one vcpu. Note that start_exclusive cannot
|
||||
* be called from within the cpu run loop, so this cannot be called from
|
||||
* within target code.
|
||||
*/
|
||||
void tb_flush__exclusive_or_serial(void);
|
||||
|
||||
/**
|
||||
* queue_tb_flush() - add flush to the cpu work queue
|
||||
* @cs: CPUState
|
||||
*
|
||||
* Flush all translation blocks the next time @cs processes the work queue.
|
||||
* This should generally be followed by cpu_loop_exit(), so that the work
|
||||
* queue is processed promptly.
|
||||
*/
|
||||
void queue_tb_flush(CPUState *cs);
|
||||
|
||||
void tcg_flush_jmp_cache(CPUState *cs);
|
||||
|
||||
#endif /* _TB_FLUSH_H_ */
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Common definitions for the softmmu tlb
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef EXEC_TLB_COMMON_H
|
||||
#define EXEC_TLB_COMMON_H 1
|
||||
|
||||
#define CPU_TLB_ENTRY_BITS (HOST_LONG_BITS == 32 ? 4 : 5)
|
||||
|
||||
/* Minimalized TLB entry for use by TCG fast path. */
|
||||
typedef union CPUTLBEntry {
|
||||
struct {
|
||||
uintptr_t addr_read;
|
||||
uintptr_t addr_write;
|
||||
uintptr_t addr_code;
|
||||
/*
|
||||
* Addend to virtual address to get host address. IO accesses
|
||||
* use the corresponding iotlb value.
|
||||
*/
|
||||
uintptr_t addend;
|
||||
};
|
||||
/*
|
||||
* Padding to get a power of two size, as well as index
|
||||
* access to addr_{read,write,code}.
|
||||
*/
|
||||
uintptr_t addr_idx[(1 << CPU_TLB_ENTRY_BITS) / sizeof(uintptr_t)];
|
||||
} CPUTLBEntry;
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
|
||||
|
||||
/*
|
||||
* Data elements that are per MMU mode, accessed by the fast path.
|
||||
* The structure is aligned to aid loading the pair with one insn.
|
||||
*/
|
||||
typedef struct CPUTLBDescFast {
|
||||
/* Contains (n_entries - 1) << CPU_TLB_ENTRY_BITS */
|
||||
uintptr_t mask;
|
||||
/* The array of tlb entries itself. */
|
||||
CPUTLBEntry *table;
|
||||
} CPUTLBDescFast QEMU_ALIGNED(2 * sizeof(void *));
|
||||
|
||||
#endif /* EXEC_TLB_COMMON_H */
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* TLB flags definition
|
||||
*
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#ifndef TLB_FLAGS_H
|
||||
#define TLB_FLAGS_H
|
||||
|
||||
/*
|
||||
* Flags returned for lookup of a TLB virtual address.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
||||
/*
|
||||
* Allow some level of source compatibility with softmmu.
|
||||
* INVALID is set when the page does not have requested permissions.
|
||||
* FORCE_SLOW is set when we want the target helper to use the functional
|
||||
* interface for load/store so that plugins see the access.
|
||||
*/
|
||||
#define TLB_INVALID_MASK (1 << 0)
|
||||
#define TLB_FORCE_SLOW (1 << 1)
|
||||
#define TLB_MMIO 0
|
||||
#define TLB_WATCHPOINT 0
|
||||
|
||||
#else
|
||||
|
||||
/*
|
||||
* Flags stored in CPUTLBEntryFull.slow_flags[x].
|
||||
* TLB_FORCE_SLOW must be set in CPUTLBEntry.addr_idx[x].
|
||||
*/
|
||||
|
||||
/* Set if TLB entry requires byte swap. */
|
||||
#define TLB_BSWAP (1 << 0)
|
||||
/* Set if TLB entry contains a watchpoint. */
|
||||
#define TLB_WATCHPOINT (1 << 1)
|
||||
/* Set if TLB entry requires aligned accesses. */
|
||||
#define TLB_CHECK_ALIGNED (1 << 2)
|
||||
/* Set if TLB entry writes ignored. */
|
||||
#define TLB_DISCARD_WRITE (1 << 3)
|
||||
/* Set if TLB entry is an IO callback. */
|
||||
#define TLB_MMIO (1 << 4)
|
||||
|
||||
#define TLB_SLOW_FLAGS_MASK \
|
||||
(TLB_BSWAP | TLB_WATCHPOINT | TLB_CHECK_ALIGNED | \
|
||||
TLB_DISCARD_WRITE | TLB_MMIO)
|
||||
|
||||
/*
|
||||
* Flags stored in CPUTLBEntry.addr_idx[x].
|
||||
* These must be above the largest alignment (64 bytes),
|
||||
* and below the smallest page size (1024 bytes).
|
||||
* This leaves bits [9:6] available for use.
|
||||
*/
|
||||
|
||||
/* Zero if TLB entry is valid. */
|
||||
#define TLB_INVALID_MASK (1 << 6)
|
||||
/* Set if TLB entry references a clean RAM page. */
|
||||
#define TLB_NOTDIRTY (1 << 7)
|
||||
/* Set if the slow path must be used; more flags in CPUTLBEntryFull. */
|
||||
#define TLB_FORCE_SLOW (1 << 8)
|
||||
|
||||
/*
|
||||
* Use this mask to check interception with an alignment mask
|
||||
* in a TCG backend.
|
||||
*/
|
||||
#define TLB_FLAGS_MASK \
|
||||
(TLB_INVALID_MASK | TLB_NOTDIRTY | TLB_FORCE_SLOW)
|
||||
|
||||
/* The two sets of flags must not overlap. */
|
||||
QEMU_BUILD_BUG_ON(TLB_FLAGS_MASK & TLB_SLOW_FLAGS_MASK);
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
#endif /* TLB_FLAGS_H */
|
||||
@@ -0,0 +1,217 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
/*
|
||||
* Definition of TranslationBlock.
|
||||
* Copyright (c) 2003 Fabrice Bellard
|
||||
*/
|
||||
|
||||
#ifndef EXEC_TRANSLATION_BLOCK_H
|
||||
#define EXEC_TRANSLATION_BLOCK_H
|
||||
|
||||
#include "qemu/atomic.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/vaddr.h"
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#include "qemu/interval-tree.h"
|
||||
#include "exec/target_page.h"
|
||||
#else
|
||||
#include "system/ram_addr.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Page tracking code uses ram addresses in system mode, and virtual
|
||||
* addresses in userspace mode. Define tb_page_addr_t to be an
|
||||
* appropriate type.
|
||||
*/
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
typedef vaddr tb_page_addr_t;
|
||||
#define TB_PAGE_ADDR_FMT "%" VADDR_PRIx
|
||||
#else
|
||||
typedef ram_addr_t tb_page_addr_t;
|
||||
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Translation Cache-related fields of a TB.
|
||||
* This struct exists just for convenience; we keep track of TB's in a binary
|
||||
* search tree, and the only fields needed to compare TB's in the tree are
|
||||
* @ptr and @size.
|
||||
* Note: the address of search data can be obtained by adding @size to @ptr.
|
||||
*/
|
||||
struct tb_tc {
|
||||
const void *ptr; /* pointer to the translated code */
|
||||
size_t size;
|
||||
};
|
||||
|
||||
struct TranslationBlock {
|
||||
/*
|
||||
* Guest PC corresponding to this block. This must be the true
|
||||
* virtual address. Therefore e.g. x86 stores EIP + CS_BASE, and
|
||||
* targets like Arm, MIPS, HP-PA, which reuse low bits for ISA or
|
||||
* privilege, must store those bits elsewhere.
|
||||
*
|
||||
* If CF_PCREL, the opcodes for the TranslationBlock are written
|
||||
* such that the TB is associated only with the physical page and
|
||||
* may be run in any virtual address context. In this case, PC
|
||||
* must always be taken from ENV in a target-specific manner.
|
||||
* Unwind information is taken as offsets from the page, to be
|
||||
* deposited into the "current" PC.
|
||||
*/
|
||||
vaddr pc;
|
||||
|
||||
/*
|
||||
* Target-specific data associated with the TranslationBlock, e.g.:
|
||||
* x86: the original user, the Code Segment virtual base,
|
||||
* arm: an extension of tb->flags,
|
||||
* s390x: instruction data for EXECUTE,
|
||||
* sparc: the next pc of the instruction queue (for delay slots).
|
||||
* riscv: an extension of tb->flags,
|
||||
*/
|
||||
uint64_t cs_base;
|
||||
|
||||
uint32_t flags; /* flags defining in which context the code was generated */
|
||||
uint32_t cflags; /* compile flags */
|
||||
|
||||
/* Note that TCG_MAX_INSNS is 512; we validate this match elsewhere. */
|
||||
#define CF_COUNT_MASK 0x000001ff
|
||||
#define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */
|
||||
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
|
||||
#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
|
||||
#define CF_MEMI_ONLY 0x00001000 /* Only instrument memory ops */
|
||||
#define CF_USE_ICOUNT 0x00002000
|
||||
#define CF_INVALID 0x00004000 /* TB is stale. Set with @jmp_lock held */
|
||||
#define CF_PARALLEL 0x00008000 /* Generate code for a parallel context */
|
||||
#define CF_NOIRQ 0x00010000 /* Generate an uninterruptible TB */
|
||||
#define CF_PCREL 0x00020000 /* Opcodes in TB are PC-relative */
|
||||
#define CF_BP_PAGE 0x00040000 /* Breakpoint present in code page */
|
||||
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
||||
#define CF_CLUSTER_SHIFT 24
|
||||
|
||||
/*
|
||||
* Above fields used for comparing
|
||||
*/
|
||||
|
||||
/* size of target code for this block (1 <= size <= TARGET_PAGE_SIZE) */
|
||||
uint16_t size;
|
||||
uint16_t icount;
|
||||
|
||||
struct tb_tc tc;
|
||||
|
||||
/*
|
||||
* Track tb_page_addr_t intervals that intersect this TB.
|
||||
* For user-only, the virtual addresses are always contiguous,
|
||||
* and we use a unified interval tree. For system, we use a
|
||||
* linked list headed in each PageDesc. Within the list, the lsb
|
||||
* of the previous pointer tells the index of page_next[], and the
|
||||
* list is protected by the PageDesc lock(s).
|
||||
*/
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
IntervalTreeNode itree;
|
||||
#else
|
||||
uintptr_t page_next[2];
|
||||
tb_page_addr_t page_addr[2];
|
||||
#endif
|
||||
|
||||
/* jmp_lock placed here to fill a 4-byte hole. Its documentation is below */
|
||||
QemuSpin jmp_lock;
|
||||
|
||||
/* The following data are used to directly call another TB from
|
||||
* the code of this one. This can be done either by emitting direct or
|
||||
* indirect native jump instructions. These jumps are reset so that the TB
|
||||
* just continues its execution. The TB can be linked to another one by
|
||||
* setting one of the jump targets (or patching the jump instruction). Only
|
||||
* two of such jumps are supported.
|
||||
*/
|
||||
#define TB_JMP_OFFSET_INVALID 0xffff /* indicates no jump generated */
|
||||
uint16_t jmp_reset_offset[2]; /* offset of original jump target */
|
||||
uint16_t jmp_insn_offset[2]; /* offset of direct jump insn */
|
||||
uintptr_t jmp_target_addr[2]; /* target address */
|
||||
|
||||
/*
|
||||
* Each TB has a NULL-terminated list (jmp_list_head) of incoming jumps.
|
||||
* Each TB can have two outgoing jumps, and therefore can participate
|
||||
* in two lists. The list entries are kept in jmp_list_next[2]. The least
|
||||
* significant bit (LSB) of the pointers in these lists is used to encode
|
||||
* which of the two list entries is to be used in the pointed TB.
|
||||
*
|
||||
* List traversals are protected by jmp_lock. The destination TB of each
|
||||
* outgoing jump is kept in jmp_dest[] so that the appropriate jmp_lock
|
||||
* can be acquired from any origin TB.
|
||||
*
|
||||
* jmp_dest[] are tagged pointers as well. The LSB is set when the TB is
|
||||
* being invalidated, so that no further outgoing jumps from it can be set.
|
||||
*
|
||||
* jmp_lock also protects the CF_INVALID cflag; a jump must not be chained
|
||||
* to a destination TB that has CF_INVALID set.
|
||||
*/
|
||||
uintptr_t jmp_list_head;
|
||||
uintptr_t jmp_list_next[2];
|
||||
uintptr_t jmp_dest[2];
|
||||
};
|
||||
|
||||
/* The alignment given to TranslationBlock during allocation. */
|
||||
#define CODE_GEN_ALIGN 16
|
||||
|
||||
/* Hide the qatomic_read to make code a little easier on the eyes */
|
||||
static inline uint32_t tb_cflags(const TranslationBlock *tb)
|
||||
{
|
||||
return qatomic_read(&tb->cflags);
|
||||
}
|
||||
|
||||
bool tcg_cflags_has(CPUState *cpu, uint32_t flags);
|
||||
void tcg_cflags_set(CPUState *cpu, uint32_t flags);
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
return tb->itree.start;
|
||||
#else
|
||||
return tb->page_addr[0];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr1(const TranslationBlock *tb)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
tb_page_addr_t next = tb->itree.last & TARGET_PAGE_MASK;
|
||||
return next == (tb->itree.start & TARGET_PAGE_MASK) ? -1 : next;
|
||||
#else
|
||||
return tb->page_addr[1];
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr0(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
tb->itree.start = addr;
|
||||
/*
|
||||
* To begin, we record an interval of one byte. When the translation
|
||||
* loop encounters a second page, the interval will be extended to
|
||||
* include the first byte of the second page, which is sufficient to
|
||||
* allow tb_page_addr1() above to work properly. The final corrected
|
||||
* interval will be set by tb_page_add() from tb->size before the
|
||||
* node is added to the interval tree.
|
||||
*/
|
||||
tb->itree.last = addr;
|
||||
#else
|
||||
tb->page_addr[0] = addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr1(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/* Extend the interval to the first byte of the second page. See above. */
|
||||
tb->itree.last = addr;
|
||||
#else
|
||||
tb->page_addr[1] = addr;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* TranslationBlock invalidate API */
|
||||
void tb_invalidate_phys_range(CPUState *cpu, tb_page_addr_t start,
|
||||
tb_page_addr_t last);
|
||||
|
||||
#endif /* EXEC_TRANSLATION_BLOCK_H */
|
||||
@@ -0,0 +1,282 @@
|
||||
/*
|
||||
* Generic intermediate code generation.
|
||||
*
|
||||
* Copyright (C) 2016-2017 Lluís Vilanova <[email protected]>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or later.
|
||||
* See the COPYING file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef EXEC__TRANSLATOR_H
|
||||
#define EXEC__TRANSLATOR_H
|
||||
|
||||
/*
|
||||
* Include this header from a target-specific file, and add a
|
||||
*
|
||||
* DisasContextBase base;
|
||||
*
|
||||
* member in your target-specific DisasContext.
|
||||
*/
|
||||
|
||||
#include "exec/memop.h"
|
||||
#include "exec/vaddr.h"
|
||||
#include "tcg/tcg.h"
|
||||
|
||||
/**
|
||||
* DisasJumpType:
|
||||
* @DISAS_NEXT: Next instruction in program order.
|
||||
* @DISAS_TOO_MANY: Too many instructions translated.
|
||||
* @DISAS_NORETURN: Following code is dead.
|
||||
* @DISAS_TARGET_*: Start of target-specific conditions.
|
||||
*
|
||||
* What instruction to disassemble next.
|
||||
*/
|
||||
typedef enum DisasJumpType {
|
||||
DISAS_NEXT,
|
||||
DISAS_TOO_MANY,
|
||||
DISAS_NORETURN,
|
||||
DISAS_TARGET_0,
|
||||
DISAS_TARGET_1,
|
||||
DISAS_TARGET_2,
|
||||
DISAS_TARGET_3,
|
||||
DISAS_TARGET_4,
|
||||
DISAS_TARGET_5,
|
||||
DISAS_TARGET_6,
|
||||
DISAS_TARGET_7,
|
||||
DISAS_TARGET_8,
|
||||
DISAS_TARGET_9,
|
||||
DISAS_TARGET_10,
|
||||
DISAS_TARGET_11,
|
||||
} DisasJumpType;
|
||||
|
||||
/**
|
||||
* DisasContextBase:
|
||||
* @tb: Translation block for this disassembly.
|
||||
* @pc_first: Address of first guest instruction in this TB.
|
||||
* @pc_next: Address of next guest instruction in this TB (current during
|
||||
* disassembly).
|
||||
* @is_jmp: What instruction to disassemble next.
|
||||
* @num_insns: Number of translated instructions (including current).
|
||||
* @max_insns: Maximum number of instructions to be translated in this TB.
|
||||
* @plugin_enabled: TCG plugin enabled in this TB.
|
||||
* @fake_insn: True if translator_fake_ldb used.
|
||||
* @insn_start: The last op emitted by the insn_start hook,
|
||||
* which is expected to be INDEX_op_insn_start.
|
||||
*
|
||||
* Architecture-agnostic disassembly context.
|
||||
*/
|
||||
struct DisasContextBase {
|
||||
TranslationBlock *tb;
|
||||
vaddr pc_first;
|
||||
vaddr pc_next;
|
||||
DisasJumpType is_jmp;
|
||||
int num_insns;
|
||||
int max_insns;
|
||||
bool plugin_enabled;
|
||||
bool fake_insn;
|
||||
uint8_t code_mmuidx;
|
||||
struct TCGOp *insn_start;
|
||||
void *host_addr[2];
|
||||
|
||||
/*
|
||||
* Record insn data that we cannot read directly from host memory.
|
||||
* There are only two reasons we cannot use host memory:
|
||||
* (1) We are executing from I/O,
|
||||
* (2) We are executing a synthetic instruction (s390x EX).
|
||||
* In both cases we need record exactly one instruction,
|
||||
* and thus the maximum amount of data we record is limited.
|
||||
*/
|
||||
int record_start;
|
||||
int record_len;
|
||||
uint8_t record[32];
|
||||
};
|
||||
|
||||
/**
|
||||
* TranslatorOps:
|
||||
* @init_disas_context:
|
||||
* Initialize the target-specific portions of DisasContext struct.
|
||||
* The generic DisasContextBase has already been initialized.
|
||||
*
|
||||
* @tb_start:
|
||||
* Emit any code required before the start of the main loop,
|
||||
* after the generic gen_tb_start().
|
||||
*
|
||||
* @insn_start:
|
||||
* Emit the tcg_gen_insn_start opcode.
|
||||
*
|
||||
* @translate_insn:
|
||||
* Disassemble one instruction and set db->pc_next for the start
|
||||
* of the following instruction. Set db->is_jmp as necessary to
|
||||
* terminate the main loop.
|
||||
*
|
||||
* @tb_stop:
|
||||
* Emit any opcodes required to exit the TB, based on db->is_jmp.
|
||||
*
|
||||
* @disas_log:
|
||||
* Print instruction disassembly to log.
|
||||
*/
|
||||
typedef struct TranslatorOps {
|
||||
void (*init_disas_context)(DisasContextBase *db, CPUState *cpu);
|
||||
void (*tb_start)(DisasContextBase *db, CPUState *cpu);
|
||||
void (*insn_start)(DisasContextBase *db, CPUState *cpu);
|
||||
void (*translate_insn)(DisasContextBase *db, CPUState *cpu);
|
||||
void (*tb_stop)(DisasContextBase *db, CPUState *cpu);
|
||||
bool (*disas_log)(const DisasContextBase *db, CPUState *cpu, FILE *f);
|
||||
} TranslatorOps;
|
||||
|
||||
/**
|
||||
* translator_loop:
|
||||
* @cpu: Target vCPU.
|
||||
* @tb: Translation block.
|
||||
* @max_insns: Maximum number of insns to translate.
|
||||
* @pc: guest virtual program counter address
|
||||
* @host_pc: host physical program counter address
|
||||
* @ops: Target-specific operations.
|
||||
* @db: Disassembly context.
|
||||
* @addr_type: TCG Type for addresses (TCG_TYPE_VA).
|
||||
*
|
||||
* Generic translator loop.
|
||||
*
|
||||
* Translation will stop in the following cases (in order):
|
||||
* - When is_jmp set by #TranslatorOps::breakpoint_check.
|
||||
* - set to DISAS_TOO_MANY exits after translating one more insn
|
||||
* - set to any other value than DISAS_NEXT exits immediately.
|
||||
* - When is_jmp set by #TranslatorOps::translate_insn.
|
||||
* - set to any value other than DISAS_NEXT exits immediately.
|
||||
* - When the TCG operation buffer is full.
|
||||
* - When single-stepping is enabled (system-wide or on the current vCPU).
|
||||
* - When too many instructions have been translated.
|
||||
*/
|
||||
void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
vaddr pc, void *host_pc, const TranslatorOps *ops,
|
||||
DisasContextBase *db, TCGType addr_type);
|
||||
|
||||
/**
|
||||
* translator_use_goto_tb
|
||||
* @db: Disassembly context
|
||||
* @dest: target pc of the goto
|
||||
*
|
||||
* Return true if goto_tb is allowed between the current TB
|
||||
* and the destination PC.
|
||||
*/
|
||||
bool translator_use_goto_tb(DisasContextBase *db, vaddr dest);
|
||||
|
||||
/**
|
||||
* translator_io_start
|
||||
* @db: Disassembly context
|
||||
*
|
||||
* If icount is enabled, set cpu->can_do_io, adjust db->is_jmp to
|
||||
* DISAS_TOO_MANY if it is still DISAS_NEXT, and return true.
|
||||
* Otherwise return false.
|
||||
*/
|
||||
bool translator_io_start(DisasContextBase *db);
|
||||
|
||||
/*
|
||||
* Translator Load Functions
|
||||
*
|
||||
* These are intended to replace the direct usage of the cpu_ld*_code
|
||||
* functions and are mandatory for front-ends that have been migrated
|
||||
* to the common translator_loop. These functions are only intended
|
||||
* to be called from the translation stage and should not be called
|
||||
* from helper functions. Those functions should be converted to encode
|
||||
* the relevant information at translation time.
|
||||
*/
|
||||
|
||||
uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc);
|
||||
uint16_t translator_lduw_end(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, MemOp endian);
|
||||
uint32_t translator_ldl_end(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, MemOp endian);
|
||||
uint64_t translator_ldq_end(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, MemOp endian);
|
||||
|
||||
#if !defined(TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API) \
|
||||
&& defined(COMPILING_PER_TARGET)
|
||||
static inline uint16_t
|
||||
translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
{
|
||||
return translator_lduw_end(env, db, pc, MO_TE);
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
{
|
||||
return translator_ldl_end(env, db, pc, MO_TE);
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
|
||||
{
|
||||
return translator_ldq_end(env, db, pc, MO_TE);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, bool do_swap)
|
||||
{
|
||||
return translator_lduw_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
|
||||
}
|
||||
|
||||
static inline uint32_t
|
||||
translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, bool do_swap)
|
||||
{
|
||||
return translator_ldl_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
|
||||
vaddr pc, bool do_swap)
|
||||
{
|
||||
return translator_ldq_end(env, db, pc, MO_TE ^ (do_swap * MO_BSWAP));
|
||||
}
|
||||
#endif /* !TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API && COMPILING_PER_TARGET */
|
||||
|
||||
/**
|
||||
* translator_fake_ld - fake instruction load
|
||||
* @db: Disassembly context
|
||||
* @data: bytes of instruction
|
||||
* @len: number of bytes
|
||||
*
|
||||
* This is a special case helper used where the instruction we are
|
||||
* about to translate comes from somewhere else (e.g. being
|
||||
* re-synthesised for s390x "ex"). It ensures we update other areas of
|
||||
* the translator with details of the executed instruction.
|
||||
*/
|
||||
void translator_fake_ld(DisasContextBase *db, const void *data, size_t len);
|
||||
|
||||
/**
|
||||
* translator_st
|
||||
* @db: disassembly context
|
||||
* @dest: address to copy into
|
||||
* @addr: virtual address within TB
|
||||
* @len: length
|
||||
*
|
||||
* Copy @len bytes from @addr into @dest.
|
||||
* All bytes must have been read during translation.
|
||||
* Return true on success or false on failure.
|
||||
*/
|
||||
bool translator_st(const DisasContextBase *db, void *dest,
|
||||
vaddr addr, size_t len);
|
||||
|
||||
/**
|
||||
* translator_st_len
|
||||
* @db: disassembly context
|
||||
*
|
||||
* Return the number of bytes available to copy from the
|
||||
* current translation block with translator_st.
|
||||
*/
|
||||
size_t translator_st_len(const DisasContextBase *db);
|
||||
|
||||
/**
|
||||
* translator_is_same_page
|
||||
* @db: disassembly context
|
||||
* @addr: virtual address within TB
|
||||
*
|
||||
* Return whether @addr is on the same page as where disassembly started.
|
||||
* Translators can use this to enforce the rule that only single-insn
|
||||
* translation blocks are allowed to cross page boundaries.
|
||||
*/
|
||||
bool translator_is_same_page(const DisasContextBase *db, vaddr addr);
|
||||
|
||||
#endif /* EXEC__TRANSLATOR_H */
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Macros for swapping a value if the endianness is different
|
||||
* between the target and the host.
|
||||
*
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef TSWAP_H
|
||||
#define TSWAP_H
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/target-info.h"
|
||||
#include "hw/core/cpu.h"
|
||||
|
||||
/*
|
||||
* If we're in target-specific code, we can hard-code the swapping
|
||||
* condition, otherwise we have to do (slower) run-time checks.
|
||||
*/
|
||||
#ifdef COMPILING_PER_TARGET
|
||||
#define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN)
|
||||
#else
|
||||
#define target_needs_bswap() (HOST_BIG_ENDIAN != target_big_endian())
|
||||
#endif /* COMPILING_PER_TARGET */
|
||||
|
||||
#if defined(CONFIG_USER_ONLY) \
|
||||
|| !defined(TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API)
|
||||
static inline uint16_t tswap16(uint16_t s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
return bswap16(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t tswap32(uint32_t s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
return bswap32(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t tswap64(uint64_t s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
return bswap64(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tswap16s(uint16_t *s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
*s = bswap16(*s);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tswap32s(uint32_t *s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
*s = bswap32(*s);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void tswap64s(uint64_t *s)
|
||||
{
|
||||
if (target_needs_bswap()) {
|
||||
*s = bswap64(*s);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* If we're in semihosting code, have to swap depending on the currently
|
||||
* configured endianness of the CPU. These functions should not be used in
|
||||
* other contexts.
|
||||
*/
|
||||
#define cpu_internal_needs_bswap(cpu) \
|
||||
(HOST_BIG_ENDIAN != cpu_internal_is_big_endian(cpu))
|
||||
|
||||
static inline uint16_t cpu_internal_tswap16(CPUState *cpu, uint16_t s)
|
||||
{
|
||||
if (cpu_internal_needs_bswap(cpu)) {
|
||||
return bswap16(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_internal_tswap32(CPUState *cpu, uint32_t s)
|
||||
{
|
||||
if (cpu_internal_needs_bswap(cpu)) {
|
||||
return bswap32(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint64_t cpu_internal_tswap64(CPUState *cpu, uint64_t s)
|
||||
{
|
||||
if (cpu_internal_needs_bswap(cpu)) {
|
||||
return bswap64(s);
|
||||
} else {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* TSWAP_H */
|
||||
@@ -0,0 +1,20 @@
|
||||
/* Define vaddr. */
|
||||
|
||||
#ifndef VADDR_H
|
||||
#define VADDR_H
|
||||
|
||||
/**
|
||||
* vaddr:
|
||||
* Type wide enough to contain any #target_ulong virtual address.
|
||||
* We do not support 64-bit guest on 32-host and detect at configure time.
|
||||
* Therefore, a host pointer width will always fit a guest pointer.
|
||||
*/
|
||||
typedef uintptr_t vaddr;
|
||||
#define VADDR_PRId PRIdPTR
|
||||
#define VADDR_PRIu PRIuPTR
|
||||
#define VADDR_PRIo PRIoPTR
|
||||
#define VADDR_PRIx PRIxPTR
|
||||
#define VADDR_PRIX PRIXPTR
|
||||
#define VADDR_MAX UINTPTR_MAX
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* CPU watchpoints
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
* SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
*/
|
||||
|
||||
#ifndef EXEC_WATCHPOINT_H
|
||||
#define EXEC_WATCHPOINT_H
|
||||
|
||||
int cpu_watchpoint_insert(CPUState *cpu, vaddr addr, vaddr len,
|
||||
int flags, CPUWatchpoint **watchpoint);
|
||||
int cpu_watchpoint_remove(CPUState *cpu, vaddr addr,
|
||||
vaddr len, int flags);
|
||||
void cpu_watchpoint_remove_by_ref(CPUState *cpu, CPUWatchpoint *watchpoint);
|
||||
void cpu_watchpoint_remove_all(CPUState *cpu, int mask);
|
||||
|
||||
#endif /* EXEC_WATCHPOINT_H */
|
||||
Reference in new issue
Block a user