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:
parent
f63c7a7355
commit
022ef92b62
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in New Issue