Skip to content

Commit 8538d0f

Browse files
automerging branch "kernel.org-palmer-linux/wip-timer" into "riscv-all"
# Conflicts: # arch/riscv/Kconfig
2 parents 4b52002 + e56e8bd commit 8538d0f

File tree

15 files changed

+328
-25
lines changed

15 files changed

+328
-25
lines changed

arch/riscv/Kconfig

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,16 @@ config RISCV
1515
select OF_EARLY_FLATTREE
1616
select OF_IRQ
1717
select ARCH_WANT_FRAME_POINTERS
18+
select ARCH_SUPPORTS_INT128
1819
select CLONE_BACKWARDS
1920
select COMMON_CLK
2021
select DMA_DIRECT_OPS
2122
select GENERIC_CLOCKEVENTS
22-
select GENERIC_CPU_DEVICES
2323
select GENERIC_IRQ_SHOW
2424
select GENERIC_PCI_IOMAP
2525
select GENERIC_STRNCPY_FROM_USER
2626
select GENERIC_STRNLEN_USER
27+
select GENERIC_SCHED_CLOCK
2728
select GENERIC_SMP_IDLE_THREAD
2829
select GENERIC_ATOMIC64 if !64BIT || !RISCV_ISA_A
2930
select HAVE_ARCH_SECCOMP_FILTER
@@ -186,6 +187,16 @@ config NR_CPUS
186187
depends on SMP
187188
default "8"
188189

190+
config HOTPLUG_CPU
191+
bool "Support for hot-pluggable CPUs"
192+
select GENERIC_IRQ_MIGRATION
193+
help
194+
195+
Say Y here to experiment with turning CPUs off and on. CPUs
196+
can be controlled through /sys/devices/system/cpu.
197+
198+
Say N if you want to disable CPU hotplug.
199+
189200
choice
190201
prompt "CPU Tuning"
191202
default TUNE_GENERIC

arch/riscv/include/asm/csr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
/* Interrupt Enable and Interrupt Pending flags */
5555
#define SIE_SSIE _AC(0x00000002, UL) /* Software Interrupt Enable */
5656
#define SIE_STIE _AC(0x00000020, UL) /* Timer Interrupt Enable */
57+
#define SIE_SEIE _AC(0x000000200, UL) /* External Interrupt Enable */
5758

5859
#define EXC_INST_MISALIGNED 0
5960
#define EXC_INST_ACCESS 1

arch/riscv/include/asm/smp.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424

2525
#ifdef CONFIG_SMP
2626

27-
/* SMP initialization hook for setup_arch */
28-
void __init init_clockevent(void);
29-
3027
/* SMP initialization hook for setup_arch */
3128
void __init setup_smp(void);
3229

@@ -47,6 +44,12 @@ void arch_send_call_function_single_ipi(int cpu);
4744
/* Interprocessor interrupt handler */
4845
irqreturn_t handle_ipi(void);
4946

47+
#ifdef CONFIG_HOTPLUG_CPU
48+
extern int __cpu_disable(void);
49+
extern void __cpu_die(unsigned int cpu);
50+
extern void cpu_play_dead(void);
51+
extern void boot_sec_cpu(void);
52+
#endif
5053
#endif /* CONFIG_SMP */
5154

5255
#endif /* _ASM_RISCV_SMP_H */

arch/riscv/include/asm/timex.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
typedef unsigned long cycles_t;
2020

21-
static inline cycles_t get_cycles_inline(void)
21+
static inline notrace cycles_t get_cycles_inline(void)
2222
{
2323
cycles_t n;
2424

@@ -30,12 +30,12 @@ static inline cycles_t get_cycles_inline(void)
3030
#define get_cycles get_cycles_inline
3131

3232
#ifdef CONFIG_64BIT
33-
static inline uint64_t get_cycles64(void)
33+
static inline notrace uint64_t get_cycles64(void)
3434
{
3535
return get_cycles();
3636
}
3737
#else
38-
static inline uint64_t get_cycles64(void)
38+
static inline notrace uint64_t get_cycles64(void)
3939
{
4040
u32 lo, hi, tmp;
4141
__asm__ __volatile__ (

arch/riscv/kernel/head.S

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,18 @@ relocate:
149149
j .Lsecondary_park
150150
END(_start)
151151

152+
.section .text
153+
.global boot_sec_cpu
154+
155+
boot_sec_cpu:
156+
/* clear all pending flags */
157+
csrw sip, zero
158+
/* Mask all interrupts */
159+
csrw sie, zero
160+
fence
161+
162+
tail smp_callin
163+
152164
__PAGE_ALIGNED_BSS
153165
/* Empty zero page */
154166
.balign PAGE_SIZE

arch/riscv/kernel/process.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,13 @@ void arch_cpu_idle(void)
4242
local_irq_enable();
4343
}
4444

45+
#ifdef CONFIG_HOTPLUG_CPU
46+
void arch_cpu_idle_dead(void)
47+
{
48+
cpu_play_dead();
49+
}
50+
#endif
51+
4552
void show_regs(struct pt_regs *regs)
4653
{
4754
show_regs_print_info(KERN_DEFAULT);

arch/riscv/kernel/setup.c

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ EXPORT_SYMBOL(empty_zero_page);
8181

8282
/* The lucky hart to first increment this variable will boot the other cores */
8383
atomic_t hart_lottery;
84+
static DEFINE_PER_CPU(struct cpu, cpu_devices);
8485

8586
#ifdef CONFIG_BLK_DEV_INITRD
8687
static void __init setup_initrd(void)
@@ -249,6 +250,22 @@ void __init setup_arch(char **cmdline_p)
249250
riscv_fill_hwcap();
250251
}
251252

253+
static int __init topology_init(void)
254+
{
255+
int i;
256+
257+
for_each_possible_cpu(i) {
258+
struct cpu *cpu = &per_cpu(cpu_devices, i);
259+
#ifdef CONFIG_HOTPLUG_CPU
260+
cpu->hotpluggable = 1;
261+
#endif
262+
register_cpu(cpu, i);
263+
}
264+
265+
return 0;
266+
}
267+
subsys_initcall(topology_init);
268+
252269
static int __init riscv_device_init(void)
253270
{
254271
return of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);

arch/riscv/kernel/smpboot.c

Lines changed: 67 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/irq.h>
3131
#include <linux/of.h>
3232
#include <linux/sched/task_stack.h>
33+
#include <linux/sched/hotplug.h>
3334
#include <asm/irq.h>
3435
#include <asm/mmu_context.h>
3536
#include <asm/tlbflush.h>
@@ -82,20 +83,84 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
8283
__cpu_up_stack_pointer[cpu] = task_stack_page(tidle) + THREAD_SIZE;
8384
__cpu_up_task_pointer[cpu] = tidle;
8485

86+
arch_send_call_function_single_ipi(cpu);
8587
while (!cpu_online(cpu))
8688
cpu_relax();
8789

90+
pr_notice("CPU%u: online\n", cpu);
8891
return 0;
8992
}
9093

9194
void __init smp_cpus_done(unsigned int max_cpus)
9295
{
9396
}
9497

98+
#ifdef CONFIG_HOTPLUG_CPU
99+
/*
100+
* __cpu_disable runs on the processor to be shutdown.
101+
*/
102+
int __cpu_disable(void)
103+
{
104+
unsigned int cpu = smp_processor_id();
105+
int ret;
106+
107+
set_cpu_online(cpu, false);
108+
irq_migrate_all_off_this_cpu();
109+
110+
return 0;
111+
}
112+
/*
113+
* called on the thread which is asking for a CPU to be shutdown -
114+
* waits until shutdown has completed, or it is timed out.
115+
*/
116+
void __cpu_die(unsigned int cpu)
117+
{
118+
int err = 0;
119+
120+
if (!cpu_wait_death(cpu, 5)) {
121+
pr_err("CPU %u: didn't die\n", cpu);
122+
return;
123+
}
124+
pr_notice("CPU%u: shutdown\n", cpu);
125+
}
126+
/*
127+
* Called from the idle thread for the CPU which has been shutdown.
128+
*/
129+
void cpu_play_dead(void)
130+
{
131+
int sipval, sieval, scauseval;
132+
int cpu = smp_processor_id();
133+
134+
idle_task_exit();
135+
136+
(void)cpu_report_death();
137+
138+
/* Do not disable software interrupt to restart cpu after WFI */
139+
csr_clear(sie, SIE_STIE | SIE_SEIE);
140+
141+
/* clear all pending flags */
142+
csr_write(sip, 0);
143+
/* clear any previous scause data */
144+
csr_write(scause, 0);
145+
146+
do {
147+
wait_for_interrupt();
148+
sipval = csr_read(sip);
149+
sieval = csr_read(sie);
150+
scauseval = csr_read(scause);
151+
/* only break if wfi returns for an enabled interrupt */
152+
} while ((sipval & sieval) == 0 &&
153+
scauseval != INTERRUPT_CAUSE_SOFTWARE);
154+
155+
boot_sec_cpu();
156+
}
157+
158+
159+
#endif
95160
/*
96161
* C entry point for a secondary processor.
97162
*/
98-
asmlinkage void __init smp_callin(void)
163+
asmlinkage void smp_callin(void)
99164
{
100165
struct mm_struct *mm = &init_mm;
101166

@@ -104,9 +169,8 @@ asmlinkage void __init smp_callin(void)
104169
current->active_mm = mm;
105170

106171
trap_init();
107-
init_clockevent();
108172
notify_cpu_starting(smp_processor_id());
109-
set_cpu_online(smp_processor_id(), 1);
173+
set_cpu_online(smp_processor_id(), true);
110174
local_flush_tlb_all();
111175
local_irq_enable();
112176
preempt_disable();

arch/riscv/kernel/time.c

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -35,27 +35,34 @@ void riscv_timer_interrupt(void)
3535
*/
3636
struct clock_event_device *evdev = this_cpu_ptr(&riscv_clock_event);
3737

38+
/*
39+
* There are no direct SBI calls to clear pending timer interrupt bit.
40+
* Disable timer interrupt to ignore pending interrupt until next
41+
* interrupt.
42+
*/
43+
csr_clear(sie, SIE_STIE);
3844
evdev->event_handler(evdev);
3945
#endif
4046
}
4147

42-
void __init init_clockevent(void)
43-
{
44-
timer_probe();
45-
csr_set(sie, SIE_STIE);
46-
}
47-
48-
void __init time_init(void)
48+
static long __init timebase_frequency(void)
4949
{
5050
struct device_node *cpu;
5151
u32 prop;
5252

5353
cpu = of_find_node_by_path("/cpus");
54-
if (!cpu || of_property_read_u32(cpu, "timebase-frequency", &prop))
55-
panic(KERN_WARNING "RISC-V system with no 'timebase-frequency' in DTS\n");
56-
riscv_timebase = prop;
54+
if (cpu && !of_property_read_u32(cpu, "timebase-frequency", &prop))
55+
return prop;
56+
cpu = of_find_node_by_path("/cpus/cpu@0");
57+
if (cpu && !of_property_read_u32(cpu, "timebase-frequency", &prop))
58+
return prop;
5759

58-
lpj_fine = riscv_timebase / HZ;
60+
panic(KERN_WARNING "RISC-V system with no 'timebase-frequency' in DTS\n");
61+
}
5962

60-
init_clockevent();
63+
void __init time_init(void)
64+
{
65+
riscv_timebase = timebase_frequency();
66+
lpj_fine = riscv_timebase / HZ;
67+
timer_probe();
6168
}

arch/riscv/kernel/traps.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ int is_valid_bugaddr(unsigned long pc)
166166
}
167167
#endif /* CONFIG_GENERIC_BUG */
168168

169-
void __init trap_init(void)
169+
void trap_init(void)
170170
{
171171
/*
172172
* Set sup0 scratch register to 0, indicating to exception vector
@@ -175,6 +175,6 @@ void __init trap_init(void)
175175
csr_write(sscratch, 0);
176176
/* Set the exception vector address */
177177
csr_write(stvec, &handle_exception);
178-
/* Enable all interrupts */
179-
csr_write(sie, -1);
178+
/* Enable all interrupts but timer interrupt*/
179+
csr_set(sie, SIE_SSIE | SIE_SEIE);
180180
}

0 commit comments

Comments
 (0)