From owner-svn-src-projects@FreeBSD.ORG Tue May 24 14:12:32 2011 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 357421065676; Tue, 24 May 2011 14:12:32 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 1C5978FC15; Tue, 24 May 2011 14:12:32 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id p4OECWeN071665; Tue, 24 May 2011 14:12:32 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id p4OECVHf071663; Tue, 24 May 2011 14:12:31 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201105241412.p4OECVHf071663@svn.freebsd.org> From: Nathan Whitehorn Date: Tue, 24 May 2011 14:12:31 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r222256 - projects/pseries/powerpc/pseries X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 24 May 2011 14:12:32 -0000 Author: nwhitehorn Date: Tue May 24 14:12:31 2011 New Revision: 222256 URL: http://svn.freebsd.org/changeset/base/222256 Log: Add SMP support on CHRP/PAPR system, including support for multi-threaded CPUs. Modified: projects/pseries/powerpc/pseries/platform_chrp.c Modified: projects/pseries/powerpc/pseries/platform_chrp.c ============================================================================== --- projects/pseries/powerpc/pseries/platform_chrp.c Tue May 24 14:10:33 2011 (r222255) +++ projects/pseries/powerpc/pseries/platform_chrp.c Tue May 24 14:12:31 2011 (r222256) @@ -43,8 +43,10 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include +#include #include #include @@ -150,33 +152,12 @@ chrp_timebase_freq(platform_t plat, stru return (ticks); } - -static int -chrp_smp_fill_cpuref(struct cpuref *cpuref, phandle_t cpu) -{ - cell_t cpuid, res; - - cpuref->cr_hwref = cpu; - res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); - - /* - * psim doesn't have a reg property, so assume 0 as for the - * uniprocessor case in the CHRP spec. - */ - if (res < 0) { - cpuid = 0; - } - - cpuref->cr_cpuid = cpuid & 0xff; - return (0); -} - static int chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref) { char buf[8]; phandle_t cpu, dev, root; - int res; + int res, cpuid; root = OF_peer(0); @@ -208,7 +189,16 @@ chrp_smp_first_cpu(platform_t plat, stru if (cpu == 0) return (ENOENT); - return (chrp_smp_fill_cpuref(cpuref, cpu)); + cpuref->cr_hwref = cpu; + res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + sizeof(cpuid)); + if (res <= 0) + res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + if (res <= 0) + cpuid = 0; + cpuref->cr_cpuid = cpuid; + + return (0); } static int @@ -216,8 +206,23 @@ chrp_smp_next_cpu(platform_t plat, struc { char buf[8]; phandle_t cpu; - int res; + int i, res, cpuid; + + /* Check for whether it should be the next thread */ + res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s"); + if (res > 0) { + cell_t interrupt_servers[res/sizeof(cell_t)]; + OF_getprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s", + interrupt_servers, res); + for (i = 0; i < res/sizeof(cell_t) - 1; i++) { + if (interrupt_servers[i] == cpuref->cr_cpuid) { + cpuref->cr_cpuid = interrupt_servers[i+1]; + return (0); + } + } + } + /* Next CPU core/package */ cpu = OF_peer(cpuref->cr_hwref); while (cpu != 0) { res = OF_getprop(cpu, "device_type", buf, sizeof(buf)); @@ -228,7 +233,16 @@ chrp_smp_next_cpu(platform_t plat, struc if (cpu == 0) return (ENOENT); - return (chrp_smp_fill_cpuref(cpuref, cpu)); + cpuref->cr_hwref = cpu; + res = OF_getprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid, + sizeof(cpuid)); + if (res <= 0) + res = OF_getprop(cpu, "reg", &cpuid, sizeof(cpuid)); + if (res <= 0) + cpuid = 0; + cpuref->cr_cpuid = cpuid; + + return (0); } static int @@ -236,7 +250,7 @@ chrp_smp_get_bsp(platform_t plat, struct { ihandle_t inst; phandle_t bsp, chosen; - int res; + int res, cpuid; chosen = OF_finddevice("/chosen"); if (chosen == 0) @@ -247,14 +261,55 @@ chrp_smp_get_bsp(platform_t plat, struct return (ENXIO); bsp = OF_instance_to_package(inst); - return (chrp_smp_fill_cpuref(cpuref, bsp)); + + /* Pick the primary thread. Can it be any other? */ + cpuref->cr_hwref = bsp; + res = OF_getprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid, + sizeof(cpuid)); + if (res <= 0) + res = OF_getprop(bsp, "reg", &cpuid, sizeof(cpuid)); + if (res <= 0) + cpuid = 0; + cpuref->cr_cpuid = cpuid; + + return (0); } static int chrp_smp_start_cpu(platform_t plat, struct pcpu *pc) { - /* XXX: Uses RTAS call, will add later */ - return (ENXIO); + cell_t start_cpu; + int result, err, timeout; + + if (!rtas_exists()) { + printf("RTAS unitialized: unable to start AP %d\n", + pc->pc_cpuid); + return (ENXIO); + } + + start_cpu = rtas_token_lookup("start-cpu"); + if (start_cpu == -1) { + printf("RTAS unknown method: unable to start AP %d\n", + pc->pc_cpuid); + return (ENXIO); + } + + ap_pcpu = pc; + powerpc_sync(); + + result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc, + &err); + if (result < 0 || err != 0) { + printf("RTAS error (%d/%d): unable to start AP %d\n", + result, err, pc->pc_cpuid); + return (ENXIO); + } + + timeout = 10000; + while (!pc->pc_awake && timeout--) + DELAY(100); + + return ((pc->pc_awake) ? 0 : EBUSY); } static void