[BACK]Return to cpu.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / arch / x86 / x86

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/arch/x86/x86/cpu.c between version 1.4 and 1.4.2.3

version 1.4, 2007/10/18 15:28:38 version 1.4.2.3, 2007/12/27 00:43:26
Line 1 
Line 1 
 /* $NetBSD$ */  /*      $NetBSD$        */
   
 /*-  /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.   * Copyright (c) 2000, 2006, 2007 The NetBSD Foundation, Inc.
  * All rights reserved.   * All rights reserved.
  *   *
  * This code is derived from software contributed to The NetBSD Foundation   * This code is derived from software contributed to The NetBSD Foundation
  * by RedBack Networks Inc.   * by Bill Sommerfeld of RedBack Networks Inc, and by Andrew Doran.
  *  
  * Author: Bill Sommerfeld  
  *   *
  * Redistribution and use in source and binary forms, with or without   * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions   * modification, are permitted provided that the following conditions
Line 87  __KERNEL_RCSID(0, "$NetBSD$");
Line 85  __KERNEL_RCSID(0, "$NetBSD$");
 #include <sys/systm.h>  #include <sys/systm.h>
 #include <sys/device.h>  #include <sys/device.h>
 #include <sys/malloc.h>  #include <sys/malloc.h>
   #include <sys/cpu.h>
   #include <sys/atomic.h>
   
 #include <uvm/uvm_extern.h>  #include <uvm/uvm_extern.h>
   
 #include <machine/cpu.h>  
 #include <machine/cpufunc.h>  #include <machine/cpufunc.h>
 #include <machine/cpuvar.h>  #include <machine/cpuvar.h>
 #include <machine/pmap.h>  #include <machine/pmap.h>
Line 124  __KERNEL_RCSID(0, "$NetBSD$");
Line 123  __KERNEL_RCSID(0, "$NetBSD$");
 int     cpu_match(struct device *, struct cfdata *, void *);  int     cpu_match(struct device *, struct cfdata *, void *);
 void    cpu_attach(struct device *, struct device *, void *);  void    cpu_attach(struct device *, struct device *, void *);
   
   static bool     cpu_suspend(device_t);
   static bool     cpu_resume(device_t);
   
 struct cpu_softc {  struct cpu_softc {
         struct device sc_dev;           /* device tree glue */          struct device sc_dev;           /* device tree glue */
         struct cpu_info *sc_info;       /* pointer to CPU info */          struct cpu_info *sc_info;       /* pointer to CPU info */
 };  };
   
 int mp_cpu_start(struct cpu_info *);  int mp_cpu_start(struct cpu_info *, paddr_t);
 void mp_cpu_start_cleanup(struct cpu_info *);  void mp_cpu_start_cleanup(struct cpu_info *);
 const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,  const struct cpu_functions mp_cpu_funcs = { mp_cpu_start, NULL,
                                             mp_cpu_start_cleanup };                                              mp_cpu_start_cleanup };
