summaryrefslogtreecommitdiffstats
path: root/arch/m68k/apollo
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2026-09-14 22:12:34 -1000
committerTejun Heo <tj@kernel.org>2026-09-15 06:57:20 -1000
commita9e3760b0838299649c0d57cca44daaf40ba3c33 (patch)
tree95807ff0e511c05602ef34808cfc660303309057 /arch/m68k/apollo
downloadlinux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.tar.gz
linux-stable-a9e3760b0838299649c0d57cca44daaf40ba3c33.zip
sched_ext: Maintain an online cid mask in the scheduler arenagrafted
Schedulers on the default cid mapping treat [0, nr_online_cids) as the online set and restart on hotplug. Schedulers that install their own mapping with scx_bpf_cid_override() have no way to learn which cids are online: the count no longer identifies members and the CPU-form cpumask is unusable from cid programs. This is an obvious hole in the cid API. Add scx_bpf_online_cmask(), a kernel-maintained cmask in the scheduler's arena, allocated alongside the per-CPU scratch masks and populated after the cid mapping is finalized and before ops.init(), for child schedulers too. The pointer stays valid through ops.exit() with no reference to take. It is the arena offset as a void pointer, the same form struct_ops arena arguments arrive in. The verifier types the void return as a scalar for the program's arena cast. The mask follows the SCX hotplug notifications: seeded from cpu_active_mask and updated before ops.cid_online/offline() runs, so it lags cpu_online_mask only inside a hotplug transition. Updates walk the scheduler list under the lock that also serializes unlinking. Reads are live, not atomic snapshots. Root initialization excludes hotplug. v2: Reworded the getter kerneldoc (Andrea Righi). Signed-off-by: Tejun Heo <tj@kernel.org> Reviewed-by: Andrea Righi <arighi@nvidia.com>
Diffstat (limited to 'arch/m68k/apollo')
-rw-r--r--arch/m68k/apollo/Makefile6
-rw-r--r--arch/m68k/apollo/apollo.h4
-rw-r--r--arch/m68k/apollo/config.c240
-rw-r--r--arch/m68k/apollo/dn_ints.c50
4 files changed, 300 insertions, 0 deletions
diff --git a/arch/m68k/apollo/Makefile b/arch/m68k/apollo/Makefile
new file mode 100644
index 000000000..676c74b26
--- /dev/null
+++ b/arch/m68k/apollo/Makefile
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0-only
+#
+# Makefile for Linux arch/m68k/apollo source directory
+#
+
+obj-y := config.o dn_ints.o
diff --git a/arch/m68k/apollo/apollo.h b/arch/m68k/apollo/apollo.h
new file mode 100644
index 000000000..1fe9d856d
--- /dev/null
+++ b/arch/m68k/apollo/apollo.h
@@ -0,0 +1,4 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/* dn_ints.c */
+void dn_init_IRQ(void);
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
new file mode 100644
index 000000000..e324c5f67
--- /dev/null
+++ b/arch/m68k/apollo/config.c
@@ -0,0 +1,240 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/rtc.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/bootinfo.h>
+#include <asm/bootinfo-apollo.h>
+#include <asm/byteorder.h>
+#include <asm/apollohw.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/config.h>
+
+#include "apollo.h"
+
+u_long sio01_physaddr;
+u_long sio23_physaddr;
+u_long rtc_physaddr;
+u_long pica_physaddr;
+u_long picb_physaddr;
+u_long cpuctrl_physaddr;
+u_long timer_physaddr;
+u_long apollo_model;
+
+extern void dn_sched_init(void);
+extern int dn_dummy_hwclk(int, struct rtc_time *);
+static void dn_dummy_reset(void);
+#ifdef CONFIG_HEARTBEAT
+static void dn_heartbeat(int on);
+#endif
+static irqreturn_t dn_timer_int(int irq,void *);
+static void dn_get_model(char *model);
+static const char *apollo_models[] = {
+ [APOLLO_DN3000-APOLLO_DN3000] = "DN3000 (Otter)",
+ [APOLLO_DN3010-APOLLO_DN3000] = "DN3010 (Otter)",
+ [APOLLO_DN3500-APOLLO_DN3000] = "DN3500 (Cougar II)",
+ [APOLLO_DN4000-APOLLO_DN3000] = "DN4000 (Mink)",
+ [APOLLO_DN4500-APOLLO_DN3000] = "DN4500 (Roadrunner)"
+};
+
+int __init apollo_parse_bootinfo(const struct bi_record *record)
+{
+ int unknown = 0;
+ const void *data = record->data;
+
+ switch (be16_to_cpu(record->tag)) {
+ case BI_APOLLO_MODEL:
+ apollo_model = be32_to_cpup(data);
+ break;
+
+ default:
+ unknown=1;
+ }
+
+ return unknown;
+}
+
+static void __init dn_setup_model(void)
+{
+ pr_info("Apollo hardware found: [%s]\n",
+ apollo_models[apollo_model - APOLLO_DN3000]);
+
+ switch(apollo_model) {
+ case APOLLO_UNKNOWN:
+ panic("Unknown apollo model");
+ break;
+ case APOLLO_DN3000:
+ case APOLLO_DN3010:
+ sio01_physaddr=SAU8_SIO01_PHYSADDR;
+ rtc_physaddr=SAU8_RTC_PHYSADDR;
+ pica_physaddr=SAU8_PICA;
+ picb_physaddr=SAU8_PICB;
+ cpuctrl_physaddr=SAU8_CPUCTRL;
+ timer_physaddr=SAU8_TIMER;
+ break;
+ case APOLLO_DN4000:
+ sio01_physaddr=SAU7_SIO01_PHYSADDR;
+ sio23_physaddr=SAU7_SIO23_PHYSADDR;
+ rtc_physaddr=SAU7_RTC_PHYSADDR;
+ pica_physaddr=SAU7_PICA;
+ picb_physaddr=SAU7_PICB;
+ cpuctrl_physaddr=SAU7_CPUCTRL;
+ timer_physaddr=SAU7_TIMER;
+ break;
+ case APOLLO_DN4500:
+ panic("Apollo model not yet supported");
+ break;
+ case APOLLO_DN3500:
+ sio01_physaddr=SAU7_SIO01_PHYSADDR;
+ sio23_physaddr=SAU7_SIO23_PHYSADDR;
+ rtc_physaddr=SAU7_RTC_PHYSADDR;
+ pica_physaddr=SAU7_PICA;
+ picb_physaddr=SAU7_PICB;
+ cpuctrl_physaddr=SAU7_CPUCTRL;
+ timer_physaddr=SAU7_TIMER;
+ break;
+ default:
+ panic("Undefined apollo model");
+ break;
+ }
+
+
+}
+
+static void dn_serial_print(const char *str)
+{
+ while (*str) {
+ if (*str == '\n') {
+ sio01.rhrb_thrb = (unsigned char)'\r';
+ while (!(sio01.srb_csrb & 0x4))
+ ;
+ }
+ sio01.rhrb_thrb = (unsigned char)*str++;
+ while (!(sio01.srb_csrb & 0x4))
+ ;
+ }
+}
+
+void __init config_apollo(void)
+{
+ int i;
+
+ dn_setup_model();
+
+ mach_sched_init=dn_sched_init; /* */
+ mach_init_IRQ=dn_init_IRQ;
+ mach_hwclk = dn_dummy_hwclk; /* */
+ mach_reset = dn_dummy_reset; /* */
+#ifdef CONFIG_HEARTBEAT
+ mach_heartbeat = dn_heartbeat;
+#endif
+ mach_get_model = dn_get_model;
+
+ cpuctrl=0xaa00;
+
+ /* clear DMA translation table */
+ for(i=0;i<0x400;i++)
+ addr_xlat_map[i]=0;
+
+}
+
+irqreturn_t dn_timer_int(int irq, void *dev_id)
+{
+ unsigned char *at = (unsigned char *)apollo_timer;
+
+ legacy_timer_tick(1);
+ timer_heartbeat();
+
+ READ_ONCE(*(at + 3));
+ READ_ONCE(*(at + 5));
+
+ return IRQ_HANDLED;
+}
+
+void dn_sched_init(void)
+{
+ /* program timer 1 */
+ *(volatile unsigned char *)(apollo_timer + 3) = 0x01;
+ *(volatile unsigned char *)(apollo_timer + 1) = 0x40;
+ *(volatile unsigned char *)(apollo_timer + 5) = 0x09;
+ *(volatile unsigned char *)(apollo_timer + 7) = 0xc4;
+
+ /* enable IRQ of PIC B */
+ *(volatile unsigned char *)(pica+1)&=(~8);
+
+#if 0
+ pr_info("*(0x10803) %02x\n",
+ *(volatile unsigned char *)(apollo_timer + 0x3));
+ pr_info("*(0x10803) %02x\n",
+ *(volatile unsigned char *)(apollo_timer + 0x3));
+#endif
+
+ if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", NULL))
+ pr_err("Couldn't register timer interrupt\n");
+}
+
+int dn_dummy_hwclk(int op, struct rtc_time *t) {
+
+
+ if(!op) { /* read */
+ t->tm_sec=rtc->second;
+ t->tm_min=rtc->minute;
+ t->tm_hour=rtc->hours;
+ t->tm_mday=rtc->day_of_month;
+ t->tm_wday=rtc->day_of_week;
+ t->tm_mon = rtc->month - 1;
+ t->tm_year=rtc->year;
+ if (t->tm_year < 70)
+ t->tm_year += 100;
+ } else {
+ rtc->second=t->tm_sec;
+ rtc->minute=t->tm_min;
+ rtc->hours=t->tm_hour;
+ rtc->day_of_month=t->tm_mday;
+ if(t->tm_wday!=-1)
+ rtc->day_of_week=t->tm_wday;
+ rtc->month = t->tm_mon + 1;
+ rtc->year = t->tm_year % 100;
+ }
+
+ return 0;
+
+}
+
+static void dn_dummy_reset(void)
+{
+ dn_serial_print("The end !\n");
+
+ for(;;);
+
+}
+
+static void dn_get_model(char *model)
+{
+ strcpy(model, "Apollo ");
+ if (apollo_model >= APOLLO_DN3000 && apollo_model <= APOLLO_DN4500)
+ strcat(model, apollo_models[apollo_model - APOLLO_DN3000]);
+}
+
+#ifdef CONFIG_HEARTBEAT
+static int dn_cpuctrl=0xff00;
+
+static void dn_heartbeat(int on) {
+
+ if(on) {
+ dn_cpuctrl&=~0x100;
+ cpuctrl=dn_cpuctrl;
+ }
+ else {
+ dn_cpuctrl&=~0x100;
+ dn_cpuctrl|=0x100;
+ cpuctrl=dn_cpuctrl;
+ }
+}
+#endif
+
diff --git a/arch/m68k/apollo/dn_ints.c b/arch/m68k/apollo/dn_ints.c
new file mode 100644
index 000000000..ba96a92f8
--- /dev/null
+++ b/arch/m68k/apollo/dn_ints.c
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/traps.h>
+#include <asm/apollohw.h>
+
+#include "apollo.h"
+
+static unsigned int apollo_irq_startup(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ if (irq < 8)
+ *(volatile unsigned char *)(pica+1) &= ~(1 << irq);
+ else
+ *(volatile unsigned char *)(picb+1) &= ~(1 << (irq - 8));
+ return 0;
+}
+
+static void apollo_irq_shutdown(struct irq_data *data)
+{
+ unsigned int irq = data->irq;
+
+ if (irq < 8)
+ *(volatile unsigned char *)(pica+1) |= (1 << irq);
+ else
+ *(volatile unsigned char *)(picb+1) |= (1 << (irq - 8));
+}
+
+static void apollo_irq_eoi(struct irq_data *data)
+{
+ *(volatile unsigned char *)(pica) = 0x20;
+ *(volatile unsigned char *)(picb) = 0x20;
+}
+
+static struct irq_chip apollo_irq_chip = {
+ .name = "apollo",
+ .irq_startup = apollo_irq_startup,
+ .irq_shutdown = apollo_irq_shutdown,
+ .irq_eoi = apollo_irq_eoi,
+};
+
+
+void __init dn_init_IRQ(void)
+{
+ m68k_setup_user_interrupt(VEC_USER + 96, 16);
+ m68k_setup_irq_controller(&apollo_irq_chip, handle_fasteoi_irq,
+ IRQ_APOLLO, 16);
+}