Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
qemu
提交
296af7c9
Q
qemu
项目概览
openeuler
/
qemu
通知
10
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
Q
qemu
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
296af7c9
编写于
3月 29, 2010
作者:
B
Blue Swirl
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Refactor CPUState handling out of vl.c
Signed-off-by:
N
Blue Swirl
<
blauwirbel@gmail.com
>
上级
de06f8d1
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
795 addition
and
747 deletion
+795
-747
Makefile.target
Makefile.target
+1
-1
cpus.c
cpus.c
+773
-0
cpus.h
cpus.h
+18
-0
vl.c
vl.c
+3
-746
未找到文件。
Makefile.target
浏览文件 @
296af7c9
...
...
@@ -161,7 +161,7 @@ endif #CONFIG_BSD_USER
# System emulator target
ifdef
CONFIG_SOFTMMU
obj-y
=
vl.o monitor.o machine.o gdbstub.o
obj-y
=
vl.o
cpus.o
monitor.o machine.o gdbstub.o
obj-y
+=
qemu-timer.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
...
...
cpus.c
0 → 100644
浏览文件 @
296af7c9
/*
* QEMU System Emulator
*
* Copyright (c) 2003-2008 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
/* Needed early for CONFIG_BSD etc. */
#include "config-host.h"
#include "monitor.h"
#include "sysemu.h"
#include "gdbstub.h"
#include "dma.h"
#include "kvm.h"
#include "cpus.h"
static
CPUState
*
cur_cpu
;
static
CPUState
*
next_cpu
;
/***********************************************************/
void
hw_error
(
const
char
*
fmt
,
...)
{
va_list
ap
;
CPUState
*
env
;
va_start
(
ap
,
fmt
);
fprintf
(
stderr
,
"qemu: hardware error: "
);
vfprintf
(
stderr
,
fmt
,
ap
);
fprintf
(
stderr
,
"
\n
"
);
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
{
fprintf
(
stderr
,
"CPU #%d:
\n
"
,
env
->
cpu_index
);
#ifdef TARGET_I386
cpu_dump_state
(
env
,
stderr
,
fprintf
,
X86_DUMP_FPU
);
#else
cpu_dump_state
(
env
,
stderr
,
fprintf
,
0
);
#endif
}
va_end
(
ap
);
abort
();
}
void
cpu_synchronize_all_states
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_state
(
cpu
);
}
}
void
cpu_synchronize_all_post_reset
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_post_reset
(
cpu
);
}
}
void
cpu_synchronize_all_post_init
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_post_init
(
cpu
);
}
}
static
void
do_vm_stop
(
int
reason
)
{
if
(
vm_running
)
{
cpu_disable_ticks
();
vm_running
=
0
;
pause_all_vcpus
();
vm_state_notify
(
0
,
reason
);
monitor_protocol_event
(
QEVENT_STOP
,
NULL
);
}
}
static
int
cpu_can_run
(
CPUState
*
env
)
{
if
(
env
->
stop
)
return
0
;
if
(
env
->
stopped
)
return
0
;
if
(
!
vm_running
)
return
0
;
return
1
;
}
static
int
cpu_has_work
(
CPUState
*
env
)
{
if
(
env
->
stop
)
return
1
;
if
(
env
->
stopped
)
return
0
;
if
(
!
env
->
halted
)
return
1
;
if
(
qemu_cpu_has_work
(
env
))
return
1
;
return
0
;
}
static
int
tcg_has_work
(
void
)
{
CPUState
*
env
;
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
if
(
cpu_has_work
(
env
))
return
1
;
return
0
;
}
#ifndef _WIN32
static
int
io_thread_fd
=
-
1
;
static
void
qemu_event_increment
(
void
)
{
/* Write 8 bytes to be compatible with eventfd. */
static
uint64_t
val
=
1
;
ssize_t
ret
;
if
(
io_thread_fd
==
-
1
)
return
;
do
{
ret
=
write
(
io_thread_fd
,
&
val
,
sizeof
(
val
));
}
while
(
ret
<
0
&&
errno
==
EINTR
);
/* EAGAIN is fine, a read must be pending. */
if
(
ret
<
0
&&
errno
!=
EAGAIN
)
{
fprintf
(
stderr
,
"qemu_event_increment: write() filed: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
}
static
void
qemu_event_read
(
void
*
opaque
)
{
int
fd
=
(
unsigned
long
)
opaque
;
ssize_t
len
;
char
buffer
[
512
];
/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
do
{
len
=
read
(
fd
,
buffer
,
sizeof
(
buffer
));
}
while
((
len
==
-
1
&&
errno
==
EINTR
)
||
len
==
sizeof
(
buffer
));
}
static
int
qemu_event_init
(
void
)
{
int
err
;
int
fds
[
2
];
err
=
qemu_eventfd
(
fds
);
if
(
err
==
-
1
)
return
-
errno
;
err
=
fcntl_setfl
(
fds
[
0
],
O_NONBLOCK
);
if
(
err
<
0
)
goto
fail
;
err
=
fcntl_setfl
(
fds
[
1
],
O_NONBLOCK
);
if
(
err
<
0
)
goto
fail
;
qemu_set_fd_handler2
(
fds
[
0
],
NULL
,
qemu_event_read
,
NULL
,
(
void
*
)(
unsigned
long
)
fds
[
0
]);
io_thread_fd
=
fds
[
1
];
return
0
;
fail:
close
(
fds
[
0
]);
close
(
fds
[
1
]);
return
err
;
}
#else
HANDLE
qemu_event_handle
;
static
void
dummy_event_handler
(
void
*
opaque
)
{
}
static
int
qemu_event_init
(
void
)
{
qemu_event_handle
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
!
qemu_event_handle
)
{
fprintf
(
stderr
,
"Failed CreateEvent: %ld
\n
"
,
GetLastError
());
return
-
1
;
}
qemu_add_wait_object
(
qemu_event_handle
,
dummy_event_handler
,
NULL
);
return
0
;
}
static
void
qemu_event_increment
(
void
)
{
if
(
!
SetEvent
(
qemu_event_handle
))
{
fprintf
(
stderr
,
"qemu_event_increment: SetEvent failed: %ld
\n
"
,
GetLastError
());
exit
(
1
);
}
}
#endif
#ifndef CONFIG_IOTHREAD
int
qemu_init_main_loop
(
void
)
{
return
qemu_event_init
();
}
void
qemu_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
env
->
nr_cores
=
smp_cores
;
env
->
nr_threads
=
smp_threads
;
if
(
kvm_enabled
())
kvm_init_vcpu
(
env
);
return
;
}
int
qemu_cpu_self
(
void
*
env
)
{
return
1
;
}
void
resume_all_vcpus
(
void
)
{
}
void
pause_all_vcpus
(
void
)
{
}
void
qemu_cpu_kick
(
void
*
env
)
{
return
;
}
void
qemu_notify_event
(
void
)
{
CPUState
*
env
=
cpu_single_env
;
qemu_event_increment
();
if
(
env
)
{
cpu_exit
(
env
);
}
if
(
next_cpu
&&
env
!=
next_cpu
)
{
cpu_exit
(
next_cpu
);
}
}
void
qemu_mutex_lock_iothread
(
void
)
{}
void
qemu_mutex_unlock_iothread
(
void
)
{}
void
vm_stop
(
int
reason
)
{
do_vm_stop
(
reason
);
}
#else
/* CONFIG_IOTHREAD */
#include "qemu-thread.h"
QemuMutex
qemu_global_mutex
;
static
QemuMutex
qemu_fair_mutex
;
static
QemuThread
io_thread
;
static
QemuThread
*
tcg_cpu_thread
;
static
QemuCond
*
tcg_halt_cond
;
static
int
qemu_system_ready
;
/* cpu creation */
static
QemuCond
qemu_cpu_cond
;
/* system init */
static
QemuCond
qemu_system_cond
;
static
QemuCond
qemu_pause_cond
;
static
void
tcg_block_io_signals
(
void
);
static
void
kvm_block_io_signals
(
CPUState
*
env
);
static
void
unblock_io_signals
(
void
);
int
qemu_init_main_loop
(
void
)
{
int
ret
;
ret
=
qemu_event_init
();
if
(
ret
)
return
ret
;
qemu_cond_init
(
&
qemu_pause_cond
);
qemu_mutex_init
(
&
qemu_fair_mutex
);
qemu_mutex_init
(
&
qemu_global_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
unblock_io_signals
();
qemu_thread_self
(
&
io_thread
);
return
0
;
}
static
void
qemu_wait_io_event_common
(
CPUState
*
env
)
{
if
(
env
->
stop
)
{
env
->
stop
=
0
;
env
->
stopped
=
1
;
qemu_cond_signal
(
&
qemu_pause_cond
);
}
}
static
void
qemu_wait_io_event
(
CPUState
*
env
)
{
while
(
!
tcg_has_work
())
qemu_cond_timedwait
(
env
->
halt_cond
,
&
qemu_global_mutex
,
1000
);
qemu_mutex_unlock
(
&
qemu_global_mutex
);
/*
* Users of qemu_global_mutex can be starved, having no chance
* to acquire it since this path will get to it first.
* So use another lock to provide fairness.
*/
qemu_mutex_lock
(
&
qemu_fair_mutex
);
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
qemu_wait_io_event_common
(
env
);
}
static
void
qemu_kvm_eat_signal
(
CPUState
*
env
,
int
timeout
)
{
struct
timespec
ts
;
int
r
,
e
;
siginfo_t
siginfo
;
sigset_t
waitset
;
ts
.
tv_sec
=
timeout
/
1000
;
ts
.
tv_nsec
=
(
timeout
%
1000
)
*
1000000
;
sigemptyset
(
&
waitset
);
sigaddset
(
&
waitset
,
SIG_IPI
);
qemu_mutex_unlock
(
&
qemu_global_mutex
);
r
=
sigtimedwait
(
&
waitset
,
&
siginfo
,
&
ts
);
e
=
errno
;
qemu_mutex_lock
(
&
qemu_global_mutex
);
if
(
r
==
-
1
&&
!
(
e
==
EAGAIN
||
e
==
EINTR
))
{
fprintf
(
stderr
,
"sigtimedwait: %s
\n
"
,
strerror
(
e
));
exit
(
1
);
}
}
static
void
qemu_kvm_wait_io_event
(
CPUState
*
env
)
{
while
(
!
cpu_has_work
(
env
))
qemu_cond_timedwait
(
env
->
halt_cond
,
&
qemu_global_mutex
,
1000
);
qemu_kvm_eat_signal
(
env
,
0
);
qemu_wait_io_event_common
(
env
);
}
static
int
qemu_cpu_exec
(
CPUState
*
env
);
static
void
*
kvm_cpu_thread_fn
(
void
*
arg
)
{
CPUState
*
env
=
arg
;
qemu_thread_self
(
env
->
thread
);
if
(
kvm_enabled
())
kvm_init_vcpu
(
env
);
kvm_block_io_signals
(
env
);
/* signal CPU creation */
qemu_mutex_lock
(
&
qemu_global_mutex
);
env
->
created
=
1
;
qemu_cond_signal
(
&
qemu_cpu_cond
);
/* and wait for machine initialization */
while
(
!
qemu_system_ready
)
qemu_cond_timedwait
(
&
qemu_system_cond
,
&
qemu_global_mutex
,
100
);
while
(
1
)
{
if
(
cpu_can_run
(
env
))
qemu_cpu_exec
(
env
);
qemu_kvm_wait_io_event
(
env
);
}
return
NULL
;
}
static
void
*
tcg_cpu_thread_fn
(
void
*
arg
)
{
CPUState
*
env
=
arg
;
tcg_block_io_signals
();
qemu_thread_self
(
env
->
thread
);
/* signal CPU creation */
qemu_mutex_lock
(
&
qemu_global_mutex
);
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
env
->
created
=
1
;
qemu_cond_signal
(
&
qemu_cpu_cond
);
/* and wait for machine initialization */
while
(
!
qemu_system_ready
)
qemu_cond_timedwait
(
&
qemu_system_cond
,
&
qemu_global_mutex
,
100
);
while
(
1
)
{
tcg_cpu_exec
();
qemu_wait_io_event
(
cur_cpu
);
}
return
NULL
;
}
void
qemu_cpu_kick
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
qemu_cond_broadcast
(
env
->
halt_cond
);
if
(
kvm_enabled
())
qemu_thread_signal
(
env
->
thread
,
SIG_IPI
);
}
int
qemu_cpu_self
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
QemuThread
this
;
qemu_thread_self
(
&
this
);
return
qemu_thread_equal
(
&
this
,
env
->
thread
);
}
static
void
cpu_signal
(
int
sig
)
{
if
(
cpu_single_env
)
cpu_exit
(
cpu_single_env
);
}
static
void
tcg_block_io_signals
(
void
)
{
sigset_t
set
;
struct
sigaction
sigact
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
sigaddset
(
&
set
,
SIGCHLD
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_UNBLOCK
,
&
set
,
NULL
);
memset
(
&
sigact
,
0
,
sizeof
(
sigact
));
sigact
.
sa_handler
=
cpu_signal
;
sigaction
(
SIG_IPI
,
&
sigact
,
NULL
);
}
static
void
dummy_signal
(
int
sig
)
{
}
static
void
kvm_block_io_signals
(
CPUState
*
env
)
{
int
r
;
sigset_t
set
;
struct
sigaction
sigact
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
sigaddset
(
&
set
,
SIGCHLD
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
pthread_sigmask
(
SIG_BLOCK
,
NULL
,
&
set
);
sigdelset
(
&
set
,
SIG_IPI
);
memset
(
&
sigact
,
0
,
sizeof
(
sigact
));
sigact
.
sa_handler
=
dummy_signal
;
sigaction
(
SIG_IPI
,
&
sigact
,
NULL
);
r
=
kvm_set_signal_mask
(
env
,
&
set
);
if
(
r
)
{
fprintf
(
stderr
,
"kvm_set_signal_mask: %s
\n
"
,
strerror
(
r
));
exit
(
1
);
}
}
static
void
unblock_io_signals
(
void
)
{
sigset_t
set
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
pthread_sigmask
(
SIG_UNBLOCK
,
&
set
,
NULL
);
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
}
static
void
qemu_signal_lock
(
unsigned
int
msecs
)
{
qemu_mutex_lock
(
&
qemu_fair_mutex
);
while
(
qemu_mutex_trylock
(
&
qemu_global_mutex
))
{
qemu_thread_signal
(
tcg_cpu_thread
,
SIG_IPI
);
if
(
!
qemu_mutex_timedlock
(
&
qemu_global_mutex
,
msecs
))
break
;
}
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
}
void
qemu_mutex_lock_iothread
(
void
)
{
if
(
kvm_enabled
())
{
qemu_mutex_lock
(
&
qemu_fair_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
}
else
qemu_signal_lock
(
100
);
}
void
qemu_mutex_unlock_iothread
(
void
)
{
qemu_mutex_unlock
(
&
qemu_global_mutex
);
}
static
int
all_vcpus_paused
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
if
(
!
penv
->
stopped
)
return
0
;
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
return
1
;
}
void
pause_all_vcpus
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
penv
->
stop
=
1
;
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
qemu_cpu_kick
(
penv
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
while
(
!
all_vcpus_paused
())
{
qemu_cond_timedwait
(
&
qemu_pause_cond
,
&
qemu_global_mutex
,
100
);
penv
=
first_cpu
;
while
(
penv
)
{
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
}
}
void
resume_all_vcpus
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
penv
->
stop
=
0
;
penv
->
stopped
=
0
;
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
qemu_cpu_kick
(
penv
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
}
static
void
tcg_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
/* share a single thread for all cpus with TCG */
if
(
!
tcg_cpu_thread
)
{
env
->
thread
=
qemu_mallocz
(
sizeof
(
QemuThread
));
env
->
halt_cond
=
qemu_mallocz
(
sizeof
(
QemuCond
));
qemu_cond_init
(
env
->
halt_cond
);
qemu_thread_create
(
env
->
thread
,
tcg_cpu_thread_fn
,
env
);
while
(
env
->
created
==
0
)
qemu_cond_timedwait
(
&
qemu_cpu_cond
,
&
qemu_global_mutex
,
100
);
tcg_cpu_thread
=
env
->
thread
;
tcg_halt_cond
=
env
->
halt_cond
;
}
else
{
env
->
thread
=
tcg_cpu_thread
;
env
->
halt_cond
=
tcg_halt_cond
;
}
}
static
void
kvm_start_vcpu
(
CPUState
*
env
)
{
env
->
thread
=
qemu_mallocz
(
sizeof
(
QemuThread
));
env
->
halt_cond
=
qemu_mallocz
(
sizeof
(
QemuCond
));
qemu_cond_init
(
env
->
halt_cond
);
qemu_thread_create
(
env
->
thread
,
kvm_cpu_thread_fn
,
env
);
while
(
env
->
created
==
0
)
qemu_cond_timedwait
(
&
qemu_cpu_cond
,
&
qemu_global_mutex
,
100
);
}
void
qemu_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
env
->
nr_cores
=
smp_cores
;
env
->
nr_threads
=
smp_threads
;
if
(
kvm_enabled
())
kvm_start_vcpu
(
env
);
else
tcg_init_vcpu
(
env
);
}
void
qemu_notify_event
(
void
)
{
qemu_event_increment
();
}
static
void
qemu_system_vmstop_request
(
int
reason
)
{
vmstop_requested
=
reason
;
qemu_notify_event
();
}
void
vm_stop
(
int
reason
)
{
QemuThread
me
;
qemu_thread_self
(
&
me
);
if
(
!
qemu_thread_equal
(
&
me
,
&
io_thread
))
{
qemu_system_vmstop_request
(
reason
);
/*
* FIXME: should not return to device code in case
* vm_stop() has been requested.
*/
if
(
cpu_single_env
)
{
cpu_exit
(
cpu_single_env
);
cpu_single_env
->
stop
=
1
;
}
return
;
}
do_vm_stop
(
reason
);
}
#endif
static
int
qemu_cpu_exec
(
CPUState
*
env
)
{
int
ret
;
#ifdef CONFIG_PROFILER
int64_t
ti
;
#endif
#ifdef CONFIG_PROFILER
ti
=
profile_getclock
();
#endif
if
(
use_icount
)
{
int64_t
count
;
int
decr
;
qemu_icount
-=
(
env
->
icount_decr
.
u16
.
low
+
env
->
icount_extra
);
env
->
icount_decr
.
u16
.
low
=
0
;
env
->
icount_extra
=
0
;
count
=
qemu_icount_round
(
qemu_next_deadline
());
qemu_icount
+=
count
;
decr
=
(
count
>
0xffff
)
?
0xffff
:
count
;
count
-=
decr
;
env
->
icount_decr
.
u16
.
low
=
decr
;
env
->
icount_extra
=
count
;
}
ret
=
cpu_exec
(
env
);
#ifdef CONFIG_PROFILER
qemu_time
+=
profile_getclock
()
-
ti
;
#endif
if
(
use_icount
)
{
/* Fold pending instructions back into the
instruction counter, and clear the interrupt flag. */
qemu_icount
-=
(
env
->
icount_decr
.
u16
.
low
+
env
->
icount_extra
);
env
->
icount_decr
.
u32
=
0
;
env
->
icount_extra
=
0
;
}
return
ret
;
}
bool
tcg_cpu_exec
(
void
)
{
int
ret
=
0
;
if
(
next_cpu
==
NULL
)
next_cpu
=
first_cpu
;
for
(;
next_cpu
!=
NULL
;
next_cpu
=
next_cpu
->
next_cpu
)
{
CPUState
*
env
=
cur_cpu
=
next_cpu
;
qemu_clock_enable
(
vm_clock
,
(
cur_cpu
->
singlestep_enabled
&
SSTEP_NOTIMER
)
==
0
);
if
(
qemu_alarm_pending
())
break
;
if
(
cpu_can_run
(
env
))
ret
=
qemu_cpu_exec
(
env
);
else
if
(
env
->
stop
)
break
;
if
(
ret
==
EXCP_DEBUG
)
{
gdb_set_stop_cpu
(
env
);
debug_requested
=
EXCP_DEBUG
;
break
;
}
}
return
tcg_has_work
();
}
void
set_numa_modes
(
void
)
{
CPUState
*
env
;
int
i
;
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
{
for
(
i
=
0
;
i
<
nb_numa_nodes
;
i
++
)
{
if
(
node_cpumask
[
i
]
&
(
1
<<
env
->
cpu_index
))
{
env
->
numa_node
=
i
;
}
}
}
}
void
set_cpu_log
(
const
char
*
optarg
)
{
int
mask
;
const
CPULogItem
*
item
;
mask
=
cpu_str_to_log_mask
(
optarg
);
if
(
!
mask
)
{
printf
(
"Log items (comma separated):
\n
"
);
for
(
item
=
cpu_log_items
;
item
->
mask
!=
0
;
item
++
)
{
printf
(
"%-10s %s
\n
"
,
item
->
name
,
item
->
help
);
}
exit
(
1
);
}
cpu_set_log
(
mask
);
}
cpus.h
0 → 100644
浏览文件 @
296af7c9
#ifndef QEMU_CPUS_H
#define QEMU_CPUS_H
/* cpu-common.c */
int
qemu_init_main_loop
(
void
);
void
resume_all_vcpus
(
void
);
void
pause_all_vcpus
(
void
);
/* vl.c */
extern
int
smp_cores
;
extern
int
smp_threads
;
extern
int
debug_requested
;
void
vm_state_notify
(
int
running
,
int
reason
);
bool
tcg_cpu_exec
(
void
);
void
set_numa_modes
(
void
);
void
set_cpu_log
(
const
char
*
optarg
);
#endif
vl.c
浏览文件 @
296af7c9
...
...
@@ -160,6 +160,7 @@ int main(int argc, char **argv)
#include "slirp/libslirp.h"
#include "qemu-queue.h"
#include "cpus.h"
//#define DEBUG_NET
//#define DEBUG_SLIRP
...
...
@@ -249,8 +250,6 @@ int nb_numa_nodes;
uint64_t
node_mem
[
MAX_NODES
];
uint64_t
node_cpumask
[
MAX_NODES
];
static
CPUState
*
cur_cpu
;
static
CPUState
*
next_cpu
;
static
QEMUTimer
*
nographic_timer
;
uint8_t
qemu_uuid
[
16
];
...
...
@@ -314,28 +313,6 @@ static int default_driver_check(QemuOpts *opts, void *opaque)
target_phys_addr_t
isa_mem_base
=
0
;
PicState2
*
isa_pic
;
/***********************************************************/
void
hw_error
(
const
char
*
fmt
,
...)
{
va_list
ap
;
CPUState
*
env
;
va_start
(
ap
,
fmt
);
fprintf
(
stderr
,
"qemu: hardware error: "
);
vfprintf
(
stderr
,
fmt
,
ap
);
fprintf
(
stderr
,
"
\n
"
);
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
{
fprintf
(
stderr
,
"CPU #%d:
\n
"
,
env
->
cpu_index
);
#ifdef TARGET_I386
cpu_dump_state
(
env
,
stderr
,
fprintf
,
X86_DUMP_FPU
);
#else
cpu_dump_state
(
env
,
stderr
,
fprintf
,
0
);
#endif
}
va_end
(
ap
);
abort
();
}
static
void
set_proc_name
(
const
char
*
s
)
{
#if defined(__linux__) && defined(PR_SET_NAME)
...
...
@@ -1962,33 +1939,6 @@ static void nographic_update(void *opaque)
qemu_mod_timer
(
nographic_timer
,
interval
+
qemu_get_clock
(
rt_clock
));
}
void
cpu_synchronize_all_states
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_state
(
cpu
);
}
}
void
cpu_synchronize_all_post_reset
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_post_reset
(
cpu
);
}
}
void
cpu_synchronize_all_post_init
(
void
)
{
CPUState
*
cpu
;
for
(
cpu
=
first_cpu
;
cpu
;
cpu
=
cpu
->
next_cpu
)
{
cpu_synchronize_post_init
(
cpu
);
}
}
struct
vm_change_state_entry
{
VMChangeStateHandler
*
cb
;
void
*
opaque
;
...
...
@@ -2016,7 +1966,7 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
qemu_free
(
e
);
}
static
void
vm_state_notify
(
int
running
,
int
reason
)
void
vm_state_notify
(
int
running
,
int
reason
)
{
VMChangeStateEntry
*
e
;
...
...
@@ -2025,9 +1975,6 @@ static void vm_state_notify(int running, int reason)
}
}
static
void
resume_all_vcpus
(
void
);
static
void
pause_all_vcpus
(
void
);
void
vm_start
(
void
)
{
if
(
!
vm_running
)
{
...
...
@@ -2051,7 +1998,7 @@ static QTAILQ_HEAD(reset_handlers, QEMUResetEntry) reset_handlers =
static
int
reset_requested
;
static
int
shutdown_requested
;
static
int
powerdown_requested
;
static
int
debug_requested
;
int
debug_requested
;
static
int
vmstop_requested
;
int
qemu_shutdown_requested
(
void
)
...
...
@@ -2089,17 +2036,6 @@ static int qemu_vmstop_requested(void)
return
r
;
}
static
void
do_vm_stop
(
int
reason
)
{
if
(
vm_running
)
{
cpu_disable_ticks
();
vm_running
=
0
;
pause_all_vcpus
();
vm_state_notify
(
0
,
reason
);
monitor_protocol_event
(
QEVENT_STOP
,
NULL
);
}
}
void
qemu_register_reset
(
QEMUResetHandler
*
func
,
void
*
opaque
)
{
QEMUResetEntry
*
re
=
qemu_mallocz
(
sizeof
(
QEMUResetEntry
));
...
...
@@ -2156,589 +2092,6 @@ void qemu_system_powerdown_request(void)
qemu_notify_event
();
}
static
int
cpu_can_run
(
CPUState
*
env
)
{
if
(
env
->
stop
)
return
0
;
if
(
env
->
stopped
)
return
0
;
if
(
!
vm_running
)
return
0
;
return
1
;
}
static
int
cpu_has_work
(
CPUState
*
env
)
{
if
(
env
->
stop
)
return
1
;
if
(
env
->
stopped
)
return
0
;
if
(
!
env
->
halted
)
return
1
;
if
(
qemu_cpu_has_work
(
env
))
return
1
;
return
0
;
}
static
int
tcg_has_work
(
void
)
{
CPUState
*
env
;
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
if
(
cpu_has_work
(
env
))
return
1
;
return
0
;
}
#ifndef _WIN32
static
int
io_thread_fd
=
-
1
;
static
void
qemu_event_increment
(
void
)
{
/* Write 8 bytes to be compatible with eventfd. */
static
uint64_t
val
=
1
;
ssize_t
ret
;
if
(
io_thread_fd
==
-
1
)
return
;
do
{
ret
=
write
(
io_thread_fd
,
&
val
,
sizeof
(
val
));
}
while
(
ret
<
0
&&
errno
==
EINTR
);
/* EAGAIN is fine, a read must be pending. */
if
(
ret
<
0
&&
errno
!=
EAGAIN
)
{
fprintf
(
stderr
,
"qemu_event_increment: write() filed: %s
\n
"
,
strerror
(
errno
));
exit
(
1
);
}
}
static
void
qemu_event_read
(
void
*
opaque
)
{
int
fd
=
(
unsigned
long
)
opaque
;
ssize_t
len
;
char
buffer
[
512
];
/* Drain the notify pipe. For eventfd, only 8 bytes will be read. */
do
{
len
=
read
(
fd
,
buffer
,
sizeof
(
buffer
));
}
while
((
len
==
-
1
&&
errno
==
EINTR
)
||
len
==
sizeof
(
buffer
));
}
static
int
qemu_event_init
(
void
)
{
int
err
;
int
fds
[
2
];
err
=
qemu_eventfd
(
fds
);
if
(
err
==
-
1
)
return
-
errno
;
err
=
fcntl_setfl
(
fds
[
0
],
O_NONBLOCK
);
if
(
err
<
0
)
goto
fail
;
err
=
fcntl_setfl
(
fds
[
1
],
O_NONBLOCK
);
if
(
err
<
0
)
goto
fail
;
qemu_set_fd_handler2
(
fds
[
0
],
NULL
,
qemu_event_read
,
NULL
,
(
void
*
)(
unsigned
long
)
fds
[
0
]);
io_thread_fd
=
fds
[
1
];
return
0
;
fail:
close
(
fds
[
0
]);
close
(
fds
[
1
]);
return
err
;
}
#else
HANDLE
qemu_event_handle
;
static
void
dummy_event_handler
(
void
*
opaque
)
{
}
static
int
qemu_event_init
(
void
)
{
qemu_event_handle
=
CreateEvent
(
NULL
,
FALSE
,
FALSE
,
NULL
);
if
(
!
qemu_event_handle
)
{
fprintf
(
stderr
,
"Failed CreateEvent: %ld
\n
"
,
GetLastError
());
return
-
1
;
}
qemu_add_wait_object
(
qemu_event_handle
,
dummy_event_handler
,
NULL
);
return
0
;
}
static
void
qemu_event_increment
(
void
)
{
if
(
!
SetEvent
(
qemu_event_handle
))
{
fprintf
(
stderr
,
"qemu_event_increment: SetEvent failed: %ld
\n
"
,
GetLastError
());
exit
(
1
);
}
}
#endif
#ifndef CONFIG_IOTHREAD
static
int
qemu_init_main_loop
(
void
)
{
return
qemu_event_init
();
}
void
qemu_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
env
->
nr_cores
=
smp_cores
;
env
->
nr_threads
=
smp_threads
;
if
(
kvm_enabled
())
kvm_init_vcpu
(
env
);
return
;
}
int
qemu_cpu_self
(
void
*
env
)
{
return
1
;
}
static
void
resume_all_vcpus
(
void
)
{
}
static
void
pause_all_vcpus
(
void
)
{
}
void
qemu_cpu_kick
(
void
*
env
)
{
return
;
}
void
qemu_notify_event
(
void
)
{
CPUState
*
env
=
cpu_single_env
;
qemu_event_increment
();
if
(
env
)
{
cpu_exit
(
env
);
}
if
(
next_cpu
&&
env
!=
next_cpu
)
{
cpu_exit
(
next_cpu
);
}
}
void
qemu_mutex_lock_iothread
(
void
)
{}
void
qemu_mutex_unlock_iothread
(
void
)
{}
void
vm_stop
(
int
reason
)
{
do_vm_stop
(
reason
);
}
#else
/* CONFIG_IOTHREAD */
#include "qemu-thread.h"
QemuMutex
qemu_global_mutex
;
static
QemuMutex
qemu_fair_mutex
;
static
QemuThread
io_thread
;
static
QemuThread
*
tcg_cpu_thread
;
static
QemuCond
*
tcg_halt_cond
;
static
int
qemu_system_ready
;
/* cpu creation */
static
QemuCond
qemu_cpu_cond
;
/* system init */
static
QemuCond
qemu_system_cond
;
static
QemuCond
qemu_pause_cond
;
static
void
tcg_block_io_signals
(
void
);
static
void
kvm_block_io_signals
(
CPUState
*
env
);
static
void
unblock_io_signals
(
void
);
static
int
qemu_init_main_loop
(
void
)
{
int
ret
;
ret
=
qemu_event_init
();
if
(
ret
)
return
ret
;
qemu_cond_init
(
&
qemu_pause_cond
);
qemu_mutex_init
(
&
qemu_fair_mutex
);
qemu_mutex_init
(
&
qemu_global_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
unblock_io_signals
();
qemu_thread_self
(
&
io_thread
);
return
0
;
}
static
void
qemu_wait_io_event_common
(
CPUState
*
env
)
{
if
(
env
->
stop
)
{
env
->
stop
=
0
;
env
->
stopped
=
1
;
qemu_cond_signal
(
&
qemu_pause_cond
);
}
}
static
void
qemu_wait_io_event
(
CPUState
*
env
)
{
while
(
!
tcg_has_work
())
qemu_cond_timedwait
(
env
->
halt_cond
,
&
qemu_global_mutex
,
1000
);
qemu_mutex_unlock
(
&
qemu_global_mutex
);
/*
* Users of qemu_global_mutex can be starved, having no chance
* to acquire it since this path will get to it first.
* So use another lock to provide fairness.
*/
qemu_mutex_lock
(
&
qemu_fair_mutex
);
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
qemu_wait_io_event_common
(
env
);
}
static
void
qemu_kvm_eat_signal
(
CPUState
*
env
,
int
timeout
)
{
struct
timespec
ts
;
int
r
,
e
;
siginfo_t
siginfo
;
sigset_t
waitset
;
ts
.
tv_sec
=
timeout
/
1000
;
ts
.
tv_nsec
=
(
timeout
%
1000
)
*
1000000
;
sigemptyset
(
&
waitset
);
sigaddset
(
&
waitset
,
SIG_IPI
);
qemu_mutex_unlock
(
&
qemu_global_mutex
);
r
=
sigtimedwait
(
&
waitset
,
&
siginfo
,
&
ts
);
e
=
errno
;
qemu_mutex_lock
(
&
qemu_global_mutex
);
if
(
r
==
-
1
&&
!
(
e
==
EAGAIN
||
e
==
EINTR
))
{
fprintf
(
stderr
,
"sigtimedwait: %s
\n
"
,
strerror
(
e
));
exit
(
1
);
}
}
static
void
qemu_kvm_wait_io_event
(
CPUState
*
env
)
{
while
(
!
cpu_has_work
(
env
))
qemu_cond_timedwait
(
env
->
halt_cond
,
&
qemu_global_mutex
,
1000
);
qemu_kvm_eat_signal
(
env
,
0
);
qemu_wait_io_event_common
(
env
);
}
static
int
qemu_cpu_exec
(
CPUState
*
env
);
static
void
*
kvm_cpu_thread_fn
(
void
*
arg
)
{
CPUState
*
env
=
arg
;
qemu_thread_self
(
env
->
thread
);
if
(
kvm_enabled
())
kvm_init_vcpu
(
env
);
kvm_block_io_signals
(
env
);
/* signal CPU creation */
qemu_mutex_lock
(
&
qemu_global_mutex
);
env
->
created
=
1
;
qemu_cond_signal
(
&
qemu_cpu_cond
);
/* and wait for machine initialization */
while
(
!
qemu_system_ready
)
qemu_cond_timedwait
(
&
qemu_system_cond
,
&
qemu_global_mutex
,
100
);
while
(
1
)
{
if
(
cpu_can_run
(
env
))
qemu_cpu_exec
(
env
);
qemu_kvm_wait_io_event
(
env
);
}
return
NULL
;
}
static
bool
tcg_cpu_exec
(
void
);
static
void
*
tcg_cpu_thread_fn
(
void
*
arg
)
{
CPUState
*
env
=
arg
;
tcg_block_io_signals
();
qemu_thread_self
(
env
->
thread
);
/* signal CPU creation */
qemu_mutex_lock
(
&
qemu_global_mutex
);
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
env
->
created
=
1
;
qemu_cond_signal
(
&
qemu_cpu_cond
);
/* and wait for machine initialization */
while
(
!
qemu_system_ready
)
qemu_cond_timedwait
(
&
qemu_system_cond
,
&
qemu_global_mutex
,
100
);
while
(
1
)
{
tcg_cpu_exec
();
qemu_wait_io_event
(
cur_cpu
);
}
return
NULL
;
}
void
qemu_cpu_kick
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
qemu_cond_broadcast
(
env
->
halt_cond
);
if
(
kvm_enabled
())
qemu_thread_signal
(
env
->
thread
,
SIG_IPI
);
}
int
qemu_cpu_self
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
QemuThread
this
;
qemu_thread_self
(
&
this
);
return
qemu_thread_equal
(
&
this
,
env
->
thread
);
}
static
void
cpu_signal
(
int
sig
)
{
if
(
cpu_single_env
)
cpu_exit
(
cpu_single_env
);
}
static
void
tcg_block_io_signals
(
void
)
{
sigset_t
set
;
struct
sigaction
sigact
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
sigaddset
(
&
set
,
SIGCHLD
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_UNBLOCK
,
&
set
,
NULL
);
memset
(
&
sigact
,
0
,
sizeof
(
sigact
));
sigact
.
sa_handler
=
cpu_signal
;
sigaction
(
SIG_IPI
,
&
sigact
,
NULL
);
}
static
void
dummy_signal
(
int
sig
)
{
}
static
void
kvm_block_io_signals
(
CPUState
*
env
)
{
int
r
;
sigset_t
set
;
struct
sigaction
sigact
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
sigaddset
(
&
set
,
SIGCHLD
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
pthread_sigmask
(
SIG_BLOCK
,
NULL
,
&
set
);
sigdelset
(
&
set
,
SIG_IPI
);
memset
(
&
sigact
,
0
,
sizeof
(
sigact
));
sigact
.
sa_handler
=
dummy_signal
;
sigaction
(
SIG_IPI
,
&
sigact
,
NULL
);
r
=
kvm_set_signal_mask
(
env
,
&
set
);
if
(
r
)
{
fprintf
(
stderr
,
"kvm_set_signal_mask: %s
\n
"
,
strerror
(
r
));
exit
(
1
);
}
}
static
void
unblock_io_signals
(
void
)
{
sigset_t
set
;
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIGUSR2
);
sigaddset
(
&
set
,
SIGIO
);
sigaddset
(
&
set
,
SIGALRM
);
pthread_sigmask
(
SIG_UNBLOCK
,
&
set
,
NULL
);
sigemptyset
(
&
set
);
sigaddset
(
&
set
,
SIG_IPI
);
pthread_sigmask
(
SIG_BLOCK
,
&
set
,
NULL
);
}
static
void
qemu_signal_lock
(
unsigned
int
msecs
)
{
qemu_mutex_lock
(
&
qemu_fair_mutex
);
while
(
qemu_mutex_trylock
(
&
qemu_global_mutex
))
{
qemu_thread_signal
(
tcg_cpu_thread
,
SIG_IPI
);
if
(
!
qemu_mutex_timedlock
(
&
qemu_global_mutex
,
msecs
))
break
;
}
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
}
void
qemu_mutex_lock_iothread
(
void
)
{
if
(
kvm_enabled
())
{
qemu_mutex_lock
(
&
qemu_fair_mutex
);
qemu_mutex_lock
(
&
qemu_global_mutex
);
qemu_mutex_unlock
(
&
qemu_fair_mutex
);
}
else
qemu_signal_lock
(
100
);
}
void
qemu_mutex_unlock_iothread
(
void
)
{
qemu_mutex_unlock
(
&
qemu_global_mutex
);
}
static
int
all_vcpus_paused
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
if
(
!
penv
->
stopped
)
return
0
;
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
return
1
;
}
static
void
pause_all_vcpus
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
penv
->
stop
=
1
;
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
qemu_cpu_kick
(
penv
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
while
(
!
all_vcpus_paused
())
{
qemu_cond_timedwait
(
&
qemu_pause_cond
,
&
qemu_global_mutex
,
100
);
penv
=
first_cpu
;
while
(
penv
)
{
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
}
}
static
void
resume_all_vcpus
(
void
)
{
CPUState
*
penv
=
first_cpu
;
while
(
penv
)
{
penv
->
stop
=
0
;
penv
->
stopped
=
0
;
qemu_thread_signal
(
penv
->
thread
,
SIG_IPI
);
qemu_cpu_kick
(
penv
);
penv
=
(
CPUState
*
)
penv
->
next_cpu
;
}
}
static
void
tcg_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
/* share a single thread for all cpus with TCG */
if
(
!
tcg_cpu_thread
)
{
env
->
thread
=
qemu_mallocz
(
sizeof
(
QemuThread
));
env
->
halt_cond
=
qemu_mallocz
(
sizeof
(
QemuCond
));
qemu_cond_init
(
env
->
halt_cond
);
qemu_thread_create
(
env
->
thread
,
tcg_cpu_thread_fn
,
env
);
while
(
env
->
created
==
0
)
qemu_cond_timedwait
(
&
qemu_cpu_cond
,
&
qemu_global_mutex
,
100
);
tcg_cpu_thread
=
env
->
thread
;
tcg_halt_cond
=
env
->
halt_cond
;
}
else
{
env
->
thread
=
tcg_cpu_thread
;
env
->
halt_cond
=
tcg_halt_cond
;
}
}
static
void
kvm_start_vcpu
(
CPUState
*
env
)
{
env
->
thread
=
qemu_mallocz
(
sizeof
(
QemuThread
));
env
->
halt_cond
=
qemu_mallocz
(
sizeof
(
QemuCond
));
qemu_cond_init
(
env
->
halt_cond
);
qemu_thread_create
(
env
->
thread
,
kvm_cpu_thread_fn
,
env
);
while
(
env
->
created
==
0
)
qemu_cond_timedwait
(
&
qemu_cpu_cond
,
&
qemu_global_mutex
,
100
);
}
void
qemu_init_vcpu
(
void
*
_env
)
{
CPUState
*
env
=
_env
;
env
->
nr_cores
=
smp_cores
;
env
->
nr_threads
=
smp_threads
;
if
(
kvm_enabled
())
kvm_start_vcpu
(
env
);
else
tcg_init_vcpu
(
env
);
}
void
qemu_notify_event
(
void
)
{
qemu_event_increment
();
}
static
void
qemu_system_vmstop_request
(
int
reason
)
{
vmstop_requested
=
reason
;
qemu_notify_event
();
}
void
vm_stop
(
int
reason
)
{
QemuThread
me
;
qemu_thread_self
(
&
me
);
if
(
!
qemu_thread_equal
(
&
me
,
&
io_thread
))
{
qemu_system_vmstop_request
(
reason
);
/*
* FIXME: should not return to device code in case
* vm_stop() has been requested.
*/
if
(
cpu_single_env
)
{
cpu_exit
(
cpu_single_env
);
cpu_single_env
->
stop
=
1
;
}
return
;
}
do_vm_stop
(
reason
);
}
#endif
#ifdef _WIN32
static
void
host_main_loop_wait
(
int
*
timeout
)
{
...
...
@@ -2865,102 +2218,6 @@ void main_loop_wait(int nonblocking)
}
static
int
qemu_cpu_exec
(
CPUState
*
env
)
{
int
ret
;
#ifdef CONFIG_PROFILER
int64_t
ti
;
#endif
#ifdef CONFIG_PROFILER
ti
=
profile_getclock
();
#endif
if
(
use_icount
)
{
int64_t
count
;
int
decr
;
qemu_icount
-=
(
env
->
icount_decr
.
u16
.
low
+
env
->
icount_extra
);
env
->
icount_decr
.
u16
.
low
=
0
;
env
->
icount_extra
=
0
;
count
=
qemu_icount_round
(
qemu_next_deadline
());
qemu_icount
+=
count
;
decr
=
(
count
>
0xffff
)
?
0xffff
:
count
;
count
-=
decr
;
env
->
icount_decr
.
u16
.
low
=
decr
;
env
->
icount_extra
=
count
;
}
ret
=
cpu_exec
(
env
);
#ifdef CONFIG_PROFILER
qemu_time
+=
profile_getclock
()
-
ti
;
#endif
if
(
use_icount
)
{
/* Fold pending instructions back into the
instruction counter, and clear the interrupt flag. */
qemu_icount
-=
(
env
->
icount_decr
.
u16
.
low
+
env
->
icount_extra
);
env
->
icount_decr
.
u32
=
0
;
env
->
icount_extra
=
0
;
}
return
ret
;
}
static
bool
tcg_cpu_exec
(
void
)
{
int
ret
=
0
;
if
(
next_cpu
==
NULL
)
next_cpu
=
first_cpu
;
for
(;
next_cpu
!=
NULL
;
next_cpu
=
next_cpu
->
next_cpu
)
{
CPUState
*
env
=
cur_cpu
=
next_cpu
;
qemu_clock_enable
(
vm_clock
,
(
cur_cpu
->
singlestep_enabled
&
SSTEP_NOTIMER
)
==
0
);
if
(
qemu_alarm_pending
())
break
;
if
(
cpu_can_run
(
env
))
ret
=
qemu_cpu_exec
(
env
);
else
if
(
env
->
stop
)
break
;
if
(
ret
==
EXCP_DEBUG
)
{
gdb_set_stop_cpu
(
env
);
debug_requested
=
EXCP_DEBUG
;
break
;
}
}
return
tcg_has_work
();
}
static
void
set_numa_modes
(
void
)
{
CPUState
*
env
;
int
i
;
for
(
env
=
first_cpu
;
env
!=
NULL
;
env
=
env
->
next_cpu
)
{
for
(
i
=
0
;
i
<
nb_numa_nodes
;
i
++
)
{
if
(
node_cpumask
[
i
]
&
(
1
<<
env
->
cpu_index
))
{
env
->
numa_node
=
i
;
}
}
}
}
static
void
set_cpu_log
(
const
char
*
optarg
)
{
int
mask
;
const
CPULogItem
*
item
;
mask
=
cpu_str_to_log_mask
(
optarg
);
if
(
!
mask
)
{
printf
(
"Log items (comma separated):
\n
"
);
for
(
item
=
cpu_log_items
;
item
->
mask
!=
0
;
item
++
)
{
printf
(
"%-10s %s
\n
"
,
item
->
name
,
item
->
help
);
}
exit
(
1
);
}
cpu_set_log
(
mask
);
}
static
int
vm_can_run
(
void
)
{
if
(
powerdown_requested
)
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录