1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 38eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 5*4ef0f4d6SPekka Enberg #include "kvm/mutex.h" 646aa8d69SPekka Enberg #include "kvm/util.h" 705d1a2a6SAsias He #include "kvm/term.h" 8e557eef9SPekka Enberg #include "kvm/kvm.h" 913a7760fSPekka Enberg 104e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 114e49b05bSCyrill Gorcunov 122932c9ebSPekka Enberg #include <pthread.h> 1313a7760fSPekka Enberg 1446aa8d69SPekka Enberg struct serial8250_device { 152932c9ebSPekka Enberg pthread_mutex_t mutex; 162932c9ebSPekka Enberg 1746aa8d69SPekka Enberg uint16_t iobase; 18e557eef9SPekka Enberg uint8_t irq; 1976b4a122SPekka Enberg 20251cf9a6SPekka Enberg uint8_t rbr; /* receive buffer */ 2146aa8d69SPekka Enberg uint8_t dll; 2246aa8d69SPekka Enberg uint8_t dlm; 23e557eef9SPekka Enberg uint8_t iir; 2446aa8d69SPekka Enberg uint8_t ier; 2546aa8d69SPekka Enberg uint8_t fcr; 2646aa8d69SPekka Enberg uint8_t lcr; 2746aa8d69SPekka Enberg uint8_t mcr; 2876b4a122SPekka Enberg uint8_t lsr; 29369c01c0SPekka Enberg uint8_t msr; 3046aa8d69SPekka Enberg uint8_t scr; 3146aa8d69SPekka Enberg }; 3246aa8d69SPekka Enberg 33e62c18deSPekka Enberg static struct serial8250_device devices[] = { 34c6a69c61SPekka Enberg /* ttyS0 */ 35c6a69c61SPekka Enberg [0] = { 362932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 372932c9ebSPekka Enberg 38c6a69c61SPekka Enberg .iobase = 0x3f8, 39e557eef9SPekka Enberg .irq = 4, 40e557eef9SPekka Enberg 41369c01c0SPekka Enberg .iir = UART_IIR_NO_INT, 42bc4b0ffeSPekka Enberg .lsr = UART_LSR_TEMT | UART_LSR_THRE, 43bc4b0ffeSPekka Enberg .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, 44bc4b0ffeSPekka Enberg .mcr = UART_MCR_OUT2, 45c6a69c61SPekka Enberg }, 46e62c18deSPekka Enberg /* ttyS1 */ 47e62c18deSPekka Enberg [1] = { 482932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 492932c9ebSPekka Enberg 50e62c18deSPekka Enberg .iobase = 0x2f8, 51e62c18deSPekka Enberg .irq = 3, 52133bedc1SPekka Enberg 53133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 54e62c18deSPekka Enberg }, 55e62c18deSPekka Enberg /* ttyS2 */ 56e62c18deSPekka Enberg [2] = { 572932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 582932c9ebSPekka Enberg 59e62c18deSPekka Enberg .iobase = 0x3e8, 60e62c18deSPekka Enberg .irq = 4, 61133bedc1SPekka Enberg 62133bedc1SPekka Enberg .iir = UART_IIR_NO_INT, 63e62c18deSPekka Enberg }, 6446aa8d69SPekka Enberg }; 6546aa8d69SPekka Enberg 66a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE 0 67a428f72eSPekka Enberg #define SYSRQ_PENDING_BREAK 1 68a428f72eSPekka Enberg #define SYSRQ_PENDING_CMD 2 69a428f72eSPekka Enberg 70a428f72eSPekka Enberg static int sysrq_pending; 71a428f72eSPekka Enberg 72a428f72eSPekka Enberg static void serial8250__sysrq(struct kvm *self, struct serial8250_device *dev) 73a428f72eSPekka Enberg { 74a428f72eSPekka Enberg switch (sysrq_pending) { 75a428f72eSPekka Enberg case SYSRQ_PENDING_BREAK: 76a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR | UART_LSR_BI; 77a428f72eSPekka Enberg 78a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_CMD; 79a428f72eSPekka Enberg break; 80a428f72eSPekka Enberg case SYSRQ_PENDING_CMD: 81a428f72eSPekka Enberg dev->rbr = 'p'; 82a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR; 83a428f72eSPekka Enberg 84a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_NONE; 85a428f72eSPekka Enberg break; 86a428f72eSPekka Enberg } 87a428f72eSPekka Enberg } 88a428f72eSPekka Enberg 89251cf9a6SPekka Enberg static void serial8250__receive(struct kvm *self, struct serial8250_device *dev) 90251cf9a6SPekka Enberg { 91251cf9a6SPekka Enberg int c; 92251cf9a6SPekka Enberg 93db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 94db34045cSPekka Enberg return; 95db34045cSPekka Enberg 96a428f72eSPekka Enberg if (sysrq_pending) { 97a428f72eSPekka Enberg serial8250__sysrq(self, dev); 98a428f72eSPekka Enberg return; 99a428f72eSPekka Enberg } 100a428f72eSPekka Enberg 10105d1a2a6SAsias He if (!term_readable(CONSOLE_8250)) 102251cf9a6SPekka Enberg return; 103251cf9a6SPekka Enberg 10405d1a2a6SAsias He c = term_getc(CONSOLE_8250); 10505d1a2a6SAsias He 106251cf9a6SPekka Enberg if (c < 0) 107251cf9a6SPekka Enberg return; 108251cf9a6SPekka Enberg 109251cf9a6SPekka Enberg dev->rbr = c; 110251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 111251cf9a6SPekka Enberg } 112251cf9a6SPekka Enberg 113c6a69c61SPekka Enberg /* 114c6a69c61SPekka Enberg * Interrupts are injected for ttyS0 only. 115c6a69c61SPekka Enberg */ 11605d1a2a6SAsias He void serial8250__inject_interrupt(struct kvm *self) 1178bb34e0dSPekka Enberg { 118c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[0]; 119934c193bSPekka Enberg 120*4ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1212932c9ebSPekka Enberg 122251cf9a6SPekka Enberg serial8250__receive(self, dev); 123251cf9a6SPekka Enberg 124369c01c0SPekka Enberg if (dev->ier & UART_IER_RDI && dev->lsr & UART_LSR_DR) 125369c01c0SPekka Enberg dev->iir = UART_IIR_RDI; 126251cf9a6SPekka Enberg else if (dev->ier & UART_IER_THRI) 127369c01c0SPekka Enberg dev->iir = UART_IIR_THRI; 128369c01c0SPekka Enberg else 129369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 13076b4a122SPekka Enberg 131369c01c0SPekka Enberg if (dev->iir != UART_IIR_NO_INT) { 132c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 0); 133c6a69c61SPekka Enberg kvm__irq_line(self, dev->irq, 1); 134e557eef9SPekka Enberg } 1352932c9ebSPekka Enberg 136*4ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 1378bb34e0dSPekka Enberg } 1388bb34e0dSPekka Enberg 139a428f72eSPekka Enberg void serial8250__inject_sysrq(struct kvm *self) 140a428f72eSPekka Enberg { 141a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_BREAK; 142a428f72eSPekka Enberg } 143a428f72eSPekka Enberg 144c6a69c61SPekka Enberg static struct serial8250_device *find_device(uint16_t port) 145c6a69c61SPekka Enberg { 146c6a69c61SPekka Enberg unsigned int i; 147c6a69c61SPekka Enberg 148c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 149c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 150c6a69c61SPekka Enberg 151c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 152c6a69c61SPekka Enberg return dev; 153c6a69c61SPekka Enberg } 154c6a69c61SPekka Enberg return NULL; 155c6a69c61SPekka Enberg } 156c6a69c61SPekka Enberg 15746aa8d69SPekka Enberg static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 15813a7760fSPekka Enberg { 159c6a69c61SPekka Enberg struct serial8250_device *dev; 160c6a69c61SPekka Enberg uint16_t offset; 1612932c9ebSPekka Enberg bool ret = true; 16246aa8d69SPekka Enberg 163c6a69c61SPekka Enberg dev = find_device(port); 164c6a69c61SPekka Enberg if (!dev) 165c6a69c61SPekka Enberg return false; 166c6a69c61SPekka Enberg 167*4ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1682932c9ebSPekka Enberg 169c6a69c61SPekka Enberg offset = port - dev->iobase; 170c6a69c61SPekka Enberg 171c6a69c61SPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 17246aa8d69SPekka Enberg switch (offset) { 1734e49b05bSCyrill Gorcunov case UART_DLL: 174c6a69c61SPekka Enberg dev->dll = ioport__read8(data); 17546aa8d69SPekka Enberg break; 1764e49b05bSCyrill Gorcunov case UART_DLM: 177c6a69c61SPekka Enberg dev->dlm = ioport__read8(data); 17846aa8d69SPekka Enberg break; 179369c01c0SPekka Enberg case UART_FCR: 180369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 181369c01c0SPekka Enberg break; 182369c01c0SPekka Enberg case UART_LCR: 183369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 184369c01c0SPekka Enberg break; 185369c01c0SPekka Enberg case UART_MCR: 186369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 187369c01c0SPekka Enberg break; 188369c01c0SPekka Enberg case UART_LSR: 189369c01c0SPekka Enberg /* Factory test */ 190369c01c0SPekka Enberg break; 191369c01c0SPekka Enberg case UART_MSR: 192369c01c0SPekka Enberg /* Not used */ 193369c01c0SPekka Enberg break; 194369c01c0SPekka Enberg case UART_SCR: 195369c01c0SPekka Enberg dev->scr = ioport__read8(data); 196369c01c0SPekka Enberg break; 197369c01c0SPekka Enberg default: 1982932c9ebSPekka Enberg ret = false; 1992932c9ebSPekka Enberg goto out_unlock; 20046aa8d69SPekka Enberg } 20146aa8d69SPekka Enberg } else { 20246aa8d69SPekka Enberg switch (offset) { 2034e49b05bSCyrill Gorcunov case UART_TX: { 20405d1a2a6SAsias He char *addr = data; 2050ea58e5bSPekka Enberg 2060ea58e5bSPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) 20705d1a2a6SAsias He term_putc(CONSOLE_8250, addr, size * count); 2080ea58e5bSPekka Enberg 209133bedc1SPekka Enberg dev->iir = UART_IIR_NO_INT; 21046aa8d69SPekka Enberg break; 21146aa8d69SPekka Enberg } 212369c01c0SPekka Enberg case UART_FCR: 213369c01c0SPekka Enberg dev->fcr = ioport__read8(data); 214369c01c0SPekka Enberg break; 2154e49b05bSCyrill Gorcunov case UART_IER: 216369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 21746aa8d69SPekka Enberg break; 218369c01c0SPekka Enberg case UART_LCR: 219369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 220369c01c0SPekka Enberg break; 221369c01c0SPekka Enberg case UART_MCR: 222369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 223369c01c0SPekka Enberg break; 224369c01c0SPekka Enberg case UART_LSR: 225369c01c0SPekka Enberg /* Factory test */ 226369c01c0SPekka Enberg break; 227369c01c0SPekka Enberg case UART_MSR: 228369c01c0SPekka Enberg /* Not used */ 229369c01c0SPekka Enberg break; 230369c01c0SPekka Enberg case UART_SCR: 231369c01c0SPekka Enberg dev->scr = ioport__read8(data); 232369c01c0SPekka Enberg break; 233369c01c0SPekka Enberg default: 2342932c9ebSPekka Enberg ret = false; 2352932c9ebSPekka Enberg goto out_unlock; 23646aa8d69SPekka Enberg } 23746aa8d69SPekka Enberg } 2382932c9ebSPekka Enberg 2392932c9ebSPekka Enberg out_unlock: 240*4ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2412932c9ebSPekka Enberg 2422932c9ebSPekka Enberg return ret; 24313a7760fSPekka Enberg } 24413a7760fSPekka Enberg 24546aa8d69SPekka Enberg static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) 24625af6674SPekka Enberg { 247c6a69c61SPekka Enberg struct serial8250_device *dev; 248c6a69c61SPekka Enberg uint16_t offset; 2492932c9ebSPekka Enberg bool ret = true; 25046aa8d69SPekka Enberg 251c6a69c61SPekka Enberg dev = find_device(port); 252c6a69c61SPekka Enberg if (!dev) 253c6a69c61SPekka Enberg return false; 254c6a69c61SPekka Enberg 255*4ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2562932c9ebSPekka Enberg 257c6a69c61SPekka Enberg offset = port - dev->iobase; 258c6a69c61SPekka Enberg 25919a2bb7dSPekka Enberg if (dev->lcr & UART_LCR_DLAB) { 26019a2bb7dSPekka Enberg switch (offset) { 26119a2bb7dSPekka Enberg case UART_DLL: 26219a2bb7dSPekka Enberg ioport__write8(data, dev->dll); 2632932c9ebSPekka Enberg goto out_unlock; 2642932c9ebSPekka Enberg 26519a2bb7dSPekka Enberg case UART_DLM: 26619a2bb7dSPekka Enberg ioport__write8(data, dev->dlm); 2672932c9ebSPekka Enberg goto out_unlock; 2682932c9ebSPekka Enberg 269369c01c0SPekka Enberg default: 270369c01c0SPekka Enberg break; 27119a2bb7dSPekka Enberg } 27219a2bb7dSPekka Enberg } else { 27346aa8d69SPekka Enberg switch (offset) { 274251cf9a6SPekka Enberg case UART_RX: 275251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 276369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 277369c01c0SPekka Enberg dev->iir = UART_IIR_NO_INT; 2782932c9ebSPekka Enberg goto out_unlock; 2792932c9ebSPekka Enberg 2804e49b05bSCyrill Gorcunov case UART_IER: 281c6a69c61SPekka Enberg ioport__write8(data, dev->ier); 2822932c9ebSPekka Enberg goto out_unlock; 2832932c9ebSPekka Enberg 284369c01c0SPekka Enberg default: 285369c01c0SPekka Enberg break; 28619a2bb7dSPekka Enberg } 28719a2bb7dSPekka Enberg } 28819a2bb7dSPekka Enberg 28919a2bb7dSPekka Enberg switch (offset) { 290369c01c0SPekka Enberg case UART_IIR: { 291369c01c0SPekka Enberg uint8_t iir = dev->iir; 292369c01c0SPekka Enberg 293369c01c0SPekka Enberg if (dev->fcr & UART_FCR_ENABLE_FIFO) 294369c01c0SPekka Enberg iir |= 0xc0; 295369c01c0SPekka Enberg 296369c01c0SPekka Enberg ioport__write8(data, iir); 29746aa8d69SPekka Enberg break; 298369c01c0SPekka Enberg } 2994e49b05bSCyrill Gorcunov case UART_LCR: 300c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 30146aa8d69SPekka Enberg break; 3024e49b05bSCyrill Gorcunov case UART_MCR: 303c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 30446aa8d69SPekka Enberg break; 3054e49b05bSCyrill Gorcunov case UART_LSR: 306c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 307369c01c0SPekka Enberg dev->lsr &= ~(UART_LSR_OE|UART_LSR_PE|UART_LSR_FE|UART_LSR_BI); 30846aa8d69SPekka Enberg break; 3094e49b05bSCyrill Gorcunov case UART_MSR: 310369c01c0SPekka Enberg ioport__write8(data, dev->msr); 31146aa8d69SPekka Enberg break; 3124e49b05bSCyrill Gorcunov case UART_SCR: 313369c01c0SPekka Enberg ioport__write8(data, dev->scr); 31446aa8d69SPekka Enberg break; 315369c01c0SPekka Enberg default: 3162932c9ebSPekka Enberg ret = false; 3172932c9ebSPekka Enberg goto out_unlock; 31825af6674SPekka Enberg } 3192932c9ebSPekka Enberg out_unlock: 320*4ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 3212932c9ebSPekka Enberg 3222932c9ebSPekka Enberg return ret; 32313a7760fSPekka Enberg } 32413a7760fSPekka Enberg 32546aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 32646aa8d69SPekka Enberg .io_in = serial8250_in, 32746aa8d69SPekka Enberg .io_out = serial8250_out, 328a93ec68bSPekka Enberg }; 329a93ec68bSPekka Enberg 330bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 331bc4b0ffeSPekka Enberg { 332bc4b0ffeSPekka Enberg ioport__register(dev->iobase, &serial8250_ops, 8); 333bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 334bc4b0ffeSPekka Enberg } 335bc4b0ffeSPekka Enberg 336bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 33713a7760fSPekka Enberg { 338c6a69c61SPekka Enberg unsigned int i; 339c6a69c61SPekka Enberg 340c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 341c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 342c6a69c61SPekka Enberg 343bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 344c6a69c61SPekka Enberg } 34513a7760fSPekka Enberg } 346