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