Skip to content

Commit 3d4619e

Browse files
committed
apps/system : Add cputest application for Secondary CPUs management testing
Add cputest application with shell commands for testing CPU driver functionality. Provides commands to enable/disable secondary CPUs and check CPU status through device interface. Shell commands added: - cpuctrl on <cpu_id>: Power on specified CPU - cpuctrl off <cpu_id>: Power off specified CPU - cpuctrl status: Show status of all Secondary CPUs - cpuctrl help : Show the help message Test Cases: Default: TASH>smp - smp will run and all threads exit properly TASH>cpuctrl off 1 - CPU1 Power off TASH>cpuctrl on 1 - CPU1 turned back on TASH>smp - smp will run and all threads exit properly
1 parent 242108b commit 3d4619e

File tree

5 files changed

+371
-0
lines changed

5 files changed

+371
-0
lines changed

apps/system/cpucontrol/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#
2+
# For a description of the syntax of this configuration file,
3+
# see kconfig-language at https://www.kernel.org/doc/Documentation/kbuild/kconfig-language.txt
4+
#
5+
6+
config SYSTEM_CPUCONTROL
7+
bool "CPU Control commands"
8+
default n
9+
depends on SMP
10+
---help---
11+
Enable support for CPU control commands in TASH. This provides commands
12+
for managing CPU power management and status functionality on multi-core
13+
systems. Commands include cpu1on, cpu1off, cpustatus.

apps/system/cpucontrol/Make.defs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
###########################################################################
2+
#
3+
# Copyright 2025 Samsung Electronics All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14+
# either express or implied.
15+
# See the License for the specific
16+
# language governing permissions and limitations under the License.
17+
#
18+
###########################################################################
19+
20+
21+
ifeq ($(CONFIG_SYSTEM_CPUCONTROL),y)
22+
CONFIGURED_APPS += system/cpucontrol
23+
endif

