[PATCH 01/10] virtio: console: Add a __send_control_msg() that can send messages without a valid port

2010-04-05 Thread Amit Shah
We will introduce control messages that operate on the device as a whole
rather than just ports. Make send_control_msg() a wrapper around
__send_control_msg() which does not need a valid port.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |   16 +++-
 1 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 8f665bc..5d24015 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -373,22 +373,22 @@ out:
return ret;
 }
 
-static ssize_t send_control_msg(struct port *port, unsigned int event,
-   unsigned int value)
+static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id,
+ unsigned int event, unsigned int value)
 {
struct scatterlist sg[1];
struct virtio_console_control cpkt;
struct virtqueue *vq;
unsigned int len;
 
-   if (!use_multiport(port-portdev))
+   if (!use_multiport(portdev))
return 0;
 
-   cpkt.id = port-id;
+   cpkt.id = port_id;
cpkt.event = event;
cpkt.value = value;
 
-   vq = port-portdev-c_ovq;
+   vq = portdev-c_ovq;
 
sg_init_one(sg, cpkt, sizeof(cpkt));
if (vq-vq_ops-add_buf(vq, sg, 1, 0, cpkt) = 0) {
@@ -399,6 +399,12 @@ static ssize_t send_control_msg(struct port *port, 
unsigned int event,
return 0;
 }
 
+static ssize_t send_control_msg(struct port *port, unsigned int event,
+   unsigned int value)
+{
+   return __send_control_msg(port-portdev, port-id, event, value);
+}
+
 static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count)
 {
struct scatterlist sg[1];
-- 
1.6.2.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


[PATCH 05/10] virtio: console: Remove config work handler

2010-04-05 Thread Amit Shah
We're going to switch to using control messages for port hot-plug and
initial port discovery. Remove the config work handler which handled
port hot-plug so far.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |   64 +
 1 files changed, 1 insertions(+), 63 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index b40b112..0473221 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -109,7 +109,6 @@ struct ports_device {
 * notification
 */
struct work_struct control_work;
-   struct work_struct config_work;
 
struct list_head ports;
 
@@ -1091,10 +1090,7 @@ static void config_intr(struct virtio_device *vdev)
struct ports_device *portdev;
 
portdev = vdev-priv;
-   if (use_multiport(portdev)) {
-   /* Handle port hot-add */
-   schedule_work(portdev-config_work);
-   }
+
/*
 * We'll use this way of resizing only for legacy support.
 * For newer userspace (VIRTIO_CONSOLE_F_MULTPORT+), use
@@ -1237,62 +1233,6 @@ fail:
return err;
 }
 
-/*
- * The workhandler for config-space updates.
- *
- * This is called when ports are hot-added.
- */
-static void config_work_handler(struct work_struct *work)
-{
-   struct virtio_console_config virtconconf;
-   struct ports_device *portdev;
-   struct virtio_device *vdev;
-   int err;
-
-   portdev = container_of(work, struct ports_device, config_work);
-
-   vdev = portdev-vdev;
-   vdev-config-get(vdev,
- offsetof(struct virtio_console_config, nr_ports),
- virtconconf.nr_ports,
- sizeof(virtconconf.nr_ports));
-
-   if (portdev-config.nr_ports == virtconconf.nr_ports) {
-   /*
-* Port 0 got hot-added.  Since we already did all the
-* other initialisation for it, just tell the Host
-* that the port is ready if we find the port.  In
-* case the port was hot-removed earlier, we call
-* add_port to add the port.
-*/
-   struct port *port;
-
-   port = find_port_by_id(portdev, 0);
-   if (!port)
-   add_port(portdev, 0);
-   else
-   send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
-   return;
-   }
-   if (virtconconf.nr_ports  portdev-config.max_nr_ports) {
-   dev_warn(vdev-dev,
-More ports specified (%u) than allowed (%u),
-portdev-config.nr_ports + 1,
-portdev-config.max_nr_ports);
-   return;
-   }
-   if (virtconconf.nr_ports  portdev-config.nr_ports)
-   return;
-
-   /* Hot-add ports */
-   while (virtconconf.nr_ports - portdev-config.nr_ports) {
-   err = add_port(portdev, portdev-config.nr_ports);
-   if (err)
-   break;
-   portdev-config.nr_ports++;
-   }
-}
-
 static int init_vqs(struct ports_device *portdev)
 {
vq_callback_t **io_callbacks;
@@ -1485,7 +1425,6 @@ static int __devinit virtcons_probe(struct virtio_device 
*vdev)
 
spin_lock_init(portdev-cvq_lock);
INIT_WORK(portdev-control_work, control_work_handler);
-   INIT_WORK(portdev-config_work, config_work_handler);
 
nr_added_bufs = fill_queue(portdev-c_ivq, portdev-cvq_lock);
if (!nr_added_bufs) {
@@ -1528,7 +1467,6 @@ static void virtcons_remove(struct virtio_device *vdev)
portdev = vdev-priv;
 
cancel_work_sync(portdev-control_work);
-   cancel_work_sync(portdev-config_work);
 
list_for_each_entry_safe(port, port2, portdev-ports, list)
remove_port(port);
-- 
1.6.2.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


[PATCH 04/10] virtio: console: Don't call hvc_remove() on unplugging console ports

2010-04-05 Thread Amit Shah
hvc_remove() has some bug which freezes other active hvc ports when one
port is removed.

So disable calling of hvc_remove() which deregisters a port with the
hvc_console.

If the hvc_console code calls into our get_chars() routine as a result
of a poll operation, we will return -EPIPE and the hvc_console code will
then do the necessary cleanup.

This call will be restored when the bug in hvc_remove() is found and
fixed.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |   11 +++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 733276d..b40b112 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -876,7 +876,18 @@ static int remove_port(struct port *port)
spin_lock_irq(pdrvdata_lock);
list_del(port-cons.list);
spin_unlock_irq(pdrvdata_lock);
+#if 0
+   /*
+* hvc_remove() not called as removing one hvc port
+* results in other hvc ports getting frozen.
+*
+* Once this is resolved in hvc, this functionality
+* will be enabled.  Till that is done, the -EPIPE
+* return from get_chars() above will help
+* hvc_console.c to clean up on ports we remove here.
+*/
hvc_remove(port-cons.hvc);
+#endif
}
if (port-guest_connected)
send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 0);
-- 
1.6.2.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


[PATCH 10/10] virtio: console: Add support for nonblocking write()s

2010-04-05 Thread Amit Shah
If the host port is not open, a write() should either just return if the
file is opened in non-blocking mode, or block till the host port is
opened.

Also, don't spin till host consumes data for nonblocking ports. For
non-blocking ports, we can do away with the spinning and reclaim the
buffers consumed by the host on the next write call or on the condition
that'll make poll return.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |   82 +++--
 1 files changed, 78 insertions(+), 4 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 680ea25..d70efda 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -183,6 +183,8 @@ struct port {
/* The 'id' to identify the port with the Host */
u32 id;
 
+   bool outvq_full;
+
/* Is the host device open */
bool host_connected;
 
@@ -404,7 +406,19 @@ static ssize_t send_control_msg(struct port *port, 
unsigned int event,
return __send_control_msg(port-portdev, port-id, event, value);
 }
 
-static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count)
+static void reclaim_consumed_buffers(struct port *port)
+{
+   void *buf;
+   unsigned int len;
+
+   while ((buf = port-out_vq-vq_ops-get_buf(port-out_vq, len))) {
+   kfree(buf);
+   port-outvq_full = false;
+   }
+}
+
+static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count,
+   bool nonblock)
 {
struct scatterlist sg[1];
struct virtqueue *out_vq;
@@ -413,6 +427,8 @@ static ssize_t send_buf(struct port *port, void *in_buf, 
size_t in_count)
 
out_vq = port-out_vq;
 
+   reclaim_consumed_buffers(port);
+
sg_init_one(sg, in_buf, in_count);
ret = out_vq-vq_ops-add_buf(out_vq, sg, 1, 0, in_buf);
 
@@ -424,6 +440,12 @@ static ssize_t send_buf(struct port *port, void *in_buf, 
size_t in_count)
goto fail;
}
 
+   if (ret == 0)
+   port-outvq_full = true;
+
+   if (nonblock)
+   return in_count;
+
/*
 * Wait till the host acknowledges it pushed out the data we
 * sent.  This is done for ports in blocking mode or for data
@@ -491,6 +513,20 @@ static bool will_read_block(struct port *port)
return !port_has_data(port)  port-host_connected;
 }
 
+static bool will_write_block(struct port *port)
+{
+   if (!port-host_connected)
+   return true;
+
+   /*
+* Check if the Host has consumed any buffers since we last
+* sent data (this is only applicable for nonblocking ports).
+*/
+   reclaim_consumed_buffers(port);
+
+   return port-outvq_full;
+}
+
 static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
  size_t count, loff_t *offp)
 {
@@ -537,9 +573,22 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
struct port *port;
char *buf;
ssize_t ret;
+   bool nonblock;
 
port = filp-private_data;
 
+   nonblock = filp-f_flags  O_NONBLOCK;
+
+   if (will_write_block(port)) {
+   if (nonblock)
+   return -EAGAIN;
+
+   ret = wait_event_interruptible(port-waitqueue,
+  !will_write_block(port));
+   if (ret  0)
+   return ret;
+   }
+
count = min((size_t)(32 * 1024), count);
 
buf = kmalloc(count, GFP_KERNEL);
@@ -552,9 +601,14 @@ static ssize_t port_fops_write(struct file *filp, const 
char __user *ubuf,
goto free_buf;
}
 
-   ret = send_buf(port, buf, count);
+   ret = send_buf(port, buf, count, nonblock);
+
+   if (nonblock  ret  0)
+   goto out;
+
 free_buf:
kfree(buf);
+out:
return ret;
 }
 
@@ -569,7 +623,7 @@ static unsigned int port_fops_poll(struct file *filp, 
poll_table *wait)
ret = 0;
if (port-inbuf)
ret |= POLLIN | POLLRDNORM;
-   if (port-host_connected)
+   if (!will_write_block(port))
ret |= POLLOUT;
if (!port-host_connected)
ret |= POLLHUP;
@@ -592,6 +646,7 @@ static int port_fops_release(struct inode *inode, struct 
file *filp)
discard_port_data(port);
 
spin_unlock_irq(port-inbuf_lock);
+   reclaim_consumed_buffers(port);
 
return 0;
 }
@@ -621,6 +676,13 @@ static int port_fops_open(struct inode *inode, struct file 
*filp)
port-guest_connected = true;
spin_unlock_irq(port-inbuf_lock);
 
+   /*
+* There might be a chance that we missed reclaiming a few
+* buffers in the window of the port getting previously closed
+* and opening now.
+*/
+   reclaim_consumed_buffers(port);
+
/* Notify host of port 

[PATCH 09/10] virtio: console: Rename wait_is_over() to will_read_block()

2010-04-05 Thread Amit Shah
We'll introduce a function that checks if write will block.  Have
function names that are similar for the two cases.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 3d70729..680ea25 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -486,9 +486,9 @@ static ssize_t fill_readbuf(struct port *port, char 
*out_buf, size_t out_count,
 }
 
 /* The condition that must be true for polling to end */
