From owner-svn-src-head@freebsd.org Tue May 8 13:23:40 2018 Return-Path: Delivered-To: svn-src-head@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id DDAB7FB6003; Tue, 8 May 2018 13:23:39 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 8F7A46AB35; Tue, 8 May 2018 13:23:39 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 708C12ADB3; Tue, 8 May 2018 13:23:39 +0000 (UTC) (envelope-from jhibbits@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w48DNdGs020036; Tue, 8 May 2018 13:23:39 GMT (envelope-from jhibbits@FreeBSD.org) Received: (from jhibbits@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w48DNdhO020035; Tue, 8 May 2018 13:23:39 GMT (envelope-from jhibbits@FreeBSD.org) Message-Id: <201805081323.w48DNdhO020035@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: jhibbits set sender to jhibbits@FreeBSD.org using -f From: Justin Hibbits Date: Tue, 8 May 2018 13:23:39 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r333363 - head/sys/powerpc/pseries X-SVN-Group: head X-SVN-Commit-Author: jhibbits X-SVN-Commit-Paths: head/sys/powerpc/pseries X-SVN-Commit-Revision: 333363 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 08 May 2018 13:23:40 -0000 Author: jhibbits Date: Tue May 8 13:23:39 2018 New Revision: 333363 URL: https://svnweb.freebsd.org/changeset/base/333363 Log: Fix wrong cpu0 identification Summary: chrp_cpuref_init() was relying on the boot strap processor to be the first child of /cpus. That was not always the case, specially on pseries with FDT. This change uses the "reg" property of each CPU instead and also adds several sanity checks to avoid unexpected behavior (maybe too many panics?). The main observed symptom was interrupts being missed by the main processor, leading to timeouts and the kernel aborting the boot. Submitted by: Leandro Lupori Reviewed by: nwhitehorn Differential Revision: https://reviews.freebsd.org/D15174 Modified: head/sys/powerpc/pseries/platform_chrp.c Modified: head/sys/powerpc/pseries/platform_chrp.c ============================================================================== --- head/sys/powerpc/pseries/platform_chrp.c Tue May 8 11:39:01 2018 (r333362) +++ head/sys/powerpc/pseries/platform_chrp.c Tue May 8 13:23:39 2018 (r333363) @@ -350,14 +350,26 @@ chrp_smp_get_bsp(platform_t plat, struct cpuref *cpure return (0); } +static void +get_cpu_reg(phandle_t cpu, cell_t *reg) +{ + int res; + + res = OF_getproplen(cpu, "reg"); + if (res != sizeof(cell_t)) + panic("Unexpected length for CPU property reg on Open Firmware\n"); + OF_getencprop(cpu, "reg", reg, res); +} + static int chrp_cpuref_init(void) { - phandle_t cpu, dev; + phandle_t cpu, dev, chosen, pbsp; + ihandle_t ibsp; char buf[32]; - int a, res; - cell_t interrupt_servers[32]; - uint64_t bsp; + int a, bsp, res, res2, tmp_cpuref_cnt; + static struct cpuref tmp_cpuref[MAXCPU]; + cell_t interrupt_servers[32], addr_cells, size_cells, reg, bsp_reg; if (platform_cpuref_valid) return (0); @@ -371,25 +383,77 @@ chrp_cpuref_init(void) dev = OF_peer(dev); } - bsp = 0; + /* Make sure that cpus reg property have 1 address cell and 0 size cells */ + res = OF_getproplen(dev, "#address-cells"); + res2 = OF_getproplen(dev, "#size-cells"); + if (res != res2 || res != sizeof(cell_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"); + + /* Look for boot CPU in /chosen/cpu and /chosen/fdtbootcpu */ + + chosen = OF_finddevice("/chosen"); + if (chosen == -1) + panic("Device /chosen not found on Open Firmware\n"); + + bsp_reg = -1; + + /* /chosen/cpu */ + if (OF_getproplen(chosen, "cpu") == sizeof(ihandle_t)) { + OF_getprop(chosen, "cpu", &ibsp, sizeof(ibsp)); + pbsp = OF_instance_to_package(ibsp); + if (pbsp != -1) + get_cpu_reg(pbsp, &bsp_reg); + } + + /* /chosen/fdtbootcpu */ + if (bsp_reg == -1) { + if (OF_getproplen(chosen, "fdtbootcpu") == sizeof(cell_t)) + OF_getprop(chosen, "fdtbootcpu", &bsp_reg, sizeof(bsp_reg)); + } + + if (bsp_reg == -1) + panic("Boot CPU not found on Open Firmware\n"); + + bsp = -1; + tmp_cpuref_cnt = 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); - 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; + get_cpu_reg(cpu, ®); + if (reg == bsp_reg) + bsp = tmp_cpuref_cnt; - platform_cpuref_cnt++; + for (a = 0; a < res/sizeof(cell_t); a++) { + tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a]; + tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt; + tmp_cpuref_cnt++; } } } + } + + if (bsp == -1) + panic("Boot CPU not found\n"); + + /* Map IDs, so BSP has CPUID 0 regardless of hwref */ + for (a = bsp; a < tmp_cpuref_cnt; a++) { + platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref; + platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt; + platform_cpuref_cnt++; + } + for (a = 0; a < bsp; a++) { + platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref; + platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt; + platform_cpuref_cnt++; } platform_cpuref_valid = 1;