Merge remote branch 'origin/master' into pci

This commit is contained in:
Michael S. Tsirkin 2011-01-10 13:43:48 +02:00
commit 6107ff1292
95 changed files with 4349 additions and 870 deletions

View File

@ -205,7 +205,7 @@ common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
ifdef INSTALL_BLOBS
BLOBS=bios.bin vgabios.bin vgabios-cirrus.bin \
vgabios-stdvga.bin vgabios-vmware.bin \
vgabios-stdvga.bin vgabios-vmware.bin vgabios-qxl.bin \
ppc_rom.bin openbios-sparc32 openbios-sparc64 openbios-ppc \
gpxe-eepro100-80861209.rom \
pxe-e1000.bin \

View File

@ -219,6 +219,7 @@ obj-i386-y += vmmouse.o vmport.o hpet.o applesmc.o
obj-i386-y += device-hotplug.o pci-hotplug.o smbios.o wdt_ib700.o
obj-i386-y += debugcon.o multiboot.o
obj-i386-y += pc_piix.o
obj-i386-$(CONFIG_SPICE) += qxl.o qxl-logger.o qxl-render.o
# shared objects
obj-ppc-y = ppc.o

View File

@ -182,6 +182,70 @@ Example:
"host": "127.0.0.1", "sasl_username": "luiz" } },
"timestamp": { "seconds": 1263475302, "microseconds": 150772 } }
SPICE_CONNECTED, SPICE_DISCONNECTED
-----------------------------------
Emitted when a SPICE client connects or disconnects.
Data:
- "server": Server information (json-object)
- "host": IP address (json-string)
- "port": port number (json-string)
- "family": address family (json-string, "ipv4" or "ipv6")
- "client": Client information (json-object)
- "host": IP address (json-string)
- "port": port number (json-string)
- "family": address family (json-string, "ipv4" or "ipv6")
Example:
{ "timestamp": {"seconds": 1290688046, "microseconds": 388707},
"event": "SPICE_CONNECTED",
"data": {
"server": { "port": "5920", "family": "ipv4", "host": "127.0.0.1"},
"client": {"port": "52873", "family": "ipv4", "host": "127.0.0.1"}
}}
SPICE_INITIALIZED
-----------------
Emitted after initial handshake and authentication takes place (if any)
and the SPICE channel is up'n'running
Data:
- "server": Server information (json-object)
- "host": IP address (json-string)
- "port": port number (json-string)
- "family": address family (json-string, "ipv4" or "ipv6")
- "auth": authentication method (json-string, optional)
- "client": Client information (json-object)
- "host": IP address (json-string)
- "port": port number (json-string)
- "family": address family (json-string, "ipv4" or "ipv6")
- "connection-id": spice connection id. All channels with the same id
belong to the same spice session (json-int)
- "channel-type": channel type. "1" is the main control channel, filter for
this one if you want track spice sessions only (json-int)
- "channel-id": channel id. Usually "0", might be different needed when
multiple channels of the same type exist, such as multiple
display channels in a multihead setup (json-int)
- "tls": whevener the channel is encrypted (json-bool)
Example:
{ "timestamp": {"seconds": 1290688046, "microseconds": 417172},
"event": "SPICE_INITIALIZED",
"data": {"server": {"auth": "spice", "port": "5921",
"family": "ipv4", "host": "127.0.0.1"},
"client": {"port": "49004", "family": "ipv4", "channel-type": 3,
"connection-id": 1804289383, "host": "127.0.0.1",
"channel-id": 0, "tls": true}
}}
WATCHDOG
--------

View File