apps/system/cpucontrol/Makefile

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
############################################################################
2+
#
3+
# Copyright (c) 2025 Samsung Electronics Co., Ltd All Rights Reserved.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14+
# either express or implied.
15+
# See the License for the specific
16+
# language governing permissions and limitations under the License.
17+
#
18+
###########################################################################
19+
20+
-include $(TOPDIR)/.config
21+
-include $(TOPDIR)/Make.defs
22+
include $(APPDIR)/Make.defs
23+
24+
ifeq ($(WINTOOL),y)
25+
INCDIROPT = -w
26+
endif
27+
28+
# CPU Control System Utility
29+
30+
ASRCS =
31+
CSRCS =
32+
MAINSRC = cpucontrol.c
33+
34+
AOBJS = $(ASRCS:.S=$(OBJEXT))
35+
COBJS = $(CSRCS:.c=$(OBJEXT))
36+
MAINOBJ = $(MAINSRC:.c=$(OBJEXT))
37+
38+
SRCS = $(ASRCS) $(CSRCS) $(MAINSRC)
39+
OBJS = $(AOBJS) $(COBJS)
40+
41+
ifneq ($(CONFIG_BUILD_KERNEL),y)
42+
OBJS += $(MAINOBJ)
43+
endif
44+
45+
ifeq ($(CONFIG_WINDOWS_NATIVE),y)
46+
BIN = ..\..\libapps$(LIBEXT)
47+
else
48+
ifeq ($(WINTOOL),y)
49+
BIN = ..\\..\\libapps$(LIBEXT)
50+
else
51+
BIN = ../../libapps$(LIBEXT)
52+
endif
53+
endif
54+
55+
ifeq ($(WINTOOL),y)
56+
INSTALL_DIR = "${shell cygpath -w $(BIN_DIR)}"
57+
else
58+
INSTALL_DIR = $(BIN_DIR)
59+
endif
60+
61+
ROOTDEPPATH = --dep-path .
62+
63+
# Common build
64+
65+
VPATH =
66+
67+
all: .built
68+
.PHONY: context depend clean distclean
69+
70+
$(AOBJS): %$(OBJEXT): %.S
71+
$(call ASSEMBLE, $<, $@)
72+
73+
$(COBJS) $(MAINOBJ): %$(OBJEXT): %.c
74+
$(call COMPILE, $<, $@)
75+
76+
.built: $(OBJS)
77+
$(call ARCHIVE, $(BIN), $(OBJS))
78+
$(Q) touch .built
79+
80+
install:
81+
82+
context:
83+
84+
# Create dependencies
85+
86+
.depend: Makefile $(SRCS)
87+
$(Q) $(MKDEP) $(ROOTDEPPATH) "$(CC)" -- $(CFLAGS) -- $(SRCS) >Make.dep
88+
$(Q) touch $@
89+
90+
depend: .depend
91+
92+
clean:
93+
$(call DELFILE, .built)
94+
$(call CLEAN)
95+
96+
distclean: clean
97+
$(call DELFILE, Make.dep)
98+
$(call DELFILE, .depend)
99+
100+
-include Make.dep
101+
.PHONY: preconfig
102+
preconfig:
Lines changed: 225 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,225 @@
1+
/****************************************************************************
2+
*
3+
* Copyright 2025 Samsung Electronics All Rights Reserved.
4+
*
5+
* Licensed under the Apache License, Version 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an
13+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
14+
* either express or implied.
15+
* See the License for the specific
16+
* language governing permissions and limitations under the License.
17+
*
18+
****************************************************************************/
19+
20+
/****************************************************************************
21+
* Included Files
22+
****************************************************************************/
23+
24+
#include <tinyara/config.h>
25+
#include <stdio.h>
26+
#include <stdlib.h>
27+
#include <string.h>
28+
#include <fcntl.h>
29+
#include <sys/ioctl.h>
30+
#include <errno.h>
31+
#include <unistd.h>
32+
#include <tinyara/cpu_driver.h>
33+
#include <apps/shell/tash.h>
34+
35+
/****************************************************************************
36+
* Preprocessor Definitions
37+
****************************************************************************/
38+
39+
const char *cpu_states[] = {
40+
"running", //0
41+
"stop", //1
42+
};
43+
44+
/****************************************************************************
45+
* Private Function Prototypes
46+
****************************************************************************/
47+
48+
49+
static int cpucontrol_cpu_on(int argc, char *argv[]);
50+
static int cpucontrol_cpu_off(int argc, char *argv[]);
51+
static int cpucontrol_cpu_status(int argc, char *argv[]);
52+
static int cpucontrol_help(int argc, char *argv[]);
53+
static int cpucontrol_main(int argc, char *argv[]);
54+
55+
/****************************************************************************
56+
* Private Functions
57+
****************************************************************************/
58+
59+
static int cpucontrol_cpu_on(int argc, char *argv[])
60+
{
61+
int fd, state, cpu_num;
62+
char devname[16];
63+
64+
if (argc < 3) {
65+
printf("Usage: cpuctrl on <cpu_id>\n");
66+
printf("Example: cpuctrl on 1\n");
67+
return -EINVAL;
68+
}
69+
70+
cpu_num = atoi(argv[2]);
71+
if (cpu_num <= 0 || cpu_num >= CONFIG_SMP_NCPUS) {
72+
printf("Invalid CPU ID %d. Valid range: 1-%d\n", cpu_num, CONFIG_SMP_NCPUS - 1);
73+
return -EINVAL;
74+
}
75+
76+
if (sched_getcpu() > 0) {
77+
printf("can only powerup cpu%d from cpu0!\n", cpu_num);
78+
return -EPERM;
79+
}
80+
81+
printf("powering up cpu%d!\n", cpu_num);
82+
83+
snprintf(devname, sizeof(devname), "/dev/cpu%d", cpu_num);
84+
fd = open(devname, O_RDWR);
85+
if (fd < 0) {
86+
printf("Cannot open %s: errno = %d\n", devname, get_errno());
87+
return -get_errno();
88+
}
89+
90+
if (ioctl(fd, IOC_CPU_ENABLE, 1) < 0) {
91+
printf("IOC_CPU_ENABLE ioctl failed for %s : errno = %d\n", devname, get_errno());
92+
close(fd);
93+
return -get_errno();
94+
}
95+
printf("cpu%d successfully enabled\n", cpu_num);
96+
97+
if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
98+
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
99+
close(fd);
100+
return -get_errno();
101+
}
102+
103+
printf("state: %d (%s)\n", state, cpu_states[state]);
104+
close(fd);
105+
return 0;
106+
}
107+
108+
static int cpucontrol_cpu_off(int argc, char *argv[])
109+
{
110+
int fd, state, cpu_num;
111+
char devname[16];
112+
113+
if (argc < 3) {
114+
printf("Usage: cpuctrl off <cpu_id>\n");
115+
printf("Example: cpuctrl off 1\n");
116+
return -EINVAL;
117+
}
118+
119+
cpu_num = atoi(argv[2]);
120+
if (cpu_num <= 0 || cpu_num >= CONFIG_SMP_NCPUS) {
121+
printf("Invalid CPU ID %d. Valid range: 1-%d\n", cpu_num, CONFIG_SMP_NCPUS - 1);
122+
return -EINVAL;
123+
}
124+
125+
if (sched_getcpu() > 0) {
126+
printf("can only powerdown cpu%d from cpu0!\n", cpu_num);
127+
return -EPERM;
128+
}
129+
130+
printf("powering down cpu%d!\n", cpu_num);
131+
132+
snprintf(devname, sizeof(devname), "/dev/cpu%d", cpu_num);
133+
fd = open(devname, O_RDWR);
134+
if (fd < 0) {
135+
printf("Cannot open %s: errno = %d\n", devname, get_errno());
136+
return -get_errno();
137+
}
138+
139+
if (ioctl(fd, IOC_CPU_DISABLE, 1) < 0) {
140+
printf("IOC_CPU_DISABLE ioctl failed for %s : errno = %d\n", devname, get_errno());
141+
close(fd);
142+
return -get_errno();
143+
}
144+
printf("cpu%d successfully disabled\n", cpu_num);
145+
146+
if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
147+
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
148+
close(fd);
149+
return -get_errno();
150+
}
151+
printf("state: %d (%s)\n", state, cpu_states[state]);
152+
close(fd);
153+
return 0;
154+
}
155+
156+
static int cpucontrol_cpu_status(int argc, char *argv[])
157+
{
158+
int fd, state;
159+
char devname[16];
160+
161+
for (u8 i = 1; i < CONFIG_SMP_NCPUS; i++) {
162+
snprintf(devname, sizeof(devname), "/dev/cpu%d", i);
163+
164+
fd = open(devname, O_RDWR);
165+
if (fd < 0) {
166+
printf("Cannot open %s: errno = %d\n", devname, get_errno());
167+
continue;
168+
}
169+
170+
if (ioctl(fd, IOC_CPU_GET_STATE, &state) < 0) {
171+
printf("IOC_CPU_GET_STATE ioctl failed for %s : errno = %d\n", devname, get_errno());
172+
close(fd);
173+
continue;
174+
}
175+
176+
printf("cpu state for cpu%d: %d (%s)\n", i, state, cpu_states[state]);
177+
close(fd);
178+
}
179+
return 0;
180+
}
181+
182+
static int cpucontrol_help(int argc, char *argv[])
183+
{
184+
printf("CPU Control Commands:\n");
185+
printf(" cpuctrl on <cpu_id> - Power on specified CPU\n");
186+
printf(" cpuctrl off <cpu_id> - Power off specified CPU\n");
187+
printf(" cpuctrl status - Show status of all secondary CPUs\n");
188+
printf(" cpuctrl help - Show this help message\n");
189+
printf("\nExamples:\n");
190+
printf(" cpuctrl on 1 - Power on CPU1\n");
191+
printf(" cpuctrl off 1 - Power off CPU1\n");
192+
printf(" cpuctrl status - Show all CPU states\n");
193+
printf("\nNote: CPU control operations can only be performed from CPU0\n");
194+
return 0;
195+
}
196+
197+
static int cpucontrol_main(int argc, char *argv[])
198+
{
199+
if (argc < 2) {
200+
return cpucontrol_help(argc, argv);
201+
}
202+
203+
if (strcmp(argv[1], "on") == 0) {
204+
return cpucontrol_cpu_on(argc, argv);
205+
} else if (strcmp(argv[1], "off") == 0) {
206+
return cpucontrol_cpu_off(argc, argv);
207+
} else if (strcmp(argv[1], "help") == 0) {
208+
return cpucontrol_help(argc, argv);
209+
} else if (strcmp(argv[1], "status") == 0) {
210+
return cpucontrol_cpu_status(argc, argv);
211+
} else {
212+
printf("Unknown subcommand: %s\n", argv[1]);
213+
return cpucontrol_help(argc, argv);
214+
}
215+
}
216+
217+
/****************************************************************************
218+
* Public Functions
219+
****************************************************************************/
220+
221+
void cpucontrol_register_cmds(void)
222+
{
223+
/* Register the CPU control command during system initialization */
224+
tash_cmd_install("cpuctrl", cpucontrol_main, TASH_EXECMD_ASYNC);
225+
}

apps/system/init/init.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,10 @@
7373
extern void iotjs_register_cmds(void);
7474
#endif
7575

76+
#ifdef CONFIG_SYSTEM_CPUCONTROL
77+
extern void cpucontrol_register_cmds(void);
78+
#endif
79+
7680
/****************************************************************************
7781
* Pravite Functions
7882
****************************************************************************/
@@ -107,6 +111,10 @@ static void tash_register_cmds(void)
107111
#ifdef CONFIG_DEBUG_SYSTEM_APP
108112
sysdbgapp_init();
109113
#endif
114+
115+
#ifdef CONFIG_SYSTEM_CPUCONTROL
116+
cpucontrol_register_cmds();
117+
#endif
110118
}
111119
#endif /* CONFIG_TASH */
112120

0 commit comments

Comments
 (0)