Index: sys/powerpc/pseries/platform_chrp.c =================================================================== --- sys/powerpc/pseries/platform_chrp.c +++ sys/powerpc/pseries/platform_chrp.c @@ -350,14 +350,27 @@ return (0); } +static int +u32_cmp(const void *ap, const void *bp) +{ + const uint32_t *a = ap, *b = bp; + if (*a < *b) + return (-1); + else if (*a > *b) + return (1); + else + return (0); +} + static int chrp_cpuref_init(void) { phandle_t cpu, dev; char buf[32]; - int a, res; + int a, res, res2; + uint32_t reg, addr_cells, size_cells; cell_t interrupt_servers[32]; - uint64_t bsp; + uint32_t cpuids[MAXCPU], ids; if (platform_cpuref_valid) return (0); @@ -371,27 +384,51 @@ dev = OF_peer(dev); } - bsp = 0; + res = OF_getproplen(dev, "#address-cells"); + res2 = OF_getproplen(dev, "#size-cells"); + if (res != res2 || res != sizeof(uint32_t)) + panic("CPU properties #address-cells and #size-cells not found on Open Firmware\n"); + OF_getencprop(dev, "#address-cells", &addr_cells, sizeof(addr_cells)); + OF_getencprop(dev, "#size-cells", &size_cells, sizeof(size_cells)); + if (addr_cells != 1 || size_cells != 0) + panic("Unexpected values for CPU properties #address-cells and #size-cells on Open Firmware\n"); + + ids = 0; for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) { res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); if (res > 0 && strcmp(buf, "cpu") == 0) { res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s"); if (res > 0) { - - OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", interrupt_servers, res); + res2 = OF_getproplen(cpu, "reg"); + if (res2 != sizeof(uint32_t)) + panic("Unexpected length for CPU property reg on Open Firmware\n"); + OF_getencprop(cpu, "reg", ®, res2); + if (reg >= MAXCPU || reg + res/sizeof(cell_t) > MAXCPU) + panic("Invalid CPU ID found on Open Firmware\n"); + for (a = 0; a < res/sizeof(cell_t); a++) { - platform_cpuref[platform_cpuref_cnt].cr_hwref = interrupt_servers[a]; - platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt; + platform_cpuref[reg + a].cr_hwref = interrupt_servers[a]; + platform_cpuref[reg + a].cr_cpuid = reg + a; platform_cpuref_cnt++; + cpuids[ids++] = reg + a; } } } } + qsort(cpuids, ids, sizeof(uint32_t), u32_cmp); + for (a = 0; a < ids; a++) { + reg = cpuids[a]; + platform_cpuref[a].cr_hwref = platform_cpuref[reg].cr_hwref; + platform_cpuref[a].cr_cpuid = platform_cpuref[reg].cr_cpuid; + } + bzero(&platform_cpuref[a], + sizeof(platform_cpuref) - sizeof(platform_cpuref[0]) * platform_cpuref_cnt); + platform_cpuref_valid = 1; return (0);