From patchwork Thu Apr 28 19:13:38 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pekka Enberg X-Patchwork-Id: 739571 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p3SJDjTb023188 for ; Thu, 28 Apr 2011 19:13:45 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755015Ab1D1TNm (ORCPT ); Thu, 28 Apr 2011 15:13:42 -0400 Received: from filtteri5.pp.htv.fi ([213.243.153.188]:41900 "EHLO filtteri5.pp.htv.fi" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751499Ab1D1TNl (ORCPT ); Thu, 28 Apr 2011 15:13:41 -0400 Received: from localhost (localhost [127.0.0.1]) by filtteri5.pp.htv.fi (Postfix) with ESMTP id 8F7AA5A62D3; Thu, 28 Apr 2011 22:13:40 +0300 (EEST) X-Virus-Scanned: Debian amavisd-new at pp.htv.fi Received: from smtp5.welho.com ([213.243.153.39]) by localhost (filtteri5.pp.htv.fi [213.243.153.188]) (amavisd-new, port 10024) with ESMTP id PcTdaOude2IX; Thu, 28 Apr 2011 22:13:40 +0300 (EEST) Received: from localhost.localdomain (cs181148025.pp.htv.fi [82.181.148.25]) by smtp5.welho.com (Postfix) with ESMTP id E2BB25BC005; Thu, 28 Apr 2011 22:13:39 +0300 (EEST) From: Pekka Enberg To: kvm@vger.kernel.org Cc: Pekka Enberg , Asias He , Cyrill Gorcunov , Ingo Molnar , Prasad Joshi , Sasha Levin Subject: [PATCH] kvm tools: Emulate RTC to fix system time in guests Date: Thu, 28 Apr 2011 22:13:38 +0300 Message-Id: <1304018018-8662-1-git-send-email-penberg@kernel.org> X-Mailer: git-send-email 1.7.0.4 Sender: kvm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: kvm@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 28 Apr 2011 19:13:45 +0000 (UTC) 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 Cc: Cyrill Gorcunov Cc: Ingo Molnar Cc: Prasad Joshi Cc: Sasha Levin Signed-off-by: Pekka Enberg --- 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 #include #include +#include #include #include #include @@ -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 + +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); +}