1 #include "kvm/rtc.h" 2 3 #include "kvm/ioport.h" 4 #include "kvm/kvm.h" 5 6 #include <time.h> 7 8 /* 9 * MC146818 RTC registers 10 */ 11 #define RTC_SECONDS 0x00 12 #define RTC_SECONDS_ALARM 0x01 13 #define RTC_MINUTES 0x02 14 #define RTC_MINUTES_ALARM 0x03 15 #define RTC_HOURS 0x04 16 #define RTC_HOURS_ALARM 0x05 17 #define RTC_DAY_OF_WEEK 0x06 18 #define RTC_DAY_OF_MONTH 0x07 19 #define RTC_MONTH 0x08 20 #define RTC_YEAR 0x09 21 #define RTC_CENTURY 0x32 22 23 #define RTC_REG_A 0x0A 24 #define RTC_REG_B 0x0B 25 #define RTC_REG_C 0x0C 26 #define RTC_REG_D 0x0D 27 28 /* 29 * Register D Bits 30 */ 31 #define RTC_REG_D_VRT (1 << 7) 32 33 struct rtc_device { 34 u8 cmos_idx; 35 u8 cmos_data[128]; 36 }; 37 38 static struct rtc_device rtc; 39 40 static inline unsigned char bin2bcd(unsigned val) 41 { 42 return ((val / 10) << 4) + val % 10; 43 } 44 45 static void cmos_ram_io(struct kvm_cpu *vcpu, u64 addr, u8 *data, 46 u32 len, u8 is_write, void *ptr) 47 { 48 struct tm *tm; 49 time_t ti; 50 51 if (is_write) { 52 if (addr == 0x70) { /* index register */ 53 u8 value = ioport__read8(data); 54 55 vcpu->kvm->nmi_disabled = value & (1UL << 7); 56 rtc.cmos_idx = value & ~(1UL << 7); 57 58 return; 59 } 60 61 switch (rtc.cmos_idx) { 62 case RTC_REG_C: 63 case RTC_REG_D: 64 /* Read-only */ 65 break; 66 default: 67 rtc.cmos_data[rtc.cmos_idx] = ioport__read8(data); 68 break; 69 } 70 return; 71 } 72 73 if (addr == 0x70) 74 return; 75 76 time(&ti); 77 78 tm = gmtime(&ti); 79 80 switch (rtc.cmos_idx) { 81 case RTC_SECONDS: 82 ioport__write8(data, bin2bcd(tm->tm_sec)); 83 break; 84 case RTC_MINUTES: 85 ioport__write8(data, bin2bcd(tm->tm_min)); 86 break; 87 case RTC_HOURS: 88 ioport__write8(data, bin2bcd(tm->tm_hour)); 89 break; 90 case RTC_DAY_OF_WEEK: 91 ioport__write8(data, bin2bcd(tm->tm_wday + 1)); 92 break; 93 case RTC_DAY_OF_MONTH: 94 ioport__write8(data, bin2bcd(tm->tm_mday)); 95 break; 96 case RTC_MONTH: 97 ioport__write8(data, bin2bcd(tm->tm_mon + 1)); 98 break; 99 case RTC_YEAR: { 100 int year; 101 102 year = tm->tm_year + 1900; 103 104 ioport__write8(data, bin2bcd(year % 100)); 105 106 break; 107 } 108 case RTC_CENTURY: { 109 int year; 110 111 year = tm->tm_year + 1900; 112 113 ioport__write8(data, bin2bcd(year / 100)); 114 115 break; 116 } 117 default: 118 ioport__write8(data, rtc.cmos_data[rtc.cmos_idx]); 119 break; 120 } 121 } 122 123 #ifdef CONFIG_HAS_LIBFDT 124 static void generate_rtc_fdt_node(void *fdt, 125 struct device_header *dev_hdr, 126 void (*generate_irq_prop)(void *fdt, 127 u8 irq, 128 enum irq_type)) 129 { 130 u64 reg_prop[2] = { cpu_to_fdt64(0x70), cpu_to_fdt64(2) }; 131 132 _FDT(fdt_begin_node(fdt, "rtc")); 133 _FDT(fdt_property_string(fdt, "compatible", "motorola,mc146818")); 134 _FDT(fdt_property(fdt, "reg", reg_prop, sizeof(reg_prop))); 135 _FDT(fdt_end_node(fdt)); 136 } 137 #else 138 #define generate_rtc_fdt_node NULL 139 #endif 140 141 struct device_header rtc_dev_hdr = { 142 .bus_type = DEVICE_BUS_IOPORT, 143 .data = generate_rtc_fdt_node, 144 }; 145 146 int rtc__init(struct kvm *kvm) 147 { 148 int r; 149 150 r = device__register(&rtc_dev_hdr); 151 if (r < 0) 152 return r; 153 154 /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ 155 r = kvm__register_pio(kvm, 0x0070, 2, cmos_ram_io, NULL); 156 if (r < 0) 157 goto out_device; 158 159 /* Set the VRT bit in Register D to indicate valid RAM and time */ 160 rtc.cmos_data[RTC_REG_D] = RTC_REG_D_VRT; 161 162 return r; 163 164 out_device: 165 device__unregister(&rtc_dev_hdr); 166 167 return r; 168 } 169 dev_init(rtc__init); 170 171 int rtc__exit(struct kvm *kvm) 172 { 173 /* PORT 0070-007F - CMOS RAM/RTC (REAL TIME CLOCK) */ 174 kvm__deregister_pio(kvm, 0x0070); 175 176 return 0; 177 } 178 dev_exit(rtc__exit); 179