2006-01-08 01:01:31 -08:00
/*
2007-10-16 01:27:00 -07:00
* Copyright ( C ) 2000 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2005-04-16 15:20:36 -07:00
* Licensed under the GPL
*/
2008-02-04 22:31:14 -08:00
# include <linux/delay.h>
# include <linux/init.h>
# include <linux/mm.h>
# include <linux/module.h>
# include <linux/seq_file.h>
# include <linux/string.h>
# include <linux/utsname.h>
2012-05-03 09:03:00 +00:00
# include <linux/sched.h>
2008-02-04 22:31:14 -08:00
# include <asm/pgtable.h>
# include <asm/processor.h>
# include <asm/setup.h>
2012-10-08 03:27:32 +01:00
# include <as-layout.h>
# include <arch.h>
# include <init.h>
# include <kern.h>
# include <kern_util.h>
# include <mem_user.h>
# include <os.h>
2005-04-16 15:20:36 -07:00
# define DEFAULT_COMMAND_LINE "root=98:0"
2007-05-06 14:51:26 -07:00
/* Changed in add_arg and setup_arch, which run before SMP is started */
2007-02-12 00:54:26 -08:00
static char __initdata command_line [ COMMAND_LINE_SIZE ] = { 0 } ;
2005-04-16 15:20:36 -07:00
2007-02-12 00:54:26 -08:00
static void __init add_arg ( char * arg )
2005-04-16 15:20:36 -07:00
{
if ( strlen ( command_line ) + strlen ( arg ) + 1 > COMMAND_LINE_SIZE ) {
printf ( " add_arg: Too many command line arguments! \n " ) ;
exit ( 1 ) ;
}
2007-10-16 01:27:00 -07:00
if ( strlen ( command_line ) > 0 )
2005-04-16 15:20:36 -07:00
strcat ( command_line , " " ) ;
strcat ( command_line , arg ) ;
}
2007-05-06 14:51:26 -07:00
/*
* These fields are initialized at boot time and not changed .
* XXX This structure is used only in the non - SMP case . Maybe this
* should be moved to smp . c .
*/
struct cpuinfo_um boot_cpu_data = {
2005-04-16 15:20:36 -07:00
. loops_per_jiffy = 0 ,
. ipi_pipe = { - 1 , - 1 }
} ;
2012-05-03 09:03:00 +00:00
union thread_union cpu0_irqstack
__attribute__ ( ( __section__ ( " .data..init_irqstack " ) ) ) =
{ INIT_THREAD_INFO ( init_task ) } ;
2005-04-16 15:20:36 -07:00
unsigned long thread_saved_pc ( struct task_struct * task )
{
2007-10-16 01:26:58 -07:00
/* FIXME: Need to look up userspace_pid by cpu */
return os_process_pc ( userspace_pid [ 0 ] ) ;
2005-04-16 15:20:36 -07:00
}
2007-05-06 14:50:59 -07:00
/* Changed in setup_arch, which is called in early boot */
static char host_info [ ( __NEW_UTS_LEN + 1 ) * 5 ] ;
2005-04-16 15:20:36 -07:00
static int show_cpuinfo ( struct seq_file * m , void * v )
{
int index = 0 ;
# ifdef CONFIG_SMP
index = ( struct cpuinfo_um * ) v - cpu_data ;
if ( ! cpu_online ( index ) )
return 0 ;
# endif
seq_printf ( m , " processor \t : %d \n " , index ) ;
seq_printf ( m , " vendor_id \t : User Mode Linux \n " ) ;
seq_printf ( m , " model name \t : UML \n " ) ;
2007-10-16 01:26:56 -07:00
seq_printf ( m , " mode \t \t : skas \n " ) ;
2005-04-16 15:20:36 -07:00
seq_printf ( m , " host \t \t : %s \n " , host_info ) ;
seq_printf ( m , " bogomips \t : %lu.%02lu \n \n " ,
loops_per_jiffy / ( 500000 / HZ ) ,
( loops_per_jiffy / ( 5000 / HZ ) ) % 100 ) ;
2007-05-06 14:50:58 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
static void * c_start ( struct seq_file * m , loff_t * pos )
{
return * pos < NR_CPUS ? cpu_data + * pos : NULL ;
}
static void * c_next ( struct seq_file * m , void * v , loff_t * pos )
{
+ + * pos ;
return c_start ( m , pos ) ;
}
static void c_stop ( struct seq_file * m , void * v )
{
}
2006-09-27 01:50:33 -07:00
const struct seq_operations cpuinfo_op = {
2005-04-16 15:20:36 -07:00
. start = c_start ,
. next = c_next ,
. stop = c_stop ,
. show = show_cpuinfo ,
} ;
/* Set in linux_main */
unsigned long uml_physmem ;
2011-08-18 20:14:10 +01:00
EXPORT_SYMBOL ( uml_physmem ) ;
2007-05-06 14:51:26 -07:00
unsigned long uml_reserved ; /* Also modified in mem_init */
2005-04-16 15:20:36 -07:00
unsigned long start_vm ;
unsigned long end_vm ;
2007-05-06 14:51:26 -07:00
/* Set in uml_ncpus_setup */
2005-04-16 15:20:36 -07:00
int ncpus = 1 ;
/* Set in early boot */
static int have_root __initdata = 0 ;
2007-05-06 14:51:26 -07:00
/* Set in uml_mem_setup and modified in linux_main */
2005-11-07 00:58:57 -08:00
long long physmem_size = 32 * 1024 * 1024 ;
2005-04-16 15:20:36 -07:00
2008-04-28 02:13:52 -07:00
static const char * usage_string =
2005-04-16 15:20:36 -07:00
" User Mode Linux v%s \n "
" available at http://user-mode-linux.sourceforge.net/ \n \n " ;
static int __init uml_version_setup ( char * line , int * add )
{
2006-10-02 02:18:13 -07:00
printf ( " %s \n " , init_utsname ( ) - > release ) ;
2005-04-16 15:20:36 -07:00
exit ( 0 ) ;
return 0 ;
}
__uml_setup ( " --version " , uml_version_setup ,
" --version \n "
" Prints the version number of the kernel. \n \n "
) ;
static int __init uml_root_setup ( char * line , int * add )
{
have_root = 1 ;
return 0 ;
}
__uml_setup ( " root= " , uml_root_setup ,
" root=<file containing the root fs> \n "
" This is actually used by the generic kernel in exactly the same \n "
" way as in any other kernel. If you configure a number of block \n "
" devices and want to boot off something other than ubd0, you \n "
" would use something like: \n "
" root=/dev/ubd5 \n \n "
) ;
2006-02-07 12:58:40 -08:00
static int __init no_skas_debug_setup ( char * line , int * add )
{
printf ( " 'debug' is not necessary to gdb UML in skas mode - run \n " ) ;
2008-05-12 14:01:48 -07:00
printf ( " 'gdb linux' \n " ) ;
2006-02-07 12:58:40 -08:00
return 0 ;
}
__uml_setup ( " debug " , no_skas_debug_setup ,
" debug \n "
" this flag is not needed to run gdb on UML in skas mode \n \n "
) ;
2005-04-16 15:20:36 -07:00
# ifdef CONFIG_SMP
static int __init uml_ncpus_setup ( char * line , int * add )
{
2007-05-06 14:50:58 -07:00
if ( ! sscanf ( line , " %d " , & ncpus ) ) {
printf ( " Couldn't parse [%s] \n " , line ) ;
return - 1 ;
}
2005-04-16 15:20:36 -07:00
2007-05-06 14:50:58 -07:00
return 0 ;
2005-04-16 15:20:36 -07:00
}
__uml_setup ( " ncpus= " , uml_ncpus_setup ,
" ncpus=<# of desired CPUs> \n "
2007-10-16 01:27:00 -07:00
" This tells an SMP kernel how many virtual processors to start. \n \n "
2005-04-16 15:20:36 -07:00
) ;
# endif
static int __init Usage ( char * line , int * add )
{
2007-05-06 14:50:58 -07:00
const char * * p ;
2005-04-16 15:20:36 -07:00
2006-10-02 02:18:13 -07:00
printf ( usage_string , init_utsname ( ) - > release ) ;
2007-05-06 14:50:58 -07:00
p = & __uml_help_start ;
while ( p < & __uml_help_end ) {
printf ( " %s " , * p ) ;
p + + ;
}
2005-04-16 15:20:36 -07:00
exit ( 0 ) ;
return 0 ;
}
__uml_setup ( " --help " , Usage ,
" --help \n "
" Prints this message. \n \n "
) ;
2008-02-04 22:30:50 -08:00
static void __init uml_checksetup ( char * line , int * add )
2005-04-16 15:20:36 -07:00
{
struct uml_param * p ;
p = & __uml_setup_start ;
2008-02-04 22:31:14 -08:00
while ( p < & __uml_setup_end ) {
2008-04-28 02:13:52 -07:00
size_t n ;
2005-04-16 15:20:36 -07:00
n = strlen ( p - > str ) ;
2007-10-16 01:27:00 -07:00
if ( ! strncmp ( line , p - > str , n ) & & p - > setup_func ( line + n , add ) )
2008-02-04 22:30:50 -08:00
return ;
2005-04-16 15:20:36 -07:00
p + + ;
}
}
static void __init uml_postsetup ( void )
{
initcall_t * p ;
p = & __uml_postsetup_start ;
2008-02-04 22:31:14 -08:00
while ( p < & __uml_postsetup_end ) {
2005-04-16 15:20:36 -07:00
( * p ) ( ) ;
p + + ;
}
return ;
}
2008-02-04 22:31:08 -08:00
static int panic_exit ( struct notifier_block * self , unsigned long unused1 ,
void * unused2 )
{
bust_spinlocks ( 1 ) ;
show_regs ( & ( current - > thread . regs ) ) ;
bust_spinlocks ( 0 ) ;
uml_exitcode = 1 ;
os_dump_core ( ) ;
return 0 ;
}
static struct notifier_block panic_exit_notifier = {
. notifier_call = panic_exit ,
. next = NULL ,
. priority = 0
} ;
2005-04-16 15:20:36 -07:00
/* Set during early boot */
2008-02-08 04:22:07 -08:00
unsigned long task_size ;
EXPORT_SYMBOL ( task_size ) ;
unsigned long host_task_size ;
2005-04-16 15:20:36 -07:00
unsigned long brk_start ;
unsigned long end_iomem ;
EXPORT_SYMBOL ( end_iomem ) ;
# define MIN_VMALLOC (32 * 1024 * 1024)
2006-07-10 04:45:06 -07:00
extern char __binary_start ;
2007-02-12 00:54:26 -08:00
int __init linux_main ( int argc , char * * argv )
2005-04-16 15:20:36 -07:00
{
unsigned long avail , diff ;
unsigned long virtmem_size , max_physmem ;
2008-05-12 14:01:57 -07:00
unsigned long stack ;
2008-04-28 02:13:52 -07:00
unsigned int i ;
int add ;
2005-07-27 11:43:31 -07:00
char * mode ;
2005-04-16 15:20:36 -07:00
2007-10-16 01:27:00 -07:00
for ( i = 1 ; i < argc ; i + + ) {
if ( ( i = = 1 ) & & ( argv [ i ] [ 0 ] = = ' ' ) )
continue ;
2005-04-16 15:20:36 -07:00
add = 1 ;
uml_checksetup ( argv [ i ] , & add ) ;
if ( add )
add_arg ( argv [ i ] ) ;
}
2007-10-16 01:27:00 -07:00
if ( have_root = = 0 )
2005-04-16 15:20:36 -07:00
add_arg ( DEFAULT_COMMAND_LINE ) ;
2008-06-05 22:46:12 -07:00
host_task_size = os_get_top_address ( ) ;
2008-02-08 04:22:07 -08:00
/*
* TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
* out
*/
task_size = host_task_size & PGDIR_MASK ;
2007-10-16 01:27:00 -07:00
/* OS sanity checks that need to happen before the kernel runs */
2005-09-03 15:57:47 -07:00
os_early_checks ( ) ;
2005-07-27 11:43:31 -07:00
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 01:26:50 -07:00
can_do_skas ( ) ;
if ( proc_mm & & ptrace_faultinfo )
2005-07-27 11:43:31 -07:00
mode = " SKAS3 " ;
else
mode = " SKAS0 " ;
printf ( " UML running in %s mode \n " , mode ) ;
2005-04-16 15:20:36 -07:00
brk_start = ( unsigned long ) sbrk ( 0 ) ;
2007-10-16 01:26:58 -07:00
2007-10-16 01:27:00 -07:00
/*
* Increase physical memory size for exec - shield users
* so they actually get what they asked for . This should
* add zero for non - exec shield users
*/
2005-04-16 15:20:36 -07:00
diff = UML_ROUND_UP ( brk_start ) - UML_ROUND_UP ( & _end ) ;
2007-10-16 01:27:00 -07:00
if ( diff > 1024 * 1024 ) {
2005-04-16 15:20:36 -07:00
printf ( " Adding %ld bytes to physical memory to account for "
" exec-shield gap \n " , diff ) ;
physmem_size + = UML_ROUND_UP ( brk_start ) - UML_ROUND_UP ( & _end ) ;
}
2007-05-06 14:51:26 -07:00
uml_physmem = ( unsigned long ) & __binary_start & PAGE_MASK ;
2005-04-16 15:20:36 -07:00
/* Reserve up to 4M after the current brk */
uml_reserved = ROUND_4M ( brk_start ) + ( 1 < < 22 ) ;
2006-10-02 02:18:13 -07:00
setup_machinename ( init_utsname ( ) - > machine ) ;
2005-04-16 15:20:36 -07:00
highmem = 0 ;
iomem_size = ( iomem_size + PAGE_SIZE - 1 ) & PAGE_MASK ;
2008-02-08 04:22:07 -08:00
max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC ;
2005-04-16 15:20:36 -07:00
2007-10-16 01:27:00 -07:00
/*
* Zones have to begin on a 1 < < MAX_ORDER page boundary ,
2005-04-16 15:20:36 -07:00
* so this makes sure that ' s true for highmem
*/
max_physmem & = ~ ( ( 1 < < ( PAGE_SHIFT + MAX_ORDER ) ) - 1 ) ;
2007-10-16 01:27:00 -07:00
if ( physmem_size + iomem_size > max_physmem ) {
2005-04-16 15:20:36 -07:00
highmem = physmem_size + iomem_size - max_physmem ;
physmem_size - = highmem ;
# ifndef CONFIG_HIGHMEM
highmem = 0 ;
printf ( " CONFIG_HIGHMEM not enabled - physical memory shrunk "
2006-03-27 01:14:29 -08:00
" to %Lu bytes \n " , physmem_size ) ;
2005-04-16 15:20:36 -07:00
# endif
}
high_physmem = uml_physmem + physmem_size ;
end_iomem = high_physmem + iomem_size ;
high_memory = ( void * ) end_iomem ;
start_vm = VMALLOC_START ;
setup_physmem ( uml_physmem , uml_reserved , physmem_size , highmem ) ;
2007-10-16 01:27:00 -07:00
if ( init_maps ( physmem_size , iomem_size , highmem ) ) {
2006-03-27 01:14:29 -08:00
printf ( " Failed to allocate mem_map for %Lu bytes of physical "
" memory and %Lu bytes of highmem \n " , physmem_size ,
2005-04-16 15:20:36 -07:00
highmem ) ;
exit ( 1 ) ;
}
virtmem_size = physmem_size ;
2008-05-12 14:01:57 -07:00
stack = ( unsigned long ) argv ;
stack & = ~ ( 1024 * 1024 - 1 ) ;
avail = stack - start_vm ;
2007-10-16 01:27:00 -07:00
if ( physmem_size > avail )
virtmem_size = avail ;
2005-04-16 15:20:36 -07:00
end_vm = start_vm + virtmem_size ;
2007-10-16 01:27:00 -07:00
if ( virtmem_size < physmem_size )
2005-11-07 00:58:57 -08:00
printf ( " Kernel virtual memory size shrunk to %lu bytes \n " ,
2005-04-16 15:20:36 -07:00
virtmem_size ) ;
2008-02-04 22:31:08 -08:00
atomic_notifier_chain_register ( & panic_notifier_list ,
& panic_exit_notifier ) ;
2007-05-06 14:50:58 -07:00
uml_postsetup ( ) ;
2005-04-16 15:20:36 -07:00
2007-05-10 22:22:30 -07:00
stack_protections ( ( unsigned long ) & init_thread_info ) ;
2005-04-16 15:20:36 -07:00
os_flush_stdout ( ) ;
2007-10-16 01:26:58 -07:00
return start_uml ( ) ;
2005-04-16 15:20:36 -07:00
}
void __init setup_arch ( char * * cmdline_p )
{
paging_init ( ) ;
2007-02-12 00:54:23 -08:00
strlcpy ( boot_command_line , command_line , COMMAND_LINE_SIZE ) ;
2007-05-06 14:50:58 -07:00
* cmdline_p = command_line ;
2007-05-06 14:50:59 -07:00
setup_hostinfo ( host_info , sizeof host_info ) ;
2005-04-16 15:20:36 -07:00
}
void __init check_bugs ( void )
{
arch_check_bugs ( ) ;
2007-05-06 14:50:58 -07:00
os_check_bugs ( ) ;
2005-04-16 15:20:36 -07:00
}
2006-03-23 02:59:32 -08:00
void apply_alternatives ( struct alt_instr * start , struct alt_instr * end )
{
}
2006-07-03 00:24:09 -07:00
# ifdef CONFIG_SMP
2006-03-23 02:59:32 -08:00
void alternatives_smp_module_add ( struct module * mod , char * name ,
void * locks , void * locks_end ,
void * text , void * text_end )
{
}
void alternatives_smp_module_del ( struct module * mod )
2005-04-16 15:20:36 -07:00
{
}
2006-07-03 00:24:09 -07:00
# endif