@ -373,45 +373,64 @@ uint32_t do_arm_semihosting(CPUState *env)
#ifdef CONFIG_USER_ONLY
/* Build a commandline from the original argv. */
{
char **arg = ts->info->host_argv;
int len = ARG(1);
/* lock the buffer on the ARM side */
char *cmdline_buffer = (char*)lock_user(VERIFY_WRITE, ARG(0), len, 0);
char *arm_cmdline_buffer;
const char *host_cmdline_buffer;
if (!cmdline_buffer)
/* FIXME - should this error code be -TARGET_EFAULT ? */
return (uint32_t)-1;
unsigned int i;
unsigned int arm_cmdline_len = ARG(1);
unsigned int host_cmdline_len =
ts->info->arg_end-ts->info->arg_start;
s = cmdline_buffer;
while (*arg && len > 2) {
int n = strlen(*arg);
if (s != cmdline_buffer) {
*(s++) = ' ';
len--;
}
if (n >= len)
n = len - 1;
memcpy(s, *arg, n);
s += n;
len -= n;
arg++;
if (!arm_cmdline_len || host_cmdline_len > arm_cmdline_len) {
return -1; /* not enough space to store command line */
}
/* Null terminate the string. */
*s = 0;
len = s - cmdline_buffer;
/* Unlock the buffer on the ARM side. */
unlock_user(cmdline_buffer, ARG(0), len);
if (!host_cmdline_len) {
/* We special-case the "empty command line" case (argc==0).
Just provide the terminating 0. */
arm_cmdline_buffer = lock_user(VERIFY_WRITE, ARG(0), 1, 0);
arm_cmdline_buffer[0] = 0;
unlock_user(arm_cmdline_buffer, ARG(0), 1);
/* Adjust the commandline length argument. */
SET_ARG(1, len);
/* Adjust the commandline length argument. */
SET_ARG(1, 0);
return 0;
}
/* Return success if commandline fit into buffer. */
return *arg ? -1 : 0;
/* lock the buffers on the ARM side */
arm_cmdline_buffer =
lock_user(VERIFY_WRITE, ARG(0), host_cmdline_len, 0);
host_cmdline_buffer =
lock_user(VERIFY_READ, ts->info->arg_start,
host_cmdline_len, 1);
if (arm_cmdline_buffer && host_cmdline_buffer)
{
/* the last argument is zero-terminated;
no need for additional termination */
memcpy(arm_cmdline_buffer, host_cmdline_buffer,
host_cmdline_len);
/* separate arguments by white spaces */
for (i = 0; i < host_cmdline_len-1; i++) {
if (arm_cmdline_buffer[i] == 0) {
arm_cmdline_buffer[i] = ' ';
}
}
/* Adjust the commandline length argument. */
SET_ARG(1, host_cmdline_len-1);
}
/* Unlock the buffers on the ARM side. */
unlock_user(arm_cmdline_buffer, ARG(0), host_cmdline_len);
unlock_user((void*)host_cmdline_buffer, ts->info->arg_start, 0);
/* Return success if we could return a commandline. */
return (arm_cmdline_buffer && host_cmdline_buffer) ? 0 : -1;
}
#else
return -1;
return -1;
#endif
case SYS_HEAPINFO:
{

View File

@ -318,7 +318,7 @@ static int alsa_write (SWVoiceOut *sw, void *buf, int len)
return audio_pcm_sw_write (sw, buf, len);
}
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt, int endianness)
{
switch (fmt) {
case AUD_FMT_S8:
@ -328,16 +328,36 @@ static snd_pcm_format_t aud_to_alsafmt (audfmt_e fmt)
return SND_PCM_FORMAT_U8;
case AUD_FMT_S16:
return SND_PCM_FORMAT_S16_LE;
if (endianness) {
return SND_PCM_FORMAT_S16_BE;
}
else {
return SND_PCM_FORMAT_S16_LE;
}
case AUD_FMT_U16:
return SND_PCM_FORMAT_U16_LE;
if (endianness) {
return SND_PCM_FORMAT_U16_BE;
}
else {
return SND_PCM_FORMAT_U16_LE;
}
case AUD_FMT_S32:
return SND_PCM_FORMAT_S32_LE;
if (endianness) {
return SND_PCM_FORMAT_S32_BE;
}
else {
return SND_PCM_FORMAT_S32_LE;
}
case AUD_FMT_U32:
return SND_PCM_FORMAT_U32_LE;
if (endianness) {
return SND_PCM_FORMAT_U32_BE;
}
else {
return SND_PCM_FORMAT_U32_LE;
}
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
@ -809,7 +829,7 @@ static int alsa_init_out (HWVoiceOut *hw, struct audsettings *as)
snd_pcm_t *handle;
struct audsettings obt_as;
req.fmt = aud_to_alsafmt (as->fmt);
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_out;
@ -918,7 +938,7 @@ static int alsa_init_in (HWVoiceIn *hw, struct audsettings *as)
snd_pcm_t *handle;
struct audsettings obt_as;
req.fmt = aud_to_alsafmt (as->fmt);
req.fmt = aud_to_alsafmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.period_size = conf.period_size_in;

View File

@ -117,9 +117,12 @@ static int no_run_in (HWVoiceIn *hw)
static int no_read (SWVoiceIn *sw, void *buf, int size)
{
/* use custom code here instead of audio_pcm_sw_read() to avoid
* useless resampling/mixing */
int samples = size >> sw->info.shift;
int total = sw->hw->total_samples_captured - sw->total_hw_samples_acquired;
int to_clear = audio_MIN (samples, total);
sw->total_hw_samples_acquired += total;
audio_pcm_info_clear_buf (&sw->info, buf, to_clear);
return to_clear << sw->info.shift;
}

View File

@ -161,7 +161,7 @@ static int oss_write (SWVoiceOut *sw, void *buf, int len)
return audio_pcm_sw_write (sw, buf, len);
}
static int aud_to_ossfmt (audfmt_e fmt)
static int aud_to_ossfmt (audfmt_e fmt, int endianness)
{
switch (fmt) {
case AUD_FMT_S8:
@ -171,10 +171,20 @@ static int aud_to_ossfmt (audfmt_e fmt)
return AFMT_U8;
case AUD_FMT_S16:
return AFMT_S16_LE;
if (endianness) {
return AFMT_S16_BE;
}
else {
return AFMT_S16_LE;
}
case AUD_FMT_U16:
return AFMT_U16_LE;
if (endianness) {
return AFMT_U16_BE;
}
else {
return AFMT_U16_LE;
}
default:
dolog ("Internal logic error: Bad audio format %d\n", fmt);
@ -516,7 +526,7 @@ static int oss_init_out (HWVoiceOut *hw, struct audsettings *as)
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt);
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.fragsize = conf.fragsize;
@ -682,7 +692,7 @@ static int oss_init_in (HWVoiceIn *hw, struct audsettings *as)
oss->fd = -1;
req.fmt = aud_to_ossfmt (as->fmt);
req.fmt = aud_to_ossfmt (as->fmt, as->endianness);
req.freq = as->freq;
req.nchannels = as->nchannels;
req.fragsize = conf.fragsize;

View File

@ -2859,13 +2859,8 @@ int bdrv_img_create(const char *filename, const char *fmt,
if (get_option_parameter(param, BLOCK_OPT_SIZE)->value.n == -1) {
if (backing_file && backing_file->value.s) {
uint64_t size;
const char *fmt = NULL;
char buf[32];
if (backing_fmt && backing_fmt->value.s) {
fmt = backing_fmt->value.s;
}
bs = bdrv_new("");
ret = bdrv_open(bs, backing_file->value.s, flags, drv);

View File

@ -176,8 +176,6 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
retval = prepare_binprm(&bprm);
infop->host_argv = argv;
if(retval>=0) {
if (bprm.buf[0] == 0x7f
&& bprm.buf[1] == 'E'

View File

@ -50,7 +50,6 @@ struct image_info {
abi_ulong entry;
abi_ulong code_offset;
abi_ulong data_offset;
char **host_argv;
int personality;
};

15
bswap.h
View File

@ -144,6 +144,7 @@ CPU_CONVERT(le, 64, uint64_t)
#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
#define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
#else
@ -201,6 +202,20 @@ static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
p1[3] = v & 0xff;
}
static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
{
uint8_t *p1 = (uint8_t *)p;
p1[0] = v >> 56;
p1[1] = v >> 48;
p1[2] = v >> 40;
p1[3] = v >> 32;
p1[4] = v >> 24;
p1[5] = v >> 16;
p1[6] = v >> 8;
p1[7] = v & 0xff;
}
#endif
#ifdef HOST_WORDS_BIGENDIAN

18
configure vendored
View File

@ -2075,6 +2075,21 @@ if compile_prog "$ARCH_CFLAGS" "" ; then
fallocate=yes
fi
# check for sync_file_range
sync_file_range=no
cat > $TMPC << EOF
#include <fcntl.h>
int main(void)
{
sync_file_range(0, 0, 0, 0);
return 0;
}
EOF
if compile_prog "$ARCH_CFLAGS" "" ; then
sync_file_range=yes
fi
# check for dup3
dup3=no
cat > $TMPC << EOF
@ -2613,6 +2628,9 @@ fi
if test "$fallocate" = "yes" ; then
echo "CONFIG_FALLOCATE=y" >> $config_host_mak
fi
if test "$sync_file_range" = "yes" ; then
echo "CONFIG_SYNC_FILE_RANGE=y" >> $config_host_mak
fi
if test "$dup3" = "yes" ; then
echo "CONFIG_DUP3=y" >> $config_host_mak
fi

View File

@ -329,7 +329,7 @@ static inline void console_write_ch(console_ch_t *dest, uint32_t ch)
{
if (!(ch & 0xff))
ch |= ' ';
cpu_to_le32wu((uint32_t *) dest, ch);
*dest = ch;
}
typedef void (*vga_hw_update_ptr)(void *);
@ -369,6 +369,7 @@ void vnc_display_init(DisplayState *ds);
void vnc_display_close(DisplayState *ds);
int vnc_display_open(DisplayState *ds, const char *display);
int vnc_display_password(DisplayState *ds, const char *password);
int vnc_display_pw_expire(DisplayState *ds, time_t expires);
void do_info_vnc_print(Monitor *mon, const QObject *data);
void do_info_vnc(Monitor *mon, QObject **ret_data);
char *vnc_display_local_addr(DisplayState *ds);

View File

@ -454,11 +454,7 @@ int cpu_exec(CPUState *env1)
}
#elif defined(TARGET_MIPS)
if ((interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env) &&
(env->CP0_Status & (1 << CP0St_IE)) &&
!(env->CP0_Status & (1 << CP0St_EXL)) &&
!(env->CP0_Status & (1 << CP0St_ERL)) &&
!(env->hflags & MIPS_HFLAG_DM)) {
cpu_mips_hw_interrupts_pending(env)) {
/* Raise it */
env->exception_index = EXCP_EXT_INTERRUPT;
env->error_code = 0;

View File

@ -177,7 +177,7 @@ static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
static inline unsigned int tb_phys_hash_func(tb_page_addr_t pc)
{
return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
return (pc >> 2) & (CODE_GEN_PHYS_HASH_SIZE - 1);
}
TranslationBlock *tb_alloc(target_ulong pc);
@ -204,9 +204,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
#elif defined(__arm__)
static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
{
#if QEMU_GNUC_PREREQ(4, 1)
void __clear_cache(char *beg, char *end);
#else
#if !QEMU_GNUC_PREREQ(4, 1)
register unsigned long _beg __asm ("a1");
register unsigned long _end __asm ("a2");
register unsigned long _flg __asm ("a3");
@ -218,7 +216,7 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
| (((addr - (jmp_addr + 8)) >> 2) & 0xffffff);
#if QEMU_GNUC_PREREQ(4, 1)
__clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
__builtin___clear_cache((char *) jmp_addr, (char *) jmp_addr + 4);
#else
/* flush icache */
_beg = jmp_addr;

3
exec.c
View File

@ -517,7 +517,8 @@ static void code_gen_alloc(unsigned long tb_size)
exit(1);
}
}
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) \
|| defined(__DragonFly__) || defined(__OpenBSD__)
{
int flags;
void *addr = NULL;

View File

@ -254,7 +254,7 @@ int float32_is_signaling_nan( float32 a1)
return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
}
int float32_is_nan( float32 a1 )
int float32_is_quiet_nan( float32 a1 )
{
float32u u;
uint64_t a;
@ -411,7 +411,7 @@ int float64_is_signaling_nan( float64 a1)
}
int float64_is_nan( float64 a1 )
int float64_is_quiet_nan( float64 a1 )
{
float64u u;
uint64_t a;
@ -504,7 +504,7 @@ int floatx80_is_signaling_nan( floatx80 a1)
&& ( u.i.low == aLow );
}
int floatx80_is_nan( floatx80 a1 )
int floatx80_is_quiet_nan( floatx80 a1 )
{
floatx80u u;
u.f = a1;

View File

@ -242,7 +242,7 @@ INLINE int float32_unordered( float32 a, float32 b STATUS_PARAM)
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_signaling_nan( float32 );
int float32_is_nan( float32 );
int float32_is_quiet_nan( float32 );
INLINE float32 float32_abs(float32 a)
{
@ -351,7 +351,7 @@ INLINE int float64_unordered( float64 a, float64 b STATUS_PARAM)
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_signaling_nan( float64 );
int float64_is_nan( float64 );
int float64_is_quiet_nan( float64 );
INLINE float64 float64_abs(float64 a)
{
@ -455,7 +455,7 @@ INLINE int floatx80_unordered( floatx80 a, floatx80 b STATUS_PARAM)
int floatx80_compare( floatx80, floatx80 STATUS_PARAM );
int floatx80_compare_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_signaling_nan( floatx80 );
int floatx80_is_nan( floatx80 );
int floatx80_is_quiet_nan( floatx80 );
INLINE floatx80 floatx80_abs(floatx80 a)
{

View File

@ -30,7 +30,7 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
#if defined(TARGET_MIPS) || defined(TARGET_HPPA)
#if defined(TARGET_MIPS)
#define SNAN_BIT_IS_ONE 1
#else
#define SNAN_BIT_IS_ONE 0
@ -61,10 +61,8 @@ typedef struct {
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
#define float32_default_nan make_float32(0x7FFFFFFF)
#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#define float32_default_nan make_float32(0x7FC00000)
#elif defined(TARGET_HPPA)
#define float32_default_nan make_float32(0x7FA00000)
#elif SNAN_BIT_IS_ONE
#define float32_default_nan make_float32(0x7FBFFFFF)
#else
@ -76,7 +74,7 @@ typedef struct {
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
int float32_is_nan( float32 a_ )
int float32_is_quiet_nan( float32 a_ )
{
uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE
@ -109,13 +107,17 @@ int float32_is_signaling_nan( float32 a_ )
float32 float32_maybe_silence_nan( float32 a_ )
{
if (float32_is_signaling_nan(a_)) {
uint32_t a = float32_val(a_);
#if SNAN_BIT_IS_ONE
a &= ~(1 << 22);
# if defined(TARGET_MIPS)
return float32_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
# endif
#else
bits32 a = float32_val(a_);
a |= (1 << 22);
#endif
return make_float32(a);
#endif
}
return a_;
}
@ -152,6 +154,118 @@ static float32 commonNaNToFloat32( commonNaNT a )
return float32_default_nan;
}
/*----------------------------------------------------------------------------
| Select which NaN to propagate for a two-input operation.
| IEEE754 doesn't specify all the details of this, so the
| algorithm is target-specific.
| The routine is passed various bits of information about the
| two NaNs and should return 0 to select NaN a and 1 for NaN b.
| Note that signalling NaNs are always squashed to quiet NaNs
| by the caller, by calling floatXX_maybe_silence_nan() before
| returning them.
|
| aIsLargerSignificand is only valid if both a and b are NaNs
| of some kind, and is true if a has the larger significand,
| or if both a and b have the same significand but a is
| positive but b is negative. It is only needed for the x87
| tie-break rule.
*----------------------------------------------------------------------------*/
#if defined(TARGET_ARM)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag aIsLargerSignificand)
{
/* ARM mandated NaN propagation rules: take the first of:
* 1. A if it is signaling
* 2. B if it is signaling
* 3. A (quiet)
* 4. B (quiet)
* A signaling NaN is always quietened before returning it.
*/
if (aIsSNaN) {
return 0;
} else if (bIsSNaN) {
return 1;
} else if (aIsQNaN) {
return 0;
} else {
return 1;
}
}
#elif defined(TARGET_MIPS)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag aIsLargerSignificand)
{
/* According to MIPS specifications, if one of the two operands is
* a sNaN, a new qNaN has to be generated. This is done in
* floatXX_maybe_silence_nan(). For qNaN inputs the specifications
* says: "When possible, this QNaN result is one of the operand QNaN
* values." In practice it seems that most implementations choose
* the first operand if both operands are qNaN. In short this gives
* the following rules:
* 1. A if it is signaling
* 2. B if it is signaling
* 3. A (quiet)
* 4. B (quiet)
* A signaling NaN is always silenced before returning it.
*/
if (aIsSNaN) {
return 0;
} else if (bIsSNaN) {
return 1;
} else if (aIsQNaN) {
return 0;
} else {
return 1;
}
}
#elif defined(TARGET_PPC)
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag aIsLargerSignificand)
{
/* PowerPC propagation rules:
* 1. A if it sNaN or qNaN
* 2. B if it sNaN or qNaN
* A signaling NaN is always silenced before returning it.
*/
if (aIsSNaN || aIsQNaN) {
return 0;
} else {
return 1;
}
}
#else
static int pickNaN(flag aIsQNaN, flag aIsSNaN, flag bIsQNaN, flag bIsSNaN,
flag aIsLargerSignificand)
{
/* This implements x87 NaN propagation rules:
* SNaN + QNaN => return the QNaN
* two SNaNs => return the one with the larger significand, silenced
* two QNaNs => return the one with the larger significand
* SNaN and a non-NaN => return the SNaN, silenced
* QNaN and a non-NaN => return the QNaN
*
* If we get down to comparing significands and they are the same,
* return the NaN with the positive sign bit (if any).
*/
if (aIsSNaN) {
if (bIsSNaN) {
return aIsLargerSignificand ? 0 : 1;
}
return bIsQNaN ? 1 : 0;
}
else if (aIsQNaN) {
if (bIsSNaN || !bIsQNaN)
return 0;
else {
return aIsLargerSignificand ? 0 : 1;
}
} else {
return 1;
}
}
#endif
/*----------------------------------------------------------------------------
| Takes two single-precision floating-point values `a' and `b', one of which
| is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
@ -160,47 +274,36 @@ static float32 commonNaNToFloat32( commonNaNT a )
static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
bits32 av, bv, res;
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
bits32 av, bv;
if ( STATUS(default_nan_mode) )
return float32_default_nan;
aIsNaN = float32_is_nan( a );
aIsQuietNaN = float32_is_quiet_nan( a );
aIsSignalingNaN = float32_is_signaling_nan( a );
bIsNaN = float32_is_nan( b );
bIsQuietNaN = float32_is_quiet_nan( b );
bIsSignalingNaN = float32_is_signaling_nan( b );
av = float32_val(a);
bv = float32_val(b);
#if SNAN_BIT_IS_ONE
av &= ~0x00400000;
bv &= ~0x00400000;
#else
av |= 0x00400000;
bv |= 0x00400000;
#endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
res = bIsNaN ? bv : av;
if ((bits32)(av<<1) < (bits32)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits32)(bv<<1) < (bits32)(av<<1)) {
aIsLargerSignificand = 1;
} else {
aIsLargerSignificand = (av < bv) ? 1 : 0;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN || ! bIsNaN )
res = av;
else {
returnLargerSignificand:
if ( (bits32) ( av<<1 ) < (bits32) ( bv<<1 ) )
res = bv;
else if ( (bits32) ( bv<<1 ) < (bits32) ( av<<1 ) )
res = av;
else
res = ( av < bv ) ? av : bv;
}
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
aIsLargerSignificand)) {
return float32_maybe_silence_nan(b);
} else {
return float32_maybe_silence_nan(a);
}
else {
res = bv;
}
return make_float32(res);
}
/*----------------------------------------------------------------------------
@ -208,10 +311,8 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
*----------------------------------------------------------------------------*/
#if defined(TARGET_SPARC)
#define float64_default_nan make_float64(LIT64( 0x7FFFFFFFFFFFFFFF ))
#elif defined(TARGET_POWERPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#elif defined(TARGET_PPC) || defined(TARGET_ARM) || defined(TARGET_ALPHA)
#define float64_default_nan make_float64(LIT64( 0x7FF8000000000000 ))
#elif defined(TARGET_HPPA)
#define float64_default_nan make_float64(LIT64( 0x7FF4000000000000 ))
#elif SNAN_BIT_IS_ONE
#define float64_default_nan make_float64(LIT64( 0x7FF7FFFFFFFFFFFF ))
#else
@ -223,7 +324,7 @@ static float32 propagateFloat32NaN( float32 a, float32 b STATUS_PARAM)
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
int float64_is_nan( float64 a_ )
int float64_is_quiet_nan( float64 a_ )
{
bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE
@ -260,13 +361,17 @@ int float64_is_signaling_nan( float64 a_ )
float64 float64_maybe_silence_nan( float64 a_ )
{
if (float64_is_signaling_nan(a_)) {
bits64 a = float64_val(a_);
#if SNAN_BIT_IS_ONE
a &= ~LIT64( 0x0008000000000000 );
# if defined(TARGET_MIPS)
return float64_default_nan;
# else
# error Rules for silencing a signaling NaN are target-specific
# endif
#else
bits64 a = float64_val(a_);
a |= LIT64( 0x0008000000000000 );
#endif
return make_float64(a);
#endif
}
return a_;
}
@ -314,47 +419,36 @@ static float64 commonNaNToFloat64( commonNaNT a )
static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
bits64 av, bv, res;
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
bits64 av, bv;
if ( STATUS(default_nan_mode) )
return float64_default_nan;
aIsNaN = float64_is_nan( a );
aIsQuietNaN = float64_is_quiet_nan( a );
aIsSignalingNaN = float64_is_signaling_nan( a );
bIsNaN = float64_is_nan( b );
bIsQuietNaN = float64_is_quiet_nan( b );
bIsSignalingNaN = float64_is_signaling_nan( b );
av = float64_val(a);
bv = float64_val(b);
#if SNAN_BIT_IS_ONE
av &= ~LIT64( 0x0008000000000000 );
bv &= ~LIT64( 0x0008000000000000 );
#else
av |= LIT64( 0x0008000000000000 );
bv |= LIT64( 0x0008000000000000 );
#endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
res = bIsNaN ? bv : av;
if ((bits64)(av<<1) < (bits64)(bv<<1)) {
aIsLargerSignificand = 0;
} else if ((bits64)(bv<<1) < (bits64)(av<<1)) {
aIsLargerSignificand = 1;
} else {
aIsLargerSignificand = (av < bv) ? 1 : 0;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN || ! bIsNaN )
res = av;
else {
returnLargerSignificand:
if ( (bits64) ( av<<1 ) < (bits64) ( bv<<1 ) )
res = bv;
else if ( (bits64) ( bv<<1 ) < (bits64) ( av<<1 ) )
res = av;
else
res = ( av < bv ) ? av : bv;
}
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
aIsLargerSignificand)) {
return float64_maybe_silence_nan(b);
} else {
return float64_maybe_silence_nan(a);
}
else {
res = bv;
}
return make_float64(res);
}
#ifdef FLOATX80
@ -377,7 +471,7 @@ static float64 propagateFloat64NaN( float64 a, float64 b STATUS_PARAM)
| quiet NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
int floatx80_is_nan( floatx80 a )
int floatx80_is_quiet_nan( floatx80 a )
{
#if SNAN_BIT_IS_ONE
bits64 aLow;
@ -412,6 +506,29 @@ int floatx80_is_signaling_nan( floatx80 a )
#endif
}
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the extended double-precision floating point value
| `a' is a signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/
floatx80 floatx80_maybe_silence_nan( floatx80 a )
{
if (floatx80_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
# if defined(TARGET_MIPS)
a.low = floatx80_default_nan_low;
a.high = floatx80_default_nan_high;
# else
# error Rules for silencing a signaling NaN are target-specific
# endif
#else
a.low |= LIT64( 0xC000000000000000 );
return a;
#endif
}
return a;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the extended double-precision floating-
| point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
@ -454,7 +571,8 @@ static floatx80 commonNaNToFloatx80( commonNaNT a )
static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
if ( STATUS(default_nan_mode) ) {
a.low = floatx80_default_nan_low;
@ -462,31 +580,26 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
return a;
}
aIsNaN = floatx80_is_nan( a );
aIsQuietNaN = floatx80_is_quiet_nan( a );
aIsSignalingNaN = floatx80_is_signaling_nan( a );
bIsNaN = floatx80_is_nan( b );
bIsQuietNaN = floatx80_is_quiet_nan( b );
bIsSignalingNaN = floatx80_is_signaling_nan( b );
#if SNAN_BIT_IS_ONE
a.low &= ~LIT64( 0xC000000000000000 );
b.low &= ~LIT64( 0xC000000000000000 );
#else
a.low |= LIT64( 0xC000000000000000 );
b.low |= LIT64( 0xC000000000000000 );
#endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
if (a.low < b.low) {
aIsLargerSignificand = 0;
} else if (b.low < a.low) {
aIsLargerSignificand = 1;
} else {
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN || ! bIsNaN ) return a;
returnLargerSignificand:
if ( a.low < b.low ) return b;
if ( b.low < a.low ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
aIsLargerSignificand)) {
return floatx80_maybe_silence_nan(b);
} else {
return floatx80_maybe_silence_nan(a);
}
}
@ -511,7 +624,7 @@ static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b STATUS_PARAM)
| NaN; otherwise returns 0.
*----------------------------------------------------------------------------*/
int float128_is_nan( float128 a )
int float128_is_quiet_nan( float128 a )
{
#if SNAN_BIT_IS_ONE
return
@ -542,6 +655,29 @@ int float128_is_signaling_nan( float128 a )
#endif
}
/*----------------------------------------------------------------------------
| Returns a quiet NaN if the quadruple-precision floating point value `a' is
| a signaling NaN; otherwise returns `a'.
*----------------------------------------------------------------------------*/
float128 float128_maybe_silence_nan( float128 a )
{
if (float128_is_signaling_nan(a)) {
#if SNAN_BIT_IS_ONE
# if defined(TARGET_MIPS)
a.low = float128_default_nan_low;
a.high = float128_default_nan_high;
# else
# error Rules for silencing a signaling NaN are target-specific
# endif
#else
a.high |= LIT64( 0x0000800000000000 );
return a;
#endif
}
return a;
}
/*----------------------------------------------------------------------------
| Returns the result of converting the quadruple-precision floating-point NaN
| `a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
@ -580,7 +716,8 @@ static float128 commonNaNToFloat128( commonNaNT a )
static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
{
flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
flag aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN;
flag aIsLargerSignificand;
if ( STATUS(default_nan_mode) ) {
a.low = float128_default_nan_low;
@ -588,31 +725,26 @@ static float128 propagateFloat128NaN( float128 a, float128 b STATUS_PARAM)
return a;
}
aIsNaN = float128_is_nan( a );
aIsQuietNaN = float128_is_quiet_nan( a );
aIsSignalingNaN = float128_is_signaling_nan( a );
bIsNaN = float128_is_nan( b );
bIsQuietNaN = float128_is_quiet_nan( b );
bIsSignalingNaN = float128_is_signaling_nan( b );
#if SNAN_BIT_IS_ONE
a.high &= ~LIT64( 0x0000800000000000 );
b.high &= ~LIT64( 0x0000800000000000 );
#else
a.high |= LIT64( 0x0000800000000000 );
b.high |= LIT64( 0x0000800000000000 );
#endif
if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid STATUS_VAR);
if ( aIsSignalingNaN ) {
if ( bIsSignalingNaN ) goto returnLargerSignificand;
return bIsNaN ? b : a;
if (lt128(a.high<<1, a.low, b.high<<1, b.low)) {
aIsLargerSignificand = 0;
} else if (lt128(b.high<<1, b.low, a.high<<1, a.low)) {
aIsLargerSignificand = 1;
} else {
aIsLargerSignificand = (a.high < b.high) ? 1 : 0;
}
else if ( aIsNaN ) {
if ( bIsSignalingNaN || ! bIsNaN ) return a;
returnLargerSignificand:
if ( lt128( a.high<<1, a.low, b.high<<1, b.low ) ) return b;
if ( lt128( b.high<<1, b.low, a.high<<1, a.low ) ) return a;
return ( a.high < b.high ) ? a : b;
}
else {
return b;
if (pickNaN(aIsQuietNaN, aIsSignalingNaN, bIsQuietNaN, bIsSignalingNaN,
aIsLargerSignificand)) {
return float128_maybe_silence_nan(b);
} else {
return float128_maybe_silence_nan(a);
}
}

View File

@ -30,8 +30,6 @@ these four paragraphs for those parts of this code that are retained.
=============================================================================*/
/* FIXME: Flush-To-Zero only effects results. Denormal inputs should also
be flushed to zero. */
#include "softfloat.h"
/*----------------------------------------------------------------------------
@ -203,6 +201,21 @@ INLINE flag extractFloat32Sign( float32 a )
}
/*----------------------------------------------------------------------------
| 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.
*----------------------------------------------------------------------------*/
static float32 float32_squash_input_denormal(float32 a STATUS_PARAM)
{
if (STATUS(flush_inputs_to_zero)) {
if (extractFloat32Exp(a) == 0 && extractFloat32Frac(a) != 0) {
float_raise(float_flag_input_denormal STATUS_VAR);
return make_float32(float32_val(a) & 0x80000000);
}
}
return a;
}
/*----------------------------------------------------------------------------
| Normalizes the subnormal single-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
@ -367,6 +380,21 @@ INLINE flag extractFloat64Sign( float64 a )
}
/*----------------------------------------------------------------------------
| 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.
*----------------------------------------------------------------------------*/
static float64 float64_squash_input_denormal(float64 a STATUS_PARAM)
{
if (STATUS(flush_inputs_to_zero)) {
if (extractFloat64Exp(a) == 0 && extractFloat64Frac(a) != 0) {
float_raise(float_flag_input_denormal STATUS_VAR);
return make_float64(float64_val(a) & (1ULL << 63));
}
}
return a;
}
/*----------------------------------------------------------------------------
| Normalizes the subnormal double-precision floating-point value represented
| by the denormalized significand `aSig'. The normalized exponent and
@ -1298,6 +1326,7 @@ int32 float32_to_int32( float32 a STATUS_PARAM )
bits32 aSig;
bits64 aSig64;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -1327,6 +1356,7 @@ int32 float32_to_int32_round_to_zero( float32 a STATUS_PARAM )
int16 aExp, shiftCount;
bits32 aSig;
int32 z;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -1418,6 +1448,7 @@ int64 float32_to_int64( float32 a STATUS_PARAM )
int16 aExp, shiftCount;
bits32 aSig;
bits64 aSig64, aSigExtra;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -1455,6 +1486,7 @@ int64 float32_to_int64_round_to_zero( float32 a STATUS_PARAM )
bits32 aSig;
bits64 aSig64;
int64 z;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -1496,6 +1528,7 @@ float64 float32_to_float64( float32 a STATUS_PARAM )
flag aSign;
int16 aExp;
bits32 aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -1528,6 +1561,7 @@ floatx80 float32_to_floatx80( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -1561,6 +1595,7 @@ float128 float32_to_float128( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -1593,6 +1628,7 @@ float32 float32_round_to_int( float32 a STATUS_PARAM)
bits32 lastBitMask, roundBitsMask;
int8 roundingMode;
bits32 z;
a = float32_squash_input_denormal(a STATUS_VAR);
aExp = extractFloat32Exp( a );
if ( 0x96 <= aExp ) {
@ -1796,6 +1832,8 @@ static float32 subFloat32Sigs( float32 a, float32 b, flag zSign STATUS_PARAM)
float32 float32_add( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
@ -1817,6 +1855,8 @@ float32 float32_add( float32 a, float32 b STATUS_PARAM )
float32 float32_sub( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
@ -1843,6 +1883,9 @@ float32 float32_mul( float32 a, float32 b STATUS_PARAM )
bits64 zSig64;
bits32 zSig;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -1900,6 +1943,8 @@ float32 float32_div( float32 a, float32 b STATUS_PARAM )
flag aSign, bSign, zSign;
int16 aExp, bExp, zExp;
bits32 aSig, bSig, zSig;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -1966,6 +2011,8 @@ float32 float32_rem( float32 a, float32 b STATUS_PARAM )
bits64 aSig64, bSig64, q64;
bits32 alternateASig;
sbits32 sigMean;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -2062,6 +2109,7 @@ float32 float32_sqrt( float32 a STATUS_PARAM )
int16 aExp, zExp;
bits32 aSig, zSig;
bits64 rem, term;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -2148,6 +2196,7 @@ float32 float32_exp2( float32 a STATUS_PARAM )
bits32 aSig;
float64 r, x, xn;
int i;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -2194,6 +2243,7 @@ float32 float32_log2( float32 a STATUS_PARAM )
int16 aExp;
bits32 aSig, zSig, i;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -2238,6 +2288,8 @@ float32 float32_log2( float32 a STATUS_PARAM )
int float32_eq( float32 a, float32 b STATUS_PARAM )
{
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2263,6 +2315,8 @@ int float32_le( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2289,6 +2343,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2315,6 +2371,8 @@ int float32_lt( float32 a, float32 b STATUS_PARAM )
int float32_eq_signaling( float32 a, float32 b STATUS_PARAM )
{
bits32 av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2339,6 +2397,8 @@ int float32_le_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2368,6 +2428,8 @@ int float32_lt_quiet( float32 a, float32 b STATUS_PARAM )
{
flag aSign, bSign;
bits32 av, bv;
a = float32_squash_input_denormal(a STATUS_VAR);
b = float32_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
@ -2401,6 +2463,7 @@ int32 float64_to_int32( float64 a STATUS_PARAM )
flag aSign;
int16 aExp, shiftCount;
bits64 aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -2429,6 +2492,7 @@ int32 float64_to_int32_round_to_zero( float64 a STATUS_PARAM )
int16 aExp, shiftCount;
bits64 aSig, savedASig;
int32 z;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -2525,6 +2589,7 @@ int64 float64_to_int64( float64 a STATUS_PARAM )
flag aSign;
int16 aExp, shiftCount;
bits64 aSig, aSigExtra;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -2568,6 +2633,7 @@ int64 float64_to_int64_round_to_zero( float64 a STATUS_PARAM )
int16 aExp, shiftCount;
bits64 aSig;
int64 z;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -2617,6 +2683,7 @@ float32 float64_to_float32( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig;
bits32 zSig;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -2694,6 +2761,7 @@ bits16 float32_to_float16( float32 a, flag ieee STATUS_PARAM)
bits32 mask;
bits32 increment;
int8 roundingMode;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
@ -2788,6 +2856,7 @@ floatx80 float64_to_floatx80( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@ -2822,6 +2891,7 @@ float128 float64_to_float128( float64 a STATUS_PARAM )
int16 aExp;
bits64 aSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@ -2855,6 +2925,7 @@ float64 float64_round_to_int( float64 a STATUS_PARAM )
bits64 lastBitMask, roundBitsMask;
int8 roundingMode;
bits64 z;
a = float64_squash_input_denormal(a STATUS_VAR);
aExp = extractFloat64Exp( a );
if ( 0x433 <= aExp ) {
@ -3071,6 +3142,8 @@ static float64 subFloat64Sigs( float64 a, float64 b, flag zSign STATUS_PARAM )
float64 float64_add( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
@ -3092,6 +3165,8 @@ float64 float64_add( float64 a, float64 b STATUS_PARAM )
float64 float64_sub( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
aSign = extractFloat64Sign( a );
bSign = extractFloat64Sign( b );
@ -3116,6 +3191,9 @@ float64 float64_mul( float64 a, float64 b STATUS_PARAM )
int16 aExp, bExp, zExp;
bits64 aSig, bSig, zSig0, zSig1;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@ -3175,6 +3253,8 @@ float64 float64_div( float64 a, float64 b STATUS_PARAM )
bits64 aSig, bSig, zSig;
bits64 rem0, rem1;
bits64 term0, term1;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -3246,6 +3326,8 @@ float64 float64_rem( float64 a, float64 b STATUS_PARAM )
bits64 q, alternateASig;
sbits64 sigMean;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );
@ -3328,6 +3410,7 @@ float64 float64_sqrt( float64 a STATUS_PARAM )
int16 aExp, zExp;
bits64 aSig, zSig, doubleZSig;
bits64 rem0, rem1, term0, term1;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -3377,6 +3460,7 @@ float64 float64_log2( float64 a STATUS_PARAM )
flag aSign, zSign;
int16 aExp;
bits64 aSig, aSig0, aSig1, zSig, i;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
@ -3422,6 +3506,8 @@ float64 float64_log2( float64 a STATUS_PARAM )
int float64_eq( float64 a, float64 b STATUS_PARAM )
{
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@ -3448,6 +3534,8 @@ int float64_le( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@ -3475,6 +3563,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
flag aSign, bSign;
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
) {
@ -3500,6 +3590,8 @@ int float64_lt( float64 a, float64 b STATUS_PARAM )
int float64_eq_signaling( float64 a, float64 b STATUS_PARAM )
{
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@ -3524,6 +3616,8 @@ int float64_le_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@ -3553,6 +3647,8 @@ int float64_lt_quiet( float64 a, float64 b STATUS_PARAM )
{
flag aSign, bSign;
bits64 av, bv;
a = float64_squash_input_denormal(a STATUS_VAR);
b = float64_squash_input_denormal(b STATUS_VAR);
if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
|| ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
@ -5833,6 +5929,8 @@ INLINE int float ## s ## _compare_internal( float ## s a, float ## s b, \
{ \
flag aSign, bSign; \
bits ## s av, bv; \
a = float ## s ## _squash_input_denormal(a STATUS_VAR); \
b = float ## s ## _squash_input_denormal(b STATUS_VAR); \
\
if (( ( extractFloat ## s ## Exp( a ) == nan_exp ) && \
extractFloat ## s ## Frac( a ) ) || \
@ -5929,6 +6027,7 @@ float32 float32_scalbn( float32 a, int n STATUS_PARAM )
int16 aExp;
bits32 aSig;
a = float32_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
@ -5952,6 +6051,7 @@ float64 float64_scalbn( float64 a, int n STATUS_PARAM )
int16 aExp;
bits64 aSig;
a = float64_squash_input_denormal(a STATUS_VAR);
aSig = extractFloat64Frac( a );
aExp = extractFloat64Exp( a );
aSign = extractFloat64Sign( a );

View File

@ -180,7 +180,8 @@ enum {
float_flag_divbyzero = 4,
float_flag_overflow = 8,
float_flag_underflow = 16,
float_flag_inexact = 32
float_flag_inexact = 32,
float_flag_input_denormal = 64
};
typedef struct float_status {
@ -190,7 +191,10 @@ typedef struct float_status {
#ifdef FLOATX80
signed char floatx80_rounding_precision;
#endif
/* 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;
@ -200,6 +204,10 @@ INLINE void set_flush_to_zero(flag val STATUS_PARAM)
{
STATUS(flush_to_zero) = val;
}
INLINE void set_flush_inputs_to_zero(flag val STATUS_PARAM)
{
STATUS(flush_inputs_to_zero) = val;
}
INLINE void set_default_nan_mode(flag val STATUS_PARAM)
{
STATUS(default_nan_mode) = val;
@ -287,18 +295,24 @@ int float32_le_quiet( float32, float32 STATUS_PARAM );
int float32_lt_quiet( float32, float32 STATUS_PARAM );
int float32_compare( float32, float32 STATUS_PARAM );
int float32_compare_quiet( float32, float32 STATUS_PARAM );
int float32_is_nan( float32 );
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 );
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);
}
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);
}
@ -367,18 +381,24 @@ int float64_le_quiet( float64, float64 STATUS_PARAM );
int float64_lt_quiet( float64, float64 STATUS_PARAM );
int float64_compare( float64, float64 STATUS_PARAM );
int float64_compare_quiet( float64, float64 STATUS_PARAM );
int float64_is_nan( float64 a );
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 );
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);
}
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);
}
@ -437,8 +457,9 @@ int floatx80_lt( floatx80, floatx80 STATUS_PARAM );
int floatx80_eq_signaling( floatx80, floatx80 STATUS_PARAM );
int floatx80_le_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_lt_quiet( floatx80, floatx80 STATUS_PARAM );
int floatx80_is_nan( floatx80 );
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 );
INLINE floatx80 floatx80_abs(floatx80 a)
@ -468,6 +489,11 @@ INLINE int floatx80_is_zero(floatx80 a)
return (a.high & 0x7fff) == 0 && a.low == 0;
}
INLINE int floatx80_is_any_nan(floatx80 a)
{
return ((a.high & 0x7fff) == 0x7fff) && (a.low<<1);
}
#endif
#ifdef FLOAT128
@ -503,8 +529,9 @@ int float128_le_quiet( float128, float128 STATUS_PARAM );
int float128_lt_quiet( float128, float128 STATUS_PARAM );
int float128_compare( float128, float128 STATUS_PARAM );
int float128_compare_quiet( float128, float128 STATUS_PARAM );
int float128_is_nan( float128 );
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 );
INLINE float128 float128_abs(float128 a)
@ -534,6 +561,12 @@ INLINE int float128_is_zero(float128 a)
return (a.high & 0x7fffffffffffffffLL) == 0 && a.low == 0;
}
INLINE int float128_is_any_nan(float128 a)
{
return ((a.high >> 48) & 0x7fff) == 0x7fff &&
((a.low != 0) || ((a.high & 0xffffffffffffLL) != 0));
}
#endif
#else /* CONFIG_SOFTFLOAT */

View File

@ -1176,6 +1176,60 @@ STEXI
@item block_passwd @var{device} @var{password}
@findex block_passwd
Set the encrypted device @var{device} password to @var{password}
ETEXI
{
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.user_print = monitor_user_noop,
.mhandler.cmd_new = set_password,
},
STEXI
@item set_password [ vnc | spice ] password [ action-if-connected ]
@findex set_password
Change spice/vnc password. Use zero to make the password stay valid
forever. @var{action-if-connected} specifies what should happen in
case a connection is established: @var{fail} makes the password change
fail. @var{disconnect} changes the password and disconnects the
client. @var{keep} changes the password and keeps the connection up.
@var{keep} is the default.
ETEXI
{
.name = "expire_password",
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.user_print = monitor_user_noop,
.mhandler.cmd_new = expire_password,
},
STEXI
@item expire_password [ vnc | spice ] expire-time
@findex expire_password
Specify when a password for spice/vnc becomes
invalid. @var{expire-time} accepts:
@table @var
@item now
Invalidate password instantly.
@item never
Password stays valid forever.
@item +nsec
Password stays valid for @var{nsec} seconds starting now.
@item nsec
Password is invalidated at the given time. @var{nsec} are the seconds
passed since 1970, i.e. unix epoch.
@end table
ETEXI
{
@ -1215,7 +1269,7 @@ show i8259 (PIC) state
@item info pci
show emulated PCI device info
@item info tlb
show virtual to physical memory mappings (i386 only)
show virtual to physical memory mappings (i386, SH4 and SPARC only)
@item info mem
show the active virtual memory mappings (i386 only)
@item info jit

View File

@ -765,7 +765,7 @@ static uint32_t apic_mem_readl(void *opaque, target_phys_addr_t addr)
return val;
}
static void apic_send_msi(target_phys_addr_t addr, uint32 data)
static void apic_send_msi(target_phys_addr_t addr, uint32_t data)
{
uint8_t dest = (addr & MSI_ADDR_DEST_ID_MASK) >> MSI_ADDR_DEST_ID_SHIFT;
uint8_t vector = (data & MSI_DATA_VECTOR_MASK) >> MSI_DATA_VECTOR_SHIFT;

View File

@ -673,46 +673,47 @@ static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
static void cirrus_do_copy(CirrusVGAState *s, int dst, int src, int w, int h)
{
int sx, sy;
int dx, dy;
int width, height;
int depth;
int sx = 0, sy = 0;
int dx = 0, dy = 0;
int depth = 0;
int notify = 0;
depth = s->vga.get_bpp(&s->vga) / 8;
s->vga.get_resolution(&s->vga, &width, &height);
/* make sure to only copy if it's a plain copy ROP */
if (*s->cirrus_rop == cirrus_bitblt_rop_fwd_src ||
*s->cirrus_rop == cirrus_bitblt_rop_bkwd_src) {
/* extra x, y */
sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
sy = (src / ABS(s->cirrus_blt_srcpitch));
dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
dy = (dst / ABS(s->cirrus_blt_dstpitch));
int width, height;
/* normalize width */
w /= depth;
depth = s->vga.get_bpp(&s->vga) / 8;
s->vga.get_resolution(&s->vga, &width, &height);
/* if we're doing a backward copy, we have to adjust
our x/y to be the upper left corner (instead of the lower
right corner) */
if (s->cirrus_blt_dstpitch < 0) {
sx -= (s->cirrus_blt_width / depth) - 1;
dx -= (s->cirrus_blt_width / depth) - 1;
sy -= s->cirrus_blt_height - 1;
dy -= s->cirrus_blt_height - 1;
/* extra x, y */
sx = (src % ABS(s->cirrus_blt_srcpitch)) / depth;
sy = (src / ABS(s->cirrus_blt_srcpitch));
dx = (dst % ABS(s->cirrus_blt_dstpitch)) / depth;
dy = (dst / ABS(s->cirrus_blt_dstpitch));
/* normalize width */
w /= depth;
/* if we're doing a backward copy, we have to adjust
our x/y to be the upper left corner (instead of the lower
right corner) */
if (s->cirrus_blt_dstpitch < 0) {
sx -= (s->cirrus_blt_width / depth) - 1;
dx -= (s->cirrus_blt_width / depth) - 1;
sy -= s->cirrus_blt_height - 1;
dy -= s->cirrus_blt_height - 1;
}
/* are we in the visible portion of memory? */
if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
(sx + w) <= width && (sy + h) <= height &&
(dx + w) <= width && (dy + h) <= height) {
notify = 1;
}
}
/* are we in the visible portion of memory? */
if (sx >= 0 && sy >= 0 && dx >= 0 && dy >= 0 &&
(sx + w) <= width && (sy + h) <= height &&
(dx + w) <= width && (dy + h) <= height) {
notify = 1;
}
/* make to sure only copy if it's a plain copy ROP */
if (*s->cirrus_rop != cirrus_bitblt_rop_fwd_src &&
*s->cirrus_rop != cirrus_bitblt_rop_bkwd_src)
notify = 0;
/* we have to flush all pending changes so that the copy
is generated at the appropriate moment in time */
if (notify)
@ -2003,30 +2004,20 @@ static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_vga_mem_readb(opaque, addr) << 8;
v |= cirrus_vga_mem_readb(opaque, addr + 1);
#else
v = cirrus_vga_mem_readb(opaque, addr);
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_vga_mem_readb(opaque, addr) << 24;
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
v |= cirrus_vga_mem_readb(opaque, addr + 3);
#else
v = cirrus_vga_mem_readb(opaque, addr);
v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
#endif
return v;
}
@ -2097,28 +2088,16 @@ static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
#else
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
#endif
}
static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
#else
cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
static CPUReadMemoryFunc * const cirrus_vga_mem_read[3] = {
@ -2340,30 +2319,20 @@ static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_linear_readb(opaque, addr) << 8;
v |= cirrus_linear_readb(opaque, addr + 1);
#else
v = cirrus_linear_readb(opaque, addr);
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_linear_readb(opaque, addr) << 24;
v |= cirrus_linear_readb(opaque, addr + 1) << 16;
v |= cirrus_linear_readb(opaque, addr + 2) << 8;
v |= cirrus_linear_readb(opaque, addr + 3);
#else
v = cirrus_linear_readb(opaque, addr);
v |= cirrus_linear_readb(opaque, addr + 1) << 8;
v |= cirrus_linear_readb(opaque, addr + 2) << 16;
v |= cirrus_linear_readb(opaque, addr + 3) << 24;
#endif
return v;
}
@ -2411,29 +2380,17 @@ static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
#else
cirrus_linear_writeb(opaque, addr, val & 0xff);
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
#endif
}
static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
#else
cirrus_linear_writeb(opaque, addr, val & 0xff);
cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
@ -2468,30 +2425,20 @@ static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr
static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
#else
v = cirrus_linear_bitblt_readb(opaque, addr);
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
#else
v = cirrus_linear_bitblt_readb(opaque, addr);
v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
#endif
return v;
}
@ -2512,29 +2459,17 @@ static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
#else
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
#endif
}
static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
#else
cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
@ -2841,30 +2776,20 @@ static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_mmio_readb(opaque, addr) << 8;
v |= cirrus_mmio_readb(opaque, addr + 1);
#else
v = cirrus_mmio_readb(opaque, addr);
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
#endif
return v;
}
static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
{
uint32_t v;
#ifdef TARGET_WORDS_BIGENDIAN
v = cirrus_mmio_readb(opaque, addr) << 24;
v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
v |= cirrus_mmio_readb(opaque, addr + 3);
#else
v = cirrus_mmio_readb(opaque, addr);
v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
#endif
return v;
}
@ -2885,29 +2810,17 @@ static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
#else
cirrus_mmio_writeb(opaque, addr, val & 0xff);
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
#endif
}
static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
uint32_t val)
{
#ifdef TARGET_WORDS_BIGENDIAN
cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
#else
cirrus_mmio_writeb(opaque, addr, val & 0xff);
cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
#endif
}
@ -3077,7 +2990,7 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
s->vga.vga_io_memory = cpu_register_io_memory(cirrus_vga_mem_read,
cirrus_vga_mem_write, s,
DEVICE_NATIVE_ENDIAN);
DEVICE_LITTLE_ENDIAN);
cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
s->vga.vga_io_memory);
qemu_register_coalesced_mmio(isa_mem_base + 0x000a0000, 0x20000);
@ -3085,18 +2998,18 @@ static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
/* I/O handler for LFB */
s->cirrus_linear_io_addr =
cpu_register_io_memory(cirrus_linear_read, cirrus_linear_write, s,
DEVICE_NATIVE_ENDIAN);
DEVICE_LITTLE_ENDIAN);
/* I/O handler for LFB */
s->cirrus_linear_bitblt_io_addr =
cpu_register_io_memory(cirrus_linear_bitblt_read,
cirrus_linear_bitblt_write, s,
DEVICE_NATIVE_ENDIAN);
DEVICE_LITTLE_ENDIAN);
/* I/O handler for memory-mapped I/O */
s->cirrus_mmio_io_addr =
cpu_register_io_memory(cirrus_mmio_read, cirrus_mmio_write, s,
DEVICE_NATIVE_ENDIAN);
DEVICE_LITTLE_ENDIAN);
s->real_vram_size =
(s->device_id == CIRRUS_ID_CLGD5446) ? 4096 * 1024 : 2048 * 1024;

