x86 candidate patches for review VI: MTRR, APIC, more paravirt, misc
Subsystems (4)
PATCH 2/34 x86: Adds mtrr_save_fixed_ranges() for use in two later patches.
In reply to Andi KleenFrom: Bernhard Kaindl <[email protected]>
In this current implementation which is used in other patches, mtrr_save_fixed_ranges() accepts a dummy void pointer because in the current implementation of one of these patches, this function may be called from smp_call_function_single() which requires that this function takes a void pointer argument.
This function calls get_fixed_ranges(), passing mtrr_state.fixed_ranges which is the element of the static struct which stores our current backup of the fixed-range MTRR values which all CPUs shall be using.
Because mtrr_save_fixed_ranges calls get_fixed_ranges after kernel initialisation time, __init needs to be removed from the declaration of get_fixed_ranges().
If CONFIG_MTRR is not set, we define mtrr_save_fixed_ranges as an empty statement because there is nothing to do.
AK: Moved prototypes for x86-64 around to fix warnings
--- arch/i386/kernel/cpu/mtrr/generic.c | 7 ++++++- include/asm-i386/mtrr.h | 2 ++ include/asm-x86_64/mtrr.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-)
arch/i386/kernel/cpu/mtrr/generic.c +6 -1
@@ -37,7 +37,7 @@ get_mtrr_var_range(unsigned int index, srdmsr (MTRRphysMask_MSR (index), vr->mask_lo, vr->mask_hi); } -static void __init +static void get_fixed_ranges (mtrr_type * frs) {unsigned int *p = (unsigned int *) frs;
@@ -51,6 +51,11 @@ get_fixed_ranges(mtrr_type * frs)rdmsr (MTRRfix4K_C0000_MSR + i, p[6 + i *2 ], p[7 + i *2 ]); } +void mtrr_save_fixed_ranges (void *info) +{ +get_fixed_ranges (mtrr_state.fixed_ranges); +} +static void __init print_fixed (unsigned base,unsigned step,const mtrr_type *types) {unsigned i;
include/asm-i386/mtrr.h +2 -0
@@ -69,6 +69,7 @@ struct mtrr_gentry/* The following functions are for use by other drivers */ # ifdef CONFIG_MTRR +extern void mtrr_save_fixed_ranges (void *);extern int mtrr_add (unsigned long base,unsigned long size,unsigned int type,char increment); extern int mtrr_add_page (unsigned long base, unsigned long size,
@@ -79,6 +80,7 @@ extern void mtrr_centaur_report_mcr(intextern void mtrr_ap_init (void );extern void mtrr_bp_init (void );# else +#define mtrr_save_fixed_ranges (arg) do {} while (0)static __inline__int mtrr_add (unsigned long base,unsigned long size,unsigned int type,char increment) {
include/asm-x86_64/mtrr.h +2 -0
@@ -138,9 +138,11 @@ struct mtrr_gentry32#ifdef CONFIG_MTRR extern void mtrr_ap_init (void );extern void mtrr_bp_init (void ); +extern void mtrr_save_fixed_ranges (void *);#else #define mtrr_ap_init () do {} while (0)#define mtrr_bp_init () do {} while (0) +#define mtrr_save_fixed_ranges (arg) do {} while (0)#endif #endif /* __KERNEL__ */
PATCH 4/34 x86: Save and restore the fixed-range MTRRs of the BSP when suspending
In reply to Andi KleenFrom: Bernhard Kaindl <[email protected]>
Note: This patch didn'nt need an update since it's initial post.
Some BIOSes may modify fixed-range MTRRs in SMM, e.g. when they transition the system into ACPI mode, which is entered thru an SMI, triggered by Linux in acpi_enable().
SMIs which cause that Linux is interrupted and BIOS code is executed (which may change e.g. fixed-range MTRRs) in SMM may be raised by an embedded system controller which is often found in notebooks also at other occasions.
If we would not update our copy of the fixed-range MTRRs before suspending to RAM or to disk, restore_processor_state() would set the fixed-range MTRRs of the BSP using old backup values which may be outdated and this could cause the system to fail later during resume.
This patch ensures that our copy of the fixed-range MTRRs is updated when saving the boot processor state on suspend to disk and suspend to RAM.
In combination with other patches this allows to fix s2ram and s2disk on the Acer Ferrari 1000 notebook and at least s2disk on the Acer Ferrari 5000 notebook.
--- arch/i386/power/cpu.c | 1 + arch/x86_64/kernel/suspend.c | 1 + 2 files changed, 2 insertions(+)
arch/i386/power/cpu.c +1 -0
@@ -21,6 +21,7 @@ unsigned long saved_context_eflags;void __save_processor_state (struct saved_context *ctxt) { +mtrr_save_fixed_ranges (NULL );kernel_fpu_begin ();/*
arch/x86_64/kernel/suspend.c +1 -0
@@ -48,6 +48,7 @@ void __save_processor_state(struct savedrdmsrl (MSR_FS_BASE , ctxt->fs_base);rdmsrl (MSR_GS_BASE , ctxt->gs_base);rdmsrl (MSR_KERNEL_GS_BASE , ctxt->gs_kernel_base); +mtrr_save_fixed_ranges (NULL );/* * control registers
PATCH 29/34 i386: pte simplify ops
In reply to Andi KleenFrom: Zachary Amsden <[email protected]>
Add comment and condense code to make use of native_local_ptep_get_and_clear function. Also, it turns out the 2-level and 3-level paging definitions were identical, so move the common definition into pgtable.h
---
include/asm-i386/pgtable-2level.h | 10 ---------- include/asm-i386/pgtable-3level.h | 10 ---------- include/asm-i386/pgtable.h | 17 +++++++++++++++-- 3 files changed, 15 insertions(+), 22 deletions(-)
include/asm-i386/pgtable-2level.h +0 -10
@@ -41,16 +41,6 @@ static inline void native_pte_clear(stru *xp =__pte (0 ); } -/* local pte updates need not use xchg for locking */ -static inline pte_t native_local_ptep_get_and_clear (pte_t *ptep) -{ -pte_t res; - - res = *ptep; -native_pte_clear (NULL ,0 , ptep); -return res; -} -#ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear (pte_t *xp) {
include/asm-i386/pgtable-3level.h +0 -10
@@ -139,16 +139,6 @@ static inline void pud_clear (pud_t * pu#define pmd_offset (pud, address) ((pmd_t *) pud_page(*(pud)) + \ pmd_index(address)) -/* local pte updates need not use xchg for locking */ -static inline pte_t native_local_ptep_get_and_clear (pte_t *ptep) -{ -pte_t res; - - res = *ptep; -native_pte_clear (NULL ,0 , ptep); -return res; -} -#ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear (pte_t *ptep) {
include/asm-i386/pgtable.h +15 -2
@@ -269,6 +269,16 @@ extern void vmalloc_sync_all(void);#define pte_update_defer (mm, addr, ptep) do { } while (0)#endif +/* local pte updates need not use xchg for locking */ +static inline pte_t native_local_ptep_get_and_clear (pte_t *ptep) +{ +pte_t res = *ptep; + +/* Pure native function needs no input for mm, addr */ +native_pte_clear (NULL ,0 , ptep); +return res; +} +/* * We only update the dirty/accessed state if we set * the dirty bit by hand in the kernel, since the hardware
@@ -343,8 +353,11 @@ static inline pte_t ptep_get_and_clear_f {pte_t pte;if (full) { - pte = *ptep; -native_pte_clear (mm, addr, ptep); +/* +* Full address destruction in progress; paravirt does not +* care about updates and native needs no locking +*/ + pte =native_local_ptep_get_and_clear (ptep); }else { pte =ptep_get_and_clear (mm, addr, ptep); }
PATCH 25/34 x86_64: skip cache_free_alien() on non NUMA
In reply to Andi KleenFrom: "Siddha, Suresh B" <[email protected]>
Set use_alien_caches to 0 on non NUMA platforms. And avoid calling the cache_free_alien() when use_alien_caches is not set. This will avoid the cache miss that happens while dereferencing slabp to get nodeid.
---
mm/slab.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
mm/slab.c +5 -2
@@ -1146,7 +1146,7 @@ static inline int cache_free_alien(struc* Make sure we are not freeing a object from another node to the array * cache on this cpu. */ -if (likely (slabp->nodeid == node) ||unlikely (!use_alien_caches)) +if (likely (slabp->nodeid == node))return 0 ; l3 = cachep->nodelists[node];
@@ -1394,6 +1394,9 @@ void __init kmem_cache_init(void)int order;int node; +if (num_possible_nodes () ==1 ) + use_alien_caches =0 ; +for (i =0 ; i <NUM_INIT_LISTS ; i++) {kmem_list3_init (&initkmem_list3[i]);if (i <MAX_NUMNODES )
@@ -3563,7 +3566,7 @@ static inline void __cache_free(struct kcheck_irq_off (); objp =cache_free_debugcheck (cachep, objp,__builtin_return_address (0 )); -if (cache_free_alien (cachep, objp)) +if (use_alien_caches &&cache_free_alien (cachep, objp))return ;if (likely (ac->avail < ac->limit)) {
PATCH 30/34 i386: convert the monitor thread to use the kthread API
In reply to Andi KleenFrom: Eric W. Biederman <[email protected]>
This patch just trivially replaces kernel_thread and daemonize with a single call to kthread_run.
---
arch/i386/mach-voyager/voyager_thread.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-)
arch/i386/mach-voyager/voyager_thread.c +2 -3
@@ -24,6 +24,7 @@#include <linux/kmod.h> #include <linux/completion.h> #include <linux/sched.h> +#include <linux/kthread.h> #include <asm/desc.h> #include <asm/voyager.h> #include <asm/vic.h>
@@ -44,7 +45,7 @@ static __u8 set_timeout = 0;static int __init voyager_thread_start (void ) { -if (kernel_thread (thread,NULL ,CLONE_KERNEL ) <0 ) { +if (IS_ERR (kthread_run (thread,NULL ,"%s" ,THREAD_NAME ))) {/* This is serious, but not fatal */ printk (KERN_ERR "Voyager: Failed to create system monitor thread!!!\n" );return 1 ;
@@ -123,8 +124,6 @@ thread(void *unused) kvoyagerd_running =1 ; -daemonize (THREAD_NAME ); - set_timeout =0 ;init_timer (&wakeup_timer);
PATCH 27/34 i386: pte clear optimization
In reply to Andi KleenFrom: Zachary Amsden <[email protected]>
When exiting from an address space, no special hypervisor notification of page table updates needs to occur; direct page table hypervisors, such as Xen, switch to another address space first (init_mm) and unprotects the page tables to avoid the cost of trapping to the hypervisor for each pte_clear. Shadow mode hypervisors, such as VMI and lhype don't need to do the extra work of calling through paravirt-ops, and can just directly clear the page table entries without notifiying the hypervisor, since all the page tables are about to be freed.
So introduce native_pte_clear functions which bypass any paravirt-ops notification. This results in a significant performance win for VMI and removes some indirect calls from zap_pte_range.
Note the 3-level paging already had a native_pte_clear function, thus demanding argument conformance and extra args for the 2-level definition.
---
include/asm-i386/pgtable-2level.h | 5 +++++ include/asm-i386/pgtable.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-)
include/asm-i386/pgtable-2level.h +5 -0
@@ -36,6 +36,11 @@ static inline void native_set_pmd(pmd_t#define pte_clear (mm,addr,xp) do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)#define pmd_clear (xp) do { set_pmd(xp, __pmd(0)); } while (0) +static inline void native_pte_clear (struct mm_struct *mm,unsigned long addr,pte_t *xp) +{ + *xp =__pte (0 ); +} +static inline pte_t native_ptep_get_and_clear (pte_t *xp) {return __pte (xchg (&xp->pte_low,0 ));
include/asm-i386/pgtable.h +1 -1
@@ -344,7 +344,7 @@ static inline pte_t ptep_get_and_clear_fpte_t pte;if (full) { pte = *ptep; -pte_clear (mm, addr, ptep); +native_pte_clear (mm, addr, ptep); }else { pte =ptep_get_and_clear (mm, addr, ptep); }
PATCH 31/34 i386: convert to the kthread API
In reply to Andi KleenFrom: "Eric W. Biederman" <[email protected]>
This patch just trivial converts from calling kernel_thread and daemonize to just calling kthread_run.
---
arch/i386/kernel/io_apic.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-)
arch/i386/kernel/io_apic.c +3 -5
@@ -35,6 +35,7 @@#include <linux/msi.h> #include <linux/htirq.h> #include <linux/freezer.h> +#include <linux/kthread.h> #include <asm/io.h> #include <asm/smp.h>
@@ -661,8 +662,6 @@ static int balanced_irq(void *unused)unsigned long prev_balance_time = jiffies;long time_remaining = balanced_irq_interval; -daemonize ("kirqd" ); -/* push everything to CPU 0 to give us a starting point. */ for (i =0 ; i <NR_IRQS ; i++) { irq_desc[i].pending_mask =cpumask_of_cpu (0 );
@@ -722,10 +721,9 @@ static int __init balanced_irq_init(void }printk (KERN_INFO "Starting balanced_irq\n" ); -if (kernel_thread (balanced_irq,NULL ,CLONE_KERNEL ) >=0 ) +if (!IS_ERR (kthread_run (balanced_irq,NULL ,"kirqd" )))return 0 ; -else -printk (KERN_ERR "balanced_irq_init: failed to spawn balanced_irq" ); +printk (KERN_ERR "balanced_irq_init: failed to spawn balanced_irq" ); failed:for_each_possible_cpu (i) {kfree (irq_cpu_data[i].irq_delta);
PATCH 32/34 x86_64: unexport cpu_llc_id
In reply to Andi KleenFrom: Andrew Morton <[email protected]>
WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.data:cpu_llc_id from __ksymtab between '__ksymtab_cpu_llc_id' (at offset 0x4a0) and '__ksymtab_smp_num_siblings'
It is strange to export a __cpuinitdata symbols to modules, and no module appears to use it anyway.
---
arch/x86_64/kernel/smpboot.c | 1 - 1 file changed, 1 deletion(-)
arch/x86_64/kernel/smpboot.c +0 -1
@@ -67,7 +67,6 @@ EXPORT_SYMBOL(smp_num_siblings);/* Last level cache ID of each logical CPU */ u8 cpu_llc_id[NR_CPUS ]__cpuinitdata = {[0 ...NR_CPUS -1 ] =BAD_APICID }; -EXPORT_SYMBOL (cpu_llc_id);/* Bitmask of currently online CPUs */ cpumask_t cpu_online_map__read_mostly ;
PATCH 26/34 i386: remove xtime_lock'ing around cpufreq notifier
In reply to Andi KleenFrom: Daniel Walker <[email protected]>
The locking of the xtime_lock around the cpu notifier is unessesary now. At one time the tsc was used after a frequency change for timekeeping, but the re-write of timekeeping no longer uses the TSC unless the frequency is constant.
The variables that are changed in this section of code had also once been used for timekeeping, but not any longer ..
---
arch/i386/kernel/tsc.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-)
arch/i386/kernel/tsc.c +1 -7
@@ -144,13 +144,10 @@ time_cpufreq_notifier(struct notifier_bl {struct cpufreq_freqs *freq = data; -if (val !=CPUFREQ_RESUMECHANGE && val !=CPUFREQ_SUSPENDCHANGE ) -write_seqlock_irq (&xtime_lock); -if (!ref_freq) {if (!freq->old){ ref_freq = freq->new; - goto end; +return 0 ; } ref_freq = freq->old; loops_per_jiffy_ref = cpu_data[freq->cpu].loops_per_jiffy;
@@ -176,9 +173,6 @@ time_cpufreq_notifier(struct notifier_bl } } } -end: -if (val !=CPUFREQ_RESUMECHANGE && val !=CPUFREQ_SUSPENDCHANGE ) -write_sequnlock_irq (&xtime_lock);return 0 ; }
PATCH 34/34 x86_64: ignore vgacon if hardware not present
In reply to Andi KleenFrom: Gerd Hoffmann <[email protected]>
Avoid trying to set up vgacon if there's no vga hardware present.
--- drivers/video/console/vgacon.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
===================================================================
drivers/video/console/vgacon.c +2 -1
@@ -371,7 +371,8 @@ static const char *vgacon_startup(void) }/* VGA16 modes are not handled by VGACON */ - if ((ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ + if ((ORIG_VIDEO_MODE == 0x00) || /* SCREEN_INFO not initialized */ + (ORIG_VIDEO_MODE == 0x0D) || /* 320x200/4 */ (ORIG_VIDEO_MODE == 0x0E) || /* 640x200/4 */ (ORIG_VIDEO_MODE == 0x10) || /* 640x350/4 */ (ORIG_VIDEO_MODE == 0x12) || /* 640x480/4 */
PATCH 23/34 i386: check capability
In reply to Andi KleenFrom: "Joachim Deguara" <[email protected]>
Currently the i386 architecture checks the family for mce capability and this removes that and uses the CPUID information. Tested on a K8 revE and a family10h processor.
This eliminates checking of a set AMD procesor family if mce is allowed and relies on the information being in CPUID.
---
arch/i386/kernel/cpu/mcheck/k7.c | 3 +++ arch/i386/kernel/cpu/mcheck/mce.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-)
arch/i386/kernel/cpu/mcheck/k7.c +3 -0
@@ -75,6 +75,9 @@ void amd_mcheck_init(struct cpuinfo_x86 machine_check_vector = k7_machine_check;wmb (); +if (!cpu_has (c,X86_FEATURE_MCE )) +return ; +printk (KERN_INFO "Intel machine check architecture supported.\n" );rdmsr (MSR_IA32_MCG_CAP , l, h);if (l & (1 <<8 ))/* Control register present ? */
arch/i386/kernel/cpu/mcheck/mce.c +1 -2
@@ -38,8 +38,7 @@ void mcheck_init(struct cpuinfo_x86 *c)switch (c->x86_vendor) {case X86_VENDOR_AMD : -if (c->x86==6 || c->x86==15 ) -amd_mcheck_init (c); +amd_mcheck_init (c);break ;case X86_VENDOR_INTEL :
PATCH 17/34 x86: PARAVIRT: Add a sched_clock paravirt_op
In reply to Andi KleenFrom: Jeremy Fitzhardinge <[email protected]>
The tsc-based get_scheduled_cycles interface is not a good match for Xen's runstate accounting, which reports everything in nanoseconds.
This patch replaces this interface with a sched_clock interface, which matches both Xen and VMI's requirements.
In order to do this, we:
1. replace get_scheduled_cycles with sched_clock
2. hoist cycles_2_ns into a common header
3. update vmi accordingly
One thing to note: because sched_clock is implemented as a weak function in kernel/sched.c, we must define a real function in order to override this weak binding. This means the usual paravirt_ops technique of using an inline function won't work in this case.
[ This is against Andi's patch queue. It fixes the x86-64 build problem. ]
--- arch/i386/kernel/paravirt.c | 2 - arch/i386/kernel/sched-clock.c | 43 ++++++++++++++--------------------- arch/i386/kernel/vmi.c | 2 - arch/i386/kernel/vmiclock.c | 4 +-- include/asm-i386/paravirt.h | 7 ++++- include/asm-i386/sched-clock.h | 49 +++++++++++++++++++++++++++++++++++++++++ include/asm-i386/timer.h | 2 - include/asm-i386/vmi_time.h | 2 - include/asm-x86_64/timer.h | 2 - 9 files changed, 78 insertions(+), 35 deletions(-)
===================================================================
arch/i386/kernel/paravirt.c +1 -1
@@ -268,7 +268,7 @@ struct paravirt_ops paravirt_ops = { .write_msr = native_write_msr_safe, .read_tsc = native_read_tsc, .read_pmc = native_read_pmc, - .get_scheduled_cycles = native_read_tsc, + .sched_clock = native_sched_clock, .get_cpu_khz = native_calculate_cpu_khz, .load_tr_desc = native_load_tr_desc, .set_ldt = native_set_ldt,
arch/i386/kernel/sched-clock.c +17 -26
75 lines not on this page · raw message
arch/i386/kernel/vmi.c +1 -1
@@ -890,7 +890,7 @@ static inline int __init activate_vmi(vo paravirt_ops.setup_boot_clock = vmi_time_bsp_init; paravirt_ops.setup_secondary_clock = vmi_time_ap_init;#endif - paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles; + paravirt_ops.sched_clock = vmi_sched_clock; paravirt_ops.get_cpu_khz = vmi_cpu_khz;/* We have true wallclock functions; disable CMOS clock sync */
arch/i386/kernel/vmiclock.c +2 -2
@@ -65,9 +65,9 @@ int vmi_set_wallclock(unsigned long now) }/* paravirt_ops.get_scheduled_cycles = vmi_get_sched_cycles */ -unsigned long long vmi_get_sched_cycles (void ) +unsigned long long vmi_sched_clock (void ) { -return vmi_timer_ops.get_cycle_counter (VMI_CYCLES_AVAILABLE ); +return cycles_2_ns (vmi_timer_ops.get_cycle_counter (VMI_CYCLES_AVAILABLE )); }/* paravirt_ops.get_cpu_khz = vmi_cpu_khz */
include/asm-i386/paravirt.h +5 -2
@@ -116,7 +116,7 @@ struct paravirt_opsu64 (*read_tsc)(void);u64 (*read_pmc)(void); -u64 (*get_scheduled_cycles)(void); +unsigned long long (*sched_clock)(void );unsigned long (*get_cpu_khz)(void );/* Segment descriptor handling */
@@ -573,7 +573,10 @@ static inline u64 paravirt_read_tsc(void#define rdtscll (val) (val = paravirt_read_tsc()) -#define get_scheduled_cycles (val) (val = paravirt_ops.get_scheduled_cycles()) +static inline unsigned long long paravirt_sched_clock (void ) +{ + return PVOP_CALL0(unsigned long long, sched_clock); +}#define calculate_cpu_khz () (paravirt_ops.get_cpu_khz())#define write_tsc (val1,val2) wrmsr(0x10, val1, val2)
include/asm-i386/sched-clock.h new file +49 -0
49 lines not on this page · raw message
include/asm-i386/timer.h +1 -1
@@ -2,6 +2,7 @@#define _ASMi386_TIMER_H#include <linux/init.h> #include <linux/pm.h> +#include <asm/sched-clock.h> #define TICK_SIZE (tick_nsec / 1000)
@@ -15,7 +16,6 @@ extern int no_sync_cmos_clock;extern int recalibrate_cpu_khz (void );#ifndef CONFIG_PARAVIRT -#define get_scheduled_cycles (val) rdtscll(val)#define calculate_cpu_khz () native_calculate_cpu_khz()#endif
include/asm-i386/vmi_time.h +1 -1
@@ -49,7 +49,7 @@ extern struct vmi_timer_ops {extern void __init vmi_time_init (void );extern unsigned long vmi_get_wallclock (void );extern int vmi_set_wallclock (unsigned long now); -extern unsigned long long vmi_get_sched_cycles (void ); +extern unsigned long long vmi_sched_clock (void );extern unsigned long vmi_cpu_khz (void );#ifdef CONFIG_X86_LOCAL_APIC
include/asm-x86_64/timer.h +1 -1
@@ -1 +1 @@ -#define get_scheduled_cycles (x) rdtscll(x) +#include <asm-i386/sched-clock.h>
PATCH 24/34 x86_64: Auto compute __NR_syscall_max at compile time
In reply to Andi KleenNo need to maintain it anymore
--- arch/x86_64/kernel/asm-offsets.c | 10 ++++++++++ arch/x86_64/kernel/syscall.c | 1 + include/asm-x86_64/unistd.h | 2 -- 3 files changed, 11 insertions(+), 2 deletions(-)
arch/x86_64/kernel/asm-offsets.c +10 -0
@@ -21,6 +21,14 @@#define BLANK () asm volatile("\n->" : : ) +#define __NO_STUBS 1 +#undef __SYSCALL +#undef _ASM_X86_64_UNISTD_H_ +#define __SYSCALL (nr, sym) [nr] = 1, +static char syscalls[] = { +#include <asm/unistd.h> +}; +int main (void ) {#define ENTRY (entry) DEFINE(tsk_ ## entry, offsetof(struct task_struct, entry))
@@ -71,5 +79,7 @@ int main(void)DEFINE (TSS_ist, offsetof(struct tss_struct , ist));BLANK ();DEFINE (crypto_tfm_ctx_offset, offsetof(struct crypto_tfm , __crt_ctx)); +BLANK (); +DEFINE (__NR_syscall_max,sizeof (syscalls) -1 );return 0 ; }
arch/x86_64/kernel/syscall.c +1 -0
@@ -3,6 +3,7 @@#include <linux/linkage.h> #include <linux/sys.h> #include <linux/cache.h> +#include <asm/asm-offsets.h> #define __NO_STUBS
include/asm-x86_64/unistd.h +0 -2
@@ -620,8 +620,6 @@ __SYSCALL(__NR_vmsplice, sys_vmsplice)#define __NR_move_pages 279 __SYSCALL(__NR_move_pages, sys_move_pages) -#define __NR_syscall_max __NR_move_pages -#ifndef __NO_STUBS#define __ARCH_WANT_OLD_READDIR#define __ARCH_WANT_OLD_STAT
PATCH 28/34 i386: pte xchg optimization
In reply to Andi KleenFrom: Zachary Amsden <[email protected]>
In situations where page table updates need only be made locally, and there is no cross-processor A/D bit races involved, we need not use the heavyweight xchg instruction to atomically fetch and clear page table entries. Instead, we can just read and clear them directly.
This introduces a neat optimization for non-SMP kernels; drop the atomic xchg operations from page table updates.
Thanks to Michel Lespinasse for noting this potential optimization.
---
include/asm-i386/pgtable-2level.h | 14 ++++++++++++++ include/asm-i386/pgtable-3level.h | 14 ++++++++++++++ 2 files changed, 28 insertions(+)
include/asm-i386/pgtable-2level.h +14 -0
@@ -41,10 +41,24 @@ static inline void native_pte_clear(stru *xp =__pte (0 ); } +/* local pte updates need not use xchg for locking */ +static inline pte_t native_local_ptep_get_and_clear (pte_t *ptep) +{ +pte_t res; + + res = *ptep; +native_pte_clear (NULL ,0 , ptep); +return res; +} + +#ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear (pte_t *xp) {return __pte (xchg (&xp->pte_low,0 )); } +#else +#define native_ptep_get_and_clear (xp) native_local_ptep_get_and_clear(xp) +#endif #define pte_page (x) pfn_to_page(pte_pfn(x))#define pte_none (x) (!(x).pte_low)
include/asm-i386/pgtable-3level.h +14 -0
@@ -139,6 +139,17 @@ static inline void pud_clear (pud_t * pu#define pmd_offset (pud, address) ((pmd_t *) pud_page(*(pud)) + \ pmd_index(address)) +/* local pte updates need not use xchg for locking */ +static inline pte_t native_local_ptep_get_and_clear (pte_t *ptep) +{ +pte_t res; + + res = *ptep; +native_pte_clear (NULL ,0 , ptep); +return res; +} + +#ifdef CONFIG_SMP static inline pte_t native_ptep_get_and_clear (pte_t *ptep) {pte_t res;
@@ -150,6 +161,9 @@ static inline pte_t native_ptep_get_and_ return res; } +#else +#define native_ptep_get_and_clear (xp) native_local_ptep_get_and_clear(xp) +#endif #define __HAVE_ARCH_PTE_SAMEstatic inline int pte_same (pte_t a,pte_t b)
PATCH 5/34 i386: Enable support for fixed-range IORRs to keep RdMem & WrMem in sync
In reply to Andi KleenFrom: Bernhard Kaindl <[email protected]>
If our copy of the MTRRs of the BSP has RdMem or WrMem set, and we are running on an AMD64/K8 system, the boot CPU must have had MtrrFixDramEn and MtrrFixDramModEn set (otherwise our RDMSR would have copied these bits cleared), so we set them on this CPU as well.
This allows us to keep the AMD64/K8 RdMem and WrMem bits in sync across the CPUs of SMP systems in order to fullfill the duty of system software to "initialize and maintain MTRR consistency across all processors." as written in the AMD and Intel manuals.
If an WRMSR instruction fails because MtrrFixDramModEn is not set, I expect that also the Intel-style MTRR bits are not updated.
AK: minor cleanup, moved MSR defines around
--- arch/i386/kernel/cpu/mtrr/generic.c | 85 +++++++++++++++++++++++++----------- include/asm-i386/msr-index.h | 5 ++ 2 files changed, 65 insertions(+), 25 deletions(-)
arch/i386/kernel/cpu/mtrr/generic.c +60 -25
@@ -20,6 +20,18 @@ struct mtrr_state {mtrr_type def_type; }; +struct fixed_range_block { +int base_msr;/* start address of an MTRR block */ +int ranges;/* number of MTRRs in this block */ +}; + +static struct fixed_range_block fixed_range_blocks[] = { + { MTRRfix64K_00000_MSR,1 },/* one 64k MTRR */ + { MTRRfix16K_80000_MSR,2 },/* two 16k MTRRs */ + { MTRRfix4K_C0000_MSR,8 },/* eight 4k MTRRs */ + {} +}; +static unsigned long smp_changes_mask;static struct mtrr_state mtrr_state = {};
@@ -152,6 +164,44 @@ void mtrr_wrmsr(unsigned msr, unsigned a smp_processor_id(), msr, a, b); } +/** +* Enable and allow read/write of extended fixed-range MTRR bits on K8 CPUs +* see AMD publication no. 24593, chapter 3.2.1 for more information +*/ +static inline void k8_enable_fixed_iorrs (void ) +{ +unsigned lo, hi; + +rdmsr (MSR_K8_SYSCFG , lo, hi); +mtrr_wrmsr (MSR_K8_SYSCFG , lo + |K8_MTRRFIXRANGE_DRAM_ENABLE + |K8_MTRRFIXRANGE_DRAM_MODIFY , hi); +} + +/** +* Checks and updates an fixed-range MTRR if it differs from the value it +* should have. If K8 extenstions are wanted, update the K8 SYSCFG MSR also. +* see AMD publication no. 24593, chapter 7.8.1, page 233 for more information +* \param msr MSR address of the MTTR which should be checked and updated +* \param changed pointer which indicates whether the MTRR needed to be changed +* \param msrwords pointer to the MSR values which the MSR should have +*/ +static void set_fixed_range (int msr,int * changed,unsigned int * msrwords) +{ +unsigned lo, hi; + +rdmsr (msr, lo, hi); + +if (lo != msrwords[0 ] || hi != msrwords[1 ]) { +if (boot_cpu_data.x86_vendor ==X86_VENDOR_AMD && + boot_cpu_data.x86 ==15 && + ((msrwords[0 ] | msrwords[1 ]) &K8_MTRR_RDMEM_WRMEM_MASK )) +k8_enable_fixed_iorrs (); +mtrr_wrmsr (msr, msrwords[0 ], msrwords[1 ]); + *changed = TRUE; + } +} +int generic_get_free_region (unsigned long base,unsigned long size,int replace_reg)/* [SUMMARY] Get a free MTRR. <base> The starting (base) address of the region.
@@ -201,36 +251,21 @@ static void generic_get_mtrr(unsigned in *type = base_lo &0xff ; } +/** +* Checks and updates the fixed-range MTRRs if they differ from the saved set +* \param frs pointer to fixed-range MTRR values, saved by get_fixed_ranges() +*/ static int set_fixed_ranges (mtrr_type * frs) { -unsigned int *p = (unsigned int *) frs; +unsigned long long *saved = (unsigned long long *) frs;int changed = FALSE; -int i; -unsigned int lo, hi; - -rdmsr (MTRRfix64K_00000_MSR, lo, hi); -if (p[0 ] != lo || p[1 ] != hi) { -mtrr_wrmsr (MTRRfix64K_00000_MSR, p[0 ], p[1 ]); - changed = TRUE; - } +int block=-1 , range; -for (i =0 ; i <2 ; i++) { -rdmsr (MTRRfix16K_80000_MSR + i, lo, hi); -if (p[2 + i *2 ] != lo || p[3 + i *2 ] != hi) { -mtrr_wrmsr (MTRRfix16K_80000_MSR + i, p[2 + i *2 ], - p[3 + i *2 ]); - changed = TRUE; - } - } +while (fixed_range_blocks[++block].ranges) +for (range=0 ; range < fixed_range_blocks[block].ranges; range++) +set_fixed_range (fixed_range_blocks[block].base_msr + range, + &changed, (unsigned int *) saved++); -for (i =0 ; i <8 ; i++) { -rdmsr (MTRRfix4K_C0000_MSR + i, lo, hi); -if (p[6 + i *2 ] != lo || p[7 + i *2 ] != hi) { -mtrr_wrmsr (MTRRfix4K_C0000_MSR + i, p[6 + i *2 ], - p[7 + i *2 ]); - changed = TRUE; - } - }return changed; }
include/asm-i386/msr-index.h +5 -0
@@ -87,6 +87,11 @@#define MSR_K7_CLK_CTL 0xc001001b#define MSR_K8_TOP_MEM2 0xc001001d#define MSR_K8_SYSCFG 0xc0010010 + +#define K8_MTRRFIXRANGE_DRAM_ENABLE 0x00040000/* MtrrFixDramEn bit */ +#define K8_MTRRFIXRANGE_DRAM_MODIFY 0x00080000/* MtrrFixDramModEn bit */ +#define K8_MTRR_RDMEM_WRMEM_MASK 0x18181818/* Mask: RdMem|WrMem */ +#define MSR_K7_HWCR 0xc0010015#define MSR_K8_HWCR 0xc0010015#define MSR_K7_FID_VID_CTL 0xc0010041
PATCH 3/34 x86: Save the MTRRs of the BSP before booting an AP
In reply to Andi KleenFrom: Bernhard Kaindl <[email protected]>
Applied fix by Andew Morton:
http://lkml.org/lkml/2007/4/8/88 - Fix `make headers_check'.
AMD and Intel x86 CPU manuals state that it is the responsibility of system software to initialize and maintain MTRR consistency across all processors in Multi-Processing Environments.
Quote from page 188 of the AMD64 System Programming manual (Volume 2):
7.6.5 MTRRs in Multi-Processing Environments
"In multi-processing environments, the MTRRs located in all processors must characterize memory in the same way. Generally, this means that identical values are written to the MTRRs used by the processors." (short omission here) "Failure to do so may result in coherency violations or loss of atomicity. Processor implementations do not check the MTRR settings in other processors to ensure consistency. It is the responsibility of system software to initialize and maintain MTRR consistency across all processors."
Current Linux MTRR code already implements the above in the case that the BIOS does not properly initialize MTRRs on the secondary processors, but the case where the fixed-range MTRRs of the boot processor are changed after Linux started to boot, before the initialsation of a secondary processor, is not handled yet.
In this case, secondary processors are currently initialized by Linux with MTRRs which the boot processor had very early, when mtrr_bp_init() did run, but not with the MTRRs which the boot processor uses at the time when that secondary processors is actually booted, causing differing MTRR contents on the secondary processors.
Such situation happens on Acer Ferrari 1000 and 5000 notebooks where the BIOS enables and sets AMD-specific IORR bits in the fixed-range MTRRs of the boot processor when it transitions the system into ACPI mode. The SMI handler of the BIOS does this in SMM, entered while Linux ACPI code runs acpi_enable().
Other occasions where the SMI handler of the BIOS may change bits in the MTRRs could occur as well. To initialize newly booted secodary processors with the fixed-range MTRRs which the boot processor uses at that time, this patch saves the fixed-range MTRRs of the boot processor before new secondary processors are started. When the secondary processors run their Linux initialisation code, their fixed-range MTRRs will be updated with the saved fixed-range MTRRs.
If CONFIG_MTRR is not set, we define mtrr_save_state as an empty statement because there is nothing to do.
Possible TODOs:
*) CPU-hotplugging outside of SMP suspend/resume is not yet tested
with this patch.
*) If, even in this case, an AP never runs i386/do_boot_cpu or x86_64/cpu_up,
then the calls to mtrr_save_state() could be replaced by calls to mtrr_save_fixed_ranges(NULL) and mtrr_save_state() would not be needed.
That would need either verification of the CPU-hotplug code or at least a test on a >2 CPU machine.
*) The MTRRs of other running processors are not yet checked at this
time but it might be interesting to syncronize the MTTRs of all processors before booting. That would be an incremental patch, but of rather low priority since there is no machine known so far which would require this.
AK: moved prototypes on x86-64 around to fix warnings
--- arch/i386/kernel/cpu/mtrr/main.c | 11 +++++++++++ arch/i386/kernel/smpboot.c | 7 +++++++ arch/x86_64/kernel/smpboot.c | 6 ++++++ include/asm-i386/mtrr.h | 2 ++ include/asm-x86_64/mtrr.h | 2 ++ 5 files changed, 28 insertions(+)
arch/i386/kernel/smpboot.c +7 -0
@@ -58,6 +58,7 @@#include <mach_wakecpu.h> #include <smpboot_hooks.h> #include <asm/vmi.h> +#include <asm/mtrr.h> /* Set if we find a B stepping CPU */ static int __devinitdata smp_b_stepping;
@@ -815,6 +816,12 @@ static int __cpuinit do_boot_cpu(int apiunsigned short nmi_high =0 , nmi_low =0 ;/* +* Save current MTRR state in case it was changed since early boot +* (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: +*/ +mtrr_save_state (); + +/* * We can't use kernel_thread since we must avoid to * reschedule the child. */
arch/x86_64/kernel/smpboot.c +6 -0
@@ -944,6 +944,12 @@ int __cpuinit __cpu_up(unsigned int cpu)return -ENOSYS ; } +/* +* Save current MTRR state in case it was changed since early boot +* (e.g. by the ACPI SMI) to initialize new CPUs with MTRRs in sync: +*/ +mtrr_save_state (); +per_cpu (cpu_state, cpu) =CPU_UP_PREPARE ;/* Boot it! */ err =do_boot_cpu (cpu, apicid);
include/asm-i386/mtrr.h +2 -0
@@ -70,6 +70,7 @@ struct mtrr_gentry/* The following functions are for use by other drivers */ # ifdef CONFIG_MTRR extern void mtrr_save_fixed_ranges (void *); +extern void mtrr_save_state (void );extern int mtrr_add (unsigned long base,unsigned long size,unsigned int type,char increment); extern int mtrr_add_page (unsigned long base, unsigned long size,
@@ -81,6 +82,7 @@ extern void mtrr_ap_init(void);extern void mtrr_bp_init (void );# else #define mtrr_save_fixed_ranges (arg) do {} while (0) +#define mtrr_save_state () do {} while (0)static __inline__int mtrr_add (unsigned long base,unsigned long size,unsigned int type,char increment) {
arch/i386/kernel/cpu/mtrr/main.c +11 -0
@@ -729,6 +729,17 @@ void mtrr_ap_init(void)local_irq_restore (flags); } +/** +* Save current fixed-range MTRR state of the BSP +*/ +void mtrr_save_state (void ) +{ +if (smp_processor_id () ==0 ) +mtrr_save_fixed_ranges (NULL ); +else +smp_call_function_single (0 , mtrr_save_fixed_ranges,NULL ,1 ,1 ); +} +static int __init mtrr_init_finialize (void ) {if (!mtrr_if)
include/asm-x86_64/mtrr.h +2 -0
@@ -139,10 +139,12 @@ struct mtrr_gentry32extern void mtrr_ap_init (void );extern void mtrr_bp_init (void );extern void mtrr_save_fixed_ranges (void *); +extern void mtrr_save_state (void );#else #define mtrr_ap_init () do {} while (0)#define mtrr_bp_init () do {} while (0)#define mtrr_save_fixed_ranges (arg) do {} while (0) +#define mtrr_save_state () do {} while (0)#endif #endif /* __KERNEL__ */
PATCH 22/34 i386: clean up flush_tlb_others fn
In reply to Andi KleenFrom: "Keshavamurthy, Anil S" <[email protected]>
Cleanup flush_tlb_others(), no functional change.
---
arch/i386/kernel/smp.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-)
arch/i386/kernel/smp.c +1 -11
@@ -375,17 +375,7 @@ void native_flush_tlb_others(const cpuma flush_mm = mm; flush_va = va; -#if NR_CPUS <=BITS_PER_LONG -atomic_set_mask (cpumask, &flush_cpumask); -#else - { -int k; -unsigned long *flush_mask = (unsigned long *)&flush_cpumask; -unsigned long *cpu_mask = (unsigned long *)&cpumask; -for (k =0 ; k <BITS_TO_LONGS (NR_CPUS ); ++k) -atomic_set_mask (cpu_mask[k], &flush_mask[k]); - } -#endif +cpus_or (flush_cpumask, cpumask, flush_cpumask);/* * We have to send the IPI only to * CPUs affected.
PATCH 7/34 x86_64: safe_apic_wait_icr_idle - x86_64
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
apic_wait_icr_idle looks like this:
static __inline__ void apic_wait_icr_idle(void)
{
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
cpu_relax(); }
The busy loop in this function would not be problematic if the corresponding status bit in the ICR were always updated, but that does not seem to be the case under certain crash scenarios. Kdump uses an IPI to stop the other CPUs in the event of a crash, but when any of the other CPUs are locked-up inside the NMI handler the CPU that sends the IPI will end up looping forever in the ICR check, effectively hard-locking the whole system.
Quoting from Intel's "MultiProcessor Specification" (Version 1.4), B-3:
"A local APIC unit indicates successful dispatch of an IPI by resetting the Delivery Status bit in the Interrupt Command Register (ICR). The operating system polls the delivery status bit after sending an INIT or STARTUP IPI until the command has been dispatched.
A period of 20 microseconds should be sufficient for IPI dispatch to complete under normal operating conditions. If the IPI is not successfully dispatched, the operating system can abort the command. Alternatively, the operating system can retry the IPI by writing the lower 32-bit double word of the ICR. This “time-out” mechanism can be implemented through an external interrupt, if interrupts are enabled on the processor, or through execution of an instruction or time-stamp counter spin loop."
Intel's documentation suggests the implementation of a time-out mechanism, which, by the way, is already being open-coded in some parts of the kernel that tinker with ICR.
Create a apic_wait_icr_idle replacement that implements the time-out mechanism and that can be used to solve the aforementioned problem.
AK: moved both functions out of line
AK: Added improved loop from Keith Owens
---
--- arch/x86_64/kernel/apic.c | 22 ++++++++++++++++++++++ include/asm-x86_64/apic.h | 8 +++----- 2 files changed, 25 insertions(+), 5 deletions(-)
include/asm-x86_64/apic.h +3 -5
@@ -2,6 +2,7 @@#define __ASM_APIC_H#include <linux/pm.h> +#include <linux/delay.h> #include <asm/fixmap.h> #include <asm/apicdef.h> #include <asm/system.h>
@@ -47,11 +48,8 @@ static __inline unsigned int apic_read(ureturn *((volatile unsigned int *)(APIC_BASE +reg)); } -static __inline__void apic_wait_icr_idle (void ) -{ -while (apic_read (APIC_ICR ) &APIC_ICR_BUSY ) -cpu_relax (); -} +extern void apic_wait_icr_idle (void ); +extern unsigned int safe_apic_wait_icr_idle (void );static inline void ack_APIC_irq (void ) {
arch/x86_64/kernel/apic.c +22 -0
@@ -68,6 +68,28 @@ int using_apic_timer __read_mostly = 0;static void apic_pm_activate (void ); +void apic_wait_icr_idle (void ) +{ +while (apic_read (APIC_ICR ) &APIC_ICR_BUSY ) +cpu_relax (); +} + +unsigned int safe_apic_wait_icr_idle (void ) +{ +unsigned int send_status; +int timeout; + + timeout =0 ; +do { + send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; +if (!send_status) +break ; +udelay (100 ); + }while (timeout++ <1000 ); + +return send_status; +} +void enable_NMI_through_LVT0 (void * dummy) {unsigned int v;
cover x86 candidate patches for review VI: MTRR, APIC, more paravirt, misc
Various more x86 patches:
- Safer APIC access during kcrash
- Handle fixed MTRRs on K8
- A few more paravirt changes
- Pagetable optimizations from Zach
- Slab optimization for non NUMA systems from Suresh
- Support machine checks on AMD Fam10 on 32bit kernels from Joachim
- Other misc stuff
Happy reviewing!
-Andi
PATCH 1/34 x86_64: Move mtrr prototypes from proto.h to mtrr.h
--- include/asm-x86_64/mtrr.h | 8 ++++++++ include/asm-x86_64/proto.h | 7 ------- 2 files changed, 8 insertions(+), 7 deletions(-)
include/asm-x86_64/mtrr.h +8 -0
@@ -135,6 +135,14 @@ struct mtrr_gentry32#endif /* CONFIG_COMPAT */ +#ifdef CONFIG_MTRR +extern void mtrr_ap_init (void ); +extern void mtrr_bp_init (void ); +#else +#define mtrr_ap_init () do {} while (0) +#define mtrr_bp_init () do {} while (0) +#endif +#endif /* __KERNEL__ */ #endif /* _LINUX_MTRR_H */
include/asm-x86_64/proto.h +0 -7
@@ -14,13 +14,6 @@ extern void pda_init(int);extern void early_idt_handler (void );extern void mcheck_init (struct cpuinfo_x86 *c); -#ifdef CONFIG_MTRR -extern void mtrr_ap_init (void ); -extern void mtrr_bp_init (void ); -#else -#define mtrr_ap_init () do {} while (0) -#define mtrr_bp_init () do {} while (0) -#endif extern void init_memory_mapping (unsigned long start,unsigned long end);extern void system_call (void );
PATCH 6/34 i386: safe_apic_wait_icr_idle - i386
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
apic_wait_icr_idle looks like this:
static __inline__ void apic_wait_icr_idle(void)
{
while (apic_read(APIC_ICR) & APIC_ICR_BUSY)
cpu_relax(); }
The busy loop in this function would not be problematic if the corresponding status bit in the ICR were always updated, but that does not seem to be the case under certain crash scenarios. Kdump uses an IPI to stop the other CPUs in the event of a crash, but when any of the other CPUs are locked-up inside the NMI handler the CPU that sends the IPI will end up looping forever in the ICR check, effectively hard-locking the whole system.
Quoting from Intel's "MultiProcessor Specification" (Version 1.4), B-3:
"A local APIC unit indicates successful dispatch of an IPI by resetting the Delivery Status bit in the Interrupt Command Register (ICR). The operating system polls the delivery status bit after sending an INIT or STARTUP IPI until the command has been dispatched.
A period of 20 microseconds should be sufficient for IPI dispatch to complete under normal operating conditions. If the IPI is not successfully dispatched, the operating system can abort the command. Alternatively, the operating system can retry the IPI by writing the lower 32-bit double word of the ICR. This “time-out” mechanism can be implemented through an external interrupt, if interrupts are enabled on the processor, or through execution of an instruction or time-stamp counter spin loop."
Intel's documentation suggests the implementation of a time-out mechanism, which, by the way, is already being open-coded in some parts of the kernel that tinker with ICR.
Create a apic_wait_icr_idle replacement that implements the time-out mechanism and that can be used to solve the aforementioned problem.
AK: moved both functions out of line
AK: added improved loop from Keith Owens
---
--- arch/i386/kernel/apic.c | 22 ++++++++++++++++++++++ include/asm-i386/apic.h | 9 +++------ 2 files changed, 25 insertions(+), 6 deletions(-)
include/asm-i386/apic.h +3 -6
@@ -2,6 +2,7 @@#define __ASM_APIC_H#include <linux/pm.h> +#include <linux/delay.h> #include <asm/fixmap.h> #include <asm/apicdef.h> #include <asm/processor.h>
@@ -64,12 +65,8 @@ static __inline fastcall unsigned long nreturn *((volatile unsigned long *)(APIC_BASE +reg)); } -static __inline__void apic_wait_icr_idle (void ) -{ -while (apic_read (APIC_ICR ) &APIC_ICR_BUSY ) -cpu_relax (); -} - +void apic_wait_icr_idle (void ); +unsigned long safe_apic_wait_icr_idle (void );int get_physical_broadcast (void );#ifdef CONFIG_X86_GOOD_APIC
arch/i386/kernel/apic.c +22 -0
@@ -129,6 +129,28 @@ static int modern_apic(void)return lapic_get_version () >=0x14 ; } +void apic_wait_icr_idle (void ) +{ +while (apic_read (APIC_ICR ) &APIC_ICR_BUSY ) +cpu_relax (); +} + +unsigned long safe_apic_wait_icr_idle (void ) +{ +unsigned long send_status; +int timeout; + + timeout =0 ; +do { + send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; +if (!send_status) +break ; +udelay (100 ); + }while (timeout++ <1000 ); + +return send_status; +} +/** * enable_NMI_through_LVT0 - enable NMI through local vector table 0 */
PATCH 10/34 i386: use safe_apic_wait_icr_idle in smpboot.c
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
__inquire_remote_apic is used for APIC debugging, so use safe_apic_wait_icr_idle instead of apic_wait_icr_idle to avoid possible lockups when APIC delivery fails.
---
--- arch/i386/kernel/smpboot.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
arch/i386/kernel/smpboot.c +5 -2
@@ -521,7 +521,8 @@ static inline void __inquire_remote_apic {int i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };char *names[] = {"ID" ,"VERSION" ,"SPIV" }; -int timeout, status; +int timeout; +unsigned long status;printk ("Inquiring remote APIC #%d...\n" , apicid);
@@ -531,7 +532,9 @@ static inline void __inquire_remote_apic/* * Wait for idle. */ -apic_wait_icr_idle (); + status =safe_apic_wait_icr_idle (); +if (status) +printk ("a previous APIC delivery may have failed\n" );apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid));apic_write_around (APIC_ICR ,APIC_DM_REMRD | regs[i]);
PATCH 9/34 x86_64: use safe_apic_wait_icr_idle in smpboot.c - x86_64
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
The functionality provided by the new safe_apic_wait_icr_idle is being open-coded all over "kernel/smpboot.c". Use safe_apic_wait_icr_idle instead to consolidate code and ease maintenance.
---
--- arch/x86_64/kernel/smpboot.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-)
arch/x86_64/kernel/smpboot.c +5 -20
@@ -429,8 +429,8 @@ static void inquire_remote_apic(int apic*/ static int __cpuinit wakeup_secondary_via_INIT (int phys_apicid,unsigned int start_rip) { -unsigned long send_status =0 , accept_status =0 ; -int maxlvt, timeout, num_starts, j; +unsigned long send_status, accept_status =0 ; +int maxlvt, num_starts, j;Dprintk ("Asserting INIT.\n" );
@@ -446,12 +446,7 @@ static int __cpuinit wakeup_secondary_vi | APIC_DM_INIT);Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();mdelay (10 );
@@ -464,12 +459,7 @@ static int __cpuinit wakeup_secondary_viapic_write (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_DM_INIT );Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();mb ();atomic_set (&init_deasserted,1 );
@@ -508,12 +498,7 @@ static int __cpuinit wakeup_secondary_viDprintk ("Startup point 1.\n" );Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();/* * Give the other CPU some time to accept the IPI.
PATCH 8/34 i386: use safe_apic_wait_icr_idle - i386
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
The functionality provided by the new safe_apic_wait_icr_idle is being open-coded all over "kernel/smpboot.c". Use safe_apic_wait_icr_idle instead to consolidate code and ease maintenance.
---
--- arch/i386/kernel/smpboot.c | 36 ++++++++---------------------------- 1 file changed, 8 insertions(+), 28 deletions(-)
arch/i386/kernel/smpboot.c +8 -28
@@ -563,8 +563,8 @@ static inline void __inquire_remote_apicstatic int __devinit wakeup_secondary_cpu (int logical_apicid,unsigned long start_eip) { -unsigned long send_status =0 , accept_status =0 ; -int timeout, maxlvt; +unsigned long send_status, accept_status =0 ; +int maxlvt;/* Target chip */ apic_write_around (APIC_ICR2 ,SET_APIC_DEST_FIELD (logical_apicid));
@@ -574,12 +574,7 @@ wakeup_secondary_cpu(int logical_apicid,apic_write_around (APIC_ICR ,APIC_DM_NMI |APIC_DEST_LOGICAL );Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();/* * Give the other CPU some time to accept the IPI.
@@ -609,8 +604,8 @@ wakeup_secondary_cpu(int logical_apicid,static int __devinit wakeup_secondary_cpu (int phys_apicid,unsigned long start_eip) { -unsigned long send_status =0 , accept_status =0 ; -int maxlvt, timeout, num_starts, j; +unsigned long send_status, accept_status =0 ; +int maxlvt, num_starts, j;/* * Be paranoid about clearing APIC errors.
@@ -635,12 +630,7 @@ wakeup_secondary_cpu(int phys_apicid, un | APIC_DM_INIT);Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();mdelay (10 );
@@ -653,12 +643,7 @@ wakeup_secondary_cpu(int phys_apicid, unapic_write_around (APIC_ICR ,APIC_INT_LEVELTRIG |APIC_DM_INIT );Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();atomic_set (&init_deasserted,1 );
@@ -714,12 +699,7 @@ wakeup_secondary_cpu(int phys_apicid, unDprintk ("Startup point 1.\n" );Dprintk ("Waiting for send to finish...\n" ); - timeout =0 ; -do { -Dprintk ("+" ); -udelay (100 ); - send_status =apic_read (APIC_ICR ) &APIC_ICR_BUSY ; - }while (send_status && (timeout++ <1000 )); + send_status =safe_apic_wait_icr_idle ();/* * Give the other CPU some time to accept the IPI.
PATCH 12/34 i386: __send_IPI_dest_field - i386
In reply to Andi KleenFrom: Fernando Luis [** ISO-8859-1 charset **] V�zquezCao <[email protected]> Implement __send_IPI_dest_field which can be used to send IPIs when the "destination shorthand" field of the ICR is set to 00 (destination field). Use it whenever possible.
---
--- arch/i386/kernel/smp.c | 47 ++++++++++++++++++----------------------------- 1 file changed, 18 insertions(+), 29 deletions(-)
arch/i386/kernel/smp.c +18 -29
@@ -165,16 +165,13 @@ void fastcall send_IPI_self(int vector) }/* -* This is only used on smaller machines. +* This is used to send an IPI with no shorthand notation (the destination is +* specified in bits 56 to 63 of the ICR). */ -void send_IPI_mask_bitmask (cpumask_t cpumask,int vector) +static inline void __send_IPI_dest_field (unsigned long mask,int vector) { -unsigned long mask =cpus_addr (cpumask)[0 ];unsigned long cfg; -unsigned long flags; -local_irq_save (flags); -WARN_ON (mask & ~cpus_addr (cpu_online_map)[0 ]);/* * Wait for idle. */
@@ -195,13 +192,25 @@ void send_IPI_mask_bitmask(cpumask_t cpu* Send the IPI. The write to APIC_ICR fires this off. */ apic_write_around (APIC_ICR , cfg); +} +/* +* This is only used on smaller machines. +*/ +void send_IPI_mask_bitmask (cpumask_t cpumask,int vector) +{ +unsigned long mask =cpus_addr (cpumask)[0 ]; +unsigned long flags; + +local_irq_save (flags); +WARN_ON (mask & ~cpus_addr (cpu_online_map)[0 ]); +__send_IPI_dest_field (mask, vector);local_irq_restore (flags); }void send_IPI_mask_sequence (cpumask_t mask,int vector) { -unsigned long cfg, flags; +unsigned long flags;unsigned int query_cpu;/*
@@ -211,30 +220,10 @@ void send_IPI_mask_sequence(cpumask_t ma*/ local_irq_save (flags); -for (query_cpu =0 ; query_cpu <NR_CPUS ; ++query_cpu) {if (cpu_isset (query_cpu, mask)) { - -/* -* Wait for idle. -*/ -apic_wait_icr_idle (); - -/* -* prepare target chip field -*/ - cfg =__prepare_ICR2 (cpu_to_logical_apicid (query_cpu)); -apic_write_around (APIC_ICR2 , cfg); - -/* -* program the ICR -*/ - cfg =__prepare_ICR (0 , vector); - -/* -* Send the IPI. The write to APIC_ICR fires this off. -*/ -apic_write_around (APIC_ICR , cfg); +__send_IPI_dest_field (cpu_to_logical_apicid (query_cpu), + vector); } }local_irq_restore (flags);
PATCH 11/34 x86_64: use safe_apic_wait_icr_idle in smpboot.c - x86_64
In reply to Andi KleenFrom: Fernando Luis VazquezCao <[email protected]>
inquire_remote_apic is used for APIC debugging, so use safe_apic_wait_icr_idle instead of apic_wait_icr_idle to avoid possible lockups when APIC delivery fails.
---
--- arch/x86_64/kernel/smpboot.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-)
arch/x86_64/kernel/smpboot.c +5 -2
@@ -391,7 +391,8 @@ static void inquire_remote_apic(int apic {unsigned i, regs[] = {APIC_ID >>4 ,APIC_LVR >>4 ,APIC_SPIV >>4 };char *names[] = {"ID" ,"VERSION" ,"SPIV" }; -int timeout, status; +int timeout; +unsigned int status;printk (KERN_INFO "Inquiring remote APIC #%d...\n" , apicid);
@@ -401,7 +402,9 @@ static void inquire_remote_apic(int apic/* * Wait for idle. */ -apic_wait_icr_idle (); + status =safe_apic_wait_icr_idle (); +if (status) +printk ("a previous APIC delivery may have failed\n" );apic_write (APIC_ICR2 ,SET_APIC_DEST_FIELD (apicid));apic_write (APIC_ICR ,APIC_DM_REMRD | regs[i]);
PATCH 14/34 i386: Use safe_apic_wait_icr_idle in safe_apic_wait_icr_idle - i386
In reply to Andi KleenFrom: Fernando Luis [** ISO-8859-1 charset **] V�zquezCao <[email protected]> Use safe_apic_wait_icr_idle to check ICR idle bit if the vector is NMI_VECTOR to avoid potential hangups in the event of crash when kdump tries to stop the other CPUs.
---
--- arch/i386/kernel/smp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
arch/i386/kernel/smp.c +4 -1
@@ -175,7 +175,10 @@ static inline void __send_IPI_dest_field/* * Wait for idle. */ -apic_wait_icr_idle (); +if (unlikely (vector ==NMI_VECTOR )) +safe_apic_wait_icr_idle (); +else +apic_wait_icr_idle ();/* * prepare target chip field
PATCH 21/34 i386: replace spin_lock_irqsave with spin_lock
In reply to Andi KleenFrom: Hisashi Hifumi <[email protected]>
IRQ is already disabled through local_irq_disable(). So spin_lock_irqsave() can be replaced with spin_lock().
---
arch/i386/kernel/reboot.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-)
arch/i386/kernel/reboot.c +2 -4
@@ -198,8 +198,6 @@ static unsigned char jump_to_bios [] =*/ void machine_real_restart (unsigned char *code,int length) { -unsigned long flags; -local_irq_disable ();/* Write zero to CMOS register number 0x0f, which the BIOS POST
@@ -212,9 +210,9 @@ void machine_real_restart(unsigned charsafe side. (Yes, CMOS_WRITE does outb_p's. - Paul G.) */ -spin_lock_irqsave (&rtc_lock, flags); +spin_lock (&rtc_lock);CMOS_WRITE (0x00 ,0x8f ); -spin_unlock_irqrestore (&rtc_lock, flags); +spin_unlock (&rtc_lock);/* Remap the kernel at virtual address zero, as well as offset zero from the kernel segment. This assumes the kernel segment starts at
PATCH 13/34 x86_64: __send_IPI_dest_field - x86_64
In reply to Andi KleenFrom: Fernando Luis [** ISO-8859-1 charset **] V�zquezCao <[email protected]> Implement __send_IPI_dest_field which can be used to send IPIs when the "destination shorthand" field of the ICR is set to 00 (destination field). Use it whenever possible.
---
--- arch/x86_64/kernel/genapic_flat.c | 23 ---------------- include/asm-x86_64/ipi.h | 54 ++++++++++++++++++++++---------------- 2 files changed, 33 insertions(+), 44 deletions(-)
arch/x86_64/kernel/genapic_flat.c +1 -22
@@ -61,31 +61,10 @@ static void flat_init_apic_ldr(void)static void flat_send_IPI_mask (cpumask_t cpumask,int vector) {unsigned long mask =cpus_addr (cpumask)[0 ]; -unsigned long cfg;unsigned long flags;local_irq_save (flags); - -/* -* Wait for idle. -*/ -apic_wait_icr_idle (); - -/* -* prepare target chip field -*/ - cfg =__prepare_ICR2 (mask); -apic_write (APIC_ICR2 , cfg); - -/* -* program the ICR -*/ - cfg =__prepare_ICR (0 , vector,APIC_DEST_LOGICAL ); - -/* -* Send the IPI. The write to APIC_ICR fires this off. -*/ -apic_write (APIC_ICR , cfg); +__send_IPI_dest_field (mask, vector,APIC_DEST_LOGICAL );local_irq_restore (flags); }
include/asm-x86_64/ipi.h +32 -22
70 lines not on this page · raw message
PATCH 19/34 x86_64: move __vgetcpu_mode & __jiffies to the vsyscall_2 zone
In reply to Andi KleenFrom: Eric Dumazet <[email protected]>
We apparently hit the 1024 limit of vsyscall_0 zone when some debugging options are set, or if __vsyscall_gtod_data is 64 bytes larger.
In order to save 128 bytes from the vsyscall_0 zone, we move __vgetcpu_mode & __jiffies to vsyscall_2 zone where they really belong, since they are used only from vgetcpu() (which is in this vsyscall_2 area).
After patch is applied, new layout is :
ffffffffff600000 T vgettimeofdayffffffffff60004e t vsysc2ffffffffff600140 t vread_hpetffffffffff600150 t vread_tscffffffffff600180 D __vsyscall_gtod_dataffffffffff600400 T vtimeffffffffff600413 t vsysc1ffffffffff600800 T vgetcpuffffffffff600870 D __vgetcpu_modeffffffffff600880 D __jiffiesffffffffff600c00 T venosys_1
---
arch/x86_64/kernel/vmlinux.lds.S | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-)
arch/x86_64/kernel/vmlinux.lds.S +6 -4
@@ -95,6 +95,12 @@ SECTIONS { *(.vsyscall_gtod_data) } vsyscall_gtod_data = VVIRT(.vsyscall_gtod_data); + + .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) + { *(.vsyscall_1) } + .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) + { *(.vsyscall_2) } + .vgetcpu_mode : AT(VLOAD(.vgetcpu_mode)) { *(.vgetcpu_mode) } vgetcpu_mode = VVIRT(.vgetcpu_mode);
@@ -102,10 +108,6 @@ SECTIONS .jiffies : AT(VLOAD(.jiffies)) { *(.jiffies) } jiffies = VVIRT(.jiffies); - .vsyscall_1 ADDR(.vsyscall_0) + 1024: AT(VLOAD(.vsyscall_1)) - { *(.vsyscall_1) } - .vsyscall_2 ADDR(.vsyscall_0) + 2048: AT(VLOAD(.vsyscall_2)) - { *(.vsyscall_2) } .vsyscall_3 ADDR(.vsyscall_0) + 3072: AT(VLOAD(.vsyscall_3)) { *(.vsyscall_3) }
PATCH 15/34 x86_64: Use safe_apic_wait_icr_idle in __send_IPI_dest_field - x86_64
In reply to Andi KleenFrom: Fernando Luis [** ISO-8859-1 charset **] V�zquezCao <[email protected]> Use safe_apic_wait_icr_idle to check ICR idle bit if the vector is NMI_VECTOR to avoid potential hangups in the event of crash when kdump tries to stop the other CPUs.
---
--- include/asm-x86_64/ipi.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-)
include/asm-x86_64/ipi.h +4 -1
@@ -85,7 +85,10 @@ static inline void __send_IPI_dest_field/* * Wait for idle. */ -apic_wait_icr_idle (); +if (unlikely (vector ==NMI_VECTOR )) +safe_apic_wait_icr_idle (); +else +apic_wait_icr_idle ();/* * prepare target chip field
PATCH 16/34 i386: fix mtrr sections
In reply to Andi KleenFrom: Randy Dunlap <[email protected]>
Fix section mismatch warnings in mtrr code.
Fix line length on one source line.
WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.data: from .text.get_mtrr_state after 'get_mtrr_state' (at offset 0x103)
WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset 0x180)
WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset 0x199)
WARNING: arch/x86_64/kernel/built-in.o - Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset 0x1c1)
---
arch/i386/kernel/cpu/mtrr/generic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
arch/i386/kernel/cpu/mtrr/generic.c +4 -3
@@ -38,7 +38,7 @@ static struct mtrr_state mtrr_state = {}#undef MODULE_PARAM_PREFIX#define MODULE_PARAM_PREFIX "mtrr." -static __initdata int mtrr_show; +static int mtrr_show;module_param_named (show, mtrr_show, bool,0 );/* Get the MSR pair relating to a var range */
@@ -68,12 +68,13 @@ void mtrr_save_fixed_ranges(void *info)get_fixed_ranges (mtrr_state.fixed_ranges); } -static void __init print_fixed (unsigned base,unsigned step,const mtrr_type *types) +static void __cpuinit print_fixed (unsigned base,unsigned step,const mtrr_type *types) {unsigned i;for (i =0 ; i <8 ; ++i, ++types, base += step) -printk (KERN_INFO "MTRR %05X-%05X %s\n" , base, base + step -1 ,mtrr_attrib_to_str (*types)); +printk (KERN_INFO "MTRR %05X-%05X %s\n" , + base, base + step -1 ,mtrr_attrib_to_str (*types)); }/* Grab all of the MTRR state for this CPU into *state */
PATCH 18/34 i386: PARAVIRT: fix startup_ipi_hook config dependency
In reply to Andi KleenFrom: Jeremy Fitzhardinge <[email protected]> startup_ipi_hook depends on CONFIG_X86_LOCAL_APIC, so move it to the right part of the paravirt_ops initialization.
--- arch/i386/kernel/paravirt.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
===================================================================
arch/i386/kernel/paravirt.c +1 -2
@@ -292,6 +292,7 @@ struct paravirt_ops paravirt_ops = { .apic_read = native_apic_read, .setup_boot_clock = setup_boot_APIC_clock, .setup_secondary_clock = setup_secondary_APIC_clock, + .startup_ipi_hook = paravirt_nop, #endif .set_lazy_mode = paravirt_nop,
@@ -342,8 +343,6 @@ struct paravirt_ops paravirt_ops = { .dup_mmap = paravirt_nop, .exit_mmap = paravirt_nop, .activate_mm = paravirt_nop, - - .startup_ipi_hook = paravirt_nop, };EXPORT_SYMBOL (paravirt_ops);
PATCH 20/34 i386: avoid checking for cpu gone when CONFIG_HOTPLUG_CPU not defined
In reply to Andi KleenFrom: "Keshavamurthy, Anil S" <[email protected]>
Avoid checking for cpu gone in mm hot path when CONFIG_HOTPLUG_CPU is not defined.
---
arch/i386/kernel/smp.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
arch/i386/kernel/smp.c +3 -1
@@ -359,10 +359,12 @@ void native_flush_tlb_others(const cpumaBUG_ON (cpu_isset (smp_processor_id (), cpumask));BUG_ON (!mm); +#ifdef CONFIG_HOTPLUG_CPU /* If a CPU which we ran on has gone down, OK. */ cpus_and (cpumask, cpumask, cpu_online_map); -if (cpus_empty (cpumask)) +if (unlikely (cpus_empty (cpumask)))return ; +#endif /* * i'm not happy about this global shared spinlock in the
Re: [PATCH] [30/34] i386: convert the monitor thread to use the kthread API
In reply to Andi KleenQuoted 4 lines · Andi Kleen
From: Eric W. Biederman <[email protected]>
This patch just trivially replaces
kernel_threadand daemonize with a single call tokthread_run.
Actually, no, I'm checking out Christoph's full conversion now. If it works, I'll send it in via the voyager tree.
James
Re: [PATCH] [30/34] i386: convert the monitor thread to use the kthread API
Quoted 8 lines · James Bottomley
Quoted 4 lines · Andi Kleen
From: Eric W. Biederman <[email protected]>
This patch just trivially replaces
kernel_threadand daemonize with a single call tokthread_run.Actually, no, I'm checking out Christoph's full conversion now. If it works, I'll send it in via the voyager tree.
Dropped
-Andi
Re: [patches] [PATCH] [28/34] i386: pte xchg optimization
In reply to Andi KleenQuoted 8 lines
Quoted 1 line
Quoted 1 line
Andi Kleen <[email protected]> 30.04.07 17:50 >>>
From: Zachary Amsden <[email protected]>
In situations where page table updates need only be made locally, and there is no cross-processor A/D bit races involved, we need not use the heavyweight xchg instruction to atomically fetch and clear page table entries. Instead, we can just read and clear them directly.
I always wondered why the xchg is necessary here at all. If the process of tearing down a page table entry has started, other users of the mapped linear address are broken anyway - why is it necessary to still monitor the effect they may have on the A/D bits, unless this is a transient tear down?
Checking for the uses of ptep_get_and_clear, I would judge that the use in change_pte_range() may in fact need the xchg, but the uses in vunmap_pte_range() and zap_pte_range() shouldn't.
Jan
Re: [patches] [PATCH] [28/34] i386: pte xchg optimization
Quoted 9 lines
I always wondered why the xchg is necessary here at all. If the process of tearing down a page table entry has started, other users of the mapped linear address are broken anyway - why is it necessary to still monitor the effect they may have on the A/D bits, unless this is a transient tear down?
Checking for the uses of
ptep_get_and_clear, I would judge that the use inchange_pte_range()may in fact need the xchg, but the uses invunmap_pte_range()andzap_pte_range()shouldn't.
Yes I agree. Might be a nice speed up for exit to distingush the cases.
-Andi
Bernhard Kaindl
NAKRe: [PATCH] [16/34] i386: fix mtrr sections
In reply to Andi KleenQuoted 1 line · Andi Kleen
Subject: [PATCH] [16/34] i386: fix mtrr sections
NACK - obsolete, replaced by:
Jeremy Fitzhardinge - "x86: clean up identify_cpu"
http://lkml.org/lkml/2007/4/7/113 [it's also patch 11/26 in this thread]
It's a leftover of "__init to __cpuinit in mtrr code" (Prarit Bhargava):
http://lkml.org/lkml/2007/2/28/198 - (acked by Bhavana Nagendra) which itself is rejected from Andrews tree already.
Description:
------------
This function tree (as of 2.6.21) here explains it all:
__cpuinit identify_cpu()
-> if BSP is inited, so only at __init time, these functions are called:
__init mtrr_bp_init()
__init get_mtrr_state()
__initdata show_mtrr;
__init print_fixed()The above works just fine in practice, but of course it's ugly.
Prarit Bhargava's approach was to silence the warnings was to change mtrr_bp_init() and everything it uses (which is quite a lot) to __cpuinit, but this prevents a lot of code to be freed on kernels which support CPU hotplug.
He also forgot to change the last two references in the tree above (show_mtrr and print_fixed) to __cpuinit, which is what this patch here from Randy does.
-----> Thank God, Jeremy Fitzhardinge cleaned up identify_cpu:
"x86: clean up identify_cpu" - http://lkml.org/lkml/2007/4/7/113
It replaces this rather ugly code
if (c == &boot_cpu_data)
--------------> sysenter_setup();
enable_sep_cpu();
if (c == &boot_cpu_data)
--------------> mtrr_bp_init();
else
mtrr_ap_init();and by moving these calls into separate __cpuinit and __init functions.
That means that quite some of stuff (the init code for all the various MTRR implementations on Intel, AMD, Cyrix and Centar CPUs) can be kept in __init and Prarit Bhargava's and Randy Dunlap's MTRR warning changes are obsolete.
You posted Jeremy Fitzhardinge's patch as part of this patchset for review:
Subject: [PATCH] [11/26] i386: clean up identify_cpu
The i386 label above is actally wrong, it should be "x86".
Concusion:
----------
The above "clean up identify_cpu" by Jeremy Fitzhardinge properly fixes
WARNING: vmlinux - Section mismatch: reference to .init.text:sysenter_setup from .text between 'identify_cpu' (at offset 0xc010a1e8) and 'display_cacheinfo'
WARNING: vmlinux - Section mismatch: reference to .init.text:mtrr_bp_init from .text between 'identify_cpu' (at offset 0xc010a1f2) and 'display_cacheinfo'
and this patch should be rejected because it's only cured symptoms caused by a patch which was already rejected by Andrew in favour of "clean up identify_cpu". This patch only was a leftover.
Best Regards,
Bernhard
PS: I reviewed the MTRR __init labels myself while working on MTRR debugging so I know these functions from the top of my head and I verified what I state with the patches sent by you for review by checking the MODPOST with CONFIG_RELOCATABLE=y with/out the patches mentioned.
PPS: Hint for people which want to verfiy what I state:
Note that "clean up identify_cpu" needs the cleanup of bugs.h (also included in the patches which you posted for review) and it needs
"Change sysenter_setup to __cpuinit", which is partly (for the __cpuinit sysenter change) again wrong (also by Prarit Bhargava) but that is fixed back to init by "clean up identify_cpu"...
Quoted 4 lines
From: Randy Dunlap <[email protected]>
Fix section mismatch warnings in mtrr code.
Fix line length on one source line.
PPS: While it's bad that the line is long, it can be kept as is. The MTTR code has a lot of CodingStyle fixes to go (e.g. lots of missing function headers which describe what the functions do).
It's on my TODO list to make the MTRR code comforming to CodingStyle.
Quoted 33 lines
WARNING:
arch/x86_64/kernel/built-in.o- Section mismatch: reference to .init.data: from .text.get_mtrr_state after 'get_mtrr_state' (at offset0x103)
WARNING:arch/x86_64/kernel/built-in.o- Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset0x180)
WARNING:arch/x86_64/kernel/built-in.o- Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset0x199)
WARNING:arch/x86_64/kernel/built-in.o- Section mismatch: reference to .init.text: from .text.get_mtrr_state after 'get_mtrr_state' (at offset0x1c1)Signed-off-by Randy Dunlap <[email protected]>Signed-off-by Andi Kleen <[email protected]>Cc Andi Kleen <[email protected]>Signed-off-by Andrew Morton <[email protected]>---
arch/i386/kernel/cpu/mtrr/generic.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)Index:
linux/arch/i386/kernel/cpu/mtrr/generic.c
===================================================================arch/i386/kernel/cpu/mtrr/generic.c +2
-2@@ -38,7 +38,7 @@ static struct mtrr_state mtrr_state = {}#undef MODULE_PARAM_PREFIX#define MODULE_PARAM_PREFIX "mtrr." -static __initdata int mtrr_show; +static int mtrr_show;module_param_named (show, mtrr_show, bool,0 );/* Get the MSR pair relating to a var range */ @@ -68,12 +68,13 @@ void mtrr_save_fixed_ranges(void *info)get_fixed_ranges (mtrr_state.fixed_ranges); } -static void __init print_fixed (unsigned base,unsigned step,const mtrr_type *types) +static void __cpuinit print_fixed (unsigned base,unsigned step,const mtrr_type *types)
Re: [patches] [PATCH] [28/34] i386: pte xchg optimization
In reply to Andi KleenQuoted 5 lines · Andi Kleen
Quoted 5 lines
I always wondered why the xchg is necessary here at all. If the process of tearing down a page table entry has started, other users of the mapped linear address are broken anyway - why is it necessary to still monitor the effect they may have on the A/D bits, unless this is a transient tear down?
Quoted 7 lines
Quoted 4 lines
Checking for the uses of
ptep_get_and_clear, I would judge that the use inchange_pte_range()may in fact need the xchg, but the uses invunmap_pte_range()andzap_pte_range()shouldn't.Yes I agree. Might be a nice speed up for exit to distingush the cases.
That is what I did in this patch - but with care zap_pte_range can also be called in non-teardown cases when unmapping (when !fullmm) and user mappings could still be in effect on remote processors.
Zach
Re: [PATCH] [16/34] i386: fix mtrr sections
In reply to Bernhard KaindlI noticed that I can just use call graphs to make more clear what I want to say.
There is otherwise nothing new in this mail and I'll submit a new patch which reverts this patch if my review came too late, if in doubt, just ignore this mail, I may just refer to it later then.
Quoted 11 lines
NACK - obsolete, replaced by:
Jeremy Fitzhardinge - "x86: clean upidentify_cpu"
http://lkml.org/lkml/2007/4/7/113 [it's also patch 11/26 in this thread]It's a leftover of "
__initto__cpuinitin mtrr code" (Prarit Bhargava):
http://lkml.org/lkml/2007/2/28/198 - (acked by Bhavana Nagendra) which itself is rejected from Andrews tree already.Description:
------------
Quoted 8 lines
This function tree (as of 2.6.21) here explains it all:
__cpuinitidentify_cpu()-> if BSP is inited, so only at __init time, these functions are called: __init mtrr_bp_init() __init get_mtrr_state() __initdata show_mtrr; __init print_fixed()
That was around 2.6.15 till 2.6.21.
Prarit Bhargava's patch "__init to __cpuinit in mtrr code" did this:
__cpuinit identify_cpu()
-> if BSP is inited, so only at __init time, these functions are called:
- __init mtrr_bp_init()
- __init get_mtrr_state()
+ __cpuinit mtrr_bp_init()
+ __cpuinit get_mtrr_state()
(plus half a dozen other functions)
__initdata show_mtrr;
__init print_fixed()
and Randy's patch (on top of Prarit Bhargava's, which is removed now) does:
- __initdata show_mtrr; + show_mtrr; - __init print_fixed() + __cpuinit print_fixed()
While Jeremy Fitzhardinge - "x86: clean up identify_cpu" cleans it up:
- __cpuinit identify_cpu() + __init identify_boot_cpu() (only does the boot-only calls)
__init mtrr_bp_init()
__init get_mtrr_state()
(and half a dozen other functions also keep __init)
__initdata show_mtrr;
__init print_fixed()
which is best and Randy's patch "fix mtrr sections" is also obsolete then, show_mtrr and print_fixed() can keep the __init/__initdata prefix.
As Andy already submitted it to Linus with http://lkml.org/lkml/2007/5/2/346
we may have to create a patch which reverts this patch.
I'm also planning to add some function headers to the MTRR functions and also fix the existing and upcoming function headers to be complant to kernel-doc.
Bernhard
Re: [PATCH] [16/34] i386: fix mtrr sections
Quoted 4 lines
As Andy already submitted it to Linus with http://lkml.org/lkml/2007/5/2/346
we may have to create a patch which reverts this patch.
Ok thanks for the explanation. I will queue a revert patch
Quoted 3 lines
I'm also planning to add some function headers to the MTRR functions and also fix the existing and upcoming function headers to be complant to kernel-doc.
Thanks
-Andi
Re: [PATCH] [16/34] i386: fix mtrr sections
Quoted 5 lines · Andi Kleen
Quoted 2 lines
As Andy already submitted it to Linus with http://lkml.org/lkml/2007/5/2/346
we may have to create a patch which reverts this patch.Ok thanks for the explanation. I will queue a revert patch
Quoted 7 lines
Quoted 3 lines
I'm also planning to add some function headers to the MTRR functions and also fix the existing and upcoming function headers to be complant to kernel-doc.
Thanks
-Andi
Thanks from me also.
Signature · 2 lines
~Randy *** Remember to use Documentation/SubmitChecklist when testing your code ***