Skip to content

Commit 8d152e7

Browse files
mcgrofIngo Molnar
authored and
Ingo Molnar
committed
x86/rtc: Replace paravirt rtc check with platform legacy quirk
We have 4 types of x86 platforms that disable RTC: * Intel MID * Lguest - uses paravirt * Xen dom-U - uses paravirt * x86 on legacy systems annotated with an ACPI legacy flag We can consolidate all of these into a platform specific legacy quirk set early in boot through i386_start_kernel() and through x86_64_start_reservations(). This deals with the RTC quirks which we can rely on through the hardware subarch, the ACPI check can be dealt with separately. For Xen things are bit more complex given that the @X86_SUBARCH_XEN x86_hardware_subarch is shared on for Xen which uses the PV path for both domU and dom0. Since the semantics for differentiating between the two are Xen specific we provide a platform helper to help override default legacy features -- x86_platform.set_legacy_features(). Use of this helper is highly discouraged, its only purpose should be to account for the lack of semantics available within your given x86_hardware_subarch. As per 0-day, this bumps the vmlinux size using i386-tinyconfig as follows: TOTAL TEXT init.text x86_early_init_platform_quirks() +70 +62 +62 +43 Only 8 bytes overhead total, as the main increase in size is all removed via __init. Suggested-by: Ingo Molnar <mingo@kernel.org> Signed-off-by: Luis R. Rodriguez <mcgrof@kernel.org> Reviewed-by: Juergen Gross <jgross@suse.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: andrew.cooper3@citrix.com Cc: andriy.shevchenko@linux.intel.com Cc: bigeasy@linutronix.de Cc: boris.ostrovsky@oracle.com Cc: david.vrabel@citrix.com Cc: ffainelli@freebox.fr Cc: george.dunlap@citrix.com Cc: glin@suse.com Cc: jlee@suse.com Cc: josh@joshtriplett.org Cc: julien.grall@linaro.org Cc: konrad.wilk@oracle.com Cc: kozerkov@parallels.com Cc: lenb@kernel.org Cc: lguest@lists.ozlabs.org Cc: linux-acpi@vger.kernel.org Cc: lv.zheng@intel.com Cc: matt@codeblueprint.co.uk Cc: mbizon@freebox.fr Cc: rjw@rjwysocki.net Cc: robert.moore@intel.com Cc: rusty@rustcorp.com.au Cc: tiwai@suse.de Cc: toshi.kani@hp.com Cc: xen-devel@lists.xensource.com Link: http://lkml.kernel.org/r/1460592286-300-5-git-send-email-mcgrof@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
1 parent 907bb65 commit 8d152e7

File tree

12 files changed

+60
-22
lines changed

12 files changed

+60
-22
lines changed

arch/x86/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@ endif
209209
head-y := arch/x86/kernel/head_$(BITS).o
210210
head-y += arch/x86/kernel/head$(BITS).o
211211
head-y += arch/x86/kernel/head.o
212+
head-y += arch/x86/kernel/platform-quirks.o
212213

213214
libs-y += arch/x86/lib/
214215

arch/x86/include/asm/paravirt.h

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,6 @@ static inline int paravirt_enabled(void)
2020
return pv_info.paravirt_enabled;
2121
}
2222

