diff --git a/scripts/guest_time_keeping.sh b/scripts/guest_time_keeping.sh index dcb48ac..a9bb9ae 100755 --- a/scripts/guest_time_keeping.sh +++ b/scripts/guest_time_keeping.sh @@ -11,6 +11,9 @@ # QMP RTC_EVENT JSON Sample: # {"timestamp": {"seconds": 1585714481, "microseconds": 85991}, "event": "RTC_CHANGE", "data": {"offset": -1}} +# QMP RTC_ALARM JSON Sample: +# {"timestamp": {"seconds": 1593413313, "microseconds": 568267}, "event": "RTC_ALARM", "data": {"expire": 1593499713567502000}} + # If guest time is set earlier than the image build time, the guest time will become the image build time after # reboot @@ -18,6 +21,7 @@ set -eE #------------------------------------ Global Variables ----------------------------------------- QMP_PIPE=$1 +RTC_MONITOR=$2 #------------------------------------ Functions ----------------------------------------- function send_qmp_cmd() { @@ -66,63 +70,6 @@ function connect_qmp_pipe() { fi } -function update_host_date() { - local offset=$1 - - [[ $offset -eq 0 ]] && return - - echo "Guest time changed" - local old_time=$(date) - date -s "$offset seconds" - local updated_time=$(date) - - if [ $? = "0" ]; then - hwclock --systohc - echo "Host time is set from \"$old_time\" to \"$updated_time\"" - else - echo "Fail to set host time" - fi -} - -function monitor_guest_rtc_change() { - if [[ -z $1 ]]; then - echo "E: Empty QMP pipe" - return -1 - fi - - local qmp_pipe_out=$1".out" - if [[ ! -p $qmp_pipe_out ]]; then - echo "E: Not named pipe: $qmp_pipe_out" - return -1 - fi - - local pout - while true; do - if [ ! `pgrep qemu-system` ]; then - echo "E: Guest is not alive!" - return -1 - fi - - read pout < $qmp_pipe_out - local event=$(jq -r .event <<< "$pout") - - case $event in - RTC_CHANGE) - local offset=$(jq -r .data.offset <<< "$pout") - update_host_date "$offset" - ;; - SHUTDOWN) - return - ;; - *) - continue - ;; - esac - - sleep 1 - done -} - function create_pipe() { [[ -z $1 ]] && return [[ -p $1".in" ]] || mkfifo $1".in" @@ -132,4 +79,4 @@ function create_pipe() { #------------------------------------ Main process ----------------------------------------- create_pipe "$QMP_PIPE" || exit -1 connect_qmp_pipe "$QMP_PIPE" || exit -1 -monitor_guest_rtc_change "$QMP_PIPE" +exec "$RTC_MONITOR" "$QMP_PIPE.in" "$QMP_PIPE.out" diff --git a/scripts/setup_host.sh b/scripts/setup_host.sh index 43d945d..f1d84bd 100755 --- a/scripts/setup_host.sh +++ b/scripts/setup_host.sh @@ -47,6 +47,8 @@ function ubu_install_qemu_gvt(){ patch -p1 < $CIV_WORK_DIR/patches/qemu/Disable-EDID-auto-generation-in-QEMU.patch patch -p1 < $CIV_WORK_DIR/patches/qemu/0001-Revert-Revert-vfio-pci-quirks.c-Disable-stolen-memor.patch patch -p1 < $CIV_WORK_DIR/patches/qemu/0002-qemu-change-fence-poll-time-by-current-workload.patch + patch -p1 < $CIV_WORK_DIR/patches/qemu/0003-mc146818rtc-add-RTC_ALARM-QMP-event.patch + patch -p1 < $CIV_WORK_DIR/patches/qemu/0004-mc146818rtc-add-rtc-refresh-timer-QMP-command.patch if [ -d $CIV_GOP_DIR ]; then for i in $CIV_GOP_DIR/qemu/*.patch; do patch -p1 < $i; done fi @@ -173,6 +175,8 @@ function prepare_required_scripts(){ chmod +x $CIV_WORK_DIR/scripts/findall.py chmod +x $CIV_WORK_DIR/scripts/thermsys chmod +x $CIV_WORK_DIR/scripts/batsys + sudo chown root $CIV_WORK_DIR/scripts/guest_rtc_monitor + sudo chmod u+s $CIV_WORK_DIR/scripts/guest_rtc_monitor } function install_auto_start_service(){ diff --git a/scripts/start_civ.sh b/scripts/start_civ.sh index 6d8a0a3..86287c8 100755 --- a/scripts/start_civ.sh +++ b/scripts/start_civ.sh @@ -16,6 +16,7 @@ EMULATOR_PATH=$(which qemu-system-x86_64) GUEST_MEM="-m 2G" GUEST_CPU_NUM="-smp 1" GUEST_DISK="-drive file=$WORK_DIR/android.qcow2,if=none,id=disk1,discard=unmap,detect-zeroes=unmap" +GUEST_EXTERNAL_WAKEUP= GUEST_FIRMWARE="-drive file=$WORK_DIR/OVMF.fd,format=raw,if=pflash" GUEST_DISP_TYPE="-display gtk,gl=on" GUEST_KIRQ_CHIP="-machine kernel_irqchip=on" @@ -584,9 +585,10 @@ function set_guest_pm() { function set_guest_time_keep() { local guest_time_keep_daemon=$SCRIPTS_DIR/guest_time_keeping.sh - if [ -f $guest_keep_daemon ]; then + local guest_time_keep_rtc_daemon=$SCRIPTS_DIR/guest_rtc_monitor + if [ -f $guest_keep_daemon ] && [ -f $guest_time_keep_rtc_daemon ]; then local guest_time_keep_pipe=$WORK_DIR/qmp-time-keep-pipe - $guest_time_keep_daemon "$guest_time_keep_pipe" & + $guest_time_keep_daemon "$guest_time_keep_pipe" "$guest_time_keep_rtc_daemon" & GUEST_TIME_KEEP="-qmp pipe:$guest_time_keep_pipe" fi } @@ -617,6 +619,10 @@ function set_guest_pwr_vol_button() { cd - } +function enable_external_wakeup_mode() { + GUEST_EXTERNAL_WAKEUP='-global mc146818rtc.external_wakeup=on' +} + function cleanup() { cleanup_rpmb_dev cleanup_thermal_mediation @@ -662,6 +668,7 @@ function launch_guest() { $GUEST_WIFI_PT_DEV \ $GUEST_PM_CTRL \ $GUEST_TIME_KEEP \ + $GUEST_EXTERNAL_WAKEUP \ $GUEST_QMP_PIPE \ $GUEST_POWER_BUTTON \ $GUSET_VTPM \ @@ -704,7 +711,7 @@ function show_help() { printf "\t--thermal-mediation enable thermal mediation.\n" printf "\t--battery-mediation enable battery mediation.\n" printf "\t--guest-pm-control allow guest control host PM.\n" - printf "\t--guest-time-keep reflect guest time setting on Host OS.\n" + printf "\t--guest-time-keep reflect guest RTC settings on Host OS.\n" printf "\t--qmp-pipe specify the name of the pipe used for qmp communication.\n" printf "\t--allow-suspend option allow guest enter S3 state, by default guest cannot enter S3 state.\n" printf "\t--disable-kernel-irqchip set kernel_irqchip=off.\n" @@ -811,6 +818,10 @@ function parse_arg() { set_guest_time_keep ;; + --external-wakeup-mode) + enable_external_wakeup_mode + ;; + --allow-suspend) allow_guest_suspend ;;