2018-03-25 04:21:26

by Wanpeng Li

[permalink] [raw]
Subject: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

From: Wanpeng Li <[email protected]>

static_key_disable_cpuslocked(): static key 'virt_spin_lock_key+0x0/0x20' used before call to jump_label_init()
WARNING: CPU: 0 PID: 0 at kernel/jump_label.c:161 static_key_disable_cpuslocked+0x61/0x80
RIP: 0010:static_key_disable_cpuslocked+0x61/0x80
Call Trace:
static_key_disable+0x16/0x20
start_kernel+0x192/0x4b3
secondary_startup_64+0xa5/0xb0

Qspinlock will be choosed when dedicated pCPUs are available, however, the
static virt_spin_lock_key is set in kvm_spinlock_init() before jump_label_init()
has been called, which will result in a WARN(). This patch fixes it by delaying
the virt_spin_lock_key setup to .smp_prepare_cpus().

Reported-by: Davidlohr Bueso <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Radim Krčmář <[email protected]>
Cc: Davidlohr Bueso <[email protected]>
Signed-off-by: Wanpeng Li <[email protected]>
---
Note: Peterz pointed out in the IRC we have to audit all the architectures that
implement smp_prepare_boot_cpu() to see what they depend on if we want to move
jump_label_init() before smp_prepare_boot_cpu(). So what this patch does is
similar to the issue which handled in xen ca5d376e.

arch/x86/kernel/kvm.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 4ccbff6..747c61b 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -454,6 +454,13 @@ static void __init sev_map_percpu_data(void)
}

