@@ -1,10 +1,15 @@
#ifndef KVM__CONSOLE_VIRTIO_H
#define KVM__CONSOLE_VIRTIO_H
+#include <linux/types.h>
+
struct kvm;
int virtio_console__init(struct kvm *kvm);
void virtio_console__inject_interrupt(struct kvm *kvm);
int virtio_console__exit(struct kvm *kvm);
+void console_write_config(struct kvm *kvm, void *dev, u64 addr, u32 i, u8 *data);
+void console_read_config(struct kvm *kvm, void *dev, u64 addr, u32 i, u8 *data);
+
#endif /* KVM__CONSOLE_VIRTIO_H */
@@ -118,9 +118,37 @@ static u8 *get_config(struct kvm *kvm, void *dev)
return ((u8 *)(&cdev->config));
}
+void console_write_config(struct kvm *kvm, void *dev, u64 addr, u32 i, u8 *data)
+{
+ struct con_dev *cdev = dev;
+ u8 *p;
+
+ if (addr != offsetof(struct virtio_console_config, early_rw)) {
+ p = ((u8 *)(&cdev->config));
+ p[addr + i] = *(u8 *)data + i;
+
+ } else {
+ /* early_rw write */
+ term_putc((char *) (data + i), 1, 0);
+ }
+}
+
+void console_read_config(struct kvm *kvm, void *dev, u64 addr, u32 i, u8 *data)
+{
+ struct con_dev *cdev = dev;
+ u8 *p;
+
+ if (addr != offsetof(struct virtio_console_config, early_rw)) {
+ p = ((u8 *)(&cdev->config));
+ data[i] = p[addr + i];
+ } else {
+ /* TBD: implement early_rw read with the help of term_getc */
+ }
+}
+
static u32 get_host_features(struct kvm *kvm, void *dev)
{
- return 0;
+ return (1 << VIRTIO_CONSOLE_F_EARLY_WRITE);
}
static void set_guest_features(struct kvm *kvm, void *dev, u32 features)
@@ -3,9 +3,11 @@
#include "kvm/ioeventfd.h"
#include "kvm/ioport.h"
#include "kvm/virtio.h"
+#include "kvm/virtio-console.h"
#include "kvm/kvm.h"
#include "kvm/irq.h"
+#include <linux/virtio_ids.h>
#include <linux/virtio_mmio.h>
#include <string.h>
@@ -94,12 +96,24 @@ static void virtio_mmio_device_specific(u64 addr, u8 *data, u32 len,
u32 i;
for (i = 0; i < len; i++) {
- if (is_write)
- vdev->ops->get_config(vmmio->kvm, vmmio->dev)[addr + i] =
- *(u8 *)data + i;
- else
- data[i] = vdev->ops->get_config(vmmio->kvm,
+ if (is_write) {
+ if (vmmio->hdr.device_id == VIRTIO_ID_CONSOLE) {
+ console_write_config(vmmio->kvm, vmmio->dev,
+ addr, i, data);
+ } else {
+ vdev->ops->get_config(vmmio->kvm,
+ vmmio->dev)[addr + i] =
+ *(u8 *)data + i;
+ }
+ } else {
+ if (vmmio->hdr.device_id == VIRTIO_ID_CONSOLE) {
+ console_read_config(vmmio->kvm, vmmio->dev,
+ addr, i, data);
+ } else {
+ data[i] = vdev->ops->get_config(vmmio->kvm,
vmmio->dev)[addr + i];
+ }
+ }
}
}