Ejemplo n.º 1
0
static void cpuid_or_from_dump(unsigned *eax, unsigned *ebx, unsigned *ecx, unsigned *edx, struct cpuiddump *src_cpuiddump)
{
  if (src_cpuiddump) {
    cpuiddump_find_by_input(eax, ebx, ecx, edx, src_cpuiddump);
  } else {
    hwloc_x86_cpuid(eax, ebx, ecx, edx);
  }
}
Ejemplo n.º 2
0
static void dump_one_cpuid(FILE *output, unsigned *regs, unsigned inregmask)
{
  unsigned i;

  /* clear unused inputs */
  for(i=0; i<4; i++)
    if (!(inregmask & (1<<i)))
      regs[i] = 0;

  fprintf(output, "%x %x %x %x %x", inregmask, regs[0], regs[1], regs[2], regs[3]);
  hwloc_x86_cpuid(&regs[0], &regs[1], &regs[2], &regs[3]);
  fprintf(output, " => %x %x %x %x\n", regs[0], regs[1], regs[2], regs[3]);
}
Ejemplo n.º 3
0
static int dump_one_proc(hwloc_topology_t topo, hwloc_obj_t pu, const char *path)
{
  unsigned regs[4];
  unsigned highest_cpuid, highest_ext_cpuid;
  unsigned i;
  int has_intel_x2apic = 0;
  int has_intel_sgx = 0;
  int has_amd_topoext = 0;
  FILE *output;
  int err;

  err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_PROCESS);
  if (err < 0) {
    err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_THREAD);
    if (err < 0) {
      fprintf(stderr, "Cannot bind to PU P#%u\n", pu->os_index);
      return -1;
    }
  }

  if (path) {
    output = fopen(path, "w");
    if (!output) {
      fprintf(stderr, "Cannot open file '%s' for writing: %s\n", path, strerror(errno));
      return -1;
    }
    if (verbose)
      printf("Gathering CPUID of PU P#%u in path %s ...\n", pu->os_index, path);
  } else {
    output = stdout;
    if (verbose)
      printf("Gathering CPUID of PU P#%u on stdout ...\n", pu->os_index);
  }

  fprintf(output, "# mask e[abcd]x => e[abcd]x\n");

  regs[0] = 0;
  hwloc_x86_cpuid(&regs[0], &regs[1], &regs[2], &regs[3]);
  highest_cpuid = regs[0];
  regs[0] = 0x80000000;
  hwloc_x86_cpuid(&regs[0], &regs[1], &regs[2], &regs[3]);
  highest_ext_cpuid = regs[0];

  /* 0x0 = Highest cpuid + Vendor string */
  regs[0] = 0x0;
  dump_one_cpuid(output, regs, 0x1);

  /* 0x1 = Family, Model, Stepping, Topology, Features */
  if (highest_cpuid >= 0x1) {
    regs[0] = 0x1;
    dump_one_cpuid(output, regs, 0x1);
    if (regs[2] & (1 << 21))
      has_intel_x2apic = 1;
  }

  /* 0x2 = Cache + TLB on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x2) {
    regs[0] = 0x2;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x3 = Processor serial number on Intel P3, reserved otherwise ; Reserved on AMD */
  if (highest_cpuid >= 0x3) {
    regs[0] = 0x3;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x4 = Caches on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x4) {
    for(i=0; ; i++) {
      regs[0] = 0x4; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[0] & 0x1f))
	/* invalid, no more caches */
	break;
    }
  }

  /* 0x5 = Monitor/mwait */
  if (highest_cpuid >= 0x5) {
    regs[0] = 0x5;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x6 = Thermal and Power management */
  if (highest_cpuid >= 0x6) {
    regs[0] = 0x6;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x7 = Extended features */
  if (highest_cpuid >= 0x7) {
    unsigned max;
    regs[0] = 0x7; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    if (regs[1] & (1<<2))
      has_intel_sgx = 1;
    max = regs[0];
    for(i=1; i<=max; i++) {
      regs[0] = 0x7; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
    }
  }

  /* 0x9 = DCA on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x9) {
    regs[0] = 0x9;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0xa = Perf monitoring on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0xa) {
    regs[0] = 0xa;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0xb = Extended topology on Intel ; Reserved on AMD */
  if (has_intel_x2apic && highest_cpuid >= 0xb) {
    for(i=0; ; i++) {
      regs[0] = 0xb; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[2] & 0xff00))
	/* invalid, no more levels */
	break;
    }
  }

  /* 0xd = Extended state enumeration */
  if (highest_cpuid >= 0xd) {
    unsigned xcr0_l, xcr0_h, ia32xss_l, ia32xss_h;

    regs[0] = 0xd; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    xcr0_l = regs[0]; xcr0_h = regs[3];

    regs[0] = 0xd; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
    ia32xss_l = regs[2]; ia32xss_h = regs[3];

    for(i=2; i<32; i++) {
      if ((xcr0_l | ia32xss_l) & (1<<i)) {
	regs[0] = 0xd; regs[2] = i;
	dump_one_cpuid(output, regs, 0x5);
      }
    }
    for(i=0; i<32; i++) {
      if ((xcr0_h | ia32xss_h) & (1<<i)) {
	regs[0] = 0xd; regs[2] = i+32;
	dump_one_cpuid(output, regs, 0x5);
      }
    }
  }

  /* 0xf = Platform/L3 QoS enumeration on Intel and AMD */
  if (highest_cpuid >= 0xf) {
    regs[0] = 0xf; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0xf; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x10 = Platform/L3 QoS enforcement enumeration on Intel and AMD */
  if (highest_cpuid >= 0x10) {
    /* Intel Resource Director Technology (Intel RDT) Allocation */
    regs[0] = 0x10; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    /* L3 Cache Allocation Technology */
    regs[0] = 0x10; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
    /* L2 Cache Allocation Technology */
    regs[0] = 0x10; regs[2] = 2;
    dump_one_cpuid(output, regs, 0x5);
    /* Memory Bandwidth Allocation */
    regs[0] = 0x10; regs[2] = 3;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x12 = SGX Attributes Enumeration on Intel ; Reserved on AMD */
  if (has_intel_sgx && highest_cpuid >= 0x12) {
    regs[0] = 0x12; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0x12; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
    for(i=2; ; i++) {
      regs[0] = 0x12; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[0] & 0xf))
	/* invalid, no more subleaves */
	break;
    }
  }

  /* 0x14 = Processor trace enumeration on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x14) {
    regs[0] = 0x14; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0x14; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x15 = Timestamp counter/core crystal clock on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x15) {
    regs[0] = 0x15;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x16 = Processor frequency on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x16) {
    regs[0] = 0x16;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x17 = System-On-Chip Vendor Attribute on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x17) {
    unsigned maxsocid;
    regs[0] = 0x17; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    maxsocid = regs[0];
    if (maxsocid >= 3) {
      for(i=1; i<=maxsocid; i++) {
	regs[0] = 0x17; regs[2] = i;
	dump_one_cpuid(output, regs, 0x5);
      }
    }
  }

  /* 0x18 = Deterministic Address Translation Parameters on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x18) {
    unsigned max;
    regs[0] = 0x18; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    max = regs[0];
    for(i=1; i<=max; i++) {
      regs[0] = 0x18; regs[2] = i;
      regs[3] = 0; /* mark as invalid in case the cpuid call doesn't do anything */
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[3] & 0x1f))
	/* invalid, but it doesn't mean the next subleaf will be invalid */
        continue;
    }
  }

  /* 0x1b = (Removed) PCONFIG Information on Intel ; Reserved on AMD */

  /* 0x1f = V2 Extended Topology Enumeration on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x1f) {
    for(i=0; ; i++) {
      regs[0] = 0x1f; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[2] & 0xff00))
	/* invalid, no more levels */
	break;
    }
  }

  if (highest_cpuid > 0x1f) {
    static int reported = 0;
    if (!reported)
      fprintf(stderr, "WARNING: Processor supports new CPUID leaves upto 0x%x\n", highest_cpuid);
    reported = 1;
  }

  /* 0x80000000 = Largest extended cpuid */
  regs[0] = 0x80000000;
  dump_one_cpuid(output, regs, 0x1);

  /* 0x80000001 = Extended processor signature and features */
  if (highest_ext_cpuid >= 0x80000001) {
    regs[0] = 0x80000001;
    dump_one_cpuid(output, regs, 0x1);
    if (regs[2] & (1 << 22))
      has_amd_topoext = 1;
  }

  /* 0x80000002-4 = Processor name string */
  if (highest_ext_cpuid >= 0x80000002) {
    regs[0] = 0x80000002;
    dump_one_cpuid(output, regs, 0x1);
  }
  if (highest_ext_cpuid >= 0x80000003) {
    regs[0] = 0x80000003;
    dump_one_cpuid(output, regs, 0x1);
  }
  if (highest_ext_cpuid >= 0x80000004) {
    regs[0] = 0x80000004;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000005 = L1 and TLB on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x80000005) {
    regs[0] = 0x80000005;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000006 = L2, L3 and TLB on AMD ; L2 and reserved on Intel */
  if (highest_ext_cpuid >= 0x80000006) {
    regs[0] = 0x80000006;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000007 = Advanced power management on AMD ; Almost reserved on Intel */
  if (highest_ext_cpuid >= 0x80000007) {
    regs[0] = 0x80000007;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000008 = Long mode and topology on AMD ; Long mode on Intel */
  if (highest_ext_cpuid >= 0x80000008) {
    regs[0] = 0x80000008;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000000a = SVM on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000000a) {
    regs[0] = 0x8000000a;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000019 = TLB1G + Perf optim identifiers on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x80000019) {
    regs[0] = 0x80000019;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001b = IBS on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001b) {
    regs[0] = 0x8000001b;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001c = Profiling on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001c) {
    regs[0] = 0x8000001c;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001d = Cache properties on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001d) {
    for(i=0; ; i++) {
      regs[0] = 0x8000001d; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[0] & 0x1f))
	/* no such cache, no more cache */
	break;
    }
  }

  /* 0x8000001e = Topoext on AMD ; Reserved on Intel */
  if (has_amd_topoext && highest_ext_cpuid >= 0x8000001e) {
    regs[0] = 0x8000001e;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001f = Encrypted Memory Capabilities ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001f) {
    regs[0] = 0x8000001f;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000020 = Platform QoS Enforcement for Memory Bandwidth */
  if (highest_ext_cpuid >= 0x80000020) {
    regs[0] = 0x80000020; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0x80000020; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
  }

  if (highest_ext_cpuid > 0x8000001f) {
    static int reported = 0;
    if (!reported)
      fprintf(stderr, "WARNING: Processor supports new extended CPUID leaves upto 0x%x\n", highest_ext_cpuid);
    reported = 1;
  }

  if (path)
    fclose(output);
  return 0;
}
Ejemplo n.º 4
0
static int dump_one_proc(hwloc_topology_t topo, hwloc_obj_t pu, const char *path)
{
  unsigned regs[4];
  unsigned highest_cpuid, highest_ext_cpuid;
  unsigned i;
  FILE *output;
  int err;

  err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_PROCESS);
  if (err < 0) {
    err = hwloc_set_cpubind(topo, pu->cpuset, HWLOC_CPUBIND_THREAD);
    if (err < 0) {
      fprintf(stderr, "Cannot bind to PU P#%u\n", pu->os_index);
      return -1;
    }
  }

  if (path) {
    output = fopen(path, "w");
    if (!output) {
      fprintf(stderr, "Cannot open file '%s' for writing: %s\n", path, strerror(errno));
      return -1;
    }
    printf("Gathering CPUID of PU P#%u in path %s ...\n", pu->os_index, path);
  } else {
    output = stdout;
    printf("Gathering CPUID of PU P#%u on stdout ...\n", pu->os_index);
  }

  fprintf(output, "# mask e[abcd]x => e[abcd]x\n");

  regs[0] = 0;
  hwloc_x86_cpuid(&regs[0], &regs[1], &regs[2], &regs[3]);
  highest_cpuid = regs[0];
  regs[0] = 0x80000000;
  hwloc_x86_cpuid(&regs[0], &regs[1], &regs[2], &regs[3]);
  highest_ext_cpuid = regs[0];

  /* 0x0 = Highest cpuid + Vendor string */
  regs[0] = 0x0;
  dump_one_cpuid(output, regs, 0x1);

  /* 0x1 = Family, Model, Stepping, Topology, Features */
  if (highest_cpuid >= 0x1) {
    regs[0] = 0x1;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x2 = Cache + TLB on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x2) {
    regs[0] = 0x2;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x3 = Processor serial number on Intel P3, reserved otherwise ; Reserved on AMD */
  if (highest_cpuid >= 0x3) {
    regs[0] = 0x3;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x4 = Caches on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x4) {
    for(i=0; ; i++) {
      regs[0] = 0x4; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[0] & 0x1f))
	break;
    }
  }

  /* 0x5 = Monitor/mwait */
  if (highest_cpuid >= 0x5) {
    regs[0] = 0x5;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x6 = Thermal and Power management */
  if (highest_cpuid >= 0x6) {
    regs[0] = 0x6;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x7 = Extended features */
  if (highest_cpuid >= 0x7) {
    unsigned max;
    regs[0] = 0x7; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    max = regs[0];
    for(i=1; i<=max; i++) {
      regs[0] = 0x7; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
    }
  }

  /* 0x9 = DCA on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x9) {
    regs[0] = 0x9;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0xa = Perf monitoring on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0xa) {
    regs[0] = 0xa;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0xb = Extended topology on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0xb) {
    for(i=0; ; i++) {
      regs[0] = 0xb; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!regs[0] && !regs[1])
	break;
    }
  }

  /* 0xd = Extended state enumeration */
  if (highest_cpuid >= 0xd) {
    unsigned xcr0_l, xcr0_h, ia32xss_l, ia32xss_h;

    regs[0] = 0xd; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    xcr0_l = regs[0]; xcr0_h = regs[3];

    regs[0] = 0xd; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
    ia32xss_l = regs[2]; ia32xss_h = regs[3];

    for(i=2; i<32; i++) {
      if ((xcr0_l | ia32xss_l) & (1<<i)) {
	regs[0] = 0xd; regs[2] = i;
	dump_one_cpuid(output, regs, 0x5);
      }
    }
    for(i=0; i<32; i++) {
      if ((xcr0_h | ia32xss_h) & (1<<i)) {
	regs[0] = 0xd; regs[2] = i+32;
	dump_one_cpuid(output, regs, 0x5);
      }
    }
  }

  /* 0xf = Platform/L3 QoS enumeration on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0xf) {
    regs[0] = 0xf; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0xf; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x10 = Platform/L3 QoS enforcement enumeration on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x10) {
    regs[0] = 0x10; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
    regs[0] = 0x10; regs[2] = 1;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x14 = Processor trace enumeration on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x14) {
    regs[0] = 0x14; regs[2] = 0;
    dump_one_cpuid(output, regs, 0x5);
  }

  /* 0x15 = Timestamp counter/core crystal clock on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x15) {
    regs[0] = 0x15;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x16 = Processor frequency on Intel ; Reserved on AMD */
  if (highest_cpuid >= 0x16) {
    regs[0] = 0x16;
    dump_one_cpuid(output, regs, 0x1);
  }

  if (highest_cpuid > 0x16) {
    static int reported = 0;
    if (!reported)
      fprintf(stderr, "WARNING: Processor supports new CPUID leaves upto 0x%x\n", highest_cpuid);
    reported = 1;
  }

  /* 0x80000000 = Largest extended cpuid */
  regs[0] = 0x80000000;
  dump_one_cpuid(output, regs, 0x1);

  /* 0x80000001 = Extended processor signature and features */
  if (highest_ext_cpuid >= 0x80000001) {
    regs[0] = 0x80000001;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000002-4 = Processor name string */
  if (highest_ext_cpuid >= 0x80000002) {
    regs[0] = 0x80000002;
    dump_one_cpuid(output, regs, 0x1);
  }
  if (highest_ext_cpuid >= 0x80000003) {
    regs[0] = 0x80000003;
    dump_one_cpuid(output, regs, 0x1);
  }
  if (highest_ext_cpuid >= 0x80000004) {
    regs[0] = 0x80000004;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000005 = L1 and TLB on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x80000005) {
    regs[0] = 0x80000005;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000006 = L2, L3 and TLB on AMD ; L2 and reserved on Intel */
  if (highest_ext_cpuid >= 0x80000006) {
    regs[0] = 0x80000006;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000007 = Advanced power management on AMD ; Almost reserved on Intel */
  if (highest_ext_cpuid >= 0x80000007) {
    regs[0] = 0x80000007;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000008 = Long mode and topology on AMD ; Long mode on Intel */
  if (highest_ext_cpuid >= 0x80000008) {
    regs[0] = 0x80000008;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000000a = SVM on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000000a) {
    regs[0] = 0x8000000a;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x80000019 = TLB1G + Perf optim identifiers on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x80000019) {
    regs[0] = 0x80000019;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001b = IBS on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001b) {
    regs[0] = 0x8000001b;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001c = Profiling on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001c) {
    regs[0] = 0x8000001c;
    dump_one_cpuid(output, regs, 0x1);
  }

  /* 0x8000001d = Cache properties on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001d) {
    for(i=0; ; i++) {
      regs[0] = 0x8000001d; regs[2] = i;
      dump_one_cpuid(output, regs, 0x5);
      if (!(regs[0] & 0x1f))
	break;
    }
  }

  /* 0x8000001e = Topoext on AMD ; Reserved on Intel */
  if (highest_ext_cpuid >= 0x8000001e) {
    regs[0] = 0x8000001e;
    dump_one_cpuid(output, regs, 0x1);
  }

  if (highest_ext_cpuid > 0x8000001e) {
    static int reported = 0;
    if (!reported)
      fprintf(stderr, "WARNING: Processor supports new extended CPUID leaves upto 0x%x\n", highest_ext_cpuid);
    reported = 1;
  }

  if (path)
    fclose(output);
  return 0;
}