All of lore.kernel.org
 help / color / mirror / Atom feed
From: Jan Kiszka <jan.kiszka@web.de>
To: Avi Kivity <avi@redhat.com>
Cc: kvm-devel <kvm@vger.kernel.org>
Subject: [PATCH v3] qemu-kvm: Make PC speaker emulation aware of in-kernel PIT
Date: Tue, 12 May 2009 23:58:17 +0200	[thread overview]
Message-ID: <4A09F0F9.7080804@web.de> (raw)
In-Reply-To: <4A092506.9090308@web.de>

[-- Attachment #1: Type: text/plain, Size: 5491 bytes --]

When using the in-kernel PIT the speaker emulation has to synchronize
the PIT state with KVM. Enhance the existing speaker sound device and
allow it to take over port 0x61 by using KVM_CREATE_PIT2 where
available. This unbreaks -soundhw pcspk in KVM mode.

Changes in v3:
 - re-added incorrectly dropped kvm_enabled checks

Changes in v2:
 - rebased over qemu-kvm and KVM_CREATE_PIT2
 - refactored hooks in pcspk

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
---

 hw/pcspk.c                     |   41 ++++++++++++++++++++++++++++++++++++++++
 kvm/kernel/include/linux/kvm.h |   10 ++++++++++
 kvm/libkvm/libkvm-x86.c        |   26 ++++++++++++++++++-------
 3 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/hw/pcspk.c b/hw/pcspk.c
index ec1d0c6..fea3863 100644
--- a/hw/pcspk.c
+++ b/hw/pcspk.c
@@ -27,6 +27,8 @@
 #include "isa.h"
 #include "audio/audio.h"
 #include "qemu-timer.h"
+#include "i8254.h"
+#include "qemu-kvm.h"
 
 #define PCSPK_BUF_LEN 1792
 #define PCSPK_SAMPLE_RATE 32000
@@ -48,6 +50,37 @@ typedef struct {
 static const char *s_spk = "pcspk";
 static PCSpkState pcspk_state;
 
+#ifdef USE_KVM_PIT
+static void kvm_get_pit_ch2(PITState *pit)
+{
+    struct kvm_pit_state pit_state;
+
+    if (kvm_enabled() && qemu_kvm_pit_in_kernel()) {
+        kvm_get_pit(kvm_context, &pit_state);
+        pit->channels[2].mode = pit_state.channels[2].mode;
+        pit->channels[2].count = pit_state.channels[2].count;
+        pit->channels[2].count_load_time = pit_state.channels[2].count_load_time;
+        pit->channels[2].gate = pit_state.channels[2].gate;
+    }
+}
+
+static void kvm_set_pit_ch2(PITState *pit)
+{
+    struct kvm_pit_state pit_state;
+
+    if (kvm_enabled() && qemu_kvm_pit_in_kernel()) {
+        pit_state.channels[2].mode = pit->channels[2].mode;
+        pit_state.channels[2].count = pit->channels[2].count;
+        pit_state.channels[2].count_load_time = pit->channels[2].count_load_time;
+        pit_state.channels[2].gate = pit->channels[2].gate;
+        kvm_set_pit(kvm_context, &pit_state);
+    }
+}
+#else
+static inline void kvm_get_pit_ch2(PITState *pit) { }
+static inline void kvm_set_pit_ch2(PITState *pit) { }
+#endif
+
 static inline void generate_samples(PCSpkState *s)
 {
     unsigned int i;
@@ -72,6 +105,8 @@ static void pcspk_callback(void *opaque, int free)
     PCSpkState *s = opaque;
     unsigned int n;
 
+    kvm_get_pit_ch2(s->pit);
+
     if (pit_get_mode(s->pit, 2) != 3)
         return;
 
@@ -121,6 +156,8 @@ static uint32_t pcspk_ioport_read(void *opaque, uint32_t addr)
     PCSpkState *s = opaque;
     int out;
 
+    kvm_get_pit_ch2(s->pit);
+
     s->dummy_refresh_clock ^= (1 << 4);
     out = pit_get_out(s->pit, 2, qemu_get_clock(vm_clock)) << 5;
 
@@ -132,6 +169,8 @@ static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
     PCSpkState *s = opaque;
     const int gate = val & 1;
 
+    kvm_get_pit_ch2(s->pit);
+
     s->data_on = (val >> 1) & 1;
     pit_set_gate(s->pit, 2, gate);
     if (s->voice) {
@@ -139,6 +178,8 @@ static void pcspk_ioport_write(void *opaque, uint32_t addr, uint32_t val)
             s->play_pos = 0;
         AUD_set_active_out(s->voice, gate & s->data_on);
     }
+
+    kvm_set_pit_ch2(s->pit);
 }
 
 void pcspk_init(PITState *pit)
diff --git a/kvm/kernel/include/linux/kvm.h b/kvm/kernel/include/linux/kvm.h
index f5e9d66..9ed4892 100644
--- a/kvm/kernel/include/linux/kvm.h
+++ b/kvm/kernel/include/linux/kvm.h
@@ -110,6 +110,14 @@ struct kvm_irqchip {
 	} chip;
 };
 
+/* for KVM_CREATE_PIT2 */
+struct kvm_pit_config {
+	__u32 flags;
+	__u32 pad;
+};
+
+#define KVM_PIT_SPEAKER_DUMMY     1
+
 #define KVM_EXIT_UNKNOWN          0
 #define KVM_EXIT_EXCEPTION        1
 #define KVM_EXIT_IO               2
@@ -455,6 +463,7 @@ struct kvm_trace_rec {
 #define KVM_CAP_ASSIGN_DEV_IRQ 29
 /* Another bug in KVM_SET_USER_MEMORY_REGION fixed: */
 #define KVM_CAP_JOIN_MEMORY_REGIONS_WORKS 30
+#define KVM_CAP_PIT2 31
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -538,6 +547,7 @@ struct kvm_irq_routing {
 #define KVM_ASSIGN_SET_MSIX_ENTRY \
 			_IOW(KVMIO, 0x74, struct kvm_assigned_msix_entry)
 #define KVM_DEASSIGN_DEV_IRQ       _IOW(KVMIO, 0x75, struct kvm_assigned_irq)
+#define KVM_CREATE_PIT2		   _IOW(KVMIO, 0x76, struct kvm_pit_config)
 
 /*
  * ioctls for vcpu fds
diff --git a/kvm/libkvm/libkvm-x86.c b/kvm/libkvm/libkvm-x86.c
index a2f6320..9c0d967 100644
--- a/kvm/libkvm/libkvm-x86.c
+++ b/kvm/libkvm/libkvm-x86.c
@@ -59,16 +59,26 @@ static int kvm_create_pit(kvm_context_t kvm)
 
 	kvm->pit_in_kernel = 0;
 	if (!kvm->no_pit_creation) {
-		r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_PIT);
-		if (r > 0) {
+#ifdef KVM_CAP_PIT2
+		struct kvm_pit_config config = { .flags = 0 };
+
+		r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_PIT2);
+		if (r > 0)
+			r = ioctl(kvm->vm_fd, KVM_CREATE_PIT2, &config);
+		else
+#endif
+		{
+			r = ioctl(kvm->fd, KVM_CHECK_EXTENSION, KVM_CAP_PIT);
+			if (r <= 0)
+				return 0;
+
 			r = ioctl(kvm->vm_fd, KVM_CREATE_PIT);
-			if (r >= 0)
-				kvm->pit_in_kernel = 1;
-			else {
-				fprintf(stderr, "Create kernel PIC irqchip failed\n");
-				return r;
-			}
 		}
+		if (r < 0) {
+			fprintf(stderr, "Create kernel PIC irqchip failed\n");
+			return r;
+		}
+		kvm->pit_in_kernel = 1;
 	}
 #endif
 	return 0;


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 257 bytes --]

  reply	other threads:[~2009-05-12 21:58 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-05-12  7:28 [PATCH v2] qemu-kvm: Make PC speaker emulation aware of in-kernel PIT Jan Kiszka
2009-05-12 21:58 ` Jan Kiszka [this message]
2009-05-14 20:43   ` [PATCH v4] " Jan Kiszka
2009-05-15 22:14     ` Marcelo Tosatti
2009-05-31 10:10       ` Jan Kiszka
2009-05-31 11:09         ` Avi Kivity

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4A09F0F9.7080804@web.de \
    --to=jan.kiszka@web.de \
    --cc=avi@redhat.com \
    --cc=kvm@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.