This patch fixes system time in guests by implementing proper CMOS RTC clock support. # Before: sh-2.05b# date Fri Aug 7 04:02:01 UTC 2009 # After: sh-2.05b# date Thu Apr 28 19:12:21 UTC 2011 Cc: Asias He <asias.hejun@xxxxxxxxx> Cc: Cyrill Gorcunov <gorcunov@xxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: Prasad Joshi <prasadjoshi124@xxxxxxxxx> Cc: Sasha Levin <levinsasha928@xxxxxxxxx> Signed-off-by: Pekka Enberg <penberg@xxxxxxxxxx> --- tools/kvm/Makefile | 3 +- tools/kvm/include/kvm/rtc.h | 6 +++ tools/kvm/ioport.c | 26 ------------- tools/kvm/kvm-run.c | 3 + tools/kvm/rtc.c | 87 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 98 insertions(+), 27 deletions(-) create mode 100644 tools/kvm/include/kvm/rtc.h create mode 100644 tools/kvm/rtc.c diff --git a/tools/kvm/Makefile b/tools/kvm/Makefile index fbce14d..659bc35 100644 --- a/tools/kvm/Makefile +++ b/tools/kvm/Makefile @@ -26,8 +26,9 @@ OBJS += kvm-cpu.o OBJS += main.o OBJS += mmio.o OBJS += pci.o -OBJS += util.o +OBJS += rtc.o OBJS += term.o +OBJS += util.o OBJS += virtio.o OBJS += util/parse-options.o OBJS += util/strbuf.o diff --git a/tools/kvm/include/kvm/rtc.h b/tools/kvm/include/kvm/rtc.h new file mode 100644 index 0000000..0b8d9f9 --- /dev/null +++ b/tools/kvm/include/kvm/rtc.h @@ -0,0 +1,6 @@ +#ifndef KVM__RTC_H +#define KVM__RTC_H + +void rtc__init(void); + +#endif /* KVM__RTC_H */ diff --git a/tools/kvm/ioport.c b/tools/kvm/ioport.c index e3f67fc..a38d2d1 100644 --- a/tools/kvm/ioport.c +++ b/tools/kvm/ioport.c @@ -12,28 +12,6 @@ bool ioport_debug; -static uint8_t ioport_to_uint8(void *data) -{ - uint8_t *p = data; - - return *p; -} - -static bool cmos_ram_rtc_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) -{ - uint8_t value; - - value = ioport_to_uint8(data); - - self->nmi_disabled = value & (1UL << 7); - - return true; -} - -static struct ioport_operations cmos_ram_rtc_ops = { - .io_out = cmos_ram_rtc_io_out, -}; - static bool debug_io_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) { exit(EXIT_SUCCESS); @@ -128,10 +106,6 @@ void ioport__setup_legacy(void) ioport__register(0x0060, &dummy_read_write_ioport_ops, 2); ioport__register(0x0064, &dummy_read_write_ioport_ops, 1); - /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ - ioport__register(0x0070, &cmos_ram_rtc_ops, 1); - ioport__register(0x0071, &dummy_read_write_ioport_ops, 1); - /* 0x00A0 - 0x00AF - 8259A PIC 2 */ ioport__register(0x00A0, &dummy_read_write_ioport_ops, 2); diff --git a/tools/kvm/kvm-run.c b/tools/kvm/kvm-run.c index b21b4a2..64f3409 100644 --- a/tools/kvm/kvm-run.c +++ b/tools/kvm/kvm-run.c @@ -22,6 +22,7 @@ #include <kvm/disk-image.h> #include <kvm/util.h> #include <kvm/pci.h> +#include <kvm/rtc.h> #include <kvm/term.h> #include <kvm/ioport.h> #include <kvm/threadpool.h> @@ -416,6 +417,8 @@ int kvm_cmd_run(int argc, const char **argv, const char *prefix) ioport__setup_legacy(); + rtc__init(); + kvm__setup_bios(kvm); serial8250__init(kvm); diff --git a/tools/kvm/rtc.c b/tools/kvm/rtc.c new file mode 100644 index 0000000..b9c09b9 --- /dev/null +++ b/tools/kvm/rtc.c @@ -0,0 +1,87 @@ +#include "kvm/rtc.h" + +#include "kvm/ioport.h" +#include "kvm/kvm.h" + +#include <time.h> + +static uint8_t cmos_index; + +#define CMOS_RTC_SECONDS 0x00 +#define CMOS_RTC_MINUTES 0x02 +#define CMOS_RTC_HOURS 0x04 +#define CMOS_RTC_DATE_OF_MONTH 0x07 +#define CMOS_RTC_MONTH 0x08 +#define CMOS_RTC_YEAR 0x09 + +static inline unsigned char bin2bcd(unsigned val) +{ + return ((val / 10) << 4) + val % 10; +} + +static bool cmos_ram_data_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + struct tm *tm; + time_t ti; + + time(&ti); + + tm = gmtime(&ti); + + switch (cmos_index) { + case CMOS_RTC_SECONDS: + ioport__write8(data, bin2bcd(tm->tm_sec)); + break; + case CMOS_RTC_MINUTES: + ioport__write8(data, bin2bcd(tm->tm_min)); + break; + case CMOS_RTC_HOURS: + ioport__write8(data, bin2bcd(tm->tm_hour)); + break; + case CMOS_RTC_DATE_OF_MONTH: + ioport__write8(data, bin2bcd(tm->tm_mday)); + break; + case CMOS_RTC_MONTH: + ioport__write8(data, bin2bcd(tm->tm_mon + 1)); + break; + case CMOS_RTC_YEAR: + ioport__write8(data, bin2bcd(tm->tm_year)); + break; + } + + return true; +} + +static bool cmos_ram_data_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + 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 kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + uint8_t value; + + value = ioport__read8(data); + + self->nmi_disabled = value & (1UL << 7); + + cmos_index = value & ~(1UL << 7); + + return true; +} + +static struct ioport_operations cmos_ram_index_ioport_ops = { + .io_out = cmos_ram_index_out, +}; + +void rtc__init(void) +{ + /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ + ioport__register(0x0070, &cmos_ram_index_ioport_ops, 1); + ioport__register(0x0071, &cmos_ram_data_ioport_ops, 1); +} -- 1.7.0.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html