* [PATCH RFC v3 3/6] sched/idle: Add a generic poll before enter real idle path
From: Quan Xu @ 2017-11-13 10:06 UTC (permalink / raw)
To: kvm, linux-doc, linux-fsdevel, linux-kernel, virtualization, x86,
xen-devel
Cc: Yang Zhang, Len Brown, Quan Xu, Tom Lendacky, Peter Zijlstra,
Kyle Huey, Ingo Molnar, Borislav Petkov, Andy Lutomirski,
H. Peter Anvin, Thomas Gleixner, Tobias Klauser
In-Reply-To: <1510567565-5118-1-git-send-email-quan.xu0@gmail.com>
From: Yang Zhang <yang.zhang.wz@gmail.com>
Implement a generic idle poll which resembles the functionality
found in arch/. Provide weak arch_cpu_idle_poll function which
can be overridden by the architecture code if needed.
Interrupts arrive which may not cause a reschedule in idle loops.
In KVM guest, this costs several VM-exit/VM-entry cycles, VM-entry
for interrupts and VM-exit immediately. Also this becomes more
expensive than bare metal. Add a generic idle poll before enter
real idle path. When a reschedule event is pending, we can bypass
the real idle path.
Signed-off-by: Quan Xu <quan.xu0@gmail.com>
Signed-off-by: Yang Zhang <yang.zhang.wz@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Kyle Huey <me@kylehuey.com>
Cc: Len Brown <len.brown@intel.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Cc: Tobias Klauser <tklauser@distanz.ch>
Cc: linux-kernel@vger.kernel.org
---
arch/x86/kernel/process.c | 7 +++++++
kernel/sched/idle.c | 2 ++
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c
index c676853..f7db8b5 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -333,6 +333,13 @@ void arch_cpu_idle(void)
x86_idle();
}
+#ifdef CONFIG_PARAVIRT
+void arch_cpu_idle_poll(void)
+{
+ paravirt_idle_poll();
+}
+#endif
+
/*
* We use this if we don't have any better idle routine..
*/
diff --git a/kernel/sched/idle.c b/kernel/sched/idle.c
index 257f4f0..df7c422 100644
--- a/kernel/sched/idle.c
+++ b/kernel/sched/idle.c
@@ -74,6 +74,7 @@ static noinline int __cpuidle cpu_idle_poll(void)
}
/* Weak implementations for optional arch specific functions */
+void __weak arch_cpu_idle_poll(void) { }
void __weak arch_cpu_idle_prepare(void) { }
void __weak arch_cpu_idle_enter(void) { }
void __weak arch_cpu_idle_exit(void) { }
@@ -219,6 +220,7 @@ static void do_idle(void)
*/
__current_set_polling();
+ arch_cpu_idle_poll();
quiet_vmstat();
tick_nohz_idle_enter();
--
1.7.1
^ permalink raw reply related
* [PATCH RFC v3 2/6] KVM guest: register kvm_idle_poll for pv_idle_ops
From: Quan Xu @ 2017-11-13 10:06 UTC (permalink / raw)
To: kvm, linux-doc, linux-fsdevel, linux-kernel, virtualization, x86,
xen-devel
Cc: Yang Zhang, Quan Xu, Radim Krčmář, Ingo Molnar,
H. Peter Anvin, Paolo Bonzini, Thomas Gleixner
In-Reply-To: <1510567565-5118-1-git-send-email-quan.xu0@gmail.com>
From: Quan Xu <quan.xu0@gmail.com>
Although smart idle poll has nothing to do with paravirt, it can
not bring any benifit to native. So we only enable it when Linux
runs as a KVM guest( also it can extend to other hypervisor like
Xen, HyperV and VMware).
Introduce per-CPU variable poll_duration_ns to control the max
poll time.
Signed-off-by: Yang Zhang <yang.zhang.wz@gmail.com>
Signed-off-by: Quan Xu <quan.xu0@gmail.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: "Radim Krčmář" <rkrcmar@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: kvm@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
arch/x86/kernel/kvm.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 8bb9594..2a6e402 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -75,6 +75,7 @@ static int parse_no_kvmclock_vsyscall(char *arg)
early_param("no-kvmclock-vsyscall", parse_no_kvmclock_vsyscall);
+static DEFINE_PER_CPU(unsigned long, poll_duration_ns);
static DEFINE_PER_CPU(struct kvm_vcpu_pv_apf_data, apf_reason) __aligned(64);
static DEFINE_PER_CPU(struct kvm_steal_time, steal_time) __aligned(64);
static int has_steal_clock = 0;
@@ -364,6 +365,29 @@ static void kvm_guest_cpu_init(void)
kvm_register_steal_time();
}
+static void kvm_idle_poll(void)
+{
+ unsigned long poll_duration = this_cpu_read(poll_duration_ns);
+ ktime_t start, cur, stop;
+
+ start = cur = ktime_get();
+ stop = ktime_add_ns(ktime_get(), poll_duration);
+
+ do {
+ if (need_resched())
+ break;
+ cur = ktime_get();
+ } while (ktime_before(cur, stop));
+}
+
+static void kvm_guest_idle_init(void)
+{
+ if (!kvm_para_available())
+ return;
+
+ pv_idle_ops.poll = kvm_idle_poll;
+}
+
static void kvm_pv_disable_apf(void)
{
if (!__this_cpu_read(apf_reason.enabled))
@@ -499,6 +523,8 @@ void __init kvm_guest_init(void)
kvm_guest_cpu_init();
#endif
+ kvm_guest_idle_init();
+
/*
* Hard lockup detection is enabled by default. Disable it, as guests
* can get false positives too easily, for example if the host is
--
1.7.1
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related
* [PATCH RFC v3 1/6] x86/paravirt: Add pv_idle_ops to paravirt ops
From: Quan Xu @ 2017-11-13 10:06 UTC (permalink / raw)
To: kvm, linux-doc, linux-fsdevel, linux-kernel, virtualization, x86,
xen-devel
Cc: Yang Zhang, Juergen Gross, Quan Xu, Rusty Russell, Ingo Molnar,
H. Peter Anvin, Alok Kataria, Thomas Gleixner
In-Reply-To: <1510567565-5118-1-git-send-email-quan.xu0@gmail.com>
From: Quan Xu <quan.xu0@gmail.com>
So far, pv_idle_ops.poll is the only ops for pv_idle. .poll is called
in idle path which will poll for a while before we enter the real idle
state.
In virtualization, idle path includes several heavy operations
includes timer access(LAPIC timer or TSC deadline timer) which will
hurt performance especially for latency intensive workload like message
passing task. The cost is mainly from the vmexit which is a hardware
context switch between virtual machine and hypervisor. Our solution is
to poll for a while and do not enter real idle path if we can get the
schedule event during polling.
Poll may cause the CPU waste so we adopt a smart polling mechanism to
reduce the useless poll.
Signed-off-by: Yang Zhang <yang.zhang.wz@gmail.com>
Signed-off-by: Quan Xu <quan.xu0@gmail.com>
Cc: Juergen Gross <jgross@suse.com>
Cc: Alok Kataria <akataria@vmware.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: virtualization@lists.linux-foundation.org
Cc: linux-kernel@vger.kernel.org
Cc: xen-devel@lists.xenproject.org
---
arch/x86/include/asm/paravirt.h | 5 +++++
arch/x86/include/asm/paravirt_types.h | 6 ++++++
arch/x86/kernel/paravirt.c | 6 ++++++
3 files changed, 17 insertions(+), 0 deletions(-)
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
index fd81228..3c83727 100644
--- a/arch/x86/include/asm/paravirt.h
+++ b/arch/x86/include/asm/paravirt.h
@@ -198,6 +198,11 @@ static inline unsigned long long paravirt_read_pmc(int counter)
#define rdpmcl(counter, val) ((val) = paravirt_read_pmc(counter))
+static inline void paravirt_idle_poll(void)
+{
+ PVOP_VCALL0(pv_idle_ops.poll);
+}
+
static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
{
PVOP_VCALL2(pv_cpu_ops.alloc_ldt, ldt, entries);
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
index 10cc3b9..95c0e3e 100644
--- a/arch/x86/include/asm/paravirt_types.h
+++ b/arch/x86/include/asm/paravirt_types.h
@@ -313,6 +313,10 @@ struct pv_lock_ops {
struct paravirt_callee_save vcpu_is_preempted;
} __no_randomize_layout;
+struct pv_idle_ops {
+ void (*poll)(void);
+} __no_randomize_layout;
+
/* This contains all the paravirt structures: we get a convenient
* number for each function using the offset which we use to indicate
* what to patch. */
@@ -323,6 +327,7 @@ struct paravirt_patch_template {
struct pv_irq_ops pv_irq_ops;
struct pv_mmu_ops pv_mmu_ops;
struct pv_lock_ops pv_lock_ops;
+ struct pv_idle_ops pv_idle_ops;
} __no_randomize_layout;
extern struct pv_info pv_info;
@@ -332,6 +337,7 @@ struct paravirt_patch_template {
extern struct pv_irq_ops pv_irq_ops;
extern struct pv_mmu_ops pv_mmu_ops;
extern struct pv_lock_ops pv_lock_ops;
+extern struct pv_idle_ops pv_idle_ops;
#define PARAVIRT_PATCH(x) \
(offsetof(struct paravirt_patch_template, x) / sizeof(void *))
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
index 19a3e8f..67cab22 100644
--- a/arch/x86/kernel/paravirt.c
+++ b/arch/x86/kernel/paravirt.c
@@ -128,6 +128,7 @@ unsigned paravirt_patch_jmp(void *insnbuf, const void *target,
#ifdef CONFIG_PARAVIRT_SPINLOCKS
.pv_lock_ops = pv_lock_ops,
#endif
+ .pv_idle_ops = pv_idle_ops,
};
return *((void **)&tmpl + type);
}
@@ -312,6 +313,10 @@ struct pv_time_ops pv_time_ops = {
.steal_clock = native_steal_clock,
};
+struct pv_idle_ops pv_idle_ops = {
+ .poll = paravirt_nop,
+};
+
__visible struct pv_irq_ops pv_irq_ops = {
.save_fl = __PV_IS_CALLEE_SAVE(native_save_fl),
.restore_fl = __PV_IS_CALLEE_SAVE(native_restore_fl),
@@ -463,3 +468,4 @@ struct pv_mmu_ops pv_mmu_ops __ro_after_init = {
EXPORT_SYMBOL (pv_mmu_ops);
EXPORT_SYMBOL_GPL(pv_info);
EXPORT_SYMBOL (pv_irq_ops);
+EXPORT_SYMBOL (pv_idle_ops);
--
1.7.1
^ permalink raw reply related
* [PATCH RFC v3 0/6] x86/idle: add halt poll support
From: Quan Xu @ 2017-11-13 10:05 UTC (permalink / raw)
To: kvm, linux-doc, linux-fsdevel, linux-kernel, virtualization, x86,
xen-devel
Cc: Yang Zhang
From: Yang Zhang <yang.zhang.wz@gmail.com>
Some latency-intensive workload have seen obviously performance
drop when running inside VM. The main reason is that the overhead
is amplified when running inside VM. The most cost I have seen is
inside idle path.
This patch introduces a new mechanism to poll for a while before
entering idle state. If schedule is needed during poll, then we
don't need to goes through the heavy overhead path.
Here is the data we get when running benchmark contextswitch to measure
the latency(lower is better):
1. w/o patch and disable kvm dynamic poll (halt_poll_ns=0):
3402.9 ns/ctxsw -- 199.8 %CPU
2. w/ patch and disable kvm dynamic poll (halt_poll_ns=0):
halt_poll_threshold=10000 -- 1151.4 ns/ctxsw -- 200.1 %CPU
halt_poll_threshold=20000 -- 1149.7 ns/ctxsw -- 199.9 %CPU
halt_poll_threshold=30000 -- 1151.0 ns/ctxsw -- 199.9 %CPU
halt_poll_threshold=40000 -- 1155.4 ns/ctxsw -- 199.3 %CPU
halt_poll_threshold=50000 -- 1161.0 ns/ctxsw -- 200.0 %CPU
halt_poll_threshold=100000 -- 1163.8 ns/ctxsw -- 200.4 %CPU
halt_poll_threshold=300000 -- 1159.4 ns/ctxsw -- 201.9 %CPU
halt_poll_threshold=500000 -- 1163.5 ns/ctxsw -- 205.5 %CPU
3. w/ kvm dynamic poll:
halt_poll_ns=10000 -- 3470.5 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=20000 -- 3273.0 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=30000 -- 3628.7 ns/ctxsw -- 199.4 %CPU
halt_poll_ns=40000 -- 2280.6 ns/ctxsw -- 199.5 %CPU
halt_poll_ns=50000 -- 3200.3 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=100000 -- 2186.6 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=300000 -- 3178.7 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=500000 -- 3505.4 ns/ctxsw -- 199.7 %CPU
4. w/patch and w/ kvm dynamic poll:
halt_poll_ns=10000 & halt_poll_threshold=10000 -- 1155.5 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=20000 -- 1165.6 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=30000 -- 1161.1 ns/ctxsw -- 200.0 %CPU
halt_poll_ns=20000 & halt_poll_threshold=10000 -- 1158.1 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=20000 & halt_poll_threshold=20000 -- 1161.0 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=20000 & halt_poll_threshold=30000 -- 1163.7 ns/ctxsw -- 199.9 %CPU
halt_poll_ns=30000 & halt_poll_threshold=10000 -- 1158.7 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=30000 & halt_poll_threshold=20000 -- 1153.8 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=30000 & halt_poll_threshold=30000 -- 1155.1 ns/ctxsw -- 199.8 %CPU
5. idle=poll
3957.57 ns/ctxsw -- 999.4%CPU
Here is the data we get when running benchmark netperf:
1. w/o patch and disable kvm dynamic poll (halt_poll_ns=0):
29031.6 bit/s -- 76.1 %CPU
2. w/ patch and disable kvm dynamic poll (halt_poll_ns=0):
halt_poll_threshold=10000 -- 29021.7 bit/s -- 105.1 %CPU
halt_poll_threshold=20000 -- 33463.5 bit/s -- 128.2 %CPU
halt_poll_threshold=30000 -- 34436.4 bit/s -- 127.8 %CPU
halt_poll_threshold=40000 -- 35563.3 bit/s -- 129.6 %CPU
halt_poll_threshold=50000 -- 35787.7 bit/s -- 129.4 %CPU
halt_poll_threshold=100000 -- 35477.7 bit/s -- 130.0 %CPU
halt_poll_threshold=300000 -- 35730.0 bit/s -- 132.4 %CPU
halt_poll_threshold=500000 -- 34978.4 bit/s -- 134.2 %CPU
3. w/ kvm dynamic poll:
halt_poll_ns=10000 -- 28849.8 bit/s -- 75.2 %CPU
halt_poll_ns=20000 -- 29004.8 bit/s -- 76.1 %CPU
halt_poll_ns=30000 -- 35662.0 bit/s -- 199.7 %CPU
halt_poll_ns=40000 -- 35874.8 bit/s -- 187.5 %CPU
halt_poll_ns=50000 -- 35603.1 bit/s -- 199.8 %CPU
halt_poll_ns=100000 -- 35588.8 bit/s -- 200.0 %CPU
halt_poll_ns=300000 -- 35912.4 bit/s -- 200.0 %CPU
halt_poll_ns=500000 -- 35735.6 bit/s -- 200.0 %CPU
4. w/patch and w/ kvm dynamic poll:
halt_poll_ns=10000 & halt_poll_threshold=10000 -- 29427.9 bit/s -- 107.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=20000 -- 33048.4 bit/s -- 128.1 %CPU
halt_poll_ns=10000 & halt_poll_threshold=30000 -- 35129.8 bit/s -- 129.1 %CPU
halt_poll_ns=20000 & halt_poll_threshold=10000 -- 31091.3 bit/s -- 130.3 %CPU
halt_poll_ns=20000 & halt_poll_threshold=20000 -- 33587.9 bit/s -- 128.9 %CPU
halt_poll_ns=20000 & halt_poll_threshold=30000 -- 35532.9 bit/s -- 129.1 %CPU
halt_poll_ns=30000 & halt_poll_threshold=10000 -- 35633.1 bit/s -- 199.4 %CPU
halt_poll_ns=30000 & halt_poll_threshold=20000 -- 42225.3 bit/s -- 198.7 %CPU
halt_poll_ns=30000 & halt_poll_threshold=30000 -- 42210.7 bit/s -- 200.3 %CPU
5. idle=poll
37081.7 bit/s -- 998.1 %CPU
---
V2 -> V3:
- move poll update into arch/. in v3, poll update is based on duration of the
last idle loop which is from tick_nohz_idle_enter to tick_nohz_idle_exit,
and try our best not to interfere with scheduler/idle code. (This seems
not to follow Peter's v2 comment, however we had a f2f discussion about it
in Prague.)
- enhance patch desciption.
- enhance Documentation and sysctls.
- test with IRQ_TIMINGS related code, which seems not working so far.
V1 -> V2:
- integrate the smart halt poll into paravirt code
- use idle_stamp instead of check_poll
- since it hard to get whether vcpu is the only task in pcpu, so we
don't consider it in this series.(May improve it in future)
---
Quan Xu (4):
x86/paravirt: Add pv_idle_ops to paravirt ops
KVM guest: register kvm_idle_poll for pv_idle_ops
Documentation: Add three sysctls for smart idle poll
tick: get duration of the last idle loop
Yang Zhang (2):
sched/idle: Add a generic poll before enter real idle path
KVM guest: introduce smart idle poll algorithm
Documentation/sysctl/kernel.txt | 35 ++++++++++++++++
arch/x86/include/asm/paravirt.h | 5 ++
arch/x86/include/asm/paravirt_types.h | 6 +++
arch/x86/kernel/kvm.c | 73 +++++++++++++++++++++++++++++++++
arch/x86/kernel/paravirt.c | 10 +++++
arch/x86/kernel/process.c | 7 +++
include/linux/kernel.h | 6 +++
include/linux/tick.h | 2 +
kernel/sched/idle.c | 2 +
kernel/sysctl.c | 34 +++++++++++++++
kernel/time/tick-sched.c | 11 +++++
kernel/time/tick-sched.h | 3 +
12 files changed, 194 insertions(+), 0 deletions(-)
^ permalink raw reply
* [PATCH RFC v3 0/6] x86/idle: add halt poll support
From: Quan Xu @ 2017-11-13 8:16 UTC (permalink / raw)
To: kvm, linux-doc, linux-fsdevel, linux-kernel, virtualization, x86,
xen-devel
Cc: Yang Zhang
From: Yang Zhang <yang.zhang.wz@gmail.com>
Some latency-intensive workload have seen obviously performance
drop when running inside VM. The main reason is that the overhead
is amplified when running inside VM. The most cost I have seen is
inside idle path.
This patch introduces a new mechanism to poll for a while before
entering idle state. If schedule is needed during poll, then we
don't need to goes through the heavy overhead path.
Here is the data we get when running benchmark contextswitch to measure
the latency(lower is better):
1. w/o patch and disable kvm dynamic poll (halt_poll_ns=0):
3402.9 ns/ctxsw -- 199.8 %CPU
2. w/ patch and disable kvm dynamic poll (halt_poll_ns=0):
halt_poll_threshold=10000 -- 1151.4 ns/ctxsw -- 200.1 %CPU
halt_poll_threshold=20000 -- 1149.7 ns/ctxsw -- 199.9 %CPU
halt_poll_threshold=30000 -- 1151.0 ns/ctxsw -- 199.9 %CPU
halt_poll_threshold=40000 -- 1155.4 ns/ctxsw -- 199.3 %CPU
halt_poll_threshold=50000 -- 1161.0 ns/ctxsw -- 200.0 %CPU
halt_poll_threshold=100000 -- 1163.8 ns/ctxsw -- 200.4 %CPU
halt_poll_threshold=300000 -- 1159.4 ns/ctxsw -- 201.9 %CPU
halt_poll_threshold=500000 -- 1163.5 ns/ctxsw -- 205.5 %CPU
3. w/ kvm dynamic poll:
halt_poll_ns=10000 -- 3470.5 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=20000 -- 3273.0 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=30000 -- 3628.7 ns/ctxsw -- 199.4 %CPU
halt_poll_ns=40000 -- 2280.6 ns/ctxsw -- 199.5 %CPU
halt_poll_ns=50000 -- 3200.3 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=100000 -- 2186.6 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=300000 -- 3178.7 ns/ctxsw -- 199.6 %CPU
halt_poll_ns=500000 -- 3505.4 ns/ctxsw -- 199.7 %CPU
4. w/patch and w/ kvm dynamic poll:
halt_poll_ns=10000 & halt_poll_threshold=10000 -- 1155.5 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=20000 -- 1165.6 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=30000 -- 1161.1 ns/ctxsw -- 200.0 %CPU
halt_poll_ns=20000 & halt_poll_threshold=10000 -- 1158.1 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=20000 & halt_poll_threshold=20000 -- 1161.0 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=20000 & halt_poll_threshold=30000 -- 1163.7 ns/ctxsw -- 199.9 %CPU
halt_poll_ns=30000 & halt_poll_threshold=10000 -- 1158.7 ns/ctxsw -- 199.7 %CPU
halt_poll_ns=30000 & halt_poll_threshold=20000 -- 1153.8 ns/ctxsw -- 199.8 %CPU
halt_poll_ns=30000 & halt_poll_threshold=30000 -- 1155.1 ns/ctxsw -- 199.8 %CPU
5. idle=poll
3957.57 ns/ctxsw -- 999.4%CPU
Here is the data we get when running benchmark netperf:
1. w/o patch and disable kvm dynamic poll (halt_poll_ns=0):
29031.6 bit/s -- 76.1 %CPU
2. w/ patch and disable kvm dynamic poll (halt_poll_ns=0):
halt_poll_threshold=10000 -- 29021.7 bit/s -- 105.1 %CPU
halt_poll_threshold=20000 -- 33463.5 bit/s -- 128.2 %CPU
halt_poll_threshold=30000 -- 34436.4 bit/s -- 127.8 %CPU
halt_poll_threshold=40000 -- 35563.3 bit/s -- 129.6 %CPU
halt_poll_threshold=50000 -- 35787.7 bit/s -- 129.4 %CPU
halt_poll_threshold=100000 -- 35477.7 bit/s -- 130.0 %CPU
halt_poll_threshold=300000 -- 35730.0 bit/s -- 132.4 %CPU
halt_poll_threshold=500000 -- 34978.4 bit/s -- 134.2 %CPU
3. w/ kvm dynamic poll:
halt_poll_ns=10000 -- 28849.8 bit/s -- 75.2 %CPU
halt_poll_ns=20000 -- 29004.8 bit/s -- 76.1 %CPU
halt_poll_ns=30000 -- 35662.0 bit/s -- 199.7 %CPU
halt_poll_ns=40000 -- 35874.8 bit/s -- 187.5 %CPU
halt_poll_ns=50000 -- 35603.1 bit/s -- 199.8 %CPU
halt_poll_ns=100000 -- 35588.8 bit/s -- 200.0 %CPU
halt_poll_ns=300000 -- 35912.4 bit/s -- 200.0 %CPU
halt_poll_ns=500000 -- 35735.6 bit/s -- 200.0 %CPU
4. w/patch and w/ kvm dynamic poll:
halt_poll_ns=10000 & halt_poll_threshold=10000 -- 29427.9 bit/s -- 107.8 %CPU
halt_poll_ns=10000 & halt_poll_threshold=20000 -- 33048.4 bit/s -- 128.1 %CPU
halt_poll_ns=10000 & halt_poll_threshold=30000 -- 35129.8 bit/s -- 129.1 %CPU
halt_poll_ns=20000 & halt_poll_threshold=10000 -- 31091.3 bit/s -- 130.3 %CPU
halt_poll_ns=20000 & halt_poll_threshold=20000 -- 33587.9 bit/s -- 128.9 %CPU
halt_poll_ns=20000 & halt_poll_threshold=30000 -- 35532.9 bit/s -- 129.1 %CPU
halt_poll_ns=30000 & halt_poll_threshold=10000 -- 35633.1 bit/s -- 199.4 %CPU
halt_poll_ns=30000 & halt_poll_threshold=20000 -- 42225.3 bit/s -- 198.7 %CPU
halt_poll_ns=30000 & halt_poll_threshold=30000 -- 42210.7 bit/s -- 200.3 %CPU
5. idle=poll
37081.7 bit/s -- 998.1 %CPU
---
V2 -> V3:
- move poll update into arch/. in v3, poll update is based on duration of the
last idle loop which is from tick_nohz_idle_enter to tick_nohz_idle_exit,
and try our best not to interfere with scheduler/idle code. (This seems
not to follow Peter's v2 comment, however we had a f2f discussion about it
in Prague.)
- enhance patch desciption.
- enhance Documentation and sysctls.
- test with IRQ_TIMINGS related code, which seems not working so far.
V1 -> V2:
- integrate the smart halt poll into paravirt code
- use idle_stamp instead of check_poll
- since it hard to get whether vcpu is the only task in pcpu, so we
don't consider it in this series.(May improve it in future)
---
Quan Xu (4):
x86/paravirt: Add pv_idle_ops to paravirt ops
KVM guest: register kvm_idle_poll for pv_idle_ops
Documentation: Add three sysctls for smart idle poll
tick: get duration of the last idle loop
Yang Zhang (2):
sched/idle: Add a generic poll before enter real idle path
KVM guest: introduce smart idle poll algorithm
Documentation/sysctl/kernel.txt | 35 ++++++++++++++++
arch/x86/include/asm/paravirt.h | 5 ++
arch/x86/include/asm/paravirt_types.h | 6 +++
arch/x86/kernel/kvm.c | 73 +++++++++++++++++++++++++++++++++
arch/x86/kernel/paravirt.c | 10 +++++
arch/x86/kernel/process.c | 7 +++
include/linux/kernel.h | 6 +++
include/linux/tick.h | 2 +
kernel/sched/idle.c | 2 +
kernel/sysctl.c | 34 +++++++++++++++
kernel/time/tick-sched.c | 11 +++++
kernel/time/tick-sched.h | 3 +
12 files changed, 194 insertions(+), 0 deletions(-)
^ permalink raw reply
* [PATCH net-next V2] vhost_net: conditionally enable tx polling
From: Jason Wang @ 2017-11-13 3:45 UTC (permalink / raw)
To: mst, jasowang, kvm, virtualization, netdev, linux-kernel
Cc: Matthew Rosato, Wei Xu
We always poll tx for socket, this is sub optimal since this will
slightly increase the waitqueue traversing time and more important,
vhost could not benefit from commit 9e641bdcfa4e ("net-tun:
restructure tun_do_read for better sleep/wakeup efficiency") even if
we've stopped rx polling during handle_rx(), tx poll were still left
in the waitqueue.
Pktgen from a remote host to VM over mlx4 on two 2.00GHz Xeon E5-2650
shows 11.7% improvements on rx PPS. (from 1.28Mpps to 1.44Mpps)
Cc: Wei Xu <wexu@redhat.com>
Cc: Matthew Rosato <mjrosato@linux.vnet.ibm.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
---
Changes from V1:
- don't try to disable tx polling during start
- poll tx on error unconditonally
---
drivers/vhost/net.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c
index 68677d9..8d626d7 100644
--- a/drivers/vhost/net.c
+++ b/drivers/vhost/net.c
@@ -471,6 +471,7 @@ static void handle_tx(struct vhost_net *net)
goto out;
vhost_disable_notify(&net->dev, vq);
+ vhost_net_disable_vq(net, vq);
hdr_size = nvq->vhost_hlen;
zcopy = nvq->ubufs;
@@ -556,6 +557,7 @@ static void handle_tx(struct vhost_net *net)
% UIO_MAXIOV;
}
vhost_discard_vq_desc(vq, 1);
+ vhost_net_enable_vq(net, vq);
break;
}
if (err != len)
--
2.7.4
^ permalink raw reply related
* [PATCH v3] virtio_balloon: include disk/file caches memory statistics
From: Tomáš Golembiovský @ 2017-11-12 12:05 UTC (permalink / raw)
To: linux-mm, virtio-dev, qemu-devel, kvm, virtualization
Cc: Rik van Riel, Michael S. Tsirkin, Gal Hammer,
Tomáš Golembiovský, Shaohua Li, Huang Ying
Add a new field VIRTIO_BALLOON_S_CACHES to virtio_balloon memory
statistics protocol. The value represents all disk/file caches.
In this case it corresponds to the sum of values
Buffers+Cached+SwapCached from /proc/meminfo.
Signed-off-by: Tomáš Golembiovský <tgolembi@redhat.com>
---
drivers/virtio/virtio_balloon.c | 4 ++++
include/uapi/linux/virtio_balloon.h | 3 ++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f0b3a0b9d42f..d2bd13bbaf9f 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -244,11 +244,13 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb)
struct sysinfo i;
unsigned int idx = 0;
long available;
+ unsigned long caches;
all_vm_events(events);
si_meminfo(&i);
available = si_mem_available();
+ caches = global_node_page_state(NR_FILE_PAGES);
#ifdef CONFIG_VM_EVENT_COUNTERS
update_stat(vb, idx++, VIRTIO_BALLOON_S_SWAP_IN,
@@ -264,6 +266,8 @@ static unsigned int update_balloon_stats(struct virtio_balloon *vb)
pages_to_bytes(i.totalram));
update_stat(vb, idx++, VIRTIO_BALLOON_S_AVAIL,
pages_to_bytes(available));
+ update_stat(vb, idx++, VIRTIO_BALLOON_S_CACHES,
+ pages_to_bytes(caches));
return idx;
}
diff --git a/include/uapi/linux/virtio_balloon.h b/include/uapi/linux/virtio_balloon.h
index 343d7ddefe04..4e8b8304b793 100644
--- a/include/uapi/linux/virtio_balloon.h
+++ b/include/uapi/linux/virtio_balloon.h
@@ -52,7 +52,8 @@ struct virtio_balloon_config {
#define VIRTIO_BALLOON_S_MEMFREE 4 /* Total amount of free memory */
#define VIRTIO_BALLOON_S_MEMTOT 5 /* Total amount of memory */
#define VIRTIO_BALLOON_S_AVAIL 6 /* Available memory as in /proc */
-#define VIRTIO_BALLOON_S_NR 7
+#define VIRTIO_BALLOON_S_CACHES 7 /* Disk caches */
+#define VIRTIO_BALLOON_S_NR 8
/*
* Memory statistics structure.
--
2.15.0
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply related
* RE: [PATCH v2 2/5] x86: add enum for hypervisors to replace x86_hyper
From: KY Srinivasan via Virtualization @ 2017-11-10 20:39 UTC (permalink / raw)
To: Dmitry Torokhov, Juergen Gross
Cc: kvm@vger.kernel.org, rkrcmar@redhat.com, pv-drivers@vmware.com,
akataria@vmware.com, virtualization@lists.linux-foundation.org,
hpa@zytor.com, tglx@linutronix.de, Stephen Hemminger,
x86@kernel.org, moltmann@vmware.com, mingo@redhat.com,
linux-graphics-maintainer@vmware.com, linux-input@vger.kernel.org,
xen-devel@lists.xenproject.org, arnd@arndb.de,
xdeguillard@vmware.com, Haiyang Zhang, pbonzini@redhat.com
In-Reply-To: <20171110182611.maikfgykek7y6xww@dtor-ws>
> -----Original Message-----
> From: Dmitry Torokhov [mailto:dmitry.torokhov@gmail.com]
> Sent: Friday, November 10, 2017 10:26 AM
> To: Juergen Gross <jgross@suse.com>
> Cc: linux-kernel@vger.kernel.org; tglx@linutronix.de; mingo@redhat.com;
> hpa@zytor.com; x86@kernel.org; KY Srinivasan <kys@microsoft.com>;
> Haiyang Zhang <haiyangz@microsoft.com>; Stephen Hemminger
> <sthemmin@microsoft.com>; akataria@vmware.com;
> pbonzini@redhat.com; rkrcmar@redhat.com; boris.ostrovsky@oracle.com;
> devel@linuxdriverproject.org; virtualization@lists.linux-foundation.org;
> kvm@vger.kernel.org; xen-devel@lists.xenproject.org; linux-graphics-
> maintainer@vmware.com; pv-drivers@vmware.com;
> xdeguillard@vmware.com; moltmann@vmware.com; arnd@arndb.de;
> gregkh@linuxfoundation.org; linux-input@vger.kernel.org
> Subject: Re: [PATCH v2 2/5] x86: add enum for hypervisors to replace
> x86_hyper
>
> On Thu, Nov 09, 2017 at 02:27:36PM +0100, Juergen Gross wrote:
> > The x86_hyper pointer is only used for checking whether a virtual
> > device is supporting the hypervisor the system is running on.
> >
> > Use an enum for that purpose instead and drop the x86_hyper pointer.
> >
> > Cc: kys@microsoft.com
> > Cc: haiyangz@microsoft.com
> > Cc: sthemmin@microsoft.com
> > Cc: akataria@vmware.com
> > Cc: pbonzini@redhat.com
> > Cc: rkrcmar@redhat.com
> > Cc: boris.ostrovsky@oracle.com
> > Cc: devel@linuxdriverproject.org
> > Cc: virtualization@lists.linux-foundation.org
> > Cc: kvm@vger.kernel.org
> > Cc: xen-devel@lists.xenproject.org
> > Cc: linux-graphics-maintainer@vmware.com
> > Cc: pv-drivers@vmware.com
> > Cc: dmitry.torokhov@gmail.com
> > Cc: xdeguillard@vmware.com
> > Cc: moltmann@vmware.com
> > Cc: arnd@arndb.de
> > Cc: gregkh@linuxfoundation.org
> > Cc: linux-input@vger.kernel.org
> >
> > Signed-off-by: Juergen Gross <jgross@suse.com>
> > ---
> > arch/x86/hyperv/hv_init.c | 2 +-
> > arch/x86/include/asm/hypervisor.h | 23 ++++++++++++++---------
> > arch/x86/kernel/cpu/hypervisor.c | 12 +++++++++---
> > arch/x86/kernel/cpu/mshyperv.c | 4 ++--
> > arch/x86/kernel/cpu/vmware.c | 4 ++--
> > arch/x86/kernel/kvm.c | 4 ++--
> > arch/x86/xen/enlighten_hvm.c | 4 ++--
> > arch/x86/xen/enlighten_pv.c | 4 ++--
> > drivers/hv/vmbus_drv.c | 2 +-
> > drivers/input/mouse/vmmouse.c | 10 ++++------
>
> Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Acked-by: K. Y. Srinivasan <kys@microsoft.com>
>
> > drivers/misc/vmw_balloon.c | 2 +-
> > 11 files changed, 40 insertions(+), 31 deletions(-)
> >
> > diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> > index a5db63f728a2..a0b86cf486e0 100644
> > --- a/arch/x86/hyperv/hv_init.c
> > +++ b/arch/x86/hyperv/hv_init.c
> > @@ -113,7 +113,7 @@ void hyperv_init(void)
> > u64 guest_id;
> > union hv_x64_msr_hypercall_contents hypercall_msr;
> >
> > - if (x86_hyper != &x86_hyper_ms_hyperv)
> > + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> > return;
> >
> > /* Allocate percpu VP index */
> > diff --git a/arch/x86/include/asm/hypervisor.h
> b/arch/x86/include/asm/hypervisor.h
> > index 0eca7239a7aa..1b0a5abcd8ae 100644
> > --- a/arch/x86/include/asm/hypervisor.h
> > +++ b/arch/x86/include/asm/hypervisor.h
> > @@ -29,6 +29,16 @@
> > /*
> > * x86 hypervisor information
> > */
> > +
> > +enum x86_hypervisor_type {
> > + X86_HYPER_NATIVE = 0,
> > + X86_HYPER_VMWARE,
> > + X86_HYPER_MS_HYPERV,
> > + X86_HYPER_XEN_PV,
> > + X86_HYPER_XEN_HVM,
> > + X86_HYPER_KVM,
> > +};
> > +
> > struct hypervisor_x86 {
> > /* Hypervisor name */
> > const char *name;
> > @@ -36,6 +46,9 @@ struct hypervisor_x86 {
> > /* Detection routine */
> > uint32_t (*detect)(void);
> >
> > + /* Hypervisor type */
> > + enum x86_hypervisor_type type;
> > +
> > /* init time callbacks */
> > struct x86_hyper_init init;
> >
> > @@ -43,15 +56,7 @@ struct hypervisor_x86 {
> > struct x86_hyper_runtime runtime;
> > };
> >
> > -extern const struct hypervisor_x86 *x86_hyper;
> > -
> > -/* Recognized hypervisors */
> > -extern const struct hypervisor_x86 x86_hyper_vmware;
> > -extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> > -extern const struct hypervisor_x86 x86_hyper_xen_pv;
> > -extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> > -extern const struct hypervisor_x86 x86_hyper_kvm;
> > -
> > +extern enum x86_hypervisor_type x86_hyper_type;
> > extern void init_hypervisor_platform(void);
> > #else
> > static inline void init_hypervisor_platform(void) { }
> > diff --git a/arch/x86/kernel/cpu/hypervisor.c
> b/arch/x86/kernel/cpu/hypervisor.c
> > index 22226c1bf092..bea8d3e24f50 100644
> > --- a/arch/x86/kernel/cpu/hypervisor.c
> > +++ b/arch/x86/kernel/cpu/hypervisor.c
> > @@ -26,6 +26,12 @@
> > #include <asm/processor.h>
> > #include <asm/hypervisor.h>
> >
> > +extern const struct hypervisor_x86 x86_hyper_vmware;
> > +extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> > +extern const struct hypervisor_x86 x86_hyper_xen_pv;
> > +extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> > +extern const struct hypervisor_x86 x86_hyper_kvm;
> > +
> > static const __initconst struct hypervisor_x86 * const hypervisors[] =
> > {
> > #ifdef CONFIG_XEN_PV
> > @@ -41,8 +47,8 @@ static const __initconst struct hypervisor_x86 * const
> hypervisors[] =
> > #endif
> > };
> >
> > -const struct hypervisor_x86 *x86_hyper;
> > -EXPORT_SYMBOL(x86_hyper);
> > +enum x86_hypervisor_type x86_hyper_type;
> > +EXPORT_SYMBOL(x86_hyper_type);
> >
> > static inline const struct hypervisor_x86 * __init
> > detect_hypervisor_vendor(void)
> > @@ -87,6 +93,6 @@ void __init init_hypervisor_platform(void)
> > copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
> > copy_array(&h->runtime, &x86_platform.hyper, sizeof(h-
> >runtime));
> >
> > - x86_hyper = h;
> > + x86_hyper_type = h->type;
> > x86_init.hyper.init_platform();
> > }
> > diff --git a/arch/x86/kernel/cpu/mshyperv.c
> b/arch/x86/kernel/cpu/mshyperv.c
> > index 6bb84d655e4b..85eb5fc180c8 100644
> > --- a/arch/x86/kernel/cpu/mshyperv.c
> > +++ b/arch/x86/kernel/cpu/mshyperv.c
> > @@ -254,9 +254,9 @@ static void __init ms_hyperv_init_platform(void)
> > #endif
> > }
> >
> > -const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> > +const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> > .name = "Microsoft Hyper-V",
> > .detect = ms_hyperv_platform,
> > + .type = X86_HYPER_MS_HYPERV,
> > .init.init_platform = ms_hyperv_init_platform,
> > };
> > -EXPORT_SYMBOL(x86_hyper_ms_hyperv);
> > diff --git a/arch/x86/kernel/cpu/vmware.c
> b/arch/x86/kernel/cpu/vmware.c
> > index 4804c1d063c8..8e005329648b 100644
> > --- a/arch/x86/kernel/cpu/vmware.c
> > +++ b/arch/x86/kernel/cpu/vmware.c
> > @@ -205,10 +205,10 @@ static bool __init
> vmware_legacy_x2apic_available(void)
> > (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
> > }
> >
> > -const __refconst struct hypervisor_x86 x86_hyper_vmware = {
> > +const __initconst struct hypervisor_x86 x86_hyper_vmware = {
> > .name = "VMware",
> > .detect = vmware_platform,
> > + .type = X86_HYPER_VMWARE,
> > .init.init_platform = vmware_platform_setup,
> > .init.x2apic_available = vmware_legacy_x2apic_available,
> > };
> > -EXPORT_SYMBOL(x86_hyper_vmware);
> > diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> > index 9dca8437c795..a94de09edbed 100644
> > --- a/arch/x86/kernel/kvm.c
> > +++ b/arch/x86/kernel/kvm.c
> > @@ -544,12 +544,12 @@ static uint32_t __init kvm_detect(void)
> > return kvm_cpuid_base();
> > }
> >
> > -const struct hypervisor_x86 x86_hyper_kvm __refconst = {
> > +const __initconst struct hypervisor_x86 x86_hyper_kvm = {
> > .name = "KVM",
> > .detect = kvm_detect,
> > + .type = X86_HYPER_KVM,
> > .init.x2apic_available = kvm_para_available,
> > };
> > -EXPORT_SYMBOL_GPL(x86_hyper_kvm);
> >
> > static __init int activate_jump_labels(void)
> > {
> > diff --git a/arch/x86/xen/enlighten_hvm.c
> b/arch/x86/xen/enlighten_hvm.c
> > index 7b1622089f96..754d5391d9fa 100644
> > --- a/arch/x86/xen/enlighten_hvm.c
> > +++ b/arch/x86/xen/enlighten_hvm.c
> > @@ -226,12 +226,12 @@ static uint32_t __init xen_platform_hvm(void)
> > return xen_cpuid_base();
> > }
> >
> > -const struct hypervisor_x86 x86_hyper_xen_hvm = {
> > +const __initconst struct hypervisor_x86 x86_hyper_xen_hvm = {
> > .name = "Xen HVM",
> > .detect = xen_platform_hvm,
> > + .type = X86_HYPER_XEN_HVM,
> > .init.init_platform = xen_hvm_guest_init,
> > .init.x2apic_available = xen_x2apic_para_available,
> > .init.init_mem_mapping = xen_hvm_init_mem_mapping,
> > .runtime.pin_vcpu = xen_pin_vcpu,
> > };
> > -EXPORT_SYMBOL(x86_hyper_xen_hvm);
> > diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
> > index 69d1a7054ddb..168efb2534c0 100644
> > --- a/arch/x86/xen/enlighten_pv.c
> > +++ b/arch/x86/xen/enlighten_pv.c
> > @@ -1460,9 +1460,9 @@ static uint32_t __init xen_platform_pv(void)
> > return 0;
> > }
> >
> > -const struct hypervisor_x86 x86_hyper_xen_pv = {
> > +const __initconst struct hypervisor_x86 x86_hyper_xen_pv = {
> > .name = "Xen PV",
> > .detect = xen_platform_pv,
> > + .type = X86_HYPER_XEN_PV,
> > .runtime.pin_vcpu = xen_pin_vcpu,
> > };
> > -EXPORT_SYMBOL(x86_hyper_xen_pv);
> > diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> > index 937801ac2fe0..2cd134dd94d2 100644
> > --- a/drivers/hv/vmbus_drv.c
> > +++ b/drivers/hv/vmbus_drv.c
> > @@ -1534,7 +1534,7 @@ static int __init hv_acpi_init(void)
> > {
> > int ret, t;
> >
> > - if (x86_hyper != &x86_hyper_ms_hyperv)
> > + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> > return -ENODEV;
> >
> > init_completion(&probe_event);
> > diff --git a/drivers/input/mouse/vmmouse.c
> b/drivers/input/mouse/vmmouse.c
> > index 0f586780ceb4..1ae5c1ef3f5b 100644
> > --- a/drivers/input/mouse/vmmouse.c
> > +++ b/drivers/input/mouse/vmmouse.c
> > @@ -316,11 +316,9 @@ static int vmmouse_enable(struct psmouse
> *psmouse)
> > /*
> > * Array of supported hypervisors.
> > */
> > -static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] =
> {
> > - &x86_hyper_vmware,
> > -#ifdef CONFIG_KVM_GUEST
> > - &x86_hyper_kvm,
> > -#endif
> > +static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
> > + X86_HYPER_VMWARE,
> > + X86_HYPER_KVM,
> > };
> >
> > /**
> > @@ -331,7 +329,7 @@ static bool vmmouse_check_hypervisor(void)
> > int i;
> >
> > for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
> > - if (vmmouse_supported_hypervisors[i] == x86_hyper)
> > + if (vmmouse_supported_hypervisors[i] == x86_hyper_type)
> > return true;
> >
> > return false;
> > diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
> > index 1e688bfec567..9047c0a529b2 100644
> > --- a/drivers/misc/vmw_balloon.c
> > +++ b/drivers/misc/vmw_balloon.c
> > @@ -1271,7 +1271,7 @@ static int __init vmballoon_init(void)
> > * Check if we are running on VMware's hypervisor and bail out
> > * if we are not.
> > */
> > - if (x86_hyper != &x86_hyper_vmware)
> > + if (x86_hyper_type != X86_HYPER_VMWARE)
> > return -ENODEV;
> >
> > for (is_2m_pages = 0; is_2m_pages <
> VMW_BALLOON_NUM_PAGE_SIZES;
> > --
> > 2.12.3
> >
>
> --
> Dmitry
^ permalink raw reply
* Re: [PATCH v2 2/5] x86: add enum for hypervisors to replace x86_hyper
From: Dmitry Torokhov @ 2017-11-10 18:26 UTC (permalink / raw)
To: Juergen Gross
Cc: kvm, rkrcmar, pv-drivers, akataria, virtualization, hpa, tglx,
sthemmin, x86, moltmann, mingo, linux-graphics-maintainer,
linux-input, xen-devel, arnd, xdeguillard, haiyangz, pbonzini,
boris.ostrovsky, gregkh, linux-kernel, devel
In-Reply-To: <20171109132739.23465-3-jgross@suse.com>
On Thu, Nov 09, 2017 at 02:27:36PM +0100, Juergen Gross wrote:
> The x86_hyper pointer is only used for checking whether a virtual
> device is supporting the hypervisor the system is running on.
>
> Use an enum for that purpose instead and drop the x86_hyper pointer.
>
> Cc: kys@microsoft.com
> Cc: haiyangz@microsoft.com
> Cc: sthemmin@microsoft.com
> Cc: akataria@vmware.com
> Cc: pbonzini@redhat.com
> Cc: rkrcmar@redhat.com
> Cc: boris.ostrovsky@oracle.com
> Cc: devel@linuxdriverproject.org
> Cc: virtualization@lists.linux-foundation.org
> Cc: kvm@vger.kernel.org
> Cc: xen-devel@lists.xenproject.org
> Cc: linux-graphics-maintainer@vmware.com
> Cc: pv-drivers@vmware.com
> Cc: dmitry.torokhov@gmail.com
> Cc: xdeguillard@vmware.com
> Cc: moltmann@vmware.com
> Cc: arnd@arndb.de
> Cc: gregkh@linuxfoundation.org
> Cc: linux-input@vger.kernel.org
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> arch/x86/hyperv/hv_init.c | 2 +-
> arch/x86/include/asm/hypervisor.h | 23 ++++++++++++++---------
> arch/x86/kernel/cpu/hypervisor.c | 12 +++++++++---
> arch/x86/kernel/cpu/mshyperv.c | 4 ++--
> arch/x86/kernel/cpu/vmware.c | 4 ++--
> arch/x86/kernel/kvm.c | 4 ++--
> arch/x86/xen/enlighten_hvm.c | 4 ++--
> arch/x86/xen/enlighten_pv.c | 4 ++--
> drivers/hv/vmbus_drv.c | 2 +-
> drivers/input/mouse/vmmouse.c | 10 ++++------
Acked-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
> drivers/misc/vmw_balloon.c | 2 +-
> 11 files changed, 40 insertions(+), 31 deletions(-)
>
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index a5db63f728a2..a0b86cf486e0 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -113,7 +113,7 @@ void hyperv_init(void)
> u64 guest_id;
> union hv_x64_msr_hypercall_contents hypercall_msr;
>
> - if (x86_hyper != &x86_hyper_ms_hyperv)
> + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> return;
>
> /* Allocate percpu VP index */
> diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
> index 0eca7239a7aa..1b0a5abcd8ae 100644
> --- a/arch/x86/include/asm/hypervisor.h
> +++ b/arch/x86/include/asm/hypervisor.h
> @@ -29,6 +29,16 @@
> /*
> * x86 hypervisor information
> */
> +
> +enum x86_hypervisor_type {
> + X86_HYPER_NATIVE = 0,
> + X86_HYPER_VMWARE,
> + X86_HYPER_MS_HYPERV,
> + X86_HYPER_XEN_PV,
> + X86_HYPER_XEN_HVM,
> + X86_HYPER_KVM,
> +};
> +
> struct hypervisor_x86 {
> /* Hypervisor name */
> const char *name;
> @@ -36,6 +46,9 @@ struct hypervisor_x86 {
> /* Detection routine */
> uint32_t (*detect)(void);
>
> + /* Hypervisor type */
> + enum x86_hypervisor_type type;
> +
> /* init time callbacks */
> struct x86_hyper_init init;
>
> @@ -43,15 +56,7 @@ struct hypervisor_x86 {
> struct x86_hyper_runtime runtime;
> };
>
> -extern const struct hypervisor_x86 *x86_hyper;
> -
> -/* Recognized hypervisors */
> -extern const struct hypervisor_x86 x86_hyper_vmware;
> -extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> -extern const struct hypervisor_x86 x86_hyper_xen_pv;
> -extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> -extern const struct hypervisor_x86 x86_hyper_kvm;
> -
> +extern enum x86_hypervisor_type x86_hyper_type;
> extern void init_hypervisor_platform(void);
> #else
> static inline void init_hypervisor_platform(void) { }
> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
> index 22226c1bf092..bea8d3e24f50 100644
> --- a/arch/x86/kernel/cpu/hypervisor.c
> +++ b/arch/x86/kernel/cpu/hypervisor.c
> @@ -26,6 +26,12 @@
> #include <asm/processor.h>
> #include <asm/hypervisor.h>
>
> +extern const struct hypervisor_x86 x86_hyper_vmware;
> +extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> +extern const struct hypervisor_x86 x86_hyper_xen_pv;
> +extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> +extern const struct hypervisor_x86 x86_hyper_kvm;
> +
> static const __initconst struct hypervisor_x86 * const hypervisors[] =
> {
> #ifdef CONFIG_XEN_PV
> @@ -41,8 +47,8 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
> #endif
> };
>
> -const struct hypervisor_x86 *x86_hyper;
> -EXPORT_SYMBOL(x86_hyper);
> +enum x86_hypervisor_type x86_hyper_type;
> +EXPORT_SYMBOL(x86_hyper_type);
>
> static inline const struct hypervisor_x86 * __init
> detect_hypervisor_vendor(void)
> @@ -87,6 +93,6 @@ void __init init_hypervisor_platform(void)
> copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
> copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
>
> - x86_hyper = h;
> + x86_hyper_type = h->type;
> x86_init.hyper.init_platform();
> }
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 6bb84d655e4b..85eb5fc180c8 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -254,9 +254,9 @@ static void __init ms_hyperv_init_platform(void)
> #endif
> }
>
> -const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> +const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> .name = "Microsoft Hyper-V",
> .detect = ms_hyperv_platform,
> + .type = X86_HYPER_MS_HYPERV,
> .init.init_platform = ms_hyperv_init_platform,
> };
> -EXPORT_SYMBOL(x86_hyper_ms_hyperv);
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 4804c1d063c8..8e005329648b 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -205,10 +205,10 @@ static bool __init vmware_legacy_x2apic_available(void)
> (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
> }
>
> -const __refconst struct hypervisor_x86 x86_hyper_vmware = {
> +const __initconst struct hypervisor_x86 x86_hyper_vmware = {
> .name = "VMware",
> .detect = vmware_platform,
> + .type = X86_HYPER_VMWARE,
> .init.init_platform = vmware_platform_setup,
> .init.x2apic_available = vmware_legacy_x2apic_available,
> };
> -EXPORT_SYMBOL(x86_hyper_vmware);
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index 9dca8437c795..a94de09edbed 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -544,12 +544,12 @@ static uint32_t __init kvm_detect(void)
> return kvm_cpuid_base();
> }
>
> -const struct hypervisor_x86 x86_hyper_kvm __refconst = {
> +const __initconst struct hypervisor_x86 x86_hyper_kvm = {
> .name = "KVM",
> .detect = kvm_detect,
> + .type = X86_HYPER_KVM,
> .init.x2apic_available = kvm_para_available,
> };
> -EXPORT_SYMBOL_GPL(x86_hyper_kvm);
>
> static __init int activate_jump_labels(void)
> {
> diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
> index 7b1622089f96..754d5391d9fa 100644
> --- a/arch/x86/xen/enlighten_hvm.c
> +++ b/arch/x86/xen/enlighten_hvm.c
> @@ -226,12 +226,12 @@ static uint32_t __init xen_platform_hvm(void)
> return xen_cpuid_base();
> }
>
> -const struct hypervisor_x86 x86_hyper_xen_hvm = {
> +const __initconst struct hypervisor_x86 x86_hyper_xen_hvm = {
> .name = "Xen HVM",
> .detect = xen_platform_hvm,
> + .type = X86_HYPER_XEN_HVM,
> .init.init_platform = xen_hvm_guest_init,
> .init.x2apic_available = xen_x2apic_para_available,
> .init.init_mem_mapping = xen_hvm_init_mem_mapping,
> .runtime.pin_vcpu = xen_pin_vcpu,
> };
> -EXPORT_SYMBOL(x86_hyper_xen_hvm);
> diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
> index 69d1a7054ddb..168efb2534c0 100644
> --- a/arch/x86/xen/enlighten_pv.c
> +++ b/arch/x86/xen/enlighten_pv.c
> @@ -1460,9 +1460,9 @@ static uint32_t __init xen_platform_pv(void)
> return 0;
> }
>
> -const struct hypervisor_x86 x86_hyper_xen_pv = {
> +const __initconst struct hypervisor_x86 x86_hyper_xen_pv = {
> .name = "Xen PV",
> .detect = xen_platform_pv,
> + .type = X86_HYPER_XEN_PV,
> .runtime.pin_vcpu = xen_pin_vcpu,
> };
> -EXPORT_SYMBOL(x86_hyper_xen_pv);
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 937801ac2fe0..2cd134dd94d2 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -1534,7 +1534,7 @@ static int __init hv_acpi_init(void)
> {
> int ret, t;
>
> - if (x86_hyper != &x86_hyper_ms_hyperv)
> + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> return -ENODEV;
>
> init_completion(&probe_event);
> diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
> index 0f586780ceb4..1ae5c1ef3f5b 100644
> --- a/drivers/input/mouse/vmmouse.c
> +++ b/drivers/input/mouse/vmmouse.c
> @@ -316,11 +316,9 @@ static int vmmouse_enable(struct psmouse *psmouse)
> /*
> * Array of supported hypervisors.
> */
> -static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = {
> - &x86_hyper_vmware,
> -#ifdef CONFIG_KVM_GUEST
> - &x86_hyper_kvm,
> -#endif
> +static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
> + X86_HYPER_VMWARE,
> + X86_HYPER_KVM,
> };
>
> /**
> @@ -331,7 +329,7 @@ static bool vmmouse_check_hypervisor(void)
> int i;
>
> for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
> - if (vmmouse_supported_hypervisors[i] == x86_hyper)
> + if (vmmouse_supported_hypervisors[i] == x86_hyper_type)
> return true;
>
> return false;
> diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
> index 1e688bfec567..9047c0a529b2 100644
> --- a/drivers/misc/vmw_balloon.c
> +++ b/drivers/misc/vmw_balloon.c
> @@ -1271,7 +1271,7 @@ static int __init vmballoon_init(void)
> * Check if we are running on VMware's hypervisor and bail out
> * if we are not.
> */
> - if (x86_hyper != &x86_hyper_vmware)
> + if (x86_hyper_type != X86_HYPER_VMWARE)
> return -ENODEV;
>
> for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
> --
> 2.12.3
>
--
Dmitry
^ permalink raw reply
* Re: [PATCH] MAINTAINERS: add virtio-ccw.h to virtio/s390 section
From: Heiko Carstens @ 2017-11-10 18:15 UTC (permalink / raw)
To: Cornelia Huck; +Cc: schwidefsky, linux-s390, kvm, virtualization
In-Reply-To: <20171110145611.15306-1-cohuck@redhat.com>
On Fri, Nov 10, 2017 at 03:56:11PM +0100, Cornelia Huck wrote:
> The file arch/s390/include/uapi/asm/virtio-ccw.h belongs to the
> s390 virtio drivers as well.
>
> Signed-off-by: Cornelia Huck <cohuck@redhat.com>
> ---
>
> Martin, Heiko: It's probably best to take this through your tree.
>
> ---
> MAINTAINERS | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 6671f375f7fc..48c6f1179b9b 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -14312,6 +14312,7 @@ L: virtualization@lists.linux-foundation.org
> L: kvm@vger.kernel.org
> S: Supported
> F: drivers/s390/virtio/
> +F: arch/s390/include/uapi/asm/virtio-ccw.h
Applied, thanks.
^ permalink raw reply
* [PATCH] MAINTAINERS: add virtio-ccw.h to virtio/s390 section
From: Cornelia Huck @ 2017-11-10 14:56 UTC (permalink / raw)
To: schwidefsky, heiko.carstens, pasic
Cc: linux-s390, Cornelia Huck, kvm, virtualization
The file arch/s390/include/uapi/asm/virtio-ccw.h belongs to the
s390 virtio drivers as well.
Signed-off-by: Cornelia Huck <cohuck@redhat.com>
---
Martin, Heiko: It's probably best to take this through your tree.
---
MAINTAINERS | 1 +
1 file changed, 1 insertion(+)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6671f375f7fc..48c6f1179b9b 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -14312,6 +14312,7 @@ L: virtualization@lists.linux-foundation.org
L: kvm@vger.kernel.org
S: Supported
F: drivers/s390/virtio/
+F: arch/s390/include/uapi/asm/virtio-ccw.h
VIRTIO GPU DRIVER
M: David Airlie <airlied@linux.ie>
--
2.13.6
^ permalink raw reply related
* Re: [PATCH v2 2/5] x86: add enum for hypervisors to replace x86_hyper
From: Xavier Deguillard @ 2017-11-09 17:57 UTC (permalink / raw)
To: Juergen Gross
Cc: kvm, rkrcmar, pv-drivers, virtualization, hpa, tglx, sthemmin,
x86, akataria, mingo, linux-graphics-maintainer, linux-input,
xen-devel, arnd, haiyangz, pbonzini, boris.ostrovsky, gregkh,
dmitry.torokhov, linux-kernel, devel
In-Reply-To: <20171109132739.23465-3-jgross@suse.com>
Hello Juergen,
The changes to vmw_balloon.c looks good.
Acked-by: Xavier Deguillard <xdeguillard@vmware.com>
Xavier
On Thu, Nov 09, 2017 at 02:27:36PM +0100, Juergen Gross wrote:
> The x86_hyper pointer is only used for checking whether a virtual
> device is supporting the hypervisor the system is running on.
>
> Use an enum for that purpose instead and drop the x86_hyper pointer.
>
> Cc: kys@microsoft.com
> Cc: haiyangz@microsoft.com
> Cc: sthemmin@microsoft.com
> Cc: akataria@vmware.com
> Cc: pbonzini@redhat.com
> Cc: rkrcmar@redhat.com
> Cc: boris.ostrovsky@oracle.com
> Cc: devel@linuxdriverproject.org
> Cc: virtualization@lists.linux-foundation.org
> Cc: kvm@vger.kernel.org
> Cc: xen-devel@lists.xenproject.org
> Cc: linux-graphics-maintainer@vmware.com
> Cc: pv-drivers@vmware.com
> Cc: dmitry.torokhov@gmail.com
> Cc: xdeguillard@vmware.com
> Cc: moltmann@vmware.com
> Cc: arnd@arndb.de
> Cc: gregkh@linuxfoundation.org
> Cc: linux-input@vger.kernel.org
>
> Signed-off-by: Juergen Gross <jgross@suse.com>
> ---
> arch/x86/hyperv/hv_init.c | 2 +-
> arch/x86/include/asm/hypervisor.h | 23 ++++++++++++++---------
> arch/x86/kernel/cpu/hypervisor.c | 12 +++++++++---
> arch/x86/kernel/cpu/mshyperv.c | 4 ++--
> arch/x86/kernel/cpu/vmware.c | 4 ++--
> arch/x86/kernel/kvm.c | 4 ++--
> arch/x86/xen/enlighten_hvm.c | 4 ++--
> arch/x86/xen/enlighten_pv.c | 4 ++--
> drivers/hv/vmbus_drv.c | 2 +-
> drivers/input/mouse/vmmouse.c | 10 ++++------
> drivers/misc/vmw_balloon.c | 2 +-
> 11 files changed, 40 insertions(+), 31 deletions(-)
>
> diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
> index a5db63f728a2..a0b86cf486e0 100644
> --- a/arch/x86/hyperv/hv_init.c
> +++ b/arch/x86/hyperv/hv_init.c
> @@ -113,7 +113,7 @@ void hyperv_init(void)
> u64 guest_id;
> union hv_x64_msr_hypercall_contents hypercall_msr;
>
> - if (x86_hyper != &x86_hyper_ms_hyperv)
> + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> return;
>
> /* Allocate percpu VP index */
> diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
> index 0eca7239a7aa..1b0a5abcd8ae 100644
> --- a/arch/x86/include/asm/hypervisor.h
> +++ b/arch/x86/include/asm/hypervisor.h
> @@ -29,6 +29,16 @@
> /*
> * x86 hypervisor information
> */
> +
> +enum x86_hypervisor_type {
> + X86_HYPER_NATIVE = 0,
> + X86_HYPER_VMWARE,
> + X86_HYPER_MS_HYPERV,
> + X86_HYPER_XEN_PV,
> + X86_HYPER_XEN_HVM,
> + X86_HYPER_KVM,
> +};
> +
> struct hypervisor_x86 {
> /* Hypervisor name */
> const char *name;
> @@ -36,6 +46,9 @@ struct hypervisor_x86 {
> /* Detection routine */
> uint32_t (*detect)(void);
>
> + /* Hypervisor type */
> + enum x86_hypervisor_type type;
> +
> /* init time callbacks */
> struct x86_hyper_init init;
>
> @@ -43,15 +56,7 @@ struct hypervisor_x86 {
> struct x86_hyper_runtime runtime;
> };
>
> -extern const struct hypervisor_x86 *x86_hyper;
> -
> -/* Recognized hypervisors */
> -extern const struct hypervisor_x86 x86_hyper_vmware;
> -extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> -extern const struct hypervisor_x86 x86_hyper_xen_pv;
> -extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> -extern const struct hypervisor_x86 x86_hyper_kvm;
> -
> +extern enum x86_hypervisor_type x86_hyper_type;
> extern void init_hypervisor_platform(void);
> #else
> static inline void init_hypervisor_platform(void) { }
> diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
> index 22226c1bf092..bea8d3e24f50 100644
> --- a/arch/x86/kernel/cpu/hypervisor.c
> +++ b/arch/x86/kernel/cpu/hypervisor.c
> @@ -26,6 +26,12 @@
> #include <asm/processor.h>
> #include <asm/hypervisor.h>
>
> +extern const struct hypervisor_x86 x86_hyper_vmware;
> +extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
> +extern const struct hypervisor_x86 x86_hyper_xen_pv;
> +extern const struct hypervisor_x86 x86_hyper_xen_hvm;
> +extern const struct hypervisor_x86 x86_hyper_kvm;
> +
> static const __initconst struct hypervisor_x86 * const hypervisors[] =
> {
> #ifdef CONFIG_XEN_PV
> @@ -41,8 +47,8 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
> #endif
> };
>
> -const struct hypervisor_x86 *x86_hyper;
> -EXPORT_SYMBOL(x86_hyper);
> +enum x86_hypervisor_type x86_hyper_type;
> +EXPORT_SYMBOL(x86_hyper_type);
>
> static inline const struct hypervisor_x86 * __init
> detect_hypervisor_vendor(void)
> @@ -87,6 +93,6 @@ void __init init_hypervisor_platform(void)
> copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
> copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
>
> - x86_hyper = h;
> + x86_hyper_type = h->type;
> x86_init.hyper.init_platform();
> }
> diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
> index 6bb84d655e4b..85eb5fc180c8 100644
> --- a/arch/x86/kernel/cpu/mshyperv.c
> +++ b/arch/x86/kernel/cpu/mshyperv.c
> @@ -254,9 +254,9 @@ static void __init ms_hyperv_init_platform(void)
> #endif
> }
>
> -const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> +const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
> .name = "Microsoft Hyper-V",
> .detect = ms_hyperv_platform,
> + .type = X86_HYPER_MS_HYPERV,
> .init.init_platform = ms_hyperv_init_platform,
> };
> -EXPORT_SYMBOL(x86_hyper_ms_hyperv);
> diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
> index 4804c1d063c8..8e005329648b 100644
> --- a/arch/x86/kernel/cpu/vmware.c
> +++ b/arch/x86/kernel/cpu/vmware.c
> @@ -205,10 +205,10 @@ static bool __init vmware_legacy_x2apic_available(void)
> (eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
> }
>
> -const __refconst struct hypervisor_x86 x86_hyper_vmware = {
> +const __initconst struct hypervisor_x86 x86_hyper_vmware = {
> .name = "VMware",
> .detect = vmware_platform,
> + .type = X86_HYPER_VMWARE,
> .init.init_platform = vmware_platform_setup,
> .init.x2apic_available = vmware_legacy_x2apic_available,
> };
> -EXPORT_SYMBOL(x86_hyper_vmware);
> diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
> index 9dca8437c795..a94de09edbed 100644
> --- a/arch/x86/kernel/kvm.c
> +++ b/arch/x86/kernel/kvm.c
> @@ -544,12 +544,12 @@ static uint32_t __init kvm_detect(void)
> return kvm_cpuid_base();
> }
>
> -const struct hypervisor_x86 x86_hyper_kvm __refconst = {
> +const __initconst struct hypervisor_x86 x86_hyper_kvm = {
> .name = "KVM",
> .detect = kvm_detect,
> + .type = X86_HYPER_KVM,
> .init.x2apic_available = kvm_para_available,
> };
> -EXPORT_SYMBOL_GPL(x86_hyper_kvm);
>
> static __init int activate_jump_labels(void)
> {
> diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
> index 7b1622089f96..754d5391d9fa 100644
> --- a/arch/x86/xen/enlighten_hvm.c
> +++ b/arch/x86/xen/enlighten_hvm.c
> @@ -226,12 +226,12 @@ static uint32_t __init xen_platform_hvm(void)
> return xen_cpuid_base();
> }
>
> -const struct hypervisor_x86 x86_hyper_xen_hvm = {
> +const __initconst struct hypervisor_x86 x86_hyper_xen_hvm = {
> .name = "Xen HVM",
> .detect = xen_platform_hvm,
> + .type = X86_HYPER_XEN_HVM,
> .init.init_platform = xen_hvm_guest_init,
> .init.x2apic_available = xen_x2apic_para_available,
> .init.init_mem_mapping = xen_hvm_init_mem_mapping,
> .runtime.pin_vcpu = xen_pin_vcpu,
> };
> -EXPORT_SYMBOL(x86_hyper_xen_hvm);
> diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
> index 69d1a7054ddb..168efb2534c0 100644
> --- a/arch/x86/xen/enlighten_pv.c
> +++ b/arch/x86/xen/enlighten_pv.c
> @@ -1460,9 +1460,9 @@ static uint32_t __init xen_platform_pv(void)
> return 0;
> }
>
> -const struct hypervisor_x86 x86_hyper_xen_pv = {
> +const __initconst struct hypervisor_x86 x86_hyper_xen_pv = {
> .name = "Xen PV",
> .detect = xen_platform_pv,
> + .type = X86_HYPER_XEN_PV,
> .runtime.pin_vcpu = xen_pin_vcpu,
> };
> -EXPORT_SYMBOL(x86_hyper_xen_pv);
> diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
> index 937801ac2fe0..2cd134dd94d2 100644
> --- a/drivers/hv/vmbus_drv.c
> +++ b/drivers/hv/vmbus_drv.c
> @@ -1534,7 +1534,7 @@ static int __init hv_acpi_init(void)
> {
> int ret, t;
>
> - if (x86_hyper != &x86_hyper_ms_hyperv)
> + if (x86_hyper_type != X86_HYPER_MS_HYPERV)
> return -ENODEV;
>
> init_completion(&probe_event);
> diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
> index 0f586780ceb4..1ae5c1ef3f5b 100644
> --- a/drivers/input/mouse/vmmouse.c
> +++ b/drivers/input/mouse/vmmouse.c
> @@ -316,11 +316,9 @@ static int vmmouse_enable(struct psmouse *psmouse)
> /*
> * Array of supported hypervisors.
> */
> -static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = {
> - &x86_hyper_vmware,
> -#ifdef CONFIG_KVM_GUEST
> - &x86_hyper_kvm,
> -#endif
> +static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
> + X86_HYPER_VMWARE,
> + X86_HYPER_KVM,
> };
>
> /**
> @@ -331,7 +329,7 @@ static bool vmmouse_check_hypervisor(void)
> int i;
>
> for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
> - if (vmmouse_supported_hypervisors[i] == x86_hyper)
> + if (vmmouse_supported_hypervisors[i] == x86_hyper_type)
> return true;
>
> return false;
> diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
> index 1e688bfec567..9047c0a529b2 100644
> --- a/drivers/misc/vmw_balloon.c
> +++ b/drivers/misc/vmw_balloon.c
> @@ -1271,7 +1271,7 @@ static int __init vmballoon_init(void)
> * Check if we are running on VMware's hypervisor and bail out
> * if we are not.
> */
> - if (x86_hyper != &x86_hyper_vmware)
> + if (x86_hyper_type != X86_HYPER_VMWARE)
> return -ENODEV;
>
> for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
> --
> 2.12.3
>
^ permalink raw reply
* [PATCH] vhost/vsock: fix uninitialized vhost_vsock->guest_cid
From: Stefan Hajnoczi @ 2017-11-09 13:29 UTC (permalink / raw)
To: kvm; +Cc: Gao feng, Peng Tao, virtualization, Stefan Hajnoczi,
Michael S. Tsirkin
The vhost_vsock->guest_cid field is uninitialized when /dev/vhost-vsock
is opened until the VHOST_VSOCK_SET_GUEST_CID ioctl is called.
kvmalloc(..., GFP_KERNEL | __GFP_RETRY_MAYFAIL) does not zero memory.
All other vhost_vsock fields are initialized explicitly so just
initialize this field too.
Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
drivers/vhost/vsock.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/vhost/vsock.c b/drivers/vhost/vsock.c
index c9de9c41aa97..5a5e981bd8e4 100644
--- a/drivers/vhost/vsock.c
+++ b/drivers/vhost/vsock.c
@@ -518,6 +518,8 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
goto out;
}
+ vsock->guest_cid = 0; /* no CID assigned yet */
+
atomic_set(&vsock->queued_replies, 0);
vqs[VSOCK_VQ_TX] = &vsock->vqs[VSOCK_VQ_TX];
--
2.13.6
^ permalink raw reply related
* [PATCH v2 2/5] x86: add enum for hypervisors to replace x86_hyper
From: Juergen Gross @ 2017-11-09 13:27 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, rkrcmar, pv-drivers, akataria, virtualization, hpa, tglx,
sthemmin, x86, moltmann, mingo, linux-graphics-maintainer,
linux-input, xen-devel, arnd, xdeguillard, haiyangz, pbonzini,
boris.ostrovsky, Juergen Gross, gregkh, dmitry.torokhov, devel
In-Reply-To: <20171109132739.23465-1-jgross@suse.com>
The x86_hyper pointer is only used for checking whether a virtual
device is supporting the hypervisor the system is running on.
Use an enum for that purpose instead and drop the x86_hyper pointer.
Cc: kys@microsoft.com
Cc: haiyangz@microsoft.com
Cc: sthemmin@microsoft.com
Cc: akataria@vmware.com
Cc: pbonzini@redhat.com
Cc: rkrcmar@redhat.com
Cc: boris.ostrovsky@oracle.com
Cc: devel@linuxdriverproject.org
Cc: virtualization@lists.linux-foundation.org
Cc: kvm@vger.kernel.org
Cc: xen-devel@lists.xenproject.org
Cc: linux-graphics-maintainer@vmware.com
Cc: pv-drivers@vmware.com
Cc: dmitry.torokhov@gmail.com
Cc: xdeguillard@vmware.com
Cc: moltmann@vmware.com
Cc: arnd@arndb.de
Cc: gregkh@linuxfoundation.org
Cc: linux-input@vger.kernel.org
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/hyperv/hv_init.c | 2 +-
arch/x86/include/asm/hypervisor.h | 23 ++++++++++++++---------
arch/x86/kernel/cpu/hypervisor.c | 12 +++++++++---
arch/x86/kernel/cpu/mshyperv.c | 4 ++--
arch/x86/kernel/cpu/vmware.c | 4 ++--
arch/x86/kernel/kvm.c | 4 ++--
arch/x86/xen/enlighten_hvm.c | 4 ++--
arch/x86/xen/enlighten_pv.c | 4 ++--
drivers/hv/vmbus_drv.c | 2 +-
drivers/input/mouse/vmmouse.c | 10 ++++------
drivers/misc/vmw_balloon.c | 2 +-
11 files changed, 40 insertions(+), 31 deletions(-)
diff --git a/arch/x86/hyperv/hv_init.c b/arch/x86/hyperv/hv_init.c
index a5db63f728a2..a0b86cf486e0 100644
--- a/arch/x86/hyperv/hv_init.c
+++ b/arch/x86/hyperv/hv_init.c
@@ -113,7 +113,7 @@ void hyperv_init(void)
u64 guest_id;
union hv_x64_msr_hypercall_contents hypercall_msr;
- if (x86_hyper != &x86_hyper_ms_hyperv)
+ if (x86_hyper_type != X86_HYPER_MS_HYPERV)
return;
/* Allocate percpu VP index */
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 0eca7239a7aa..1b0a5abcd8ae 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -29,6 +29,16 @@
/*
* x86 hypervisor information
*/
+
+enum x86_hypervisor_type {
+ X86_HYPER_NATIVE = 0,
+ X86_HYPER_VMWARE,
+ X86_HYPER_MS_HYPERV,
+ X86_HYPER_XEN_PV,
+ X86_HYPER_XEN_HVM,
+ X86_HYPER_KVM,
+};
+
struct hypervisor_x86 {
/* Hypervisor name */
const char *name;
@@ -36,6 +46,9 @@ struct hypervisor_x86 {
/* Detection routine */
uint32_t (*detect)(void);
+ /* Hypervisor type */
+ enum x86_hypervisor_type type;
+
/* init time callbacks */
struct x86_hyper_init init;
@@ -43,15 +56,7 @@ struct hypervisor_x86 {
struct x86_hyper_runtime runtime;
};
-extern const struct hypervisor_x86 *x86_hyper;
-
-/* Recognized hypervisors */
-extern const struct hypervisor_x86 x86_hyper_vmware;
-extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
-extern const struct hypervisor_x86 x86_hyper_xen_pv;
-extern const struct hypervisor_x86 x86_hyper_xen_hvm;
-extern const struct hypervisor_x86 x86_hyper_kvm;
-
+extern enum x86_hypervisor_type x86_hyper_type;
extern void init_hypervisor_platform(void);
#else
static inline void init_hypervisor_platform(void) { }
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 22226c1bf092..bea8d3e24f50 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -26,6 +26,12 @@
#include <asm/processor.h>
#include <asm/hypervisor.h>
+extern const struct hypervisor_x86 x86_hyper_vmware;
+extern const struct hypervisor_x86 x86_hyper_ms_hyperv;
+extern const struct hypervisor_x86 x86_hyper_xen_pv;
+extern const struct hypervisor_x86 x86_hyper_xen_hvm;
+extern const struct hypervisor_x86 x86_hyper_kvm;
+
static const __initconst struct hypervisor_x86 * const hypervisors[] =
{
#ifdef CONFIG_XEN_PV
@@ -41,8 +47,8 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
#endif
};
-const struct hypervisor_x86 *x86_hyper;
-EXPORT_SYMBOL(x86_hyper);
+enum x86_hypervisor_type x86_hyper_type;
+EXPORT_SYMBOL(x86_hyper_type);
static inline const struct hypervisor_x86 * __init
detect_hypervisor_vendor(void)
@@ -87,6 +93,6 @@ void __init init_hypervisor_platform(void)
copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
- x86_hyper = h;
+ x86_hyper_type = h->type;
x86_init.hyper.init_platform();
}
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 6bb84d655e4b..85eb5fc180c8 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -254,9 +254,9 @@ static void __init ms_hyperv_init_platform(void)
#endif
}
-const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
+const __initconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
.name = "Microsoft Hyper-V",
.detect = ms_hyperv_platform,
+ .type = X86_HYPER_MS_HYPERV,
.init.init_platform = ms_hyperv_init_platform,
};
-EXPORT_SYMBOL(x86_hyper_ms_hyperv);
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 4804c1d063c8..8e005329648b 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -205,10 +205,10 @@ static bool __init vmware_legacy_x2apic_available(void)
(eax & (1 << VMWARE_PORT_CMD_LEGACY_X2APIC)) != 0;
}
-const __refconst struct hypervisor_x86 x86_hyper_vmware = {
+const __initconst struct hypervisor_x86 x86_hyper_vmware = {
.name = "VMware",
.detect = vmware_platform,
+ .type = X86_HYPER_VMWARE,
.init.init_platform = vmware_platform_setup,
.init.x2apic_available = vmware_legacy_x2apic_available,
};
-EXPORT_SYMBOL(x86_hyper_vmware);
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 9dca8437c795..a94de09edbed 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -544,12 +544,12 @@ static uint32_t __init kvm_detect(void)
return kvm_cpuid_base();
}
-const struct hypervisor_x86 x86_hyper_kvm __refconst = {
+const __initconst struct hypervisor_x86 x86_hyper_kvm = {
.name = "KVM",
.detect = kvm_detect,
+ .type = X86_HYPER_KVM,
.init.x2apic_available = kvm_para_available,
};
-EXPORT_SYMBOL_GPL(x86_hyper_kvm);
static __init int activate_jump_labels(void)
{
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 7b1622089f96..754d5391d9fa 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -226,12 +226,12 @@ static uint32_t __init xen_platform_hvm(void)
return xen_cpuid_base();
}
-const struct hypervisor_x86 x86_hyper_xen_hvm = {
+const __initconst struct hypervisor_x86 x86_hyper_xen_hvm = {
.name = "Xen HVM",
.detect = xen_platform_hvm,
+ .type = X86_HYPER_XEN_HVM,
.init.init_platform = xen_hvm_guest_init,
.init.x2apic_available = xen_x2apic_para_available,
.init.init_mem_mapping = xen_hvm_init_mem_mapping,
.runtime.pin_vcpu = xen_pin_vcpu,
};
-EXPORT_SYMBOL(x86_hyper_xen_hvm);
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index 69d1a7054ddb..168efb2534c0 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1460,9 +1460,9 @@ static uint32_t __init xen_platform_pv(void)
return 0;
}
-const struct hypervisor_x86 x86_hyper_xen_pv = {
+const __initconst struct hypervisor_x86 x86_hyper_xen_pv = {
.name = "Xen PV",
.detect = xen_platform_pv,
+ .type = X86_HYPER_XEN_PV,
.runtime.pin_vcpu = xen_pin_vcpu,
};
-EXPORT_SYMBOL(x86_hyper_xen_pv);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 937801ac2fe0..2cd134dd94d2 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -1534,7 +1534,7 @@ static int __init hv_acpi_init(void)
{
int ret, t;
- if (x86_hyper != &x86_hyper_ms_hyperv)
+ if (x86_hyper_type != X86_HYPER_MS_HYPERV)
return -ENODEV;
init_completion(&probe_event);
diff --git a/drivers/input/mouse/vmmouse.c b/drivers/input/mouse/vmmouse.c
index 0f586780ceb4..1ae5c1ef3f5b 100644
--- a/drivers/input/mouse/vmmouse.c
+++ b/drivers/input/mouse/vmmouse.c
@@ -316,11 +316,9 @@ static int vmmouse_enable(struct psmouse *psmouse)
/*
* Array of supported hypervisors.
*/
-static const struct hypervisor_x86 *vmmouse_supported_hypervisors[] = {
- &x86_hyper_vmware,
-#ifdef CONFIG_KVM_GUEST
- &x86_hyper_kvm,
-#endif
+static enum x86_hypervisor_type vmmouse_supported_hypervisors[] = {
+ X86_HYPER_VMWARE,
+ X86_HYPER_KVM,
};
/**
@@ -331,7 +329,7 @@ static bool vmmouse_check_hypervisor(void)
int i;
for (i = 0; i < ARRAY_SIZE(vmmouse_supported_hypervisors); i++)
- if (vmmouse_supported_hypervisors[i] == x86_hyper)
+ if (vmmouse_supported_hypervisors[i] == x86_hyper_type)
return true;
return false;
diff --git a/drivers/misc/vmw_balloon.c b/drivers/misc/vmw_balloon.c
index 1e688bfec567..9047c0a529b2 100644
--- a/drivers/misc/vmw_balloon.c
+++ b/drivers/misc/vmw_balloon.c
@@ -1271,7 +1271,7 @@ static int __init vmballoon_init(void)
* Check if we are running on VMware's hypervisor and bail out
* if we are not.
*/
- if (x86_hyper != &x86_hyper_vmware)
+ if (x86_hyper_type != X86_HYPER_VMWARE)
return -ENODEV;
for (is_2m_pages = 0; is_2m_pages < VMW_BALLOON_NUM_PAGE_SIZES;
--
2.12.3
^ permalink raw reply related
* [PATCH v2 1/5] x86: merge x86_hyper into x86_platform and x86_init
From: Juergen Gross @ 2017-11-09 13:27 UTC (permalink / raw)
To: linux-kernel
Cc: Juergen Gross, rusty, sthemmin, xen-devel, kvm, rkrcmar,
boris.ostrovsky, haiyangz, x86, devel, mingo, hpa, pbonzini, tglx,
virtualization, akataria
In-Reply-To: <20171109132739.23465-1-jgross@suse.com>
Instead of x86_hyper being either NULL on bare metal or a pointer to a
struct hypervisor_x86 in case of the kernel running as a guest merge
the struct into x86_platform and x86_init.
This will remove the need for wrappers making it hard to find out what
is being called. With dummy functions added for all callbacks testing
for a NULL function pointer can be removed, too.
Cc: kys@microsoft.com
Cc: haiyangz@microsoft.com
Cc: sthemmin@microsoft.com
Cc: akataria@vmware.com
Cc: pbonzini@redhat.com
Cc: rkrcmar@redhat.com
Cc: boris.ostrovsky@oracle.com
Cc: rusty@rustcorp.com.au
Cc: devel@linuxdriverproject.org
Cc: virtualization@lists.linux-foundation.org
Cc: kvm@vger.kernel.org
Cc: xen-devel@lists.xenproject.org
Suggested-by: Ingo Molnar <mingo@kernel.org>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
arch/x86/include/asm/hypervisor.h | 25 ++++--------------
arch/x86/include/asm/x86_init.h | 24 +++++++++++++++++
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/cpu/hypervisor.c | 54 +++++++++++++++++++--------------------
arch/x86/kernel/cpu/mshyperv.c | 2 +-
arch/x86/kernel/cpu/vmware.c | 4 +--
arch/x86/kernel/kvm.c | 2 +-
arch/x86/kernel/x86_init.c | 9 +++++++
arch/x86/mm/init.c | 2 +-
arch/x86/xen/enlighten_hvm.c | 8 +++---
arch/x86/xen/enlighten_pv.c | 2 +-
include/linux/hypervisor.h | 8 ++++--
12 files changed, 81 insertions(+), 61 deletions(-)
diff --git a/arch/x86/include/asm/hypervisor.h b/arch/x86/include/asm/hypervisor.h
index 0ead9dbb9130..0eca7239a7aa 100644
--- a/arch/x86/include/asm/hypervisor.h
+++ b/arch/x86/include/asm/hypervisor.h
@@ -23,6 +23,7 @@
#ifdef CONFIG_HYPERVISOR_GUEST
#include <asm/kvm_para.h>
+#include <asm/x86_init.h>
#include <asm/xen/hypervisor.h>
/*
@@ -35,17 +36,11 @@ struct hypervisor_x86 {
/* Detection routine */
uint32_t (*detect)(void);
- /* Platform setup (run once per boot) */
- void (*init_platform)(void);
+ /* init time callbacks */
+ struct x86_hyper_init init;
- /* X2APIC detection (run once per boot) */
- bool (*x2apic_available)(void);
-
- /* pin current vcpu to specified physical cpu (run rarely) */
- void (*pin_vcpu)(int);
-
- /* called during init_mem_mapping() to setup early mappings. */
- void (*init_mem_mapping)(void);
+ /* runtime callbacks */
+ struct x86_hyper_runtime runtime;
};
extern const struct hypervisor_x86 *x86_hyper;
@@ -58,17 +53,7 @@ extern const struct hypervisor_x86 x86_hyper_xen_hvm;
extern const struct hypervisor_x86 x86_hyper_kvm;
extern void init_hypervisor_platform(void);
-extern bool hypervisor_x2apic_available(void);
-extern void hypervisor_pin_vcpu(int cpu);
-
-static inline void hypervisor_init_mem_mapping(void)
-{
- if (x86_hyper && x86_hyper->init_mem_mapping)
- x86_hyper->init_mem_mapping();
-}
#else
static inline void init_hypervisor_platform(void) { }
-static inline bool hypervisor_x2apic_available(void) { return false; }
-static inline void hypervisor_init_mem_mapping(void) { }
#endif /* CONFIG_HYPERVISOR_GUEST */
#endif /* _ASM_X86_HYPERVISOR_H */
diff --git a/arch/x86/include/asm/x86_init.h b/arch/x86/include/asm/x86_init.h
index 8a1ebf9540dd..ad15a0fda917 100644
--- a/arch/x86/include/asm/x86_init.h
+++ b/arch/x86/include/asm/x86_init.h
@@ -115,6 +115,18 @@ struct x86_init_pci {
};
/**
+ * struct x86_hyper_init - x86 hypervisor init functions
+ * @init_platform: platform setup
+ * @x2apic_available: X2APIC detection
+ * @init_mem_mapping: setup early mappings during init_mem_mapping()
+ */
+struct x86_hyper_init {
+ void (*init_platform)(void);
+ bool (*x2apic_available)(void);
+ void (*init_mem_mapping)(void);
+};
+
+/**
* struct x86_init_ops - functions for platform specific setup
*
*/
@@ -127,6 +139,7 @@ struct x86_init_ops {
struct x86_init_timers timers;
struct x86_init_iommu iommu;
struct x86_init_pci pci;
+ struct x86_hyper_init hyper;
};
/**
@@ -200,6 +213,15 @@ struct x86_legacy_features {
};
/**
+ * struct x86_hyper_runtime - x86 hypervisor specific runtime callbacks
+ *
+ * @pin_vcpu: pin current vcpu to specified physical cpu (run rarely)
+ */
+struct x86_hyper_runtime {
+ void (*pin_vcpu)(int cpu);
+};
+
+/**
* struct x86_platform_ops - platform specific runtime functions
* @calibrate_cpu: calibrate CPU
* @calibrate_tsc: calibrate TSC, if different from CPU
@@ -218,6 +240,7 @@ struct x86_legacy_features {
* possible in x86_early_init_platform_quirks() by
* only using the current x86_hardware_subarch
* semantics.
+ * @hyper: x86 hypervisor specific runtime callbacks
*/
struct x86_platform_ops {
unsigned long (*calibrate_cpu)(void);
@@ -233,6 +256,7 @@ struct x86_platform_ops {
void (*apic_post_init)(void);
struct x86_legacy_features legacy;
void (*set_legacy_features)(void);
+ struct x86_hyper_runtime hyper;
};
struct pci_dev;
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c
index ff891772c9f8..89c7c8569e5e 100644
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1645,7 +1645,7 @@ static __init void try_to_enable_x2apic(int remap_mode)
* under KVM
*/
if (max_physical_apicid > 255 ||
- !hypervisor_x2apic_available()) {
+ !x86_init.hyper.x2apic_available()) {
pr_info("x2apic: IRQ remapping doesn't support X2APIC mode\n");
x2apic_disable();
return;
diff --git a/arch/x86/kernel/cpu/hypervisor.c b/arch/x86/kernel/cpu/hypervisor.c
index 4fa90006ac68..22226c1bf092 100644
--- a/arch/x86/kernel/cpu/hypervisor.c
+++ b/arch/x86/kernel/cpu/hypervisor.c
@@ -44,51 +44,49 @@ static const __initconst struct hypervisor_x86 * const hypervisors[] =
const struct hypervisor_x86 *x86_hyper;
EXPORT_SYMBOL(x86_hyper);
-static inline void __init
+static inline const struct hypervisor_x86 * __init
detect_hypervisor_vendor(void)
{
- const struct hypervisor_x86 *h, * const *p;
+ const struct hypervisor_x86 *h = NULL, * const *p;
uint32_t pri, max_pri = 0;
for (p = hypervisors; p < hypervisors + ARRAY_SIZE(hypervisors); p++) {
- h = *p;
- pri = h->detect();
- if (pri != 0 && pri > max_pri) {
+ pri = (*p)->detect();
+ if (pri > max_pri) {
max_pri = pri;
- x86_hyper = h;
+ h = *p;
}
}
- if (max_pri)
- pr_info("Hypervisor detected: %s\n", x86_hyper->name);
+ if (h)
+ pr_info("Hypervisor detected: %s\n", h->name);
+
+ return h;
}
-void __init init_hypervisor_platform(void)
+static void __init copy_array(const void *src, void *target, unsigned int size)
{
+ unsigned int i, n = size / sizeof(void *);
+ const void * const *from = (const void * const *)src;
+ const void **to = (const void **)target;
- detect_hypervisor_vendor();
-
- if (!x86_hyper)
- return;
-
- if (x86_hyper->init_platform)
- x86_hyper->init_platform();
+ for (i = 0; i < n; i++)
+ if (from[i])
+ to[i] = from[i];
}
-bool __init hypervisor_x2apic_available(void)
+void __init init_hypervisor_platform(void)
{
- return x86_hyper &&
- x86_hyper->x2apic_available &&
- x86_hyper->x2apic_available();
-}
+ const struct hypervisor_x86 *h;
-void hypervisor_pin_vcpu(int cpu)
-{
- if (!x86_hyper)
+ h = detect_hypervisor_vendor();
+
+ if (!h)
return;
- if (x86_hyper->pin_vcpu)
- x86_hyper->pin_vcpu(cpu);
- else
- WARN_ONCE(1, "vcpu pinning requested but not supported!\n");
+ copy_array(&h->init, &x86_init.hyper, sizeof(h->init));
+ copy_array(&h->runtime, &x86_platform.hyper, sizeof(h->runtime));
+
+ x86_hyper = h;
+ x86_init.hyper.init_platform();
}
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index 236324e83a3a..6bb84d655e4b 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -257,6 +257,6 @@ static void __init ms_hyperv_init_platform(void)
const __refconst struct hypervisor_x86 x86_hyper_ms_hyperv = {
.name = "Microsoft Hyper-V",
.detect = ms_hyperv_platform,
- .init_platform = ms_hyperv_init_platform,
+ .init.init_platform = ms_hyperv_init_platform,
};
EXPORT_SYMBOL(x86_hyper_ms_hyperv);
diff --git a/arch/x86/kernel/cpu/vmware.c b/arch/x86/kernel/cpu/vmware.c
index 40ed26852ebd..4804c1d063c8 100644
--- a/arch/x86/kernel/cpu/vmware.c
+++ b/arch/x86/kernel/cpu/vmware.c
@@ -208,7 +208,7 @@ static bool __init vmware_legacy_x2apic_available(void)
const __refconst struct hypervisor_x86 x86_hyper_vmware = {
.name = "VMware",
.detect = vmware_platform,
- .init_platform = vmware_platform_setup,
- .x2apic_available = vmware_legacy_x2apic_available,
+ .init.init_platform = vmware_platform_setup,
+ .init.x2apic_available = vmware_legacy_x2apic_available,
};
EXPORT_SYMBOL(x86_hyper_vmware);
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 8bb9594d0761..9dca8437c795 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -547,7 +547,7 @@ static uint32_t __init kvm_detect(void)
const struct hypervisor_x86 x86_hyper_kvm __refconst = {
.name = "KVM",
.detect = kvm_detect,
- .x2apic_available = kvm_para_available,
+ .init.x2apic_available = kvm_para_available,
};
EXPORT_SYMBOL_GPL(x86_hyper_kvm);
diff --git a/arch/x86/kernel/x86_init.c b/arch/x86/kernel/x86_init.c
index a088b2c47f73..5b2d10c1973a 100644
--- a/arch/x86/kernel/x86_init.c
+++ b/arch/x86/kernel/x86_init.c
@@ -28,6 +28,8 @@ void x86_init_noop(void) { }
void __init x86_init_uint_noop(unsigned int unused) { }
int __init iommu_init_noop(void) { return 0; }
void iommu_shutdown_noop(void) { }
+bool __init bool_x86_init_noop(void) { return false; }
+void x86_op_int_noop(int cpu) { }
/*
* The platform setup functions are preset with the default functions
@@ -81,6 +83,12 @@ struct x86_init_ops x86_init __initdata = {
.init_irq = x86_default_pci_init_irq,
.fixup_irqs = x86_default_pci_fixup_irqs,
},
+
+ .hyper = {
+ .init_platform = x86_init_noop,
+ .x2apic_available = bool_x86_init_noop,
+ .init_mem_mapping = x86_init_noop,
+ },
};
struct x86_cpuinit_ops x86_cpuinit = {
@@ -101,6 +109,7 @@ struct x86_platform_ops x86_platform __ro_after_init = {
.get_nmi_reason = default_get_nmi_reason,
.save_sched_clock_state = tsc_save_sched_clock_state,
.restore_sched_clock_state = tsc_restore_sched_clock_state,
+ .hyper.pin_vcpu = x86_op_int_noop,
};
EXPORT_SYMBOL_GPL(x86_platform);
diff --git a/arch/x86/mm/init.c b/arch/x86/mm/init.c
index af5c1ed21d43..a22c2b95e513 100644
--- a/arch/x86/mm/init.c
+++ b/arch/x86/mm/init.c
@@ -671,7 +671,7 @@ void __init init_mem_mapping(void)
load_cr3(swapper_pg_dir);
__flush_tlb_all();
- hypervisor_init_mem_mapping();
+ x86_init.hyper.init_mem_mapping();
early_memtest(0, max_pfn_mapped << PAGE_SHIFT);
}
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index de503c225ae1..7b1622089f96 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -229,9 +229,9 @@ static uint32_t __init xen_platform_hvm(void)
const struct hypervisor_x86 x86_hyper_xen_hvm = {
.name = "Xen HVM",
.detect = xen_platform_hvm,
- .init_platform = xen_hvm_guest_init,
- .pin_vcpu = xen_pin_vcpu,
- .x2apic_available = xen_x2apic_para_available,
- .init_mem_mapping = xen_hvm_init_mem_mapping,
+ .init.init_platform = xen_hvm_guest_init,
+ .init.x2apic_available = xen_x2apic_para_available,
+ .init.init_mem_mapping = xen_hvm_init_mem_mapping,
+ .runtime.pin_vcpu = xen_pin_vcpu,
};
EXPORT_SYMBOL(x86_hyper_xen_hvm);
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index d4396e27b1fb..69d1a7054ddb 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1463,6 +1463,6 @@ static uint32_t __init xen_platform_pv(void)
const struct hypervisor_x86 x86_hyper_xen_pv = {
.name = "Xen PV",
.detect = xen_platform_pv,
- .pin_vcpu = xen_pin_vcpu,
+ .runtime.pin_vcpu = xen_pin_vcpu,
};
EXPORT_SYMBOL(x86_hyper_xen_pv);
diff --git a/include/linux/hypervisor.h b/include/linux/hypervisor.h
index b4054fd5b6f6..b19563f9a8eb 100644
--- a/include/linux/hypervisor.h
+++ b/include/linux/hypervisor.h
@@ -7,8 +7,12 @@
* Juergen Gross <jgross@suse.com>
*/
-#ifdef CONFIG_HYPERVISOR_GUEST
-#include <asm/hypervisor.h>
+#ifdef CONFIG_X86
+#include <asm/x86_init.h>
+static inline void hypervisor_pin_vcpu(int cpu)
+{
+ x86_platform.hyper.pin_vcpu(cpu);
+}
#else
static inline void hypervisor_pin_vcpu(int cpu)
{
--
2.12.3
^ permalink raw reply related
* [PATCH v2 0/5] x86/xen: support booting PVH guest via standard boot path
From: Juergen Gross @ 2017-11-09 13:27 UTC (permalink / raw)
To: linux-kernel
Cc: kvm, rkrcmar, pv-drivers, akataria, virtualization, pavel, hpa,
tglx, sthemmin, x86, moltmann, mingo, linux-graphics-maintainer,
linux-input, xen-devel, len.brown, arnd, linux-pm, xdeguillard,
haiyangz, rusty, pbonzini, boris.ostrovsky, Juergen Gross, gregkh,
dmitry.torokhov, rjw, devel
Booting a Xen PVH guest requires a special boot entry as it is
mandatory to setup some Xen-specific interfaces rather early. When grub
or OVMF are used as boot loaders, however, those will fill the boot
parameters in zeropage and there is no longer a need to do something
PVH specific in the early boot path.
This patch series adds support for that scenario by identifying PVH
environment and doing the required init steps via Xen hooks instead of
using a dedicated boot entry.
The dedicated entry is still mandatory for support of Dom0 running in
PVH mode as in this case there is no grub or OVMF involved for filling
in the boot parameters.
Changes in V2:
- added new patches 1 and 2
Cc: kys@microsoft.com
Cc: haiyangz@microsoft.com
Cc: sthemmin@microsoft.com
Cc: akataria@vmware.com
Cc: pbonzini@redhat.com
Cc: rkrcmar@redhat.com
Cc: boris.ostrovsky@oracle.com
Cc: rusty@rustcorp.com.au
Cc: devel@linuxdriverproject.org
Cc: virtualization@lists.linux-foundation.org
Cc: kvm@vger.kernel.org
Cc: xen-devel@lists.xenproject.org
Cc: linux-graphics-maintainer@vmware.com
Cc: pv-drivers@vmware.com
Cc: dmitry.torokhov@gmail.com
Cc: xdeguillard@vmware.com
Cc: moltmann@vmware.com
Cc: arnd@arndb.de
Cc: gregkh@linuxfoundation.org
Cc: linux-input@vger.kernel.org
Cc: rjw@rjwysocki.net
Cc: len.brown@intel.com
Cc: pavel@ucw.cz
Cc: linux-pm@vger.kernel.org
Juergen Gross (5):
x86: merge x86_hyper into x86_platform and x86_init
x86: add enum for hypervisors to replace x86_hyper
x86/acpi: add test for ACPI_FADT_NO_VGA
x86: add guest_late_init hook to hypervisor_x86 structure
x86/xen: use guest_late_init to detect Xen PVH guest
arch/x86/hyperv/hv_init.c | 2 +-
arch/x86/include/asm/hypervisor.h | 46 +++++++++++-----------------
arch/x86/include/asm/kvm_para.h | 2 --
arch/x86/include/asm/x86_init.h | 27 +++++++++++++++++
arch/x86/kernel/acpi/boot.c | 5 +++
arch/x86/kernel/apic/apic.c | 2 +-
arch/x86/kernel/cpu/hypervisor.c | 64 +++++++++++++++++++++------------------
arch/x86/kernel/cpu/mshyperv.c | 6 ++--
arch/x86/kernel/cpu/vmware.c | 8 ++---
arch/x86/kernel/kvm.c | 9 +++---
arch/x86/kernel/setup.c | 2 +-
arch/x86/kernel/x86_init.c | 10 ++++++
arch/x86/mm/init.c | 2 +-
arch/x86/xen/enlighten_hvm.c | 36 +++++++++++++++++-----
arch/x86/xen/enlighten_pv.c | 6 ++--
arch/x86/xen/enlighten_pvh.c | 9 ------
drivers/hv/vmbus_drv.c | 2 +-
drivers/input/mouse/vmmouse.c | 10 +++---
drivers/misc/vmw_balloon.c | 2 +-
include/linux/hypervisor.h | 8 +++--
20 files changed, 153 insertions(+), 105 deletions(-)
--
2.12.3
^ permalink raw reply
* Re: [PATCH v6] x86: use lock+addl for smp_mb()
From: Peter Zijlstra @ 2017-11-09 9:32 UTC (permalink / raw)
To: Michael S. Tsirkin
Cc: qemu-devel, x86, linux-kernel, Andy Lutomirski, Ingo Molnar,
H. Peter Anvin, Thomas Gleixner, virtualization
In-Reply-To: <1509118355-4890-1-git-send-email-mst@redhat.com>
On Fri, Oct 27, 2017 at 07:14:31PM +0300, Michael S. Tsirkin wrote:
> The one difference between lock+add and mfence is that lock+addl does
> not affect clflush, previous patches converted all uses of clflush to
> call mb(), such that changes to smp_mb won't affect it.
>
> Update mb/rmb/wmb on 32 bit to use the negative offset, too, for
> consistency.
So I briefly spoke to hpa about this patch in Prague, and yes, we should
do this.
By the very simple argument that we already rely on all LOCK prefixed
instructions to fully imply smp_mb().
And yes, there are differences between MFENCE and LOCK prefix, but as
already noted above, those should not have been using smp_mb() in the
first place and should be converted to mb()
So:
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
> diff --git a/arch/x86/include/asm/barrier.h b/arch/x86/include/asm/barrier.h
> index bfb28ca..3c6ba1e 100644
> --- a/arch/x86/include/asm/barrier.h
> +++ b/arch/x86/include/asm/barrier.h
> @@ -11,11 +11,11 @@
> */
>
> #ifdef CONFIG_X86_32
> -#define mb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "mfence", \
> +#define mb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "mfence", \
> X86_FEATURE_XMM2) ::: "memory", "cc")
> -#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "lfence", \
> +#define rmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "lfence", \
> X86_FEATURE_XMM2) ::: "memory", "cc")
> -#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,0(%%esp)", "sfence", \
> +#define wmb() asm volatile(ALTERNATIVE("lock; addl $0,-4(%%esp)", "sfence", \
> X86_FEATURE_XMM2) ::: "memory", "cc")
> #else
> #define mb() asm volatile("mfence":::"memory")
> @@ -30,7 +30,11 @@
> #endif
> #define dma_wmb() barrier()
>
> -#define __smp_mb() mb()
> +#ifdef CONFIG_X86_32
> +#define __smp_mb() asm volatile("lock; addl $0,-4(%%esp)" ::: "memory", "cc")
> +#else
> +#define __smp_mb() asm volatile("lock; addl $0,-4(%%rsp)" ::: "memory", "cc")
> +#endif
> #define __smp_rmb() dma_rmb()
> #define __smp_wmb() barrier()
> #define __smp_store_mb(var, value) do { (void)xchg(&var, value); } while (0)
^ permalink raw reply
* [PATCH] vhost/scsi: Use safe iteration in vhost_scsi_complete_cmd_work()
From: Byungchul Park @ 2017-11-09 0:17 UTC (permalink / raw)
To: nab, mst, jasowang; +Cc: kernel-team, netdev, linux-kernel, kvm, virtualization
I am sorry for having made a mistake on it.
-----8<-----
From ba9a0f76dffceffa4fa3aa2d9be49cdb0d9b7d4f Mon Sep 17 00:00:00 2001
From: Byungchul Park <byungchul.park@lge.com>
Date: Thu, 9 Nov 2017 09:00:21 +0900
Subject: [PATCH] vhost/scsi: Use safe iteration in vhost_scsi_complete_cmd_work()
The following patch changed the behavior which originally did safe
iteration. Make it safe as it was.
12bdcbd539c6327c09da0503c674733cb2d82cb5
vhost/scsi: Don't reinvent the wheel but use existing llist API
Signed-off-by: Byungchul Park <byungchul.park@lge.com>
---
drivers/vhost/scsi.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/vhost/scsi.c b/drivers/vhost/scsi.c
index 046f6d2..46539ca 100644
--- a/drivers/vhost/scsi.c
+++ b/drivers/vhost/scsi.c
@@ -519,7 +519,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
vs_completion_work);
DECLARE_BITMAP(signal, VHOST_SCSI_MAX_VQ);
struct virtio_scsi_cmd_resp v_rsp;
- struct vhost_scsi_cmd *cmd;
+ struct vhost_scsi_cmd *cmd, *t;
struct llist_node *llnode;
struct se_cmd *se_cmd;
struct iov_iter iov_iter;
@@ -527,7 +527,7 @@ static void vhost_scsi_complete_cmd_work(struct vhost_work *work)
bitmap_zero(signal, VHOST_SCSI_MAX_VQ);
llnode = llist_del_all(&vs->vs_completion_list);
- llist_for_each_entry(cmd, llnode, tvc_completion_list) {
+ llist_for_each_entry_safe(cmd, t, llnode, tvc_completion_list) {
se_cmd = &cmd->tvc_se_cmd;
pr_debug("%s tv_cmd %p resid %u status %#02x\n", __func__,
--
1.9.1
^ permalink raw reply related
* [PATCH] drm/cirrus: add create_handle support.
From: Lepton Wu @ 2017-11-08 18:55 UTC (permalink / raw)
To: airlied, kraxel; +Cc: Lepton Wu, virtualization
In-Reply-To: <20171108125659.oyjzylx26zmz7753@phenom.ffwll.local>
Add create_handle support to cirrus fb. Without this, screenshot tool
in chromium OS can't work.
Signed-off-by: Lepton Wu <ytht.net@gmail.com>
---
drivers/gpu/drm/cirrus/cirrus_main.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
index b5f528543956..26df1e8cd490 100644
--- a/drivers/gpu/drm/cirrus/cirrus_main.c
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -13,6 +13,14 @@
#include "cirrus_drv.h"
+static int cirrus_create_handle(struct drm_framebuffer *fb,
+ struct drm_file* file_priv,
+ unsigned int* handle)
+{
+ struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
+
+ return drm_gem_handle_create(file_priv, cirrus_fb->obj, handle);
+}
static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
{
@@ -24,6 +32,7 @@ static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
}
static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
+ .create_handle = cirrus_create_handle,
.destroy = cirrus_user_framebuffer_destroy,
};
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related
* [PATCH] drm/virtio: add create_handle support.
From: Lepton Wu @ 2017-11-08 18:42 UTC (permalink / raw)
To: airlied, kraxel; +Cc: Lepton Wu, dri-devel, virtualization
In-Reply-To: <20171108125659.oyjzylx26zmz7753@phenom.ffwll.local>
Add create_handle support to virtio fb. Without this, screenshot tool
in chromium OS can't work.
Signed-off-by: Lepton Wu <ytht.net@gmail.com>
---
drivers/gpu/drm/virtio/virtgpu_display.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/virtio/virtgpu_display.c b/drivers/gpu/drm/virtio/virtgpu_display.c
index b6d52055a11f..274b4206ca96 100644
--- a/drivers/gpu/drm/virtio/virtgpu_display.c
+++ b/drivers/gpu/drm/virtio/virtgpu_display.c
@@ -71,7 +71,19 @@ virtio_gpu_framebuffer_surface_dirty(struct drm_framebuffer *fb,
return virtio_gpu_surface_dirty(virtio_gpu_fb, clips, num_clips);
}
+static int
+virtio_gpu_framebuffer_create_handle(struct drm_framebuffer *fb,
+ struct drm_file *file_priv,
+ unsigned int *handle)
+{
+ struct virtio_gpu_framebuffer *virtio_gpu_fb =
+ to_virtio_gpu_framebuffer(fb);
+
+ return drm_gem_handle_create(file_priv, virtio_gpu_fb->obj, handle);
+}
+
static const struct drm_framebuffer_funcs virtio_gpu_fb_funcs = {
+ .create_handle = virtio_gpu_framebuffer_create_handle,
.destroy = virtio_gpu_user_framebuffer_destroy,
.dirty = virtio_gpu_framebuffer_surface_dirty,
};
--
2.15.0.403.gc27cc4dac6-goog
^ permalink raw reply related
* [PATCH v3] virtio_balloon: fix deadlock on OOM
From: Michael S. Tsirkin @ 2017-11-08 15:17 UTC (permalink / raw)
To: linux-kernel; +Cc: Michal Hocko, Tetsuo Handa, virtualization, linux-mm
fill_balloon doing memory allocations under balloon_lock
can cause a deadlock when leak_balloon is called from
virtballoon_oom_notify and tries to take same lock.
To fix, split page allocation and enqueue and do allocations outside the lock.
Here's a detailed analysis of the deadlock by Tetsuo Handa:
In leak_balloon(), mutex_lock(&vb->balloon_lock) is called in order to
serialize against fill_balloon(). But in fill_balloon(),
alloc_page(GFP_HIGHUSER[_MOVABLE] | __GFP_NOMEMALLOC | __GFP_NORETRY) is
called with vb->balloon_lock mutex held. Since GFP_HIGHUSER[_MOVABLE]
implies __GFP_DIRECT_RECLAIM | __GFP_IO | __GFP_FS, despite __GFP_NORETRY
is specified, this allocation attempt might indirectly depend on somebody
else's __GFP_DIRECT_RECLAIM memory allocation. And such indirect
__GFP_DIRECT_RECLAIM memory allocation might call leak_balloon() via
virtballoon_oom_notify() via blocking_notifier_call_chain() callback via
out_of_memory() when it reached __alloc_pages_may_oom() and held oom_lock
mutex. Since vb->balloon_lock mutex is already held by fill_balloon(), it
will cause OOM lockup.
Thread1 Thread2
fill_balloon()
takes a balloon_lock
balloon_page_enqueue()
alloc_page(GFP_HIGHUSER_MOVABLE)
direct reclaim (__GFP_FS context) takes a fs lock
waits for that fs lock alloc_page(GFP_NOFS)
__alloc_pages_may_oom()
takes the oom_lock
out_of_memory()
blocking_notifier_call_chain()
leak_balloon()
tries to take that balloon_lock and deadlocks
Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Wei Wang <wei.w.wang@intel.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Changes since v2:
drop an unused declaration, reported by Tetsuo Hocko
Changes from v1:
fix a build warning
drivers/virtio/virtio_balloon.c | 24 +++++++++++++++++++-----
include/linux/balloon_compaction.h | 35 ++++++++++++++++++++++++++++++++++-
mm/balloon_compaction.c | 28 +++++++++++++++++++++-------
3 files changed, 74 insertions(+), 13 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f0b3a0b..7960746 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
{
- struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
unsigned num_allocated_pages;
+ unsigned num_pfns;
+ struct page *page;
+ LIST_HEAD(pages);
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
- mutex_lock(&vb->balloon_lock);
- for (vb->num_pfns = 0; vb->num_pfns < num;
- vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
- struct page *page = balloon_page_enqueue(vb_dev_info);
+ for (num_pfns = 0; num_pfns < num;
+ num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+ struct page *page = balloon_page_alloc();
if (!page) {
dev_info_ratelimited(&vb->vdev->dev,
@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200);
break;
}
+
+ balloon_page_push(&pages, page);
+ }
+
+ mutex_lock(&vb->balloon_lock);
+
+ vb->num_pfns = 0;
+
+ while ((page = balloon_page_pop(&pages))) {
+ balloon_page_enqueue(&vb->vb_dev_info, page);
+
+ vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
+
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
if (!virtio_has_feature(vb->vdev,
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index fbbe6da..c4c8df9 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -50,6 +50,7 @@
#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/fs.h>
+#include <linux/list.h>
/*
* Balloon device information descriptor.
@@ -67,7 +68,9 @@ struct balloon_dev_info {
struct inode *inode;
};
-extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
+extern struct page *balloon_page_alloc(void);
+extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
+ struct page *page);
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
@@ -89,6 +92,36 @@ extern int balloon_page_migrate(struct address_space *mapping,
struct page *page, enum migrate_mode mode);
/*
+ * balloon_page_push - insert a page into a page list.
+ * @head : pointer to list
+ * @page : page to be added
+ *
+ * Caller must ensure the page is private and protect the list.
+ */
+static inline void balloon_page_push(struct list_head *pages, struct page *page)
+{
+ list_add(&page->lru, pages);
+}
+
+/*
+ * balloon_page_pop - remove a page from a page list.
+ * @head : pointer to list
+ * @page : page to be added
+ *
+ * Caller must ensure the page is private and protect the list.
+ */
+static inline struct page *balloon_page_pop(struct list_head *pages)
+{
+ struct page *page = list_first_entry_or_null(pages, struct page, lru);
+
+ if (!page)
+ return NULL;
+
+ list_del(&page->lru);
+ return page;
+}
+
+/*
* balloon_page_insert - insert a page into the balloon's page list and make
* the page->private assignment accordingly.
* @balloon : pointer to balloon device
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 68d2892..ef858d5 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -11,22 +11,37 @@
#include <linux/balloon_compaction.h>
/*
+ * balloon_page_alloc - allocates a new page for insertion into the balloon
+ * page list.
+ *
+ * Driver must call it to properly allocate a new enlisted balloon page.
+ * Driver must call balloon_page_enqueue before definitively removing it from
+ * the guest system. This function returns the page address for the recently
+ * allocated page or NULL in the case we fail to allocate a new page this turn.
+ */
+struct page *balloon_page_alloc(void)
+{
+ struct page *page = alloc_page(balloon_mapping_gfp_mask() |
+ __GFP_NOMEMALLOC | __GFP_NORETRY);
+ return page;
+}
+EXPORT_SYMBOL_GPL(balloon_page_alloc);
+
+/*
* balloon_page_enqueue - allocates a new page and inserts it into the balloon
* page list.
* @b_dev_info: balloon device descriptor where we will insert a new page to
+ * @page: new page to enqueue - allocated using balloon_page_alloc.
*
- * Driver must call it to properly allocate a new enlisted balloon page
+ * Driver must call it to properly enqueue a new allocated balloon page
* before definitively removing it from the guest system.
* This function returns the page address for the recently enqueued page or
* NULL in the case we fail to allocate a new page this turn.
*/
-struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
+void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
+ struct page *page)
{
unsigned long flags;
- struct page *page = alloc_page(balloon_mapping_gfp_mask() |
- __GFP_NOMEMALLOC | __GFP_NORETRY);
- if (!page)
- return NULL;
/*
* Block others from accessing the 'page' when we get around to
@@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
__count_vm_event(BALLOON_INFLATE);
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
unlock_page(page);
- return page;
}
EXPORT_SYMBOL_GPL(balloon_page_enqueue);
--
MST
^ permalink raw reply related
* [PATCH v2] virtio_balloon: fix deadlock on OOM
From: Michael S. Tsirkin @ 2017-11-08 5:24 UTC (permalink / raw)
To: linux-kernel; +Cc: Michal Hocko, Tetsuo Handa, virtualization, linux-mm
fill_balloon doing memory allocations under balloon_lock
can cause a deadlock when leak_balloon is called from
virtballoon_oom_notify and tries to take same lock.
To fix, split page allocation and enqueue and do allocations outside the lock.
Here's a detailed analysis of the deadlock by Tetsuo Handa:
In leak_balloon(), mutex_lock(&vb->balloon_lock) is called in order to
serialize against fill_balloon(). But in fill_balloon(),
alloc_page(GFP_HIGHUSER[_MOVABLE] | __GFP_NOMEMALLOC | __GFP_NORETRY) is
called with vb->balloon_lock mutex held. Since GFP_HIGHUSER[_MOVABLE]
implies __GFP_DIRECT_RECLAIM | __GFP_IO | __GFP_FS, despite __GFP_NORETRY
is specified, this allocation attempt might indirectly depend on somebody
else's __GFP_DIRECT_RECLAIM memory allocation. And such indirect
__GFP_DIRECT_RECLAIM memory allocation might call leak_balloon() via
virtballoon_oom_notify() via blocking_notifier_call_chain() callback via
out_of_memory() when it reached __alloc_pages_may_oom() and held oom_lock
mutex. Since vb->balloon_lock mutex is already held by fill_balloon(), it
will cause OOM lockup.
Thread1 Thread2
fill_balloon()
takes a balloon_lock
balloon_page_enqueue()
alloc_page(GFP_HIGHUSER_MOVABLE)
direct reclaim (__GFP_FS context) takes a fs lock
waits for that fs lock alloc_page(GFP_NOFS)
__alloc_pages_may_oom()
takes the oom_lock
out_of_memory()
blocking_notifier_call_chain()
leak_balloon()
tries to take that balloon_lock and deadlocks
Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Wei Wang <wei.w.wang@intel.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---
Fixed a build warning.
Fixed buffer overflow when num > array size.
drivers/virtio/virtio_balloon.c | 24 +++++++++++++++++++-----
include/linux/balloon_compaction.h | 38 +++++++++++++++++++++++++++++++++++++-
mm/balloon_compaction.c | 28 +++++++++++++++++++++-------
3 files changed, 77 insertions(+), 13 deletions(-)
diff --git a/drivers/virtio/virtio_balloon.c b/drivers/virtio/virtio_balloon.c
index f0b3a0b..7960746 100644
--- a/drivers/virtio/virtio_balloon.c
+++ b/drivers/virtio/virtio_balloon.c
@@ -143,16 +143,17 @@ static void set_page_pfns(struct virtio_balloon *vb,
static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
{
- struct balloon_dev_info *vb_dev_info = &vb->vb_dev_info;
unsigned num_allocated_pages;
+ unsigned num_pfns;
+ struct page *page;
+ LIST_HEAD(pages);
/* We can only do one array worth at a time. */
num = min(num, ARRAY_SIZE(vb->pfns));
- mutex_lock(&vb->balloon_lock);
- for (vb->num_pfns = 0; vb->num_pfns < num;
- vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
- struct page *page = balloon_page_enqueue(vb_dev_info);
+ for (num_pfns = 0; num_pfns < num;
+ num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
+ struct page *page = balloon_page_alloc();
if (!page) {
dev_info_ratelimited(&vb->vdev->dev,
@@ -162,6 +163,19 @@ static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
msleep(200);
break;
}
+
+ balloon_page_push(&pages, page);
+ }
+
+ mutex_lock(&vb->balloon_lock);
+
+ vb->num_pfns = 0;
+
+ while ((page = balloon_page_pop(&pages))) {
+ balloon_page_enqueue(&vb->vb_dev_info, page);
+
+ vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
+
set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
if (!virtio_has_feature(vb->vdev,
diff --git a/include/linux/balloon_compaction.h b/include/linux/balloon_compaction.h
index fbbe6da..36734ff 100644
--- a/include/linux/balloon_compaction.h
+++ b/include/linux/balloon_compaction.h
@@ -50,6 +50,7 @@
#include <linux/gfp.h>
#include <linux/err.h>
#include <linux/fs.h>
+#include <linux/list.h>
/*
* Balloon device information descriptor.
@@ -67,9 +68,14 @@ struct balloon_dev_info {
struct inode *inode;
};
-extern struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info);
+extern struct page *balloon_page_alloc(void);
+extern void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
+ struct page *page);
extern struct page *balloon_page_dequeue(struct balloon_dev_info *b_dev_info);
+extern void balloon_devinfo_splice(struct balloon_dev_info *to_add,
+ struct balloon_dev_info *b_dev_info);
+
static inline void balloon_devinfo_init(struct balloon_dev_info *balloon)
{
balloon->isolated_pages = 0;
@@ -89,6 +95,36 @@ extern int balloon_page_migrate(struct address_space *mapping,
struct page *page, enum migrate_mode mode);
/*
+ * balloon_page_push - insert a page into a page list.
+ * @head : pointer to list
+ * @page : page to be added
+ *
+ * Caller must ensure the page is private and protect the list.
+ */
+static inline void balloon_page_push(struct list_head *pages, struct page *page)
+{
+ list_add(&page->lru, pages);
+}
+
+/*
+ * balloon_page_pop - remove a page from a page list.
+ * @head : pointer to list
+ * @page : page to be added
+ *
+ * Caller must ensure the page is private and protect the list.
+ */
+static inline struct page *balloon_page_pop(struct list_head *pages)
+{
+ struct page *page = list_first_entry_or_null(pages, struct page, lru);
+
+ if (!page)
+ return NULL;
+
+ list_del(&page->lru);
+ return page;
+}
+
+/*
* balloon_page_insert - insert a page into the balloon's page list and make
* the page->private assignment accordingly.
* @balloon : pointer to balloon device
diff --git a/mm/balloon_compaction.c b/mm/balloon_compaction.c
index 68d2892..ef858d5 100644
--- a/mm/balloon_compaction.c
+++ b/mm/balloon_compaction.c
@@ -11,22 +11,37 @@
#include <linux/balloon_compaction.h>
/*
+ * balloon_page_alloc - allocates a new page for insertion into the balloon
+ * page list.
+ *
+ * Driver must call it to properly allocate a new enlisted balloon page.
+ * Driver must call balloon_page_enqueue before definitively removing it from
+ * the guest system. This function returns the page address for the recently
+ * allocated page or NULL in the case we fail to allocate a new page this turn.
+ */
+struct page *balloon_page_alloc(void)
+{
+ struct page *page = alloc_page(balloon_mapping_gfp_mask() |
+ __GFP_NOMEMALLOC | __GFP_NORETRY);
+ return page;
+}
+EXPORT_SYMBOL_GPL(balloon_page_alloc);
+
+/*
* balloon_page_enqueue - allocates a new page and inserts it into the balloon
* page list.
* @b_dev_info: balloon device descriptor where we will insert a new page to
+ * @page: new page to enqueue - allocated using balloon_page_alloc.
*
- * Driver must call it to properly allocate a new enlisted balloon page
+ * Driver must call it to properly enqueue a new allocated balloon page
* before definitively removing it from the guest system.
* This function returns the page address for the recently enqueued page or
* NULL in the case we fail to allocate a new page this turn.
*/
-struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
+void balloon_page_enqueue(struct balloon_dev_info *b_dev_info,
+ struct page *page)
{
unsigned long flags;
- struct page *page = alloc_page(balloon_mapping_gfp_mask() |
- __GFP_NOMEMALLOC | __GFP_NORETRY);
- if (!page)
- return NULL;
/*
* Block others from accessing the 'page' when we get around to
@@ -39,7 +54,6 @@ struct page *balloon_page_enqueue(struct balloon_dev_info *b_dev_info)
__count_vm_event(BALLOON_INFLATE);
spin_unlock_irqrestore(&b_dev_info->pages_lock, flags);
unlock_page(page);
- return page;
}
EXPORT_SYMBOL_GPL(balloon_page_enqueue);
--
MST
^ permalink raw reply related
* Re: [PULL] virtio: last minute bugfix
From: Wei Wang @ 2017-11-08 1:24 UTC (permalink / raw)
To: Michael S. Tsirkin, Linus Torvalds
Cc: Michal Hocko, KVM list, Tetsuo Handa, Network Development,
Linux Kernel Mailing List, virtualization
In-Reply-To: <20171107211730-mutt-send-email-mst@kernel.org>
On 11/08/2017 03:23 AM, Michael S. Tsirkin wrote:
> On Tue, Nov 07, 2017 at 08:13:10PM +0200, Michael S. Tsirkin wrote:
>> On Tue, Nov 07, 2017 at 09:29:59AM -0800, Linus Torvalds wrote:
>>> On Tue, Nov 7, 2017 at 9:23 AM, Linus Torvalds
>>> <torvalds@linux-foundation.org> wrote:
>>>> I guess I'll take it, but please don't do things like this to me.
>>> Oh no I wont.
>>>
>>> The garbage you sent me doesn't even compile cleanly, and is utter shite.
>>>
>>> Not acceptable for last-minute bugfixes, and you're now on my shit-list.
>>>
>>> Linus
>> Sorry about that.
>>
>> I'll investigate what went wrong.
>>
>> Will be more careful not to cut corners next time around, just follow
>> the standard procedure.
> All right, my local tests didn't fail on new warnings, and I didn't give
> the zero day infrastructure enough time to do it's job.
>
> Lesson hopefully learned - don't rush it, give tools the time to do
> their job.
>
> Wei, you'll want to respin your 4.15 patchset on top of my fixed tree.
> At this point the fix will only land in 4.15, sorry about that.
>
> Thanks everyone.
>
OK, I'll use the fixed tree. Thanks, Michael.
Best,
Wei
^ permalink raw reply
* Re: [PULL] virtio: last minute bugfix
From: Michael S. Tsirkin @ 2017-11-07 19:23 UTC (permalink / raw)
To: Linus Torvalds
Cc: Michal Hocko, KVM list, Tetsuo Handa, Network Development,
Linux Kernel Mailing List, virtualization
In-Reply-To: <20171107201156-mutt-send-email-mst@kernel.org>
On Tue, Nov 07, 2017 at 08:13:10PM +0200, Michael S. Tsirkin wrote:
> On Tue, Nov 07, 2017 at 09:29:59AM -0800, Linus Torvalds wrote:
> > On Tue, Nov 7, 2017 at 9:23 AM, Linus Torvalds
> > <torvalds@linux-foundation.org> wrote:
> > >
> > > I guess I'll take it, but please don't do things like this to me.
> >
> > Oh no I wont.
> >
> > The garbage you sent me doesn't even compile cleanly, and is utter shite.
> >
> > Not acceptable for last-minute bugfixes, and you're now on my shit-list.
> >
> > Linus
>
> Sorry about that.
>
> I'll investigate what went wrong.
>
> Will be more careful not to cut corners next time around, just follow
> the standard procedure.
All right, my local tests didn't fail on new warnings, and I didn't give
the zero day infrastructure enough time to do it's job.
Lesson hopefully learned - don't rush it, give tools the time to do
their job.
Wei, you'll want to respin your 4.15 patchset on top of my fixed tree.
At this point the fix will only land in 4.15, sorry about that.
Thanks everyone.
> --
> MST
^ permalink raw reply
* [vhost:vhost 1/1] drivers/virtio/virtio_balloon.c:164:3: error: implicit declaration of function 'balloon_page_push'
From: kbuild test robot @ 2017-11-07 19:09 UTC (permalink / raw)
To: Michael S. Tsirkin; +Cc: netdev, kbuild-all, kvm, virtualization
[-- Attachment #1: Type: text/plain, Size: 3104 bytes --]
tree: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git vhost
head: 823b45b4f154384941d57e124ed726847e293b36
commit: 823b45b4f154384941d57e124ed726847e293b36 [1/1] virtio_balloon: fix deadlock on OOM
config: i386-randconfig-x001-201745 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
git checkout 823b45b4f154384941d57e124ed726847e293b36
# save the attached .config to linux build tree
make ARCH=i386
All error/warnings (new ones prefixed by >>):
drivers/virtio/virtio_balloon.c: In function 'fill_balloon':
>> drivers/virtio/virtio_balloon.c:164:3: error: implicit declaration of function 'balloon_page_push' [-Werror=implicit-function-declaration]
balloon_page_push(&pages, page);
^~~~~~~~~~~~~~~~~
>> drivers/virtio/virtio_balloon.c:174:17: error: implicit declaration of function 'balloon_page_pop' [-Werror=implicit-function-declaration]
while ((page = balloon_page_pop(&pages))) {
^~~~~~~~~~~~~~~~
>> drivers/virtio/virtio_balloon.c:174:15: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
while ((page = balloon_page_pop(&pages))) {
^
cc1: some warnings being treated as errors
vim +/balloon_page_push +164 drivers/virtio/virtio_balloon.c
143
144 static unsigned fill_balloon(struct virtio_balloon *vb, size_t num)
145 {
146 unsigned num_allocated_pages;
147 unsigned num_pfns;
148 struct page *page;
149 LIST_HEAD(pages);
150
151 for (num_pfns = 0; num_pfns < num;
152 num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE) {
153 struct page *page = balloon_page_alloc();
154
155 if (!page) {
156 dev_info_ratelimited(&vb->vdev->dev,
157 "Out of puff! Can't get %u pages\n",
158 VIRTIO_BALLOON_PAGES_PER_PAGE);
159 /* Sleep for at least 1/5 of a second before retry. */
160 msleep(200);
161 break;
162 }
163
> 164 balloon_page_push(&pages, page);
165 }
166
167 /* We can only do one array worth at a time. */
168 num = min(num, ARRAY_SIZE(vb->pfns));
169
170 mutex_lock(&vb->balloon_lock);
171
172 vb->num_pfns = 0;
173
> 174 while ((page = balloon_page_pop(&pages))) {
175 balloon_page_enqueue(&vb->vb_dev_info, page);
176
177 vb->num_pfns += VIRTIO_BALLOON_PAGES_PER_PAGE;
178
179 set_page_pfns(vb, vb->pfns + vb->num_pfns, page);
180 vb->num_pages += VIRTIO_BALLOON_PAGES_PER_PAGE;
181 if (!virtio_has_feature(vb->vdev,
182 VIRTIO_BALLOON_F_DEFLATE_ON_OOM))
183 adjust_managed_page_count(page, -1);
184 }
185
186 num_allocated_pages = vb->num_pfns;
187 /* Did we get any? */
188 if (vb->num_pfns != 0)
189 tell_host(vb, vb->inflate_vq);
190 mutex_unlock(&vb->balloon_lock);
191
192 return num_allocated_pages;
193 }
194
---
0-DAY kernel test infrastructure Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all Intel Corporation
[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 33858 bytes --]
[-- Attachment #3: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox