diff --git a/hypervisor/dm/vrtc.c b/hypervisor/dm/vrtc.c index 95f88606b..fd5c747be 100644 --- a/hypervisor/dm/vrtc.c +++ b/hypervisor/dm/vrtc.c @@ -1,6 +1,6 @@ /* * Copyright (c) 2014, Neel Natu (neel@freebsd.org) - * Copyright (c) 2022 Intel Corporation. + * Copyright (c) 2024 Intel Corporation. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -34,6 +34,20 @@ #include "mc146818rtc.h" +/** + * @addtogroup vp-dm_vperipheral + * + * @{ + */ + +/** + * @file + * @brief Implementation of virtual RTC device. + * + * This file provides the implementation of the virtual RTC device. The virtual RTC device is used to provide the RTC + * service to the guest VMs. It is a part of the virtual peripheral devices. + */ + /* #define DEBUG_RTC */ #ifdef DEBUG_RTC # define RTC_DEBUG pr_info @@ -489,8 +503,34 @@ static void vrtc_set_reg_b(struct acrn_vrtc *vrtc, uint8_t newval) } /** + * @brief Read from the virtual RTC device. + * + * This function reads the value from the RTC register specified by the address port. To read from the virtual RTC + * device, the guest writes the register index to the RTC address port and then reads the register value from the RTC + * data port. This function is used to simulate the behavior of reading in a virtualized environment. + * + * - If the accessed port is CMOS_ADDR_PORT, it will set the value as index cached in last write (0 by default) and + * return. + * - If the accessed port is CMOS_DATA_PORT, + * - For Service VM, it will directly read the value from the physical CMOS register. + * - For a non-Service VM, it will return false indicating the read operation failed if the address is greater than + * RTC_CENTURY. Otherwise, the read operation will be emulated. + * + * @param[inout] vcpu Pointer to the virtual CPU that is reading from the virtual RTC. The value read from the virtual + * RTC will be stored in the PIO request. + * @param[in] addr The address port to read from. + * @param[in] width The width of the data to be read. This is not used in this function. + * + * @return A boolean value indicating whether the read operation is successful. + * + * @retval true Successfully read from the virtual RTC device. + * @retval false Failed to read from the virtual RTC device. + * * @pre vcpu != NULL * @pre vcpu->vm != NULL + * @pre addr == 0x70U || addr == 0x71U + * + * @post N/A */ static bool vrtc_read(struct acrn_vcpu *vcpu, uint16_t addr, __unused size_t width) { @@ -536,8 +576,39 @@ static inline bool vrtc_is_time_register(uint32_t offset) } /** + * @brief Write a value to the virtual RTC. + * + * This function writes a specified value to the virtual RTC at a given offset. To write to the virtual RTC, the guest + * writes the register index to the RTC address port and then writes the register value to the RTC data port. This + * function is used to simulate the behavior of writing in a virtualized environment. + * + * - If the accessed port is CMOS_ADDR_PORT and the width is 1 byte, it will store the value as the index and return. + * - If the accessed port is CMOS_DATA_PORT, + * - For Service VM, it will directly write the value to the physical CMOS register. If the physical date/time is + * changed, for RT VMs and pre-launched VMs, the RTC/TSC snapshots will be updated. Those snapshots are used to + * emulate the virtual date/time for non-Service VM. + * - For a non-Service VM, it will ignore the write to the RTC_STATUSA, RTC_INTR and RTC_STATUSD. Otherwise, it will + * update the virtual register value and RTC time. And for Post-launched VM, it will send a VM event to notify the + * VM of the change in the RTC time if the address port is in the range of the time registers. + * + * @param[inout] vcpu Pointer to the virtual CPU that is writing to the virtual RTC. + * @param[in] addr The address port to write to. + * @param[in] width Width of the value to be written to the virtual RTC. + * @param[in] value Value to be written to the virtual RTC. + * + * @return A boolean value indicating whether the write operation is handled successfully, which is always true in + * current design. It either updates the physical registers, updates the virtual registers, or ignores the + * write. + * + * @retval true The write operation is handled successfully. + * * @pre vcpu != NULL * @pre vcpu->vm != NULL + * @pre addr == 0x70U || addr == 0x71U + * + * @post N/A + * + * @remark N/A */ static bool vrtc_write(struct acrn_vcpu *vcpu, uint16_t addr, size_t width, uint32_t value) @@ -707,6 +778,29 @@ void resume_vrtc(void) calibrate_setup_timer(); } +/** + * @brief Initialize the virtual RTC. + * + * This function initializes the virtual RTC (Real-Time Clock) device for the given virtual machine. It sets up the + * necessary data structures and state required for the RTC to function correctly. This function should be called during + * the initialization phase of the virtual machine. + * + * - When Service VM's vRTC device is initialized, a periodic timer (every 3 hours) is set up to calibrate the virtual + * date/time of other VMs. When the calibration timer is triggered, for RT VMs and pre-launched VMs, the TSC/RTC + * snapshots are updated to reflect the physical TSC/RTC-time at that moment. + * - When non-Service VM's vRTC device is initialized, the TSC/RTC snapshots are initialized to reflect the physical + * TSC/RTC-time at the moment. + * + * @param[inout] vm The virtual machine that contains the virtual RTC to be initialized. + * + * @return None + * + * @pre vm != NULL + * + * @post N/A + * + * @remark N/A + */ void vrtc_init(struct acrn_vm *vm) { struct vm_io_range range = { @@ -725,3 +819,7 @@ void vrtc_init(struct acrn_vm *vm) vm->vrtc.base_tsc = cpu_ticks(); } } + +/** + * @} + */ \ No newline at end of file diff --git a/hypervisor/include/dm/vrtc.h b/hypervisor/include/dm/vrtc.h index fa57eb542..27be54023 100644 --- a/hypervisor/include/dm/vrtc.h +++ b/hypervisor/include/dm/vrtc.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2022 Intel Corporation. + * Copyright (C) 2024 Intel Corporation. * * SPDX-License-Identifier: BSD-3-Clause */ @@ -7,6 +7,25 @@ #ifndef VRTC_H #define VRTC_H +/** + * @defgroup vp-dm_vperipheral vp-dm.vperipheral + * @ingroup vp-dm + * @brief Implementation of virtual peripheral devices in hypervisor. + * + * This module implements the virtualization of all peripheral devices in hypervisor. The virtual device initial + * function is usually called by the VM initialization function and registers their port IO and memory IO access + * functions. So when a guest VM accesses its peripheral device by port IO or memory IO, it would cause VM exit and then + * call their registered functions. + * @{ + */ + +/** + * @file + * @brief Definitions for the virtual RTC device. + * + * This file defines types and data structure for the virtual RTC device. + */ + typedef int32_t time_t; /* Register layout of the RTC */ @@ -29,17 +48,34 @@ struct rtcdev { uint8_t century; }; +/** + * @brief Data structure to illustrate a virtual RTC device. + * + * This structure contains the information of a virtual RTC device. + * + * @consistency self.vm->vrtc == self + * @alignment N/A + * + * @remark N/A + */ struct acrn_vrtc { - struct acrn_vm *vm; - uint32_t addr; /* RTC register to read or write */ - - time_t base_rtctime; /* Base time calulated from physical rtc register. */ - time_t offset_rtctime; /* RTC offset against base time. */ - time_t last_rtctime; /* Last RTC time, to keep monotonicity. */ - - uint64_t base_tsc; /* Base tsc value */ - - struct rtcdev rtcdev; /* RTC register */ + struct acrn_vm *vm; /**< Pointer to the VM that owns the virtual RTC device. */ + /** + * @brief The RTC register to read or write. + * + * To access RTC registers, the guest writes the register index to the RTC address port and then reads/writes + * the register value from/to the RTC data port. This field is used to store the register index. + */ + uint32_t addr; + time_t base_rtctime; /**< Base time calculated from physical RTC register. */ + time_t offset_rtctime; /**< RTC offset against base time. */ + time_t last_rtctime; /**< Last RTC time, to keep monotonicity. */ + uint64_t base_tsc; /**< Base TSC value. */ + struct rtcdev rtcdev; /**< Register layout of RTC. */ }; #endif /* VRTC_H */ + +/** + * @} + */ \ No newline at end of file