-static bool wait_is_over(struct port *port)
+static bool will_read_block(struct port *port)
 {
-   return port_has_data(port) || !port-host_connected;
+   return !port_has_data(port)  port-host_connected;
 }
 
 static ssize_t port_fops_read(struct file *filp, char __user *ubuf,
@@ -511,7 +511,7 @@ static ssize_t port_fops_read(struct file *filp, char 
__user *ubuf,
return -EAGAIN;
 
ret = wait_event_interruptible(port-waitqueue,
-  wait_is_over(port));
+  !will_read_block(port));
if (ret  0)
return ret;
}
-- 
1.6.2.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


[PATCH 07/10] virtio: console: Use a control message to add ports

2010-04-05 Thread Amit Shah
Instead of the host and guest independently enumerating ports, switch to
a control message to add ports where the host supplies the port number
so there's no ambiguity or a possibility of a race between the host and
the guest port numbers.

We now no longer need the 'nr_ports' config value. Since no kernel has
been released with the MULTIPORT changes yet, we have a chance to fiddle
with the config space without adding compatibility features.

This is beneficial for management software, which would now be able to
instantiate ports at known locations and avoid problems that arise with
implicit numbering in the host and the guest. This removes the 'guessing
game' part of it, and management software can now actually indicate
which id to spawn a particular port on.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c  |   78 +--
 include/linux/virtio_console.h |   17 -
 2 files changed, 42 insertions(+), 53 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index fd98861..7b2dcdd 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -1053,7 +1053,7 @@ static void handle_control_message(struct ports_device 
*portdev,
cpkt = (struct virtio_console_control *)(buf-buf + buf-offset);
 
port = find_port_by_id(portdev, cpkt-id);
-   if (!port) {
+   if (!port  cpkt-event != VIRTIO_CONSOLE_PORT_ADD) {
/* No valid header at start of buffer.  Drop it. */
dev_dbg(portdev-vdev-dev,
Invalid index %u in control packet\n, cpkt-id);
@@ -1061,6 +1061,30 @@ static void handle_control_message(struct ports_device 
*portdev,
}
 
switch (cpkt-event) {
+   case VIRTIO_CONSOLE_PORT_ADD:
+   if (port) {
+   /*
+* This can happen for port 0: we have to
+* create a console port during probe() as was
+* the behaviour before the MULTIPORT feature.
+* On a newer host, when the host tells us
+* that a port 0 is available, we should just
+* say we have the port all set up.
+*/
+   send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
+   break;
+   }
+   if (cpkt-id = portdev-config.max_nr_ports) {
+   dev_warn(portdev-vdev-dev,
+   Request for adding port with out-of-bound id 
%u, max. supported id: %u\n,
+   cpkt-id, portdev-config.max_nr_ports - 1);
+   break;
+   }
+   add_port(portdev, cpkt-id);
+   break;
+   case VIRTIO_CONSOLE_PORT_REMOVE:
+   remove_port(port);
+   break;
case VIRTIO_CONSOLE_CONSOLE_PORT:
if (!cpkt-value)
break;
@@ -1119,32 +1143,6 @@ static void handle_control_message(struct ports_device 
*portdev,
kobject_uevent(port-dev-kobj, KOBJ_CHANGE);
}
break;
-   case VIRTIO_CONSOLE_PORT_REMOVE:
-   /*
-* Hot unplug the port.  We don't decrement nr_ports
-* since we don't want to deal with extra complexities
-* of using the lowest-available port id: We can just
-* pick up the nr_ports number as the id and not have
-* userspace send it to us.  This helps us in two
-* ways:
-*
-* - We don't need to have a 'port_id' field in the
-*   config space when a port is hot-added.  This is a
-*   good thing as we might queue up multiple hotplug
-*   requests issued in our workqueue.
-*
-* - Another way to deal with this would have been to
-*   use a bitmap of the active ports and select the
-*   lowest non-active port from that map.  That
-*   bloats the already tight config space and we
-*   would end up artificially limiting the
-*   max. number of ports to sizeof(bitmap).  Right
-*   now we can support 2^32 ports (as the port id is
-*   stored in a u32 type).
-*
-*/
-   remove_port(port);
-   break;
}
 }
 
@@ -1352,7 +1350,6 @@ static const struct file_operations portdev_fops = {
 static int __devinit virtcons_probe(struct virtio_device *vdev)
 {
struct ports_device *portdev;
-   u32 i;
int err;
bool multiport;
 
@@ -1381,29 +1378,15 @@ static int __devinit virtcons_probe(struct 
virtio_device *vdev)
}
 
multiport = false;
-   

[PATCH 08/10] virtio: console: Don't always create a port 0 if using multiport

2010-04-05 Thread Amit Shah
If we're using multiport, there's no point in always creating a console
port. Create the console port only if the host doesn't support
multiport.

Signed-off-by: Amit Shah amit.s...@redhat.com
---
 drivers/char/virtio_console.c |   33 +++--
 1 files changed, 15 insertions(+), 18 deletions(-)

diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c
index 7b2dcdd..3d70729 100644
--- a/drivers/char/virtio_console.c
+++ b/drivers/char/virtio_console.c
@@ -791,6 +791,13 @@ int init_port_console(struct port *port)
spin_unlock_irq(pdrvdata_lock);
port-guest_connected = true;
 
+   /*
+* Start using the new console output if this is the first
+* console to come up.
+*/
+   if (early_put_chars)
+   early_put_chars = NULL;
+
/* Notify host of port being opened */
send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1);
 
@@ -1063,14 +1070,8 @@ static void handle_control_message(struct ports_device 
*portdev,
switch (cpkt-event) {
case VIRTIO_CONSOLE_PORT_ADD:
if (port) {
-   /*
-* This can happen for port 0: we have to
-* create a console port during probe() as was
-* the behaviour before the MULTIPORT feature.
-* On a newer host, when the host tells us
-* that a port 0 is available, we should just
-* say we have the port all set up.
-*/
+   dev_dbg(portdev-vdev-dev,
+   Port %u already added\n, port-id);
send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1);
break;
}
@@ -1414,18 +1415,14 @@ static int __devinit virtcons_probe(struct 
virtio_device *vdev)
err = -ENOMEM;
goto free_vqs;
}
-
+   } else {
+   /*
+* If we're running on an older host, we always want
+* to create a console port.
+*/
+   add_port(portdev, 0);
}
 
-   /*
-* For backward compatibility: if we're running on an older
-* host, we always want to create a console port.
-*/
-   add_port(portdev, 0);
-
-   /* Start using the new console output. */
-   early_put_chars = NULL;
-
__send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID,
   VIRTIO_CONSOLE_DEVICE_READY, 1);