14
hw/hw.h
View File

@ -528,6 +528,17 @@ extern const VMStateInfo vmstate_info_unused_buffer;
.start = (_start), \
}
#define VMSTATE_VBUFFER_UINT32(_field, _state, _version, _test, _start, _field_size) { \
.name = (stringify(_field)), \
.version_id = (_version), \
.field_exists = (_test), \
.size_offset = vmstate_offset_value(_state, _field_size, uint32_t),\
.info = &vmstate_info_buffer, \
.flags = VMS_VBUFFER|VMS_POINTER, \
.offset = offsetof(_state, _field), \
.start = (_start), \
}
#define VMSTATE_BUFFER_UNSAFE_INFO(_field, _state, _version, _info, _size) { \
.name = (stringify(_field)), \
.version_id = (_version), \
@ -745,6 +756,9 @@ extern const VMStateDescription vmstate_i2c_slave;
#define VMSTATE_PARTIAL_VBUFFER(_f, _s, _size) \
VMSTATE_VBUFFER(_f, _s, 0, NULL, 0, _size)
#define VMSTATE_PARTIAL_VBUFFER_UINT32(_f, _s, _size) \
VMSTATE_VBUFFER_UINT32(_f, _s, 0, NULL, 0, _size)
#define VMSTATE_SUB_VBUFFER(_f, _s, _start, _size) \
VMSTATE_VBUFFER(_f, _s, 0, NULL, _start, _size)

97
hw/pc.c
View File

@ -40,6 +40,7 @@
#include "sysbus.h"
#include "sysemu.h"
#include "blockdev.h"
#include "ui/qemu-spice.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
@ -410,11 +411,92 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
qemu_register_reset(pc_cmos_init_late, &arg);
}
/* port 92 stuff: could be split off */
typedef struct Port92State {
ISADevice dev;
uint8_t outport;
qemu_irq *a20_out;
} Port92State;
static void port92_write(void *opaque, uint32_t addr, uint32_t val)
{
Port92State *s = opaque;
DPRINTF("port92: write 0x%02x\n", val);
s->outport = val;
qemu_set_irq(*s->a20_out, (val >> 1) & 1);
if (val & 1) {
qemu_system_reset_request();
}
}
static uint32_t port92_read(void *opaque, uint32_t addr)
{
Port92State *s = opaque;
uint32_t ret;
ret = s->outport;
DPRINTF("port92: read 0x%02x\n", ret);
return ret;
}
static void port92_init(ISADevice *dev, qemu_irq *a20_out)
{
Port92State *s = DO_UPCAST(Port92State, dev, dev);
s->a20_out = a20_out;
}
static const VMStateDescription vmstate_port92_isa = {
.name = "port92",
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields = (VMStateField []) {
VMSTATE_UINT8(outport, Port92State),
VMSTATE_END_OF_LIST()
}
};
static void port92_reset(DeviceState *d)
{
Port92State *s = container_of(d, Port92State, dev.qdev);
s->outport &= ~1;
}
static int port92_initfn(ISADevice *dev)
{
Port92State *s = DO_UPCAST(Port92State, dev, dev);
register_ioport_read(0x92, 1, 1, port92_read, s);
register_ioport_write(0x92, 1, 1, port92_write, s);
isa_init_ioport(dev, 0x92);
s->outport = 0;
return 0;
}
static ISADeviceInfo port92_info = {
.qdev.name = "port92",
.qdev.size = sizeof(Port92State),
.qdev.vmsd = &vmstate_port92_isa,
.qdev.no_user = 1,
.qdev.reset = port92_reset,
.init = port92_initfn,
};
static void port92_register(void)
{
isa_qdev_register(&port92_info);
}
device_init(port92_register)
static void handle_a20_line_change(void *opaque, int irq, int level)
{
CPUState *cpu = opaque;
/* XXX: send to all CPUs ? */
/* XXX: add logic to handle multiple A20 line sources */
cpu_x86_set_a20(cpu, level);
}
@ -992,6 +1074,13 @@ void pc_vga_init(PCIBus *pci_bus)
pci_vmsvga_init(pci_bus);
else
fprintf(stderr, "%s: vmware_vga: no PCI bus\n", __FUNCTION__);
#ifdef CONFIG_SPICE
} else if (qxl_enabled) {
if (pci_bus)
pci_create_simple(pci_bus, -1, "qxl-vga");
else
fprintf(stderr, "%s: qxl: no PCI bus\n", __FUNCTION__);
#endif
} else if (std_vga_enabled) {
if (pci_bus) {
pci_vga_init(pci_bus);
@ -1019,7 +1108,7 @@ void pc_basic_device_init(qemu_irq *isa_irq,
PITState *pit;
qemu_irq rtc_irq = NULL;
qemu_irq *a20_line;
ISADevice *i8042;
ISADevice *i8042, *port92;
qemu_irq *cpu_exit_irq;
register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
@ -1053,10 +1142,12 @@ void pc_basic_device_init(qemu_irq *isa_irq,
}
}
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 1);
a20_line = qemu_allocate_irqs(handle_a20_line_change, first_cpu, 2);
i8042 = isa_create_simple("i8042");
i8042_setup_a20_line(i8042, a20_line);
i8042_setup_a20_line(i8042, &a20_line[0]);
vmmouse_init(i8042);
port92 = isa_create_simple("port92");
port92_init(port92, &a20_line[1]);
cpu_exit_irq = qemu_allocate_irqs(cpu_request_exit, NULL, 1);
DMA_init(0, cpu_exit_irq);

View File

@ -211,10 +211,8 @@ static void kbd_queue(KBDState *s, int b, int aux)
ps2_queue(s->kbd, b);
}
static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
static void outport_write(KBDState *s, uint32_t val)
{
KBDState *s = opaque;
DPRINTF("kbd: write outport=0x%02x\n", val);
s->outport = val;
if (s->a20_out) {
@ -225,16 +223,6 @@ static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
}
}
static uint32_t ioport92_read(void *opaque, uint32_t addr)
{
KBDState *s = opaque;
uint32_t ret;
ret = s->outport;
DPRINTF("kbd: read outport=0x%02x\n", ret);
return ret;
}
static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
{
KBDState *s = opaque;
@ -357,7 +345,7 @@ static void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
kbd_queue(s, val, 1);
break;
case KBD_CCMD_WRITE_OUTPORT:
ioport92_write(s, 0, val);
outport_write(s, val);
break;
case KBD_CCMD_WRITE_MOUSE:
ps2_write_mouse(s->mouse, val);
@ -489,9 +477,6 @@ static int i8042_initfn(ISADevice *dev)
register_ioport_read(0x64, 1, 1, kbd_read_status, s);
register_ioport_write(0x64, 1, 1, kbd_write_command, s);
isa_init_ioport(dev, 0x64);
register_ioport_read(0x92, 1, 1, ioport92_read, s);
register_ioport_write(0x92, 1, 1, ioport92_write, s);
isa_init_ioport(dev, 0x92);
s->kbd = ps2_kbd_init(kbd_update_kbd_irq, s);
s->mouse = ps2_mouse_init(kbd_update_aux_irq, s);

248
hw/qxl-logger.c Normal file
View File

@ -0,0 +1,248 @@
/*
* qxl command logging -- for debug purposes
*
* Copyright (C) 2010 Red Hat, Inc.
*
* maintained by Gerd Hoffmann <kraxel@redhat.com>
*
* 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 or
* (at your option) version 3 of the License.
*
* 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/>.
*/
#include "qxl.h"
static const char *qxl_type[] = {
[ QXL_CMD_NOP ] = "nop",
[ QXL_CMD_DRAW ] = "draw",
[ QXL_CMD_UPDATE ] = "update",
[ QXL_CMD_CURSOR ] = "cursor",
[ QXL_CMD_MESSAGE ] = "message",
[ QXL_CMD_SURFACE ] = "surface",
};
static const char *qxl_draw_type[] = {
[ QXL_DRAW_NOP ] = "nop",
[ QXL_DRAW_FILL ] = "fill",
[ QXL_DRAW_OPAQUE ] = "opaque",
[ QXL_DRAW_COPY ] = "copy",
[ QXL_COPY_BITS ] = "copy-bits",
[ QXL_DRAW_BLEND ] = "blend",
[ QXL_DRAW_BLACKNESS ] = "blackness",
[ QXL_DRAW_WHITENESS ] = "whitemess",
[ QXL_DRAW_INVERS ] = "invers",
[ QXL_DRAW_ROP3 ] = "rop3",
[ QXL_DRAW_STROKE ] = "stroke",
[ QXL_DRAW_TEXT ] = "text",
[ QXL_DRAW_TRANSPARENT ] = "transparent",
[ QXL_DRAW_ALPHA_BLEND ] = "alpha-blend",
};
static const char *qxl_draw_effect[] = {
[ QXL_EFFECT_BLEND ] = "blend",
[ QXL_EFFECT_OPAQUE ] = "opaque",
[ QXL_EFFECT_REVERT_ON_DUP ] = "revert-on-dup",
[ QXL_EFFECT_BLACKNESS_ON_DUP ] = "blackness-on-dup",
[ QXL_EFFECT_WHITENESS_ON_DUP ] = "whiteness-on-dup",
[ QXL_EFFECT_NOP_ON_DUP ] = "nop-on-dup",
[ QXL_EFFECT_NOP ] = "nop",
[ QXL_EFFECT_OPAQUE_BRUSH ] = "opaque-brush",
};
static const char *qxl_surface_cmd[] = {
[ QXL_SURFACE_CMD_CREATE ] = "create",
[ QXL_SURFACE_CMD_DESTROY ] = "destroy",
};
static const char *spice_surface_fmt[] = {
[ SPICE_SURFACE_FMT_INVALID ] = "invalid",
[ SPICE_SURFACE_FMT_1_A ] = "alpha/1",
[ SPICE_SURFACE_FMT_8_A ] = "alpha/8",
[ SPICE_SURFACE_FMT_16_555 ] = "555/16",
[ SPICE_SURFACE_FMT_16_565 ] = "565/16",
[ SPICE_SURFACE_FMT_32_xRGB ] = "xRGB/32",
[ SPICE_SURFACE_FMT_32_ARGB ] = "ARGB/32",
};
static const char *qxl_cursor_cmd[] = {
[ QXL_CURSOR_SET ] = "set",
[ QXL_CURSOR_MOVE ] = "move",
[ QXL_CURSOR_HIDE ] = "hide",
[ QXL_CURSOR_TRAIL ] = "trail",
};
static const char *spice_cursor_type[] = {
[ SPICE_CURSOR_TYPE_ALPHA ] = "alpha",
[ SPICE_CURSOR_TYPE_MONO ] = "mono",
[ SPICE_CURSOR_TYPE_COLOR4 ] = "color4",
[ SPICE_CURSOR_TYPE_COLOR8 ] = "color8",
[ SPICE_CURSOR_TYPE_COLOR16 ] = "color16",
[ SPICE_CURSOR_TYPE_COLOR24 ] = "color24",
[ SPICE_CURSOR_TYPE_COLOR32 ] = "color32",
};
static const char *qxl_v2n(const char *n[], size_t l, int v)
{
if (v >= l || !n[v]) {
return "???";
}
return n[v];
}
#define qxl_name(_list, _value) qxl_v2n(_list, ARRAY_SIZE(_list), _value)
static void qxl_log_image(PCIQXLDevice *qxl, QXLPHYSICAL addr, int group_id)
{
QXLImage *image;
QXLImageDescriptor *desc;
image = qxl_phys2virt(qxl, addr, group_id);
desc = &image->descriptor;
fprintf(stderr, " (id %" PRIx64 " type %d flags %d width %d height %d",
desc->id, desc->type, desc->flags, desc->width, desc->height);
switch (desc->type) {
case SPICE_IMAGE_TYPE_BITMAP:
fprintf(stderr, ", fmt %d flags %d x %d y %d stride %d"
" palette %" PRIx64 " data %" PRIx64,
image->bitmap.format, image->bitmap.flags,
image->bitmap.x, image->bitmap.y,
image->bitmap.stride,
image->bitmap.palette, image->bitmap.data);
break;
}
fprintf(stderr, ")");
}
static void qxl_log_rect(QXLRect *rect)
{
fprintf(stderr, " %dx%d+%d+%d",
rect->right - rect->left,
rect->bottom - rect->top,
rect->left, rect->top);
}
static void qxl_log_cmd_draw_copy(PCIQXLDevice *qxl, QXLCopy *copy, int group_id)
{
fprintf(stderr, " src %" PRIx64,
copy->src_bitmap);
qxl_log_image(qxl, copy->src_bitmap, group_id);
fprintf(stderr, " area");
qxl_log_rect(&copy->src_area);
fprintf(stderr, " rop %d", copy->rop_descriptor);
}
static void qxl_log_cmd_draw(PCIQXLDevice *qxl, QXLDrawable *draw, int group_id)
{
fprintf(stderr, ": surface_id %d type %s effect %s",
draw->surface_id,
qxl_name(qxl_draw_type, draw->type),
qxl_name(qxl_draw_effect, draw->effect));
switch (draw->type) {
case QXL_DRAW_COPY:
qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
break;
}
}
static void qxl_log_cmd_draw_compat(PCIQXLDevice *qxl, QXLCompatDrawable *draw,
int group_id)
{
fprintf(stderr, ": type %s effect %s",
qxl_name(qxl_draw_type, draw->type),
qxl_name(qxl_draw_effect, draw->effect));
if (draw->bitmap_offset) {
fprintf(stderr, ": bitmap %d",
draw->bitmap_offset);
qxl_log_rect(&draw->bitmap_area);
}
switch (draw->type) {
case QXL_DRAW_COPY:
qxl_log_cmd_draw_copy(qxl, &draw->u.copy, group_id);
break;
}
}
static void qxl_log_cmd_surface(PCIQXLDevice *qxl, QXLSurfaceCmd *cmd)
{
fprintf(stderr, ": %s id %d",
qxl_name(qxl_surface_cmd, cmd->type),
cmd->surface_id);
if (cmd->type == QXL_SURFACE_CMD_CREATE) {
fprintf(stderr, " size %dx%d stride %d format %s (count %d, max %d)",
cmd->u.surface_create.width,
cmd->u.surface_create.height,
cmd->u.surface_create.stride,
qxl_name(spice_surface_fmt, cmd->u.surface_create.format),
qxl->guest_surfaces.count, qxl->guest_surfaces.max);
}
if (cmd->type == QXL_SURFACE_CMD_DESTROY) {
fprintf(stderr, " (count %d)", qxl->guest_surfaces.count);
}
}
void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id)
{
QXLCursor *cursor;
fprintf(stderr, ": %s",
qxl_name(qxl_cursor_cmd, cmd->type));
switch (cmd->type) {
case QXL_CURSOR_SET:
fprintf(stderr, " +%d+%d visible %s, shape @ 0x%" PRIx64,
cmd->u.set.position.x,
cmd->u.set.position.y,
cmd->u.set.visible ? "yes" : "no",
cmd->u.set.shape);
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, group_id);
fprintf(stderr, " type %s size %dx%d hot-spot +%d+%d"
" unique 0x%" PRIx64 " data-size %d",
qxl_name(spice_cursor_type, cursor->header.type),
cursor->header.width, cursor->header.height,
cursor->header.hot_spot_x, cursor->header.hot_spot_y,
cursor->header.unique, cursor->data_size);
break;
case QXL_CURSOR_MOVE:
fprintf(stderr, " +%d+%d", cmd->u.position.x, cmd->u.position.y);
break;
}
}
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext)
{
bool compat = ext->flags & QXL_COMMAND_FLAG_COMPAT;
void *data;
if (!qxl->cmdlog) {
return;
}
fprintf(stderr, "qxl-%d/%s:", qxl->id, ring);
fprintf(stderr, " cmd @ 0x%" PRIx64 " %s%s", ext->cmd.data,
qxl_name(qxl_type, ext->cmd.type),
compat ? "(compat)" : "");
data = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
switch (ext->cmd.type) {
case QXL_CMD_DRAW:
if (!compat) {
qxl_log_cmd_draw(qxl, data, ext->group_id);
} else {
qxl_log_cmd_draw_compat(qxl, data, ext->group_id);
}
break;
case QXL_CMD_SURFACE:
qxl_log_cmd_surface(qxl, data);
break;
case QXL_CMD_CURSOR:
qxl_log_cmd_cursor(qxl, data, ext->group_id);
break;
}
fprintf(stderr, "\n");
}

226
hw/qxl-render.c Normal file
View File

@ -0,0 +1,226 @@
/*
* qxl local rendering (aka display on sdl/vnc)
*
* Copyright (C) 2010 Red Hat, Inc.
*
* maintained by Gerd Hoffmann <kraxel@redhat.com>
*
* 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 or
* (at your option) version 3 of the License.
*
* 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/>.
*/
#include "qxl.h"
static void qxl_flip(PCIQXLDevice *qxl, QXLRect *rect)
{
uint8_t *src = qxl->guest_primary.data;
uint8_t *dst = qxl->guest_primary.flipped;
int len, i;
src += (qxl->guest_primary.surface.height - rect->top - 1) *
qxl->guest_primary.stride;
dst += rect->top * qxl->guest_primary.stride;
src += rect->left * qxl->guest_primary.bytes_pp;
dst += rect->left * qxl->guest_primary.bytes_pp;
len = (rect->right - rect->left) * qxl->guest_primary.bytes_pp;
for (i = rect->top; i < rect->bottom; i++) {
memcpy(dst, src, len);
dst += qxl->guest_primary.stride;
src -= qxl->guest_primary.stride;
}
}
void qxl_render_resize(PCIQXLDevice *qxl)
{
QXLSurfaceCreate *sc = &qxl->guest_primary.surface;
qxl->guest_primary.stride = sc->stride;
qxl->guest_primary.resized++;
switch (sc->format) {
case SPICE_SURFACE_FMT_16_555:
qxl->guest_primary.bytes_pp = 2;
qxl->guest_primary.bits_pp = 15;
break;
case SPICE_SURFACE_FMT_16_565:
qxl->guest_primary.bytes_pp = 2;
qxl->guest_primary.bits_pp = 16;
break;
case SPICE_SURFACE_FMT_32_xRGB:
case SPICE_SURFACE_FMT_32_ARGB:
qxl->guest_primary.bytes_pp = 4;
qxl->guest_primary.bits_pp = 32;
break;
default:
fprintf(stderr, "%s: unhandled format: %x\n", __FUNCTION__,
qxl->guest_primary.surface.format);
qxl->guest_primary.bytes_pp = 4;
qxl->guest_primary.bits_pp = 32;
break;
}
}
void qxl_render_update(PCIQXLDevice *qxl)
{
VGACommonState *vga = &qxl->vga;
QXLRect dirty[32], update;
void *ptr;
int i;
if (qxl->guest_primary.resized) {
qxl->guest_primary.resized = 0;
if (qxl->guest_primary.flipped) {
qemu_free(qxl->guest_primary.flipped);
qxl->guest_primary.flipped = NULL;
}
qemu_free_displaysurface(vga->ds);
qxl->guest_primary.data = qemu_get_ram_ptr(qxl->vga.vram_offset);
if (qxl->guest_primary.stride < 0) {
/* spice surface is upside down -> need extra buffer to flip */
qxl->guest_primary.stride = -qxl->guest_primary.stride;
qxl->guest_primary.flipped = qemu_malloc(qxl->guest_primary.surface.width *
qxl->guest_primary.stride);
ptr = qxl->guest_primary.flipped;
} else {
ptr = qxl->guest_primary.data;
}
dprint(qxl, 1, "%s: %dx%d, stride %d, bpp %d, depth %d, flip %s\n",
__FUNCTION__,
qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.stride,
qxl->guest_primary.bytes_pp,
qxl->guest_primary.bits_pp,
qxl->guest_primary.flipped ? "yes" : "no");
vga->ds->surface =
qemu_create_displaysurface_from(qxl->guest_primary.surface.width,
qxl->guest_primary.surface.height,
qxl->guest_primary.bits_pp,
qxl->guest_primary.stride,
ptr);
dpy_resize(vga->ds);
}
if (!qxl->guest_primary.commands) {
return;
}
qxl->guest_primary.commands = 0;
update.left = 0;
update.right = qxl->guest_primary.surface.width;
update.top = 0;
update.bottom = qxl->guest_primary.surface.height;
memset(dirty, 0, sizeof(dirty));
qxl->ssd.worker->update_area(qxl->ssd.worker, 0, &update,
dirty, ARRAY_SIZE(dirty), 1);
for (i = 0; i < ARRAY_SIZE(dirty); i++) {
if (qemu_spice_rect_is_empty(dirty+i)) {
break;
}
if (qxl->guest_primary.flipped) {
qxl_flip(qxl, dirty+i);
}
dpy_update(vga->ds,
dirty[i].left, dirty[i].top,
dirty[i].right - dirty[i].left,
dirty[i].bottom - dirty[i].top);
}
}
static QEMUCursor *qxl_cursor(PCIQXLDevice *qxl, QXLCursor *cursor)
{
QEMUCursor *c;
uint8_t *image, *mask;
int size;
c = cursor_alloc(cursor->header.width, cursor->header.height);
c->hot_x = cursor->header.hot_spot_x;
c->hot_y = cursor->header.hot_spot_y;
switch (cursor->header.type) {
case SPICE_CURSOR_TYPE_ALPHA:
size = cursor->header.width * cursor->header.height * sizeof(uint32_t);
memcpy(c->data, cursor->chunk.data, size);
if (qxl->debug > 2) {
cursor_print_ascii_art(c, "qxl/alpha");
}
break;
case SPICE_CURSOR_TYPE_MONO:
mask = cursor->chunk.data;
image = mask + cursor_get_mono_bpl(c) * c->width;
cursor_set_mono(c, 0xffffff, 0x000000, image, 1, mask);
if (qxl->debug > 2) {
cursor_print_ascii_art(c, "qxl/mono");
}
break;
default:
fprintf(stderr, "%s: not implemented: type %d\n",
__FUNCTION__, cursor->header.type);
goto fail;
}
return c;
fail:
cursor_put(c);
return NULL;
}
/* called from spice server thread context only */
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext)
{
QXLCursorCmd *cmd = qxl_phys2virt(qxl, ext->cmd.data, ext->group_id);
QXLCursor *cursor;
QEMUCursor *c;
int x = -1, y = -1;
if (!qxl->ssd.ds->mouse_set || !qxl->ssd.ds->cursor_define) {
return;
}
if (qxl->debug > 1 && cmd->type != QXL_CURSOR_MOVE) {
fprintf(stderr, "%s", __FUNCTION__);
qxl_log_cmd_cursor(qxl, cmd, ext->group_id);
fprintf(stderr, "\n");
}
switch (cmd->type) {
case QXL_CURSOR_SET:
x = cmd->u.set.position.x;
y = cmd->u.set.position.y;
cursor = qxl_phys2virt(qxl, cmd->u.set.shape, ext->group_id);
if (cursor->chunk.data_size != cursor->data_size) {
fprintf(stderr, "%s: multiple chunks\n", __FUNCTION__);
return;
}
c = qxl_cursor(qxl, cursor);
if (c == NULL) {
c = cursor_builtin_left_ptr();
}
qemu_mutex_lock_iothread();
qxl->ssd.ds->cursor_define(c);
qxl->ssd.ds->mouse_set(x, y, 1);
qemu_mutex_unlock_iothread();
cursor_put(c);
break;
case QXL_CURSOR_MOVE:
x = cmd->u.position.x;
y = cmd->u.position.y;
qemu_mutex_lock_iothread();
qxl->ssd.ds->mouse_set(x, y, 1);
qemu_mutex_unlock_iothread();
break;
}
}

