Exemplo n.º 1
0
kern_return_t
  lotto_pset_port
  (mach_port_t *pset_port,
   boolean_t need_privileged)
{
  /*
   * modifies: pset_port
   * effects:  Attempts to obtain a port for the current processor set.
   *           If unable to obtain a privileged port, an ordinary port is
   *	       returned unless need_privileged is set. If successful, sets
   *	       pset_port and returns KERN_SUCCESS, otherwise KERN_FAILURE.
   *
   */

  host_t auth;
 // mach_port_t auth, pset;
  kern_return_t result;
	
  processor_set_name_t default_pset, pset;

  /* obtain priv host port */
 // auth = mach_host_priv_self();
 // if (!MACH_PORT_VALID(auth))
   // {
      /* fail if unable and need priv */
       if (need_privileged)
	return(KERN_FAILURE);
      
      /* fallback to unprivileged auth */
      auth = mach_host_self();
  //  }
  
  /* obtain default pset port */
  printf("Get Default pset for auth %d\n",auth);
  result = processor_set_default(auth, &default_pset);
  if (result != KERN_SUCCESS)
    return(result);
  
  printf("Get Default pset for auth %d\n",auth);
  /* obtain priv pset port */
  result = host_processor_set_priv(auth, default_pset, &pset);
  if (result != KERN_SUCCESS)
    {
      /* fail uf unable and need priv */
      if (need_privileged)
	return(result);

      /* fallback to default pset port */
      pset = default_pset;
    }

  /* set pset port */
  *pset_port = pset;

  /* everything OK */
  return(KERN_SUCCESS);
}
Exemplo n.º 2
0
int getla()
{
    processor_set_t default_set;
    kern_return_t error;
    unsigned int info_count;
    struct processor_set_basic_info info;
    host_t host;

    error = processor_set_default(host_self(), &default_set);
    if (error != KERN_SUCCESS)
	return -1;
    info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
    if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
			   &host, (processor_set_info_t) & info,
			   &info_count) != KERN_SUCCESS)
	return -1;
    return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
}
Exemplo n.º 3
0
static task_t task_for_pid_workaround(int pid) {
	host_t myhost = mach_host_self();
	mach_port_t psDefault = 0;
	mach_port_t psDefault_control = 0;
	task_array_t tasks = NULL;
	mach_msg_type_number_t numTasks = 0;
	kern_return_t kr = -1;
	int i;

	if (pid == -1) {
		return MACH_PORT_NULL;
	}
	kr = processor_set_default (myhost, &psDefault);
	if (kr != KERN_SUCCESS) {
		return MACH_PORT_NULL;
	}
	kr = host_processor_set_priv (myhost, psDefault, &psDefault_control);
	if (kr != KERN_SUCCESS) {
//		eprintf ("host_processor_set_priv failed with error 0x%x\n", kr);
		//mach_error ("host_processor_set_priv",kr);
		return MACH_PORT_NULL;
	}
	numTasks = 0;
	kr = processor_set_tasks (psDefault_control, &tasks, &numTasks);
	if (kr != KERN_SUCCESS) {
//		eprintf ("processor_set_tasks failed with error %x\n", kr);
		return MACH_PORT_NULL;
	}
	if (pid == 0) {
		/* kernel task */
		return tasks[0];
	}
	for (i = 0; i < numTasks; i++) {
		int pid2 = -1;
		pid_for_task (i, &pid2);
		if (pid == pid2) {
			return tasks[i];
		}
	}
	return MACH_PORT_NULL;
}
Exemplo n.º 4
0
void
default_pager_set_policy(
	mach_port_t master_host_port)
{
	host_priority_info_data_t	host_pri_info;
	mach_port_t		default_processor_set_name;
	mach_port_t		default_processor_set;
	policy_rr_base_data_t	rr_base;
	policy_rr_limit_data_t	rr_limit;
	kern_return_t		r;
	mach_msg_type_number_t	count;
	static char here[] = "default_pager_set_policy";

	count = HOST_PRIORITY_INFO_COUNT;
	r = host_info(mach_host_self(),
		      HOST_PRIORITY_INFO,
		      (host_info_t) &host_pri_info,
		      &count);
	if (r != KERN_SUCCESS)
		dprintf(("Could not get host priority info.  Error = 0x%x\n",
			 r));

	rr_base.quantum = 0;
	rr_base.base_priority = host_pri_info.system_priority;
	rr_limit.max_priority = host_pri_info.system_priority;

	(void)processor_set_default(mach_host_self(),
				    &default_processor_set_name);
	(void)host_processor_set_priv(master_host_port,
				      default_processor_set_name,
				      &default_processor_set);

	r = task_set_policy(default_pager_self, default_processor_set,
			    POLICY_RR,
			    (policy_base_t) & rr_base, POLICY_RR_BASE_COUNT,
			    (policy_limit_t) & rr_limit, POLICY_RR_LIMIT_COUNT,
			    TRUE);
	if (r != KERN_SUCCESS)
		dprintf(("task_set_policy returned 0x%x %s\n",
			 r, mach_error_string(r)));
}
Exemplo n.º 5
0
int mach_load_avg(void)
{
    kern_return_t                    status;
    host_t                           host;
    unsigned int                     info_count;
    struct processor_set_basic_info  info;
    processor_set_t                  default_set;

    status=processor_set_default(host_self(), &default_set);
    if (status!=KERN_SUCCESS) {
        mach_error("Error calling processor_set_default", status);
        exit(1);
    }

    info_count=PROCESSOR_SET_BASIC_INFO_COUNT;
    status=processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
                              &host, (processor_set_info_t)&info, &info_count);
#ifdef DEBUG
    if (status != KERN_SUCCESS)
        mach_error("Error calling processor_set_info", status);
#endif
    return info.load_average;
}
Exemplo n.º 6
0
/*
 *  Credits to Jonathan Levin!
 *  This function is able to "exploit" the processor_set_tasks mach trap to retrieve
 *  the kernel's mach port. This only works on systems where SIP is either disabled or
 *  not present at all.
 *  If you want to use an alternative method to read from kernel memory, try with enabling
 *  /dev/kmem and read from that device.
 *
 *  Note that code in this project is tuned to read directly from kernel task, hence you
 *  just need to disable SIP and you're good to go, instead of rewriting code to support
 *  /dev/kmem.
 */
