Skip to content

Commit f682a79

Browse files
committed
Merge branch 'x86-paravirt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 paravirt updates from Ingo Molnar: "Two main changes: - Remove no longer used parts of the paravirt infrastructure and put large quantities of paravirt ops under a new config option PARAVIRT_XXL=y, which is selected by XEN_PV only. (Joergen Gross) - Enable PV spinlocks on Hyperv (Yi Sun)" * 'x86-paravirt-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/hyperv: Enable PV qspinlock for Hyper-V x86/hyperv: Add GUEST_IDLE_MSR support x86/paravirt: Clean up native_patch() x86/paravirt: Prevent redefinition of SAVE_FLAGS macro x86/xen: Make xen_reservation_lock static x86/paravirt: Remove unneeded mmu related paravirt ops bits x86/paravirt: Move the Xen-only pv_mmu_ops under the PARAVIRT_XXL umbrella x86/paravirt: Move the pv_irq_ops under the PARAVIRT_XXL umbrella x86/paravirt: Move the Xen-only pv_cpu_ops under the PARAVIRT_XXL umbrella x86/paravirt: Move items in pv_info under PARAVIRT_XXL umbrella x86/paravirt: Introduce new config option PARAVIRT_XXL x86/paravirt: Remove unused paravirt bits x86/paravirt: Use a single ops structure x86/paravirt: Remove clobbers from struct paravirt_patch_site x86/paravirt: Remove clobbers parameter from paravirt patch functions x86/paravirt: Make paravirt_patch_call() and paravirt_patch_jmp() static x86/xen: Add SPDX identifier in arch/x86/xen files x86/xen: Link platform-pci-unplug.o only if CONFIG_XEN_PVHVM x86/xen: Move pv specific parts of arch/x86/xen/mmu.c to mmu_pv.c x86/xen: Move pv irq related functions under CONFIG_XEN_PV umbrella
2 parents 99792e0 + 3a025de commit f682a79

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1023
-1006
lines changed

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1390,6 +1390,11 @@
13901390
hvc_iucv_allow= [S390] Comma-separated list of z/VM user IDs.
13911391
If specified, z/VM IUCV HVC accepts connections
13921392
from listed z/VM user IDs only.
1393+
1394+
hv_nopvspin [X86,HYPER_V] Disables the paravirt spinlock optimizations
1395+
which allow the hypervisor to 'idle' the
1396+
guest on lock contention.
1397+
13931398
keep_bootcon [KNL]
13941399
Do not unregister boot console at start. This is only
13951400
useful for debugging when something happens in the window

arch/arm/include/asm/paravirt.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ extern struct static_key paravirt_steal_rq_enabled;
1010
struct pv_time_ops {
1111
unsigned long long (*steal_clock)(int cpu);
1212
};
13-
extern struct pv_time_ops pv_time_ops;
13+
14+
struct paravirt_patch_template {
15+
struct pv_time_ops time;
16+
};
17+
18+
extern struct paravirt_patch_template pv_ops;
1419

1520
static inline u64 paravirt_steal_clock(int cpu)
1621
{
17-
return pv_time_ops.steal_clock(cpu);
22+
return pv_ops.time.steal_clock(cpu);
1823
}
1924
#endif
2025

arch/arm/kernel/paravirt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
struct static_key paravirt_steal_enabled;
2222
struct static_key paravirt_steal_rq_enabled;
2323

24-
struct pv_time_ops pv_time_ops;
25-
EXPORT_SYMBOL_GPL(pv_time_ops);
24+
struct paravirt_patch_template pv_ops;
25+
EXPORT_SYMBOL_GPL(pv_ops);

arch/arm/xen/enlighten.c

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -62,47 +62,13 @@ static __read_mostly unsigned int xen_events_irq;
6262
uint32_t xen_start_flags;
6363
EXPORT_SYMBOL(xen_start_flags);
6464

65-
int xen_remap_domain_gfn_array(struct vm_area_struct *vma,
66-
unsigned long addr,
67-
xen_pfn_t *gfn, int nr,
68-
int *err_ptr, pgprot_t prot,
69-
unsigned domid,
70-
struct page **pages)
71-
{
72-
return xen_xlate_remap_gfn_array(vma, addr, gfn, nr, err_ptr,
73-
prot, domid, pages);
74-
}
75-
EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_array);
76-
77-
/* Not used by XENFEAT_auto_translated guests. */
78-
int xen_remap_domain_gfn_range(struct vm_area_struct *vma,
79-
unsigned long addr,
80-
xen_pfn_t gfn, int nr,
81-
pgprot_t prot, unsigned domid,
82-
struct page **pages)
83-
{
84-
return -ENOSYS;
85-
}
86-
EXPORT_SYMBOL_GPL(xen_remap_domain_gfn_range);
87-
8865
int xen_unmap_domain_gfn_range(struct vm_area_struct *vma,
8966
int nr, struct page **pages)
9067
{
9168
return xen_xlate_unmap_gfn_range(vma, nr, pages);
9269
}
9370
EXPORT_SYMBOL_GPL(xen_unmap_domain_gfn_range);
9471

