hv: Add vrtc emulation support for ACRN partition mode

This patch adds code to support read-only RTC support for guests
run by partition mode ACRN. It supports RW for CMOS address port 0x70
and RO for CMOS data port 0x71. Reads to CMOS RAM offsets are fetched
by reading CMOS h/w directly and writes to CMOS offsets are discarded.

Signed-off-by: Sainath Grandhi <sainath.grandhi@intel.com>
This commit is contained in:
Sainath Grandhi 2018-08-14 22:21:11 -07:00 committed by lijinxia
parent f63c7a7355
commit 022ef92b62
4 changed files with 91 additions and 1 deletions

View File

@ -177,6 +177,7 @@ C_SRCS += dm/vioapic.c
ifeq ($(CONFIG_PARTITION_MODE),y)
C_SRCS += $(wildcard dm/vpci/*.c)
C_SRCS += $(wildcard partition/*.c)
C_SRCS += dm/vrtc.c
endif
C_SRCS += bsp/$(CONFIG_PLATFORM)/vm_description.c

View File

@ -205,7 +205,7 @@ int create_vm(struct vm_description *vm_desc, struct vm **rtn_vm)
if (vm_desc->vm_vuart) {
vm->vuart = vuart_init(vm);
}
vrtc_init(vm);
vpci_init(vm);
#endif

86
hypervisor/dm/vrtc.c Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (C) 2018 Intel Corporation. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <hypervisor.h>
#include <hv_lib.h>
#include <acrn_common.h>
#include <hv_arch.h>
#include <hv_debug.h>
#define CMOS_ADDR_PORT 0x70U
#define CMOS_DATA_PORT 0x71U
#define RTC_STATUSA 0x0AU /* status register A */
#define RTCSA_TUP 0x80U /* time update, don't look now */
static spinlock_t cmos_lock = { .head = 0U, .tail = 0U };
static uint8_t cmos_read(uint8_t addr)
{
pio_write8(addr, CMOS_ADDR_PORT);
return pio_read8(CMOS_DATA_PORT);
}
static bool cmos_update_in_progress(void)
{
return (cmos_read(RTC_STATUSA) & RTCSA_TUP)?1:0;
}
static uint8_t cmos_get_reg_val(uint8_t addr)
{
uint8_t reg;
int tries = 2000U;
spinlock_obtain(&cmos_lock);
/* Make sure an update isn't in progress */
while (cmos_update_in_progress() && tries--)
;
reg = cmos_read(addr);
spinlock_release(&cmos_lock);
return reg;
}
static uint32_t vrtc_read(__unused struct vm_io_handler *hdlr, struct vm *vm,
uint16_t addr, __unused size_t width)
{
uint8_t reg;
uint8_t offset;
offset = vm->vrtc_offset;
if (addr == CMOS_ADDR_PORT) {
return vm->vrtc_offset;
}
reg = cmos_get_reg_val(offset);
return reg;
}
static void vrtc_write(__unused struct vm_io_handler *hdlr, struct vm *vm, uint16_t addr,
size_t width, uint32_t value)
{
if (width != 1U)
return;
if (addr == CMOS_ADDR_PORT) {
vm->vrtc_offset = value & 0x7FU;
}
}
void vrtc_init(struct vm *vm)
{
struct vm_io_range range = {
.flags = IO_ATTR_RW, .base = CMOS_ADDR_PORT, .len = 2U};
/* Initializing the CMOS RAM offset to 0U */
vm->vrtc_offset = 0U;
register_io_emulation_handler(vm, &range, vrtc_read, vrtc_write);
}

View File

@ -166,6 +166,7 @@ struct vm {
#ifdef CONFIG_PARTITION_MODE
struct vm_description *vm_desc;
struct vpci vpci;
uint8_t vrtc_offset;
#endif
};
@ -275,5 +276,7 @@ struct pcpu_vm_desc_mapping {
bool is_bsp;
};
extern const struct pcpu_vm_desc_mapping pcpu_vm_desc_map[];
void vrtc_init(struct vm *vm);
#endif
#endif /* VM_H_ */