From 13a7760f97195e83997c4aab20afbd851459e7c3 Mon Sep 17 00:00:00 2001 From: Pekka Enberg Date: Sun, 11 Apr 2010 20:42:10 +0300 Subject: [PATCH] kvm: Add support for early serial printk Signed-off-by: Pekka Enberg --- Makefile | 1 + early_printk.c | 37 +++++++++++++++++++++++++++++++++++++ include/kvm/early_printk.h | 6 ++++++ include/kvm/ioport.h | 16 ++++++++++++++++ ioport.c | 19 ++++++++++++++----- main.c | 3 +++ 6 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 early_printk.c create mode 100644 include/kvm/early_printk.h create mode 100644 include/kvm/ioport.h diff --git a/Makefile b/Makefile index 1846f3c..8db8548 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ export E Q PROGRAM = kvm OBJS += cpuid.o +OBJS += early_printk.o OBJS += interrupt.o OBJS += ioport.o OBJS += kvm.o diff --git a/early_printk.c b/early_printk.c new file mode 100644 index 0000000..026ab78 --- /dev/null +++ b/early_printk.c @@ -0,0 +1,37 @@ +#include "kvm/early_printk.h" + +#include "kvm/ioport.h" + +#include + +static bool early_serial_txr_out(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + char *p = data; + + printf("%c", *p); + + return true; +} + +static struct ioport_operations early_serial_txr_ops = { + .io_out = early_serial_txr_out, +}; + +static bool early_serial_lsr_in(struct kvm *self, uint16_t port, void *data, int size, uint32_t count) +{ + uint8_t *p = data; + + *p = 0x20; /* xmtrdy */ + + return true; +} + +static struct ioport_operations early_serial_lsr_ops = { + .io_in = early_serial_lsr_in, +}; + +void early_printk__init(void) +{ + ioport__register(0x03F8, &early_serial_txr_ops); + ioport__register(0x03FD, &early_serial_lsr_ops); +} diff --git a/include/kvm/early_printk.h b/include/kvm/early_printk.h new file mode 100644 index 0000000..3ff49c0 --- /dev/null +++ b/include/kvm/early_printk.h @@ -0,0 +1,6 @@ +#ifndef KVM__EARLY_PRINTK_H +#define KVM__EARLY_PRINTK_H + +void early_printk__init(void); + +#endif /* KVM__EARLY_PRINTK_H */ diff --git a/include/kvm/ioport.h b/include/kvm/ioport.h new file mode 100644 index 0000000..3721910 --- /dev/null +++ b/include/kvm/ioport.h @@ -0,0 +1,16 @@ +#ifndef KVM__IOPORT_H +#define KVM__IOPORT_H + +#include +#include + +struct kvm; + +struct ioport_operations { + bool (*io_in)(struct kvm *self, uint16_t port, void *data, int size, uint32_t count); + bool (*io_out)(struct kvm *self, uint16_t port, void *data, int size, uint32_t count); +}; + +void ioport__register(uint16_t port, struct ioport_operations *ops); + +#endif /* KVM__IOPORT_H */ diff --git a/ioport.c b/ioport.c index 31324b3..8930ccb 100644 --- a/ioport.c +++ b/ioport.c @@ -1,13 +1,11 @@ +#include "kvm/ioport.h" + #include "kvm/kvm.h" +#include #include #include -struct ioport_operations { - bool (*io_in)(struct kvm *self, uint16_t port, void *data, int size, uint32_t count); - bool (*io_out)(struct kvm *self, uint16_t port, void *data, int size, uint32_t count); -}; - static uint8_t ioport_to_uint8(void *data) { uint8_t *p = data; @@ -81,12 +79,23 @@ static struct ioport_operations *ioport_ops[USHRT_MAX] = { [0x3D4] = &dummy_read_write_ioport_ops, [0x3D5] = &dummy_write_only_ioport_ops, + /* PORT 03F8-03FF - Serial port (8250,8250A,8251,16450,16550,16550A,etc.) COM1 */ + [0x03F9] = &dummy_read_write_ioport_ops, + [0x03FA] = &dummy_read_write_ioport_ops, + [0x03FB] = &dummy_read_write_ioport_ops, + [0x03FC] = &dummy_read_write_ioport_ops, + /* PORT 0CF8-0CFF - PCI Configuration Mechanism 1 - Configuration Registers */ [0x0CF8] = &dummy_write_only_ioport_ops, [0x0CFC] = &dummy_read_write_ioport_ops, [0x0CFE] = &dummy_read_write_ioport_ops, }; +void ioport__register(uint16_t port, struct ioport_operations *ops) +{ + ioport_ops[port] = ops; +} + static const char *to_direction(int direction) { if (direction == KVM_EXIT_IO_IN) diff --git a/main.c b/main.c index b6414e7..61253fd 100644 --- a/main.c +++ b/main.c @@ -1,5 +1,6 @@ #include "kvm/kvm.h" +#include "kvm/early_printk.h" #include "kvm/util.h" #include @@ -58,6 +59,8 @@ int main(int argc, char *argv[]) if (single_step) kvm__enable_singlestep(kvm); + early_printk__init(); + for (;;) { kvm__run(kvm);