#ifdef CONFIG_SMP
+static void __init kvm_smp_prepare_cpus(unsigned int max_cpus)
+{
+ native_smp_prepare_cpus(max_cpus);
+ if (kvm_para_has_hint(KVM_HINTS_DEDICATED))
+ static_branch_disable(&virt_spin_lock_key);
+}
+
static void __init kvm_smp_prepare_boot_cpu(void)
{
/*
@@ -557,6 +564,7 @@ static void __init kvm_guest_init(void)
kvm_setup_vsyscall_timeinfo();

#ifdef CONFIG_SMP
+ smp_ops.smp_prepare_cpus = kvm_smp_prepare_cpus;
smp_ops.smp_prepare_boot_cpu = kvm_smp_prepare_boot_cpu;
if (cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN, "x86/kvm:online",
kvm_cpu_online, kvm_cpu_down_prepare) < 0)
@@ -737,10 +745,8 @@ void __init kvm_spinlock_init(void)
if (!kvm_para_has_feature(KVM_FEATURE_PV_UNHALT))
return;

- if (kvm_para_has_hint(KVM_HINTS_DEDICATED)) {
- static_branch_disable(&virt_spin_lock_key);
+ if (kvm_para_has_hint(KVM_HINTS_DEDICATED))
return;
- }

__pv_init_lock_hash();
pv_lock_ops.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath;
--
2.7.4



2018-03-26 00:41:05

by Davidlohr Bueso

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

On Sat, 24 Mar 2018, Wanpeng Li wrote:

>Note: Peterz pointed out in the IRC we have to audit all the architectures that
>implement smp_prepare_boot_cpu() to see what they depend on if we want to move
>jump_label_init() before smp_prepare_boot_cpu(). So what this patch does is
>similar to the issue which handled in xen ca5d376e.

After some auditing, the jump_label_init() being moved before smp_prepare_boot_cpu()
seems fine, however, bulky mechanisms to update text segments conflict with early smp
bootup stages, such as this patch. So, while the disabling virt_spin_lock_key would
be done correctly _after_ jump_label_init(), it is still fragile in that we want to
be using lightweight patching such as jump_label_transform_static() -- which doesn't
take the text_mutex (blocking is out of the question), for example.

For pretty much all archs this means using the transform_static() version. For example
x86, this means using text_poke_early(). -- also ouchy on the !PageReserved(pages[0])
warning for text_poke().

I'm not sure yet of the best way to teach jump_label_transform() to behave like
jump_label_transform_static() under pre-smp bootup, such as when disabling hypervisor
pvspinlocks.

The s390 implementation seems safe as is given that stop_machine is now safe for early
pre-smp boot.

Thanks,
Davidlohr

2018-03-26 14:12:39

by Wanpeng Li

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

2018-03-26 8:27 GMT+08:00 Davidlohr Bueso <[email protected]>:
> On Sat, 24 Mar 2018, Wanpeng Li wrote:
>
>> Note: Peterz pointed out in the IRC we have to audit all the architectures
>> that
>> implement smp_prepare_boot_cpu() to see what they depend on if we want to
>> move
>> jump_label_init() before smp_prepare_boot_cpu(). So what this patch does
>> is
>> similar to the issue which handled in xen ca5d376e.
>
>
> After some auditing, the jump_label_init() being moved before
> smp_prepare_boot_cpu()
> seems fine, however, bulky mechanisms to update text segments conflict with
> early smp
> bootup stages, such as this patch. So, while the disabling

I didn't see any issue when testing this patch, could you elaborate
what's the bulky mechanism and how it conflicts with early smp bootup
stages? In addition, do you mean the xen fix is also not suitable?

Regards,
Wanpeng Li

2018-03-26 22:45:57

by Davidlohr Bueso

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

On Mon, 26 Mar 2018, Wanpeng Li wrote:

>I didn't see any issue when testing this patch, could you elaborate
>what's the bulky mechanism and how it conflicts with early smp bootup
>stages? In addition, do you mean the xen fix is also not suitable?

I have nothing against your patch (or the xen one for that matter), other than
the fact that both seem like band-aid solutions to being able to move up the jump
label init call. I was actually peddling a similar patch but didn't want to add
the extra callback just for that -- at least xen already had smp_ops.smp_prepare_cpus.

Instead of dropping the patches in -tip (ie: delaying the feature), I have nothing
against these fixes being merged. If a better solution is available later, we can
always move dealing with virt_spin_lock_key back into smp_prepare_boot_cpu().

Also a bit unrelated, but am I correct to assume that KVM_HINTS_DEDICATED can be
used via qemu? I've only been dealing with kernel parameters.

Thanks,
Davidlohr

2018-03-27 00:53:47

by Wanpeng Li

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

2018-03-27 6:32 GMT+08:00 Davidlohr Bueso <[email protected]>:
> On Mon, 26 Mar 2018, Wanpeng Li wrote:
>
>> I didn't see any issue when testing this patch, could you elaborate
>> what's the bulky mechanism and how it conflicts with early smp bootup
>> stages? In addition, do you mean the xen fix is also not suitable?
>
>
> I have nothing against your patch (or the xen one for that matter), other
> than
> the fact that both seem like band-aid solutions to being able to move up the
> jump
> label init call. I was actually peddling a similar patch but didn't want to
> add
> the extra callback just for that -- at least xen already had
> smp_ops.smp_prepare_cpus.
>
> Instead of dropping the patches in -tip (ie: delaying the feature), I have
> nothing
> against these fixes being merged. If a better solution is available later,
> we can
> always move dealing with virt_spin_lock_key back into
> smp_prepare_boot_cpu().

Yeah, we can pick the current patch for the fixes and wait a better
solution is available later.

>
> Also a bit unrelated, but am I correct to assume that KVM_HINTS_DEDICATED
> can be
> used via qemu? I've only been dealing with kernel parameters.

The host admin can control it by qemu command-line, -cpu ...+kvm-hint-dedicated

Regards,
Wanpeng Li

2018-03-27 16:44:55

by Davidlohr Bueso

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

On Tue, 27 Mar 2018, Wanpeng Li wrote:

>The host admin can control it by qemu command-line, -cpu ...+kvm-hint-dedicated

So this requires qemu code modification, no?

2018-03-28 00:46:26

by Wanpeng Li

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

2018-03-28 0:29 GMT+08:00 Davidlohr Bueso <[email protected]>:
> On Tue, 27 Mar 2018, Wanpeng Li wrote:
>
>> The host admin can control it by qemu command-line, -cpu
>> ...+kvm-hint-dedicated
>
>
> So this requires qemu code modification, no?

Yeah, https://git.qemu.org/?p=qemu.git;a=commitdiff;h=be7773268d98176489483a315d3e2323cb0615b9

Regards,
Wanpeng Li

2018-03-28 20:21:03

by Radim Krčmář

[permalink] [raw]
Subject: Re: [PATCH 1/2] KVM: X86: Fix setup the virt_spin_lock_key before static key get initialized

2018-03-24 21:17-0700, Wanpeng Li:
> From: Wanpeng Li <[email protected]>
>
> static_key_disable_cpuslocked(): static key 'virt_spin_lock_key+0x0/0x20' used before call to jump_label_init()
> WARNING: CPU: 0 PID: 0 at kernel/jump_label.c:161 static_key_disable_cpuslocked+0x61/0x80
> RIP: 0010:static_key_disable_cpuslocked+0x61/0x80
> Call Trace:
> static_key_disable+0x16/0x20
> start_kernel+0x192/0x4b3
> secondary_startup_64+0xa5/0xb0
>
> Qspinlock will be choosed when dedicated pCPUs are available, however, the
> static virt_spin_lock_key is set in kvm_spinlock_init() before jump_label_init()
> has been called, which will result in a WARN(). This patch fixes it by delaying
> the virt_spin_lock_key setup to .smp_prepare_cpus().
>
> Reported-by: Davidlohr Bueso <[email protected]>
> Cc: Paolo Bonzini <[email protected]>
> Cc: Radim Krčmář <[email protected]>
> Cc: Davidlohr Bueso <[email protected]>
> Signed-off-by: Wanpeng Li <[email protected]>
> ---

Queued, thanks.