mach_port_t task_for_pid_workaround(int Pid)
{

    host_t        myhost = mach_host_self();
    mach_port_t   psDefault;
    mach_port_t   psDefault_control;

    task_array_t  tasks;
    mach_msg_type_number_t numTasks;
    int i;

    kern_return_t kr;

    kr = processor_set_default(myhost, &psDefault);

    kr = host_processor_set_priv(myhost, psDefault, &psDefault_control);
    if (kr != KERN_SUCCESS) {
        fprintf(stderr, "host_processor_set_priv failed with error %x\n", kr);
        mach_error("host_processor_set_priv",kr);
        exit(1);
    }

    kr = processor_set_tasks(psDefault_control, &tasks, &numTasks);
    if (kr != KERN_SUCCESS) {
        fprintf(stderr,"processor_set_tasks failed with error %x\n",kr);
        exit(1);
    }

    for (i = 0; i < numTasks; i++)
    {
        int pid;
        pid_for_task(tasks[i], &pid);
        if (pid == Pid) return (tasks[i]);
    }

    return (MACH_PORT_NULL);
}
Exemplo n.º 7
0
int
getloadavg (double loadavg[], int nelem)
{
  int elem = 0;                 /* Return value.  */

# ifdef NO_GET_LOAD_AVG
#  define LDAV_DONE
  /* Set errno to zero to indicate that there was no particular error;
     this function just can't work at all on this system.  */
  errno = 0;
  elem = -1;
# endif

# if !defined (LDAV_DONE) && defined (HAVE_LIBKSTAT)
/* Use libkstat because we don't have to be root.  */
#  define LDAV_DONE
  kstat_ctl_t *kc;
  kstat_t *ksp;
  kstat_named_t *kn;

  kc = kstat_open ();
  if (kc == 0)
    return -1;
  ksp = kstat_lookup (kc, "unix", 0, "system_misc");
  if (ksp == 0)
    return -1;
  if (kstat_read (kc, ksp, 0) == -1)
    return -1;


  kn = kstat_data_lookup (ksp, "avenrun_1min");
  if (kn == 0)
    {
      /* Return -1 if no load average information is available.  */
      nelem = 0;
      elem = -1;
    }

  if (nelem >= 1)
    loadavg[elem++] = (double) kn->value.ul / FSCALE;

  if (nelem >= 2)
    {
      kn = kstat_data_lookup (ksp, "avenrun_5min");
      if (kn != 0)
        {
          loadavg[elem++] = (double) kn->value.ul / FSCALE;

          if (nelem >= 3)
            {
              kn = kstat_data_lookup (ksp, "avenrun_15min");
              if (kn != 0)
                loadavg[elem++] = (double) kn->value.ul / FSCALE;
            }
        }
    }

  kstat_close (kc);
# endif /* HAVE_LIBKSTAT */

# if !defined (LDAV_DONE) && defined (hpux) && defined (HAVE_PSTAT_GETDYNAMIC)
/* Use pstat_getdynamic() because we don't have to be root.  */
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE

  struct pst_dynamic dyn_info;
  if (pstat_getdynamic (&dyn_info, sizeof (dyn_info), 0, 0) < 0)
    return -1;
  if (nelem > 0)
    loadavg[elem++] = dyn_info.psd_avg_1_min;
  if (nelem > 1)
    loadavg[elem++] = dyn_info.psd_avg_5_min;
  if (nelem > 2)
    loadavg[elem++] = dyn_info.psd_avg_15_min;

# endif /* hpux && HAVE_PSTAT_GETDYNAMIC */

# if ! defined LDAV_DONE && defined HAVE_LIBPERFSTAT
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE
/* Use perfstat_cpu_total because we don't have to be root. */
  {
    perfstat_cpu_total_t cpu_stats;
    int result = perfstat_cpu_total (NULL, &cpu_stats, sizeof cpu_stats, 1);
    if (result == -1)
      return result;
    loadavg[0] = cpu_stats.loadavg[0] / (double)(1 << SBITS);
    loadavg[1] = cpu_stats.loadavg[1] / (double)(1 << SBITS);
    loadavg[2] = cpu_stats.loadavg[2] / (double)(1 << SBITS);
    elem = 3;
  }
# endif

# if !defined (LDAV_DONE) && (defined (__linux__) || defined (__CYGWIN__))
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE

#  ifndef LINUX_LDAV_FILE
#   define LINUX_LDAV_FILE "/proc/loadavg"
#  endif

  char ldavgbuf[3 * (INT_STRLEN_BOUND (int) + sizeof ".00 ")];
  char const *ptr = ldavgbuf;
  int fd, count;

  fd = open (LINUX_LDAV_FILE, O_RDONLY);
  if (fd == -1)
    return -1;
  count = read (fd, ldavgbuf, sizeof ldavgbuf - 1);
  (void) close (fd);
  if (count <= 0)
    return -1;
  ldavgbuf[count] = '\0';

  for (elem = 0; elem < nelem; elem++)
    {
      char *endptr;
      double d;

      errno = 0;
      d = c_strtod (ptr, &endptr);
      if (ptr == endptr || (d == 0 && errno != 0))
        {
          if (elem == 0)
            return -1;
          break;
        }
      loadavg[elem] = d;
      ptr = endptr;
    }

  return elem;

# endif /* __linux__ || __CYGWIN__ */

# if !defined (LDAV_DONE) && defined (__NetBSD__)
#  define LDAV_DONE
#  undef LOAD_AVE_TYPE

#  ifndef NETBSD_LDAV_FILE
#   define NETBSD_LDAV_FILE "/kern/loadavg"
#  endif

  unsigned long int load_ave[3], scale;
  int count;
  FILE *fp;

  fp = fopen (NETBSD_LDAV_FILE, "r");
  if (fp == NULL)
    return -1;
  count = fscanf (fp, "%lu %lu %lu %lu\n",
                  &load_ave[0], &load_ave[1], &load_ave[2],
                  &scale);
  (void) fclose (fp);
  if (count != 4)
    return -1;

  for (elem = 0; elem < nelem; elem++)
    loadavg[elem] = (double) load_ave[elem] / (double) scale;

  return elem;

# endif /* __NetBSD__ */

# if !defined (LDAV_DONE) && defined (NeXT)
#  define LDAV_DONE
  /* The NeXT code was adapted from iscreen 3.2.  */

  host_t host;
  struct processor_set_basic_info info;
  unsigned int info_count;

  /* We only know how to get the 1-minute average for this system,
     so even if the caller asks for more than 1, we only return 1.  */

  if (!getloadavg_initialized)
    {
      if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
        getloadavg_initialized = true;
    }

  if (getloadavg_initialized)
    {
      info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
      if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
                              (processor_set_info_t) &info, &info_count)
          != KERN_SUCCESS)
        getloadavg_initialized = false;
      else
        {
          if (nelem > 0)
            loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
        }
    }

  if (!getloadavg_initialized)
    return -1;
