diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c index eecd8031cf6c326f1816da179cf104c9c6dfb983..52304ab9bbe68a475e7bc371d81d4e778256be39 100644 --- a/accel/kvm/kvm-all.c +++ b/accel/kvm/kvm-all.c @@ -53,6 +53,8 @@ #include #endif +#include "hw/timer/rtc.h" + /* KVM uses PAGE_SIZE in its definition of KVM_COALESCED_MMIO_MAX. We * need to use the real host PAGE_SIZE, as that's what KVM will use. */ @@ -170,6 +172,7 @@ bool kvm_ioeventfd_any_length_allowed; bool kvm_msi_use_devid; static bool kvm_immediate_exit; static hwaddr kvm_max_slot_size = ~0; +bool kvm_rtc_reinject_enable; static const KVMCapabilityInfo kvm_required_capabilites[] = { KVM_CAP_INFO(USER_MEMORY), @@ -2581,6 +2584,11 @@ static int kvm_init(MachineState *ms) kvm_irqchip_create(s); } + kvm_rtc_reinject_enable = (kvm_check_extension(kvm_state, KVM_CAP_RTC_IRQ_COALESCED) > 0); + if (!kvm_rtc_reinject_enable) { + QEMU_LOG(LOG_INFO, "kvm rtc irq reinjection not supported.\n"); + } + if (kvm_eventfds_allowed) { s->memory_listener.listener.eventfd_add = kvm_mem_ioeventfd_add; s->memory_listener.listener.eventfd_del = kvm_mem_ioeventfd_del; diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c index 4fbafddb226d4e65fa2e4504ab225f0a7696590d..afe082f687b1302eafe086d62ec79993b24599be 100644 --- a/hw/rtc/mc146818rtc.c +++ b/hw/rtc/mc146818rtc.c @@ -42,7 +42,7 @@ #include "qapi/error.h" #include "qapi/qapi-events-misc-target.h" #include "qapi/visitor.h" -#include "hw/rtc/mc146818rtc_regs.h" +#include "hw/timer/rtc.h" #ifdef TARGET_I386 #include "qapi/qapi-commands-misc-target.h" @@ -111,6 +111,21 @@ static QLIST_HEAD(, RTCState) rtc_devices = QLIST_HEAD_INITIALIZER(rtc_devices); #ifdef TARGET_I386 +void qmp_set_rtc_catchup_speed(const uint32_t speed, Error **errp) +{ + RTCState *s; + + if (!kvm_rtc_reinject_enable) { + return; + } + + QLIST_FOREACH(s, &rtc_devices, link) { + if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + set_rtc_catchup_speed(speed); + } + } +} + void qmp_rtc_reset_reinjection(Error **errp) { RTCState *s; @@ -217,9 +232,17 @@ periodic_timer_update(RTCState *s, int64_t current_time, uint32_t old_period, bo */ if (s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { uint32_t old_irq_coalesced = s->irq_coalesced; + if (kvm_rtc_reinject_enable) { + old_irq_coalesced += rtc_get_coalesced_irq(); + } lost_clock += old_irq_coalesced * old_period; s->irq_coalesced = lost_clock / s->period; + if (kvm_rtc_reinject_enable) { + rtc_set_coalesced_irq(s->irq_coalesced); + s->irq_coalesced = 0; + old_irq_coalesced = 0; + } lost_clock %= s->period; if (old_irq_coalesced != s->irq_coalesced || old_period != s->period) { @@ -784,6 +807,11 @@ static int rtc_pre_save(void *opaque) rtc_update_time(s); + if (kvm_rtc_reinject_enable && + s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + s->irq_coalesced += rtc_get_coalesced_irq(); + } + return 0; } @@ -815,6 +843,13 @@ static int rtc_post_load(void *opaque, int version_id) rtc_coalesced_timer_update(s); } } + + if (kvm_rtc_reinject_enable && s->irq_coalesced != 0 && + s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + rtc_set_coalesced_irq(s->irq_coalesced); + s->irq_coalesced = 0; + } + return 0; } @@ -949,6 +984,10 @@ static void rtc_realizefn(DeviceState *dev, Error **errp) object_property_add_tm(OBJECT(s), "date", rtc_get_date); qdev_init_gpio_out(dev, &s->irq, 1); + if (kvm_rtc_reinject_enable && + s->lost_tick_policy == LOST_TICK_POLICY_SLEW) { + rtc_lost_tick_policy_slew(); + } QLIST_INSERT_HEAD(&rtc_devices, s, link); } diff --git a/hw/timer/meson.build b/hw/timer/meson.build index 03092e2cebf4e8811084b643af6acd3bf52df7e7..785fb6825bfb5319228521d699d1a98c59215694 100644 --- a/hw/timer/meson.build +++ b/hw/timer/meson.build @@ -36,5 +36,6 @@ softmmu_ss.add(when: 'CONFIG_STM32F2XX_TIMER', if_true: files('stm32f2xx_timer.c softmmu_ss.add(when: 'CONFIG_XILINX', if_true: files('xilinx_timer.c')) specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_timer.c')) softmmu_ss.add(when: 'CONFIG_SIFIVE_PWM', if_true: files('sifive_pwm.c')) +softmmu_ss.add(files('rtc.c')) specific_ss.add(when: 'CONFIG_AVR_TIMER16', if_true: files('avr_timer16.c')) diff --git a/hw/timer/rtc.c b/hw/timer/rtc.c new file mode 100644 index 0000000000000000000000000000000000000000..3f50e8b8929dab77fa360f9e501b477669caa78b --- /dev/null +++ b/hw/timer/rtc.c @@ -0,0 +1,95 @@ + /* + * QEMU rtc + * + * We introduce the functions here to decouple for the upstream + * hw/timer/mc146818rtc.c + * + * Copyright (c) 2017-2020 HUAWEI TECHNOLOGIES CO.,LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include +#include "qemu/osdep.h" +#include "hw/timer/rtc.h" +#include "sysemu/kvm.h" +#include "qemu/config-file.h" +#include "qemu/option.h" + +extern int kvm_vm_ioctl(KVMState *s, int type, ...); + +uint32_t rtc_get_coalesced_irq(void) +{ + struct kvm_rtc_reinject_control control = {}; + int ret; + + control.flag = KVM_GET_RTC_IRQ_COALESCED; + ret = kvm_vm_ioctl(kvm_state, KVM_RTC_REINJECT_CONTROL, &control); + if (ret < 0) { + QEMU_LOG(LOG_ERR, "Failed to get coalesced irqs from kmod: %d\n", ret); + } + return control.rtc_irq_coalesced; +} + +void rtc_set_coalesced_irq(uint32_t nr_irqs) +{ + struct kvm_rtc_reinject_control control = {}; + int ret; + + control.rtc_irq_coalesced = nr_irqs; + control.flag = KVM_SET_RTC_IRQ_COALESCED; + ret = kvm_vm_ioctl(kvm_state, KVM_RTC_REINJECT_CONTROL, &control); + if (ret < 0) { + QEMU_LOG(LOG_ERR, "Failed to set coalesced irqs to kmod: %d, %u\n", ret, nr_irqs); + } +} + +void rtc_lost_tick_policy_slew(void) +{ + struct kvm_rtc_reinject_control control = {}; + int ret; + + control.flag = KVM_RTC_LOST_TICK_POLICY_SLEW; + ret = kvm_vm_ioctl(kvm_state, KVM_RTC_REINJECT_CONTROL, &control); + if (ret < 0) { + QEMU_LOG(LOG_ERR, "Failed to notify kvm to use lost tick policy slew: %d\n", ret); + } +} + +uint32_t rtc_catchup_speed(void) +{ + uint32_t speed; + QemuOpts *opts = qemu_find_opts_singleton("rtc"); + + speed = qemu_opt_get_number(opts, "speed", 0); + QEMU_LOG(LOG_INFO, "rtc catchup speed: %u\n", speed); + + return speed; +} + +void set_rtc_catchup_speed(const uint32_t speed) +{ + struct kvm_rtc_reinject_control control = {}; + int ret; + + if (speed > 0) { + control.flag = KVM_SET_RTC_CATCHUP_SPEED; + control.speed = speed; + ret = kvm_vm_ioctl(kvm_state, KVM_RTC_REINJECT_CONTROL, &control); + if (ret < 0) { + QEMU_LOG(LOG_ERR, "Failed to set rtc_catchup_speed: %d\n", ret); + } + QEMU_LOG(LOG_INFO, "Success to set rtc_catchup_speed: %u\n", speed); + } +} diff --git a/include/hw/timer/rtc.h b/include/hw/timer/rtc.h new file mode 100644 index 0000000000000000000000000000000000000000..2d064d2994ad3abd09cde01fd15f26a9d785e1ef --- /dev/null +++ b/include/hw/timer/rtc.h @@ -0,0 +1,56 @@ +/* +* QEMU rtc +* +* We introduce the functions here to decouple for the upstream +* include/hw/timer/mc146818rtc.h +* +* Copyright (c) 2017-2020 HUAWEI TECHNOLOGIES CO.,LTD. +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. + +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. + +* You should have received a copy of the GNU General Public License along +* with this program; if not, see . +*/ + +#ifndef INCLUDE_HW_TIMER_RTC_H +#define INCLUDE_HW_TIMER_RTC_H + +#include +#include +#include +#include "qemu-log.h" + +/* flags to control coalesced irq */ +#define KVM_GET_RTC_IRQ_COALESCED (1 << 0) +#define KVM_SET_RTC_IRQ_COALESCED (1 << 1) +#define KVM_RTC_LOST_TICK_POLICY_SLEW (1 << 2) +#define KVM_SET_RTC_CATCHUP_SPEED (1 << 3) + +/* RTC is emulated in qemu, but the colasced irqs are reinjected in kvm */ +#define KVM_CAP_RTC_IRQ_COALESCED 163 +#define KVM_RTC_REINJECT_CONTROL _IOWR(KVMIO, 0x56, struct kvm_rtc_reinject_control) + +struct kvm_rtc_reinject_control { + __u32 rtc_irq_coalesced; + __u8 flag; + __u8 speed; + __u8 reserved[30]; +}; + +extern bool kvm_rtc_reinject_enable; + +uint32_t rtc_get_coalesced_irq(void); +void rtc_set_coalesced_irq(uint32_t nr_irqs); +void rtc_lost_tick_policy_slew(void); +uint32_t rtc_catchup_speed(void); +void set_rtc_catchup_speed(const uint32_t speed); + +#endif diff --git a/include/qemu-log.h b/include/qemu-log.h new file mode 100644 index 0000000000000000000000000000000000000000..1de8c62c24cef5526a2696e191f8e1f942ce7bfe --- /dev/null +++ b/include/qemu-log.h @@ -0,0 +1,47 @@ +/* + * Introduce QEMU_LOG + * + * LOG: Introduce QEMU_LOG. + * + * Copyright (c) 2017-2020 HUAWEI TECHNOLOGIES CO.,LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef UVP_QEMU_COMMON_H +#define UVP_QEMU_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "qemu/typedefs.h" +#include "qemu/osdep.h" + +#define TIMESTAMP_MAX_LEN 33 /* RFC 3339 timestamp length shuold be 33 */ + +void qemu_get_timestamp(char *buf, int buf_size); +void qemu_convert_timestamp(struct timeval tp, char *buf, int buf_size); +void qemu_log_print(int level, const char *funcname, int linenr, + const char *fmt, ...); + +#define QEMU_LOG(level, format, ...) \ + qemu_log_print(level, __func__, __LINE__, format, ##__VA_ARGS__) + +#endif diff --git a/include/qemu/qemu-timer.inc.h b/include/qemu/qemu-timer.inc.h new file mode 100644 index 0000000000000000000000000000000000000000..bbe7b67f7a5015517197602dc849e1a67d272a45 --- /dev/null +++ b/include/qemu/qemu-timer.inc.h @@ -0,0 +1,31 @@ +/* + * Introduce qemu-timer function + * + * We introduce the functions here to decouple for the upstream + * include/qemu/timer.h + * + * Copyright (c) 2017-2020 HUAWEI TECHNOLOGIES CO.,LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#ifndef INCLUDE_QEMU_QEMU_TIMER_INC_H +#define INCLUDE_QEMU_QEMU_TIMER_INC_H + +#include "qemu/timer.h" + +void qemu_clock_trigger_reset(QEMUClockType type); +void qemu_clock_disable_reset(void); + +#endif /* end of include guard: INCLUDE_QEMU_QEMU_TIMER_INC_H */ diff --git a/qapi/misc-target.json b/qapi/misc-target.json index 5aa2b95b7d4aa09a4b11a9bbabafa2b30ce4f2ae..ac7f7bf43aaf5c3d3d1983f82325daddd237a822 100644 --- a/qapi/misc-target.json +++ b/qapi/misc-target.json @@ -54,6 +54,18 @@ { 'command': 'rtc-reset-reinjection', 'if': 'TARGET_I386' } +## +# @set-rtc-catchup-speed: +# +# set rtc catchup speed +# +# @speed: rtc catchup speed +# +# Returns: Nothing on success +# +# Since: 2.8.1 +## +{ 'command': 'set-rtc-catchup-speed', 'data': {'speed': 'uint32'}, 'if': 'TARGET_I386'} ## # @SevState: diff --git a/qapi/pragma.json b/qapi/pragma.json index 3bc0335d1f9a4d7d6dd5337ddae65556f89b3e98..d546f1ab49b2afa5d667124ebf61362e382c7c07 100644 --- a/qapi/pragma.json +++ b/qapi/pragma.json @@ -20,7 +20,8 @@ 'set_password', 'system_powerdown', 'system_reset', - 'system_wakeup' ], + 'system_wakeup', + 'set-rtc-catchup-speed' ], 'command-returns-exceptions': [ 'human-monitor-command', 'qom-get', diff --git a/qemu.spec b/qemu.spec new file mode 100644 index 0000000000000000000000000000000000000000..ae9e0f3939a05d202ea9eab06c619fc3272c71a1 --- /dev/null +++ b/qemu.spec @@ -0,0 +1,35 @@ +Name: +Version: +Release: 1%{?dist} +Summary: + +Group: +License: +URL: +Source0: + +BuildRequires: +Requires: + +%description + + +%prep +%setup -q + + +%build +%configure +make %{?_smp_mflags} + + +%install +%make_install + + +%files +%doc + + + +%changelog diff --git a/softmmu/cpus.c b/softmmu/cpus.c index 071085f840b02ce35327031386aec911639f2de6..902a13eacb32769f0e784f663a859e0e27ac14f9 100644 --- a/softmmu/cpus.c +++ b/softmmu/cpus.c @@ -45,6 +45,8 @@ #include "hw/boards.h" #include "hw/hw.h" #include "trace.h" +#include "qemu/timer.h" +#include "qemu/qemu-timer.inc.h" #ifdef CONFIG_LINUX @@ -65,6 +67,7 @@ #endif /* CONFIG_LINUX */ static QemuMutex qemu_global_mutex; +extern QEMUClockType rtc_clock; bool cpu_is_stopped(CPUState *cpu) { @@ -683,6 +686,7 @@ int vm_prepare_start(void) return -1; } + qemu_clock_trigger_reset(rtc_clock); /* We are sending this now, but the CPUs will be resumed shortly later */ qapi_event_send_resume(); diff --git a/softmmu/vl.c b/softmmu/vl.c index d9e4c619d3e1a7929e5c3a8f7e85bb301a15dd26..381f9a61d84a34ce9025d62daafbe7f1c0db4f7c 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -126,6 +126,7 @@ #include "qapi/qmp/qerror.h" #include "sysemu/iothread.h" #include "qemu/guest-random.h" +#include "qemu/qemu-timer.inc.h" #include "config-host.h" @@ -227,6 +228,9 @@ static QemuOptsList qemu_rtc_opts = { },{ .name = "driftfix", .type = QEMU_OPT_STRING, + },{ + .name = "speed", + .type = QEMU_OPT_NUMBER, }, { /* end of list */ } }, @@ -3504,6 +3508,8 @@ void qemu_init(int argc, char **argv, char **envp) runstate_set(RUN_STATE_INMIGRATE); } incoming = optarg; + + qemu_clock_disable_reset(); break; case QEMU_OPTION_only_migratable: only_migratable = 1; diff --git a/util/meson.build b/util/meson.build index 05b593055a143698107a2f1dfab3070194c5776d..26743838063b0372d607a024e288adfc2c055ea6 100644 --- a/util/meson.build +++ b/util/meson.build @@ -80,6 +80,7 @@ if have_block util_ss.add(files('qemu-coroutine-sleep.c')) util_ss.add(files('qemu-co-shared-resource.c')) util_ss.add(files('thread-pool.c', 'qemu-timer.c')) + util_ss.add(files('qemu-log.c')) util_ss.add(files('readline.c')) util_ss.add(files('throttle.c')) util_ss.add(files('timed-average.c')) diff --git a/util/qemu-log.c b/util/qemu-log.c new file mode 100644 index 0000000000000000000000000000000000000000..31379bfa78557bc348ddefd96da64a81353617df --- /dev/null +++ b/util/qemu-log.c @@ -0,0 +1,225 @@ +/* + * Introduce QEMU_LOG + * + * LOG: Introduce QEMU_LOG. + * + * Copyright (c) 2017-2020 HUAWEI TECHNOLOGIES CO.,LTD. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, see . + */ + +#include "qemu-log.h" +#include +#include "qemu/osdep.h" + +#define BEGIN_YEAR 1900 +#define DEFAULT_SECFRACPRECISION 6 +#define LOG_LEVEL_NAME_MAX_LEN 10 + +static const int tenPowers[6] = { 1, 10, 100, 1000, 10000, 100000 }; + +typedef char intTiny; + +struct syslogTime { + intTiny timeType; /* 0 - unitinialized + * 1 - RFC 3164 + * 2 - syslog-protocol + */ + intTiny month; + intTiny day; + intTiny hour; /* 24 hour clock */ + intTiny minute; + intTiny second; + intTiny secfracPrecision; + intTiny OffsetMinute; /* UTC offset in minutes */ + intTiny OffsetHour; /* UTC offset in hours + * full UTC offset minutes + * = OffsetHours*60 + OffsetMinute. + * Then use OffsetMode to know the direction. + */ + char OffsetMode; /* UTC offset + or - */ + short year; + int secfrac; /* fractional seconds (must be 32 bit!) */ + intTiny inUTC; /* forced UTC? */ +}; +typedef struct syslogTime syslogTime_t; + +typedef struct syslogName_s { + const char *c_name; + int c_val; +} syslogName_t; + +static syslogName_t syslogPriNames[] = { + {"emerg", LOG_EMERG}, + {"alert", LOG_ALERT}, + {"crit", LOG_CRIT}, + {"err", LOG_ERR}, + {"warning", LOG_WARNING}, + {"notice", LOG_NOTICE}, + {"info", LOG_INFO}, + {"debug", LOG_DEBUG}, + {NULL, -1} +}; + +/** + * Format a syslogTimestamp to a RFC3339 timestamp string (as + * specified in syslog-protocol). + * + * Notes: rfc_time_buf size >= TIMESTAMP_MAX_LEN + */ +static void formatTimestamp3339(struct syslogTime *ts, char *rfc_time_buf) +{ + int iBuf = 0; + int power = 0; + int secfrac = 0; + short digit = 0; + char *pBuf = rfc_time_buf; + + pBuf[iBuf++] = (ts->year / 1000) % 10 + '0'; + pBuf[iBuf++] = (ts->year / 100) % 10 + '0'; + pBuf[iBuf++] = (ts->year / 10) % 10 + '0'; + pBuf[iBuf++] = ts->year % 10 + '0'; + pBuf[iBuf++] = '-'; + /* month */ + pBuf[iBuf++] = (ts->month / 10) % 10 + '0'; + pBuf[iBuf++] = ts->month % 10 + '0'; + pBuf[iBuf++] = '-'; + /* day */ + pBuf[iBuf++] = (ts->day / 10) % 10 + '0'; + pBuf[iBuf++] = ts->day % 10 + '0'; + pBuf[iBuf++] = 'T'; + /* hour */ + pBuf[iBuf++] = (ts->hour / 10) % 10 + '0'; + pBuf[iBuf++] = ts->hour % 10 + '0'; + pBuf[iBuf++] = ':'; + /* minute */ + pBuf[iBuf++] = (ts->minute / 10) % 10 + '0'; + pBuf[iBuf++] = ts->minute % 10 + '0'; + pBuf[iBuf++] = ':'; + /* second */ + pBuf[iBuf++] = (ts->second / 10) % 10 + '0'; + pBuf[iBuf++] = ts->second % 10 + '0'; + + if (ts->secfracPrecision > 0) { + pBuf[iBuf++] = '.'; + power = tenPowers[(ts->secfracPrecision - 1) % 6]; + secfrac = ts->secfrac; + while (power > 0) { + digit = secfrac / power; + secfrac -= digit * power; + power /= 10; + pBuf[iBuf++] = digit + '0'; + } + } + + pBuf[iBuf++] = ts->OffsetMode; + pBuf[iBuf++] = (ts->OffsetHour / 10) % 10 + '0'; + pBuf[iBuf++] = ts->OffsetHour % 10 + '0'; + pBuf[iBuf++] = ':'; + pBuf[iBuf++] = (ts->OffsetMinute / 10) % 10 + '0'; + pBuf[iBuf++] = ts->OffsetMinute % 10 + '0'; + + pBuf[iBuf] = '\0'; +} + +void qemu_convert_timestamp(struct timeval tp, char *buf, int buf_size) +{ + struct tm *tm; + struct tm tmBuf; + long lBias = 0; + time_t secs; + syslogTime_t ts; + char rfc_time_buf[TIMESTAMP_MAX_LEN] = {0}; + + /* RFC 3339 timestamp length must be greater than or equal 33 */ + if (buf_size < TIMESTAMP_MAX_LEN) { + buf[0] = '\0'; + (void)printf("RFC 3339 timestamp length must be greater than or equal 33\n"); + return; + } + + secs = tp.tv_sec; + tm = localtime_r(&secs, &tmBuf); + + ts.year = tm->tm_year + BEGIN_YEAR; + ts.month = tm->tm_mon + 1; + ts.day = tm->tm_mday; + ts.hour = tm->tm_hour; + ts.minute = tm->tm_min; + ts.second = tm->tm_sec; + ts.secfrac = tp.tv_usec; + ts.secfracPrecision = DEFAULT_SECFRACPRECISION; + + lBias = tm->tm_gmtoff; + if (lBias < 0) { + ts.OffsetMode = '-'; + lBias *= -1; + } else { + ts.OffsetMode = '+'; + } + + ts.OffsetHour = lBias / 3600; + ts.OffsetMinute = (lBias % 3600) / 60; + + formatTimestamp3339(&ts, rfc_time_buf); + (void)snprintf(buf, buf_size, "%s", rfc_time_buf); +} + +void qemu_get_timestamp(char *buf, int buf_size) +{ + struct timeval tp; + (void)gettimeofday(&tp, NULL); + + qemu_convert_timestamp(tp, buf, buf_size); +} + + +static void qemu_get_loglevelname(int level, char *log_level_name, int len) +{ + syslogName_t *c; + + for (c = syslogPriNames; c->c_name; c++) { + if (level == c->c_val) { + (void)snprintf(log_level_name, len, "%s", c->c_name); + return; + } + } + + (void)printf("The log level is wrong\n"); +} + +void qemu_log_print(int level, const char *funcname, int linenr, + const char *fmt, ...) +{ + va_list ap; + char time_buf[TIMESTAMP_MAX_LEN] = {0}; + char log_level_name[LOG_LEVEL_NAME_MAX_LEN] = {0}; + char buf[1024] = {0}; + + qemu_get_timestamp(time_buf, TIMESTAMP_MAX_LEN); + qemu_get_loglevelname(level, log_level_name, sizeof(log_level_name)); + + va_start(ap, fmt); + (void)vsnprintf(buf, 1024, fmt, ap); + va_end(ap); + + if (funcname != NULL) { + (void)fprintf(stderr, "%s|%s|qemu[%d]|[%d]|%s[%d]|: %s", time_buf, + log_level_name, getpid(), qemu_get_thread_id(), + funcname, linenr, buf); + } else { + (void)fprintf(stderr, "%s|%s|qemu[%d]|[%d]|%s", time_buf, log_level_name, + getpid(), qemu_get_thread_id(), buf); + } +} diff --git a/util/qemu-timer.c b/util/qemu-timer.c index f36c75e594a6f23a7b982567f81180605d17f73d..ed888d91e05dcb5189d58b42b5cb53e313708957 100644 --- a/util/qemu-timer.c +++ b/util/qemu-timer.c @@ -29,6 +29,8 @@ #include "sysemu/cpu-timers.h" #include "sysemu/replay.h" #include "sysemu/cpus.h" +#include "qemu-log.h" +#include "qemu/qemu-timer.inc.h" #ifdef CONFIG_POSIX #include @@ -44,11 +46,15 @@ /***********************************************************/ /* timers */ +bool g_vm_cold_start_flag = true; typedef struct QEMUClock { /* We rely on BQL to protect the timerlists */ QLIST_HEAD(, QEMUTimerList) timerlists; + NotifierList reset_notifiers; + int64_t last; + QEMUClockType type; bool enabled; } QEMUClock; @@ -672,3 +678,23 @@ bool qemu_clock_run_all_timers(void) return progress; } + +void qemu_clock_disable_reset(void) +{ + g_vm_cold_start_flag = false; +} + +void qemu_clock_trigger_reset(QEMUClockType type) +{ + if (!g_vm_cold_start_flag) { + return; + } + if (type == QEMU_CLOCK_VIRTUAL) { + int64_t now; + QEMUClock *clock = qemu_clock_ptr(type); + now = REPLAY_CLOCK(REPLAY_CLOCK_HOST, get_clock_realtime()); + notifier_list_notify(&clock->reset_notifiers, &now); + QEMU_LOG(LOG_INFO, "Guest synchronise time success.\n"); + } + g_vm_cold_start_flag = false; +}