1587
hw/qxl.c Normal file

File diff suppressed because it is too large Load Diff

112
hw/qxl.h Normal file
View File

@ -0,0 +1,112 @@
#include "qemu-common.h"
#include "console.h"
#include "hw.h"
#include "pci.h"
#include "vga_int.h"
#include "ui/qemu-spice.h"
#include "ui/spice-display.h"
enum qxl_mode {
QXL_MODE_UNDEFINED,
QXL_MODE_VGA,
QXL_MODE_COMPAT, /* spice 0.4.x */
QXL_MODE_NATIVE,
};
typedef struct PCIQXLDevice {
PCIDevice pci;
SimpleSpiceDisplay ssd;
int id;
uint32_t debug;
uint32_t guestdebug;
uint32_t cmdlog;
enum qxl_mode mode;
uint32_t cmdflags;
int generation;
uint32_t revision;
int32_t num_memslots;
int32_t num_surfaces;
struct guest_slots {
QXLMemSlot slot;
void *ptr;
uint64_t size;
uint64_t delta;
uint32_t active;
} guest_slots[NUM_MEMSLOTS];
struct guest_primary {
QXLSurfaceCreate surface;
uint32_t commands;
uint32_t resized;
int32_t stride;
uint32_t bits_pp;
uint32_t bytes_pp;
uint8_t *data, *flipped;
} guest_primary;
struct surfaces {
QXLPHYSICAL cmds[NUM_SURFACES];
uint32_t count;
uint32_t max;
} guest_surfaces;
QXLPHYSICAL guest_cursor;
/* thread signaling */
pthread_t main;
int pipe[2];
/* ram pci bar */
QXLRam *ram;
VGACommonState vga;
uint32_t num_free_res;
QXLReleaseInfo *last_release;
uint32_t last_release_offset;
uint32_t oom_running;
/* rom pci bar */
QXLRom shadow_rom;
QXLRom *rom;
QXLModes *modes;
uint32_t rom_size;
uint64_t rom_offset;
/* vram pci bar */
uint32_t vram_size;
uint64_t vram_offset;
/* io bar */
uint32_t io_base;
/* spice 0.4 loadvm compatibility */
void *worker_data;
uint32_t worker_data_size;
} PCIQXLDevice;
#define PANIC_ON(x) if ((x)) { \
printf("%s: PANIC %s failed\n", __FUNCTION__, #x); \
exit(-1); \
}
#define dprint(_qxl, _level, _fmt, ...) \
do { \
if (_qxl->debug >= _level) { \
fprintf(stderr, "qxl-%d: ", _qxl->id); \
fprintf(stderr, _fmt, ## __VA_ARGS__); \
} \
} while (0)
/* qxl.c */
void *qxl_phys2virt(PCIQXLDevice *qxl, QXLPHYSICAL phys, int group_id);
/* qxl-logger.c */
void qxl_log_cmd_cursor(PCIQXLDevice *qxl, QXLCursorCmd *cmd, int group_id);
void qxl_log_command(PCIQXLDevice *qxl, const char *ring, QXLCommandExt *ext);
/* qxl-render.c */
void qxl_render_resize(PCIQXLDevice *qxl);
void qxl_render_update(PCIQXLDevice *qxl);
void qxl_render_cursor(PCIQXLDevice *qxl, QXLCommandExt *ext);

View File

@ -17,6 +17,8 @@
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "virtio-net.h"
#define VIRTIO_DEV_OFFS_TYPE 0 /* 8 bits */
#define VIRTIO_DEV_OFFS_NUM_VQ 1 /* 8 bits */
#define VIRTIO_DEV_OFFS_FEATURE_LEN 2 /* 8 bits */

View File

@ -19,6 +19,7 @@
#include "hw.h"
#include "block.h"
#include "blockdev.h"
#include "sysemu.h"
#include "net.h"
#include "boards.h"

View File

@ -670,6 +670,8 @@ static void sh7750_mmct_writel(void *opaque, target_phys_addr_t addr,
/* do nothing */
break;
case MM_ITLB_ADDR:
cpu_sh4_write_mmaped_itlb_addr(s->cpu, addr, mem_value);
break;
case MM_ITLB_DATA:
/* XXXXX */
abort();

View File

@ -44,7 +44,7 @@
/* We need the mask, because one instance of the device is not page
aligned (ledma, start address 0x0010) */
#define DMA_MASK (DMA_SIZE - 1)
/* ledma has more than 4 registers, Solaris reads the 5th one */
/* OBP says 0x20 bytes for ledma, the extras are aliased to espdma */
#define DMA_ETH_SIZE (8 * sizeof(uint32_t))
#define DMA_MAX_REG_OFFSET (2 * DMA_SIZE - 1)
@ -170,7 +170,10 @@ static uint32_t dma_mem_readl(void *opaque, target_phys_addr_t addr)
uint32_t saddr;
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
return 0; /* extra mystery register(s) */
/* aliased to espdma, but we can't get there from here */
/* buggy driver if using undocumented behavior, just return 0 */
trace_sparc32_dma_mem_readl(addr, 0);
return 0;
}
saddr = (addr & DMA_MASK) >> 2;
trace_sparc32_dma_mem_readl(addr, s->dmaregs[saddr]);
@ -183,7 +186,9 @@ static void dma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
uint32_t saddr;
if (s->is_ledma && (addr > DMA_MAX_REG_OFFSET)) {
return; /* extra mystery register(s) */
/* aliased to espdma, but we can't get there from here */
trace_sparc32_dma_mem_writel(addr, 0, val);
return;
}
saddr = (addr & DMA_MASK) >> 2;
trace_sparc32_dma_mem_writel(addr, s->dmaregs[saddr], val);

View File

@ -2073,14 +2073,14 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
if (full_update) {
for (i = 0; i < size; src ++, dst ++, i ++)
console_write_ch(dst, VMEM2CHTYPE(*src));
console_write_ch(dst, VMEM2CHTYPE(le32_to_cpu(*src)));
dpy_update(s->ds, 0, 0, width, height);
} else {
c_max = 0;
for (i = 0; i < size; src ++, dst ++, i ++) {
console_write_ch(&val, VMEM2CHTYPE(*src));
console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
if (*dst != val) {
*dst = val;
c_max = i;
@ -2089,7 +2089,7 @@ static void vga_update_text(void *opaque, console_ch_t *chardata)
}
c_min = i;
for (; i < size; src ++, dst ++, i ++) {
console_write_ch(&val, VMEM2CHTYPE(*src));
console_write_ch(&val, VMEM2CHTYPE(le32_to_cpu(*src)));
if (*dst != val) {
*dst = val;
c_max = i;

View File

@ -106,7 +106,7 @@ typedef void (* vga_update_retrace_info_fn)(struct VGACommonState *s);
typedef struct VGACommonState {
uint8_t *vram_ptr;
ram_addr_t vram_offset;
unsigned int vram_size;
uint32_t vram_size;
uint32_t lfb_addr;
uint32_t lfb_end;
uint32_t map_addr;

View File

@ -53,7 +53,7 @@ static void ib700_write_enable_reg(void *vp, uint32_t addr, uint32_t data)
30, 28, 26, 24, 22, 20, 18, 16,
14, 12, 10, 8, 6, 4, 2, 0
};
int64 timeout;
int64_t timeout;
ib700_debug("addr = %x, data = %x\n", addr, data);

View File

@ -199,21 +199,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
{
case typeSingle:
//printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fn].fSingle))
if (float32_is_any_nan(fpa11->fpreg[Fn].fSingle))
goto unordered;
rFn = float32_to_floatx80(fpa11->fpreg[Fn].fSingle, &fpa11->fp_status);
break;
case typeDouble:
//printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fn].fDouble))
if (float64_is_any_nan(fpa11->fpreg[Fn].fDouble))
goto unordered;
rFn = float64_to_floatx80(fpa11->fpreg[Fn].fDouble, &fpa11->fp_status);
break;
case typeExtended:
//printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fn].fExtended))
if (floatx80_is_any_nan(fpa11->fpreg[Fn].fExtended))
goto unordered;
rFn = fpa11->fpreg[Fn].fExtended;
break;
@ -225,7 +225,7 @@ static unsigned int PerformComparison(const unsigned int opcode)
{
//printk("Fm is a constant: #%d.\n",Fm);
rFm = getExtendedConstant(Fm);
if (floatx80_is_nan(rFm))
if (floatx80_is_any_nan(rFm))
goto unordered;
}
else
@ -235,21 +235,21 @@ static unsigned int PerformComparison(const unsigned int opcode)
{
case typeSingle:
//printk("single.\n");
if (float32_is_nan(fpa11->fpreg[Fm].fSingle))
if (float32_is_any_nan(fpa11->fpreg[Fm].fSingle))
goto unordered;
rFm = float32_to_floatx80(fpa11->fpreg[Fm].fSingle, &fpa11->fp_status);
break;
case typeDouble:
//printk("double.\n");
if (float64_is_nan(fpa11->fpreg[Fm].fDouble))
if (float64_is_any_nan(fpa11->fpreg[Fm].fDouble))
goto unordered;
rFm = float64_to_floatx80(fpa11->fpreg[Fm].fDouble, &fpa11->fp_status);
break;
case typeExtended:
//printk("extended.\n");
if (floatx80_is_nan(fpa11->fpreg[Fm].fExtended))
if (floatx80_is_any_nan(fpa11->fpreg[Fm].fExtended))
goto unordered;
rFm = fpa11->fpreg[Fm].fExtended;
break;

View File

@ -76,6 +76,10 @@
#ifdef FIGETBSZ
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
#endif
#ifdef FS_IOC_FIEMAP
IOCTL_SPECIAL(FS_IOC_FIEMAP, IOC_W | IOC_R, do_ioctl_fs_ioc_fiemap,
MK_PTR(MK_STRUCT(STRUCT_fiemap)))
#endif
IOCTL(SIOCATMARK, 0, TYPE_NULL)
IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))

View File

@ -174,8 +174,6 @@ int loader_exec(const char * filename, char ** argv, char ** envp,
retval = prepare_binprm(bprm);
infop->host_argv = argv;
if(retval>=0) {
if (bprm->buf[0] == 0x7f
&& bprm->buf[1] == 'E'

View File

@ -50,7 +50,6 @@ struct image_info {
abi_ulong saved_auxv;
abi_ulong arg_start;
abi_ulong arg_end;
char **host_argv;
int personality;
};

View File

@ -1518,3 +1518,9 @@
#ifdef TARGET_NR_utimensat
{ TARGET_NR_utimensat, "utimensat", NULL, print_utimensat, NULL },
#endif
#ifdef TARGET_NR_sync_file_range
{ TARGET_NR_sync_file_range, "sync_file_range", NULL, NULL, NULL },
#endif
#ifdef TARGET_NR_sync_file_range2
{ TARGET_NR_sync_file_range2, "sync_file_range2", NULL, NULL, NULL },
#endif

View File

@ -83,6 +83,7 @@ int __clone2(int (*fn)(void *), void *child_stack_base,
#include <linux/kd.h>
#include <linux/mtio.h>
#include <linux/fs.h>
#include <linux/fiemap.h>
#include <linux/fb.h>
#include <linux/vt.h>
#include "linux_loop.h"
@ -2965,13 +2966,19 @@ enum {
#undef STRUCT
#undef STRUCT_SPECIAL
typedef struct IOCTLEntry {
typedef struct IOCTLEntry IOCTLEntry;
typedef abi_long do_ioctl_fn(const IOCTLEntry *ie, uint8_t *buf_temp,
int fd, abi_long cmd, abi_long arg);
struct IOCTLEntry {
unsigned int target_cmd;
unsigned int host_cmd;
const char *name;
int access;
do_ioctl_fn *do_ioctl;
const argtype arg_type[5];
} IOCTLEntry;
};
#define IOC_R 0x0001
#define IOC_W 0x0002
@ -2979,9 +2986,98 @@ typedef struct IOCTLEntry {
#define MAX_STRUCT_SIZE 4096
/* So fiemap access checks don't overflow on 32 bit systems.
* This is very slightly smaller than the limit imposed by
* the underlying kernel.
*/
#define FIEMAP_MAX_EXTENTS ((UINT_MAX - sizeof(struct fiemap)) \
/ sizeof(struct fiemap_extent))
static abi_long do_ioctl_fs_ioc_fiemap(const IOCTLEntry *ie, uint8_t *buf_temp,
int fd, abi_long cmd, abi_long arg)
{
/* The parameter for this ioctl is a struct fiemap followed
* by an array of struct fiemap_extent whose size is set
* in fiemap->fm_extent_count. The array is filled in by the
* ioctl.
*/
int target_size_in, target_size_out;
struct fiemap *fm;
const argtype *arg_type = ie->arg_type;
const argtype extent_arg_type[] = { MK_STRUCT(STRUCT_fiemap_extent) };
void *argptr, *p;
abi_long ret;
int i, extent_size = thunk_type_size(extent_arg_type, 0);
uint32_t outbufsz;
int free_fm = 0;
assert(arg_type[0] == TYPE_PTR);
assert(ie->access == IOC_RW);
arg_type++;
target_size_in = thunk_type_size(arg_type, 0);
argptr = lock_user(VERIFY_READ, arg, target_size_in, 1);
if (!argptr) {
return -TARGET_EFAULT;
}
thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST);
unlock_user(argptr, arg, 0);
fm = (struct fiemap *)buf_temp;
if (fm->fm_extent_count > FIEMAP_MAX_EXTENTS) {
return -TARGET_EINVAL;
}
outbufsz = sizeof (*fm) +
(sizeof(struct fiemap_extent) * fm->fm_extent_count);
if (outbufsz > MAX_STRUCT_SIZE) {
/* We can't fit all the extents into the fixed size buffer.
* Allocate one that is large enough and use it instead.
*/
fm = malloc(outbufsz);
if (!fm) {
return -TARGET_ENOMEM;
}
memcpy(fm, buf_temp, sizeof(struct fiemap));
free_fm = 1;
}
ret = get_errno(ioctl(fd, ie->host_cmd, fm));
if (!is_error(ret)) {
target_size_out = target_size_in;
/* An extent_count of 0 means we were only counting the extents
* so there are no structs to copy
*/
if (fm->fm_extent_count != 0) {
target_size_out += fm->fm_mapped_extents * extent_size;
}
argptr = lock_user(VERIFY_WRITE, arg, target_size_out, 0);
if (!argptr) {
ret = -TARGET_EFAULT;
} else {
/* Convert the struct fiemap */
thunk_convert(argptr, fm, arg_type, THUNK_TARGET);
if (fm->fm_extent_count != 0) {
p = argptr + target_size_in;
/* ...and then all the struct fiemap_extents */
for (i = 0; i < fm->fm_mapped_extents; i++) {
thunk_convert(p, &fm->fm_extents[i], extent_arg_type,
THUNK_TARGET);
p += extent_size;
}
}
unlock_user(argptr, arg, target_size_out);
}
}
if (free_fm) {
free(fm);
}
return ret;
}
static IOCTLEntry ioctl_entries[] = {
#define IOCTL(cmd, access, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, { __VA_ARGS__ } },
{ TARGET_ ## cmd, cmd, #cmd, access, 0, { __VA_ARGS__ } },
#define IOCTL_SPECIAL(cmd, access, dofn, ...) \
{ TARGET_ ## cmd, cmd, #cmd, access, dofn, { __VA_ARGS__ } },
#include "ioctls.h"
{ 0, 0, },
};
@ -3011,6 +3107,10 @@ static abi_long do_ioctl(int fd, abi_long cmd, abi_long arg)
#if defined(DEBUG)
gemu_log("ioctl: cmd=0x%04lx (%s)\n", (long)cmd, ie->name);
#endif
if (ie->do_ioctl) {
return ie->do_ioctl(ie, buf_temp, fd, cmd, arg);
}
switch(arg_type[0]) {
case TYPE_NULL:
/* no argument */
@ -7364,6 +7464,29 @@ abi_long do_syscall(void *cpu_env, int num, abi_long arg1,
case TARGET_NR_fallocate:
ret = get_errno(fallocate(arg1, arg2, arg3, arg4));
break;
#endif
#if defined(CONFIG_SYNC_FILE_RANGE)
#if defined(TARGET_NR_sync_file_range)
case TARGET_NR_sync_file_range:
#if TARGET_ABI_BITS == 32
ret = get_errno(sync_file_range(arg1, target_offset64(arg2, arg3),
target_offset64(arg4, arg5), arg6));
#else
ret = get_errno(sync_file_range(arg1, arg2, arg3, arg4));
#endif
break;
#endif
#if defined(TARGET_NR_sync_file_range2)
case TARGET_NR_sync_file_range2:
/* This is like sync_file_range but the arguments are reordered */
#if TARGET_ABI_BITS == 32
ret = get_errno(sync_file_range(arg1, target_offset64(arg3, arg4),
target_offset64(arg5, arg6), arg2));
#else
ret = get_errno(sync_file_range(arg1, arg3, arg4, arg2));
#endif
break;
#endif
#endif
default:
unimplemented:

View File

@ -783,6 +783,7 @@ struct target_pollfd {
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
#define TARGET_FS_IOC_FIEMAP TARGET_IOWR('f',11,struct fiemap)
/* cdrom commands */
#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */

View File

@ -165,3 +165,19 @@ STRUCT(vt_stat,
TYPE_SHORT, /* v_active */
TYPE_SHORT, /* v_signal */
TYPE_SHORT) /* v_state */
STRUCT(fiemap_extent,
TYPE_ULONGLONG, /* fe_logical */
TYPE_ULONGLONG, /* fe_physical */
TYPE_ULONGLONG, /* fe_length */
MK_ARRAY(TYPE_ULONGLONG, 2), /* fe_reserved64[2] */
TYPE_INT, /* fe_flags */
MK_ARRAY(TYPE_INT, 3)) /* fe_reserved[3] */
STRUCT(fiemap,
TYPE_ULONGLONG, /* fm_start */
TYPE_ULONGLONG, /* fm_length */
TYPE_INT, /* fm_flags */
TYPE_INT, /* fm_mapped_extents */
TYPE_INT, /* fm_extent_count */
TYPE_INT) /* fm_reserved */

141
monitor.c
View File

@ -34,6 +34,7 @@
#include "net.h"
#include "net/slirp.h"
#include "qemu-char.h"
#include "ui/qemu-spice.h"
#include "sysemu.h"
#include "monitor.h"
#include "readline.h"
@ -59,6 +60,7 @@
#ifdef CONFIG_SIMPLE_TRACE
#include "trace.h"
#endif
#include "ui/qemu-spice.h"
//#define DEBUG
//#define DEBUG_COMPLETION
@ -457,6 +459,15 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
case QEVENT_WATCHDOG:
event_name = "WATCHDOG";
break;
case QEVENT_SPICE_CONNECTED:
event_name = "SPICE_CONNECTED";
break;
case QEVENT_SPICE_INITIALIZED:
event_name = "SPICE_INITIALIZED";
break;
case QEVENT_SPICE_DISCONNECTED:
event_name = "SPICE_DISCONNECTED";
break;
default:
abort();
break;
@ -1063,6 +1074,105 @@ static int do_change(Monitor *mon, const QDict *qdict, QObject **ret_data)
return ret;
}
static int set_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *protocol = qdict_get_str(qdict, "protocol");
const char *password = qdict_get_str(qdict, "password");
const char *connected = qdict_get_try_str(qdict, "connected");
int disconnect_if_connected = 0;
int fail_if_connected = 0;
int rc;
if (connected) {
if (strcmp(connected, "fail") == 0) {
fail_if_connected = 1;
} else if (strcmp(connected, "disconnect") == 0) {
disconnect_if_connected = 1;
} else if (strcmp(connected, "keep") == 0) {
/* nothing */
} else {
qerror_report(QERR_INVALID_PARAMETER, "connected");
return -1;
}
}
if (strcmp(protocol, "spice") == 0) {
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
rc = qemu_spice_set_passwd(password, fail_if_connected,
disconnect_if_connected);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
if (strcmp(protocol, "vnc") == 0) {
if (fail_if_connected || disconnect_if_connected) {
/* vnc supports "connected=keep" only */
qerror_report(QERR_INVALID_PARAMETER, "connected");
return -1;
}
rc = vnc_display_password(NULL, password);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
qerror_report(QERR_INVALID_PARAMETER, "protocol");
return -1;
}
static int expire_password(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
const char *protocol = qdict_get_str(qdict, "protocol");
const char *whenstr = qdict_get_str(qdict, "time");
time_t when;
int rc;
if (strcmp(whenstr, "now")) {
when = 0;
} else if (strcmp(whenstr, "never")) {
when = TIME_MAX;
} else if (whenstr[0] == '+') {
when = time(NULL) + strtoull(whenstr+1, NULL, 10);
} else {
when = strtoull(whenstr, NULL, 10);
}
if (strcmp(protocol, "spice") == 0) {
if (!using_spice) {
/* correct one? spice isn't a device ,,, */
qerror_report(QERR_DEVICE_NOT_ACTIVE, "spice");
return -1;
}
rc = qemu_spice_set_pw_expire(when);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
if (strcmp(protocol, "vnc") == 0) {
rc = vnc_display_pw_expire(NULL, when);
if (rc != 0) {
qerror_report(QERR_SET_PASSWD_FAILED);
return -1;
}
return 0;
}
qerror_report(QERR_INVALID_PARAMETER, "protocol");
return -1;
}
static int do_screen_dump(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
vga_hw_screen_dump(qdict_get_str(qdict, "filename"));
@ -2272,6 +2382,15 @@ static void tlb_info(Monitor *mon)
#endif
#if defined(TARGET_SPARC)
static void tlb_info(Monitor *mon)
{
CPUState *env1 = mon_get_cpu();
dump_mmu((FILE*)mon, (fprintf_function)monitor_printf, env1);
}
#endif
static void do_info_kvm_print(Monitor *mon, const QObject *data)
{
QDict *qdict;
@ -2744,7 +2863,7 @@ static const mon_cmd_t info_cmds[] = {
.user_print = do_pci_info_print,
.mhandler.info_new = do_pci_info,
},
#if defined(TARGET_I386) || defined(TARGET_SH4)
#if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC)
{
.name = "tlb",
.args_type = "",
@ -2850,6 +2969,16 @@ static const mon_cmd_t info_cmds[] = {
.user_print = do_info_vnc_print,
.mhandler.info_new = do_info_vnc,
},
#if defined(CONFIG_SPICE)
{
.name = "spice",
.args_type = "",
.params = "",
.help = "show the spice server status",
.user_print = do_info_spice_print,
.mhandler.info_new = do_info_spice,
},
#endif
{
.name = "name",
.args_type = "",
@ -3037,6 +3166,16 @@ static const mon_cmd_t qmp_query_cmds[] = {
.user_print = do_info_vnc_print,
.mhandler.info_new = do_info_vnc,
},
#if defined(CONFIG_SPICE)
{
.name = "spice",
.args_type = "",
.params = "",
.help = "show the spice server status",
.user_print = do_info_spice_print,
.mhandler.info_new = do_info_spice,
},
#endif
{
.name = "name",
.args_type = "",

View File

@ -32,6 +32,9 @@ typedef enum MonitorEvent {
QEVENT_BLOCK_IO_ERROR,
QEVENT_RTC_CHANGE,
QEVENT_WATCHDOG,
QEVENT_SPICE_CONNECTED,
QEVENT_SPICE_INITIALIZED,
QEVENT_SPICE_DISCONNECTED,
QEVENT_MAX,
} MonitorEvent;

View File

@ -43,8 +43,8 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
char *dev;
struct stat s;
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
/* if no ifname is given, always start the search from tap0. */
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__)
/* if no ifname is given, always start the search from tap0/tun0. */
int i;
char dname[100];
@ -52,7 +52,11 @@ int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required
if (*ifname) {
snprintf(dname, sizeof dname, "/dev/%s", ifname);
} else {
#if defined(__OpenBSD__)
snprintf(dname, sizeof dname, "/dev/tun%d", i);
#else
snprintf(dname, sizeof dname, "/dev/tap%d", i);
#endif
}
TFR(fd = open(dname, O_RDWR));
if (fd >= 0) {

BIN
pc-bios/vgabios-qxl.bin Normal file

Binary file not shown.

View File

@ -50,6 +50,9 @@ typedef struct DeviceState DeviceState;
#if !defined(ENOTSUP)
#define ENOTSUP 4096
#endif
#ifndef TIME_MAX
#define TIME_MAX LONG_MAX
#endif
#ifndef CONFIG_IOVEC
#define CONFIG_IOVEC

View File

@ -162,6 +162,7 @@ TODO (no longer available)
* pcsys_monitor:: QEMU Monitor
* disk_images:: Disk Images
* pcsys_network:: Network emulation
* pcsys_other_devs:: Other Devices
* direct_linux_boot:: Direct Linux Boot
* pcsys_usb:: USB emulation
* vnc_security:: VNC security
@ -202,7 +203,7 @@ Intel 82801AA AC97 Audio compatible sound card
@item
Intel HD Audio Controller and HDA codec
@item
Adlib(OPL2) - Yamaha YM3812 compatible chip
Adlib (OPL2) - Yamaha YM3812 compatible chip
@item
Gravis Ultrasound GF1 sound card
@item
@ -222,7 +223,7 @@ VGA BIOS.
QEMU uses YM3812 emulation by Tatsuyuki Satoh.
QEMU uses GUS emulation(GUSEMU32 @url{http://www.deinmeister.de/gusemu/})
QEMU uses GUS emulation (GUSEMU32 @url{http://www.deinmeister.de/gusemu/})
by Tibor "TS" Schütz.
Not that, by default, GUS shares IRQ(7) with parallel ports and so
@ -715,6 +716,7 @@ Using the @option{-net socket} option, it is possible to make VLANs
that span several QEMU instances. See @ref{sec_invocation} to have a
basic example.
@node pcsys_other_devs
@section Other Devices
@subsection Inter-VM Shared Memory device
@ -832,7 +834,7 @@ Standard USB keyboard. Will override the PS/2 keyboard (if present).
Serial converter. This emulates an FTDI FT232BM chip connected to host character
device @var{dev}. The available character devices are the same as for the
@code{-serial} option. The @code{vendorid} and @code{productid} options can be
used to override the default 0403:6001. For instance,
used to override the default 0403:6001. For instance,
@example
usb_add serial:productid=FA00:tcp:192.168.0.2:4444
@end example
@ -1047,7 +1049,7 @@ qemu [...OPTIONS...] -vnc :1,tls,x509,sasl -monitor stdio
The GNU TLS packages provides a command called @code{certtool} which can
be used to generate certificates and keys in PEM format. At a minimum it
is neccessary to setup a certificate authority, and issue certificates to
is necessary to setup a certificate authority, and issue certificates to
each server. If using certificates for authentication, then each client
will also need to be issued a certificate. The recommendation is for the
server to keep its certificates in either @code{/etc/pki/qemu} or for
@ -1190,7 +1192,7 @@ keytab: /etc/qemu/krb5.tab
For this to work the administrator of your KDC must generate a Kerberos
principal for the server, with a name of 'qemu/somehost.example.com@@EXAMPLE.COM'
replacing 'somehost.example.com' with the fully qualified host name of the
machine running QEMU, and 'EXAMPLE.COM' with the Keberos Realm.
machine running QEMU, and 'EXAMPLE.COM' with the Kerberos Realm.
Other configurations will be left as an exercise for the reader. It should
be noted that only Digest-MD5 and GSSAPI provides a SSF layer for data
@ -1772,7 +1774,7 @@ enabled in the kernel, and expect 512M RAM. Kernels for The PBX-A9 board
should have CONFIG_SPARSEMEM enabled, CONFIG_REALVIEW_HIGH_PHYS_OFFSET
disabled and expect 1024M RAM.
The following devices are emuilated:
The following devices are emulated:
@itemize @minus
@item
@ -1872,7 +1874,7 @@ Secure Digital card connected to OMAP MMC/SD host
@item
Three OMAP on-chip UARTs and on-chip STI debugging console
@item
A Bluetooth(R) transciever and HCI connected to an UART
A Bluetooth(R) transceiver and HCI connected to an UART
@item
Mentor Graphics "Inventra" dual-role USB controller embedded in a TI
TUSB6010 chip - only USB host mode is supported
@ -1934,7 +1936,7 @@ MV88W8618 audio controller, WM8750 CODEC and mixer
@end itemize
The Siemens SX1 models v1 and v2 (default) basic emulation.
The emulaton includes the following elements:
The emulation includes the following elements:
@itemize @minus
@item
@ -2190,7 +2192,7 @@ Set the x86 stack size in bytes (default=524288)
Select CPU model (-cpu ? for list and additional feature selection)
@item -ignore-environment
Start with an empty environment. Without this option,
the inital environment is a copy of the caller's environment.
the initial environment is a copy of the caller's environment.
@item -E @var{var}=@var{value}
Set environment @var{var} to @var{value}.
@item -U @var{var}
@ -2201,7 +2203,7 @@ the address region required by guest applications is reserved on the host.
This option is currently only supported on some hosts.
@item -R size
Pre-allocate a guest virtual address space of the given size (in bytes).
"G", "M", and "k" suffixes may be used when specifying the size.
"G", "M", and "k" suffixes may be used when specifying the size.
@end table
Debug options:
@ -2420,7 +2422,7 @@ Set the library root path (default=/)
Set the stack size in bytes (default=524288)
@item -ignore-environment
Start with an empty environment. Without this option,
the inital environment is a copy of the caller's environment.
the initial environment is a copy of the caller's environment.
@item -E @var{var}=@var{value}
Set environment @var{var} to @var{value}.
@item -U @var{var}
@ -2493,7 +2495,7 @@ correct SDL directory when invoked.
@item Install the MinGW version of zlib and make sure
@file{zlib.h} and @file{libz.dll.a} are in
MingGW's default header and linker search paths.
MinGW's default header and linker search paths.
@item Extract the current version of QEMU.
@ -2528,7 +2530,7 @@ the QEMU configuration script.
@item Install the MinGW version of zlib and make sure
@file{zlib.h} and @file{libz.dll.a} are in
MingGW's default header and linker search paths.
MinGW's default header and linker search paths.
@item
Configure QEMU for Windows cross compilation:
@ -2537,7 +2539,7 @@ PATH=/usr/i686-pc-mingw32/sys-root/mingw/bin:$PATH ./configure --cross-prefix='i
@end example
The example assumes @file{sdl-config} is installed under @file{/usr/i686-pc-mingw32/sys-root/mingw/bin} and
MinGW cross compilation tools have names like @file{i686-pc-mingw32-gcc} and @file{i686-pc-mingw32-strip}.
We set the @code{PATH} environment variable to ensure the MingW version of @file{sdl-config} is used and
We set the @code{PATH} environment variable to ensure the MinGW version of @file{sdl-config} is used and
use --cross-prefix to specify the name of the cross compiler.
You can also use --prefix to set the Win32 install path which defaults to @file{c:/Program Files/Qemu}.

View File

@ -751,7 +751,7 @@ Rotate graphical output 90 deg left (only PXA LCD).
ETEXI
DEF("vga", HAS_ARG, QEMU_OPTION_vga,
"-vga [std|cirrus|vmware|xenfb|none]\n"
"-vga [std|cirrus|vmware|qxl|xenfb|none]\n"
" select video card type\n", QEMU_ARCH_ALL)
STEXI
@item -vga @var{type}
@ -772,6 +772,10 @@ this option.
VMWare SVGA-II compatible adapter. Use it if you have sufficiently
recent XFree86/XOrg server or Windows guest with a driver for this
card.
@item qxl
QXL paravirtual graphic card. It is VGA compatible (including VESA
2.0 VBE support). Works best with qxl guest drivers installed though.
Recommended choice when using the spice protocol.
@item none
Disable VGA card.
@end table

View File

@ -516,7 +516,7 @@ timers, especially together with the use of bottom halves (BHs).
@section Hardware interrupts
In order to be faster, QEMU does not check at every basic block if an
hardware interrupt is pending. Instead, the user must asynchrously
hardware interrupt is pending. Instead, the user must asynchronously
call a specific function to tell that an interrupt is pending. This
function resets the chaining of the currently executing basic
block. It ensures that the execution will return soon in the main loop
@ -548,7 +548,7 @@ Linux kernel does. The @code{sigreturn()} system call is emulated to return
from the virtual signal handler.
Some signals (such as SIGALRM) directly come from the host. Other
signals are synthetized from the virtual CPU exceptions such as SIGFPE
signals are synthesized from the virtual CPU exceptions such as SIGFPE
when a division by zero is done (see @code{main.c:cpu_loop()}).
The blocked signal mask is still handled by the host Linux kernel so

View File

@ -50,7 +50,8 @@ static void __attribute__((constructor)) init_get_clock(void)
{
use_rt_clock = 0;
#if defined(__linux__) || (defined(__FreeBSD__) && __FreeBSD_version >= 500000) \
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__)
|| defined(__DragonFly__) || defined(__FreeBSD_kernel__) \
|| defined(__OpenBSD__)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {

View File

@ -510,7 +510,7 @@ Set maximum speed for migrations.
Arguments:
- "value": maximum speed, in bytes per second (json-number)
- "value": maximum speed, in bytes per second (json-int)
Example:
@ -735,6 +735,63 @@ Example:
"password": "12345" } }
<- { "return": {} }
EQMP
{
.name = "set_password",
.args_type = "protocol:s,password:s,connected:s?",
.params = "protocol password action-if-connected",
.help = "set spice/vnc password",
.user_print = monitor_user_noop,
.mhandler.cmd_new = set_password,
},
SQMP
set_password
------------
Set the password for vnc/spice protocols.
Arguments:
- "protocol": protocol name (json-string)
- "password": password (json-string)
- "connected": [ keep | disconnect | fail ] (josn-string, optional)
Example:
-> { "execute": "set_password", "arguments": { "protocol": "vnc",
"password": "secret" } }
<- { "return": {} }
EQMP
{
.name = "expire_password",
.args_type = "protocol:s,time:s",
.params = "protocol time",
.help = "set spice/vnc password expire-time",
.user_print = monitor_user_noop,
.mhandler.cmd_new = expire_password,
},
SQMP
expire_password
---------------
Set the password expire time for vnc/spice protocols.
Arguments:
- "protocol": protocol name (json-string)
- "time": [ now | never | +secs | secs ] (json-string)
Example:
-> { "execute": "expire_password", "arguments": { "protocol": "vnc",
"time": "+60" } }
<- { "return": {} }
EQMP
{
@ -1438,6 +1495,76 @@ Example:
EQMP
SQMP
query-spice
-----------
Show SPICE server information.
Return a json-object with server information. Connected clients are returned
as a json-array of json-objects.
The main json-object contains the following:
- "enabled": true or false (json-bool)
- "host": server's IP address (json-string)
- "port": server's port number (json-int, optional)
- "tls-port": server's port number (json-int, optional)
- "auth": authentication method (json-string)
- Possible values: "none", "spice"
- "channels": a json-array of all active channels clients
Channels are described by a json-object, each one contain the following:
- "host": client's IP address (json-string)
- "family": address family (json-string)
- Possible values: "ipv4", "ipv6", "unix", "unknown"
- "port": client's port number (json-string)
- "connection-id": spice connection id. All channels with the same id
belong to the same spice session (json-int)
- "channel-type": channel type. "1" is the main control channel, filter for
this one if you want track spice sessions only (json-int)
- "channel-id": channel id. Usually "0", might be different needed when
multiple channels of the same type exist, such as multiple
display channels in a multihead setup (json-int)
- "tls": whevener the channel is encrypted (json-bool)
Example:
-> { "execute": "query-spice" }
<- {
"return": {
"enabled": true,
"auth": "spice",
"port": 5920,
"tls-port": 5921,
"host": "0.0.0.0",
"channels": [
{
"port": "54924",
"family": "ipv4",
"channel-type": 1,
"connection-id": 1804289383,
"host": "127.0.0.1",
"channel-id": 0,
"tls": true
},
{
"port": "36710",
"family": "ipv4",
"channel-type": 4,
"connection-id": 1804289383,
"host": "127.0.0.1",
"channel-id": 0,
"tls": false
},
[ ... more channels follow ... ]
]
}
}
EQMP
SQMP
query-name
----------

View File

@ -92,13 +92,13 @@ static BOOTPClient *find_addr(Slirp *slirp, struct in_addr *paddr,
}
static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
const struct in_addr **preq_addr)
struct in_addr *preq_addr)
{
const uint8_t *p, *p_end;
int len, tag;
*pmsg_type = 0;
*preq_addr = NULL;
preq_addr->s_addr = htonl(0L);
p = bp->bp_vend;
p_end = p + DHCP_OPT_LEN;
@ -124,8 +124,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
*pmsg_type = p[0];
break;
case RFC2132_REQ_ADDR:
if (len >= 4)
*preq_addr = (struct in_addr *)p;
if (len >= 4) {
memcpy(&(preq_addr->s_addr), p, 4);
}
break;
default:
break;
@ -133,8 +134,9 @@ static void dhcp_decode(const struct bootp_t *bp, int *pmsg_type,
p += len;
}
}
if (*pmsg_type == DHCPREQUEST && !*preq_addr && bp->bp_ciaddr.s_addr) {
*preq_addr = &bp->bp_ciaddr;
if (*pmsg_type == DHCPREQUEST && preq_addr->s_addr == htonl(0L) &&
bp->bp_ciaddr.s_addr) {
memcpy(&(preq_addr->s_addr), &bp->bp_ciaddr, 4);
}
}
@ -144,15 +146,15 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
struct mbuf *m;
struct bootp_t *rbp;
struct sockaddr_in saddr, daddr;
const struct in_addr *preq_addr;
struct in_addr preq_addr;
int dhcp_msg_type, val;
uint8_t *q;
/* extract exact DHCP msg type */
dhcp_decode(bp, &dhcp_msg_type, &preq_addr);
DPRINTF("bootp packet op=%d msgtype=%d", bp->bp_op, dhcp_msg_type);
if (preq_addr)
DPRINTF(" req_addr=%08x\n", ntohl(preq_addr->s_addr));
if (preq_addr.s_addr != htonl(0L))
DPRINTF(" req_addr=%08x\n", ntohl(preq_addr.s_addr));
else
DPRINTF("\n");
@ -175,10 +177,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
memset(rbp, 0, sizeof(struct bootp_t));
if (dhcp_msg_type == DHCPDISCOVER) {
if (preq_addr) {
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
if (preq_addr.s_addr != htonl(0L)) {
bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) {
daddr.sin_addr = *preq_addr;
daddr.sin_addr = preq_addr;
}
}
if (!bc) {
@ -190,10 +192,10 @@ static void bootp_reply(Slirp *slirp, const struct bootp_t *bp)
}
}
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else if (preq_addr) {
bc = request_addr(slirp, preq_addr, slirp->client_ethaddr);
} else if (preq_addr.s_addr != htonl(0L)) {
bc = request_addr(slirp, &preq_addr, slirp->client_ethaddr);
if (bc) {
daddr.sin_addr = *preq_addr;
daddr.sin_addr = preq_addr;
memcpy(bc->macaddr, slirp->client_ethaddr, 6);
} else {
daddr.sin_addr.s_addr = 0;

View File

@ -104,7 +104,7 @@ extern int incoming_expected;
extern int bios_size;
typedef enum {
VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB
VGA_NONE, VGA_STD, VGA_CIRRUS, VGA_VMWARE, VGA_XENFB, VGA_QXL,
} VGAInterfaceType;
extern int vga_interface_type;
@ -112,6 +112,7 @@ extern int vga_interface_type;
#define std_vga_enabled (vga_interface_type == VGA_STD)
#define xenfb_enabled (vga_interface_type == VGA_XENFB)
#define vmsvga_enabled (vga_interface_type == VGA_VMWARE)
#define qxl_enabled (vga_interface_type == VGA_QXL)
extern int graphic_width;
extern int graphic_height;

View File

@ -904,7 +904,7 @@ uint64_t helper_cmptun (uint64_t a, uint64_t b)
fa = t_to_float64(a);
fb = t_to_float64(b);
if (float64_is_nan(fa) || float64_is_nan(fb))
if (float64_is_quiet_nan(fa) || float64_is_quiet_nan(fb))
return 0x4000000000000000ULL;
else
return 0;

View File

@ -76,6 +76,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
memcpy(env->cp15.c0_c1, arm1136_cp15_c0_c1, 8 * sizeof(uint32_t));
memcpy(env->cp15.c0_c2, arm1136_cp15_c0_c2, 8 * sizeof(uint32_t));
env->cp15.c0_cachetype = 0x1dd20d2;
env->cp15.c1_sys = 0x00050078;
break;
case ARM_CPUID_ARM11MPCORE:
set_feature(env, ARM_FEATURE_V6);
@ -109,6 +110,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env->cp15.c0_ccsid[0] = 0xe007e01a; /* 16k L1 dcache. */
env->cp15.c0_ccsid[1] = 0x2007e01a; /* 16k L1 icache. */
env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
env->cp15.c1_sys = 0x00c50078;
break;
case ARM_CPUID_CORTEXA9:
set_feature(env, ARM_FEATURE_V6);
@ -130,6 +132,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
env->cp15.c0_clid = (1 << 27) | (1 << 24) | 3;
env->cp15.c0_ccsid[0] = 0xe00fe015; /* 16k L1 dcache. */
env->cp15.c0_ccsid[1] = 0x200fe015; /* 16k L1 icache. */
env->cp15.c1_sys = 0x00c50078;
break;
case ARM_CPUID_CORTEXM3:
set_feature(env, ARM_FEATURE_V6);
@ -1084,22 +1087,26 @@ static int get_phys_addr_v6(CPUState *env, uint32_t address, int access_type,
}
code = 15;
}
if (xn && access_type == 2)
goto do_fault;
if (domain == 3) {
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
} else {
if (xn && access_type == 2)
goto do_fault;
/* The simplified model uses AP[0] as an access control bit. */
if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
/* Access flag fault. */
code = (code == 15) ? 6 : 3;
goto do_fault;
}
*prot = check_ap(env, ap, domain, access_type, is_user);
if (!*prot) {
/* Access permission fault. */
goto do_fault;
}
if (!xn) {
*prot |= PAGE_EXEC;
/* The simplified model uses AP[0] as an access control bit. */
if ((env->cp15.c1_sys & (1 << 29)) && (ap & 1) == 0) {
/* Access flag fault. */
code = (code == 15) ? 6 : 3;
goto do_fault;
}
*prot = check_ap(env, ap, domain, access_type, is_user);
if (!*prot) {
/* Access permission fault. */
goto do_fault;
}
if (!xn) {
*prot |= PAGE_EXEC;
}
}
*phys_ptr = phys_addr;
return 0;
@ -2235,6 +2242,8 @@ static inline int vfp_exceptbits_from_host(int host_bits)
target_bits |= 8;
if (host_bits & float_flag_inexact)
target_bits |= 0x10;
if (host_bits & float_flag_input_denormal)
target_bits |= 0x80;
return target_bits;
}
@ -2271,6 +2280,8 @@ static inline int vfp_exceptbits_to_host(int target_bits)
host_bits |= float_flag_underflow;
if (target_bits & 0x10)
host_bits |= float_flag_inexact;
if (target_bits & 0x80)
host_bits |= float_flag_input_denormal;
return host_bits;
}
@ -2303,12 +2314,14 @@ void HELPER(vfp_set_fpscr)(CPUState *env, uint32_t val)
}
set_float_rounding_mode(i, &env->vfp.fp_status);
}
if (changed & (1 << 24))
if (changed & (1 << 24)) {
set_flush_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
set_flush_inputs_to_zero((val & (1 << 24)) != 0, &env->vfp.fp_status);
}
if (changed & (1 << 25))
set_default_nan_mode((val & (1 << 25)) != 0, &env->vfp.fp_status);
i = vfp_exceptbits_to_host((val >> 8) & 0x1f);
i = vfp_exceptbits_to_host(val);
set_float_exception_flags(i, &env->vfp.fp_status);
}

View File

@ -560,8 +560,6 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
if (val) {
val = ~(uint64_t)0;
SET_QC();
} else {
val = 0;
}
} else if (shift <= -64) {
val = 0;
@ -582,9 +580,15 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
int8_t tmp; \
tmp = (int8_t)src2; \
if (tmp >= (ssize_t)sizeof(src1) * 8) { \
if (src1) \
if (src1) { \
SET_QC(); \
dest = src1 >> 31; \
dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
if (src1 > 0) { \
dest--; \
} \
} else { \
dest = src1; \
} \
} else if (tmp <= -(ssize_t)sizeof(src1) * 8) { \
dest = src1 >> 31; \
} else if (tmp < 0) { \
@ -593,7 +597,10 @@ uint64_t HELPER(neon_qshl_u64)(CPUState *env, uint64_t val, uint64_t shiftop)
dest = src1 << tmp; \
if ((dest >> tmp) != src1) { \
SET_QC(); \
dest = src2 >> 31; \
dest = (uint32_t)(1 << (sizeof(src1) * 8 - 1)); \
if (src1 > 0) { \
dest--; \
} \
} \
}} while (0)
NEON_VOP_ENV(qshl_s8, neon_s8, 4)
@ -608,9 +615,9 @@ uint64_t HELPER(neon_qshl_s64)(CPUState *env, uint64_t valop, uint64_t shiftop)
if (shift >= 64) {
if (val) {
SET_QC();
val = (val >> 63) & ~SIGNBIT64;
val = (val >> 63) ^ ~SIGNBIT64;
}
} else if (shift <= 64) {
} else if (shift <= -64) {
val >>= 63;
} else if (shift < 0) {
val >>= -shift;

View File

@ -250,13 +250,9 @@ static void gen_rev16(TCGv var)
/* Byteswap low halfword and sign extend. */
static void gen_revsh(TCGv var)
{
TCGv tmp = new_tmp();
tcg_gen_shri_i32(tmp, var, 8);
tcg_gen_andi_i32(tmp, tmp, 0x00ff);
tcg_gen_shli_i32(var, var, 8);
tcg_gen_ext8s_i32(var, var);
tcg_gen_or_i32(var, var, tmp);
dead_tmp(tmp);
tcg_gen_ext16u_i32(var, var);
tcg_gen_bswap16_i32(var, var);
tcg_gen_ext16s_i32(var, var);
}
/* Unsigned bitfield extract. */
@ -291,11 +287,32 @@ static void gen_bfi(TCGv dest, TCGv base, TCGv val, int shift, uint32_t mask)
tcg_gen_or_i32(dest, base, val);
}
/* Round the top 32 bits of a 64-bit value. */
static void gen_roundqd(TCGv a, TCGv b)
/* Return (b << 32) + a. Mark inputs as dead */
static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv b)
{
tcg_gen_shri_i32(a, a, 31);
tcg_gen_add_i32(a, a, b);
TCGv_i64 tmp64 = tcg_temp_new_i64();
tcg_gen_extu_i32_i64(tmp64, b);
dead_tmp(b);
tcg_gen_shli_i64(tmp64, tmp64, 32);
tcg_gen_add_i64(a, tmp64, a);
tcg_temp_free_i64(tmp64);
return a;
}
/* Return (b << 32) - a. Mark inputs as dead. */
static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv b)
{
TCGv_i64 tmp64 = tcg_temp_new_i64();
tcg_gen_extu_i32_i64(tmp64, b);
dead_tmp(b);
tcg_gen_shli_i64(tmp64, tmp64, 32);
tcg_gen_sub_i64(a, tmp64, a);
tcg_temp_free_i64(tmp64);
return a;
}
/* FIXME: Most targets have native widening multiplication.
@ -329,22 +346,6 @@ static TCGv_i64 gen_muls_i64_i32(TCGv a, TCGv b)
return tmp1;
}
/* Signed 32x32->64 multiply. */
static void gen_imull(TCGv a, TCGv b)
{
TCGv_i64 tmp1 = tcg_temp_new_i64();
TCGv_i64 tmp2 = tcg_temp_new_i64();
tcg_gen_ext_i32_i64(tmp1, a);
tcg_gen_ext_i32_i64(tmp2, b);
tcg_gen_mul_i64(tmp1, tmp1, tmp2);
tcg_temp_free_i64(tmp2);
tcg_gen_trunc_i64_i32(a, tmp1);
tcg_gen_shri_i64(tmp1, tmp1, 32);
tcg_gen_trunc_i64_i32(b, tmp1);
tcg_temp_free_i64(tmp1);
}
/* Swap low and high halfwords. */
static void gen_swap_half(TCGv var)
{
@ -4240,9 +4241,9 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn)
case 9: /* VQSHL */
if (u) {
gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
cpu_V0, cpu_V0);
cpu_V1, cpu_V0);
} else {
gen_helper_neon_qshl_s64(cpu_V1, cpu_env,
gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
cpu_V1, cpu_V0);
}
break;
@ -6641,26 +6642,38 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
gen_logic_CC(tmp);
store_reg(s, rd, tmp);
break;
default:
/* 64 bit mul */
case 4:
/* 64 bit mul double accumulate (UMAAL) */
ARCH(6);
tmp = load_reg(s, rs);
tmp2 = load_reg(s, rm);
if (insn & (1 << 22))
tmp64 = gen_muls_i64_i32(tmp, tmp2);
else
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
if (insn & (1 << 21)) /* mult accumulate */
gen_addq(s, tmp64, rn, rd);
if (!(insn & (1 << 23))) { /* double accumulate */
ARCH(6);
gen_addq_lo(s, tmp64, rn);
gen_addq_lo(s, tmp64, rd);
}
if (insn & (1 << 20))
gen_logicq_cc(tmp64);
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
gen_addq_lo(s, tmp64, rn);
gen_addq_lo(s, tmp64, rd);
gen_storeq_reg(s, rn, rd, tmp64);
tcg_temp_free_i64(tmp64);
break;
case 8: case 9: case 10: case 11:
case 12: case 13: case 14: case 15:
/* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
tmp = load_reg(s, rs);
tmp2 = load_reg(s, rm);
if (insn & (1 << 22)) {
tmp64 = gen_muls_i64_i32(tmp, tmp2);
} else {
tmp64 = gen_mulu_i64_i32(tmp, tmp2);
}
if (insn & (1 << 21)) { /* mult accumulate */
gen_addq(s, tmp64, rn, rd);
}
if (insn & (1 << 20)) {
gen_logicq_cc(tmp64);
}
gen_storeq_reg(s, rn, rd, tmp64);
tcg_temp_free_i64(tmp64);
break;
default:
goto illegal_op;
}
} else {
rn = (insn >> 16) & 0xf;
@ -6945,23 +6958,25 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
tmp = load_reg(s, rm);
tmp2 = load_reg(s, rs);
if (insn & (1 << 20)) {
/* Signed multiply most significant [accumulate]. */
/* Signed multiply most significant [accumulate].
(SMMUL, SMMLA, SMMLS) */
tmp64 = gen_muls_i64_i32(tmp, tmp2);
if (insn & (1 << 5))
if (rd != 15) {
tmp = load_reg(s, rd);
if (insn & (1 << 6)) {
tmp64 = gen_subq_msw(tmp64, tmp);
} else {
tmp64 = gen_addq_msw(tmp64, tmp);
}
}
if (insn & (1 << 5)) {
tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
}
tcg_gen_shri_i64(tmp64, tmp64, 32);
tmp = new_tmp();
tcg_gen_trunc_i64_i32(tmp, tmp64);
tcg_temp_free_i64(tmp64);
if (rd != 15) {
tmp2 = load_reg(s, rd);
if (insn & (1 << 6)) {
tcg_gen_sub_i32(tmp, tmp, tmp2);
} else {
tcg_gen_add_i32(tmp, tmp, tmp2);
}
dead_tmp(tmp2);
}
store_reg(s, rn, tmp);
} else {
if (insn & (1 << 5))
@ -7832,24 +7847,23 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
dead_tmp(tmp2);
}
break;
case 5: case 6: /* 32 * 32 -> 32msb */
gen_imull(tmp, tmp2);
if (insn & (1 << 5)) {
gen_roundqd(tmp, tmp2);
dead_tmp(tmp2);
} else {
dead_tmp(tmp);
tmp = tmp2;
}
case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
tmp64 = gen_muls_i64_i32(tmp, tmp2);
if (rs != 15) {
tmp2 = load_reg(s, rs);
if (insn & (1 << 21)) {
tcg_gen_add_i32(tmp, tmp, tmp2);
tmp = load_reg(s, rs);
if (insn & (1 << 20)) {
tmp64 = gen_addq_msw(tmp64, tmp);
} else {
tcg_gen_sub_i32(tmp, tmp2, tmp);
tmp64 = gen_subq_msw(tmp64, tmp);
}
dead_tmp(tmp2);
}
if (insn & (1 << 4)) {
tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
}
tcg_gen_shri_i64(tmp64, tmp64, 32);
tmp = new_tmp();
tcg_gen_trunc_i64_i32(tmp, tmp64);
tcg_temp_free_i64(tmp64);
break;
case 7: /* Unsigned sum of absolute differences. */
gen_helper_usad8(tmp, tmp, tmp2);

View File

@ -577,20 +577,15 @@ static inline void t_gen_swapr(TCGv d, TCGv s)
static void t_gen_cc_jmp(TCGv pc_true, TCGv pc_false)
{
TCGv btaken;
int l1;
l1 = gen_new_label();
btaken = tcg_temp_new();
/* Conditional jmp. */
tcg_gen_mov_tl(btaken, env_btaken);
tcg_gen_mov_tl(env_pc, pc_false);
tcg_gen_brcondi_tl(TCG_COND_EQ, btaken, 0, l1);
tcg_gen_brcondi_tl(TCG_COND_EQ, env_btaken, 0, l1);
tcg_gen_mov_tl(env_pc, pc_true);
gen_set_label(l1);
tcg_temp_free(btaken);
}
static void gen_goto_tb(DisasContext *dc, int n, target_ulong dest)
@ -1134,7 +1129,7 @@ static void cris_store_direct_jmp(DisasContext *dc)
/* Store the direct jmp state into the cpu-state. */
if (dc->jmp == JMP_DIRECT) {
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
tcg_gen_movi_tl(env_btaken, 1);
dc->jmp = JMP_INDIRECT;
}
}
@ -1144,17 +1139,11 @@ static void cris_prepare_cc_branch (DisasContext *dc,
/* This helps us re-schedule the micro-code to insns in delay-slots
before the actual jump. */
dc->delayed_branch = 2;
dc->jmp = JMP_DIRECT;
dc->jmp_pc = dc->pc + offset;
if (cond != CC_A)
{
dc->jmp = JMP_INDIRECT;
gen_tst_cc (dc, env_btaken, cond);
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
} else {
/* Allow chaining. */
dc->jmp = JMP_DIRECT;
}
gen_tst_cc (dc, env_btaken, cond);
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
}
@ -1166,8 +1155,7 @@ static inline void cris_prepare_jmp (DisasContext *dc, unsigned int type)
before the actual jump. */
dc->delayed_branch = 2;
dc->jmp = type;
if (type == JMP_INDIRECT)
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_movi_tl(env_btaken, 1);
}
static void gen_load64(DisasContext *dc, TCGv_i64 dst, TCGv addr)
@ -3320,8 +3308,24 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
if (tb->flags & 7)
t_gen_mov_env_TN(dslot,
tcg_const_tl(0));
if (dc->cpustate_changed || !dc->flagx_known
|| (dc->flags_x != (tb->flags & X_FLAG))) {
cris_store_direct_jmp(dc);
}
if (dc->jmp == JMP_DIRECT) {
dc->is_jmp = DISAS_NEXT;
int l1;
l1 = gen_new_label();
cris_evaluate_flags(dc);
/* Conditional jmp. */
tcg_gen_brcondi_tl(TCG_COND_EQ,
env_btaken, 0, l1);
gen_goto_tb(dc, 1, dc->jmp_pc);
gen_set_label(l1);
gen_goto_tb(dc, 0, dc->pc);
dc->is_jmp = DISAS_TB_JUMP;
dc->jmp = JMP_NOJMP;
} else {
t_gen_cc_jmp(env_btarget,
tcg_const_tl(dc->pc));
@ -3341,16 +3345,10 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
&& (dc->pc < next_page_start)
&& num_insns < max_insns);
if (dc->tb_flags != orig_flags) {
dc->cpustate_changed = 1;
}
if (dc->clear_locked_irq)
t_gen_mov_env_TN(locked_irq, tcg_const_tl(0));
npc = dc->pc;
if (dc->jmp == JMP_DIRECT && !dc->delayed_branch)
npc = dc->jmp_pc;
if (tb->cflags & CF_LAST_IO)
gen_io_end();

View File

@ -737,10 +737,10 @@ typedef struct CPUX86State {
user */
struct DeviceState *apic_state;
uint64 mcg_cap;
uint64 mcg_status;
uint64 mcg_ctl;
uint64 mce_banks[MCE_BANKS_DEF*4];
uint64_t mcg_cap;
uint64_t mcg_status;
uint64_t mcg_ctl;
uint64_t mce_banks[MCE_BANKS_DEF*4];
uint64_t tsc_aux;

View File

@ -175,12 +175,12 @@ cpu_x86_dump_seg_cache(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
#ifdef TARGET_X86_64
if (env->hflags & HF_CS64_MASK) {
cpu_fprintf(f, "%-3s=%04x %016" PRIx64 " %08x %08x", name,
sc->selector, sc->base, sc->limit, sc->flags);
sc->selector, sc->base, sc->limit, sc->flags & 0x00ffff00);
} else
#endif
{
cpu_fprintf(f, "%-3s=%04x %08x %08x %08x", name, sc->selector,
(uint32_t)sc->base, sc->limit, sc->flags);
(uint32_t)sc->base, sc->limit, sc->flags & 0x00ffff00);
}
if (!(env->hflags & HF_PE_MASK) || !(sc->flags & DESC_P_MASK))

View File

@ -614,10 +614,10 @@ float64 HELPER(sub_cmp_f64)(CPUState *env, float64 a, float64 b)
/* ??? Should flush denormals to zero. */
float64 res;
res = float64_sub(a, b, &env->fp_status);
if (float64_is_nan(res)) {
if (float64_is_quiet_nan(res)) {
/* +/-inf compares equal against itself, but sub returns nan. */
if (!float64_is_nan(a)
&& !float64_is_nan(b)) {
if (!float64_is_quiet_nan(a)
&& !float64_is_quiet_nan(b)) {
res = float64_zero;
if (float64_lt_quiet(a, res, &env->fp_status))
res = float64_chs(res);

View File

@ -308,7 +308,7 @@ uint32_t helper_fcmp_un(uint32_t a, uint32_t b)
r = 1;
}
if (float32_is_nan(fa.f) || float32_is_nan(fb.f)) {
if (float32_is_quiet_nan(fa.f) || float32_is_quiet_nan(fb.f)) {
r = 1;
}

View File

@ -752,9 +752,8 @@ static void dec_bit(DisasContext *dc)
static inline void sync_jmpstate(DisasContext *dc)
{
if (dc->jmp == JMP_DIRECT) {
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btarget, dc->jmp_pc);
}
}
@ -976,11 +975,13 @@ static void dec_bcc(DisasContext *dc)
int32_t offset = (int32_t)((int16_t)dc->imm); /* sign-extend. */
tcg_gen_movi_tl(env_btarget, dc->pc + offset);
dc->jmp = JMP_DIRECT;
dc->jmp_pc = dc->pc + offset;
} else {
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btarget, dc->pc);
tcg_gen_add_tl(env_btarget, env_btarget, *(dec_alu_op_b(dc)));
}
dc->jmp = JMP_INDIRECT;
eval_cc(dc, cc, env_btaken, cpu_R[dc->ra], tcg_const_tl(0));
}
@ -1028,6 +1029,7 @@ static void dec_br(DisasContext *dc)
if (dec_alu_op_b_is_small_imm(dc)) {
dc->jmp = JMP_DIRECT;
dc->jmp_pc = dc->pc + (int32_t)((int16_t)dc->imm);
tcg_gen_movi_tl(env_btaken, 1);
} else {
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_movi_tl(env_btarget, dc->pc);
@ -1130,6 +1132,7 @@ static void dec_rts(DisasContext *dc)
} else
LOG_DIS("rts ir=%x\n", dc->ir);
dc->jmp = JMP_INDIRECT;
tcg_gen_movi_tl(env_btaken, 1);
tcg_gen_add_tl(env_btarget, cpu_R[dc->ra], *(dec_alu_op_b(dc)));
}
@ -1370,6 +1373,9 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
dc->is_jmp = DISAS_NEXT;
dc->jmp = 0;
dc->delayed_branch = !!(dc->tb_flags & D_FLAG);
if (dc->delayed_branch) {
dc->jmp = JMP_INDIRECT;
}
dc->pc = pc_start;
dc->singlestep_enabled = env->singlestep_enabled;
dc->cpustate_changed = 0;
@ -1441,9 +1447,21 @@ gen_intermediate_code_internal(CPUState *env, TranslationBlock *tb,
/* Clear the delay slot flag. */
dc->tb_flags &= ~D_FLAG;
/* If it is a direct jump, try direct chaining. */
if (dc->jmp != JMP_DIRECT) {
if (dc->jmp == JMP_INDIRECT) {
eval_cond_jmp(dc, env_btarget, tcg_const_tl(dc->pc));
dc->is_jmp = DISAS_JUMP;
} else if (dc->jmp == JMP_DIRECT) {
int l1;
t_sync_flags(dc);
l1 = gen_new_label();
/* Conditional jmp. */
tcg_gen_brcondi_tl(TCG_COND_NE, env_btaken, 0, l1);
gen_goto_tb(dc, 1, dc->pc);
gen_set_label(l1);
gen_goto_tb(dc, 0, dc->jmp_pc);
dc->is_jmp = DISAS_TB_JUMP;
}
break;
}

View File

@ -532,6 +532,14 @@ static inline int cpu_mips_hw_interrupts_pending(CPUState *env)
int32_t status;
int r;
if (!(env->CP0_Status & (1 << CP0St_IE)) ||
(env->CP0_Status & (1 << CP0St_EXL)) ||
(env->CP0_Status & (1 << CP0St_ERL)) ||
(env->hflags & MIPS_HFLAG_DM)) {
/* Interrupts are disabled */
return 0;
}
pending = env->CP0_Cause & CP0Ca_IP_mask;
status = env->CP0_Status & CP0Ca_IP_mask;

View File

@ -19,10 +19,22 @@ register struct CPUMIPSState *env asm(AREG0);
static inline int cpu_has_work(CPUState *env)
{
return (env->interrupt_request &
(CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER));
}
int has_work = 0;
/* It is implementation dependent if non-enabled interrupts
wake-up the CPU, however most of the implementations only
check for interrupts that can be taken. */
if ((env->interrupt_request & CPU_INTERRUPT_HARD) &&
cpu_mips_hw_interrupts_pending(env)) {
has_work = 1;
}
if (env->interrupt_request & CPU_INTERRUPT_TIMER) {
has_work = 1;
}
return has_work;
}
static inline int cpu_halted(CPUState *env)
{

View File

@ -154,10 +154,10 @@ DEF_HELPER_2(mttlo, void, tl, i32)
DEF_HELPER_2(mtthi, void, tl, i32)
DEF_HELPER_2(mttacx, void, tl, i32)
DEF_HELPER_1(mttdsp, void, tl)
DEF_HELPER_1(dmt, tl, tl)
DEF_HELPER_1(emt, tl, tl)
DEF_HELPER_1(dvpe, tl, tl)
DEF_HELPER_1(evpe, tl, tl)
DEF_HELPER_0(dmt, tl)
DEF_HELPER_0(emt, tl)
DEF_HELPER_0(dvpe, tl)
DEF_HELPER_0(evpe, tl)
#endif /* !CONFIG_USER_ONLY */
/* microMIPS functions */

View File

@ -1554,40 +1554,28 @@ void helper_mttdsp(target_ulong arg1)
}
/* MIPS MT functions */
target_ulong helper_dmt(target_ulong arg1)
target_ulong helper_dmt(void)
{
// TODO
arg1 = 0;
// rt = arg1
return arg1;
return 0;
}
target_ulong helper_emt(target_ulong arg1)
target_ulong helper_emt(void)
{
// TODO
arg1 = 0;
// rt = arg1
return arg1;
return 0;
}
target_ulong helper_dvpe(target_ulong arg1)
target_ulong helper_dvpe(void)
{
// TODO
arg1 = 0;
// rt = arg1
return arg1;
return 0;
}
target_ulong helper_evpe(target_ulong arg1)
target_ulong helper_evpe(void)
{
// TODO
arg1 = 0;
// rt = arg1
return arg1;
return 0;
}
#endif /* !CONFIG_USER_ONLY */
@ -2889,10 +2877,10 @@ static int float64_is_unordered(int sig, float64 a, float64 b STATUS_PARAM)
{
if (float64_is_signaling_nan(a) ||
float64_is_signaling_nan(b) ||
(sig && (float64_is_nan(a) || float64_is_nan(b)))) {
(sig && (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)))) {
float_raise(float_flag_invalid, status);
return 1;
} else if (float64_is_nan(a) || float64_is_nan(b)) {
} else if (float64_is_quiet_nan(a) || float64_is_quiet_nan(b)) {
return 1;
} else {
return 0;
@ -2947,10 +2935,10 @@ static flag float32_is_unordered(int sig, float32 a, float32 b STATUS_PARAM)
{
if (float32_is_signaling_nan(a) ||
float32_is_signaling_nan(b) ||
(sig && (float32_is_nan(a) || float32_is_nan(b)))) {
(sig && (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)))) {
float_raise(float_flag_invalid, status);
return 1;
} else if (float32_is_nan(a) || float32_is_nan(b)) {
} else if (float32_is_quiet_nan(a) || float32_is_quiet_nan(b)) {
return 1;
} else {
return 0;

View File

@ -12033,22 +12033,22 @@ static void decode_opc (CPUState *env, DisasContext *ctx, int *is_branch)
switch (op2) {
case OPC_DMT:
check_insn(env, ctx, ASE_MT);
gen_helper_dmt(t0, t0);
gen_helper_dmt(t0);
gen_store_gpr(t0, rt);
break;
case OPC_EMT:
check_insn(env, ctx, ASE_MT);
gen_helper_emt(t0, t0);
gen_helper_emt(t0);
gen_store_gpr(t0, rt);
break;
case OPC_DVPE:
check_insn(env, ctx, ASE_MT);
gen_helper_dvpe(t0, t0);
gen_helper_dvpe(t0);
gen_store_gpr(t0, rt);
break;
case OPC_EVPE:
check_insn(env, ctx, ASE_MT);
gen_helper_evpe(t0, t0);
gen_helper_evpe(t0);
gen_store_gpr(t0, rt);
break;
case OPC_DI:

View File

@ -26,9 +26,6 @@
#include "cpu.h"
#include "exec-all.h"
/* Precise emulation is needed to correctly emulate exception flags */
#define USE_PRECISE_EMULATION 1
register struct CPUPPCState *env asm(AREG0);
#if !defined(CONFIG_USER_ONLY)

View File

@ -546,7 +546,7 @@ uint32_t helper_compute_fprf (uint64_t arg, uint32_t set_fprf)
int ret;
farg.ll = arg;
isneg = float64_is_neg(farg.d);
if (unlikely(float64_is_nan(farg.d))) {
if (unlikely(float64_is_quiet_nan(farg.d))) {
if (float64_is_signaling_nan(farg.d)) {
/* Signaling NaN: flags are undefined */
ret = 0x00;
@ -643,7 +643,7 @@ static inline uint64_t fload_invalid_op_excp(int op)
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
if (ve == 0) {
/* Set the result to quiet NaN */
ret = 0xFFF8000000000000ULL;
ret = 0x7FF8000000000000ULL;
env->fpscr &= ~(0xF << FPSCR_FPCC);
env->fpscr |= 0x11 << FPSCR_FPCC;
}
@ -654,7 +654,7 @@ static inline uint64_t fload_invalid_op_excp(int op)
env->fpscr &= ~((1 << FPSCR_FR) | (1 << FPSCR_FI));
if (ve == 0) {
/* Set the result to quiet NaN */
ret = 0xFFF8000000000000ULL;
ret = 0x7FF8000000000000ULL;
env->fpscr &= ~(0xF << FPSCR_FPCC);
env->fpscr |= 0x11 << FPSCR_FPCC;
}
@ -974,7 +974,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN addition */
@ -986,9 +986,7 @@ uint64_t helper_fadd (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
}
#else
farg1.d = float64_add(farg1.d, farg2.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -999,8 +997,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
#if USE_PRECISE_EMULATION
{
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN subtraction */
@ -1012,10 +1009,7 @@ uint64_t helper_fsub (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
}
}
#else
farg1.d = float64_sub(farg1.d, farg2.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -1026,7 +1020,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN multiplication */
@ -1038,9 +1032,7 @@ uint64_t helper_fmul (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
}
#else
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -1051,7 +1043,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
farg1.ll = arg1;
farg2.ll = arg2;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d))) {
/* sNaN division */
@ -1065,9 +1057,7 @@ uint64_t helper_fdiv (uint64_t arg1, uint64_t arg2)
} else {
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
}
#else
farg1.d = float64_div(farg1.d, farg2.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -1111,17 +1101,15 @@ uint64_t helper_fctiw (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
farg.ll = float64_to_int32(farg.d, &env->fp_status);
#if USE_PRECISE_EMULATION
/* XXX: higher bits are not supposed to be significant.
* to make tests easier, return the same as a real PowerPC 750
*/
farg.ll |= 0xFFF80000ULL << 32;
#endif
}
return farg.ll;
}
@ -1135,17 +1123,15 @@ uint64_t helper_fctiwz (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
farg.ll = float64_to_int32_round_to_zero(farg.d, &env->fp_status);
#if USE_PRECISE_EMULATION
/* XXX: higher bits are not supposed to be significant.
* to make tests easier, return the same as a real PowerPC 750
*/
farg.ll |= 0xFFF80000ULL << 32;
#endif
}
return farg.ll;
}
@ -1168,7 +1154,7 @@ uint64_t helper_fctid (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
@ -1186,7 +1172,7 @@ uint64_t helper_fctidz (uint64_t arg)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
/* qNan / infinity conversion */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
@ -1205,7 +1191,7 @@ static inline uint64_t do_fri(uint64_t arg, int rounding_mode)
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN round */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN | POWERPC_EXCP_FP_VXCVI);
} else if (unlikely(float64_is_nan(farg.d) || float64_is_infinity(farg.d))) {
} else if (unlikely(float64_is_quiet_nan(farg.d) || float64_is_infinity(farg.d))) {
/* qNan / infinity round */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXCVI);
} else {
@ -1245,7 +1231,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
farg2.ll = arg2;
farg3.ll = arg3;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
@ -1277,10 +1263,7 @@ uint64_t helper_fmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
}
#else
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -1292,7 +1275,7 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
farg2.ll = arg2;
farg3.ll = arg3;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg1.d) ||
float64_is_signaling_nan(farg2.d) ||
float64_is_signaling_nan(farg3.d))) {
@ -1324,10 +1307,6 @@ uint64_t helper_fmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
}
#else
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
#endif
return farg1.ll;
}
@ -1350,7 +1329,6 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
#if USE_PRECISE_EMULATION
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@ -1371,11 +1349,7 @@ uint64_t helper_fnmadd (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) + farg3.d;
#endif
#else
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
farg1.d = float64_add(farg1.d, farg3.d, &env->fp_status);
#endif
if (likely(!float64_is_nan(farg1.d)))
if (likely(!float64_is_quiet_nan(farg1.d)))
farg1.d = float64_chs(farg1.d);
}
return farg1.ll;
@ -1400,7 +1374,6 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* Multiplication of zero by infinity */
farg1.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXIMZ);
} else {
#if USE_PRECISE_EMULATION
#ifdef FLOAT128
/* This is the way the PowerPC specification defines it */
float128 ft0_128, ft1_128;
@ -1421,11 +1394,7 @@ uint64_t helper_fnmsub (uint64_t arg1, uint64_t arg2, uint64_t arg3)
/* This is OK on x86 hosts */
farg1.d = (farg1.d * farg2.d) - farg3.d;
#endif
#else
farg1.d = float64_mul(farg1.d, farg2.d, &env->fp_status);
farg1.d = float64_sub(farg1.d, farg3.d, &env->fp_status);
#endif
if (likely(!float64_is_nan(farg1.d)))
if (likely(!float64_is_quiet_nan(farg1.d)))
farg1.d = float64_chs(farg1.d);
}
return farg1.ll;
@ -1438,7 +1407,6 @@ uint64_t helper_frsp (uint64_t arg)
float32 f32;
farg.ll = arg;
#if USE_PRECISE_EMULATION
if (unlikely(float64_is_signaling_nan(farg.d))) {
/* sNaN square root */
farg.ll = fload_invalid_op_excp(POWERPC_EXCP_FP_VXSNAN);
@ -1446,10 +1414,6 @@ uint64_t helper_frsp (uint64_t arg)
f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status);
}
#else
f32 = float64_to_float32(farg.d, &env->fp_status);
farg.d = float32_to_float64(f32, &env->fp_status);
#endif
return farg.ll;
}
@ -1533,7 +1497,7 @@ uint64_t helper_fsel (uint64_t arg1, uint64_t arg2, uint64_t arg3)
farg1.ll = arg1;
if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_nan(farg1.d))
if ((!float64_is_neg(farg1.d) || float64_is_zero(farg1.d)) && !float64_is_quiet_nan(farg1.d))
return arg2;
else
return arg3;
@ -1546,8 +1510,8 @@ void helper_fcmpu (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
if (unlikely(float64_is_nan(farg1.d) ||
float64_is_nan(farg2.d))) {
if (unlikely(float64_is_quiet_nan(farg1.d) ||
float64_is_quiet_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@ -1575,8 +1539,8 @@ void helper_fcmpo (uint64_t arg1, uint64_t arg2, uint32_t crfD)
farg1.ll = arg1;
farg2.ll = arg2;
if (unlikely(float64_is_nan(farg1.d) ||
float64_is_nan(farg2.d))) {
if (unlikely(float64_is_quiet_nan(farg1.d) ||
float64_is_quiet_nan(farg2.d))) {
ret = 0x01UL;
} else if (float64_lt(farg1.d, farg2.d, &env->fp_status)) {
ret = 0x08UL;
@ -1938,7 +1902,7 @@ target_ulong helper_dlmzb (target_ulong high, target_ulong low, uint32_t update_
/* If X is a NaN, store the corresponding QNaN into RESULT. Otherwise,
* execute the following block. */
#define DO_HANDLE_NAN(result, x) \
if (float32_is_nan(x) || float32_is_signaling_nan(x)) { \
if (float32_is_any_nan(x)) { \
CPU_FloatU __f; \
__f.f = x; \
__f.l = __f.l | (1 << 22); /* Set QNaN bit. */ \
@ -2283,8 +2247,7 @@ void helper_vcmpbfp_dot (ppc_avr_t *r, ppc_avr_t *a, ppc_avr_t *b)
float_status s = env->vec_status; \
set_float_rounding_mode(float_round_to_zero, &s); \
for (i = 0; i < ARRAY_SIZE(r->f); i++) { \
if (float32_is_nan(b->f[i]) || \
float32_is_signaling_nan(b->f[i])) { \
if (float32_is_any_nan(b->f[i])) { \
r->element[i] = 0; \
} else { \
float64 t = float32_to_float64(b->f[i], &s); \
@ -3132,7 +3095,7 @@ static inline int32_t efsctsi(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
return float32_to_int32(u.f, &env->vec_status);
@ -3144,7 +3107,7 @@ static inline uint32_t efsctui(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
return float32_to_uint32(u.f, &env->vec_status);
@ -3156,7 +3119,7 @@ static inline uint32_t efsctsiz(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
return float32_to_int32_round_to_zero(u.f, &env->vec_status);
@ -3168,7 +3131,7 @@ static inline uint32_t efsctuiz(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
return float32_to_uint32_round_to_zero(u.f, &env->vec_status);
@ -3205,7 +3168,7 @@ static inline uint32_t efsctsf(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
u.f = float32_mul(u.f, tmp, &env->vec_status);
@ -3220,7 +3183,7 @@ static inline uint32_t efsctuf(uint32_t val)
u.l = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float32_is_nan(u.f)))
if (unlikely(float32_is_quiet_nan(u.f)))
return 0;
tmp = uint64_to_float32(1ULL << 32, &env->vec_status);
u.f = float32_mul(u.f, tmp, &env->vec_status);
@ -3474,7 +3437,7 @@ uint32_t helper_efdctsi (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_int32(u.d, &env->vec_status);
@ -3486,7 +3449,7 @@ uint32_t helper_efdctui (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_uint32(u.d, &env->vec_status);
@ -3498,7 +3461,7 @@ uint32_t helper_efdctsiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_int32_round_to_zero(u.d, &env->vec_status);
@ -3510,7 +3473,7 @@ uint64_t helper_efdctsidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_int64_round_to_zero(u.d, &env->vec_status);
@ -3522,7 +3485,7 @@ uint32_t helper_efdctuiz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_uint32_round_to_zero(u.d, &env->vec_status);
@ -3534,7 +3497,7 @@ uint64_t helper_efdctuidz (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
return float64_to_uint64_round_to_zero(u.d, &env->vec_status);
@ -3571,7 +3534,7 @@ uint32_t helper_efdctsf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);
@ -3586,7 +3549,7 @@ uint32_t helper_efdctuf (uint64_t val)
u.ll = val;
/* NaN are not treated the same way IEEE 754 does */
if (unlikely(float64_is_nan(u.d)))
if (unlikely(float64_is_quiet_nan(u.d)))
return 0;
tmp = uint64_to_float64(1ULL << 32, &env->vec_status);
u.d = float64_mul(u.d, tmp, &env->vec_status);

View File

@ -7751,10 +7751,10 @@ static inline void gen_evfsabs(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000080000000LL);
#else
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x80000000);
tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
static inline void gen_evfsnabs(DisasContext *ctx)
@ -7764,10 +7764,10 @@ static inline void gen_evfsnabs(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
static inline void gen_evfsneg(DisasContext *ctx)
@ -7777,10 +7777,10 @@ static inline void gen_evfsneg(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000080000000LL);
#else
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
@ -7832,7 +7832,7 @@ static inline void gen_efsabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_APU);
return;
}
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], (target_long)~0x80000000LL);
}
static inline void gen_efsnabs(DisasContext *ctx)
{
@ -7840,7 +7840,7 @@ static inline void gen_efsnabs(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_APU);
return;
}
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}
static inline void gen_efsneg(DisasContext *ctx)
{
@ -7848,7 +7848,7 @@ static inline void gen_efsneg(DisasContext *ctx)
gen_exception(ctx, POWERPC_EXCP_APU);
return;
}
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x80000000);
}
/* Conversion */
@ -7901,9 +7901,10 @@ static inline void gen_efdabs(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_andi_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
tcg_gen_andi_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], ~0x8000000000000000LL);
#else
tcg_gen_andi_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_andi_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], ~0x80000000);
#endif
}
static inline void gen_efdnabs(DisasContext *ctx)
@ -7913,9 +7914,10 @@ static inline void gen_efdnabs(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_ori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
tcg_gen_ori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
tcg_gen_ori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_ori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}
static inline void gen_efdneg(DisasContext *ctx)
@ -7925,9 +7927,10 @@ static inline void gen_efdneg(DisasContext *ctx)
return;
}
#if defined(TARGET_PPC64)
tcg_gen_xori_tl(cpu_gpr[rA(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
tcg_gen_xori_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)], 0x8000000000000000LL);
#else
tcg_gen_xori_tl(cpu_gprh[rA(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
tcg_gen_mov_tl(cpu_gpr[rD(ctx->opcode)], cpu_gpr[rA(ctx->opcode)]);
tcg_gen_xori_tl(cpu_gprh[rD(ctx->opcode)], cpu_gprh[rA(ctx->opcode)], 0x80000000);
#endif
}

View File

@ -119,7 +119,7 @@ int kvm_arch_put_registers(CPUState *env, int level)
int kvm_arch_get_registers(CPUState *env)
{
uint32_t ret;
int ret;
struct kvm_regs regs;
int i;

View File

@ -36,7 +36,7 @@ void cpu_dump_state(CPUState *env, FILE *f, fprintf_function cpu_fprintf,
}
}
for (i = 0; i < 16; i++) {
cpu_fprintf(f, "F%02d=%016lx", i, env->fregs[i]);
cpu_fprintf(f, "F%02d=%016lx", i, (long)env->fregs[i].i);
if ((i % 4) == 3) {
cpu_fprintf(f, "\n");
} else {

View File

@ -172,6 +172,8 @@ void do_interrupt(CPUSH4State * env);
void sh4_cpu_list(FILE *f, fprintf_function cpu_fprintf);
#if !defined(CONFIG_USER_ONLY)
void cpu_sh4_invalidate_tlb(CPUSH4State *s);
void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value);
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value);
#endif

View File

@ -280,35 +280,40 @@ static void increment_urc(CPUState * env)
env->mmucr = (env->mmucr & 0xffff03ff) | (urc << 10);
}
/* Find itlb entry - update itlb from utlb if necessary and asked for
/* Copy and utlb entry into itlb
Return entry
*/
static int copy_utlb_entry_itlb(CPUState *env, int utlb)
{
int itlb;
tlb_t * ientry;
itlb = itlb_replacement(env);
ientry = &env->itlb[itlb];
if (ientry->v) {
tlb_flush_page(env, ientry->vpn << 10);
}
*ientry = env->utlb[utlb];
update_itlb_use(env, itlb);
return itlb;
}
/* Find itlb entry
Return entry, MMU_ITLB_MISS, MMU_ITLB_MULTIPLE or MMU_DTLB_MULTIPLE
Update the itlb from utlb if update is not 0
*/
static int find_itlb_entry(CPUState * env, target_ulong address,
int use_asid, int update)
int use_asid)
{
int e, n;
int e;
e = find_tlb_entry(env, address, env->itlb, ITLB_SIZE, use_asid);
if (e == MMU_DTLB_MULTIPLE)
if (e == MMU_DTLB_MULTIPLE) {
e = MMU_ITLB_MULTIPLE;
else if (e == MMU_DTLB_MISS && update) {
e = find_tlb_entry(env, address, env->utlb, UTLB_SIZE, use_asid);
if (e >= 0) {
tlb_t * ientry;
n = itlb_replacement(env);
ientry = &env->itlb[n];
if (ientry->v) {
tlb_flush_page(env, ientry->vpn << 10);
}
*ientry = env->utlb[e];
e = n;
} else if (e == MMU_DTLB_MISS)
e = MMU_ITLB_MISS;
} else if (e == MMU_DTLB_MISS)
} else if (e == MMU_DTLB_MISS) {
e = MMU_ITLB_MISS;
if (e >= 0)
} else if (e >= 0) {
update_itlb_use(env, e);
}
return e;
}
@ -340,13 +345,31 @@ static int get_mmu_address(CPUState * env, target_ulong * physical,
use_asid = (env->mmucr & MMUCR_SV) == 0 || (env->sr & SR_MD) == 0;
if (rw == 2) {
n = find_itlb_entry(env, address, use_asid, 1);
n = find_itlb_entry(env, address, use_asid);
if (n >= 0) {
matching = &env->itlb[n];
if (!(env->sr & SR_MD) && !(matching->pr & 2))
n = MMU_ITLB_VIOLATION;
else
*prot = PAGE_EXEC;
} else {
n = find_utlb_entry(env, address, use_asid);
if (n >= 0) {
n = copy_utlb_entry_itlb(env, n);
matching = &env->itlb[n];
if (!(env->sr & SR_MD) && !(matching->pr & 2)) {
n = MMU_ITLB_VIOLATION;
} else {
*prot = PAGE_READ | PAGE_EXEC;
if ((matching->pr & 1) && matching->d) {
*prot |= PAGE_WRITE;
}
}
} else if (n == MMU_DTLB_MULTIPLE) {
n = MMU_ITLB_MULTIPLE;
} else if (n == MMU_DTLB_MISS) {
n = MMU_ITLB_MISS;
}
}
} else {
n = find_utlb_entry(env, address, use_asid);
@ -544,6 +567,25 @@ void cpu_load_tlb(CPUSH4State * env)
tlb_flush(s, 1);
}
void cpu_sh4_write_mmaped_itlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value)
{
uint32_t vpn = (mem_value & 0xfffffc00) >> 10;
uint8_t v = (uint8_t)((mem_value & 0x00000100) >> 8);
uint8_t asid = (uint8_t)(mem_value & 0x000000ff);
int index = (addr & 0x00003f00) >> 8;
tlb_t * entry = &s->itlb[index];
if (entry->v) {
/* Overwriting valid entry in itlb. */
target_ulong address = entry->vpn << 10;
tlb_flush_page(s, address);
}
entry->asid = asid;
entry->vpn = vpn;
entry->v = v;
}
void cpu_sh4_write_mmaped_utlb_addr(CPUSH4State *s, target_phys_addr_t addr,
uint32_t mem_value)
{

View File

@ -448,7 +448,7 @@ int cpu_sparc_handle_mmu_fault(CPUSPARCState *env1, target_ulong address, int rw
int mmu_idx, int is_softmmu);
#define cpu_handle_mmu_fault cpu_sparc_handle_mmu_fault
target_ulong mmu_probe(CPUSPARCState *env, target_ulong address, int mmulev);
void dump_mmu(CPUSPARCState *env);
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env);
/* translate.c */
void gen_intermediate_code_init(CPUSPARCState *env);

View File

@ -320,47 +320,45 @@ target_ulong mmu_probe(CPUState *env, target_ulong address, int mmulev)
return 0;
}
#ifdef DEBUG_MMU
void dump_mmu(CPUState *env)
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
{
target_ulong va, va1, va2;
unsigned int n, m, o;
target_phys_addr_t pde_ptr, pa;
uint32_t pde;
printf("MMU dump:\n");
pde_ptr = (env->mmuregs[1] << 4) + (env->mmuregs[2] << 2);
pde = ldl_phys(pde_ptr);
printf("Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
(target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
(*cpu_fprintf)(f, "Root ptr: " TARGET_FMT_plx ", ctx: %d\n",
(target_phys_addr_t)env->mmuregs[1] << 4, env->mmuregs[2]);
for (n = 0, va = 0; n < 256; n++, va += 16 * 1024 * 1024) {
pde = mmu_probe(env, va, 2);
if (pde) {
pa = cpu_get_phys_page_debug(env, va);
printf("VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
" PDE: " TARGET_FMT_lx "\n", va, pa, pde);
(*cpu_fprintf)(f, "VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
" PDE: " TARGET_FMT_lx "\n", va, pa, pde);
for (m = 0, va1 = va; m < 64; m++, va1 += 256 * 1024) {
pde = mmu_probe(env, va1, 1);
if (pde) {
pa = cpu_get_phys_page_debug(env, va1);
printf(" VA: " TARGET_FMT_lx ", PA: " TARGET_FMT_plx
" PDE: " TARGET_FMT_lx "\n", va1, pa, pde);
(*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
TARGET_FMT_plx " PDE: " TARGET_FMT_lx "\n",
va1, pa, pde);
for (o = 0, va2 = va1; o < 64; o++, va2 += 4 * 1024) {
pde = mmu_probe(env, va2, 0);
if (pde) {
pa = cpu_get_phys_page_debug(env, va2);
printf(" VA: " TARGET_FMT_lx ", PA: "
TARGET_FMT_plx " PTE: " TARGET_FMT_lx "\n",
va2, pa, pde);
(*cpu_fprintf)(f, " VA: " TARGET_FMT_lx ", PA: "
TARGET_FMT_plx " PTE: "
TARGET_FMT_lx "\n",
va2, pa, pde);
}
}
}
}
}
}
printf("MMU dump ends\n");
}
#endif /* DEBUG_MMU */
#else /* !TARGET_SPARC64 */
@ -622,18 +620,19 @@ int cpu_sparc_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
return 1;
}
#ifdef DEBUG_MMU
void dump_mmu(CPUState *env)
void dump_mmu(FILE *f, fprintf_function cpu_fprintf, CPUState *env)
{
unsigned int i;
const char *mask;
printf("MMU contexts: Primary: %" PRId64 ", Secondary: %" PRId64 "\n",
env->dmmu.mmu_primary_context, env->dmmu.mmu_secondary_context);
(*cpu_fprintf)(f, "MMU contexts: Primary: %" PRId64 ", Secondary: %"
PRId64 "\n",
env->dmmu.mmu_primary_context,
env->dmmu.mmu_secondary_context);
if ((env->lsu & DMMU_E) == 0) {
printf("DMMU disabled\n");
(*cpu_fprintf)(f, "DMMU disabled\n");
} else {
printf("DMMU dump:\n");
(*cpu_fprintf)(f, "DMMU dump\n");
for (i = 0; i < 64; i++) {
switch ((env->dtlb[i].tte >> 61) & 3) {
default:
@ -651,24 +650,25 @@ void dump_mmu(CPUState *env)
break;
}
if ((env->dtlb[i].tte & 0x8000000000000000ULL) != 0) {
printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
i,
env->dtlb[i].tag & (uint64_t)~0x1fffULL,
env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
mask,
env->dtlb[i].tte & 0x4? "priv": "user",
env->dtlb[i].tte & 0x2? "RW": "RO",
env->dtlb[i].tte & 0x40? "locked": "unlocked",
env->dtlb[i].tag & (uint64_t)0x1fffULL,
TTE_IS_GLOBAL(env->dtlb[i].tte)? "global" : "local");
(*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
", %s, %s, %s, %s, ctx %" PRId64 " %s\n",
i,
env->dtlb[i].tag & (uint64_t)~0x1fffULL,
env->dtlb[i].tte & (uint64_t)0x1ffffffe000ULL,
mask,
env->dtlb[i].tte & 0x4? "priv": "user",
env->dtlb[i].tte & 0x2? "RW": "RO",
env->dtlb[i].tte & 0x40? "locked": "unlocked",
env->dtlb[i].tag & (uint64_t)0x1fffULL,
TTE_IS_GLOBAL(env->dtlb[i].tte)?
"global" : "local");
}
}
}
if ((env->lsu & IMMU_E) == 0) {
printf("IMMU disabled\n");
(*cpu_fprintf)(f, "IMMU disabled\n");
} else {
printf("IMMU dump:\n");
(*cpu_fprintf)(f, "IMMU dump\n");
for (i = 0; i < 64; i++) {
switch ((env->itlb[i].tte >> 61) & 3) {
default:
@ -686,21 +686,21 @@ void dump_mmu(CPUState *env)
break;
}
if ((env->itlb[i].tte & 0x8000000000000000ULL) != 0) {
printf("[%02u] VA: %" PRIx64 ", PA: %" PRIx64
", %s, %s, %s, ctx %" PRId64 " %s\n",
i,
env->itlb[i].tag & (uint64_t)~0x1fffULL,
env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
mask,
env->itlb[i].tte & 0x4? "priv": "user",
env->itlb[i].tte & 0x40? "locked": "unlocked",
env->itlb[i].tag & (uint64_t)0x1fffULL,
TTE_IS_GLOBAL(env->itlb[i].tte)? "global" : "local");
(*cpu_fprintf)(f, "[%02u] VA: %" PRIx64 ", PA: %" PRIx64
", %s, %s, %s, ctx %" PRId64 " %s\n",
i,
env->itlb[i].tag & (uint64_t)~0x1fffULL,
env->itlb[i].tte & (uint64_t)0x1ffffffe000ULL,
mask,
env->itlb[i].tte & 0x4? "priv": "user",
env->itlb[i].tte & 0x40? "locked": "unlocked",
env->itlb[i].tag & (uint64_t)0x1fffULL,
TTE_IS_GLOBAL(env->itlb[i].tte)?
"global" : "local");
}
}
}
}
#endif /* DEBUG_MMU */
#endif /* TARGET_SPARC64 */
#endif /* !CONFIG_USER_ONLY */

View File

@ -37,7 +37,9 @@ DEF_HELPER_0(save, void)
DEF_HELPER_0(restore, void)
DEF_HELPER_1(flush, void, tl)
DEF_HELPER_2(udiv, tl, tl, tl)
DEF_HELPER_2(udiv_cc, tl, tl, tl)
DEF_HELPER_2(sdiv, tl, tl, tl)
DEF_HELPER_2(sdiv_cc, tl, tl, tl)
DEF_HELPER_2(stdf, void, tl, int)
DEF_HELPER_2(lddf, void, tl, int)
DEF_HELPER_2(ldqf, void, tl, int)

View File

@ -180,7 +180,7 @@ static void demap_tlb(SparcTLBEntry *tlb, target_ulong demap_addr,
replace_tlb_entry(&tlb[i], 0, 0, env1);
#ifdef DEBUG_MMU
DPRINTF_MMU("%s demap invalidated entry [%02u]\n", strmmu, i);
dump_mmu(env1);
dump_mmu(stdout, fprintf, env1);
#endif
}
}
@ -198,7 +198,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
replace_tlb_entry(&tlb[i], tlb_tag, tlb_tte, env1);
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replaced invalid entry [%i]\n", strmmu, i);
dump_mmu(env1);
dump_mmu(stdout, fprintf, env1);
#endif
return;
}
@ -217,7 +217,7 @@ static void replace_tlb_1bit_lru(SparcTLBEntry *tlb,
#ifdef DEBUG_MMU
DPRINTF_MMU("%s lru replaced unlocked %s entry [%i]\n",
strmmu, (replace_used?"used":"unused"), i);
dump_mmu(env1);
dump_mmu(stdout, fprintf, env1);
#endif
return;
}
@ -1959,7 +1959,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
break;
}
#ifdef DEBUG_MMU
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
}
break;
@ -2011,7 +2011,7 @@ void helper_st_asi(target_ulong addr, uint64_t val, int asi, int size)
reg, oldreg, env->mmuregs[reg]);
}
#ifdef DEBUG_MMU
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
}
break;
@ -2912,7 +2912,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
DPRINTF_MMU("LSU change: 0x%" PRIx64 " -> 0x%" PRIx64 "\n",
oldreg, env->lsu);
#ifdef DEBUG_MMU
dump_mmu(env);
dump_mmu(stdout, fprintf, env1);
#endif
tlb_flush(env, 1);
}
@ -2957,7 +2957,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
PRIx64 "\n", reg, oldreg, env->immuregs[reg]);
}
#ifdef DEBUG_MMU
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
return;
}
@ -2974,7 +2974,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#ifdef DEBUG_MMU
DPRINTF_MMU("immu data access replaced entry [%i]\n", i);
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
return;
}
@ -3030,7 +3030,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
PRIx64 "\n", reg, oldreg, env->dmmuregs[reg]);
}
#ifdef DEBUG_MMU
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
return;
}
@ -3045,7 +3045,7 @@ void helper_st_asi(target_ulong addr, target_ulong val, int asi, int size)
#ifdef DEBUG_MMU
DPRINTF_MMU("dmmu data access replaced entry [%i]\n", i);
dump_mmu(env);
dump_mmu(stdout, fprintf, env);
#endif
return;
}
@ -3300,8 +3300,9 @@ void helper_rett(void)
}
#endif
target_ulong helper_udiv(target_ulong a, target_ulong b)
static target_ulong helper_udiv_common(target_ulong a, target_ulong b, int cc)
{
int overflow = 0;
uint64_t x0;
uint32_t x1;
@ -3314,16 +3315,31 @@ target_ulong helper_udiv(target_ulong a, target_ulong b)
x0 = x0 / x1;
if (x0 > 0xffffffff) {
env->cc_src2 = 1;
return 0xffffffff;
} else {
env->cc_src2 = 0;
return x0;
x0 = 0xffffffff;
overflow = 1;
}
if (cc) {
env->cc_dst = x0;
env->cc_src2 = overflow;
env->cc_op = CC_OP_DIV;
}
return x0;
}
target_ulong helper_sdiv(target_ulong a, target_ulong b)
target_ulong helper_udiv(target_ulong a, target_ulong b)
{
return helper_udiv_common(a, b, 0);
}
target_ulong helper_udiv_cc(target_ulong a, target_ulong b)
{
return helper_udiv_common(a, b, 1);
}
static target_ulong helper_sdiv_common(target_ulong a, target_ulong b, int cc)
{
int overflow = 0;
int64_t x0;
int32_t x1;
@ -3336,12 +3352,26 @@ target_ulong helper_sdiv(target_ulong a, target_ulong b)
x0 = x0 / x1;
if ((int32_t) x0 != x0) {
env->cc_src2 = 1;
return x0 < 0? 0x80000000: 0x7fffffff;
} else {
env->cc_src2 = 0;
return x0;
x0 = x0 < 0 ? 0x80000000: 0x7fffffff;
overflow = 1;
}
if (cc) {
env->cc_dst = x0;
env->cc_src2 = overflow;
env->cc_op = CC_OP_DIV;
}
return x0;
}
target_ulong helper_sdiv(target_ulong a, target_ulong b)
{
return helper_sdiv_common(a, b, 0);
}
target_ulong helper_sdiv_cc(target_ulong a, target_ulong b)
{
return helper_sdiv_common(a, b, 1);
}
void helper_stdf(target_ulong addr, int mem_idx)

