This commit is contained in:
Nguyen Anh Quynh
2015-08-21 15:04:50 +08:00
commit 344d016104
499 changed files with 266445 additions and 0 deletions

2
qemu/include/config.h Normal file
View File

@@ -0,0 +1,2 @@
#include "config-host.h"
#include "config-target.h"

1548
qemu/include/elf.h Normal file

File diff suppressed because it is too large Load Diff

View 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
View 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 */

View 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 */

View 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

View 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 */

View 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

View 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

View 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

View 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

View 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 */

View 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 */

View 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 */

View 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 */

View 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

View 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 */

View 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
View 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

View 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

View 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

View 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

View 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

View 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
View 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
View 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
View 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

View 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
View 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

View 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

View 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
View 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
View 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

View 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

View 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

View 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

View 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

View 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
View 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
View File

@@ -0,0 +1,7 @@
#ifndef QDEV_H
#define QDEV_H
#include "hw/hw.h"
#include "hw/qdev-core.h"
#endif

View 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_ */

View 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

View 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

View 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

View 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
View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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

View 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
View 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

View 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

View 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
View 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
View 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
View 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
View 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
View 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
View 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 */

View 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 */

View 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

View 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
View 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
View 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

View 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

View 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

View 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
View 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

View 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
View 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
View 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
View 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

View 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

View 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

View 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

View 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
View 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
View 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

View 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
View 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

File diff suppressed because it is too large Load Diff

View 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

View 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

View 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