95-
/* Not used by XENFEAT_auto_translated guests. */
96-
int xen_remap_domain_mfn_array(struct vm_area_struct *vma,
97-
unsigned long addr,
98-
xen_pfn_t *mfn, int nr,
99-
int *err_ptr, pgprot_t prot,
100-
unsigned int domid, struct page **pages)
101-
{
102-
return -ENOSYS;
103-
}
104-
EXPORT_SYMBOL_GPL(xen_remap_domain_mfn_array);
105-
10672
static void xen_read_wallclock(struct timespec64 *ts)
10773
{
10874
u32 version;

arch/arm64/include/asm/paravirt.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,16 @@ extern struct static_key paravirt_steal_rq_enabled;
1010
struct pv_time_ops {
1111
unsigned long long (*steal_clock)(int cpu);
1212
};
13-
extern struct pv_time_ops pv_time_ops;
13+
14+
struct paravirt_patch_template {
15+
struct pv_time_ops time;
16+
};
17+
18+
extern struct paravirt_patch_template pv_ops;
1419

1520
static inline u64 paravirt_steal_clock(int cpu)
1621
{
17-
return pv_time_ops.steal_clock(cpu);
22+
return pv_ops.time.steal_clock(cpu);
1823
}
1924
#endif
2025

arch/arm64/kernel/paravirt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
struct static_key paravirt_steal_enabled;
2222
struct static_key paravirt_steal_rq_enabled;
2323

24-
struct pv_time_ops pv_time_ops;
25-
EXPORT_SYMBOL_GPL(pv_time_ops);
24+
struct paravirt_patch_template pv_ops;
25+
EXPORT_SYMBOL_GPL(pv_ops);

arch/x86/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,7 @@ config X86_VSMP
523523
bool "ScaleMP vSMP"
524524
select HYPERVISOR_GUEST
525525
select PARAVIRT
526+
select PARAVIRT_XXL
526527
depends on X86_64 && PCI
527528
depends on X86_EXTENDED_PLATFORM
528529
depends on SMP
@@ -753,6 +754,9 @@ config PARAVIRT
753754
over full virtualization. However, when run without a hypervisor
754755
the kernel is theoretically slower and slightly larger.
755756

757+
config PARAVIRT_XXL
758+
bool
759+
756760
config PARAVIRT_DEBUG
757761
bool "paravirt-ops debugging"
758762
depends on PARAVIRT && DEBUG_KERNEL

arch/x86/boot/compressed/misc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
* paravirt and debugging variants are added.)
1010
*/
1111
#undef CONFIG_PARAVIRT
12+
#undef CONFIG_PARAVIRT_XXL
1213
#undef CONFIG_PARAVIRT_SPINLOCKS
1314
#undef CONFIG_KASAN
1415

arch/x86/entry/entry_32.S

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,7 @@ GLOBAL(__begin_SYSENTER_singlestep_region)
783783
* will ignore all of the single-step traps generated in this range.
784784
*/
785785

786-
#ifdef CONFIG_XEN
786+
#ifdef CONFIG_XEN_PV
787787
/*
788788
* Xen doesn't set %esp to be precisely what the normal SYSENTER
789789
* entry point expects, so fix it up before using the normal path.
@@ -1241,7 +1241,7 @@ ENTRY(spurious_interrupt_bug)
12411241
jmp common_exception
12421242
END(spurious_interrupt_bug)
12431243

1244-
#ifdef CONFIG_XEN
1244+
#ifdef CONFIG_XEN_PV
12451245
ENTRY(xen_hypervisor_callback)
12461246
pushl $-1 /* orig_ax = -1 => not a system call */
12471247
SAVE_ALL
@@ -1322,11 +1322,13 @@ ENTRY(xen_failsafe_callback)
13221322
_ASM_EXTABLE(3b, 8b)
13231323
_ASM_EXTABLE(4b, 9b)
13241324
ENDPROC(xen_failsafe_callback)
1325+
#endif /* CONFIG_XEN_PV */
13251326

1327+
#ifdef CONFIG_XEN_PVHVM
13261328
BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
13271329
xen_evtchn_do_upcall)
1330+
#endif
13281331

