diff options
Diffstat (limited to 'arch/xtensa/kernel')
-rw-r--r-- | arch/xtensa/kernel/head.S | 5 | ||||
-rw-r--r-- | arch/xtensa/kernel/process.c | 6 | ||||
-rw-r--r-- | arch/xtensa/kernel/smp.c | 79 | ||||
-rw-r--r-- | arch/xtensa/kernel/syscalls/syscall.tbl | 78 | ||||
-rw-r--r-- | arch/xtensa/kernel/time.c | 55 | ||||
-rw-r--r-- | arch/xtensa/kernel/traps.c | 5 |
6 files changed, 134 insertions, 94 deletions
diff --git a/arch/xtensa/kernel/head.S b/arch/xtensa/kernel/head.S index da08e75100ab..7f009719304e 100644 --- a/arch/xtensa/kernel/head.S +++ b/arch/xtensa/kernel/head.S @@ -276,12 +276,13 @@ should_never_return: movi a2, cpu_start_ccount 1: + memw l32i a3, a2, 0 beqi a3, 0, 1b movi a3, 0 s32i a3, a2, 0 - memw 1: + memw l32i a3, a2, 0 beqi a3, 0, 1b wsr a3, ccount @@ -317,11 +318,13 @@ ENTRY(cpu_restart) rsr a0, prid neg a2, a0 movi a3, cpu_start_id + memw s32i a2, a3, 0 #if XCHAL_DCACHE_IS_WRITEBACK dhwbi a3, 0 #endif 1: + memw l32i a2, a3, 0 dhi a3, 0 bne a2, a0, 1b diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 74969a437a37..db278a9e80c7 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c @@ -52,8 +52,6 @@ extern void ret_from_fork(void); extern void ret_from_kernel_thread(void); -struct task_struct *current_set[NR_CPUS] = {&init_task, }; - void (*pm_power_off)(void) = NULL; EXPORT_SYMBOL(pm_power_off); @@ -321,8 +319,8 @@ unsigned long get_wchan(struct task_struct *p) /* Stack layout: sp-4: ra, sp-3: sp' */ - pc = MAKE_PC_FROM_RA(*(unsigned long*)sp - 4, sp); - sp = *(unsigned long *)sp - 3; + pc = MAKE_PC_FROM_RA(SPILL_SLOT(sp, 0), sp); + sp = SPILL_SLOT(sp, 1); } while (count++ < 16); return 0; } diff --git a/arch/xtensa/kernel/smp.c b/arch/xtensa/kernel/smp.c index 932d64689bac..3699d6d3e479 100644 --- a/arch/xtensa/kernel/smp.c +++ b/arch/xtensa/kernel/smp.c @@ -83,7 +83,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) { unsigned i; - for (i = 0; i < max_cpus; ++i) + for_each_possible_cpu(i) set_cpu_present(i, true); } @@ -96,6 +96,11 @@ void __init smp_init_cpus(void) pr_info("%s: Core Count = %d\n", __func__, ncpus); pr_info("%s: Core Id = %d\n", __func__, core_id); + if (ncpus > NR_CPUS) { + ncpus = NR_CPUS; + pr_info("%s: limiting core count by %d\n", __func__, ncpus); + } + for (i = 0; i < ncpus; ++i) set_cpu_possible(i, true); } @@ -195,9 +200,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts) int i; #ifdef CONFIG_HOTPLUG_CPU - cpu_start_id = cpu; - system_flush_invalidate_dcache_range( - (unsigned long)&cpu_start_id, sizeof(cpu_start_id)); + WRITE_ONCE(cpu_start_id, cpu); + /* Pairs with the third memw in the cpu_restart */ + mb(); + system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id, + sizeof(cpu_start_id)); #endif smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1); @@ -206,18 +213,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts) ccount = get_ccount(); while (!ccount); - cpu_start_ccount = ccount; + WRITE_ONCE(cpu_start_ccount, ccount); - while (time_before(jiffies, timeout)) { + do { + /* + * Pairs with the first two memws in the + * .Lboot_secondary. + */ mb(); - if (!cpu_start_ccount) - break; - } + ccount = READ_ONCE(cpu_start_ccount); + } while (ccount && time_before(jiffies, timeout)); - if (cpu_start_ccount) { + if (ccount) { smp_call_function_single(0, mx_cpu_stop, - (void *)cpu, 1); - cpu_start_ccount = 0; + (void *)cpu, 1); + WRITE_ONCE(cpu_start_ccount, 0); return -EIO; } } @@ -237,6 +247,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n", __func__, cpu, idle, start_info.stack); + init_completion(&cpu_running); ret = boot_secondary(cpu, idle); if (ret == 0) { wait_for_completion_timeout(&cpu_running, @@ -298,8 +309,10 @@ void __cpu_die(unsigned int cpu) unsigned long timeout = jiffies + msecs_to_jiffies(1000); while (time_before(jiffies, timeout)) { system_invalidate_dcache_range((unsigned long)&cpu_start_id, - sizeof(cpu_start_id)); - if (cpu_start_id == -cpu) { + sizeof(cpu_start_id)); + /* Pairs with the second memw in the cpu_restart */ + mb(); + if (READ_ONCE(cpu_start_id) == -cpu) { platform_cpu_kill(cpu); return; } @@ -359,8 +372,7 @@ static void send_ipi_message(const struct cpumask *callmask, unsigned long mask = 0; for_each_cpu(index, callmask) - if (index != smp_processor_id()) - mask |= 1 << index; + mask |= 1 << index; set_er(mask, MIPISET(msg_id)); } @@ -399,22 +411,31 @@ irqreturn_t ipi_interrupt(int irq, void *dev_id) { unsigned int cpu = smp_processor_id(); struct ipi_data *ipi = &per_cpu(ipi_data, cpu); - unsigned int msg; - unsigned i; - msg = get_er(MIPICAUSE(cpu)); - for (i = 0; i < IPI_MAX; i++) - if (msg & (1 << i)) { - set_er(1 << i, MIPICAUSE(cpu)); - ++ipi->ipi_count[i]; + for (;;) { + unsigned int msg; + + msg = get_er(MIPICAUSE(cpu)); + set_er(msg, MIPICAUSE(cpu)); + + if (!msg) + break; + + if (msg & (1 << IPI_CALL_FUNC)) { + ++ipi->ipi_count[IPI_CALL_FUNC]; + generic_smp_call_function_interrupt(); + } + + if (msg & (1 << IPI_RESCHEDULE)) { + ++ipi->ipi_count[IPI_RESCHEDULE]; + scheduler_ipi(); } - if (msg & (1 << IPI_RESCHEDULE)) - scheduler_ipi(); - if (msg & (1 << IPI_CALL_FUNC)) - generic_smp_call_function_interrupt(); - if (msg & (1 << IPI_CPU_STOP)) - ipi_cpu_stop(cpu); + if (msg & (1 << IPI_CPU_STOP)) { + ++ipi->ipi_count[IPI_CPU_STOP]; + ipi_cpu_stop(cpu); + } + } return IRQ_HANDLED; } diff --git a/arch/xtensa/kernel/syscalls/syscall.tbl b/arch/xtensa/kernel/syscalls/syscall.tbl index 69cf91b03b26..6af49929de85 100644 --- a/arch/xtensa/kernel/syscalls/syscall.tbl +++ b/arch/xtensa/kernel/syscalls/syscall.tbl @@ -72,8 +72,8 @@ 61 common fcntl64 sys_fcntl64 62 common fallocate sys_fallocate 63 common fadvise64_64 xtensa_fadvise64_64 -64 common utime sys_utime -65 common utimes sys_utimes +64 common utime sys_utime32 +65 common utimes sys_utimes_time32 66 common ioctl sys_ioctl 67 common fcntl sys_fcntl 68 common setxattr sys_setxattr @@ -103,7 +103,7 @@ 91 common madvise sys_madvise 92 common shmget sys_shmget 93 common shmat xtensa_shmat -94 common shmctl sys_shmctl +94 common shmctl sys_old_shmctl 95 common shmdt sys_shmdt # Socket Operations 96 common socket sys_socket @@ -174,15 +174,15 @@ 158 common capget sys_capget 159 common capset sys_capset 160 common ptrace sys_ptrace -161 common semtimedop sys_semtimedop +161 common semtimedop sys_semtimedop_time32 162 common semget sys_semget 163 common semop sys_semop -164 common semctl sys_semctl +164 common semctl sys_old_semctl 165 common available165 sys_ni_syscall 166 common msgget sys_msgget 167 common msgsnd sys_msgsnd 168 common msgrcv sys_msgrcv -169 common msgctl sys_msgctl +169 common msgctl sys_old_msgctl 170 common available170 sys_ni_syscall # File System 171 common umount2 sys_umount @@ -206,11 +206,11 @@ 188 common setrlimit sys_setrlimit 189 common getrlimit sys_getrlimit 190 common getrusage sys_getrusage -191 common futex sys_futex +191 common futex sys_futex_time32 192 common gettimeofday sys_gettimeofday 193 common settimeofday sys_settimeofday -194 common adjtimex sys_adjtimex -195 common nanosleep sys_nanosleep +194 common adjtimex sys_adjtimex_time32 +195 common nanosleep sys_nanosleep_time32 196 common getgroups sys_getgroups 197 common setgroups sys_setgroups 198 common sethostname sys_sethostname @@ -234,7 +234,7 @@ 215 common sched_getscheduler sys_sched_getscheduler 216 common sched_get_priority_max sys_sched_get_priority_max 217 common sched_get_priority_min sys_sched_get_priority_min -218 common sched_rr_get_interval sys_sched_rr_get_interval +218 common sched_rr_get_interval sys_sched_rr_get_interval_time32 219 common sched_yield sys_sched_yield 222 common available222 sys_ni_syscall # Signal Handling @@ -244,14 +244,14 @@ 226 common rt_sigaction sys_rt_sigaction 227 common rt_sigprocmask sys_rt_sigprocmask 228 common rt_sigpending sys_rt_sigpending -229 common rt_sigtimedwait sys_rt_sigtimedwait +229 common rt_sigtimedwait sys_rt_sigtimedwait_time32 230 common rt_sigqueueinfo sys_rt_sigqueueinfo 231 common rt_sigsuspend sys_rt_sigsuspend # Message 232 common mq_open sys_mq_open 233 common mq_unlink sys_mq_unlink -234 common mq_timedsend sys_mq_timedsend -235 common mq_timedreceive sys_mq_timedreceive +234 common mq_timedsend sys_mq_timedsend_time32 +235 common mq_timedreceive sys_mq_timedreceive_time32 236 common mq_notify sys_mq_notify 237 common mq_getsetattr sys_mq_getsetattr 238 common available238 sys_ni_syscall @@ -259,17 +259,17 @@ # IO 240 common io_destroy sys_io_destroy 241 common io_submit sys_io_submit -242 common io_getevents sys_io_getevents +242 common io_getevents sys_io_getevents_time32 243 common io_cancel sys_io_cancel -244 common clock_settime sys_clock_settime -245 common clock_gettime sys_clock_gettime -246 common clock_getres sys_clock_getres -247 common clock_nanosleep sys_clock_nanosleep +244 common clock_settime sys_clock_settime32 +245 common clock_gettime sys_clock_gettime32 +246 common clock_getres sys_clock_getres_time32 +247 common clock_nanosleep sys_clock_nanosleep_time32 # Timer 248 common timer_create sys_timer_create 249 common timer_delete sys_timer_delete -250 common timer_settime sys_timer_settime -251 common timer_gettime sys_timer_gettime +250 common timer_settime sys_timer_settime32 +251 common timer_gettime sys_timer_gettime32 252 common timer_getoverrun sys_timer_getoverrun # System 253 common reserved253 sys_ni_syscall @@ -291,8 +291,8 @@ 269 common tee sys_tee 270 common vmsplice sys_vmsplice 271 common available271 sys_ni_syscall -272 common pselect6 sys_pselect6 -273 common ppoll sys_ppoll +272 common pselect6 sys_pselect6_time32 +273 common ppoll sys_ppoll_time32 274 common epoll_pwait sys_epoll_pwait 275 common epoll_create1 sys_epoll_create1 276 common inotify_init sys_inotify_init @@ -316,9 +316,9 @@ 293 common linkat sys_linkat 294 common symlinkat sys_symlinkat 295 common readlinkat sys_readlinkat -296 common utimensat sys_utimensat +296 common utimensat sys_utimensat_time32 297 common fchownat sys_fchownat -298 common futimesat sys_futimesat +298 common futimesat sys_futimesat_time32 299 common fstatat64 sys_fstatat64 300 common fchmodat sys_fchmodat 301 common faccessat sys_faccessat @@ -327,14 +327,14 @@ 304 common signalfd sys_signalfd # 305 was timerfd 306 common eventfd sys_eventfd -307 common recvmmsg sys_recvmmsg +307 common recvmmsg sys_recvmmsg_time32 308 common setns sys_setns 309 common signalfd4 sys_signalfd4 310 common dup3 sys_dup3 311 common pipe2 sys_pipe2 312 common timerfd_create sys_timerfd_create -313 common timerfd_settime sys_timerfd_settime -314 common timerfd_gettime sys_timerfd_gettime +313 common timerfd_settime sys_timerfd_settime32 +314 common timerfd_gettime sys_timerfd_gettime32 315 common available315 sys_ni_syscall 316 common eventfd2 sys_eventfd2 317 common preadv sys_preadv @@ -349,7 +349,7 @@ 326 common sync_file_range2 sys_sync_file_range2 327 common perf_event_open sys_perf_event_open 328 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo -329 common clock_adjtime sys_clock_adjtime +329 common clock_adjtime sys_clock_adjtime32 330 common prlimit64 sys_prlimit64 331 common kcmp sys_kcmp 332 common finit_module sys_finit_module @@ -372,3 +372,25 @@ 349 common pkey_alloc sys_pkey_alloc 350 common pkey_free sys_pkey_free 351 common statx sys_statx +352 common rseq sys_rseq +# 353 through 402 are unassigned to sync up with generic numbers +403 common clock_gettime64 sys_clock_gettime +404 common clock_settime64 sys_clock_settime +405 common clock_adjtime64 sys_clock_adjtime +406 common clock_getres_time64 sys_clock_getres +407 common clock_nanosleep_time64 sys_clock_nanosleep +408 common timer_gettime64 sys_timer_gettime +409 common timer_settime64 sys_timer_settime +410 common timerfd_gettime64 sys_timerfd_gettime +411 common timerfd_settime64 sys_timerfd_settime +412 common utimensat_time64 sys_utimensat +413 common pselect6_time64 sys_pselect6 +414 common ppoll_time64 sys_ppoll +416 common io_pgetevents_time64 sys_io_pgetevents +417 common recvmmsg_time64 sys_recvmmsg +418 common mq_timedsend_time64 sys_mq_timedsend +419 common mq_timedreceive_time64 sys_mq_timedreceive +420 common semtimedop_time64 sys_semtimedop +421 common rt_sigtimedwait_time64 sys_rt_sigtimedwait +422 common futex_time64 sys_futex +423 common sched_rr_get_interval_time64 sys_sched_rr_get_interval diff --git a/arch/xtensa/kernel/time.c b/arch/xtensa/kernel/time.c index fd524a54d2ab..69db8c93c1f9 100644 --- a/arch/xtensa/kernel/time.c +++ b/arch/xtensa/kernel/time.c @@ -52,14 +52,11 @@ static struct clocksource ccount_clocksource = { .flags = CLOCK_SOURCE_IS_CONTINUOUS, }; -static int ccount_timer_set_next_event(unsigned long delta, - struct clock_event_device *dev); struct ccount_timer { struct clock_event_device evt; int irq_enabled; char name[24]; }; -static DEFINE_PER_CPU(struct ccount_timer, ccount_timer); static int ccount_timer_set_next_event(unsigned long delta, struct clock_event_device *dev) @@ -89,7 +86,7 @@ static int ccount_timer_shutdown(struct clock_event_device *evt) container_of(evt, struct ccount_timer, evt); if (timer->irq_enabled) { - disable_irq(evt->irq); + disable_irq_nosync(evt->irq); timer->irq_enabled = 0; } return 0; @@ -107,7 +104,30 @@ static int ccount_timer_set_oneshot(struct clock_event_device *evt) return 0; } -static irqreturn_t timer_interrupt(int irq, void *dev_id); +static DEFINE_PER_CPU(struct ccount_timer, ccount_timer) = { + .evt = { + .features = CLOCK_EVT_FEAT_ONESHOT, + .rating = 300, + .set_next_event = ccount_timer_set_next_event, + .set_state_shutdown = ccount_timer_shutdown, + .set_state_oneshot = ccount_timer_set_oneshot, + .tick_resume = ccount_timer_set_oneshot, + }, +}; + +static irqreturn_t timer_interrupt(int irq, void *dev_id) +{ + struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; + + set_linux_timer(get_linux_timer()); + evt->event_handler(evt); + + /* Allow platform to do something useful (Wdog). */ + platform_heartbeat(); + + return IRQ_HANDLED; +} + static struct irqaction timer_irqaction = { .handler = timer_interrupt, .flags = IRQF_TIMER, @@ -120,14 +140,8 @@ void local_timer_setup(unsigned cpu) struct clock_event_device *clockevent = &timer->evt; timer->irq_enabled = 1; - clockevent->name = timer->name; snprintf(timer->name, sizeof(timer->name), "ccount_clockevent_%u", cpu); - clockevent->features = CLOCK_EVT_FEAT_ONESHOT; - clockevent->rating = 300; - clockevent->set_next_event = ccount_timer_set_next_event; - clockevent->set_state_shutdown = ccount_timer_shutdown; - clockevent->set_state_oneshot = ccount_timer_set_oneshot; - clockevent->tick_resume = ccount_timer_set_oneshot; + clockevent->name = timer->name; clockevent->cpumask = cpumask_of(cpu); clockevent->irq = irq_create_mapping(NULL, LINUX_TIMER_INT); if (WARN(!clockevent->irq, "error: can't map timer irq")) @@ -190,23 +204,6 @@ void __init time_init(void) timer_probe(); } -/* - * The timer interrupt is called HZ times per second. - */ - -irqreturn_t timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = &this_cpu_ptr(&ccount_timer)->evt; - - set_linux_timer(get_linux_timer()); - evt->event_handler(evt); - - /* Allow platform to do something useful (Wdog). */ - platform_heartbeat(); - - return IRQ_HANDLED; -} - #ifndef CONFIG_GENERIC_CALIBRATE_DELAY void calibrate_delay(void) { diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c index e6fa55aa1ccb..454d53096bc9 100644 --- a/arch/xtensa/kernel/traps.c +++ b/arch/xtensa/kernel/traps.c @@ -420,16 +420,15 @@ void __init trap_init(void) /* Setup specific handlers. */ for(i = 0; dispatch_init_table[i].cause >= 0; i++) { - int fast = dispatch_init_table[i].fast; int cause = dispatch_init_table[i].cause; void *handler = dispatch_init_table[i].handler; if (fast == 0) set_handler(default_handler, cause, handler); - if (fast && fast & USER) + if ((fast & USER) != 0) set_handler(fast_user_handler, cause, handler); - if (fast && fast & KRNL) + if ((fast & KRNL) != 0) set_handler(fast_kernel_handler, cause, handler); } |