# endif /* NeXT */

# if !defined (LDAV_DONE) && defined (UMAX)
#  define LDAV_DONE
/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
   have a /dev/kmem.  Information about the workings of the running kernel
   can be gathered with inq_stats system calls.
   We only know how to get the 1-minute average for this system.  */

  struct proc_summary proc_sum_data;
  struct stat_descr proc_info;
  double load;
  register unsigned int i, j;

  if (cpus == 0)
    {
      register unsigned int c, i;
      struct cpu_config conf;
      struct stat_descr desc;

      desc.sd_next = 0;
      desc.sd_subsys = SUBSYS_CPU;
      desc.sd_type = CPUTYPE_CONFIG;
      desc.sd_addr = (char *) &conf;
      desc.sd_size = sizeof conf;

      if (inq_stats (1, &desc))
        return -1;

      c = 0;
      for (i = 0; i < conf.config_maxclass; ++i)
        {
          struct class_stats stats;
          bzero ((char *) &stats, sizeof stats);

          desc.sd_type = CPUTYPE_CLASS;
          desc.sd_objid = i;
          desc.sd_addr = (char *) &stats;
          desc.sd_size = sizeof stats;

          if (inq_stats (1, &desc))
            return -1;

          c += stats.class_numcpus;
        }
      cpus = c;
      samples = cpus < 2 ? 3 : (2 * cpus / 3);
    }

  proc_info.sd_next = 0;
  proc_info.sd_subsys = SUBSYS_PROC;
  proc_info.sd_type = PROCTYPE_SUMMARY;
  proc_info.sd_addr = (char *) &proc_sum_data;
  proc_info.sd_size = sizeof (struct proc_summary);
  proc_info.sd_sizeused = 0;

  if (inq_stats (1, &proc_info) != 0)
    return -1;

  load = proc_sum_data.ps_nrunnable;
  j = 0;
  for (i = samples - 1; i > 0; --i)
    {
      load += proc_sum_data.ps_nrun[j];
      if (j++ == PS_NRUNSIZE)
        j = 0;
    }

  if (nelem > 0)
    loadavg[elem++] = load / samples / cpus;
# endif /* UMAX */

# if !defined (LDAV_DONE) && defined (DGUX)
#  define LDAV_DONE
  /* This call can return -1 for an error, but with good args
     it's not supposed to fail.  The first argument is for no
     apparent reason of type `long int *'.  */
  dg_sys_info ((long int *) &load_info,
               DG_SYS_INFO_LOAD_INFO_TYPE,
               DG_SYS_INFO_LOAD_VERSION_0);

  if (nelem > 0)
    loadavg[elem++] = load_info.one_minute;
  if (nelem > 1)
    loadavg[elem++] = load_info.five_minute;
  if (nelem > 2)
    loadavg[elem++] = load_info.fifteen_minute;
# endif /* DGUX */

# if !defined (LDAV_DONE) && defined (apollo)
#  define LDAV_DONE
/* Apollo code from [email protected] (Ray Lischner).

   This system call is not documented.  The load average is obtained as
   three long integers, for the load average over the past minute,
   five minutes, and fifteen minutes.  Each value is a scaled integer,
   with 16 bits of integer part and 16 bits of fraction part.

   I'm not sure which operating system first supported this system call,
   but I know that SR10.2 supports it.  */

  extern void proc1_$get_loadav ();
  unsigned long load_ave[3];

  proc1_$get_loadav (load_ave);

  if (nelem > 0)
    loadavg[elem++] = load_ave[0] / 65536.0;
  if (nelem > 1)
    loadavg[elem++] = load_ave[1] / 65536.0;
  if (nelem > 2)
    loadavg[elem++] = load_ave[2] / 65536.0;
# endif /* apollo */

# if !defined (LDAV_DONE) && defined (OSF_MIPS)
#  define LDAV_DONE

  struct tbl_loadavg load_ave;
  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
  loadavg[elem++]
    = (load_ave.tl_lscale == 0
       ? load_ave.tl_avenrun.d[0]
       : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
# endif /* OSF_MIPS */

# if !defined (LDAV_DONE) && (defined (__MSDOS__) || defined (WINDOWS32))
#  define LDAV_DONE

  /* A faithful emulation is going to have to be saved for a rainy day.  */
  for ( ; elem < nelem; elem++)
    {
      loadavg[elem] = 0.0;
    }
# endif  /* __MSDOS__ || WINDOWS32 */

# if !defined (LDAV_DONE) && defined (OSF_ALPHA)
#  define LDAV_DONE

  struct tbl_loadavg load_ave;
  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
  for (elem = 0; elem < nelem; elem++)
    loadavg[elem]
      = (load_ave.tl_lscale == 0
         ? load_ave.tl_avenrun.d[elem]
         : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
# endif /* OSF_ALPHA */

# if ! defined LDAV_DONE && defined __VMS
  /* VMS specific code -- read from the Load Ave driver.  */

  LOAD_AVE_TYPE load_ave[3];
  static bool getloadavg_initialized;
#  ifdef eunice
  struct
  {
    int dsc$w_length;
    char *dsc$a_pointer;
  } descriptor;
#  endif

  /* Ensure that there is a channel open to the load ave device.  */
  if (!getloadavg_initialized)
    {
      /* Attempt to open the channel.  */
#  ifdef eunice
      descriptor.dsc$w_length = 18;
      descriptor.dsc$a_pointer = "$$VMS_LOAD_AVERAGE";
#  else
      $DESCRIPTOR (descriptor, "LAV0:");
#  endif
      if (sys$assign (&descriptor, &channel, 0, 0) & 1)
        getloadavg_initialized = true;
    }

  /* Read the load average vector.  */
  if (getloadavg_initialized
      && !(sys$qiow (0, channel, IO$_READVBLK, 0, 0, 0,
                     load_ave, 12, 0, 0, 0, 0) & 1))
    {
      sys$dassgn (channel);
      getloadavg_initialized = false;
    }

  if (!getloadavg_initialized)
    return -1;
# endif /* ! defined LDAV_DONE && defined __VMS */

# if ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS

  /* UNIX-specific code -- read the average from /dev/kmem.  */

#  define LDAV_PRIVILEGED               /* This code requires special installation.  */

  LOAD_AVE_TYPE load_ave[3];

  /* Get the address of LDAV_SYMBOL.  */
  if (offset == 0)
    {
#  ifndef sgi
#   if ! defined NLIST_STRUCT || ! defined N_NAME_POINTER
      strcpy (nl[0].n_name, LDAV_SYMBOL);
      strcpy (nl[1].n_name, "");
#   else /* NLIST_STRUCT */
#    ifdef HAVE_STRUCT_NLIST_N_UN_N_NAME
      nl[0].n_un.n_name = LDAV_SYMBOL;
      nl[1].n_un.n_name = 0;
#    else /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
      nl[0].n_name = LDAV_SYMBOL;
      nl[1].n_name = 0;
#    endif /* not HAVE_STRUCT_NLIST_N_UN_N_NAME */
#   endif /* NLIST_STRUCT */

#   ifndef SUNOS_5
      if (
#    if !(defined (_AIX) && !defined (ps2))
          nlist (KERNEL_FILE, nl)
#    else  /* _AIX */
          knlist (nl, 1, sizeof (nl[0]))
#    endif
          >= 0)
          /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i.  */
          {
#    ifdef FIXUP_KERNEL_SYMBOL_ADDR
            FIXUP_KERNEL_SYMBOL_ADDR (nl);
#    endif
            offset = nl[0].n_value;
          }
#   endif /* !SUNOS_5 */
#  else  /* sgi */
      int ldav_off;

      ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
      if (ldav_off != -1)
        offset = (long int) ldav_off & 0x7fffffff;
#  endif /* sgi */
    }

  /* Make sure we have /dev/kmem open.  */
  if (!getloadavg_initialized)
    {
#  ifndef SUNOS_5
      channel = open ("/dev/kmem", O_RDONLY);
      if (channel >= 0)
        {
          /* Set the channel to close on exec, so it does not
             litter any child's descriptor table.  */
          set_cloexec_flag (channel, true);
          getloadavg_initialized = true;
        }
#  else /* SUNOS_5 */
      /* We pass 0 for the kernel, corefile, and swapfile names
         to use the currently running kernel.  */
      kd = kvm_open (0, 0, 0, O_RDONLY, 0);
      if (kd != 0)
        {
          /* nlist the currently running kernel.  */
          kvm_nlist (kd, nl);
          offset = nl[0].n_value;
          getloadavg_initialized = true;
        }
#  endif /* SUNOS_5 */
    }

  /* If we can, get the load average values.  */
  if (offset && getloadavg_initialized)
    {
      /* Try to read the load.  */
#  ifndef SUNOS_5
      if (lseek (channel, offset, 0) == -1L
          || read (channel, (char *) load_ave, sizeof (load_ave))
          != sizeof (load_ave))
        {
          close (channel);
          getloadavg_initialized = false;
        }
#  else  /* SUNOS_5 */
      if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
          != sizeof (load_ave))
        {
          kvm_close (kd);
          getloadavg_initialized = false;
        }
#  endif /* SUNOS_5 */
    }

  if (offset == 0 || !getloadavg_initialized)
    return -1;
# endif /* ! defined LDAV_DONE && defined LOAD_AVE_TYPE && ! defined __VMS */

# if !defined (LDAV_DONE) && defined (LOAD_AVE_TYPE) /* Including VMS.  */
  if (nelem > 0)
    loadavg[elem++] = LDAV_CVT (load_ave[0]);
  if (nelem > 1)
    loadavg[elem++] = LDAV_CVT (load_ave[1]);
  if (nelem > 2)
    loadavg[elem++] = LDAV_CVT (load_ave[2]);

#  define LDAV_DONE
# endif /* !LDAV_DONE && LOAD_AVE_TYPE */

# if !defined LDAV_DONE
  /* Set errno to zero to indicate that there was no particular error;
     this function just can't work at all on this system.  */
  errno = 0;
  elem = -1;
# endif
  return elem;
}
Exemplo n.º 8
0
int
getloadavg (double loadavg[], int nelem)
{
  int elem = 0;			/* Return value.  */

#ifdef NO_GET_LOAD_AVG
#define LDAV_DONE
  /* Set errno to zero to indicate that there was no particular error;
     this function just can't work at all on this system.  */
  errno = 0;
  elem = -2;
#endif /* NO_GET_LOAD_AVG */

#if ! defined (LDAV_DONE) && defined (HAVE_KSTAT_H) && defined (HAVE_LIBKSTAT)
#define LDAV_DONE
/* getloadavg is best implemented using kstat (kernel stats), on
   systems (like SunOS5) that support it, since you don't need special
   privileges to use it.

   Initial implementation courtesy Zlatko Calusic <*****@*****.**>.
   Integrated to XEmacs by Hrvoje Niksic <*****@*****.**>.
   Additional cleanup by Hrvoje Niksic, based on code published by
   Casper Dik <*****@*****.**>.  */
  kstat_ctl_t *kc;
  kstat_t *ksp;
  static char *avestrings[] = { "avenrun_1min",
				"avenrun_5min",
				"avenrun_15min" };

  if (nelem > countof (avestrings))
    nelem = countof (avestrings);

  kc = kstat_open ();
  if (!kc)
    return -1;
  ksp = kstat_lookup (kc, "unix", 0, "system_misc");
  if (!ksp)
    {
      kstat_close (kc);
      return -1;
    }
  if (kstat_read (kc, ksp, 0) < 0)
    {
      kstat_close (kc);
      return -1;
    }
  for (elem = 0; elem < nelem; elem++)
    {
      kstat_named_t *kn =
	(kstat_named_t *) kstat_data_lookup (ksp, avestrings[elem]);
      if (!kn)
	{
	  kstat_close (kc);
	  return -1;
	}
      loadavg[elem] = (double)kn->value.ul / FSCALE;
    }
  kstat_close (kc);
#endif /* HAVE_KSTAT_H && HAVE_LIBKSTAT */

#if !defined (LDAV_DONE) && defined (HAVE_SYS_PSTAT_H)
#define LDAV_DONE
  /* This is totally undocumented, and is not guaranteed to work, but
     mayhap it might ....  If it does work, it will work only on HP-UX
     8.0 or later.  -- Darryl Okahata <*****@*****.**> */
#undef LOAD_AVE_TYPE		/* Make sure these don't exist. */
#undef LOAD_AVE_CVT
#undef LDAV_SYMBOL
  struct pst_dynamic	procinfo;
  union pstun		statbuf;

  statbuf.pst_dynamic = &procinfo;
  if (pstat (PSTAT_DYNAMIC, statbuf, sizeof (struct pst_dynamic), 0, 0) == -1)
    return (-1);
  loadavg[elem++] = procinfo.psd_avg_1_min;
  loadavg[elem++] = procinfo.psd_avg_5_min;
  loadavg[elem++] = procinfo.psd_avg_15_min;
#endif	/* HPUX */

#if !defined (LDAV_DONE) && defined (__linux__)
#define LDAV_DONE
#undef LOAD_AVE_TYPE

#ifndef LINUX_LDAV_FILE
#define LINUX_LDAV_FILE "/proc/loadavg"
#endif

  char ldavgbuf[40];
  double load_ave[3];
  int fd, count;

  fd = open (LINUX_LDAV_FILE, O_RDONLY);
  if (fd == -1)
    return -1;
  count = read (fd, ldavgbuf, 40);
  (void) close (fd);
  if (count <= 0)
    return -1;

  count = sscanf (ldavgbuf, "%lf %lf %lf",
		  &load_ave[0], &load_ave[1], &load_ave[2]);
  if (count < 1)
    return -1;

  for (elem = 0; elem < nelem && elem < count; elem++)
    loadavg[elem] = load_ave[elem];
#endif /* __linux__ */

#if !defined (LDAV_DONE) && defined (__NetBSD__) || defined (__OpenBSD__)
#define LDAV_DONE
#undef LOAD_AVE_TYPE

#ifndef NETBSD_LDAV_FILE
#define NETBSD_LDAV_FILE "/kern/loadavg"
#endif

  unsigned long int load_ave[3], scale;
  int count;
  FILE *fp;

  fp = fopen (NETBSD_LDAV_FILE, "r");
  if (fp == NULL)
    return -1;
  count = fscanf (fp, "%lu %lu %lu %lu\n",
		  &load_ave[0], &load_ave[1], &load_ave[2],
		  &scale);
  (void) fclose (fp);
  if (count != 4)
    return -1;

  for (elem = 0; elem < nelem; elem++)
    loadavg[elem] = (double) load_ave[elem] / (double) scale;
#endif /* __NetBSD__ or __OpenBSD__ */

#if !defined (LDAV_DONE) && defined (NeXT)
#define LDAV_DONE
  /* The NeXT code was adapted from iscreen 3.2.  */

  host_t host;
  struct processor_set_basic_info info;
  unsigned info_count;

  /* We only know how to get the 1-minute average for this system,
     so even if the caller asks for more than 1, we only return 1.  */

  if (!getloadavg_initialized)
    {
      if (processor_set_default (host_self (), &default_set) == KERN_SUCCESS)
	getloadavg_initialized = 1;
    }

  if (getloadavg_initialized)
    {
      info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
      if (processor_set_info (default_set, PROCESSOR_SET_BASIC_INFO, &host,
			     (processor_set_info_t) &info, &info_count)
	  != KERN_SUCCESS)
	getloadavg_initialized = 0;
      else
	{
	  if (nelem > 0)
	    loadavg[elem++] = (double) info.load_average / LOAD_SCALE;
	}
    }

  if (!getloadavg_initialized)
    return -1;
#endif /* NeXT */

#if !defined (LDAV_DONE) && defined (UMAX)
#define LDAV_DONE
/* UMAX 4.2, which runs on the Encore Multimax multiprocessor, does not
   have a /dev/kmem.  Information about the workings of the running kernel
   can be gathered with inq_stats system calls.
   We only know how to get the 1-minute average for this system.  */

  struct proc_summary proc_sum_data;
  struct stat_descr proc_info;
  double load;
  REGISTER unsigned int i, j;

  if (cpus == 0)
    {
      REGISTER unsigned int c, i;
      struct cpu_config conf;
      struct stat_descr desc;

      desc.sd_next = 0;
      desc.sd_subsys = SUBSYS_CPU;
      desc.sd_type = CPUTYPE_CONFIG;
      desc.sd_addr = (char *) &conf;
      desc.sd_size = sizeof conf;

      if (inq_stats (1, &desc))
	return -1;

      c = 0;
      for (i = 0; i < conf.config_maxclass; ++i)
	{
	  struct class_stats stats;
	  memset ((char *) &stats, 0, sizeof stats);

	  desc.sd_type = CPUTYPE_CLASS;
	  desc.sd_objid = i;
	  desc.sd_addr = (char *) &stats;
	  desc.sd_size = sizeof stats;

	  if (inq_stats (1, &desc))
	    return -1;

	  c += stats.class_numcpus;
	}
      cpus = c;
      samples = cpus < 2 ? 3 : (2 * cpus / 3);
    }

  proc_info.sd_next = 0;
  proc_info.sd_subsys = SUBSYS_PROC;
  proc_info.sd_type = PROCTYPE_SUMMARY;
  proc_info.sd_addr = (char *) &proc_sum_data;
  proc_info.sd_size = sizeof (struct proc_summary);
  proc_info.sd_sizeused = 0;

  if (inq_stats (1, &proc_info) != 0)
    return -1;

  load = proc_sum_data.ps_nrunnable;
  j = 0;
  for (i = samples - 1; i > 0; --i)
    {
      load += proc_sum_data.ps_nrun[j];
      if (j++ == PS_NRUNSIZE)
	j = 0;
    }

  if (nelem > 0)
    loadavg[elem++] = load / samples / cpus;
#endif /* UMAX */

#if !defined (LDAV_DONE) && defined (DGUX)
#define LDAV_DONE
  /* This call can return -1 for an error, but with good args
     it's not supposed to fail.  The first argument is for no
     apparent reason of type `long int *'.  */
  dg_sys_info ((long int *) &load_info,
	       DG_SYS_INFO_LOAD_INFO_TYPE,
	       DG_SYS_INFO_LOAD_VERSION_0);

  if (nelem > 0)
    loadavg[elem++] = load_info.one_minute;
  if (nelem > 1)
    loadavg[elem++] = load_info.five_minute;
  if (nelem > 2)
    loadavg[elem++] = load_info.fifteen_minute;
#endif /* DGUX */

#if !defined (LDAV_DONE) && defined (OSF_MIPS)
#define LDAV_DONE

  struct tbl_loadavg load_ave;
  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
  loadavg[elem++]
    = (load_ave.tl_lscale == 0
       ? load_ave.tl_avenrun.d[0]
       : (load_ave.tl_avenrun.l[0] / (double) load_ave.tl_lscale));
#endif	/* OSF_MIPS */

#if !defined (LDAV_DONE) && (defined (WIN32_NATIVE) || defined (CYGWIN))
#define LDAV_DONE

  /* A faithful emulation is going to have to be saved for a rainy day.  */
  for ( ; elem < nelem; elem++)
    {
      loadavg[elem] = 0.0;
    }
#endif  /* WIN32_NATIVE or CYGWIN */

#if !defined (LDAV_DONE) && defined (OSF_ALPHA)
#define LDAV_DONE

  struct tbl_loadavg load_ave;
  table (TBL_LOADAVG, 0, &load_ave, 1, sizeof (load_ave));
  for (elem = 0; elem < nelem; elem++)
    loadavg[elem]
      = (load_ave.tl_lscale == 0
       ? load_ave.tl_avenrun.d[elem]
       : (load_ave.tl_avenrun.l[elem] / (double) load_ave.tl_lscale));
#endif /* OSF_ALPHA */

#if !defined (LDAV_DONE) && defined(LOAD_AVE_TYPE)

  /* UNIX-specific code -- read the average from /dev/kmem.  */

#define LDAV_PRIVILEGED		/* This code requires special installation.  */

  LOAD_AVE_TYPE load_ave[3];

  /* Get the address of LDAV_SYMBOL.  */
  if (offset == 0)
    {
#ifndef sgi
#ifndef NLIST_STRUCT
      strcpy (nl[0].n_name, LDAV_SYMBOL);
      strcpy (nl[1].n_name, "");
#else /* NLIST_STRUCT */
#ifdef NLIST_NAME_UNION
      nl[0].n_un.n_name = LDAV_SYMBOL;
      nl[1].n_un.n_name = 0;
#else /* not NLIST_NAME_UNION */
      nl[0].n_name = (char *) LDAV_SYMBOL;
      nl[1].n_name = 0;
#endif /* not NLIST_NAME_UNION */
#endif /* NLIST_STRUCT */

#ifndef SUNOS_5
      if (
#if !(defined (_AIX) && !defined (ps2))
	  nlist (KERNEL_FILE, nl)
#else  /* _AIX */
	  knlist (nl, 1, sizeof (nl[0]))
#endif
	  >= 0)
	  /* Omit "&& nl[0].n_type != 0 " -- it breaks on Sun386i.  */
	  {
#ifdef FIXUP_KERNEL_SYMBOL_ADDR
	    FIXUP_KERNEL_SYMBOL_ADDR (nl);
#endif
	    offset = nl[0].n_value;
	  }
#endif /* !SUNOS_5 */
#else  /* sgi */
	  int ldav_off;

	  ldav_off = sysmp (MP_KERNADDR, MPKA_AVENRUN);
	  if (ldav_off != -1)
	  offset = (long) ldav_off & 0x7fffffff;
#endif /* sgi */
	}

  /* Make sure we have /dev/kmem open.  */
  if (!getloadavg_initialized)
    {
#ifndef SUNOS_5
      channel = open ("/dev/kmem", 0);
      if (channel >= 0)
	{
	  /* Set the channel to close on exec, so it does not
	     litter any child's descriptor table.  */
#ifdef FD_SETFD
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
	  (void) fcntl (channel, F_SETFD, FD_CLOEXEC);
#endif
	  getloadavg_initialized = 1;
	}
#else /* SUNOS_5 */
      /* We pass 0 for the kernel, corefile, and swapfile names
	 to use the currently running kernel.  */
      kd = kvm_open (0, 0, 0, O_RDONLY, 0);
      if (kd != 0)
	{
	  /* nlist the currently running kernel.  */
	  kvm_nlist (kd, nl);
	  offset = nl[0].n_value;
	  getloadavg_initialized = 1;
	}
#endif /* SUNOS_5 */
    }

  /* If we can, get the load average values.  */
  if (offset && getloadavg_initialized)
    {
      /* Try to read the load.  */
#ifndef SUNOS_5
      if (lseek (channel, offset, 0) == -1L
	  || read (channel, (char *) load_ave, sizeof (load_ave))
	  != sizeof (load_ave))
	{
	  close (channel);
	  getloadavg_initialized = 0;
	}
#else  /* SUNOS_5 */
      if (kvm_read (kd, offset, (char *) load_ave, sizeof (load_ave))
	  != sizeof (load_ave))
        {
          kvm_close (kd);
          getloadavg_initialized = 0;
	}
#endif /* SUNOS_5 */
    }

  if (offset == 0 || !getloadavg_initialized)
    return -1;

  if (nelem > 0)
    loadavg[elem++] = LDAV_CVT (load_ave[0]);
  if (nelem > 1)
    loadavg[elem++] = LDAV_CVT (load_ave[1]);
  if (nelem > 2)
    loadavg[elem++] = LDAV_CVT (load_ave[2]);

#define LDAV_DONE
#endif /* !LDAV_DONE && LOAD_AVE_TYPE */

  return elem;
}
Exemplo n.º 9
0
int main(int argc, char *argv[])
{
    kern_return_t		ret;
    unsigned int		size, count;
    char			*cpu_name, *cpu_subname;
    int			i;
    int 			mib[2];
    size_t			len;
    uint64_t		memsize;
    processor_set_name_port_t		default_pset;
    host_name_port_t			host;
    struct processor_set_basic_info	basic_info;
    struct processor_set_load_info	load_info;

    host = mach_host_self();
    ret = host_kernel_version(host, version);
    if (ret != KERN_SUCCESS) {
        mach_error(argv[0], ret);
        exit(EXIT_FAILURE);
    }
    printf("Mach kernel version:\n\t %s\n", version);
    size = sizeof(hi)/sizeof(int);
    ret = host_info(host, HOST_BASIC_INFO, (host_info_t)&hi, &size);
    if (ret != KERN_SUCCESS) {
        mach_error(argv[0], ret);
        exit(EXIT_FAILURE);
    }

    ret = processor_set_default(host, &default_pset);
    if (ret != KERN_SUCCESS) {
        mach_error(argv[0], ret);
        exit(EXIT_FAILURE);
    }

    count = PROCESSOR_SET_BASIC_INFO_COUNT;
    ret = processor_set_info(default_pset, PROCESSOR_SET_BASIC_INFO,
                             &host, (processor_set_info_t)&basic_info, &count);
    if (ret != KERN_SUCCESS) {
        mach_error(argv[0], ret);
        exit(EXIT_FAILURE);
    }

    count = PROCESSOR_SET_LOAD_INFO_COUNT;
    ret = processor_set_statistics(default_pset, PROCESSOR_SET_LOAD_INFO,
                                   (processor_set_info_t)&load_info, &count);
    if (ret != KERN_SUCCESS) {
        mach_error(argv[0], ret);
        exit(EXIT_FAILURE);
    }

    mib[0] = CTL_HW;
    mib[1] = HW_MEMSIZE;
    len = sizeof(memsize);
    memsize = 0L;
    if(sysctl(mib, 2, &memsize, &len, NULL, 0 ) == -1)
    {
        perror("sysctl");
        exit(EXIT_FAILURE);
    }


    if (hi.max_cpus > 1)
        printf("Kernel configured for up to %d processors.\n",
               hi.max_cpus);
    else
        printf("Kernel configured for a single processor only.\n");
    printf("%d processor%s physically available.\n", hi.physical_cpu,
           (hi.physical_cpu > 1) ? "s are" : " is");

    printf("%d processor%s logically available.\n", hi.logical_cpu,
           (hi.logical_cpu > 1) ? "s are" : " is");

    printf("Processor type:");
    slot_name(hi.cpu_type, hi.cpu_subtype, &cpu_name, &cpu_subname);
    printf(" %s (%s)\n", cpu_name, cpu_subname);

    printf("Processor%s active:", (hi.avail_cpus > 1) ? "s" : "");
    for (i = 0; i < hi.avail_cpus; i++)
        printf(" %d", i);
    printf("\n");

    if (((float)memsize / (1024.0 * 1024.0)) >= 1024.0)
        printf("Primary memory available: %.2f gigabytes\n",
               (float)memsize/(1024.0*1024.0*1024.0));
    else
        printf("Primary memory available: %.2f megabytes\n",
               (float)memsize/(1024.0*1024.0));

    printf("Default processor set: %d tasks, %d threads, %d processors\n",
           load_info.task_count, load_info.thread_count, basic_info.processor_count);
    printf("Load average: %d.%02d, Mach factor: %d.%02d\n",
           load_info.load_average/LOAD_SCALE,
           (load_info.load_average%LOAD_SCALE)/10,
           load_info.mach_factor/LOAD_SCALE,
           (load_info.mach_factor%LOAD_SCALE)/10);

    exit(0);
}
Exemplo n.º 10
0
bool SysInfo::GetAllProcess()
{
	kern_return_t	error;
	processor_set_t	*psets, pset;
	task_t		*tasks;
	unsigned	i, j, pcnt, tcnt;
	
	m_nTotalTime = 0;
	host_priv_t libtop_port = mach_host_self();

	// 必须获得系统root权限才能访问所有process list,下面这段代码不能获得,暂用pxl制作包来解决权限问题
	host_t myhost = mach_host_self();
	processor_set_name_t p_default_set;
	processor_set_t p_default_set_control;
	/* get the default processor set */
	error = processor_set_default(myhost, &p_default_set);
	if (KERN_SUCCESS != error)
	{
		printf("Error in processor_set_default(): %s \n",mach_error_string(error));

		char szInfo[256] = { 0 };
		snprintf(szInfo, sizeof(szInfo) - 1, "processor_set_default error");
		LogMsg(szInfo);
	}
	/* get the control port for this processor set */
	error = host_processor_set_priv(myhost, p_default_set, &p_default_set_control);
	if (KERN_SUCCESS != error)
	{
	}

	error = host_processor_sets(libtop_port, &psets, &pcnt);
	if (error != KERN_SUCCESS) {
		GetProcessInfo(mach_task_self());
		return TRUE;
	}
	
	m_pInfoList.clear();

	for (i = 0; i < pcnt; i++) {
		error = host_processor_set_priv(libtop_port, psets[i], &pset);
		if (error != KERN_SUCCESS) {
			printf("Error in host_processor_set_priv(): %s \n",mach_error_string(error));
			
			char szInfo[256] = { 0 };
			snprintf(szInfo, sizeof(szInfo) - 1, "host_processor_set_priv error");
			LogMsg(szInfo);

			return true;
		}
		
		error = processor_set_tasks(pset, &tasks, &tcnt);
		if (error != KERN_SUCCESS) {
			printf("Error in processor_set_tasks(): %s \n",mach_error_string(error));
			
			char szInfo[256] = { 0 };
			snprintf(szInfo, sizeof(szInfo) - 1, "processor_set_tasks error");
			LogMsg(szInfo);

			return true;
		}
		
		for (j = 0; j < tcnt; j++) {
			if (GetProcessInfo(tasks[j])) 
			{
				return true;
			}
			mach_port_deallocate(mach_task_self(),tasks[j]);
		}
		error = vm_deallocate((vm_map_t)mach_task_self(),(vm_address_t)tasks, tcnt * sizeof(task_t));
		if (error != KERN_SUCCESS) {
			printf("Error in vm_deallocate(): %s \n",mach_error_string(error));
			return true;
		}
		if ((error = mach_port_deallocate(mach_task_self(),pset)) != KERN_SUCCESS
		    || (error = mach_port_deallocate(mach_task_self(),psets[i])) != KERN_SUCCESS) 
		{
			printf("Error in mach_port_deallocate(): %s \n",mach_error_string(error));
			return true;
		}
	}
	
	error = vm_deallocate((vm_map_t)mach_task_self(),(vm_address_t)psets, pcnt * sizeof(processor_set_t));
	if (error != KERN_SUCCESS) {
		printf("Error in vm_deallocate(): %s \n",mach_error_string(error));
		return true;
	}
	
	return false;
}
Exemplo n.º 11
0
int
main(int argc, char ** argv)
{
    int option = 0;
    struct config cfg = {0};

    header();
    if (argc < 2)
    {
        usage();
    }
        
    while( (option=getopt(argc,argv,"ha:Aco:Ci:rRs")) != -1 )
    {
        switch(option)
        {
            case 'h':
                usage();
                exit(1);
            case 'a':
                cfg.interrupt = atoi(optarg);
                break;
            case 'A': 
                cfg.show_all_descriptors = 1;
                break;
            case 'c': 
                cfg.create_file_archive = 1;
                break;
            case 'r': 
                cfg.read_file_archive = 1;
                break;
            case 'R': 
                cfg.restore_idt = 1;
                break;
            case 'o':
                if(strlen(optarg) > MAXPATHLEN - 1)
                {
                    ERROR_MSG("File name too long.");
                    return -1;
                }
                strncpy(cfg.out_filename, optarg, sizeof(cfg.out_filename));
                break;
            case 'C': 
                cfg.compare_idt = 1;
                break;
            case 'i': 
                if(strlen(optarg) > MAXPATHLEN - 1)
                {
                    ERROR_MSG("File name too long.");
                    return -1;
                }
                strncpy(cfg.in_filename, optarg, sizeof(cfg.in_filename));
                break;
            case 's': 
                cfg.resolve = 1;
                break;
        }
    }
    OUTPUT_MSG("");
    
    if (getuid() != 0)
    {
        ERROR_MSG("This program needs to be run as root!");
        return -1;
    }
    
    cfg.kernel_type = get_kernel_type();
    if (cfg.kernel_type == -1)
    {
        ERROR_MSG("Unable to retrieve kernel type.");
        return -1;
    }
    else if (cfg.kernel_type == X86)
    {
        ERROR_MSG("32 bits kernels not supported.");
        return -1;
    }
    
    cfg.idt_addr = get_addr_idt(cfg.kernel_type);
    cfg.idt_size = get_size_idt();
    cfg.idt_entries = cfg.idt_size / sizeof(struct descriptor_idt);
    /* we need to populate the size variable else syscall fails */
    cfg.kaslr_size = sizeof(cfg.kaslr_size);
    get_kaslr_slide(&cfg.kaslr_size, &cfg.kaslr_slide);
    
    OUTPUT_MSG("[INFO] Kaslr slide is 0x%llx", cfg.kaslr_slide);
    OUTPUT_MSG("[INFO] IDT base address is: 0x%llx", cfg.idt_addr);
    OUTPUT_MSG("[INFO] IDT size: 0x%x\n", cfg.idt_size);

    /* test if we can read kernel memory using processor_set_tasks() vulnerability */
    /* vulnerability presented at BlackHat Asia 2014 by Ming-chieh Pan, Sung-ting Tsai. */
    /* also described in Mac OS X and iOS Internals, page 387 */
    host_t host_port = mach_host_self();
    mach_port_t proc_set_default = 0;
    mach_port_t proc_set_default_control = 0;
    task_array_t all_tasks = NULL;
    mach_msg_type_number_t all_tasks_cnt = 0;
    kern_return_t kr = 0;
    int valid_kernel_port = 0;
    
    kr = processor_set_default(host_port, &proc_set_default);
    if (kr == KERN_SUCCESS)
    {
        kr = host_processor_set_priv(host_port, proc_set_default, &proc_set_default_control);
        if (kr == KERN_SUCCESS)
        {
            kr = processor_set_tasks(proc_set_default_control, &all_tasks, &all_tasks_cnt);
            if (kr == KERN_SUCCESS)
            {
                DEBUG_MSG("Found valid kernel port using processor_set_tasks() vulnerability!");
                cfg.kernel_port = all_tasks[0];
                valid_kernel_port = 1;
            }
        }
    }
    /* if we can't use the vulnerability then try /dev/kmem */
    if (valid_kernel_port == 0)
    {
        if( (cfg.fd_kmem = open("/dev/kmem",O_RDWR)) == -1 )
        {
            ERROR_MSG("Error while opening /dev/kmem. Is /dev/kmem enabled?");
            ERROR_MSG("Verify that /Library/Preferences/SystemConfiguration/com.apple.Boot.plist has kmem=1 parameter configured.");
            return -1;
        }
    }
    
    if (cfg.resolve == 1)
    {
        retrieve_kernel_symbols(&cfg);
    }
    
    if(cfg.interrupt >= 0 || cfg.show_all_descriptors == 1)
    {
        show_idt_info(&cfg);
    }
    if(cfg.create_file_archive == 1)
    {
        create_idt_archive(&cfg);
    }
    if(cfg.read_file_archive == 1)
    {
        read_idt_archive(&cfg);
    }
    if(cfg.compare_idt == 1)
    {
        compare_idt(&cfg);
    }
    if(cfg.restore_idt == 1)
    {
        compare_idt(&cfg);
    }
    return 0;
}