1899fe063SPekka Enberg #include "kvm/8250-serial.h" 213a7760fSPekka Enberg 38eb47d29SSasha Levin #include "kvm/read-write.h" 413a7760fSPekka Enberg #include "kvm/ioport.h" 54ef0f4d6SPekka 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 103fdf659dSSasha Levin #include <linux/types.h> 114e49b05bSCyrill Gorcunov #include <linux/serial_reg.h> 124e49b05bSCyrill Gorcunov 132932c9ebSPekka Enberg #include <pthread.h> 1413a7760fSPekka Enberg 1546aa8d69SPekka Enberg struct serial8250_device { 162932c9ebSPekka Enberg pthread_mutex_t mutex; 171add4b76SSasha Levin u8 id; 182932c9ebSPekka Enberg 193fdf659dSSasha Levin u16 iobase; 203fdf659dSSasha Levin u8 irq; 21f6b8ccc1SThomas Gleixner u8 irq_state; 22*8dfae8beSThomas Gleixner int txcnt; 2376b4a122SPekka Enberg 243fdf659dSSasha Levin u8 rbr; /* receive buffer */ 253fdf659dSSasha Levin u8 dll; 263fdf659dSSasha Levin u8 dlm; 273fdf659dSSasha Levin u8 iir; 283fdf659dSSasha Levin u8 ier; 293fdf659dSSasha Levin u8 fcr; 303fdf659dSSasha Levin u8 lcr; 313fdf659dSSasha Levin u8 mcr; 323fdf659dSSasha Levin u8 lsr; 333fdf659dSSasha Levin u8 msr; 343fdf659dSSasha Levin u8 scr; 3546aa8d69SPekka Enberg }; 3646aa8d69SPekka Enberg 37f3efa592SLiming Wang #define SERIAL_REGS_SETTING \ 38f3efa592SLiming Wang .iir = UART_IIR_NO_INT, \ 39f3efa592SLiming Wang .lsr = UART_LSR_TEMT | UART_LSR_THRE, \ 40f3efa592SLiming Wang .msr = UART_MSR_DCD | UART_MSR_DSR | UART_MSR_CTS, \ 41f3efa592SLiming Wang .mcr = UART_MCR_OUT2, 42f3efa592SLiming Wang 43e62c18deSPekka Enberg static struct serial8250_device devices[] = { 44c6a69c61SPekka Enberg /* ttyS0 */ 45c6a69c61SPekka Enberg [0] = { 462932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 472932c9ebSPekka Enberg 481add4b76SSasha Levin .id = 0, 49c6a69c61SPekka Enberg .iobase = 0x3f8, 50e557eef9SPekka Enberg .irq = 4, 51e557eef9SPekka Enberg 52f3efa592SLiming Wang SERIAL_REGS_SETTING 53c6a69c61SPekka Enberg }, 54e62c18deSPekka Enberg /* ttyS1 */ 55e62c18deSPekka Enberg [1] = { 562932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 572932c9ebSPekka Enberg 581add4b76SSasha Levin .id = 1, 59e62c18deSPekka Enberg .iobase = 0x2f8, 60e62c18deSPekka Enberg .irq = 3, 61133bedc1SPekka Enberg 62f3efa592SLiming Wang SERIAL_REGS_SETTING 63e62c18deSPekka Enberg }, 64e62c18deSPekka Enberg /* ttyS2 */ 65e62c18deSPekka Enberg [2] = { 662932c9ebSPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 672932c9ebSPekka Enberg 681add4b76SSasha Levin .id = 2, 69e62c18deSPekka Enberg .iobase = 0x3e8, 70e62c18deSPekka Enberg .irq = 4, 71133bedc1SPekka Enberg 72f3efa592SLiming Wang SERIAL_REGS_SETTING 73e62c18deSPekka Enberg }, 74bf459c83SPekka Enberg /* ttyS3 */ 75bf459c83SPekka Enberg [3] = { 76bf459c83SPekka Enberg .mutex = PTHREAD_MUTEX_INITIALIZER, 77bf459c83SPekka Enberg 781add4b76SSasha Levin .id = 3, 79bf459c83SPekka Enberg .iobase = 0x2e8, 80bf459c83SPekka Enberg .irq = 3, 81bf459c83SPekka Enberg 82f3efa592SLiming Wang SERIAL_REGS_SETTING 83bf459c83SPekka Enberg }, 8446aa8d69SPekka Enberg }; 8546aa8d69SPekka Enberg 86f6b8ccc1SThomas Gleixner static void serial8250_update_irq(struct kvm *kvm, struct serial8250_device *dev) 87f6b8ccc1SThomas Gleixner { 88f6b8ccc1SThomas Gleixner u8 iir = 0; 89f6b8ccc1SThomas Gleixner 90f6b8ccc1SThomas Gleixner /* Data ready and rcv interrupt enabled ? */ 91f6b8ccc1SThomas Gleixner if ((dev->ier & UART_IER_RDI) && (dev->lsr & UART_LSR_DR)) 92f6b8ccc1SThomas Gleixner iir |= UART_IIR_RDI; 93f6b8ccc1SThomas Gleixner 94f6b8ccc1SThomas Gleixner /* Transmitter empty and interrupt enabled ? */ 95f6b8ccc1SThomas Gleixner if ((dev->ier & UART_IER_THRI) && (dev->lsr & UART_LSR_TEMT)) 96f6b8ccc1SThomas Gleixner iir |= UART_IIR_THRI; 97f6b8ccc1SThomas Gleixner 98f6b8ccc1SThomas Gleixner /* Now update the irq line, if necessary */ 99f6b8ccc1SThomas Gleixner if (!iir) { 100f6b8ccc1SThomas Gleixner dev->iir = UART_IIR_NO_INT; 101f6b8ccc1SThomas Gleixner if (dev->irq_state) 102f6b8ccc1SThomas Gleixner kvm__irq_line(kvm, dev->irq, 0); 103f6b8ccc1SThomas Gleixner } else { 104f6b8ccc1SThomas Gleixner dev->iir = iir; 105f6b8ccc1SThomas Gleixner if (!dev->irq_state) 106f6b8ccc1SThomas Gleixner kvm__irq_line(kvm, dev->irq, 1); 107f6b8ccc1SThomas Gleixner } 108f6b8ccc1SThomas Gleixner dev->irq_state = iir; 109*8dfae8beSThomas Gleixner 110*8dfae8beSThomas Gleixner /* 111*8dfae8beSThomas Gleixner * If the kernel disabled the tx interrupt, we know that there 112*8dfae8beSThomas Gleixner * is nothing more to transmit, so we can reset our tx logic 113*8dfae8beSThomas Gleixner * here. 114*8dfae8beSThomas Gleixner */ 115*8dfae8beSThomas Gleixner if (!(dev->ier & UART_IER_THRI)) { 116*8dfae8beSThomas Gleixner dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; 117*8dfae8beSThomas Gleixner dev->txcnt = 0; 118*8dfae8beSThomas Gleixner } 119f6b8ccc1SThomas Gleixner } 120f6b8ccc1SThomas Gleixner 121a428f72eSPekka Enberg #define SYSRQ_PENDING_NONE 0 122a428f72eSPekka Enberg #define SYSRQ_PENDING_BREAK 1 123a428f72eSPekka Enberg #define SYSRQ_PENDING_CMD 2 124a428f72eSPekka Enberg 125a428f72eSPekka Enberg static int sysrq_pending; 126a428f72eSPekka Enberg 12743835ac9SSasha Levin static void serial8250__sysrq(struct kvm *kvm, struct serial8250_device *dev) 128a428f72eSPekka Enberg { 129a428f72eSPekka Enberg switch (sysrq_pending) { 130a428f72eSPekka Enberg case SYSRQ_PENDING_BREAK: 131a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR | UART_LSR_BI; 132a428f72eSPekka Enberg 133a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_CMD; 134a428f72eSPekka Enberg break; 135a428f72eSPekka Enberg case SYSRQ_PENDING_CMD: 136a428f72eSPekka Enberg dev->rbr = 'p'; 137a428f72eSPekka Enberg dev->lsr |= UART_LSR_DR; 138a428f72eSPekka Enberg 139a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_NONE; 140a428f72eSPekka Enberg break; 141a428f72eSPekka Enberg } 142a428f72eSPekka Enberg } 143a428f72eSPekka Enberg 14443835ac9SSasha Levin static void serial8250__receive(struct kvm *kvm, struct serial8250_device *dev) 145251cf9a6SPekka Enberg { 146251cf9a6SPekka Enberg int c; 147251cf9a6SPekka Enberg 148*8dfae8beSThomas Gleixner /* 149*8dfae8beSThomas Gleixner * If the guest transmitted 16 chars in a row, we clear the 150*8dfae8beSThomas Gleixner * TEMT/THRE bits to let the kernel escape from the 8250 151*8dfae8beSThomas Gleixner * interrupt handler. We come here only once a ms, so that 152*8dfae8beSThomas Gleixner * should give the kernel the desired pause. 153*8dfae8beSThomas Gleixner */ 154*8dfae8beSThomas Gleixner dev->lsr |= UART_LSR_TEMT | UART_LSR_THRE; 155*8dfae8beSThomas Gleixner dev->txcnt = 0; 156*8dfae8beSThomas Gleixner 157db34045cSPekka Enberg if (dev->lsr & UART_LSR_DR) 158db34045cSPekka Enberg return; 159db34045cSPekka Enberg 160a428f72eSPekka Enberg if (sysrq_pending) { 16143835ac9SSasha Levin serial8250__sysrq(kvm, dev); 162a428f72eSPekka Enberg return; 163a428f72eSPekka Enberg } 164a428f72eSPekka Enberg 1651add4b76SSasha Levin if (!term_readable(CONSOLE_8250, dev->id)) 166251cf9a6SPekka Enberg return; 167251cf9a6SPekka Enberg 1681add4b76SSasha Levin c = term_getc(CONSOLE_8250, dev->id); 16905d1a2a6SAsias He 170251cf9a6SPekka Enberg if (c < 0) 171251cf9a6SPekka Enberg return; 172251cf9a6SPekka Enberg 173251cf9a6SPekka Enberg dev->rbr = c; 174251cf9a6SPekka Enberg dev->lsr |= UART_LSR_DR; 175251cf9a6SPekka Enberg } 176251cf9a6SPekka Enberg 177f6b8ccc1SThomas Gleixner void serial8250__update_consoles(struct kvm *kvm) 1788bb34e0dSPekka Enberg { 179479de16fSCyrill Gorcunov unsigned int i; 1801add4b76SSasha Levin 181479de16fSCyrill Gorcunov for (i = 0; i < ARRAY_SIZE(devices); i++) { 1821add4b76SSasha Levin struct serial8250_device *dev = &devices[i]; 183934c193bSPekka Enberg 1844ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 1852932c9ebSPekka Enberg 18643835ac9SSasha Levin serial8250__receive(kvm, dev); 187251cf9a6SPekka Enberg 188f6b8ccc1SThomas Gleixner serial8250_update_irq(kvm, dev); 1892932c9ebSPekka Enberg 1904ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 1918bb34e0dSPekka Enberg } 1921add4b76SSasha Levin } 1938bb34e0dSPekka Enberg 19443835ac9SSasha Levin void serial8250__inject_sysrq(struct kvm *kvm) 195a428f72eSPekka Enberg { 196a428f72eSPekka Enberg sysrq_pending = SYSRQ_PENDING_BREAK; 197a428f72eSPekka Enberg } 198a428f72eSPekka Enberg 1993fdf659dSSasha Levin static struct serial8250_device *find_device(u16 port) 200c6a69c61SPekka Enberg { 201c6a69c61SPekka Enberg unsigned int i; 202c6a69c61SPekka Enberg 203c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 204c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 205c6a69c61SPekka Enberg 206c6a69c61SPekka Enberg if (dev->iobase == (port & ~0x7)) 207c6a69c61SPekka Enberg return dev; 208c6a69c61SPekka Enberg } 209c6a69c61SPekka Enberg return NULL; 210c6a69c61SPekka Enberg } 211c6a69c61SPekka Enberg 212c9f6a037SXiao Guangrong static bool serial8250_out(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 21313a7760fSPekka Enberg { 214c6a69c61SPekka Enberg struct serial8250_device *dev; 2153fdf659dSSasha Levin u16 offset; 2162932c9ebSPekka Enberg bool ret = true; 21746aa8d69SPekka Enberg 218c6a69c61SPekka Enberg dev = find_device(port); 219c6a69c61SPekka Enberg if (!dev) 220c6a69c61SPekka Enberg return false; 221c6a69c61SPekka Enberg 2224ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2232932c9ebSPekka Enberg 224c6a69c61SPekka Enberg offset = port - dev->iobase; 225c6a69c61SPekka Enberg 22646aa8d69SPekka Enberg switch (offset) { 227c59fa0c4SThomas Gleixner case UART_TX: 228c59fa0c4SThomas Gleixner if (!(dev->lcr & UART_LCR_DLAB)) { 22905d1a2a6SAsias He char *addr = data; 2300ea58e5bSPekka Enberg 2310ea58e5bSPekka Enberg if (!(dev->mcr & UART_MCR_LOOP)) 2321add4b76SSasha Levin term_putc(CONSOLE_8250, addr, size, dev->id); 233f6b8ccc1SThomas Gleixner /* else FIXME: Inject data into rcv path for LOOP */ 2340ea58e5bSPekka Enberg 235*8dfae8beSThomas Gleixner if (++dev->txcnt == 16) 236*8dfae8beSThomas Gleixner dev->lsr &= ~(UART_LSR_TEMT | UART_LSR_THRE); 237f6b8ccc1SThomas Gleixner break; 238c59fa0c4SThomas Gleixner } else { 239c59fa0c4SThomas Gleixner dev->dll = ioport__read8(data); 24046aa8d69SPekka Enberg } 241369c01c0SPekka Enberg break; 2424e49b05bSCyrill Gorcunov case UART_IER: 243f6b8ccc1SThomas Gleixner if (!(dev->lcr & UART_LCR_DLAB)) 244369c01c0SPekka Enberg dev->ier = ioport__read8(data) & 0x3f; 245f6b8ccc1SThomas Gleixner else 246c59fa0c4SThomas Gleixner dev->dlm = ioport__read8(data); 247c59fa0c4SThomas Gleixner break; 248c59fa0c4SThomas Gleixner case UART_FCR: 249c59fa0c4SThomas Gleixner dev->fcr = ioport__read8(data); 25046aa8d69SPekka Enberg break; 251369c01c0SPekka Enberg case UART_LCR: 252369c01c0SPekka Enberg dev->lcr = ioport__read8(data); 253369c01c0SPekka Enberg break; 254369c01c0SPekka Enberg case UART_MCR: 255369c01c0SPekka Enberg dev->mcr = ioport__read8(data); 256369c01c0SPekka Enberg break; 257369c01c0SPekka Enberg case UART_LSR: 258369c01c0SPekka Enberg /* Factory test */ 259369c01c0SPekka Enberg break; 260369c01c0SPekka Enberg case UART_MSR: 261369c01c0SPekka Enberg /* Not used */ 262369c01c0SPekka Enberg break; 263369c01c0SPekka Enberg case UART_SCR: 264369c01c0SPekka Enberg dev->scr = ioport__read8(data); 265369c01c0SPekka Enberg break; 266369c01c0SPekka Enberg default: 2672932c9ebSPekka Enberg ret = false; 268d2ea115dSThomas Gleixner break; 26946aa8d69SPekka Enberg } 2702932c9ebSPekka Enberg 271f6b8ccc1SThomas Gleixner serial8250_update_irq(kvm, dev); 272f6b8ccc1SThomas Gleixner 2734ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 2742932c9ebSPekka Enberg 2752932c9ebSPekka Enberg return ret; 27613a7760fSPekka Enberg } 27713a7760fSPekka Enberg 278c9f6a037SXiao Guangrong static bool serial8250_in(struct ioport *ioport, struct kvm *kvm, u16 port, void *data, int size) 27925af6674SPekka Enberg { 280c6a69c61SPekka Enberg struct serial8250_device *dev; 2813fdf659dSSasha Levin u16 offset; 2822932c9ebSPekka Enberg bool ret = true; 28346aa8d69SPekka Enberg 284c6a69c61SPekka Enberg dev = find_device(port); 285c6a69c61SPekka Enberg if (!dev) 286c6a69c61SPekka Enberg return false; 287c6a69c61SPekka Enberg 2884ef0f4d6SPekka Enberg mutex_lock(&dev->mutex); 2892932c9ebSPekka Enberg 290c6a69c61SPekka Enberg offset = port - dev->iobase; 291c6a69c61SPekka Enberg 29246aa8d69SPekka Enberg switch (offset) { 293251cf9a6SPekka Enberg case UART_RX: 294c59fa0c4SThomas Gleixner if (dev->lcr & UART_LCR_DLAB) { 295c59fa0c4SThomas Gleixner ioport__write8(data, dev->dll); 296c59fa0c4SThomas Gleixner } else { 297251cf9a6SPekka Enberg ioport__write8(data, dev->rbr); 298369c01c0SPekka Enberg dev->lsr &= ~UART_LSR_DR; 299c59fa0c4SThomas Gleixner } 300369c01c0SPekka Enberg break; 301c59fa0c4SThomas Gleixner case UART_IER: 302c59fa0c4SThomas Gleixner if (dev->lcr & UART_LCR_DLAB) 303c59fa0c4SThomas Gleixner ioport__write8(data, dev->dlm); 304c59fa0c4SThomas Gleixner else 305c59fa0c4SThomas Gleixner ioport__write8(data, dev->ier); 306c59fa0c4SThomas Gleixner break; 307f6b8ccc1SThomas Gleixner case UART_IIR: 308f6b8ccc1SThomas Gleixner ioport__write8(data, dev->iir); 30946aa8d69SPekka Enberg break; 3104e49b05bSCyrill Gorcunov case UART_LCR: 311c6a69c61SPekka Enberg ioport__write8(data, dev->lcr); 31246aa8d69SPekka Enberg break; 3134e49b05bSCyrill Gorcunov case UART_MCR: 314c6a69c61SPekka Enberg ioport__write8(data, dev->mcr); 31546aa8d69SPekka Enberg break; 3164e49b05bSCyrill Gorcunov case UART_LSR: 317c6a69c61SPekka Enberg ioport__write8(data, dev->lsr); 31846aa8d69SPekka Enberg break; 3194e49b05bSCyrill Gorcunov case UART_MSR: 320369c01c0SPekka Enberg ioport__write8(data, dev->msr); 32146aa8d69SPekka Enberg break; 3224e49b05bSCyrill Gorcunov case UART_SCR: 323369c01c0SPekka Enberg ioport__write8(data, dev->scr); 32446aa8d69SPekka Enberg break; 325369c01c0SPekka Enberg default: 3262932c9ebSPekka Enberg ret = false; 327c59fa0c4SThomas Gleixner break; 32825af6674SPekka Enberg } 329f6b8ccc1SThomas Gleixner 330f6b8ccc1SThomas Gleixner serial8250_update_irq(kvm, dev); 331f6b8ccc1SThomas Gleixner 3324ef0f4d6SPekka Enberg mutex_unlock(&dev->mutex); 3332932c9ebSPekka Enberg 3342932c9ebSPekka Enberg return ret; 33513a7760fSPekka Enberg } 33613a7760fSPekka Enberg 33746aa8d69SPekka Enberg static struct ioport_operations serial8250_ops = { 33846aa8d69SPekka Enberg .io_in = serial8250_in, 33946aa8d69SPekka Enberg .io_out = serial8250_out, 340a93ec68bSPekka Enberg }; 341a93ec68bSPekka Enberg 342bc4b0ffeSPekka Enberg static void serial8250__device_init(struct kvm *kvm, struct serial8250_device *dev) 343bc4b0ffeSPekka Enberg { 3443d62dea6SSasha Levin ioport__register(dev->iobase, &serial8250_ops, 8, NULL); 345bc4b0ffeSPekka Enberg kvm__irq_line(kvm, dev->irq, 0); 346bc4b0ffeSPekka Enberg } 347bc4b0ffeSPekka Enberg 348bc4b0ffeSPekka Enberg void serial8250__init(struct kvm *kvm) 34913a7760fSPekka Enberg { 350c6a69c61SPekka Enberg unsigned int i; 351c6a69c61SPekka Enberg 352c6a69c61SPekka Enberg for (i = 0; i < ARRAY_SIZE(devices); i++) { 353c6a69c61SPekka Enberg struct serial8250_device *dev = &devices[i]; 354c6a69c61SPekka Enberg 355bc4b0ffeSPekka Enberg serial8250__device_init(kvm, dev); 356c6a69c61SPekka Enberg } 35713a7760fSPekka Enberg } 358