public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Marcelo Tosatti <mtosatti@redhat.com>
To: Avi Kivity <avi@qumranet.com>
Cc: Chris Wright <chrisw@redhat.com>,
	Glauber Costa <gcosta@redhat.com>,
	Anthony Liguori <aliguori@us.ibm.com>,
	kvm@vger.kernel.org, Marcelo Tosatti <mtosatti@redhat.com>
Subject: [patch 05/12] KVM: in-kernel ACPI timer emulation
Date: Thu, 29 May 2008 19:22:54 -0300	[thread overview]
Message-ID: <20080529222828.816210417@localhost.localdomain> (raw)
In-Reply-To: 20080529222249.563011248@localhost.localdomain

[-- Attachment #1: acpi-tmr-inkernel --]
[-- Type: text/plain, Size: 6863 bytes --]

C1 emulation reads the pmtimer very often, so move ACPI pmtimer to
kernel space.

Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>

Index: kvm/arch/x86/kvm/Makefile
===================================================================
--- kvm.orig/arch/x86/kvm/Makefile
+++ kvm/arch/x86/kvm/Makefile
@@ -10,7 +10,7 @@ endif
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/x86/kvm
 
 kvm-objs := $(common-objs) x86.o mmu.o x86_emulate.o i8259.o irq.o lapic.o \
-	i8254.o
+	i8254.o acpi.o
 obj-$(CONFIG_KVM) += kvm.o
 kvm-intel-objs = vmx.o
 obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
Index: kvm/arch/x86/kvm/acpi.c
===================================================================
--- /dev/null
+++ kvm/arch/x86/kvm/acpi.c
@@ -0,0 +1,103 @@
+#include <linux/kvm_host.h>
+#include <linux/kvm.h>
+#include <linux/acpi_pmtmr.h>
+#include "iodev.h"
+#include "irq.h"
+#include "acpi.h"
+
+static void get_pmtmr(int pmtmr_offset, void *data)
+{
+	u32 d;
+	d = muldiv64(ktime_to_ns(ktime_get()), PMTMR_TICKS_PER_SEC, NSEC_PER_SEC);
+	d &= ACPI_PM_MASK;
+	d += pmtmr_offset;
+	d &= ACPI_PM_MASK;
+	memcpy(data, &d, sizeof d);
+}
+
+static void acpi_ioport_read(struct kvm_io_device *this, gpa_t addr, int len,
+			     void *data)
+{
+	struct kvm_acpi_timer *acpi = (struct kvm_acpi_timer *)this->private;
+
+	if (len == 4)
+		get_pmtmr(acpi->pmtmr_offset, data);
+
+	return;
+}
+
+static void acpi_ioport_write(struct kvm_io_device *this, gpa_t addr, int len,
+			      const void *data)
+{
+	return;
+}
+
+static int acpi_in_range(struct kvm_io_device *this, gpa_t addr)
+{
+	struct kvm_acpi_timer *acpi = (struct kvm_acpi_timer *)this->private;
+	struct kvm *kvm = acpi->kvm;
+
+	if (!kvm->arch.vacpi_timer)
+		return 0;
+
+	return (addr == kvm->arch.vacpi_timer->pmtmr_state.base_address);
+}
+
+void kvm_acpi_free(struct kvm_io_device *this)
+{
+	struct kvm_acpi_timer *acpi = (struct kvm_acpi_timer *)this->private;
+
+	kfree(acpi);
+}
+
+int kvm_vm_ioctl_get_acpi_timer(struct kvm *kvm,
+				struct kvm_acpi_timer_state *pmtmr)
+{
+	if (!kvm->arch.vacpi_timer)
+		return -EINVAL;
+
+	get_pmtmr(kvm->arch.vacpi_timer->pmtmr_offset, &pmtmr->timer_val);
+	pmtmr->base_address = kvm->arch.vacpi_timer->pmtmr_state.base_address;
+	return 0;
+}
+
+int kvm_vm_ioctl_set_acpi_timer(struct kvm *kvm,
+				struct kvm_acpi_timer_state *pmtmr)
+{
+	u32 d;
+
+	if (!kvm->arch.vacpi_timer)
+		return -EINVAL;
+	kvm->arch.vacpi_timer->pmtmr_state.base_address = pmtmr->base_address;
+
+	d = muldiv64(ktime_to_ns(ktime_get()), PMTMR_TICKS_PER_SEC, NSEC_PER_SEC);
+	d &= ACPI_PM_MASK;
+	kvm->arch.vacpi_timer->pmtmr_offset = (pmtmr->timer_val - d) & ACPI_PM_MASK;
+	return 0;
+}
+
+/*
+ * Note: matches BIOS (currently hardcoded) definition.
+ */
+#define ACPI_PMTMR_BASE 0xb008
+
+int kvm_acpi_init(struct kvm *kvm)
+{
+	struct kvm_acpi_timer *acpi;
+
+	acpi = kzalloc(sizeof(struct kvm_acpi_timer), GFP_KERNEL);
+	if (!acpi)
+		return -ENOMEM;
+
+	acpi->dev.read = acpi_ioport_read;
+	acpi->dev.write = acpi_ioport_write;
+	acpi->dev.in_range = acpi_in_range;
+	acpi->dev.private = acpi;
+	acpi->kvm = kvm;
+	acpi->dev.destructor = kvm_acpi_free;
+	acpi->pmtmr_state.base_address = ACPI_PMTMR_BASE;
+	kvm->arch.vacpi_timer = acpi;
+	kvm_io_bus_register_dev(&kvm->pio_bus, &acpi->dev);
+
+	return 0;
+}
Index: kvm/arch/x86/kvm/acpi.h
===================================================================
--- /dev/null
+++ kvm/arch/x86/kvm/acpi.h
@@ -0,0 +1,19 @@
+#ifndef __KVM_ACPI_H
+#define __KVM_ACPI_H
+
+struct kvm_acpi_timer {
+	struct kvm_io_device dev;
+	struct kvm *kvm;
+	int pmtmr_offset;
+	struct kvm_acpi_timer_state pmtmr_state;
+};
+
+int kvm_acpi_init(struct kvm *kvm);
+
+int kvm_vm_ioctl_get_acpi_timer(struct kvm *kvm,
+				struct kvm_acpi_timer_state *pmtmr);
+
+int kvm_vm_ioctl_set_acpi_timer(struct kvm *kvm,
+				struct kvm_acpi_timer_state *pmtmr);
+
+#endif
Index: kvm/arch/x86/kvm/x86.c
===================================================================
--- kvm.orig/arch/x86/kvm/x86.c
+++ kvm/arch/x86/kvm/x86.c
@@ -19,6 +19,7 @@
 #include "mmu.h"
 #include "i8254.h"
 #include "tss.h"
+#include "acpi.h"
 
 #include <linux/clocksource.h>
 #include <linux/kvm.h>
@@ -794,6 +795,7 @@ int kvm_dev_ioctl_check_extension(long e
 	case KVM_CAP_NOP_IO_DELAY:
 	case KVM_CAP_MP_STATE:
 	case KVM_CAP_OPEN_IOPORT:
+	case KVM_CAP_ACPI_TIMER:
 		r = 1;
 		break;
 	case KVM_CAP_VAPIC:
@@ -1742,6 +1744,31 @@ long kvm_arch_vm_ioctl(struct file *filp
 			goto out;
 		break;
 	}
+	case KVM_CREATE_ACPI_TIMER: {
+		r = kvm_acpi_init(kvm);
+		break;
+	}
+	case KVM_GET_ACPI_TIMER: {
+		struct kvm_acpi_timer_state acpi_timer;
+		r = kvm_vm_ioctl_get_acpi_timer(kvm, &acpi_timer);
+		if (r)
+			goto out;
+		r = -EFAULT;
+		if (copy_to_user(argp, &acpi_timer, sizeof acpi_timer))
+			goto out;
+		r = 0;
+		break;
+	}
+	case KVM_SET_ACPI_TIMER: {
+		struct kvm_acpi_timer_state acpi_timer;
+		r = -EFAULT;
+		if (copy_from_user(&acpi_timer, argp, sizeof acpi_timer))
+			goto out;
+		r = kvm_vm_ioctl_set_acpi_timer(kvm, &acpi_timer);
+		if (r)
+			goto out;
+		break;
+	}
 	default:
 		;
 	}
Index: kvm/include/linux/kvm.h
===================================================================
--- kvm.orig/include/linux/kvm.h
+++ kvm/include/linux/kvm.h
@@ -347,6 +347,7 @@ struct kvm_trace_rec {
 #define KVM_CAP_PV_MMU 13
 #define KVM_CAP_MP_STATE 14
 #define KVM_CAP_OPEN_IOPORT 15
+#define KVM_CAP_ACPI_TIMER 16
 
 /*
  * ioctls for VM fds
@@ -373,6 +374,9 @@ struct kvm_trace_rec {
 #define KVM_GET_PIT		  _IOWR(KVMIO, 0x65, struct kvm_pit_state)
 #define KVM_SET_PIT		  _IOR(KVMIO,  0x66, struct kvm_pit_state)
 #define KVM_SET_OPEN_IOPORT	  _IOR(KVMIO,  0x67, struct kvm_ioport_list)
+#define KVM_CREATE_ACPI_TIMER	  _IO(KVMIO,  0x68)
+#define KVM_GET_ACPI_TIMER	  _IOWR(KVMIO, 0x69, struct kvm_acpi_timer_state)
+#define KVM_SET_ACPI_TIMER	  _IOR(KVMIO, 0x70, struct kvm_acpi_timer_state)
 
 /*
  * ioctls for vcpu fds
Index: kvm/include/asm-x86/kvm.h
===================================================================
--- kvm.orig/include/asm-x86/kvm.h
+++ kvm/include/asm-x86/kvm.h
@@ -220,6 +220,12 @@ struct kvm_ioport_list {
 	struct kvm_ioport ioports[0];
 };
 
+/* for KVM_GET_ACPI_TIMER and KVM_SET_ACPI_TIMER */
+struct kvm_acpi_timer_state {
+	__u32 base_address;
+	__u32 timer_val;
+};
+
 #define KVM_TRC_INJ_VIRQ         (KVM_TRC_HANDLER + 0x02)
 #define KVM_TRC_REDELIVER_EVT    (KVM_TRC_HANDLER + 0x03)
 #define KVM_TRC_PEND_INTR        (KVM_TRC_HANDLER + 0x04)
Index: kvm/include/asm-x86/kvm_host.h
===================================================================
--- kvm.orig/include/asm-x86/kvm_host.h
+++ kvm/include/asm-x86/kvm_host.h
@@ -318,6 +318,7 @@ struct kvm_arch{
 	struct kvm_pic *vpic;
 	struct kvm_ioapic *vioapic;
 	struct kvm_pit *vpit;
+	struct kvm_acpi_timer *vacpi_timer;
 
 	int round_robin_prev_vcpu;
 	unsigned int tss_addr;

-- 


  parent reply	other threads:[~2008-05-29 22:29 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-29 22:22 [patch 00/12] fake ACPI C2 emulation v2 Marcelo Tosatti
2008-05-29 22:22 ` [patch 01/12] expose ACPI pmtimer to userspace (/dev/pmtimer) Marcelo Tosatti
2008-06-01 16:34   ` Thomas Gleixner
2008-06-01 16:56     ` Anthony Liguori
2008-06-04  9:53       ` Avi Kivity
2008-06-04 10:01         ` Thomas Gleixner
2008-06-04 10:35           ` Avi Kivity
2008-06-01 17:56     ` Marcelo Tosatti
2008-06-01 18:17       ` Thomas Gleixner
2008-06-02 16:43       ` John Stultz
2008-06-03  4:09         ` Marcelo Tosatti
2008-05-29 22:22 ` [patch 02/12] KVM: allow multiple IO bitmap pages, provide userspace interface Marcelo Tosatti
2008-05-29 22:22 ` [patch 03/12] KVM: allow userspace to open access to ACPI pmtimer Marcelo Tosatti
2008-05-29 22:22 ` [patch 04/12] KVM: move muldiv64 to x86.c, export Marcelo Tosatti
2008-05-29 22:22 ` Marcelo Tosatti [this message]
2008-05-29 22:22 ` [patch 06/12] QEMU/KVM: self-disabling C2 emulation Marcelo Tosatti
2008-05-29 22:22 ` [patch 07/12] libkvm: interface to KVM_SET_OPEN_IOPORT Marcelo Tosatti
2008-05-29 22:22 ` [patch 08/12] QEMU/KVM: non-virtualized ACPI PMTimer support Marcelo Tosatti
2008-05-29 22:22 ` [patch 09/12] libkvm: in-kernel ACPI pmtimer interface Marcelo Tosatti
2008-05-29 22:22 ` [patch 10/12] QEMU/KVM: add option to disable in-kernel pmtimer emulation Marcelo Tosatti
2008-05-29 22:23 ` [patch 11/12] libkvm: interface for pmtimer save/restore Marcelo Tosatti
2008-05-29 22:23 ` [patch 12/12] QEMU/KVM: in-kernel pmtimer save/restore support Marcelo Tosatti
2008-06-01  9:21 ` [patch 00/12] fake ACPI C2 emulation v2 Avi Kivity
2008-06-02 16:08   ` Marcelo Tosatti
2008-06-04 10:49     ` Avi Kivity
2008-06-05  3:12       ` Marcelo Tosatti
2008-06-05  7:56         ` 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=20080529222828.816210417@localhost.localdomain \
    --to=mtosatti@redhat.com \
    --cc=aliguori@us.ibm.com \
    --cc=avi@qumranet.com \
    --cc=chrisw@redhat.com \
    --cc=gcosta@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox