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