Line 158  struct cpu_info cpu_info_primary = {
Line 160  struct cpu_info cpu_info_primary = {
   
 struct cpu_info *cpu_info_list = &cpu_info_primary;  struct cpu_info *cpu_info_list = &cpu_info_primary;
   
 static void     cpu_set_tss_gates(struct cpu_info *ci);  static void     cpu_set_tss_gates(struct cpu_info *);
   
 #ifdef i386  #ifdef i386
 static void     cpu_init_tss(struct i386tss *, void *, void *);  static void     cpu_init_tss(struct i386tss *, void *, void *);
 #endif  #endif
   
   #ifdef MULTIPROCESSOR
   static void     cpu_init_idle_lwp(struct cpu_info *);
   #endif
   
 uint32_t cpus_attached = 0;  uint32_t cpus_attached = 0;
   uint32_t cpus_running = 0;
   
 extern char x86_64_doubleflt_stack[];  extern char x86_64_doubleflt_stack[];
   
   bool x86_mp_online;
   paddr_t mp_trampoline_paddr = MP_TRAMPOLINE;
   
   static vaddr_t cmos_data_mapping;
   
 #ifdef MULTIPROCESSOR  #ifdef MULTIPROCESSOR
 /*  /*
  * Array of CPU info structures.  Must be statically-allocated because   * Array of CPU info structures.  Must be statically-allocated because
Line 175  extern char x86_64_doubleflt_stack[];
Line 187  extern char x86_64_doubleflt_stack[];
  */   */
 struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary, };  struct cpu_info *cpu_info[X86_MAXPROCS] = { &cpu_info_primary, };
   
 uint32_t cpus_running = 0;  
   
 void            cpu_hatch(void *);  void            cpu_hatch(void *);
 static void     cpu_boot_secondary(struct cpu_info *ci);  static void     cpu_boot_secondary(struct cpu_info *ci);
 static void     cpu_start_secondary(struct cpu_info *ci);  static void     cpu_start_secondary(struct cpu_info *ci);
Line 189  static void cpu_copy_trampoline(void);
Line 199  static void cpu_copy_trampoline(void);
  * Called from lapic_boot_init() (from mpbios_scan()).   * Called from lapic_boot_init() (from mpbios_scan()).
  */   */
 void  void
 cpu_init_first()  cpu_init_first(void)
 {  {
         int cpunum = lapic_cpu_number();          int cpunum = lapic_cpu_number();
   
Line 200  cpu_init_first()
Line 210  cpu_init_first()
   
         cpu_info_primary.ci_cpuid = cpunum;          cpu_info_primary.ci_cpuid = cpunum;
         cpu_copy_trampoline();          cpu_copy_trampoline();
   
           cmos_data_mapping = uvm_km_alloc(kernel_map, PAGE_SIZE, 0, UVM_KMF_VAONLY);
           if (cmos_data_mapping == 0)
                   panic("No KVA for page 0");
           pmap_kenter_pa(cmos_data_mapping, 0, VM_PROT_READ|VM_PROT_WRITE);
           pmap_update(pmap_kernel());
 }  }
 #endif  #endif
   
Line 328  cpu_attach(struct device *parent, struct
Line 344  cpu_attach(struct device *parent, struct
         switch (caa->cpu_role) {          switch (caa->cpu_role) {
         case CPU_ROLE_SP:          case CPU_ROLE_SP:
                 aprint_normal(": (uniprocessor)\n");                  aprint_normal(": (uniprocessor)\n");
                 ci->ci_flags |= CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY;                  atomic_or_32(&ci->ci_flags,
                       CPUF_PRESENT | CPUF_SP | CPUF_PRIMARY);
                 cpu_intr_init(ci);                  cpu_intr_init(ci);
                 identifycpu(ci);                  identifycpu(ci);
                 cpu_init(ci);                  cpu_init(ci);
                 cpu_set_tss_gates(ci);                  cpu_set_tss_gates(ci);
                 pmap_cpu_init_late(ci);                  pmap_cpu_init_late(ci);
                   x86_errata();
                 break;                  break;
   
         case CPU_ROLE_BP:          case CPU_ROLE_BP:
                 aprint_normal(": (boot processor)\n");                  aprint_normal(": (boot processor)\n");
                 ci->ci_flags |= CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY;                  atomic_or_32(&ci->ci_flags,
                       CPUF_PRESENT | CPUF_BSP | CPUF_PRIMARY);
                 cpu_intr_init(ci);                  cpu_intr_init(ci);
                 identifycpu(ci);                  identifycpu(ci);
                 cpu_init(ci);                  cpu_init(ci);
Line 354  cpu_attach(struct device *parent, struct
Line 373  cpu_attach(struct device *parent, struct
 #if NIOAPIC > 0  #if NIOAPIC > 0
                 ioapic_bsp_id = caa->cpu_number;                  ioapic_bsp_id = caa->cpu_number;
 #endif  #endif
                   x86_errata();
                 break;                  break;
   
         case CPU_ROLE_AP:          case CPU_ROLE_AP:
Line 387  cpu_attach(struct device *parent, struct
Line 407  cpu_attach(struct device *parent, struct
   
         cpus_attached |= ci->ci_cpumask;          cpus_attached |= ci->ci_cpumask;
   
           if (!pmf_device_register(self, cpu_suspend, cpu_resume))
                   aprint_error_dev(self, "couldn't establish power handler\n");
   
 #if defined(MULTIPROCESSOR)  #if defined(MULTIPROCESSOR)
         if (mp_verbose) {          if (mp_verbose) {
                 struct lwp *l = ci->ci_data.cpu_idlelwp;                  struct lwp *l = ci->ci_data.cpu_idlelwp;
Line 409  cpu_attach(struct device *parent, struct
Line 432  cpu_attach(struct device *parent, struct
  */   */
   
 void  void
 cpu_init(ci)  cpu_init(struct cpu_info *ci)
         struct cpu_info *ci;  
 {  {
         /* configure the CPU if needed */          /* configure the CPU if needed */
         if (ci->cpu_setup != NULL)          if (ci->cpu_setup != NULL)
Line 474  cpu_init(ci)
Line 496  cpu_init(ci)
 #endif  /* i386 */  #endif  /* i386 */
 #endif /* MTRR */  #endif /* MTRR */
   
 #ifdef MULTIPROCESSOR          atomic_or_32(&ci->ci_flags, CPUF_RUNNING);
         ci->ci_flags |= CPUF_RUNNING;          atomic_or_32(&cpus_running, ci->ci_cpumask);
         cpus_running |= ci->ci_cpumask;  
   #ifndef MULTIPROCESSOR
           /* XXX */
           x86_patch();
 #endif  #endif
 }  }
   
 bool x86_mp_online;  
   
 #ifdef MULTIPROCESSOR  #ifdef MULTIPROCESSOR
 void  void
 cpu_boot_secondary_processors()  cpu_boot_secondary_processors(void)
 {  {
         struct cpu_info *ci;          struct cpu_info *ci;
         u_long i;          u_long i;
   
           /* Now that we know the number of CPUs, patch the text segment. */
           x86_patch();
   
         for (i=0; i < X86_MAXPROCS; i++) {          for (i=0; i < X86_MAXPROCS; i++) {
                 ci = cpu_info[i];                  ci = cpu_info[i];
                 if (ci == NULL)                  if (ci == NULL)
Line 515  cpu_init_idle_lwp(struct cpu_info *ci)
Line 541  cpu_init_idle_lwp(struct cpu_info *ci)
 }  }
   
 void  void
 cpu_init_idle_lwps()  cpu_init_idle_lwps(void)
 {  {
         struct cpu_info *ci;          struct cpu_info *ci;
         u_long i;          u_long i;
Line 533  cpu_init_idle_lwps()
Line 559  cpu_init_idle_lwps()
 }  }
   
 void  void
 cpu_start_secondary(ci)  cpu_start_secondary(struct cpu_info *ci)
         struct cpu_info *ci;  
 {  {
         int i;          int i;
         struct pmap *kpm = pmap_kernel();  
         extern paddr_t mp_pdirpa;          extern paddr_t mp_pdirpa;
   
 #ifdef __x86_64__          mp_pdirpa = pmap_init_tmp_pgtbl(mp_trampoline_paddr);
         /*  
          * The initial PML4 pointer must be below 4G, so if the  
          * current one isn't, use a "bounce buffer"  
          *  
          * XXX move elsewhere, not per CPU.  
          */  
         if (kpm->pm_pdirpa > 0xffffffff) {  
                 extern vaddr_t lo32_vaddr;  
                 extern paddr_t lo32_paddr;  
                 memcpy((void *)lo32_vaddr, kpm->pm_pdir, PAGE_SIZE);  
                 mp_pdirpa = lo32_paddr;  
         } else  
 #endif  
                 mp_pdirpa = kpm->pm_pdirpa;  
   
         ci->ci_flags |= CPUF_AP;          atomic_or_32(&ci->ci_flags, CPUF_AP);
   
         aprint_debug("%s: starting\n", ci->ci_dev->dv_xname);          aprint_debug("%s: starting\n", ci->ci_dev->dv_xname);
   
         ci->ci_curlwp = ci->ci_data.cpu_idlelwp;          ci->ci_curlwp = ci->ci_data.cpu_idlelwp;
         CPU_STARTUP(ci);          CPU_STARTUP(ci, mp_trampoline_paddr);
   
         /*          /*
          * wait for it to become ready           * wait for it to become ready
          */           */
         for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {          for (i = 100000; (!(ci->ci_flags & CPUF_PRESENT)) && i>0;i--) {
                 delay(10);                  i8254_delay(10);
         }          }
         if (! (ci->ci_flags & CPUF_PRESENT)) {          if ((ci->ci_flags & CPUF_PRESENT) == 0) {
                 aprint_error("%s: failed to become ready\n",                  aprint_error("%s: failed to become ready\n",
                     ci->ci_dev->dv_xname);                      ci->ci_dev->dv_xname);
 #if defined(MPDEBUG) && defined(DDB)  #if defined(MPDEBUG) && defined(DDB)
Line 582  cpu_start_secondary(ci)
Line 592  cpu_start_secondary(ci)
 }  }
   
 void  void
 cpu_boot_secondary(ci)  cpu_boot_secondary(struct cpu_info *ci)
         struct cpu_info *ci;  
 {  {
         int i;          int i;
   
         ci->ci_flags |= CPUF_GO; /* XXX atomic */          atomic_or_32(&ci->ci_flags, CPUF_GO);
   
         for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {          for (i = 100000; (!(ci->ci_flags & CPUF_RUNNING)) && i>0;i--) {
                 delay(10);                  i8254_delay(10);
         }          }
         if (! (ci->ci_flags & CPUF_RUNNING)) {          if ((ci->ci_flags & CPUF_RUNNING) == 0) {
                 aprint_error("%s: failed to start\n", ci->ci_dev->dv_xname);                  aprint_error("%s: failed to start\n", ci->ci_dev->dv_xname);
 #if defined(MPDEBUG) && defined(DDB)  #if defined(MPDEBUG) && defined(DDB)
                 printf("dropping into debugger; continue from here to resume boot\n");                  printf("dropping into debugger; continue from here to resume boot\n");
Line 606  cpu_boot_secondary(ci)
Line 614  cpu_boot_secondary(ci)
  * This is called from code in mptramp.s; at this point, we are running   * This is called from code in mptramp.s; at this point, we are running
  * in the idle pcb/idle stack of the new CPU.  When this function returns,   * in the idle pcb/idle stack of the new CPU.  When this function returns,
  * this processor will enter the idle loop and start looking for work.   * this processor will enter the idle loop and start looking for work.
  *  
  * XXX should share some of this with init386 in machdep.c  
  */   */
 void  void
 cpu_hatch(void *v)  cpu_hatch(void *v)
 {  {
         struct cpu_info *ci = (struct cpu_info *)v;          struct cpu_info *ci = (struct cpu_info *)v;
         int s;          int s, i;
   
 #ifdef __x86_64__  #ifdef __x86_64__
         cpu_init_msrs(ci);          cpu_init_msrs(ci, true);
 #endif  #endif
         cpu_probe_features(ci);          cpu_probe_features(ci);
         cpu_feature &= ci->ci_feature_flags;          cpu_feature &= ci->ci_feature_flags;
         cpu_feature2 &= ci->ci_feature2_flags;          cpu_feature2 &= ci->ci_feature2_flags;
   
 #ifdef DEBUG          KDASSERT((ci->ci_flags & CPUF_PRESENT) == 0);
         if (ci->ci_flags & CPUF_PRESENT)          atomic_or_32(&ci->ci_flags, CPUF_PRESENT);
                 panic("%s: already running!?", ci->ci_dev->dv_xname);          while ((ci->ci_flags & CPUF_GO) == 0) {
 #endif                  /* Don't use delay, boot CPU may be patching the text. */
                   for (i = 10000; i != 0; i--)
         ci->ci_flags |= CPUF_PRESENT;                          x86_pause();
           }
   
           /* Beacuse the text may have been patched in x86_patch(). */
           wbinvd();
           x86_flush();
   
         lapic_enable();          KASSERT((ci->ci_flags & CPUF_RUNNING) == 0);
         lapic_initclocks();  
   
         while ((ci->ci_flags & CPUF_GO) == 0)  
                 delay(10);  
 #ifdef DEBUG  
         if (ci->ci_flags & CPUF_RUNNING)  
                 panic("%s: already running!?", ci->ci_dev->dv_xname);  
 #endif  
   
           lcr3(pmap_kernel()->pm_pdirpa);
           curlwp->l_addr->u_pcb.pcb_cr3 = pmap_kernel()->pm_pdirpa;
         lcr0(ci->ci_data.cpu_idlelwp->l_addr->u_pcb.pcb_cr0);          lcr0(ci->ci_data.cpu_idlelwp->l_addr->u_pcb.pcb_cr0);
         cpu_init_idt();          cpu_init_idt();
         lapic_set_lvt();  
         gdt_init_cpu(ci);          gdt_init_cpu(ci);
           lapic_enable();
           lapic_set_lvt();
           lapic_initclocks();
   
 #ifdef i386  #ifdef i386
         npxinit(ci);          npxinit(ci);
Line 652  cpu_hatch(void *v)
Line 659  cpu_hatch(void *v)
         lldt(GSYSSEL(GLDT_SEL, SEL_KPL));          lldt(GSYSSEL(GLDT_SEL, SEL_KPL));
   
         cpu_init(ci);          cpu_init(ci);
           cpu_get_tsc_freq(ci);
   
         s = splhigh();          s = splhigh();
 #ifdef i386  #ifdef i386
Line 661  cpu_hatch(void *v)
Line 669  cpu_hatch(void *v)
 #endif  #endif
         x86_enable_intr();          x86_enable_intr();
         splx(s);          splx(s);
           x86_errata();
   
         aprint_debug("%s: CPU %ld running\n", ci->ci_dev->dv_xname,          aprint_debug("%s: CPU %ld running\n", ci->ci_dev->dv_xname,
             (long)ci->ci_cpuid);              (long)ci->ci_cpuid);
Line 694  cpu_debug_dump(void)
Line 703  cpu_debug_dump(void)
 #endif  #endif
   
 static void  static void
 cpu_copy_trampoline()  cpu_copy_trampoline(void)
 {  {
         /*          /*
          * Copy boot code.           * Copy boot code.
          */           */
         extern u_char cpu_spinup_trampoline[];          extern u_char cpu_spinup_trampoline[];
         extern u_char cpu_spinup_trampoline_end[];          extern u_char cpu_spinup_trampoline_end[];
         pmap_kenter_pa((vaddr_t)MP_TRAMPOLINE,  /* virtual */  
             (paddr_t)MP_TRAMPOLINE,     /* physical */          vaddr_t mp_trampoline_vaddr;
             VM_PROT_ALL);               /* protection */  
           mp_trampoline_vaddr = uvm_km_alloc(kernel_map, PAGE_SIZE, 0,
               UVM_KMF_VAONLY);
   
           pmap_kenter_pa(mp_trampoline_vaddr, mp_trampoline_paddr,
               VM_PROT_READ | VM_PROT_WRITE);
         pmap_update(pmap_kernel());          pmap_update(pmap_kernel());
         memcpy((void *)MP_TRAMPOLINE,          memcpy((void *)mp_trampoline_vaddr,
             cpu_spinup_trampoline,              cpu_spinup_trampoline,
             cpu_spinup_trampoline_end-cpu_spinup_trampoline);              cpu_spinup_trampoline_end-cpu_spinup_trampoline);
   
           pmap_kremove(mp_trampoline_vaddr, PAGE_SIZE);
           pmap_update(pmap_kernel());
           uvm_km_free(kernel_map, mp_trampoline_vaddr, PAGE_SIZE, UVM_KMF_VAONLY);
 }  }
   
 #endif  #endif
Line 783  cpu_set_tss_gates(struct cpu_info *ci)
Line 801  cpu_set_tss_gates(struct cpu_info *ci)
 }  }
 #endif  /* i386 */  #endif  /* i386 */
   
   
 int  int
 mp_cpu_start(struct cpu_info *ci)  mp_cpu_start(struct cpu_info *ci, paddr_t target)
 {  {
 #if NLAPIC > 0  #if NLAPIC > 0
         int error;          int error;
Line 793  mp_cpu_start(struct cpu_info *ci)
Line 810  mp_cpu_start(struct cpu_info *ci)
         unsigned short dwordptr[2];          unsigned short dwordptr[2];
   
         /*          /*
            * Bootstrap code must be addressable in real mode
            * and it must be page aligned.
            */
           KASSERT(target < 0x10000 && target % PAGE_SIZE == 0);
   
           /*
          * "The BSP must initialize CMOS shutdown code to 0Ah ..."           * "The BSP must initialize CMOS shutdown code to 0Ah ..."
          */           */
   
Line 805  mp_cpu_start(struct cpu_info *ci)
Line 828  mp_cpu_start(struct cpu_info *ci)
          */           */
   
         dwordptr[0] = 0;          dwordptr[0] = 0;
         dwordptr[1] = MP_TRAMPOLINE >> 4;          dwordptr[1] = target >> 4;
   
         pmap_kenter_pa(0, 0, VM_PROT_READ|VM_PROT_WRITE);          memcpy((uint8_t *)(cmos_data_mapping + 0x467), dwordptr, 4);
         pmap_update(pmap_kernel());  
         memcpy((uint8_t *)0x467, dwordptr, 4);  
         pmap_kremove(0, PAGE_SIZE);  
         pmap_update(pmap_kernel());  
   
 #if NLAPIC > 0  #if NLAPIC > 0
         /*          /*
Line 822  mp_cpu_start(struct cpu_info *ci)
Line 841  mp_cpu_start(struct cpu_info *ci)
                 if ((error = x86_ipi_init(ci->ci_apicid)) != 0)                  if ((error = x86_ipi_init(ci->ci_apicid)) != 0)
                         return error;                          return error;
   
                 delay(10000);                  i8254_delay(10000);
   
                 if (cpu_feature & CPUID_APIC) {                  if (cpu_feature & CPUID_APIC) {
   
                         if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,                          if ((error = x86_ipi(target / PAGE_SIZE,
                                              ci->ci_apicid,                                               ci->ci_apicid,
                                              LAPIC_DLMODE_STARTUP)) != 0)                                               LAPIC_DLMODE_STARTUP)) != 0)
                                 return error;                                  return error;
                         delay(200);                          i8254_delay(200);
   
                         if ((error = x86_ipi(MP_TRAMPOLINE/PAGE_SIZE,                          if ((error = x86_ipi(target / PAGE_SIZE,
                                              ci->ci_apicid,                                               ci->ci_apicid,
                                              LAPIC_DLMODE_STARTUP)) != 0)                                               LAPIC_DLMODE_STARTUP)) != 0)
                                 return error;                                  return error;
                         delay(200);                          i8254_delay(200);
                 }                  }
         }          }
 #endif  #endif
Line 859  typedef void (vector)(void);
Line 878  typedef void (vector)(void);
 extern vector Xsyscall, Xsyscall32;  extern vector Xsyscall, Xsyscall32;
   
 void  void
 cpu_init_msrs(struct cpu_info *ci)  cpu_init_msrs(struct cpu_info *ci, bool full)
 {  {
         wrmsr(MSR_STAR,          wrmsr(MSR_STAR,
             ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |              ((uint64_t)GSEL(GCODE_SEL, SEL_KPL) << 32) |
Line 868  cpu_init_msrs(struct cpu_info *ci)
Line 887  cpu_init_msrs(struct cpu_info *ci)
         wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32);          wrmsr(MSR_CSTAR, (uint64_t)Xsyscall32);
         wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);          wrmsr(MSR_SFMASK, PSL_NT|PSL_T|PSL_I|PSL_C);
   
         wrmsr(MSR_FSBASE, 0);          if (full) {
         wrmsr(MSR_GSBASE, (u_int64_t)ci);                  wrmsr(MSR_FSBASE, 0);
         wrmsr(MSR_KERNELGSBASE, 0);                  wrmsr(MSR_GSBASE, (u_int64_t)ci);
                   wrmsr(MSR_KERNELGSBASE, 0);
           }
   
         if (cpu_feature & CPUID_NOX)          if (cpu_feature & CPUID_NOX)
                 wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE);                  wrmsr(MSR_EFER, rdmsr(MSR_EFER) | EFER_NXE);
 }  }
 #endif  /* __x86_64__ */  #endif  /* __x86_64__ */
   
   /* XXX joerg restructure and restart CPUs individually */
   static bool
   cpu_suspend(device_t dv)
   {
           struct cpu_softc *sc = device_private(dv);
           struct cpu_info *ci = sc->sc_info;
           int err;
   
           if (ci->ci_flags & CPUF_PRIMARY)
                   return true;
           if (ci->ci_data.cpu_idlelwp == NULL)
                   return true;
           if ((ci->ci_flags & CPUF_PRESENT) == 0)
                   return true;
   
           mutex_enter(&cpu_lock);
           err = cpu_setonline(ci, false);
           mutex_exit(&cpu_lock);
           return err == 0;
   }
   
   static bool
   cpu_resume(device_t dv)
   {
           struct cpu_softc *sc = device_private(dv);
           struct cpu_info *ci = sc->sc_info;
           int err;
   
           if (ci->ci_flags & CPUF_PRIMARY)
                   return true;
           if (ci->ci_data.cpu_idlelwp == NULL)
                   return true;
           if ((ci->ci_flags & CPUF_PRESENT) == 0)
                   return true;
   
           mutex_enter(&cpu_lock);
           err = cpu_setonline(ci, true);
           mutex_exit(&cpu_lock);
   
           return err == 0;
   }
   
   void
   cpu_get_tsc_freq(struct cpu_info *ci)
   {
           uint64_t last_tsc;
           u_int junk[4];
   
           if (ci->ci_feature_flags & CPUID_TSC) {
                   /* Serialize. */
                   x86_cpuid(0, junk);
                   last_tsc = rdtsc();
                   i8254_delay(100000);
                   ci->ci_tsc_freq = (rdtsc() - last_tsc) * 10;
           }
   }

Legend:
Removed from v.1.4  
changed lines
  Added in v.1.4.2.3

CVSweb <webmaster@jp.NetBSD.org>