View File

@ -3162,20 +3162,20 @@ static void disas_sparc_insn(DisasContext * dc)
#endif
case 0xe: /* udiv */
CHECK_IU_FEATURE(dc, DIV);
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
if (xop & 0x10) {
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
gen_helper_udiv_cc(cpu_dst, cpu_src1, cpu_src2);
dc->cc_op = CC_OP_DIV;
} else {
gen_helper_udiv(cpu_dst, cpu_src1, cpu_src2);
}
break;
case 0xf: /* sdiv */
CHECK_IU_FEATURE(dc, DIV);
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
if (xop & 0x10) {
tcg_gen_mov_tl(cpu_cc_dst, cpu_dst);
tcg_gen_movi_i32(cpu_cc_op, CC_OP_DIV);
gen_helper_sdiv_cc(cpu_dst, cpu_src1, cpu_src2);
dc->cc_op = CC_OP_DIV;
} else {
gen_helper_sdiv(cpu_dst, cpu_src1, cpu_src2);
}
break;
default:

View File

@ -75,11 +75,11 @@ destroyed, but local temporaries and globals are preserved.
* Helpers:
Using the tcg_gen_helper_x_y it is possible to call any function
taking i32, i64 or pointer types. By default, before calling an helper,
taking i32, i64 or pointer types. By default, before calling a helper,
all globals are stored at their canonical location and it is assumed
that the function can modify them. This can be overriden by the
that the function can modify them. This can be overridden by the
TCG_CALL_CONST function modifier. By default, the helper is allowed to
modify the CPU state or raise an exception. This can be overriden by
modify the CPU state or raise an exception. This can be overridden by
the TCG_CALL_PURE function modifier, in which case the call to the
function is removed if the return value is not used.
@ -364,7 +364,7 @@ formed from two 32-bit arguments. The result is a 32-bit value.
********* QEMU specific operations
* tb_exit t0
* exit_tb t0
Exit the current TB and return the value t0 (word type).
@ -488,7 +488,7 @@ register.
the speed of the translation.
- Don't hesitate to use helpers for complicated or seldom used target
intructions. There is little performance advantage in using TCG to
instructions. There is little performance advantage in using TCG to
implement target instructions taking more than about twenty TCG
instructions.

