import
This commit is contained in:
2
qemu/include/config.h
Normal file
2
qemu/include/config.h
Normal file
@@ -0,0 +1,2 @@
|
||||
#include "config-host.h"
|
||||
#include "config-target.h"
|
||||
1548
qemu/include/elf.h
Normal file
1548
qemu/include/elf.h
Normal file
File diff suppressed because it is too large
Load Diff
35
qemu/include/exec/address-spaces.h
Normal file
35
qemu/include/exec/address-spaces.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Internal memory management interfaces
|
||||
*
|
||||
* Copyright 2011 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Avi Kivity <avi@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EXEC_MEMORY_H
|
||||
#define EXEC_MEMORY_H
|
||||
|
||||
/*
|
||||
* Internal interfaces between memory.c/exec.c/vl.c. Do not #include unless
|
||||
* you're one of them.
|
||||
*/
|
||||
|
||||
#include "exec/memory.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/* Get the root memory region. This interface should only be used temporarily
|
||||
* until a proper bus interface is available.
|
||||
*/
|
||||
MemoryRegion *get_system_memory(struct uc_struct *uc);
|
||||
|
||||
extern AddressSpace address_space_memory;
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
309
qemu/include/exec/cpu-all.h
Normal file
309
qemu/include/exec/cpu-all.h
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* defines common to all virtual 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 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_ALL_H
|
||||
#define CPU_ALL_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
/* some important defines:
|
||||
*
|
||||
* WORDS_ALIGNED : if defined, the host cpu can only make word aligned
|
||||
* memory accesses.
|
||||
*
|
||||
* HOST_WORDS_BIGENDIAN : if defined, the host cpu is big endian and
|
||||
* otherwise little endian.
|
||||
*
|
||||
* (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
|
||||
*
|
||||
* TARGET_WORDS_BIGENDIAN : same for target cpu
|
||||
*/
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
|
||||
#define BSWAP_NEEDED
|
||||
#endif
|
||||
|
||||
#ifdef BSWAP_NEEDED
|
||||
|
||||
static inline uint16_t tswap16(uint16_t s)
|
||||
{
|
||||
return bswap16(s);
|
||||
}
|
||||
|
||||
static inline uint32_t tswap32(uint32_t s)
|
||||
{
|
||||
return bswap32(s);
|
||||
}
|
||||
|
||||
static inline uint64_t tswap64(uint64_t s)
|
||||
{
|
||||
return bswap64(s);
|
||||
}
|
||||
|
||||
static inline void tswap16s(uint16_t *s)
|
||||
{
|
||||
*s = bswap16(*s);
|
||||
}
|
||||
|
||||
static inline void tswap32s(uint32_t *s)
|
||||
{
|
||||
*s = bswap32(*s);
|
||||
}
|
||||
|
||||
static inline void tswap64s(uint64_t *s)
|
||||
{
|
||||
*s = bswap64(*s);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline uint16_t tswap16(uint16_t s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline uint32_t tswap32(uint32_t s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline uint64_t tswap64(uint64_t s)
|
||||
{
|
||||
return s;
|
||||
}
|
||||
|
||||
static inline void tswap16s(uint16_t *s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tswap32s(uint32_t *s)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tswap64s(uint64_t *s)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if TARGET_LONG_SIZE == 4
|
||||
#define tswapl(s) tswap32(s)
|
||||
#define tswapls(s) tswap32s((uint32_t *)(s))
|
||||
#define bswaptls(s) bswap32s(s)
|
||||
#else
|
||||
#define tswapl(s) tswap64(s)
|
||||
#define tswapls(s) tswap64s((uint64_t *)(s))
|
||||
#define bswaptls(s) bswap64s(s)
|
||||
#endif
|
||||
|
||||
/* CPU memory access without any memory or io remapping */
|
||||
|
||||
/*
|
||||
* the generic syntax for the memory accesses is:
|
||||
*
|
||||
* load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
|
||||
*
|
||||
* store: st{type}{size}{endian}_{access_type}(ptr, val)
|
||||
*
|
||||
* type is:
|
||||
* (empty): integer access
|
||||
* f : float access
|
||||
*
|
||||
* sign is:
|
||||
* (empty): for floats or 32 bit size
|
||||
* u : unsigned
|
||||
* s : signed
|
||||
*
|
||||
* size is:
|
||||
* b: 8 bits
|
||||
* w: 16 bits
|
||||
* l: 32 bits
|
||||
* q: 64 bits
|
||||
*
|
||||
* endian is:
|
||||
* (empty): target cpu endianness or 8 bit access
|
||||
* r : reversed target cpu endianness (not implemented yet)
|
||||
* be : big endian (not implemented yet)
|
||||
* le : little endian (not implemented yet)
|
||||
*
|
||||
* access_type is:
|
||||
* raw : host memory access
|
||||
* user : user mode access using soft MMU
|
||||
* kernel : kernel mode access using soft MMU
|
||||
*/
|
||||
|
||||
/* target-endianness CPU memory access functions */
|
||||
#if defined(TARGET_WORDS_BIGENDIAN)
|
||||
#define lduw_p(p) lduw_be_p(p)
|
||||
#define ldsw_p(p) ldsw_be_p(p)
|
||||
#define ldl_p(p) ldl_be_p(p)
|
||||
#define ldq_p(p) ldq_be_p(p)
|
||||
#define ldfl_p(p) ldfl_be_p(p)
|
||||
#define ldfq_p(p) ldfq_be_p(p)
|
||||
#define stw_p(p, v) stw_be_p(p, v)
|
||||
#define stl_p(p, v) stl_be_p(p, v)
|
||||
#define stq_p(p, v) stq_be_p(p, v)
|
||||
#define stfl_p(p, v) stfl_be_p(p, v)
|
||||
#define stfq_p(p, v) stfq_be_p(p, v)
|
||||
#else
|
||||
#define lduw_p(p) lduw_le_p(p)
|
||||
#define ldsw_p(p) ldsw_le_p(p)
|
||||
#define ldl_p(p) ldl_le_p(p)
|
||||
#define ldq_p(p) ldq_le_p(p)
|
||||
#define ldfl_p(p) ldfl_le_p(p)
|
||||
#define ldfq_p(p) ldfq_le_p(p)
|
||||
#define stw_p(p, v) stw_le_p(p, v)
|
||||
#define stl_p(p, v) stl_le_p(p, v)
|
||||
#define stq_p(p, v) stq_le_p(p, v)
|
||||
#define stfl_p(p, v) stfl_le_p(p, v)
|
||||
#define stfq_p(p, v) stfq_le_p(p, v)
|
||||
#endif
|
||||
|
||||
/* MMU memory access macros */
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
#include <assert.h>
|
||||
#include "exec/user/abitypes.h"
|
||||
|
||||
/* On some host systems the guest address space is reserved on the host.
|
||||
* This allows the guest address space to be offset to a convenient location.
|
||||
*/
|
||||
#if defined(CONFIG_USE_GUEST_BASE)
|
||||
extern unsigned long guest_base;
|
||||
extern int have_guest_base;
|
||||
extern unsigned long reserved_va;
|
||||
#define GUEST_BASE guest_base
|
||||
#define RESERVED_VA reserved_va
|
||||
#else
|
||||
#define GUEST_BASE 0ul
|
||||
#define RESERVED_VA 0ul
|
||||
#endif
|
||||
|
||||
#define GUEST_ADDR_MAX (RESERVED_VA ? RESERVED_VA : \
|
||||
(1ul << TARGET_VIRT_ADDR_SPACE_BITS) - 1)
|
||||
#endif
|
||||
|
||||
/* page related stuff */
|
||||
|
||||
#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
|
||||
#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
|
||||
#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
|
||||
|
||||
#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
|
||||
|
||||
/* same as PROT_xxx */
|
||||
#define PAGE_READ 0x0001
|
||||
#define PAGE_WRITE 0x0002
|
||||
#define PAGE_EXEC 0x0004
|
||||
#define PAGE_BITS (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
|
||||
#if defined(CONFIG_BSD) && defined(CONFIG_USER_ONLY)
|
||||
/* FIXME: Code that sets/uses this is broken and needs to go away. */
|
||||
#define PAGE_RESERVED 0x0020
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
//void page_dump(FILE *f);
|
||||
|
||||
int page_get_flags(target_ulong address);
|
||||
#endif
|
||||
|
||||
CPUArchState *cpu_copy(CPUArchState *env);
|
||||
|
||||
/* Flags for use in ENV->INTERRUPT_PENDING.
|
||||
|
||||
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)
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* memory API */
|
||||
|
||||
/* Flags stored in the low bits of the TLB virtual address. These are
|
||||
defined so that fast path ram access is all zeros. */
|
||||
/* Zero if TLB entry is valid. */
|
||||
#define TLB_INVALID_MASK (1 << 3)
|
||||
/* Set if TLB entry references a clean RAM page. The iotlb entry will
|
||||
contain the page physical address. */
|
||||
#define TLB_NOTDIRTY (1 << 4)
|
||||
/* Set if TLB entry is an IO callback. */
|
||||
#define TLB_MMIO (1 << 5)
|
||||
|
||||
ram_addr_t last_ram_offset(struct uc_struct *uc);
|
||||
void qemu_mutex_lock_ramlist(struct uc_struct *uc);
|
||||
void qemu_mutex_unlock_ramlist(struct uc_struct *uc);
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
|
||||
int cpu_memory_rw_debug(CPUState *cpu, target_ulong addr,
|
||||
uint8_t *buf, int len, int is_write);
|
||||
|
||||
#endif /* CPU_ALL_H */
|
||||
124
qemu/include/exec/cpu-common.h
Normal file
124
qemu/include/exec/cpu-common.h
Normal file
@@ -0,0 +1,124 @@
|
||||
#ifndef CPU_COMMON_H
|
||||
#define CPU_COMMON_H 1
|
||||
|
||||
/* CPU interfaces that are target independent. */
|
||||
|
||||
struct uc_struct;
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/hwaddr.h"
|
||||
#endif
|
||||
|
||||
#ifndef NEED_CPU_H
|
||||
#include "exec/poison.h"
|
||||
#endif
|
||||
|
||||
#include "qemu/bswap.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef enum MMUAccessType {
|
||||
MMU_DATA_LOAD = 0,
|
||||
MMU_DATA_STORE = 1,
|
||||
MMU_INST_FETCH = 2
|
||||
} MMUAccessType;
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
enum device_endian {
|
||||
DEVICE_NATIVE_ENDIAN,
|
||||
DEVICE_BIG_ENDIAN,
|
||||
DEVICE_LITTLE_ENDIAN,
|
||||
};
|
||||
|
||||
/* address in the RAM (different from a physical address) */
|
||||
#if defined(CONFIG_XEN_BACKEND)
|
||||
typedef uint64_t ram_addr_t;
|
||||
# define RAM_ADDR_MAX UINT64_MAX
|
||||
# define RAM_ADDR_FMT "%" PRIx64
|
||||
#else
|
||||
typedef uintptr_t ram_addr_t;
|
||||
# define RAM_ADDR_MAX UINTPTR_MAX
|
||||
# define RAM_ADDR_FMT "%" PRIxPTR
|
||||
#endif
|
||||
|
||||
extern ram_addr_t ram_size;
|
||||
|
||||
/* memory API */
|
||||
|
||||
typedef void CPUWriteMemoryFunc(void *opaque, hwaddr addr, uint32_t value);
|
||||
typedef uint32_t CPUReadMemoryFunc(void *opaque, hwaddr addr);
|
||||
|
||||
void qemu_ram_remap(struct uc_struct *uc, ram_addr_t addr, ram_addr_t length);
|
||||
/* This should not be used by devices. */
|
||||
MemoryRegion *qemu_ram_addr_from_host(struct uc_struct* uc, void *ptr, ram_addr_t *ram_addr);
|
||||
void qemu_ram_set_idstr(struct uc_struct *uc, ram_addr_t addr, const char *name, DeviceState *dev);
|
||||
void qemu_ram_unset_idstr(struct uc_struct *uc, ram_addr_t addr);
|
||||
|
||||
bool cpu_physical_memory_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
int len, int is_write);
|
||||
static inline void cpu_physical_memory_read(AddressSpace *as, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
cpu_physical_memory_rw(as, addr, buf, len, 0);
|
||||
}
|
||||
static inline void cpu_physical_memory_write(AddressSpace *as, hwaddr addr,
|
||||
const void *buf, int len)
|
||||
{
|
||||
cpu_physical_memory_rw(as, addr, (void *)buf, len, 1);
|
||||
}
|
||||
void *cpu_physical_memory_map(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *plen,
|
||||
int is_write);
|
||||
void cpu_physical_memory_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
||||
int is_write, hwaddr access_len);
|
||||
void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
|
||||
|
||||
bool cpu_physical_memory_is_io(AddressSpace *as, hwaddr phys_addr);
|
||||
|
||||
/* Coalesced MMIO regions are areas where write operations can be reordered.
|
||||
* This usually implies that write operations are side-effect free. This allows
|
||||
* batching which can make a major impact on performance when using
|
||||
* virtualization.
|
||||
*/
|
||||
void qemu_flush_coalesced_mmio_buffer(void);
|
||||
|
||||
uint32_t ldub_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t lduw_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t lduw_be_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_be_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_le_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_be_phys(AddressSpace *as, hwaddr addr);
|
||||
void stb_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_le_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_be_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_le_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
uint32_t lduw_phys(AddressSpace *as, hwaddr addr);
|
||||
uint32_t ldl_phys(AddressSpace *as, hwaddr addr);
|
||||
uint64_t ldq_phys(AddressSpace *as, hwaddr addr);
|
||||
void stl_phys_notdirty(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stw_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stl_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
||||
void stq_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
#endif
|
||||
|
||||
void cpu_physical_memory_write_rom(AddressSpace *as, hwaddr addr,
|
||||
const uint8_t *buf, int len);
|
||||
void cpu_flush_icache_range(AddressSpace *as, hwaddr start, int len);
|
||||
|
||||
extern struct MemoryRegion io_mem_rom;
|
||||
extern struct MemoryRegion io_mem_notdirty;
|
||||
|
||||
typedef void (RAMBlockIterFunc)(void *host_addr,
|
||||
ram_addr_t offset, ram_addr_t length, void *opaque);
|
||||
|
||||
void qemu_ram_foreach_block(struct uc_struct *uc, RAMBlockIterFunc func, void *opaque);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !CPU_COMMON_H */
|
||||
132
qemu/include/exec/cpu-defs.h
Normal file
132
qemu/include/exec/cpu-defs.h
Normal file
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* 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 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 NEED_CPU_H
|
||||
#error cpu.h included from common code
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include <inttypes.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/queue.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/hwaddr.h"
|
||||
#endif
|
||||
|
||||
#ifndef TARGET_LONG_BITS
|
||||
#error TARGET_LONG_BITS must be defined before including this header
|
||||
#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"
|
||||
#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
|
||||
#else
|
||||
#error TARGET_LONG_SIZE undefined
|
||||
#endif
|
||||
|
||||
#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 */
|
||||
|
||||
/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
|
||||
addresses on the same page. The top bits are the same. This allows
|
||||
TLB invalidation to quickly clear a subset of the hash table. */
|
||||
#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
|
||||
#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
|
||||
#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
|
||||
#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
#define CPU_TLB_BITS 8
|
||||
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
|
||||
/* use a fully associative victim tlb of 8 entries */
|
||||
#define CPU_VTLB_SIZE 8
|
||||
|
||||
#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
|
||||
#define CPU_TLB_ENTRY_BITS 4
|
||||
#else
|
||||
#define CPU_TLB_ENTRY_BITS 5
|
||||
#endif
|
||||
|
||||
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
|
||||
go directly to ram.
|
||||
bit 3 : indicates that the entry is invalid
|
||||
bit 2..0 : zero
|
||||
*/
|
||||
target_ulong addr_read;
|
||||
target_ulong addr_write;
|
||||
target_ulong 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 */
|
||||
uint8_t dummy[(1 << CPU_TLB_ENTRY_BITS) -
|
||||
(sizeof(target_ulong) * 3 +
|
||||
((-sizeof(target_ulong) * 3) & (sizeof(uintptr_t) - 1)) +
|
||||
sizeof(uintptr_t))];
|
||||
} CPUTLBEntry;
|
||||
|
||||
QEMU_BUILD_BUG_ON(sizeof(CPUTLBEntry) != (1 << CPU_TLB_ENTRY_BITS));
|
||||
|
||||
#define CPU_COMMON_TLB \
|
||||
/* The meaning of the MMU modes is defined in the target code. */ \
|
||||
CPUTLBEntry tlb_table[NB_MMU_MODES][CPU_TLB_SIZE]; \
|
||||
CPUTLBEntry tlb_v_table[NB_MMU_MODES][CPU_VTLB_SIZE]; \
|
||||
hwaddr iotlb[NB_MMU_MODES][CPU_TLB_SIZE]; \
|
||||
hwaddr iotlb_v[NB_MMU_MODES][CPU_VTLB_SIZE]; \
|
||||
target_ulong tlb_flush_addr; \
|
||||
target_ulong tlb_flush_mask; \
|
||||
target_ulong vtlb_index; \
|
||||
|
||||
#else
|
||||
|
||||
#define CPU_COMMON_TLB
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#define CPU_TEMP_BUF_NLONGS 128
|
||||
|
||||
// Unicorn engine
|
||||
// @invalid_addr: invalid memory access address
|
||||
// @invalid_error: error code for memory access (1 = READ, 2 = WRITE)
|
||||
#define CPU_COMMON \
|
||||
/* soft mmu support */ \
|
||||
CPU_COMMON_TLB \
|
||||
uint64_t invalid_addr; \
|
||||
int invalid_error;
|
||||
#endif
|
||||
400
qemu/include/exec/cpu_ldst.h
Normal file
400
qemu/include/exec/cpu_ldst.h
Normal file
@@ -0,0 +1,400 @@
|
||||
/*
|
||||
* Software MMU support
|
||||
*
|
||||
* 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 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Generate inline load/store functions for all MMU modes (typically
|
||||
* at least _user and _kernel) as well as _data versions, for all data
|
||||
* sizes.
|
||||
*
|
||||
* Used by target op helpers.
|
||||
*
|
||||
* MMU mode suffixes are defined in target cpu.h.
|
||||
*/
|
||||
#ifndef CPU_LDST_H
|
||||
#define CPU_LDST_H
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
/* All direct uses of g2h and h2g need to go away for usermode softmmu. */
|
||||
#define g2h(x) ((void *)((unsigned long)(target_ulong)(x) + GUEST_BASE))
|
||||
|
||||
#if HOST_LONG_BITS <= TARGET_VIRT_ADDR_SPACE_BITS
|
||||
#define h2g_valid(x) 1
|
||||
#else
|
||||
#define h2g_valid(x) ({ \
|
||||
unsigned long __guest = (unsigned long)(x) - GUEST_BASE; \
|
||||
(__guest < (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) && \
|
||||
(!RESERVED_VA || (__guest < RESERVED_VA)); \
|
||||
})
|
||||
#endif
|
||||
|
||||
#define h2g_nocheck(x) ({ \
|
||||
unsigned long __ret = (unsigned long)(x) - GUEST_BASE; \
|
||||
(abi_ulong)__ret; \
|
||||
})
|
||||
|
||||
#define h2g(x) ({ \
|
||||
/* Check if given address fits target address space */ \
|
||||
assert(h2g_valid(x)); \
|
||||
h2g_nocheck(x); \
|
||||
})
|
||||
|
||||
#define saddr(x) g2h(x)
|
||||
#define laddr(x) g2h(x)
|
||||
|
||||
#else /* !CONFIG_USER_ONLY */
|
||||
/* NOTE: we use double casts if pointers and target_ulong have
|
||||
different sizes */
|
||||
#define saddr(x) (uint8_t *)(intptr_t)(x)
|
||||
#define laddr(x) (uint8_t *)(intptr_t)(x)
|
||||
#endif
|
||||
|
||||
#define ldub_raw(p) ldub_p(laddr((p)))
|
||||
#define ldsb_raw(p) ldsb_p(laddr((p)))
|
||||
#define lduw_raw(p) lduw_p(laddr((p)))
|
||||
#define ldsw_raw(p) ldsw_p(laddr((p)))
|
||||
#define ldl_raw(p) ldl_p(laddr((p)))
|
||||
#define ldq_raw(p) ldq_p(laddr((p)))
|
||||
#define ldfl_raw(p) ldfl_p(laddr((p)))
|
||||
#define ldfq_raw(p) ldfq_p(laddr((p)))
|
||||
#define stb_raw(p, v) stb_p(saddr((p)), v)
|
||||
#define stw_raw(p, v) stw_p(saddr((p)), v)
|
||||
#define stl_raw(p, v) stl_p(saddr((p)), v)
|
||||
#define stq_raw(p, v) stq_p(saddr((p)), v)
|
||||
#define stfl_raw(p, v) stfl_p(saddr((p)), v)
|
||||
#define stfq_raw(p, v) stfq_p(saddr((p)), v)
|
||||
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
||||
/* if user mode, no other memory access functions */
|
||||
#define ldub(p) ldub_raw(p)
|
||||
#define ldsb(p) ldsb_raw(p)
|
||||
#define lduw(p) lduw_raw(p)
|
||||
#define ldsw(p) ldsw_raw(p)
|
||||
#define ldl(p) ldl_raw(p)
|
||||
#define ldq(p) ldq_raw(p)
|
||||
#define ldfl(p) ldfl_raw(p)
|
||||
#define ldfq(p) ldfq_raw(p)
|
||||
#define stb(p, v) stb_raw(p, v)
|
||||
#define stw(p, v) stw_raw(p, v)
|
||||
#define stl(p, v) stl_raw(p, v)
|
||||
#define stq(p, v) stq_raw(p, v)
|
||||
#define stfl(p, v) stfl_raw(p, v)
|
||||
#define stfq(p, v) stfq_raw(p, v)
|
||||
|
||||
#define cpu_ldub_code(env1, p) ldub_raw(p)
|
||||
#define cpu_ldsb_code(env1, p) ldsb_raw(p)
|
||||
#define cpu_lduw_code(env1, p) lduw_raw(p)
|
||||
#define cpu_ldsw_code(env1, p) ldsw_raw(p)
|
||||
#define cpu_ldl_code(env1, p) ldl_raw(p)
|
||||
#define cpu_ldq_code(env1, p) ldq_raw(p)
|
||||
|
||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
|
||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
|
||||
#define cpu_ldsw_data(env, addr) ldsw_raw(addr)
|
||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
|
||||
#define cpu_ldq_data(env, addr) ldq_raw(addr)
|
||||
|
||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
|
||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
|
||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
|
||||
#define cpu_stq_data(env, addr, data) stq_raw(addr, data)
|
||||
|
||||
#define cpu_ldub_kernel(env, addr) ldub_raw(addr)
|
||||
#define cpu_lduw_kernel(env, addr) lduw_raw(addr)
|
||||
#define cpu_ldsw_kernel(env, addr) ldsw_raw(addr)
|
||||
#define cpu_ldl_kernel(env, addr) ldl_raw(addr)
|
||||
#define cpu_ldq_kernel(env, addr) ldq_raw(addr)
|
||||
|
||||
#define cpu_stb_kernel(env, addr, data) stb_raw(addr, data)
|
||||
#define cpu_stw_kernel(env, addr, data) stw_raw(addr, data)
|
||||
#define cpu_stl_kernel(env, addr, data) stl_raw(addr, data)
|
||||
#define cpu_stq_kernel(env, addr, data) stq_raw(addr, data)
|
||||
|
||||
#define ldub_kernel(p) ldub_raw(p)
|
||||
#define ldsb_kernel(p) ldsb_raw(p)
|
||||
#define lduw_kernel(p) lduw_raw(p)
|
||||
#define ldsw_kernel(p) ldsw_raw(p)
|
||||
#define ldl_kernel(p) ldl_raw(p)
|
||||
#define ldq_kernel(p) ldq_raw(p)
|
||||
#define ldfl_kernel(p) ldfl_raw(p)
|
||||
#define ldfq_kernel(p) ldfq_raw(p)
|
||||
#define stb_kernel(p, v) stb_raw(p, v)
|
||||
#define stw_kernel(p, v) stw_raw(p, v)
|
||||
#define stl_kernel(p, v) stl_raw(p, v)
|
||||
#define stq_kernel(p, v) stq_raw(p, v)
|
||||
#define stfl_kernel(p, v) stfl_raw(p, v)
|
||||
#define stfq_kernel(p, vt) stfq_raw(p, v)
|
||||
|
||||
#define cpu_ldub_data(env, addr) ldub_raw(addr)
|
||||
#define cpu_lduw_data(env, addr) lduw_raw(addr)
|
||||
#define cpu_ldl_data(env, addr) ldl_raw(addr)
|
||||
|
||||
#define cpu_stb_data(env, addr, data) stb_raw(addr, data)
|
||||
#define cpu_stw_data(env, addr, data) stw_raw(addr, data)
|
||||
#define cpu_stl_data(env, addr, data) stl_raw(addr, data)
|
||||
|
||||
#else
|
||||
|
||||
/* XXX: find something cleaner.
|
||||
* Furthermore, this is false for 64 bits targets
|
||||
*/
|
||||
#define ldul_user ldl_user
|
||||
#define ldul_kernel ldl_kernel
|
||||
#define ldul_hypv ldl_hypv
|
||||
#define ldul_executive ldl_executive
|
||||
#define ldul_supervisor ldl_supervisor
|
||||
|
||||
/* The memory helpers for tcg-generated code need tcg_target_long etc. */
|
||||
#include "tcg.h"
|
||||
|
||||
uint8_t helper_ldb_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint16_t helper_ldw_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint32_t helper_ldl_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint64_t helper_ldq_mmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
|
||||
void helper_stb_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint8_t val, int mmu_idx);
|
||||
void helper_stw_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint16_t val, int mmu_idx);
|
||||
void helper_stl_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint32_t val, int mmu_idx);
|
||||
void helper_stq_mmu(CPUArchState *env, target_ulong addr,
|
||||
uint64_t val, int mmu_idx);
|
||||
|
||||
uint8_t helper_ldb_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint16_t helper_ldw_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint32_t helper_ldl_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
uint64_t helper_ldq_cmmu(CPUArchState *env, target_ulong addr, int mmu_idx);
|
||||
|
||||
#define CPU_MMU_INDEX 0
|
||||
#define MEMSUFFIX MMU_MODE0_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
|
||||
#define CPU_MMU_INDEX 1
|
||||
#define MEMSUFFIX MMU_MODE1_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
|
||||
#if (NB_MMU_MODES >= 3)
|
||||
|
||||
#define CPU_MMU_INDEX 2
|
||||
#define MEMSUFFIX MMU_MODE2_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
#endif /* (NB_MMU_MODES >= 3) */
|
||||
|
||||
#if (NB_MMU_MODES >= 4)
|
||||
|
||||
#define CPU_MMU_INDEX 3
|
||||
#define MEMSUFFIX MMU_MODE3_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
#endif /* (NB_MMU_MODES >= 4) */
|
||||
|
||||
#if (NB_MMU_MODES >= 5)
|
||||
|
||||
#define CPU_MMU_INDEX 4
|
||||
#define MEMSUFFIX MMU_MODE4_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
#endif /* (NB_MMU_MODES >= 5) */
|
||||
|
||||
#if (NB_MMU_MODES >= 6)
|
||||
|
||||
#define CPU_MMU_INDEX 5
|
||||
#define MEMSUFFIX MMU_MODE5_SUFFIX
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
#endif /* (NB_MMU_MODES >= 6) */
|
||||
|
||||
#if (NB_MMU_MODES > 6)
|
||||
#error "NB_MMU_MODES > 6 is not supported for now"
|
||||
#endif /* (NB_MMU_MODES > 6) */
|
||||
|
||||
/* these access are slower, they must be as rare as possible */
|
||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
|
||||
#define MEMSUFFIX _data
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
|
||||
#define ldub(p) ldub_data(p)
|
||||
#define ldsb(p) ldsb_data(p)
|
||||
#define lduw(p) lduw_data(p)
|
||||
#define ldsw(p) ldsw_data(p)
|
||||
#define ldl(p) ldl_data(p)
|
||||
#define ldq(p) ldq_data(p)
|
||||
|
||||
#define stb(p, v) stb_data(p, v)
|
||||
#define stw(p, v) stw_data(p, v)
|
||||
#define stl(p, v) stl_data(p, v)
|
||||
#define stq(p, v) stq_data(p, v)
|
||||
|
||||
#define CPU_MMU_INDEX (cpu_mmu_index(env))
|
||||
#define MEMSUFFIX _code
|
||||
#define SOFTMMU_CODE_ACCESS
|
||||
|
||||
#define DATA_SIZE 1
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 2
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 4
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#define DATA_SIZE 8
|
||||
#include "exec/cpu_ldst_template.h"
|
||||
|
||||
#undef CPU_MMU_INDEX
|
||||
#undef MEMSUFFIX
|
||||
#undef SOFTMMU_CODE_ACCESS
|
||||
|
||||
/**
|
||||
* tlb_vaddr_to_host:
|
||||
* @env: CPUArchState
|
||||
* @addr: guest virtual address to look up
|
||||
* @access_type: 0 for read, 1 for write, 2 for execute
|
||||
* @mmu_idx: MMU index to use for lookup
|
||||
*
|
||||
* Look up the specified guest virtual index in the TCG softmmu TLB.
|
||||
* If the TLB contains a host virtual address suitable for direct RAM
|
||||
* access, then return it. Otherwise (TLB miss, TLB entry is for an
|
||||
* I/O access, etc) return NULL.
|
||||
*
|
||||
* This is the equivalent of the initial fast-path code used by
|
||||
* TCG backends for guest load and store accesses.
|
||||
*/
|
||||
static inline void *tlb_vaddr_to_host(CPUArchState *env, target_ulong addr,
|
||||
int access_type, int mmu_idx)
|
||||
{
|
||||
int index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
CPUTLBEntry *tlbentry = &env->tlb_table[mmu_idx][index];
|
||||
target_ulong tlb_addr;
|
||||
uintptr_t haddr;
|
||||
|
||||
switch (access_type) {
|
||||
case 0:
|
||||
tlb_addr = tlbentry->addr_read;
|
||||
break;
|
||||
case 1:
|
||||
tlb_addr = tlbentry->addr_write;
|
||||
break;
|
||||
case 2:
|
||||
tlb_addr = tlbentry->addr_code;
|
||||
break;
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
if ((addr & TARGET_PAGE_MASK)
|
||||
!= (tlb_addr & (TARGET_PAGE_MASK | TLB_INVALID_MASK))) {
|
||||
/* TLB entry is for a different page */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (tlb_addr & ~TARGET_PAGE_MASK) {
|
||||
/* IO access */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
haddr = addr + env->tlb_table[mmu_idx][index].addend;
|
||||
return (void *)haddr;
|
||||
}
|
||||
|
||||
#endif /* defined(CONFIG_USER_ONLY) */
|
||||
|
||||
#endif /* CPU_LDST_H */
|
||||
193
qemu/include/exec/cpu_ldst_template.h
Normal file
193
qemu/include/exec/cpu_ldst_template.h
Normal file
@@ -0,0 +1,193 @@
|
||||
/*
|
||||
* Software MMU support
|
||||
*
|
||||
* Generate inline load/store functions for one MMU mode and data
|
||||
* size.
|
||||
*
|
||||
* Generate a store function as well as signed and unsigned loads. For
|
||||
* 32 and 64 bit cases, also generate floating point functions with
|
||||
* the same size.
|
||||
*
|
||||
* Not used directly but included from cpu_ldst.h.
|
||||
*
|
||||
* 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 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/>.
|
||||
*/
|
||||
#if DATA_SIZE == 8
|
||||
#define SUFFIX q
|
||||
#define USUFFIX q
|
||||
#define DATA_TYPE uint64_t
|
||||
#elif DATA_SIZE == 4
|
||||
#define SUFFIX l
|
||||
#define USUFFIX l
|
||||
#define DATA_TYPE uint32_t
|
||||
#elif DATA_SIZE == 2
|
||||
#define SUFFIX w
|
||||
#define USUFFIX uw
|
||||
#define DATA_TYPE uint16_t
|
||||
#define DATA_STYPE int16_t
|
||||
#elif DATA_SIZE == 1
|
||||
#define SUFFIX b
|
||||
#define USUFFIX ub
|
||||
#define DATA_TYPE uint8_t
|
||||
#define DATA_STYPE int8_t
|
||||
#else
|
||||
#error unsupported data size
|
||||
#endif
|
||||
|
||||
#if DATA_SIZE == 8
|
||||
#define RES_TYPE uint64_t
|
||||
#else
|
||||
#define RES_TYPE uint32_t
|
||||
#endif
|
||||
|
||||
#ifdef SOFTMMU_CODE_ACCESS
|
||||
#define ADDR_READ addr_code
|
||||
#define MMUSUFFIX _cmmu
|
||||
#else
|
||||
#define ADDR_READ addr_read
|
||||
#define MMUSUFFIX _mmu
|
||||
#endif
|
||||
|
||||
/* generic load/store macros */
|
||||
|
||||
static inline RES_TYPE
|
||||
glue(glue(cpu_ld, USUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
int page_index;
|
||||
RES_TYPE res;
|
||||
target_ulong addr;
|
||||
int mmu_idx;
|
||||
|
||||
addr = ptr;
|
||||
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
res = glue(glue(helper_ld, SUFFIX), MMUSUFFIX)(env, addr, mmu_idx);
|
||||
} else {
|
||||
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
res = glue(glue(ld, USUFFIX), _raw)(hostaddr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
#if DATA_SIZE <= 2
|
||||
static inline int
|
||||
glue(glue(cpu_lds, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr)
|
||||
{
|
||||
int res, page_index;
|
||||
target_ulong addr;
|
||||
int mmu_idx;
|
||||
|
||||
addr = ptr;
|
||||
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].ADDR_READ !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
res = (DATA_STYPE)glue(glue(helper_ld, SUFFIX),
|
||||
MMUSUFFIX)(env, addr, mmu_idx);
|
||||
} else {
|
||||
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
res = glue(glue(lds, SUFFIX), _raw)(hostaddr);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef SOFTMMU_CODE_ACCESS
|
||||
|
||||
/* generic store macro */
|
||||
|
||||
static inline void
|
||||
glue(glue(cpu_st, SUFFIX), MEMSUFFIX)(CPUArchState *env, target_ulong ptr,
|
||||
RES_TYPE v)
|
||||
{
|
||||
int page_index;
|
||||
target_ulong addr;
|
||||
int mmu_idx;
|
||||
|
||||
addr = ptr;
|
||||
page_index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
|
||||
mmu_idx = CPU_MMU_INDEX;
|
||||
if (unlikely(env->tlb_table[mmu_idx][page_index].addr_write !=
|
||||
(addr & (TARGET_PAGE_MASK | (DATA_SIZE - 1))))) {
|
||||
glue(glue(helper_st, SUFFIX), MMUSUFFIX)(env, addr, v, mmu_idx);
|
||||
} else {
|
||||
uintptr_t hostaddr = addr + env->tlb_table[mmu_idx][page_index].addend;
|
||||
glue(glue(st, SUFFIX), _raw)(hostaddr, v);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
#if DATA_SIZE == 8
|
||||
static inline float64 glue(cpu_ldfq, MEMSUFFIX)(CPUArchState *env,
|
||||
target_ulong ptr)
|
||||
{
|
||||
union {
|
||||
float64 d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.i = glue(cpu_ldq, MEMSUFFIX)(env, ptr);
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static inline void glue(cpu_stfq, MEMSUFFIX)(CPUArchState *env,
|
||||
target_ulong ptr, float64 v)
|
||||
{
|
||||
union {
|
||||
float64 d;
|
||||
uint64_t i;
|
||||
} u;
|
||||
u.d = v;
|
||||
glue(cpu_stq, MEMSUFFIX)(env, ptr, u.i);
|
||||
}
|
||||
#endif /* DATA_SIZE == 8 */
|
||||
|
||||
#if DATA_SIZE == 4
|
||||
static inline float32 glue(cpu_ldfl, MEMSUFFIX)(CPUArchState *env,
|
||||
target_ulong ptr)
|
||||
{
|
||||
union {
|
||||
float32 f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
u.i = glue(cpu_ldl, MEMSUFFIX)(env, ptr);
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static inline void glue(cpu_stfl, MEMSUFFIX)(CPUArchState *env,
|
||||
target_ulong ptr, float32 v)
|
||||
{
|
||||
union {
|
||||
float32 f;
|
||||
uint32_t i;
|
||||
} u;
|
||||
u.f = v;
|
||||
glue(cpu_stl, MEMSUFFIX)(env, ptr, u.i);
|
||||
}
|
||||
#endif /* DATA_SIZE == 4 */
|
||||
|
||||
#endif /* !SOFTMMU_CODE_ACCESS */
|
||||
|
||||
#undef RES_TYPE
|
||||
#undef DATA_TYPE
|
||||
#undef DATA_STYPE
|
||||
#undef SUFFIX
|
||||
#undef USUFFIX
|
||||
#undef DATA_SIZE
|
||||
#undef MMUSUFFIX
|
||||
#undef ADDR_READ
|
||||
48
qemu/include/exec/cputlb.h
Normal file
48
qemu/include/exec/cputlb.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 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
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* cputlb.c */
|
||||
void tlb_protect_code(struct uc_struct *uc, ram_addr_t ram_addr);
|
||||
void tlb_unprotect_code_phys(CPUState *cpu, ram_addr_t ram_addr,
|
||||
target_ulong vaddr);
|
||||
void tlb_reset_dirty_range(CPUTLBEntry *tlb_entry,
|
||||
uintptr_t start, uintptr_t length);
|
||||
void cpu_tlb_reset_dirty_all(struct uc_struct *uc, ram_addr_t start1, ram_addr_t length);
|
||||
void tlb_set_dirty(CPUArchState *env, target_ulong vaddr);
|
||||
//extern int tlb_flush_count;
|
||||
|
||||
/* exec.c */
|
||||
void tb_flush_jmp_cache(CPUState *cpu, target_ulong addr);
|
||||
|
||||
MemoryRegionSection *
|
||||
address_space_translate_for_iotlb(AddressSpace *as, hwaddr addr, hwaddr *xlat,
|
||||
hwaddr *plen);
|
||||
hwaddr memory_region_section_get_iotlb(CPUState *cpu,
|
||||
MemoryRegionSection *section,
|
||||
target_ulong vaddr,
|
||||
hwaddr paddr, hwaddr xlat,
|
||||
int prot,
|
||||
target_ulong *address);
|
||||
bool memory_region_is_unassigned(struct uc_struct* uc, MemoryRegion *mr);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
380
qemu/include/exec/exec-all.h
Normal file
380
qemu/include/exec/exec-all.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/*
|
||||
* internal execution defines for qemu
|
||||
*
|
||||
* 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 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_ALL_H_
|
||||
#define _EXEC_ALL_H_
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
/* allow to see translation results - the slowdown should be negligible, so we leave it */
|
||||
#define DEBUG_DISAS
|
||||
|
||||
/* 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 abi_ulong tb_page_addr_t;
|
||||
#else
|
||||
typedef ram_addr_t tb_page_addr_t;
|
||||
#endif
|
||||
|
||||
/* is_jmp field values */
|
||||
#define DISAS_NEXT 0 /* next instruction can be analyzed */
|
||||
#define DISAS_JUMP 1 /* only pc was modified dynamically */
|
||||
#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
|
||||
#define DISAS_TB_JUMP 3 /* only pc was modified statically */
|
||||
|
||||
struct TranslationBlock;
|
||||
typedef struct TranslationBlock TranslationBlock;
|
||||
|
||||
/* XXX: make safe guess about sizes */
|
||||
#define MAX_OP_PER_INSTR 266
|
||||
|
||||
#if HOST_LONG_BITS == 32
|
||||
#define MAX_OPC_PARAM_PER_ARG 2
|
||||
#else
|
||||
#define MAX_OPC_PARAM_PER_ARG 1
|
||||
#endif
|
||||
#define MAX_OPC_PARAM_IARGS 5
|
||||
#define MAX_OPC_PARAM_OARGS 1
|
||||
#define MAX_OPC_PARAM_ARGS (MAX_OPC_PARAM_IARGS + MAX_OPC_PARAM_OARGS)
|
||||
|
||||
/* A Call op needs up to 4 + 2N parameters on 32-bit archs,
|
||||
* and up to 4 + N parameters on 64-bit archs
|
||||
* (N = number of input arguments + output arguments). */
|
||||
#define MAX_OPC_PARAM (4 + (MAX_OPC_PARAM_PER_ARG * MAX_OPC_PARAM_ARGS))
|
||||
#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
|
||||
|
||||
/* Maximum size a TCG op can expand to. This is complicated because a
|
||||
single op may require several host instructions and register reloads.
|
||||
For now take a wild guess at 192 bytes, which should allow at least
|
||||
a couple of fixup instructions per argument. */
|
||||
#define TCG_MAX_OP_SIZE 192
|
||||
|
||||
#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * MAX_OPC_PARAM)
|
||||
|
||||
#include "qemu/log.h"
|
||||
|
||||
void gen_intermediate_code(CPUArchState *env, struct TranslationBlock *tb);
|
||||
void gen_intermediate_code_pc(CPUArchState *env, struct TranslationBlock *tb);
|
||||
void restore_state_to_opc(CPUArchState *env, struct TranslationBlock *tb,
|
||||
int pc_pos);
|
||||
bool cpu_restore_state(CPUState *cpu, uintptr_t searched_pc);
|
||||
|
||||
void QEMU_NORETURN cpu_resume_from_signal(CPUState *cpu, void *puc);
|
||||
|
||||
void QEMU_NORETURN cpu_io_recompile(CPUState *cpu, uintptr_t retaddr);
|
||||
TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
target_ulong pc, target_ulong cs_base, int flags,
|
||||
int cflags);
|
||||
void cpu_exec_init(CPUArchState *env, void *opaque);
|
||||
|
||||
void QEMU_NORETURN cpu_loop_exit(CPUState *cpu);
|
||||
|
||||
void tb_invalidate_phys_page_range(struct uc_struct *uc, tb_page_addr_t start, tb_page_addr_t end,
|
||||
int is_cpu_write_access);
|
||||
void tb_invalidate_phys_range(struct uc_struct *uc, tb_page_addr_t start, tb_page_addr_t end,
|
||||
int is_cpu_write_access);
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
void tcg_cpu_address_space_init(CPUState *cpu, AddressSpace *as);
|
||||
/* cputlb.c */
|
||||
void tlb_flush_page(CPUState *cpu, target_ulong addr);
|
||||
void tlb_flush(CPUState *cpu, int flush_global);
|
||||
void tlb_set_page(CPUState *cpu, target_ulong vaddr,
|
||||
hwaddr paddr, int prot,
|
||||
int mmu_idx, target_ulong size);
|
||||
|
||||
void tb_invalidate_phys_addr(AddressSpace *as, hwaddr addr);
|
||||
|
||||
#else
|
||||
static inline void tlb_flush_page(CPUState *cpu, target_ulong addr)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void tlb_flush(CPUState *cpu, int flush_global)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
||||
|
||||
#define CODE_GEN_PHYS_HASH_BITS 15
|
||||
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
|
||||
|
||||
/* estimated block size for TB allocation */
|
||||
/* XXX: use a per code average code fragment size and modulate it
|
||||
according to the host CPU */
|
||||
#if defined(CONFIG_SOFTMMU)
|
||||
#define CODE_GEN_AVG_BLOCK_SIZE 128
|
||||
#else
|
||||
#define CODE_GEN_AVG_BLOCK_SIZE 64
|
||||
#endif
|
||||
|
||||
#if defined(__arm__) || defined(_ARCH_PPC) \
|
||||
|| defined(__x86_64__) || defined(__i386__) \
|
||||
|| defined(__sparc__) || defined(__aarch64__) \
|
||||
|| defined(__s390x__) || defined(__mips__) \
|
||||
|| defined(CONFIG_TCG_INTERPRETER)
|
||||
#define USE_DIRECT_JUMP
|
||||
#endif
|
||||
|
||||
struct TranslationBlock {
|
||||
target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
|
||||
target_ulong cs_base; /* CS base for this block */
|
||||
uint64_t flags; /* flags defining in which context the code was generated */
|
||||
uint16_t size; /* size of target code for this block (1 <=
|
||||
size <= TARGET_PAGE_SIZE) */
|
||||
uint16_t cflags; /* compile flags */
|
||||
#define CF_COUNT_MASK 0x7fff
|
||||
#define CF_LAST_IO 0x8000 /* Last insn may be an IO access. */
|
||||
|
||||
void *tc_ptr; /* pointer to the translated code */
|
||||
/* next matching tb for physical address. */
|
||||
struct TranslationBlock *phys_hash_next;
|
||||
/* first and second physical page containing code. The lower bit
|
||||
of the pointer tells the index in page_next[] */
|
||||
struct TranslationBlock *page_next[2];
|
||||
tb_page_addr_t page_addr[2];
|
||||
|
||||
/* the following data are used to directly call another TB from
|
||||
the code of this one. */
|
||||
uint16_t tb_next_offset[2]; /* offset of original jump target */
|
||||
#ifdef USE_DIRECT_JUMP
|
||||
uint16_t tb_jmp_offset[2]; /* offset of jump instruction */
|
||||
#else
|
||||
uintptr_t tb_next[2]; /* address of jump generated code */
|
||||
#endif
|
||||
/* list of TBs jumping to this one. This is a circular list using
|
||||
the two least significant bits of the pointers to tell what is
|
||||
the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
|
||||
jmp_first */
|
||||
struct TranslationBlock *jmp_next[2];
|
||||
struct TranslationBlock *jmp_first;
|
||||
uint32_t icount;
|
||||
};
|
||||
|
||||
#include "exec/spinlock.h"
|
||||
|
||||
typedef struct TBContext TBContext;
|
||||
|
||||
struct TBContext {
|
||||
|
||||
TranslationBlock *tbs;
|
||||
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
||||
int nb_tbs;
|
||||
/* any access to the tbs or the page table must use this lock */
|
||||
spinlock_t tb_lock;
|
||||
|
||||
/* statistics */
|
||||
int tb_flush_count;
|
||||
int tb_phys_invalidate_count;
|
||||
|
||||
int tb_invalidated_flag;
|
||||
};
|
||||
|
||||
static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
|
||||
{
|
||||
target_ulong tmp;
|
||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||
return (tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
|
||||
{
|
||||
target_ulong tmp;
|
||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||
return (((tmp >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)) & TB_JMP_PAGE_MASK)
|
||||
| (tmp & TB_JMP_ADDR_MASK));
|
||||
}
|
||||
|
||||
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
|
||||
{
|
||||
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
|
||||
}
|
||||
|
||||
void tb_free(struct uc_struct *uc, TranslationBlock *tb);
|
||||
void tb_flush(CPUArchState *env);
|
||||
void tb_phys_invalidate(struct uc_struct *uc,
|
||||
TranslationBlock *tb, tb_page_addr_t page_addr);
|
||||
|
||||
#if defined(USE_DIRECT_JUMP)
|
||||
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
*(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(_ARCH_PPC)
|
||||
void ppc_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#define tb_set_jmp_target1 ppc_tb_set_jmp_target
|
||||
#elif defined(__i386__) || defined(__x86_64__)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
stl_le_p((void*)jmp_addr, addr - (jmp_addr + 4));
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(__s390x__)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
/* patch the branch destination */
|
||||
intptr_t disp = addr - (jmp_addr - 2);
|
||||
stl_be_p((void*)jmp_addr, disp / 2);
|
||||
/* no need to flush icache explicitly */
|
||||
}
|
||||
#elif defined(__aarch64__)
|
||||
void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#define tb_set_jmp_target1 aarch64_tb_set_jmp_target
|
||||
#elif defined(__arm__)
|
||||
static inline void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr)
|
||||
{
|
||||
#if !QEMU_GNUC_PREREQ(4, 1)
|
||||
register unsigned long _beg __asm ("a1");
|
||||
register unsigned long _end __asm ("a2");
|
||||
register unsigned long _flg __asm ("a3");
|
||||
#endif
|
||||
|
||||
/* we could use a ldr pc, [pc, #-4] kind of branch and avoid the flush */
|
||||
*(uint32_t *)jmp_addr =
|
||||
(*(uint32_t *)jmp_addr & ~0xffffff)
|
||||
| (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
|
||||
|
||||
#if QEMU_GNUC_PREREQ(4, 1)
|
||||
__builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
|
||||
#else
|
||||
/* flush icache */
|
||||
_beg = jmp_addr;
|
||||
_end = jmp_addr + 4;
|
||||
_flg = 0;
|
||||
__asm __volatile__ ("swi 0x9f0002" : : "r" (_beg), "r" (_end), "r" (_flg));
|
||||
#endif
|
||||
}
|
||||
#elif defined(__sparc__) || defined(__mips__)
|
||||
void tb_set_jmp_target1(uintptr_t jmp_addr, uintptr_t addr);
|
||||
#else
|
||||
#error tb_set_jmp_target1 is missing
|
||||
#endif
|
||||
|
||||
static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
int n, uintptr_t addr)
|
||||
{
|
||||
uint16_t offset = tb->tb_jmp_offset[n];
|
||||
tb_set_jmp_target1((uintptr_t)(tb->tc_ptr + offset), addr);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* set the jump target */
|
||||
static inline void tb_set_jmp_target(TranslationBlock *tb,
|
||||
int n, uintptr_t addr)
|
||||
{
|
||||
tb->tb_next[n] = addr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static inline void tb_add_jump(TranslationBlock *tb, int n,
|
||||
TranslationBlock *tb_next)
|
||||
{
|
||||
/* NOTE: this test is only needed for thread safety */
|
||||
if (!tb->jmp_next[n]) {
|
||||
/* patch the native jump address */
|
||||
tb_set_jmp_target(tb, n, (uintptr_t)tb_next->tc_ptr);
|
||||
|
||||
/* add in TB jmp circular list */
|
||||
tb->jmp_next[n] = tb_next->jmp_first;
|
||||
tb_next->jmp_first = (TranslationBlock *)((uintptr_t)(tb) | (n));
|
||||
}
|
||||
}
|
||||
|
||||
/* GETRA is the true target of the return instruction that we'll execute,
|
||||
defined here for simplicity of defining the follow-up macros. */
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
extern uintptr_t tci_tb_ptr;
|
||||
# define GETRA() tci_tb_ptr
|
||||
#else
|
||||
# define GETRA() \
|
||||
((uintptr_t)__builtin_extract_return_addr(__builtin_return_address(0)))
|
||||
#endif
|
||||
|
||||
/* The true return address will often point to a host insn that is part of
|
||||
the next translated guest insn. Adjust the address backward to point to
|
||||
the middle of the call insn. Subtracting one would do the job except for
|
||||
several compressed mode architectures (arm, mips) which set the low bit
|
||||
to indicate the compressed mode; subtracting two works around that. It
|
||||
is also the case that there are no host isas that contain a call insn
|
||||
smaller than 4 bytes, so we don't worry about special-casing this. */
|
||||
#if defined(CONFIG_TCG_INTERPRETER)
|
||||
# define GETPC_ADJ 0
|
||||
#else
|
||||
# define GETPC_ADJ 2
|
||||
#endif
|
||||
|
||||
#define GETPC() (GETRA() - GETPC_ADJ)
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
|
||||
void phys_mem_set_alloc(void *(*alloc)(size_t, uint64_t *align));
|
||||
|
||||
struct MemoryRegion *iotlb_to_region(AddressSpace *as, hwaddr index);
|
||||
bool io_mem_read(struct MemoryRegion *mr, hwaddr addr,
|
||||
uint64_t *pvalue, unsigned size);
|
||||
bool io_mem_write(struct MemoryRegion *mr, hwaddr addr,
|
||||
uint64_t value, unsigned size);
|
||||
|
||||
|
||||
void tlb_fill(CPUState *cpu, target_ulong addr, int is_write, int mmu_idx,
|
||||
uintptr_t retaddr);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
static inline tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr)
|
||||
{
|
||||
return addr;
|
||||
}
|
||||
#else
|
||||
/* cputlb.c */
|
||||
tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr);
|
||||
#endif
|
||||
|
||||
/* vl.c */
|
||||
extern int singlestep;
|
||||
|
||||
/* cpu-exec.c */
|
||||
extern volatile sig_atomic_t exit_request;
|
||||
|
||||
/**
|
||||
* cpu_can_do_io:
|
||||
* @cpu: The CPU for which to check IO.
|
||||
*
|
||||
* Deterministic execution requires that IO only be performed on the last
|
||||
* instruction of a TB so that interrupts take effect immediately.
|
||||
*
|
||||
* Returns: %true if memory-mapped IO is safe, %false otherwise.
|
||||
*/
|
||||
static inline bool cpu_can_do_io(CPUState *cpu)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void phys_mem_clean(struct uc_struct* uc);
|
||||
|
||||
#endif
|
||||
72
qemu/include/exec/gen-icount.h
Normal file
72
qemu/include/exec/gen-icount.h
Normal file
@@ -0,0 +1,72 @@
|
||||
#ifndef GEN_ICOUNT_H
|
||||
#define GEN_ICOUNT_H 1
|
||||
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/* Helpers for instruction counting code generation. */
|
||||
|
||||
//static TCGArg *icount_arg;
|
||||
//static int icount_label;
|
||||
|
||||
static inline void gen_tb_start(TCGContext *tcg_ctx)
|
||||
{
|
||||
// TCGv_i32 count;
|
||||
TCGv_i32 flag;
|
||||
|
||||
tcg_ctx->exitreq_label = gen_new_label(tcg_ctx);
|
||||
flag = tcg_temp_new_i32(tcg_ctx);
|
||||
tcg_gen_ld_i32(tcg_ctx, flag, tcg_ctx->cpu_env,
|
||||
offsetof(CPUState, tcg_exit_req) - ENV_OFFSET);
|
||||
tcg_gen_brcondi_i32(tcg_ctx, TCG_COND_NE, flag, 0, tcg_ctx->exitreq_label);
|
||||
tcg_temp_free_i32(tcg_ctx, flag);
|
||||
|
||||
#if 0
|
||||
if (!use_icount)
|
||||
return;
|
||||
|
||||
icount_label = gen_new_label();
|
||||
count = tcg_temp_local_new_i32();
|
||||
tcg_gen_ld_i32(count, cpu_env,
|
||||
-ENV_OFFSET + offsetof(CPUState, icount_decr.u32));
|
||||
/* This is a horrid hack to allow fixing up the value later. */
|
||||
icount_arg = tcg_ctx.gen_opparam_ptr + 1;
|
||||
tcg_gen_subi_i32(count, count, 0xdeadbeef);
|
||||
|
||||
tcg_gen_brcondi_i32(TCG_COND_LT, count, 0, icount_label);
|
||||
tcg_gen_st16_i32(count, cpu_env,
|
||||
-ENV_OFFSET + offsetof(CPUState, icount_decr.u16.low));
|
||||
tcg_temp_free_i32(count);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void gen_tb_end(TCGContext *tcg_ctx, TranslationBlock *tb, int num_insns)
|
||||
{
|
||||
gen_set_label(tcg_ctx, tcg_ctx->exitreq_label);
|
||||
tcg_gen_exit_tb(tcg_ctx, (uintptr_t)tb + TB_EXIT_REQUESTED);
|
||||
|
||||
#if 0
|
||||
if (use_icount) {
|
||||
*icount_arg = num_insns;
|
||||
gen_set_label(icount_label);
|
||||
tcg_gen_exit_tb((uintptr_t)tb + TB_EXIT_ICOUNT_EXPIRED);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if 0
|
||||
static inline void gen_io_start(void)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(1);
|
||||
tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
|
||||
static inline void gen_io_end(void)
|
||||
{
|
||||
TCGv_i32 tmp = tcg_const_i32(0);
|
||||
tcg_gen_st_i32(tmp, cpu_env, -ENV_OFFSET + offsetof(CPUState, can_do_io));
|
||||
tcg_temp_free_i32(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
70
qemu/include/exec/helper-gen.h
Normal file
70
qemu/include/exec/helper-gen.h
Normal file
@@ -0,0 +1,70 @@
|
||||
/* Helper file for declaring TCG helper functions.
|
||||
This one expands generation functions for tcg opcodes. */
|
||||
|
||||
#ifndef HELPER_GEN_H
|
||||
#define HELPER_GEN_H 1
|
||||
|
||||
#include <exec/helper-head.h>
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, dh_retvar_decl0(ret)) \
|
||||
{ \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 0, NULL); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1)) \
|
||||
{ \
|
||||
TCGArg args[1] = { dh_arg(t1, 1) }; \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 1, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2)) \
|
||||
{ \
|
||||
TCGArg args[2] = { dh_arg(t1, 1), dh_arg(t2, 2) }; \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 2, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_3(name, flags, ret, t1, t2, t3) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), dh_arg_decl(t3, 3)) \
|
||||
{ \
|
||||
TCGArg args[3] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3) }; \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 3, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_4(name, flags, ret, t1, t2, t3, t4) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, dh_retvar_decl(ret) \
|
||||
dh_arg_decl(t1, 1), dh_arg_decl(t2, 2), \
|
||||
dh_arg_decl(t3, 3), dh_arg_decl(t4, 4)) \
|
||||
{ \
|
||||
TCGArg args[4] = { dh_arg(t1, 1), dh_arg(t2, 2), \
|
||||
dh_arg(t3, 3), dh_arg(t4, 4) }; \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 4, args); \
|
||||
}
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(name, flags, ret, t1, t2, t3, t4, t5) \
|
||||
static inline void glue(gen_helper_, name)(TCGContext *tcg_ctx, 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)) \
|
||||
{ \
|
||||
TCGArg args[5] = { dh_arg(t1, 1), dh_arg(t2, 2), dh_arg(t3, 3), \
|
||||
dh_arg(t4, 4), dh_arg(t5, 5) }; \
|
||||
tcg_gen_callN(tcg_ctx, HELPER(name), dh_retvar(ret), 5, args); \
|
||||
}
|
||||
|
||||
#include "helper.h"
|
||||
#include "tcg-runtime.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 GEN_HELPER
|
||||
|
||||
#endif /* HELPER_GEN_H */
|
||||
134
qemu/include/exec/helper-head.h
Normal file
134
qemu/include/exec/helper-head.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/* Helper file for declaring TCG helper functions.
|
||||
Used by other helper files.
|
||||
|
||||
Targets should use DEF_HELPER_N and DEF_HELPER_FLAGS_N to declare helper
|
||||
functions. Names should be specified without the helper_ prefix, and
|
||||
the return and argument types specified. 3 basic types are understood
|
||||
(i32, i64 and ptr). Additional aliases are provided for convenience and
|
||||
to match the types used by the C helper implementation.
|
||||
|
||||
The target helper.h should be included in all files that use/define
|
||||
helper functions. THis will ensure that function prototypes are
|
||||
consistent. In addition it should be included an extra two times for
|
||||
helper.c, defining:
|
||||
GEN_HELPER 1 to produce op generation functions (gen_helper_*)
|
||||
GEN_HELPER 2 to do runtime registration helper functions.
|
||||
*/
|
||||
|
||||
#ifndef DEF_HELPER_H
|
||||
#define DEF_HELPER_H 1
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#define HELPER(name) glue(helper_, name)
|
||||
|
||||
#define GET_TCGV_i32 GET_TCGV_I32
|
||||
#define GET_TCGV_i64 GET_TCGV_I64
|
||||
#define GET_TCGV_ptr GET_TCGV_PTR
|
||||
|
||||
/* 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_f32 i32
|
||||
#define dh_alias_f64 i64
|
||||
#ifdef TARGET_LONG_BITS
|
||||
# if TARGET_LONG_BITS == 32
|
||||
# define dh_alias_tl i32
|
||||
# else
|
||||
# define dh_alias_tl i64
|
||||
# endif
|
||||
#endif
|
||||
#define dh_alias_ptr ptr
|
||||
#define dh_alias_void void
|
||||
#define dh_alias_noreturn noreturn
|
||||
#define dh_alias_env ptr
|
||||
#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_f32 float32
|
||||
#define dh_ctype_f64 float64
|
||||
#define dh_ctype_tl target_ulong
|
||||
#define dh_ctype_ptr void *
|
||||
#define dh_ctype_void void
|
||||
#define dh_ctype_noreturn void QEMU_NORETURN
|
||||
#define dh_ctype_env CPUArchState *
|
||||
#define dh_ctype(t) dh_ctype_##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_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_ptr TCGv_ptr retval,
|
||||
#define dh_retvar_decl(t) glue(dh_retvar_decl_, dh_alias(t))
|
||||
|
||||
#define dh_retvar_void TCG_CALL_DUMMY_ARG
|
||||
#define dh_retvar_noreturn TCG_CALL_DUMMY_ARG
|
||||
#define dh_retvar_i32 GET_TCGV_i32(retval)
|
||||
#define dh_retvar_i64 GET_TCGV_i64(retval)
|
||||
#define dh_retvar_ptr GET_TCGV_ptr(retval)
|
||||
#define dh_retvar(t) glue(dh_retvar_, dh_alias(t))
|
||||
|
||||
#define dh_is_64bit_void 0
|
||||
#define dh_is_64bit_noreturn 0
|
||||
#define dh_is_64bit_i32 0
|
||||
#define dh_is_64bit_i64 1
|
||||
#define dh_is_64bit_ptr (sizeof(void *) == 8)
|
||||
#define dh_is_64bit(t) glue(dh_is_64bit_, dh_alias(t))
|
||||
|
||||
#define dh_is_signed_void 0
|
||||
#define dh_is_signed_noreturn 0
|
||||
#define dh_is_signed_i32 0
|
||||
#define dh_is_signed_s32 1
|
||||
#define dh_is_signed_i64 0
|
||||
#define dh_is_signed_s64 1
|
||||
#define dh_is_signed_f32 0
|
||||
#define dh_is_signed_f64 0
|
||||
#define dh_is_signed_tl 0
|
||||
#define dh_is_signed_int 1
|
||||
/* ??? This is highly specific to the host cpu. There are even special
|
||||
extension instructions that may be required, e.g. ia64's addp4. But
|
||||
for now we don't support any 64-bit targets with 32-bit pointers. */
|
||||
#define dh_is_signed_ptr 0
|
||||
#define dh_is_signed_env dh_is_signed_ptr
|
||||
#define dh_is_signed(t) dh_is_signed_##t
|
||||
|
||||
#define dh_sizemask(t, n) \
|
||||
((dh_is_64bit(t) << (n*2)) | (dh_is_signed(t) << (n*2+1)))
|
||||
|
||||
#define dh_arg(t, n) \
|
||||
glue(GET_TCGV_, dh_alias(t))(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)
|
||||
|
||||
/* MAX_OPC_PARAM_IARGS must be set to n if last entry is DEF_HELPER_FLAGS_n. */
|
||||
|
||||
#endif /* DEF_HELPER_H */
|
||||
39
qemu/include/exec/helper-proto.h
Normal file
39
qemu/include/exec/helper-proto.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/* Helper file for declaring TCG helper functions.
|
||||
This one expands prototypes for the helper functions. */
|
||||
|
||||
#ifndef HELPER_PROTO_H
|
||||
#define HELPER_PROTO_H 1
|
||||
|
||||
#include <exec/helper-head.h>
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(name, flags, ret) \
|
||||
dh_ctype(ret) HELPER(name) (void);
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(name, flags, ret, t1) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1));
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(name, flags, ret, t1, t2) \
|
||||
dh_ctype(ret) HELPER(name) (dh_ctype(t1), dh_ctype(t2));
|
||||
|
||||
#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));
|
||||
|
||||
#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));
|
||||
|
||||
#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));
|
||||
|
||||
#include "helper.h"
|
||||
#include "tcg-runtime.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
|
||||
|
||||
#endif /* HELPER_PROTO_H */
|
||||
48
qemu/include/exec/helper-tcg.h
Normal file
48
qemu/include/exec/helper-tcg.h
Normal file
@@ -0,0 +1,48 @@
|
||||
/* Helper file for declaring TCG helper functions.
|
||||
This one defines data structures private to tcg.c. */
|
||||
|
||||
#ifndef HELPER_TCG_H
|
||||
#define HELPER_TCG_H 1
|
||||
|
||||
#include <exec/helper-head.h>
|
||||
|
||||
#define DEF_HELPER_FLAGS_0(NAME, FLAGS, ret) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) },
|
||||
|
||||
#define DEF_HELPER_FLAGS_1(NAME, FLAGS, ret, t1) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) },
|
||||
|
||||
#define DEF_HELPER_FLAGS_2(NAME, FLAGS, ret, t1, t2) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
|
||||
| dh_sizemask(t2, 2) },
|
||||
|
||||
#define DEF_HELPER_FLAGS_3(NAME, FLAGS, ret, t1, t2, t3) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
|
||||
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) },
|
||||
|
||||
#define DEF_HELPER_FLAGS_4(NAME, FLAGS, ret, t1, t2, t3, t4) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
|
||||
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) },
|
||||
|
||||
#define DEF_HELPER_FLAGS_5(NAME, FLAGS, ret, t1, t2, t3, t4, t5) \
|
||||
{ .func = HELPER(NAME), .name = #NAME, .flags = FLAGS, \
|
||||
.sizemask = dh_sizemask(ret, 0) | dh_sizemask(t1, 1) \
|
||||
| dh_sizemask(t2, 2) | dh_sizemask(t3, 3) | dh_sizemask(t4, 4) \
|
||||
| dh_sizemask(t5, 5) },
|
||||
|
||||
#include "helper.h"
|
||||
#include "tcg-runtime.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
|
||||
|
||||
#endif /* HELPER_TCG_H */
|
||||
22
qemu/include/exec/hwaddr.h
Normal file
22
qemu/include/exec/hwaddr.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* 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'). */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uint64_t hwaddr;
|
||||
#define HWADDR_MAX UINT64_MAX
|
||||
#define TARGET_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
|
||||
|
||||
#endif
|
||||
59
qemu/include/exec/ioport.h
Normal file
59
qemu/include/exec/ioport.h
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* defines ioport related functions
|
||||
*
|
||||
* 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 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/>.
|
||||
*/
|
||||
|
||||
/**************************************************************************
|
||||
* IO ports API
|
||||
*/
|
||||
|
||||
#ifndef IOPORT_H
|
||||
#define IOPORT_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qom/object.h"
|
||||
#include "exec/memory.h"
|
||||
|
||||
typedef uint32_t pio_addr_t;
|
||||
#define FMT_pioaddr PRIx32
|
||||
|
||||
#define MAX_IOPORTS (64 * 1024)
|
||||
#define IOPORTS_MASK (MAX_IOPORTS - 1)
|
||||
|
||||
typedef struct MemoryRegionPortio {
|
||||
uint32_t offset;
|
||||
uint32_t len;
|
||||
unsigned size;
|
||||
uint32_t (*read)(void *opaque, uint32_t address);
|
||||
void (*write)(void *opaque, uint32_t address, uint32_t data);
|
||||
uint32_t base; /* private field */
|
||||
} MemoryRegionPortio;
|
||||
|
||||
#define PORTIO_END_OF_LIST() { }
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
extern const MemoryRegionOps unassigned_io_ops;
|
||||
#endif
|
||||
|
||||
void cpu_outb(struct uc_struct *uc, pio_addr_t addr, uint8_t val);
|
||||
void cpu_outw(struct uc_struct *uc, pio_addr_t addr, uint16_t val);
|
||||
void cpu_outl(struct uc_struct *uc, pio_addr_t addr, uint32_t val);
|
||||
uint8_t cpu_inb(struct uc_struct *uc, pio_addr_t addr);
|
||||
uint16_t cpu_inw(struct uc_struct *uc, pio_addr_t addr);
|
||||
uint32_t cpu_inl(struct uc_struct *uc, pio_addr_t addr);
|
||||
|
||||
#endif /* IOPORT_H */
|
||||
36
qemu/include/exec/memory-internal.h
Normal file
36
qemu/include/exec/memory-internal.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Declarations for obsolete exec.c functions
|
||||
*
|
||||
* Copyright 2011 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Avi Kivity <avi@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header is for use by exec.c and memory.c ONLY. Do not include it.
|
||||
* The functions declared here will be removed soon.
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_INTERNAL_H
|
||||
#define MEMORY_INTERNAL_H
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
typedef struct AddressSpaceDispatch AddressSpaceDispatch;
|
||||
|
||||
void address_space_init_dispatch(AddressSpace *as);
|
||||
void address_space_destroy_dispatch(AddressSpace *as);
|
||||
|
||||
extern const MemoryRegionOps unassigned_mem_ops;
|
||||
|
||||
bool memory_region_access_valid(MemoryRegion *mr, hwaddr addr,
|
||||
unsigned size, bool is_write);
|
||||
|
||||
void address_space_unregister(AddressSpace *as);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
942
qemu/include/exec/memory.h
Normal file
942
qemu/include/exec/memory.h
Normal file
@@ -0,0 +1,942 @@
|
||||
/*
|
||||
* Physical memory management API
|
||||
*
|
||||
* Copyright 2011 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Avi Kivity <avi@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MEMORY_H
|
||||
#define MEMORY_H
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
#define DIRTY_MEMORY_VGA 0
|
||||
#define DIRTY_MEMORY_CODE 1
|
||||
#define DIRTY_MEMORY_MIGRATION 2
|
||||
#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "qemu-common.h"
|
||||
#include "exec/cpu-common.h"
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
#include "exec/hwaddr.h"
|
||||
#endif
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/int128.h"
|
||||
#include "qemu/notify.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
#define MAX_PHYS_ADDR_SPACE_BITS 62
|
||||
#define MAX_PHYS_ADDR (((hwaddr)1 << MAX_PHYS_ADDR_SPACE_BITS) - 1)
|
||||
|
||||
#define TYPE_MEMORY_REGION "qemu:memory-region"
|
||||
#define MEMORY_REGION(uc, obj) \
|
||||
OBJECT_CHECK(uc, MemoryRegion, (obj), TYPE_MEMORY_REGION)
|
||||
|
||||
typedef struct MemoryRegionOps MemoryRegionOps;
|
||||
typedef struct MemoryRegionMmio MemoryRegionMmio;
|
||||
|
||||
struct MemoryRegionMmio {
|
||||
CPUReadMemoryFunc *read[3];
|
||||
CPUWriteMemoryFunc *write[3];
|
||||
};
|
||||
|
||||
typedef struct IOMMUTLBEntry IOMMUTLBEntry;
|
||||
|
||||
/* See address_space_translate: bit 0 is read, bit 1 is write. */
|
||||
typedef enum {
|
||||
IOMMU_NONE = 0,
|
||||
IOMMU_RO = 1,
|
||||
IOMMU_WO = 2,
|
||||
IOMMU_RW = 3,
|
||||
} IOMMUAccessFlags;
|
||||
|
||||
struct IOMMUTLBEntry {
|
||||
AddressSpace *target_as;
|
||||
hwaddr iova;
|
||||
hwaddr translated_addr;
|
||||
hwaddr addr_mask; /* 0xfff = 4k translation */
|
||||
IOMMUAccessFlags perm;
|
||||
};
|
||||
|
||||
/*
|
||||
* Memory region callbacks
|
||||
*/
|
||||
struct MemoryRegionOps {
|
||||
/* Read from the memory region. @addr is relative to @mr; @size is
|
||||
* in bytes. */
|
||||
uint64_t (*read)(struct uc_struct* uc, void *opaque,
|
||||
hwaddr addr,
|
||||
unsigned size);
|
||||
/* Write to the memory region. @addr is relative to @mr; @size is
|
||||
* in bytes. */
|
||||
void (*write)(struct uc_struct* uc, void *opaque,
|
||||
hwaddr addr,
|
||||
uint64_t data,
|
||||
unsigned size);
|
||||
|
||||
enum device_endian endianness;
|
||||
/* Guest-visible constraints: */
|
||||
struct {
|
||||
/* If nonzero, specify bounds on access sizes beyond which a machine
|
||||
* check is thrown.
|
||||
*/
|
||||
unsigned min_access_size;
|
||||
unsigned max_access_size;
|
||||
/* If true, unaligned accesses are supported. Otherwise unaligned
|
||||
* accesses throw machine checks.
|
||||
*/
|
||||
bool unaligned;
|
||||
/*
|
||||
* If present, and returns #false, the transaction is not accepted
|
||||
* by the device (and results in machine dependent behaviour such
|
||||
* as a machine check exception).
|
||||
*/
|
||||
bool (*accepts)(void *opaque, hwaddr addr,
|
||||
unsigned size, bool is_write);
|
||||
} valid;
|
||||
/* Internal implementation constraints: */
|
||||
struct {
|
||||
/* If nonzero, specifies the minimum size implemented. Smaller sizes
|
||||
* will be rounded upwards and a partial result will be returned.
|
||||
*/
|
||||
unsigned min_access_size;
|
||||
/* If nonzero, specifies the maximum size implemented. Larger sizes
|
||||
* will be done as a series of accesses with smaller sizes.
|
||||
*/
|
||||
unsigned max_access_size;
|
||||
/* If true, unaligned accesses are supported. Otherwise all accesses
|
||||
* are converted to (possibly multiple) naturally aligned accesses.
|
||||
*/
|
||||
bool unaligned;
|
||||
} impl;
|
||||
|
||||
/* If .read and .write are not present, old_mmio may be used for
|
||||
* backwards compatibility with old mmio registration
|
||||
*/
|
||||
const MemoryRegionMmio old_mmio;
|
||||
};
|
||||
|
||||
typedef struct MemoryRegionIOMMUOps MemoryRegionIOMMUOps;
|
||||
|
||||
struct MemoryRegionIOMMUOps {
|
||||
/* Return a TLB entry that contains a given address. */
|
||||
IOMMUTLBEntry (*translate)(MemoryRegion *iommu, hwaddr addr, bool is_write);
|
||||
};
|
||||
|
||||
typedef struct CoalescedMemoryRange CoalescedMemoryRange;
|
||||
typedef struct MemoryRegionIoeventfd MemoryRegionIoeventfd;
|
||||
|
||||
struct MemoryRegion {
|
||||
Object parent_obj;
|
||||
/* All fields are private - violators will be prosecuted */
|
||||
const MemoryRegionOps *ops;
|
||||
const MemoryRegionIOMMUOps *iommu_ops;
|
||||
void *opaque;
|
||||
MemoryRegion *container;
|
||||
Int128 size;
|
||||
hwaddr addr;
|
||||
void (*destructor)(MemoryRegion *mr);
|
||||
ram_addr_t ram_addr;
|
||||
uint64_t align;
|
||||
bool subpage;
|
||||
bool terminates;
|
||||
bool romd_mode;
|
||||
bool ram;
|
||||
bool skip_dump;
|
||||
bool readonly; /* For RAM regions */
|
||||
bool enabled;
|
||||
bool rom_device;
|
||||
bool warning_printed; /* For reservations */
|
||||
bool flush_coalesced_mmio;
|
||||
MemoryRegion *alias;
|
||||
hwaddr alias_offset;
|
||||
int32_t priority;
|
||||
bool may_overlap;
|
||||
QTAILQ_HEAD(subregions, MemoryRegion) subregions;
|
||||
QTAILQ_ENTRY(MemoryRegion) subregions_link;
|
||||
QTAILQ_HEAD(coalesced_ranges, CoalescedMemoryRange) coalesced;
|
||||
const char *name;
|
||||
uint8_t dirty_log_mask;
|
||||
unsigned ioeventfd_nb;
|
||||
MemoryRegionIoeventfd *ioeventfds;
|
||||
NotifierList iommu_notify;
|
||||
struct uc_struct *uc;
|
||||
};
|
||||
|
||||
/**
|
||||
* MemoryListener: callbacks structure for updates to the physical memory map
|
||||
*
|
||||
* Allows a component to adjust to changes in the guest-visible memory map.
|
||||
* Use with memory_listener_register() and memory_listener_unregister().
|
||||
*/
|
||||
struct MemoryListener {
|
||||
void (*begin)(MemoryListener *listener);
|
||||
void (*commit)(MemoryListener *listener);
|
||||
void (*region_add)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*region_del)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*region_nop)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*log_start)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*log_stop)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*log_sync)(MemoryListener *listener, MemoryRegionSection *section);
|
||||
void (*log_global_start)(MemoryListener *listener);
|
||||
void (*log_global_stop)(MemoryListener *listener);
|
||||
void (*eventfd_add)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
bool match_data, uint64_t data, EventNotifier *e);
|
||||
void (*eventfd_del)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
bool match_data, uint64_t data, EventNotifier *e);
|
||||
void (*coalesced_mmio_add)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
hwaddr addr, hwaddr len);
|
||||
void (*coalesced_mmio_del)(MemoryListener *listener, MemoryRegionSection *section,
|
||||
hwaddr addr, hwaddr len);
|
||||
/* Lower = earlier (during add), later (during del) */
|
||||
unsigned priority;
|
||||
AddressSpace *address_space_filter;
|
||||
QTAILQ_ENTRY(MemoryListener) link;
|
||||
};
|
||||
|
||||
/**
|
||||
* AddressSpace: describes a mapping of addresses to #MemoryRegion objects
|
||||
*/
|
||||
struct AddressSpace {
|
||||
/* All fields are private. */
|
||||
char *name;
|
||||
MemoryRegion *root;
|
||||
struct FlatView *current_map;
|
||||
int ioeventfd_nb;
|
||||
struct MemoryRegionIoeventfd *ioeventfds;
|
||||
struct AddressSpaceDispatch *dispatch;
|
||||
struct AddressSpaceDispatch *next_dispatch;
|
||||
MemoryListener dispatch_listener;
|
||||
struct uc_struct* uc;
|
||||
|
||||
QTAILQ_ENTRY(AddressSpace) address_spaces_link;
|
||||
};
|
||||
|
||||
/**
|
||||
* MemoryRegionSection: describes a fragment of a #MemoryRegion
|
||||
*
|
||||
* @mr: the region, or %NULL if empty
|
||||
* @address_space: the address space the region is mapped in
|
||||
* @offset_within_region: the beginning of the section, relative to @mr's start
|
||||
* @size: the size of the section; will not exceed @mr's boundaries
|
||||
* @offset_within_address_space: the address of the first byte of the section
|
||||
* relative to the region's address space
|
||||
* @readonly: writes to this section are ignored
|
||||
*/
|
||||
struct MemoryRegionSection {
|
||||
MemoryRegion *mr;
|
||||
AddressSpace *address_space;
|
||||
hwaddr offset_within_region;
|
||||
Int128 size;
|
||||
hwaddr offset_within_address_space;
|
||||
bool readonly;
|
||||
};
|
||||
|
||||
/**
|
||||
* memory_region_init: Initialize a memory region
|
||||
*
|
||||
* The region typically acts as a container for other memory regions. Use
|
||||
* memory_region_add_subregion() to add subregions.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region; any subregions beyond this size will be clipped
|
||||
*/
|
||||
void memory_region_init(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_ref: Add 1 to a memory region's reference count
|
||||
*
|
||||
* Whenever memory regions are accessed outside the BQL, they need to be
|
||||
* preserved against hot-unplug. MemoryRegions actually do not have their
|
||||
* own reference count; they piggyback on a QOM object, their "owner".
|
||||
* This function adds a reference to the owner.
|
||||
*
|
||||
* All MemoryRegions must have an owner if they can disappear, even if the
|
||||
* device they belong to operates exclusively under the BQL. This is because
|
||||
* the region could be returned at any time by memory_region_find, and this
|
||||
* is usually under guest control.
|
||||
*
|
||||
* @mr: the #MemoryRegion
|
||||
*/
|
||||
void memory_region_ref(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_unref: Remove 1 to a memory region's reference count
|
||||
*
|
||||
* Whenever memory regions are accessed outside the BQL, they need to be
|
||||
* preserved against hot-unplug. MemoryRegions actually do not have their
|
||||
* own reference count; they piggyback on a QOM object, their "owner".
|
||||
* This function removes a reference to the owner and possibly destroys it.
|
||||
*
|
||||
* @mr: the #MemoryRegion
|
||||
*/
|
||||
void memory_region_unref(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_init_io: Initialize an I/O memory region.
|
||||
*
|
||||
* Accesses into the region will cause the callbacks in @ops to be called.
|
||||
* if @size is nonzero, subregions will be clipped to @size.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: a structure containing read and write callbacks to be used when
|
||||
* I/O is performed on the region.
|
||||
* @opaque: passed to to the read and write callbacks of the @ops structure.
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_io(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const MemoryRegionOps *ops,
|
||||
void *opaque,
|
||||
const char *name,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_init_ram: Initialize RAM memory region. Accesses into the
|
||||
* region will modify memory directly.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
void memory_region_init_ram(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_init_ram_ptr: Initialize RAM memory region from a
|
||||
* user-provided pointer. Accesses into the
|
||||
* region will modify memory directly.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @ptr: memory to be mapped; must contain at least @size bytes.
|
||||
*/
|
||||
void memory_region_init_ram_ptr(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
void *ptr);
|
||||
|
||||
/**
|
||||
* memory_region_init_alias: Initialize a memory region that aliases all or a
|
||||
* part of another memory region.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @orig: the region to be referenced; @mr will be equivalent to
|
||||
* @orig between @offset and @offset + @size - 1.
|
||||
* @offset: start of the section in @orig to be referenced.
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_alias(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
MemoryRegion *orig,
|
||||
hwaddr offset,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_init_rom_device: Initialize a ROM memory region. Writes are
|
||||
* handled via callbacks.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized.
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: callbacks for write access handling.
|
||||
* @name: the name of the region.
|
||||
* @size: size of the region.
|
||||
* @errp: pointer to Error*, to store an error if it happens.
|
||||
*/
|
||||
void memory_region_init_rom_device(MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const MemoryRegionOps *ops,
|
||||
void *opaque,
|
||||
const char *name,
|
||||
uint64_t size,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* memory_region_init_reservation: Initialize a memory region that reserves
|
||||
* I/O space.
|
||||
*
|
||||
* A reservation region primariy serves debugging purposes. It claims I/O
|
||||
* space that is not supposed to be handled by QEMU itself. Any access via
|
||||
* the memory API will cause an abort().
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_reservation(struct uc_struct *uc, MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const char *name,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_init_iommu: Initialize a memory region that translates
|
||||
* addresses
|
||||
*
|
||||
* An IOMMU region translates addresses and forwards accesses to a target
|
||||
* memory region.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be initialized
|
||||
* @owner: the object that tracks the region's reference count
|
||||
* @ops: a function that translates addresses into the @target region
|
||||
* @name: used for debugging; not visible to the user or ABI
|
||||
* @size: size of the region.
|
||||
*/
|
||||
void memory_region_init_iommu(MemoryRegion *mr,
|
||||
struct Object *owner,
|
||||
const MemoryRegionIOMMUOps *ops,
|
||||
const char *name,
|
||||
uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_size: get a memory region's size.
|
||||
*
|
||||
* @mr: the memory region being queried.
|
||||
*/
|
||||
uint64_t memory_region_size(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_ram: check whether a memory region is random access
|
||||
*
|
||||
* Returns %true is a memory region is random access.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_ram(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_skip_dump: check whether a memory region should not be
|
||||
* dumped
|
||||
*
|
||||
* Returns %true is a memory region should not be dumped(e.g. VFIO BAR MMAP).
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_skip_dump(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_set_skip_dump: Set skip_dump flag, dump will ignore this memory
|
||||
* region
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
void memory_region_set_skip_dump(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_romd: check whether a memory region is in ROMD mode
|
||||
*
|
||||
* Returns %true if a memory region is a ROM device and currently set to allow
|
||||
* direct reads.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
static inline bool memory_region_is_romd(MemoryRegion *mr)
|
||||
{
|
||||
return mr->rom_device && mr->romd_mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* memory_region_is_iommu: check whether a memory region is an iommu
|
||||
*
|
||||
* Returns %true is a memory region is an iommu.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_iommu(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_notify_iommu: notify a change in an IOMMU translation entry.
|
||||
*
|
||||
* @mr: the memory region that was changed
|
||||
* @entry: the new entry in the IOMMU translation table. The entry
|
||||
* replaces all old entries for the same virtual I/O address range.
|
||||
* Deleted entries have .@perm == 0.
|
||||
*/
|
||||
void memory_region_notify_iommu(MemoryRegion *mr,
|
||||
IOMMUTLBEntry entry);
|
||||
|
||||
/**
|
||||
* memory_region_register_iommu_notifier: register a notifier for changes to
|
||||
* IOMMU translation entries.
|
||||
*
|
||||
* @mr: the memory region to observe
|
||||
* @n: the notifier to be added; the notifier receives a pointer to an
|
||||
* #IOMMUTLBEntry as the opaque value; the pointer ceases to be
|
||||
* valid on exit from the notifier.
|
||||
*/
|
||||
void memory_region_register_iommu_notifier(MemoryRegion *mr, Notifier *n);
|
||||
|
||||
/**
|
||||
* memory_region_unregister_iommu_notifier: unregister a notifier for
|
||||
* changes to IOMMU translation entries.
|
||||
*
|
||||
* @n: the notifier to be removed.
|
||||
*/
|
||||
void memory_region_unregister_iommu_notifier(Notifier *n);
|
||||
|
||||
/**
|
||||
* memory_region_name: get a memory region's name
|
||||
*
|
||||
* Returns the string that was used to initialize the memory region.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
const char *memory_region_name(const MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_logging: return whether a memory region is logging writes
|
||||
*
|
||||
* Returns %true if the memory region is logging writes
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_logging(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_is_rom: check whether a memory region is ROM
|
||||
*
|
||||
* Returns %true is a memory region is read-only memory.
|
||||
*
|
||||
* @mr: the memory region being queried
|
||||
*/
|
||||
bool memory_region_is_rom(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_get_fd: Get a file descriptor backing a RAM memory region.
|
||||
*
|
||||
* Returns a file descriptor backing a file-based RAM memory region,
|
||||
* or -1 if the region is not a file-based RAM memory region.
|
||||
*
|
||||
* @mr: the RAM or alias memory region being queried.
|
||||
*/
|
||||
int memory_region_get_fd(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_get_ram_ptr: Get a pointer into a RAM memory region.
|
||||
*
|
||||
* Returns a host pointer to a RAM memory region (created with
|
||||
* memory_region_init_ram() or memory_region_init_ram_ptr()). Use with
|
||||
* care.
|
||||
*
|
||||
* @mr: the memory region being queried.
|
||||
*/
|
||||
void *memory_region_get_ram_ptr(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_set_readonly: Turn a memory region read-only (or read-write)
|
||||
*
|
||||
* Allows a memory region to be marked as read-only (turning it into a ROM).
|
||||
* only useful on RAM regions.
|
||||
*
|
||||
* @mr: the region being updated.
|
||||
* @readonly: whether rhe region is to be ROM or RAM.
|
||||
*/
|
||||
void memory_region_set_readonly(MemoryRegion *mr, bool readonly);
|
||||
|
||||
/**
|
||||
* memory_region_rom_device_set_romd: enable/disable ROMD mode
|
||||
*
|
||||
* Allows a ROM device (initialized with memory_region_init_rom_device() to
|
||||
* set to ROMD mode (default) or MMIO mode. When it is in ROMD mode, the
|
||||
* device is mapped to guest memory and satisfies read access directly.
|
||||
* When in MMIO mode, reads are forwarded to the #MemoryRegion.read function.
|
||||
* Writes are always handled by the #MemoryRegion.write function.
|
||||
*
|
||||
* @mr: the memory region to be updated
|
||||
* @romd_mode: %true to put the region into ROMD mode
|
||||
*/
|
||||
void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode);
|
||||
|
||||
/**
|
||||
* memory_region_clear_coalescing: Disable MMIO coalescing for the region.
|
||||
*
|
||||
* Disables any coalescing caused by memory_region_set_coalescing() or
|
||||
* memory_region_add_coalescing(). Roughly equivalent to uncacheble memory
|
||||
* hardware.
|
||||
*
|
||||
* @mr: the memory region to be updated.
|
||||
*/
|
||||
void memory_region_clear_coalescing(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_add_eventfd: Request an eventfd to be triggered when a word
|
||||
* is written to a location.
|
||||
*
|
||||
* Marks a word in an IO region (initialized with memory_region_init_io())
|
||||
* as a trigger for an eventfd event. The I/O callback will not be called.
|
||||
* The caller must be prepared to handle failure (that is, take the required
|
||||
* action if the callback _is_ called).
|
||||
*
|
||||
* @mr: the memory region being updated.
|
||||
* @addr: the address within @mr that is to be monitored
|
||||
* @size: the size of the access to trigger the eventfd
|
||||
* @match_data: whether to match against @data, instead of just @addr
|
||||
* @data: the data to match against the guest write
|
||||
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
|
||||
**/
|
||||
void memory_region_add_eventfd(MemoryRegion *mr,
|
||||
hwaddr addr,
|
||||
unsigned size,
|
||||
bool match_data,
|
||||
uint64_t data,
|
||||
EventNotifier *e);
|
||||
|
||||
/**
|
||||
* memory_region_del_eventfd: Cancel an eventfd.
|
||||
*
|
||||
* Cancels an eventfd trigger requested by a previous
|
||||
* memory_region_add_eventfd() call.
|
||||
*
|
||||
* @mr: the memory region being updated.
|
||||
* @addr: the address within @mr that is to be monitored
|
||||
* @size: the size of the access to trigger the eventfd
|
||||
* @match_data: whether to match against @data, instead of just @addr
|
||||
* @data: the data to match against the guest write
|
||||
* @fd: the eventfd to be triggered when @addr, @size, and @data all match.
|
||||
*/
|
||||
void memory_region_del_eventfd(MemoryRegion *mr,
|
||||
hwaddr addr,
|
||||
unsigned size,
|
||||
bool match_data,
|
||||
uint64_t data,
|
||||
EventNotifier *e);
|
||||
|
||||
/**
|
||||
* memory_region_add_subregion: Add a subregion to a container.
|
||||
*
|
||||
* Adds a subregion at @offset. The subregion may not overlap with other
|
||||
* subregions (except for those explicitly marked as overlapping). A region
|
||||
* may only be added once as a subregion (unless removed with
|
||||
* memory_region_del_subregion()); use memory_region_init_alias() if you
|
||||
* want a region to be a subregion in multiple locations.
|
||||
*
|
||||
* @mr: the region to contain the new subregion; must be a container
|
||||
* initialized with memory_region_init().
|
||||
* @offset: the offset relative to @mr where @subregion is added.
|
||||
* @subregion: the subregion to be added.
|
||||
*/
|
||||
void memory_region_add_subregion(MemoryRegion *mr,
|
||||
hwaddr offset,
|
||||
MemoryRegion *subregion);
|
||||
/**
|
||||
* memory_region_add_subregion_overlap: Add a subregion to a container
|
||||
* with overlap.
|
||||
*
|
||||
* Adds a subregion at @offset. The subregion may overlap with other
|
||||
* subregions. Conflicts are resolved by having a higher @priority hide a
|
||||
* lower @priority. Subregions without priority are taken as @priority 0.
|
||||
* A region may only be added once as a subregion (unless removed with
|
||||
* memory_region_del_subregion()); use memory_region_init_alias() if you
|
||||
* want a region to be a subregion in multiple locations.
|
||||
*
|
||||
* @mr: the region to contain the new subregion; must be a container
|
||||
* initialized with memory_region_init().
|
||||
* @offset: the offset relative to @mr where @subregion is added.
|
||||
* @subregion: the subregion to be added.
|
||||
* @priority: used for resolving overlaps; highest priority wins.
|
||||
*/
|
||||
void memory_region_add_subregion_overlap(MemoryRegion *mr,
|
||||
hwaddr offset,
|
||||
MemoryRegion *subregion,
|
||||
int priority);
|
||||
|
||||
/**
|
||||
* memory_region_get_ram_addr: Get the ram address associated with a memory
|
||||
* region
|
||||
*
|
||||
* DO NOT USE THIS FUNCTION. This is a temporary workaround while the Xen
|
||||
* code is being reworked.
|
||||
*/
|
||||
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr);
|
||||
|
||||
uint64_t memory_region_get_alignment(const MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_del_subregion: Remove a subregion.
|
||||
*
|
||||
* Removes a subregion from its container.
|
||||
*
|
||||
* @mr: the container to be updated.
|
||||
* @subregion: the region being removed; must be a current subregion of @mr.
|
||||
*/
|
||||
void memory_region_del_subregion(MemoryRegion *mr,
|
||||
MemoryRegion *subregion);
|
||||
|
||||
/*
|
||||
* memory_region_set_enabled: dynamically enable or disable a region
|
||||
*
|
||||
* Enables or disables a memory region. A disabled memory region
|
||||
* ignores all accesses to itself and its subregions. It does not
|
||||
* obscure sibling subregions with lower priority - it simply behaves as
|
||||
* if it was removed from the hierarchy.
|
||||
*
|
||||
* Regions default to being enabled.
|
||||
*
|
||||
* @mr: the region to be updated
|
||||
* @enabled: whether to enable or disable the region
|
||||
*/
|
||||
void memory_region_set_enabled(MemoryRegion *mr, bool enabled);
|
||||
|
||||
/*
|
||||
* memory_region_set_address: dynamically update the address of a region
|
||||
*
|
||||
* Dynamically updates the address of a region, relative to its container.
|
||||
* May be used on regions are currently part of a memory hierarchy.
|
||||
*
|
||||
* @mr: the region to be updated
|
||||
* @addr: new address, relative to container region
|
||||
*/
|
||||
void memory_region_set_address(MemoryRegion *mr, hwaddr addr);
|
||||
|
||||
/*
|
||||
* memory_region_set_alias_offset: dynamically update a memory alias's offset
|
||||
*
|
||||
* Dynamically updates the offset into the target region that an alias points
|
||||
* to, as if the fourth argument to memory_region_init_alias() has changed.
|
||||
*
|
||||
* @mr: the #MemoryRegion to be updated; should be an alias.
|
||||
* @offset: the new offset into the target memory region
|
||||
*/
|
||||
void memory_region_set_alias_offset(MemoryRegion *mr,
|
||||
hwaddr offset);
|
||||
|
||||
/**
|
||||
* memory_region_present: checks if an address relative to a @container
|
||||
* translates into #MemoryRegion within @container
|
||||
*
|
||||
* Answer whether a #MemoryRegion within @container covers the address
|
||||
* @addr.
|
||||
*
|
||||
* @container: a #MemoryRegion within which @addr is a relative address
|
||||
* @addr: the area within @container to be searched
|
||||
*/
|
||||
bool memory_region_present(MemoryRegion *container, hwaddr addr);
|
||||
|
||||
/**
|
||||
* memory_region_is_mapped: returns true if #MemoryRegion is mapped
|
||||
* into any address space.
|
||||
*
|
||||
* @mr: a #MemoryRegion which should be checked if it's mapped
|
||||
*/
|
||||
bool memory_region_is_mapped(MemoryRegion *mr);
|
||||
|
||||
/**
|
||||
* memory_region_find: translate an address/size relative to a
|
||||
* MemoryRegion into a #MemoryRegionSection.
|
||||
*
|
||||
* Locates the first #MemoryRegion within @mr that overlaps the range
|
||||
* given by @addr and @size.
|
||||
*
|
||||
* Returns a #MemoryRegionSection that describes a contiguous overlap.
|
||||
* It will have the following characteristics:
|
||||
* .@size = 0 iff no overlap was found
|
||||
* .@mr is non-%NULL iff an overlap was found
|
||||
*
|
||||
* Remember that in the return value the @offset_within_region is
|
||||
* relative to the returned region (in the .@mr field), not to the
|
||||
* @mr argument.
|
||||
*
|
||||
* Similarly, the .@offset_within_address_space is relative to the
|
||||
* address space that contains both regions, the passed and the
|
||||
* returned one. However, in the special case where the @mr argument
|
||||
* has no container (and thus is the root of the address space), the
|
||||
* following will hold:
|
||||
* .@offset_within_address_space >= @addr
|
||||
* .@offset_within_address_space + .@size <= @addr + @size
|
||||
*
|
||||
* @mr: a MemoryRegion within which @addr is a relative address
|
||||
* @addr: start of the area within @as to be searched
|
||||
* @size: size of the area to be searched
|
||||
*/
|
||||
MemoryRegionSection memory_region_find(MemoryRegion *mr,
|
||||
hwaddr addr, uint64_t size);
|
||||
|
||||
/**
|
||||
* memory_region_transaction_begin: Start a transaction.
|
||||
*
|
||||
* During a transaction, changes will be accumulated and made visible
|
||||
* only when the transaction ends (is committed).
|
||||
*/
|
||||
void memory_region_transaction_begin(struct uc_struct*);
|
||||
|
||||
/**
|
||||
* memory_region_transaction_commit: Commit a transaction and make changes
|
||||
* visible to the guest.
|
||||
*/
|
||||
void memory_region_transaction_commit(struct uc_struct*);
|
||||
|
||||
/**
|
||||
* memory_listener_register: register callbacks to be called when memory
|
||||
* sections are mapped or unmapped into an address
|
||||
* space
|
||||
*
|
||||
* @listener: an object containing the callbacks to be called
|
||||
* @filter: if non-%NULL, only regions in this address space will be observed
|
||||
*/
|
||||
void memory_listener_register(struct uc_struct* uc, MemoryListener *listener, AddressSpace *filter);
|
||||
|
||||
/**
|
||||
* memory_listener_unregister: undo the effect of memory_listener_register()
|
||||
*
|
||||
* @listener: an object containing the callbacks to be removed
|
||||
*/
|
||||
void memory_listener_unregister(struct uc_struct* uc, MemoryListener *listener);
|
||||
|
||||
/**
|
||||
* address_space_init: initializes an address space
|
||||
*
|
||||
* @as: an uninitialized #AddressSpace
|
||||
* @root: a #MemoryRegion that routes addesses for the address space
|
||||
* @name: an address space name. The name is only used for debugging
|
||||
* output.
|
||||
*/
|
||||
void address_space_init(struct uc_struct *uc, AddressSpace *as, MemoryRegion *root, const char *name);
|
||||
|
||||
|
||||
/**
|
||||
* address_space_destroy: destroy an address space
|
||||
*
|
||||
* Releases all resources associated with an address space. After an address space
|
||||
* is destroyed, its root memory region (given by address_space_init()) may be destroyed
|
||||
* as well.
|
||||
*
|
||||
* @as: address space to be destroyed
|
||||
*/
|
||||
void address_space_destroy(AddressSpace *as);
|
||||
|
||||
/**
|
||||
* address_space_rw: read from or write to an address space.
|
||||
*
|
||||
* Return true if the operation hit any unassigned memory or encountered an
|
||||
* IOMMU fault.
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @buf: buffer with the data transferred
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
bool address_space_rw(AddressSpace *as, hwaddr addr, uint8_t *buf,
|
||||
int len, bool is_write);
|
||||
|
||||
/**
|
||||
* address_space_write: write to address space.
|
||||
*
|
||||
* Return true if the operation hit any unassigned memory or encountered an
|
||||
* IOMMU fault.
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @buf: buffer with the data transferred
|
||||
*/
|
||||
bool address_space_write(AddressSpace *as, hwaddr addr,
|
||||
const uint8_t *buf, int len);
|
||||
|
||||
/**
|
||||
* address_space_read: read from an address space.
|
||||
*
|
||||
* Return true if the operation hit any unassigned memory or encountered an
|
||||
* IOMMU fault.
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @buf: buffer with the data transferred
|
||||
*/
|
||||
bool address_space_read(AddressSpace *as, hwaddr addr, uint8_t *buf, int len);
|
||||
|
||||
/* address_space_translate: translate an address range into an address space
|
||||
* into a MemoryRegion and an address range into that section
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @xlat: pointer to address within the returned memory region section's
|
||||
* #MemoryRegion.
|
||||
* @len: pointer to length
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
MemoryRegion *address_space_translate(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *xlat, hwaddr *len,
|
||||
bool is_write);
|
||||
|
||||
/* address_space_access_valid: check for validity of accessing an address
|
||||
* space range
|
||||
*
|
||||
* Check whether memory is assigned to the given address space range, and
|
||||
* access is permitted by any IOMMU regions that are active for the address
|
||||
* space.
|
||||
*
|
||||
* For now, addr and len should be aligned to a page size. This limitation
|
||||
* will be lifted in the future.
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @len: length of the area to be checked
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
bool address_space_access_valid(AddressSpace *as, hwaddr addr, int len, bool is_write);
|
||||
|
||||
/* address_space_map: map a physical memory region into a host virtual address
|
||||
*
|
||||
* May map a subset of the requested range, given by and returned in @plen.
|
||||
* May return %NULL if resources needed to perform the mapping are exhausted.
|
||||
* Use only for reads OR writes - not for read-modify-write operations.
|
||||
* Use cpu_register_map_client() to know when retrying the map operation is
|
||||
* likely to succeed.
|
||||
*
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @plen: pointer to length of buffer; updated on return
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
void *address_space_map(AddressSpace *as, hwaddr addr,
|
||||
hwaddr *plen, bool is_write);
|
||||
|
||||
/* address_space_unmap: Unmaps a memory region previously mapped by address_space_map()
|
||||
*
|
||||
* Will also mark the memory as dirty if @is_write == %true. @access_len gives
|
||||
* the amount of memory that was actually read or written by the caller.
|
||||
*
|
||||
* @as: #AddressSpace used
|
||||
* @addr: address within that address space
|
||||
* @len: buffer length as returned by address_space_map()
|
||||
* @access_len: amount of data actually transferred
|
||||
* @is_write: indicates the transfer direction
|
||||
*/
|
||||
void address_space_unmap(AddressSpace *as, void *buffer, hwaddr len,
|
||||
int is_write, hwaddr access_len);
|
||||
|
||||
|
||||
void memory_register_types(struct uc_struct *uc);
|
||||
|
||||
int memory_map(struct uc_struct *uc, ram_addr_t begin, size_t size);
|
||||
int memory_free(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
62
qemu/include/exec/poison.h
Normal file
62
qemu/include/exec/poison.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* Poison identifiers that should not be used when building
|
||||
target independent device code. */
|
||||
|
||||
#ifndef HW_POISON_H
|
||||
#define HW_POISON_H
|
||||
#ifdef __GNUC__
|
||||
|
||||
#pragma GCC poison TARGET_I386
|
||||
#pragma GCC poison TARGET_X86_64
|
||||
#pragma GCC poison TARGET_ALPHA
|
||||
#pragma GCC poison TARGET_ARM
|
||||
#pragma GCC poison TARGET_CRIS
|
||||
#pragma GCC poison TARGET_LM32
|
||||
#pragma GCC poison TARGET_M68K
|
||||
#pragma GCC poison TARGET_MIPS
|
||||
#pragma GCC poison TARGET_MIPS64
|
||||
#pragma GCC poison TARGET_OPENRISC
|
||||
#pragma GCC poison TARGET_PPC
|
||||
#pragma GCC poison TARGET_PPCEMB
|
||||
#pragma GCC poison TARGET_PPC64
|
||||
#pragma GCC poison TARGET_ABI32
|
||||
#pragma GCC poison TARGET_SH4
|
||||
#pragma GCC poison TARGET_SPARC
|
||||
#pragma GCC poison TARGET_SPARC64
|
||||
|
||||
#pragma GCC poison TARGET_WORDS_BIGENDIAN
|
||||
#pragma GCC poison BSWAP_NEEDED
|
||||
|
||||
#pragma GCC poison TARGET_LONG_BITS
|
||||
#pragma GCC poison TARGET_FMT_lx
|
||||
#pragma GCC poison TARGET_FMT_ld
|
||||
|
||||
#pragma GCC poison TARGET_PAGE_SIZE
|
||||
#pragma GCC poison TARGET_PAGE_MASK
|
||||
#pragma GCC poison TARGET_PAGE_BITS
|
||||
#pragma GCC poison TARGET_PAGE_ALIGN
|
||||
|
||||
#pragma GCC poison CPUArchState
|
||||
|
||||
#pragma GCC poison lduw_phys
|
||||
#pragma GCC poison ldl_phys
|
||||
#pragma GCC poison ldq_phys
|
||||
#pragma GCC poison stl_phys_notdirty
|
||||
#pragma GCC poison stw_phys
|
||||
#pragma GCC poison stl_phys
|
||||
#pragma GCC poison stq_phys
|
||||
|
||||
#pragma GCC poison CPU_INTERRUPT_HARD
|
||||
#pragma GCC poison CPU_INTERRUPT_EXITTB
|
||||
#pragma GCC poison CPU_INTERRUPT_HALT
|
||||
#pragma GCC poison CPU_INTERRUPT_DEBUG
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_0
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_1
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_2
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_3
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_EXT_4
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_INT_0
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_INT_1
|
||||
#pragma GCC poison CPU_INTERRUPT_TGT_INT_2
|
||||
|
||||
#endif
|
||||
#endif
|
||||
187
qemu/include/exec/ram_addr.h
Normal file
187
qemu/include/exec/ram_addr.h
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* Declarations for cpu physical memory functions
|
||||
*
|
||||
* Copyright 2011 Red Hat, Inc. and/or its affiliates
|
||||
*
|
||||
* Authors:
|
||||
* Avi Kivity <avi@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2 or
|
||||
* later. See the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This header is for use by exec.c and memory.c ONLY. Do not include it.
|
||||
* The functions declared here will be removed soon.
|
||||
*/
|
||||
|
||||
#ifndef RAM_ADDR_H
|
||||
#define RAM_ADDR_H
|
||||
|
||||
#include "uc_priv.h"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host,
|
||||
MemoryRegion *mr, Error **errp);
|
||||
ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp);
|
||||
int qemu_get_ram_fd(struct uc_struct *uc, ram_addr_t addr);
|
||||
void *qemu_get_ram_block_host_ptr(struct uc_struct *uc, ram_addr_t addr);
|
||||
void *qemu_get_ram_ptr(struct uc_struct *uc, ram_addr_t addr);
|
||||
void qemu_ram_free(struct uc_struct *c, ram_addr_t addr);
|
||||
void qemu_ram_free_from_ptr(struct uc_struct *uc, ram_addr_t addr);
|
||||
|
||||
static inline bool cpu_physical_memory_get_dirty(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
{
|
||||
unsigned long end, page, next;
|
||||
|
||||
assert(client < DIRTY_MEMORY_NUM);
|
||||
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
next = find_next_bit(uc->ram_list.dirty_memory[client], end, page);
|
||||
|
||||
return next < end;
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_get_clean(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
{
|
||||
unsigned long end, page, next;
|
||||
|
||||
assert(client < DIRTY_MEMORY_NUM);
|
||||
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
next = find_next_zero_bit(uc->ram_list.dirty_memory[client], end, page);
|
||||
|
||||
return next < end;
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_get_dirty_flag(struct uc_struct *uc, ram_addr_t addr,
|
||||
unsigned client)
|
||||
{
|
||||
return cpu_physical_memory_get_dirty(uc, addr, 1, client);
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_is_clean(struct uc_struct *uc, ram_addr_t addr)
|
||||
{
|
||||
bool vga = cpu_physical_memory_get_dirty_flag(uc, addr, DIRTY_MEMORY_VGA);
|
||||
bool code = cpu_physical_memory_get_dirty_flag(uc, addr, DIRTY_MEMORY_CODE);
|
||||
bool migration =
|
||||
cpu_physical_memory_get_dirty_flag(uc, addr, DIRTY_MEMORY_MIGRATION);
|
||||
return !(vga && code && migration);
|
||||
}
|
||||
|
||||
static inline bool cpu_physical_memory_range_includes_clean(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length)
|
||||
{
|
||||
bool vga = cpu_physical_memory_get_clean(uc, start, length, DIRTY_MEMORY_VGA);
|
||||
bool code = cpu_physical_memory_get_clean(uc, start, length, DIRTY_MEMORY_CODE);
|
||||
bool migration =
|
||||
cpu_physical_memory_get_clean(uc, start, length, DIRTY_MEMORY_MIGRATION);
|
||||
return vga || code || migration;
|
||||
}
|
||||
|
||||
static inline void cpu_physical_memory_set_dirty_flag(struct uc_struct *uc, ram_addr_t addr,
|
||||
unsigned client)
|
||||
{
|
||||
assert(client < DIRTY_MEMORY_NUM);
|
||||
set_bit(addr >> TARGET_PAGE_BITS, uc->ram_list.dirty_memory[client]);
|
||||
}
|
||||
|
||||
static inline void cpu_physical_memory_set_dirty_range_nocode(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length)
|
||||
{
|
||||
unsigned long end, page;
|
||||
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
bitmap_set(uc->ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page);
|
||||
bitmap_set(uc->ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page);
|
||||
}
|
||||
|
||||
static inline void cpu_physical_memory_set_dirty_range(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length)
|
||||
{
|
||||
unsigned long end, page;
|
||||
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
bitmap_set(uc->ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page);
|
||||
bitmap_set(uc->ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page);
|
||||
bitmap_set(uc->ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page);
|
||||
}
|
||||
|
||||
#if !defined(_WIN32)
|
||||
static inline void cpu_physical_memory_set_dirty_lebitmap(struct uc_struct *uc, unsigned long *bitmap,
|
||||
ram_addr_t start,
|
||||
ram_addr_t pages)
|
||||
{
|
||||
unsigned long i, j;
|
||||
unsigned long page_number, c;
|
||||
hwaddr addr;
|
||||
ram_addr_t ram_addr;
|
||||
unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS;
|
||||
unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE;
|
||||
unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS);
|
||||
|
||||
/* start address is aligned at the start of a word? */
|
||||
if ((((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) &&
|
||||
(hpratio == 1)) {
|
||||
long k;
|
||||
long nr = BITS_TO_LONGS(pages);
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
if (bitmap[k]) {
|
||||
unsigned long temp = leul_to_cpu(bitmap[k]);
|
||||
|
||||
uc->ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION][page + k] |= temp;
|
||||
uc->ram_list.dirty_memory[DIRTY_MEMORY_VGA][page + k] |= temp;
|
||||
uc->ram_list.dirty_memory[DIRTY_MEMORY_CODE][page + k] |= temp;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* bitmap-traveling is faster than memory-traveling (for addr...)
|
||||
* especially when most of the memory is not dirty.
|
||||
*/
|
||||
for (i = 0; i < len; i++) {
|
||||
if (bitmap[i] != 0) {
|
||||
c = leul_to_cpu(bitmap[i]);
|
||||
do {
|
||||
j = ctzl(c);
|
||||
c &= ~(1ul << j);
|
||||
page_number = (i * HOST_LONG_BITS + j) * hpratio;
|
||||
addr = page_number * TARGET_PAGE_SIZE;
|
||||
ram_addr = start + addr;
|
||||
cpu_physical_memory_set_dirty_range(uc, ram_addr,
|
||||
TARGET_PAGE_SIZE * hpratio);
|
||||
} while (c != 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* not _WIN32 */
|
||||
|
||||
static inline void cpu_physical_memory_clear_dirty_range(struct uc_struct *uc, ram_addr_t start,
|
||||
ram_addr_t length,
|
||||
unsigned client)
|
||||
{
|
||||
unsigned long end, page;
|
||||
|
||||
assert(client < DIRTY_MEMORY_NUM);
|
||||
end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS;
|
||||
page = start >> TARGET_PAGE_BITS;
|
||||
bitmap_clear(uc->ram_list.dirty_memory[client], page, end - page);
|
||||
}
|
||||
|
||||
void cpu_physical_memory_reset_dirty(struct uc_struct *uc,
|
||||
ram_addr_t start, ram_addr_t length, unsigned client);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
79
qemu/include/exec/softmmu-semi.h
Normal file
79
qemu/include/exec/softmmu-semi.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Helper routines to provide target memory access for semihosting
|
||||
* syscalls in system emulation mode.
|
||||
*
|
||||
* Copyright (c) 2007 CodeSourcery.
|
||||
*
|
||||
* This code is licensed under the GPL
|
||||
*/
|
||||
#ifndef SOFTMMU_SEMI_H
|
||||
#define SOFTMMU_SEMI_H 1
|
||||
|
||||
static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr)
|
||||
{
|
||||
uint32_t val;
|
||||
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 0);
|
||||
return tswap32(val);
|
||||
}
|
||||
static inline uint32_t softmmu_tget8(CPUArchState *env, uint32_t addr)
|
||||
{
|
||||
uint8_t val;
|
||||
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &val, 1, 0);
|
||||
return val;
|
||||
}
|
||||
|
||||
#define get_user_u32(arg, p) ({ arg = softmmu_tget32(env, p) ; 0; })
|
||||
#define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
|
||||
#define get_user_ual(arg, p) get_user_u32(arg, p)
|
||||
|
||||
static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t val)
|
||||
{
|
||||
val = tswap32(val);
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)&val, 4, 1);
|
||||
}
|
||||
#define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
|
||||
#define put_user_ual(arg, p) put_user_u32(arg, p)
|
||||
|
||||
static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
|
||||
int copy)
|
||||
{
|
||||
uint8_t *p;
|
||||
/* TODO: Make this something that isn't fixed size. */
|
||||
p = malloc(len);
|
||||
if (p && copy) {
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 0);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
#define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
|
||||
static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
|
||||
{
|
||||
char *p;
|
||||
char *s;
|
||||
uint8_t c;
|
||||
/* TODO: Make this something that isn't fixed size. */
|
||||
s = p = malloc(1024);
|
||||
if (!s) {
|
||||
return NULL;
|
||||
}
|
||||
do {
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, &c, 1, 0);
|
||||
addr++;
|
||||
*(p++) = c;
|
||||
} while (c);
|
||||
return s;
|
||||
}
|
||||
#define lock_user_string(p) softmmu_lock_user_string(env, p)
|
||||
static void softmmu_unlock_user(CPUArchState *env, void *p, target_ulong addr,
|
||||
target_ulong len)
|
||||
{
|
||||
if (len) {
|
||||
cpu_memory_rw_debug(ENV_GET_CPU(env), addr, p, len, 1);
|
||||
}
|
||||
free(p);
|
||||
}
|
||||
#define unlock_user(s, args, len) softmmu_unlock_user(env, s, args, len)
|
||||
|
||||
#endif
|
||||
53
qemu/include/exec/spinlock.h
Normal file
53
qemu/include/exec/spinlock.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 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/>
|
||||
*/
|
||||
|
||||
/* configure guarantees us that we have pthreads on any host except
|
||||
* mingw32, which doesn't support any of the user-only targets.
|
||||
* So we can simply assume we have pthread mutexes here.
|
||||
*/
|
||||
#ifndef QEMU_EXEC_SPINLOCK_H
|
||||
#define QEMU_EXEC_SPINLOCK_H
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
||||
#include <pthread.h>
|
||||
#define spin_lock pthread_mutex_lock
|
||||
#define spin_unlock pthread_mutex_unlock
|
||||
#define spinlock_t pthread_mutex_t
|
||||
#define SPIN_LOCK_UNLOCKED PTHREAD_MUTEX_INITIALIZER
|
||||
|
||||
#else
|
||||
|
||||
/* Empty implementations, on the theory that system mode emulation
|
||||
* is single-threaded. This means that these functions should only
|
||||
* be used from code run in the TCG cpu thread, and cannot protect
|
||||
* data structures which might also be accessed from the IO thread
|
||||
* or from signal handlers.
|
||||
*/
|
||||
typedef int spinlock_t;
|
||||
#define SPIN_LOCK_UNLOCKED 0
|
||||
|
||||
static inline void spin_lock(spinlock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void spin_unlock(spinlock_t *lock)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
721
qemu/include/fpu/softfloat.h
Normal file
721
qemu/include/fpu/softfloat.h
Normal file
@@ -0,0 +1,721 @@
|
||||
/*
|
||||
* QEMU float support
|
||||
*
|
||||
* Derived from SoftFloat.
|
||||
*/
|
||||
|
||||
/*============================================================================
|
||||
|
||||
This C header file is part of the SoftFloat IEC/IEEE Floating-point Arithmetic
|
||||
Package, Release 2b.
|
||||
|
||||
Written by John R. Hauser. This work was made possible in part by the
|
||||
International Computer Science Institute, located at Suite 600, 1947 Center
|
||||
Street, Berkeley, California 94704. Funding was partially provided by the
|
||||
National Science Foundation under grant MIP-9311980. The original version
|
||||
of this code was written as part of a project to build a fixed-point vector
|
||||
processor in collaboration with the University of California at Berkeley,
|
||||
overseen by Profs. Nelson Morgan and John Wawrzynek. More information
|
||||
is available through the Web page `http://www.cs.berkeley.edu/~jhauser/
|
||||
arithmetic/SoftFloat.html'.
|
||||
|
||||
THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort has
|
||||
been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT TIMES
|
||||
RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO PERSONS
|
||||
AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ALL LOSSES,
|
||||
COSTS, OR OTHER PROBLEMS THEY INCUR DUE TO THE SOFTWARE, AND WHO FURTHERMORE
|
||||
EFFECTIVELY INDEMNIFY JOHN HAUSER AND THE INTERNATIONAL COMPUTER SCIENCE
|
||||
INSTITUTE (possibly via similar legal warning) AGAINST ALL LOSSES, COSTS, OR
|
||||
OTHER PROBLEMS INCURRED BY THEIR CUSTOMERS AND CLIENTS DUE TO THE SOFTWARE.
|
||||
|
||||
Derivative works are acceptable, even for commercial purposes, so long as
|
||||
(1) the source code for the derivative work includes prominent notice that
|
||||
the work is derivative, and (2) the source code includes prominent notice with
|
||||
these four paragraphs for those parts of this code that are retained.
|
||||
|
||||
=============================================================================*/
|
||||
|
||||
#ifndef SOFTFLOAT_H
|
||||
#define SOFTFLOAT_H
|
||||
|
||||
#if defined(CONFIG_SOLARIS) && defined(CONFIG_NEEDS_LIBSUNMATH)
|
||||
#include <sunmath.h>
|
||||
#endif
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "config-host.h"
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Each of the following `typedef's defines the most convenient type that holds
|
||||
| integers of at least as many bits as specified. For example, `uint8' should
|
||||
| be the most convenient type that can hold unsigned integers of as many as
|
||||
| 8 bits. The `flag' type must be able to hold either a 0 or 1. For most
|
||||
| implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
|
||||
| to the same as `int'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
typedef uint8_t flag;
|
||||
typedef uint8_t uint8;
|
||||
typedef int8_t int8;
|
||||
typedef unsigned int uint32;
|
||||
typedef signed int int32;
|
||||
typedef uint64_t uint64;
|
||||
typedef int64_t int64;
|
||||
|
||||
#define LIT64( a ) a##LL
|
||||
|
||||
#define STATUS_PARAM , float_status *status
|
||||
#define STATUS(field) status->field
|
||||
#define STATUS_VAR , status
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point ordering relations
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_relation_less = -1,
|
||||
float_relation_equal = 0,
|
||||
float_relation_greater = 1,
|
||||
float_relation_unordered = 2
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point types.
|
||||
*----------------------------------------------------------------------------*/
|
||||
/* Use structures for soft-float types. This prevents accidentally mixing
|
||||
them with native int/float types. A sufficiently clever compiler and
|
||||
sane ABI should be able to see though these structs. However
|
||||
x86/gcc 3.x seems to struggle a bit, so leave them disabled by default. */
|
||||
//#define USE_SOFTFLOAT_STRUCT_TYPES
|
||||
#ifdef USE_SOFTFLOAT_STRUCT_TYPES
|
||||
typedef struct {
|
||||
uint16_t v;
|
||||
} float16;
|
||||
#define float16_val(x) (((float16)(x)).v)
|
||||
#define make_float16(x) __extension__ ({ float16 f16_val = {x}; f16_val; })
|
||||
#define const_float16(x) { x }
|
||||
typedef struct {
|
||||
uint32_t v;
|
||||
} float32;
|
||||
/* The cast ensures an error if the wrong type is passed. */
|
||||
#define float32_val(x) (((float32)(x)).v)
|
||||
#define make_float32(x) __extension__ ({ float32 f32_val = {x}; f32_val; })
|
||||
#define const_float32(x) { x }
|
||||
typedef struct {
|
||||
uint64_t v;
|
||||
} float64;
|
||||
#define float64_val(x) (((float64)(x)).v)
|
||||
#define make_float64(x) __extension__ ({ float64 f64_val = {x}; f64_val; })
|
||||
#define const_float64(x) { x }
|
||||
#else
|
||||
typedef uint16_t float16;
|
||||
typedef uint32_t float32;
|
||||
typedef uint64_t float64;
|
||||
#define float16_val(x) (x)
|
||||
#define float32_val(x) (x)
|
||||
#define float64_val(x) (x)
|
||||
#define make_float16(x) (x)
|
||||
#define make_float32(x) (x)
|
||||
#define make_float64(x) (x)
|
||||
#define const_float16(x) (x)
|
||||
#define const_float32(x) (x)
|
||||
#define const_float64(x) (x)
|
||||
#endif
|
||||
typedef struct {
|
||||
uint64_t low;
|
||||
uint16_t high;
|
||||
} floatx80;
|
||||
#define make_floatx80(exp, mant) ((floatx80) { mant, exp })
|
||||
#define make_floatx80_init(exp, mant) { .low = mant, .high = exp }
|
||||
typedef struct {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
uint64_t high, low;
|
||||
#else
|
||||
uint64_t low, high;
|
||||
#endif
|
||||
} float128;
|
||||
#define make_float128(high_, low_) ((float128) { .high = high_, .low = low_ })
|
||||
#define make_float128_init(high_, low_) { .high = high_, .low = low_ }
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point underflow tininess-detection mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_tininess_after_rounding = 0,
|
||||
float_tininess_before_rounding = 1
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point rounding mode.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_round_nearest_even = 0,
|
||||
float_round_down = 1,
|
||||
float_round_up = 2,
|
||||
float_round_to_zero = 3,
|
||||
float_round_ties_away = 4,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE floating-point exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_flag_invalid = 1,
|
||||
float_flag_divbyzero = 4,
|
||||
float_flag_overflow = 8,
|
||||
float_flag_underflow = 16,
|
||||
float_flag_inexact = 32,
|
||||
float_flag_input_denormal = 64,
|
||||
float_flag_output_denormal = 128
|
||||
};
|
||||
|
||||
typedef struct float_status {
|
||||
signed char float_detect_tininess;
|
||||
signed char float_rounding_mode;
|
||||
signed char float_exception_flags;
|
||||
signed char floatx80_rounding_precision;
|
||||
/* should denormalised results go to zero and set the inexact flag? */
|
||||
flag flush_to_zero;
|
||||
/* should denormalised inputs go to zero and set the input_denormal flag? */
|
||||
flag flush_inputs_to_zero;
|
||||
flag default_nan_mode;
|
||||
} float_status;
|
||||
|
||||
static inline void set_float_detect_tininess(int val STATUS_PARAM)
|
||||
{
|
||||
STATUS(float_detect_tininess) = val;
|
||||
}
|
||||
static inline void set_float_rounding_mode(int val STATUS_PARAM)
|
||||
{
|
||||
STATUS(float_rounding_mode) = val;
|
||||
}
|
||||
static inline void set_float_exception_flags(int val STATUS_PARAM)
|
||||
{
|
||||
STATUS(float_exception_flags) = val;
|
||||
}
|
||||
static inline void set_floatx80_rounding_precision(int val STATUS_PARAM)
|
||||
{
|
||||
STATUS(floatx80_rounding_precision) = val;
|
||||
}
|
||||
static inline void set_flush_to_zero(flag val STATUS_PARAM)
|
||||
{
|
||||
STATUS(flush_to_zero) = val;
|
||||
}
|
||||
static inline void set_flush_inputs_to_zero(flag val STATUS_PARAM)
|
||||
{
|
||||
STATUS(flush_inputs_to_zero) = val;
|
||||
}
|
||||
static inline void set_default_nan_mode(flag val STATUS_PARAM)
|
||||
{
|
||||
STATUS(default_nan_mode) = val;
|
||||
}
|
||||
static inline int get_float_detect_tininess(float_status *status)
|
||||
{
|
||||
return STATUS(float_detect_tininess);
|
||||
}
|
||||
static inline int get_float_rounding_mode(float_status *status)
|
||||
{
|
||||
return STATUS(float_rounding_mode);
|
||||
}
|
||||
static inline int get_float_exception_flags(float_status *status)
|
||||
{
|
||||
return STATUS(float_exception_flags);
|
||||
}
|
||||
static inline int get_floatx80_rounding_precision(float_status *status)
|
||||
{
|
||||
return STATUS(floatx80_rounding_precision);
|
||||
}
|
||||
static inline flag get_flush_to_zero(float_status *status)
|
||||
{
|
||||
return STATUS(flush_to_zero);
|
||||
}
|
||||
static inline flag get_flush_inputs_to_zero(float_status *status)
|
||||
{
|
||||
return STATUS(flush_inputs_to_zero);
|
||||
}
|
||||
static inline flag get_default_nan_mode(float_status *status)
|
||||
{
|
||||
return STATUS(default_nan_mode);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Routine to raise any or all of the software IEC/IEEE floating-point
|
||||
| exception flags.
|
||||
*----------------------------------------------------------------------------*/
|
||||
void float_raise( int8 flags STATUS_PARAM);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| If `a' is denormal and we are in flush-to-zero mode then set the
|
||||
| input-denormal exception and return zero. Otherwise just return the value.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 float32_squash_input_denormal(float32 a STATUS_PARAM);
|
||||
float64 float64_squash_input_denormal(float64 a STATUS_PARAM);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Options to indicate which negations to perform in float*_muladd()
|
||||
| Using these differs from negating an input or output before calling
|
||||
| the muladd function in that this means that a NaN doesn't have its
|
||||
| sign bit inverted before it is propagated.
|
||||
| We also support halving the result before rounding, as a special
|
||||
| case to support the ARM fused-sqrt-step instruction FRSQRTS.
|
||||
*----------------------------------------------------------------------------*/
|
||||
enum {
|
||||
float_muladd_negate_c = 1,
|
||||
float_muladd_negate_product = 2,
|
||||
float_muladd_negate_result = 4,
|
||||
float_muladd_halve_result = 8,
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE integer-to-floating-point conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 int32_to_float32(int32_t STATUS_PARAM);
|
||||
float64 int32_to_float64(int32_t STATUS_PARAM);
|
||||
float32 uint32_to_float32(uint32_t STATUS_PARAM);
|
||||
float64 uint32_to_float64(uint32_t STATUS_PARAM);
|
||||
floatx80 int32_to_floatx80(int32_t STATUS_PARAM);
|
||||
float128 int32_to_float128(int32_t STATUS_PARAM);
|
||||
float32 int64_to_float32(int64_t STATUS_PARAM);
|
||||
float32 uint64_to_float32(uint64_t STATUS_PARAM);
|
||||
float64 int64_to_float64(int64_t STATUS_PARAM);
|
||||
float64 uint64_to_float64(uint64_t STATUS_PARAM);
|
||||
floatx80 int64_to_floatx80(int64_t STATUS_PARAM);
|
||||
float128 int64_to_float128(int64_t STATUS_PARAM);
|
||||
float128 uint64_to_float128(uint64_t STATUS_PARAM);
|
||||
|
||||
/* We provide the int16 versions for symmetry of API with float-to-int */
|
||||
static inline float32 int16_to_float32(int16_t v STATUS_PARAM)
|
||||
{
|
||||
return int32_to_float32(v STATUS_VAR);
|
||||
}
|
||||
|
||||
static inline float32 uint16_to_float32(uint16_t v STATUS_PARAM)
|
||||
{
|
||||
return uint32_to_float32(v STATUS_VAR);
|
||||
}
|
||||
|
||||
static inline float64 int16_to_float64(int16_t v STATUS_PARAM)
|
||||
{
|
||||
return int32_to_float64(v STATUS_VAR);
|
||||
}
|
||||
|
||||
static inline float64 uint16_to_float64(uint16_t v STATUS_PARAM)
|
||||
{
|
||||
return uint32_to_float64(v STATUS_VAR);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software half-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float16 float32_to_float16( float32, flag STATUS_PARAM );
|
||||
float32 float16_to_float32( float16, flag STATUS_PARAM );
|
||||
float16 float64_to_float16(float64 a, flag ieee STATUS_PARAM);
|
||||
float64 float16_to_float64(float16 a, flag ieee STATUS_PARAM);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software half-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int float16_is_quiet_nan( float16 );
|
||||
int float16_is_signaling_nan( float16 );
|
||||
float16 float16_maybe_silence_nan( float16 );
|
||||
|
||||
static inline int float16_is_any_nan(float16 a)
|
||||
{
|
||||
return ((float16_val(a) & ~0x8000) > 0x7c00);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated half-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const float16 float16_default_nan;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE single-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int_fast16_t float32_to_int16(float32 STATUS_PARAM);
|
||||
uint_fast16_t float32_to_uint16(float32 STATUS_PARAM);
|
||||
int_fast16_t float32_to_int16_round_to_zero(float32 STATUS_PARAM);
|
||||
uint_fast16_t float32_to_uint16_round_to_zero(float32 STATUS_PARAM);
|
||||
int32 float32_to_int32( float32 STATUS_PARAM );
|
||||
int32 float32_to_int32_round_to_zero( float32 STATUS_PARAM );
|
||||
uint32 float32_to_uint32( float32 STATUS_PARAM );
|
||||
uint32 float32_to_uint32_round_to_zero( float32 STATUS_PARAM );
|
||||
int64 float32_to_int64( float32 STATUS_PARAM );
|
||||
uint64 float32_to_uint64(float32 STATUS_PARAM);
|
||||
uint64 float32_to_uint64_round_to_zero(float32 STATUS_PARAM);
|
||||
int64 float32_to_int64_round_to_zero( float32 STATUS_PARAM );
|
||||
float64 float32_to_float64( float32 STATUS_PARAM );
|
||||
floatx80 float32_to_floatx80( float32 STATUS_PARAM );
|
||||
float128 float32_to_float128( float32 STATUS_PARAM );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE single-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float32 float32_round_to_int( float32 STATUS_PARAM );
|
||||
float32 float32_add( float32, float32 STATUS_PARAM );
|
||||
float32 float32_sub( float32, float32 STATUS_PARAM );
|
||||
float32 float32_mul( float32, float32 STATUS_PARAM );
|
||||
float32 float32_div( float32, float32 STATUS_PARAM );
|
||||
float32 float32_rem( float32, float32 STATUS_PARAM );
|
||||
float32 float32_muladd(float32, float32, float32, int STATUS_PARAM);
|
||||
float32 float32_sqrt( float32 STATUS_PARAM );
|
||||
float32 float32_exp2( float32 STATUS_PARAM );
|
||||
float32 float32_log2( float32 STATUS_PARAM );
|
||||
int float32_eq( float32, float32 STATUS_PARAM );
|
||||
int float32_le( float32, float32 STATUS_PARAM );
|
||||
int float32_lt( float32, float32 STATUS_PARAM );
|
||||
int float32_unordered( float32, float32 STATUS_PARAM );
|
||||
int float32_eq_quiet( float32, float32 STATUS_PARAM );
|
||||
int float32_le_quiet( float32, float32 STATUS_PARAM );
|
||||
int float32_lt_quiet( float32, float32 STATUS_PARAM );
|
||||
int float32_unordered_quiet( float32, float32 STATUS_PARAM );
|
||||
int float32_compare( float32, float32 STATUS_PARAM );
|
||||
int float32_compare_quiet( float32, float32 STATUS_PARAM );
|
||||
float32 float32_min(float32, float32 STATUS_PARAM);
|
||||
float32 float32_max(float32, float32 STATUS_PARAM);
|
||||
float32 float32_minnum(float32, float32 STATUS_PARAM);
|
||||
float32 float32_maxnum(float32, float32 STATUS_PARAM);
|
||||
float32 float32_minnummag(float32, float32 STATUS_PARAM);
|
||||
float32 float32_maxnummag(float32, float32 STATUS_PARAM);
|
||||
int float32_is_quiet_nan( float32 );
|
||||
int float32_is_signaling_nan( float32 );
|
||||
float32 float32_maybe_silence_nan( float32 );
|
||||
float32 float32_scalbn( float32, int STATUS_PARAM );
|
||||
|
||||
static inline float32 float32_abs(float32 a)
|
||||
{
|
||||
/* Note that abs does *not* handle NaN specially, nor does
|
||||
* it flush denormal inputs to zero.
|
||||
*/
|
||||
return make_float32(float32_val(a) & 0x7fffffff);
|
||||
}
|
||||
|
||||
static inline float32 float32_chs(float32 a)
|
||||
{
|
||||
/* Note that chs does *not* handle NaN specially, nor does
|
||||
* it flush denormal inputs to zero.
|
||||
*/
|
||||
return make_float32(float32_val(a) ^ 0x80000000);
|
||||
}
|
||||
|
||||
static inline int float32_is_infinity(float32 a)
|
||||
{
|
||||
return (float32_val(a) & 0x7fffffff) == 0x7f800000;
|
||||
}
|
||||
|
||||
static inline int float32_is_neg(float32 a)
|
||||
{
|
||||
return float32_val(a) >> 31;
|
||||
}
|
||||
|
||||
static inline int float32_is_zero(float32 a)
|
||||
{
|
||||
return (float32_val(a) & 0x7fffffff) == 0;
|
||||
}
|
||||
|
||||
static inline int float32_is_any_nan(float32 a)
|
||||
{
|
||||
return ((float32_val(a) & ~(1 << 31)) > 0x7f800000UL);
|
||||
}
|
||||
|
||||
static inline int float32_is_zero_or_denormal(float32 a)
|
||||
{
|
||||
return (float32_val(a) & 0x7f800000) == 0;
|
||||
}
|
||||
|
||||
static inline float32 float32_set_sign(float32 a, int sign)
|
||||
{
|
||||
return make_float32((float32_val(a) & 0x7fffffff) | (sign << 31));
|
||||
}
|
||||
|
||||
#define float32_zero make_float32(0)
|
||||
#define float32_one make_float32(0x3f800000)
|
||||
#define float32_ln2 make_float32(0x3f317218)
|
||||
#define float32_pi make_float32(0x40490fdb)
|
||||
#define float32_half make_float32(0x3f000000)
|
||||
#define float32_infinity make_float32(0x7f800000)
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated single-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const float32 float32_default_nan;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE double-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int_fast16_t float64_to_int16(float64 STATUS_PARAM);
|
||||
uint_fast16_t float64_to_uint16(float64 STATUS_PARAM);
|
||||
int_fast16_t float64_to_int16_round_to_zero(float64 STATUS_PARAM);
|
||||
uint_fast16_t float64_to_uint16_round_to_zero(float64 STATUS_PARAM);
|
||||
int32 float64_to_int32( float64 STATUS_PARAM );
|
||||
int32 float64_to_int32_round_to_zero( float64 STATUS_PARAM );
|
||||
uint32 float64_to_uint32( float64 STATUS_PARAM );
|
||||
uint32 float64_to_uint32_round_to_zero( float64 STATUS_PARAM );
|
||||
int64 float64_to_int64( float64 STATUS_PARAM );
|
||||
int64 float64_to_int64_round_to_zero( float64 STATUS_PARAM );
|
||||
uint64 float64_to_uint64 (float64 a STATUS_PARAM);
|
||||
uint64 float64_to_uint64_round_to_zero (float64 a STATUS_PARAM);
|
||||
float32 float64_to_float32( float64 STATUS_PARAM );
|
||||
floatx80 float64_to_floatx80( float64 STATUS_PARAM );
|
||||
float128 float64_to_float128( float64 STATUS_PARAM );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float64 float64_round_to_int( float64 STATUS_PARAM );
|
||||
float64 float64_trunc_to_int( float64 STATUS_PARAM );
|
||||
float64 float64_add( float64, float64 STATUS_PARAM );
|
||||
float64 float64_sub( float64, float64 STATUS_PARAM );
|
||||
float64 float64_mul( float64, float64 STATUS_PARAM );
|
||||
float64 float64_div( float64, float64 STATUS_PARAM );
|
||||
float64 float64_rem( float64, float64 STATUS_PARAM );
|
||||
float64 float64_muladd(float64, float64, float64, int STATUS_PARAM);
|
||||
float64 float64_sqrt( float64 STATUS_PARAM );
|
||||
float64 float64_log2( float64 STATUS_PARAM );
|
||||
int float64_eq( float64, float64 STATUS_PARAM );
|
||||
int float64_le( float64, float64 STATUS_PARAM );
|
||||
int float64_lt( float64, float64 STATUS_PARAM );
|
||||
int float64_unordered( float64, float64 STATUS_PARAM );
|
||||
int float64_eq_quiet( float64, float64 STATUS_PARAM );
|
||||
int float64_le_quiet( float64, float64 STATUS_PARAM );
|
||||
int float64_lt_quiet( float64, float64 STATUS_PARAM );
|
||||
int float64_unordered_quiet( float64, float64 STATUS_PARAM );
|
||||
int float64_compare( float64, float64 STATUS_PARAM );
|
||||
int float64_compare_quiet( float64, float64 STATUS_PARAM );
|
||||
float64 float64_min(float64, float64 STATUS_PARAM);
|
||||
float64 float64_max(float64, float64 STATUS_PARAM);
|
||||
float64 float64_minnum(float64, float64 STATUS_PARAM);
|
||||
float64 float64_maxnum(float64, float64 STATUS_PARAM);
|
||||
float64 float64_minnummag(float64, float64 STATUS_PARAM);
|
||||
float64 float64_maxnummag(float64, float64 STATUS_PARAM);
|
||||
int float64_is_quiet_nan( float64 a );
|
||||
int float64_is_signaling_nan( float64 );
|
||||
float64 float64_maybe_silence_nan( float64 );
|
||||
float64 float64_scalbn( float64, int STATUS_PARAM );
|
||||
|
||||
static inline float64 float64_abs(float64 a)
|
||||
{
|
||||
/* Note that abs does *not* handle NaN specially, nor does
|
||||
* it flush denormal inputs to zero.
|
||||
*/
|
||||
return make_float64(float64_val(a) & 0x7fffffffffffffffLL);
|
||||
}
|
||||
|
||||
static inline float64 float64_chs(float64 a)
|
||||
{
|
||||
/* Note that chs does *not* handle NaN specially, nor does
|
||||
* it flush denormal inputs to zero.
|
||||
*/
|
||||
return make_float64(float64_val(a) ^ 0x8000000000000000LL);
|
||||
}
|
||||
|
||||
static inline int float64_is_infinity(float64 a)
|
||||
{
|
||||
return (float64_val(a) & 0x7fffffffffffffffLL ) == 0x7ff0000000000000LL;
|
||||
}
|
||||
|
||||
static inline int float64_is_neg(float64 a)
|
||||
{
|
||||
return float64_val(a) >> 63;
|
||||
}
|
||||
|
||||
static inline int float64_is_zero(float64 a)
|
||||
{
|
||||
return (float64_val(a) & 0x7fffffffffffffffLL) == 0;
|
||||
}
|
||||
|
||||
static inline int float64_is_any_nan(float64 a)
|
||||
{
|
||||
return ((float64_val(a) & ~(1ULL << 63)) > 0x7ff0000000000000ULL);
|
||||
}
|
||||
|
||||
static inline int float64_is_zero_or_denormal(float64 a)
|
||||
{
|
||||
return (float64_val(a) & 0x7ff0000000000000LL) == 0;
|
||||
}
|
||||
|
||||
static inline float64 float64_set_sign(float64 a, int sign)
|
||||
{
|
||||
return make_float64((float64_val(a) & 0x7fffffffffffffffULL)
|
||||
| ((int64_t)sign << 63));
|
||||
}
|
||||
|
||||
#define float64_zero make_float64(0)
|
||||
#define float64_one make_float64(0x3ff0000000000000LL)
|
||||
#define float64_ln2 make_float64(0x3fe62e42fefa39efLL)
|
||||
#define float64_pi make_float64(0x400921fb54442d18LL)
|
||||
#define float64_half make_float64(0x3fe0000000000000LL)
|
||||
#define float64_infinity make_float64(0x7ff0000000000000LL)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated double-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const float64 float64_default_nan;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE extended double-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 floatx80_to_int32( floatx80 STATUS_PARAM );
|
||||
int32 floatx80_to_int32_round_to_zero( floatx80 STATUS_PARAM );
|
||||
int64 floatx80_to_int64( floatx80 STATUS_PARAM );
|
||||
int64 floatx80_to_int64_round_to_zero( floatx80 STATUS_PARAM );
|
||||
float32 floatx80_to_float32( floatx80 STATUS_PARAM );
|
||||
float64 floatx80_to_float64( floatx80 STATUS_PARAM );
|
||||
float128 floatx80_to_float128( floatx80 STATUS_PARAM );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE extended double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
floatx80 floatx80_round_to_int( floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_add( floatx80, floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_sub( floatx80, floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_mul( floatx80, floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_div( floatx80, floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_rem( floatx80, floatx80 STATUS_PARAM );
|
||||
floatx80 floatx80_sqrt( floatx80 STATUS_PARAM );
|
||||
int floatx80_eq( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_le( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_unordered( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_eq_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_unordered_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
|
||||
int floatx80_is_quiet_nan( floatx80 );
|
||||
int floatx80_is_signaling_nan( floatx80 );
|
||||
floatx80 floatx80_maybe_silence_nan( floatx80 );
|
||||
floatx80 floatx80_scalbn( floatx80, int STATUS_PARAM );
|
||||
|
||||
static inline floatx80 floatx80_abs(floatx80 a)
|
||||
{
|
||||
a.high &= 0x7fff;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline floatx80 floatx80_chs(floatx80 a)
|
||||
{
|
||||
a.high ^= 0x8000;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_infinity(floatx80 a)
|
||||
{
|
||||
return (a.high & 0x7fff) == 0x7fff && a.low == 0x8000000000000000LL;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_neg(floatx80 a)
|
||||
{
|
||||
return a.high >> 15;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_zero(floatx80 a)
|
||||
{
|
||||
return (a.high & 0x7fff) == 0 && a.low == 0;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_zero_or_denormal(floatx80 a)
|
||||
{
|
||||
return (a.high & 0x7fff) == 0;
|
||||
}
|
||||
|
||||
static inline int floatx80_is_any_nan(floatx80 a)
|
||||
{
|
||||
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
|
||||
}
|
||||
|
||||
#define floatx80_zero make_floatx80(0x0000, 0x0000000000000000LL)
|
||||
#define floatx80_one make_floatx80(0x3fff, 0x8000000000000000LL)
|
||||
#define floatx80_ln2 make_floatx80(0x3ffe, 0xb17217f7d1cf79acLL)
|
||||
#define floatx80_pi make_floatx80(0x4000, 0xc90fdaa22168c235LL)
|
||||
#define floatx80_half make_floatx80(0x3ffe, 0x8000000000000000LL)
|
||||
#define floatx80_infinity make_floatx80(0x7fff, 0x8000000000000000LL)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated extended double-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const floatx80 floatx80_default_nan;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE quadruple-precision conversion routines.
|
||||
*----------------------------------------------------------------------------*/
|
||||
int32 float128_to_int32( float128 STATUS_PARAM );
|
||||
int32 float128_to_int32_round_to_zero( float128 STATUS_PARAM );
|
||||
int64 float128_to_int64( float128 STATUS_PARAM );
|
||||
int64 float128_to_int64_round_to_zero( float128 STATUS_PARAM );
|
||||
float32 float128_to_float32( float128 STATUS_PARAM );
|
||||
float64 float128_to_float64( float128 STATUS_PARAM );
|
||||
floatx80 float128_to_floatx80( float128 STATUS_PARAM );
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Software IEC/IEEE quadruple-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
float128 float128_round_to_int( float128 STATUS_PARAM );
|
||||
float128 float128_add( float128, float128 STATUS_PARAM );
|
||||
float128 float128_sub( float128, float128 STATUS_PARAM );
|
||||
float128 float128_mul( float128, float128 STATUS_PARAM );
|
||||
float128 float128_div( float128, float128 STATUS_PARAM );
|
||||
float128 float128_rem( float128, float128 STATUS_PARAM );
|
||||
float128 float128_sqrt( float128 STATUS_PARAM );
|
||||
int float128_eq( float128, float128 STATUS_PARAM );
|
||||
int float128_le( float128, float128 STATUS_PARAM );
|
||||
int float128_lt( float128, float128 STATUS_PARAM );
|
||||
int float128_unordered( float128, float128 STATUS_PARAM );
|
||||
int float128_eq_quiet( float128, float128 STATUS_PARAM );
|
||||
int float128_le_quiet( float128, float128 STATUS_PARAM );
|
||||
int float128_lt_quiet( float128, float128 STATUS_PARAM );
|
||||
int float128_unordered_quiet( float128, float128 STATUS_PARAM );
|
||||
int float128_compare( float128, float128 STATUS_PARAM );
|
||||
int float128_compare_quiet( float128, float128 STATUS_PARAM );
|
||||
int float128_is_quiet_nan( float128 );
|
||||
int float128_is_signaling_nan( float128 );
|
||||
float128 float128_maybe_silence_nan( float128 );
|
||||
float128 float128_scalbn( float128, int STATUS_PARAM );
|
||||
|
||||
static inline float128 float128_abs(float128 a)
|
||||
{
|
||||
a.high &= 0x7fffffffffffffffLL;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline float128 float128_chs(float128 a)
|
||||
{
|
||||
a.high ^= 0x8000000000000000LL;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline int float128_is_infinity(float128 a)
|
||||
{
|
||||
return (a.high & 0x7fffffffffffffffLL) == 0x7fff000000000000LL && a.low == 0;
|
||||
}
|
||||
|
||||
static inline int float128_is_neg(float128 a)
|
||||
{
|
||||
return a.high >> 63;
|
||||
}
|
||||
|
||||
static inline int float128_is_zero(float128 a)
|
||||
{
|
||||
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
|
||||
}
|
||||
|
||||
static inline int float128_is_zero_or_denormal(float128 a)
|
||||
{
|
||||
return (a.high & 0x7fff000000000000LL) == 0;
|
||||
}
|
||||
|
||||
static inline int float128_is_any_nan(float128 a)
|
||||
{
|
||||
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
|
||||
((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
|
||||
}
|
||||
|
||||
#define float128_zero make_float128(0, 0)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The pattern for a default generated quadruple-precision NaN.
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern const float128 float128_default_nan;
|
||||
|
||||
#endif /* !SOFTFLOAT_H */
|
||||
201
qemu/include/glib-compat.h
Normal file
201
qemu/include/glib-compat.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* GLIB Compatibility Functions
|
||||
*
|
||||
* Copyright IBM, Corp. 2013
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
* Michael Tokarev <mjt@tls.msk.ru>
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* 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 QEMU_GLIB_COMPAT_H
|
||||
#define QEMU_GLIB_COMPAT_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
/* GLIB version compatibility flags */
|
||||
#if !GLIB_CHECK_VERSION(2, 26, 0)
|
||||
#define G_TIME_SPAN_SECOND (G_GINT64_CONSTANT(1000000))
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 14, 0)
|
||||
static inline guint g_timeout_add_seconds(guint interval, GSourceFunc function,
|
||||
gpointer data)
|
||||
{
|
||||
return g_timeout_add(interval * 1000, function, data);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 28, 0)
|
||||
static inline gint64 g_get_monotonic_time(void)
|
||||
{
|
||||
/* g_get_monotonic_time() is best-effort so we can use the wall clock as a
|
||||
* fallback.
|
||||
*/
|
||||
|
||||
GTimeVal time;
|
||||
g_get_current_time(&time);
|
||||
|
||||
return time.tv_sec * G_TIME_SPAN_SECOND + time.tv_usec;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 16, 0)
|
||||
static inline int g_strcmp0(const char *str1, const char *str2)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (!str1) {
|
||||
result = -(str1 != str2);
|
||||
} else if (!str2) {
|
||||
result = (str1 != str2);
|
||||
} else {
|
||||
result = strcmp(str1, str2);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/*
|
||||
* g_poll has a problem on Windows when using
|
||||
* timeouts < 10ms, so use wrapper.
|
||||
*/
|
||||
#define g_poll(fds, nfds, timeout) g_poll_fixed(fds, nfds, timeout)
|
||||
gint g_poll_fixed(GPollFD *fds, guint nfds, gint timeout);
|
||||
#elif !GLIB_CHECK_VERSION(2, 20, 0)
|
||||
/*
|
||||
* Glib before 2.20.0 doesn't implement g_poll, so wrap it to compile properly
|
||||
* on older systems.
|
||||
*/
|
||||
static inline gint g_poll(GPollFD *fds, guint nfds, gint timeout)
|
||||
{
|
||||
GMainContext *ctx = g_main_context_default();
|
||||
return g_main_context_get_poll_func(ctx)(fds, nfds, timeout);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2, 31, 0)
|
||||
/* before glib-2.31, GMutex and GCond was dynamic-only (there was a separate
|
||||
* GStaticMutex, but it didn't work with condition variables).
|
||||
*
|
||||
* Our implementation uses GOnce to fake a static implementation that does
|
||||
* not require separate initialization.
|
||||
* We need to rename the types to avoid passing our CompatGMutex/CompatGCond
|
||||
* by mistake to a function that expects GMutex/GCond. However, for ease
|
||||
* of use we keep the GLib function names. GLib uses macros for the
|
||||
* implementation, we use inline functions instead and undefine the macros.
|
||||
*/
|
||||
|
||||
typedef struct CompatGMutex {
|
||||
GOnce once;
|
||||
} CompatGMutex;
|
||||
|
||||
typedef struct CompatGCond {
|
||||
GOnce once;
|
||||
} CompatGCond;
|
||||
|
||||
static inline gpointer do_g_mutex_new(gpointer unused)
|
||||
{
|
||||
return (gpointer) g_mutex_new();
|
||||
}
|
||||
|
||||
static inline void g_mutex_init(CompatGMutex *mutex)
|
||||
{
|
||||
mutex->once = (GOnce) G_ONCE_INIT;
|
||||
}
|
||||
|
||||
static inline void g_mutex_clear(CompatGMutex *mutex)
|
||||
{
|
||||
assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
|
||||
if (mutex->once.retval) {
|
||||
g_mutex_free((GMutex *) mutex->once.retval);
|
||||
}
|
||||
mutex->once = (GOnce) G_ONCE_INIT;
|
||||
}
|
||||
|
||||
static inline void (g_mutex_lock)(CompatGMutex *mutex)
|
||||
{
|
||||
g_once(&mutex->once, do_g_mutex_new, NULL);
|
||||
g_mutex_lock((GMutex *) mutex->once.retval);
|
||||
}
|
||||
#undef g_mutex_lock
|
||||
|
||||
static inline gboolean (g_mutex_trylock)(CompatGMutex *mutex)
|
||||
{
|
||||
g_once(&mutex->once, do_g_mutex_new, NULL);
|
||||
return g_mutex_trylock((GMutex *) mutex->once.retval);
|
||||
}
|
||||
#undef g_mutex_trylock
|
||||
|
||||
|
||||
static inline void (g_mutex_unlock)(CompatGMutex *mutex)
|
||||
{
|
||||
g_mutex_unlock((GMutex *) mutex->once.retval);
|
||||
}
|
||||
#undef g_mutex_unlock
|
||||
|
||||
static inline gpointer do_g_cond_new(gpointer unused)
|
||||
{
|
||||
return (gpointer) g_cond_new();
|
||||
}
|
||||
|
||||
static inline void g_cond_init(CompatGCond *cond)
|
||||
{
|
||||
cond->once = (GOnce) G_ONCE_INIT;
|
||||
}
|
||||
|
||||
static inline void g_cond_clear(CompatGCond *cond)
|
||||
{
|
||||
assert(cond->once.status != G_ONCE_STATUS_PROGRESS);
|
||||
if (cond->once.retval) {
|
||||
g_cond_free((GCond *) cond->once.retval);
|
||||
}
|
||||
cond->once = (GOnce) G_ONCE_INIT;
|
||||
}
|
||||
|
||||
static inline void (g_cond_wait)(CompatGCond *cond, CompatGMutex *mutex)
|
||||
{
|
||||
assert(mutex->once.status != G_ONCE_STATUS_PROGRESS);
|
||||
g_once(&cond->once, do_g_cond_new, NULL);
|
||||
g_cond_wait((GCond *) cond->once.retval, (GMutex *) mutex->once.retval);
|
||||
}
|
||||
#undef g_cond_wait
|
||||
|
||||
static inline void (g_cond_broadcast)(CompatGCond *cond)
|
||||
{
|
||||
g_once(&cond->once, do_g_cond_new, NULL);
|
||||
g_cond_broadcast((GCond *) cond->once.retval);
|
||||
}
|
||||
#undef g_cond_broadcast
|
||||
|
||||
static inline void (g_cond_signal)(CompatGCond *cond)
|
||||
{
|
||||
g_once(&cond->once, do_g_cond_new, NULL);
|
||||
g_cond_signal((GCond *) cond->once.retval);
|
||||
}
|
||||
#undef g_cond_signal
|
||||
|
||||
|
||||
/* before 2.31 there was no g_thread_new() */
|
||||
static inline GThread *g_thread_new(const char *name,
|
||||
GThreadFunc func, gpointer data)
|
||||
{
|
||||
GThread *thread = g_thread_create(func, data, TRUE, NULL);
|
||||
if (!thread) {
|
||||
g_error("creating thread");
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
#else
|
||||
#define CompatGMutex GMutex
|
||||
#define CompatGCond GCond
|
||||
#endif /* glib 2.31 */
|
||||
|
||||
#endif
|
||||
82
qemu/include/hw/arm/arm.h
Normal file
82
qemu/include/hw/arm/arm.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Misc ARM declarations
|
||||
*
|
||||
* Copyright (c) 2006 CodeSourcery.
|
||||
* Written by Paul Brook
|
||||
*
|
||||
* This code is licensed under the LGPL.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef ARM_MISC_H
|
||||
#define ARM_MISC_H 1
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/irq.h"
|
||||
|
||||
void tosa_machine_init(struct uc_struct *uc);
|
||||
void machvirt_machine_init(struct uc_struct *uc); // ARM64
|
||||
|
||||
/* armv7m.c */
|
||||
qemu_irq *armv7m_init(MemoryRegion *system_memory,
|
||||
int flash_size, int sram_size,
|
||||
const char *kernel_filename, const char *cpu_model);
|
||||
|
||||
/* arm_boot.c */
|
||||
struct arm_boot_info {
|
||||
uint64_t ram_size;
|
||||
const char *kernel_filename;
|
||||
const char *kernel_cmdline;
|
||||
const char *initrd_filename;
|
||||
const char *dtb_filename;
|
||||
hwaddr loader_start;
|
||||
/* multicore boards that use the default secondary core boot functions
|
||||
* need to put the address of the secondary boot code, the boot reg,
|
||||
* and the GIC address in the next 3 values, respectively. boards that
|
||||
* have their own boot functions can use these values as they want.
|
||||
*/
|
||||
hwaddr smp_loader_start;
|
||||
hwaddr smp_bootreg_addr;
|
||||
hwaddr gic_cpu_if_addr;
|
||||
int nb_cpus;
|
||||
int board_id;
|
||||
int (*atag_board)(const struct arm_boot_info *info, void *p);
|
||||
/* multicore boards that use the default secondary core boot functions
|
||||
* can ignore these two function calls. If the default functions won't
|
||||
* work, then write_secondary_boot() should write a suitable blob of
|
||||
* code mimicking the secondary CPU startup process used by the board's
|
||||
* boot loader/boot ROM code, and secondary_cpu_reset_hook() should
|
||||
* perform any necessary CPU reset handling and set the PC for the
|
||||
* secondary CPUs to point at this boot blob.
|
||||
*/
|
||||
void (*write_secondary_boot)(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info);
|
||||
void (*secondary_cpu_reset_hook)(ARMCPU *cpu,
|
||||
const struct arm_boot_info *info);
|
||||
/* if a board is able to create a dtb without a dtb file then it
|
||||
* sets get_dtb. This will only be used if no dtb file is provided
|
||||
* by the user. On success, sets *size to the length of the created
|
||||
* dtb, and returns a pointer to it. (The caller must free this memory
|
||||
* with g_free() when it has finished with it.) On failure, returns NULL.
|
||||
*/
|
||||
void *(*get_dtb)(const struct arm_boot_info *info, int *size);
|
||||
/* if a board needs to be able to modify a device tree provided by
|
||||
* the user it should implement this hook.
|
||||
*/
|
||||
void (*modify_dtb)(const struct arm_boot_info *info, void *fdt);
|
||||
/* Used internally by arm_boot.c */
|
||||
int is_linux;
|
||||
hwaddr initrd_start;
|
||||
hwaddr initrd_size;
|
||||
hwaddr entry;
|
||||
};
|
||||
void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info);
|
||||
|
||||
/* Multiplication factor to convert from system clock ticks to qemu timer
|
||||
ticks. */
|
||||
extern int system_clock_scale;
|
||||
|
||||
void arm_cpu_register_types(void *opaque);
|
||||
void aarch64_cpu_register_types(void *opaque);
|
||||
|
||||
#endif /* !ARM_MISC_H */
|
||||
82
qemu/include/hw/boards.h
Normal file
82
qemu/include/hw/boards.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/* Declarations for use by board files for creating devices. */
|
||||
|
||||
#ifndef HW_BOARDS_H
|
||||
#define HW_BOARDS_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "sysemu/accel.h"
|
||||
#include "hw/qdev.h"
|
||||
#include "qom/object.h"
|
||||
#include "uc_priv.h"
|
||||
|
||||
typedef void QEMUMachineInitFunc(struct uc_struct *uc, MachineState *ms);
|
||||
|
||||
typedef void QEMUMachineResetFunc(void);
|
||||
|
||||
struct QEMUMachine {
|
||||
const char *family; /* NULL iff @name identifies a standalone machtype */
|
||||
const char *name;
|
||||
QEMUMachineInitFunc *init;
|
||||
QEMUMachineResetFunc *reset;
|
||||
int max_cpus;
|
||||
int is_default;
|
||||
int arch;
|
||||
};
|
||||
|
||||
void memory_region_allocate_system_memory(MemoryRegion *mr, Object *owner,
|
||||
const char *name,
|
||||
uint64_t ram_size);
|
||||
|
||||
void qemu_register_machine(struct uc_struct *uc, QEMUMachine *m, const char *type_machine,
|
||||
void (*init)(struct uc_struct *uc, ObjectClass *oc, void *data));
|
||||
|
||||
#define TYPE_MACHINE_SUFFIX "-machine"
|
||||
#define TYPE_MACHINE "machine"
|
||||
#undef MACHINE /* BSD defines it and QEMU does not use it */
|
||||
#define MACHINE(uc, obj) \
|
||||
OBJECT_CHECK(uc, MachineState, (obj), TYPE_MACHINE)
|
||||
#define MACHINE_GET_CLASS(uc, obj) \
|
||||
OBJECT_GET_CLASS(uc, MachineClass, (obj), TYPE_MACHINE)
|
||||
#define MACHINE_CLASS(uc, klass) \
|
||||
OBJECT_CLASS_CHECK(uc, MachineClass, (klass), TYPE_MACHINE)
|
||||
|
||||
MachineClass *find_default_machine(struct uc_struct *uc, int arch);
|
||||
|
||||
/**
|
||||
* MachineClass:
|
||||
* @qemu_machine: #QEMUMachine
|
||||
*/
|
||||
struct MachineClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
const char *family; /* NULL iff @name identifies a standalone machtype */
|
||||
const char *name;
|
||||
|
||||
void (*init)(struct uc_struct *uc, MachineState *state);
|
||||
void (*reset)(void);
|
||||
|
||||
int max_cpus;
|
||||
int is_default;
|
||||
int arch;
|
||||
};
|
||||
|
||||
/**
|
||||
* MachineState:
|
||||
*/
|
||||
struct MachineState {
|
||||
/*< private >*/
|
||||
Object parent_obj;
|
||||
|
||||
/*< public >*/
|
||||
ram_addr_t ram_size;
|
||||
ram_addr_t maxram_size;
|
||||
const char *cpu_model;
|
||||
struct uc_struct *uc;
|
||||
AccelState *accelerator;
|
||||
};
|
||||
|
||||
void machine_register_types(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
79
qemu/include/hw/cpu/icc_bus.h
Normal file
79
qemu/include/hw/cpu/icc_bus.h
Normal file
@@ -0,0 +1,79 @@
|
||||
/* icc_bus.h
|
||||
* emulate x86 ICC (Interrupt Controller Communications) bus
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc
|
||||
*
|
||||
* Authors:
|
||||
* Igor Mammedov <imammedo@redhat.com>
|
||||
*
|
||||
* 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 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 ICC_BUS_H
|
||||
#define ICC_BUS_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
#define TYPE_ICC_BUS "icc-bus"
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
/**
|
||||
* ICCBus:
|
||||
*
|
||||
* ICC bus
|
||||
*/
|
||||
typedef struct ICCBus {
|
||||
/*< private >*/
|
||||
BusState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
MemoryRegion *apic_address_space;
|
||||
} ICCBus;
|
||||
|
||||
#define ICC_BUS(uc, obj) OBJECT_CHECK(uc, ICCBus, (obj), TYPE_ICC_BUS)
|
||||
|
||||
/**
|
||||
* ICCDevice:
|
||||
*
|
||||
* ICC device
|
||||
*/
|
||||
typedef struct ICCDevice {
|
||||
/*< private >*/
|
||||
DeviceState qdev;
|
||||
/*< public >*/
|
||||
} ICCDevice;
|
||||
|
||||
/**
|
||||
* ICCDeviceClass:
|
||||
* @init: Initialization callback for derived classes.
|
||||
*
|
||||
* ICC device class
|
||||
*/
|
||||
typedef struct ICCDeviceClass {
|
||||
/*< private >*/
|
||||
DeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DeviceRealize realize;
|
||||
} ICCDeviceClass;
|
||||
|
||||
#define TYPE_ICC_DEVICE "icc-device"
|
||||
#define ICC_DEVICE_CLASS(uc, klass) \
|
||||
OBJECT_CLASS_CHECK(uc, ICCDeviceClass, (klass), TYPE_ICC_DEVICE)
|
||||
|
||||
void icc_bus_register_types(struct uc_struct *uc);
|
||||
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
#endif
|
||||
42
qemu/include/hw/hw.h
Normal file
42
qemu/include/hw/hw.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/* Declarations for use by hardware emulation. */
|
||||
#ifndef QEMU_HW_H
|
||||
#define QEMU_HW_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY) && !defined(NEED_CPU_H)
|
||||
#include "exec/cpu-common.h"
|
||||
#endif
|
||||
|
||||
#include "exec/ioport.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qemu/log.h"
|
||||
|
||||
#ifdef NEED_CPU_H
|
||||
#if TARGET_LONG_BITS == 64
|
||||
#define qemu_put_betl qemu_put_be64
|
||||
#define qemu_get_betl qemu_get_be64
|
||||
#define qemu_put_betls qemu_put_be64s
|
||||
#define qemu_get_betls qemu_get_be64s
|
||||
#define qemu_put_sbetl qemu_put_sbe64
|
||||
#define qemu_get_sbetl qemu_get_sbe64
|
||||
#define qemu_put_sbetls qemu_put_sbe64s
|
||||
#define qemu_get_sbetls qemu_get_sbe64s
|
||||
#else
|
||||
#define qemu_put_betl qemu_put_be32
|
||||
#define qemu_get_betl qemu_get_be32
|
||||
#define qemu_put_betls qemu_put_be32s
|
||||
#define qemu_get_betls qemu_get_be32s
|
||||
#define qemu_put_sbetl qemu_put_sbe32
|
||||
#define qemu_get_sbetl qemu_get_sbe32
|
||||
#define qemu_put_sbetls qemu_put_sbe32s
|
||||
#define qemu_get_sbetls qemu_get_sbe32s
|
||||
#endif
|
||||
#endif
|
||||
|
||||
typedef void QEMUResetHandler(void *opaque);
|
||||
|
||||
void qemu_register_reset(QEMUResetHandler *func, void *opaque);
|
||||
void qemu_unregister_reset(QEMUResetHandler *func, void *opaque);
|
||||
|
||||
#endif
|
||||
29
qemu/include/hw/i386/apic.h
Normal file
29
qemu/include/hw/i386/apic.h
Normal file
@@ -0,0 +1,29 @@
|
||||
#ifndef APIC_H
|
||||
#define APIC_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
/* apic.c */
|
||||
int apic_accept_pic_intr(DeviceState *s);
|
||||
int apic_get_interrupt(DeviceState *s);
|
||||
void cpu_set_apic_base(struct uc_struct *uc, DeviceState *s, uint64_t val);
|
||||
uint64_t cpu_get_apic_base(struct uc_struct *uc, DeviceState *s);
|
||||
void cpu_set_apic_tpr(struct uc_struct *uc, DeviceState *s, uint8_t val);
|
||||
uint8_t cpu_get_apic_tpr(struct uc_struct *uc, DeviceState *s);
|
||||
void apic_init_reset(struct uc_struct *uc, DeviceState *s);
|
||||
void apic_sipi(DeviceState *s);
|
||||
void apic_handle_tpr_access_report(DeviceState *d, target_ulong ip,
|
||||
TPRAccess access);
|
||||
void apic_poll_irq(DeviceState *d);
|
||||
void apic_designate_bsp(struct uc_struct *uc, DeviceState *d);
|
||||
|
||||
/* pc.c */
|
||||
DeviceState *cpu_get_current_apic(struct uc_struct *uc);
|
||||
|
||||
/* cpu.c */
|
||||
bool cpu_is_bsp(X86CPU *cpu);
|
||||
|
||||
void apic_register_types(struct uc_struct *uc);
|
||||
void apic_common_register_types(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
147
qemu/include/hw/i386/apic_internal.h
Normal file
147
qemu/include/hw/i386/apic_internal.h
Normal file
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* APIC support - internal interfaces
|
||||
*
|
||||
* Copyright (c) 2004-2005 Fabrice Bellard
|
||||
* Copyright (c) 2011 Jan Kiszka, Siemens AG
|
||||
*
|
||||
* 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 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 QEMU_APIC_INTERNAL_H
|
||||
#define QEMU_APIC_INTERNAL_H
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "hw/cpu/icc_bus.h"
|
||||
#include "qemu/timer.h"
|
||||
|
||||
/* APIC Local Vector Table */
|
||||
#define APIC_LVT_TIMER 0
|
||||
#define APIC_LVT_THERMAL 1
|
||||
#define APIC_LVT_PERFORM 2
|
||||
#define APIC_LVT_LINT0 3
|
||||
#define APIC_LVT_LINT1 4
|
||||
#define APIC_LVT_ERROR 5
|
||||
#define APIC_LVT_NB 6
|
||||
|
||||
/* APIC delivery modes */
|
||||
#define APIC_DM_FIXED 0
|
||||
#define APIC_DM_LOWPRI 1
|
||||
#define APIC_DM_SMI 2
|
||||
#define APIC_DM_NMI 4
|
||||
#define APIC_DM_INIT 5
|
||||
#define APIC_DM_SIPI 6
|
||||
#define APIC_DM_EXTINT 7
|
||||
|
||||
/* APIC destination mode */
|
||||
#define APIC_DESTMODE_FLAT 0xf
|
||||
#define APIC_DESTMODE_CLUSTER 1
|
||||
|
||||
#define APIC_TRIGGER_EDGE 0
|
||||
#define APIC_TRIGGER_LEVEL 1
|
||||
|
||||
#define APIC_LVT_TIMER_PERIODIC (1<<17)
|
||||
#define APIC_LVT_MASKED (1<<16)
|
||||
#define APIC_LVT_LEVEL_TRIGGER (1<<15)
|
||||
#define APIC_LVT_REMOTE_IRR (1<<14)
|
||||
#define APIC_INPUT_POLARITY (1<<13)
|
||||
#define APIC_SEND_PENDING (1<<12)
|
||||
|
||||
#define ESR_ILLEGAL_ADDRESS (1 << 7)
|
||||
|
||||
#define APIC_SV_DIRECTED_IO (1<<12)
|
||||
#define APIC_SV_ENABLE (1<<8)
|
||||
|
||||
#define VAPIC_ENABLE_BIT 0
|
||||
#define VAPIC_ENABLE_MASK (1 << VAPIC_ENABLE_BIT)
|
||||
|
||||
#define MAX_APICS 255
|
||||
|
||||
typedef struct APICCommonState APICCommonState;
|
||||
|
||||
#define TYPE_APIC_COMMON "apic-common"
|
||||
#define APIC_COMMON(uc, obj) \
|
||||
OBJECT_CHECK(uc, APICCommonState, (obj), TYPE_APIC_COMMON)
|
||||
#define APIC_COMMON_CLASS(uc, klass) \
|
||||
OBJECT_CLASS_CHECK(uc, APICCommonClass, (klass), TYPE_APIC_COMMON)
|
||||
#define APIC_COMMON_GET_CLASS(uc, obj) \
|
||||
OBJECT_GET_CLASS(uc, APICCommonClass, (obj), TYPE_APIC_COMMON)
|
||||
|
||||
typedef struct APICCommonClass
|
||||
{
|
||||
ICCDeviceClass parent_class;
|
||||
|
||||
DeviceRealize realize;
|
||||
void (*set_base)(APICCommonState *s, uint64_t val);
|
||||
void (*set_tpr)(APICCommonState *s, uint8_t val);
|
||||
uint8_t (*get_tpr)(APICCommonState *s);
|
||||
void (*enable_tpr_reporting)(APICCommonState *s, bool enable);
|
||||
void (*vapic_base_update)(APICCommonState *s);
|
||||
void (*external_nmi)(APICCommonState *s);
|
||||
void (*pre_save)(APICCommonState *s);
|
||||
void (*post_load)(APICCommonState *s);
|
||||
void (*reset)(APICCommonState *s);
|
||||
} APICCommonClass;
|
||||
|
||||
struct APICCommonState {
|
||||
ICCDevice busdev;
|
||||
|
||||
MemoryRegion io_memory;
|
||||
X86CPU *cpu;
|
||||
uint32_t apicbase;
|
||||
uint8_t id;
|
||||
uint8_t version;
|
||||
uint8_t arb_id;
|
||||
uint8_t tpr;
|
||||
uint32_t spurious_vec;
|
||||
uint8_t log_dest;
|
||||
uint8_t dest_mode;
|
||||
uint32_t isr[8]; /* in service register */
|
||||
uint32_t tmr[8]; /* trigger mode register */
|
||||
uint32_t irr[8]; /* interrupt request register */
|
||||
uint32_t lvt[APIC_LVT_NB];
|
||||
uint32_t esr; /* error register */
|
||||
uint32_t icr[2];
|
||||
|
||||
uint32_t divide_conf;
|
||||
int count_shift;
|
||||
uint32_t initial_count;
|
||||
int64_t initial_count_load_time;
|
||||
int64_t next_time;
|
||||
int idx;
|
||||
QEMUTimer *timer;
|
||||
int64_t timer_expiry;
|
||||
int sipi_vector;
|
||||
int wait_for_sipi;
|
||||
|
||||
uint32_t vapic_control;
|
||||
DeviceState *vapic;
|
||||
hwaddr vapic_paddr; /* note: persistence via kvmvapic */
|
||||
};
|
||||
|
||||
typedef struct VAPICState {
|
||||
uint8_t tpr;
|
||||
uint8_t isr;
|
||||
uint8_t zero;
|
||||
uint8_t irr;
|
||||
uint8_t enabled;
|
||||
} QEMU_PACKED VAPICState;
|
||||
|
||||
extern bool apic_report_tpr_access;
|
||||
|
||||
bool apic_next_timer(APICCommonState *s, int64_t current_time);
|
||||
void apic_enable_vapic(struct uc_struct *uc, DeviceState *d, hwaddr paddr);
|
||||
|
||||
void vapic_report_tpr_access(DeviceState *dev, CPUState *cpu, target_ulong ip,
|
||||
TPRAccess access);
|
||||
|
||||
#endif /* !QEMU_APIC_INTERNAL_H */
|
||||
52
qemu/include/hw/i386/pc.h
Normal file
52
qemu/include/hw/i386/pc.h
Normal file
@@ -0,0 +1,52 @@
|
||||
#ifndef HW_PC_H
|
||||
#define HW_PC_H
|
||||
|
||||
#include "hw/boards.h"
|
||||
|
||||
/**
|
||||
* PCMachineState:
|
||||
*/
|
||||
struct PCMachineState {
|
||||
/*< private >*/
|
||||
MachineState parent_obj;
|
||||
|
||||
uint64_t max_ram_below_4g;
|
||||
};
|
||||
|
||||
#define PC_MACHINE_MAX_RAM_BELOW_4G "max-ram-below-4g"
|
||||
|
||||
/**
|
||||
* PCMachineClass:
|
||||
*/
|
||||
struct PCMachineClass {
|
||||
/*< private >*/
|
||||
MachineClass parent_class;
|
||||
};
|
||||
|
||||
typedef struct PCMachineState PCMachineState;
|
||||
typedef struct PCMachineClass PCMachineClass;
|
||||
|
||||
#define TYPE_PC_MACHINE "generic-pc-machine"
|
||||
#define PC_MACHINE(uc, obj) \
|
||||
OBJECT_CHECK(uc, PCMachineState, (obj), TYPE_PC_MACHINE)
|
||||
#define PC_MACHINE_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(PCMachineClass, (obj), TYPE_PC_MACHINE)
|
||||
#define PC_MACHINE_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(PCMachineClass, (klass), TYPE_PC_MACHINE)
|
||||
|
||||
void pc_cpus_init(struct uc_struct *uc, const char *cpu_model);
|
||||
|
||||
FWCfgState *pc_memory_init(MachineState *machine,
|
||||
MemoryRegion *system_memory,
|
||||
ram_addr_t begin,
|
||||
MemoryRegion **ram_memory);
|
||||
typedef void (*cpu_set_smm_t)(int smm, void *arg);
|
||||
void cpu_smm_register(cpu_set_smm_t callback, void *arg);
|
||||
|
||||
void pc_machine_register_types(struct uc_struct *uc);
|
||||
void x86_cpu_register_types(struct uc_struct *uc);
|
||||
|
||||
#define PC_DEFAULT_MACHINE_OPTIONS \
|
||||
.max_cpus = 255
|
||||
|
||||
#endif
|
||||
64
qemu/include/hw/irq.h
Normal file
64
qemu/include/hw/irq.h
Normal file
@@ -0,0 +1,64 @@
|
||||
#ifndef QEMU_IRQ_H
|
||||
#define QEMU_IRQ_H
|
||||
|
||||
/* Generic IRQ/GPIO pin infrastructure. */
|
||||
|
||||
#define TYPE_IRQ "irq"
|
||||
|
||||
typedef struct IRQState *qemu_irq;
|
||||
|
||||
typedef void (*qemu_irq_handler)(void *opaque, int n, int level);
|
||||
|
||||
void qemu_set_irq(qemu_irq irq, int level);
|
||||
|
||||
static inline void qemu_irq_raise(qemu_irq irq)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void qemu_irq_lower(qemu_irq irq)
|
||||
{
|
||||
qemu_set_irq(irq, 0);
|
||||
}
|
||||
|
||||
static inline void qemu_irq_pulse(qemu_irq irq)
|
||||
{
|
||||
qemu_set_irq(irq, 1);
|
||||
qemu_set_irq(irq, 0);
|
||||
}
|
||||
|
||||
/* Returns an array of N IRQs. Each IRQ is assigned the argument handler and
|
||||
* opaque data.
|
||||
*/
|
||||
qemu_irq *qemu_allocate_irqs(qemu_irq_handler handler, void *opaque, int n);
|
||||
|
||||
/*
|
||||
* Allocates a single IRQ. The irq is assigned with a handler, an opaque
|
||||
* data and the interrupt number.
|
||||
*/
|
||||
qemu_irq qemu_allocate_irq(qemu_irq_handler handler, void *opaque, int n);
|
||||
|
||||
/* Extends an Array of IRQs. Old IRQs have their handlers and opaque data
|
||||
* preserved. New IRQs are assigned the argument handler and opaque data.
|
||||
*/
|
||||
qemu_irq *qemu_extend_irqs(qemu_irq *old, int n_old, qemu_irq_handler handler,
|
||||
void *opaque, int n);
|
||||
|
||||
void qemu_free_irqs(qemu_irq *s, int n);
|
||||
void qemu_free_irq(qemu_irq irq);
|
||||
|
||||
/* Returns a new IRQ with opposite polarity. */
|
||||
qemu_irq qemu_irq_invert(qemu_irq irq);
|
||||
|
||||
/* Returns a new IRQ which feeds into both the passed IRQs */
|
||||
qemu_irq qemu_irq_split(qemu_irq irq1, qemu_irq irq2);
|
||||
|
||||
/* Returns a new IRQ set which connects 1:1 to another IRQ set, which
|
||||
* may be set later.
|
||||
*/
|
||||
qemu_irq *qemu_irq_proxy(qemu_irq **target, int n);
|
||||
|
||||
/* For internal use in qtest. Similar to qemu_irq_split, but operating
|
||||
on an existing vector of qemu_irq. */
|
||||
void qemu_irq_intercept_in(qemu_irq *gpio_in, qemu_irq_handler handler, int n);
|
||||
|
||||
#endif
|
||||
10
qemu/include/hw/m68k/m68k.h
Normal file
10
qemu/include/hw/m68k/m68k.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef HW_M68K_H
|
||||
#define HW_M68K_H
|
||||
|
||||
#include "uc_priv.h"
|
||||
|
||||
void dummy_m68k_machine_init(struct uc_struct *uc);
|
||||
|
||||
void m68k_cpu_register_types(void *opaque);
|
||||
|
||||
#endif
|
||||
30
qemu/include/hw/m68k/mcf.h
Normal file
30
qemu/include/hw/m68k/mcf.h
Normal file
@@ -0,0 +1,30 @@
|
||||
#ifndef HW_MCF_H
|
||||
#define HW_MCF_H
|
||||
/* Motorola ColdFire device prototypes. */
|
||||
|
||||
struct MemoryRegion;
|
||||
|
||||
/* mcf_uart.c */
|
||||
uint64_t mcf_uart_read(void *opaque, hwaddr addr,
|
||||
unsigned size);
|
||||
void mcf_uart_write(void *opaque, hwaddr addr,
|
||||
uint64_t val, unsigned size);
|
||||
void *mcf_uart_init(qemu_irq irq, CharDriverState *chr);
|
||||
void mcf_uart_mm_init(struct MemoryRegion *sysmem,
|
||||
hwaddr base,
|
||||
qemu_irq irq, CharDriverState *chr);
|
||||
|
||||
/* mcf_intc.c */
|
||||
qemu_irq *mcf_intc_init(struct MemoryRegion *sysmem,
|
||||
hwaddr base,
|
||||
M68kCPU *cpu);
|
||||
|
||||
/* mcf_fec.c */
|
||||
void mcf_fec_init(struct MemoryRegion *sysmem, NICInfo *nd,
|
||||
hwaddr base, qemu_irq *irq);
|
||||
|
||||
/* mcf5206.c */
|
||||
qemu_irq *mcf5206_init(struct MemoryRegion *sysmem,
|
||||
uint32_t base, M68kCPU *cpu);
|
||||
|
||||
#endif
|
||||
8
qemu/include/hw/mips/bios.h
Normal file
8
qemu/include/hw/mips/bios.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "cpu.h"
|
||||
|
||||
#define BIOS_SIZE (4 * 1024 * 1024)
|
||||
#ifdef TARGET_WORDS_BIGENDIAN
|
||||
#define BIOS_FILENAME "mips_bios.bin"
|
||||
#else
|
||||
#define BIOS_FILENAME "mipsel_bios.bin"
|
||||
#endif
|
||||
17
qemu/include/hw/mips/cpudevs.h
Normal file
17
qemu/include/hw/mips/cpudevs.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef HW_MIPS_CPUDEVS_H
|
||||
#define HW_MIPS_CPUDEVS_H
|
||||
/* Definitions for MIPS CPU internal devices. */
|
||||
|
||||
/* mips_addr.c */
|
||||
uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
|
||||
uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
|
||||
uint64_t cpu_mips_kvm_um_phys_to_kseg0(void *opaque, uint64_t addr);
|
||||
|
||||
|
||||
/* mips_int.c */
|
||||
void cpu_mips_irq_init_cpu(CPUMIPSState *env);
|
||||
|
||||
/* mips_timer.c */
|
||||
void cpu_mips_clock_init(CPUMIPSState *);
|
||||
|
||||
#endif
|
||||
36
qemu/include/hw/mips/mips.h
Normal file
36
qemu/include/hw/mips/mips.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef HW_MIPS_H
|
||||
#define HW_MIPS_H
|
||||
/* Definitions for mips board emulation. */
|
||||
|
||||
/* Kernels can be configured with 64KB pages */
|
||||
#define INITRD_PAGE_MASK (~((1 << 16) - 1))
|
||||
|
||||
#include "exec/memory.h"
|
||||
|
||||
/* gt64xxx.c */
|
||||
PCIBus *gt64120_register(qemu_irq *pic);
|
||||
|
||||
/* bonito.c */
|
||||
PCIBus *bonito_init(qemu_irq *pic);
|
||||
|
||||
/* rc4030.c */
|
||||
typedef struct rc4030DMAState *rc4030_dma;
|
||||
void rc4030_dma_memory_rw(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write);
|
||||
void rc4030_dma_read(void *dma, uint8_t *buf, int len);
|
||||
void rc4030_dma_write(void *dma, uint8_t *buf, int len);
|
||||
|
||||
void *rc4030_init(qemu_irq timer, qemu_irq jazz_bus,
|
||||
qemu_irq **irqs, rc4030_dma **dmas,
|
||||
MemoryRegion *sysmem);
|
||||
|
||||
/* dp8393x.c */
|
||||
void dp83932_init(NICInfo *nd, hwaddr base, int it_shift,
|
||||
MemoryRegion *address_space,
|
||||
qemu_irq irq, void* mem_opaque,
|
||||
void (*memory_rw)(void *opaque, hwaddr addr, uint8_t *buf, int len, int is_write));
|
||||
|
||||
void mips_machine_init(struct uc_struct *uc);
|
||||
|
||||
void mips_cpu_register_types(void *opaque);
|
||||
|
||||
#endif
|
||||
373
qemu/include/hw/qdev-core.h
Normal file
373
qemu/include/hw/qdev-core.h
Normal file
@@ -0,0 +1,373 @@
|
||||
#ifndef QDEV_CORE_H
|
||||
#define QDEV_CORE_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qemu/bitmap.h"
|
||||
#include "qom/object.h"
|
||||
#include "hw/irq.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
enum {
|
||||
DEV_NVECTORS_UNSPECIFIED = -1,
|
||||
};
|
||||
|
||||
#define TYPE_DEVICE "device"
|
||||
#define DEVICE(uc, obj) OBJECT_CHECK(uc, DeviceState, (obj), TYPE_DEVICE)
|
||||
#define DEVICE_CLASS(uc, klass) OBJECT_CLASS_CHECK(uc, DeviceClass, (klass), TYPE_DEVICE)
|
||||
#define DEVICE_GET_CLASS(uc, obj) OBJECT_GET_CLASS(uc, DeviceClass, (obj), TYPE_DEVICE)
|
||||
|
||||
typedef enum DeviceCategory {
|
||||
DEVICE_CATEGORY_BRIDGE,
|
||||
DEVICE_CATEGORY_USB,
|
||||
DEVICE_CATEGORY_STORAGE,
|
||||
DEVICE_CATEGORY_NETWORK,
|
||||
DEVICE_CATEGORY_INPUT,
|
||||
DEVICE_CATEGORY_DISPLAY,
|
||||
DEVICE_CATEGORY_SOUND,
|
||||
DEVICE_CATEGORY_MISC,
|
||||
DEVICE_CATEGORY_MAX
|
||||
} DeviceCategory;
|
||||
|
||||
typedef int (*qdev_initfn)(DeviceState *dev);
|
||||
typedef int (*qdev_event)(DeviceState *dev);
|
||||
typedef void (*qdev_resetfn)(DeviceState *dev);
|
||||
typedef void (*DeviceRealize)(struct uc_struct *uc, DeviceState *dev, Error **errp);
|
||||
typedef void (*DeviceUnrealize)(DeviceState *dev, Error **errp);
|
||||
typedef void (*BusRealize)(BusState *bus, Error **errp);
|
||||
typedef void (*BusUnrealize)(BusState *bus, Error **errp);
|
||||
|
||||
struct VMStateDescription;
|
||||
|
||||
/**
|
||||
* DeviceClass:
|
||||
* @props: Properties accessing state fields.
|
||||
* @realize: Callback function invoked when the #DeviceState:realized
|
||||
* property is changed to %true. The default invokes @init if not %NULL.
|
||||
* @unrealize: Callback function invoked when the #DeviceState:realized
|
||||
* property is changed to %false.
|
||||
* @init: Callback function invoked when the #DeviceState::realized property
|
||||
* is changed to %true. Deprecated, new types inheriting directly from
|
||||
* TYPE_DEVICE should use @realize instead, new leaf types should consult
|
||||
* their respective parent type.
|
||||
* @hotpluggable: indicates if #DeviceClass is hotpluggable, available
|
||||
* as readonly "hotpluggable" property of #DeviceState instance
|
||||
*
|
||||
* # Realization #
|
||||
* Devices are constructed in two stages,
|
||||
* 1) object instantiation via object_initialize() and
|
||||
* 2) device realization via #DeviceState:realized property.
|
||||
* The former may not fail (it might assert or exit), the latter may return
|
||||
* error information to the caller and must be re-entrant.
|
||||
* Trivial field initializations should go into #TypeInfo.instance_init.
|
||||
* Operations depending on @props static properties should go into @realize.
|
||||
* After successful realization, setting static properties will fail.
|
||||
*
|
||||
* As an interim step, the #DeviceState:realized property is set by deprecated
|
||||
* functions qdev_init() and qdev_init_nofail().
|
||||
* In the future, devices will propagate this state change to their children
|
||||
* and along busses they expose.
|
||||
* The point in time will be deferred to machine creation, so that values
|
||||
* set in @realize will not be introspectable beforehand. Therefore devices
|
||||
* must not create children during @realize; they should initialize them via
|
||||
* object_initialize() in their own #TypeInfo.instance_init and forward the
|
||||
* realization events appropriately.
|
||||
*
|
||||
* The @init callback is considered private to a particular bus implementation
|
||||
* (immediate abstract child types of TYPE_DEVICE). Derived leaf types set an
|
||||
* "init" callback on their parent class instead.
|
||||
*
|
||||
* Any type may override the @realize and/or @unrealize callbacks but needs
|
||||
* to call the parent type's implementation if keeping their functionality
|
||||
* is desired. Refer to QOM documentation for further discussion and examples.
|
||||
*
|
||||
* <note>
|
||||
* <para>
|
||||
* If a type derived directly from TYPE_DEVICE implements @realize, it does
|
||||
* not need to implement @init and therefore does not need to store and call
|
||||
* #DeviceClass' default @realize callback.
|
||||
* For other types consult the documentation and implementation of the
|
||||
* respective parent types.
|
||||
* </para>
|
||||
* </note>
|
||||
*/
|
||||
typedef struct DeviceClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
DECLARE_BITMAP(categories, DEVICE_CATEGORY_MAX);
|
||||
const char *fw_name;
|
||||
const char *desc;
|
||||
Property *props;
|
||||
|
||||
/*
|
||||
* Shall we hide this device model from -device / device_add?
|
||||
* All devices should support instantiation with device_add, and
|
||||
* this flag should not exist. But we're not there, yet. Some
|
||||
* devices fail to instantiate with cryptic error messages.
|
||||
* Others instantiate, but don't work. Exposing users to such
|
||||
* behavior would be cruel; this flag serves to protect them. It
|
||||
* should never be set without a comment explaining why it is set.
|
||||
* TODO remove once we're there
|
||||
*/
|
||||
bool cannot_instantiate_with_device_add_yet;
|
||||
bool hotpluggable;
|
||||
|
||||
/* callbacks */
|
||||
void (*reset)(struct uc_struct *uc, DeviceState *dev);
|
||||
DeviceRealize realize;
|
||||
DeviceUnrealize unrealize;
|
||||
|
||||
/* device state */
|
||||
const struct VMStateDescription *vmsd;
|
||||
|
||||
/* Private to qdev / bus. */
|
||||
qdev_initfn init; /* TODO remove, once users are converted to realize */
|
||||
qdev_event exit; /* TODO remove, once users are converted to unrealize */
|
||||
const char *bus_type;
|
||||
} DeviceClass;
|
||||
|
||||
typedef struct NamedGPIOList NamedGPIOList;
|
||||
|
||||
struct NamedGPIOList {
|
||||
char *name;
|
||||
qemu_irq *in;
|
||||
int num_in;
|
||||
int num_out;
|
||||
QLIST_ENTRY(NamedGPIOList) node;
|
||||
};
|
||||
|
||||
/**
|
||||
* DeviceState:
|
||||
* @realized: Indicates whether the device has been fully constructed.
|
||||
*
|
||||
* This structure should not be accessed directly. We declare it here
|
||||
* so that it can be embedded in individual device state structures.
|
||||
*/
|
||||
struct DeviceState {
|
||||
/*< private >*/
|
||||
Object parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
const char *id;
|
||||
bool realized;
|
||||
bool pending_deleted_event;
|
||||
int hotplugged;
|
||||
BusState *parent_bus;
|
||||
QLIST_HEAD(, NamedGPIOList) gpios;
|
||||
QLIST_HEAD(, BusState) child_bus;
|
||||
int num_child_bus;
|
||||
int instance_id_alias;
|
||||
int alias_required_for_version;
|
||||
};
|
||||
|
||||
#define TYPE_BUS "bus"
|
||||
#define BUS(uc, obj) OBJECT_CHECK(uc, BusState, (obj), TYPE_BUS)
|
||||
#define BUS_CLASS(klass) OBJECT_CLASS_CHECK(BusClass, (klass), TYPE_BUS)
|
||||
#define BUS_GET_CLASS(obj) OBJECT_GET_CLASS(BusClass, (obj), TYPE_BUS)
|
||||
|
||||
struct BusClass {
|
||||
ObjectClass parent_class;
|
||||
|
||||
/* FIXME first arg should be BusState */
|
||||
void (*print_dev)(Monitor *mon, DeviceState *dev, int indent);
|
||||
char *(*get_dev_path)(DeviceState *dev);
|
||||
/*
|
||||
* This callback is used to create Open Firmware device path in accordance
|
||||
* with OF spec http://forthworks.com/standards/of1275.pdf. Individual bus
|
||||
* bindings can be found at http://playground.sun.com/1275/bindings/.
|
||||
*/
|
||||
char *(*get_fw_dev_path)(DeviceState *dev);
|
||||
void (*reset)(BusState *bus);
|
||||
BusRealize realize;
|
||||
BusUnrealize unrealize;
|
||||
|
||||
/* maximum devices allowed on the bus, 0: no limit. */
|
||||
int max_dev;
|
||||
/* number of automatically allocated bus ids (e.g. ide.0) */
|
||||
int automatic_ids;
|
||||
};
|
||||
|
||||
typedef struct BusChild {
|
||||
DeviceState *child;
|
||||
int index;
|
||||
QTAILQ_ENTRY(BusChild) sibling;
|
||||
} BusChild;
|
||||
|
||||
#define QDEV_HOTPLUG_HANDLER_PROPERTY "hotplug-handler"
|
||||
|
||||
/**
|
||||
* BusState:
|
||||
* @hotplug_device: link to a hotplug device associated with bus.
|
||||
*/
|
||||
struct BusState {
|
||||
Object obj;
|
||||
DeviceState *parent;
|
||||
const char *name;
|
||||
int max_index;
|
||||
bool realized;
|
||||
QTAILQ_HEAD(ChildrenHead, BusChild) children;
|
||||
QLIST_ENTRY(BusState) sibling;
|
||||
};
|
||||
|
||||
struct Property {
|
||||
const char *name;
|
||||
PropertyInfo *info;
|
||||
int offset;
|
||||
uint8_t bitnr;
|
||||
uint8_t qtype;
|
||||
int64_t defval;
|
||||
int arrayoffset;
|
||||
PropertyInfo *arrayinfo;
|
||||
int arrayfieldsize;
|
||||
};
|
||||
|
||||
struct PropertyInfo {
|
||||
const char *name;
|
||||
const char *description;
|
||||
const char **enum_table;
|
||||
int (*print)(DeviceState *dev, Property *prop, char *dest, size_t len);
|
||||
ObjectPropertyAccessor *get;
|
||||
ObjectPropertyAccessor *set;
|
||||
ObjectPropertyRelease *release;
|
||||
};
|
||||
|
||||
/**
|
||||
* GlobalProperty:
|
||||
* @user_provided: Set to true if property comes from user-provided config
|
||||
* (command-line or config file).
|
||||
* @used: Set to true if property was used when initializing a device.
|
||||
*/
|
||||
typedef struct GlobalProperty {
|
||||
const char *driver;
|
||||
const char *property;
|
||||
const char *value;
|
||||
bool user_provided;
|
||||
bool used;
|
||||
QTAILQ_ENTRY(GlobalProperty) next;
|
||||
} GlobalProperty;
|
||||
|
||||
/*** Board API. This should go away once we have a machine config file. ***/
|
||||
|
||||
DeviceState *qdev_create(BusState *bus, const char *name);
|
||||
DeviceState *qdev_try_create(BusState *bus, const char *name);
|
||||
int qdev_init(DeviceState *dev) QEMU_WARN_UNUSED_RESULT;
|
||||
void qdev_init_nofail(DeviceState *dev);
|
||||
void qdev_set_legacy_instance_id(DeviceState *dev, int alias_id,
|
||||
int required_for_version);
|
||||
void qdev_unplug(DeviceState *dev, Error **errp);
|
||||
void qdev_machine_creation_done(void);
|
||||
bool qdev_machine_modified(void);
|
||||
|
||||
qemu_irq qdev_get_gpio_in(DeviceState *dev, int n);
|
||||
qemu_irq qdev_get_gpio_in_named(DeviceState *dev, const char *name, int n);
|
||||
|
||||
void qdev_connect_gpio_out(DeviceState *dev, int n, qemu_irq pin);
|
||||
void qdev_connect_gpio_out_named(DeviceState *dev, const char *name, int n,
|
||||
qemu_irq pin);
|
||||
qemu_irq qdev_get_gpio_out_connector(DeviceState *dev, const char *name, int n);
|
||||
qemu_irq qdev_intercept_gpio_out(DeviceState *dev, qemu_irq icpt,
|
||||
const char *name, int n);
|
||||
|
||||
BusState *qdev_get_child_bus(DeviceState *dev, const char *name);
|
||||
|
||||
/*** Device API. ***/
|
||||
|
||||
/* Register device properties. */
|
||||
/* GPIO inputs also double as IRQ sinks. */
|
||||
void qdev_init_gpio_in(DeviceState *dev, qemu_irq_handler handler, int n);
|
||||
void qdev_init_gpio_out(DeviceState *dev, qemu_irq *pins, int n);
|
||||
void qdev_init_gpio_in_named(DeviceState *dev, qemu_irq_handler handler,
|
||||
const char *name, int n);
|
||||
void qdev_init_gpio_out_named(DeviceState *dev, qemu_irq *pins,
|
||||
const char *name, int n);
|
||||
|
||||
void qdev_pass_gpios(DeviceState *dev, DeviceState *container,
|
||||
const char *name);
|
||||
|
||||
BusState *qdev_get_parent_bus(DeviceState *dev);
|
||||
|
||||
/*** BUS API. ***/
|
||||
|
||||
DeviceState *qdev_find_recursive(BusState *bus, const char *id);
|
||||
|
||||
/* Returns 0 to walk children, > 0 to skip walk, < 0 to terminate walk. */
|
||||
typedef int (qbus_walkerfn)(BusState *bus, void *opaque);
|
||||
typedef int (qdev_walkerfn)(DeviceState *dev, void *opaque);
|
||||
|
||||
void qbus_create_inplace(void *bus, size_t size, const char *typename,
|
||||
DeviceState *parent, const char *name);
|
||||
BusState *qbus_create(const char *typename, DeviceState *parent, const char *name);
|
||||
/* Returns > 0 if either devfn or busfn skip walk somewhere in cursion,
|
||||
* < 0 if either devfn or busfn terminate walk somewhere in cursion,
|
||||
* 0 otherwise. */
|
||||
int qbus_walk_children(BusState *bus,
|
||||
qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
||||
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
||||
void *opaque);
|
||||
int qdev_walk_children(DeviceState *dev,
|
||||
qdev_walkerfn *pre_devfn, qbus_walkerfn *pre_busfn,
|
||||
qdev_walkerfn *post_devfn, qbus_walkerfn *post_busfn,
|
||||
void *opaque);
|
||||
|
||||
void qdev_reset_all(DeviceState *dev);
|
||||
|
||||
/**
|
||||
* @qbus_reset_all:
|
||||
* @bus: Bus to be reset.
|
||||
*
|
||||
* Reset @bus and perform a bus-level ("hard") reset of all devices connected
|
||||
* to it, including recursive processing of all buses below @bus itself. A
|
||||
* hard reset means that qbus_reset_all will reset all state of the device.
|
||||
* For PCI devices, for example, this will include the base address registers
|
||||
* or configuration space.
|
||||
*/
|
||||
void qbus_reset_all(BusState *bus);
|
||||
void qbus_reset_all_fn(void *opaque);
|
||||
|
||||
/* This should go away once we get rid of the NULL bus hack */
|
||||
BusState *sysbus_get_default(void);
|
||||
|
||||
char *qdev_get_fw_dev_path(DeviceState *dev);
|
||||
|
||||
/**
|
||||
* @qdev_machine_init
|
||||
*
|
||||
* Initialize platform devices before machine init. This is a hack until full
|
||||
* support for composition is added.
|
||||
*/
|
||||
void qdev_machine_init(void);
|
||||
|
||||
/**
|
||||
* @device_reset
|
||||
*
|
||||
* Reset a single device (by calling the reset method).
|
||||
*/
|
||||
void device_reset(DeviceState *dev);
|
||||
|
||||
const struct VMStateDescription *qdev_get_vmsd(DeviceState *dev);
|
||||
|
||||
const char *qdev_fw_name(DeviceState *dev);
|
||||
|
||||
Object *qdev_get_machine(struct uc_struct *);
|
||||
|
||||
/* FIXME: make this a link<> */
|
||||
void qdev_set_parent_bus(DeviceState *dev, BusState *bus);
|
||||
|
||||
extern int qdev_hotplug;
|
||||
|
||||
char *qdev_get_dev_path(DeviceState *dev);
|
||||
|
||||
GSList *qdev_build_hotpluggable_device_list(Object *peripheral);
|
||||
|
||||
void qbus_set_hotplug_handler(BusState *bus, DeviceState *handler,
|
||||
Error **errp);
|
||||
|
||||
void qbus_set_bus_hotplug_handler(BusState *bus, Error **errp);
|
||||
|
||||
void qdev_register_types(struct uc_struct *uc);
|
||||
|
||||
void sysbus_register_types(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
7
qemu/include/hw/qdev.h
Normal file
7
qemu/include/hw/qdev.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef QDEV_H
|
||||
#define QDEV_H
|
||||
|
||||
#include "hw/hw.h"
|
||||
#include "hw/qdev-core.h"
|
||||
|
||||
#endif
|
||||
125
qemu/include/hw/sparc/grlib.h
Normal file
125
qemu/include/hw/sparc/grlib.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* QEMU GRLIB Components
|
||||
*
|
||||
* Copyright (c) 2010-2011 AdaCore
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _GRLIB_H_
|
||||
#define _GRLIB_H_
|
||||
|
||||
#include "hw/qdev.h"
|
||||
|
||||
/* Emulation of GrLib device is base on the GRLIB IP Core User's Manual:
|
||||
* http://www.gaisler.com/products/grlib/grip.pdf
|
||||
*/
|
||||
|
||||
/* IRQMP */
|
||||
|
||||
typedef void (*set_pil_in_fn) (void *opaque, uint32_t pil_in);
|
||||
|
||||
void grlib_irqmp_set_irq(void *opaque, int irq, int level);
|
||||
|
||||
void grlib_irqmp_ack(DeviceState *dev, int intno);
|
||||
|
||||
static inline
|
||||
DeviceState *grlib_irqmp_create(hwaddr base,
|
||||
CPUSPARCState *env,
|
||||
qemu_irq **cpu_irqs,
|
||||
uint32_t nr_irqs,
|
||||
set_pil_in_fn set_pil_in)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
assert(cpu_irqs != NULL);
|
||||
|
||||
dev = qdev_create(NULL, "grlib,irqmp");
|
||||
qdev_prop_set_ptr(dev, "set_pil_in", set_pil_in);
|
||||
qdev_prop_set_ptr(dev, "set_pil_in_opaque", env);
|
||||
|
||||
if (qdev_init(dev)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
env->irq_manager = dev;
|
||||
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||
|
||||
*cpu_irqs = qemu_allocate_irqs(grlib_irqmp_set_irq,
|
||||
dev,
|
||||
nr_irqs);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* GPTimer */
|
||||
|
||||
static inline
|
||||
DeviceState *grlib_gptimer_create(hwaddr base,
|
||||
uint32_t nr_timers,
|
||||
uint32_t freq,
|
||||
qemu_irq *cpu_irqs,
|
||||
int base_irq)
|
||||
{
|
||||
DeviceState *dev;
|
||||
int i;
|
||||
|
||||
dev = qdev_create(NULL, "grlib,gptimer");
|
||||
qdev_prop_set_uint32(dev, "nr-timers", nr_timers);
|
||||
qdev_prop_set_uint32(dev, "frequency", freq);
|
||||
qdev_prop_set_uint32(dev, "irq-line", base_irq);
|
||||
|
||||
if (qdev_init(dev)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||
|
||||
for (i = 0; i < nr_timers; i++) {
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), i, cpu_irqs[base_irq + i]);
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/* APB UART */
|
||||
|
||||
static inline
|
||||
DeviceState *grlib_apbuart_create(hwaddr base,
|
||||
CharDriverState *serial,
|
||||
qemu_irq irq)
|
||||
{
|
||||
DeviceState *dev;
|
||||
|
||||
dev = qdev_create(NULL, "grlib,apbuart");
|
||||
qdev_prop_set_chr(dev, "chrdev", serial);
|
||||
|
||||
if (qdev_init(dev)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, base);
|
||||
|
||||
sysbus_connect_irq(SYS_BUS_DEVICE(dev), 0, irq);
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
#endif /* ! _GRLIB_H_ */
|
||||
8
qemu/include/hw/sparc/sparc.h
Normal file
8
qemu/include/hw/sparc/sparc.h
Normal file
@@ -0,0 +1,8 @@
|
||||
#ifndef HW_SPARC_H
|
||||
#define HW_SPARC_H
|
||||
|
||||
void sparc_cpu_register_types(void *opaque);
|
||||
void leon3_machine_init(struct uc_struct *uc);
|
||||
void sun4u_machine_init(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
12
qemu/include/hw/sparc/sparc32_dma.h
Normal file
12
qemu/include/hw/sparc/sparc32_dma.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#ifndef SPARC32_DMA_H
|
||||
#define SPARC32_DMA_H
|
||||
|
||||
/* sparc32_dma.c */
|
||||
void ledma_memory_read(void *opaque, hwaddr addr,
|
||||
uint8_t *buf, int len, int do_bswap);
|
||||
void ledma_memory_write(void *opaque, hwaddr addr,
|
||||
uint8_t *buf, int len, int do_bswap);
|
||||
void espdma_memory_read(void *opaque, uint8_t *buf, int len);
|
||||
void espdma_memory_write(void *opaque, uint8_t *buf, int len);
|
||||
|
||||
#endif
|
||||
38
qemu/include/hw/sparc/sun4m.h
Normal file
38
qemu/include/hw/sparc/sun4m.h
Normal file
@@ -0,0 +1,38 @@
|
||||
#ifndef SUN4M_H
|
||||
#define SUN4M_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "qapi/qmp/types.h"
|
||||
|
||||
/* Devices used by sparc32 system. */
|
||||
|
||||
/* iommu.c */
|
||||
void sparc_iommu_memory_rw(void *opaque, hwaddr addr,
|
||||
uint8_t *buf, int len, int is_write);
|
||||
static inline void sparc_iommu_memory_read(void *opaque,
|
||||
hwaddr addr,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
sparc_iommu_memory_rw(opaque, addr, buf, len, 0);
|
||||
}
|
||||
|
||||
static inline void sparc_iommu_memory_write(void *opaque,
|
||||
hwaddr addr,
|
||||
uint8_t *buf, int len)
|
||||
{
|
||||
sparc_iommu_memory_rw(opaque, addr, buf, len, 1);
|
||||
}
|
||||
|
||||
/* slavio_intctl.c */
|
||||
void slavio_pic_info(Monitor *mon, DeviceState *dev);
|
||||
void slavio_irq_info(Monitor *mon, DeviceState *dev);
|
||||
|
||||
/* sun4m.c */
|
||||
void sun4m_pic_info(Monitor *mon, const QDict *qdict);
|
||||
void sun4m_irq_info(Monitor *mon, const QDict *qdict);
|
||||
|
||||
/* sparc32_dma.c */
|
||||
#include "hw/sparc/sparc32_dma.h"
|
||||
|
||||
#endif
|
||||
26
qemu/include/qapi/dealloc-visitor.h
Normal file
26
qemu/include/qapi/dealloc-visitor.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Dealloc Visitor
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Michael Roth <mdroth@linux.vnet.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QAPI_DEALLOC_VISITOR_H
|
||||
#define QAPI_DEALLOC_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
typedef struct QapiDeallocVisitor QapiDeallocVisitor;
|
||||
|
||||
QapiDeallocVisitor *qapi_dealloc_visitor_new(void);
|
||||
void qapi_dealloc_visitor_cleanup(QapiDeallocVisitor *d);
|
||||
|
||||
Visitor *qapi_dealloc_get_visitor(QapiDeallocVisitor *v);
|
||||
|
||||
#endif
|
||||
103
qemu/include/qapi/error.h
Normal file
103
qemu/include/qapi/error.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* QEMU Error Objects
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2. See
|
||||
* the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#ifndef ERROR_H
|
||||
#define ERROR_H
|
||||
|
||||
#include "qemu/compiler.h"
|
||||
#include "qapi-types.h"
|
||||
#include <stdbool.h>
|
||||
|
||||
/**
|
||||
* A class representing internal errors within QEMU. An error has a ErrorClass
|
||||
* code and a human message.
|
||||
*/
|
||||
typedef struct Error Error;
|
||||
|
||||
/**
|
||||
* Set an indirect pointer to an error given a ErrorClass value and a
|
||||
* printf-style human message. This function is not meant to be used outside
|
||||
* of QEMU.
|
||||
*/
|
||||
void error_set(Error **errp, ErrorClass err_class, const char *fmt, ...)
|
||||
GCC_FMT_ATTR(3, 4);
|
||||
|
||||
/**
|
||||
* Set an indirect pointer to an error given a ErrorClass value and a
|
||||
* printf-style human message, followed by a strerror() string if
|
||||
* @os_error is not zero.
|
||||
*/
|
||||
void error_set_errno(Error **errp, int os_error, ErrorClass err_class,
|
||||
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
|
||||
|
||||
#ifdef _WIN32
|
||||
/**
|
||||
* Set an indirect pointer to an error given a ErrorClass value and a
|
||||
* printf-style human message, followed by a g_win32_error_message() string if
|
||||
* @win32_err is not zero.
|
||||
*/
|
||||
void error_set_win32(Error **errp, int win32_err, ErrorClass err_class,
|
||||
const char *fmt, ...) GCC_FMT_ATTR(4, 5);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Same as error_set(), but sets a generic error
|
||||
*/
|
||||
#define error_setg(errp, fmt, ...) \
|
||||
error_set(errp, ERROR_CLASS_GENERIC_ERROR, fmt, ## __VA_ARGS__)
|
||||
#define error_setg_errno(errp, os_error, fmt, ...) \
|
||||
error_set_errno(errp, os_error, ERROR_CLASS_GENERIC_ERROR, \
|
||||
fmt, ## __VA_ARGS__)
|
||||
#ifdef _WIN32
|
||||
#define error_setg_win32(errp, win32_err, fmt, ...) \
|
||||
error_set_win32(errp, win32_err, ERROR_CLASS_GENERIC_ERROR, \
|
||||
fmt, ## __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Helper for open() errors
|
||||
*/
|
||||
void error_setg_file_open(Error **errp, int os_errno, const char *filename);
|
||||
|
||||
/*
|
||||
* Get the error class of an error object.
|
||||
*/
|
||||
ErrorClass error_get_class(const Error *err);
|
||||
|
||||
/**
|
||||
* Returns an exact copy of the error passed as an argument.
|
||||
*/
|
||||
Error *error_copy(const Error *err);
|
||||
|
||||
/**
|
||||
* Get a human readable representation of an error object.
|
||||
*/
|
||||
const char *error_get_pretty(Error *err);
|
||||
|
||||
/**
|
||||
* Propagate an error to an indirect pointer to an error. This function will
|
||||
* always transfer ownership of the error reference and handles the case where
|
||||
* dst_err is NULL correctly. Errors after the first are discarded.
|
||||
*/
|
||||
void error_propagate(Error **dst_errp, Error *local_err);
|
||||
|
||||
/**
|
||||
* Free an error object.
|
||||
*/
|
||||
void error_free(Error *err);
|
||||
|
||||
/**
|
||||
* If passed to error_set and friends, abort().
|
||||
*/
|
||||
|
||||
extern Error *error_abort;
|
||||
|
||||
#endif
|
||||
37
qemu/include/qapi/opts-visitor.h
Normal file
37
qemu/include/qapi/opts-visitor.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Options Visitor
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2012
|
||||
*
|
||||
* Author: Laszlo Ersek <lersek@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef OPTS_VISITOR_H
|
||||
#define OPTS_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qemu/option.h"
|
||||
|
||||
/* Inclusive upper bound on the size of any flattened range. This is a safety
|
||||
* (= anti-annoyance) measure; wrong ranges should not cause long startup
|
||||
* delays nor exhaust virtual memory.
|
||||
*/
|
||||
#define OPTS_VISITOR_RANGE_MAX 65536
|
||||
|
||||
typedef struct OptsVisitor OptsVisitor;
|
||||
|
||||
/* Contrarily to qemu-option.c::parse_option_number(), OptsVisitor's "int"
|
||||
* parser relies on strtoll() instead of strtoull(). Consequences:
|
||||
* - string representations of negative numbers yield negative values,
|
||||
* - values below INT64_MIN or LLONG_MIN are rejected,
|
||||
* - values above INT64_MAX or LLONG_MAX are rejected.
|
||||
*/
|
||||
OptsVisitor *opts_visitor_new(const QemuOpts *opts);
|
||||
void opts_visitor_cleanup(OptsVisitor *nv);
|
||||
Visitor *opts_get_visitor(OptsVisitor *nv);
|
||||
|
||||
#endif
|
||||
27
qemu/include/qapi/qmp-event.h
Normal file
27
qemu/include/qapi/qmp-event.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* QMP Event related
|
||||
*
|
||||
* Copyright (c) 2014 Wenchao Xia
|
||||
*
|
||||
* Authors:
|
||||
* Wenchao Xia <wenchaoqemu@gmail.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_EVENT_H
|
||||
#define QMP_EVENT_H
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
typedef void (*QMPEventFuncEmit)(unsigned event, QDict *dict, Error **errp);
|
||||
|
||||
void qmp_event_set_func_emit(QMPEventFuncEmit emit);
|
||||
|
||||
QMPEventFuncEmit qmp_event_get_func_emit(void);
|
||||
|
||||
QDict *qmp_event_build_dict(const char *event_name);
|
||||
#endif
|
||||
29
qemu/include/qapi/qmp-input-visitor.h
Normal file
29
qemu/include/qapi/qmp-input-visitor.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Input Visitor
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_INPUT_VISITOR_H
|
||||
#define QMP_INPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QmpInputVisitor QmpInputVisitor;
|
||||
|
||||
QmpInputVisitor *qmp_input_visitor_new(QObject *obj);
|
||||
QmpInputVisitor *qmp_input_visitor_new_strict(QObject *obj);
|
||||
|
||||
void qmp_input_visitor_cleanup(QmpInputVisitor *v);
|
||||
|
||||
Visitor *qmp_input_get_visitor(QmpInputVisitor *v);
|
||||
|
||||
#endif
|
||||
28
qemu/include/qapi/qmp-output-visitor.h
Normal file
28
qemu/include/qapi/qmp-output-visitor.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Output Visitor
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_OUTPUT_VISITOR_H
|
||||
#define QMP_OUTPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QmpOutputVisitor QmpOutputVisitor;
|
||||
|
||||
QmpOutputVisitor *qmp_output_visitor_new(void);
|
||||
void qmp_output_visitor_cleanup(QmpOutputVisitor *v);
|
||||
|
||||
QObject *qmp_output_get_qobject(QmpOutputVisitor *v);
|
||||
Visitor *qmp_output_get_visitor(QmpOutputVisitor *v);
|
||||
|
||||
#endif
|
||||
58
qemu/include/qapi/qmp/dispatch.h
Normal file
58
qemu/include/qapi/qmp/dispatch.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Core Definitions for QAPI/QMP Dispatch
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QMP_CORE_H
|
||||
#define QMP_CORE_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
|
||||
|
||||
typedef enum QmpCommandType
|
||||
{
|
||||
QCT_NORMAL,
|
||||
} QmpCommandType;
|
||||
|
||||
typedef enum QmpCommandOptions
|
||||
{
|
||||
QCO_NO_OPTIONS = 0x0,
|
||||
QCO_NO_SUCCESS_RESP = 0x1,
|
||||
} QmpCommandOptions;
|
||||
|
||||
typedef struct QmpCommand
|
||||
{
|
||||
const char *name;
|
||||
QmpCommandType type;
|
||||
QmpCommandFunc *fn;
|
||||
QmpCommandOptions options;
|
||||
QTAILQ_ENTRY(QmpCommand) node;
|
||||
bool enabled;
|
||||
} QmpCommand;
|
||||
|
||||
void qmp_register_command(const char *name, QmpCommandFunc *fn,
|
||||
QmpCommandOptions options);
|
||||
QmpCommand *qmp_find_command(const char *name);
|
||||
QObject *qmp_dispatch(QObject *request);
|
||||
void qmp_disable_command(const char *name);
|
||||
void qmp_enable_command(const char *name);
|
||||
bool qmp_command_is_enabled(const QmpCommand *cmd);
|
||||
const char *qmp_command_name(const QmpCommand *cmd);
|
||||
bool qmp_has_success_response(const QmpCommand *cmd);
|
||||
QObject *qmp_build_error_object(Error *err);
|
||||
typedef void (*qmp_cmd_callback_fn)(QmpCommand *cmd, void *opaque);
|
||||
void qmp_for_each_command(qmp_cmd_callback_fn fn, void *opaque);
|
||||
|
||||
#endif
|
||||
|
||||
51
qemu/include/qapi/qmp/json-lexer.h
Normal file
51
qemu/include/qapi/qmp/json-lexer.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* JSON lexer
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_JSON_LEXER_H
|
||||
#define QEMU_JSON_LEXER_H
|
||||
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
|
||||
typedef enum json_token_type {
|
||||
JSON_OPERATOR = 100,
|
||||
JSON_INTEGER,
|
||||
JSON_FLOAT,
|
||||
JSON_KEYWORD,
|
||||
JSON_STRING,
|
||||
JSON_ESCAPE,
|
||||
JSON_SKIP,
|
||||
JSON_ERROR,
|
||||
} JSONTokenType;
|
||||
|
||||
typedef struct JSONLexer JSONLexer;
|
||||
|
||||
typedef void (JSONLexerEmitter)(JSONLexer *, QString *, JSONTokenType, int x, int y);
|
||||
|
||||
struct JSONLexer
|
||||
{
|
||||
JSONLexerEmitter *emit;
|
||||
int state;
|
||||
QString *token;
|
||||
int x, y;
|
||||
};
|
||||
|
||||
void json_lexer_init(JSONLexer *lexer, JSONLexerEmitter func);
|
||||
|
||||
int json_lexer_feed(JSONLexer *lexer, const char *buffer, size_t size);
|
||||
|
||||
int json_lexer_flush(JSONLexer *lexer);
|
||||
|
||||
void json_lexer_destroy(JSONLexer *lexer);
|
||||
|
||||
#endif
|
||||
24
qemu/include/qapi/qmp/json-parser.h
Normal file
24
qemu/include/qapi/qmp/json-parser.h
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* JSON Parser
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_JSON_PARSER_H
|
||||
#define QEMU_JSON_PARSER_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/error.h"
|
||||
|
||||
QObject *json_parser_parse(QList *tokens, va_list *ap);
|
||||
QObject *json_parser_parse_err(QList *tokens, va_list *ap, Error **errp);
|
||||
|
||||
#endif
|
||||
40
qemu/include/qapi/qmp/json-streamer.h
Normal file
40
qemu/include/qapi/qmp/json-streamer.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* JSON streaming support
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_JSON_STREAMER_H
|
||||
#define QEMU_JSON_STREAMER_H
|
||||
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/json-lexer.h"
|
||||
|
||||
typedef struct JSONMessageParser
|
||||
{
|
||||
void (*emit)(struct JSONMessageParser *parser, QList *tokens);
|
||||
JSONLexer lexer;
|
||||
int brace_count;
|
||||
int bracket_count;
|
||||
QList *tokens;
|
||||
uint64_t token_size;
|
||||
} JSONMessageParser;
|
||||
|
||||
void json_message_parser_init(JSONMessageParser *parser,
|
||||
void (*func)(JSONMessageParser *, QList *));
|
||||
|
||||
int json_message_parser_feed(JSONMessageParser *parser,
|
||||
const char *buffer, size_t size);
|
||||
|
||||
int json_message_parser_flush(JSONMessageParser *parser);
|
||||
|
||||
void json_message_parser_destroy(JSONMessageParser *parser);
|
||||
|
||||
#endif
|
||||
29
qemu/include/qapi/qmp/qbool.h
Normal file
29
qemu/include/qapi/qmp/qbool.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* QBool Module
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QBOOL_H
|
||||
#define QBOOL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QBool {
|
||||
QObject_HEAD;
|
||||
int value;
|
||||
} QBool;
|
||||
|
||||
QBool *qbool_from_int(int value);
|
||||
int qbool_get_int(const QBool *qb);
|
||||
QBool *qobject_to_qbool(const QObject *obj);
|
||||
|
||||
#endif /* QBOOL_H */
|
||||
76
qemu/include/qapi/qmp/qdict.h
Normal file
76
qemu/include/qapi/qmp/qdict.h
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* QDict Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QDICT_H
|
||||
#define QDICT_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qemu/queue.h"
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define QDICT_BUCKET_MAX 512
|
||||
|
||||
typedef struct QDictEntry {
|
||||
char *key;
|
||||
QObject *value;
|
||||
QLIST_ENTRY(QDictEntry) next;
|
||||
} QDictEntry;
|
||||
|
||||
typedef struct QDict {
|
||||
QObject_HEAD;
|
||||
size_t size;
|
||||
QLIST_HEAD(,QDictEntry) table[QDICT_BUCKET_MAX];
|
||||
} QDict;
|
||||
|
||||
/* Object API */
|
||||
QDict *qdict_new(void);
|
||||
const char *qdict_entry_key(const QDictEntry *entry);
|
||||
QObject *qdict_entry_value(const QDictEntry *entry);
|
||||
size_t qdict_size(const QDict *qdict);
|
||||
void qdict_put_obj(QDict *qdict, const char *key, QObject *value);
|
||||
void qdict_del(QDict *qdict, const char *key);
|
||||
int qdict_haskey(const QDict *qdict, const char *key);
|
||||
QObject *qdict_get(const QDict *qdict, const char *key);
|
||||
QDict *qobject_to_qdict(const QObject *obj);
|
||||
void qdict_iter(const QDict *qdict,
|
||||
void (*iter)(const char *key, QObject *obj, void *opaque),
|
||||
void *opaque);
|
||||
const QDictEntry *qdict_first(const QDict *qdict);
|
||||
const QDictEntry *qdict_next(const QDict *qdict, const QDictEntry *entry);
|
||||
|
||||
/* Helper to qdict_put_obj(), accepts any object */
|
||||
#define qdict_put(qdict, key, obj) \
|
||||
qdict_put_obj(qdict, key, QOBJECT(obj))
|
||||
|
||||
/* High level helpers */
|
||||
double qdict_get_double(const QDict *qdict, const char *key);
|
||||
int64_t qdict_get_int(const QDict *qdict, const char *key);
|
||||
int qdict_get_bool(const QDict *qdict, const char *key);
|
||||
QList *qdict_get_qlist(const QDict *qdict, const char *key);
|
||||
QDict *qdict_get_qdict(const QDict *qdict, const char *key);
|
||||
const char *qdict_get_str(const QDict *qdict, const char *key);
|
||||
int64_t qdict_get_try_int(const QDict *qdict, const char *key,
|
||||
int64_t def_value);
|
||||
int qdict_get_try_bool(const QDict *qdict, const char *key, int def_value);
|
||||
const char *qdict_get_try_str(const QDict *qdict, const char *key);
|
||||
|
||||
QDict *qdict_clone_shallow(const QDict *src);
|
||||
void qdict_flatten(QDict *qdict);
|
||||
|
||||
void qdict_extract_subqdict(QDict *src, QDict **dst, const char *start);
|
||||
void qdict_array_split(QDict *src, QList **dst);
|
||||
|
||||
void qdict_join(QDict *dest, QDict *src, bool overwrite);
|
||||
|
||||
#endif /* QDICT_H */
|
||||
155
qemu/include/qapi/qmp/qerror.h
Normal file
155
qemu/include/qapi/qmp/qerror.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* QError Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
#ifndef QERROR_H
|
||||
#define QERROR_H
|
||||
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi-types.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
typedef struct QError {
|
||||
QObject_HEAD;
|
||||
char *err_msg;
|
||||
ErrorClass err_class;
|
||||
} QError;
|
||||
|
||||
QString *qerror_human(const QError *qerror);
|
||||
void qerror_report(ErrorClass err_class, const char *fmt, ...) GCC_FMT_ATTR(2, 3);
|
||||
void qerror_report_err(Error *err);
|
||||
|
||||
/*
|
||||
* QError class list
|
||||
* Please keep the definitions in alphabetical order.
|
||||
* Use scripts/check-qerror.sh to check.
|
||||
*/
|
||||
#define QERR_BASE_NOT_FOUND \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Base '%s' not found"
|
||||
|
||||
#define QERR_BLOCK_JOB_NOT_ACTIVE \
|
||||
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No active block job on device '%s'"
|
||||
|
||||
#define QERR_BLOCK_JOB_NOT_READY \
|
||||
ERROR_CLASS_GENERIC_ERROR, "The active block job for device '%s' cannot be completed"
|
||||
|
||||
#define QERR_BLOCK_FORMAT_FEATURE_NOT_SUPPORTED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Block format '%s' used by device '%s' does not support feature '%s'"
|
||||
|
||||
#define QERR_BUS_NO_HOTPLUG \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' does not support hotplugging"
|
||||
|
||||
#define QERR_BUS_NOT_FOUND \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Bus '%s' not found"
|
||||
|
||||
#define QERR_COMMAND_NOT_FOUND \
|
||||
ERROR_CLASS_COMMAND_NOT_FOUND, "The command %s has not been found"
|
||||
|
||||
#define QERR_DEVICE_ENCRYPTED \
|
||||
ERROR_CLASS_DEVICE_ENCRYPTED, "'%s' (%s) is encrypted"
|
||||
|
||||
#define QERR_DEVICE_HAS_NO_MEDIUM \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' has no medium"
|
||||
|
||||
#define QERR_DEVICE_INIT_FAILED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' could not be initialized"
|
||||
|
||||
#define QERR_DEVICE_IN_USE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is in use"
|
||||
|
||||
#define QERR_DEVICE_IS_READ_ONLY \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is read only"
|
||||
|
||||
#define QERR_DEVICE_NO_HOTPLUG \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' does not support hotplugging"
|
||||
|
||||
#define QERR_DEVICE_NOT_ACTIVE \
|
||||
ERROR_CLASS_DEVICE_NOT_ACTIVE, "No %s device has been activated"
|
||||
|
||||
#define QERR_DEVICE_NOT_ENCRYPTED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Device '%s' is not encrypted"
|
||||
|
||||
#define QERR_DEVICE_NOT_FOUND \
|
||||
ERROR_CLASS_DEVICE_NOT_FOUND, "Device '%s' not found"
|
||||
|
||||
#define QERR_FD_NOT_FOUND \
|
||||
ERROR_CLASS_GENERIC_ERROR, "File descriptor named '%s' not found"
|
||||
|
||||
#define QERR_FD_NOT_SUPPLIED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "No file descriptor supplied via SCM_RIGHTS"
|
||||
|
||||
#define QERR_FEATURE_DISABLED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "The feature '%s' is not enabled"
|
||||
|
||||
#define QERR_INVALID_BLOCK_FORMAT \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid block format '%s'"
|
||||
|
||||
#define QERR_INVALID_PARAMETER \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter '%s'"
|
||||
|
||||
#define QERR_INVALID_PARAMETER_TYPE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid parameter type for '%s', expected: %s"
|
||||
|
||||
#define QERR_INVALID_PARAMETER_VALUE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' expects %s"
|
||||
|
||||
#define QERR_INVALID_PASSWORD \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Password incorrect"
|
||||
|
||||
#define QERR_IO_ERROR \
|
||||
ERROR_CLASS_GENERIC_ERROR, "An IO error has occurred"
|
||||
|
||||
#define QERR_JSON_PARSING \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Invalid JSON syntax"
|
||||
|
||||
#define QERR_KVM_MISSING_CAP \
|
||||
ERROR_CLASS_KVM_MISSING_CAP, "Using KVM without %s, %s unavailable"
|
||||
|
||||
#define QERR_MIGRATION_ACTIVE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "There's a migration process in progress"
|
||||
|
||||
#define QERR_MISSING_PARAMETER \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Parameter '%s' is missing"
|
||||
|
||||
#define QERR_PERMISSION_DENIED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Insufficient permission to perform this operation"
|
||||
|
||||
#define QERR_PROPERTY_VALUE_BAD \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Property '%s.%s' doesn't take value '%s'"
|
||||
|
||||
#define QERR_PROPERTY_VALUE_OUT_OF_RANGE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Property %s.%s doesn't take value %" PRId64 " (minimum: %" PRId64 ", maximum: %" PRId64 ")"
|
||||
|
||||
#define QERR_QGA_COMMAND_FAILED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Guest agent command failed, error was '%s'"
|
||||
|
||||
#define QERR_QMP_BAD_INPUT_OBJECT \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Expected '%s' in QMP input"
|
||||
|
||||
#define QERR_QMP_BAD_INPUT_OBJECT_MEMBER \
|
||||
ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' expects '%s'"
|
||||
|
||||
#define QERR_QMP_EXTRA_MEMBER \
|
||||
ERROR_CLASS_GENERIC_ERROR, "QMP input object member '%s' is unexpected"
|
||||
|
||||
#define QERR_SET_PASSWD_FAILED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "Could not set password"
|
||||
|
||||
#define QERR_UNDEFINED_ERROR \
|
||||
ERROR_CLASS_GENERIC_ERROR, "An undefined error has occurred"
|
||||
|
||||
#define QERR_UNKNOWN_BLOCK_FORMAT_FEATURE \
|
||||
ERROR_CLASS_GENERIC_ERROR, "'%s' uses a %s feature which is not supported by this qemu version: %s"
|
||||
|
||||
#define QERR_UNSUPPORTED \
|
||||
ERROR_CLASS_GENERIC_ERROR, "this feature or command is not currently supported"
|
||||
|
||||
#endif /* QERROR_H */
|
||||
29
qemu/include/qapi/qmp/qfloat.h
Normal file
29
qemu/include/qapi/qmp/qfloat.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* QFloat Module
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QFLOAT_H
|
||||
#define QFLOAT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QFloat {
|
||||
QObject_HEAD;
|
||||
double value;
|
||||
} QFloat;
|
||||
|
||||
QFloat *qfloat_from_double(double value);
|
||||
double qfloat_get_double(const QFloat *qi);
|
||||
QFloat *qobject_to_qfloat(const QObject *obj);
|
||||
|
||||
#endif /* QFLOAT_H */
|
||||
28
qemu/include/qapi/qmp/qint.h
Normal file
28
qemu/include/qapi/qmp/qint.h
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* QInt Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QINT_H
|
||||
#define QINT_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QInt {
|
||||
QObject_HEAD;
|
||||
int64_t value;
|
||||
} QInt;
|
||||
|
||||
QInt *qint_from_int(int64_t value);
|
||||
int64_t qint_get_int(const QInt *qi);
|
||||
QInt *qobject_to_qint(const QObject *obj);
|
||||
|
||||
#endif /* QINT_H */
|
||||
29
qemu/include/qapi/qmp/qjson.h
Normal file
29
qemu/include/qapi/qmp/qjson.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* QObject JSON integration
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QJSON_H
|
||||
#define QJSON_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "qemu/compiler.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
|
||||
QObject *qobject_from_json(const char *string);
|
||||
QObject *qobject_from_jsonf(const char *string, ...) GCC_FMT_ATTR(1, 2);
|
||||
QObject *qobject_from_jsonv(const char *string, va_list *ap) GCC_FMT_ATTR(1, 0);
|
||||
|
||||
QString *qobject_to_json(const QObject *obj);
|
||||
QString *qobject_to_json_pretty(const QObject *obj);
|
||||
|
||||
#endif /* QJSON_H */
|
||||
63
qemu/include/qapi/qmp/qlist.h
Normal file
63
qemu/include/qapi/qmp/qlist.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* QList Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QLIST_H
|
||||
#define QLIST_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct QListEntry {
|
||||
QObject *value;
|
||||
QTAILQ_ENTRY(QListEntry) next;
|
||||
} QListEntry;
|
||||
|
||||
typedef struct QList {
|
||||
QObject_HEAD;
|
||||
QTAILQ_HEAD(,QListEntry) head;
|
||||
} QList;
|
||||
|
||||
#define qlist_append(qlist, obj) \
|
||||
qlist_append_obj(qlist, QOBJECT(obj))
|
||||
|
||||
#define QLIST_FOREACH_ENTRY(qlist, var) \
|
||||
for ((var) = ((qlist)->head.tqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->next.tqe_next))
|
||||
|
||||
static inline QObject *qlist_entry_obj(const QListEntry *entry)
|
||||
{
|
||||
return entry->value;
|
||||
}
|
||||
|
||||
QList *qlist_new(void);
|
||||
QList *qlist_copy(QList *src);
|
||||
void qlist_append_obj(QList *qlist, QObject *obj);
|
||||
void qlist_iter(const QList *qlist,
|
||||
void (*iter)(QObject *obj, void *opaque), void *opaque);
|
||||
QObject *qlist_pop(QList *qlist);
|
||||
QObject *qlist_peek(QList *qlist);
|
||||
int qlist_empty(const QList *qlist);
|
||||
size_t qlist_size(const QList *qlist);
|
||||
QList *qobject_to_qlist(const QObject *obj);
|
||||
|
||||
static inline const QListEntry *qlist_first(const QList *qlist)
|
||||
{
|
||||
return QTAILQ_FIRST(&qlist->head);
|
||||
}
|
||||
|
||||
static inline const QListEntry *qlist_next(const QListEntry *entry)
|
||||
{
|
||||
return QTAILQ_NEXT(entry, next);
|
||||
}
|
||||
|
||||
#endif /* QLIST_H */
|
||||
113
qemu/include/qapi/qmp/qobject.h
Normal file
113
qemu/include/qapi/qmp/qobject.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* QEMU Object Model.
|
||||
*
|
||||
* Based on ideas by Avi Kivity <avi@redhat.com>
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
* QObject Reference Counts Terminology
|
||||
* ------------------------------------
|
||||
*
|
||||
* - Returning references: A function that returns an object may
|
||||
* return it as either a weak or a strong reference. If the reference
|
||||
* is strong, you are responsible for calling QDECREF() on the reference
|
||||
* when you are done.
|
||||
*
|
||||
* If the reference is weak, the owner of the reference may free it at
|
||||
* any time in the future. Before storing the reference anywhere, you
|
||||
* should call QINCREF() to make the reference strong.
|
||||
*
|
||||
* - Transferring ownership: when you transfer ownership of a reference
|
||||
* by calling a function, you are no longer responsible for calling
|
||||
* QDECREF() when the reference is no longer needed. In other words,
|
||||
* when the function returns you must behave as if the reference to the
|
||||
* passed object was weak.
|
||||
*/
|
||||
#ifndef QOBJECT_H
|
||||
#define QOBJECT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef enum {
|
||||
QTYPE_NONE,
|
||||
QTYPE_QINT,
|
||||
QTYPE_QSTRING,
|
||||
QTYPE_QDICT,
|
||||
QTYPE_QLIST,
|
||||
QTYPE_QFLOAT,
|
||||
QTYPE_QBOOL,
|
||||
QTYPE_QERROR,
|
||||
QTYPE_MAX,
|
||||
} qtype_code;
|
||||
|
||||
struct QObject;
|
||||
|
||||
typedef struct QType {
|
||||
qtype_code code;
|
||||
void (*destroy)(struct QObject *);
|
||||
} QType;
|
||||
|
||||
typedef struct QObject {
|
||||
const QType *type;
|
||||
size_t refcnt;
|
||||
} QObject;
|
||||
|
||||
/* Objects definitions must include this */
|
||||
#define QObject_HEAD \
|
||||
QObject base
|
||||
|
||||
/* Get the 'base' part of an object */
|
||||
#define QOBJECT(obj) (&(obj)->base)
|
||||
|
||||
/* High-level interface for qobject_incref() */
|
||||
#define QINCREF(obj) \
|
||||
qobject_incref(QOBJECT(obj))
|
||||
|
||||
/* High-level interface for qobject_decref() */
|
||||
#define QDECREF(obj) \
|
||||
qobject_decref(obj ? QOBJECT(obj) : NULL)
|
||||
|
||||
/* Initialize an object to default values */
|
||||
#define QOBJECT_INIT(obj, qtype_type) \
|
||||
obj->base.refcnt = 1; \
|
||||
obj->base.type = qtype_type
|
||||
|
||||
/**
|
||||
* qobject_incref(): Increment QObject's reference count
|
||||
*/
|
||||
static inline void qobject_incref(QObject *obj)
|
||||
{
|
||||
if (obj)
|
||||
obj->refcnt++;
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_decref(): Decrement QObject's reference count, deallocate
|
||||
* when it reaches zero
|
||||
*/
|
||||
static inline void qobject_decref(QObject *obj)
|
||||
{
|
||||
if (obj && --obj->refcnt == 0) {
|
||||
assert(obj->type != NULL);
|
||||
assert(obj->type->destroy != NULL);
|
||||
obj->type->destroy(obj);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* qobject_type(): Return the QObject's type
|
||||
*/
|
||||
static inline qtype_code qobject_type(const QObject *obj)
|
||||
{
|
||||
assert(obj->type != NULL);
|
||||
return obj->type->code;
|
||||
}
|
||||
|
||||
#endif /* QOBJECT_H */
|
||||
36
qemu/include/qapi/qmp/qstring.h
Normal file
36
qemu/include/qapi/qmp/qstring.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* QString Module
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QSTRING_H
|
||||
#define QSTRING_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qapi/qmp/qobject.h"
|
||||
|
||||
typedef struct QString {
|
||||
QObject_HEAD;
|
||||
char *string;
|
||||
size_t length;
|
||||
size_t capacity;
|
||||
} QString;
|
||||
|
||||
QString *qstring_new(void);
|
||||
QString *qstring_from_str(const char *str);
|
||||
QString *qstring_from_substr(const char *str, int start, int end);
|
||||
size_t qstring_get_length(const QString *qstring);
|
||||
const char *qstring_get_str(const QString *qstring);
|
||||
void qstring_append_int(QString *qstring, int64_t value);
|
||||
void qstring_append(QString *qstring, const char *str);
|
||||
void qstring_append_chr(QString *qstring, int c);
|
||||
QString *qobject_to_qstring(const QObject *obj);
|
||||
|
||||
#endif /* QSTRING_H */
|
||||
25
qemu/include/qapi/qmp/types.h
Normal file
25
qemu/include/qapi/qmp/types.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Include all QEMU objects.
|
||||
*
|
||||
* Copyright (C) 2009 Red Hat Inc.
|
||||
*
|
||||
* Authors:
|
||||
* Luiz Capitulino <lcapitulino@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_OBJECTS_H
|
||||
#define QEMU_OBJECTS_H
|
||||
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/qmp/qint.h"
|
||||
#include "qapi/qmp/qfloat.h"
|
||||
#include "qapi/qmp/qbool.h"
|
||||
#include "qapi/qmp/qstring.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
#include "qapi/qmp/qlist.h"
|
||||
#include "qapi/qmp/qjson.h"
|
||||
|
||||
#endif /* QEMU_OBJECTS_H */
|
||||
25
qemu/include/qapi/string-input-visitor.h
Normal file
25
qemu/include/qapi/string-input-visitor.h
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* String parsing Visitor
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2012
|
||||
*
|
||||
* Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STRING_INPUT_VISITOR_H
|
||||
#define STRING_INPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
typedef struct StringInputVisitor StringInputVisitor;
|
||||
|
||||
StringInputVisitor *string_input_visitor_new(const char *str);
|
||||
void string_input_visitor_cleanup(StringInputVisitor *v);
|
||||
|
||||
Visitor *string_input_get_visitor(StringInputVisitor *v);
|
||||
|
||||
#endif
|
||||
26
qemu/include/qapi/string-output-visitor.h
Normal file
26
qemu/include/qapi/string-output-visitor.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* String printing Visitor
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2012
|
||||
*
|
||||
* Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef STRING_OUTPUT_VISITOR_H
|
||||
#define STRING_OUTPUT_VISITOR_H
|
||||
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
typedef struct StringOutputVisitor StringOutputVisitor;
|
||||
|
||||
StringOutputVisitor *string_output_visitor_new(bool human);
|
||||
void string_output_visitor_cleanup(StringOutputVisitor *v);
|
||||
|
||||
char *string_output_get_string(StringOutputVisitor *v);
|
||||
Visitor *string_output_get_visitor(StringOutputVisitor *v);
|
||||
|
||||
#endif
|
||||
17
qemu/include/qapi/util.h
Normal file
17
qemu/include/qapi/util.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* QAPI util functions
|
||||
*
|
||||
* Copyright Fujitsu, Inc. 2014
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QAPI_UTIL_H
|
||||
#define QAPI_UTIL_H
|
||||
|
||||
int qapi_enum_parse(const char *lookup[], const char *buf,
|
||||
int max, int def, Error **errp);
|
||||
|
||||
#endif
|
||||
67
qemu/include/qapi/visitor-impl.h
Normal file
67
qemu/include/qapi/visitor-impl.h
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Core Definitions for QAPI Visitor implementations
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Author: Paolo Bonizni <pbonzini@redhat.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#ifndef QAPI_VISITOR_IMPL_H
|
||||
#define QAPI_VISITOR_IMPL_H
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/visitor.h"
|
||||
|
||||
struct Visitor
|
||||
{
|
||||
/* Must be set */
|
||||
void (*start_struct)(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, size_t size, Error **errp);
|
||||
void (*end_struct)(Visitor *v, Error **errp);
|
||||
|
||||
void (*start_implicit_struct)(Visitor *v, void **obj, size_t size,
|
||||
Error **errp);
|
||||
void (*end_implicit_struct)(Visitor *v, Error **errp);
|
||||
|
||||
void (*start_list)(Visitor *v, const char *name, Error **errp);
|
||||
GenericList *(*next_list)(Visitor *v, GenericList **list, Error **errp);
|
||||
void (*end_list)(Visitor *v, Error **errp);
|
||||
|
||||
void (*type_enum)(Visitor *v, int *obj, const char *strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
void (*get_next_type)(Visitor *v, int *kind, const int *qobjects,
|
||||
const char *name, Error **errp);
|
||||
|
||||
void (*type_int)(Visitor *v, int64_t *obj, const char *name, Error **errp);
|
||||
void (*type_bool)(Visitor *v, bool *obj, const char *name, Error **errp);
|
||||
void (*type_str)(Visitor *v, char **obj, const char *name, Error **errp);
|
||||
void (*type_number)(Visitor *v, double *obj, const char *name,
|
||||
Error **errp);
|
||||
|
||||
/* May be NULL */
|
||||
void (*optional)(Visitor *v, bool *present, const char *name,
|
||||
Error **errp);
|
||||
|
||||
void (*type_uint8)(Visitor *v, uint8_t *obj, const char *name, Error **errp);
|
||||
void (*type_uint16)(Visitor *v, uint16_t *obj, const char *name, Error **errp);
|
||||
void (*type_uint32)(Visitor *v, uint32_t *obj, const char *name, Error **errp);
|
||||
void (*type_uint64)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
|
||||
void (*type_int8)(Visitor *v, int8_t *obj, const char *name, Error **errp);
|
||||
void (*type_int16)(Visitor *v, int16_t *obj, const char *name, Error **errp);
|
||||
void (*type_int32)(Visitor *v, int32_t *obj, const char *name, Error **errp);
|
||||
void (*type_int64)(Visitor *v, int64_t *obj, const char *name, Error **errp);
|
||||
/* visit_type_size() falls back to (*type_uint64)() if type_size is unset */
|
||||
void (*type_size)(Visitor *v, uint64_t *obj, const char *name, Error **errp);
|
||||
bool (*start_union)(Visitor *v, bool data_present, Error **errp);
|
||||
void (*end_union)(Visitor *v, bool data_present, Error **errp);
|
||||
};
|
||||
|
||||
void input_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
void output_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
|
||||
#endif
|
||||
64
qemu/include/qapi/visitor.h
Normal file
64
qemu/include/qapi/visitor.h
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Core Definitions for QAPI Visitor Classes
|
||||
*
|
||||
* Copyright IBM, Corp. 2011
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
#ifndef QAPI_VISITOR_CORE_H
|
||||
#define QAPI_VISITOR_CORE_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qapi/qmp/qobject.h"
|
||||
#include "qapi/error.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct GenericList
|
||||
{
|
||||
union {
|
||||
void *value;
|
||||
uint64_t padding;
|
||||
};
|
||||
struct GenericList *next;
|
||||
} GenericList;
|
||||
|
||||
void visit_start_handle(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, Error **errp);
|
||||
void visit_end_handle(Visitor *v, Error **errp);
|
||||
void visit_start_struct(Visitor *v, void **obj, const char *kind,
|
||||
const char *name, size_t size, Error **errp);
|
||||
void visit_end_struct(Visitor *v, Error **errp);
|
||||
void visit_start_implicit_struct(Visitor *v, void **obj, size_t size,
|
||||
Error **errp);
|
||||
void visit_end_implicit_struct(Visitor *v, Error **errp);
|
||||
void visit_start_list(Visitor *v, const char *name, Error **errp);
|
||||
GenericList *visit_next_list(Visitor *v, GenericList **list, Error **errp);
|
||||
void visit_end_list(Visitor *v, Error **errp);
|
||||
void visit_optional(Visitor *v, bool *present, const char *name,
|
||||
Error **errp);
|
||||
void visit_get_next_type(Visitor *v, int *obj, const int *qtypes,
|
||||
const char *name, Error **errp);
|
||||
void visit_type_enum(Visitor *v, int *obj, const char *strings[],
|
||||
const char *kind, const char *name, Error **errp);
|
||||
void visit_type_int(Visitor *v, int64_t *obj, const char *name, Error **errp);
|
||||
void visit_type_uint8(Visitor *v, uint8_t *obj, const char *name, Error **errp);
|
||||
void visit_type_uint16(Visitor *v, uint16_t *obj, const char *name, Error **errp);
|
||||
void visit_type_uint32(Visitor *v, uint32_t *obj, const char *name, Error **errp);
|
||||
void visit_type_uint64(Visitor *v, uint64_t *obj, const char *name, Error **errp);
|
||||
void visit_type_int8(Visitor *v, int8_t *obj, const char *name, Error **errp);
|
||||
void visit_type_int16(Visitor *v, int16_t *obj, const char *name, Error **errp);
|
||||
void visit_type_int32(Visitor *v, int32_t *obj, const char *name, Error **errp);
|
||||
void visit_type_int64(Visitor *v, int64_t *obj, const char *name, Error **errp);
|
||||
void visit_type_size(Visitor *v, uint64_t *obj, const char *name, Error **errp);
|
||||
void visit_type_bool(Visitor *v, bool *obj, const char *name, Error **errp);
|
||||
void visit_type_str(Visitor *v, char **obj, const char *name, Error **errp);
|
||||
void visit_type_number(Visitor *v, double *obj, const char *name, Error **errp);
|
||||
bool visit_start_union(Visitor *v, bool data_present, Error **errp);
|
||||
void visit_end_union(Visitor *v, bool data_present, Error **errp);
|
||||
|
||||
#endif
|
||||
353
qemu/include/qemu-common.h
Normal file
353
qemu/include/qemu-common.h
Normal file
@@ -0,0 +1,353 @@
|
||||
|
||||
/* Common header file that is included by all of QEMU.
|
||||
*
|
||||
* This file is supposed to be included only by .c files. No header file should
|
||||
* depend on qemu-common.h, as this would easily lead to circular header
|
||||
* dependencies.
|
||||
*
|
||||
* If a header file uses a definition from qemu-common.h, that definition
|
||||
* must be moved to a separate header file, and the header that uses it
|
||||
* must include that header.
|
||||
*/
|
||||
#ifndef QEMU_COMMON_H
|
||||
#define QEMU_COMMON_H
|
||||
|
||||
#include "qemu/compiler.h"
|
||||
#include "config-host.h"
|
||||
#include "qemu/typedefs.h"
|
||||
#include "exec/cpu-common.h"
|
||||
|
||||
#if defined(__arm__) || defined(__sparc__) || defined(__mips__) || defined(__hppa__) || defined(__ia64__)
|
||||
#define WORDS_ALIGNED
|
||||
#endif
|
||||
|
||||
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
|
||||
|
||||
/* we put basic includes here to avoid repeating them in device drivers */
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <time.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include "glib-compat.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "sysemu/os-win32.h"
|
||||
#endif
|
||||
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
#endif
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0
|
||||
#endif
|
||||
#ifndef MAP_ANONYMOUS
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif
|
||||
#ifndef ENOMEDIUM
|
||||
#define ENOMEDIUM ENODEV
|
||||
#endif
|
||||
#if !defined(ENOTSUP)
|
||||
#define ENOTSUP 4096
|
||||
#endif
|
||||
#if !defined(ECANCELED)
|
||||
#define ECANCELED 4097
|
||||
#endif
|
||||
#if !defined(EMEDIUMTYPE)
|
||||
#define EMEDIUMTYPE 4098
|
||||
#endif
|
||||
#ifndef TIME_MAX
|
||||
#define TIME_MAX LONG_MAX
|
||||
#endif
|
||||
|
||||
/* HOST_LONG_BITS is the size of a native pointer in bits. */
|
||||
#if UINTPTR_MAX == UINT32_MAX
|
||||
# define HOST_LONG_BITS 32
|
||||
#elif UINTPTR_MAX == UINT64_MAX
|
||||
# define HOST_LONG_BITS 64
|
||||
#else
|
||||
# error Unknown pointer size
|
||||
#endif
|
||||
|
||||
typedef int (*fprintf_function)(FILE *f, const char *fmt, ...)
|
||||
GCC_FMT_ATTR(2, 3);
|
||||
|
||||
#ifdef _WIN32
|
||||
#define fsync _commit
|
||||
#if !defined(lseek)
|
||||
# define lseek _lseeki64
|
||||
#endif
|
||||
int qemu_ftruncate64(int, int64_t);
|
||||
#if !defined(ftruncate)
|
||||
# define ftruncate qemu_ftruncate64
|
||||
#endif
|
||||
|
||||
static inline char *realpath(const char *path, char *resolved_path)
|
||||
{
|
||||
_fullpath(resolved_path, path, _MAX_PATH);
|
||||
return resolved_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
void cpu_ticks_init(void);
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bswap.h"
|
||||
|
||||
/* FIXME: Remove NEED_CPU_H. */
|
||||
#ifdef NEED_CPU_H
|
||||
#include "cpu.h"
|
||||
#endif /* !defined(NEED_CPU_H) */
|
||||
|
||||
/* main function, renamed */
|
||||
#if defined(CONFIG_COCOA)
|
||||
int qemu_main(int argc, char **argv, char **envp);
|
||||
#endif
|
||||
|
||||
void qemu_get_timedate(struct tm *tm, int offset);
|
||||
int qemu_timedate_diff(struct tm *tm);
|
||||
|
||||
/**
|
||||
* is_help_option:
|
||||
* @s: string to test
|
||||
*
|
||||
* Check whether @s is one of the standard strings which indicate
|
||||
* that the user is asking for a list of the valid values for a
|
||||
* command option like -cpu or -M. The current accepted strings
|
||||
* are 'help' and '?'. '?' is deprecated (it is a shell wildcard
|
||||
* which makes it annoying to use in a reliable way) but provided
|
||||
* for backwards compatibility.
|
||||
*
|
||||
* Returns: true if @s is a request for a list.
|
||||
*/
|
||||
static inline bool is_help_option(const char *s)
|
||||
{
|
||||
return !strcmp(s, "?") || !strcmp(s, "help");
|
||||
}
|
||||
|
||||
/* cutils.c */
|
||||
void pstrcpy(char *buf, int buf_size, const char *str);
|
||||
void strpadcpy(char *buf, int buf_size, const char *str, char pad);
|
||||
char *pstrcat(char *buf, int buf_size, const char *s);
|
||||
int strstart(const char *str, const char *val, const char **ptr);
|
||||
int stristart(const char *str, const char *val, const char **ptr);
|
||||
int qemu_strnlen(const char *s, int max_len);
|
||||
char *qemu_strsep(char **input, const char *delim);
|
||||
time_t mktimegm(struct tm *tm);
|
||||
int qemu_fls(int i);
|
||||
int qemu_fdatasync(int fd);
|
||||
int fcntl_setfl(int fd, int flag);
|
||||
int qemu_parse_fd(const char *param);
|
||||
|
||||
int parse_uint(const char *s, unsigned long long *value, char **endptr,
|
||||
int base);
|
||||
int parse_uint_full(const char *s, unsigned long long *value, int base);
|
||||
|
||||
/*
|
||||
* strtosz() suffixes used to specify the default treatment of an
|
||||
* argument passed to strtosz() without an explicit suffix.
|
||||
* These should be defined using upper case characters in the range
|
||||
* A-Z, as strtosz() will use qemu_toupper() on the given argument
|
||||
* prior to comparison.
|
||||
*/
|
||||
#define STRTOSZ_DEFSUFFIX_EB 'E'
|
||||
#define STRTOSZ_DEFSUFFIX_PB 'P'
|
||||
#define STRTOSZ_DEFSUFFIX_TB 'T'
|
||||
#define STRTOSZ_DEFSUFFIX_GB 'G'
|
||||
#define STRTOSZ_DEFSUFFIX_MB 'M'
|
||||
#define STRTOSZ_DEFSUFFIX_KB 'K'
|
||||
#define STRTOSZ_DEFSUFFIX_B 'B'
|
||||
int64_t strtosz(const char *nptr, char **end);
|
||||
int64_t strtosz_suffix(const char *nptr, char **end, const char default_suffix);
|
||||
int64_t strtosz_suffix_unit(const char *nptr, char **end,
|
||||
const char default_suffix, int64_t unit);
|
||||
|
||||
/* used to print char* safely */
|
||||
#define STR_OR_NULL(str) ((str) ? (str) : "null")
|
||||
|
||||
/* id.c */
|
||||
bool id_wellformed(const char *id);
|
||||
|
||||
/* path.c */
|
||||
void init_paths(const char *prefix);
|
||||
const char *path(const char *pathname);
|
||||
|
||||
#define qemu_isalnum(c) isalnum((unsigned char)(c))
|
||||
#define qemu_isalpha(c) isalpha((unsigned char)(c))
|
||||
#define qemu_iscntrl(c) iscntrl((unsigned char)(c))
|
||||
#define qemu_isdigit(c) isdigit((unsigned char)(c))
|
||||
#define qemu_isgraph(c) isgraph((unsigned char)(c))
|
||||
#define qemu_islower(c) islower((unsigned char)(c))
|
||||
#define qemu_isprint(c) isprint((unsigned char)(c))
|
||||
#define qemu_ispunct(c) ispunct((unsigned char)(c))
|
||||
#define qemu_isspace(c) isspace((unsigned char)(c))
|
||||
#define qemu_isupper(c) isupper((unsigned char)(c))
|
||||
#define qemu_isxdigit(c) isxdigit((unsigned char)(c))
|
||||
#define qemu_tolower(c) tolower((unsigned char)(c))
|
||||
#define qemu_toupper(c) toupper((unsigned char)(c))
|
||||
#define qemu_isascii(c) isascii((unsigned char)(c))
|
||||
#define qemu_toascii(c) toascii((unsigned char)(c))
|
||||
|
||||
void *qemu_oom_check(void *ptr);
|
||||
|
||||
ssize_t qemu_write_full(int fd, const void *buf, size_t count)
|
||||
QEMU_WARN_UNUSED_RESULT;
|
||||
ssize_t qemu_send_full(int fd, const void *buf, size_t count, int flags)
|
||||
QEMU_WARN_UNUSED_RESULT;
|
||||
ssize_t qemu_recv_full(int fd, void *buf, size_t count, int flags)
|
||||
QEMU_WARN_UNUSED_RESULT;
|
||||
|
||||
#ifndef _WIN32
|
||||
int qemu_pipe(int pipefd[2]);
|
||||
/* like openpty() but also makes it raw; return master fd */
|
||||
int qemu_openpty_raw(int *aslave, char *pty_name);
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
/* MinGW needs type casts for the 'buf' and 'optval' arguments. */
|
||||
#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
|
||||
getsockopt(sockfd, level, optname, (void *)optval, optlen)
|
||||
#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
|
||||
setsockopt(sockfd, level, optname, (const void *)optval, optlen)
|
||||
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, (void *)buf, len, flags)
|
||||
#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
|
||||
sendto(sockfd, (const void *)buf, len, flags, destaddr, addrlen)
|
||||
#else
|
||||
#define qemu_getsockopt(sockfd, level, optname, optval, optlen) \
|
||||
getsockopt(sockfd, level, optname, optval, optlen)
|
||||
#define qemu_setsockopt(sockfd, level, optname, optval, optlen) \
|
||||
setsockopt(sockfd, level, optname, optval, optlen)
|
||||
#define qemu_recv(sockfd, buf, len, flags) recv(sockfd, buf, len, flags)
|
||||
#define qemu_sendto(sockfd, buf, len, flags, destaddr, addrlen) \
|
||||
sendto(sockfd, buf, len, flags, destaddr, addrlen)
|
||||
#endif
|
||||
|
||||
/* Error handling. */
|
||||
|
||||
void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size);
|
||||
bool tcg_enabled(struct uc_struct *uc);
|
||||
|
||||
struct uc_struct;
|
||||
void cpu_exec_init_all(struct uc_struct *uc);
|
||||
|
||||
/* work queue */
|
||||
struct qemu_work_item {
|
||||
struct qemu_work_item *next;
|
||||
void (*func)(void *data);
|
||||
void *data;
|
||||
int done;
|
||||
bool free;
|
||||
};
|
||||
|
||||
/* Convert a byte between binary and BCD. */
|
||||
static inline uint8_t to_bcd(uint8_t val)
|
||||
{
|
||||
return ((val / 10) << 4) | (val % 10);
|
||||
}
|
||||
|
||||
static inline uint8_t from_bcd(uint8_t val)
|
||||
{
|
||||
return ((val >> 4) * 10) + (val & 0x0f);
|
||||
}
|
||||
|
||||
/* compute with 96 bit intermediate result: (a*b)/c */
|
||||
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
|
||||
{
|
||||
union {
|
||||
uint64_t ll;
|
||||
struct {
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
uint32_t high, low;
|
||||
#else
|
||||
uint32_t low, high;
|
||||
#endif
|
||||
} l;
|
||||
} u, res;
|
||||
uint64_t rl, rh;
|
||||
|
||||
u.ll = a;
|
||||
rl = (uint64_t)u.l.low * (uint64_t)b;
|
||||
rh = (uint64_t)u.l.high * (uint64_t)b;
|
||||
rh += (rl >> 32);
|
||||
res.l.high = rh / c;
|
||||
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
|
||||
return res.ll;
|
||||
}
|
||||
|
||||
/* Round number down to multiple */
|
||||
#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m))
|
||||
|
||||
/* Round number up to multiple */
|
||||
#define QEMU_ALIGN_UP(n, m) QEMU_ALIGN_DOWN((n) + (m) - 1, (m))
|
||||
|
||||
static inline bool is_power_of_2(uint64_t value)
|
||||
{
|
||||
if (!value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return !(value & (value - 1));
|
||||
}
|
||||
|
||||
/* round down to the nearest power of 2*/
|
||||
int64_t pow2floor(int64_t value);
|
||||
|
||||
#include "qemu/module.h"
|
||||
|
||||
/*
|
||||
* Implementation of ULEB128 (http://en.wikipedia.org/wiki/LEB128)
|
||||
* Input is limited to 14-bit numbers
|
||||
*/
|
||||
|
||||
int uleb128_encode_small(uint8_t *out, uint32_t n);
|
||||
int uleb128_decode_small(const uint8_t *in, uint32_t *n);
|
||||
|
||||
/* unicode.c */
|
||||
int mod_utf8_codepoint(const char *s, size_t n, char **end);
|
||||
|
||||
/*
|
||||
* Hexdump a buffer to a file. An optional string prefix is added to every line
|
||||
*/
|
||||
|
||||
void qemu_hexdump(const char *buf, FILE *fp, const char *prefix, size_t size);
|
||||
|
||||
/* vector definitions */
|
||||
#ifdef __ALTIVEC__
|
||||
#include <altivec.h>
|
||||
/* The altivec.h header says we're allowed to undef these for
|
||||
* C++ compatibility. Here we don't care about C++, but we
|
||||
* undef them anyway to avoid namespace pollution.
|
||||
*/
|
||||
#undef vector
|
||||
#undef pixel
|
||||
#undef bool
|
||||
#define VECTYPE __vector unsigned char
|
||||
#define SPLAT(p) vec_splat(vec_ld(0, p), 0)
|
||||
#define ALL_EQ(v1, v2) vec_all_eq(v1, v2)
|
||||
/* altivec.h may redefine the bool macro as vector type.
|
||||
* Reset it to POSIX semantics. */
|
||||
#define bool _Bool
|
||||
#elif defined __SSE2__
|
||||
#include <emmintrin.h>
|
||||
#define VECTYPE __m128i
|
||||
#define SPLAT(p) _mm_set1_epi8(*(p))
|
||||
#define ALL_EQ(v1, v2) (_mm_movemask_epi8(_mm_cmpeq_epi8(v1, v2)) == 0xFFFF)
|
||||
#else
|
||||
#define VECTYPE unsigned long
|
||||
#define SPLAT(p) (*(p) * (~0UL / 255))
|
||||
#define ALL_EQ(v1, v2) ((v1) == (v2))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
68
qemu/include/qemu/aes.h
Normal file
68
qemu/include/qemu/aes.h
Normal file
@@ -0,0 +1,68 @@
|
||||
#ifndef QEMU_AES_H
|
||||
#define QEMU_AES_H
|
||||
|
||||
#define AES_MAXNR 14
|
||||
#define AES_BLOCK_SIZE 16
|
||||
|
||||
struct aes_key_st {
|
||||
uint32_t rd_key[4 *(AES_MAXNR + 1)];
|
||||
int rounds;
|
||||
};
|
||||
typedef struct aes_key_st AES_KEY;
|
||||
|
||||
/* FreeBSD has its own AES_set_decrypt_key in -lcrypto, avoid conflicts */
|
||||
#ifdef __FreeBSD__
|
||||
#define AES_set_encrypt_key QEMU_AES_set_encrypt_key
|
||||
#define AES_set_decrypt_key QEMU_AES_set_decrypt_key
|
||||
#define AES_encrypt QEMU_AES_encrypt
|
||||
#define AES_decrypt QEMU_AES_decrypt
|
||||
#define AES_cbc_encrypt QEMU_AES_cbc_encrypt
|
||||
#endif
|
||||
|
||||
int AES_set_encrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
int AES_set_decrypt_key(const unsigned char *userKey, const int bits,
|
||||
AES_KEY *key);
|
||||
|
||||
void AES_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void AES_decrypt(const unsigned char *in, unsigned char *out,
|
||||
const AES_KEY *key);
|
||||
void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
|
||||
const unsigned long length, const AES_KEY *key,
|
||||
unsigned char *ivec, const int enc);
|
||||
|
||||
extern const uint8_t AES_sbox[256];
|
||||
extern const uint8_t AES_isbox[256];
|
||||
|
||||
/* AES ShiftRows and InvShiftRows */
|
||||
extern const uint8_t AES_shifts[16];
|
||||
extern const uint8_t AES_ishifts[16];
|
||||
|
||||
/* AES InvMixColumns */
|
||||
/* AES_imc[x][0] = [x].[0e, 09, 0d, 0b]; */
|
||||
/* AES_imc[x][1] = [x].[0b, 0e, 09, 0d]; */
|
||||
/* AES_imc[x][2] = [x].[0d, 0b, 0e, 09]; */
|
||||
/* AES_imc[x][3] = [x].[09, 0d, 0b, 0e]; */
|
||||
extern const uint32_t AES_imc[256][4];
|
||||
|
||||
/*
|
||||
AES_Te0[x] = S [x].[02, 01, 01, 03];
|
||||
AES_Te1[x] = S [x].[03, 02, 01, 01];
|
||||
AES_Te2[x] = S [x].[01, 03, 02, 01];
|
||||
AES_Te3[x] = S [x].[01, 01, 03, 02];
|
||||
AES_Te4[x] = S [x].[01, 01, 01, 01];
|
||||
|
||||
AES_Td0[x] = Si[x].[0e, 09, 0d, 0b];
|
||||
AES_Td1[x] = Si[x].[0b, 0e, 09, 0d];
|
||||
AES_Td2[x] = Si[x].[0d, 0b, 0e, 09];
|
||||
AES_Td3[x] = Si[x].[09, 0d, 0b, 0e];
|
||||
AES_Td4[x] = Si[x].[01, 01, 01, 01];
|
||||
*/
|
||||
|
||||
extern const uint32_t AES_Te0[256], AES_Te1[256], AES_Te2[256],
|
||||
AES_Te3[256], AES_Te4[256];
|
||||
extern const uint32_t AES_Td0[256], AES_Td1[256], AES_Td2[256],
|
||||
AES_Td3[256], AES_Td4[256];
|
||||
|
||||
#endif
|
||||
202
qemu/include/qemu/atomic.h
Normal file
202
qemu/include/qemu/atomic.h
Normal file
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Simple interface for atomic operations.
|
||||
*
|
||||
* Copyright (C) 2013 Red Hat, Inc.
|
||||
*
|
||||
* Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* 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 __QEMU_ATOMIC_H
|
||||
#define __QEMU_ATOMIC_H 1
|
||||
|
||||
#include "qemu/compiler.h"
|
||||
|
||||
/* For C11 atomic ops */
|
||||
|
||||
/* Compiler barrier */
|
||||
#define barrier() ({ asm volatile("" ::: "memory"); (void)0; })
|
||||
|
||||
#ifndef __ATOMIC_RELAXED
|
||||
|
||||
/*
|
||||
* We use GCC builtin if it's available, as that can use mfence on
|
||||
* 32-bit as well, e.g. if built with -march=pentium-m. However, on
|
||||
* i386 the spec is buggy, and the implementation followed it until
|
||||
* 4.3 (http://gcc.gnu.org/bugzilla/show_bug.cgi?id=36793).
|
||||
*/
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
#if !QEMU_GNUC_PREREQ(4, 4)
|
||||
#if defined __x86_64__
|
||||
#define smp_mb() ({ asm volatile("mfence" ::: "memory"); (void)0; })
|
||||
#else
|
||||
#define smp_mb() ({ asm volatile("lock; addl $0,0(%%esp) " ::: "memory"); (void)0; })
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __alpha__
|
||||
#define smp_read_barrier_depends() asm volatile("mb":::"memory")
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__) || defined(__s390x__)
|
||||
|
||||
/*
|
||||
* Because of the strongly ordered storage model, wmb() and rmb() are nops
|
||||
* here (a compiler barrier only). QEMU doesn't do accesses to write-combining
|
||||
* qemu memory or non-temporal load/stores from C code.
|
||||
*/
|
||||
#define smp_wmb() barrier()
|
||||
#define smp_rmb() barrier()
|
||||
|
||||
/*
|
||||
* __sync_lock_test_and_set() is documented to be an acquire barrier only,
|
||||
* but it is a full barrier at the hardware level. Add a compiler barrier
|
||||
* to make it a full barrier also at the compiler level.
|
||||
*/
|
||||
#define atomic_xchg(ptr, i) (barrier(), __sync_lock_test_and_set(ptr, i))
|
||||
|
||||
/*
|
||||
* Load/store with Java volatile semantics.
|
||||
*/
|
||||
#define atomic_mb_set(ptr, i) ((void)atomic_xchg(ptr, i))
|
||||
|
||||
#elif defined(_ARCH_PPC)
|
||||
|
||||
/*
|
||||
* We use an eieio() for wmb() on powerpc. This assumes we don't
|
||||
* need to order cacheable and non-cacheable stores with respect to
|
||||
* each other.
|
||||
*
|
||||
* smp_mb has the same problem as on x86 for not-very-new GCC
|
||||
* (http://patchwork.ozlabs.org/patch/126184/, Nov 2011).
|
||||
*/
|
||||
#define smp_wmb() ({ asm volatile("eieio" ::: "memory"); (void)0; })
|
||||
#if defined(__powerpc64__)
|
||||
#define smp_rmb() ({ asm volatile("lwsync" ::: "memory"); (void)0; })
|
||||
#else
|
||||
#define smp_rmb() ({ asm volatile("sync" ::: "memory"); (void)0; })
|
||||
#endif
|
||||
#define smp_mb() ({ asm volatile("sync" ::: "memory"); (void)0; })
|
||||
|
||||
#endif /* _ARCH_PPC */
|
||||
|
||||
#endif /* C11 atomics */
|
||||
|
||||
/*
|
||||
* For (host) platforms we don't have explicit barrier definitions
|
||||
* for, we use the gcc __sync_synchronize() primitive to generate a
|
||||
* full barrier. This should be safe on all platforms, though it may
|
||||
* be overkill for smp_wmb() and smp_rmb().
|
||||
*/
|
||||
#ifndef smp_mb
|
||||
#define smp_mb() __sync_synchronize()
|
||||
#endif
|
||||
|
||||
#ifndef smp_wmb
|
||||
#ifdef __ATOMIC_RELEASE
|
||||
#define smp_wmb() __atomic_thread_fence(__ATOMIC_RELEASE)
|
||||
#else
|
||||
#define smp_wmb() __sync_synchronize()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef smp_rmb
|
||||
#ifdef __ATOMIC_ACQUIRE
|
||||
#define smp_rmb() __atomic_thread_fence(__ATOMIC_ACQUIRE)
|
||||
#else
|
||||
#define smp_rmb() __sync_synchronize()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef smp_read_barrier_depends
|
||||
#ifdef __ATOMIC_CONSUME
|
||||
#define smp_read_barrier_depends() __atomic_thread_fence(__ATOMIC_CONSUME)
|
||||
#else
|
||||
#define smp_read_barrier_depends() barrier()
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef atomic_read
|
||||
#define atomic_read(ptr) (*(__typeof__(*ptr) *volatile) (ptr))
|
||||
#endif
|
||||
|
||||
#ifndef atomic_set
|
||||
#define atomic_set(ptr, i) ((*(__typeof__(*ptr) *volatile) (ptr)) = (i))
|
||||
#endif
|
||||
|
||||
/* These have the same semantics as Java volatile variables.
|
||||
* See http://gee.cs.oswego.edu/dl/jmm/cookbook.html:
|
||||
* "1. Issue a StoreStore barrier (wmb) before each volatile store."
|
||||
* 2. Issue a StoreLoad barrier after each volatile store.
|
||||
* Note that you could instead issue one before each volatile load, but
|
||||
* this would be slower for typical programs using volatiles in which
|
||||
* reads greatly outnumber writes. Alternatively, if available, you
|
||||
* can implement volatile store as an atomic instruction (for example
|
||||
* XCHG on x86) and omit the barrier. This may be more efficient if
|
||||
* atomic instructions are cheaper than StoreLoad barriers.
|
||||
* 3. Issue LoadLoad and LoadStore barriers after each volatile load."
|
||||
*
|
||||
* If you prefer to think in terms of "pairing" of memory barriers,
|
||||
* an atomic_mb_read pairs with an atomic_mb_set.
|
||||
*
|
||||
* And for the few ia64 lovers that exist, an atomic_mb_read is a ld.acq,
|
||||
* while an atomic_mb_set is a st.rel followed by a memory barrier.
|
||||
*
|
||||
* These are a bit weaker than __atomic_load/store with __ATOMIC_SEQ_CST
|
||||
* (see docs/atomics.txt), and I'm not sure that __ATOMIC_ACQ_REL is enough.
|
||||
* Just always use the barriers manually by the rules above.
|
||||
*/
|
||||
#ifndef atomic_mb_read
|
||||
#define atomic_mb_read(ptr) ({ \
|
||||
typeof(*ptr) _val = atomic_read(ptr); \
|
||||
smp_rmb(); \
|
||||
_val; \
|
||||
})
|
||||
#endif
|
||||
|
||||
#ifndef atomic_mb_set
|
||||
#define atomic_mb_set(ptr, i) do { \
|
||||
smp_wmb(); \
|
||||
atomic_set(ptr, i); \
|
||||
smp_mb(); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
#ifndef atomic_xchg
|
||||
#if defined(__clang__)
|
||||
#define atomic_xchg(ptr, i) __sync_swap(ptr, i)
|
||||
#elif defined(__ATOMIC_SEQ_CST)
|
||||
#define atomic_xchg(ptr, i) ({ \
|
||||
typeof(*ptr) _new = (i), _old; \
|
||||
__atomic_exchange(ptr, &_new, &_old, __ATOMIC_SEQ_CST); \
|
||||
_old; \
|
||||
})
|
||||
#else
|
||||
/* __sync_lock_test_and_set() is documented to be an acquire barrier only. */
|
||||
#define atomic_xchg(ptr, i) (smp_mb(), __sync_lock_test_and_set(ptr, i))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Provide shorter names for GCC atomic builtins. */
|
||||
#define atomic_fetch_inc(ptr) __sync_fetch_and_add(ptr, 1)
|
||||
#define atomic_fetch_dec(ptr) __sync_fetch_and_add(ptr, -1)
|
||||
#define atomic_fetch_add __sync_fetch_and_add
|
||||
#define atomic_fetch_sub __sync_fetch_and_sub
|
||||
#define atomic_fetch_and __sync_fetch_and_and
|
||||
#define atomic_fetch_or __sync_fetch_and_or
|
||||
#define atomic_cmpxchg __sync_val_compare_and_swap
|
||||
|
||||
/* And even shorter names that return void. */
|
||||
#define atomic_inc(ptr) ((void) __sync_fetch_and_add(ptr, 1))
|
||||
#define atomic_dec(ptr) ((void) __sync_fetch_and_add(ptr, -1))
|
||||
#define atomic_add(ptr, n) ((void) __sync_fetch_and_add(ptr, n))
|
||||
#define atomic_sub(ptr, n) ((void) __sync_fetch_and_sub(ptr, n))
|
||||
#define atomic_and(ptr, n) ((void) __sync_fetch_and_and(ptr, n))
|
||||
#define atomic_or(ptr, n) ((void) __sync_fetch_and_or(ptr, n))
|
||||
|
||||
#endif
|
||||
245
qemu/include/qemu/bitmap.h
Normal file
245
qemu/include/qemu/bitmap.h
Normal file
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Bitmap Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITMAP_H
|
||||
#define BITMAP_H
|
||||
|
||||
#include <glib.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/bitops.h"
|
||||
|
||||
/*
|
||||
* The available bitmap operations and their rough meaning in the
|
||||
* case that the bitmap is a single unsigned long are thus:
|
||||
*
|
||||
* Note that nbits should be always a compile time evaluable constant.
|
||||
* Otherwise many inlines will generate horrible code.
|
||||
*
|
||||
* bitmap_zero(dst, nbits) *dst = 0UL
|
||||
* bitmap_fill(dst, nbits) *dst = ~0UL
|
||||
* bitmap_copy(dst, src, nbits) *dst = *src
|
||||
* bitmap_and(dst, src1, src2, nbits) *dst = *src1 & *src2
|
||||
* bitmap_or(dst, src1, src2, nbits) *dst = *src1 | *src2
|
||||
* bitmap_xor(dst, src1, src2, nbits) *dst = *src1 ^ *src2
|
||||
* bitmap_andnot(dst, src1, src2, nbits) *dst = *src1 & ~(*src2)
|
||||
* bitmap_complement(dst, src, nbits) *dst = ~(*src)
|
||||
* bitmap_equal(src1, src2, nbits) Are *src1 and *src2 equal?
|
||||
* bitmap_intersects(src1, src2, nbits) Do *src1 and *src2 overlap?
|
||||
* bitmap_empty(src, nbits) Are all bits zero in *src?
|
||||
* bitmap_full(src, nbits) Are all bits set in *src?
|
||||
* bitmap_set(dst, pos, nbits) Set specified bit area
|
||||
* bitmap_clear(dst, pos, nbits) Clear specified bit area
|
||||
* bitmap_find_next_zero_area(buf, len, pos, n, mask) Find bit free area
|
||||
*/
|
||||
|
||||
/*
|
||||
* Also the following operations apply to bitmaps.
|
||||
*
|
||||
* set_bit(bit, addr) *addr |= bit
|
||||
* clear_bit(bit, addr) *addr &= ~bit
|
||||
* change_bit(bit, addr) *addr ^= bit
|
||||
* test_bit(bit, addr) Is bit set in *addr?
|
||||
* test_and_set_bit(bit, addr) Set bit and return old value
|
||||
* test_and_clear_bit(bit, addr) Clear bit and return old value
|
||||
* test_and_change_bit(bit, addr) Change bit and return old value
|
||||
* find_first_zero_bit(addr, nbits) Position first zero bit in *addr
|
||||
* find_first_bit(addr, nbits) Position first set bit in *addr
|
||||
* find_next_zero_bit(addr, nbits, bit) Position next zero bit in *addr >= bit
|
||||
* find_next_bit(addr, nbits, bit) Position next set bit in *addr >= bit
|
||||
*/
|
||||
|
||||
#define BITMAP_LAST_WORD_MASK(nbits) \
|
||||
( \
|
||||
((nbits) % BITS_PER_LONG) ? \
|
||||
(1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL \
|
||||
)
|
||||
|
||||
#define DECLARE_BITMAP(name,bits) \
|
||||
unsigned long name[BITS_TO_LONGS(bits)]
|
||||
|
||||
#define small_nbits(nbits) \
|
||||
((nbits) <= BITS_PER_LONG)
|
||||
|
||||
int slow_bitmap_empty(const unsigned long *bitmap, long bits);
|
||||
int slow_bitmap_full(const unsigned long *bitmap, long bits);
|
||||
int slow_bitmap_equal(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_complement(unsigned long *dst, const unsigned long *src,
|
||||
long bits);
|
||||
void slow_bitmap_shift_right(unsigned long *dst,
|
||||
const unsigned long *src, int shift, long bits);
|
||||
void slow_bitmap_shift_left(unsigned long *dst,
|
||||
const unsigned long *src, int shift, long bits);
|
||||
int slow_bitmap_and(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_or(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
void slow_bitmap_xor(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
int slow_bitmap_andnot(unsigned long *dst, const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
int slow_bitmap_intersects(const unsigned long *bitmap1,
|
||||
const unsigned long *bitmap2, long bits);
|
||||
|
||||
static inline unsigned long *bitmap_try_new(long nbits)
|
||||
{
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
return g_try_malloc0(len);
|
||||
}
|
||||
|
||||
static inline unsigned long *bitmap_new(long nbits)
|
||||
{
|
||||
unsigned long *ptr = bitmap_try_new(nbits);
|
||||
if (ptr == NULL) {
|
||||
abort();
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
|
||||
static inline void bitmap_zero(unsigned long *dst, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = 0UL;
|
||||
} else {
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memset(dst, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_fill(unsigned long *dst, long nbits)
|
||||
{
|
||||
size_t nlongs = BITS_TO_LONGS(nbits);
|
||||
if (!small_nbits(nbits)) {
|
||||
long len = (nlongs - 1) * sizeof(unsigned long);
|
||||
memset(dst, 0xff, len);
|
||||
}
|
||||
dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_copy(unsigned long *dst, const unsigned long *src,
|
||||
long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src;
|
||||
} else {
|
||||
long len = BITS_TO_LONGS(nbits) * sizeof(unsigned long);
|
||||
memcpy(dst, src, len);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_and(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & *src2) != 0;
|
||||
}
|
||||
return slow_bitmap_and(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_or(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 | *src2;
|
||||
} else {
|
||||
slow_bitmap_or(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void bitmap_xor(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = *src1 ^ *src2;
|
||||
} else {
|
||||
slow_bitmap_xor(dst, src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_andnot(unsigned long *dst, const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return (*dst = *src1 & ~(*src2)) != 0;
|
||||
}
|
||||
return slow_bitmap_andnot(dst, src1, src2, nbits);
|
||||
}
|
||||
|
||||
static inline void bitmap_complement(unsigned long *dst,
|
||||
const unsigned long *src,
|
||||
long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
*dst = ~(*src) & BITMAP_LAST_WORD_MASK(nbits);
|
||||
} else {
|
||||
slow_bitmap_complement(dst, src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_equal(const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! ((*src1 ^ *src2) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_equal(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_empty(const unsigned long *src, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (*src & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_empty(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_full(const unsigned long *src, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ! (~(*src) & BITMAP_LAST_WORD_MASK(nbits));
|
||||
} else {
|
||||
return slow_bitmap_full(src, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int bitmap_intersects(const unsigned long *src1,
|
||||
const unsigned long *src2, long nbits)
|
||||
{
|
||||
if (small_nbits(nbits)) {
|
||||
return ((*src1 & *src2) & BITMAP_LAST_WORD_MASK(nbits)) != 0;
|
||||
} else {
|
||||
return slow_bitmap_intersects(src1, src2, nbits);
|
||||
}
|
||||
}
|
||||
|
||||
void bitmap_set(unsigned long *map, long i, long len);
|
||||
void bitmap_clear(unsigned long *map, long start, long nr);
|
||||
unsigned long bitmap_find_next_zero_area(unsigned long *map,
|
||||
unsigned long size,
|
||||
unsigned long start,
|
||||
unsigned long nr,
|
||||
unsigned long align_mask);
|
||||
|
||||
static inline unsigned long *bitmap_zero_extend(unsigned long *old,
|
||||
long old_nbits, long new_nbits)
|
||||
{
|
||||
long new_len = BITS_TO_LONGS(new_nbits) * sizeof(unsigned long);
|
||||
unsigned long *new = g_realloc(old, new_len);
|
||||
bitmap_clear(new, old_nbits, new_nbits - old_nbits);
|
||||
return new;
|
||||
}
|
||||
|
||||
#endif /* BITMAP_H */
|
||||
418
qemu/include/qemu/bitops.h
Normal file
418
qemu/include/qemu/bitops.h
Normal file
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* Bitops Module
|
||||
*
|
||||
* Copyright (C) 2010 Corentin Chary <corentin.chary@gmail.com>
|
||||
*
|
||||
* Mostly inspired by (stolen from) linux/bitmap.h and linux/bitops.h
|
||||
*
|
||||
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
||||
* See the COPYING.LIB file in the top-level directory.
|
||||
*/
|
||||
|
||||
#ifndef BITOPS_H
|
||||
#define BITOPS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "host-utils.h"
|
||||
|
||||
#define BITS_PER_BYTE CHAR_BIT
|
||||
#define BITS_PER_LONG (sizeof (unsigned long) * BITS_PER_BYTE)
|
||||
|
||||
#define BIT(nr) (1UL << (nr))
|
||||
#define BIT_MASK(nr) (1UL << ((nr) % BITS_PER_LONG))
|
||||
#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)
|
||||
#define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))
|
||||
|
||||
/**
|
||||
* set_bit - Set a bit in memory
|
||||
* @nr: the bit to set
|
||||
* @addr: the address to start counting from
|
||||
*/
|
||||
static inline void set_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p |= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* clear_bit - Clears a bit in memory
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void clear_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* change_bit - Toggle a bit in memory
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline void change_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
|
||||
*p ^= mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_set_bit - Set a bit and return its old value
|
||||
* @nr: Bit to set
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_set_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old | mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_clear_bit - Clear a bit and return its old value
|
||||
* @nr: Bit to clear
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_clear_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old & ~mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_and_change_bit - Change a bit and return its old value
|
||||
* @nr: Bit to change
|
||||
* @addr: Address to count from
|
||||
*/
|
||||
static inline int test_and_change_bit(long nr, unsigned long *addr)
|
||||
{
|
||||
unsigned long mask = BIT_MASK(nr);
|
||||
unsigned long *p = addr + BIT_WORD(nr);
|
||||
unsigned long old = *p;
|
||||
|
||||
*p = old ^ mask;
|
||||
return (old & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* test_bit - Determine whether a bit is set
|
||||
* @nr: bit number to test
|
||||
* @addr: Address to start counting from
|
||||
*/
|
||||
static inline int test_bit(long nr, const unsigned long *addr)
|
||||
{
|
||||
return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));
|
||||
}
|
||||
|
||||
/**
|
||||
* find_last_bit - find the last set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit, or size.
|
||||
*/
|
||||
unsigned long find_last_bit(const unsigned long *addr,
|
||||
unsigned long size);
|
||||
|
||||
/**
|
||||
* find_next_bit - find the next set bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*/
|
||||
unsigned long find_next_bit(const unsigned long *addr,
|
||||
unsigned long size, unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_next_zero_bit - find the next cleared bit in a memory region
|
||||
* @addr: The address to base the search on
|
||||
* @offset: The bitnumber to start searching at
|
||||
* @size: The bitmap size in bits
|
||||
*/
|
||||
|
||||
unsigned long find_next_zero_bit(const unsigned long *addr,
|
||||
unsigned long size,
|
||||
unsigned long offset);
|
||||
|
||||
/**
|
||||
* find_first_bit - find the first set bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first set bit.
|
||||
*/
|
||||
static inline unsigned long find_first_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
unsigned long result, tmp;
|
||||
|
||||
for (result = 0; result < size; result += BITS_PER_LONG) {
|
||||
tmp = *addr++;
|
||||
if (tmp) {
|
||||
result += ctzl(tmp);
|
||||
return result < size ? result : size;
|
||||
}
|
||||
}
|
||||
/* Not found */
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* find_first_zero_bit - find the first cleared bit in a memory region
|
||||
* @addr: The address to start the search at
|
||||
* @size: The maximum size to search
|
||||
*
|
||||
* Returns the bit number of the first cleared bit.
|
||||
*/
|
||||
static inline unsigned long find_first_zero_bit(const unsigned long *addr,
|
||||
unsigned long size)
|
||||
{
|
||||
return find_next_zero_bit(addr, size, 0);
|
||||
}
|
||||
|
||||
static inline unsigned long hweight_long(unsigned long w)
|
||||
{
|
||||
unsigned long count;
|
||||
|
||||
for (count = 0; w; w >>= 1) {
|
||||
count += w & 1;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* rol8 - rotate an 8-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint8_t rol8(uint8_t word, unsigned int shift)
|
||||
{
|
||||
return (word << shift) | (word >> (8 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror8 - rotate an 8-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint8_t ror8(uint8_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> shift) | (word << (8 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol16 - rotate a 16-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint16_t rol16(uint16_t word, unsigned int shift)
|
||||
{
|
||||
return (word << shift) | (word >> (16 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror16 - rotate a 16-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint16_t ror16(uint16_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> shift) | (word << (16 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol32 - rotate a 32-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint32_t rol32(uint32_t word, unsigned int shift)
|
||||
{
|
||||
return (word << shift) | (word >> (32 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror32 - rotate a 32-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint32_t ror32(uint32_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> shift) | (word << (32 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* rol64 - rotate a 64-bit value left
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint64_t rol64(uint64_t word, unsigned int shift)
|
||||
{
|
||||
return (word << shift) | (word >> (64 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* ror64 - rotate a 64-bit value right
|
||||
* @word: value to rotate
|
||||
* @shift: bits to roll
|
||||
*/
|
||||
static inline uint64_t ror64(uint64_t word, unsigned int shift)
|
||||
{
|
||||
return (word >> shift) | (word << (64 - shift));
|
||||
}
|
||||
|
||||
/**
|
||||
* extract32:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 32 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 32 bit word. It is valid to request that
|
||||
* all 32 bits are returned (ie @length 32 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint32_t extract32(uint32_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
return (value >> start) & (~0U >> (32 - length));
|
||||
}
|
||||
|
||||
/**
|
||||
* extract64:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 64 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it. The bit field must
|
||||
* lie entirely within the 64 bit word. It is valid to request that
|
||||
* all 64 bits are returned (ie @length 64 and @start 0).
|
||||
*
|
||||
* Returns: the value of the bit field extracted from the input value.
|
||||
*/
|
||||
static inline uint64_t extract64(uint64_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
return (value >> start) & (~0ULL >> (64 - length));
|
||||
}
|
||||
|
||||
/**
|
||||
* sextract32:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 32 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it, sign extended to
|
||||
* an int32_t (ie with the most significant bit of the field propagated
|
||||
* to all the upper bits of the return value). The bit field must lie
|
||||
* entirely within the 32 bit word. It is valid to request that
|
||||
* all 32 bits are returned (ie @length 32 and @start 0).
|
||||
*
|
||||
* Returns: the sign extended value of the bit field extracted from the
|
||||
* input value.
|
||||
*/
|
||||
static inline int32_t sextract32(uint32_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
/* Note that this implementation relies on right shift of signed
|
||||
* integers being an arithmetic shift.
|
||||
*/
|
||||
return ((int32_t)(value << (32 - length - start))) >> (32 - length);
|
||||
}
|
||||
|
||||
/**
|
||||
* sextract64:
|
||||
* @value: the value to extract the bit field from
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
*
|
||||
* Extract from the 64 bit input @value the bit field specified by the
|
||||
* @start and @length parameters, and return it, sign extended to
|
||||
* an int64_t (ie with the most significant bit of the field propagated
|
||||
* to all the upper bits of the return value). The bit field must lie
|
||||
* entirely within the 64 bit word. It is valid to request that
|
||||
* all 64 bits are returned (ie @length 64 and @start 0).
|
||||
*
|
||||
* Returns: the sign extended value of the bit field extracted from the
|
||||
* input value.
|
||||
*/
|
||||
static inline uint64_t sextract64(uint64_t value, int start, int length)
|
||||
{
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
/* Note that this implementation relies on right shift of signed
|
||||
* integers being an arithmetic shift.
|
||||
*/
|
||||
return ((int64_t)(value << (64 - length - start))) >> (64 - length);
|
||||
}
|
||||
|
||||
/**
|
||||
* deposit32:
|
||||
* @value: initial value to insert bit field into
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
* @fieldval: the value to insert into the bit field
|
||||
*
|
||||
* Deposit @fieldval into the 32 bit @value at the bit field specified
|
||||
* by the @start and @length parameters, and return the modified
|
||||
* @value. Bits of @value outside the bit field are not modified.
|
||||
* Bits of @fieldval above the least significant @length bits are
|
||||
* ignored. The bit field must lie entirely within the 32 bit word.
|
||||
* It is valid to request that all 32 bits are modified (ie @length
|
||||
* 32 and @start 0).
|
||||
*
|
||||
* Returns: the modified @value.
|
||||
*/
|
||||
static inline uint32_t deposit32(uint32_t value, int start, int length,
|
||||
uint32_t fieldval)
|
||||
{
|
||||
uint32_t mask;
|
||||
assert(start >= 0 && length > 0 && length <= 32 - start);
|
||||
mask = (~0U >> (32 - length)) << start;
|
||||
return (value & ~mask) | ((fieldval << start) & mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* deposit64:
|
||||
* @value: initial value to insert bit field into
|
||||
* @start: the lowest bit in the bit field (numbered from 0)
|
||||
* @length: the length of the bit field
|
||||
* @fieldval: the value to insert into the bit field
|
||||
*
|
||||
* Deposit @fieldval into the 64 bit @value at the bit field specified
|
||||
* by the @start and @length parameters, and return the modified
|
||||
* @value. Bits of @value outside the bit field are not modified.
|
||||
* Bits of @fieldval above the least significant @length bits are
|
||||
* ignored. The bit field must lie entirely within the 64 bit word.
|
||||
* It is valid to request that all 64 bits are modified (ie @length
|
||||
* 64 and @start 0).
|
||||
*
|
||||
* Returns: the modified @value.
|
||||
*/
|
||||
static inline uint64_t deposit64(uint64_t value, int start, int length,
|
||||
uint64_t fieldval)
|
||||
{
|
||||
uint64_t mask;
|
||||
assert(start >= 0 && length > 0 && length <= 64 - start);
|
||||
mask = (~0ULL >> (64 - length)) << start;
|
||||
return (value & ~mask) | ((fieldval << start) & mask);
|
||||
}
|
||||
|
||||
#endif
|
||||
434
qemu/include/qemu/bswap.h
Normal file
434
qemu/include/qemu/bswap.h
Normal file
@@ -0,0 +1,434 @@
|
||||
#ifndef BSWAP_H
|
||||
#define BSWAP_H
|
||||
|
||||
#include "config-host.h"
|
||||
#include <inttypes.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include "fpu/softfloat.h"
|
||||
|
||||
#ifdef CONFIG_MACHINE_BSWAP_H
|
||||
# include <sys/endian.h>
|
||||
# include <sys/types.h>
|
||||
# include <machine/bswap.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
# include <sys/endian.h>
|
||||
#elif defined(CONFIG_BYTESWAP_H)
|
||||
# include <byteswap.h>
|
||||
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return bswap_16(x);
|
||||
}
|
||||
|
||||
static inline uint32_t bswap32(uint32_t x)
|
||||
{
|
||||
return bswap_32(x);
|
||||
}
|
||||
|
||||
static inline uint64_t bswap64(uint64_t x)
|
||||
{
|
||||
return bswap_64(x);
|
||||
}
|
||||
# else
|
||||
static inline uint16_t bswap16(uint16_t x)
|
||||
{
|
||||
return (((x & 0x00ff) << 8) |
|
||||
((x & 0xff00) >> 8));
|
||||
}
|
||||
|
||||
static inline uint32_t bswap32(uint32_t x)
|
||||
{
|
||||
return (((x & 0x000000ffU) << 24) |
|
||||
((x & 0x0000ff00U) << 8) |
|
||||
((x & 0x00ff0000U) >> 8) |
|
||||
((x & 0xff000000U) >> 24));
|
||||
}
|
||||
|
||||
static inline uint64_t bswap64(uint64_t x)
|
||||
{
|
||||
return (((x & 0x00000000000000ffULL) << 56) |
|
||||
((x & 0x000000000000ff00ULL) << 40) |
|
||||
((x & 0x0000000000ff0000ULL) << 24) |
|
||||
((x & 0x00000000ff000000ULL) << 8) |
|
||||
((x & 0x000000ff00000000ULL) >> 8) |
|
||||
((x & 0x0000ff0000000000ULL) >> 24) |
|
||||
((x & 0x00ff000000000000ULL) >> 40) |
|
||||
((x & 0xff00000000000000ULL) >> 56));
|
||||
}
|
||||
#endif /* ! CONFIG_MACHINE_BSWAP_H */
|
||||
|
||||
static inline void bswap16s(uint16_t *s)
|
||||
{
|
||||
*s = bswap16(*s);
|
||||
}
|
||||
|
||||
static inline void bswap32s(uint32_t *s)
|
||||
{
|
||||
*s = bswap32(*s);
|
||||
}
|
||||
|
||||
static inline void bswap64s(uint64_t *s)
|
||||
{
|
||||
*s = bswap64(*s);
|
||||
}
|
||||
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
#define be_bswap(v, size) (v)
|
||||
#define le_bswap(v, size) glue(bswap, size)(v)
|
||||
#define be_bswaps(v, size)
|
||||
#define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
|
||||
#else
|
||||
#define le_bswap(v, size) (v)
|
||||
#define be_bswap(v, size) glue(bswap, size)(v)
|
||||
#define le_bswaps(v, size)
|
||||
#define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0)
|
||||
#endif
|
||||
|
||||
#define CPU_CONVERT(endian, size, type)\
|
||||
static inline type endian ## size ## _to_cpu(type v)\
|
||||
{\
|
||||
return glue(endian, _bswap)(v, size);\
|
||||
}\
|
||||
\
|
||||
static inline type cpu_to_ ## endian ## size(type v)\
|
||||
{\
|
||||
return glue(endian, _bswap)(v, size);\
|
||||
}\
|
||||
\
|
||||
static inline void endian ## size ## _to_cpus(type *p)\
|
||||
{\
|
||||
glue(endian, _bswaps)(p, size);\
|
||||
}\
|
||||
\
|
||||
static inline void cpu_to_ ## endian ## size ## s(type *p)\
|
||||
{\
|
||||
glue(endian, _bswaps)(p, size);\
|
||||
}\
|
||||
\
|
||||
static inline type endian ## size ## _to_cpup(const type *p)\
|
||||
{\
|
||||
return glue(glue(endian, size), _to_cpu)(*p);\
|
||||
}\
|
||||
\
|
||||
static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
|
||||
{\
|
||||
*p = glue(glue(cpu_to_, endian), size)(v);\
|
||||
}
|
||||
|
||||
CPU_CONVERT(be, 16, uint16_t)
|
||||
CPU_CONVERT(be, 32, uint32_t)
|
||||
CPU_CONVERT(be, 64, uint64_t)
|
||||
|
||||
CPU_CONVERT(le, 16, uint16_t)
|
||||
CPU_CONVERT(le, 32, uint32_t)
|
||||
CPU_CONVERT(le, 64, uint64_t)
|
||||
|
||||
/* len must be one of 1, 2, 4 */
|
||||
static inline uint32_t qemu_bswap_len(uint32_t value, int len)
|
||||
{
|
||||
return bswap32(value) >> (32 - 8 * len);
|
||||
}
|
||||
|
||||
/* Unions for reinterpreting between floats and integers. */
|
||||
|
||||
typedef union {
|
||||
float32 f;
|
||||
uint32_t l;
|
||||
} CPU_FloatU;
|
||||
|
||||
typedef union {
|
||||
float64 d;
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
struct {
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
} l;
|
||||
#else
|
||||
struct {
|
||||
uint32_t lower;
|
||||
uint32_t upper;
|
||||
} l;
|
||||
#endif
|
||||
uint64_t ll;
|
||||
} CPU_DoubleU;
|
||||
|
||||
typedef union {
|
||||
floatx80 d;
|
||||
struct {
|
||||
uint64_t lower;
|
||||
uint16_t upper;
|
||||
} l;
|
||||
} CPU_LDoubleU;
|
||||
|
||||
typedef union {
|
||||
float128 q;
|
||||
#if defined(HOST_WORDS_BIGENDIAN)
|
||||
struct {
|
||||
uint32_t upmost;
|
||||
uint32_t upper;
|
||||
uint32_t lower;
|
||||
uint32_t lowest;
|
||||
} l;
|
||||
struct {
|
||||
uint64_t upper;
|
||||
uint64_t lower;
|
||||
} ll;
|
||||
#else
|
||||
struct {
|
||||
uint32_t lowest;
|
||||
uint32_t lower;
|
||||
uint32_t upper;
|
||||
uint32_t upmost;
|
||||
} l;
|
||||
struct {
|
||||
uint64_t lower;
|
||||
uint64_t upper;
|
||||
} ll;
|
||||
#endif
|
||||
} CPU_QuadU;
|
||||
|
||||
/* unaligned/endian-independent pointer access */
|
||||
|
||||
/*
|
||||
* the generic syntax is:
|
||||
*
|
||||
* load: ld{type}{sign}{size}{endian}_p(ptr)
|
||||
*
|
||||
* store: st{type}{size}{endian}_p(ptr, val)
|
||||
*
|
||||
* Note there are small differences with the softmmu access API!
|
||||
*
|
||||
* type is:
|
||||
* (empty): integer access
|
||||
* f : float access
|
||||
*
|
||||
* sign is:
|
||||
* (empty): for floats or 32 bit size
|
||||
* u : unsigned
|
||||
* s : signed
|
||||
*
|
||||
* size is:
|
||||
* b: 8 bits
|
||||
* w: 16 bits
|
||||
* l: 32 bits
|
||||
* q: 64 bits
|
||||
*
|
||||
* endian is:
|
||||
* he : host endian
|
||||
* be : big endian
|
||||
* le : little endian
|
||||
* (except for byte accesses, which have no endian infix).
|
||||
*/
|
||||
|
||||
static inline int ldub_p(const void *ptr)
|
||||
{
|
||||
return *(uint8_t *)ptr;
|
||||
}
|
||||
|
||||
static inline int ldsb_p(const void *ptr)
|
||||
{
|
||||
return *(int8_t *)ptr;
|
||||
}
|
||||
|
||||
static inline void stb_p(void *ptr, uint8_t v)
|
||||
{
|
||||
*(uint8_t *)ptr = v;
|
||||
}
|
||||
|
||||
/* Any compiler worth its salt will turn these memcpy into native unaligned
|
||||
operations. Thus we don't need to play games with packed attributes, or
|
||||
inline byte-by-byte stores. */
|
||||
|
||||
static inline int lduw_he_p(const void *ptr)
|
||||
{
|
||||
uint16_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline int ldsw_he_p(const void *ptr)
|
||||
{
|
||||
int16_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stw_he_p(void *ptr, uint16_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline int ldl_he_p(const void *ptr)
|
||||
{
|
||||
int32_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stl_he_p(void *ptr, uint32_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_he_p(const void *ptr)
|
||||
{
|
||||
uint64_t r;
|
||||
memcpy(&r, ptr, sizeof(r));
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void stq_he_p(void *ptr, uint64_t v)
|
||||
{
|
||||
memcpy(ptr, &v, sizeof(v));
|
||||
}
|
||||
|
||||
static inline int lduw_le_p(const void *ptr)
|
||||
{
|
||||
return (uint16_t)le_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldsw_le_p(const void *ptr)
|
||||
{
|
||||
return (int16_t)le_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldl_le_p(const void *ptr)
|
||||
{
|
||||
return le_bswap(ldl_he_p(ptr), 32);
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_le_p(const void *ptr)
|
||||
{
|
||||
return le_bswap(ldq_he_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_le_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_he_p(ptr, le_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void stl_le_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_he_p(ptr, le_bswap(v, 32));
|
||||
}
|
||||
|
||||
static inline void stq_le_p(void *ptr, uint64_t v)
|
||||
{
|
||||
stq_he_p(ptr, le_bswap(v, 64));
|
||||
}
|
||||
|
||||
/* float access */
|
||||
|
||||
static inline float32 ldfl_le_p(const void *ptr)
|
||||
{
|
||||
CPU_FloatU u;
|
||||
u.l = ldl_le_p(ptr);
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static inline void stfl_le_p(void *ptr, float32 v)
|
||||
{
|
||||
CPU_FloatU u;
|
||||
u.f = v;
|
||||
stl_le_p(ptr, u.l);
|
||||
}
|
||||
|
||||
static inline float64 ldfq_le_p(const void *ptr)
|
||||
{
|
||||
CPU_DoubleU u;
|
||||
u.ll = ldq_le_p(ptr);
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static inline void stfq_le_p(void *ptr, float64 v)
|
||||
{
|
||||
CPU_DoubleU u;
|
||||
u.d = v;
|
||||
stq_le_p(ptr, u.ll);
|
||||
}
|
||||
|
||||
static inline int lduw_be_p(const void *ptr)
|
||||
{
|
||||
return (uint16_t)be_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldsw_be_p(const void *ptr)
|
||||
{
|
||||
return (int16_t)be_bswap(lduw_he_p(ptr), 16);
|
||||
}
|
||||
|
||||
static inline int ldl_be_p(const void *ptr)
|
||||
{
|
||||
return be_bswap(ldl_he_p(ptr), 32);
|
||||
}
|
||||
|
||||
static inline uint64_t ldq_be_p(const void *ptr)
|
||||
{
|
||||
return be_bswap(ldq_he_p(ptr), 64);
|
||||
}
|
||||
|
||||
static inline void stw_be_p(void *ptr, uint16_t v)
|
||||
{
|
||||
stw_he_p(ptr, be_bswap(v, 16));
|
||||
}
|
||||
|
||||
static inline void stl_be_p(void *ptr, uint32_t v)
|
||||
{
|
||||
stl_he_p(ptr, be_bswap(v, 32));
|
||||
}
|
||||
|
||||
static inline void stq_be_p(void *ptr, uint64_t v)
|
||||
{
|
||||
stq_he_p(ptr, be_bswap(v, 64));
|
||||
}
|
||||
|
||||
/* float access */
|
||||
|
||||
static inline float32 ldfl_be_p(const void *ptr)
|
||||
{
|
||||
CPU_FloatU u;
|
||||
u.l = ldl_be_p(ptr);
|
||||
return u.f;
|
||||
}
|
||||
|
||||
static inline void stfl_be_p(void *ptr, float32 v)
|
||||
{
|
||||
CPU_FloatU u;
|
||||
u.f = v;
|
||||
stl_be_p(ptr, u.l);
|
||||
}
|
||||
|
||||
static inline float64 ldfq_be_p(const void *ptr)
|
||||
{
|
||||
CPU_DoubleU u;
|
||||
u.ll = ldq_be_p(ptr);
|
||||
return u.d;
|
||||
}
|
||||
|
||||
static inline void stfq_be_p(void *ptr, float64 v)
|
||||
{
|
||||
CPU_DoubleU u;
|
||||
u.d = v;
|
||||
stq_be_p(ptr, u.ll);
|
||||
}
|
||||
|
||||
static inline unsigned long leul_to_cpu(unsigned long v)
|
||||
{
|
||||
/* In order to break an include loop between here and
|
||||
qemu-common.h, don't rely on HOST_LONG_BITS. */
|
||||
#if ULONG_MAX == UINT32_MAX
|
||||
return le_bswap(v, 32);
|
||||
#elif ULONG_MAX == UINT64_MAX
|
||||
return le_bswap(v, 64);
|
||||
#else
|
||||
# error Unknown sizeof long
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef le_bswap
|
||||
#undef be_bswap
|
||||
#undef le_bswaps
|
||||
#undef be_bswaps
|
||||
|
||||
#endif /* BSWAP_H */
|
||||
61
qemu/include/qemu/compiler.h
Normal file
61
qemu/include/qemu/compiler.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/* public domain */
|
||||
|
||||
#ifndef COMPILER_H
|
||||
#define COMPILER_H
|
||||
|
||||
#include "config-host.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| The macro QEMU_GNUC_PREREQ tests for minimum version of the GNU C compiler.
|
||||
| The code is a copy of SOFTFLOAT_GNUC_PREREQ, see softfloat-macros.h.
|
||||
*----------------------------------------------------------------------------*/
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
# define QEMU_GNUC_PREREQ(maj, min) \
|
||||
((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
|
||||
#else
|
||||
# define QEMU_GNUC_PREREQ(maj, min) 0
|
||||
#endif
|
||||
|
||||
#define QEMU_NORETURN __attribute__ ((__noreturn__))
|
||||
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
#define QEMU_WARN_UNUSED_RESULT __attribute__((warn_unused_result))
|
||||
#else
|
||||
#define QEMU_WARN_UNUSED_RESULT
|
||||
#endif
|
||||
|
||||
#if QEMU_GNUC_PREREQ(4, 3)
|
||||
#define QEMU_ARTIFICIAL __attribute__((always_inline, artificial))
|
||||
#else
|
||||
#define QEMU_ARTIFICIAL
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
# define QEMU_PACKED __attribute__((gcc_struct, packed))
|
||||
#else
|
||||
# define QEMU_PACKED __attribute__((packed))
|
||||
#endif
|
||||
|
||||
#define cat(x,y) x ## y
|
||||
#define cat2(x,y) cat(x,y)
|
||||
#define QEMU_BUILD_BUG_ON(x) \
|
||||
typedef char cat2(qemu_build_bug_on__,__LINE__)[(x)?-1:1] __attribute__((unused));
|
||||
|
||||
#if defined __GNUC__
|
||||
# if !QEMU_GNUC_PREREQ(4, 4)
|
||||
/* gcc versions before 4.4.x don't support gnu_printf, so use printf. */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(printf, n, m)))
|
||||
# else
|
||||
/* Use gnu_printf when supported (qemu uses standard format strings). */
|
||||
# define GCC_FMT_ATTR(n, m) __attribute__((format(gnu_printf, n, m)))
|
||||
# if defined(_WIN32)
|
||||
/* Map __printf__ to __gnu_printf__ because we want standard format strings
|
||||
* even when MinGW or GLib include files use __printf__. */
|
||||
# define __printf__ __gnu_printf__
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
#define GCC_FMT_ATTR(n, m)
|
||||
#endif
|
||||
|
||||
#endif /* COMPILER_H */
|
||||
35
qemu/include/qemu/crc32c.h
Normal file
35
qemu/include/qemu/crc32c.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Castagnoli CRC32C Checksum Algorithm
|
||||
*
|
||||
* Polynomial: 0x11EDC6F41
|
||||
*
|
||||
* Castagnoli93: Guy Castagnoli and Stefan Braeuer and Martin Herrman
|
||||
* "Optimization of Cyclic Redundancy-Check Codes with 24
|
||||
* and 32 Parity Bits",IEEE Transactions on Communication,
|
||||
* Volume 41, Number 6, June 1993
|
||||
*
|
||||
* Copyright (c) 2013 Red Hat, Inc.,
|
||||
*
|
||||
* Authors:
|
||||
* Jeff Cody <jcody@redhat.com>
|
||||
*
|
||||
* Based on the Linux kernel cryptographic crc32c module,
|
||||
*
|
||||
* Copyright (c) 2004 Cisco Systems, Inc.
|
||||
* Copyright (c) 2008 Herbert Xu <herbert@gondor.apana.org.au>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the Free
|
||||
* Software Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_CRC32C_H
|
||||
#define QEMU_CRC32C_H
|
||||
|
||||
#include "qemu-common.h"
|
||||
|
||||
uint32_t crc32c(uint32_t crc, const uint8_t *data, unsigned int length);
|
||||
|
||||
#endif
|
||||
382
qemu/include/qemu/host-utils.h
Normal file
382
qemu/include/qemu/host-utils.h
Normal file
@@ -0,0 +1,382 @@
|
||||
/*
|
||||
* Utility compute operations used by translated code.
|
||||
*
|
||||
* Copyright (c) 2007 Thiemo Seufer
|
||||
* Copyright (c) 2007 Jocelyn Mayer
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef HOST_UTILS_H
|
||||
#define HOST_UTILS_H 1
|
||||
|
||||
#include "qemu/compiler.h" /* QEMU_GNUC_PREREQ */
|
||||
#include <limits.h>
|
||||
|
||||
#ifdef CONFIG_INT128
|
||||
static inline void mulu64(uint64_t *plow, uint64_t *phigh,
|
||||
uint64_t a, uint64_t b)
|
||||
{
|
||||
__uint128_t r = (__uint128_t)a * b;
|
||||
*plow = r;
|
||||
*phigh = r >> 64;
|
||||
}
|
||||
|
||||
static inline void muls64(uint64_t *plow, uint64_t *phigh,
|
||||
int64_t a, int64_t b)
|
||||
{
|
||||
__int128_t r = (__int128_t)a * b;
|
||||
*plow = r;
|
||||
*phigh = r >> 64;
|
||||
}
|
||||
|
||||
static inline int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor)
|
||||
{
|
||||
if (divisor == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
__uint128_t dividend = ((__uint128_t)*phigh << 64) | *plow;
|
||||
__uint128_t result = dividend / divisor;
|
||||
*plow = result;
|
||||
*phigh = dividend % divisor;
|
||||
return result > UINT64_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int divs128(int64_t *plow, int64_t *phigh, int64_t divisor)
|
||||
{
|
||||
if (divisor == 0) {
|
||||
return 1;
|
||||
} else {
|
||||
__int128_t dividend = ((__int128_t)*phigh << 64) | *plow;
|
||||
__int128_t result = dividend / divisor;
|
||||
*plow = result;
|
||||
*phigh = dividend % divisor;
|
||||
return result != *plow;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
|
||||
void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
|
||||
int divu128(uint64_t *plow, uint64_t *phigh, uint64_t divisor);
|
||||
int divs128(int64_t *plow, int64_t *phigh, int64_t divisor);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* clz32 - count leading zeros in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int clz32(uint32_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return val ? __builtin_clz(val) : 32;
|
||||
#else
|
||||
/* Binary search for the leading one bit. */
|
||||
int cnt = 0;
|
||||
|
||||
if (!(val & 0xFFFF0000U)) {
|
||||
cnt += 16;
|
||||
val <<= 16;
|
||||
}
|
||||
if (!(val & 0xFF000000U)) {
|
||||
cnt += 8;
|
||||
val <<= 8;
|
||||
}
|
||||
if (!(val & 0xF0000000U)) {
|
||||
cnt += 4;
|
||||
val <<= 4;
|
||||
}
|
||||
if (!(val & 0xC0000000U)) {
|
||||
cnt += 2;
|
||||
val <<= 2;
|
||||
}
|
||||
if (!(val & 0x80000000U)) {
|
||||
cnt++;
|
||||
val <<= 1;
|
||||
}
|
||||
if (!(val & 0x80000000U)) {
|
||||
cnt++;
|
||||
}
|
||||
return cnt;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clo32 - count leading ones in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is -1.
|
||||
*/
|
||||
static inline int clo32(uint32_t val)
|
||||
{
|
||||
return clz32(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* clz64 - count leading zeros in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int clz64(uint64_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return val ? __builtin_clzll(val) : 64;
|
||||
#else
|
||||
int cnt = 0;
|
||||
|
||||
if (!(val >> 32)) {
|
||||
cnt += 32;
|
||||
} else {
|
||||
val >>= 32;
|
||||
}
|
||||
|
||||
return cnt + clz32(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clo64 - count leading ones in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is -1.
|
||||
*/
|
||||
static inline int clo64(uint64_t val)
|
||||
{
|
||||
return clz64(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz32 - count trailing zeros in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz32(uint32_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return val ? __builtin_ctz(val) : 32;
|
||||
#else
|
||||
/* Binary search for the trailing one bit. */
|
||||
int cnt;
|
||||
|
||||
cnt = 0;
|
||||
if (!(val & 0x0000FFFFUL)) {
|
||||
cnt += 16;
|
||||
val >>= 16;
|
||||
}
|
||||
if (!(val & 0x000000FFUL)) {
|
||||
cnt += 8;
|
||||
val >>= 8;
|
||||
}
|
||||
if (!(val & 0x0000000FUL)) {
|
||||
cnt += 4;
|
||||
val >>= 4;
|
||||
}
|
||||
if (!(val & 0x00000003UL)) {
|
||||
cnt += 2;
|
||||
val >>= 2;
|
||||
}
|
||||
if (!(val & 0x00000001UL)) {
|
||||
cnt++;
|
||||
val >>= 1;
|
||||
}
|
||||
if (!(val & 0x00000001UL)) {
|
||||
cnt++;
|
||||
}
|
||||
|
||||
return cnt;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* cto32 - count trailing ones in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 32 if the value is -1.
|
||||
*/
|
||||
static inline int cto32(uint32_t val)
|
||||
{
|
||||
return ctz32(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* ctz64 - count trailing zeros in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is zero. Note that the GCC builtin is
|
||||
* undefined if the value is zero.
|
||||
*/
|
||||
static inline int ctz64(uint64_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return val ? __builtin_ctzll(val) : 64;
|
||||
#else
|
||||
int cnt;
|
||||
|
||||
cnt = 0;
|
||||
if (!((uint32_t)val)) {
|
||||
cnt += 32;
|
||||
val >>= 32;
|
||||
}
|
||||
|
||||
return cnt + ctz32(val);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* cto64 - count trailing ones in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns 64 if the value is -1.
|
||||
*/
|
||||
static inline int cto64(uint64_t val)
|
||||
{
|
||||
return ctz64(~val);
|
||||
}
|
||||
|
||||
/**
|
||||
* clrsb32 - count leading redundant sign bits in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns the number of bits following the sign bit that are equal to it.
|
||||
* No special cases; output range is [0-31].
|
||||
*/
|
||||
static inline int clrsb32(uint32_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(4, 7)
|
||||
return __builtin_clrsb(val);
|
||||
#else
|
||||
return clz32(val ^ ((int32_t)val >> 1)) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* clrsb64 - count leading redundant sign bits in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*
|
||||
* Returns the number of bits following the sign bit that are equal to it.
|
||||
* No special cases; output range is [0-63].
|
||||
*/
|
||||
static inline int clrsb64(uint64_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(4, 7)
|
||||
return __builtin_clrsbll(val);
|
||||
#else
|
||||
return clz64(val ^ ((int64_t)val >> 1)) - 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop8 - count the population of one bits in an 8-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop8(uint8_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcount(val);
|
||||
#else
|
||||
val = (val & 0x55) + ((val >> 1) & 0x55);
|
||||
val = (val & 0x33) + ((val >> 2) & 0x33);
|
||||
val = (val & 0x0f) + ((val >> 4) & 0x0f);
|
||||
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop16 - count the population of one bits in a 16-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop16(uint16_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcount(val);
|
||||
#else
|
||||
val = (val & 0x5555) + ((val >> 1) & 0x5555);
|
||||
val = (val & 0x3333) + ((val >> 2) & 0x3333);
|
||||
val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
|
||||
val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
|
||||
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop32 - count the population of one bits in a 32-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop32(uint32_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcount(val);
|
||||
#else
|
||||
val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
|
||||
val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
|
||||
val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
|
||||
val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
|
||||
val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
|
||||
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* ctpop64 - count the population of one bits in a 64-bit value.
|
||||
* @val: The value to search
|
||||
*/
|
||||
static inline int ctpop64(uint64_t val)
|
||||
{
|
||||
#if QEMU_GNUC_PREREQ(3, 4)
|
||||
return __builtin_popcountll(val);
|
||||
#else
|
||||
val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
|
||||
val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
|
||||
val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
|
||||
val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL);
|
||||
val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
|
||||
val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
|
||||
|
||||
return val;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Host type specific sizes of these routines. */
|
||||
|
||||
#if ULONG_MAX == UINT32_MAX
|
||||
# define clzl clz32
|
||||
# define ctzl ctz32
|
||||
# define clol clo32
|
||||
# define ctol cto32
|
||||
# define ctpopl ctpop32
|
||||
#elif ULONG_MAX == UINT64_MAX
|
||||
# define clzl clz64
|
||||
# define ctzl ctz64
|
||||
# define clol clo64
|
||||
# define ctol cto64
|
||||
# define ctpopl ctpop64
|
||||
#else
|
||||
# error Unknown sizeof long
|
||||
#endif
|
||||
|
||||
#endif
|
||||
149
qemu/include/qemu/int128.h
Normal file
149
qemu/include/qemu/int128.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef INT128_H
|
||||
#define INT128_H
|
||||
|
||||
//#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct Int128 Int128;
|
||||
|
||||
struct Int128 {
|
||||
uint64_t lo;
|
||||
int64_t hi;
|
||||
};
|
||||
|
||||
static inline Int128 int128_make64(uint64_t a)
|
||||
{
|
||||
return (Int128) { a, 0 };
|
||||
}
|
||||
|
||||
static inline uint64_t int128_get64(Int128 a)
|
||||
{
|
||||
//assert(!a.hi);
|
||||
return a.lo;
|
||||
}
|
||||
|
||||
static inline Int128 int128_zero(void)
|
||||
{
|
||||
return int128_make64(0);
|
||||
}
|
||||
|
||||
static inline Int128 int128_one(void)
|
||||
{
|
||||
return int128_make64(1);
|
||||
}
|
||||
|
||||
static inline Int128 int128_2_64(void)
|
||||
{
|
||||
return (Int128) { 0, 1 };
|
||||
}
|
||||
|
||||
static inline Int128 int128_exts64(int64_t a)
|
||||
{
|
||||
return (Int128) { .lo = a, .hi = (a < 0) ? -1 : 0 };
|
||||
}
|
||||
|
||||
static inline Int128 int128_and(Int128 a, Int128 b)
|
||||
{
|
||||
return (Int128) { a.lo & b.lo, a.hi & b.hi };
|
||||
}
|
||||
|
||||
static inline Int128 int128_rshift(Int128 a, int n)
|
||||
{
|
||||
int64_t h;
|
||||
if (!n) {
|
||||
return a;
|
||||
}
|
||||
h = a.hi >> (n & 63);
|
||||
if (n >= 64) {
|
||||
return (Int128) { h, h >> 63 };
|
||||
} else {
|
||||
return (Int128) { (a.lo >> n) | ((uint64_t)a.hi << (64 - n)), h };
|
||||
}
|
||||
}
|
||||
|
||||
static inline Int128 int128_add(Int128 a, Int128 b)
|
||||
{
|
||||
uint64_t lo = a.lo + b.lo;
|
||||
|
||||
/* a.lo <= a.lo + b.lo < a.lo + k (k is the base, 2^64). Hence,
|
||||
* a.lo + b.lo >= k implies 0 <= lo = a.lo + b.lo - k < a.lo.
|
||||
* Similarly, a.lo + b.lo < k implies a.lo <= lo = a.lo + b.lo < k.
|
||||
*
|
||||
* So the carry is lo < a.lo.
|
||||
*/
|
||||
return (Int128) { lo, (uint64_t)a.hi + b.hi + (lo < a.lo) };
|
||||
}
|
||||
|
||||
static inline Int128 int128_neg(Int128 a)
|
||||
{
|
||||
uint64_t lo = -a.lo;
|
||||
return (Int128) { lo, ~(uint64_t)a.hi + !lo };
|
||||
}
|
||||
|
||||
static inline Int128 int128_sub(Int128 a, Int128 b)
|
||||
{
|
||||
return (Int128){ a.lo - b.lo, (uint64_t)a.hi - b.hi - (a.lo < b.lo) };
|
||||
}
|
||||
|
||||
static inline bool int128_nonneg(Int128 a)
|
||||
{
|
||||
return a.hi >= 0;
|
||||
}
|
||||
|
||||
static inline bool int128_eq(Int128 a, Int128 b)
|
||||
{
|
||||
return a.lo == b.lo && a.hi == b.hi;
|
||||
}
|
||||
|
||||
static inline bool int128_ne(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_eq(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_ge(Int128 a, Int128 b)
|
||||
{
|
||||
return a.hi > b.hi || (a.hi == b.hi && a.lo >= b.lo);
|
||||
}
|
||||
|
||||
static inline bool int128_lt(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_ge(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_le(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_ge(b, a);
|
||||
}
|
||||
|
||||
static inline bool int128_gt(Int128 a, Int128 b)
|
||||
{
|
||||
return !int128_le(a, b);
|
||||
}
|
||||
|
||||
static inline bool int128_nz(Int128 a)
|
||||
{
|
||||
return a.lo || a.hi;
|
||||
}
|
||||
|
||||
static inline Int128 int128_min(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_le(a, b) ? a : b;
|
||||
}
|
||||
|
||||
static inline Int128 int128_max(Int128 a, Int128 b)
|
||||
{
|
||||
return int128_ge(a, b) ? a : b;
|
||||
}
|
||||
|
||||
static inline void int128_addto(Int128 *a, Int128 b)
|
||||
{
|
||||
*a = int128_add(*a, b);
|
||||
}
|
||||
|
||||
static inline void int128_subfrom(Int128 *a, Int128 b)
|
||||
{
|
||||
*a = int128_sub(*a, b);
|
||||
}
|
||||
|
||||
#endif
|
||||
118
qemu/include/qemu/log.h
Normal file
118
qemu/include/qemu/log.h
Normal file
@@ -0,0 +1,118 @@
|
||||
#ifndef QEMU_LOG_H
|
||||
#define QEMU_LOG_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include "qemu/compiler.h"
|
||||
#include "qom/cpu.h"
|
||||
|
||||
/* Private global variables, don't use */
|
||||
extern FILE *qemu_logfile;
|
||||
extern int qemu_loglevel;
|
||||
|
||||
/*
|
||||
* The new API:
|
||||
*
|
||||
*/
|
||||
|
||||
/* Log settings checking macros: */
|
||||
|
||||
/* Returns true if qemu_log() will really write somewhere
|
||||
*/
|
||||
static inline bool qemu_log_enabled(void)
|
||||
{
|
||||
return qemu_logfile != NULL;
|
||||
}
|
||||
|
||||
#define CPU_LOG_TB_OUT_ASM (1 << 0)
|
||||
#define CPU_LOG_TB_IN_ASM (1 << 1)
|
||||
#define CPU_LOG_TB_OP (1 << 2)
|
||||
#define CPU_LOG_TB_OP_OPT (1 << 3)
|
||||
#define CPU_LOG_INT (1 << 4)
|
||||
#define CPU_LOG_EXEC (1 << 5)
|
||||
#define CPU_LOG_PCALL (1 << 6)
|
||||
#define CPU_LOG_IOPORT (1 << 7)
|
||||
#define CPU_LOG_TB_CPU (1 << 8)
|
||||
#define CPU_LOG_RESET (1 << 9)
|
||||
#define LOG_UNIMP (1 << 10)
|
||||
#define LOG_GUEST_ERROR (1 << 11)
|
||||
|
||||
/* Returns true if a bit is set in the current loglevel mask
|
||||
*/
|
||||
static inline bool qemu_loglevel_mask(int mask)
|
||||
{
|
||||
return (qemu_loglevel & mask) != 0;
|
||||
}
|
||||
|
||||
/* Logging functions: */
|
||||
|
||||
/* main logging function
|
||||
*/
|
||||
void GCC_FMT_ATTR(1, 2) qemu_log(const char *fmt, ...);
|
||||
|
||||
/* vfprintf-like logging function
|
||||
*/
|
||||
static inline void GCC_FMT_ATTR(1, 0)
|
||||
qemu_log_vprintf(const char *fmt, va_list va)
|
||||
{
|
||||
if (qemu_logfile) {
|
||||
vfprintf(qemu_logfile, fmt, va);
|
||||
}
|
||||
}
|
||||
|
||||
/* log only if a bit is set on the current loglevel mask
|
||||
*/
|
||||
void GCC_FMT_ATTR(2, 3) qemu_log_mask(int mask, const char *fmt, ...);
|
||||
|
||||
|
||||
/* Special cases: */
|
||||
|
||||
/* 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)
|
||||
{
|
||||
if (qemu_log_enabled()) {
|
||||
cpu_dump_state(cpu, qemu_logfile, fprintf, flags);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
|
||||
/* fflush() the log file */
|
||||
static inline void qemu_log_flush(void)
|
||||
{
|
||||
fflush(qemu_logfile);
|
||||
}
|
||||
|
||||
/* Close the log file */
|
||||
static inline void qemu_log_close(void)
|
||||
{
|
||||
if (qemu_logfile) {
|
||||
if (qemu_logfile != stderr) {
|
||||
fclose(qemu_logfile);
|
||||
}
|
||||
qemu_logfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
77
qemu/include/qemu/main-loop.h
Normal file
77
qemu/include/qemu/main-loop.h
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* QEMU System Emulator
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MAIN_LOOP_H
|
||||
#define QEMU_MAIN_LOOP_H 1
|
||||
|
||||
#define SIG_IPI SIGUSR1
|
||||
|
||||
struct uc_struct;
|
||||
|
||||
/**
|
||||
* qemu_init_main_loop: Set up the process so that it can run the main loop.
|
||||
*
|
||||
* This includes setting up signal handlers. It should be called before
|
||||
* any other threads are created. In addition, threads other than the
|
||||
* main one should block signals that are trapped by the main loop.
|
||||
* For simplicity, you can consider these signals to be safe: SIGUSR1,
|
||||
* SIGUSR2, thread signals (SIGFPE, SIGILL, SIGSEGV, SIGBUS) and real-time
|
||||
* signals if available. Remember that Windows in practice does not have
|
||||
* signals, though.
|
||||
*
|
||||
* In the case of QEMU tools, this will also start/initialize timers.
|
||||
*/
|
||||
int qemu_init_main_loop(void);
|
||||
|
||||
/**
|
||||
* qemu_mutex_lock_iothread: Lock the main loop mutex.
|
||||
*
|
||||
* This function locks the main loop mutex. The mutex is taken by
|
||||
* qemu_init_main_loop and always taken except while waiting on
|
||||
* external events (such as with select). The mutex should be taken
|
||||
* by threads other than the main loop thread when calling
|
||||
* qemu_bh_new(), qemu_set_fd_handler() and basically all other
|
||||
* functions documented in this file.
|
||||
*
|
||||
* NOTE: tools currently are single-threaded and qemu_mutex_lock_iothread
|
||||
* is a no-op there.
|
||||
*/
|
||||
void qemu_mutex_lock_iothread(struct uc_struct* uc);
|
||||
|
||||
/**
|
||||
* qemu_mutex_unlock_iothread: Unlock the main loop mutex.
|
||||
*
|
||||
* This function unlocks the main loop mutex. The mutex is taken by
|
||||
* qemu_init_main_loop and always taken except while waiting on
|
||||
* external events (such as with select). The mutex should be unlocked
|
||||
* as soon as possible by threads other than the main loop thread,
|
||||
* because it prevents the main loop from processing callbacks,
|
||||
* including timers and bottom halves.
|
||||
*
|
||||
* NOTE: tools currently are single-threaded and qemu_mutex_unlock_iothread
|
||||
* is a no-op there.
|
||||
*/
|
||||
void qemu_mutex_unlock_iothread(struct uc_struct* uc);
|
||||
|
||||
#endif
|
||||
61
qemu/include/qemu/module.h
Normal file
61
qemu/include/qemu/module.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* QEMU Module Infrastructure
|
||||
*
|
||||
* Copyright IBM, Corp. 2009
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_MODULE_H
|
||||
#define QEMU_MODULE_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#define DSO_STAMP_FUN glue(qemu_stamp, CONFIG_STAMP)
|
||||
#define DSO_STAMP_FUN_STR stringify(DSO_STAMP_FUN)
|
||||
|
||||
#ifdef BUILD_DSO
|
||||
void DSO_STAMP_FUN(void);
|
||||
/* This is a dummy symbol to identify a loaded DSO as a QEMU module, so we can
|
||||
* distinguish "version mismatch" from "not a QEMU module", when the stamp
|
||||
* check fails during module loading */
|
||||
void qemu_module_dummy(void);
|
||||
|
||||
#define module_init(function, type) \
|
||||
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
|
||||
{ \
|
||||
register_dso_module_init(function, type); \
|
||||
}
|
||||
#else
|
||||
/* This should not be used directly. Use block_init etc. instead. */
|
||||
#define module_init(function, type) \
|
||||
static void __attribute__((constructor)) do_qemu_init_ ## function(void) \
|
||||
{ \
|
||||
register_module_init(function, type); \
|
||||
}
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
MODULE_INIT_BLOCK,
|
||||
MODULE_INIT_MACHINE,
|
||||
MODULE_INIT_QAPI,
|
||||
MODULE_INIT_QOM,
|
||||
MODULE_INIT_MAX
|
||||
} module_init_type;
|
||||
|
||||
#define block_init(function) module_init(function, MODULE_INIT_BLOCK)
|
||||
#define machine_init(function) module_init(function, MODULE_INIT_MACHINE)
|
||||
#define qapi_init(function) module_init(function, MODULE_INIT_QAPI)
|
||||
#define type_init(function) module_init(function, MODULE_INIT_QOM)
|
||||
|
||||
void register_module_init(void (*fn)(void), module_init_type type);
|
||||
void register_dso_module_init(void (*fn)(void), module_init_type type);
|
||||
|
||||
void module_call_init(struct uc_struct *uc, module_init_type type);
|
||||
|
||||
#endif
|
||||
72
qemu/include/qemu/notify.h
Normal file
72
qemu/include/qemu/notify.h
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Notifier lists
|
||||
*
|
||||
* Copyright IBM, Corp. 2010
|
||||
*
|
||||
* Authors:
|
||||
* Anthony Liguori <aliguori@us.ibm.com>
|
||||
*
|
||||
* This work is licensed under the terms of the GNU GPL, version 2. See
|
||||
* the COPYING file in the top-level directory.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef QEMU_NOTIFY_H
|
||||
#define QEMU_NOTIFY_H
|
||||
|
||||
#include "qemu/queue.h"
|
||||
|
||||
typedef struct Notifier Notifier;
|
||||
|
||||
struct Notifier
|
||||
{
|
||||
void (*notify)(Notifier *notifier, void *data);
|
||||
QLIST_ENTRY(Notifier) node;
|
||||
};
|
||||
|
||||
typedef struct NotifierList
|
||||
{
|
||||
QLIST_HEAD(, Notifier) notifiers;
|
||||
} NotifierList;
|
||||
|
||||
#define NOTIFIER_LIST_INITIALIZER(head) \
|
||||
{ QLIST_HEAD_INITIALIZER((head).notifiers) }
|
||||
|
||||
void notifier_list_init(NotifierList *list);
|
||||
|
||||
void notifier_list_add(NotifierList *list, Notifier *notifier);
|
||||
|
||||
void notifier_remove(Notifier *notifier);
|
||||
|
||||
void notifier_list_notify(NotifierList *list, void *data);
|
||||
|
||||
/* Same as Notifier but allows .notify() to return errors */
|
||||
typedef struct NotifierWithReturn NotifierWithReturn;
|
||||
|
||||
struct NotifierWithReturn {
|
||||
/**
|
||||
* Return 0 on success (next notifier will be invoked), otherwise
|
||||
* notifier_with_return_list_notify() will stop and return the value.
|
||||
*/
|
||||
int (*notify)(NotifierWithReturn *notifier, void *data);
|
||||
QLIST_ENTRY(NotifierWithReturn) node;
|
||||
};
|
||||
|
||||
typedef struct NotifierWithReturnList {
|
||||
QLIST_HEAD(, NotifierWithReturn) notifiers;
|
||||
} NotifierWithReturnList;
|
||||
|
||||
#define NOTIFIER_WITH_RETURN_LIST_INITIALIZER(head) \
|
||||
{ QLIST_HEAD_INITIALIZER((head).notifiers) }
|
||||
|
||||
void notifier_with_return_list_init(NotifierWithReturnList *list);
|
||||
|
||||
void notifier_with_return_list_add(NotifierWithReturnList *list,
|
||||
NotifierWithReturn *notifier);
|
||||
|
||||
void notifier_with_return_remove(NotifierWithReturn *notifier);
|
||||
|
||||
int notifier_with_return_list_notify(NotifierWithReturnList *list,
|
||||
void *data);
|
||||
|
||||
#endif
|
||||
134
qemu/include/qemu/option.h
Normal file
134
qemu/include/qemu/option.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Commandline option parsing functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_OPTIONS_H
|
||||
#define QEMU_OPTIONS_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "qemu/queue.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qapi/qmp/qdict.h"
|
||||
|
||||
const char *get_opt_name(char *buf, int buf_size, const char *p, char delim);
|
||||
const char *get_opt_value(char *buf, int buf_size, const char *p);
|
||||
int get_next_param_value(char *buf, int buf_size,
|
||||
const char *tag, const char **pstr);
|
||||
int get_param_value(char *buf, int buf_size,
|
||||
const char *tag, const char *str);
|
||||
|
||||
|
||||
void parse_option_size(const char *name, const char *value,
|
||||
uint64_t *ret, Error **errp);
|
||||
bool has_help_option(const char *param);
|
||||
bool is_valid_option_list(const char *param);
|
||||
|
||||
typedef struct QemuOpt QemuOpt;
|
||||
typedef struct QemuOpts QemuOpts;
|
||||
typedef struct QemuOptsList QemuOptsList;
|
||||
|
||||
enum QemuOptType {
|
||||
QEMU_OPT_STRING = 0, /* no parsing (use string as-is) */
|
||||
QEMU_OPT_BOOL, /* on/off */
|
||||
QEMU_OPT_NUMBER, /* simple number */
|
||||
QEMU_OPT_SIZE, /* size, accepts (K)ilo, (M)ega, (G)iga, (T)era postfix */
|
||||
};
|
||||
|
||||
typedef struct QemuOptDesc {
|
||||
const char *name;
|
||||
enum QemuOptType type;
|
||||
const char *help;
|
||||
const char *def_value_str;
|
||||
} QemuOptDesc;
|
||||
|
||||
struct QemuOptsList {
|
||||
const char *name;
|
||||
const char *implied_opt_name;
|
||||
bool merge_lists; /* Merge multiple uses of option into a single list? */
|
||||
QTAILQ_HEAD(, QemuOpts) head;
|
||||
QemuOptDesc desc[];
|
||||
};
|
||||
|
||||
const char *qemu_opt_get(QemuOpts *opts, const char *name);
|
||||
char *qemu_opt_get_del(QemuOpts *opts, const char *name);
|
||||
/**
|
||||
* qemu_opt_has_help_opt:
|
||||
* @opts: options to search for a help request
|
||||
*
|
||||
* Check whether the options specified by @opts include one of the
|
||||
* standard strings which indicate that the user is asking for a
|
||||
* list of the valid values for a command line option (as defined
|
||||
* by is_help_option()).
|
||||
*
|
||||
* Returns: true if @opts includes 'help' or equivalent.
|
||||
*/
|
||||
bool qemu_opt_has_help_opt(QemuOpts *opts);
|
||||
QemuOpt *qemu_opt_find(QemuOpts *opts, const char *name);
|
||||
bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
|
||||
bool qemu_opt_get_bool_del(QemuOpts *opts, const char *name, bool defval);
|
||||
uint64_t qemu_opt_get_number_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
uint64_t qemu_opt_get_size_del(QemuOpts *opts, const char *name,
|
||||
uint64_t defval);
|
||||
int qemu_opt_unset(QemuOpts *opts, const char *name);
|
||||
int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
|
||||
void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
|
||||
Error **errp);
|
||||
int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
|
||||
int qemu_opt_set_number(QemuOpts *opts, const char *name, int64_t val);
|
||||
typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
|
||||
int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
|
||||
int abort_on_failure);
|
||||
|
||||
QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
|
||||
QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
|
||||
int fail_if_exists, Error **errp);
|
||||
void qemu_opts_reset(QemuOptsList *list);
|
||||
void qemu_opts_loc_restore(QemuOpts *opts);
|
||||
int qemu_opts_set(QemuOptsList *list, const char *id,
|
||||
const char *name, const char *value);
|
||||
const char *qemu_opts_id(QemuOpts *opts);
|
||||
void qemu_opts_set_id(QemuOpts *opts, char *id);
|
||||
void qemu_opts_del(QemuOpts *opts);
|
||||
void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
|
||||
int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
|
||||
QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
|
||||
void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
|
||||
int permit_abbrev);
|
||||
QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
|
||||
Error **errp);
|
||||
QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
|
||||
void qemu_opts_absorb_qdict(QemuOpts *opts, QDict *qdict, Error **errp);
|
||||
|
||||
typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
|
||||
void qemu_opts_print(QemuOpts *opts);
|
||||
int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
|
||||
int abort_on_failure);
|
||||
void qemu_opts_print_help(QemuOptsList *list);
|
||||
void qemu_opts_free(QemuOptsList *list);
|
||||
QemuOptsList *qemu_opts_append(QemuOptsList *dst, QemuOptsList *list);
|
||||
|
||||
#endif
|
||||
52
qemu/include/qemu/option_int.h
Normal file
52
qemu/include/qemu/option_int.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Commandline option parsing functions
|
||||
*
|
||||
* Copyright (c) 2003-2008 Fabrice Bellard
|
||||
* Copyright (c) 2009 Kevin Wolf <kwolf@redhat.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_OPTIONS_INTERNAL_H
|
||||
#define QEMU_OPTIONS_INTERNAL_H
|
||||
|
||||
#include "qemu/option.h"
|
||||
|
||||
struct QemuOpt {
|
||||
char *name;
|
||||
char *str;
|
||||
|
||||
const QemuOptDesc *desc;
|
||||
union {
|
||||
bool boolean;
|
||||
uint64_t uint;
|
||||
} value;
|
||||
|
||||
QemuOpts *opts;
|
||||
QTAILQ_ENTRY(QemuOpt) next;
|
||||
};
|
||||
|
||||
struct QemuOpts {
|
||||
char *id;
|
||||
QemuOptsList *list;
|
||||
QTAILQ_HEAD(QemuOptHead, QemuOpt) head;
|
||||
QTAILQ_ENTRY(QemuOpts) next;
|
||||
};
|
||||
|
||||
#endif
|
||||
239
qemu/include/qemu/osdep.h
Normal file
239
qemu/include/qemu/osdep.h
Normal file
@@ -0,0 +1,239 @@
|
||||
#ifndef QEMU_OSDEP_H
|
||||
#define QEMU_OSDEP_H
|
||||
|
||||
#include "config-host.h"
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#ifdef __OpenBSD__
|
||||
#include <sys/signal.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <sys/wait.h>
|
||||
#else
|
||||
#define WIFEXITED(x) 1
|
||||
#define WEXITSTATUS(x) (x)
|
||||
#endif
|
||||
|
||||
#include <sys/time.h>
|
||||
|
||||
#if defined(CONFIG_SOLARIS) && CONFIG_SOLARIS_VERSION < 10
|
||||
/* [u]int_fast*_t not in <sys/int_types.h> */
|
||||
typedef unsigned char uint_fast8_t;
|
||||
typedef unsigned int uint_fast16_t;
|
||||
typedef signed int int_fast16_t;
|
||||
#endif
|
||||
|
||||
#ifndef glue
|
||||
#define xglue(x, y) x ## y
|
||||
#define glue(x, y) xglue(x, y)
|
||||
#define stringify(s) tostring(s)
|
||||
#define tostring(s) #s
|
||||
#endif
|
||||
|
||||
#ifndef likely
|
||||
#if __GNUC__ < 3
|
||||
#define __builtin_expect(x, n) (x)
|
||||
#endif
|
||||
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
|
||||
#ifndef container_of
|
||||
#define container_of(ptr, type, member) ({ \
|
||||
const typeof(((type *) 0)->member) *__mptr = (ptr); \
|
||||
(type *) ((char *) __mptr - offsetof(type, member));})
|
||||
#endif
|
||||
|
||||
/* Convert from a base type to a parent type, with compile time checking. */
|
||||
#ifdef __GNUC__
|
||||
#define DO_UPCAST(type, field, dev) ( __extension__ ( { \
|
||||
char __attribute__((unused)) offset_must_be_zero[ \
|
||||
-offsetof(type, field)]; \
|
||||
container_of(dev, type, field);}))
|
||||
#else
|
||||
#define DO_UPCAST(type, field, dev) container_of(dev, type, field)
|
||||
#endif
|
||||
|
||||
#define typeof_field(type, field) typeof(((type *)0)->field)
|
||||
#define type_check(t1,t2) ((t1*)0 - (t2*)0)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
/* Minimum function that returns zero only iff both values are zero.
|
||||
* Intended for use with unsigned values only. */
|
||||
#ifndef MIN_NON_ZERO
|
||||
#define MIN_NON_ZERO(a, b) (((a) != 0 && (a) < (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
#ifndef ROUND_UP
|
||||
#define ROUND_UP(n,d) (((n) + (d) - 1) & -(d))
|
||||
#endif
|
||||
|
||||
#ifndef DIV_ROUND_UP
|
||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||
#endif
|
||||
|
||||
#ifndef always_inline
|
||||
#if !((__GNUC__ < 3) || defined(__APPLE__))
|
||||
#ifdef __OPTIMIZE__
|
||||
#undef inline
|
||||
#define inline __attribute__ (( always_inline )) __inline__
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#undef inline
|
||||
#define inline always_inline
|
||||
#endif
|
||||
|
||||
#define qemu_printf printf
|
||||
|
||||
int qemu_daemon(int nochdir, int noclose);
|
||||
void *qemu_try_memalign(size_t alignment, size_t size);
|
||||
void *qemu_memalign(size_t alignment, size_t size);
|
||||
void *qemu_anon_ram_alloc(size_t size, uint64_t *align);
|
||||
void qemu_vfree(void *ptr);
|
||||
void qemu_anon_ram_free(void *ptr, size_t size);
|
||||
|
||||
#define QEMU_MADV_INVALID -1
|
||||
|
||||
#if defined(CONFIG_MADVISE)
|
||||
|
||||
#define QEMU_MADV_WILLNEED MADV_WILLNEED
|
||||
#define QEMU_MADV_DONTNEED MADV_DONTNEED
|
||||
#ifdef MADV_DONTFORK
|
||||
#define QEMU_MADV_DONTFORK MADV_DONTFORK
|
||||
#else
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_MERGEABLE
|
||||
#define QEMU_MADV_MERGEABLE MADV_MERGEABLE
|
||||
#else
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_UNMERGEABLE
|
||||
#define QEMU_MADV_UNMERGEABLE MADV_UNMERGEABLE
|
||||
#else
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_DODUMP
|
||||
#define QEMU_MADV_DODUMP MADV_DODUMP
|
||||
#else
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_DONTDUMP
|
||||
#define QEMU_MADV_DONTDUMP MADV_DONTDUMP
|
||||
#else
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#endif
|
||||
#ifdef MADV_HUGEPAGE
|
||||
#define QEMU_MADV_HUGEPAGE MADV_HUGEPAGE
|
||||
#else
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
#endif
|
||||
|
||||
#elif defined(CONFIG_POSIX_MADVISE)
|
||||
|
||||
#define QEMU_MADV_WILLNEED POSIX_MADV_WILLNEED
|
||||
#define QEMU_MADV_DONTNEED POSIX_MADV_DONTNEED
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
|
||||
#else /* no-op */
|
||||
|
||||
#define QEMU_MADV_WILLNEED QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTNEED QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTFORK QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_MERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_UNMERGEABLE QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DODUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_DONTDUMP QEMU_MADV_INVALID
|
||||
#define QEMU_MADV_HUGEPAGE QEMU_MADV_INVALID
|
||||
|
||||
#endif
|
||||
|
||||
int qemu_madvise(void *addr, size_t len, int advice);
|
||||
|
||||
int qemu_open(const char *name, int flags, ...);
|
||||
int qemu_close(int fd);
|
||||
|
||||
#if defined(__HAIKU__) && defined(__i386__)
|
||||
#define FMT_pid "%ld"
|
||||
#elif defined(WIN64)
|
||||
#define FMT_pid "%" PRId64
|
||||
#else
|
||||
#define FMT_pid "%d"
|
||||
#endif
|
||||
|
||||
int qemu_create_pidfile(const char *filename);
|
||||
int qemu_get_thread_id(void);
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline void qemu_timersub(const struct timeval *val1,
|
||||
const struct timeval *val2,
|
||||
struct timeval *res)
|
||||
{
|
||||
res->tv_sec = val1->tv_sec - val2->tv_sec;
|
||||
if (val1->tv_usec < val2->tv_usec) {
|
||||
res->tv_sec--;
|
||||
res->tv_usec = val1->tv_usec - val2->tv_usec + 1000 * 1000;
|
||||
} else {
|
||||
res->tv_usec = val1->tv_usec - val2->tv_usec;
|
||||
}
|
||||
}
|
||||
#else
|
||||
#define qemu_timersub timersub
|
||||
#endif
|
||||
|
||||
void qemu_set_cloexec(int fd);
|
||||
|
||||
void qemu_set_version(const char *);
|
||||
const char *qemu_get_version(void);
|
||||
|
||||
void fips_set_state(bool requested);
|
||||
bool fips_get_state(void);
|
||||
|
||||
/* Return a dynamically allocated pathname denoting a file or directory that is
|
||||
* appropriate for storing local state.
|
||||
*
|
||||
* @relative_pathname need not start with a directory separator; one will be
|
||||
* added automatically.
|
||||
*
|
||||
* The caller is responsible for releasing the value returned with g_free()
|
||||
* after use.
|
||||
*/
|
||||
char *qemu_get_local_state_pathname(const char *relative_pathname);
|
||||
|
||||
/* Get the saved exec dir.
|
||||
* Caller needs to release the returned string by g_free() */
|
||||
char *qemu_get_exec_dir(void);
|
||||
|
||||
/**
|
||||
* qemu_getauxval:
|
||||
* @type: the auxiliary vector key to lookup
|
||||
*
|
||||
* Search the auxiliary vector for @type, returning the value
|
||||
* or 0 if @type is not present.
|
||||
*/
|
||||
unsigned long qemu_getauxval(unsigned long type);
|
||||
|
||||
void qemu_set_tty_echo(int fd, bool echo);
|
||||
|
||||
#endif
|
||||
414
qemu/include/qemu/queue.h
Normal file
414
qemu/include/qemu/queue.h
Normal file
@@ -0,0 +1,414 @@
|
||||
/* $NetBSD: queue.h,v 1.52 2009/04/20 09:56:08 mschuett Exp $ */
|
||||
|
||||
/*
|
||||
* QEMU version: Copy from netbsd, removed debug code, removed some of
|
||||
* the implementations. Left in singly-linked lists, lists, simple
|
||||
* queues, and tail queues.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1991, 1993
|
||||
* The Regents of the University of California. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the University nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||
*/
|
||||
|
||||
#ifndef QEMU_SYS_QUEUE_H_
|
||||
#define QEMU_SYS_QUEUE_H_
|
||||
|
||||
/*
|
||||
* This file defines four types of data structures: singly-linked lists,
|
||||
* lists, simple queues, and tail queues.
|
||||
*
|
||||
* A singly-linked list is headed by a single forward pointer. The
|
||||
* elements are singly linked for minimum space and pointer manipulation
|
||||
* overhead at the expense of O(n) removal for arbitrary elements. New
|
||||
* elements can be added to the list after an existing element or at the
|
||||
* head of the list. Elements being removed from the head of the list
|
||||
* should use the explicit macro for this purpose for optimum
|
||||
* efficiency. A singly-linked list may only be traversed in the forward
|
||||
* direction. Singly-linked lists are ideal for applications with large
|
||||
* datasets and few or no removals or for implementing a LIFO queue.
|
||||
*
|
||||
* A list is headed by a single forward pointer (or an array of forward
|
||||
* pointers for a hash table header). The elements are doubly linked
|
||||
* so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before
|
||||
* or after an existing element or at the head of the list. A list
|
||||
* may only be traversed in the forward direction.
|
||||
*
|
||||
* A simple queue is headed by a pair of pointers, one the head of the
|
||||
* list and the other to the tail of the list. The elements are singly
|
||||
* linked to save space, so elements can only be removed from the
|
||||
* head of the list. New elements can be added to the list after
|
||||
* an existing element, at the head of the list, or at the end of the
|
||||
* list. A simple queue may only be traversed in the forward direction.
|
||||
*
|
||||
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||
* list and the other to the tail of the list. The elements are doubly
|
||||
* linked so that an arbitrary element can be removed without a need to
|
||||
* traverse the list. New elements can be added to the list before or
|
||||
* after an existing element, at the head of the list, or at the end of
|
||||
* the list. A tail queue may be traversed in either direction.
|
||||
*
|
||||
* For details on the use of these macros, see the queue(3) manual page.
|
||||
*/
|
||||
|
||||
#include "qemu/atomic.h" /* for smp_wmb() */
|
||||
|
||||
/*
|
||||
* List definitions.
|
||||
*/
|
||||
#define QLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *lh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define QLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define QLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *le_next; /* next element */ \
|
||||
struct type **le_prev; /* address of previous next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* List functions.
|
||||
*/
|
||||
#define QLIST_INIT(head) do { \
|
||||
(head)->lh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||
if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
|
||||
(listelm)->field.le_next->field.le_prev = \
|
||||
&(elm)->field.le_next; \
|
||||
(listelm)->field.le_next = (elm); \
|
||||
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||
(elm)->field.le_next = (listelm); \
|
||||
*(listelm)->field.le_prev = (elm); \
|
||||
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.le_next = (head)->lh_first) != NULL) \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||
(head)->lh_first = (elm); \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_INSERT_HEAD_RCU(head, elm, field) do { \
|
||||
(elm)->field.le_prev = &(head)->lh_first; \
|
||||
(elm)->field.le_next = (head)->lh_first; \
|
||||
smp_wmb(); /* fill elm before linking it */ \
|
||||
if ((head)->lh_first != NULL) { \
|
||||
(head)->lh_first->field.le_prev = &(elm)->field.le_next; \
|
||||
} \
|
||||
(head)->lh_first = (elm); \
|
||||
smp_wmb(); \
|
||||
} while (/* CONSTCOND*/0)
|
||||
|
||||
#define QLIST_REMOVE(elm, field) do { \
|
||||
if ((elm)->field.le_next != NULL) \
|
||||
(elm)->field.le_next->field.le_prev = \
|
||||
(elm)->field.le_prev; \
|
||||
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QLIST_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.le_next))
|
||||
|
||||
#define QLIST_FOREACH_SAFE(var, head, field, next_var) \
|
||||
for ((var) = ((head)->lh_first); \
|
||||
(var) && ((next_var) = ((var)->field.le_next), 1); \
|
||||
(var) = (next_var))
|
||||
|
||||
/*
|
||||
* List access methods.
|
||||
*/
|
||||
#define QLIST_EMPTY(head) ((head)->lh_first == NULL)
|
||||
#define QLIST_FIRST(head) ((head)->lh_first)
|
||||
#define QLIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||
|
||||
|
||||
/*
|
||||
* Singly-linked List definitions.
|
||||
*/
|
||||
#define QSLIST_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *slh_first; /* first element */ \
|
||||
}
|
||||
|
||||
#define QSLIST_HEAD_INITIALIZER(head) \
|
||||
{ NULL }
|
||||
|
||||
#define QSLIST_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sle_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Singly-linked List functions.
|
||||
*/
|
||||
#define QSLIST_INIT(head) do { \
|
||||
(head)->slh_first = NULL; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||
(slistelm)->field.sle_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_INSERT_HEAD(head, elm, field) do { \
|
||||
(elm)->field.sle_next = (head)->slh_first; \
|
||||
(head)->slh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_HEAD(head, field) do { \
|
||||
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_REMOVE_AFTER(slistelm, field) do { \
|
||||
(slistelm)->field.sle_next = \
|
||||
QSLIST_NEXT(QSLIST_NEXT((slistelm), field), field); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSLIST_FOREACH(var, head, field) \
|
||||
for((var) = (head)->slh_first; (var); (var) = (var)->field.sle_next)
|
||||
|
||||
#define QSLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||
for ((var) = QSLIST_FIRST((head)); \
|
||||
(var) && ((tvar) = QSLIST_NEXT((var), field), 1); \
|
||||
(var) = (tvar))
|
||||
|
||||
/*
|
||||
* Singly-linked List access methods.
|
||||
*/
|
||||
#define QSLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||
#define QSLIST_FIRST(head) ((head)->slh_first)
|
||||
#define QSLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||
|
||||
|
||||
/*
|
||||
* Simple queue definitions.
|
||||
*/
|
||||
#define QSIMPLEQ_HEAD(name, type) \
|
||||
struct name { \
|
||||
struct type *sqh_first; /* first element */ \
|
||||
struct type **sqh_last; /* addr of last next element */ \
|
||||
}
|
||||
|
||||
#define QSIMPLEQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).sqh_first }
|
||||
|
||||
#define QSIMPLEQ_ENTRY(type) \
|
||||
struct { \
|
||||
struct type *sqe_next; /* next element */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Simple queue functions.
|
||||
*/
|
||||
#define QSIMPLEQ_INIT(head) do { \
|
||||
(head)->sqh_first = NULL; \
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(head)->sqh_first = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.sqe_next = NULL; \
|
||||
*(head)->sqh_last = (elm); \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||
(listelm)->field.sqe_next = (elm); \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL)\
|
||||
(head)->sqh_last = &(head)->sqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_REMOVE(head, elm, type, field) do { \
|
||||
if ((head)->sqh_first == (elm)) { \
|
||||
QSIMPLEQ_REMOVE_HEAD((head), field); \
|
||||
} else { \
|
||||
struct type *curelm = (head)->sqh_first; \
|
||||
while (curelm->field.sqe_next != (elm)) \
|
||||
curelm = curelm->field.sqe_next; \
|
||||
if ((curelm->field.sqe_next = \
|
||||
curelm->field.sqe_next->field.sqe_next) == NULL) \
|
||||
(head)->sqh_last = &(curelm)->field.sqe_next; \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.sqe_next))
|
||||
|
||||
#define QSIMPLEQ_FOREACH_SAFE(var, head, field, next) \
|
||||
for ((var) = ((head)->sqh_first); \
|
||||
(var) && ((next = ((var)->field.sqe_next)), 1); \
|
||||
(var) = (next))
|
||||
|
||||
#define QSIMPLEQ_CONCAT(head1, head2) do { \
|
||||
if (!QSIMPLEQ_EMPTY((head2))) { \
|
||||
*(head1)->sqh_last = (head2)->sqh_first; \
|
||||
(head1)->sqh_last = (head2)->sqh_last; \
|
||||
QSIMPLEQ_INIT((head2)); \
|
||||
} \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QSIMPLEQ_LAST(head, type, field) \
|
||||
(QSIMPLEQ_EMPTY((head)) ? \
|
||||
NULL : \
|
||||
((struct type *)(void *) \
|
||||
((char *)((head)->sqh_last) - offsetof(struct type, field))))
|
||||
|
||||
/*
|
||||
* Simple queue access methods.
|
||||
*/
|
||||
#define QSIMPLEQ_EMPTY(head) ((head)->sqh_first == NULL)
|
||||
#define QSIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||
#define QSIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||
|
||||
|
||||
/*
|
||||
* Tail queue definitions.
|
||||
*/
|
||||
#define Q_TAILQ_HEAD(name, type, qual) \
|
||||
struct name { \
|
||||
qual type *tqh_first; /* first element */ \
|
||||
qual type *qual *tqh_last; /* addr of last next element */ \
|
||||
}
|
||||
#define QTAILQ_HEAD(name, type) Q_TAILQ_HEAD(name, struct type,)
|
||||
|
||||
#define QTAILQ_HEAD_INITIALIZER(head) \
|
||||
{ NULL, &(head).tqh_first }
|
||||
|
||||
#define Q_TAILQ_ENTRY(type, qual) \
|
||||
struct { \
|
||||
qual type *tqe_next; /* next element */ \
|
||||
qual type *qual *tqe_prev; /* address of previous next element */\
|
||||
}
|
||||
#define QTAILQ_ENTRY(type) Q_TAILQ_ENTRY(struct type,)
|
||||
|
||||
/*
|
||||
* Tail queue functions.
|
||||
*/
|
||||
#define QTAILQ_INIT(head) do { \
|
||||
(head)->tqh_first = NULL; \
|
||||
(head)->tqh_last = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
|
||||
(head)->tqh_first->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(head)->tqh_first = (elm); \
|
||||
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||
(elm)->field.tqe_next = NULL; \
|
||||
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||
*(head)->tqh_last = (elm); \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
&(elm)->field.tqe_next; \
|
||||
else \
|
||||
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||
(listelm)->field.tqe_next = (elm); \
|
||||
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||
(elm)->field.tqe_next = (listelm); \
|
||||
*(listelm)->field.tqe_prev = (elm); \
|
||||
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_REMOVE(head, elm, field) do { \
|
||||
if (((elm)->field.tqe_next) != NULL) \
|
||||
(elm)->field.tqe_next->field.tqe_prev = \
|
||||
(elm)->field.tqe_prev; \
|
||||
else \
|
||||
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||
} while (/*CONSTCOND*/0)
|
||||
|
||||
#define QTAILQ_FOREACH(var, head, field) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var); \
|
||||
(var) = ((var)->field.tqe_next))
|
||||
|
||||
#define QTAILQ_FOREACH_SAFE(var, head, field, next_var) \
|
||||
for ((var) = ((head)->tqh_first); \
|
||||
(var) && ((next_var) = ((var)->field.tqe_next), 1); \
|
||||
(var) = (next_var))
|
||||
|
||||
#define QTAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||
for ((var) = (*(((struct headname *)((head)->tqh_last))->tqh_last)); \
|
||||
(var); \
|
||||
(var) = (*(((struct headname *)((var)->field.tqe_prev))->tqh_last)))
|
||||
|
||||
/*
|
||||
* Tail queue access methods.
|
||||
*/
|
||||
#define QTAILQ_EMPTY(head) ((head)->tqh_first == NULL)
|
||||
#define QTAILQ_FIRST(head) ((head)->tqh_first)
|
||||
#define QTAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||
|
||||
#define QTAILQ_LAST(head, headname) \
|
||||
(*(((struct headname *)((head)->tqh_last))->tqh_last))
|
||||
#define QTAILQ_PREV(elm, headname, field) \
|
||||
(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
|
||||
|
||||
#endif /* !QEMU_SYS_QUEUE_H_ */
|
||||
135
qemu/include/qemu/range.h
Normal file
135
qemu/include/qemu/range.h
Normal file
@@ -0,0 +1,135 @@
|
||||
#ifndef QEMU_RANGE_H
|
||||
#define QEMU_RANGE_H
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <qemu/typedefs.h>
|
||||
#include "qemu/queue.h"
|
||||
|
||||
/*
|
||||
* Operations on 64 bit address ranges.
|
||||
* Notes:
|
||||
* - ranges must not wrap around 0, but can include the last byte ~0x0LL.
|
||||
* - this can not represent a full 0 to ~0x0LL range.
|
||||
*/
|
||||
|
||||
/* A structure representing a range of addresses. */
|
||||
struct Range {
|
||||
uint64_t begin; /* First byte of the range, or 0 if empty. */
|
||||
uint64_t end; /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
|
||||
};
|
||||
|
||||
static inline void range_extend(Range *range, Range *extend_by)
|
||||
{
|
||||
if (!extend_by->begin && !extend_by->end) {
|
||||
return;
|
||||
}
|
||||
if (!range->begin && !range->end) {
|
||||
*range = *extend_by;
|
||||
return;
|
||||
}
|
||||
if (range->begin > extend_by->begin) {
|
||||
range->begin = extend_by->begin;
|
||||
}
|
||||
/* Compare last byte in case region ends at ~0x0LL */
|
||||
if (range->end - 1 < extend_by->end - 1) {
|
||||
range->end = extend_by->end;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get last byte of a range from offset + length.
|
||||
* Undefined for ranges that wrap around 0. */
|
||||
static inline uint64_t range_get_last(uint64_t offset, uint64_t len)
|
||||
{
|
||||
return offset + len - 1;
|
||||
}
|
||||
|
||||
/* Check whether a given range covers a given byte. */
|
||||
static inline int range_covers_byte(uint64_t offset, uint64_t len,
|
||||
uint64_t byte)
|
||||
{
|
||||
return offset <= byte && byte <= range_get_last(offset, len);
|
||||
}
|
||||
|
||||
/* Check whether 2 given ranges overlap.
|
||||
* Undefined if ranges that wrap around 0. */
|
||||
static inline int ranges_overlap(uint64_t first1, uint64_t len1,
|
||||
uint64_t first2, uint64_t len2)
|
||||
{
|
||||
uint64_t last1 = range_get_last(first1, len1);
|
||||
uint64_t last2 = range_get_last(first2, len2);
|
||||
|
||||
return !(last2 < first1 || last1 < first2);
|
||||
}
|
||||
|
||||
/* 0,1 can merge with 1,2 but don't overlap */
|
||||
static inline bool ranges_can_merge(Range *range1, Range *range2)
|
||||
{
|
||||
return !(range1->end < range2->begin || range2->end < range1->begin);
|
||||
}
|
||||
|
||||
static inline int range_merge(Range *range1, Range *range2)
|
||||
{
|
||||
if (ranges_can_merge(range1, range2)) {
|
||||
if (range1->end < range2->end) {
|
||||
range1->end = range2->end;
|
||||
}
|
||||
if (range1->begin > range2->begin) {
|
||||
range1->begin = range2->begin;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static inline GList *g_list_insert_sorted_merged(GList *list,
|
||||
gpointer data,
|
||||
GCompareFunc func)
|
||||
{
|
||||
GList *l, *next = NULL;
|
||||
Range *r, *nextr;
|
||||
|
||||
if (!list) {
|
||||
list = g_list_insert_sorted(list, data, func);
|
||||
return list;
|
||||
}
|
||||
|
||||
nextr = data;
|
||||
l = list;
|
||||
while (l && l != next && nextr) {
|
||||
r = l->data;
|
||||
if (ranges_can_merge(r, nextr)) {
|
||||
range_merge(r, nextr);
|
||||
l = g_list_remove_link(l, next);
|
||||
next = g_list_next(l);
|
||||
if (next) {
|
||||
nextr = next->data;
|
||||
} else {
|
||||
nextr = NULL;
|
||||
}
|
||||
} else {
|
||||
l = g_list_next(l);
|
||||
}
|
||||
}
|
||||
|
||||
if (!l) {
|
||||
list = g_list_insert_sorted(list, data, func);
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
static inline gint range_compare(gconstpointer a, gconstpointer b)
|
||||
{
|
||||
Range *ra = (Range *)a, *rb = (Range *)b;
|
||||
if (ra->begin == rb->begin && ra->end == rb->end) {
|
||||
return 0;
|
||||
} else if (range_get_last(ra->begin, ra->end) <
|
||||
range_get_last(rb->begin, rb->end)) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
65
qemu/include/qemu/seqlock.h
Normal file
65
qemu/include/qemu/seqlock.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Seqlock implementation for QEMU
|
||||
*
|
||||
* Copyright Red Hat, Inc. 2013
|
||||
*
|
||||
* Author:
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* 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 QEMU_SEQLOCK_H
|
||||
#define QEMU_SEQLOCK_H 1
|
||||
|
||||
#include <qemu/atomic.h>
|
||||
#include <qemu/thread.h>
|
||||
|
||||
typedef struct QemuSeqLock QemuSeqLock;
|
||||
|
||||
struct QemuSeqLock {
|
||||
QemuMutex *mutex;
|
||||
unsigned sequence;
|
||||
};
|
||||
|
||||
static inline void seqlock_init(QemuSeqLock *sl, QemuMutex *mutex)
|
||||
{
|
||||
sl->mutex = mutex;
|
||||
sl->sequence = 0;
|
||||
}
|
||||
|
||||
/* Lock out other writers and update the count. */
|
||||
static inline void seqlock_write_lock(QemuSeqLock *sl)
|
||||
{
|
||||
if (sl->mutex) {
|
||||
qemu_mutex_lock(sl->mutex);
|
||||
}
|
||||
++sl->sequence;
|
||||
|
||||
/* Write sequence before updating other fields. */
|
||||
smp_wmb();
|
||||
}
|
||||
|
||||
static inline void seqlock_write_unlock(QemuSeqLock *sl)
|
||||
{
|
||||
/* Write other fields before finalizing sequence. */
|
||||
smp_wmb();
|
||||
|
||||
++sl->sequence;
|
||||
if (sl->mutex) {
|
||||
qemu_mutex_unlock(sl->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static inline unsigned seqlock_read_begin(QemuSeqLock *sl)
|
||||
{
|
||||
/* Always fail if a write is in progress. */
|
||||
unsigned ret = sl->sequence & ~1;
|
||||
|
||||
/* Read sequence before reading other fields. */
|
||||
smp_rmb();
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
36
qemu/include/qemu/thread-posix.h
Normal file
36
qemu/include/qemu/thread-posix.h
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef __QEMU_THREAD_POSIX_H
|
||||
#define __QEMU_THREAD_POSIX_H 1
|
||||
#include "pthread.h"
|
||||
#include <semaphore.h>
|
||||
|
||||
struct QemuMutex {
|
||||
pthread_mutex_t lock;
|
||||
};
|
||||
|
||||
struct QemuCond {
|
||||
pthread_cond_t cond;
|
||||
};
|
||||
|
||||
struct QemuSemaphore {
|
||||
#if defined(__APPLE__) || defined(__NetBSD__)
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
unsigned int count;
|
||||
#else
|
||||
sem_t sem;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct QemuEvent {
|
||||
#ifndef __linux__
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t cond;
|
||||
#endif
|
||||
unsigned value;
|
||||
};
|
||||
|
||||
struct QemuThread {
|
||||
pthread_t thread;
|
||||
};
|
||||
|
||||
#endif
|
||||
33
qemu/include/qemu/thread-win32.h
Normal file
33
qemu/include/qemu/thread-win32.h
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef __QEMU_THREAD_WIN32_H
|
||||
#define __QEMU_THREAD_WIN32_H 1
|
||||
#include "windows.h"
|
||||
|
||||
struct QemuMutex {
|
||||
CRITICAL_SECTION lock;
|
||||
LONG owner;
|
||||
};
|
||||
|
||||
struct QemuCond {
|
||||
LONG waiters, target;
|
||||
HANDLE sema;
|
||||
HANDLE continue_event;
|
||||
};
|
||||
|
||||
struct QemuSemaphore {
|
||||
HANDLE sema;
|
||||
};
|
||||
|
||||
struct QemuEvent {
|
||||
HANDLE event;
|
||||
};
|
||||
|
||||
typedef struct QemuThreadData QemuThreadData;
|
||||
struct QemuThread {
|
||||
QemuThreadData *data;
|
||||
unsigned tid;
|
||||
};
|
||||
|
||||
/* Only valid for joinable threads. */
|
||||
HANDLE qemu_thread_get_handle(QemuThread *thread);
|
||||
|
||||
#endif
|
||||
63
qemu/include/qemu/thread.h
Normal file
63
qemu/include/qemu/thread.h
Normal file
@@ -0,0 +1,63 @@
|
||||
#ifndef __QEMU_THREAD_H
|
||||
#define __QEMU_THREAD_H 1
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct QemuMutex QemuMutex;
|
||||
typedef struct QemuCond QemuCond;
|
||||
typedef struct QemuSemaphore QemuSemaphore;
|
||||
typedef struct QemuEvent QemuEvent;
|
||||
typedef struct QemuThread QemuThread;
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "qemu/thread-win32.h"
|
||||
#else
|
||||
#include "qemu/thread-posix.h"
|
||||
#endif
|
||||
|
||||
#define QEMU_THREAD_JOINABLE 0
|
||||
#define QEMU_THREAD_DETACHED 1
|
||||
|
||||
void qemu_mutex_init(QemuMutex *mutex);
|
||||
void qemu_mutex_destroy(QemuMutex *mutex);
|
||||
void qemu_mutex_lock(QemuMutex *mutex);
|
||||
int qemu_mutex_trylock(QemuMutex *mutex);
|
||||
void qemu_mutex_unlock(QemuMutex *mutex);
|
||||
|
||||
#define rcu_read_lock() do { } while (0)
|
||||
#define rcu_read_unlock() do { } while (0)
|
||||
|
||||
void qemu_cond_init(QemuCond *cond);
|
||||
void qemu_cond_destroy(QemuCond *cond);
|
||||
|
||||
/*
|
||||
* IMPORTANT: The implementation does not guarantee that pthread_cond_signal
|
||||
* and pthread_cond_broadcast can be called except while the same mutex is
|
||||
* held as in the corresponding pthread_cond_wait calls!
|
||||
*/
|
||||
void qemu_cond_signal(QemuCond *cond);
|
||||
void qemu_cond_broadcast(QemuCond *cond);
|
||||
void qemu_cond_wait(QemuCond *cond, QemuMutex *mutex);
|
||||
|
||||
void qemu_sem_init(QemuSemaphore *sem, int init);
|
||||
void qemu_sem_post(QemuSemaphore *sem);
|
||||
void qemu_sem_wait(QemuSemaphore *sem);
|
||||
int qemu_sem_timedwait(QemuSemaphore *sem, int ms);
|
||||
void qemu_sem_destroy(QemuSemaphore *sem);
|
||||
|
||||
void qemu_event_init(QemuEvent *ev, bool init);
|
||||
void qemu_event_set(QemuEvent *ev);
|
||||
void qemu_event_reset(QemuEvent *ev);
|
||||
void qemu_event_wait(QemuEvent *ev);
|
||||
void qemu_event_destroy(QemuEvent *ev);
|
||||
|
||||
void qemu_thread_create(QemuThread *thread, const char *name,
|
||||
void *(*start_routine)(void *),
|
||||
void *arg, int mode);
|
||||
void *qemu_thread_join(QemuThread *thread);
|
||||
void qemu_thread_get_self(QemuThread *thread);
|
||||
bool qemu_thread_is_self(QemuThread *thread);
|
||||
void qemu_thread_exit(void *retval);
|
||||
|
||||
#endif
|
||||
836
qemu/include/qemu/timer.h
Normal file
836
qemu/include/qemu/timer.h
Normal file
@@ -0,0 +1,836 @@
|
||||
#ifndef QEMU_TIMER_H
|
||||
#define QEMU_TIMER_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/notify.h"
|
||||
|
||||
/* timers */
|
||||
|
||||
#define SCALE_MS 1000000
|
||||
#define SCALE_US 1000
|
||||
#define SCALE_NS 1
|
||||
|
||||
/**
|
||||
* QEMUClockType:
|
||||
*
|
||||
* The following clock types are available:
|
||||
*
|
||||
* @QEMU_CLOCK_REALTIME: Real time clock
|
||||
*
|
||||
* The real time clock should be used only for stuff which does not
|
||||
* change the virtual machine state, as it is run even if the virtual
|
||||
* machine is stopped. The real time clock has a frequency of 1000
|
||||
* Hz.
|
||||
*
|
||||
* @QEMU_CLOCK_VIRTUAL: virtual clock
|
||||
*
|
||||
* The virtual clock is only run during the emulation. It is stopped
|
||||
* when the virtual machine is stopped. Virtual timers use a high
|
||||
* precision clock, usually cpu cycles (use ticks_per_sec).
|
||||
*
|
||||
* @QEMU_CLOCK_HOST: host clock
|
||||
*
|
||||
* The host clock should be use for device models that emulate accurate
|
||||
* real time sources. It will continue to run when the virtual machine
|
||||
* is suspended, and it will reflect system time changes the host may
|
||||
* undergo (e.g. due to NTP). The host clock has the same precision as
|
||||
* the virtual clock.
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
QEMU_CLOCK_REALTIME = 0,
|
||||
QEMU_CLOCK_VIRTUAL = 1,
|
||||
QEMU_CLOCK_HOST = 2,
|
||||
QEMU_CLOCK_MAX
|
||||
} QEMUClockType;
|
||||
|
||||
typedef struct QEMUTimerList QEMUTimerList;
|
||||
|
||||
struct QEMUTimerListGroup {
|
||||
QEMUTimerList *tl[QEMU_CLOCK_MAX];
|
||||
};
|
||||
|
||||
typedef void QEMUTimerCB(void *opaque);
|
||||
typedef void QEMUTimerListNotifyCB(void *opaque);
|
||||
|
||||
struct QEMUTimer {
|
||||
int64_t expire_time; /* in nanoseconds */
|
||||
QEMUTimerList *timer_list;
|
||||
QEMUTimerCB *cb;
|
||||
void *opaque;
|
||||
QEMUTimer *next;
|
||||
int scale;
|
||||
};
|
||||
|
||||
/*
|
||||
* QEMUClockType
|
||||
*/
|
||||
|
||||
/*
|
||||
* qemu_clock_get_ns;
|
||||
* @type: the clock type
|
||||
*
|
||||
* Get the nanosecond value of a clock with
|
||||
* type @type
|
||||
*
|
||||
* Returns: the clock value in nanoseconds
|
||||
*/
|
||||
int64_t qemu_clock_get_ns(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_get_ms;
|
||||
* @type: the clock type
|
||||
*
|
||||
* Get the millisecond value of a clock with
|
||||
* type @type
|
||||
*
|
||||
* Returns: the clock value in milliseconds
|
||||
*/
|
||||
static inline int64_t qemu_clock_get_ms(QEMUClockType type)
|
||||
{
|
||||
return qemu_clock_get_ns(type) / SCALE_MS;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemu_clock_get_us;
|
||||
* @type: the clock type
|
||||
*
|
||||
* Get the microsecond value of a clock with
|
||||
* type @type
|
||||
*
|
||||
* Returns: the clock value in microseconds
|
||||
*/
|
||||
static inline int64_t qemu_clock_get_us(QEMUClockType type)
|
||||
{
|
||||
return qemu_clock_get_ns(type) / SCALE_US;
|
||||
}
|
||||
|
||||
/**
|
||||
* qemu_clock_has_timers:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Determines whether a clock's default timer list
|
||||
* has timers attached
|
||||
*
|
||||
* Note that this function should not be used when other threads also access
|
||||
* the timer list. The return value may be outdated by the time it is acted
|
||||
* upon.
|
||||
*
|
||||
* Returns: true if the clock's default timer list
|
||||
* has timers attached
|
||||
*/
|
||||
bool qemu_clock_has_timers(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_expired:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Determines whether a clock's default timer list
|
||||
* has an expired clock.
|
||||
*
|
||||
* Returns: true if the clock's default timer list has
|
||||
* an expired timer
|
||||
*/
|
||||
bool qemu_clock_expired(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_use_for_deadline:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Determine whether a clock should be used for deadline
|
||||
* calculations. Some clocks, for instance vm_clock with
|
||||
* use_icount set, do not count in nanoseconds. Such clocks
|
||||
* are not used for deadline calculations, and are presumed
|
||||
* to interrupt any poll using qemu_notify/aio_notify
|
||||
* etc.
|
||||
*
|
||||
* Returns: true if the clock runs in nanoseconds and
|
||||
* should be used for a deadline.
|
||||
*/
|
||||
bool qemu_clock_use_for_deadline(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_deadline_ns_all:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Calculate the deadline across all timer lists associated
|
||||
* with a clock (as opposed to just the default one)
|
||||
* in nanoseconds, or -1 if no timer is set to expire.
|
||||
*
|
||||
* Returns: time until expiry in nanoseconds or -1
|
||||
*/
|
||||
int64_t qemu_clock_deadline_ns_all(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_get_main_loop_timerlist:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Return the default timer list assocatiated with a clock.
|
||||
*
|
||||
* Returns: the default timer list
|
||||
*/
|
||||
QEMUTimerList *qemu_clock_get_main_loop_timerlist(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_nofify:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Call the notifier callback connected with the default timer
|
||||
* list linked to the clock, or qemu_notify() if none.
|
||||
*/
|
||||
void qemu_clock_notify(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_enable:
|
||||
* @type: the clock type
|
||||
* @enabled: true to enable, false to disable
|
||||
*
|
||||
* Enable or disable a clock
|
||||
* Disabling the clock will wait for related timerlists to stop
|
||||
* executing qemu_run_timers. Thus, this functions should not
|
||||
* be used from the callback of a timer that is based on @clock.
|
||||
* Doing so would cause a deadlock.
|
||||
*
|
||||
* Caller should hold BQL.
|
||||
*/
|
||||
void qemu_clock_enable(QEMUClockType type, bool enabled);
|
||||
|
||||
/**
|
||||
* qemu_clock_warp:
|
||||
* @type: the clock type
|
||||
*
|
||||
* Warp a clock to a new value
|
||||
*/
|
||||
void qemu_clock_warp(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_register_reset_notifier:
|
||||
* @type: the clock type
|
||||
* @notifier: the notifier function
|
||||
*
|
||||
* Register a notifier function to call when the clock
|
||||
* concerned is reset.
|
||||
*/
|
||||
void qemu_clock_register_reset_notifier(QEMUClockType type,
|
||||
Notifier *notifier);
|
||||
|
||||
/**
|
||||
* qemu_clock_unregister_reset_notifier:
|
||||
* @type: the clock type
|
||||
* @notifier: the notifier function
|
||||
*
|
||||
* Unregister a notifier function to call when the clock
|
||||
* concerned is reset.
|
||||
*/
|
||||
void qemu_clock_unregister_reset_notifier(QEMUClockType type,
|
||||
Notifier *notifier);
|
||||
|
||||
/**
|
||||
* qemu_clock_run_timers:
|
||||
* @type: clock on which to operate
|
||||
*
|
||||
* Run all the timers associated with the default timer list
|
||||
* of a clock.
|
||||
*
|
||||
* Returns: true if any timer ran.
|
||||
*/
|
||||
bool qemu_clock_run_timers(QEMUClockType type);
|
||||
|
||||
/**
|
||||
* qemu_clock_run_all_timers:
|
||||
*
|
||||
* Run all the timers associated with the default timer list
|
||||
* of every clock.
|
||||
*
|
||||
* Returns: true if any timer ran.
|
||||
*/
|
||||
bool qemu_clock_run_all_timers(void);
|
||||
|
||||
/*
|
||||
* QEMUTimerList
|
||||
*/
|
||||
|
||||
/**
|
||||
* timerlist_new:
|
||||
* @type: the clock type to associate with the timerlist
|
||||
* @cb: the callback to call on notification
|
||||
* @opaque: the opaque pointer to pass to the callback
|
||||
*
|
||||
* Create a new timerlist associated with the clock of
|
||||
* type @type.
|
||||
*
|
||||
* Returns: a pointer to the QEMUTimerList created
|
||||
*/
|
||||
QEMUTimerList *timerlist_new(QEMUClockType type,
|
||||
QEMUTimerListNotifyCB *cb, void *opaque);
|
||||
|
||||
/**
|
||||
* timerlist_free:
|
||||
* @timer_list: the timer list to free
|
||||
*
|
||||
* Frees a timer_list. It must have no active timers.
|
||||
*/
|
||||
void timerlist_free(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_has_timers:
|
||||
* @timer_list: the timer list to operate on
|
||||
*
|
||||
* Determine whether a timer list has active timers
|
||||
*
|
||||
* Note that this function should not be used when other threads also access
|
||||
* the timer list. The return value may be outdated by the time it is acted
|
||||
* upon.
|
||||
*
|
||||
* Returns: true if the timer list has timers.
|
||||
*/
|
||||
bool timerlist_has_timers(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_expired:
|
||||
* @timer_list: the timer list to operate on
|
||||
*
|
||||
* Determine whether a timer list has any timers which
|
||||
* are expired.
|
||||
*
|
||||
* Returns: true if the timer list has timers which
|
||||
* have expired.
|
||||
*/
|
||||
bool timerlist_expired(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_deadline_ns:
|
||||
* @timer_list: the timer list to operate on
|
||||
*
|
||||
* Determine the deadline for a timer_list, i.e.
|
||||
* the number of nanoseconds until the first timer
|
||||
* expires. Return -1 if there are no timers.
|
||||
*
|
||||
* Returns: the number of nanoseconds until the earliest
|
||||
* timer expires -1 if none
|
||||
*/
|
||||
int64_t timerlist_deadline_ns(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_get_clock:
|
||||
* @timer_list: the timer list to operate on
|
||||
*
|
||||
* Determine the clock type associated with a timer list.
|
||||
*
|
||||
* Returns: the clock type associated with the
|
||||
* timer list.
|
||||
*/
|
||||
QEMUClockType timerlist_get_clock(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_run_timers:
|
||||
* @timer_list: the timer list to use
|
||||
*
|
||||
* Call all expired timers associated with the timer list.
|
||||
*
|
||||
* Returns: true if any timer expired
|
||||
*/
|
||||
bool timerlist_run_timers(QEMUTimerList *timer_list);
|
||||
|
||||
/**
|
||||
* timerlist_notify:
|
||||
* @timer_list: the timer list to use
|
||||
*
|
||||
* call the notifier callback associated with the timer list.
|
||||
*/
|
||||
void timerlist_notify(QEMUTimerList *timer_list);
|
||||
|
||||
/*
|
||||
* QEMUTimerListGroup
|
||||
*/
|
||||
|
||||
/**
|
||||
* timerlistgroup_init:
|
||||
* @tlg: the timer list group
|
||||
* @cb: the callback to call when a notify is required
|
||||
* @opaque: the opaque pointer to be passed to the callback.
|
||||
*
|
||||
* Initialise a timer list group. This must already be
|
||||
* allocated in memory and zeroed. The notifier callback is
|
||||
* called whenever a clock in the timer list group is
|
||||
* reenabled or whenever a timer associated with any timer
|
||||
* list is modified. If @cb is specified as null, qemu_notify()
|
||||
* is used instead.
|
||||
*/
|
||||
void timerlistgroup_init(QEMUTimerListGroup *tlg,
|
||||
QEMUTimerListNotifyCB *cb, void *opaque);
|
||||
|
||||
/**
|
||||
* timerlistgroup_deinit:
|
||||
* @tlg: the timer list group
|
||||
*
|
||||
* Deinitialise a timer list group. This must already be
|
||||
* initialised. Note the memory is not freed.
|
||||
*/
|
||||
void timerlistgroup_deinit(QEMUTimerListGroup *tlg);
|
||||
|
||||
/**
|
||||
* timerlistgroup_run_timers:
|
||||
* @tlg: the timer list group
|
||||
*
|
||||
* Run the timers associated with a timer list group.
|
||||
* This will run timers on multiple clocks.
|
||||
*
|
||||
* Returns: true if any timer callback ran
|
||||
*/
|
||||
bool timerlistgroup_run_timers(QEMUTimerListGroup *tlg);
|
||||
|
||||
/**
|
||||
* timerlistgroup_deadline_ns:
|
||||
* @tlg: the timer list group
|
||||
*
|
||||
* Determine the deadline of the soonest timer to
|
||||
* expire associated with any timer list linked to
|
||||
* the timer list group. Only clocks suitable for
|
||||
* deadline calculation are included.
|
||||
*
|
||||
* Returns: the deadline in nanoseconds or -1 if no
|
||||
* timers are to expire.
|
||||
*/
|
||||
int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
|
||||
|
||||
/*
|
||||
* QEMUTimer
|
||||
*/
|
||||
|
||||
/**
|
||||
* timer_init:
|
||||
* @ts: the timer to be initialised
|
||||
* @timer_list: the timer list to attach the timer to
|
||||
* @scale: the scale value for the timer
|
||||
* @cb: the callback to be called when the timer expires
|
||||
* @opaque: the opaque pointer to be passed to the callback
|
||||
*
|
||||
* Initialise a new timer and associate it with @timer_list.
|
||||
* The caller is responsible for allocating the memory.
|
||||
*
|
||||
* You need not call an explicit deinit call. Simply make
|
||||
* sure it is not on a list with timer_del.
|
||||
*/
|
||||
void timer_init(QEMUTimer *ts,
|
||||
QEMUTimerList *timer_list, int scale,
|
||||
QEMUTimerCB *cb, void *opaque);
|
||||
|
||||
/**
|
||||
* timer_new_tl:
|
||||
* @timer_list: the timer list to attach the timer to
|
||||
* @scale: the scale value for the timer
|
||||
* @cb: the callback to be called when the timer expires
|
||||
* @opaque: the opaque pointer to be passed to the callback
|
||||
*
|
||||
* Creeate a new timer and associate it with @timer_list.
|
||||
* The memory is allocated by the function.
|
||||
*
|
||||
* This is not the preferred interface unless you know you
|
||||
* are going to call timer_free. Use timer_init instead.
|
||||
*
|
||||
* Returns: a pointer to the timer
|
||||
*/
|
||||
static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list,
|
||||
int scale,
|
||||
QEMUTimerCB *cb,
|
||||
void *opaque)
|
||||
{
|
||||
QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer));
|
||||
timer_init(ts, timer_list, scale, cb, opaque);
|
||||
return ts;
|
||||
}
|
||||
|
||||
/**
|
||||
* timer_free:
|
||||
* @ts: the timer
|
||||
*
|
||||
* Free a timer (it must not be on the active list)
|
||||
*/
|
||||
void timer_free(QEMUTimer *ts);
|
||||
|
||||
/**
|
||||
* timer_del:
|
||||
* @ts: the timer
|
||||
*
|
||||
* Delete a timer from the active list.
|
||||
*
|
||||
* This function is thread-safe but the timer and its timer list must not be
|
||||
* freed while this function is running.
|
||||
*/
|
||||
void timer_del(QEMUTimer *ts);
|
||||
|
||||
/**
|
||||
* timer_mod_ns:
|
||||
* @ts: the timer
|
||||
* @expire_time: the expiry time in nanoseconds
|
||||
*
|
||||
* Modify a timer to expire at @expire_time
|
||||
*
|
||||
* This function is thread-safe but the timer and its timer list must not be
|
||||
* freed while this function is running.
|
||||
*/
|
||||
void timer_mod_ns(QEMUTimer *ts, int64_t expire_time);
|
||||
|
||||
/**
|
||||
* timer_mod_anticipate_ns:
|
||||
* @ts: the timer
|
||||
* @expire_time: the expiry time in nanoseconds
|
||||
*
|
||||
* Modify a timer to expire at @expire_time or the current time,
|
||||
* whichever comes earlier.
|
||||
*
|
||||
* This function is thread-safe but the timer and its timer list must not be
|
||||
* freed while this function is running.
|
||||
*/
|
||||
void timer_mod_anticipate_ns(QEMUTimer *ts, int64_t expire_time);
|
||||
|
||||
/**
|
||||
* timer_mod:
|
||||
* @ts: the timer
|
||||
* @expire_time: the expire time in the units associated with the timer
|
||||
*
|
||||
* Modify a timer to expiry at @expire_time, taking into
|
||||
* account the scale associated with the timer.
|
||||
*
|
||||
* This function is thread-safe but the timer and its timer list must not be
|
||||
* freed while this function is running.
|
||||
*/
|
||||
void timer_mod(QEMUTimer *ts, int64_t expire_timer);
|
||||
|
||||
/**
|
||||
* timer_mod_anticipate:
|
||||
* @ts: the timer
|
||||
* @expire_time: the expiry time in nanoseconds
|
||||
*
|
||||
* Modify a timer to expire at @expire_time or the current time, whichever
|
||||
* comes earlier, taking into account the scale associated with the timer.
|
||||
*
|
||||
* This function is thread-safe but the timer and its timer list must not be
|
||||
* freed while this function is running.
|
||||
*/
|
||||
void timer_mod_anticipate(QEMUTimer *ts, int64_t expire_time);
|
||||
|
||||
/**
|
||||
* timer_pending:
|
||||
* @ts: the timer
|
||||
*
|
||||
* Determines whether a timer is pending (i.e. is on the
|
||||
* active list of timers, whether or not it has not yet expired).
|
||||
*
|
||||
* Returns: true if the timer is pending
|
||||
*/
|
||||
bool timer_pending(QEMUTimer *ts);
|
||||
|
||||
/**
|
||||
* timer_expired:
|
||||
* @ts: the timer
|
||||
*
|
||||
* Determines whether a timer has expired.
|
||||
*
|
||||
* Returns: true if the timer has expired
|
||||
*/
|
||||
bool timer_expired(QEMUTimer *timer_head, int64_t current_time);
|
||||
|
||||
/**
|
||||
* timer_expire_time_ns:
|
||||
* @ts: the timer
|
||||
*
|
||||
* Determine the expiry time of a timer
|
||||
*
|
||||
* Returns: the expiry time in nanoseconds
|
||||
*/
|
||||
uint64_t timer_expire_time_ns(QEMUTimer *ts);
|
||||
|
||||
/**
|
||||
* timer_get:
|
||||
* @f: the file
|
||||
* @ts: the timer
|
||||
*
|
||||
* Read a timer @ts from a file @f
|
||||
*/
|
||||
void timer_get(QEMUFile *f, QEMUTimer *ts);
|
||||
|
||||
/**
|
||||
* timer_put:
|
||||
* @f: the file
|
||||
* @ts: the timer
|
||||
*/
|
||||
void timer_put(QEMUFile *f, QEMUTimer *ts);
|
||||
|
||||
/*
|
||||
* General utility functions
|
||||
*/
|
||||
|
||||
/**
|
||||
* qemu_timeout_ns_to_ms:
|
||||
* @ns: nanosecond timeout value
|
||||
*
|
||||
* Convert a nanosecond timeout value (or -1) to
|
||||
* a millisecond value (or -1), always rounding up.
|
||||
*
|
||||
* Returns: millisecond timeout value
|
||||
*/
|
||||
int qemu_timeout_ns_to_ms(int64_t ns);
|
||||
|
||||
/**
|
||||
* qemu_poll_ns:
|
||||
* @fds: Array of file descriptors
|
||||
* @nfds: number of file descriptors
|
||||
* @timeout: timeout in nanoseconds
|
||||
*
|
||||
* Perform a poll like g_poll but with a timeout in nanoseconds.
|
||||
* See g_poll documentation for further details.
|
||||
*
|
||||
* Returns: number of fds ready
|
||||
*/
|
||||
int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout);
|
||||
|
||||
/**
|
||||
* qemu_soonest_timeout:
|
||||
* @timeout1: first timeout in nanoseconds (or -1 for infinite)
|
||||
* @timeout2: second timeout in nanoseconds (or -1 for infinite)
|
||||
*
|
||||
* Calculates the soonest of two timeout values. -1 means infinite, which
|
||||
* is later than any other value.
|
||||
*
|
||||
* Returns: soonest timeout value in nanoseconds (or -1 for infinite)
|
||||
*/
|
||||
static inline int64_t qemu_soonest_timeout(int64_t timeout1, int64_t timeout2)
|
||||
{
|
||||
/* we can abuse the fact that -1 (which means infinite) is a maximal
|
||||
* value when cast to unsigned. As this is disgusting, it's kept in
|
||||
* one inline function.
|
||||
*/
|
||||
return ((uint64_t) timeout1 < (uint64_t) timeout2) ? timeout1 : timeout2;
|
||||
}
|
||||
|
||||
/**
|
||||
* initclocks:
|
||||
*
|
||||
* Initialise the clock & timer infrastructure
|
||||
*/
|
||||
void init_clocks(void);
|
||||
|
||||
int64_t cpu_get_ticks(void);
|
||||
/* Caller must hold BQL */
|
||||
void cpu_enable_ticks(void);
|
||||
/* Caller must hold BQL */
|
||||
void cpu_disable_ticks(void);
|
||||
|
||||
static inline int64_t get_ticks_per_sec(void)
|
||||
{
|
||||
return 1000000000LL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Low level clock functions
|
||||
*/
|
||||
|
||||
/* real time host monotonic timer */
|
||||
static inline int64_t get_clock_realtime(void)
|
||||
{
|
||||
struct timeval tv;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000);
|
||||
}
|
||||
|
||||
/* Warning: don't insert tracepoints into these functions, they are
|
||||
also used by simpletrace backend and tracepoints would cause
|
||||
an infinite recursion! */
|
||||
#ifdef _WIN32
|
||||
extern int64_t clock_freq;
|
||||
|
||||
static inline int64_t get_clock(void)
|
||||
{
|
||||
LARGE_INTEGER ti;
|
||||
QueryPerformanceCounter(&ti);
|
||||
return muldiv64(ti.QuadPart, get_ticks_per_sec(), clock_freq);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
extern int use_rt_clock;
|
||||
|
||||
static inline int64_t get_clock(void)
|
||||
{
|
||||
return get_clock_realtime();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* icount */
|
||||
int64_t cpu_get_icount(void);
|
||||
int64_t cpu_get_clock(void);
|
||||
int64_t cpu_get_clock_offset(void);
|
||||
int64_t cpu_icount_to_ns(int64_t icount);
|
||||
|
||||
/*******************************************/
|
||||
/* host CPU ticks (if available) */
|
||||
|
||||
#if defined(_ARCH_PPC)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int64_t retval;
|
||||
#ifdef _ARCH_PPC64
|
||||
/* This reads timebase in one 64bit go and includes Cell workaround from:
|
||||
http://ozlabs.org/pipermail/linuxppc-dev/2006-October/027052.html
|
||||
*/
|
||||
__asm__ __volatile__ ("mftb %0\n\t"
|
||||
"cmpwi %0,0\n\t"
|
||||
"beq- $-8"
|
||||
: "=r" (retval));
|
||||
#else
|
||||
/* http://ozlabs.org/pipermail/linuxppc-dev/1999-October/003889.html */
|
||||
unsigned long junk;
|
||||
__asm__ __volatile__ ("mfspr %1,269\n\t" /* mftbu */
|
||||
"mfspr %L0,268\n\t" /* mftb */
|
||||
"mfspr %0,269\n\t" /* mftbu */
|
||||
"cmpw %0,%1\n\t"
|
||||
"bne $-16"
|
||||
: "=r" (retval), "=r" (junk));
|
||||
#endif
|
||||
return retval;
|
||||
}
|
||||
|
||||
#elif defined(__i386__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int64_t val;
|
||||
asm volatile ("rdtsc" : "=A" (val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__x86_64__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
uint32_t low,high;
|
||||
int64_t val;
|
||||
asm volatile("rdtsc" : "=a" (low), "=d" (high));
|
||||
val = high;
|
||||
val <<= 32;
|
||||
val |= low;
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__hppa__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int val;
|
||||
asm volatile ("mfctl %%cr16, %0" : "=r"(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__ia64)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int64_t val;
|
||||
asm volatile ("mov %0 = ar.itc" : "=r"(val) :: "memory");
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__s390__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
int64_t val;
|
||||
asm volatile("stck 0(%1)" : "=m" (val) : "a" (&val) : "cc");
|
||||
return val;
|
||||
}
|
||||
|
||||
#elif defined(__sparc__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks (void)
|
||||
{
|
||||
#if defined(_LP64)
|
||||
uint64_t rval;
|
||||
asm volatile("rd %%tick,%0" : "=r"(rval));
|
||||
return rval;
|
||||
#else
|
||||
/* We need an %o or %g register for this. For recent enough gcc
|
||||
there is an "h" constraint for that. Don't bother with that. */
|
||||
union {
|
||||
uint64_t i64;
|
||||
struct {
|
||||
uint32_t high;
|
||||
uint32_t low;
|
||||
} i32;
|
||||
} rval;
|
||||
asm volatile("rd %%tick,%%g1; srlx %%g1,32,%0; mov %%g1,%1"
|
||||
: "=r"(rval.i32.high), "=r"(rval.i32.low) : : "g1");
|
||||
return rval.i64;
|
||||
#endif
|
||||
}
|
||||
|
||||
#elif defined(__mips__) && \
|
||||
((defined(__mips_isa_rev) && __mips_isa_rev >= 2) || defined(__linux__))
|
||||
/*
|
||||
* binutils wants to use rdhwr only on mips32r2
|
||||
* but as linux kernel emulate it, it's fine
|
||||
* to use it.
|
||||
*
|
||||
*/
|
||||
#define MIPS_RDHWR(rd, value) { \
|
||||
__asm__ __volatile__ (".set push\n\t" \
|
||||
".set mips32r2\n\t" \
|
||||
"rdhwr %0, "rd"\n\t" \
|
||||
".set pop" \
|
||||
: "=r" (value)); \
|
||||
}
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
/* On kernels >= 2.6.25 rdhwr <reg>, $2 and $3 are emulated */
|
||||
uint32_t count;
|
||||
static uint32_t cyc_per_count = 0;
|
||||
|
||||
if (!cyc_per_count) {
|
||||
MIPS_RDHWR("$3", cyc_per_count);
|
||||
}
|
||||
|
||||
MIPS_RDHWR("$2", count);
|
||||
return (int64_t)(count * cyc_per_count);
|
||||
}
|
||||
|
||||
#elif defined(__alpha__)
|
||||
|
||||
static inline int64_t cpu_get_real_ticks(void)
|
||||
{
|
||||
uint64_t cc;
|
||||
uint32_t cur, ofs;
|
||||
|
||||
asm volatile("rpcc %0" : "=r"(cc));
|
||||
cur = cc;
|
||||
ofs = cc >> 32;
|
||||
return cur - ofs;
|
||||
}
|
||||
|
||||
#else
|
||||
/* The host CPU doesn't have an easily accessible cycle counter.
|
||||
Just return a monotonically increasing value. This will be
|
||||
totally wrong, but hopefully better than nothing. */
|
||||
static inline int64_t cpu_get_real_ticks (void)
|
||||
{
|
||||
static int64_t ticks = 0;
|
||||
return ticks++;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROFILER
|
||||
static inline int64_t profile_getclock(void)
|
||||
{
|
||||
return cpu_get_real_ticks();
|
||||
}
|
||||
|
||||
extern int64_t qemu_time, qemu_time_start;
|
||||
extern int64_t tlb_flush_time;
|
||||
extern int64_t dev_time;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
52
qemu/include/qemu/tls.h
Normal file
52
qemu/include/qemu/tls.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Abstraction layer for defining and using TLS variables
|
||||
*
|
||||
* Copyright (c) 2011 Red Hat, Inc
|
||||
* Copyright (c) 2011 Linaro Limited
|
||||
*
|
||||
* Authors:
|
||||
* Paolo Bonzini <pbonzini@redhat.com>
|
||||
* Peter Maydell <peter.maydell@linaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef QEMU_TLS_H
|
||||
#define QEMU_TLS_H
|
||||
|
||||
/* Per-thread variables. Note that we only have implementations
|
||||
* which are really thread-local on Linux; the dummy implementations
|
||||
* define plain global variables.
|
||||
*
|
||||
* This means that for the moment use should be restricted to
|
||||
* per-VCPU variables, which are OK because:
|
||||
* - the only -user mode supporting multiple VCPU threads is linux-user
|
||||
* - TCG system mode is single-threaded regarding VCPUs
|
||||
* - KVM system mode is multi-threaded but limited to Linux
|
||||
*
|
||||
* TODO: proper implementations via Win32 .tls sections and
|
||||
* POSIX pthread_getspecific.
|
||||
*/
|
||||
#ifdef __linux__
|
||||
#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
|
||||
#define DEFINE_TLS(type, x) __thread __typeof__(type) tls__##x
|
||||
#define tls_var(x) tls__##x
|
||||
#else
|
||||
/* Dummy implementations which define plain global variables */
|
||||
#define DECLARE_TLS(type, x) extern DEFINE_TLS(type, x)
|
||||
#define DEFINE_TLS(type, x) __typeof__(type) tls__##x
|
||||
#define tls_var(x) tls__##x
|
||||
#endif
|
||||
|
||||
#endif
|
||||
82
qemu/include/qemu/typedefs.h
Normal file
82
qemu/include/qemu/typedefs.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef QEMU_TYPEDEFS_H
|
||||
#define QEMU_TYPEDEFS_H
|
||||
|
||||
/* A load of opaque types so that device init declarations don't have to
|
||||
pull in all the real definitions. */
|
||||
typedef struct QEMUTimer QEMUTimer;
|
||||
typedef struct QEMUTimerListGroup QEMUTimerListGroup;
|
||||
typedef struct QEMUFile QEMUFile;
|
||||
typedef struct QEMUBH QEMUBH;
|
||||
|
||||
typedef struct AioContext AioContext;
|
||||
|
||||
typedef struct Visitor Visitor;
|
||||
|
||||
struct Monitor;
|
||||
typedef struct Monitor Monitor;
|
||||
typedef struct MigrationParams MigrationParams;
|
||||
|
||||
typedef struct Property Property;
|
||||
typedef struct PropertyInfo PropertyInfo;
|
||||
typedef struct CompatProperty CompatProperty;
|
||||
typedef struct DeviceState DeviceState;
|
||||
typedef struct BusState BusState;
|
||||
typedef struct BusClass BusClass;
|
||||
|
||||
typedef struct AddressSpace AddressSpace;
|
||||
typedef struct MemoryRegion MemoryRegion;
|
||||
typedef struct MemoryRegionSection MemoryRegionSection;
|
||||
typedef struct MemoryListener MemoryListener;
|
||||
|
||||
typedef struct MemoryMappingList MemoryMappingList;
|
||||
|
||||
typedef struct QEMUMachine QEMUMachine;
|
||||
typedef struct MachineClass MachineClass;
|
||||
typedef struct MachineState MachineState;
|
||||
typedef struct NICInfo NICInfo;
|
||||
typedef struct HCIInfo HCIInfo;
|
||||
typedef struct AudioState AudioState;
|
||||
typedef struct BlockBackend BlockBackend;
|
||||
typedef struct BlockDriverState BlockDriverState;
|
||||
typedef struct DriveInfo DriveInfo;
|
||||
typedef struct DisplayState DisplayState;
|
||||
typedef struct DisplayChangeListener DisplayChangeListener;
|
||||
typedef struct DisplaySurface DisplaySurface;
|
||||
typedef struct PixelFormat PixelFormat;
|
||||
typedef struct QemuConsole QemuConsole;
|
||||
typedef struct CharDriverState CharDriverState;
|
||||
typedef struct MACAddr MACAddr;
|
||||
typedef struct NetClientState NetClientState;
|
||||
typedef struct I2CBus I2CBus;
|
||||
typedef struct ISABus ISABus;
|
||||
typedef struct ISADevice ISADevice;
|
||||
typedef struct SMBusDevice SMBusDevice;
|
||||
typedef struct PCIHostState PCIHostState;
|
||||
typedef struct PCIExpressHost PCIExpressHost;
|
||||
typedef struct PCIBus PCIBus;
|
||||
typedef struct PCIDevice PCIDevice;
|
||||
typedef struct PCIExpressDevice PCIExpressDevice;
|
||||
typedef struct PCIBridge PCIBridge;
|
||||
typedef struct PCIEAERMsg PCIEAERMsg;
|
||||
typedef struct PCIEAERLog PCIEAERLog;
|
||||
typedef struct PCIEAERErr PCIEAERErr;
|
||||
typedef struct PCIEPort PCIEPort;
|
||||
typedef struct PCIESlot PCIESlot;
|
||||
typedef struct MSIMessage MSIMessage;
|
||||
typedef struct SerialState SerialState;
|
||||
typedef struct PCMCIACardState PCMCIACardState;
|
||||
typedef struct MouseTransformInfo MouseTransformInfo;
|
||||
typedef struct uWireSlave uWireSlave;
|
||||
typedef struct I2SCodec I2SCodec;
|
||||
typedef struct SSIBus SSIBus;
|
||||
typedef struct EventNotifier EventNotifier;
|
||||
typedef struct VirtIODevice VirtIODevice;
|
||||
typedef struct QEMUSGList QEMUSGList;
|
||||
typedef struct QEMUSizedBuffer QEMUSizedBuffer;
|
||||
typedef struct SHPCDevice SHPCDevice;
|
||||
typedef struct FWCfgState FWCfgState;
|
||||
typedef struct PcGuestInfo PcGuestInfo;
|
||||
typedef struct Range Range;
|
||||
typedef struct AdapterInfo AdapterInfo;
|
||||
|
||||
#endif /* QEMU_TYPEDEFS_H */
|
||||
644
qemu/include/qom/cpu.h
Normal file
644
qemu/include/qom/cpu.h
Normal file
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* QEMU CPU model
|
||||
*
|
||||
* Copyright (c) 2012 SUSE LINUX Products GmbH
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, see
|
||||
* <http://www.gnu.org/licenses/gpl-2.0.html>
|
||||
*/
|
||||
#ifndef QEMU_CPU_H
|
||||
#define QEMU_CPU_H
|
||||
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include "hw/qdev-core.h"
|
||||
#include "exec/hwaddr.h"
|
||||
#include "qemu/queue.h"
|
||||
#include "qemu/thread.h"
|
||||
#include "qemu/tls.h"
|
||||
#include "qemu/typedefs.h"
|
||||
|
||||
typedef int (*WriteCoreDumpFunction)(const void *buf, size_t size,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
||||
/**
|
||||
* SECTION:cpu
|
||||
* @section_id: QEMU-cpu
|
||||
* @title: CPU Class
|
||||
* @short_description: Base class for all CPUs
|
||||
*/
|
||||
|
||||
#define TYPE_CPU "cpu"
|
||||
|
||||
/* Since this macro is used a lot in hot code paths and in conjunction with
|
||||
* FooCPU *foo_env_get_cpu(), we deviate from usual QOM practice by using
|
||||
* an unchecked cast.
|
||||
*/
|
||||
#define CPU(obj) ((CPUState *)(obj))
|
||||
|
||||
#define CPU_CLASS(uc, class) OBJECT_CLASS_CHECK(uc, CPUClass, (class), TYPE_CPU)
|
||||
#define CPU_GET_CLASS(uc, obj) OBJECT_GET_CLASS(uc, CPUClass, (obj), TYPE_CPU)
|
||||
|
||||
typedef struct CPUState CPUState;
|
||||
|
||||
typedef void (*CPUUnassignedAccess)(CPUState *cpu, hwaddr addr,
|
||||
bool is_write, bool is_exec, int opaque,
|
||||
unsigned size);
|
||||
|
||||
struct TranslationBlock;
|
||||
|
||||
//DECLARE_TLS(CPUState *, current_cpu);
|
||||
//#define current_cpu tls_var(current_cpu)
|
||||
|
||||
/**
|
||||
* CPUClass:
|
||||
* @class_by_name: Callback to map -cpu command line model name to an
|
||||
* instantiatable CPU type.
|
||||
* @parse_features: Callback to parse command line arguments.
|
||||
* @reset: Callback to reset the #CPUState to its initial state.
|
||||
* @reset_dump_flags: #CPUDumpFlags to use for reset logging.
|
||||
* @has_work: Callback for checking if there is work to do.
|
||||
* @do_interrupt: Callback for interrupt handling.
|
||||
* @do_unassigned_access: Callback for unassigned access handling.
|
||||
* @do_unaligned_access: Callback for unaligned access handling, if
|
||||
* the target defines #ALIGNED_ONLY.
|
||||
* @memory_rw_debug: Callback for GDB memory access.
|
||||
* @dump_state: Callback for dumping state.
|
||||
* @dump_statistics: Callback for dumping statistics.
|
||||
* @get_arch_id: Callback for getting architecture-dependent CPU ID.
|
||||
* @get_paging_enabled: Callback for inquiring whether paging is enabled.
|
||||
* @get_memory_mapping: Callback for obtaining the memory mappings.
|
||||
* @set_pc: Callback for setting the Program Counter register.
|
||||
* @synchronize_from_tb: Callback for synchronizing state from a TCG
|
||||
* #TranslationBlock.
|
||||
* @handle_mmu_fault: Callback for handling an MMU fault.
|
||||
* @get_phys_page_debug: Callback for obtaining a physical address.
|
||||
* @debug_excp_handler: Callback for handling debug exceptions.
|
||||
* @vmsd: State description for migration.
|
||||
* @cpu_exec_enter: Callback for cpu_exec preparation.
|
||||
* @cpu_exec_exit: Callback for cpu_exec cleanup.
|
||||
* @cpu_exec_interrupt: Callback for processing interrupts in cpu_exec.
|
||||
*
|
||||
* Represents a CPU family or model.
|
||||
*/
|
||||
typedef struct CPUClass {
|
||||
/*< private >*/
|
||||
DeviceClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
ObjectClass *(*class_by_name)(struct uc_struct *uc, const char *cpu_model);
|
||||
void (*parse_features)(CPUState *cpu, char *str, Error **errp);
|
||||
|
||||
void (*reset)(CPUState *cpu);
|
||||
int reset_dump_flags;
|
||||
bool (*has_work)(CPUState *cpu);
|
||||
void (*do_interrupt)(CPUState *cpu);
|
||||
CPUUnassignedAccess do_unassigned_access;
|
||||
void (*do_unaligned_access)(CPUState *cpu, vaddr addr,
|
||||
int is_write, int is_user, uintptr_t retaddr);
|
||||
int (*memory_rw_debug)(CPUState *cpu, vaddr addr,
|
||||
uint8_t *buf, int len, bool is_write);
|
||||
void (*dump_state)(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
void (*dump_statistics)(CPUState *cpu, FILE *f,
|
||||
fprintf_function cpu_fprintf, int flags);
|
||||
int64_t (*get_arch_id)(CPUState *cpu);
|
||||
bool (*get_paging_enabled)(const CPUState *cpu);
|
||||
void (*get_memory_mapping)(CPUState *cpu, MemoryMappingList *list,
|
||||
Error **errp);
|
||||
void (*set_pc)(CPUState *cpu, vaddr value);
|
||||
void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb);
|
||||
int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int rw,
|
||||
int mmu_index);
|
||||
hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr);
|
||||
void (*debug_excp_handler)(CPUState *cpu);
|
||||
|
||||
const struct VMStateDescription *vmsd;
|
||||
|
||||
void (*cpu_exec_enter)(CPUState *cpu);
|
||||
void (*cpu_exec_exit)(CPUState *cpu);
|
||||
bool (*cpu_exec_interrupt)(CPUState *cpu, int interrupt_request);
|
||||
} CPUClass;
|
||||
|
||||
#ifdef HOST_WORDS_BIGENDIAN
|
||||
typedef struct icount_decr_u16 {
|
||||
uint16_t high;
|
||||
uint16_t low;
|
||||
} icount_decr_u16;
|
||||
#else
|
||||
typedef struct icount_decr_u16 {
|
||||
uint16_t low;
|
||||
uint16_t high;
|
||||
} icount_decr_u16;
|
||||
#endif
|
||||
|
||||
typedef struct CPUBreakpoint {
|
||||
vaddr pc;
|
||||
int flags; /* BP_* */
|
||||
QTAILQ_ENTRY(CPUBreakpoint) entry;
|
||||
} CPUBreakpoint;
|
||||
|
||||
typedef struct CPUWatchpoint {
|
||||
vaddr vaddr;
|
||||
vaddr len;
|
||||
vaddr hitaddr;
|
||||
int flags; /* BP_* */
|
||||
QTAILQ_ENTRY(CPUWatchpoint) entry;
|
||||
} CPUWatchpoint;
|
||||
|
||||
struct KVMState;
|
||||
struct kvm_run;
|
||||
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
/**
|
||||
* CPUState:
|
||||
* @cpu_index: CPU index (informative).
|
||||
* @nr_cores: Number of cores within this CPU package.
|
||||
* @nr_threads: Number of threads within this CPU.
|
||||
* @numa_node: NUMA node this CPU is belonging to.
|
||||
* @host_tid: Host thread ID.
|
||||
* @running: #true if CPU is currently running (usermode).
|
||||
* @created: Indicates whether the CPU thread has been successfully created.
|
||||
* @interrupt_request: Indicates a pending interrupt request.
|
||||
* @halted: Nonzero if the CPU is in suspended state.
|
||||
* @stop: Indicates a pending stop request.
|
||||
* @stopped: Indicates the CPU has been artificially stopped.
|
||||
* @tcg_exit_req: Set to force TCG to stop executing linked TBs for this
|
||||
* CPU and return to its top level loop.
|
||||
* @singlestep_enabled: Flags for single-stepping.
|
||||
* @icount_extra: Instructions until next timer event.
|
||||
* @icount_decr: Number of cycles left, with interrupt flag in high bit.
|
||||
* This allows a single read-compare-cbranch-write sequence to test
|
||||
* for both decrementer underflow and exceptions.
|
||||
* @can_do_io: Nonzero if memory-mapped IO is safe.
|
||||
* @env_ptr: Pointer to subclass-specific CPUArchState field.
|
||||
* @current_tb: Currently executing TB.
|
||||
* @next_cpu: Next CPU sharing TB cache.
|
||||
* @opaque: User data.
|
||||
* @mem_io_pc: Host Program Counter at which the memory was accessed.
|
||||
* @mem_io_vaddr: Target virtual address at which the memory was accessed.
|
||||
* @kvm_fd: vCPU file descriptor for KVM.
|
||||
*
|
||||
* State of one CPU core or thread.
|
||||
*/
|
||||
struct CPUState {
|
||||
/*< private >*/
|
||||
DeviceState parent_obj;
|
||||
/*< public >*/
|
||||
|
||||
int nr_cores;
|
||||
int nr_threads;
|
||||
int numa_node;
|
||||
|
||||
struct QemuThread *thread;
|
||||
#ifdef _WIN32
|
||||
HANDLE hThread;
|
||||
#endif
|
||||
int thread_id;
|
||||
uint32_t host_tid;
|
||||
bool running;
|
||||
struct QemuCond *halt_cond;
|
||||
struct qemu_work_item *queued_work_first, *queued_work_last;
|
||||
bool thread_kicked;
|
||||
bool created;
|
||||
bool stop;
|
||||
bool stopped;
|
||||
volatile sig_atomic_t exit_request;
|
||||
uint32_t interrupt_request;
|
||||
int singlestep_enabled;
|
||||
int64_t icount_extra;
|
||||
sigjmp_buf jmp_env;
|
||||
|
||||
AddressSpace *as;
|
||||
MemoryListener *tcg_as_listener;
|
||||
|
||||
void *env_ptr; /* CPUArchState */
|
||||
struct TranslationBlock *current_tb;
|
||||
struct TranslationBlock *tb_jmp_cache[TB_JMP_CACHE_SIZE];
|
||||
QTAILQ_ENTRY(CPUState) node;
|
||||
|
||||
/* ice debug support */
|
||||
QTAILQ_HEAD(breakpoints_head, CPUBreakpoint) breakpoints;
|
||||
|
||||
QTAILQ_HEAD(watchpoints_head, CPUWatchpoint) watchpoints;
|
||||
CPUWatchpoint *watchpoint_hit;
|
||||
|
||||
void *opaque;
|
||||
|
||||
/* In order to avoid passing too many arguments to the MMIO helpers,
|
||||
* we store some rarely used information in the CPU context.
|
||||
*/
|
||||
uintptr_t mem_io_pc;
|
||||
vaddr mem_io_vaddr;
|
||||
|
||||
int kvm_fd;
|
||||
bool kvm_vcpu_dirty;
|
||||
struct KVMState *kvm_state;
|
||||
struct kvm_run *kvm_run;
|
||||
|
||||
/* TODO Move common fields from CPUArchState here. */
|
||||
int cpu_index; /* used by alpha TCG */
|
||||
uint32_t halted; /* used by alpha, cris, ppc TCG */
|
||||
union {
|
||||
uint32_t u32;
|
||||
icount_decr_u16 u16;
|
||||
} icount_decr;
|
||||
uint32_t can_do_io;
|
||||
int32_t exception_index; /* used by m68k TCG */
|
||||
|
||||
/* Note that this is accessed at the start of every TB via a negative
|
||||
offset from AREG0. Leave this field at the end so as to make the
|
||||
(absolute value) offset as small as possible. This reduces code
|
||||
size, especially for hosts without large memory offsets. */
|
||||
volatile sig_atomic_t tcg_exit_req;
|
||||
struct uc_struct* uc;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* cpu_paging_enabled:
|
||||
* @cpu: The CPU whose state is to be inspected.
|
||||
*
|
||||
* Returns: %true if paging is enabled, %false otherwise.
|
||||
*/
|
||||
bool cpu_paging_enabled(const CPUState *cpu);
|
||||
|
||||
/**
|
||||
* cpu_get_memory_mapping:
|
||||
* @cpu: The CPU whose memory mappings are to be obtained.
|
||||
* @list: Where to write the memory mappings to.
|
||||
* @errp: Pointer for reporting an #Error.
|
||||
*/
|
||||
void cpu_get_memory_mapping(CPUState *cpu, MemoryMappingList *list,
|
||||
Error **errp);
|
||||
|
||||
/**
|
||||
* cpu_write_elf64_note:
|
||||
* @f: pointer to a function that writes memory to a file
|
||||
* @cpu: The CPU whose memory is to be dumped
|
||||
* @cpuid: ID number of the CPU
|
||||
* @opaque: pointer to the CPUState struct
|
||||
*/
|
||||
int cpu_write_elf64_note(WriteCoreDumpFunction f, CPUState *cpu,
|
||||
int cpuid, void *opaque);
|
||||
|
||||
/**
|
||||
* cpu_write_elf64_qemunote:
|
||||
* @f: pointer to a function that writes memory to a file
|
||||
* @cpu: The CPU whose memory is to be dumped
|
||||
* @cpuid: ID number of the CPU
|
||||
* @opaque: pointer to the CPUState struct
|
||||
*/
|
||||
int cpu_write_elf64_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* cpu_write_elf32_note:
|
||||
* @f: pointer to a function that writes memory to a file
|
||||
* @cpu: The CPU whose memory is to be dumped
|
||||
* @cpuid: ID number of the CPU
|
||||
* @opaque: pointer to the CPUState struct
|
||||
*/
|
||||
int cpu_write_elf32_note(WriteCoreDumpFunction f, CPUState *cpu,
|
||||
int cpuid, void *opaque);
|
||||
|
||||
/**
|
||||
* cpu_write_elf32_qemunote:
|
||||
* @f: pointer to a function that writes memory to a file
|
||||
* @cpu: The CPU whose memory is to be dumped
|
||||
* @cpuid: ID number of the CPU
|
||||
* @opaque: pointer to the CPUState struct
|
||||
*/
|
||||
int cpu_write_elf32_qemunote(WriteCoreDumpFunction f, CPUState *cpu,
|
||||
void *opaque);
|
||||
|
||||
/**
|
||||
* CPUDumpFlags:
|
||||
* @CPU_DUMP_CODE:
|
||||
* @CPU_DUMP_FPU: dump FPU register state, not just integer
|
||||
* @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization state
|
||||
*/
|
||||
enum CPUDumpFlags {
|
||||
CPU_DUMP_CODE = 0x00010000,
|
||||
CPU_DUMP_FPU = 0x00020000,
|
||||
CPU_DUMP_CCOP = 0x00040000,
|
||||
};
|
||||
|
||||
/**
|
||||
* cpu_dump_state:
|
||||
* @cpu: The CPU whose state is to be dumped.
|
||||
* @f: File to dump to.
|
||||
* @cpu_fprintf: Function to dump with.
|
||||
* @flags: Flags what to dump.
|
||||
*
|
||||
* Dumps CPU state.
|
||||
*/
|
||||
void cpu_dump_state(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
|
||||
/**
|
||||
* cpu_dump_statistics:
|
||||
* @cpu: The CPU whose state is to be dumped.
|
||||
* @f: File to dump to.
|
||||
* @cpu_fprintf: Function to dump with.
|
||||
* @flags: Flags what to dump.
|
||||
*
|
||||
* Dumps CPU statistics.
|
||||
*/
|
||||
void cpu_dump_statistics(CPUState *cpu, FILE *f, fprintf_function cpu_fprintf,
|
||||
int flags);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/**
|
||||
* cpu_get_phys_page_debug:
|
||||
* @cpu: The CPU to obtain the physical page address for.
|
||||
* @addr: The virtual address.
|
||||
*
|
||||
* Obtains the physical page corresponding to a virtual one.
|
||||
* Use it only for debugging because no protection checks are done.
|
||||
*
|
||||
* Returns: Corresponding physical page address or -1 if no page found.
|
||||
*/
|
||||
static inline hwaddr cpu_get_phys_page_debug(CPUState *cpu, vaddr addr)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||
|
||||
return cc->get_phys_page_debug(cpu, addr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cpu_reset:
|
||||
* @cpu: The CPU whose state is to be reset.
|
||||
*/
|
||||
void cpu_reset(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* cpu_class_by_name:
|
||||
* @typename: The CPU base type.
|
||||
* @cpu_model: The model string without any parameters.
|
||||
*
|
||||
* Looks up a CPU #ObjectClass matching name @cpu_model.
|
||||
*
|
||||
* Returns: A #CPUClass or %NULL if not matching class is found.
|
||||
*/
|
||||
ObjectClass *cpu_class_by_name(struct uc_struct *uc, const char *typename, const char *cpu_model);
|
||||
|
||||
/**
|
||||
* cpu_generic_init:
|
||||
* @typename: The CPU base type.
|
||||
* @cpu_model: The model string including optional parameters.
|
||||
*
|
||||
* Instantiates a CPU, processes optional parameters and realizes the CPU.
|
||||
*
|
||||
* Returns: A #CPUState or %NULL if an error occurred.
|
||||
*/
|
||||
CPUState *cpu_generic_init(struct uc_struct *uc, const char *typename, const char *cpu_model);
|
||||
|
||||
/**
|
||||
* cpu_has_work:
|
||||
* @cpu: The vCPU to check.
|
||||
*
|
||||
* Checks whether the CPU has work to do.
|
||||
*
|
||||
* Returns: %true if the CPU has work, %false otherwise.
|
||||
*/
|
||||
static inline bool cpu_has_work(CPUState *cpu)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||
|
||||
g_assert(cc->has_work);
|
||||
return cc->has_work(cpu);
|
||||
}
|
||||
|
||||
/**
|
||||
* qemu_cpu_is_self:
|
||||
* @cpu: The vCPU to check against.
|
||||
*
|
||||
* Checks whether the caller is executing on the vCPU thread.
|
||||
*
|
||||
* Returns: %true if called from @cpu's thread, %false otherwise.
|
||||
*/
|
||||
bool qemu_cpu_is_self(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* qemu_cpu_kick:
|
||||
* @cpu: The vCPU to kick.
|
||||
*
|
||||
* Kicks @cpu's thread.
|
||||
*/
|
||||
void qemu_cpu_kick(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* cpu_is_stopped:
|
||||
* @cpu: The CPU to check.
|
||||
*
|
||||
* Checks whether the CPU is stopped.
|
||||
*
|
||||
* Returns: %true if run state is not running or if artificially stopped;
|
||||
* %false otherwise.
|
||||
*/
|
||||
bool cpu_is_stopped(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* run_on_cpu:
|
||||
* @cpu: The vCPU to run on.
|
||||
* @func: The function to be executed.
|
||||
* @data: Data to pass to the function.
|
||||
*
|
||||
* Schedules the function @func for execution on the vCPU @cpu.
|
||||
*/
|
||||
void run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
|
||||
|
||||
/**
|
||||
* async_run_on_cpu:
|
||||
* @cpu: The vCPU to run on.
|
||||
* @func: The function to be executed.
|
||||
* @data: Data to pass to the function.
|
||||
*
|
||||
* Schedules the function @func for execution on the vCPU @cpu asynchronously.
|
||||
*/
|
||||
void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data);
|
||||
|
||||
/**
|
||||
* qemu_get_cpu:
|
||||
* @index: The CPUState@cpu_index value of the CPU to obtain.
|
||||
*
|
||||
* Gets a CPU matching @index.
|
||||
*
|
||||
* Returns: The CPU or %NULL if there is no matching CPU.
|
||||
*/
|
||||
CPUState *qemu_get_cpu(struct uc_struct *uc, int index);
|
||||
|
||||
/**
|
||||
* cpu_exists:
|
||||
* @id: Guest-exposed CPU ID to lookup.
|
||||
*
|
||||
* Search for CPU with specified ID.
|
||||
*
|
||||
* Returns: %true - CPU is found, %false - CPU isn't found.
|
||||
*/
|
||||
bool cpu_exists(struct uc_struct* uc, int64_t id);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
|
||||
typedef void (*CPUInterruptHandler)(CPUState *, int);
|
||||
|
||||
extern CPUInterruptHandler cpu_interrupt_handler;
|
||||
|
||||
/**
|
||||
* cpu_interrupt:
|
||||
* @cpu: The CPU to set an interrupt on.
|
||||
* @mask: The interupts to set.
|
||||
*
|
||||
* Invokes the interrupt handler.
|
||||
*/
|
||||
static inline void cpu_interrupt(CPUState *cpu, int mask)
|
||||
{
|
||||
cpu_interrupt_handler(cpu, mask);
|
||||
}
|
||||
|
||||
#else /* USER_ONLY */
|
||||
|
||||
void cpu_interrupt(CPUState *cpu, int mask);
|
||||
|
||||
#endif /* USER_ONLY */
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
static inline void cpu_unassigned_access(CPUState *cpu, hwaddr addr,
|
||||
bool is_write, bool is_exec,
|
||||
int opaque, unsigned size)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||
|
||||
if (cc->do_unassigned_access) {
|
||||
cc->do_unassigned_access(cpu, addr, is_write, is_exec, opaque, size);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void cpu_unaligned_access(CPUState *cpu, vaddr addr,
|
||||
int is_write, int is_user,
|
||||
uintptr_t retaddr)
|
||||
{
|
||||
CPUClass *cc = CPU_GET_CLASS(cpu->uc, cpu);
|
||||
|
||||
return cc->do_unaligned_access(cpu, addr, is_write, is_user, retaddr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* cpu_reset_interrupt:
|
||||
* @cpu: The CPU to clear the interrupt on.
|
||||
* @mask: The interrupt mask to clear.
|
||||
*
|
||||
* Resets interrupts on the vCPU @cpu.
|
||||
*/
|
||||
void cpu_reset_interrupt(CPUState *cpu, int mask);
|
||||
|
||||
/**
|
||||
* cpu_exit:
|
||||
* @cpu: The CPU to exit.
|
||||
*
|
||||
* Requests the CPU @cpu to exit execution.
|
||||
*/
|
||||
void cpu_exit(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* cpu_resume:
|
||||
* @cpu: The CPU to resume.
|
||||
*
|
||||
* Resumes CPU, i.e. puts CPU into runnable state.
|
||||
*/
|
||||
void cpu_resume(CPUState *cpu);
|
||||
|
||||
/**
|
||||
* qemu_init_vcpu:
|
||||
* @cpu: The vCPU to initialize.
|
||||
*
|
||||
* Initializes a vCPU.
|
||||
*/
|
||||
void qemu_init_vcpu(CPUState *cpu);
|
||||
|
||||
#define SSTEP_ENABLE 0x1 /* Enable simulated HW single stepping */
|
||||
#define SSTEP_NOIRQ 0x2 /* Do not use IRQ while single stepping */
|
||||
#define SSTEP_NOTIMER 0x4 /* Do not Timers while single stepping */
|
||||
|
||||
/**
|
||||
* cpu_single_step:
|
||||
* @cpu: CPU to the flags for.
|
||||
* @enabled: Flags to enable.
|
||||
*
|
||||
* Enables or disables single-stepping for @cpu.
|
||||
*/
|
||||
void cpu_single_step(CPUState *cpu, int enabled);
|
||||
|
||||
/* 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_WATCHPOINT_HIT_READ 0x40
|
||||
#define BP_WATCHPOINT_HIT_WRITE 0x80
|
||||
#define BP_WATCHPOINT_HIT (BP_WATCHPOINT_HIT_READ | BP_WATCHPOINT_HIT_WRITE)
|
||||
|
||||
int cpu_breakpoint_insert(CPUState *cpu, vaddr pc, int flags,
|
||||
CPUBreakpoint **breakpoint);
|
||||
int cpu_breakpoint_remove(CPUState *cpu, vaddr pc, int flags);
|
||||
void cpu_breakpoint_remove_by_ref(CPUState *cpu, CPUBreakpoint *breakpoint);
|
||||
void cpu_breakpoint_remove_all(CPUState *cpu, int mask);
|
||||
|
||||
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);
|
||||
|
||||
void QEMU_NORETURN cpu_abort(CPUState *cpu, const char *fmt, ...)
|
||||
GCC_FMT_ATTR(2, 3);
|
||||
|
||||
void cpu_register_types(struct uc_struct *uc);
|
||||
|
||||
#ifdef CONFIG_SOFTMMU
|
||||
extern const struct VMStateDescription vmstate_cpu_common;
|
||||
#else
|
||||
#define vmstate_cpu_common vmstate_dummy
|
||||
#endif
|
||||
|
||||
#define VMSTATE_CPU() { \
|
||||
.name = "parent_obj", \
|
||||
.size = sizeof(CPUState), \
|
||||
.vmsd = &vmstate_cpu_common, \
|
||||
.flags = VMS_STRUCT, \
|
||||
.offset = 0, \
|
||||
}
|
||||
|
||||
#endif
|
||||
1305
qemu/include/qom/object.h
Normal file
1305
qemu/include/qom/object.h
Normal file
File diff suppressed because it is too large
Load Diff
42
qemu/include/qom/qom-qobject.h
Normal file
42
qemu/include/qom/qom-qobject.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* QEMU Object Model - QObject wrappers
|
||||
*
|
||||
* Copyright (C) 2012 Red Hat, Inc.
|
||||
*
|
||||
* Author: Paolo Bonzini <pbonzini@redhat.com>
|
||||
*
|
||||
* 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 QEMU_QOM_QOBJECT_H
|
||||
#define QEMU_QOM_QOBJECT_H
|
||||
|
||||
#include "qom/object.h"
|
||||
|
||||
/*
|
||||
* object_property_get_qobject:
|
||||
* @obj: the object
|
||||
* @name: the name of the property
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Returns: the value of the property, converted to QObject, or NULL if
|
||||
* an error occurs.
|
||||
*/
|
||||
struct QObject *object_property_get_qobject(struct uc_struct *uc, Object *obj, const char *name,
|
||||
struct Error **errp);
|
||||
|
||||
/**
|
||||
* object_property_set_qobject:
|
||||
* @obj: the object
|
||||
* @ret: The value that will be written to the property.
|
||||
* @name: the name of the property
|
||||
* @errp: returns an error if this function fails
|
||||
*
|
||||
* Writes a property to a object.
|
||||
*/
|
||||
void object_property_set_qobject(struct uc_struct *uc, Object *obj, struct QObject *qobj,
|
||||
const char *name, struct Error **errp);
|
||||
|
||||
#endif
|
||||
62
qemu/include/sysemu/accel.h
Normal file
62
qemu/include/sysemu/accel.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/* QEMU accelerator interfaces
|
||||
*
|
||||
* Copyright (c) 2014 Red Hat Inc
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
#ifndef HW_ACCEL_H
|
||||
#define HW_ACCEL_H
|
||||
|
||||
#include "qemu/typedefs.h"
|
||||
#include "qom/object.h"
|
||||
|
||||
typedef struct AccelState {
|
||||
/*< private >*/
|
||||
Object parent_obj;
|
||||
} AccelState;
|
||||
|
||||
typedef struct AccelClass {
|
||||
/*< private >*/
|
||||
ObjectClass parent_class;
|
||||
/*< public >*/
|
||||
|
||||
const char *opt_name;
|
||||
const char *name;
|
||||
int (*available)(void);
|
||||
int (*init_machine)(MachineState *ms);
|
||||
bool *allowed;
|
||||
} AccelClass;
|
||||
|
||||
#define TYPE_ACCEL "accel"
|
||||
|
||||
#define ACCEL_CLASS_SUFFIX "-" TYPE_ACCEL
|
||||
#define ACCEL_CLASS_NAME(a) (a ACCEL_CLASS_SUFFIX)
|
||||
|
||||
#define ACCEL_CLASS(uc, klass) \
|
||||
OBJECT_CLASS_CHECK(uc, AccelClass, (klass), TYPE_ACCEL)
|
||||
#define ACCEL(uc, obj) \
|
||||
OBJECT_CHECK(uc, AccelState, (obj), TYPE_ACCEL)
|
||||
#define ACCEL_GET_CLASS(uc, obj) \
|
||||
OBJECT_GET_CLASS(uc, AccelClass, (obj), TYPE_ACCEL)
|
||||
|
||||
int configure_accelerator(MachineState *ms);
|
||||
|
||||
void register_accel_types(struct uc_struct *uc);
|
||||
|
||||
#endif
|
||||
26
qemu/include/sysemu/cpus.h
Normal file
26
qemu/include/sysemu/cpus.h
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef QEMU_CPUS_H
|
||||
#define QEMU_CPUS_H
|
||||
|
||||
struct uc_struct;
|
||||
|
||||
/* cpus.c */
|
||||
void qemu_init_cpu_loop(struct uc_struct*);
|
||||
void resume_all_vcpus(struct uc_struct*);
|
||||
void pause_all_vcpus(struct uc_struct*);
|
||||
void cpu_stop_current(struct uc_struct*);
|
||||
|
||||
void cpu_synchronize_all_states(void);
|
||||
void cpu_synchronize_all_post_reset(void);
|
||||
void cpu_synchronize_all_post_init(void);
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
/* vl.c */
|
||||
extern int smp_cores;
|
||||
extern int smp_threads;
|
||||
#else
|
||||
/* *-user doesn't have configurable SMP topology */
|
||||
#define smp_cores 1
|
||||
#define smp_threads 1
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user