if (c == &boot_cpu_data)
                sysenter_setup();
        enable_sep_cpu();
+
+       if (c == &boot_cpu_data)
+               mtrr_bp_init();
+       else
+               mtrr_ap_init();
 }
 
 #ifdef CONFIG_X86_HT
 
        mtrr_state.enabled = (lo & 0xc00) >> 10;
 }
 
-/*  Free resources associated with a struct mtrr_state  */
-void __init finalize_mtrr_state(void)
-{
-       kfree(mtrr_state.var_ranges);
-       mtrr_state.var_ranges = NULL;
-}
-
 /*  Some BIOS's are fucked and don't set all MTRRs the same!  */
 void __init mtrr_state_warn(void)
 {
 */
 {
        unsigned long flags;
+       struct mtrr_var_range *vr;
+
+       vr = &mtrr_state.var_ranges[reg];
 
        local_irq_save(flags);
        prepare_set();
                /* The invalid bit is kept in the mask, so we simply clear the
                   relevant mask register to disable a range. */
                mtrr_wrmsr(MTRRphysMask_MSR(reg), 0, 0);
+               memset(vr, 0, sizeof(struct mtrr_var_range));
        } else {
-               mtrr_wrmsr(MTRRphysBase_MSR(reg), base << PAGE_SHIFT | type,
-                     (base & size_and_mask) >> (32 - PAGE_SHIFT));
-               mtrr_wrmsr(MTRRphysMask_MSR(reg), -size << PAGE_SHIFT | 0x800,
-                     (-size & size_and_mask) >> (32 - PAGE_SHIFT));
+               vr->base_lo = base << PAGE_SHIFT | type;
+               vr->base_hi = (base & size_and_mask) >> (32 - PAGE_SHIFT);
+               vr->mask_lo = -size << PAGE_SHIFT | 0x800;
+               vr->mask_hi = (-size & size_and_mask) >> (32 - PAGE_SHIFT);
+
+               mtrr_wrmsr(MTRRphysBase_MSR(reg), vr->base_lo, vr->base_hi);
+               mtrr_wrmsr(MTRRphysMask_MSR(reg), vr->mask_lo, vr->mask_hi);
        }
 
        post_set();
 
 
        error = -EINVAL;
 
+       /* No CPU hotplug when we change MTRR entries */
+       lock_cpu_hotplug();
        /*  Search for existing MTRR  */
        down(&main_lock);
        for (i = 0; i < num_var_ranges; ++i) {
        error = i;
  out:
        up(&main_lock);
+       unlock_cpu_hotplug();
        return error;
 }
 
                return -ENXIO;
 
        max = num_var_ranges;
+       /* No CPU hotplug when we change MTRR entries */
+       lock_cpu_hotplug();
        down(&main_lock);
        if (reg < 0) {
                /*  Search for existing MTRR  */
        error = reg;
  out:
        up(&main_lock);
+       unlock_cpu_hotplug();
        return error;
 }
 /**
        centaur_init_mtrr();
 }
 
-static void __init init_other_cpus(void)
-{
-       if (use_intel())
-               get_mtrr_state();
-
-       /* bring up the other processors */
-       set_mtrr(~0U,0,0,0);
-
-       if (use_intel()) {
-               finalize_mtrr_state();
-               mtrr_state_warn();
-       }
-}
-
-
+/* The suspend/resume methods are only for CPU without MTRR. CPU using generic
+ * MTRR driver doesn't require this
+ */
 struct mtrr_value {
        mtrr_type       ltype;
        unsigned long   lbase;
 
 
 /**
- * mtrr_init - initialize mtrrs on the boot CPU
+ * mtrr_bp_init - initialize mtrrs on the boot CPU
  *
  * This needs to be called early; before any of the other CPUs are 
  * initialized (i.e. before smp_init()).
  * 
  */
-static int __init mtrr_init(void)
+void __init mtrr_bp_init(void)
 {
        init_ifs();
 
        if (mtrr_if) {
                set_num_var_ranges();
                init_table();
-               init_other_cpus();
-
-               return sysdev_driver_register(&cpu_sysdev_class,
-                                             &mtrr_sysdev_driver);
+               if (use_intel())
+                       get_mtrr_state();
        }
-       return -ENXIO;
 }
 
-subsys_initcall(mtrr_init);
+void mtrr_ap_init(void)
+{
+       unsigned long flags;
+
+       if (!mtrr_if || !use_intel())
+               return;
+       /*
+        * Ideally we should hold main_lock here to avoid mtrr entries changed,
+        * but this routine will be called in cpu boot time, holding the lock
+        * breaks it. This routine is called in two cases: 1.very earily time
+        * of software resume, when there absolutely isn't mtrr entry changes;
+        * 2.cpu hotadd time. We let mtrr_add/del_page hold cpuhotplug lock to
+        * prevent mtrr entry changes
+        */
+       local_irq_save(flags);
+
+       mtrr_if->set_all();
+
+       local_irq_restore(flags);
+}
+
+static int __init mtrr_init_finialize(void)
+{
+       if (!mtrr_if)
+               return 0;
+       if (use_intel())
+               mtrr_state_warn();
+       else {
+               /* The CPUs haven't MTRR and seemes not support SMP. They have
+                * specific drivers, we use a tricky method to support
+                * suspend/resume for them.
+                * TBD: is there any system with such CPU which supports
+                * suspend/resume?  if no, we should remove the code.
+                */
+               sysdev_driver_register(&cpu_sysdev_class,
+                       &mtrr_sysdev_driver);
+       }
+       return 0;
+}
+subsys_initcall(mtrr_init_finialize);
 
 
 extern unsigned int num_var_ranges;
 
-void finalize_mtrr_state(void);
 void mtrr_state_warn(void);
 char *mtrr_attrib_to_str(int x);
 void mtrr_wrmsr(unsigned, unsigned, unsigned);
 
 
        fix_processor_context();
        do_fpu_end();
+       mtrr_ap_init();
 }
 
 void restore_processor_state(void)
 
 #ifdef CONFIG_X86_MCE
        mcheck_init(c);
 #endif
+       if (c == &boot_cpu_data)
+               mtrr_bp_init();
+       else
+               mtrr_ap_init();
 #ifdef CONFIG_NUMA
        if (c != &boot_cpu_data)
                numa_add_cpu(c - cpu_data);
 
        fix_processor_context();
 
        do_fpu_end();
+       mtrr_ap_init();
 }
 
 void restore_processor_state(void)
 
 extern void enable_sep_cpu(void);
 extern int sysenter_setup(void);
 
+#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 /* __ASM_I386_PROCESSOR_H */
 
 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);