@ -536,15 +536,6 @@ do_boot_cpu(__u8 cpu)
& ~ ( voyager_extended_vic_processors
& voyager_allowed_boot_processors ) ;
/* For the 486, we can't use the 4Mb page table trick, so
* must map a region of memory */
# ifdef CONFIG_M486
int i ;
unsigned long * page_table_copies = ( unsigned long * )
__get_free_page ( GFP_KERNEL ) ;
# endif
pgd_t orig_swapper_pg_dir0 ;
/* This is an area in head.S which was used to set up the
* initial kernel stack . We need to alter this to give the
* booting CPU a new stack ( taken from its idle process ) */
@ -573,6 +564,8 @@ do_boot_cpu(__u8 cpu)
hijack_source . idt . Segment = ( start_phys_address > > 4 ) & 0xFFFF ;
cpucount + + ;
alternatives_smp_switch ( 1 ) ;
idle = fork_idle ( cpu ) ;
if ( IS_ERR ( idle ) )
panic ( " failed fork for CPU%d " , cpu ) ;
@ -595,24 +588,11 @@ do_boot_cpu(__u8 cpu)
VDEBUG ( ( " VOYAGER SMP: Booting CPU%d at 0x%lx[%x:%x], stack %p \n " , cpu ,
( unsigned long ) hijack_source . val , hijack_source . idt . Segment ,
hijack_source . idt . Offset , stack_start . esp ) ) ;
/* set the original swapper_pg_dir[0] to map 0 to 4Mb transparently
* ( so that the booting CPU can find start_32 */
orig_swapper_pg_dir0 = swapper_pg_dir [ 0 ] ;
# ifdef CONFIG_M486
if ( page_table_copies = = NULL )
panic ( " No free memory for 486 page tables \n " ) ;
for ( i = 0 ; i < PAGE_SIZE / sizeof ( unsigned long ) ; i + + )
page_table_copies [ i ] = ( i * PAGE_SIZE )
| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT ;
( ( unsigned long * ) swapper_pg_dir ) [ 0 ] =
( ( virt_to_phys ( page_table_copies ) ) & PAGE_MASK )
| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT ;
# else
( ( unsigned long * ) swapper_pg_dir ) [ 0 ] =
( virt_to_phys ( pg0 ) & PAGE_MASK )
| _PAGE_RW | _PAGE_USER | _PAGE_PRESENT ;
# endif
/* init lowmem identity mapping */
clone_pgd_range ( swapper_pg_dir , swapper_pg_dir + USER_PGD_PTRS ,
min_t ( unsigned long , KERNEL_PGD_PTRS , USER_PGD_PTRS ) ) ;
flush_tlb_all ( ) ;
if ( quad_boot ) {
printk ( " CPU %d: non extended Quad boot \n " , cpu ) ;
@ -655,11 +635,7 @@ do_boot_cpu(__u8 cpu)
udelay ( 100 ) ;
}
/* reset the page table */
swapper_pg_dir [ 0 ] = orig_swapper_pg_dir0 ;
local_flush_tlb ( ) ;
# ifdef CONFIG_M486
free_page ( ( unsigned long ) page_table_copies ) ;
# endif
zap_low_mappings ( ) ;
if ( cpu_booted_map ) {
VDEBUG ( ( " CPU%d: Booted successfully, back in CPU %d \n " ,
@ -1082,20 +1058,11 @@ smp_call_function_interrupt(void)
}
}
/* Call this function on all CPUs using the function_interrupt above
< func > The function to run . This must be fast and non - blocking .
< info > An arbitrary pointer to pass to the function .
< retry > If true , keep retrying until ready .
< wait > If true , wait until function has completed on other CPUs .
[ RETURNS ] 0 on success , else a negative status code . Does not return until
remote CPUs are nearly ready to execute < < func > > or are or have executed .
*/
int
smp_call_function ( void ( * func ) ( void * info ) , void * info , int retry ,
int wait )
static int
__smp_call_function_mask ( void ( * func ) ( void * info ) , void * info , int retry ,
int wait , __u32 mask )
{
struct call_data_struct data ;
__u32 mask = cpus_addr ( cpu_online_map ) [ 0 ] ;
mask & = ~ ( 1 < < smp_processor_id ( ) ) ;
@ -1116,7 +1083,7 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
call_data = & data ;
wmb ( ) ;
/* Send a message to all other CPUs and wait for them to respond */
send_CPI_allbutself ( VIC_CALL_FUNCTION_CPI ) ;
send_CPI ( mask , VIC_CALL_FUNCTION_CPI ) ;
/* Wait for response */
while ( data . started )
@ -1130,8 +1097,48 @@ smp_call_function (void (*func) (void *info), void *info, int retry,
return 0 ;
}
/* Call this function on all CPUs using the function_interrupt above
< func > The function to run . This must be fast and non - blocking .
< info > An arbitrary pointer to pass to the function .
< retry > If true , keep retrying until ready .
< wait > If true , wait until function has completed on other CPUs .
[ RETURNS ] 0 on success , else a negative status code . Does not return until
remote CPUs are nearly ready to execute < < func > > or are or have executed .
*/
int
smp_call_function ( void ( * func ) ( void * info ) , void * info , int retry ,
int wait )
{
__u32 mask = cpus_addr ( cpu_online_map ) [ 0 ] ;
return __smp_call_function_mask ( func , info , retry , wait , mask ) ;
}
EXPORT_SYMBOL ( smp_call_function ) ;
/*
* smp_call_function_single - Run a function on another CPU
* @ func : The function to run . This must be fast and non - blocking .
* @ info : An arbitrary pointer to pass to the function .
* @ nonatomic : Currently unused .
* @ wait : If true , wait until function has completed on other CPUs .
*
* Retrurns 0 on success , else a negative status code .
*
* Does not return until the remote CPU is nearly ready to execute < func >
* or is or has executed .
*/
int
smp_call_function_single ( int cpu , void ( * func ) ( void * info ) , void * info ,
int nonatomic , int wait )
{
__u32 mask = 1 < < cpu ;
return __smp_call_function_mask ( func , info , nonatomic , wait , mask ) ;
}
EXPORT_SYMBOL ( smp_call_function_single ) ;
/* Sorry about the name. In an APIC based system, the APICs
* themselves are programmed to send a timer interrupt . This is used
* by linux to reschedule the processor . Voyager doesn ' t have this ,