mirror of
https://github.com/izzy2lost/xemu.git
synced 2026-07-06 00:20:22 -07:00
Merge tag 'v7.2.0' into sync/qemu-7.2.0
v7.2.0 release
This commit is contained in:
+20
-41
@@ -34,13 +34,13 @@
|
||||
|
||||
/* some important defines:
|
||||
*
|
||||
* HOST_WORDS_BIGENDIAN : if defined, the host cpu is big endian and
|
||||
* HOST_BIG_ENDIAN : whether the host cpu is big endian and
|
||||
* otherwise little endian.
|
||||
*
|
||||
* TARGET_WORDS_BIGENDIAN : same for target cpu
|
||||
* TARGET_BIG_ENDIAN : same for the target cpu
|
||||
*/
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
|
||||
#define BSWAP_NEEDED
|
||||
#endif
|
||||
|
||||
@@ -120,7 +120,7 @@ static inline void tswap64s(uint64_t *s)
|
||||
/* Target-endianness CPU memory access functions. These fit into the
|
||||
* {ld,st}{type}{sign}{size}{endian}_p naming scheme described in bswap.h.
|
||||
*/
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
#if TARGET_BIG_ENDIAN
|
||||
#define lduw_p(p) lduw_be_p(p)
|
||||
#define ldsw_p(p) ldsw_be_p(p)
|
||||
#define ldl_p(p) ldl_be_p(p)
|
||||
@@ -234,15 +234,6 @@ extern const TargetPageBits target_page;
|
||||
|
||||
#define TARGET_PAGE_ALIGN(addr) ROUND_UP((addr), TARGET_PAGE_SIZE)
|
||||
|
||||
/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
|
||||
* when intptr_t is 32-bit and we are aligning a long long.
|
||||
*/
|
||||
extern uintptr_t qemu_host_page_size;
|
||||
extern intptr_t qemu_host_page_mask;
|
||||
|
||||
#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
|
||||
#define REAL_HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_real_host_page_size)
|
||||
|
||||
/* same as PROT_xxx */
|
||||
#define PAGE_READ 0x0001
|
||||
#define PAGE_WRITE 0x0002
|
||||
@@ -271,6 +262,12 @@ extern intptr_t qemu_host_page_mask;
|
||||
#define PAGE_TARGET_1 0x0200
|
||||
#define PAGE_TARGET_2 0x0400
|
||||
|
||||
/*
|
||||
* For linux-user, indicates that the page is mapped with the same semantics
|
||||
* in both guest and host.
|
||||
*/
|
||||
#define PAGE_PASSTHROUGH 0x0800
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void page_dump(FILE *f);
|
||||
|
||||
@@ -280,31 +277,22 @@ int walk_memory_regions(void *, walk_memory_regions_fn);
|
||||
|
||||
int page_get_flags(target_ulong address);
|
||||
void page_set_flags(target_ulong start, target_ulong end, int flags);
|
||||
void page_reset_target_data(target_ulong start, target_ulong end);
|
||||
int page_check_range(target_ulong start, target_ulong len, int flags);
|
||||
|
||||
/**
|
||||
* page_alloc_target_data(address, size)
|
||||
* @address: guest virtual address
|
||||
* @size: size of data to allocate
|
||||
*
|
||||
* Allocate @size bytes of out-of-band data to associate with the
|
||||
* guest page at @address. If the page is not mapped, NULL will
|
||||
* be returned. If there is existing data associated with @address,
|
||||
* no new memory will be allocated.
|
||||
*
|
||||
* The memory will be freed when the guest page is deallocated,
|
||||
* e.g. with the munmap system call.
|
||||
*/
|
||||
void *page_alloc_target_data(target_ulong address, size_t size);
|
||||
|
||||
/**
|
||||
* page_get_target_data(address)
|
||||
* @address: guest virtual address
|
||||
*
|
||||
* Return any out-of-bound memory assocated with the guest page
|
||||
* at @address, as per page_alloc_target_data.
|
||||
* Return TARGET_PAGE_DATA_SIZE bytes of out-of-band data to associate
|
||||
* with the guest page at @address, allocating it if necessary. The
|
||||
* caller should already have verified that the address is valid.
|
||||
*
|
||||
* The memory will be freed when the guest page is deallocated,
|
||||
* e.g. with the munmap system call.
|
||||
*/
|
||||
void *page_get_target_data(target_ulong address);
|
||||
void *page_get_target_data(target_ulong address)
|
||||
__attribute__((returns_nonnull));
|
||||
#endif
|
||||
|
||||
CPUArchState *cpu_copy(CPUArchState *env);
|
||||
@@ -428,25 +416,16 @@ static inline bool tlb_hit(target_ulong tlb_addr, target_ulong addr)
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
/* accel/tcg/cpu-exec.c */
|
||||
void dump_drift_info(void);
|
||||
/* accel/tcg/translate-all.c */
|
||||
void dump_exec_info(void);
|
||||
void dump_opcount_info(void);
|
||||
void dump_exec_info(GString *buf);
|
||||
#endif /* CONFIG_TCG */
|
||||
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
#ifdef CONFIG_TCG
|
||||
/* accel/tcg/cpu-exec.c */
|
||||
int cpu_exec(CPUState *cpu);
|
||||
void tcg_exec_realizefn(CPUState *cpu, Error **errp);
|
||||
void tcg_exec_unrealizefn(CPUState *cpu);
|
||||
#endif /* CONFIG_TCG */
|
||||
|
||||
/* Returns: 0 on success, -1 on error */
|
||||
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
void *ptr, target_ulong len, bool is_write);
|
||||
|
||||
/**
|
||||
* cpu_set_cpustate_pointers(cpu)
|
||||
|
||||
@@ -7,12 +7,38 @@
|
||||
#include "exec/hwaddr.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* vaddr:
|
||||
* Type wide enough to contain any #target_ulong virtual address.
|
||||
*/
|
||||
typedef uint64_t vaddr;
|
||||
#define VADDR_PRId PRId64
|
||||
#define VADDR_PRIu PRIu64
|
||||
#define VADDR_PRIo PRIo64
|
||||
#define VADDR_PRIx PRIx64
|
||||
#define VADDR_PRIX PRIX64
|
||||
#define VADDR_MAX UINT64_MAX
|
||||
|
||||
void cpu_exec_init_all(void);
|
||||
void cpu_exec_step_atomic(CPUState *cpu);
|
||||
|
||||
/* Using intptr_t ensures that qemu_*_page_mask is sign-extended even
|
||||
* when intptr_t is 32-bit and we are aligning a long long.
|
||||
*/
|
||||
extern uintptr_t qemu_host_page_size;
|
||||
extern intptr_t qemu_host_page_mask;
|
||||
|
||||
#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
|
||||
#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 */
|
||||
void qemu_init_cpu_list(void);
|
||||
void cpu_list_lock(void);
|
||||
void cpu_list_unlock(void);
|
||||
unsigned int cpu_list_generation_id_get(void);
|
||||
|
||||
void tcg_flush_softmmu_tlb(CPUState *cs);
|
||||
void tcg_flush_jmp_cache(CPUState *cs);
|
||||
|
||||
void tcg_iommu_init_notifier_list(CPUState *cpu);
|
||||
void tcg_iommu_free_notifier_list(CPUState *cpu);
|
||||
@@ -25,7 +51,7 @@ enum device_endian {
|
||||
DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#if HOST_BIG_ENDIAN
|
||||
#define DEVICE_HOST_ENDIAN DEVICE_BIG_ENDIAN
|
||||
#else
|
||||
#define DEVICE_HOST_ENDIAN DEVICE_LITTLE_ENDIAN
|
||||
@@ -47,6 +73,7 @@ typedef uintptr_t ram_addr_t;
|
||||
void qemu_ram_remap(ram_addr_t addr, ram_addr_t length);
|
||||
/* This should not be used by devices. */
|
||||
ram_addr_t qemu_ram_addr_from_host(void *ptr);
|
||||
ram_addr_t qemu_ram_addr_from_host_nofail(void *ptr);
|
||||
RAMBlock *qemu_ram_block_by_name(const char *name);
|
||||
RAMBlock *qemu_ram_block_from_host(void *ptr, bool round_offset,
|
||||
ram_addr_t *offset);
|
||||
@@ -65,10 +92,33 @@ void qemu_ram_set_uf_zeroable(RAMBlock *rb);
|
||||
bool qemu_ram_is_migratable(RAMBlock *rb);
|
||||
void qemu_ram_set_migratable(RAMBlock *rb);
|
||||
void qemu_ram_unset_migratable(RAMBlock *rb);
|
||||
int qemu_ram_get_fd(RAMBlock *rb);
|
||||
|
||||
size_t qemu_ram_pagesize(RAMBlock *block);
|
||||
size_t qemu_ram_pagesize_largest(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.
|
||||
*
|
||||
* Before the first call to this function, the caller must set
|
||||
* cpu->num_ases to the total number of address spaces it needs
|
||||
* to support.
|
||||
*
|
||||
* Note that with KVM only one address space is supported.
|
||||
*/
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr);
|
||||
|
||||
void cpu_physical_memory_rw(hwaddr addr, void *buf,
|
||||
hwaddr len, bool is_write);
|
||||
static inline void cpu_physical_memory_read(hwaddr addr,
|
||||
@@ -81,6 +131,7 @@ static inline void cpu_physical_memory_write(hwaddr addr,
|
||||
{
|
||||
cpu_physical_memory_rw(addr, (void *)buf, len, true);
|
||||
}
|
||||
void cpu_reloading_memory_map(void);
|
||||
void *cpu_physical_memory_map(hwaddr addr,
|
||||
hwaddr *plen,
|
||||
bool is_write);
|
||||
@@ -107,7 +158,13 @@ int ram_block_discard_range(RAMBlock *rb, uint64_t start, size_t length);
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns: 0 on success, -1 on error */
|
||||
int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
|
||||
void *ptr, size_t len, bool is_write);
|
||||
|
||||
/* vl.c */
|
||||
extern int singlestep;
|
||||
|
||||
void list_cpus(const char *optarg);
|
||||
|
||||
#endif /* CPU_COMMON_H */
|
||||
|
||||
+37
-11
@@ -54,6 +54,9 @@
|
||||
# error TARGET_PAGE_BITS must be defined in cpu-param.h
|
||||
# endif
|
||||
#endif
|
||||
#ifndef TARGET_TB_PCREL
|
||||
# define TARGET_TB_PCREL 0
|
||||
#endif
|
||||
|
||||
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
|
||||
|
||||
@@ -108,6 +111,7 @@ typedef uint64_t target_ulong;
|
||||
# endif
|
||||
# endif
|
||||
|
||||
/* Minimalized TLB entry for use by TCG fast path. */
|
||||
typedef struct CPUTLBEntry {
|
||||
/* bit TARGET_LONG_BITS to TARGET_PAGE_BITS : virtual address
|
||||
bit TARGET_PAGE_BITS-1..4 : Nonzero for accesses that should not
|
||||
@@ -131,14 +135,14 @@ typedef struct CPUTLBEntry {
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
|
||||
|
||||
/* The IOTLB is not accessed directly inline by generated TCG code,
|
||||
* so the CPUIOTLBEntry layout is not as critical as that of the
|
||||
* CPUTLBEntry. (This is also why we don't want to combine the two
|
||||
* structs into one.)
|
||||
/*
|
||||
* The full TLB entry, which is not accessed by generated TCG code,
|
||||
* so the layout is not as critical as that of CPUTLBEntry. This is
|
||||
* also why we don't want to combine the two structs.
|
||||
*/
|
||||
typedef struct CPUIOTLBEntry {
|
||||
typedef struct CPUTLBEntryFull {
|
||||
/*
|
||||
* @addr contains:
|
||||
* @xlat_section contains:
|
||||
* - in the lower TARGET_PAGE_BITS, a physical section number
|
||||
* - with the lower TARGET_PAGE_BITS masked off, an offset which
|
||||
* must be added to the virtual address to obtain:
|
||||
@@ -146,9 +150,32 @@ typedef struct CPUIOTLBEntry {
|
||||
* number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM)
|
||||
* + the offset within the target MemoryRegion (otherwise)
|
||||
*/
|
||||
hwaddr addr;
|
||||
hwaddr xlat_section;
|
||||
|
||||
/*
|
||||
* @phys_addr contains the physical address in the address space
|
||||
* given by cpu_asidx_from_attrs(cpu, @attrs).
|
||||
*/
|
||||
hwaddr phys_addr;
|
||||
|
||||
/* @attrs contains the memory transaction attributes for the page. */
|
||||
MemTxAttrs attrs;
|
||||
} CPUIOTLBEntry;
|
||||
|
||||
/* @prot contains the complete protections for the page. */
|
||||
uint8_t prot;
|
||||
|
||||
/* @lg_page_size contains the log2 of the page size. */
|
||||
uint8_t lg_page_size;
|
||||
|
||||
/*
|
||||
* Allow target-specific additions to this structure.
|
||||
* This may be used to cache items from the guest cpu
|
||||
* page tables for later use by the implementation.
|
||||
*/
|
||||
#ifdef TARGET_PAGE_ENTRY_EXTRA
|
||||
TARGET_PAGE_ENTRY_EXTRA
|
||||
#endif
|
||||
} CPUTLBEntryFull;
|
||||
|
||||
/*
|
||||
* Data elements that are per MMU mode, minus the bits accessed by
|
||||
@@ -172,9 +199,8 @@ typedef struct CPUTLBDesc {
|
||||
size_t vindex;
|
||||
/* The tlb victim table, in two parts. */
|
||||
CPUTLBEntry vtable[CPU_VTLB_SIZE];
|
||||
CPUIOTLBEntry viotlb[CPU_VTLB_SIZE];
|
||||
/* The iotlb. */
|
||||
CPUIOTLBEntry *iotlb;
|
||||
CPUTLBEntryFull vfulltlb[CPU_VTLB_SIZE];
|
||||
CPUTLBEntryFull *fulltlb;
|
||||
} CPUTLBDesc;
|
||||
|
||||
/*
|
||||
|
||||
+174
-163
@@ -28,10 +28,12 @@
|
||||
* load: cpu_ld{sign}{size}{end}_{mmusuffix}(env, ptr)
|
||||
* cpu_ld{sign}{size}{end}_{mmusuffix}_ra(env, ptr, retaddr)
|
||||
* cpu_ld{sign}{size}{end}_mmuidx_ra(env, ptr, mmu_idx, retaddr)
|
||||
* cpu_ld{sign}{size}{end}_mmu(env, ptr, oi, retaddr)
|
||||
*
|
||||
* store: cpu_st{size}{end}_{mmusuffix}(env, ptr, val)
|
||||
* cpu_st{size}{end}_{mmusuffix}_ra(env, ptr, val, retaddr)
|
||||
* cpu_st{size}{end}_mmuidx_ra(env, ptr, val, mmu_idx, retaddr)
|
||||
* cpu_st{size}{end}_mmu(env, ptr, val, oi, retaddr)
|
||||
*
|
||||
* sign is:
|
||||
* (empty): for 32 and 64 bit sizes
|
||||
@@ -53,10 +55,17 @@
|
||||
* The "mmuidx" suffix carries an extra mmu_idx argument that specifies
|
||||
* the index to use; the "data" and "code" suffixes take the index from
|
||||
* cpu_mmu_index().
|
||||
*
|
||||
* The "mmu" suffix carries the full MemOpIdx, with both mmu_idx and the
|
||||
* MemOp including alignment requirements. The alignment will be enforced.
|
||||
*/
|
||||
#ifndef CPU_LDST_H
|
||||
#define CPU_LDST_H
|
||||
|
||||
#include "exec/memopidx.h"
|
||||
#include "qemu/int128.h"
|
||||
#include "cpu.h"
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* sparc32plus has 64bit long but 32bit space address
|
||||
* this can make bad result with g2h() and h2g()
|
||||
@@ -113,17 +122,15 @@ static inline bool guest_range_valid_untagged(abi_ulong start, abi_ulong len)
|
||||
})
|
||||
#else
|
||||
typedef target_ulong abi_ptr;
|
||||
#define TARGET_ABI_FMT_ptr TARGET_ABI_FMT_lx
|
||||
#define TARGET_ABI_FMT_ptr TARGET_FMT_lx
|
||||
#endif
|
||||
|
||||
uint32_t cpu_ldub_data(CPUArchState *env, abi_ptr ptr);
|
||||
int cpu_ldsb_data(CPUArchState *env, abi_ptr ptr);
|
||||
|
||||
uint32_t cpu_lduw_be_data(CPUArchState *env, abi_ptr ptr);
|
||||
int cpu_ldsw_be_data(CPUArchState *env, abi_ptr ptr);
|
||||
uint32_t cpu_ldl_be_data(CPUArchState *env, abi_ptr ptr);
|
||||
uint64_t cpu_ldq_be_data(CPUArchState *env, abi_ptr ptr);
|
||||
|
||||
uint32_t cpu_lduw_le_data(CPUArchState *env, abi_ptr ptr);
|
||||
int cpu_ldsw_le_data(CPUArchState *env, abi_ptr ptr);
|
||||
uint32_t cpu_ldl_le_data(CPUArchState *env, abi_ptr ptr);
|
||||
@@ -131,37 +138,31 @@ uint64_t cpu_ldq_le_data(CPUArchState *env, abi_ptr ptr);
|
||||
|
||||
uint32_t cpu_ldub_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
int cpu_ldsb_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_lduw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
int cpu_ldsw_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
uint32_t cpu_ldl_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
uint64_t cpu_ldq_be_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_lduw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
int cpu_ldsw_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
uint32_t cpu_ldl_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
uint64_t cpu_ldq_le_data_ra(CPUArchState *env, abi_ptr ptr, uintptr_t ra);
|
||||
|
||||
void cpu_stb_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
|
||||
|
||||
void cpu_stw_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
|
||||
void cpu_stl_be_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
|
||||
void cpu_stq_be_data(CPUArchState *env, abi_ptr ptr, uint64_t val);
|
||||
|
||||
void cpu_stw_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
|
||||
void cpu_stl_le_data(CPUArchState *env, abi_ptr ptr, uint32_t val);
|
||||
void cpu_stq_le_data(CPUArchState *env, abi_ptr ptr, uint64_t val);
|
||||
|
||||
void cpu_stb_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t ra);
|
||||
|
||||
void cpu_stw_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t ra);
|
||||
void cpu_stl_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t ra);
|
||||
void cpu_stq_be_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint64_t val, uintptr_t ra);
|
||||
|
||||
void cpu_stw_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint32_t val, uintptr_t ra);
|
||||
void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
@@ -169,6 +170,157 @@ void cpu_stl_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
void cpu_stq_le_data_ra(CPUArchState *env, abi_ptr ptr,
|
||||
uint64_t val, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
|
||||
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr ptr, uint64_t val,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
|
||||
uint8_t cpu_ldb_mmu(CPUArchState *env, abi_ptr ptr, MemOpIdx oi, uintptr_t ra);
|
||||
uint16_t cpu_ldw_be_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint32_t cpu_ldl_be_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint64_t cpu_ldq_be_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint16_t cpu_ldw_le_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint32_t cpu_ldl_le_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
uint64_t cpu_ldq_le_mmu(CPUArchState *env, abi_ptr ptr,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
|
||||
void cpu_stb_mmu(CPUArchState *env, abi_ptr ptr, uint8_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stw_be_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stl_be_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stq_be_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stw_le_mmu(CPUArchState *env, abi_ptr ptr, uint16_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stl_le_mmu(CPUArchState *env, abi_ptr ptr, uint32_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
void cpu_stq_le_mmu(CPUArchState *env, abi_ptr ptr, uint64_t val,
|
||||
MemOpIdx oi, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_atomic_cmpxchgb_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t cmpv, uint32_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint32_t cpu_atomic_cmpxchgw_le_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t cmpv, uint32_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint32_t cpu_atomic_cmpxchgl_le_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t cmpv, uint32_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint64_t cpu_atomic_cmpxchgq_le_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint64_t cmpv, uint64_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint32_t cpu_atomic_cmpxchgw_be_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t cmpv, uint32_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint32_t cpu_atomic_cmpxchgl_be_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t cmpv, uint32_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
uint64_t cpu_atomic_cmpxchgq_be_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint64_t cmpv, uint64_t newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
#define GEN_ATOMIC_HELPER(NAME, TYPE, SUFFIX) \
|
||||
TYPE cpu_atomic_ ## NAME ## SUFFIX ## _mmu \
|
||||
(CPUArchState *env, target_ulong addr, TYPE val, \
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
#ifdef CONFIG_ATOMIC64
|
||||
#define GEN_ATOMIC_HELPER_ALL(NAME) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, l_be) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint64_t, q_le) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint64_t, q_be)
|
||||
#else
|
||||
#define GEN_ATOMIC_HELPER_ALL(NAME) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, b) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, w_le) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, w_be) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, l_le) \
|
||||
GEN_ATOMIC_HELPER(NAME, uint32_t, l_be)
|
||||
#endif
|
||||
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_add)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_sub)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_and)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_or)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_xor)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_smin)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_umin)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_smax)
|
||||
GEN_ATOMIC_HELPER_ALL(fetch_umax)
|
||||
|
||||
GEN_ATOMIC_HELPER_ALL(add_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(sub_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(and_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(or_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(xor_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(smin_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(umin_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(smax_fetch)
|
||||
GEN_ATOMIC_HELPER_ALL(umax_fetch)
|
||||
|
||||
GEN_ATOMIC_HELPER_ALL(xchg)
|
||||
|
||||
#undef GEN_ATOMIC_HELPER_ALL
|
||||
#undef GEN_ATOMIC_HELPER
|
||||
|
||||
Int128 cpu_atomic_cmpxchgo_le_mmu(CPUArchState *env, target_ulong addr,
|
||||
Int128 cmpv, Int128 newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
Int128 cpu_atomic_cmpxchgo_be_mmu(CPUArchState *env, target_ulong addr,
|
||||
Int128 cmpv, Int128 newv,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
Int128 cpu_atomic_ldo_le_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
Int128 cpu_atomic_ldo_be_mmu(CPUArchState *env, target_ulong addr,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
void cpu_atomic_sto_le_mmu(CPUArchState *env, target_ulong addr, Int128 val,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
void cpu_atomic_sto_be_mmu(CPUArchState *env, target_ulong addr, Int128 val,
|
||||
MemOpIdx oi, uintptr_t retaddr);
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
||||
extern __thread uintptr_t helper_retaddr;
|
||||
@@ -193,119 +345,6 @@ static inline void clear_helper_retaddr(void)
|
||||
helper_retaddr = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Provide the same *_mmuidx_ra interface as for softmmu.
|
||||
* The mmu_idx argument is ignored.
|
||||
*/
|
||||
|
||||
static inline uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldub_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldsb_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldsw_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_be_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_lduw_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldsw_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldl_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
return cpu_ldq_le_data_ra(env, addr, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, int mmu_idx, uintptr_t ra)
|
||||
{
|
||||
cpu_stb_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stw_be_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stl_be_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stq_be_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stw_le_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint32_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stl_le_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
static inline void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
uint64_t val, int mmu_idx,
|
||||
uintptr_t ra)
|
||||
{
|
||||
cpu_stq_le_data_ra(env, addr, val, ra);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Needed for TCG_OVERSIZED_GUEST */
|
||||
@@ -336,49 +375,9 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx,
|
||||
return &env_tlb(env)->f[mmu_idx].table[tlb_index(env, mmu_idx, addr)];
|
||||
}
|
||||
|
||||
uint32_t cpu_ldub_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsb_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_lduw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_ldl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint64_t cpu_ldq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
|
||||
uint32_t cpu_lduw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
int cpu_ldsw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint32_t cpu_ldl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
uint64_t cpu_ldq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr,
|
||||
int mmu_idx, uintptr_t ra);
|
||||
|
||||
void cpu_stb_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
void cpu_stw_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
void cpu_stl_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
void cpu_stq_be_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
void cpu_stw_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
void cpu_stl_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint32_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
int mmu_idx, uintptr_t retaddr);
|
||||
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
#if TARGET_BIG_ENDIAN
|
||||
# define cpu_lduw_data cpu_lduw_be_data
|
||||
# define cpu_ldsw_data cpu_ldsw_be_data
|
||||
# define cpu_ldl_data cpu_ldl_be_data
|
||||
@@ -391,6 +390,9 @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
# define cpu_ldsw_mmuidx_ra cpu_ldsw_be_mmuidx_ra
|
||||
# define cpu_ldl_mmuidx_ra cpu_ldl_be_mmuidx_ra
|
||||
# define cpu_ldq_mmuidx_ra cpu_ldq_be_mmuidx_ra
|
||||
# define cpu_ldw_mmu cpu_ldw_be_mmu
|
||||
# define cpu_ldl_mmu cpu_ldl_be_mmu
|
||||
# define cpu_ldq_mmu cpu_ldq_be_mmu
|
||||
# define cpu_stw_data cpu_stw_be_data
|
||||
# define cpu_stl_data cpu_stl_be_data
|
||||
# define cpu_stq_data cpu_stq_be_data
|
||||
@@ -400,6 +402,9 @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
# define cpu_stw_mmuidx_ra cpu_stw_be_mmuidx_ra
|
||||
# define cpu_stl_mmuidx_ra cpu_stl_be_mmuidx_ra
|
||||
# define cpu_stq_mmuidx_ra cpu_stq_be_mmuidx_ra
|
||||
# define cpu_stw_mmu cpu_stw_be_mmu
|
||||
# define cpu_stl_mmu cpu_stl_be_mmu
|
||||
# define cpu_stq_mmu cpu_stq_be_mmu
|
||||
#else
|
||||
# define cpu_lduw_data cpu_lduw_le_data
|
||||
# define cpu_ldsw_data cpu_ldsw_le_data
|
||||
@@ -413,6 +418,9 @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
# define cpu_ldsw_mmuidx_ra cpu_ldsw_le_mmuidx_ra
|
||||
# define cpu_ldl_mmuidx_ra cpu_ldl_le_mmuidx_ra
|
||||
# define cpu_ldq_mmuidx_ra cpu_ldq_le_mmuidx_ra
|
||||
# define cpu_ldw_mmu cpu_ldw_le_mmu
|
||||
# define cpu_ldl_mmu cpu_ldl_le_mmu
|
||||
# define cpu_ldq_mmu cpu_ldq_le_mmu
|
||||
# define cpu_stw_data cpu_stw_le_data
|
||||
# define cpu_stl_data cpu_stl_le_data
|
||||
# define cpu_stq_data cpu_stq_le_data
|
||||
@@ -422,6 +430,9 @@ void cpu_stq_le_mmuidx_ra(CPUArchState *env, abi_ptr addr, uint64_t val,
|
||||
# define cpu_stw_mmuidx_ra cpu_stw_le_mmuidx_ra
|
||||
# define cpu_stl_mmuidx_ra cpu_stl_le_mmuidx_ra
|
||||
# define cpu_stq_mmuidx_ra cpu_stq_le_mmuidx_ra
|
||||
# define cpu_stw_mmu cpu_stw_le_mmu
|
||||
# define cpu_stl_mmu cpu_stl_le_mmu
|
||||
# define cpu_stq_mmu cpu_stq_le_mmu
|
||||
#endif
|
||||
|
||||
uint32_t cpu_ldub_code(CPUArchState *env, abi_ptr addr);
|
||||
|
||||
+197
-109
@@ -24,7 +24,6 @@
|
||||
#ifdef CONFIG_TCG
|
||||
#include "exec/cpu_ldst.h"
|
||||
#endif
|
||||
#include "sysemu/cpu-timers.h"
|
||||
|
||||
/* allow to see translation results - the slowdown should be negligible, so we leave it */
|
||||
#define DEBUG_DISAS
|
||||
@@ -40,31 +39,35 @@ typedef ram_addr_t tb_page_addr_t;
|
||||
#define TB_PAGE_ADDR_FMT RAM_ADDR_FMT
|
||||
#endif
|
||||
|
||||
#include "qemu/log.h"
|
||||
|
||||
void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns);
|
||||
void restore_state_to_opc(CPUArchState *env, TranslationBlock *tb,
|
||||
target_ulong *data);
|
||||
/**
|
||||
* cpu_unwind_state_data:
|
||||
* @cpu: the cpu context
|
||||
* @host_pc: the host pc within the translation
|
||||
* @data: output data
|
||||
*
|
||||
* Attempt to load the the unwind state for a host pc occurring in
|
||||
* translated code. If @host_pc is not in translated code, the
|
||||
* function returns false; otherwise @data is loaded.
|
||||
* This is the same unwind info as given to restore_state_to_opc.
|
||||
*/
|
||||
bool cpu_unwind_state_data(CPUState *cpu, uintptr_t host_pc, uint64_t *data);
|
||||
|
||||
/**
|
||||
* cpu_restore_state:
|
||||
* @cpu: the vCPU state is to be restore to
|
||||
* @searched_pc: the host PC the fault occurred at
|
||||
* @will_exit: true if the TB executed will be interrupted after some
|
||||
cpu adjustments. Required for maintaining the correct
|
||||
icount valus
|
||||
* @cpu: the cpu context
|
||||
* @host_pc: the host pc within the translation
|
||||
* @return: true if state was restored, false otherwise
|
||||
*
|
||||
* Attempt to restore the state for a fault occurring in translated
|
||||
* code. If the searched_pc is not in translated code no state is
|
||||
* code. If @host_pc is not in translated code no state is
|
||||
* restored and the function returns false.
|
||||
*/
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc, bool will_exit);
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t host_pc);
|
||||
|
||||
void QEMU_NORETURN cpu_loop_exit_noexc(CPUState *cpu);
|
||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
||||
void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
||||
void QEMU_NORETURN cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc);
|
||||
G_NORETURN void cpu_loop_exit_noexc(CPUState *cpu);
|
||||
G_NORETURN void cpu_loop_exit(CPUState *cpu);
|
||||
G_NORETURN void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc);
|
||||
G_NORETURN void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc);
|
||||
|
||||
/**
|
||||
* cpu_loop_exit_requested:
|
||||
@@ -83,31 +86,6 @@ static inline bool cpu_loop_exit_requested(CPUState *cpu)
|
||||
return (int32_t)qatomic_read(&cpu_neg(cpu)->icount_decr.u32) < 0;
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void cpu_reloading_memory_map(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.
|
||||
*
|
||||
* Before the first call to this function, the caller must set
|
||||
* cpu->num_ases to the total number of address spaces it needs
|
||||
* to support.
|
||||
*
|
||||
* Note that with KVM only one address space is supported.
|
||||
*/
|
||||
void cpu_address_space_init(CPUState *cpu, int asidx,
|
||||
const char *prefix, MemoryRegion *mr);
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_TCG)
|
||||
/* cputlb.c */
|
||||
/**
|
||||
@@ -286,6 +264,28 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
|
||||
uint16_t idxmap,
|
||||
unsigned bits);
|
||||
|
||||
/**
|
||||
* tlb_set_page_full:
|
||||
* @cpu: CPU context
|
||||
* @mmu_idx: mmu index of the tlb to modify
|
||||
* @vaddr: 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_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, target_ulong vaddr,
|
||||
CPUTLBEntryFull *full);
|
||||
|
||||
/**
|
||||
* tlb_set_page_with_attrs:
|
||||
* @cpu: CPU to add this TLB entry for
|
||||
@@ -463,6 +463,21 @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool nonfault, void **phost, uintptr_t retaddr);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/**
|
||||
* probe_access_full:
|
||||
* Like probe_access_flags, except also return into @pfull.
|
||||
*
|
||||
* The CPUTLBEntryFull structure returned via @pfull is transient
|
||||
* and must be consumed or copied immediately, before any further
|
||||
* access or changes to TLB @mmu_idx.
|
||||
*/
|
||||
int probe_access_full(CPUArchState *env, target_ulong addr,
|
||||
MMUAccessType access_type, int mmu_idx,
|
||||
bool nonfault, void **phost,
|
||||
CPUTLBEntryFull **pfull, uintptr_t retaddr);
|
||||
#endif
|
||||
|
||||
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
||||
|
||||
/* Estimated block size for TB allocation. */
|
||||
@@ -488,8 +503,32 @@ struct tb_tc {
|
||||
};
|
||||
|
||||
struct TranslationBlock {
|
||||
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
|
||||
target_ulong cs_base; /* CS base for this block */
|
||||
#if !TARGET_TB_PCREL
|
||||
/*
|
||||
* 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 TARGET_TB_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.
|
||||
*/
|
||||
target_ulong pc;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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).
|
||||
*/
|
||||
target_ulong cs_base;
|
||||
|
||||
uint32_t flags; /* flags defining in which context the code was generated */
|
||||
uint32_t cflags; /* compile flags */
|
||||
|
||||
@@ -503,6 +542,7 @@ struct TranslationBlock {
|
||||
#define CF_USE_ICOUNT 0x00020000
|
||||
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
|
||||
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
|
||||
#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */
|
||||
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
||||
#define CF_CLUSTER_SHIFT 24
|
||||
|
||||
@@ -562,31 +602,64 @@ struct TranslationBlock {
|
||||
uintptr_t jmp_dest[2];
|
||||
};
|
||||
|
||||
/* Hide the read to avoid ifdefs for TARGET_TB_PCREL. */
|
||||
static inline target_ulong tb_pc(const TranslationBlock *tb)
|
||||
{
|
||||
#if TARGET_TB_PCREL
|
||||
qemu_build_not_reached();
|
||||
#else
|
||||
return tb->pc;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr0(const TranslationBlock *tb)
|
||||
{
|
||||
return tb->page_addr[0];
|
||||
}
|
||||
|
||||
static inline tb_page_addr_t tb_page_addr1(const TranslationBlock *tb)
|
||||
{
|
||||
return tb->page_addr[1];
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr0(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
tb->page_addr[0] = addr;
|
||||
}
|
||||
|
||||
static inline void tb_set_page_addr1(TranslationBlock *tb,
|
||||
tb_page_addr_t addr)
|
||||
{
|
||||
tb->page_addr[1] = addr;
|
||||
}
|
||||
|
||||
/* current cflags for hashing/comparison */
|
||||
uint32_t curr_cflags(CPUState *cpu);
|
||||
|
||||
/* TranslationBlock invalidate API */
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void tb_invalidate_phys_addr(target_ulong addr);
|
||||
void tb_invalidate_phys_range(target_ulong start, target_ulong end);
|
||||
#else
|
||||
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr, MemTxAttrs attrs);
|
||||
#endif
|
||||
void tb_flush(CPUState *cpu);
|
||||
void tb_phys_invalidate(TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||
void tb_invalidate_phys_range(tb_page_addr_t start, tb_page_addr_t end);
|
||||
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
|
||||
|
||||
TranslationBlock *tb_htable_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
uint32_t cflags);
|
||||
TranslationBlock *inv_tb_htable_lookup(CPUState *cpu, target_ulong pc,
|
||||
target_ulong cs_base, uint32_t flags,
|
||||
uint32_t cflags);
|
||||
void tb_set_jmp_target(TranslationBlock *tb, int n, uintptr_t addr);
|
||||
|
||||
/* GETPC is the true target of the return instruction that we'll execute. */
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
@@ -606,14 +679,6 @@ extern __thread uintptr_t tci_tb_ptr;
|
||||
smaller than 4 bytes, so we don't worry about special-casing this. */
|
||||
#define GETPC_ADJ 2
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY) && defined(CONFIG_DEBUG_TCG)
|
||||
void assert_no_pages_locked(void);
|
||||
#else
|
||||
static inline void assert_no_pages_locked(void)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/**
|
||||
@@ -629,62 +694,8 @@ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu,
|
||||
hwaddr index, MemTxAttrs attrs);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void mmap_lock(void);
|
||||
void mmap_unlock(void);
|
||||
bool have_mmap_lock(void);
|
||||
|
||||
/**
|
||||
* get_page_addr_code() - user-mode version
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address of guest code
|
||||
*
|
||||
* Returns @addr.
|
||||
*/
|
||||
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
|
||||
target_ulong addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_page_addr_code_hostp() - user-mode version
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address of guest code
|
||||
*
|
||||
* Returns @addr.
|
||||
*
|
||||
* If @hostp is non-NULL, sets *@hostp to the host address where @addr's content
|
||||
* is kept.
|
||||
*/
|
||||
static inline tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env,
|
||||
target_ulong addr,
|
||||
void **hostp)
|
||||
{
|
||||
if (hostp) {
|
||||
*hostp = g2h_untagged(addr);
|
||||
}
|
||||
return addr;
|
||||
}
|
||||
#else
|
||||
static inline void mmap_lock(void) {}
|
||||
static inline void mmap_unlock(void) {}
|
||||
|
||||
/**
|
||||
* get_page_addr_code() - full-system version
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address of guest code
|
||||
*
|
||||
* If we cannot translate and execute from the entire RAM page, or if
|
||||
* the region is not backed by RAM, returns -1. Otherwise, returns the
|
||||
* ram_addr_t corresponding to the guest code at @addr.
|
||||
*
|
||||
* Note: this function can trigger an exception.
|
||||
*/
|
||||
tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr);
|
||||
|
||||
/**
|
||||
* get_page_addr_code_hostp() - full-system version
|
||||
* get_page_addr_code_hostp()
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address of guest code
|
||||
*
|
||||
@@ -700,6 +711,83 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr);
|
||||
tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
|
||||
void **hostp);
|
||||
|
||||
/**
|
||||
* get_page_addr_code()
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address of guest code
|
||||
*
|
||||
* If we cannot translate and execute from the entire RAM page, or if
|
||||
* the region is not backed by RAM, returns -1. Otherwise, returns the
|
||||
* ram_addr_t corresponding to the guest code at @addr.
|
||||
*
|
||||
* Note: this function can trigger an exception.
|
||||
*/
|
||||
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env,
|
||||
target_ulong addr)
|
||||
{
|
||||
return get_page_addr_code_hostp(env, addr, NULL);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
void mmap_lock(void);
|
||||
void mmap_unlock(void);
|
||||
bool have_mmap_lock(void);
|
||||
|
||||
/**
|
||||
* adjust_signal_pc:
|
||||
* @pc: raw pc from the host signal ucontext_t.
|
||||
* @is_write: host memory operation was write, or read-modify-write.
|
||||
*
|
||||
* Alter @pc as required for unwinding. Return the type of the
|
||||
* guest memory access -- host reads may be for guest execution.
|
||||
*/
|
||||
MMUAccessType adjust_signal_pc(uintptr_t *pc, bool is_write);
|
||||
|
||||
/**
|
||||
* handle_sigsegv_accerr_write:
|
||||
* @cpu: the cpu context
|
||||
* @old_set: the sigset_t from the signal ucontext_t
|
||||
* @host_pc: the host pc, adjusted for the signal
|
||||
* @host_addr: the host address of the fault
|
||||
*
|
||||
* Return true if the write fault has been handled, and should be re-tried.
|
||||
*/
|
||||
bool handle_sigsegv_accerr_write(CPUState *cpu, sigset_t *old_set,
|
||||
uintptr_t host_pc, abi_ptr guest_addr);
|
||||
|
||||
/**
|
||||
* cpu_loop_exit_sigsegv:
|
||||
* @cpu: the cpu context
|
||||
* @addr: the guest address of the fault
|
||||
* @access_type: access was read/write/execute
|
||||
* @maperr: true for invalid page, false for permission fault
|
||||
* @ra: host pc for unwinding
|
||||
*
|
||||
* Use the TCGCPUOps hook to record cpu state, do guest operating system
|
||||
* specific things to raise SIGSEGV, and jump to the main cpu loop.
|
||||
*/
|
||||
G_NORETURN void cpu_loop_exit_sigsegv(CPUState *cpu, target_ulong addr,
|
||||
MMUAccessType access_type,
|
||||
bool maperr, uintptr_t ra);
|
||||
|
||||
/**
|
||||
* cpu_loop_exit_sigbus:
|
||||
* @cpu: the cpu context
|
||||
* @addr: the guest address of the alignment fault
|
||||
* @access_type: access was read/write/execute
|
||||
* @ra: host pc for unwinding
|
||||
*
|
||||
* Use the TCGCPUOps hook to record cpu state, do guest operating system
|
||||
* specific things to raise SIGBUS, and jump to the main cpu loop.
|
||||
*/
|
||||
G_NORETURN void cpu_loop_exit_sigbus(CPUState *cpu, target_ulong addr,
|
||||
MMUAccessType access_type,
|
||||
uintptr_t ra);
|
||||
|
||||
#else
|
||||
static inline void mmap_lock(void) {}
|
||||
static inline void mmap_unlock(void) {}
|
||||
|
||||
void tlb_reset_dirty(CPUState *cpu, ram_addr_t start1, ram_addr_t length);
|
||||
void tlb_set_dirty(CPUState *cpu, target_ulong vaddr);
|
||||
|
||||
|
||||
+76
-15
@@ -10,11 +10,71 @@
|
||||
#define GDB_WATCHPOINT_READ 3
|
||||
#define GDB_WATCHPOINT_ACCESS 4
|
||||
|
||||
/* For gdb file i/o remote protocol open flags. */
|
||||
#define GDB_O_RDONLY 0
|
||||
#define GDB_O_WRONLY 1
|
||||
#define GDB_O_RDWR 2
|
||||
#define GDB_O_APPEND 8
|
||||
#define GDB_O_CREAT 0x200
|
||||
#define GDB_O_TRUNC 0x400
|
||||
#define GDB_O_EXCL 0x800
|
||||
|
||||
/* For gdb file i/o remote protocol errno values */
|
||||
#define GDB_EPERM 1
|
||||
#define GDB_ENOENT 2
|
||||
#define GDB_EINTR 4
|
||||
#define GDB_EBADF 9
|
||||
#define GDB_EACCES 13
|
||||
#define GDB_EFAULT 14
|
||||
#define GDB_EBUSY 16
|
||||
#define GDB_EEXIST 17
|
||||
#define GDB_ENODEV 19
|
||||
#define GDB_ENOTDIR 20
|
||||
#define GDB_EISDIR 21
|
||||
#define GDB_EINVAL 22
|
||||
#define GDB_ENFILE 23
|
||||
#define GDB_EMFILE 24
|
||||
#define GDB_EFBIG 27
|
||||
#define GDB_ENOSPC 28
|
||||
#define GDB_ESPIPE 29
|
||||
#define GDB_EROFS 30
|
||||
#define GDB_ENAMETOOLONG 91
|
||||
#define GDB_EUNKNOWN 9999
|
||||
|
||||
/* For gdb file i/o remote protocol lseek whence. */
|
||||
#define GDB_SEEK_SET 0
|
||||
#define GDB_SEEK_CUR 1
|
||||
#define GDB_SEEK_END 2
|
||||
|
||||
/* For gdb file i/o stat/fstat. */
|
||||
typedef uint32_t gdb_mode_t;
|
||||
typedef uint32_t gdb_time_t;
|
||||
|
||||
struct gdb_stat {
|
||||
uint32_t gdb_st_dev; /* device */
|
||||
uint32_t gdb_st_ino; /* inode */
|
||||
gdb_mode_t gdb_st_mode; /* protection */
|
||||
uint32_t gdb_st_nlink; /* number of hard links */
|
||||
uint32_t gdb_st_uid; /* user ID of owner */
|
||||
uint32_t gdb_st_gid; /* group ID of owner */
|
||||
uint32_t gdb_st_rdev; /* device type (if inode device) */
|
||||
uint64_t gdb_st_size; /* total size, in bytes */
|
||||
uint64_t gdb_st_blksize; /* blocksize for filesystem I/O */
|
||||
uint64_t gdb_st_blocks; /* number of blocks allocated */
|
||||
gdb_time_t gdb_st_atime; /* time of last access */
|
||||
gdb_time_t gdb_st_mtime; /* time of last modification */
|
||||
gdb_time_t gdb_st_ctime; /* time of last change */
|
||||
} QEMU_PACKED;
|
||||
|
||||
struct gdb_timeval {
|
||||
gdb_time_t tv_sec; /* second */
|
||||
uint64_t tv_usec; /* microsecond */
|
||||
} QEMU_PACKED;
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
#include "cpu.h"
|
||||
|
||||
typedef void (*gdb_syscall_complete_cb)(CPUState *cpu,
|
||||
target_ulong ret, target_ulong err);
|
||||
typedef void (*gdb_syscall_complete_cb)(CPUState *cpu, uint64_t ret, int err);
|
||||
|
||||
/**
|
||||
* gdb_do_syscall:
|
||||
@@ -45,17 +105,6 @@ void gdb_do_syscall(gdb_syscall_complete_cb cb, const char *fmt, ...);
|
||||
*/
|
||||
void gdb_do_syscallv(gdb_syscall_complete_cb cb, const char *fmt, va_list va);
|
||||
int use_gdb_syscalls(void);
|
||||
void gdb_set_stop_cpu(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* gdb_exit: exit gdb session, reporting inferior status
|
||||
* @code: exit code reported
|
||||
*
|
||||
* This closes the session and sends a final packet to GDB reporting
|
||||
* the exit status of the program. It also cleans up any connections
|
||||
* detritus before returning.
|
||||
*/
|
||||
void gdb_exit(int code);
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
/**
|
||||
@@ -121,7 +170,7 @@ static inline int gdb_get_reg128(GByteArray *buf, uint64_t val_hi,
|
||||
uint64_t val_lo)
|
||||
{
|
||||
uint64_t to_quad;
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
#if TARGET_BIG_ENDIAN
|
||||
to_quad = tswap64(val_hi);
|
||||
g_byte_array_append(buf, (uint8_t *) &to_quad, 8);
|
||||
to_quad = tswap64(val_lo);
|
||||
@@ -165,7 +214,7 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
|
||||
#define ldtul_p(addr) ldl_p(addr)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* NEED_CPU_H */
|
||||
|
||||
/**
|
||||
* gdbserver_start: start the gdb server
|
||||
@@ -177,6 +226,18 @@ static inline uint8_t * gdb_get_reg_ptr(GByteArray *buf, int len)
|
||||
*/
|
||||
int gdbserver_start(const char *port_or_device);
|
||||
|
||||
/**
|
||||
* gdb_exit: exit gdb session, reporting inferior status
|
||||
* @code: exit code reported
|
||||
*
|
||||
* This closes the session and sends a final packet to GDB reporting
|
||||
* the exit status of the program. It also cleans up any connections
|
||||
* detritus before returning.
|
||||
*/
|
||||
void gdb_exit(int code);
|
||||
|
||||
void gdb_set_stop_cpu(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* gdb_has_xml:
|
||||
* This is an ugly hack to cope with both new and old gdb.
|
||||
|
||||
+27
-21
@@ -17,27 +17,10 @@ static inline void gen_io_start(void)
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* cpu->can_do_io is cleared automatically at the beginning of
|
||||
* each translation block. The cost is minimal and only paid
|
||||
* for -icount, plus it would be very easy to forget doing it
|
||||
* in the translator. Therefore, backends only need to call
|
||||
* gen_io_start.
|
||||
*/
|
||||
static inline void gen_io_end(void)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(0);
|
||||
tcg_gen_st_i32(tmp, cpu_env,
|
||||
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
static inline void gen_tb_start(const TranslationBlock *tb)
|
||||
{
|
||||
TCGv_i32 count;
|
||||
|
||||
tcg_ctx->exitreq_label = gen_new_label();
|
||||
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
||||
count = tcg_temp_local_new_i32();
|
||||
} else {
|
||||
@@ -58,13 +41,34 @@ static inline void gen_tb_start(const TranslationBlock *tb)
|
||||
icount_start_insn = tcg_last_op();
|
||||
}
|
||||
|
||||
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
|
||||
/*
|
||||
* Emit the check against icount_decr.u32 to see if we should exit
|
||||
* unless we suppress the check with CF_NOIRQ. If we are using
|
||||
* icount and have suppressed interruption the higher level code
|
||||
* should have ensured we don't run more instructions than the
|
||||
* budget.
|
||||
*/
|
||||
if (tb_cflags(tb) & CF_NOIRQ) {
|
||||
tcg_ctx->exitreq_label = NULL;
|
||||
} else {
|
||||
tcg_ctx->exitreq_label = gen_new_label();
|
||||
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, tcg_ctx->exitreq_label);
|
||||
}
|
||||
|
||||
if (tb_cflags(tb) & CF_USE_ICOUNT) {
|
||||
tcg_gen_st16_i32(count, cpu_env,
|
||||
offsetof(ArchCPU, neg.icount_decr.u16.low) -
|
||||
offsetof(ArchCPU, env));
|
||||
gen_io_end();
|
||||
/*
|
||||
* cpu->can_do_io is cleared automatically here at the beginning of
|
||||
* each translation block. The cost is minimal and only paid for
|
||||
* -icount, plus it would be very easy to forget doing it in the
|
||||
* translator. Doing it here means we don't need a gen_io_end() to
|
||||
* go with gen_io_start().
|
||||
*/
|
||||
tcg_gen_st_i32(tcg_constant_i32(0), cpu_env,
|
||||
offsetof(ArchCPU, parent_obj.can_do_io) -
|
||||
offsetof(ArchCPU, env));
|
||||
}
|
||||
|
||||
tcg_temp_free_i32(count);
|
||||
@@ -81,8 +85,10 @@ static inline void gen_tb_end(const TranslationBlock *tb, int num_insns)
|
||||
tcgv_i32_arg(tcg_constant_i32(num_insns)));
|
||||
}
|
||||
|
||||
gen_set_label(tcg_ctx->exitreq_label);
|
||||
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
|
||||
if (tcg_ctx->exitreq_label) {
|
||||
gen_set_label(tcg_ctx->exitreq_label);
|
||||
tcg_gen_exit_tb(tb, TB_EXIT_REQUESTED);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,8 +79,6 @@ static inline void glue(gen_helper_, name)(dh_retvar_decl(ret) \
|
||||
}
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "trace/generated-helpers-wrappers.h"
|
||||
#include "accel/tcg/tcg-runtime.h"
|
||||
#include "accel/tcg/plugin-helpers.h"
|
||||
|
||||
|
||||
+11
-10
@@ -46,20 +46,23 @@
|
||||
#define dh_ctype_ptr void *
|
||||
#define dh_ctype_cptr const void *
|
||||
#define dh_ctype_void void
|
||||
#define dh_ctype_noreturn void QEMU_NORETURN
|
||||
#define dh_ctype_noreturn G_NORETURN void
|
||||
#define dh_ctype(t) dh_ctype_##t
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
# ifdef TARGET_LONG_BITS
|
||||
# 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
|
||||
# endif
|
||||
# define dh_alias_env ptr
|
||||
# define dh_ctype_tl target_ulong
|
||||
# define dh_alias_env ptr
|
||||
# define dh_ctype_env CPUArchState *
|
||||
# define dh_typecode_env dh_typecode_ptr
|
||||
#endif
|
||||
|
||||
/* We can't use glue() here because it falls foul of C preprocessor
|
||||
@@ -92,18 +95,16 @@
|
||||
#define dh_typecode_i64 4
|
||||
#define dh_typecode_s64 5
|
||||
#define dh_typecode_ptr 6
|
||||
#define dh_typecode(t) glue(dh_typecode_, dh_alias(t))
|
||||
#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(t) dh_typecode_##t
|
||||
|
||||
#define dh_callflag_i32 0
|
||||
#define dh_callflag_s32 0
|
||||
#define dh_callflag_int 0
|
||||
#define dh_callflag_i64 0
|
||||
#define dh_callflag_s64 0
|
||||
#define dh_callflag_f16 0
|
||||
#define dh_callflag_f32 0
|
||||
#define dh_callflag_f64 0
|
||||
#define dh_callflag_ptr 0
|
||||
#define dh_callflag_cptr dh_callflag_ptr
|
||||
#define dh_callflag_void 0
|
||||
#define dh_callflag_noreturn TCG_CALL_NO_RETURN
|
||||
#define dh_callflag(t) glue(dh_callflag_, dh_alias(t))
|
||||
|
||||
@@ -38,7 +38,6 @@ dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2), dh_ctype(t3), \
|
||||
#define IN_HELPER_PROTO
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "accel/tcg/tcg-runtime.h"
|
||||
#include "accel/tcg/plugin-helpers.h"
|
||||
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
| dh_typemask(t5, 5) | dh_typemask(t6, 6) | dh_typemask(t7, 7) },
|
||||
|
||||
#include "helper.h"
|
||||
#include "trace/generated-helpers.h"
|
||||
#include "accel/tcg/tcg-runtime.h"
|
||||
#include "accel/tcg/plugin-helpers.h"
|
||||
|
||||
|
||||
+4
-48
@@ -15,15 +15,10 @@
|
||||
*/
|
||||
static inline void log_cpu_state(CPUState *cpu, int flags)
|
||||
{
|
||||
QemuLogFile *logfile;
|
||||
|
||||
if (qemu_log_enabled()) {
|
||||
rcu_read_lock();
|
||||
logfile = qatomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
cpu_dump_state(cpu, logfile->fd, flags);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
FILE *f = qemu_log_trylock();
|
||||
if (f) {
|
||||
cpu_dump_state(cpu, f, flags);
|
||||
qemu_log_unlock(f);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,43 +37,4 @@ static inline void log_cpu_state_mask(int mask, CPUState *cpu, int flags)
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
/* disas() and target_disas() to qemu_logfile: */
|
||||
static inline void log_target_disas(CPUState *cpu, target_ulong start,
|
||||
target_ulong len)
|
||||
{
|
||||
QemuLogFile *logfile;
|
||||
rcu_read_lock();
|
||||
logfile = qatomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
target_disas(logfile->fd, cpu, start, len);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
static inline void log_disas(const void *code, unsigned long size)
|
||||
{
|
||||
QemuLogFile *logfile;
|
||||
rcu_read_lock();
|
||||
logfile = qatomic_rcu_read(&qemu_logfile);
|
||||
if (logfile) {
|
||||
disas(logfile->fd, code, size);
|
||||
}
|
||||
rcu_read_unlock();
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* page_dump() output to the log file: */
|
||||
static inline void log_page_dump(const char *operation)
|
||||
{
|
||||
FILE *logfile = qemu_log_lock();
|
||||
if (logfile) {
|
||||
qemu_log("page layout changed following %s\n", operation);
|
||||
page_dump(logfile);
|
||||
}
|
||||
qemu_log_unlock(logfile);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -35,6 +35,14 @@ typedef struct MemTxAttrs {
|
||||
unsigned int secure:1;
|
||||
/* 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;
|
||||
/* Requester ID (for MSI for example) */
|
||||
unsigned int requester_id:16;
|
||||
/* Invert endianness for this page */
|
||||
@@ -66,6 +74,7 @@ typedef struct MemTxAttrs {
|
||||
#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
|
||||
|
||||
+22
-11
@@ -19,12 +19,16 @@ typedef enum MemOp {
|
||||
MO_16 = 1,
|
||||
MO_32 = 2,
|
||||
MO_64 = 3,
|
||||
MO_SIZE = 3, /* Mask for the above. */
|
||||
MO_128 = 4,
|
||||
MO_256 = 5,
|
||||
MO_512 = 6,
|
||||
MO_1024 = 7,
|
||||
MO_SIZE = 0x07, /* Mask for the above. */
|
||||
|
||||
MO_SIGN = 4, /* Sign-extended, otherwise zero-extended. */
|
||||
MO_SIGN = 0x08, /* Sign-extended, otherwise zero-extended. */
|
||||
|
||||
MO_BSWAP = 8, /* Host reverse endian. */
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
MO_BSWAP = 0x10, /* Host reverse endian. */
|
||||
#if HOST_BIG_ENDIAN
|
||||
MO_LE = MO_BSWAP,
|
||||
MO_BE = 0,
|
||||
#else
|
||||
@@ -32,7 +36,7 @@ typedef enum MemOp {
|
||||
MO_BE = MO_BSWAP,
|
||||
#endif
|
||||
#ifdef NEED_CPU_H
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
#if TARGET_BIG_ENDIAN
|
||||
MO_TE = MO_BE,
|
||||
#else
|
||||
MO_TE = MO_LE,
|
||||
@@ -59,8 +63,8 @@ typedef enum MemOp {
|
||||
* - 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 = 4,
|
||||
MO_AMASK = 7 << MO_ASHIFT,
|
||||
MO_ASHIFT = 5,
|
||||
MO_AMASK = 0x7 << MO_ASHIFT,
|
||||
#ifdef NEED_CPU_H
|
||||
#ifdef TARGET_ALIGNED_ONLY
|
||||
MO_ALIGN = 0,
|
||||
@@ -81,29 +85,36 @@ typedef enum MemOp {
|
||||
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_Q = MO_64,
|
||||
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_LEQ = MO_LE | MO_Q,
|
||||
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_BEQ = MO_BE | MO_Q,
|
||||
MO_BESQ = MO_BE | MO_SQ,
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
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_TEQ = MO_TE | MO_Q,
|
||||
MO_TESQ = MO_TE | MO_SQ,
|
||||
#endif
|
||||
|
||||
MO_SSIZE = MO_SIZE | MO_SIGN,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Combine the MemOp and mmu_idx parameters into a single value.
|
||||
*
|
||||
* Authors:
|
||||
* Richard Henderson <rth@twiddle.net>
|
||||
*
|
||||
* 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 <= 15);
|
||||
#endif
|
||||
return (op << 4) | 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 >> 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_mmuidx
|
||||
* @oi: combined op/idx parameter
|
||||
*
|
||||
* Extract the mmu index from the combined value.
|
||||
*/
|
||||
static inline unsigned get_mmuidx(MemOpIdx oi)
|
||||
{
|
||||
return oi & 15;
|
||||
}
|
||||
|
||||
#endif
|
||||
+94
-10
@@ -61,7 +61,20 @@ static inline void fuzz_dma_read_cb(size_t addr,
|
||||
}
|
||||
#endif
|
||||
|
||||
extern bool global_dirty_log;
|
||||
/* Possible bits for global_dirty_log_{start|stop} */
|
||||
|
||||
/* Dirty tracking enabled because migration is running */
|
||||
#define GLOBAL_DIRTY_MIGRATION (1U << 0)
|
||||
|
||||
/* Dirty tracking enabled because measuring dirty rate */
|
||||
#define GLOBAL_DIRTY_DIRTY_RATE (1U << 1)
|
||||
|
||||
/* Dirty tracking enabled because dirty limit */
|
||||
#define GLOBAL_DIRTY_LIMIT (1U << 2)
|
||||
|
||||
#define GLOBAL_DIRTY_MASK (0x7)
|
||||
|
||||
extern unsigned int global_dirty_tracking;
|
||||
|
||||
typedef struct MemoryRegionOps MemoryRegionOps;
|
||||
|
||||
@@ -190,6 +203,9 @@ typedef struct IOMMUTLBEvent {
|
||||
*/
|
||||
#define RAM_NORESERVE (1 << 7)
|
||||
|
||||
/* RAM that isn't accessible through normal means. */
|
||||
#define RAM_PROTECTED (1 << 8)
|
||||
|
||||
static inline void iommu_notifier_init(IOMMUNotifier *n, IOMMUNotify fn,
|
||||
IOMMUNotifierFlag flags,
|
||||
hwaddr start, hwaddr end,
|
||||
@@ -537,6 +553,7 @@ static inline void ram_discard_listener_init(RamDiscardListener *rdl,
|
||||
}
|
||||
|
||||
typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaque);
|
||||
typedef void (*ReplayRamDiscard)(MemoryRegionSection *section, void *opaque);
|
||||
|
||||
/*
|
||||
* RamDiscardManagerClass:
|
||||
@@ -544,7 +561,7 @@ typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaque);
|
||||
* A #RamDiscardManager coordinates which parts of specific RAM #MemoryRegion
|
||||
* regions are currently populated to be used/accessed by the VM, notifying
|
||||
* after parts were discarded (freeing up memory) and before parts will be
|
||||
* populated (consuming memory), to be used/acessed by the VM.
|
||||
* populated (consuming memory), to be used/accessed by the VM.
|
||||
*
|
||||
* A #RamDiscardManager can only be set for a RAM #MemoryRegion while the
|
||||
* #MemoryRegion isn't mapped yet; it cannot change while the #MemoryRegion is
|
||||
@@ -568,7 +585,7 @@ typedef int (*ReplayRamPopulate)(MemoryRegionSection *section, void *opaque);
|
||||
* Listeners are called in multiples of the minimum granularity (unless it
|
||||
* would exceed the registered range) and changes are aligned to the minimum
|
||||
* granularity within the #MemoryRegion. Listeners have to prepare for memory
|
||||
* becomming discarded in a different granularity than it was populated and the
|
||||
* becoming discarded in a different granularity than it was populated and the
|
||||
* other way around.
|
||||
*/
|
||||
struct RamDiscardManagerClass {
|
||||
@@ -625,6 +642,21 @@ struct RamDiscardManagerClass {
|
||||
MemoryRegionSection *section,
|
||||
ReplayRamPopulate replay_fn, void *opaque);
|
||||
|
||||
/**
|
||||
* @replay_discarded:
|
||||
*
|
||||
* Call the #ReplayRamDiscard callback for all discarded parts within the
|
||||
* #MemoryRegionSection via the #RamDiscardManager.
|
||||
*
|
||||
* @rdm: the #RamDiscardManager
|
||||
* @section: the #MemoryRegionSection
|
||||
* @replay_fn: the #ReplayRamDiscard callback
|
||||
* @opaque: pointer to forward to the callback
|
||||
*/
|
||||
void (*replay_discarded)(const RamDiscardManager *rdm,
|
||||
MemoryRegionSection *section,
|
||||
ReplayRamDiscard replay_fn, void *opaque);
|
||||
|
||||
/**
|
||||
* @register_listener:
|
||||
*
|
||||
@@ -669,6 +701,11 @@ int ram_discard_manager_replay_populated(const RamDiscardManager *rdm,
|
||||
ReplayRamPopulate replay_fn,
|
||||
void *opaque);
|
||||
|
||||
void ram_discard_manager_replay_discarded(const RamDiscardManager *rdm,
|
||||
MemoryRegionSection *section,
|
||||
ReplayRamDiscard replay_fn,
|
||||
void *opaque);
|
||||
|
||||
void ram_discard_manager_register_listener(RamDiscardManager *rdm,
|
||||
RamDiscardListener *rdl,
|
||||
MemoryRegionSection *section);
|
||||
@@ -676,6 +713,10 @@ void ram_discard_manager_register_listener(RamDiscardManager *rdm,
|
||||
void ram_discard_manager_unregister_listener(RamDiscardManager *rdm,
|
||||
RamDiscardListener *rdl);
|
||||
|
||||
bool memory_get_xlat_addr(IOMMUTLBEntry *iotlb, void **vaddr,
|
||||
ram_addr_t *ram_addr, bool *read_only,
|
||||
bool *mr_has_discard_manager);
|
||||
|
||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
||||
|
||||
@@ -704,6 +745,7 @@ struct MemoryRegion {
|
||||
const MemoryRegionOps *ops;
|
||||
void *opaque;
|
||||
MemoryRegion *container;
|
||||
int mapped_via_alias; /* Mapped via an alias, container might be NULL */
|
||||
Int128 size;
|
||||
hwaddr addr;
|
||||
void (*destructor)(MemoryRegion *mr);
|
||||
@@ -979,6 +1021,14 @@ struct MemoryListener {
|
||||
*/
|
||||
unsigned priority;
|
||||
|
||||
/**
|
||||
* @name:
|
||||
*
|
||||
* Name of the listener. It can be used in contexts where we'd like to
|
||||
* identify one memory listener with the rest.
|
||||
*/
|
||||
const char *name;
|
||||
|
||||
/* private: */
|
||||
AddressSpace *address_space;
|
||||
QTAILQ_ENTRY(MemoryListener) link;
|
||||
@@ -1203,7 +1253,7 @@ void memory_region_init_ram_flags_nomigrate(MemoryRegion *mr,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_init_resizeable_ram: Initialize memory region with resizeable
|
||||
* memory_region_init_resizeable_ram: Initialize memory region with resizable
|
||||
* RAM. Accesses into the region will
|
||||
* modify memory directly. Only an initial
|
||||
* portion of this RAM is actually used.
|
||||
@@ -1273,7 +1323,7 @@ void memory_region_init_ram_from_file(MemoryRegion *mr,
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @ram_flags: RamBlock flags. Supported flags: RAM_SHARED, RAM_PMEM,
|
||||
* RAM_NORESERVE.
|
||||
* RAM_NORESERVE, RAM_PROTECTED.
|
||||
* @fd: the fd to mmap.
|
||||
* @offset: offset within the file referenced by fd
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
@@ -1574,6 +1624,16 @@ static inline bool memory_region_is_romd(MemoryRegion *mr)
|
||||
return mr->rom_device && mr->romd_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* memory_region_is_protected: check whether a memory region is protected
|
||||
*
|
||||
* Returns %true if a memory region is protected RAM and cannot be accessed
|
||||
* via standard mechanisms, e.g. DMA.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_protected(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_get_iommu: check whether a memory region is an iommu
|
||||
*
|
||||
@@ -1939,7 +1999,7 @@ void memory_region_clear_dirty_bitmap(MemoryRegion *mr, hwaddr start,
|
||||
* querying the same page multiple times, which is especially useful for
|
||||
* display updates where the scanlines often are not page aligned.
|
||||
*
|
||||
* The dirty bitmap region which gets copyed into the snapshot (and
|
||||
* The dirty bitmap region which gets copied into the snapshot (and
|
||||
* cleared afterwards) can be larger than requested. The boundaries
|
||||
* are rounded up/down so complete bitmap longs (covering 64 pages on
|
||||
* 64bit hosts) can be copied over into the bitmap snapshot. Which
|
||||
@@ -2269,7 +2329,8 @@ bool memory_region_present(MemoryRegion *container, hwaddr addr);
|
||||
|
||||
/**
|
||||
* memory_region_is_mapped: returns true if #MemoryRegion is mapped
|
||||
* into any address space.
|
||||
* into another memory region, which does not necessarily imply that it is
|
||||
* mapped into an address space.
|
||||
*
|
||||
* @mr: a #MemoryRegion which should be checked if it's mapped
|
||||
*/
|
||||
@@ -2392,13 +2453,17 @@ void memory_listener_unregister(MemoryListener *listener);
|
||||
|
||||
/**
|
||||
* memory_global_dirty_log_start: begin dirty logging for all regions
|
||||
*
|
||||
* @flags: purpose of starting dirty log, migration or dirty rate
|
||||
*/
|
||||
void memory_global_dirty_log_start(void);
|
||||
void memory_global_dirty_log_start(unsigned int flags);
|
||||
|
||||
/**
|
||||
* memory_global_dirty_log_stop: end dirty logging for all regions
|
||||
*
|
||||
* @flags: purpose of stopping dirty log, migration or dirty rate
|
||||
*/
|
||||
void memory_global_dirty_log_stop(void);
|
||||
void memory_global_dirty_log_stop(unsigned int flags);
|
||||
|
||||
void mtree_info(bool flatview, bool dispatch_tree, bool owner, bool disabled);
|
||||
|
||||
@@ -2777,6 +2842,9 @@ MemTxResult address_space_write_cached_slow(MemoryRegionCache *cache,
|
||||
hwaddr addr, const void *buf,
|
||||
hwaddr len);
|
||||
|
||||
int memory_access_size(MemoryRegion *mr, unsigned l, hwaddr addr);
|
||||
bool prepare_mmio_access(MemoryRegion *mr);
|
||||
|
||||
static inline bool memory_access_is_direct(MemoryRegion *mr, bool is_write)
|
||||
{
|
||||
if (is_write) {
|
||||
@@ -2875,6 +2943,22 @@ address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* address_space_set: Fill address space with a constant byte.
|
||||
*
|
||||
* Return a MemTxResult indicating whether the operation succeeded
|
||||
* or failed (eg unassigned memory, device rejected the transaction,
|
||||
* IOMMU fault).
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @c: constant byte to fill the memory
|
||||
* @len: the number of bytes to fill with the constant byte
|
||||
* @attrs: memory transaction attributes
|
||||
*/
|
||||
MemTxResult address_space_set(AddressSpace *as, hwaddr addr,
|
||||
uint8_t c, hwaddr len, MemTxAttrs attrs);
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
/* enum device_endian to MemOp. */
|
||||
static inline MemOp devend_memop(enum device_endian end)
|
||||
@@ -2882,7 +2966,7 @@ static inline MemOp devend_memop(enum device_endian end)
|
||||
QEMU_BUILD_BUG_ON(DEVICE_HOST_ENDIAN != DEVICE_LITTLE_ENDIAN &&
|
||||
DEVICE_HOST_ENDIAN != DEVICE_BIG_ENDIAN);
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
#if HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN
|
||||
/* Swap if non-host endianness or native (target) endianness */
|
||||
return (end == DEVICE_HOST_ENDIAN) ? 0 : MO_BSWAP;
|
||||
#else
|
||||
|
||||
@@ -31,4 +31,22 @@ extern bool set_preferred_target_page_bits_common(int bits);
|
||||
extern void finalize_target_page_bits_common(int min);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
#endif /* EXEC_PAGE_VARY_H */
|
||||
|
||||
@@ -19,7 +19,8 @@ struct DisasContextBase;
|
||||
|
||||
#ifdef CONFIG_PLUGIN
|
||||
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress);
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db,
|
||||
bool supress);
|
||||
void plugin_gen_tb_end(CPUState *cpu);
|
||||
void plugin_gen_insn_start(CPUState *cpu, const struct DisasContextBase *db);
|
||||
void plugin_gen_insn_end(void);
|
||||
@@ -27,21 +28,29 @@ void plugin_gen_insn_end(void);
|
||||
void plugin_gen_disable_mem_helpers(void);
|
||||
void plugin_gen_empty_mem_callback(TCGv addr, uint32_t info);
|
||||
|
||||
static inline void plugin_insn_append(const void *from, size_t size)
|
||||
static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
|
||||
{
|
||||
struct qemu_plugin_insn *insn = tcg_ctx->plugin_insn;
|
||||
abi_ptr off;
|
||||
|
||||
if (insn == NULL) {
|
||||
return;
|
||||
}
|
||||
off = pc - insn->vaddr;
|
||||
if (off < insn->data->len) {
|
||||
g_byte_array_set_size(insn->data, off);
|
||||
} else if (off > insn->data->len) {
|
||||
/* we have an unexpected gap */
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
insn->data = g_byte_array_append(insn->data, from, size);
|
||||
}
|
||||
|
||||
#else /* !CONFIG_PLUGIN */
|
||||
|
||||
static inline
|
||||
bool plugin_gen_tb_start(CPUState *cpu, const TranslationBlock *tb, bool supress)
|
||||
static inline bool
|
||||
plugin_gen_tb_start(CPUState *cpu, const struct DisasContextBase *db, bool sup)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -62,7 +71,7 @@ static inline void plugin_gen_disable_mem_helpers(void)
|
||||
static inline void plugin_gen_empty_mem_callback(TCGv addr, uint32_t info)
|
||||
{ }
|
||||
|
||||
static inline void plugin_insn_append(const void *from, size_t size)
|
||||
static inline void plugin_insn_append(abi_ptr pc, const void *from, size_t size)
|
||||
{ }
|
||||
|
||||
#endif /* CONFIG_PLUGIN */
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#pragma GCC poison TARGET_CRIS
|
||||
#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
|
||||
@@ -38,7 +39,7 @@
|
||||
#pragma GCC poison TARGET_HAS_BFLT
|
||||
#pragma GCC poison TARGET_NAME
|
||||
#pragma GCC poison TARGET_SUPPORTS_MTTCG
|
||||
#pragma GCC poison TARGET_WORDS_BIGENDIAN
|
||||
#pragma GCC poison TARGET_BIG_ENDIAN
|
||||
#pragma GCC poison BSWAP_NEEDED
|
||||
|
||||
#pragma GCC poison TARGET_LONG_BITS
|
||||
@@ -51,8 +52,6 @@
|
||||
#pragma GCC poison TARGET_PAGE_BITS
|
||||
#pragma GCC poison TARGET_PAGE_ALIGN
|
||||
|
||||
#pragma GCC poison CPUArchState
|
||||
|
||||
#pragma GCC poison CPU_INTERRUPT_HARD
|
||||
#pragma GCC poison CPU_INTERRUPT_EXITTB
|
||||
#pragma GCC poison CPU_INTERRUPT_HALT
|
||||
@@ -67,12 +66,11 @@
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_INT_2
|
||||
|
||||
#pragma GCC poison CONFIG_ALPHA_DIS
|
||||
#pragma GCC poison CONFIG_ARM_A64_DIS
|
||||
#pragma GCC poison CONFIG_ARM_DIS
|
||||
#pragma GCC poison CONFIG_CRIS_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
|
||||
|
||||
+18
-10
@@ -26,6 +26,8 @@
|
||||
#include "exec/ramlist.h"
|
||||
#include "exec/ramblock.h"
|
||||
|
||||
extern uint64_t total_dirty_pages;
|
||||
|
||||
/**
|
||||
* clear_bmap_size: calculate clear bitmap size
|
||||
*
|
||||
@@ -40,7 +42,8 @@ static inline long clear_bmap_size(uint64_t pages, uint8_t shift)
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bmap_set: set clear bitmap for the page range
|
||||
* clear_bmap_set: set clear bitmap for the page range. Must be with
|
||||
* bitmap_mutex held.
|
||||
*
|
||||
* @rb: the ramblock to operate on
|
||||
* @start: the start page number
|
||||
@@ -53,12 +56,12 @@ static inline void clear_bmap_set(RAMBlock *rb, uint64_t start,
|
||||
{
|
||||
uint8_t shift = rb->clear_bmap_shift;
|
||||
|
||||
bitmap_set_atomic(rb->clear_bmap, start >> shift,
|
||||
clear_bmap_size(npages, shift));
|
||||
bitmap_set(rb->clear_bmap, start >> shift, clear_bmap_size(npages, shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bmap_test_and_clear: test clear bitmap for the page, clear if set
|
||||
* clear_bmap_test_and_clear: test clear bitmap for the page, clear if set.
|
||||
* Must be with bitmap_mutex held.
|
||||
*
|
||||
* @rb: the ramblock to operate on
|
||||
* @page: the page number to check
|
||||
@@ -69,7 +72,7 @@ static inline bool clear_bmap_test_and_clear(RAMBlock *rb, uint64_t page)
|
||||
{
|
||||
uint8_t shift = rb->clear_bmap_shift;
|
||||
|
||||
return bitmap_test_and_clear_atomic(rb->clear_bmap, page >> shift, 1);
|
||||
return bitmap_test_and_clear(rb->clear_bmap, page >> shift, 1);
|
||||
}
|
||||
|
||||
static inline bool offset_in_ramblock(RAMBlock *b, ram_addr_t offset)
|
||||
@@ -145,8 +148,6 @@ static inline void qemu_ram_block_writeback(RAMBlock *block)
|
||||
#define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1)
|
||||
#define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE))
|
||||
|
||||
void tb_invalidate_phys_range(ram_addr_t start, ram_addr_t end);
|
||||
|
||||
static inline bool cpu_physical_memory_get_dirty(ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
@@ -359,7 +360,7 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
|
||||
hwaddr addr;
|
||||
ram_addr_t ram_addr;
|
||||
unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
|
||||
unsigned long hpratio = qemu_real_host_page_size / TARGET_PAGE_SIZE;
|
||||
unsigned long hpratio = qemu_real_host_page_size() / TARGET_PAGE_SIZE;
|
||||
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
|
||||
|
||||
/* start address is aligned at the start of a word? */
|
||||
@@ -389,10 +390,14 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
|
||||
qatomic_or(&blocks[DIRTY_MEMORY_NV2A][idx][offset], temp);
|
||||
qatomic_or(&blocks[DIRTY_MEMORY_NV2A_TEX][idx][offset], temp);
|
||||
|
||||
if (global_dirty_log) {
|
||||
if (global_dirty_tracking) {
|
||||
qatomic_or(
|
||||
&blocks[DIRTY_MEMORY_MIGRATION][idx][offset],
|
||||
temp);
|
||||
if (unlikely(
|
||||
global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
|
||||
total_dirty_pages += ctpopl(temp);
|
||||
}
|
||||
}
|
||||
|
||||
if (tcg_enabled()) {
|
||||
@@ -412,7 +417,7 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
|
||||
} else {
|
||||
uint8_t clients = tcg_enabled() ? DIRTY_CLIENTS_ALL : DIRTY_CLIENTS_NOCODE;
|
||||
|
||||
if (!global_dirty_log) {
|
||||
if (!global_dirty_tracking) {
|
||||
clients &= ~(1 << DIRTY_MEMORY_MIGRATION);
|
||||
}
|
||||
|
||||
@@ -423,6 +428,9 @@ static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap,
|
||||
for (i = 0; i < len; i++) {
|
||||
if (bitmap[i] != 0) {
|
||||
c = leul_to_cpu(bitmap[i]);
|
||||
if (unlikely(global_dirty_tracking & GLOBAL_DIRTY_DIRTY_RATE)) {
|
||||
total_dirty_pages += ctpopl(c);
|
||||
}
|
||||
do {
|
||||
j = ctzl(c);
|
||||
c &= ~(1ul << j);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user