2006-03-27 13:14:30 +04:00
/*
2007-10-16 12:26:54 +04:00
* Copyright ( C ) 2000 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-17 02:20:36 +04:00
* Licensed under the GPL
*/
2012-10-08 06:27:32 +04:00
# include <linux/percpu.h>
# include <asm/pgalloc.h>
# include <asm/tlb.h>
2005-04-17 02:20:36 +04:00
# ifdef CONFIG_SMP
2012-10-08 06:27:32 +04:00
# include <linux/sched.h>
# include <linux/module.h>
# include <linux/threads.h>
# include <linux/interrupt.h>
# include <linux/err.h>
# include <linux/hardirq.h>
# include <asm/smp.h>
# include <asm/processor.h>
# include <asm/spinlock.h>
# include <kern.h>
# include <irq_user.h>
# include <os.h>
2005-04-17 02:20:36 +04:00
/* Per CPU bogomips and other parameters
* The only piece used here is the ipi pipe , which is set before SMP is
* started and never changed .
*/
struct cpuinfo_um cpu_data [ NR_CPUS ] ;
/* A statistic, can be a little off */
int num_reschedules_sent = 0 ;
/* Not changed after boot */
struct task_struct * idle_threads [ NR_CPUS ] ;
void smp_send_reschedule ( int cpu )
{
2007-05-07 01:51:43 +04:00
os_write_file ( cpu_data [ cpu ] . ipi_pipe [ 1 ] , " R " , 1 ) ;
2005-04-17 02:20:36 +04:00
num_reschedules_sent + + ;
}
void smp_send_stop ( void )
{
int i ;
printk ( KERN_INFO " Stopping all CPUs... " ) ;
2007-10-16 12:26:54 +04:00
for ( i = 0 ; i < num_online_cpus ( ) ; i + + ) {
if ( i = = current_thread - > cpu )
2005-04-17 02:20:36 +04:00
continue ;
2007-05-07 01:51:43 +04:00
os_write_file ( cpu_data [ i ] . ipi_pipe [ 1 ] , " S " , 1 ) ;
2005-04-17 02:20:36 +04:00
}
2008-02-05 09:31:14 +03:00
printk ( KERN_CONT " done \n " ) ;
2005-04-17 02:20:36 +04:00
}
static cpumask_t smp_commenced_mask = CPU_MASK_NONE ;
static cpumask_t cpu_callin_map = CPU_MASK_NONE ;
static int idle_proc ( void * cpup )
{
int cpu = ( int ) cpup , err ;
err = os_pipe ( cpu_data [ cpu ] . ipi_pipe , 1 , 1 ) ;
2007-10-16 12:26:54 +04:00
if ( err < 0 )
2005-04-17 02:20:36 +04:00
panic ( " CPU#%d failed to create IPI pipe, err = %d " , cpu , - err ) ;
2008-02-05 09:31:04 +03:00
os_set_fd_async ( cpu_data [ cpu ] . ipi_pipe [ 0 ] ) ;
2006-03-27 13:14:30 +04:00
2005-04-17 02:20:36 +04:00
wmb ( ) ;
if ( cpu_test_and_set ( cpu , cpu_callin_map ) ) {
2007-10-16 12:26:54 +04:00
printk ( KERN_ERR " huh, CPU#%d already present?? \n " , cpu ) ;
2005-04-17 02:20:36 +04:00
BUG ( ) ;
}
while ( ! cpu_isset ( cpu , smp_commenced_mask ) )
cpu_relax ( ) ;
2008-09-07 18:57:22 +04:00
notify_cpu_starting ( cpu ) ;
2012-03-29 09:08:30 +04:00
set_cpu_online ( cpu , true ) ;
2005-04-17 02:20:36 +04:00
default_idle ( ) ;
2007-05-07 01:51:41 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
static struct task_struct * idle_thread ( int cpu )
{
struct task_struct * new_task ;
2007-05-07 01:51:41 +04:00
current - > thread . request . u . thread . proc = idle_proc ;
current - > thread . request . u . thread . arg = ( void * ) cpu ;
2005-04-17 02:20:36 +04:00
new_task = fork_idle ( cpu ) ;
2007-10-16 12:26:54 +04:00
if ( IS_ERR ( new_task ) )
2005-04-17 02:20:36 +04:00
panic ( " copy_process failed in idle_thread, error = %ld " ,
PTR_ERR ( new_task ) ) ;
2006-03-27 13:14:30 +04:00
cpu_tasks [ cpu ] = ( ( struct cpu_task )
2005-04-17 02:20:36 +04:00
{ . pid = new_task - > thread . mode . tt . extern_pid ,
. task = new_task } ) ;
idle_threads [ cpu ] = new_task ;
uml: throw out CONFIG_MODE_TT
This patchset throws out tt mode, which has been non-functional for a while.
This is done in phases, interspersed with code cleanups on the affected files.
The removal is done as follows:
remove all code, config options, and files which depend on
CONFIG_MODE_TT
get rid of the CHOOSE_MODE macro, which decided whether to
call tt-mode or skas-mode code, and replace invocations with their
skas portions
replace all now-trivial procedures with their skas equivalents
There are now a bunch of now-redundant pieces of data structures, including
mode-specific pieces of the thread structure, pt_regs, and mm_context. These
are all replaced with their skas-specific contents.
As part of the ongoing style compliance project, I made a style pass over all
files that were changed. There are three such patches, one for each phase,
covering the files affected by that phase but no later ones.
I noticed that we weren't freeing the LDT state associated with a process when
it exited, so that's fixed in one of the later patches.
The last patch is a tidying patch which I've had for a while, but which caused
inexplicable crashes under tt mode. Since that is no longer a problem, this
can now go in.
This patch:
Start getting rid of tt mode support.
This patch throws out CONFIG_MODE_TT and all config options, code, and files
which depend on it.
CONFIG_MODE_SKAS is gone and everything that depends on it is included
unconditionally.
The few changed lines are in re-written Kconfig help, lines which needed
something skas-related removed from them, and a few more which weren't
strictly deletions.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2007-10-16 12:26:50 +04:00
panic ( " skas mode doesn't support SMP " ) ;
2007-05-07 01:51:41 +04:00
return new_task ;
2005-04-17 02:20:36 +04:00
}
void smp_prepare_cpus ( unsigned int maxcpus )
{
struct task_struct * idle ;
unsigned long waittime ;
int err , cpu , me = smp_processor_id ( ) ;
int i ;
for ( i = 0 ; i < ncpus ; + + i )
2009-09-24 19:34:48 +04:00
set_cpu_possible ( i , true ) ;
2005-04-17 02:20:36 +04:00
2012-03-29 09:08:30 +04:00
set_cpu_online ( me , true ) ;
2005-04-17 02:20:36 +04:00
cpu_set ( me , cpu_callin_map ) ;
err = os_pipe ( cpu_data [ me ] . ipi_pipe , 1 , 1 ) ;
2007-10-16 12:26:54 +04:00
if ( err < 0 )
2005-04-17 02:20:36 +04:00
panic ( " CPU#0 failed to create IPI pipe, errno = %d " , - err ) ;
2008-02-05 09:31:04 +03:00
os_set_fd_async ( cpu_data [ me ] . ipi_pipe [ 0 ] ) ;
2005-04-17 02:20:36 +04:00
2007-10-16 12:26:54 +04:00
for ( cpu = 1 ; cpu < ncpus ; cpu + + ) {
printk ( KERN_INFO " Booting processor %d... \n " , cpu ) ;
2006-03-27 13:14:30 +04:00
2005-04-17 02:20:36 +04:00
idle = idle_thread ( cpu ) ;
init_idle ( idle , cpu ) ;
waittime = 200000000 ;
while ( waittime - - & & ! cpu_isset ( cpu , cpu_callin_map ) )
cpu_relax ( ) ;
2008-02-05 09:31:14 +03:00
printk ( KERN_INFO " %s \n " ,
cpu_isset ( cpu , cpu_calling_map ) ? " done " : " failed " ) ;
2005-04-17 02:20:36 +04:00
}
}
void smp_prepare_boot_cpu ( void )
{
2012-03-29 09:08:30 +04:00
set_cpu_online ( smp_processor_id ( ) , true ) ;
2005-04-17 02:20:36 +04:00
}
2012-04-20 17:05:42 +04:00
int __cpu_up ( unsigned int cpu , struct task_struct * tidle )
2005-04-17 02:20:36 +04:00
{
cpu_set ( cpu , smp_commenced_mask ) ;
2012-03-29 09:08:30 +04:00
while ( ! cpu_online ( cpu ) )
2005-04-17 02:20:36 +04:00
mb ( ) ;
2007-05-07 01:51:41 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
int setup_profiling_timer ( unsigned int multiplier )
{
printk ( KERN_INFO " setup_profiling_timer \n " ) ;
2007-05-07 01:51:41 +04:00
return 0 ;
2005-04-17 02:20:36 +04:00
}
void smp_call_function_slave ( int cpu ) ;
void IPI_handler ( int cpu )
{
unsigned char c ;
int fd ;
fd = cpu_data [ cpu ] . ipi_pipe [ 0 ] ;
2007-05-07 01:51:43 +04:00
while ( os_read_file ( fd , & c , 1 ) = = 1 ) {
2005-04-17 02:20:36 +04:00
switch ( c ) {
case ' C ' :
smp_call_function_slave ( cpu ) ;
break ;
case ' R ' :
2011-04-05 19:23:39 +04:00
scheduler_ipi ( ) ;
2005-04-17 02:20:36 +04:00
break ;
case ' S ' :
2007-10-16 12:26:54 +04:00
printk ( KERN_INFO " CPU#%d stopping \n " , cpu ) ;
while ( 1 )
2005-04-17 02:20:36 +04:00
pause ( ) ;
break ;
default :
2007-10-16 12:26:54 +04:00
printk ( KERN_ERR " CPU#%d received unknown IPI [%c]! \n " ,
cpu , c ) ;
2005-04-17 02:20:36 +04:00
break ;
}
}
}
int hard_smp_processor_id ( void )
{
2007-05-07 01:51:41 +04:00
return pid_to_processor_id ( os_getpid ( ) ) ;
2005-04-17 02:20:36 +04:00
}
static DEFINE_SPINLOCK ( call_lock ) ;
static atomic_t scf_started ;
static atomic_t scf_finished ;
static void ( * func ) ( void * info ) ;
static void * info ;
void smp_call_function_slave ( int cpu )
{
atomic_inc ( & scf_started ) ;
( * func ) ( info ) ;
atomic_inc ( & scf_finished ) ;
}
2008-06-06 13:18:06 +04:00
int smp_call_function ( void ( * _func ) ( void * info ) , void * _info , int wait )
2005-04-17 02:20:36 +04:00
{
int cpus = num_online_cpus ( ) - 1 ;
int i ;
if ( ! cpus )
return 0 ;
/* Can deadlock when called with interrupts disabled */
WARN_ON ( irqs_disabled ( ) ) ;
spin_lock_bh ( & call_lock ) ;
atomic_set ( & scf_started , 0 ) ;
atomic_set ( & scf_finished , 0 ) ;
func = _func ;
info = _info ;
for_each_online_cpu ( i )
2007-05-07 01:51:43 +04:00
os_write_file ( cpu_data [ i ] . ipi_pipe [ 1 ] , " C " , 1 ) ;
2005-04-17 02:20:36 +04:00
while ( atomic_read ( & scf_started ) ! = cpus )
barrier ( ) ;
if ( wait )
while ( atomic_read ( & scf_finished ) ! = cpus )
barrier ( ) ;
spin_unlock_bh ( & call_lock ) ;
return 0 ;
}
# endif