提交 b629a38a 编写于 作者: P Peter Maydell

Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging

Mostly bugfixes and cleanups from qemu-devel.  Yet another small patch from
the record/replay series, and a few SCSI and i386 patches as well.

# gpg: Signature made Wed 14 Jan 2015 09:39:14 GMT using RSA key ID 78C7AE83
# gpg: Good signature from "Paolo Bonzini <bonzini@gnu.org>"
# gpg:                 aka "Paolo Bonzini <pbonzini@redhat.com>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 46F5 9FBD 57D6 12E7 BFD4  E2F7 7E15 100C CD36 69B1
#      Subkey fingerprint: F133 3857 4B66 2389 866C  7682 BFFB D25F 78C7 AE83

* remotes/bonzini/tags/for-upstream:
  cpus: consistently use QEMU_CLOCK_VIRTUAL_RT for icount_warp_rt timer
  qemu-timer: rename timer_init to timer_init_tl
  scsi: fix cancellation when I/O was completed but DMA was not.
  rules.mak: Fix module build
  hw/scsi/lsi53c895a: add support for additional diag / debug registers
  qemu-common.h: optimise muldiv64 if int128 is available
  target-i386: do not memcpy in and out of xmm_regs
  target-i386: fix movntsd on big-endian hosts
  vl.c: fix regression when reading memory size from config file
  vl: Don't silently change topology when all -smp options were set
  vl: fix max_cpus check
  vl: Avoid unnecessary 'if' nesting
  9pfs: changed to use event_notifier instead of qemu_pipe
  vl.c: fix regression when reading machine type from config file
  char: restore stdio echo on resume from suspend.
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
......@@ -324,7 +324,7 @@ static void icount_adjust(void)
static void icount_adjust_rt(void *opaque)
{
timer_mod(icount_rt_timer,
qemu_clock_get_ms(QEMU_CLOCK_REALTIME) + 1000);
qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL_RT) + 1000);
icount_adjust();
}
......
......@@ -14,6 +14,7 @@
#include "fsdev/qemu-fsdev.h"
#include "qemu/thread.h"
#include "qemu/event_notifier.h"
#include "block/coroutine.h"
#include "virtio-9p-coth.h"
......@@ -26,15 +27,11 @@ void co_run_in_worker_bh(void *opaque)
g_thread_pool_push(v9fs_pool.pool, co, NULL);
}
static void v9fs_qemu_process_req_done(void *arg)
static void v9fs_qemu_process_req_done(EventNotifier *e)
{
char byte;
ssize_t len;
Coroutine *co;
do {
len = read(v9fs_pool.rfd, &byte, sizeof(byte));
} while (len == -1 && errno == EINTR);
event_notifier_test_and_clear(e);
while ((co = g_async_queue_try_pop(v9fs_pool.completed)) != NULL) {
qemu_coroutine_enter(co, NULL);
......@@ -43,22 +40,18 @@ static void v9fs_qemu_process_req_done(void *arg)
static void v9fs_thread_routine(gpointer data, gpointer user_data)
{
ssize_t len;
char byte = 0;
Coroutine *co = data;
qemu_coroutine_enter(co, NULL);
g_async_queue_push(v9fs_pool.completed, co);
do {
len = write(v9fs_pool.wfd, &byte, sizeof(byte));
} while (len == -1 && errno == EINTR);
event_notifier_set(&v9fs_pool.e);
}
int v9fs_init_worker_threads(void)
{
int ret = 0;
int notifier_fds[2];
V9fsThPool *p = &v9fs_pool;
sigset_t set, oldset;
......@@ -66,10 +59,6 @@ int v9fs_init_worker_threads(void)
/* Leave signal handling to the iothread. */
pthread_sigmask(SIG_SETMASK, &set, &oldset);
if (qemu_pipe(notifier_fds) == -1) {
ret = -1;
goto err_out;
}
p->pool = g_thread_pool_new(v9fs_thread_routine, p, -1, FALSE, NULL);
if (!p->pool) {
ret = -1;
......@@ -84,13 +73,9 @@ int v9fs_init_worker_threads(void)
ret = -1;
goto err_out;
}
p->rfd = notifier_fds[0];
p->wfd = notifier_fds[1];
fcntl(p->rfd, F_SETFL, O_NONBLOCK);
fcntl(p->wfd, F_SETFL, O_NONBLOCK);
event_notifier_init(&p->e, 0);
qemu_set_fd_handler(p->rfd, v9fs_qemu_process_req_done, NULL, NULL);
event_notifier_set_handler(&p->e, v9fs_qemu_process_req_done);
err_out:
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
return ret;
......
......@@ -21,8 +21,8 @@
#include <glib.h>
typedef struct V9fsThPool {
int rfd;
int wfd;
EventNotifier e;
GThreadPool *pool;
GAsyncQueue *completed;
} V9fsThPool;
......
......@@ -277,6 +277,7 @@ typedef struct {
uint32_t csbc;
uint32_t scratch[18]; /* SCRATCHA-SCRATCHR */
uint8_t sbr;
uint32_t adder;
/* Script ram is stored as 32-bit words in host byteorder. */
uint32_t script_ram[2048];
......@@ -1389,6 +1390,7 @@ again:
switch ((insn >> 27) & 7) {
case 0: /* Jump */
DPRINTF("Jump to 0x%08x\n", addr);
s->adder = addr;
s->dsp = addr;
break;
case 1: /* Call */
......@@ -1513,6 +1515,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
return 0x7f;
case 0x08: /* Revision ID */
return 0x00;
case 0x09: /* SOCL */
return s->socl;
case 0xa: /* SSID */
return s->ssid;
case 0xb: /* SBCL */
......@@ -1577,6 +1581,8 @@ static uint8_t lsi_reg_readb(LSIState *s, int offset)
return s->sbr;
case 0x3b: /* DCNTL */
return s->dcntl;
/* ADDER Output (Debug of relative jump address) */
CASE_GET_REG32(adder, 0x3c)
case 0x40: /* SIEN0 */
return s->sien0;
case 0x41: /* SIEN1 */
......
......@@ -1770,6 +1770,8 @@ void scsi_req_cancel(SCSIRequest *req)
req->io_canceled = true;
if (req->aiocb) {
blk_aio_cancel(req->aiocb);
} else {
scsi_req_cancel_complete(req);
}
}
......
......@@ -314,7 +314,7 @@ static inline void aio_timer_init(AioContext *ctx,
int scale,
QEMUTimerCB *cb, void *opaque)
{
timer_init(ts, ctx->tlg.tl[type], scale, cb, opaque);
timer_init_tl(ts, ctx->tlg.tl[type], scale, cb, opaque);
}
/**
......
......@@ -370,6 +370,12 @@ static inline uint8_t from_bcd(uint8_t val)
}
/* compute with 96 bit intermediate result: (a*b)/c */
#ifdef CONFIG_INT128
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
return (__int128_t)a * b / c;
}
#else
static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
{
union {
......@@ -392,6 +398,7 @@ static inline uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
return res.ll;
}
#endif
/* Round number down to multiple */
#define QEMU_ALIGN_DOWN(n, m) ((n) / (m) * (m))
......
......@@ -410,7 +410,7 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
*/
/**
* timer_init:
* timer_init_tl:
* @ts: the timer to be initialised
* @timer_list: the timer list to attach the timer to
* @scale: the scale value for the timer
......@@ -423,9 +423,9 @@ int64_t timerlistgroup_deadline_ns(QEMUTimerListGroup *tlg);
* You need not call an explicit deinit call. Simply make
* sure it is not on a list with timer_del.
*/
void timer_init(QEMUTimer *ts,
QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque);
void timer_init_tl(QEMUTimer *ts,
QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque);
/**
* timer_new_tl:
......@@ -448,7 +448,7 @@ static inline QEMUTimer *timer_new_tl(QEMUTimerList *timer_list,
void *opaque)
{
QEMUTimer *ts = g_malloc0(sizeof(QEMUTimer));
timer_init(ts, timer_list, scale, cb, opaque);
timer_init_tl(ts, timer_list, scale, cb, opaque);
return ts;
}
......
......@@ -1112,6 +1112,9 @@ static struct termios oldtty;
static int old_fd0_flags;
static bool stdio_in_use;
static bool stdio_allow_signal;
static bool stdio_echo_state;
static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo);
static void term_exit(void)
{
......@@ -1119,10 +1122,17 @@ static void term_exit(void)
fcntl(0, F_SETFL, old_fd0_flags);
}
static void term_stdio_handler(int sig)
{
/* restore echo after resume from suspend. */
qemu_chr_set_echo_stdio(NULL, stdio_echo_state);
}
static void qemu_chr_set_echo_stdio(CharDriverState *chr, bool echo)
{
struct termios tty;
stdio_echo_state = echo;
tty = oldtty;
if (!echo) {
tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
......@@ -1149,6 +1159,7 @@ static void qemu_chr_close_stdio(struct CharDriverState *chr)
static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
{
CharDriverState *chr;
struct sigaction act;
if (is_daemonized()) {
error_report("cannot use stdio with -daemonize");
......@@ -1166,6 +1177,10 @@ static CharDriverState *qemu_chr_open_stdio(ChardevStdio *opts)
qemu_set_nonblock(0);
atexit(term_exit);
memset(&act, 0, sizeof(act));
act.sa_handler = term_stdio_handler;
sigaction(SIGCONT, &act, NULL);
chr = qemu_chr_open_fd(0, 1);
chr->chr_close = qemu_chr_close_stdio;
chr->chr_set_echo = qemu_chr_set_echo_stdio;
......
......@@ -331,9 +331,9 @@ int qemu_poll_ns(GPollFD *fds, guint nfds, int64_t timeout)
}
void timer_init(QEMUTimer *ts,
QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque)
void timer_init_tl(QEMUTimer *ts,
QEMUTimerList *timer_list, int scale,
QEMUTimerCB *cb, void *opaque)
{
ts->timer_list = timer_list;
ts->cb = cb;
......
......@@ -326,7 +326,17 @@ define unnest-vars
$(if $1,$(call fix-paths,$1/,,$2))
# Descend and include every subdir Makefile.objs
$(foreach v, $2, $(call unnest-var-recursive,$1,$2,$v))
$(foreach v, $2,
$(call unnest-var-recursive,$1,$2,$v)
# Pass the .mo-cflags and .mo-libs along to its member objects
$(foreach o, $(filter %.mo,$($v)),
$(foreach p,$($o-objs),
$(if $($o-cflags), $(eval $p-cflags += $($o-cflags)))
$(if $($o-libs), $(eval $p-libs += $($o-libs))))))
# For all %.mo objects that are directly added into -y, just expand them
$(foreach v,$(filter %-y,$2),
$(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o))))
$(foreach v,$(filter %-m,$2),
# All .o found in *-m variables are single object modules, create .mo
......@@ -353,18 +363,9 @@ define unnest-vars
# according to .mo-objs. Report error if not set
$(if $($o-objs),
$(eval $(o:%.mo=%$(DSOSUF)): module-common.o $($o-objs)),
$(error $o added in $v but $o-objs is not set))
# Pass the .mo-cflags and .mo-libs along to member objects
$(foreach p,$($o-objs),
$(if $($o-cflags), $(eval $p-cflags += $($o-cflags)))
$(if $($o-libs), $(eval $p-libs += $($o-libs)))))
$(error $o added in $v but $o-objs is not set)))
$(shell mkdir -p ./ $(sort $(dir $($v))))
# Include all the .d files
$(eval -include $(addsuffix *.d, $(sort $(dir $($v)))))
$(eval $v := $(filter-out %/,$($v))))
# For all %.mo objects that are directly added into -y, expand them to %.mo-objs
$(foreach v,$2,
$(eval $v := $(foreach o,$($v),$(if $($o-objs),$($o-objs),$o))))
endef
......@@ -1019,7 +1019,10 @@ static int kvm_put_fpu(X86CPU *cpu)
fpu.ftwx |= (!env->fptags[i]) << i;
}
memcpy(fpu.fpr, env->fpregs, sizeof env->fpregs);
memcpy(fpu.xmm, env->xmm_regs, sizeof env->xmm_regs);
for (i = 0; i < CPU_NB_REGS; i++) {
stq_p(&fpu.xmm[i][0], env->xmm_regs[i].XMM_Q(0));
stq_p(&fpu.xmm[i][8], env->xmm_regs[i].XMM_Q(1));
}
fpu.mxcsr = env->mxcsr;
return kvm_vcpu_ioctl(CPU(cpu), KVM_SET_FPU, &fpu);
......@@ -1045,6 +1048,7 @@ static int kvm_put_xsave(X86CPU *cpu)
CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf;
uint16_t cwd, swd, twd;
uint8_t *xmm;
int i, r;
if (!kvm_has_xsave()) {
......@@ -1065,8 +1069,6 @@ static int kvm_put_xsave(X86CPU *cpu)
memcpy(&xsave->region[XSAVE_CWD_RDP], &env->fpdp, sizeof(env->fpdp));
memcpy(&xsave->region[XSAVE_ST_SPACE], env->fpregs,
sizeof env->fpregs);
memcpy(&xsave->region[XSAVE_XMM_SPACE], env->xmm_regs,
sizeof env->xmm_regs);
xsave->region[XSAVE_MXCSR] = env->mxcsr;
*(uint64_t *)&xsave->region[XSAVE_XSTATE_BV] = env->xstate_bv;
memcpy(&xsave->region[XSAVE_YMMH_SPACE], env->ymmh_regs,
......@@ -1079,6 +1081,13 @@ static int kvm_put_xsave(X86CPU *cpu)
sizeof env->opmask_regs);
memcpy(&xsave->region[XSAVE_ZMM_Hi256], env->zmmh_regs,
sizeof env->zmmh_regs);
xmm = (uint8_t *)&xsave->region[XSAVE_XMM_SPACE];
for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) {
stq_p(xmm, env->xmm_regs[i].XMM_Q(0));
stq_p(xmm+8, env->xmm_regs[i].XMM_Q(1));
}
#ifdef TARGET_X86_64
memcpy(&xsave->region[XSAVE_Hi16_ZMM], env->hi16_zmm_regs,
sizeof env->hi16_zmm_regs);
......@@ -1384,7 +1393,10 @@ static int kvm_get_fpu(X86CPU *cpu)
env->fptags[i] = !((fpu.ftwx >> i) & 1);
}
memcpy(env->fpregs, fpu.fpr, sizeof env->fpregs);
memcpy(env->xmm_regs, fpu.xmm, sizeof env->xmm_regs);
for (i = 0; i < CPU_NB_REGS; i++) {
env->xmm_regs[i].XMM_Q(0) = ldq_p(&fpu.xmm[i][0]);
env->xmm_regs[i].XMM_Q(1) = ldq_p(&fpu.xmm[i][8]);
}
env->mxcsr = fpu.mxcsr;
return 0;
......@@ -1395,6 +1407,7 @@ static int kvm_get_xsave(X86CPU *cpu)
CPUX86State *env = &cpu->env;
struct kvm_xsave* xsave = env->kvm_xsave_buf;
int ret, i;
const uint8_t *xmm;
uint16_t cwd, swd, twd;
if (!kvm_has_xsave()) {
......@@ -1421,8 +1434,6 @@ static int kvm_get_xsave(X86CPU *cpu)
env->mxcsr = xsave->region[XSAVE_MXCSR];
memcpy(env->fpregs, &xsave->region[XSAVE_ST_SPACE],
sizeof env->fpregs);
memcpy(env->xmm_regs, &xsave->region[XSAVE_XMM_SPACE],
sizeof env->xmm_regs);
env->xstate_bv = *(uint64_t *)&xsave->region[XSAVE_XSTATE_BV];
memcpy(env->ymmh_regs, &xsave->region[XSAVE_YMMH_SPACE],
sizeof env->ymmh_regs);
......@@ -1434,6 +1445,13 @@ static int kvm_get_xsave(X86CPU *cpu)
sizeof env->opmask_regs);
memcpy(env->zmmh_regs, &xsave->region[XSAVE_ZMM_Hi256],
sizeof env->zmmh_regs);
xmm = (const uint8_t *)&xsave->region[XSAVE_XMM_SPACE];
for (i = 0; i < CPU_NB_REGS; i++, xmm += 16) {
env->xmm_regs[i].XMM_Q(0) = ldq_p(xmm);
env->xmm_regs[i].XMM_Q(1) = ldq_p(xmm+8);
}
#ifdef TARGET_X86_64
memcpy(env->hi16_zmm_regs, &xsave->region[XSAVE_Hi16_ZMM],
sizeof env->hi16_zmm_regs);
......
......@@ -2621,10 +2621,10 @@ static inline void gen_sto_env_A0(DisasContext *s, int offset)
static inline void gen_op_movo(int d_offset, int s_offset)
{
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset);
tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset);
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + 8);
tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + 8);
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(0)));
tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(0)));
tcg_gen_ld_i64(cpu_tmp1_i64, cpu_env, s_offset + offsetof(XMMReg, XMM_Q(1)));
tcg_gen_st_i64(cpu_tmp1_i64, cpu_env, d_offset + offsetof(XMMReg, XMM_Q(1)));
}
static inline void gen_op_movq(int d_offset, int s_offset)
......@@ -3074,7 +3074,8 @@ static void gen_sse(CPUX86State *env, DisasContext *s, int b,
goto illegal_op;
gen_lea_modrm(env, s, modrm);
if (b1 & 1) {
gen_stq_env_A0(s, offsetof(CPUX86State, xmm_regs[reg]));
gen_stq_env_A0(s, offsetof(CPUX86State,
xmm_regs[reg].XMM_Q(0)));
} else {
tcg_gen_ld32u_tl(cpu_T[0], cpu_env, offsetof(CPUX86State,
xmm_regs[reg].XMM_L(0)));
......
......@@ -1170,13 +1170,17 @@ static void smp_parse(QemuOpts *opts)
if (cpus == 0) {
cpus = cores * threads * sockets;
}
} else {
if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = cpus / (sockets * threads);
} else {
threads = cpus / (cores * sockets);
}
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = cpus / (sockets * threads);
} else if (threads == 0) {
threads = cpus / (cores * sockets);
} else if (sockets * cores * threads < cpus) {
fprintf(stderr, "cpu topology: error: "
"sockets (%u) * cores (%u) * threads (%u) < "
"smp_cpus (%u)\n",
sockets, cores, threads, cpus);
exit(1);
}
max_cpus = qemu_opt_get_number(opts, "maxcpus", 0);
......@@ -2644,6 +2648,92 @@ out:
return 0;
}
static void set_memory_options(uint64_t *ram_slots, ram_addr_t *maxram_size)
{
uint64_t sz;
const char *mem_str;
const char *maxmem_str, *slots_str;
const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE *
1024 * 1024;
QemuOpts *opts = qemu_find_opts_singleton("memory");
sz = 0;
mem_str = qemu_opt_get(opts, "size");
if (mem_str) {
if (!*mem_str) {
error_report("missing 'size' option value");
exit(EXIT_FAILURE);
}
sz = qemu_opt_get_size(opts, "size", ram_size);
/* Fix up legacy suffix-less format */
if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) {
uint64_t overflow_check = sz;
sz <<= 20;
if ((sz >> 20) != overflow_check) {
error_report("too large 'size' option value");
exit(EXIT_FAILURE);
}
}
}
/* backward compatibility behaviour for case "-m 0" */
if (sz == 0) {
sz = default_ram_size;
}
sz = QEMU_ALIGN_UP(sz, 8192);
ram_size = sz;
if (ram_size != sz) {
error_report("ram size too large");
exit(EXIT_FAILURE);
}
/* store value for the future use */
qemu_opt_set_number(opts, "size", ram_size);
*maxram_size = ram_size;
maxmem_str = qemu_opt_get(opts, "maxmem");
slots_str = qemu_opt_get(opts, "slots");
if (maxmem_str && slots_str) {
uint64_t slots;
sz = qemu_opt_get_size(opts, "maxmem", 0);
if (sz < ram_size) {
error_report("invalid -m option value: maxmem "
"(0x%" PRIx64 ") <= initial memory (0x"
RAM_ADDR_FMT ")", sz, ram_size);
exit(EXIT_FAILURE);
}
slots = qemu_opt_get_number(opts, "slots", 0);
if ((sz > ram_size) && !slots) {
error_report("invalid -m option value: maxmem "
"(0x%" PRIx64 ") more than initial memory (0x"
RAM_ADDR_FMT ") but no hotplug slots where "
"specified", sz, ram_size);
exit(EXIT_FAILURE);
}
if ((sz <= ram_size) && slots) {
error_report("invalid -m option value: %"
PRIu64 " hotplug slots where specified but "
"maxmem (0x%" PRIx64 ") <= initial memory (0x"
RAM_ADDR_FMT ")", slots, sz, ram_size);
exit(EXIT_FAILURE);
}
*maxram_size = sz;
*ram_slots = slots;
} else if ((!maxmem_str && slots_str) ||
(maxmem_str && !slots_str)) {
error_report("invalid -m option value: missing "
"'%s' option", slots_str ? "maxmem" : "slots");
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv, char **envp)
{
int i;
......@@ -2679,9 +2769,7 @@ int main(int argc, char **argv, char **envp)
};
const char *trace_events = NULL;
const char *trace_file = NULL;
const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE *
1024 * 1024;
ram_addr_t maxram_size = default_ram_size;
ram_addr_t maxram_size;
uint64_t ram_slots = 0;
FILE *vmstate_dump_file = NULL;
Error *main_loop_err = NULL;
......@@ -2732,7 +2820,6 @@ int main(int argc, char **argv, char **envp)
module_call_init(MODULE_INIT_MACHINE);
machine_class = find_default_machine();
cpu_model = NULL;
ram_size = default_ram_size;
snapshot = 0;
cyls = heads = secs = 0;
translation = BIOS_ATA_TRANSLATION_AUTO;
......@@ -2796,9 +2883,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
switch(popt->index) {
case QEMU_OPTION_M:
machine_class = machine_parse(optarg);
break;
case QEMU_OPTION_no_kvm_irqchip: {
olist = qemu_find_opts("machine");
qemu_opts_parse(olist, "kernel_irqchip=off", 0);
......@@ -3022,92 +3106,13 @@ int main(int argc, char **argv, char **envp)
version();
exit(0);
break;
case QEMU_OPTION_m: {
uint64_t sz;
const char *mem_str;
const char *maxmem_str, *slots_str;
case QEMU_OPTION_m:
opts = qemu_opts_parse(qemu_find_opts("memory"),
optarg, 1);
if (!opts) {
exit(EXIT_FAILURE);
}
mem_str = qemu_opt_get(opts, "size");
if (!mem_str) {
error_report("invalid -m option, missing 'size' option");
exit(EXIT_FAILURE);
}
if (!*mem_str) {
error_report("missing 'size' option value");
exit(EXIT_FAILURE);
}
sz = qemu_opt_get_size(opts, "size", ram_size);
/* Fix up legacy suffix-less format */
if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) {
uint64_t overflow_check = sz;
sz <<= 20;
if ((sz >> 20) != overflow_check) {
error_report("too large 'size' option value");
exit(EXIT_FAILURE);
}
}
/* backward compatibility behaviour for case "-m 0" */
if (sz == 0) {
sz = default_ram_size;
}
sz = QEMU_ALIGN_UP(sz, 8192);
ram_size = sz;
if (ram_size != sz) {
error_report("ram size too large");
exit(EXIT_FAILURE);
}
maxram_size = ram_size;
maxmem_str = qemu_opt_get(opts, "maxmem");
slots_str = qemu_opt_get(opts, "slots");
if (maxmem_str && slots_str) {
uint64_t slots;
sz = qemu_opt_get_size(opts, "maxmem", 0);
if (sz < ram_size) {
error_report("invalid -m option value: maxmem "
"(0x%" PRIx64 ") <= initial memory (0x"
RAM_ADDR_FMT ")", sz, ram_size);
exit(EXIT_FAILURE);
}
slots = qemu_opt_get_number(opts, "slots", 0);
if ((sz > ram_size) && !slots) {
error_report("invalid -m option value: maxmem "
"(0x%" PRIx64 ") more than initial memory (0x"
RAM_ADDR_FMT ") but no hotplug slots where "
"specified", sz, ram_size);
exit(EXIT_FAILURE);
}
if ((sz <= ram_size) && slots) {
error_report("invalid -m option value: %"
PRIu64 " hotplug slots where specified but "
"maxmem (0x%" PRIx64 ") <= initial memory (0x"
RAM_ADDR_FMT ")", slots, sz, ram_size);
exit(EXIT_FAILURE);
}
maxram_size = sz;
ram_slots = slots;
} else if ((!maxmem_str && slots_str) ||
(maxmem_str && !slots_str)) {
error_report("invalid -m option value: missing "
"'%s' option", slots_str ? "maxmem" : "slots");
exit(EXIT_FAILURE);
}
break;
}
#ifdef CONFIG_TPM
case QEMU_OPTION_tpmdev:
if (tpm_config_parse(qemu_find_opts("tpmdev"), optarg) < 0) {
......@@ -3420,16 +3425,13 @@ int main(int argc, char **argv, char **envp)
olist = qemu_find_opts("machine");
qemu_opts_parse(olist, "accel=kvm", 0);
break;
case QEMU_OPTION_M:
case QEMU_OPTION_machine:
olist = qemu_find_opts("machine");
opts = qemu_opts_parse(olist, optarg, 1);
if (!opts) {
exit(1);
}
optarg = qemu_opt_get(opts, "type");
if (optarg) {
machine_class = machine_parse(optarg);
}
break;
case QEMU_OPTION_no_kvm:
olist = qemu_find_opts("machine");
......@@ -3752,6 +3754,15 @@ int main(int argc, char **argv, char **envp)
}
}
}
opts = qemu_get_machine_opts();
optarg = qemu_opt_get(opts, "type");
if (optarg) {
machine_class = machine_parse(optarg);
}
set_memory_options(&ram_slots, &maxram_size);
loc_set_none();
os_daemonize();
......@@ -3851,9 +3862,9 @@ int main(int argc, char **argv, char **envp)
smp_parse(qemu_opts_find(qemu_find_opts("smp-opts"), NULL));
machine_class->max_cpus = machine_class->max_cpus ?: 1; /* Default to UP */
if (smp_cpus > machine_class->max_cpus) {
if (max_cpus > machine_class->max_cpus) {
fprintf(stderr, "Number of SMP cpus requested (%d), exceeds max cpus "
"supported by machine `%s' (%d)\n", smp_cpus,
"supported by machine `%s' (%d)\n", max_cpus,
machine_class->name, machine_class->max_cpus);
exit(1);
}
......@@ -4001,9 +4012,6 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
/* store value for the future use */
qemu_opt_set_number(qemu_find_opts_singleton("memory"), "size", ram_size);
if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0)
!= 0) {
exit(0);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册