]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kvm,8250: Inject interrupts to guest
authorPekka Enberg <penberg@kernel.org>
Sun, 9 Jan 2011 16:28:03 +0000 (18:28 +0200)
committerPekka Enberg <penberg@kernel.org>
Sun, 9 Jan 2011 16:31:50 +0000 (18:31 +0200)
This patch fixes 8250 emulation to inject interrupts to guest so we actually
see what's sent to the serial console.

Signed-off-by: Pekka Enberg <penberg@kernel.org>
tools/kvm/8250-serial.c
tools/kvm/main.c

index b2101cc04e9625b9e53853582fad83aed9e35143..1bbf3f3d343a2afb7c77408f4e231ec705675337 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "kvm/ioport.h"
 #include "kvm/util.h"
+#include "kvm/kvm.h"
 
 #include <stdbool.h>
 
@@ -20,6 +21,8 @@
 /* Interrupt enable register */
 #define IER            1
 
+#define UART_IER_THRI          0x02
+
 /* Interrupt identification register */
 #define IIR            2
 
 
 struct serial8250_device {
        uint16_t                iobase;
+       uint8_t                 irq;
        uint8_t                 dll;
        uint8_t                 dlm;
+       uint8_t                 iir;
        uint8_t                 ier;
        uint8_t                 fcr;
        uint8_t                 lcr;
@@ -63,11 +68,17 @@ struct serial8250_device {
 
 static struct serial8250_device device = {
        .iobase                 = 0x3f8,        /* ttyS0 */
+       .irq                    = 4,
+
+       .iir                    = UART_IIR_NO_INT | UART_IIR_THRI,
 };
 
 void serial8250__interrupt(struct kvm *self)
 {
-       /* TODO: inject 8250 interrupt for the guest */
+       if (device.ier & UART_IER_THRI) {
+               device.iir              &= ~UART_IIR_NO_INT;
+               kvm__irq_line(self, device.irq, 1);
+       }
 }
 
 static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count)
@@ -102,6 +113,10 @@ static bool serial8250_out(struct kvm *self, uint16_t port, void *data, int size
                                        fprintf(stdout, "%c", *p++);
                        }
                        fflush(stdout);
+
+                       device.iir              |= UART_IIR_NO_INT;
+                       kvm__irq_line(self, device.irq, 0);
+
                        break;
                }
                case IER:
@@ -142,7 +157,7 @@ static bool serial8250_in(struct kvm *self, uint16_t port, void *data, int size,
                ioport__write8(data, device.ier);
                break;
        case IIR:
-               ioport__write8(data, UART_IIR_NO_INT | UART_IIR_THRI);
+               ioport__write8(data, device.iir);
                break;
        case LCR:
                ioport__write8(data, device.lcr);
index 7a3d66c03eaff6e4d32e58cb9e6d20afaa3cf0a2..720174ae91448a49b1d87c8d7e679a93c75aec8e 100644 (file)
@@ -46,7 +46,7 @@ static bool option_matches(char *arg, const char *option)
        return !strncmp(arg, option, strlen(option));
 }
 
-#define TIMER_INTERVAL_NS 1000000000
+#define TIMER_INTERVAL_NS 1000000      /* 1 msec */
 
 static void alarm_handler(int sig)
 {