1329-
#endif /* CONFIG_XEN */
13301332

13311333
#if IS_ENABLED(CONFIG_HYPERV)
13321334

arch/x86/entry/entry_64.S

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ ENTRY(do_softirq_own_stack)
10501050
ret
10511051
ENDPROC(do_softirq_own_stack)
10521052

1053-
#ifdef CONFIG_XEN
1053+
#ifdef CONFIG_XEN_PV
10541054
idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0
10551055

10561056
/*
@@ -1130,11 +1130,13 @@ ENTRY(xen_failsafe_callback)
11301130
ENCODE_FRAME_POINTER
11311131
jmp error_exit
11321132
END(xen_failsafe_callback)
1133+
#endif /* CONFIG_XEN_PV */
11331134

1135+
#ifdef CONFIG_XEN_PVHVM
11341136
apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
11351137
xen_hvm_callback_vector xen_evtchn_do_upcall
1138+
#endif
11361139

1137-
#endif /* CONFIG_XEN */
11381140

11391141
#if IS_ENABLED(CONFIG_HYPERV)
11401142
apicinterrupt3 HYPERVISOR_CALLBACK_VECTOR \
@@ -1151,7 +1153,7 @@ idtentry debug do_debug has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
11511153
idtentry int3 do_int3 has_error_code=0
11521154
idtentry stack_segment do_stack_segment has_error_code=1
11531155

1154-
#ifdef CONFIG_XEN
1156+
#ifdef CONFIG_XEN_PV
11551157
idtentry xennmi do_nmi has_error_code=0
11561158
idtentry xendebug do_debug has_error_code=0
11571159
idtentry xenint3 do_int3 has_error_code=0

arch/x86/hyperv/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
obj-y := hv_init.o mmu.o nested.o
22
obj-$(CONFIG_X86_64) += hv_apic.o
3+
4+
ifdef CONFIG_X86_64
5+
obj-$(CONFIG_PARAVIRT_SPINLOCKS) += hv_spinlock.o
6+
endif

arch/x86/hyperv/hv_spinlock.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
3+
/*
4+
* Hyper-V specific spinlock code.
5+
*
6+
* Copyright (C) 2018, Intel, Inc.
7+
*
8+
* Author : Yi Sun <yi.y.sun@intel.com>
9+
*/
10+
11+
#define pr_fmt(fmt) "Hyper-V: " fmt
12+
13+
#include <linux/spinlock.h>
14+
15+
#include <asm/mshyperv.h>
16+
#include <asm/paravirt.h>
17+
#include <asm/apic.h>
18+
19+
static bool __initdata hv_pvspin = true;
20+
21+
static void hv_qlock_kick(int cpu)
22+
{
23+
apic->send_IPI(cpu, X86_PLATFORM_IPI_VECTOR);
24+
}
25+
26+
static void hv_qlock_wait(u8 *byte, u8 val)
27+
{
28+
unsigned long msr_val;
29+
unsigned long flags;
30+
31+
if (in_nmi())
32+
return;
33+
34+
/*
35+
* Reading HV_X64_MSR_GUEST_IDLE MSR tells the hypervisor that the
36+
* vCPU can be put into 'idle' state. This 'idle' state is
37+
* terminated by an IPI, usually from hv_qlock_kick(), even if
38+
* interrupts are disabled on the vCPU.
39+
*
40+
* To prevent a race against the unlock path it is required to
41+
* disable interrupts before accessing the HV_X64_MSR_GUEST_IDLE
42+
* MSR. Otherwise, if the IPI from hv_qlock_kick() arrives between
43+
* the lock value check and the rdmsrl() then the vCPU might be put
44+
* into 'idle' state by the hypervisor and kept in that state for
45+
* an unspecified amount of time.
46+
*/
47+
local_irq_save(flags);
48+
/*
49+
* Only issue the rdmsrl() when the lock state has not changed.
50+
*/
51+
if (READ_ONCE(*byte) == val)
52+
rdmsrl(HV_X64_MSR_GUEST_IDLE, msr_val);
53+
local_irq_restore(flags);
54+
}
55+
56+
/*
57+
* Hyper-V does not support this so far.
58+
*/
59+
bool hv_vcpu_is_preempted(int vcpu)
60+
{
61+
return false;
62+
}
63+
PV_CALLEE_SAVE_REGS_THUNK(hv_vcpu_is_preempted);
64+
65+
void __init hv_init_spinlocks(void)
66+
{
67+
if (!hv_pvspin || !apic ||
68+
!(ms_hyperv.hints & HV_X64_CLUSTER_IPI_RECOMMENDED) ||
69+
!(ms_hyperv.features & HV_X64_MSR_GUEST_IDLE_AVAILABLE)) {
70+
pr_info("PV spinlocks disabled\n");
71+
return;
72+
}
73+
pr_info("PV spinlocks enabled\n");
74+
75+
__pv_init_lock_hash();
76+
pv_ops.lock.queued_spin_lock_slowpath = __pv_queued_spin_lock_slowpath;
77+
pv_ops.lock.queued_spin_unlock = PV_CALLEE_SAVE(__pv_queued_spin_unlock);
78+
pv_ops.lock.wait = hv_qlock_wait;
79+
pv_ops.lock.kick = hv_qlock_kick;
80+
pv_ops.lock.vcpu_is_preempted = PV_CALLEE_SAVE(hv_vcpu_is_preempted);
81+
}
82+
83+
static __init int hv_parse_nopvspin(char *arg)
84+
{
85+
hv_pvspin = false;
86+
return 0;
87+
}
88+
early_param("hv_nopvspin", hv_parse_nopvspin);

