@@ -42,11 +42,37 @@ static inline unsigned char bin2bcd(unsigned val)
return ((val / 10) << 4) + val % 10;
}
-static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data,
+ u32 len, u8 is_write, void *ptr)
{
struct tm *tm;
time_t ti;
+ if (is_write) {
+ if (addr == 0x70) { /* index register */
+ u8 value = ioport__read8(data);
+
+ vcpu->kvm->nmi_disabled = value & (1UL << 7);
+ rtc.cmos_idx = value & ~(1UL << 7);
+
+ return;
+ }
+
+ switch (rtc.cmos_idx) {
+ case RTC_REG_C:
+ case RTC_REG_D:
+ /* Read-only */
+ break;
+ default:
+ rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
+ break;
+ }
+ return;
+ }
+
+ if (addr == 0x70)
+ return;
+
time(&ti);
tm = gmtime(&ti);
@@ -92,42 +118,23 @@ static bool cmos_ram_data_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 po
ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]);
break;
}
-
- return true;
}
-static bool cmos_ram_data_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_in(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
{
- switch (rtc.cmos_idx) {
- case RTC_REG_C:
- case RTC_REG_D:
- /* Read-only */
- break;
- default:
- rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data);
- break;
- }
-
+ cmos_ram_io(vcpu, port, data, size, false, NULL);
return true;
}
-static struct ioport_operations cmos_ram_data_ioport_ops = {
- .io_out = cmos_ram_data_out,
- .io_in = cmos_ram_data_in,
-};
-
-static bool cmos_ram_index_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
+static bool cmos_ram_out(struct ioport *ioport, struct kvm_cpu *vcpu, u16 port, void *data, int size)
{
- u8 value = ioport__read8(data);
-
- vcpu->kvm->nmi_disabled = value & (1UL << 7);
- rtc.cmos_idx = value & ~(1UL << 7);
-
+ cmos_ram_io(vcpu, port, data, size, true, NULL);
return true;
}
-static struct ioport_operations cmos_ram_index_ioport_ops = {
- .io_out = cmos_ram_index_out,
+static struct ioport_operations cmos_ram_ioport_ops = {
+ .io_out = cmos_ram_out,
+ .io_in = cmos_ram_in,
};
#ifdef CONFIG_HAS_LIBFDT
@@ -162,21 +169,15 @@ int rtc__init(struct kvm *kvm)
return r;
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
- r = ioport__register(kvm, 0x0070, &cmos_ram_index_ioport_ops, 1, NULL);
+ r = ioport__register(kvm, 0x0070, &cmos_ram_ioport_ops, 2, NULL);
if (r < 0)
goto out_device;
- r = ioport__register(kvm, 0x0071, &cmos_ram_data_ioport_ops, 1, NULL);
- if (r < 0)
- goto out_ioport;
-
/* Set the VRT bit in Register D to indicate valid RAM and time */
rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT;
return r;
-out_ioport:
- ioport__unregister(kvm, 0x0070);
out_device:
device__unregister(&rtc_dev_hdr);
@@ -188,7 +189,6 @@ int rtc__exit(struct kvm *kvm)
{
/* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */
ioport__unregister(kvm, 0x0070);
- ioport__unregister(kvm, 0x0071);
return 0;
}