return 0;
-- 
1.6.2.5

___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


A clocksource driver for HyperV

2010-04-05 Thread Ky Srinivasan
I am attaching a clocksource driver for HyperV.

Signed-off-by: K. Y. Srinivasan ksriniva...@novell.com



From: K. Y. Srinivasan ksriniva...@novell.com
Subject:  A clocksource for Linux guests hosted on HyperV.
References: None
Patch-mainline: 

This patch is a clocksource implementation suitable for guests hosted on HyperV.
Time keeping in Linux guests hosted on HyperV is unstable. This clocksource 
driver fixes the problem. 

Signed-off-by: K. Y. Srinivasan ksriniva...@novell.com

Index: linux/drivers/staging/hv/hv_timesource.c
===
--- /dev/null   1970-01-01 00:00:00.0 +
+++ linux/drivers/staging/hv/hv_timesource.c2010-04-05 13:33:36.0 
-0600
@@ -0,0 +1,148 @@
+/*
+ * A clocksource for Linux running on HyperV.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan ksriniva...@novell.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include linux/version.h
+#include linux/clocksource.h
+#include linux/init.h
+#include linux/module.h
+#include linux/pci.h
+#include linux/dmi.h
+
+#define HV_CLOCK_SHIFT 22
+/*
+ * HyperV defined synthetic CPUID leaves:
+ */
+#define HV_CPUID_SIGNATURE 0x4000
+#define HV_CPUID_MIN   0x4005
+#define HV_HYPERVISOR_PRESENT_BIT  0x8000
+#define HV_CPUID_FEATURES  0x4003
+#define HV_CPUID_RECOMMENDATIONS   0x4004
+
+/*
+ * HyperV defined synthetic MSRs
+ */
+
+#define HV_X64_MSR_TIME_REF_COUNT  0x4020
+
+
+static cycle_t read_hv_clock(struct clocksource *arg)
+{
+   cycle_t current_tick;
+   /*
+* Read the partition counter to get the current tick count. This count
+* is set to 0 when the partition is created and is incremented in
+* 100 nanosecond units.
+*/
+   rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+   return current_tick;
+}
+
+static struct clocksource clocksource_hyperv = {
+   .name   = hyperv_clocksource,
+   .rating = 400, /* use this when running on Hyperv*/
+   .read   = read_hv_clock,
+   .mask   = CLOCKSOURCE_MASK(64),
+   .shift  = HV_CLOCK_SHIFT,
+};
+
+static struct dmi_system_id __initconst
+hv_timesource_dmi_table[] __maybe_unused  = {
+   {
+   .ident = Hyper-V,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, Microsoft Corporation),
+   DMI_MATCH(DMI_PRODUCT_NAME, Virtual Machine),
+   DMI_MATCH(DMI_BOARD_NAME, Virtual Machine),
+   },
+   },
+   { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_timesource_dmi_table);
+
+static struct pci_device_id __initconst
+hv_timesource_pci_table[] __maybe_unused = {
+   { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
+   { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_timesource_pci_table);
+
+
+static int __init hv_detect_hyperv(void)
+{
+   u32 eax, ebx, ecx, edx;
+   static char hyp_signature[20];
+
+   cpuid(1, eax, ebx, ecx, edx);
+   if (!(ecx  HV_HYPERVISOR_PRESENT_BIT)) {
+   printk(KERN_WARNING
+   Not on a Hypervisor\n);
+   return 1;
+   }
+   cpuid(HV_CPUID_SIGNATURE, eax, ebx, ecx, edx);
+   *(u32 *)(hyp_signature + 0) = ebx;
+   *(u32 *)(hyp_signature + 4) = ecx;
+   *(u32 *)(hyp_signature + 8) = edx;
+   hyp_signature[12] = 0;
+
+   if ((eax  HV_CPUID_MIN) || (strcmp(Microsoft Hv, hyp_signature))) {
+   printk(KERN_WARNING
+   Not on HyperV; signature %s, eax %x\n,
+   hyp_signature, eax);
+   return 1;
+   }
+   /*
+* Extract the features, recommendations etc.
+*/
+   cpuid(HV_CPUID_FEATURES, eax, ebx, ecx, edx);
+   if (!(eax  0x10)) {
+   printk(KERN_WARNING HyperV Time Ref Counter not available!\n);
+   return 1;
+   }
+
+   cpuid(HV_CPUID_RECOMMENDATIONS, eax, ebx, ecx, edx);
+   printk(KERN_INFO HyperV recommendations: %x\n, eax);
+   printk(KERN_INFO HyperV spin count: %x\n, ebx);
+   return 0;
+}
+
+
+static int __init init_hv_clocksource(void)
+{
+   if 

A clocksource driver for HyperV

2010-04-05 Thread Ky Srinivasan
I am attaching a clocksource driver for HyperV.

Signed-off-by: K. Y. Srinivasan ksriniva...@novell.com



From: K. Y. Srinivasan ksriniva...@novell.com
Subject:  A clocksource for Linux guests hosted on HyperV.
References: None
Patch-mainline: 

This patch is a clocksource implementation suitable for guests hosted on HyperV.
Time keeping in Linux guests hosted on HyperV is unstable. This clocksource 
driver fixes the problem. 

Signed-off-by: K. Y. Srinivasan ksriniva...@novell.com

Index: linux/drivers/staging/hv/hv_timesource.c
===
--- /dev/null   1970-01-01 00:00:00.0 +
+++ linux/drivers/staging/hv/hv_timesource.c2010-04-05 13:33:36.0 
-0600
@@ -0,0 +1,148 @@
+/*
+ * A clocksource for Linux running on HyperV.
+ *
+ *
+ * Copyright (C) 2010, Novell, Inc.
+ * Author : K. Y. Srinivasan ksriniva...@novell.com
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include linux/version.h
+#include linux/clocksource.h
+#include linux/init.h
+#include linux/module.h
+#include linux/pci.h
+#include linux/dmi.h
+
+#define HV_CLOCK_SHIFT 22
+/*
+ * HyperV defined synthetic CPUID leaves:
+ */
+#define HV_CPUID_SIGNATURE 0x4000
+#define HV_CPUID_MIN   0x4005
+#define HV_HYPERVISOR_PRESENT_BIT  0x8000
+#define HV_CPUID_FEATURES  0x4003
+#define HV_CPUID_RECOMMENDATIONS   0x4004
+
+/*
+ * HyperV defined synthetic MSRs
+ */
+
+#define HV_X64_MSR_TIME_REF_COUNT  0x4020
+
+
+static cycle_t read_hv_clock(struct clocksource *arg)
+{
+   cycle_t current_tick;
+   /*
+* Read the partition counter to get the current tick count. This count
+* is set to 0 when the partition is created and is incremented in
+* 100 nanosecond units.
+*/
+   rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
+   return current_tick;
+}
+
+static struct clocksource clocksource_hyperv = {
+   .name   = hyperv_clocksource,
+   .rating = 400, /* use this when running on Hyperv*/
+   .read   = read_hv_clock,
+   .mask   = CLOCKSOURCE_MASK(64),
+   .shift  = HV_CLOCK_SHIFT,
+};
+
+static struct dmi_system_id __initconst
+hv_timesource_dmi_table[] __maybe_unused  = {
+   {
+   .ident = Hyper-V,
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, Microsoft Corporation),
+   DMI_MATCH(DMI_PRODUCT_NAME, Virtual Machine),
+   DMI_MATCH(DMI_BOARD_NAME, Virtual Machine),
+   },
+   },
+   { },
+};
+MODULE_DEVICE_TABLE(dmi, hv_timesource_dmi_table);
+
+static struct pci_device_id __initconst
+hv_timesource_pci_table[] __maybe_unused = {
+   { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
+   { 0 }
+};
+MODULE_DEVICE_TABLE(pci, hv_timesource_pci_table);
+
+
+static int __init hv_detect_hyperv(void)
+{
+   u32 eax, ebx, ecx, edx;
+   static char hyp_signature[20];
+
+   cpuid(1, eax, ebx, ecx, edx);
+   if (!(ecx  HV_HYPERVISOR_PRESENT_BIT)) {
+   printk(KERN_WARNING
+   Not on a Hypervisor\n);
+   return 1;
+   }
+   cpuid(HV_CPUID_SIGNATURE, eax, ebx, ecx, edx);
+   *(u32 *)(hyp_signature + 0) = ebx;
+   *(u32 *)(hyp_signature + 4) = ecx;
+   *(u32 *)(hyp_signature + 8) = edx;
+   hyp_signature[12] = 0;
+
+   if ((eax  HV_CPUID_MIN) || (strcmp(Microsoft Hv, hyp_signature))) {
+   printk(KERN_WARNING
+   Not on HyperV; signature %s, eax %x\n,
+   hyp_signature, eax);
+   return 1;
+   }
+   /*
+* Extract the features, recommendations etc.
+*/
+   cpuid(HV_CPUID_FEATURES, eax, ebx, ecx, edx);
+   if (!(eax  0x10)) {
+   printk(KERN_WARNING HyperV Time Ref Counter not available!\n);
+   return 1;
+   }
+
+   cpuid(HV_CPUID_RECOMMENDATIONS, eax, ebx, ecx, edx);
+   printk(KERN_INFO HyperV recommendations: %x\n, eax);
+   printk(KERN_INFO HyperV spin count: %x\n, ebx);
+   return 0;
+}
+
+
+static int __init init_hv_clocksource(void)
+{
+   if 

Re: A clocksource driver for HyperV

2010-04-05 Thread Jeremy Fitzhardinge
On 04/05/2010 01:30 PM, Ky Srinivasan wrote:
 +static cycle_t read_hv_clock(struct clocksource *arg)
 +{
 + cycle_t current_tick;
 + /*
 +  * Read the partition counter to get the current tick count. This count
 +  * is set to 0 when the partition is created and is incremented in
 +  * 100 nanosecond units.
 +  */
 + rdmsrl(HV_X64_MSR_TIME_REF_COUNT, current_tick);
 + return current_tick;
 +}
 +
 +static struct clocksource clocksource_hyperv = {
 + .name   = hyperv_clocksource,


Seems like a redundantly long name; any use of this string is going to 
be in a context where it is obviously a clocksource.  How about just 
hyperv?

 + .rating = 400, /* use this when running on Hyperv*/
 + .read   = read_hv_clock,
 + .mask   = CLOCKSOURCE_MASK(64),
 + .shift  = HV_CLOCK_SHIFT,
 +};
 +
 +static struct dmi_system_id __initconst
 +hv_timesource_dmi_table[] __maybe_unused  = {
 + {
 + .ident = Hyper-V,
 + .matches = {
 + DMI_MATCH(DMI_SYS_VENDOR, Microsoft Corporation),
 + DMI_MATCH(DMI_PRODUCT_NAME, Virtual Machine),
 + DMI_MATCH(DMI_BOARD_NAME, Virtual Machine),
 + },
 + },
 + { },
 +};
 +MODULE_DEVICE_TABLE(dmi, hv_timesource_dmi_table);


So you use the DMI signatures to determine whether the module is needed, 
but cpuid to work out if the feature is present?

 +
 +static struct pci_device_id __initconst
 +hv_timesource_pci_table[] __maybe_unused = {
 + { PCI_DEVICE(0x1414, 0x5353) }, /* VGA compatible controller */
 + { 0 }
 +};
 +MODULE_DEVICE_TABLE(pci, hv_timesource_pci_table);


And/or PCI?

Seems a bit... ad-hoc?  Is this the official way to determine the 
presence of Hyper-V?

 +
 +
 +static int __init hv_detect_hyperv(void)


This looks generally useful.  Should it be hidden away in the 
clocksource driver, or in some common hyper-v code?  Do other hyper-v 
drivers have versions of this?

 +{
 + u32 eax, ebx, ecx, edx;
 + static char hyp_signature[20];

20?  static?

 +
 + cpuid(1,eax,ebx,ecx,edx);
 + if (!(ecx  HV_HYPERVISOR_PRESENT_BIT)) {
 + printk(KERN_WARNING
 + Not on a Hypervisor\n);

This just looks like noise, especially since it doesn't identify what is 
generating the message.  And if you compile this code in as =y 
(non-modular) then it will complain every boot.

 + return 1;
 + }
 + cpuid(HV_CPUID_SIGNATURE,eax,ebx,ecx,edx);
 + *(u32 *)(hyp_signature + 0) = ebx;
 + *(u32 *)(hyp_signature + 4) = ecx;
 + *(u32 *)(hyp_signature + 8) = edx;
 + hyp_signature[12] = 0;
 +
 + if ((eax  HV_CPUID_MIN) || (strcmp(Microsoft Hv, hyp_signature))) {


memcmp, surely?

 + printk(KERN_WARNING
 + Not on HyperV; signature %s, eax %x\n,
 + hyp_signature, eax);
 + return 1;
 + }
 + /*
 +  * Extract the features, recommendations etc.
 +  */
 + cpuid(HV_CPUID_FEATURES,eax,ebx,ecx,edx);
 + if (!(eax  0x10)) {
 + printk(KERN_WARNING HyperV Time Ref Counter not available!\n);
 + return 1;
 + }
 +
 + cpuid(HV_CPUID_RECOMMENDATIONS,eax,ebx,ecx,edx);
 + printk(KERN_INFO HyperV recommendations: %x\n, eax);
 + printk(KERN_INFO HyperV spin count: %x\n, ebx);
 + return 0;
 +}
 +
 +
 +static int __init init_hv_clocksource(void)
 +{
 + if (hv_detect_hyperv())
 + return -ENODEV;
 + /*
 +  * The time ref counter in HyperV is in 100ns units.
 +  * The definition of mult is:
 +  * mult/2^shift = ns/cyc = 100
 +  * mult = (100  shift)
 +  */
 + clocksource_hyperv.mult = (100  HV_CLOCK_SHIFT);


Why not initialize this in the structure?  It's just 10022 isn't it?

 + printk(KERN_INFO Registering HyperV clock source\n);
 + return clocksource_register(clocksource_hyperv);
 +}
 +
 +module_init(init_hv_clocksource);
 +MODULE_DESCRIPTION(HyperV based clocksource);
 +MODULE_AUTHOR(K. Y. Srinivasanksriniva...@novell.com);
 +MODULE_LICENSE(GPL);
 Index: linux/drivers/staging/hv/Makefile
 ===
 --- linux.orig/drivers/staging/hv/Makefile2010-04-05 13:02:06.0 
 -0600
 +++ linux/drivers/staging/hv/Makefile 2010-04-05 13:02:13.0 -0600
 @@ -1,4 +1,4 @@
 -obj-$(CONFIG_HYPERV) += hv_vmbus.o
 +obj-$(CONFIG_HYPERV) += hv_vmbus.o hv_timesource.o
   obj-$(CONFIG_HYPERV_STORAGE)+= hv_storvsc.o
   obj-$(CONFIG_HYPERV_BLOCK)  += hv_blkvsc.o
   obj-$(CONFIG_HYPERV_NET)+= hv_netvsc.o


___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization


Re: [PATCH 07/10] virtio: console: Use a control message to add ports

2010-04-05 Thread Rusty Russell
On Mon, 5 Apr 2010 11:24:11 pm Amit Shah wrote:
 @@ -1431,13 +1414,20 @@ static int __devinit virtcons_probe(struct 
 virtio_device *vdev)
   err = -ENOMEM;
   goto free_vqs;
   }
 +
   }

Minor nit: gratuitous whitespace addition.

Cheers,
Rusty.
___
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linux-foundation.org/mailman/listinfo/virtualization