startケネル関数
スタート地点ケネル()では、一連の初期化関数を呼び出して、ケネル自体の設定を完了します.これらの動作は公共的なものもあれば、配置が必要なものがあります.
スタントにケネル関数では、
Linuxバージョン情報を出力します.
システム構造に関する環境(setupuarch()を設定します.
ページ表構造初期化(pagiguinit())
「arch/alpha/kersnel/entry.S」の入口点設定システムを使用して、ノッチ入口(trapuuinit()
アルファを使うmv構造とentry.S入り口初期化システムIRQ(inituIRQ()
コアプロセススケジューラ初期化(いくつかのデフォルトのBottom-halfを初期化することを含む)
時間、タイマー初期化(CMOSクロックの読み取り、マスタ周波数の推定、初期化タイマの中断などを含む、timeyit()
コア起動パラメータを抽出して分析します(環境変数からパラメータを読み出し、該当フラグビット待ち処理を設定します.(パーrseuoptions()
コンソール初期化(PCI初期化よりも先に情報を出力するために、consolueuinit())
解析器データ構造初期化(profufferとprofulen変数)
コアCache初期化(Cache情報を記述するCache,kmemucache uinit()
ディレイキャリブレーション(クロックジffiesとCPUメイン周波数ticksの遅延を取得し、calibrate udelay()
メモリ初期化(メモリ上下界とページ項目初期値設定、memuuinit()
内部および汎用cache(「slabucache」,kmemucache()を作成して設定します.
uid taskycount SLAB cacheを作成します.
文書cacheを作成します.
ディレクトリcacheを作成します.
虚存に関するcacheを作成します.
ブロックデバイス読み書きバッファ初期化(同時に「バfferuhead」cacheを作成し、ユーザーの加速アクセス、バfferuuinit()
ページcacheを作成します(メモリページhashテーブル初期化、pagecacheuinit()
信号列cacheを作成します.
初期化メモリinodeテーブル(inodeuinit()
メモリファイルの説明書を作成します.
システム構造の脆弱性をチェックします.この関数は空です.checkubugs()
SMPマシンの他のCPU(現在のブートCPUを除く)初期化(SMPを構成していないカーネルに対しては、この関数は空であり、spuuinit())
initプロセスを起動します.(最初のコアスレッドを作成し、init()関数を呼び出します.元の実行シーケンスはcpuguidle()を呼び出してスケジュールを待っています.init()
これでstartukeernelが終わり、基本的な核心環境ができました.
スタントにケネル関数では、
Linuxバージョン情報を出力します.
システム構造に関する環境(setupuarch()を設定します.
ページ表構造初期化(pagiguinit())
「arch/alpha/kersnel/entry.S」の入口点設定システムを使用して、ノッチ入口(trapuuinit()
アルファを使うmv構造とentry.S入り口初期化システムIRQ(inituIRQ()
コアプロセススケジューラ初期化(いくつかのデフォルトのBottom-halfを初期化することを含む)
時間、タイマー初期化(CMOSクロックの読み取り、マスタ周波数の推定、初期化タイマの中断などを含む、timeyit()
コア起動パラメータを抽出して分析します(環境変数からパラメータを読み出し、該当フラグビット待ち処理を設定します.(パーrseuoptions()
コンソール初期化(PCI初期化よりも先に情報を出力するために、consolueuinit())
解析器データ構造初期化(profufferとprofulen変数)
コアCache初期化(Cache情報を記述するCache,kmemucache uinit()
ディレイキャリブレーション(クロックジffiesとCPUメイン周波数ticksの遅延を取得し、calibrate udelay()
メモリ初期化(メモリ上下界とページ項目初期値設定、memuuinit()
内部および汎用cache(「slabucache」,kmemucache()を作成して設定します.
uid taskycount SLAB cacheを作成します.
文書cacheを作成します.
ディレクトリcacheを作成します.
虚存に関するcacheを作成します.
ブロックデバイス読み書きバッファ初期化(同時に「バfferuhead」cacheを作成し、ユーザーの加速アクセス、バfferuuinit()
ページcacheを作成します(メモリページhashテーブル初期化、pagecacheuinit()
信号列cacheを作成します.
初期化メモリinodeテーブル(inodeuinit()
メモリファイルの説明書を作成します.
システム構造の脆弱性をチェックします.この関数は空です.checkubugs()
SMPマシンの他のCPU(現在のブートCPUを除く)初期化(SMPを構成していないカーネルに対しては、この関数は空であり、spuuinit())
initプロセスを起動します.(最初のコアスレッドを作成し、init()関数を呼び出します.元の実行シーケンスはcpuguidle()を呼び出してスケジュールを待っています.init()
これでstartukeernelが終わり、基本的な核心環境ができました.
asmlinkage void __init start_kernel(void)
{
char * command_line;
unsigned long mempages;
extern char saved_command_line[];
/*
* Interrupts are still disabled. Do necessary setups, then
* enable them
*/
/* */
lock_kernel();
/* */
printk(linux_banner);
/* */
setup_arch(&command_line);
/* */
printk("Kernel command line: %s
", saved_command_line);/* 0 */
parse_options(command_line);
/* , */
trap_init();
/* */
init_IRQ();
/* */
sched_init();
/* */
time_init();
/* tasklet */
softirq_init();
/*
* HACK ALERT! This is early. We're enabling the console before
* we've done PCI setups etc, and console_init() must be aware of
* this. But we do want output early, in case something goes wrong.
*/
/* */
console_init();
#ifdef CONFIG_MODULES
/* symbol */
init_modules();
#endif
if (prof_shift) {
unsigned int size;
/* only text is profiled */
prof_len = (unsigned long) &_etext - (unsigned long) &_stext;
prof_len >>= prof_shift;
size = prof_len * sizeof(unsigned int) + PAGE_SIZE-1;
prof_buffer = (unsigned int *) alloc_bootmem(size);
}
/* slab */
kmem_cache_init();
sti();
calibrate_delay();
#ifdef CONFIG_BLK_DEV_INITRD
if (initrd_start && !initrd_below_start_ok &&
initrd_start < min_low_pfn << PAGE_SHIFT) {
printk(KERN_CRIT "initrd overwritten (0x%08lx < 0x%08lx) - "
"disabling it.
",initrd_start,min_low_pfn << PAGE_SHIFT);initrd_start = 0;
}
#endif
/* */
mem_init();
/* slab */
kmem_cache_sizes_init();
#ifdef CONFIG_3215_CONSOLE
con3215_activate();
#endif
#ifdef CONFIG_PROC_FS
/* proc */
proc_root_init();
#endif
mempages = num_physpages;
/* */
fork_init(mempages);
/* slab */
proc_caches_init();
vfs_caches_init(mempages);
/* buffer */
buffer_init(mempages);
/* */
page_cache_init(mempages);
kiobuf_setup();
/* signal slab */
signals_init();
bdev_init();
/* inode */
inode_init(mempages);
#if defined(CONFIG_SYSVIPC)
/* sysv , , */
ipc_init();
#endif
#if defined(CONFIG_QUOTA)
dquot_init_hash();
#endif
check_bugs();
printk("POSIX conformance testing by UNIFIX
");/*
* We count on the initial thread going ok
* Like idlers init is an unlocked kernel thread, which will
* make syscalls (and thus be locked).
*/
/* SMP, APIC */
smp_init();
/* init */
kernel_thread(init, NULL, CLONE_FS | CLONE_FILES | CLONE_SIGNAL);
unlock_kernel();
current->need_resched = 1;
/* idle , */
cpu_idle();
}
void __init setup_arch(char **cmdline_p)
{
unsigned long bootmap_size;
unsigned long start_pfn, max_pfn, max_low_pfn;
int i;
#ifdef CONFIG_VISWS
visws_get_board_type_and_rev();
#endif
/* rootfs kdev , */
ROOT_DEV = to_kdev_t(ORIG_ROOT_DEV);
drive_info = DRIVE_INFO;
screen_info = SCREEN_INFO;
apm_info.bios = APM_BIOS_INFO;
/* */
if( SYS_DESC_TABLE.length != 0 ) {
MCA_bus = SYS_DESC_TABLE.table[3] &0x2;
machine_id = SYS_DESC_TABLE.table[0];
machine_submodel_id = SYS_DESC_TABLE.table[1];
BIOS_revision = SYS_DESC_TABLE.table[2];
}
aux_device_present = AUX_DEVICE_INFO;
#ifdef CONFIG_BLK_DEV_RAM
/* RAMDISK */
rd_image_start = RAMDISK_FLAGS & RAMDISK_IMAGE_START_MASK;
rd_prompt = ((RAMDISK_FLAGS & RAMDISK_PROMPT_FLAG) != 0);
rd_doload = ((RAMDISK_FLAGS & RAMDISK_LOAD_FLAG) != 0);
#endif
setup_memory_region();
if (!MOUNT_ROOT_RDONLY)
root_mountflags &= ~MS_RDONLY;
/* init_mm , , */
init_mm.start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;
/* , */
code_resource.start = virt_to_bus(&_text);
code_resource.end = virt_to_bus(&_etext)-1;
data_resource.start = virt_to_bus(&_etext);
data_resource.end = virt_to_bus(&_edata)-1;
/* "mem=" */
parse_mem_cmdline(cmdline_p);
#define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
#define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
#define PFN_PHYS(x) ((x) << PAGE_SHIFT)
/*
* 128MB for vmalloc and initrd
*/
#define VMALLOC_RESERVE (unsigned long)(128 << 20)
#define MAXMEM (unsigned long)(-PAGE_OFFSET-VMALLOC_RESERVE)
#define MAXMEM_PFN PFN_DOWN(MAXMEM)
#define MAX_NONPAE_PFN (1 << 20)
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
/* */
start_pfn = PFN_UP(__pa(&_end));
/*
* Find the highest page frame number we have available
*/
/* E820 */
max_pfn = 0;
for (i = 0; i < e820.nr_map; i++) {
unsigned long start, end;
/* RAM? */
if (e820.map[i].type != E820_RAM)
continue;
start = PFN_UP(e820.map[i].addr);
end = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
if (start >= end)
continue;
if (end > max_pfn)
max_pfn = end;
}
/*
* Determine low and high memory ranges:
*/
/* , 896M */
max_low_pfn = max_pfn;
if (max_low_pfn > MAXMEM_PFN) {
max_low_pfn = MAXMEM_PFN;
#ifndef CONFIG_HIGHMEM
/* Maximum memory usable is what is directly addressable */
printk(KERN_WARNING "Warning only %ldMB will be used.
",MAXMEM>>20);
if (max_pfn > MAX_NONPAE_PFN)
printk(KERN_WARNING "Use a PAE enabled kernel.
");else
printk(KERN_WARNING "Use a HIGHMEM enabled kernel.
");#else /* !CONFIG_HIGHMEM */
#ifndef CONFIG_X86_PAE
if (max_pfn > MAX_NONPAE_PFN) {
max_pfn = MAX_NONPAE_PFN;
printk(KERN_WARNING "Warning only 4GB will be used.
");printk(KERN_WARNING "Use a PAE enabled kernel.
");}
#endif /* !CONFIG_X86_PAE */
#endif /* !CONFIG_HIGHMEM */
}
/* */
#ifdef CONFIG_HIGHMEM
highstart_pfn = highend_pfn = max_pfn;
if (max_pfn > MAXMEM_PFN) {
highstart_pfn = MAXMEM_PFN;
printk(KERN_NOTICE "%ldMB HIGHMEM available.
",pages_to_mb(highend_pfn - highstart_pfn));
}
#endif
/*
* Initialize the boot-time allocator (with low memory only):
*/
/* 896M boot */
bootmap_size = init_bootmem(start_pfn, max_low_pfn);
/*
* Register fully available low RAM pages with the bootmem allocator.
*/
/* 896M */
for (i = 0; i < e820.nr_map; i++) {
unsigned long curr_pfn, last_pfn, size;
/*
* Reserve usable low memory
*/
if (e820.map[i].type != E820_RAM)
continue;
/*
* We are rounding up the start address of usable memory:
*/
curr_pfn = PFN_UP(e820.map[i].addr);
if (curr_pfn >= max_low_pfn)
continue;
/*
* ... and at the end of the usable range downwards:
*/
last_pfn = PFN_DOWN(e820.map[i].addr + e820.map[i].size);
if (last_pfn > max_low_pfn)
last_pfn = max_low_pfn;
/*
* .. finally, did all the rounding and playing
* around just make the area go away?
*/
if (last_pfn <= curr_pfn)
continue;
size = last_pfn - curr_pfn;
free_bootmem(PFN_PHYS(curr_pfn), PFN_PHYS(size));
}
/*
* Reserve the bootmem bitmap itself as well. We do this in two
* steps (first step was init_bootmem()) because this catches
* the (very unlikely) case of us accidentally initializing the
* bootmem allocator with an invalid RAM area.
*/
/* bootmem */
reserve_bootmem(HIGH_MEMORY, (PFN_PHYS(start_pfn) +
bootmap_size + PAGE_SIZE-1) - (HIGH_MEMORY));
/*
* reserve physical page 0 - it's a special BIOS page on many boxes,
* enabling clean reboots, SMP operation, laptop functions.
*/
/* */
reserve_bootmem(0, PAGE_SIZE);
#ifdef CONFIG_SMP
/*
* But first pinch a few for the stack/trampoline stuff
* FIXME: Don't need the extra page at 4K, but need to fix
* trampoline before removing it. (see the GDT stuff)
*/
reserve_bootmem(PAGE_SIZE, PAGE_SIZE);
smp_alloc_memory(); /* AP processor realmode stacks in low memory*/
#endif
#ifdef CONFIG_X86_IO_APIC
/*
* Find and reserve possible boot-time SMP configuration:
*/
find_smp_config();
#endif
/* */
paging_init();
#ifdef CONFIG_X86_IO_APIC
/*
* get boot-time SMP configuration:
*/
if (smp_found_config)
get_smp_config();
#endif
#ifdef CONFIG_X86_LOCAL_APIC
init_apic_mappings();
#endif
#ifdef CONFIG_BLK_DEV_INITRD
/* RAMDISK */
if (LOADER_TYPE && INITRD_START) {
if (INITRD_START + INITRD_SIZE <= (max_low_pfn << PAGE_SHIFT)) {
reserve_bootmem(INITRD_START, INITRD_SIZE);
initrd_start =
INITRD_START ? INITRD_START + PAGE_OFFSET : 0;
initrd_end = initrd_start+INITRD_SIZE;
}
else {
printk("initrd extends beyond end of memory "
"(0x%08lx > 0x%08lx)
disabling initrd
",INITRD_START + INITRD_SIZE,
max_low_pfn << PAGE_SHIFT);
initrd_start = 0;
}
}
#endif
/*
* Request address space for all standard RAM and ROM resources
* and also for regions reported as reserved by the e820.
*/
/* ROM */
probe_roms();
/* RAM */
for (i = 0; i < e820.nr_map; i++) {
struct resource *res;
if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL)
continue;
res = alloc_bootmem_low(sizeof(struct resource));
switch (e820.map[i].type) {
case E820_RAM: res->name = "System RAM"; break;
case E820_ACPI: res->name = "ACPI Tables"; break;
case E820_NVS: res->name = "ACPI Non-volatile Storage"; break;
default: res->name = "reserved";
}
res->start = e820.map[i].addr;
res->end = res->start + e820.map[i].size - 1;
res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
request_resource(&iomem_resource, res);
if (e820.map[i].type == E820_RAM) {
/*
* We dont't know which RAM region contains kernel data,
* so we try it repeatedly and let the resource manager
* test it.
*/
request_resource(res, &code_resource);
request_resource(res, &data_resource);
}
}
request_resource(&iomem_resource, &vram_resource);
/* request I/O space for devices used on all i[345]86 PCs */
for (i = 0; i < STANDARD_IO_RESOURCES; i++)
request_resource(&ioport_resource, standard_io_resources+i);
#ifdef CONFIG_VT
#if defined(CONFIG_VGA_CONSOLE)
conswitchp = &vga_con;
#elif defined(CONFIG_DUMMY_CONSOLE)
conswitchp = &dummy_con;
#endif
#endif
}