arch/x86/hyperv/mmu.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,6 @@ void hyperv_setup_mmu_ops(void)
231231
return;
232232

233233
pr_info("Using hypercall for remote TLB flush\n");
234-
pv_mmu_ops.flush_tlb_others = hyperv_flush_tlb_others;
235-
pv_mmu_ops.tlb_remove_table = tlb_remove_table;
234+
pv_ops.mmu.flush_tlb_others = hyperv_flush_tlb_others;
235+
pv_ops.mmu.tlb_remove_table = tlb_remove_table;
236236
}

arch/x86/include/asm/debugreg.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
DECLARE_PER_CPU(unsigned long, cpu_dr7);
1010

11-
#ifndef CONFIG_PARAVIRT
11+
#ifndef CONFIG_PARAVIRT_XXL
1212
/*
1313
* These special macros can be used to get or set a debugging register
1414
*/

arch/x86/include/asm/desc.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ static inline int desc_empty(const void *ptr)
108108
return !(desc[0] | desc[1]);
109109
}
110110

111-
#ifdef CONFIG_PARAVIRT
111+
#ifdef CONFIG_PARAVIRT_XXL
112112
#include <asm/paravirt.h>
113113
#else
114114
#define load_TR_desc() native_load_tr_desc()
@@ -134,7 +134,7 @@ static inline void paravirt_alloc_ldt(struct desc_struct *ldt, unsigned entries)
134134
static inline void paravirt_free_ldt(struct desc_struct *ldt, unsigned entries)
135135
{
136136
}
137-
#endif /* CONFIG_PARAVIRT */
137+
#endif /* CONFIG_PARAVIRT_XXL */
138138

139139
#define store_ldt(ldt) asm("sldt %0" : "=m"(ldt))
140140

arch/x86/include/asm/fixmap.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ void __native_set_fixmap(enum fixed_addresses idx, pte_t pte);
162162
void native_set_fixmap(enum fixed_addresses idx,
163163
phys_addr_t phys, pgprot_t flags);
164164

165-
#ifndef CONFIG_PARAVIRT
165+
#ifndef CONFIG_PARAVIRT_XXL
166166
static inline void __set_fixmap(enum fixed_addresses idx,
167167
phys_addr_t phys, pgprot_t flags)
168168
{

arch/x86/include/asm/hyperv-tlfs.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
#define HV_MSR_TIME_REF_COUNT_AVAILABLE (1 << 1)
3939
/* Partition reference TSC MSR is available */
4040
#define HV_MSR_REFERENCE_TSC_AVAILABLE (1 << 9)
41+
/* Partition Guest IDLE MSR is available */
42+
#define HV_X64_MSR_GUEST_IDLE_AVAILABLE (1 << 10)
4143

4244
/* A partition's reference time stamp counter (TSC) page */
4345
#define HV_X64_MSR_REFERENCE_TSC 0x40000021
@@ -246,6 +248,9 @@
246248
#define HV_X64_MSR_STIMER3_CONFIG 0x400000B6
247249
#define HV_X64_MSR_STIMER3_COUNT 0x400000B7
248250

251+
/* Hyper-V guest idle MSR */
252+
#define HV_X64_MSR_GUEST_IDLE 0x400000F0
253+
249254
/* Hyper-V guest crash notification MSR's */
250255
#define HV_X64_MSR_CRASH_P0 0x40000100
251256
#define HV_X64_MSR_CRASH_P1 0x40000101

0 commit comments

Comments
 (0)