From: Jeremy Fitzhardinge <jeremy-TSDbQ3PG+2Y@public.gmane.org>
To: Anthony Liguori <anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
Cc: kvm-devel
<kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org>,
virtualization
<virtualization-qjLDD68F18O7TbgM5vRIOg@public.gmane.org>
Subject: Re: [PATCH 4/5] KVM: Add hypercall queue for paravirt_ops implementation
Date: Sun, 17 Jun 2007 21:00:03 -0700 [thread overview]
Message-ID: <46760343.5070401@goop.org> (raw)
In-Reply-To: <4675F568.90608-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
Anthony Liguori wrote:
> Regards,
>
> Anthony Liguori
> ------------------------------------------------------------------------
>
> Subject: [PATCH] KVM: Add hypercall queue for paravirt_ops implementation
> Author: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
>
> Implemented a hypercall queue that can be used when paravirt_ops lazy mode
> is enabled. This patch enables queueing of MMU write operations and CR
> updates. This results in about a 50% bump in kernbench performance.
>
> Signed-off-by: Anthony Liguori <aliguori-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
>
> diff --git a/arch/i386/kernel/kvm.c b/arch/i386/kernel/kvm.c
> index 07ce38e..4b323f1 100644
> --- a/arch/i386/kernel/kvm.c
> +++ b/arch/i386/kernel/kvm.c
> @@ -33,8 +33,10 @@ struct kvm_paravirt_state
> unsigned long cached_cr[5];
> int cr_valid[5];
>
> - struct kvm_vmca *vmca;
> + enum paravirt_lazy_mode mode;
> struct kvm_hypercall_entry *queue;
> +
> + struct kvm_vmca *vmca;
> void (*hypercall)(void);
>
> u64 vmca_gpa;
> @@ -42,17 +44,17 @@ struct kvm_paravirt_state
>
> static DEFINE_PER_CPU(struct kvm_paravirt_state *, paravirt_state);
>
> +static int do_hypercall_batching;
> static int do_mmu_write;
> static int do_cr_read_caching;
> static int do_nop_io_delay;
> static u64 msr_set_vmca;
>
> -static long kvm_hypercall(unsigned int nr, unsigned long p1,
> - unsigned long p2, unsigned long p3,
> - unsigned long p4)
> +static long _kvm_hypercall(struct kvm_paravirt_state *state,
> + unsigned int nr, unsigned long p1,
> + unsigned long p2, unsigned long p3,
> + unsigned long p4)
> {
> - struct kvm_paravirt_state *state
> - = per_cpu(paravirt_state, smp_processor_id());
> long ret;
>
> asm volatile("call *(%6) \n\t"
> @@ -69,6 +71,55 @@ static long kvm_hypercall(unsigned int nr, unsigned long p1,
> return ret;
> }
>
> +static int can_defer_hypercall(struct kvm_paravirt_state *state,
> + unsigned int nr)
> +{
> + if (state->mode == PARAVIRT_LAZY_MMU) {
> + if (nr == KVM_HYPERCALL_MMU_WRITE)
> + return 1;
> + } else if (state->mode == PARAVIRT_LAZY_CPU) {
> + if (nr == KVM_HYPERCALL_SET_CR)
> + return 1;
> + }
> +
> + return 0;
> +}
> +
> +static void _kvm_hypercall_defer(struct kvm_paravirt_state *state,
> + unsigned int nr,
> + unsigned long p1, unsigned long p2,
> + unsigned long p3, unsigned long p4)
> +{
> + struct kvm_hypercall_entry *entry;
> +
> + if (state->vmca->queue_index == state->vmca->max_queue_index)
> + _kvm_hypercall(state, KVM_HYPERCALL_FLUSH, 0, 0, 0, 0);
> +
> + /* FIXME: are we preempt safe here? */
>
BUG_ON(preemptible()) would be a reasonable thing to put here to be sure.
> + entry = &state->queue[state->vmca->queue_index++];
> + entry->nr = nr;
> + entry->p1 = p1;
> + entry->p2 = p2;
> + entry->p3 = p3;
> + entry->p4 = p4;
> +}
> +
> +static long kvm_hypercall(unsigned int nr, unsigned long p1,
> + unsigned long p2, unsigned long p3,
> + unsigned long p4)
> +{
> + struct kvm_paravirt_state *state
> + = per_cpu(paravirt_state, smp_processor_id());
>
Rather than using this here and passing state around, you could use
either x86_read/write_percpu, or get/put_cpu_var (or __get_vpu_var if
you don't need the preempt-disable).
> + long ret = 0;
> +
> + if (can_defer_hypercall(state, nr))
> + _kvm_hypercall_defer(state, nr, p1, p2, p3, p4);
> + else
> + ret = _kvm_hypercall(state, nr, p1, p2, p3, p4);
> +
> + return ret;
> +}
> +
> /*
> * No need for any "IO delay" on KVM
> */
> @@ -107,7 +158,9 @@ static void kvm_write_cr(int reg, unsigned long value)
> state->cr_valid[reg] = 1;
> state->cached_cr[reg] = value;
>
> - if (reg == 0)
> + if (state->mode == PARAVIRT_LAZY_CPU)
> + kvm_hypercall(KVM_HYPERCALL_SET_CR, reg, value, 0, 0);
> + else if (reg == 0)
> native_write_cr0(value);
> else if (reg == 3)
> native_write_cr3(value);
> @@ -218,6 +271,18 @@ static void kvm_pmd_clear(pmd_t *pmdp)
> kvm_mmu_write(pmdp, &pmd, sizeof(pmd));
> }
>
> +static void kvm_set_lazy_mode(enum paravirt_lazy_mode mode)
> +{
> + struct kvm_paravirt_state *state
> + = per_cpu(paravirt_state, smp_processor_id());
> +
> + if (mode == PARAVIRT_LAZY_FLUSH || mode == PARAVIRT_LAZY_NONE) {
> + if (state->vmca->queue_index)
> + _kvm_hypercall(state, KVM_HYPERCALL_FLUSH, 0, 0, 0, 0);
> + }
> + state->mode = mode;
>
No, you don't want to set state->mode to LAZY_FLUSH (its not a mode,
just a action which overloads the interface).
> +}
> +
> static void paravirt_ops_setup(void)
> {
> paravirt_ops.name = "KVM";
> @@ -249,6 +314,9 @@ static void paravirt_ops_setup(void)
> paravirt_ops.set_pud = kvm_set_pud;
> }
>
> + if (do_hypercall_batching)
> + paravirt_ops.set_lazy_mode = kvm_set_lazy_mode;
> +
> paravirt_ops.paravirt_enabled = 1;
>
> apply_paravirt(__parainstructions, __parainstructions_end);
> @@ -293,6 +361,9 @@ static int paravirt_initialize(void)
> if ((edx & KVM_FEATURE_MMU_WRITE))
> do_mmu_write = 1;
>
> + if ((edx & KVM_FEATURE_HYPERCALL_BATCHING))
> + do_hypercall_batching = 1;
> +
> on_each_cpu(paravirt_activate, NULL, 0, 1);
>
> return 0;
> @@ -303,6 +374,9 @@ static __init void paravirt_free_state(struct kvm_paravirt_state *state)
> if (!state)
> return;
>
> + if (state->queue)
> + __free_page(pfn_to_page(__pa(state->queue) >> PAGE_SHIFT));
> +
> if (state->hypercall)
> __free_page(pfn_to_page(__pa(state->hypercall) >> PAGE_SHIFT));
>
> @@ -329,8 +403,15 @@ static __init struct kvm_paravirt_state *paravirt_alloc_state(void)
> if (!state->hypercall)
> goto err;
>
> + state->queue = (void *)get_zeroed_page(GFP_KERNEL);
> + if (!state->queue)
> + goto err;
> +
> state->vmca_gpa = __pa(state->vmca);
> state->vmca->hypercall_gpa = __pa(state->hypercall);
> + state->vmca->queue_gpa = __pa(state->queue);
> + state->vmca->max_queue_index
> + = (PAGE_SIZE / sizeof(struct kvm_hypercall_entry));
>
> return state;
>
> diff --git a/drivers/kvm/kvm.h b/drivers/kvm/kvm.h
> index b08272b..d531899 100644
> --- a/drivers/kvm/kvm.h
> +++ b/drivers/kvm/kvm.h
> @@ -291,6 +291,7 @@ struct kvm_vcpu {
> gpa_t para_state_gpa;
> struct page *para_state_page;
> gpa_t hypercall_gpa;
> + struct page *queue_page;
> unsigned long cr4;
> unsigned long cr8;
> u64 pdptrs[4]; /* pae */
> diff --git a/drivers/kvm/kvm_main.c b/drivers/kvm/kvm_main.c
> index 4f65729..79a2a64 100644
> --- a/drivers/kvm/kvm_main.c
> +++ b/drivers/kvm/kvm_main.c
> @@ -94,7 +94,8 @@ struct vfsmount *kvmfs_mnt;
>
> #define KVM_PARAVIRT_FEATURES \
> (KVM_FEATURE_VMCA | KVM_FEATURE_NOP_IO_DELAY | \
> - KVM_FEATURE_CR_READ_CACHE | KVM_FEATURE_MMU_WRITE)
> + KVM_FEATURE_CR_READ_CACHE | KVM_FEATURE_MMU_WRITE | \
> + KVM_FEATURE_HYPERCALL_BATCHING)
>
> #define KVM_MSR_SET_VMCA 0x87655678
>
> @@ -1369,6 +1370,24 @@ static int kvm_hypercall_mmu_write(struct kvm_vcpu *vcpu, gva_t addr,
> return 0;
> }
>
> +static int kvm_hypercall_set_cr(struct kvm_vcpu *vcpu,
> + u32 reg, unsigned long value)
> +{
> + switch (reg) {
> + case 0:
> + set_cr0(vcpu, value);
> + break;
> + case 3:
> + set_cr3(vcpu, value);
> + break;
> + case 4:
> + set_cr4(vcpu, value);
> + break;
> + }
> +
> + return 0;
> +}
> +
> static int dispatch_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
> unsigned long p1, unsigned long p2,
> unsigned long p3, unsigned long p4)
> @@ -1376,10 +1395,36 @@ static int dispatch_hypercall(struct kvm_vcpu *vcpu, unsigned long nr,
> switch (nr) {
> case KVM_HYPERCALL_MMU_WRITE:
> return kvm_hypercall_mmu_write(vcpu, p1, p2, p3, p4);
> + case KVM_HYPERCALL_SET_CR:
> + return kvm_hypercall_set_cr(vcpu, p1, p2);
> }
> return -ENOSYS;
> }
>
> +static int kvm_hypercall_flush(struct kvm_vcpu *vcpu)
> +{
> + struct kvm_hypercall_entry *queue;
> + struct kvm_vmca *vmca;
> + int ret = 0;
> + int i;
> +
> + queue = kmap(vcpu->queue_page);
> + vmca = kmap(vcpu->para_state_page);
>
kmap_atomic? Or why not keep them mapped all the time?
J
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
next prev parent reply other threads:[~2007-06-18 4:00 UTC|newest]
Thread overview: 85+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-06-18 2:56 [PATCH 0/5] KVM paravirt_ops implementation Anthony Liguori
[not found] ` <4675F462.1010708-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 2:58 ` [PATCH 1/5] KVM paravirt_ops core infrastructure Anthony Liguori
[not found] ` <4675F4C3.6050700-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 8:03 ` Avi Kivity
[not found] ` <46763C6B.9050004-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:25 ` Anthony Liguori
[not found] ` <467679C5.6030201-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 12:28 ` Avi Kivity
2007-06-26 8:04 ` Dor Laor
[not found] ` <64F9B87B6B770947A9F8391472E032160C73025E-yEcIvxbTEBqsx+V+t5oei8rau4O3wl8o3fe8/T/H7NteoWH0uzbU5w@public.gmane.org>
2007-06-26 8:45 ` Jun Koi
[not found] ` <fdaac4d50706260145x1ebceadt432edd5b6a6ac1f2-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2007-06-26 11:57 ` Anthony Liguori
2007-06-26 11:56 ` Anthony Liguori
2007-06-18 2:58 ` [PATCH 2/5] KVM: Implement CR read caching for KVM paravirt_ops Anthony Liguori
[not found] ` <4675F4F1.5090207-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 8:05 ` Avi Kivity
[not found] ` <46763CD3.3060704-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:26 ` Anthony Liguori
2007-06-18 8:11 ` Avi Kivity
[not found] ` <46763E35.8020108-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:27 ` Anthony Liguori
2007-06-18 3:00 ` [PATCH 3/5] KVM: Add paravirt MMU write support Anthony Liguori
[not found] ` <4675F533.40809-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 8:20 ` Avi Kivity
[not found] ` <46764061.9080705-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:33 ` Anthony Liguori
[not found] ` <46767B8C.9050001-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 12:38 ` Avi Kivity
[not found] ` <46767CD1.7030208-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:48 ` Anthony Liguori
2007-06-19 21:57 ` Anthony Liguori
[not found] ` <46785132.3070505-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-19 22:19 ` Jeremy Fitzhardinge
[not found] ` <4678567C.6040400-TSDbQ3PG+2Y@public.gmane.org>
2007-06-19 22:28 ` Anthony Liguori
2007-06-18 3:00 ` [PATCH 4/5] KVM: Add hypercall queue for paravirt_ops implementation Anthony Liguori
[not found] ` <4675F568.90608-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 4:00 ` Jeremy Fitzhardinge [this message]
[not found] ` <46760343.5070401-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 4:09 ` Jeremy Fitzhardinge
2007-06-18 12:22 ` Anthony Liguori
2007-06-18 9:07 ` Avi Kivity
[not found] ` <46764B47.5060403-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 12:40 ` Anthony Liguori
[not found] ` <46767D47.1010104-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 12:50 ` Avi Kivity
[not found] ` <46767F98.70109-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 13:03 ` Gregory Haskins
[not found] ` <1182171781.4593.38.camel-5CR4LY5GPkvLDviKLk5550HKjMygAv58XqFh9Ls21Oc@public.gmane.org>
2007-06-18 13:19 ` Anthony Liguori
[not found] ` <4676867E.1090208-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 13:25 ` Gregory Haskins
2007-06-18 13:22 ` Anthony Liguori
[not found] ` <46768724.3000509-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 13:35 ` Avi Kivity
[not found] ` <46768A3F.2010202-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 14:02 ` Anthony Liguori
[not found] ` <4676905B.6000805-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 15:08 ` Avi Kivity
[not found] ` <46769FFE.6040502-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 15:20 ` Anthony Liguori
[not found] ` <4676A2D4.2040704-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 16:01 ` Avi Kivity
2007-06-18 16:00 ` Avi Kivity
[not found] ` <4676AC10.3090007-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-18 17:47 ` Anthony Liguori
2007-06-18 3:03 ` [PATCH 5/5] KVM: paravirt time source Anthony Liguori
[not found] ` <4675F601.3090706-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 9:24 ` Avi Kivity
2007-06-18 19:11 ` Jeremy Fitzhardinge
[not found] ` <4676D8E4.3020806-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 21:52 ` Anthony Liguori
[not found] ` <4676FEB9.6060308-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 22:04 ` Jeremy Fitzhardinge
[not found] ` <46770162.6030101-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 23:33 ` Anthony Liguori
[not found] ` <4677163F.2030308-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 23:56 ` Jeremy Fitzhardinge
[not found] ` <46771BA0.2000308-TSDbQ3PG+2Y@public.gmane.org>
2007-06-19 0:53 ` Anthony Liguori
2007-06-19 7:44 ` Avi Kivity
[not found] ` <4677894D.3050500-atKUWr5tajBWk0Htik3J/w@public.gmane.org>
2007-06-19 8:04 ` Rusty Russell
2007-06-19 20:38 ` Anthony Liguori
[not found] ` <46783EDB.5010808-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-19 21:26 ` Jeremy Fitzhardinge
[not found] ` <46784A0E.3080502-TSDbQ3PG+2Y@public.gmane.org>
2007-06-19 21:38 ` Anthony Liguori
2007-06-21 7:04 ` Dong, Eddie
2007-06-18 3:19 ` [PATCH 0/5] KVM paravirt_ops implementation Jeremy Fitzhardinge
[not found] ` <4675F9DE.6080806-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 3:36 ` Anthony Liguori
[not found] ` <4675FDCA.4040006-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 4:21 ` Jeremy Fitzhardinge
[not found] ` <4676084F.3090901-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 12:46 ` Anthony Liguori
[not found] ` <46767EB2.4090707-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-18 14:46 ` Jeremy Fitzhardinge
[not found] ` <46769AD2.9080105-TSDbQ3PG+2Y@public.gmane.org>
2007-06-18 15:07 ` Anthony Liguori
2007-06-20 0:21 ` Zachary Amsden
[not found] ` <46787325.30804-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 14:22 ` Anthony Liguori
[not found] ` <4679381E.9090404-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-20 15:32 ` Jeremy Fitzhardinge
[not found] ` <46794899.6070708-TSDbQ3PG+2Y@public.gmane.org>
2007-06-20 19:35 ` Zachary Amsden
[not found] ` <46798174.2060304-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 19:47 ` Jeremy Fitzhardinge
2007-06-20 19:52 ` Anthony Liguori
[not found] ` <46798597.4020903-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-20 20:03 ` Zachary Amsden
[not found] ` <4679882B.7070605-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 20:16 ` Jeremy Fitzhardinge
[not found] ` <46798B16.5090407-TSDbQ3PG+2Y@public.gmane.org>
2007-06-20 20:27 ` Anthony Liguori
[not found] ` <46798D9B.5000400-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-20 20:33 ` Jeremy Fitzhardinge
[not found] ` <46798F1A.4090901-TSDbQ3PG+2Y@public.gmane.org>
2007-06-20 20:46 ` Zachary Amsden
[not found] ` <4679921A.8090607-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 20:55 ` Jeremy Fitzhardinge
2007-06-20 22:08 ` Anthony Liguori
[not found] ` <4679A54F.5020908-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-20 22:33 ` Jeremy Fitzhardinge
2007-06-20 20:43 ` Zachary Amsden
[not found] ` <46799157.3070805-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 20:53 ` Jeremy Fitzhardinge
[not found] ` <467993B1.6000307-TSDbQ3PG+2Y@public.gmane.org>
2007-06-20 21:08 ` Zachary Amsden
[not found] ` <46799755.8060405-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 21:48 ` Jeremy Fitzhardinge
2007-06-20 22:39 ` Anthony Liguori
2007-06-20 20:22 ` Anthony Liguori
[not found] ` <46798C99.8010303-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org>
2007-06-20 20:37 ` Zachary Amsden
[not found] ` <46799001.5020807-pghWNbHTmq7QT0dZR+AlfA@public.gmane.org>
2007-06-20 21:07 ` Jeremy Fitzhardinge
[not found] ` <46799716.9040402-TSDbQ3PG+2Y@public.gmane.org>
2007-06-20 21:27 ` ron minnich
2007-06-20 21:39 ` H. Peter Anvin
2007-06-19 23:49 ` Zachary Amsden
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=46760343.5070401@goop.org \
--to=jeremy-tsdbq3pg+2y@public.gmane.org \
--cc=anthony-rdkfGonbjUSkNkDKm+mE6A@public.gmane.org \
--cc=kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=virtualization-qjLDD68F18O7TbgM5vRIOg@public.gmane.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.