Import QEMU upstream snapshot d2e570c

Upstream: https://gitlab.com/qemu-project/qemu.git

Upstream-Commit: d2e570cc0f97b936902a5b1b86b73c0f5998b475
This commit is contained in:
Yaya48 committed 2026-08-31 02:15:30 +02:00
commit cf256aa081
11315 files changed
+3598369

No files matched your search

+33
View File
@@ -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
+44
View File
@@ -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
+115
View File
@@ -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 */
+40
View File
@@ -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
+70
View File
@@ -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 */
+283
View File
@@ -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 */
+161
View File
@@ -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 */
+14
View File
@@ -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 */
+16
View File
@@ -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 */
+110
View File
@@ -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
+148
View File
@@ -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 */
+96
View File
@@ -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
+18
View File
@@ -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 */
+16
View File
@@ -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 */
+68
View File
@@ -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
+26
View File
@@ -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
+76
View File
@@ -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 */
+40
View File
@@ -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
+93
View File
@@ -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
+219
View File
@@ -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
+56
View File
@@ -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
+33
View File
@@ -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 */
+18
View File
@@ -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
+42
View File
@@ -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
+70
View File
@@ -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 */
+52
View File
@@ -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 */
+76
View File
@@ -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
+80
View File
@@ -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
+44
View File
@@ -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_ */
+76
View File
@@ -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
+38
View File
@@ -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_ */
+56
View File
@@ -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 */
+87
View File
@@ -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 */
+217
View File
@@ -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 */
+282
View File
@@ -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 */
+111
View File
@@ -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 */
+20
View File
@@ -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
+18
View File
@@ -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 */