From patchwork Wed Jan 29 12:32:47 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 13953720 Received: from mail-ed1-f53.google.com (mail-ed1-f53.google.com [209.85.208.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B27010E5; Wed, 29 Jan 2025 12:32:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.208.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153980; cv=none; b=ULv6LxvUNR/t5gvS+3Vd4FyQIW6EFKb3/gCD5sFUQ8u1Sm0ke87JZGOxnTLcSk+a0vqwLhZNCt2ADElCziiZKXpdEIrCGtruhgWV8x68Tt8O063Wv4oGLeQQrrWFUu3Ny0z87kD3ohXfabsgd06EDNDbjuoY6W0qEmtQXPsk9Dk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153980; c=relaxed/simple; bh=4JnwAaxzzTAViWg7ct3Xj13ZKq9MDJz4VfUrOXaNL+Q=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version:Content-Type; b=ggVRLt1HuDjCTZIg4pGPDf1mpyt28GT6omIh+AeOSU59WTIeCNKCag96oFPpzgdjHhCHOPCP3tcmFuHHiOp5so6+vJ3qq5ZvuDZ+XV3AF+r2yyLYrrjXhoUsp8QeqhGNwf2eIJL6J9Lyc+tr+aweFaDq/ln6lyLafBoN2UtC5h0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=XamO8eYG; arc=none smtp.client-ip=209.85.208.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="XamO8eYG" Received: by mail-ed1-f53.google.com with SMTP id 4fb4d7f45d1cf-5da12292b67so11028678a12.3; Wed, 29 Jan 2025 04:32:57 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738153976; x=1738758776; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=TRZGYpywOr8SfCIjJp+/4G1Vc/5w1pIrXams/TeKR5k=; b=XamO8eYGm9QZ74mQ3Z36TYI9k5XrHLSi0PuG408XDatxncJ2symQZ1SWaU4H00T598 uiOx9gxmn2jhz5soMoDsdFHl6chpY4rzTjeFlVcLNGkr9jy2F97qntoNhQagJ+aIutZ3 wEwuHpZNQOJwdjKh3PxSpCOg6KQIZVAGzQ786EOAMcKcdXNV7lQb3Mii+8/68fGiDnpM S5sSAxPL68A6OnpxMGEit5/qawyFcsOM88As9VcXFDTjZYSEIF7wfdgoyIqdXanKEwea tEy55Dqn9COBxqcsdx9bOMpNLjY7MZdRjPujY6v6CHzj8qK6dePk/sM3RYjyqpEEfzWs TWTw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738153976; x=1738758776; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=TRZGYpywOr8SfCIjJp+/4G1Vc/5w1pIrXams/TeKR5k=; b=huiYq9mOIukkD5kII027GTfdLFSjkgSrPNaSWPr3FJnxaQDu+EVuDWDWv+QUtUG1Vr g/USPDeD8ITLW9Tpuj8sviyHA9PJU0HpTtUMQcR165vABzSyJ7ObBtPZ77jTAm3mRFFu AUyn6pMi3LmeKZqme6apKvvFg721symsLh6HFDoNjZUkYIqnM5UpXU4pjOpzn2MhdM4D +LcM1frUdlKCo6sJkbkic+CSvGQ6Smh0oTYGLCPFnFkJaLayblvRJBNS5DW/pWM0C2dT KG+nxHE4ulEhvUUqOX0YbZybn1snqUqZuNhJLoRyfeekUh0qib3O7maBVx5stN0NXOvq pRkQ== X-Gm-Message-State: AOJu0YyMGKMVdD593ivsHYkOjNdRU7X6/3miVkzU3ESt344vPsYK3+dn RuNA1/yJb+uwwORMwxdyZPb3GAmnWX5Rd2hklr7G6PX50WYxxpFWXXIxQdnV X-Gm-Gg: ASbGncvjUhWiUXDXckEZ3WEvkwvAx6M1km8npCw81hpWfs0nkyyeFEQ3zMVU4IQ2SaL Qz7wTy62PMLGv8MfIiHSUwa1D4vE/vTO3pSB3pnFCazGF9VmJKHqt5kiNyTU59yZ4WD2xxy1ads 0nnwQC1X/gGt6YrWcALPub1gLQs9w9NErwNBHahwPiMYWvU2+otzW3/lEAaVwJHqVhqz0UR6HOA P53TimaOGbkyfBVPOtLuZD+B1EdrW3FgI1IBFP7YD1NlaoMsKSM4WeqNaD8+1eUUrri81FS6Wqv kJsmchzjwcx4DiTCAUFJRpduGbAUP/BW80w= X-Google-Smtp-Source: AGHT+IE8Yh0fG806JI6Zpc4BUmUAg3gg85Hoi6TEqEqSyQJfl+B7oSeEefZYxLBUc05P539M6cXKrg== X-Received: by 2002:a05:6402:42c8:b0:5d0:d3eb:a78f with SMTP id 4fb4d7f45d1cf-5dc5e6ce1cdmr7568674a12.0.1738153974583; Wed, 29 Jan 2025 04:32:54 -0800 (PST) Received: from localhost.localdomain ([79.175.114.8]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ab69051b1ddsm733540766b.180.2025.01.29.04.32.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 04:32:54 -0800 (PST) From: Aleksandar Rikalo To: linux-mips@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Gregory CLEMENT , Serge Semin , Jiaxun Yang , Paul Burton , Aleksandar Rikalo , Chao-ying Fu , Djordje Todorovic Subject: [PATCH v9 1/4] clocksource: mips-gic-timer: Enable counter when CPUs start Date: Wed, 29 Jan 2025 13:32:47 +0100 Message-Id: <20250129123250.711910-2-arikalo@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250129123250.711910-1-arikalo@gmail.com> References: <20250129123250.711910-1-arikalo@gmail.com> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Paul Burton In multi-cluster MIPS I6500 systems there is a GIC in each cluster, each with its own counter. When a cluster powers up the counter will be stopped, with the COUNTSTOP bit set in the GIC_CONFIG register. In single cluster systems, it has been fine to clear COUNTSTOP once in gic_clocksource_of_init() to start the counter. In multi-cluster systems, this will only have started the counter in the boot cluster, and any CPUs in other clusters will find their counter stopped which will break the GIC clock_event_device. Resolve this by having CPUs clear the COUNTSTOP bit when they come online, using the existing gic_starting_cpu() CPU hotplug callback. This will allow CPUs in secondary clusters to ensure that the cluster's GIC counter is running as expected. Signed-off-by: Paul Burton Signed-off-by: Chao-ying Fu Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Reviewed-by: Philippe Mathieu-Daudé Tested-by: Serge Semin Tested-by: Gregory CLEMENT Acked-by: Daniel Lezcano --- drivers/clocksource/mips-gic-timer.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/clocksource/mips-gic-timer.c b/drivers/clocksource/mips-gic-timer.c index 7907b740497a..abb685a080a5 100644 --- a/drivers/clocksource/mips-gic-timer.c +++ b/drivers/clocksource/mips-gic-timer.c @@ -115,6 +115,9 @@ static void gic_update_frequency(void *data) static int gic_starting_cpu(unsigned int cpu) { + /* Ensure the GIC counter is running */ + clear_gic_config(GIC_CONFIG_COUNTSTOP); + gic_clockevent_cpu_init(cpu, this_cpu_ptr(&gic_clockevent_device)); return 0; } @@ -288,9 +291,6 @@ static int __init gic_clocksource_of_init(struct device_node *node) pr_warn("Unable to register clock notifier\n"); } - /* And finally start the counter */ - clear_gic_config(GIC_CONFIG_COUNTSTOP); - /* * It's safe to use the MIPS GIC timer as a sched clock source only if * its ticks are stable, which is true on either the platforms with From patchwork Wed Jan 29 12:32:48 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 13953721 Received: from mail-ej1-f48.google.com (mail-ej1-f48.google.com [209.85.218.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 820D110F9; Wed, 29 Jan 2025 12:32:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153980; cv=none; b=maQ/sQ3ffp2KXnzL2WrY/pPCtZcEljoQ1hVnzIB0PyCb3dfztWdTVpvD90SBgV2V3B+Vs8XdsWZeTygAEqZq+nJmgBc55eqcKbJcZmR2VKKb6xAaO8NxtOQcRjcMLrQ9NmYj5/VojhV0d9qN5UTjFs1a3VGwyvzINFSIrR297gk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153980; c=relaxed/simple; bh=juegPF0QAfCy/64jfsXI53FQb/EgNPwFWBJGG+Zvlro=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=KBRE7DOLcJQlw67kY1pWSCm2i5Q0VXYtAT12THH6yaWgRUu8jlNyMObptWNcMPJcVDiov3KrsIuzYSbHFdQVwrDBWcXWXvzFk3SIFMbgFQBJARYpthOvctNleYsocb7BeLrlX0wuMrJMkZgEP78+Jd2KBvRkkHICoH4/8/l8vgw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hZEQc7PM; arc=none smtp.client-ip=209.85.218.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hZEQc7PM" Received: by mail-ej1-f48.google.com with SMTP id a640c23a62f3a-aab6fa3e20eso1141264966b.2; Wed, 29 Jan 2025 04:32:58 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738153976; x=1738758776; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qxVQmw22U/pUgtkzMWu3ru0gpeZOa1eNAUYZCGmjfkg=; b=hZEQc7PMGnJchTvW+VkroSoOX8orXBbLq5kAKvVKbkC4GkZiJ1jnJ8p1FkxFd6ZprH WryY0YqwXiJ5VkPcz00SbH0kuQ6nfaC3YFHkxbZ/VUiW4vPSu+Y5ImFNoE3UQ3ngi7OS 7cGhIZKSh3fYgnJ4L1AHEQ8B6oeTbhqCl8l3xnmA8iiLSjB3BmpsR95SMN4qOWPalVGx U0gKw1l9HzWdQdOlH3x1rZou9V0LVnOhrvXCro5U3PY8wQ5mwBAj+gNWLLUKUkphfxT9 +UlK6l8gmykt/j24kVrjTQgi5fsdXS+YQTYD3WMO3BonTPNFaBtTbkRK29MoAQbM475w bLtw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738153976; x=1738758776; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=qxVQmw22U/pUgtkzMWu3ru0gpeZOa1eNAUYZCGmjfkg=; b=wUAx2CvLl+kfgwljTpcQ75mLcHHK6gxEkpJR5CCdLfRZFRz9uughvaJ+AMEjA6PXjX s8uyH8y81xYWW2S80IYlkYXsbjHWr5qfGm31jeFmIfK0ITzUDHUszv2iKO9yNP2LJEMp ZvD3dtOLoigl3Uk2XD6pPA6Bbk0/wOpjuhh20c0ACxnYlsT25yPbyHSFwOf/kMLDTQkT 3dUZDPJ9Z0pntJyvj2p+dbTrYQvhfLjN9tmlLRaDgFEG36l8zGTF51EYU6QMhxyhzXJc rUDBoNR5fg+nt1uD7s2qY4HIQC1P9u5Zv0WGbOb3I7ruNgC2tZoYw2l/6x+LoysAd+Is imPA== X-Gm-Message-State: AOJu0YxjyksVOjrRRdQ7IfL59iJz5V1UYIYgU9WYGqyoCUntFRGQOmQN +gifhtnPHLTPic/YEFzcmq8DkXpe7VT2aGCbXQWbh5yX43PbiozNq+qKhbak X-Gm-Gg: ASbGnct64zmzCAgxH6b6OjY9aQWnmcJGdYNc4x0DtU4M4GstyT8MaEVfPWBhYNaK8C8 e5ksMOfETOV/7LERVQ+zKHSvLx01Kl8kWcFhqcSCp8NOgWT6H35Jfiu9768Tz4MThKew8z6QAKP +hn2T7HvJe8lgBMTZQk2hvhH/A7tSvJGxYNFuaQwJb00OLVHppUahl9XhdcAaOy/QB4md2ehiGB /gVGcUBxtSOAFpCkMN/5RJAR0EyQNIoiFbXak7t74EdUlHCe+3SLZhCWujk2l/8QQ3sOmPuw8bR 22au/5Q3iiVEbTPtwLN8gwosWR4sFo4dCPQ= X-Google-Smtp-Source: AGHT+IGlkcvzoCqeKuyPGWCfZinwGBT6ijEJr0VYZNs9MFCxAJom7Swwj+GI4SALGMZv8l3X4qFjwQ== X-Received: by 2002:a17:907:2d08:b0:ab6:99b2:ad0c with SMTP id a640c23a62f3a-ab6cfe1753dmr283588066b.50.1738153975929; Wed, 29 Jan 2025 04:32:55 -0800 (PST) Received: from localhost.localdomain ([79.175.114.8]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ab69051b1ddsm733540766b.180.2025.01.29.04.32.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 04:32:55 -0800 (PST) From: Aleksandar Rikalo To: linux-mips@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Gregory CLEMENT , Serge Semin , Jiaxun Yang , Paul Burton , Aleksandar Rikalo , Chao-ying Fu , Djordje Todorovic Subject: [PATCH v9 2/4] MIPS: pm-cps: Use per-CPU variables as per-CPU, not per-core Date: Wed, 29 Jan 2025 13:32:48 +0100 Message-Id: <20250129123250.711910-3-arikalo@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250129123250.711910-1-arikalo@gmail.com> References: <20250129123250.711910-1-arikalo@gmail.com> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Paul Burton The pm-cps code has up until now used per-CPU variables indexed by core, rather than CPU number, in order to share data amongst sibling CPUs (ie. VPs/threads in a core). This works fine for single cluster systems, but with multi-cluster systems a core number is no longer unique in the system, leading to sharing between CPUs that are not actually siblings. Avoid this issue by using per-CPU variables as they are more generally used - ie. access them using CPU numbers rather than core numbers. Sharing between siblings is then accomplished by: - Assigning the same pointer to entries for each sibling CPU for the nc_asm_enter & ready_count variables, which allow this by virtue of being per-CPU pointers. - Indexing by the first CPU set in a CPUs cpu_sibling_map in the case of pm_barrier, for which we can't use the previous approach because the per-CPU variable is not a pointer. Signed-off-by: Paul Burton Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Tested-by: Serge Semin Tested-by: Gregory CLEMENT --- arch/mips/kernel/pm-cps.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index d09ca77e624d..9369a8dc385e 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -57,10 +57,7 @@ static DEFINE_PER_CPU_ALIGNED(u32*, ready_count); /* Indicates online CPUs coupled with the current CPU */ static DEFINE_PER_CPU_ALIGNED(cpumask_t, online_coupled); -/* - * Used to synchronize entry to deep idle states. Actually per-core rather - * than per-CPU. - */ +/* Used to synchronize entry to deep idle states */ static DEFINE_PER_CPU_ALIGNED(atomic_t, pm_barrier); /* Saved CPU state across the CPS_PM_POWER_GATED state */ @@ -112,9 +109,10 @@ int cps_pm_enter_state(enum cps_pm_state state) cps_nc_entry_fn entry; struct core_boot_config *core_cfg; struct vpe_boot_config *vpe_cfg; + atomic_t *barrier; /* Check that there is an entry function for this state */ - entry = per_cpu(nc_asm_enter, core)[state]; + entry = per_cpu(nc_asm_enter, cpu)[state]; if (!entry) return -EINVAL; @@ -150,7 +148,7 @@ int cps_pm_enter_state(enum cps_pm_state state) smp_mb__after_atomic(); /* Create a non-coherent mapping of the core ready_count */ - core_ready_count = per_cpu(ready_count, core); + core_ready_count = per_cpu(ready_count, cpu); nc_addr = kmap_noncoherent(virt_to_page(core_ready_count), (unsigned long)core_ready_count); nc_addr += ((unsigned long)core_ready_count & ~PAGE_MASK); @@ -158,7 +156,8 @@ int cps_pm_enter_state(enum cps_pm_state state) /* Ensure ready_count is zero-initialised before the assembly runs */ WRITE_ONCE(*nc_core_ready_count, 0); - coupled_barrier(&per_cpu(pm_barrier, core), online); + barrier = &per_cpu(pm_barrier, cpumask_first(&cpu_sibling_map[cpu])); + coupled_barrier(barrier, online); /* Run the generated entry code */ left = entry(online, nc_core_ready_count); @@ -629,12 +628,14 @@ static void *cps_gen_entry_code(unsigned cpu, enum cps_pm_state state) static int cps_pm_online_cpu(unsigned int cpu) { - enum cps_pm_state state; - unsigned core = cpu_core(&cpu_data[cpu]); + unsigned int sibling, core; void *entry_fn, *core_rc; + enum cps_pm_state state; + + core = cpu_core(&cpu_data[cpu]); for (state = CPS_PM_NC_WAIT; state < CPS_PM_STATE_COUNT; state++) { - if (per_cpu(nc_asm_enter, core)[state]) + if (per_cpu(nc_asm_enter, cpu)[state]) continue; if (!test_bit(state, state_support)) continue; @@ -646,16 +647,19 @@ static int cps_pm_online_cpu(unsigned int cpu) clear_bit(state, state_support); } - per_cpu(nc_asm_enter, core)[state] = entry_fn; + for_each_cpu(sibling, &cpu_sibling_map[cpu]) + per_cpu(nc_asm_enter, sibling)[state] = entry_fn; } - if (!per_cpu(ready_count, core)) { + if (!per_cpu(ready_count, cpu)) { core_rc = kmalloc(sizeof(u32), GFP_KERNEL); if (!core_rc) { pr_err("Failed allocate core %u ready_count\n", core); return -ENOMEM; } - per_cpu(ready_count, core) = core_rc; + + for_each_cpu(sibling, &cpu_sibling_map[cpu]) + per_cpu(ready_count, sibling) = core_rc; } return 0; From patchwork Wed Jan 29 12:32:49 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 13953722 Received: from mail-ej1-f43.google.com (mail-ej1-f43.google.com [209.85.218.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 765F823AD; Wed, 29 Jan 2025 12:32:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153981; cv=none; b=VqK6M+HIqzyMUv59B7e50LTiHyh02Ubz/gYa6bgPsmwZnaWycEbUqgM8ka+A8fTN9nqn1p0UA2KujKqZ9CW0XC6b4HFcyuT2eBLL3DyF0aQmYf47rHmEvH13uVkvsyimYtaxFLsvyXxioNTViuscmX0i7YbXTIWFB2r784n8Dzo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153981; c=relaxed/simple; bh=3cjx2TjxatDPLqJe/6zEWQTSw1AQs8ksSwrAIojLhxY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=fSUMtZpETCMGfMPu5ifRg4mJuow3hAHD8WVB5SSPrPT7MFnJul6RWqzlddFrP8eNGOGd6ZtSy6tSYCl5jXORa/gBnvE+KStpUXgORrfVWYjJ5xDI7/2lOuQU3tJbscnUGyPuJ8fzttb3klIXRGKFSJoHHWi//9B0Mf5F8XqxY3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=W5MDXvRA; arc=none smtp.client-ip=209.85.218.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="W5MDXvRA" Received: by mail-ej1-f43.google.com with SMTP id a640c23a62f3a-aa6a92f863cso1356958966b.1; Wed, 29 Jan 2025 04:32:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738153977; x=1738758777; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Nqic8N3aCmviXH9sGcbk48Wn5BVUu3oDSMpElIGJuME=; b=W5MDXvRAr4n7IxtmTZqXPshJuWkPOC3EA0wvChJ06rGSVl8+4ET6SXv8fyyxovFCon FMY57mGp42xH2/HTv51F59feV/wiSM4w2e4car5bFTU1nSYn1I1xQsPT1xkOCKKacKxx bnOdtlkbqmvs85/lDpzdFTTch9NOqGNKoX8RqRTuKxK78MF0o2ZGu92jom6aAYCpIwUE QKd+WkO9xGawkKDdqdNcdC1AGG/0qp+RTaCHIWTO228otd7y/hA8ghFPxJNpMA2+ulWy VxVKsl6VyNiS54YGbEGqS3zop6m884gjuMyvlNzKgsiveaUVsoe1j8U59NxKQWb6wa7H oUhA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738153977; x=1738758777; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Nqic8N3aCmviXH9sGcbk48Wn5BVUu3oDSMpElIGJuME=; b=eHmDUvJSLNJI5KPJleisFDD7SflLM4UkUA8Eqe1wFVlNo0bzl8qEnFi6zPqVb5WC8m FMHN+/FlcxToZWdvAb0qOxOcnjYCCmlNVX+LwxvJY33PDvUnmVloTphr1ZIVGEWydm61 iyt8CgTtBbZ1J75qZGfzv/vBAcpEBnP+nORoiGW3Z/8ocnbCt1nSv1X2vsrhOyqaSRYd HpC584uNBg3RB6G64CurY3rtVWcr6PQlyiDd5LCQh59MVIsr3sk6RgsbH/qUjQVUtac5 Rvz1Cr/ueCFMqlBM4aEnDmaPxZ62Pu7LWWIrvq5tN+CrvZwW9xGBLzFEtYKQumoa9tA6 8lXQ== X-Gm-Message-State: AOJu0YzsnFAH5GW+DSet/QpdQxFuagv60x6RoVKoRAfFbUDPyBnykf// EjYA+BhmeaehirWePLRYWAEOQmFcXxNVePIF3atTeY9ezNIw32ii6k22lDB5 X-Gm-Gg: ASbGnctxgLF6L0Oxo1jPasZUve5gqXTcolVJL+tJolgW+pDxmNgrznYaOJaznPifiWu kVDch6vJcxXGL/tfDZixiX/ILWGDxWFkC3uv8s82YYGCjrLC0q/9ruqUcXnLAaClAje6mZ8w4Ta MS11+SnsbVtXOGUz5Z+jCDvdyzew2dV6As0PtSZ9LTAvpP8GQ9+gvjgxbnzNloiSs/8VRsNpIcs ivM7n4YQaXE5TyEW6wZNw3FQmnyd+ZkCR1SYv/WXSUJFlrbz8NUx/iUv5a9YW/XexNsIUG7CIGE 2aNd1X1A08Jbn8Gs/HmQzQXr X-Google-Smtp-Source: AGHT+IFYC6HW2cW22fKXnZlUC6K8G02XvzM9QfiLtu+NzFcwfMK/TaosRDJNZar5hojZqF80RGKbBA== X-Received: by 2002:a17:907:1c27:b0:aa6:873b:ed8a with SMTP id a640c23a62f3a-ab6cfdc6719mr258649466b.47.1738153977252; Wed, 29 Jan 2025 04:32:57 -0800 (PST) Received: from localhost.localdomain ([79.175.114.8]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ab69051b1ddsm733540766b.180.2025.01.29.04.32.56 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 04:32:56 -0800 (PST) From: Aleksandar Rikalo To: linux-mips@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Gregory CLEMENT , Serge Semin , Jiaxun Yang , Paul Burton , Aleksandar Rikalo , Chao-ying Fu , Djordje Todorovic Subject: [PATCH v9 3/4] MIPS: CPS: Introduce struct cluster_boot_config Date: Wed, 29 Jan 2025 13:32:49 +0100 Message-Id: <20250129123250.711910-4-arikalo@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250129123250.711910-1-arikalo@gmail.com> References: <20250129123250.711910-1-arikalo@gmail.com> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Paul Burton In preparation for supporting multi-cluster systems, introduce a struct cluster_boot_config as an extra layer in the boot configuration maintained by the MIPS Coherent Processing System (CPS) SMP implementation. For now only one struct cluster_boot_config will be allocated & we'll simply defererence its core_config field to find the struct core_boot_config array which can be used to boot as usual. Signed-off-by: Paul Burton Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Tested-by: Serge Semin Tested-by: Gregory CLEMENT --- arch/mips/include/asm/smp-cps.h | 6 ++- arch/mips/kernel/asm-offsets.c | 3 ++ arch/mips/kernel/cps-vec.S | 19 ++++++-- arch/mips/kernel/pm-cps.c | 5 +- arch/mips/kernel/smp-cps.c | 82 +++++++++++++++++++++------------ 5 files changed, 81 insertions(+), 34 deletions(-) diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index ab94e50f62b8..a629e948a6fd 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -22,7 +22,11 @@ struct core_boot_config { struct vpe_boot_config *vpe_config; }; -extern struct core_boot_config *mips_cps_core_bootcfg; +struct cluster_boot_config { + struct core_boot_config *core_config; +}; + +extern struct cluster_boot_config *mips_cps_cluster_bootcfg; extern void mips_cps_core_boot(int cca, void __iomem *gcr_base); extern void mips_cps_core_init(void); diff --git a/arch/mips/kernel/asm-offsets.c b/arch/mips/kernel/asm-offsets.c index cb1045ebab06..b29944160b28 100644 --- a/arch/mips/kernel/asm-offsets.c +++ b/arch/mips/kernel/asm-offsets.c @@ -404,6 +404,9 @@ void output_cps_defines(void) { COMMENT(" MIPS CPS offsets. "); + OFFSET(CLUSTERBOOTCFG_CORECONFIG, cluster_boot_config, core_config); + DEFINE(CLUSTERBOOTCFG_SIZE, sizeof(struct cluster_boot_config)); + OFFSET(COREBOOTCFG_VPEMASK, core_boot_config, vpe_mask); OFFSET(COREBOOTCFG_VPECONFIG, core_boot_config, vpe_config); DEFINE(COREBOOTCFG_SIZE, sizeof(struct core_boot_config)); diff --git a/arch/mips/kernel/cps-vec.S b/arch/mips/kernel/cps-vec.S index f876309130ad..2ae7034a3d5c 100644 --- a/arch/mips/kernel/cps-vec.S +++ b/arch/mips/kernel/cps-vec.S @@ -19,6 +19,10 @@ #define GCR_CPC_BASE_OFS 0x0088 #define GCR_CL_COHERENCE_OFS 0x2008 #define GCR_CL_ID_OFS 0x2028 +#define CM3_GCR_Cx_ID_CLUSTER_SHF 8 +#define CM3_GCR_Cx_ID_CLUSTER_MSK (0xff << 8) +#define CM3_GCR_Cx_ID_CORENUM_SHF 0 +#define CM3_GCR_Cx_ID_CORENUM_MSK (0xff << 0) #define CPC_CL_VC_STOP_OFS 0x2020 #define CPC_CL_VC_RUN_OFS 0x2028 @@ -271,12 +275,21 @@ LEAF(mips_cps_core_init) */ LEAF(mips_cps_get_bootcfg) /* Calculate a pointer to this cores struct core_boot_config */ + PTR_LA v0, mips_cps_cluster_bootcfg + PTR_L v0, 0(v0) lw t0, GCR_CL_ID_OFS(s1) +#ifdef CONFIG_CPU_MIPSR6 + ext t1, t0, CM3_GCR_Cx_ID_CLUSTER_SHF, 8 + li t2, CLUSTERBOOTCFG_SIZE + mul t1, t1, t2 + PTR_ADDU \ + v0, v0, t1 +#endif + PTR_L v0, CLUSTERBOOTCFG_CORECONFIG(v0) + andi t0, t0, CM3_GCR_Cx_ID_CORENUM_MSK li t1, COREBOOTCFG_SIZE mul t0, t0, t1 - PTR_LA t1, mips_cps_core_bootcfg - PTR_L t1, 0(t1) - PTR_ADDU v0, t0, t1 + PTR_ADDU v0, v0, t0 /* Calculate this VPEs ID. If the core doesn't support MT use 0 */ li t9, 0 diff --git a/arch/mips/kernel/pm-cps.c b/arch/mips/kernel/pm-cps.c index 9369a8dc385e..3de0e05e0511 100644 --- a/arch/mips/kernel/pm-cps.c +++ b/arch/mips/kernel/pm-cps.c @@ -101,12 +101,14 @@ static void coupled_barrier(atomic_t *a, unsigned online) int cps_pm_enter_state(enum cps_pm_state state) { unsigned cpu = smp_processor_id(); + unsigned int cluster = cpu_cluster(¤t_cpu_data); unsigned core = cpu_core(¤t_cpu_data); unsigned online, left; cpumask_t *coupled_mask = this_cpu_ptr(&online_coupled); u32 *core_ready_count, *nc_core_ready_count; void *nc_addr; cps_nc_entry_fn entry; + struct cluster_boot_config *cluster_cfg; struct core_boot_config *core_cfg; struct vpe_boot_config *vpe_cfg; atomic_t *barrier; @@ -136,7 +138,8 @@ int cps_pm_enter_state(enum cps_pm_state state) if (!mips_cps_smp_in_use()) return -EINVAL; - core_cfg = &mips_cps_core_bootcfg[core]; + cluster_cfg = &mips_cps_cluster_bootcfg[cluster]; + core_cfg = &cluster_cfg->core_config[core]; vpe_cfg = &core_cfg->vpe_config[cpu_vpe_id(¤t_cpu_data)]; vpe_cfg->pc = (unsigned long)mips_cps_pm_restore; vpe_cfg->gp = (unsigned long)current_thread_info(); diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 82c8f9b9573c..3d8cf3098656 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -40,7 +40,7 @@ static DECLARE_BITMAP(core_power, NR_CPUS); static u64 core_entry_reg; static phys_addr_t cps_vec_pa; -struct core_boot_config *mips_cps_core_bootcfg; +struct cluster_boot_config *mips_cps_cluster_bootcfg; static unsigned __init core_vpe_count(unsigned int cluster, unsigned core) { @@ -238,8 +238,10 @@ static void __init cps_smp_setup(void) static void __init cps_prepare_cpus(unsigned int max_cpus) { - unsigned ncores, core_vpes, c, cca; + unsigned int nclusters, ncores, core_vpes, c, cl, cca; bool cca_unsuitable, cores_limited; + struct cluster_boot_config *cluster_bootcfg; + struct core_boot_config *core_bootcfg; mips_mt_set_cpuoptions(); @@ -281,40 +283,54 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) setup_cps_vecs(); - /* Allocate core boot configuration structs */ - ncores = mips_cps_numcores(0); - mips_cps_core_bootcfg = kcalloc(ncores, sizeof(*mips_cps_core_bootcfg), - GFP_KERNEL); - if (!mips_cps_core_bootcfg) { - pr_err("Failed to allocate boot config for %u cores\n", ncores); - goto err_out; - } + /* Allocate cluster boot configuration structs */ + nclusters = mips_cps_numclusters(); + mips_cps_cluster_bootcfg = kcalloc(nclusters, + sizeof(*mips_cps_cluster_bootcfg), + GFP_KERNEL); - /* Allocate VPE boot configuration structs */ - for (c = 0; c < ncores; c++) { - core_vpes = core_vpe_count(0, c); - mips_cps_core_bootcfg[c].vpe_config = kcalloc(core_vpes, - sizeof(*mips_cps_core_bootcfg[c].vpe_config), - GFP_KERNEL); - if (!mips_cps_core_bootcfg[c].vpe_config) { - pr_err("Failed to allocate %u VPE boot configs\n", - core_vpes); + for (cl = 0; cl < nclusters; cl++) { + /* Allocate core boot configuration structs */ + ncores = mips_cps_numcores(cl); + core_bootcfg = kcalloc(ncores, sizeof(*core_bootcfg), + GFP_KERNEL); + if (!core_bootcfg) goto err_out; + mips_cps_cluster_bootcfg[cl].core_config = core_bootcfg; + + /* Allocate VPE boot configuration structs */ + for (c = 0; c < ncores; c++) { + core_vpes = core_vpe_count(cl, c); + core_bootcfg[c].vpe_config = kcalloc(core_vpes, + sizeof(*core_bootcfg[c].vpe_config), + GFP_KERNEL); + if (!core_bootcfg[c].vpe_config) + goto err_out; } } /* Mark this CPU as booted */ - atomic_set(&mips_cps_core_bootcfg[cpu_core(¤t_cpu_data)].vpe_mask, - 1 << cpu_vpe_id(¤t_cpu_data)); + cl = cpu_cluster(¤t_cpu_data); + c = cpu_core(¤t_cpu_data); + cluster_bootcfg = &mips_cps_cluster_bootcfg[cl]; + core_bootcfg = &cluster_bootcfg->core_config[c]; + atomic_set(&core_bootcfg->vpe_mask, 1 << cpu_vpe_id(¤t_cpu_data)); return; err_out: /* Clean up allocations */ - if (mips_cps_core_bootcfg) { - for (c = 0; c < ncores; c++) - kfree(mips_cps_core_bootcfg[c].vpe_config); - kfree(mips_cps_core_bootcfg); - mips_cps_core_bootcfg = NULL; + if (mips_cps_cluster_bootcfg) { + for (cl = 0; cl < nclusters; cl++) { + cluster_bootcfg = &mips_cps_cluster_bootcfg[cl]; + ncores = mips_cps_numcores(cl); + for (c = 0; c < ncores; c++) { + core_bootcfg = &cluster_bootcfg->core_config[c]; + kfree(core_bootcfg->vpe_config); + } + kfree(mips_cps_cluster_bootcfg[c].core_config); + } + kfree(mips_cps_cluster_bootcfg); + mips_cps_cluster_bootcfg = NULL; } /* Effectively disable SMP by declaring CPUs not present */ @@ -405,17 +421,23 @@ static void boot_core(unsigned int core, unsigned int vpe_id) static void remote_vpe_boot(void *dummy) { + unsigned int cluster = cpu_cluster(¤t_cpu_data); unsigned core = cpu_core(¤t_cpu_data); - struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; + struct cluster_boot_config *cluster_cfg = + &mips_cps_cluster_bootcfg[cluster]; + struct core_boot_config *core_cfg = &cluster_cfg->core_config[core]; mips_cps_boot_vpes(core_cfg, cpu_vpe_id(¤t_cpu_data)); } static int cps_boot_secondary(int cpu, struct task_struct *idle) { + unsigned int cluster = cpu_cluster(&cpu_data[cpu]); unsigned core = cpu_core(&cpu_data[cpu]); unsigned vpe_id = cpu_vpe_id(&cpu_data[cpu]); - struct core_boot_config *core_cfg = &mips_cps_core_bootcfg[core]; + struct cluster_boot_config *cluster_cfg = + &mips_cps_cluster_bootcfg[cluster]; + struct core_boot_config *core_cfg = &cluster_cfg->core_config[core]; struct vpe_boot_config *vpe_cfg = &core_cfg->vpe_config[vpe_id]; unsigned int remote; int err; @@ -576,12 +598,14 @@ static void cps_kexec_nonboot_cpu(void) static int cps_cpu_disable(void) { unsigned cpu = smp_processor_id(); + struct cluster_boot_config *cluster_cfg; struct core_boot_config *core_cfg; if (!cps_pm_support_state(CPS_PM_POWER_GATED)) return -EINVAL; - core_cfg = &mips_cps_core_bootcfg[cpu_core(¤t_cpu_data)]; + cluster_cfg = &mips_cps_cluster_bootcfg[cpu_cluster(¤t_cpu_data)]; + core_cfg = &cluster_cfg->core_config[cpu_core(¤t_cpu_data)]; atomic_sub(1 << cpu_vpe_id(¤t_cpu_data), &core_cfg->vpe_mask); smp_mb__after_atomic(); set_cpu_online(cpu, false); From patchwork Wed Jan 29 12:32:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aleksandar Rikalo X-Patchwork-Id: 13953723 Received: from mail-ej1-f41.google.com (mail-ej1-f41.google.com [209.85.218.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DA96D8BE5; Wed, 29 Jan 2025 12:33:00 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.218.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153983; cv=none; b=C1BOP/ltAdp86m+JTMVCZ/XHZBzrLV5my3pA/GvVGlYBydwowelNgwefk2FBhzDLHX0yqXe8UdaUSP6HSXUtDmTvY2FZY+Jblm47bzpzmmU+HQXCx7p6HO7eyT8lHPpUopva9XxH9KRyUsy29R5wRjW6/w9nwmX48bdemAFNu98= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1738153983; c=relaxed/simple; bh=zJKStGWSsAVAMdDBvqbntgtAynZCg9dDBy8AbCoCFyY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=R2ChP+s7NRk7WoHqTXbPI1VFBPBWlSU4AfTJw+VjMyVPzg4twLUnJJyY9Vva2flN6Ez90kOZG19oJ64eiC5r/ME6ehunMVslBCSBq24v4bFaSd5tn2aFqVjBwhKmfGIvLEhnyLZR9JHTZq8YrUerQudhStiQH9HKQU9wfVmkogM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=hfPGQB50; arc=none smtp.client-ip=209.85.218.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="hfPGQB50" Received: by mail-ej1-f41.google.com with SMTP id a640c23a62f3a-aaedd529ba1so963879366b.1; Wed, 29 Jan 2025 04:33:00 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1738153979; x=1738758779; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=7XApyNSP9uDFDI6OWCTrLcEi5qIPQR7kGpmHTRZfXEM=; b=hfPGQB501I2Rle+L7avJ6yhEIt+tuncQMI0jPxfwCSR5d17D+ut2gQYvU/N7Jol+Ls P85PxjKVqFrp9aymglHuOWpht8M0f434lDihN33LMKbX7oVv50oqoshJcG04uQZiDWno rxNlI8WvyMWkfPNSgQlXeRCfK1sPRE37Tmjv7k5LSis1KfelpHySpCmji59DfjZz0KZ2 pFgFguWOD0mQCfEKcIVFyfHNrm0hbE8xIutTtUXIBqRzwMTgYDnuBTC6Aj8dqukXLexo Qpv1XElhqr/SMijkReAFE10QVwoag+JmuOErdn5309u0uXQlNc24kHuc9DrcIdxeY48N cPXw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1738153979; x=1738758779; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7XApyNSP9uDFDI6OWCTrLcEi5qIPQR7kGpmHTRZfXEM=; b=IMVUhKIwGvgZrLuroBuULA2nLY3kD/iT0ajK2aHiJlIMIp7TxZEF040/o+4OHrENh6 41ehZU6sTdw2n+CiWK9RGcx9UU13Ie+J9k2dbkg0IDqtQmXIGnjCyk7D1UNqQyqtWdbn 145V7V9MjKUmTMhQq3pEIYV0+9lJyE0q6B4CFmDvQGnj7F3nhC+WNU+QegdoS0/D6M5w vlmKUm7qcES07ZdLtuIyTBKjiYbWexQpMD0YbvJF8sqYhDhTbHZGO/BDQMCN+wFr1tyR dmITSIuNUCunKKcHPfXhxXnZ5Ob2zXo8G+QNcpCbeplvQg65YF/IW8665UADYkQQiD6H f7tg== X-Gm-Message-State: AOJu0YxB9eXrRVFbb903zdbylgaFe/E7pk75ck7LEzgFx2Hn7mWPKGTG 0usrMIC2iHI28oHa2MjH2tA+VMPkmYNcCI0U5um9ScZMuthJmMRyITU53yMC X-Gm-Gg: ASbGncveHJ/mKHsVEdlDb6qgO7bVW56QpVlbDyn8MVetUooL6cQGGfozY1DSQ28Hl1t Tm7tAsi25taskn60aX2nH+nFmN7YTjpRQtcPkindaaxF/Bkp6qBq5YGIDMtZTzOZlqTyt/RKGBT D5po6D0OR12VyUk/uYEhVQh0mkhsu4quNTn23YWknc4xzSI+mvznU3Mx9wkXFj9czxkyGr+IeEB hOsqUONrOriFMDTHPFp/6A67i330ZK580+xi6v6VmT3YNCT+baKl2gIsyhqBVYUyr3aIUMfAOMF GZS9bMg7HFPhqkGBgjJyY4nw X-Google-Smtp-Source: AGHT+IFsu0YKRHr/4LPFmGHJN+gVGyvvqKwEY83xOQ3oYfcisc0uZK+xisM8KM3WxklVh10MtPwSkg== X-Received: by 2002:a05:6402:1d4e:b0:5db:f423:19cf with SMTP id 4fb4d7f45d1cf-5dc5efbf1b3mr6232741a12.9.1738153978516; Wed, 29 Jan 2025 04:32:58 -0800 (PST) Received: from localhost.localdomain ([79.175.114.8]) by smtp.gmail.com with ESMTPSA id a640c23a62f3a-ab69051b1ddsm733540766b.180.2025.01.29.04.32.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 29 Jan 2025 04:32:58 -0800 (PST) From: Aleksandar Rikalo To: linux-mips@vger.kernel.org Cc: linux-kernel@vger.kernel.org, Thomas Bogendoerfer , Daniel Lezcano , Thomas Gleixner , Gregory CLEMENT , Serge Semin , Jiaxun Yang , Paul Burton , Aleksandar Rikalo , Chao-ying Fu , Djordje Todorovic Subject: [PATCH v9 4/4] MIPS: CPS: Boot CPUs in secondary clusters Date: Wed, 29 Jan 2025 13:32:50 +0100 Message-Id: <20250129123250.711910-5-arikalo@gmail.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20250129123250.711910-1-arikalo@gmail.com> References: <20250129123250.711910-1-arikalo@gmail.com> Precedence: bulk X-Mailing-List: linux-mips@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 From: Paul Burton Probe for & boot CPUs (cores & VPs) in secondary clusters (ie. not the cluster that began booting Linux) when they are present in systems with CM 3.5 or higher. Signed-off-by: Paul Burton Signed-off-by: Chao-ying Fu Signed-off-by: Dragan Mladjenovic Signed-off-by: Aleksandar Rikalo Tested-by: Serge Semin Tested-by: Gregory CLEMENT --- arch/mips/include/asm/mips-cm.h | 18 +++ arch/mips/include/asm/smp-cps.h | 1 + arch/mips/kernel/mips-cm.c | 4 +- arch/mips/kernel/smp-cps.c | 205 ++++++++++++++++++++++++++++---- 4 files changed, 207 insertions(+), 21 deletions(-) diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index 23ce951f445b..1afa85db1fb3 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -255,6 +255,12 @@ GCR_ACCESSOR_RW(32, 0x130, l2_config) GCR_ACCESSOR_RO(32, 0x150, sys_config2) #define CM_GCR_SYS_CONFIG2_MAXVPW GENMASK(3, 0) +/* GCR_L2-RAM_CONFIG - Configuration & status of L2 cache RAMs */ +GCR_ACCESSOR_RW(64, 0x240, l2_ram_config) +#define CM_GCR_L2_RAM_CONFIG_PRESENT BIT(31) +#define CM_GCR_L2_RAM_CONFIG_HCI_DONE BIT(30) +#define CM_GCR_L2_RAM_CONFIG_HCI_SUPPORTED BIT(29) + /* GCR_L2_PFT_CONTROL - Controls hardware L2 prefetching */ GCR_ACCESSOR_RW(32, 0x300, l2_pft_control) #define CM_GCR_L2_PFT_CONTROL_PAGEMASK GENMASK(31, 12) @@ -266,6 +272,18 @@ GCR_ACCESSOR_RW(32, 0x308, l2_pft_control_b) #define CM_GCR_L2_PFT_CONTROL_B_CEN BIT(8) #define CM_GCR_L2_PFT_CONTROL_B_PORTID GENMASK(7, 0) +/* GCR_L2_TAG_ADDR - Access addresses in L2 cache tags */ +GCR_ACCESSOR_RW(64, 0x600, l2_tag_addr) + +/* GCR_L2_TAG_STATE - Access L2 cache tag state */ +GCR_ACCESSOR_RW(64, 0x608, l2_tag_state) + +/* GCR_L2_DATA - Access data in L2 cache lines */ +GCR_ACCESSOR_RW(64, 0x610, l2_data) + +/* GCR_L2_ECC - Access ECC information from L2 cache lines */ +GCR_ACCESSOR_RW(64, 0x618, l2_ecc) + /* GCR_L2SM_COP - L2 cache op state machine control */ GCR_ACCESSOR_RW(32, 0x620, l2sm_cop) #define CM_GCR_L2SM_COP_PRESENT BIT(31) diff --git a/arch/mips/include/asm/smp-cps.h b/arch/mips/include/asm/smp-cps.h index a629e948a6fd..10d3ebd890cb 100644 --- a/arch/mips/include/asm/smp-cps.h +++ b/arch/mips/include/asm/smp-cps.h @@ -23,6 +23,7 @@ struct core_boot_config { }; struct cluster_boot_config { + unsigned long *core_power; struct core_boot_config *core_config; }; diff --git a/arch/mips/kernel/mips-cm.c b/arch/mips/kernel/mips-cm.c index 3eb2cfb893e1..9854bc2b6895 100644 --- a/arch/mips/kernel/mips-cm.c +++ b/arch/mips/kernel/mips-cm.c @@ -308,7 +308,9 @@ void mips_cm_lock_other(unsigned int cluster, unsigned int core, FIELD_PREP(CM3_GCR_Cx_OTHER_VP, vp); if (cm_rev >= CM_REV_CM3_5) { - val |= CM_GCR_Cx_OTHER_CLUSTER_EN; + if (cluster != cpu_cluster(¤t_cpu_data)) + val |= CM_GCR_Cx_OTHER_CLUSTER_EN; + val |= CM_GCR_Cx_OTHER_GIC_EN; val |= FIELD_PREP(CM_GCR_Cx_OTHER_CLUSTER, cluster); val |= FIELD_PREP(CM_GCR_Cx_OTHER_BLOCK, block); } else { diff --git a/arch/mips/kernel/smp-cps.c b/arch/mips/kernel/smp-cps.c index 3d8cf3098656..b20ea4048429 100644 --- a/arch/mips/kernel/smp-cps.c +++ b/arch/mips/kernel/smp-cps.c @@ -36,12 +36,56 @@ enum label_id { UASM_L_LA(_not_nmi) -static DECLARE_BITMAP(core_power, NR_CPUS); static u64 core_entry_reg; static phys_addr_t cps_vec_pa; struct cluster_boot_config *mips_cps_cluster_bootcfg; +static void power_up_other_cluster(unsigned int cluster) +{ + u32 stat, seq_state; + unsigned int timeout; + + mips_cm_lock_other(cluster, CM_GCR_Cx_OTHER_CORE_CM, 0, + CM_GCR_Cx_OTHER_BLOCK_LOCAL); + stat = read_cpc_co_stat_conf(); + mips_cm_unlock_other(); + + seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE; + seq_state >>= __ffs(CPC_Cx_STAT_CONF_SEQSTATE); + if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U5) + return; + + /* Set endianness & power up the CM */ + mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + write_cpc_redir_sys_config(IS_ENABLED(CONFIG_CPU_BIG_ENDIAN)); + write_cpc_redir_pwrup_ctl(1); + mips_cm_unlock_other(); + + /* Wait for the CM to start up */ + timeout = 1000; + mips_cm_lock_other(cluster, CM_GCR_Cx_OTHER_CORE_CM, 0, + CM_GCR_Cx_OTHER_BLOCK_LOCAL); + while (1) { + stat = read_cpc_co_stat_conf(); + seq_state = stat & CPC_Cx_STAT_CONF_SEQSTATE; + seq_state >>= __ffs(CPC_Cx_STAT_CONF_SEQSTATE); + if (seq_state == CPC_Cx_STAT_CONF_SEQSTATE_U5) + break; + + if (timeout) { + mdelay(1); + timeout--; + } else { + pr_warn("Waiting for cluster %u CM to power up... STAT_CONF=0x%x\n", + cluster, stat); + mdelay(1000); + } + } + + mips_cm_unlock_other(); +} + static unsigned __init core_vpe_count(unsigned int cluster, unsigned core) { return min(smp_max_threads, mips_cps_numvps(cluster, core)); @@ -178,6 +222,9 @@ static void __init cps_smp_setup(void) pr_cont(","); pr_cont("{"); + if (mips_cm_revision() >= CM_REV_CM3_5) + power_up_other_cluster(cl); + ncores = mips_cps_numcores(cl); for (c = 0; c < ncores; c++) { core_vpes = core_vpe_count(cl, c); @@ -205,8 +252,8 @@ static void __init cps_smp_setup(void) /* Indicate present CPUs (CPU being synonymous with VPE) */ for (v = 0; v < min_t(unsigned, nvpes, NR_CPUS); v++) { - set_cpu_possible(v, cpu_cluster(&cpu_data[v]) == 0); - set_cpu_present(v, cpu_cluster(&cpu_data[v]) == 0); + set_cpu_possible(v, true); + set_cpu_present(v, true); __cpu_number_map[v] = v; __cpu_logical_map[v] = v; } @@ -214,9 +261,6 @@ static void __init cps_smp_setup(void) /* Set a coherent default CCA (CWB) */ change_c0_config(CONF_CM_CMASK, 0x5); - /* Core 0 is powered up (we're running on it) */ - bitmap_set(core_power, 0, 1); - /* Initialise core 0 */ mips_cps_core_init(); @@ -298,6 +342,10 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) goto err_out; mips_cps_cluster_bootcfg[cl].core_config = core_bootcfg; + mips_cps_cluster_bootcfg[cl].core_power = + kcalloc(BITS_TO_LONGS(ncores), sizeof(unsigned long), + GFP_KERNEL); + /* Allocate VPE boot configuration structs */ for (c = 0; c < ncores; c++) { core_vpes = core_vpe_count(cl, c); @@ -309,11 +357,12 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) } } - /* Mark this CPU as booted */ + /* Mark this CPU as powered up & booted */ cl = cpu_cluster(¤t_cpu_data); c = cpu_core(¤t_cpu_data); cluster_bootcfg = &mips_cps_cluster_bootcfg[cl]; core_bootcfg = &cluster_bootcfg->core_config[c]; + bitmap_set(cluster_bootcfg->core_power, cpu_core(¤t_cpu_data), 1); atomic_set(&core_bootcfg->vpe_mask, 1 << cpu_vpe_id(¤t_cpu_data)); return; @@ -341,13 +390,118 @@ static void __init cps_prepare_cpus(unsigned int max_cpus) } } -static void boot_core(unsigned int core, unsigned int vpe_id) +static void init_cluster_l2(void) { - u32 stat, seq_state; - unsigned timeout; + u32 l2_cfg, l2sm_cop, result; + + while (1) { + l2_cfg = read_gcr_redir_l2_ram_config(); + + /* If HCI is not supported, use the state machine below */ + if (!(l2_cfg & CM_GCR_L2_RAM_CONFIG_PRESENT)) + break; + if (!(l2_cfg & CM_GCR_L2_RAM_CONFIG_HCI_SUPPORTED)) + break; + + /* If the HCI_DONE bit is set, we're finished */ + if (l2_cfg & CM_GCR_L2_RAM_CONFIG_HCI_DONE) + return; + } + + l2sm_cop = read_gcr_redir_l2sm_cop(); + if (WARN(!(l2sm_cop & CM_GCR_L2SM_COP_PRESENT), + "L2 init not supported on this system yet")) + return; + + /* Clear L2 tag registers */ + write_gcr_redir_l2_tag_state(0); + write_gcr_redir_l2_ecc(0); + + /* Ensure the L2 tag writes complete before the state machine starts */ + mb(); + + /* Wait for the L2 state machine to be idle */ + do { + l2sm_cop = read_gcr_redir_l2sm_cop(); + } while (l2sm_cop & CM_GCR_L2SM_COP_RUNNING); + + /* Start a store tag operation */ + l2sm_cop = CM_GCR_L2SM_COP_TYPE_IDX_STORETAG; + l2sm_cop <<= __ffs(CM_GCR_L2SM_COP_TYPE); + l2sm_cop |= CM_GCR_L2SM_COP_CMD_START; + write_gcr_redir_l2sm_cop(l2sm_cop); + + /* Ensure the state machine starts before we poll for completion */ + mb(); + + /* Wait for the operation to be complete */ + do { + l2sm_cop = read_gcr_redir_l2sm_cop(); + result = l2sm_cop & CM_GCR_L2SM_COP_RESULT; + result >>= __ffs(CM_GCR_L2SM_COP_RESULT); + } while (!result); + + WARN(result != CM_GCR_L2SM_COP_RESULT_DONE_OK, + "L2 state machine failed cache init with error %u\n", result); +} + +static void boot_core(unsigned int cluster, unsigned int core, + unsigned int vpe_id) +{ + struct cluster_boot_config *cluster_cfg; + u32 access, stat, seq_state; + unsigned int timeout, ncores; + + cluster_cfg = &mips_cps_cluster_bootcfg[cluster]; + ncores = mips_cps_numcores(cluster); + + if ((cluster != cpu_cluster(¤t_cpu_data)) && + bitmap_empty(cluster_cfg->core_power, ncores)) { + power_up_other_cluster(cluster); + + mips_cm_lock_other(cluster, core, 0, + CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + + /* Ensure cluster GCRs are where we expect */ + write_gcr_redir_base(read_gcr_base()); + write_gcr_redir_cpc_base(read_gcr_cpc_base()); + write_gcr_redir_gic_base(read_gcr_gic_base()); + + init_cluster_l2(); + + /* Mirror L2 configuration */ + write_gcr_redir_l2_only_sync_base(read_gcr_l2_only_sync_base()); + write_gcr_redir_l2_pft_control(read_gcr_l2_pft_control()); + write_gcr_redir_l2_pft_control_b(read_gcr_l2_pft_control_b()); + + /* Mirror ECC/parity setup */ + write_gcr_redir_err_control(read_gcr_err_control()); + + /* Set BEV base */ + write_gcr_redir_bev_base(core_entry_reg); + + mips_cm_unlock_other(); + } + + if (cluster != cpu_cluster(¤t_cpu_data)) { + mips_cm_lock_other(cluster, core, 0, + CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + + /* Ensure the core can access the GCRs */ + access = read_gcr_redir_access(); + access |= BIT(core); + write_gcr_redir_access(access); + + mips_cm_unlock_other(); + } else { + /* Ensure the core can access the GCRs */ + access = read_gcr_access(); + access |= BIT(core); + write_gcr_access(access); + } /* Select the appropriate core */ - mips_cm_lock_other(0, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL); + mips_cm_lock_other(cluster, core, 0, CM_GCR_Cx_OTHER_BLOCK_LOCAL); /* Set its reset vector */ if (mips_cm_is64) @@ -416,7 +570,17 @@ static void boot_core(unsigned int core, unsigned int vpe_id) mips_cm_unlock_other(); /* The core is now powered up */ - bitmap_set(core_power, core, 1); + bitmap_set(cluster_cfg->core_power, core, 1); + + /* + * Restore CM_PWRUP=0 so that the CM can power down if all the cores in + * the cluster do (eg. if they're all removed via hotplug. + */ + if (mips_cm_revision() >= CM_REV_CM3_5) { + mips_cm_lock_other(cluster, 0, 0, CM_GCR_Cx_OTHER_BLOCK_GLOBAL); + write_cpc_redir_pwrup_ctl(0); + mips_cm_unlock_other(); + } } static void remote_vpe_boot(void *dummy) @@ -442,10 +606,6 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle) unsigned int remote; int err; - /* We don't yet support booting CPUs in other clusters */ - if (cpu_cluster(&cpu_data[cpu]) != cpu_cluster(&raw_current_cpu_data)) - return -ENOSYS; - vpe_cfg->pc = (unsigned long)&smp_bootstrap; vpe_cfg->sp = __KSTK_TOS(idle); vpe_cfg->gp = (unsigned long)task_thread_info(idle); @@ -454,14 +614,15 @@ static int cps_boot_secondary(int cpu, struct task_struct *idle) preempt_disable(); - if (!test_bit(core, core_power)) { + if (!test_bit(core, cluster_cfg->core_power)) { /* Boot a VPE on a powered down core */ - boot_core(core, vpe_id); + boot_core(cluster, core, vpe_id); goto out; } if (cpu_has_vp) { - mips_cm_lock_other(0, core, vpe_id, CM_GCR_Cx_OTHER_BLOCK_LOCAL); + mips_cm_lock_other(cluster, core, vpe_id, + CM_GCR_Cx_OTHER_BLOCK_LOCAL); if (mips_cm_is64) write_gcr_co_reset64_base(core_entry_reg); else @@ -671,11 +832,15 @@ static void cps_cpu_die(unsigned int cpu) { } static void cps_cleanup_dead_cpu(unsigned cpu) { + unsigned int cluster = cpu_cluster(&cpu_data[cpu]); unsigned core = cpu_core(&cpu_data[cpu]); unsigned int vpe_id = cpu_vpe_id(&cpu_data[cpu]); ktime_t fail_time; unsigned stat; int err; + struct cluster_boot_config *cluster_cfg; + + cluster_cfg = &mips_cps_cluster_bootcfg[cluster]; /* * Now wait for the CPU to actually offline. Without doing this that @@ -727,7 +892,7 @@ static void cps_cleanup_dead_cpu(unsigned cpu) } while (1); /* Indicate the core is powered off */ - bitmap_clear(core_power, core, 1); + bitmap_clear(cluster_cfg->core_power, core, 1); } else if (cpu_has_mipsmt) { /* * Have a CPU with access to the offlined CPUs registers wait