* [RFC 02/10] KVM: wire up the TMEM HC
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 03/10] zcache: export zcache interface Sasha Levin
` (8 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
Wire up a new HC for TMEM, not doing much at the moment besides not doing
anything.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/x86.c | 10 ++++++++++
include/linux/kvm_para.h | 1 +
2 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 675dfb8..4c5b6ab 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -4993,6 +4993,13 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1;
}
+static int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
+{
+ *ret = -ENOTSUPP;
+
+ return 0;
+}
+
static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0,
unsigned long a1)
{
@@ -5035,6 +5042,9 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
case KVM_HC_VAPIC_POLL_IRQ:
ret = 0;
break;
+ case KVM_HC_TMEM:
+ r = kvm_pv_tmem_op(vcpu, hc_gpa(vcpu, a0, a1), &ret);
+ break;
default:
ret = -KVM_ENOSYS;
break;
diff --git a/include/linux/kvm_para.h b/include/linux/kvm_para.h
index ff476dd..78b27bf 100644
--- a/include/linux/kvm_para.h
+++ b/include/linux/kvm_para.h
@@ -19,6 +19,7 @@
#define KVM_HC_MMU_OP 2
#define KVM_HC_FEATURES 3
#define KVM_HC_PPC_MAP_MAGIC_PAGE 4
+#define KVM_HC_TMEM 5
/*
* hypercalls use architecture specific
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 03/10] zcache: export zcache interface
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
2012-06-06 11:00 ` [RFC 02/10] KVM: wire up the TMEM HC Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 04/10] KVM: add KVM TMEM entries in the appropriate config menu entry Sasha Levin
` (7 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
This patch exports the zcache interface to be used from the outside world.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
drivers/staging/zcache/zcache-main.c | 13 +++++++------
drivers/staging/zcache/zcache.h | 17 +++++++++++++++++
2 files changed, 24 insertions(+), 6 deletions(-)
create mode 100644 drivers/staging/zcache/zcache.h
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index 784c796..a196aff 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -32,6 +32,7 @@
#include <linux/crypto.h>
#include <linux/string.h>
#include "tmem.h"
+#include "zcache.h"
#include "../zsmalloc/zsmalloc.h"
@@ -1563,7 +1564,7 @@ static struct shrinker zcache_shrinker = {
* zcache shims between cleancache/frontswap ops and tmem
*/
-static int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
+int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
uint32_t index, struct page *page)
{
struct tmem_pool *pool;
@@ -1596,7 +1597,7 @@ out:
return ret;
}
-static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
+int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
uint32_t index, struct page *page)
{
struct tmem_pool *pool;
@@ -1616,7 +1617,7 @@ static int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
return ret;
}
-static int zcache_flush_page(int cli_id, int pool_id,
+int zcache_flush_page(int cli_id, int pool_id,
struct tmem_oid *oidp, uint32_t index)
{
struct tmem_pool *pool;
@@ -1637,7 +1638,7 @@ static int zcache_flush_page(int cli_id, int pool_id,
return ret;
}
-static int zcache_flush_object(int cli_id, int pool_id,
+int zcache_flush_object(int cli_id, int pool_id,
struct tmem_oid *oidp)
{
struct tmem_pool *pool;
@@ -1658,7 +1659,7 @@ static int zcache_flush_object(int cli_id, int pool_id,
return ret;
}
-static int zcache_destroy_pool(int cli_id, int pool_id)
+int zcache_destroy_pool(int cli_id, int pool_id)
{
struct tmem_pool *pool = NULL;
struct zcache_client *cli = NULL;
@@ -1941,7 +1942,7 @@ struct frontswap_ops zcache_frontswap_register_ops(void)
* NOTHING HAPPENS!
*/
-static int zcache_enabled;
+int zcache_enabled;
static int __init enable_zcache(char *s)
{
diff --git a/drivers/staging/zcache/zcache.h b/drivers/staging/zcache/zcache.h
new file mode 100644
index 0000000..ec06ea2
--- /dev/null
+++ b/drivers/staging/zcache/zcache.h
@@ -0,0 +1,17 @@
+#ifndef _ZCACHE_H_
+#define _ZCACHE_H_
+
+extern int zcache_enabled;
+
+extern int zcache_new_pool(uint16_t cli_id, uint32_t flags);
+extern int zcache_destroy_pool(int cli_id, int pool_id);
+extern int zcache_put_page(int cli_id, int pool_id, struct tmem_oid *oidp,
+ uint32_t index, struct page *page);
+extern int zcache_get_page(int cli_id, int pool_id, struct tmem_oid *oidp,
+ uint32_t index, struct page *page);
+extern int zcache_flush_page(int cli_id, int pool_id,
+ struct tmem_oid *oidp, uint32_t index);
+extern int zcache_flush_object(int cli_id, int pool_id,
+ struct tmem_oid *oidp);
+
+#endif
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 04/10] KVM: add KVM TMEM entries in the appropriate config menu entry
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
2012-06-06 11:00 ` [RFC 02/10] KVM: wire up the TMEM HC Sasha Levin
2012-06-06 11:00 ` [RFC 03/10] zcache: export zcache interface Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 05/10] KVM: bring in general tmem definitions Sasha Levin
` (6 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
Provide the ability to enable/disable any (future) KVM TMEM code.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/Kconfig | 1 +
arch/x86/kvm/Makefile | 2 ++
arch/x86/kvm/tmem/Kconfig | 16 ++++++++++++++++
arch/x86/kvm/tmem/Makefile | 1 +
4 files changed, 20 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kvm/tmem/Kconfig
create mode 100644 arch/x86/kvm/tmem/Makefile
diff --git a/arch/x86/kvm/Kconfig b/arch/x86/kvm/Kconfig
index 1a7fe86..08d2249 100644
--- a/arch/x86/kvm/Kconfig
+++ b/arch/x86/kvm/Kconfig
@@ -81,6 +81,7 @@ config KVM_MMU_AUDIT
# OK, it's a little counter-intuitive to do this, but it puts it neatly under
# the virtualization menu.
+source arch/x86/kvm/tmem/Kconfig
source drivers/vhost/Kconfig
source drivers/lguest/Kconfig
diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile
index 4f579e8..0df19bc 100644
--- a/arch/x86/kvm/Makefile
+++ b/arch/x86/kvm/Makefile
@@ -19,3 +19,5 @@ kvm-amd-y += svm.o
obj-$(CONFIG_KVM) += kvm.o
obj-$(CONFIG_KVM_INTEL) += kvm-intel.o
obj-$(CONFIG_KVM_AMD) += kvm-amd.o
+
+obj-$(CONFIG_KVM_TMEM) += tmem/
diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
new file mode 100644
index 0000000..15d8301
--- /dev/null
+++ b/arch/x86/kvm/tmem/Kconfig
@@ -0,0 +1,16 @@
+#
+# KVM TMEM configuration
+#
+
+menuconfig KVM_TMEM
+ bool "TMEM support"
+ depends on KVM && ZCACHE
+ default n
+ ---help---
+ This option provides the ability to use TMEM along with KVM, which provides
+ TMEM capabilities across multiple guests and (possible hosts).
+
+
+if KVM_TMEM
+
+endif # KVM_TMEM
diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
new file mode 100644
index 0000000..6812d46
--- /dev/null
+++ b/arch/x86/kvm/tmem/Makefile
@@ -0,0 +1 @@
+ccflags-y += -Idrivers/staging/zcache/
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 05/10] KVM: bring in general tmem definitions
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (2 preceding siblings ...)
2012-06-06 11:00 ` [RFC 04/10] KVM: add KVM TMEM entries in the appropriate config menu entry Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 06/10] zcache: move out client declaration and add a KVM client Sasha Levin
` (5 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
Define basic structures to be used by both host side and guest side.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/tmem/tmem.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 62 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kvm/tmem/tmem.h
diff --git a/arch/x86/kvm/tmem/tmem.h b/arch/x86/kvm/tmem/tmem.h
new file mode 100644
index 0000000..a6f0032
--- /dev/null
+++ b/arch/x86/kvm/tmem/tmem.h
@@ -0,0 +1,62 @@
+#ifndef _KVM_TMEM_H_
+#define _KVM_TMEM_H_
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/kvm_types.h>
+
+#define TMEM_CONTROL 0
+#define TMEM_NEW_POOL 1
+#define TMEM_DESTROY_POOL 2
+#define TMEM_NEW_PAGE 3
+#define TMEM_PUT_PAGE 4
+#define TMEM_GET_PAGE 5
+#define TMEM_FLUSH_PAGE 6
+#define TMEM_FLUSH_OBJECT 7
+#define TMEM_READ 8
+#define TMEM_WRITE 9
+#define TMEM_XCHG 10
+
+#define TMEM_POOL_PERSIST 1
+#define TMEM_POOL_SHARED 2
+#define TMEM_POOL_PAGESIZE_SHIFT 4
+#define TMEM_VERSION_SHIFT 24
+
+#define TMEM_SPEC_VERSION 1
+
+struct tmem_pool_uuid {
+ __u64 uuid_lo;
+ __u64 uuid_hi;
+};
+
+struct tmem_oid {
+ __u64 oid[3];
+};
+
+struct tmem_kvm_op {
+ __u32 cmd;
+ __s32 pool_id;
+ __u16 cli_id;
+ union {
+ struct { /* for cmd == TMEM_NEW_POOL */
+ __u64 uuid[2];
+ __u32 flags;
+ } new;
+ struct {
+ struct tmem_oid oid;
+ __u32 index;
+ __u32 tmem_offset;
+ __u32 pfn_offset;
+ __u32 len;
+ gfn_t gfn; /* guest machine page frame */
+ } gen;
+ } u;
+};
+
+#define TMEM_POOL_PRIVATE_UUID { 0, 0 }
+
+/* flags for tmem_ops.new_pool */
+#define TMEM_POOL_PERSIST 1
+#define TMEM_POOL_SHARED 2
+
+#endif /* _KVM_TMEM_H_ */
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 06/10] zcache: move out client declaration and add a KVM client
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (3 preceding siblings ...)
2012-06-06 11:00 ` [RFC 05/10] KVM: bring in general tmem definitions Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 07/10] KVM: add KVM TMEM host side interface Sasha Levin
` (4 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
Move out client declarations to be visible in the header, and introduce
a new KVM client.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
drivers/staging/zcache/zcache.h | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/staging/zcache/zcache.h b/drivers/staging/zcache/zcache.h
index ec06ea2..4693fd6 100644
--- a/drivers/staging/zcache/zcache.h
+++ b/drivers/staging/zcache/zcache.h
@@ -1,6 +1,9 @@
#ifndef _ZCACHE_H_
#define _ZCACHE_H_
+#define LOCAL_CLIENT ((uint16_t)-1)
+#define KVM_CLIENT 1
+
extern int zcache_enabled;
extern int zcache_new_pool(uint16_t cli_id, uint32_t flags);
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 07/10] KVM: add KVM TMEM host side interface
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (4 preceding siblings ...)
2012-06-06 11:00 ` [RFC 06/10] zcache: move out client declaration and add a KVM client Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-29 1:59 ` Konrad Rzeszutek Wilk
2012-06-06 11:00 ` [RFC 08/10] KVM: add KVM TMEM guest support Sasha Levin
` (3 subsequent siblings)
9 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
This is the host side interface that the guests which support KVM TMEM
talk to.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/tmem/Kconfig | 6 +++
arch/x86/kvm/tmem/Makefile | 2 +
arch/x86/kvm/tmem/host.c | 78 ++++++++++++++++++++++++++++++++++
arch/x86/kvm/tmem/host.h | 20 +++++++++
arch/x86/kvm/x86.c | 8 +---
drivers/staging/zcache/zcache-main.c | 35 +++++++++++++++-
6 files changed, 141 insertions(+), 8 deletions(-)
create mode 100644 arch/x86/kvm/tmem/host.c
create mode 100644 arch/x86/kvm/tmem/host.h
diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
index 15d8301..1a59e4f 100644
--- a/arch/x86/kvm/tmem/Kconfig
+++ b/arch/x86/kvm/tmem/Kconfig
@@ -13,4 +13,10 @@ menuconfig KVM_TMEM
if KVM_TMEM
+config KVM_TMEM_HOST
+ bool "Host-side KVM TMEM"
+ ---help---
+ With this option on, the KVM host will be able to process KVM TMEM requests
+ coming from guests.
+
endif # KVM_TMEM
diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
index 6812d46..706cd36 100644
--- a/arch/x86/kvm/tmem/Makefile
+++ b/arch/x86/kvm/tmem/Makefile
@@ -1 +1,3 @@
ccflags-y += -Idrivers/staging/zcache/
+
+obj-$(CONFIG_KVM_TMEM_HOST) += host.o
diff --git a/arch/x86/kvm/tmem/host.c b/arch/x86/kvm/tmem/host.c
new file mode 100644
index 0000000..9e73395
--- /dev/null
+++ b/arch/x86/kvm/tmem/host.c
@@ -0,0 +1,78 @@
+/*
+ * KVM TMEM host side interface
+ *
+ * Copyright (c) 2012 Sasha Levin
+ *
+ */
+
+#include <linux/kvm_types.h>
+#include <linux/kvm_host.h>
+
+#include "tmem.h"
+#include <zcache.h>
+
+int use_kvm_tmem_host = 1;
+
+static int no_kvmtmemhost(char *s)
+{
+ use_kvm_tmem_host = 0;
+ return 1;
+}
+
+__setup("nokvmtmemhost", no_kvmtmemhost);
+
+int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
+{
+ struct tmem_kvm_op op;
+ struct page *page;
+ int r;
+ unsigned long flags;
+
+ if (!use_kvm_tmem_host || !zcache_enabled) {
+ *ret = -ENXIO;
+ return 0;
+ }
+
+ r = kvm_read_guest(vcpu->kvm, addr, &op, sizeof(op));
+ if (r < 0) {
+ *ret = r;
+ return 0;
+ }
+
+ switch (op.cmd) {
+ case TMEM_NEW_POOL:
+ *ret = zcache_new_pool(op.cli_id, op.u.new.flags);
+ break;
+ case TMEM_DESTROY_POOL:
+ *ret = zcache_destroy_pool(op.cli_id, op.pool_id);
+ break;
+ case TMEM_NEW_PAGE:
+ break;
+ case TMEM_PUT_PAGE:
+ page = gfn_to_page(vcpu->kvm, op.u.gen.gfn);
+ local_irq_save(flags);
+ *ret = zcache_put_page(op.cli_id, op.pool_id,
+ &op.u.gen.oid, op.u.gen.index, page);
+ local_irq_restore(flags);
+ break;
+ case TMEM_GET_PAGE:
+ page = gfn_to_page(vcpu->kvm, op.u.gen.gfn);
+ local_irq_save(flags);
+ *ret = zcache_get_page(op.cli_id, op.pool_id,
+ &op.u.gen.oid, op.u.gen.index, page);
+ local_irq_restore(flags);
+ break;
+ case TMEM_FLUSH_PAGE:
+ local_irq_save(flags);
+ *ret = zcache_flush_page(op.cli_id, op.pool_id,
+ &op.u.gen.oid, op.u.gen.index);
+ local_irq_restore(flags);
+ break;
+ case TMEM_FLUSH_OBJECT:
+ local_irq_save(flags);
+ *ret = zcache_flush_object(op.cli_id, op.pool_id, &op.u.gen.oid);
+ local_irq_restore(flags);
+ break;
+ }
+ return 0;
+}
diff --git a/arch/x86/kvm/tmem/host.h b/arch/x86/kvm/tmem/host.h
new file mode 100644
index 0000000..17ba0c4
--- /dev/null
+++ b/arch/x86/kvm/tmem/host.h
@@ -0,0 +1,20 @@
+#ifndef _KVM_TMEM_HOST_H_
+#define _KVM_TMEM_HOST_H_
+
+#ifdef CONFIG_KVM_TMEM_HOST
+
+extern int use_kvm_tmem_host;
+
+extern int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret);
+
+#else
+
+static inline int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
+{
+ *ret = -ENOSUPP;
+ return 0;
+}
+
+#endif
+
+#endif
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 4c5b6ab..c92d4c8 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -27,6 +27,7 @@
#include "kvm_cache_regs.h"
#include "x86.h"
#include "cpuid.h"
+#include "tmem/host.h"
#include <linux/clocksource.h>
#include <linux/interrupt.h>
@@ -4993,13 +4994,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
return 1;
}
-static int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
-{
- *ret = -ENOTSUPP;
-
- return 0;
-}
-
static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0,
unsigned long a1)
{
diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
index a196aff..65c0ab0 100644
--- a/drivers/staging/zcache/zcache-main.c
+++ b/drivers/staging/zcache/zcache-main.c
@@ -1692,7 +1692,7 @@ out:
return ret;
}
-static int zcache_new_pool(uint16_t cli_id, uint32_t flags)
+int zcache_new_pool(uint16_t cli_id, uint32_t flags)
{
int poolid = -1;
struct tmem_pool *pool;
@@ -2011,6 +2011,37 @@ out:
return ret;
}
+#ifdef CONFIG_KVM_TMEM_HOST
+extern int use_kvm_tmem_host;
+
+static int __zcache_init_kvm(void)
+{
+ int ret = 0;
+
+ if (use_kvm_tmem_host) {
+ ret = zcache_new_client(KVM_CLIENT);
+ if (ret) {
+ pr_err("zcache: can't create client\n");
+ return -1;
+ } else {
+ pr_info("zcache: enabled support for KVM TMEM\n");
+ }
+ }
+ zbud_init();
+ register_shrinker(&zcache_shrinker);
+
+ return 0;
+}
+
+#else
+
+static inline int static int __zcache_init_kvm(void)
+{
+ return 0;
+}
+
+#endif
+
static int __init zcache_init(void)
{
int ret = 0;
@@ -2053,6 +2084,8 @@ static int __init zcache_init(void)
pr_err("zcache: can't create client\n");
goto out;
}
+ if (__zcache_init_kvm())
+ goto out;
#endif
#ifdef CONFIG_CLEANCACHE
if (zcache_enabled && use_cleancache) {
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [RFC 07/10] KVM: add KVM TMEM host side interface
2012-06-06 11:00 ` [RFC 07/10] KVM: add KVM TMEM host side interface Sasha Levin
@ 2012-06-29 1:59 ` Konrad Rzeszutek Wilk
0 siblings, 0 replies; 18+ messages in thread
From: Konrad Rzeszutek Wilk @ 2012-06-29 1:59 UTC (permalink / raw)
To: Sasha Levin; +Cc: avi, mtosatti, gregkh, sjenning, dan.magenheimer, kvm
On Wed, Jun 06, 2012 at 01:00:15PM +0200, Sasha Levin wrote:
> This is the host side interface that the guests which support KVM TMEM
> talk to.
>
> Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
> ---
> arch/x86/kvm/tmem/Kconfig | 6 +++
> arch/x86/kvm/tmem/Makefile | 2 +
> arch/x86/kvm/tmem/host.c | 78 ++++++++++++++++++++++++++++++++++
> arch/x86/kvm/tmem/host.h | 20 +++++++++
> arch/x86/kvm/x86.c | 8 +---
> drivers/staging/zcache/zcache-main.c | 35 +++++++++++++++-
> 6 files changed, 141 insertions(+), 8 deletions(-)
> create mode 100644 arch/x86/kvm/tmem/host.c
> create mode 100644 arch/x86/kvm/tmem/host.h
>
> diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
> index 15d8301..1a59e4f 100644
> --- a/arch/x86/kvm/tmem/Kconfig
> +++ b/arch/x86/kvm/tmem/Kconfig
> @@ -13,4 +13,10 @@ menuconfig KVM_TMEM
>
> if KVM_TMEM
>
> +config KVM_TMEM_HOST
> + bool "Host-side KVM TMEM"
> + ---help---
> + With this option on, the KVM host will be able to process KVM TMEM requests
> + coming from guests.
> +
> endif # KVM_TMEM
> diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
> index 6812d46..706cd36 100644
> --- a/arch/x86/kvm/tmem/Makefile
> +++ b/arch/x86/kvm/tmem/Makefile
> @@ -1 +1,3 @@
> ccflags-y += -Idrivers/staging/zcache/
> +
> +obj-$(CONFIG_KVM_TMEM_HOST) += host.o
> diff --git a/arch/x86/kvm/tmem/host.c b/arch/x86/kvm/tmem/host.c
> new file mode 100644
> index 0000000..9e73395
> --- /dev/null
> +++ b/arch/x86/kvm/tmem/host.c
> @@ -0,0 +1,78 @@
> +/*
> + * KVM TMEM host side interface
> + *
> + * Copyright (c) 2012 Sasha Levin
> + *
> + */
> +
> +#include <linux/kvm_types.h>
> +#include <linux/kvm_host.h>
> +
> +#include "tmem.h"
> +#include <zcache.h>
> +
> +int use_kvm_tmem_host = 1;
__mostly_read and bool
> +
> +static int no_kvmtmemhost(char *s)
> +{
> + use_kvm_tmem_host = 0;
> + return 1;
> +}
> +
> +__setup("nokvmtmemhost", no_kvmtmemhost);
> +
> +int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
> +{
> + struct tmem_kvm_op op;
> + struct page *page;
> + int r;
> + unsigned long flags;
> +
> + if (!use_kvm_tmem_host || !zcache_enabled) {
> + *ret = -ENXIO;
> + return 0;
> + }
> +
> + r = kvm_read_guest(vcpu->kvm, addr, &op, sizeof(op));
> + if (r < 0) {
> + *ret = r;
> + return 0;
Shouldn't this return r?
> + }
> +
> + switch (op.cmd) {
> + case TMEM_NEW_POOL:
> + *ret = zcache_new_pool(op.cli_id, op.u.new.flags);
> + break;
> + case TMEM_DESTROY_POOL:
> + *ret = zcache_destroy_pool(op.cli_id, op.pool_id);
> + break;
> + case TMEM_NEW_PAGE:
> + break;
> + case TMEM_PUT_PAGE:
> + page = gfn_to_page(vcpu->kvm, op.u.gen.gfn);
> + local_irq_save(flags);
> + *ret = zcache_put_page(op.cli_id, op.pool_id,
> + &op.u.gen.oid, op.u.gen.index, page);
> + local_irq_restore(flags);
> + break;
> + case TMEM_GET_PAGE:
> + page = gfn_to_page(vcpu->kvm, op.u.gen.gfn);
> + local_irq_save(flags);
> + *ret = zcache_get_page(op.cli_id, op.pool_id,
> + &op.u.gen.oid, op.u.gen.index, page);
> + local_irq_restore(flags);
> + break;
> + case TMEM_FLUSH_PAGE:
> + local_irq_save(flags);
> + *ret = zcache_flush_page(op.cli_id, op.pool_id,
> + &op.u.gen.oid, op.u.gen.index);
> + local_irq_restore(flags);
> + break;
> + case TMEM_FLUSH_OBJECT:
> + local_irq_save(flags);
> + *ret = zcache_flush_object(op.cli_id, op.pool_id, &op.u.gen.oid);
> + local_irq_restore(flags);
> + break;
> + }
> + return 0;
> +}
> diff --git a/arch/x86/kvm/tmem/host.h b/arch/x86/kvm/tmem/host.h
> new file mode 100644
> index 0000000..17ba0c4
> --- /dev/null
> +++ b/arch/x86/kvm/tmem/host.h
> @@ -0,0 +1,20 @@
> +#ifndef _KVM_TMEM_HOST_H_
> +#define _KVM_TMEM_HOST_H_
> +
> +#ifdef CONFIG_KVM_TMEM_HOST
> +
> +extern int use_kvm_tmem_host;
> +
> +extern int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret);
> +
> +#else
> +
> +static inline int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
> +{
> + *ret = -ENOSUPP;
> + return 0;
> +}
> +
> +#endif
> +
> +#endif
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 4c5b6ab..c92d4c8 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -27,6 +27,7 @@
> #include "kvm_cache_regs.h"
> #include "x86.h"
> #include "cpuid.h"
> +#include "tmem/host.h"
>
> #include <linux/clocksource.h>
> #include <linux/interrupt.h>
> @@ -4993,13 +4994,6 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
> return 1;
> }
>
> -static int kvm_pv_tmem_op(struct kvm_vcpu *vcpu, gpa_t addr, unsigned long *ret)
> -{
> - *ret = -ENOTSUPP;
> -
> - return 0;
> -}
> -
> static inline gpa_t hc_gpa(struct kvm_vcpu *vcpu, unsigned long a0,
> unsigned long a1)
> {
> diff --git a/drivers/staging/zcache/zcache-main.c b/drivers/staging/zcache/zcache-main.c
> index a196aff..65c0ab0 100644
> --- a/drivers/staging/zcache/zcache-main.c
> +++ b/drivers/staging/zcache/zcache-main.c
> @@ -1692,7 +1692,7 @@ out:
> return ret;
> }
>
> -static int zcache_new_pool(uint16_t cli_id, uint32_t flags)
> +int zcache_new_pool(uint16_t cli_id, uint32_t flags)
> {
> int poolid = -1;
> struct tmem_pool *pool;
> @@ -2011,6 +2011,37 @@ out:
> return ret;
> }
>
> +#ifdef CONFIG_KVM_TMEM_HOST
> +extern int use_kvm_tmem_host;
> +
> +static int __zcache_init_kvm(void)
> +{
> + int ret = 0;
> +
> + if (use_kvm_tmem_host) {
> + ret = zcache_new_client(KVM_CLIENT);
> + if (ret) {
> + pr_err("zcache: can't create client\n");
> + return -1;
> + } else {
> + pr_info("zcache: enabled support for KVM TMEM\n");
> + }
> + }
> + zbud_init();
> + register_shrinker(&zcache_shrinker);
> +
> + return 0;
> +}
> +
> +#else
> +
> +static inline int static int __zcache_init_kvm(void)
> +{
> + return 0;
> +}
> +
> +#endif
> +
> static int __init zcache_init(void)
> {
> int ret = 0;
> @@ -2053,6 +2084,8 @@ static int __init zcache_init(void)
> pr_err("zcache: can't create client\n");
> goto out;
> }
> + if (__zcache_init_kvm())
> + goto out;
> #endif
> #ifdef CONFIG_CLEANCACHE
> if (zcache_enabled && use_cleancache) {
> --
> 1.7.8.6
^ permalink raw reply [flat|nested] 18+ messages in thread
* [RFC 08/10] KVM: add KVM TMEM guest support
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (5 preceding siblings ...)
2012-06-06 11:00 ` [RFC 07/10] KVM: add KVM TMEM host side interface Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 09/10] KVM: support guest side cleancache Sasha Levin
` (2 subsequent siblings)
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
This part deals with the guest side. This is a common interface
for communicating with the host using the standard TMEM API.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/tmem/Kconfig | 3 +
arch/x86/kvm/tmem/Makefile | 1 +
arch/x86/kvm/tmem/guest.c | 95 ++++++++++++++++++++++++++++++++++++++++++++
arch/x86/kvm/tmem/guest.h | 11 +++++
4 files changed, 110 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kvm/tmem/guest.c
create mode 100644 arch/x86/kvm/tmem/guest.h
diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
index 1a59e4f..85ec25b 100644
--- a/arch/x86/kvm/tmem/Kconfig
+++ b/arch/x86/kvm/tmem/Kconfig
@@ -19,4 +19,7 @@ config KVM_TMEM_HOST
With this option on, the KVM host will be able to process KVM TMEM requests
coming from guests.
+config KVM_TMEM_GUEST
+ bool
+
endif # KVM_TMEM
diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
index 706cd36..1b15e20 100644
--- a/arch/x86/kvm/tmem/Makefile
+++ b/arch/x86/kvm/tmem/Makefile
@@ -1,3 +1,4 @@
ccflags-y += -Idrivers/staging/zcache/
obj-$(CONFIG_KVM_TMEM_HOST) += host.o
+obj-$(CONFIG_KVM_TMEM_GUEST) += guest.o
diff --git a/arch/x86/kvm/tmem/guest.c b/arch/x86/kvm/tmem/guest.c
new file mode 100644
index 0000000..465cc86
--- /dev/null
+++ b/arch/x86/kvm/tmem/guest.c
@@ -0,0 +1,95 @@
+/*
+ * KVM TMEM guest side interface
+ *
+ * Copyright (c) 2012 Sasha Levin
+ *
+ */
+
+#include <linux/kvm_para.h>
+#include <linux/kvm_types.h>
+#include <asm/io.h>
+
+#include "tmem.h"
+#include "guest.h"
+
+#include <zcache.h>
+
+int kvm_tmem_new_pool(__u16 cli_id, __u32 flags, unsigned long pagesize)
+{
+ struct tmem_kvm_op op = {0};
+
+ flags |= ((ilog2(pagesize) - PAGE_SHIFT) << TMEM_POOL_PAGESIZE_SHIFT) |
+ (TMEM_SPEC_VERSION << TMEM_VERSION_SHIFT);
+
+ op = (struct tmem_kvm_op) {
+ .cmd = TMEM_NEW_POOL,
+ .cli_id = cli_id,
+ .u.new.flags = flags,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
+
+int kvm_tmem_put_page(__u32 pool_id, struct tmem_oid oid, __u32 index, unsigned long gfn)
+{
+ struct tmem_kvm_op op = {
+ .cmd = TMEM_PUT_PAGE,
+ .cli_id = KVM_CLIENT,
+ .pool_id = pool_id,
+ .u.gen.oid = oid,
+ .u.gen.index = index,
+ .u.gen.gfn = gfn,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
+
+int kvm_tmem_get_page(__u32 pool_id, struct tmem_oid oid, __u32 index, unsigned long gfn)
+{
+ struct tmem_kvm_op op = {
+ .cmd = TMEM_GET_PAGE,
+ .cli_id = KVM_CLIENT,
+ .pool_id = pool_id,
+ .u.gen.oid = oid,
+ .u.gen.index = index,
+ .u.gen.gfn = gfn,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
+
+int kvm_tmem_flush_page(__u32 pool_id, struct tmem_oid oid, __u32 index)
+{
+ struct tmem_kvm_op op = {
+ .cmd = TMEM_FLUSH_PAGE,
+ .cli_id = KVM_CLIENT,
+ .pool_id = pool_id,
+ .u.gen.oid = oid,
+ .u.gen.index = index,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
+
+int kvm_tmem_flush_object(__u32 pool_id, struct tmem_oid oid)
+{
+ struct tmem_kvm_op op = {
+ .cmd = TMEM_FLUSH_OBJECT,
+ .cli_id = KVM_CLIENT,
+ .pool_id = pool_id,
+ .u.gen.oid = oid,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
+
+int kvm_tmem_destroy_pool(__u32 pool_id)
+{
+ struct tmem_kvm_op op = {
+ .cmd = TMEM_DESTROY_POOL,
+ .cli_id = KVM_CLIENT,
+ .pool_id = pool_id,
+ };
+
+ return kvm_hypercall2(KVM_HC_TMEM, virt_to_phys(&op), 0);
+}
diff --git a/arch/x86/kvm/tmem/guest.h b/arch/x86/kvm/tmem/guest.h
new file mode 100644
index 0000000..9225451
--- /dev/null
+++ b/arch/x86/kvm/tmem/guest.h
@@ -0,0 +1,11 @@
+#ifndef _KVM_TMEM_GUEST_H
+#define _KVM_TMEM_GUEST_H
+
+extern int kvm_tmem_new_pool(uint16_t cli_id, __u32 flags, unsigned long pagesize);
+extern int kvm_tmem_put_page(__u32 pool_id, struct tmem_oid oid, __u32 index, unsigned long gfn);
+extern int kvm_tmem_get_page(u32 pool_id, struct tmem_oid oid, __u32 index, unsigned long gfn);
+extern int kvm_tmem_flush_page(__u32 pool_id, struct tmem_oid oid, __u32 index);
+extern int kvm_tmem_flush_object(__u32 pool_id, struct tmem_oid oid);
+extern int kvm_tmem_destroy_pool(__u32 pool_id);
+
+#endif
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 09/10] KVM: support guest side cleancache
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (6 preceding siblings ...)
2012-06-06 11:00 ` [RFC 08/10] KVM: add KVM TMEM guest support Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:00 ` [RFC 10/10] KVM: support guest side frontswap Sasha Levin
2012-06-06 11:06 ` [RFC 01/10] KVM: reintroduce hc_gpa Avi Kivity
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
This patch adds support for guest-side cleancache. This is the part which communicates
with the host regarding cleancache TMEM actions.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/tmem/Kconfig | 9 +++
arch/x86/kvm/tmem/Makefile | 1 +
arch/x86/kvm/tmem/cleancache.c | 120 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 130 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kvm/tmem/cleancache.c
diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
index 85ec25b..4734db2 100644
--- a/arch/x86/kvm/tmem/Kconfig
+++ b/arch/x86/kvm/tmem/Kconfig
@@ -22,4 +22,13 @@ config KVM_TMEM_HOST
config KVM_TMEM_GUEST
bool
+config KVM_TMEM_GUEST_CLEANCACHE
+ bool "Guest-side cleancache support"
+ depends on CLEANCACHE
+ select KVM_TMEM_GUEST
+ ---help---
+ This options enables guest to use cleanswap with the KVM host acting
+ as the TMEM target, which means that cleanswap may be used across
+ VMs (and even hosts).
+
endif # KVM_TMEM
diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
index 1b15e20..b972c2b 100644
--- a/arch/x86/kvm/tmem/Makefile
+++ b/arch/x86/kvm/tmem/Makefile
@@ -2,3 +2,4 @@ ccflags-y += -Idrivers/staging/zcache/
obj-$(CONFIG_KVM_TMEM_HOST) += host.o
obj-$(CONFIG_KVM_TMEM_GUEST) += guest.o
+obj-$(CONFIG_KVM_TMEM_GUEST_CLEANCACHE) += cleancache.o
diff --git a/arch/x86/kvm/tmem/cleancache.c b/arch/x86/kvm/tmem/cleancache.c
new file mode 100644
index 0000000..97eee44
--- /dev/null
+++ b/arch/x86/kvm/tmem/cleancache.c
@@ -0,0 +1,120 @@
+/*
+ * KVM TMEM cleancache guest side interface
+ *
+ * Copyright (c) 2012 Sasha Levin
+ *
+ */
+
+#include <linux/cleancache.h>
+#include <linux/kvm_types.h>
+#include <linux/kvm_para.h>
+
+#include "tmem.h"
+#include "guest.h"
+
+#include <zcache.h>
+
+static void tmem_cleancache_put_page(int pool, struct cleancache_filekey key,
+ pgoff_t index, struct page *page)
+{
+ __u32 i = (__u32)index;
+ struct tmem_oid oid = *(struct tmem_oid *)&key;
+ unsigned long pfn = page_to_pfn(page);
+
+ if (pool < 0)
+ return;
+
+ kvm_tmem_put_page((__u32)pool, oid, i, pfn);
+}
+
+static int tmem_cleancache_get_page(int pool, struct cleancache_filekey key,
+ pgoff_t index, struct page *page)
+{
+ __u32 i = (__u32)index;
+ struct tmem_oid oid = *(struct tmem_oid *)&key;
+ unsigned long pfn = page_to_pfn(page);
+
+ if (pool < 0)
+ return -1;
+
+ return kvm_tmem_get_page((__u32)pool, oid, i, pfn);
+}
+
+static void tmem_cleancache_flush_page(int pool, struct cleancache_filekey key,
+ pgoff_t index)
+{
+ __u32 i = (__u32)index;
+ struct tmem_oid oid = *(struct tmem_oid *)&key;
+
+ if (pool < 0)
+ return;
+
+ kvm_tmem_flush_page((__u32)pool, oid, i);
+}
+
+static void tmem_cleancache_flush_inode(int pool, struct cleancache_filekey key)
+{
+ struct tmem_oid oid = *(struct tmem_oid *)&key;
+
+ if (pool < 0)
+ return;
+
+ kvm_tmem_flush_object((__u32)pool, oid);
+}
+
+static void tmem_cleancache_flush_fs(int pool)
+{
+ if (pool < 0)
+ return;
+
+ kvm_tmem_destroy_pool((__u32)pool);
+}
+
+static int tmem_cleancache_init_fs(size_t pagesize)
+{
+ return kvm_tmem_new_pool(KVM_CLIENT, 0, pagesize);
+}
+
+static int tmem_cleancache_init_shared_fs(char *uuid, size_t pagesize)
+{
+ return kvm_tmem_new_pool(KVM_CLIENT, TMEM_POOL_SHARED, pagesize);
+}
+
+static int use_kvmcleancache = 1;
+
+static int __init no_kvmcleancache(char *s)
+{
+ use_kvmcleancache = 0;
+ return 1;
+}
+
+__setup("nokvmcleancache", no_kvmcleancache);
+
+static struct cleancache_ops tmem_cleancache_ops = {
+ .put_page = tmem_cleancache_put_page,
+ .get_page = tmem_cleancache_get_page,
+ .invalidate_page = tmem_cleancache_flush_page,
+ .invalidate_inode = tmem_cleancache_flush_inode,
+ .invalidate_fs = tmem_cleancache_flush_fs,
+ .init_shared_fs = tmem_cleancache_init_shared_fs,
+ .init_fs = tmem_cleancache_init_fs
+};
+
+static int __init kvm_tmem_cleancache_init(void)
+{
+ struct cleancache_ops old_ops;
+
+ BUG_ON(sizeof(struct cleancache_filekey) != sizeof(struct tmem_oid));
+
+ if (!use_kvmcleancache || !kvm_para_available())
+ return 0;
+
+ old_ops = cleancache_register_ops(&tmem_cleancache_ops);
+
+ printk(KERN_INFO "cleancache enabled, RAM provided by KVM TMEM %s\n",
+ old_ops.init_fs?" (WARNING: cleancache_ops overridden)":"");
+
+ return 0;
+}
+
+module_init(kvm_tmem_cleancache_init)
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* [RFC 10/10] KVM: support guest side frontswap
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (7 preceding siblings ...)
2012-06-06 11:00 ` [RFC 09/10] KVM: support guest side cleancache Sasha Levin
@ 2012-06-06 11:00 ` Sasha Levin
2012-06-06 11:06 ` [RFC 01/10] KVM: reintroduce hc_gpa Avi Kivity
9 siblings, 0 replies; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:00 UTC (permalink / raw)
To: avi, mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk
Cc: kvm, Sasha Levin
This patch adds support for guest-side frontswap. This is the part which communicates
with the host regarding frontswap TMEM actions.
Signed-off-by: Sasha Levin <levinsasha928@gmail.com>
---
arch/x86/kvm/tmem/Kconfig | 9 +++
arch/x86/kvm/tmem/Makefile | 1 +
arch/x86/kvm/tmem/frontswap.c | 139 +++++++++++++++++++++++++++++++++++++++++
3 files changed, 149 insertions(+), 0 deletions(-)
create mode 100644 arch/x86/kvm/tmem/frontswap.c
diff --git a/arch/x86/kvm/tmem/Kconfig b/arch/x86/kvm/tmem/Kconfig
index 4734db2..ae46299 100644
--- a/arch/x86/kvm/tmem/Kconfig
+++ b/arch/x86/kvm/tmem/Kconfig
@@ -31,4 +31,13 @@ config KVM_TMEM_GUEST_CLEANCACHE
as the TMEM target, which means that cleanswap may be used across
VMs (and even hosts).
+config KVM_TMEM_GUEST_FRONTSWAP
+ bool "Guest-side frontswap support
+ depends on FRONTSWAP
+ select KVM_TMEM_GUEST
+ ---help---
+ This option enables guest to use frontswap with the KVM host acting
+ as the TMEM target, which means that frontswap may be used across
+ VMs (and even hosts).
+
endif # KVM_TMEM
diff --git a/arch/x86/kvm/tmem/Makefile b/arch/x86/kvm/tmem/Makefile
index b972c2b..40c0561 100644
--- a/arch/x86/kvm/tmem/Makefile
+++ b/arch/x86/kvm/tmem/Makefile
@@ -3,3 +3,4 @@ ccflags-y += -Idrivers/staging/zcache/
obj-$(CONFIG_KVM_TMEM_HOST) += host.o
obj-$(CONFIG_KVM_TMEM_GUEST) += guest.o
obj-$(CONFIG_KVM_TMEM_GUEST_CLEANCACHE) += cleancache.o
+obj-$(CONFIG_KVM_TMEM_GUEST_FRONTSWAP) += frontswap.o
diff --git a/arch/x86/kvm/tmem/frontswap.c b/arch/x86/kvm/tmem/frontswap.c
new file mode 100644
index 0000000..b63ac83
--- /dev/null
+++ b/arch/x86/kvm/tmem/frontswap.c
@@ -0,0 +1,139 @@
+/*
+ * KVM TMEM frontswap guest side interface
+ *
+ * Copyright (c) 2012 Sasha Levin
+ *
+ * Based on the equivalent Xen code.
+ *
+ */
+
+#include <linux/kvm_types.h>
+#include <linux/mm.h>
+#include <linux/frontswap.h>
+#include <linux/kvm_para.h>
+
+#include "tmem.h"
+#include "guest.h"
+
+#include <zcache.h>
+
+/* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+static int tmem_frontswap_poolid;
+
+/*
+ * Swizzling increases objects per swaptype, increasing tmem concurrency
+ * for heavy swaploads. Later, larger nr_cpus -> larger SWIZ_BITS
+ */
+#define SWIZ_BITS 4
+#define SWIZ_MASK ((1 << SWIZ_BITS) - 1)
+#define _oswiz(_type, _ind) ((_type << SWIZ_BITS) | (_ind & SWIZ_MASK))
+#define iswiz(_ind) (_ind >> SWIZ_BITS)
+
+static inline struct tmem_oid oswiz(unsigned type, __u32 ind)
+{
+ struct tmem_oid oid = { .oid = { 0 } };
+
+ oid.oid[0] = _oswiz(type, ind);
+
+ return oid;
+}
+
+/* returns 0 if the page was successfully put into frontswap, -1 if not */
+static int tmem_frontswap_store(unsigned type, pgoff_t offset,
+ struct page *page)
+{
+ __u32 ind = (__u32)offset;
+ unsigned long pfn = page_to_pfn(page);
+ int pool = tmem_frontswap_poolid;
+
+ if (pool < 0)
+ return -1;
+
+ return kvm_tmem_put_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+}
+
+/*
+ * returns 0 if the page was successfully gotten from frontswap, -1 if
+ * was not present (should never happen!)
+ */
+static int tmem_frontswap_load(unsigned type, pgoff_t offset,
+ struct page *page)
+{
+ __u32 ind = (__u32)offset;
+ unsigned long pfn = page_to_pfn(page);
+ int pool = tmem_frontswap_poolid;
+
+ if (pool < 0)
+ return -1;
+
+ return kvm_tmem_get_page(pool, oswiz(type, ind), iswiz(ind), pfn);
+}
+
+/* flush a single page from frontswap */
+static void tmem_frontswap_invalidate_page(unsigned type, pgoff_t offset)
+{
+ __u64 ind64 = (__u64)offset;
+ __u32 ind = (__u32)offset;
+ int pool = tmem_frontswap_poolid;
+
+ if (pool < 0)
+ return;
+
+ kvm_tmem_flush_page(pool, oswiz(type, ind), iswiz(ind64));
+}
+
+/* flush all pages from the passed swaptype */
+static void tmem_frontswap_invalidate_area(unsigned type)
+{
+ int pool = tmem_frontswap_poolid;
+ int ind;
+
+ if (pool < 0)
+ return;
+ for (ind = SWIZ_MASK; ind >= 0; ind--)
+ kvm_tmem_flush_object(pool, oswiz(type, ind));
+ kvm_tmem_destroy_pool((u32)pool);
+}
+
+static void tmem_frontswap_init(unsigned ignored)
+{
+ /* a single tmem poolid is used for all frontswap "types" (swapfiles) */
+ if (tmem_frontswap_poolid < 0)
+ tmem_frontswap_poolid =
+ kvm_tmem_new_pool(KVM_CLIENT, TMEM_POOL_PERSIST, PAGE_SIZE);
+}
+
+static int use_kvmfrontswap = 1;
+
+static int __init no_kvmfrontswap(char *s)
+{
+ use_kvmfrontswap = 0;
+ return 1;
+}
+
+__setup("nokvmfrontswap", no_kvmfrontswap);
+
+static struct frontswap_ops tmem_frontswap_ops = {
+ .store = tmem_frontswap_store,
+ .load = tmem_frontswap_load,
+ .invalidate_page = tmem_frontswap_invalidate_page,
+ .invalidate_area = tmem_frontswap_invalidate_area,
+ .init = tmem_frontswap_init
+};
+
+static int kvm_tmem_frontswap_init(void)
+{
+ struct frontswap_ops old_ops;
+
+ if (!use_kvmfrontswap || !kvm_para_available())
+ return 0;
+
+ old_ops = frontswap_register_ops(&tmem_frontswap_ops);
+
+ tmem_frontswap_poolid = -1;
+ printk(KERN_INFO "frontswap enabled, RAM provided by KVM TMEM %s\n",
+ old_ops.init?"(WARNING: frontswap_ops overridden)":"");
+ return 0;
+}
+
+module_init(kvm_tmem_frontswap_init);
--
1.7.8.6
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 11:00 [RFC 01/10] KVM: reintroduce hc_gpa Sasha Levin
` (8 preceding siblings ...)
2012-06-06 11:00 ` [RFC 10/10] KVM: support guest side frontswap Sasha Levin
@ 2012-06-06 11:06 ` Avi Kivity
2012-06-06 11:32 ` Sasha Levin
9 siblings, 1 reply; 18+ messages in thread
From: Avi Kivity @ 2012-06-06 11:06 UTC (permalink / raw)
To: Sasha Levin; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On 06/06/2012 02:00 PM, Sasha Levin wrote:
> While PV MMU is dead and gone, we'll still want to pass gpa from guest to
> host, and to do that properly we'll need to revive hc_gpa which died
> during the great PV MMU massacre of 3.2.
Missing 00/10 with a general explanation and benchmark results.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 11:06 ` [RFC 01/10] KVM: reintroduce hc_gpa Avi Kivity
@ 2012-06-06 11:32 ` Sasha Levin
2012-06-06 11:38 ` Avi Kivity
0 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On Wed, 2012-06-06 at 14:06 +0300, Avi Kivity wrote:
> On 06/06/2012 02:00 PM, Sasha Levin wrote:
> > While PV MMU is dead and gone, we'll still want to pass gpa from guest to
> > host, and to do that properly we'll need to revive hc_gpa which died
> > during the great PV MMU massacre of 3.2.
>
> Missing 00/10 with a general explanation
Coming right up.
> and benchmark results.
Is there a specific test you'd like to see? My tests were based around
the "streaming test" you proposed last time this discussion came up, and
runs of 'fio' in guests.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 11:32 ` Sasha Levin
@ 2012-06-06 11:38 ` Avi Kivity
2012-06-06 11:45 ` Sasha Levin
0 siblings, 1 reply; 18+ messages in thread
From: Avi Kivity @ 2012-06-06 11:38 UTC (permalink / raw)
To: Sasha Levin; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On 06/06/2012 02:32 PM, Sasha Levin wrote:
>
>> and benchmark results.
>
> Is there a specific test you'd like to see? My tests were based around
> the "streaming test" you proposed last time this discussion came up, and
> runs of 'fio' in guests.
Those are fine, thanks.
btw, IIUC, a guest can have two tmem providers: the hypervisor and
zcache. How does it choose?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 11:38 ` Avi Kivity
@ 2012-06-06 11:45 ` Sasha Levin
2012-06-06 12:15 ` Avi Kivity
0 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 11:45 UTC (permalink / raw)
To: Avi Kivity; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On Wed, 2012-06-06 at 14:38 +0300, Avi Kivity wrote:
> On 06/06/2012 02:32 PM, Sasha Levin wrote:
> >
> >> and benchmark results.
> >
> > Is there a specific test you'd like to see? My tests were based around
> > the "streaming test" you proposed last time this discussion came up, and
> > runs of 'fio' in guests.
>
> Those are fine, thanks.
>
> btw, IIUC, a guest can have two tmem providers: the hypervisor and
> zcache. How does it choose?
The guest will try to use the hypervisor, unless:
- 'nokvmcleancache' is passed as param - in that case cleancache will
use the local zcache provider.
- 'nokvmfrontswap' is passed as param - in that case frontswap will use
the local zcache provider.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 11:45 ` Sasha Levin
@ 2012-06-06 12:15 ` Avi Kivity
2012-06-06 12:32 ` Sasha Levin
0 siblings, 1 reply; 18+ messages in thread
From: Avi Kivity @ 2012-06-06 12:15 UTC (permalink / raw)
To: Sasha Levin; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On 06/06/2012 02:45 PM, Sasha Levin wrote:
> On Wed, 2012-06-06 at 14:38 +0300, Avi Kivity wrote:
>> On 06/06/2012 02:32 PM, Sasha Levin wrote:
>> >
>> >> and benchmark results.
>> >
>> > Is there a specific test you'd like to see? My tests were based around
>> > the "streaming test" you proposed last time this discussion came up, and
>> > runs of 'fio' in guests.
>>
>> Those are fine, thanks.
>>
>> btw, IIUC, a guest can have two tmem providers: the hypervisor and
>> zcache. How does it choose?
>
> The guest will try to use the hypervisor, unless:
>
> - 'nokvmcleancache' is passed as param - in that case cleancache will
> use the local zcache provider.
>
> - 'nokvmfrontswap' is passed as param - in that case frontswap will use
> the local zcache provider.
The guest may have more memory than free host memory, and its memory is
certainly faster; but I'm not sure how to integrate this better.
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 12:15 ` Avi Kivity
@ 2012-06-06 12:32 ` Sasha Levin
2012-06-06 12:37 ` Avi Kivity
0 siblings, 1 reply; 18+ messages in thread
From: Sasha Levin @ 2012-06-06 12:32 UTC (permalink / raw)
To: Avi Kivity; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On Wed, 2012-06-06 at 15:15 +0300, Avi Kivity wrote:
> On 06/06/2012 02:45 PM, Sasha Levin wrote:
> > On Wed, 2012-06-06 at 14:38 +0300, Avi Kivity wrote:
> >> On 06/06/2012 02:32 PM, Sasha Levin wrote:
> >> >
> >> >> and benchmark results.
> >> >
> >> > Is there a specific test you'd like to see? My tests were based around
> >> > the "streaming test" you proposed last time this discussion came up, and
> >> > runs of 'fio' in guests.
> >>
> >> Those are fine, thanks.
> >>
> >> btw, IIUC, a guest can have two tmem providers: the hypervisor and
> >> zcache. How does it choose?
> >
> > The guest will try to use the hypervisor, unless:
> >
> > - 'nokvmcleancache' is passed as param - in that case cleancache will
> > use the local zcache provider.
> >
> > - 'nokvmfrontswap' is passed as param - in that case frontswap will use
> > the local zcache provider.
>
> The guest may have more memory than free host memory, and its memory is
> certainly faster; but I'm not sure how to integrate this better.
Won't the free guest memory be exhausted first by regular local caching
before cleancache springs into action?
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [RFC 01/10] KVM: reintroduce hc_gpa
2012-06-06 12:32 ` Sasha Levin
@ 2012-06-06 12:37 ` Avi Kivity
0 siblings, 0 replies; 18+ messages in thread
From: Avi Kivity @ 2012-06-06 12:37 UTC (permalink / raw)
To: Sasha Levin; +Cc: mtosatti, gregkh, sjenning, dan.magenheimer, konrad.wilk, kvm
On 06/06/2012 03:32 PM, Sasha Levin wrote:
> On Wed, 2012-06-06 at 15:15 +0300, Avi Kivity wrote:
>> On 06/06/2012 02:45 PM, Sasha Levin wrote:
>> > On Wed, 2012-06-06 at 14:38 +0300, Avi Kivity wrote:
>> >> On 06/06/2012 02:32 PM, Sasha Levin wrote:
>> >> >
>> >> >> and benchmark results.
>> >> >
>> >> > Is there a specific test you'd like to see? My tests were based around
>> >> > the "streaming test" you proposed last time this discussion came up, and
>> >> > runs of 'fio' in guests.
>> >>
>> >> Those are fine, thanks.
>> >>
>> >> btw, IIUC, a guest can have two tmem providers: the hypervisor and
>> >> zcache. How does it choose?
>> >
>> > The guest will try to use the hypervisor, unless:
>> >
>> > - 'nokvmcleancache' is passed as param - in that case cleancache will
>> > use the local zcache provider.
>> >
>> > - 'nokvmfrontswap' is passed as param - in that case frontswap will use
>> > the local zcache provider.
>>
>> The guest may have more memory than free host memory, and its memory is
>> certainly faster; but I'm not sure how to integrate this better.
>
> Won't the free guest memory be exhausted first by regular local caching
> before cleancache springs into action?
>
It would. But we don't know whether it would be better to compress and
store on the guest (if we have 2:1 compression ratio, we need to process
two pages to free one) or compress and store on the host (where the
backing store is more or less free, but may be smaller, and is more
expensive to access).
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 18+ messages in thread