View File

@ -113,12 +113,25 @@ static const int tcg_target_call_oarg_regs[2] = {
TCG_REG_R0, TCG_REG_R1
};
static inline void reloc_abs32(void *code_ptr, tcg_target_long target)
{
*(uint32_t *) code_ptr = target;
}
static inline void reloc_pc24(void *code_ptr, tcg_target_long target)
{
uint32_t offset = ((target - ((tcg_target_long) code_ptr + 8)) >> 2);
*(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & ~0xffffff)
| (offset & 0xffffff);
}
static void patch_reloc(uint8_t *code_ptr, int type,
tcg_target_long value, tcg_target_long addend)
{
switch (type) {
case R_ARM_ABS32:
*(uint32_t *) code_ptr = value;
reloc_abs32(code_ptr, value);
break;
case R_ARM_CALL:
@ -127,8 +140,7 @@ static void patch_reloc(uint8_t *code_ptr, int type,
tcg_abort();
case R_ARM_PC24:
*(uint32_t *) code_ptr = ((*(uint32_t *) code_ptr) & 0xff000000) |
(((value - ((tcg_target_long) code_ptr + 8)) >> 2) & 0xffffff);
reloc_pc24(code_ptr, value);
break;
}
}
@ -394,35 +406,38 @@ static inline void tcg_out_dat_imm(TCGContext *s,
}
static inline void tcg_out_movi32(TCGContext *s,
int cond, int rd, int32_t arg)
int cond, int rd, uint32_t arg)
{
/* TODO: This is very suboptimal, we can easily have a constant
* pool somewhere after all the instructions. */
if (arg < 0 && arg > -0x100)
return tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
if (use_armv7_instructions) {
if ((int)arg < 0 && (int)arg >= -0x100) {
tcg_out_dat_imm(s, cond, ARITH_MVN, rd, 0, (~arg) & 0xff);
} else if (use_armv7_instructions) {
/* use movw/movt */
/* movw */
tcg_out32(s, (cond << 28) | 0x03000000 | (rd << 12)
| ((arg << 4) & 0x000f0000) | (arg & 0xfff));
if (arg & 0xffff0000)
if (arg & 0xffff0000) {
/* movt */
tcg_out32(s, (cond << 28) | 0x03400000 | (rd << 12)
| ((arg >> 12) & 0x000f0000) | ((arg >> 16) & 0xfff));
} else {
tcg_out_dat_imm(s, cond, ARITH_MOV, rd, 0, arg & 0xff);
if (arg & 0x0000ff00)
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
((arg >> 8) & 0xff) | 0xc00);
if (arg & 0x00ff0000)
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
((arg >> 16) & 0xff) | 0x800);
if (arg & 0xff000000)
tcg_out_dat_imm(s, cond, ARITH_ORR, rd, rd,
((arg >> 24) & 0xff) | 0x400);
}
} else {
int opc = ARITH_MOV;
int rn = 0;
do {
int i, rot;
i = ctz32(arg) & ~1;
rot = ((32 - i) << 7) & 0xf00;
tcg_out_dat_imm(s, cond, opc, rd, rn, ((arg >> i) & 0xff) | rot);
arg &= ~(0xff << i);
opc = ARITH_ORR;
rn = rd;
} while (arg);
}
}
static inline void tcg_out_mul32(TCGContext *s,
@ -1031,7 +1046,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
}
label_ptr = (void *) s->code_ptr;
tcg_out_b(s, COND_EQ, 8);
tcg_out_b_noaddr(s, COND_EQ);
/* TODO: move this code to where the constants pool will be */
if (addr_reg != TCG_REG_R0) {
@ -1076,7 +1091,7 @@ static inline void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
break;
}
*label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
uint32_t offset = GUEST_BASE;
@ -1236,7 +1251,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg2);
tcg_out_st32_rwb(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, addr_reg);
tcg_out_bswap32(s, COND_EQ, TCG_REG_R0, data_reg);
tcg_out_st32_12(s, COND_EQ, data_reg, TCG_REG_R1, 4);
tcg_out_st32_12(s, COND_EQ, TCG_REG_R0, TCG_REG_R1, 4);
} else {
tcg_out_st32_rwb(s, COND_EQ, data_reg, TCG_REG_R1, addr_reg);
tcg_out_st32_12(s, COND_EQ, data_reg2, TCG_REG_R1, 4);
@ -1245,7 +1260,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
}
label_ptr = (void *) s->code_ptr;
tcg_out_b(s, COND_EQ, 8);
tcg_out_b_noaddr(s, COND_EQ);
/* TODO: move this code to where the constants pool will be */
tcg_out_dat_reg(s, COND_AL, ARITH_MOV,
@ -1317,7 +1332,7 @@ static inline void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
if (opc == 3)
tcg_out_dat_imm(s, COND_AL, ARITH_ADD, TCG_REG_R13, TCG_REG_R13, 0x10);
*label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
reloc_pc24(label_ptr, (tcg_target_long)s->code_ptr);
#else /* !CONFIG_SOFTMMU */
if (GUEST_BASE) {
uint32_t offset = GUEST_BASE;
@ -1399,7 +1414,7 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
/* Direct jump method */
#if defined(USE_DIRECT_JUMP)
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;
tcg_out_b(s, COND_AL, 8);
tcg_out_b_noaddr(s, COND_AL);
#else
tcg_out_ld32_12(s, COND_AL, TCG_REG_PC, TCG_REG_PC, -4);
s->tb_jmp_offset[args[0]] = s->code_ptr - s->code_buf;

View File

@ -1329,7 +1329,7 @@ static inline void tcg_out_bswap32(TCGContext *s, TCGArg ret, TCGArg arg)
static inline void tcg_out_bswap64(TCGContext *s, TCGArg ret, TCGArg arg)
{
tcg_out_bundle(s, mII,
tcg_out_bundle(s, miI,
tcg_opc_m48(TCG_REG_P0, OPC_NOP_M48, 0),
tcg_opc_i18(TCG_REG_P0, OPC_NOP_I18, 0),
tcg_opc_i3 (TCG_REG_P0, OPC_MUX1_I3, ret, arg, 0xb));

View File

@ -352,7 +352,7 @@ static inline void tcg_out_opc_imm(TCGContext *s, int opc, int rt, int rs, int i
static inline void tcg_out_opc_br(TCGContext *s, int opc, int rt, int rs)
{
/* We need to keep the offset unchanged for retranslation */
uint16_t offset = (uint16_t)(*(uint32_t *) &s->code_ptr);
uint16_t offset = (uint16_t)(*(uint32_t *) s->code_ptr);
tcg_out_opc_imm(s, opc, rt, rs, offset);
}

View File

@ -32,10 +32,18 @@ void qemu_spice_input_init(void);
void qemu_spice_audio_init(void);
void qemu_spice_display_init(DisplayState *ds);
int qemu_spice_add_interface(SpiceBaseInstance *sin);
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_connected, bool disconnect_if_connected);
int qemu_spice_set_pw_expire(time_t expires);
void do_info_spice_print(Monitor *mon, const QObject *data);
void do_info_spice(Monitor *mon, QObject **ret_data);
#else /* CONFIG_SPICE */
#define using_spice 0
#define qemu_spice_set_passwd(_p, _f1, _f2) (-1)
#define qemu_spice_set_pw_expire(_e) (-1)
#endif /* CONFIG_SPICE */

View File

@ -18,16 +18,26 @@
#include <spice.h>
#include <spice-experimental.h>
#include <netdb.h>
#include "qemu-common.h"
#include "qemu-spice.h"
#include "qemu-timer.h"
#include "qemu-queue.h"
#include "qemu-x509.h"
#include "qemu_socket.h"
#include "qint.h"
#include "qbool.h"
#include "qstring.h"
#include "qjson.h"
#include "monitor.h"
/* core bits */
static SpiceServer *spice_server;
static const char *auth = "spice";
static char *auth_passwd;
static time_t auth_expires = TIME_MAX;
int using_spice = 0;
struct SpiceTimer {
@ -121,6 +131,118 @@ static void watch_remove(SpiceWatch *watch)
qemu_free(watch);
}
#if SPICE_INTERFACE_CORE_MINOR >= 3
typedef struct ChannelList ChannelList;
struct ChannelList {
SpiceChannelEventInfo *info;
QTAILQ_ENTRY(ChannelList) link;
};
static QTAILQ_HEAD(, ChannelList) channel_list = QTAILQ_HEAD_INITIALIZER(channel_list);
static void channel_list_add(SpiceChannelEventInfo *info)
{
ChannelList *item;
item = qemu_mallocz(sizeof(*item));
item->info = info;
QTAILQ_INSERT_TAIL(&channel_list, item, link);
}
static void channel_list_del(SpiceChannelEventInfo *info)
{
ChannelList *item;
QTAILQ_FOREACH(item, &channel_list, link) {
if (item->info != info) {
continue;
}
QTAILQ_REMOVE(&channel_list, item, link);
qemu_free(item);
return;
}
}
static void add_addr_info(QDict *dict, struct sockaddr *addr, int len)
{
char host[NI_MAXHOST], port[NI_MAXSERV];
const char *family;
getnameinfo(addr, len, host, sizeof(host), port, sizeof(port),
NI_NUMERICHOST | NI_NUMERICSERV);
family = inet_strfamily(addr->sa_family);
qdict_put(dict, "host", qstring_from_str(host));
qdict_put(dict, "port", qstring_from_str(port));
qdict_put(dict, "family", qstring_from_str(family));
}
static void add_channel_info(QDict *dict, SpiceChannelEventInfo *info)
{
int tls = info->flags & SPICE_CHANNEL_EVENT_FLAG_TLS;
qdict_put(dict, "connection-id", qint_from_int(info->connection_id));
qdict_put(dict, "channel-type", qint_from_int(info->type));
qdict_put(dict, "channel-id", qint_from_int(info->id));
qdict_put(dict, "tls", qbool_from_int(tls));
}
static QList *channel_list_get(void)
{
ChannelList *item;
QList *list;
QDict *dict;
list = qlist_new();
QTAILQ_FOREACH(item, &channel_list, link) {
dict = qdict_new();
add_addr_info(dict, &item->info->paddr, item->info->plen);
add_channel_info(dict, item->info);
qlist_append(list, dict);
}
return list;
}
static void channel_event(int event, SpiceChannelEventInfo *info)
{
static const int qevent[] = {
[ SPICE_CHANNEL_EVENT_CONNECTED ] = QEVENT_SPICE_CONNECTED,
[ SPICE_CHANNEL_EVENT_INITIALIZED ] = QEVENT_SPICE_INITIALIZED,
[ SPICE_CHANNEL_EVENT_DISCONNECTED ] = QEVENT_SPICE_DISCONNECTED,
};
QDict *server, *client;
QObject *data;
client = qdict_new();
add_addr_info(client, &info->paddr, info->plen);
server = qdict_new();
add_addr_info(server, &info->laddr, info->llen);
if (event == SPICE_CHANNEL_EVENT_INITIALIZED) {
qdict_put(server, "auth", qstring_from_str(auth));
add_channel_info(client, info);
channel_list_add(info);
}
if (event == SPICE_CHANNEL_EVENT_DISCONNECTED) {
channel_list_del(info);
}
data = qobject_from_jsonf("{ 'client': %p, 'server': %p }",
QOBJECT(client), QOBJECT(server));
monitor_protocol_event(qevent[event], data);
qobject_decref(data);
}
#else /* SPICE_INTERFACE_CORE_MINOR >= 3 */
static QList *channel_list_get(void)
{
return NULL;
}
#endif /* SPICE_INTERFACE_CORE_MINOR >= 3 */
static SpiceCoreInterface core_interface = {
.base.type = SPICE_INTERFACE_CORE,
.base.description = "qemu core services",
@ -135,6 +257,10 @@ static SpiceCoreInterface core_interface = {
.watch_add = watch_add,
.watch_update_mask = watch_update_mask,
.watch_remove = watch_remove,
#if SPICE_INTERFACE_CORE_MINOR >= 3
.channel_event = channel_event,
#endif
};
/* config string parsing */
@ -204,6 +330,92 @@ static const char *wan_compression_names[] = {
/* functions for the rest of qemu */
static void info_spice_iter(QObject *obj, void *opaque)
{
QDict *client;
Monitor *mon = opaque;
client = qobject_to_qdict(obj);
monitor_printf(mon, "Channel:\n");
monitor_printf(mon, " address: %s:%s%s\n",
qdict_get_str(client, "host"),
qdict_get_str(client, "port"),
qdict_get_bool(client, "tls") ? " [tls]" : "");
monitor_printf(mon, " session: %" PRId64 "\n",
qdict_get_int(client, "connection-id"));
monitor_printf(mon, " channel: %d:%d\n",
(int)qdict_get_int(client, "channel-type"),
(int)qdict_get_int(client, "channel-id"));
}
void do_info_spice_print(Monitor *mon, const QObject *data)
{
QDict *server;
QList *channels;
const char *host;
int port;
server = qobject_to_qdict(data);
if (qdict_get_bool(server, "enabled") == 0) {
monitor_printf(mon, "Server: disabled\n");
return;
}
monitor_printf(mon, "Server:\n");
host = qdict_get_str(server, "host");
port = qdict_get_try_int(server, "port", -1);
if (port != -1) {
monitor_printf(mon, " address: %s:%d\n", host, port);
}
port = qdict_get_try_int(server, "tls-port", -1);
if (port != -1) {
monitor_printf(mon, " address: %s:%d [tls]\n", host, port);
}
monitor_printf(mon, " auth: %s\n", qdict_get_str(server, "auth"));
channels = qdict_get_qlist(server, "channels");
if (qlist_empty(channels)) {
monitor_printf(mon, "Channels: none\n");
} else {
qlist_iter(channels, info_spice_iter, mon);
}
}
void do_info_spice(Monitor *mon, QObject **ret_data)
{
QemuOpts *opts = QTAILQ_FIRST(&qemu_spice_opts.head);
QDict *server;
QList *clist;
const char *addr;
int port, tls_port;
if (!spice_server) {
*ret_data = qobject_from_jsonf("{ 'enabled': false }");
return;
}
addr = qemu_opt_get(opts, "addr");
port = qemu_opt_get_number(opts, "port", 0);
tls_port = qemu_opt_get_number(opts, "tls-port", 0);
clist = channel_list_get();
server = qdict_new();
qdict_put(server, "enabled", qbool_from_int(true));
qdict_put(server, "auth", qstring_from_str(auth));
qdict_put(server, "host", qstring_from_str(addr ? addr : "0.0.0.0"));
if (port) {
qdict_put(server, "port", qint_from_int(port));
}
if (tls_port) {
qdict_put(server, "tls-port", qint_from_int(tls_port));
}
if (clist) {
qdict_put(server, "channels", clist);
}
*ret_data = QOBJECT(server);
}
static int add_channel(const char *name, const char *value, void *opaque)
{
int security = 0;
@ -316,6 +528,7 @@ void qemu_spice_init(void)
spice_server_set_ticket(spice_server, password, 0, 0, 0);
}
if (qemu_opt_get_bool(opts, "disable-ticketing", 0)) {
auth = "none";
spice_server_set_noauth(spice_server);
}
@ -370,9 +583,57 @@ void qemu_spice_init(void)
int qemu_spice_add_interface(SpiceBaseInstance *sin)
{
if (!spice_server) {
if (QTAILQ_FIRST(&qemu_spice_opts.head) != NULL) {
fprintf(stderr, "Oops: spice configured but not active\n");
exit(1);
}
/*
* Create a spice server instance.
* It does *not* listen on the network.
* It handles QXL local rendering only.
*
* With a command line like '-vnc :0 -vga qxl' you'll end up here.
*/
spice_server = spice_server_new();
spice_server_init(spice_server, &core_interface);
}
return spice_server_add_interface(spice_server, sin);
}
static int qemu_spice_set_ticket(bool fail_if_conn, bool disconnect_if_conn)
{
time_t lifetime, now = time(NULL);
char *passwd;
if (now < auth_expires) {
passwd = auth_passwd;
lifetime = (auth_expires - now);
if (lifetime > INT_MAX) {
lifetime = INT_MAX;
}
} else {
passwd = NULL;
lifetime = 1;
}
return spice_server_set_ticket(spice_server, passwd, lifetime,
fail_if_conn, disconnect_if_conn);
}
int qemu_spice_set_passwd(const char *passwd,
bool fail_if_conn, bool disconnect_if_conn)
{
free(auth_passwd);
auth_passwd = strdup(passwd);
return qemu_spice_set_ticket(fail_if_conn, disconnect_if_conn);
}
int qemu_spice_set_pw_expire(time_t expires)
{
auth_expires = expires;
return qemu_spice_set_ticket(false, false);
}
static void spice_register_config(void)
{
qemu_add_opts(&qemu_spice_opts);

View File

@ -2082,18 +2082,15 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
unsigned char response[VNC_AUTH_CHALLENGE_SIZE];
int i, j, pwlen;
unsigned char key[8];
time_t now = time(NULL);
if (!vs->vd->password || !vs->vd->password[0]) {
VNC_DEBUG("No password configured on server");
vnc_write_u32(vs, 1); /* Reject auth */
if (vs->minor >= 8) {
static const char err[] = "Authentication failed";
vnc_write_u32(vs, sizeof(err));
vnc_write(vs, err, sizeof(err));
}
vnc_flush(vs);
vnc_client_error(vs);
return 0;
goto reject;
}
if (vs->vd->expires < now) {
VNC_DEBUG("Password is expired");
goto reject;
}
memcpy(response, vs->challenge, VNC_AUTH_CHALLENGE_SIZE);
@ -2109,14 +2106,7 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
/* Compare expected vs actual challenge response */
if (memcmp(response, data, VNC_AUTH_CHALLENGE_SIZE) != 0) {
VNC_DEBUG("Client challenge reponse did not match\n");
vnc_write_u32(vs, 1); /* Reject auth */
if (vs->minor >= 8) {
static const char err[] = "Authentication failed";
vnc_write_u32(vs, sizeof(err));
vnc_write(vs, err, sizeof(err));
}
vnc_flush(vs);
vnc_client_error(vs);
goto reject;
} else {
VNC_DEBUG("Accepting VNC challenge response\n");
vnc_write_u32(vs, 0); /* Accept auth */
@ -2125,6 +2115,17 @@ static int protocol_client_auth_vnc(VncState *vs, uint8_t *data, size_t len)
start_client_init(vs);
}
return 0;
reject:
vnc_write_u32(vs, 1); /* Reject auth */
if (vs->minor >= 8) {
static const char err[] = "Authentication failed";
vnc_write_u32(vs, sizeof(err));
vnc_write(vs, err, sizeof(err));
}
vnc_flush(vs);
vnc_client_error(vs);
return 0;
}
void start_auth_vnc(VncState *vs)
@ -2436,6 +2437,7 @@ void vnc_display_init(DisplayState *ds)
vs->ds = ds;
QTAILQ_INIT(&vs->clients);
vs->expires = TIME_MAX;
if (keyboard_layout)
vs->kbd_layout = init_keyboard_layout(name2keysym, keyboard_layout);
@ -2507,6 +2509,14 @@ int vnc_display_password(DisplayState *ds, const char *password)
return 0;
}
int vnc_display_pw_expire(DisplayState *ds, time_t expires)
{
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;
vs->expires = expires;
return 0;
}
char *vnc_display_local_addr(DisplayState *ds)
{
VncDisplay *vs = ds ? (VncDisplay *)ds->opaque : vnc_display;

View File

@ -120,6 +120,7 @@ struct VncDisplay
char *display;
char *password;
time_t expires;
int auth;
bool lossy;
#ifdef CONFIG_VNC_TLS

View File

@ -306,14 +306,15 @@ USBDevice *usb_host_device_open(const char *devname)
{
struct usb_device_info bus_info, dev_info;
USBDevice *d = NULL;
USBHostDevice *dev;
USBHostDevice *dev, *ret = NULL;
char ctlpath[PATH_MAX + 1];
char buspath[PATH_MAX + 1];
int bfd, dfd, bus, address, i;
int ugendebug = UGEN_DEBUG_LEVEL;
if (usb_host_find_device(&bus, &address, devname) < 0)
return NULL;
if (usb_host_find_device(&bus, &address, devname) < 0) {
goto fail;
}
snprintf(buspath, PATH_MAX, "/dev/usb%d", bus);
@ -323,7 +324,7 @@ USBDevice *usb_host_device_open(const char *devname)
printf("usb_host_device_open: failed to open usb bus - %s\n",
strerror(errno));
#endif
return NULL;
goto fail;
}
bus_info.udi_addr = address;
@ -332,7 +333,7 @@ USBDevice *usb_host_device_open(const char *devname)
printf("usb_host_device_open: failed to grab bus information - %s\n",
strerror(errno));
#endif
return NULL;
goto fail_bfd;
}
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
@ -350,46 +351,52 @@ USBDevice *usb_host_device_open(const char *devname)
ctlpath, strerror(errno));
#endif
}
goto fail_dfd;
}
if (dfd >= 0) {
if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
if (ioctl(dfd, USB_GET_DEVICEINFO, &dev_info) < 0) {
#ifdef DEBUG
printf("usb_host_device_open: failed to grab device info - %s\n",
strerror(errno));
printf("usb_host_device_open: failed to grab device info - %s\n",
strerror(errno));
#endif
goto fail;
}
d = usb_create(NULL /* FIXME */, "usb-host");
dev = DO_UPCAST(USBHostDevice, dev, d);
if (dev_info.udi_speed == 1)
dev->dev.speed = USB_SPEED_LOW - 1;
else
dev->dev.speed = USB_SPEED_FULL - 1;
if (strncmp(dev_info.udi_product, "product", 7) != 0)
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
dev_info.udi_product);
else
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%s", devname);
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
/* Mark the endpoints as not yet open */
for (i = 0; i < USB_MAX_ENDPOINTS; i++)
dev->ep_fd[i] = -1;
ioctl(dfd, USB_SETDEBUG, &ugendebug);
return (USBDevice *)dev;
goto fail_dfd;
}
d = usb_create(NULL /* FIXME */, "usb-host");
dev = DO_UPCAST(USBHostDevice, dev, d);
if (dev_info.udi_speed == 1) {
dev->dev.speed = USB_SPEED_LOW - 1;
} else {
dev->dev.speed = USB_SPEED_FULL - 1;
}
if (strncmp(dev_info.udi_product, "product", 7) != 0) {
pstrcpy(dev->dev.product_desc, sizeof(dev->dev.product_desc),
dev_info.udi_product);
} else {
snprintf(dev->dev.product_desc, sizeof(dev->dev.product_desc),
"host:%s", devname);
}
pstrcpy(dev->devpath, sizeof(dev->devpath), "/dev/");
pstrcat(dev->devpath, sizeof(dev->devpath), dev_info.udi_devnames[0]);
/* Mark the endpoints as not yet open */
for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
dev->ep_fd[i] = -1;
}
ioctl(dfd, USB_SETDEBUG, &ugendebug);
ret = (USBDevice *)dev;
fail_dfd:
close(dfd);
fail_bfd:
close(bfd);
fail:
return NULL;
return ret;
}
static struct USBDeviceInfo usb_host_dev_info = {

12
vl.c
View File

@ -759,8 +759,10 @@ char *get_boot_devices_list(uint32_t *size)
}
if (i->suffix && devpath) {
bootpath = qemu_malloc(strlen(devpath) + strlen(i->suffix) + 1);
sprintf(bootpath, "%s%s", devpath, i->suffix);
size_t bootpathlen = strlen(devpath) + strlen(i->suffix) + 1;
bootpath = qemu_malloc(bootpathlen);
snprintf(bootpath, bootpathlen, "%s%s", devpath, i->suffix);
qemu_free(devpath);
} else if (devpath) {
bootpath = devpath;
@ -1502,6 +1504,8 @@ static void select_vgahw (const char *p)
vga_interface_type = VGA_VMWARE;
} else if (strstart(p, "xenfb", &opts)) {
vga_interface_type = VGA_XENFB;
} else if (strstart(p, "qxl", &opts)) {
vga_interface_type = VGA_QXL;
} else if (!strstart(p, "none", &opts)) {
invalid_vga:
fprintf(stderr, "Unknown vga type: %s\n", p);
@ -2601,7 +2605,7 @@ int main(int argc, char **argv, char **envp)
if (p != NULL) {
*p++ = 0;
if (strncmp(p, "process=", 8)) {
fprintf(stderr, "Unknown subargument %s to -name", p);
fprintf(stderr, "Unknown subargument %s to -name\n", p);
exit(1);
}
p += 8;
@ -3053,7 +3057,7 @@ int main(int argc, char **argv, char **envp)
}
}
#ifdef CONFIG_SPICE
if (using_spice) {
if (using_spice && !qxl_enabled) {
qemu_spice_display_init(ds);
}
#endif