23-
static inline int paravirt_has_feature(unsigned int feature)
24-
{
25-
WARN_ON_ONCE(!pv_info.paravirt_enabled);
26-
return (pv_info.features & feature);
27-
}
28-
2923
static inline void load_sp0(struct tss_struct *tss,
3024
struct thread_struct *thread)
3125
{

arch/x86/include/asm/paravirt_types.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,9 @@ struct pv_info {
7070
#endif
7171

7272
int paravirt_enabled;
73-
unsigned int features; /* valid only if paravirt_enabled is set */
7473
const char *name;
7574
};
7675

77-
#define paravirt_has(x) paravirt_has_feature(PV_SUPPORTED_##x)
78-
/* Supported features */
79-
#define PV_SUPPORTED_RTC (1<<0)
80-
8176
struct pv_init_ops {
8277
/*
8378
* Patch may replace one of the defined code sequences with

arch/x86/include/asm/processor.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -474,7 +474,6 @@ static inline unsigned long current_top_of_stack(void)
474474
#else
475475
#define __cpuid native_cpuid
476476
#define paravirt_enabled() 0
477-
#define paravirt_has(x) 0
478477

479478
static inline void load_sp0(struct tss_struct *tss,
480479
struct thread_struct *thread)

arch/x86/include/asm/x86_init.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,15 @@ struct x86_cpuinit_ops {
141141

142142
struct timespec;
143143

144+
/**
145+
* struct x86_legacy_features - legacy x86 features
146+
*
147+
* @rtc: this device has a CMOS real-time clock present
148+
*/
149+
struct x86_legacy_features {
150+
int rtc;
151+
};
152+
144153
/**
145154
* struct x86_platform_ops - platform specific runtime functions
146155
* @calibrate_tsc: calibrate TSC
@@ -152,6 +161,14 @@ struct timespec;
152161
* @save_sched_clock_state: save state for sched_clock() on suspend
153162
* @restore_sched_clock_state: restore state for sched_clock() on resume
154163
* @apic_post_init: adjust apic if neeeded
164+
* @legacy: legacy features
165+
* @set_legacy_features: override legacy features. Use of this callback
166+
* is highly discouraged. You should only need
167+
* this if your hardware platform requires further
168+
* custom fine tuning far beyong what may be
169+
* possible in x86_early_init_platform_quirks() by
170+
* only using the current x86_hardware_subarch
171+
* semantics.
155172
*/
156173
struct x86_platform_ops {
157174
unsigned long (*calibrate_tsc)(void);
@@ -165,6 +182,8 @@ struct x86_platform_ops {
165182
void (*save_sched_clock_state)(void);
166183
void (*restore_sched_clock_state)(void);
167184
void (*apic_post_init)(void);
185+
struct x86_legacy_features legacy;
186+
void (*set_legacy_features)(void);
168187
};
169188

170189
struct pci_dev;
@@ -186,6 +205,8 @@ extern struct x86_cpuinit_ops x86_cpuinit;
186205
extern struct x86_platform_ops x86_platform;
187206
extern struct x86_msi_ops x86_msi;
188207
extern struct x86_io_apic_ops x86_io_apic_ops;
208+
209+
extern void x86_early_init_platform_quirks(void);
189210
extern void x86_init_noop(void);
190211
extern void x86_init_uint_noop(unsigned int unused);
191212

arch/x86/kernel/Makefile

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,11 @@
22
# Makefile for the linux kernel.
33
#
44

5-
extra-y := head_$(BITS).o head$(BITS).o head.o vmlinux.lds
5+
extra-y := head_$(BITS).o
6+
extra-y += head$(BITS).o
7+
extra-y += head.o
8+
extra-y += platform-quirks.o
9+
extra-y += vmlinux.lds
610

711
CPPFLAGS_vmlinux.lds += -U$(UTS_MACHINE)
812

arch/x86/kernel/head32.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ asmlinkage __visible void __init i386_start_kernel(void)
3434
cr4_init_shadow();
3535
sanitize_boot_params(&boot_params);
3636

37+
x86_early_init_platform_quirks();
38+
3739
/* Call the subarch specific early setup function */
3840
switch (boot_params.hdr.hardware_subarch) {
3941
case X86_SUBARCH_INTEL_MID:

arch/x86/kernel/head64.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ void __init x86_64_start_reservations(char *real_mode_data)
182182
if (!boot_params.hdr.version)
183183
copy_bootdata(__va(real_mode_data));
184184

185+
x86_early_init_platform_quirks();
185186
reserve_ebda_region();
186187

187188
switch (boot_params.hdr.hardware_subarch) {

arch/x86/kernel/platform-quirks.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#include <linux/kernel.h>
2+
#include <linux/init.h>
3+
4+
#include <asm/setup.h>
5+
#include <asm/bios_ebda.h>
6+
7+
void __init x86_early_init_platform_quirks(void)
8+
{
9+
x86_platform.legacy.rtc = 1;
10+
11+
switch (boot_params.hdr.hardware_subarch) {
12+
case X86_SUBARCH_XEN:
13+
case X86_SUBARCH_LGUEST:
14+
case X86_SUBARCH_INTEL_MID:
15+
x86_platform.legacy.rtc = 0;
16+
break;
17+
}
18+
19+
if (x86_platform.set_legacy_features)
20+
x86_platform.set_legacy_features();
21+
}

arch/x86/kernel/rtc.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <asm/time.h>
1515
#include <asm/intel-mid.h>
1616
#include <asm/rtc.h>
17+
#include <asm/setup.h>
1718

1819
#ifdef CONFIG_X86_32
1920
/*
@@ -188,10 +189,6 @@ static __init int add_rtc_cmos(void)
188189
if (of_have_populated_dt())
189190
return 0;
190191

191-
/* Intel MID platforms don't have ioport rtc */
192-
if (intel_mid_identify_cpu())
193-
return -ENODEV;
194-
195192
#ifdef CONFIG_ACPI
196193
if (acpi_gbl_FADT.boot_flags & ACPI_FADT_NO_CMOS_RTC) {
197194
/* This warning can likely go away again in a year or two. */
@@ -200,7 +197,7 @@ static __init int add_rtc_cmos(void)
200197
}
201198
#endif
202199

203-
if (paravirt_enabled() && !paravirt_has(RTC))
200+
if (!x86_platform.legacy.rtc)
204201
return -ENODEV;
205202

206203
platform_device_register(&rtc_device);

arch/x86/lguest/boot.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1414,7 +1414,6 @@ __init void lguest_init(void)
14141414
pv_info.kernel_rpl = 1;
14151415
/* Everyone except Xen runs with this set. */
14161416
pv_info.shared_kernel_pmd = 1;
1417-
pv_info.features = 0;
14181417

14191418
/*
14201419
* We set up all the lguest overrides for sensitive operations. These

arch/x86/xen/enlighten.c

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1193,7 +1193,6 @@ static const struct pv_info xen_info __initconst = {
11931193
#ifdef CONFIG_X86_64
11941194
.extra_user_64bit_cs = FLAT_USER_CS64,
11951195
#endif
1196-
.features = 0,
11971196
.name = "Xen",
11981197
};
11991198

@@ -1506,6 +1505,11 @@ static void __init xen_pvh_early_guest_init(void)
15061505
}
15071506
#endif /* CONFIG_XEN_PVH */
15081507

1508+
static void __init xen_dom0_set_legacy_features(void)
1509+
{
1510+
x86_platform.legacy.rtc = 1;
1511+
}
1512+
15091513
/* First C function to be called on Xen boot */
15101514
asmlinkage __visible void __init xen_start_kernel(void)
15111515
{
@@ -1527,8 +1531,6 @@ asmlinkage __visible void __init xen_start_kernel(void)
15271531

15281532
/* Install Xen paravirt ops */
15291533
pv_info = xen_info;
1530-
if (xen_initial_domain())
1531-
pv_info.features |= PV_SUPPORTED_RTC;
15321534
pv_init_ops = xen_init_ops;
15331535
if (!xen_pvh_domain()) {
15341536
pv_cpu_ops = xen_cpu_ops;
@@ -1688,6 +1690,8 @@ asmlinkage __visible void __init xen_start_kernel(void)
16881690
.u.firmware_info.type = XEN_FW_KBD_SHIFT_FLAGS,
16891691
};
16901692

1693+
x86_platform.set_legacy_features =
1694+
xen_dom0_set_legacy_features;
16911695
xen_init_vga(info, xen_start_info->console.dom0.info_size);
16921696
xen_start_info->console.domU.mfn = 0;
16931697
xen_start_info->console.domU.evtchn = 0;

0 commit comments

Comments
 (0)