亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 2319 | 回復(fù): 0
打印 上一主題 下一主題

/sys/i386/i386/locore.s分析筆記 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2008-08-26 21:06 |只看該作者 |倒序?yàn)g覽
kernel的入口地址是/sys/i386/i386/locore.s中定義的btext:
200  /**********************************************************************
201   *
202   * This is where the bootblocks start us, set the ball rolling...
203   *
204   */
205  NON_GPROF_ENTRY(btext)
從/boot/kernel/kernel中可以讀出btext的鏈接地址:
# readelf -a /boot/kernel/kernel | grep btext
  6870: c0458a30     0 FUNC    GLOBAL DEFAULT    5 btext
26381: c0458a30     0 FUNC    GLOBAL DEFAULT    5 btext
因此,在物理地址0x458a30處設(shè)置斷點(diǎn),單步跟蹤locore.s中的初始化代碼。程序運(yùn)行至此
的cpu主要寄存器的內(nèi)容如下:
rax: 0x00000000:00458a30 rcx: 0x00000000:a0200000
rdx: 0x00000000:000488a0 rbx: 0x00000000:00458a30
rsp: 0x00000000:0009e844 rbp: 0x00000000:00094884
rsi: 0x00000000:000610e4 rdi: 0x00000000:0005b9cc
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:00458a30
eflags 0x00000002
首先是向0x472寫入0x1234,告知bios下次為熱引導(dǎo):
216  /* Tell the bios to warmboot next time */
217          movw    $0x1234,0x472
構(gòu)建一個新的棧幀:
220  /* Set up a real frame in case the double return in newboot is executed. */
221          pushl   %ebp
222          movl    %esp, %ebp
此時cpu主要寄存器的內(nèi)容如下:
rax: 0x00000000:00458a30 rcx: 0x00000000:a0200000
rdx: 0x00000000:000488a0 rbx: 0x00000000:00458a30
rsp: 0x00000000:0009e840 rbp: 0x00000000:0009e840
rsi: 0x00000000:000610e4 rdi: 0x00000000:0005b9cc
r8 : 0x00000000:00000000 r9 : 0x00000000:00000000
r10: 0x00000000:00000000 r11: 0x00000000:00000000
r12: 0x00000000:00000000 r13: 0x00000000:00000000
r14: 0x00000000:00000000 r15: 0x00000000:00000000
rip: 0x00000000:00458a3c
eflags 0x00000002
將PSL_KRENEL賦給eflags:
224  /* Don't trust what the BIOS gives for eflags. */
225          pushl   $PSL_KERNEL
226          popfl
PSL_KERNEL是在/sys/i386/include/psl.h中定義的:
60  /*
61   * The i486 manual says that we are not supposed to change reserved flags,
62   * but this is too much trouble since the reserved flags depend on the cpu
63   * and setting them to their historical values works in practice.
64   */
65  #define PSL_RESERVED_DEFAULT    0x00000002
66
67  /*
68   * Initial flags for kernel and user mode.  The kernel later inherits
69   * PSL_I and some other flags from user mode.
70   */
71  #define PSL_KERNEL      PSL_RESERVED_DEFAULT
72  #define PSL_USER        (PSL_RESERVED_DEFAULT | PSL_I)
將ds的內(nèi)容賦給fs和gs:
228  /*
229   * Don't trust what the BIOS gives for %fs and %gs.  Trust the bootstrap
230   * to set %cs, %ds, %es and %ss.
231   */
232          mov     %ds, %ax
233          mov     %ax, %fs
234          mov     %ax, %gs
236  /*
237   * Clear the bss.  Not all boot programs do it, and it is our job anyway.
238   *
239   * XXX we don't check that there is memory for our bss and page tables
240   * before using it.
241   *
242   * Note: we must be careful to not overwrite an active gdt or idt.  They
243   * inactive from now until we switch to new ones, since we don't load any
244   * more segment registers or permit interrupts until after the switch.
245   */
246          movl    $R(end),%ecx
247          movl    $R(edata),%edi
248          subl    %edi,%ecx
249          xorl    %eax,%eax
250          cld
251          rep
252          stosb
根據(jù)readelf -a kernel的結(jié)果,end的地址是0xc0c06020,由于KERNBASE是
0xc0000000,此處賦給ecx的就是0xc06020。edata的地址是0xc0bab9a0,這實(shí)際上就是
.bss段的起始地址,此處賦給edi的就是0xbab9a0。ecx減去edi之后的內(nèi)容是0x5a680,
這是從.bss段起始地址到end地址之間的字節(jié)數(shù)。隨后將eax清0,作為后續(xù)清0操作的
寫入值。cld保證edi遞增變化。stosb將al的內(nèi)容寫入edi指向的位置。這段代碼從
0xc0bab9a0開始連續(xù)寫入0x5a680個字節(jié)的0,從而實(shí)現(xiàn)將.bss段清0的目的。
253
254          call    recover_bootinfo
255
調(diào)用recover_bootinfo獲取由loader傳入的引導(dǎo)信息。
487          movl    28(%ebp),%ebx           /* &bootinfo.version */
488          movl    BI_VERSION(%ebx),%eax
489          cmpl    $1,%eax                 /* We only understand version 1 */
490          je      1f
491          movl    $1,%eax                 /* Return status */
492          leave
493          /*
494           * XXX this returns to our caller's caller (as is required) since
495           * we didn't set up a frame and our caller did.
496           */
497          ret
locore.s入口btext的調(diào)用格式為(*btext)(howto, bootdev, 0, 0, 0, &bootinfo),在bootinfo
之后壓棧的有5個參數(shù),占20個字節(jié),在加上返回地址和在調(diào)用recover_bootinfo之前壓棧的ebp,
一共有28個字節(jié),因此從當(dāng)前ebp位置上溯28個字節(jié)就是bootinfo結(jié)構(gòu)體的起始地址。上述代碼
從bootinfo結(jié)構(gòu)體中取出bi_version字段的內(nèi)容,判斷其是否為1,僅當(dāng)版本為1時才繼續(xù)處理。
500          /*
501           * If we have a kernelname copy it in
502           */
503          movl    BI_KERNELNAME(%ebx),%esi
504          cmpl    $0,%esi
505          je      2f                      /* No kernelname */
506          movl    $MAXPATHLEN,%ecx        /* Brute force!!! */
507          movl    $R(kernelname),%edi
508          cmpb    $'/',(%esi)             /* Make sure it starts with a slash */
509          je      1f
510          movb    $'/',(%edi)
511          incl    %edi
512          decl    %ecx
從bootinfo結(jié)構(gòu)體中取出bi_kernelname字段,寫入esi。MAXPATHLEN是最大路徑長度,定義為1024,
這是kernel中的kernelname數(shù)組的尺寸。將該數(shù)組相對于KERNBASE偏移地址寫入edi,并判斷由
bootinfo傳入的bi_kernelname是否以"/"開始,若是,則將剩余部分拷入kernelname數(shù)組。
519          /*
520           * Determine the size of the boot loader's copy of the bootinfo
521           * struct.  This is impossible to do properly because old versions
522           * of the struct don't contain a size field and there are 2 old
523           * versions with the same version number.
524           */
525          movl    $BI_ENDCOMMON,%ecx      /* prepare for sizeless version */
526          testl   $RB_BOOTINFO,8(%ebp)    /* bi_size (and bootinfo) valid? */
527          je      got_bi_size             /* no, sizeless version */
528          movl    BI_SIZE(%ebx),%ecx
將bootinfo中肯定會存在的字段的結(jié)束位置取出,寫入ecx,實(shí)際上就是前三個字段,12個字節(jié)。
RB_BOOTINFO在/sys/sys/reboot.h中定義為0x80000000,是一個表示是否傳入了完整的bootinfo
結(jié)構(gòu)體信息的標(biāo)志。若傳入了完整的bootinfo結(jié)構(gòu)體信息,則將bi_size字段的內(nèi)容賦給ecx。
531          /*
532           * Copy the common part of the bootinfo struct
533           */
534          movl    %ebx,%esi
535          movl    $R(bootinfo),%edi
536          cmpl    $BOOTINFO_SIZE,%ecx
537          jbe     got_common_bi_size
538          movl    $BOOTINFO_SIZE,%ecx
539  got_common_bi_size:
540          cld
541          rep
542          movsb
比較傳入的bi_size字段的內(nèi)容與bootinfo結(jié)構(gòu)體的大小是否一致,若傳入bi_size小于等于bootinfo
結(jié)構(gòu)體的大小,則以bi_size為準(zhǔn),否則以bootinfo結(jié)構(gòu)體的大小為準(zhǔn)。將傳入的bootinfo信息拷貝
到bootinfo結(jié)構(gòu)體中。
562          /*
563           * The old style disk boot.
564           *      (*btext)(howto, bootdev, cyloffset, esym);
565           * Note that the newer boot code just falls into here to pick
566           * up howto and bootdev, cyloffset and esym are no longer used
567           */
568  olddiskboot:
569          movl    8(%ebp),%eax
570          movl    %eax,R(boothowto)
571          movl    12(%ebp),%eax
572          movl    %eax,R(bootdev)
573
574          ret
分別從入?yún)⒅腥〕鱿嚓P(guān)信息存入boothowto和bootdev變量。返回btext。
256  /* Get onto a stack that we can trust. */
257  /*
258   * XXX this step is delayed in case recover_bootinfo needs to return via
259   * the old stack, but it need not be, since recover_bootinfo actually
260   * returns via the old frame.
261   */
262          movl    $R(tmpstk),%esp
tmpstk是在本文件中定義的一塊8192字節(jié)的連續(xù)空間,此處將esp指向這塊空間。
實(shí)際上,這塊空間就緊鄰在bootinfo結(jié)構(gòu)體的下面。
291          call    identify_cpu
獲取cpu識別信息。
292          call    create_pagetables
創(chuàng)建第一個頁面目錄及其頁表。
706  /**********************************************************************
707   *
708   * Create the first page directory and its page tables.
709   *
710   */
711
712  create_pagetables:
713
714  /* Find end of kernel image (rounded up to a page boundary). */
715          movl    $R(_end),%esi
將kernel的結(jié)束地址賦給esi,示例中為0xc06020。
717  /* Include symbols, if any. */
718          movl    R(bootinfo+BI_ESYMTAB),%edi
719          testl   %edi,%edi
720          je      over_symalloc
721          movl    %edi,%esi
722          movl    $KERNBASE,%edi
723          addl    %edi,R(bootinfo+BI_SYMTAB)
724          addl    %edi,R(bootinfo+BI_ESYMTAB)
先把bootinfo結(jié)構(gòu)體中的bi_esymtab字段的內(nèi)容賦給edi,并測試其是否為0,
如果為0,表示傳入的bootinfo中沒有這個字段。
若非0,則將此內(nèi)容賦給esi,隨后將KERNBASE賦給edi。bootinfo結(jié)構(gòu)體的地址是
0xb00460,bi_symtab和bi_esymtab字段的地址分別是0xb004a0和0xb004a4,這部分結(jié)構(gòu)體
的內(nèi)容如下:
0xb00460 :    0x00000001      0x00065f24      0x00000000      0x00000000
0xb00470 :    0x0208fe3f      0x004f010f      0x004f010f      0x004f010f
0xb00480 :    0x004f010f      0x004f010f      0x004f010f      0x004f010f
0xb00490 :    0x00000054      0x00008001      0x0000027f      0x0003fbc0
0xb004a0 :    0x00c06020      0x00d06518
723行和724行就是把這兩個地址中存放的物理地址加上KERNBASE,得到虛擬地址。
完成添加操作之后同一內(nèi)存區(qū)域的內(nèi)容如下:
0xb00460 :    0x00000001      0x00065f24      0x00000000      0x00000000
0xb00470 :    0x0208fe3f      0x004f010f      0x004f010f      0x004f010f
0xb00480 :    0x004f010f      0x004f010f      0x004f010f      0x004f010f
0xb00490 :    0x00000054      0x00008001      0x0000027f      0x0003fbc0
0xb004a0 :    0xc0c06020      0xc0d06518
727  /* If we are told where the end of the kernel space is, believe it. */
728          movl    R(bootinfo+BI_KERNEND),%edi
729          testl   %edi,%edi
730          je      no_kernend
731          movl    %edi,%esi
732  no_kernend:
733
734          addl    $PDRMASK,%esi           /* Play conservative for now, and */
735          andl    $~PDRMASK,%esi          /*   ... wrap to next 4M. */
736          movl    %esi,R(KERNend)         /* save end of kernel */
737          movl    %esi,R(physfree)        /* next free page is at end of kernel */
將bootinfo結(jié)構(gòu)體中的bi_kernend字段的內(nèi)容賦給edi,并測試其是否為0,
如果為0,表示傳入的bootinfo中沒有這個字段。
若非0,則將此內(nèi)容賦給esi。示例中,bi_kernend字段的值是0xd74000。
PDRMASK的低22比特全1,734和735兩行就是把esi中的值,也就是傳入的bi_kernend
字段的值向上調(diào)整為4M的輩數(shù)。示例中即為0x01000000。隨后將調(diào)整之后的內(nèi)核結(jié)束位置
寫入全局變量KERNend和physfree,而下一個空閑頁面就是從physfree開始的。
739  /* Allocate Kernel Page Tables */
740          ALLOCPAGES(NKPT)
NKPT目前定義為30,此處即通過ALLOCPAGES分配30個頁面。
158  #define ALLOCPAGES(foo) \
159          movl    R(physfree), %esi ; \
160          movl    $((foo)*PAGE_SIZE), %eax ; \
161          addl    %esi, %eax ; \
162          movl    %eax, R(physfree) ; \
163          movl    %esi, %edi ; \
164          movl    $((foo)*PAGE_SIZE),%ecx ; \
165          xorl    %eax,%eax ; \
166          cld ; \
167          rep ; \
168          stosb
首先將當(dāng)前的空閑物理頁面地址賦給esi,即0x01000000。PAGE_SIZE是4096,
入?yún)oo是30,由此算出總字節(jié)數(shù)是122880,將其存入eax,在加上esi中的起始地址,
得到分配區(qū)域之后的地址,即0x0101e000,將其存為physfree變量的新值。
隨后將edi指向新分配的30個頁面空間的起始位置0x01000000。將新分配空間的字節(jié)數(shù)
0x1e000寫入ecx作為計(jì)數(shù),165行到168行將這段新分配的空間清0。
741          movl    %esi,R(KPTphys)
完成30個頁面空間的分配之后,將這部分空間的起始位置,即0x01000000寫入全局變量
KPTphys,表示內(nèi)核頁表的物理地址。
749          ALLOCPAGES(NPGPTD)
NPGPTD是頁表目錄所占用的頁面數(shù)目,對于非PAE的情況,頁表目錄共需
4*(2^10)=4096字節(jié),即1個頁面。此處再通過ALLOCPAGES分配一個頁面的空間,
分配完畢之后,physfree指向新的空閑頁面起始地址0x0101f000,esi指向這個頁面
的起始位置0x0101e000。
750          movl    %esi,R(IdlePTD)
將新分配的這個頁面的起始地址0x0101e000寫入全局變量IdlePTD,
表示內(nèi)核頁表目錄的物理地址。
752  /* Allocate KSTACK */
753          ALLOCPAGES(KSTACK_PAGES)
754          movl    %esi,R(p0kpa)
755          addl    $KERNBASE, %esi
756          movl    %esi, R(proc0kstack)
757
758          ALLOCPAGES(1)                   /* vm86/bios stack */
759          movl    %esi,R(vm86phystk)
760
761          ALLOCPAGES(3)                   /* pgtable + ext + IOPAGES */
762          movl    %esi,R(vm86pa)
763          addl    $KERNBASE, %esi
764          movl    %esi, R(vm86paddr)
KSTACK_PAGES在/sys/i386/include/param.h中定義為2,此處即再分配2個頁面的空間,
physfree指向0x01021000。
分配完成之后,將這段空間的起始地址0x0101f000賦給全局變量p0kpa,
表示proc0的棧的物理地址,另外將這個
起始地址對應(yīng)的虛擬地址0xc101f000寫入全局變量proc0kstack,表示proc0的kstack
空間的(虛擬)地址。
隨后再分配一個頁面的空間,physfree指向0x01022000。分配完成之后,將這段空間的
起始地址0x01021000賦給全局變量vm86phystk,表示vm86/bios棧的物理地址。
隨后再分配三個頁面的空間,physfree指向0x01025000。分配完成之后,將這段空間的
起始地址0x01022000賦給全局變量vm86pa,表示vm86區(qū)域的物理地址,同時將這個起始
地址對應(yīng)的虛擬地址0xc1022000賦給全局變量vm86paddr,表示vm86區(qū)域的(虛擬)地址。
766  #ifdef SMP
767  /* Allocate cpu0's private data page */
768          ALLOCPAGES(1)
769          movl    %esi,R(cpu0pp)
770          addl    $KERNBASE, %esi
771          movl    %esi, R(cpu0prvpage)    /* relocated to KVM space */
772
773  /* Allocate SMP page table page */
774          ALLOCPAGES(1)
775          movl    %esi,R(SMPptpa)
776          addl    $KERNBASE, %esi
777          movl    %esi, R(SMPpt)          /* relocated to KVM space */
778  #endif  /* SMP */
對于smp的情況,再分配一個頁面的空間給cpu0的私有數(shù)據(jù)頁,physfree指向0x01026000。
分配完成之后,將這段空間的起始地址0x01025000賦給全局變量cpu0pp,同時將這個
起始地址對應(yīng)的虛擬地址0xc1025000賦給全局變量cpu0prvpage。隨后再分配一個頁面的
空間給SMP頁表頁,physfree指向0x01027000。分配完成之后,將這段空間的起始地址
0x0x01026000賦給全局變量SMPptpa,同時將這個起始地址對應(yīng)的虛擬地址0xc1026000
賦給全局變量SMPpt。
780  /*
781   * Enable PSE and PGE.
782   */
783  #ifndef DISABLE_PSE
784          testl   $CPUID_PSE, R(cpu_feature)
785          jz      1f
786          movl    $PG_PS, R(pseflag)
787          movl    %cr4, %eax
788          orl     $CR4_PSE, %eax
789          movl    %eax, %cr4
790  1:
791  #endif
CPUID_PSE在/sys/i386/include/specialreg.h中定義為0x00000008,這是PSE標(biāo)志在
cpuid返回值中的位置。全局變量cpu_feature由之前調(diào)用的identify_cpu函數(shù)設(shè)置,
內(nèi)容獲取自cpuid指令。此處判斷其PSE對應(yīng)比特是否為1。PG_PS在/sys/i386/include/pmap.h
中定義為0x080,這是頁表目錄項(xiàng)和頁表項(xiàng)中表示頁面尺寸的比特位置。pseflag是在
/sys/i386/i386/pmap.c中定義的全局變量,用于表示是否開啟了PSE功能。CR4_PSE在
/sys/i386/include/specialreg.h中定義為0x00000010,這是PSE在cr4寄存器中的比特位置。
上面這幾行的意思就是如果cpuid指令的結(jié)果顯示cpu支持PSE,則將全局變量pseflag設(shè)置為
0x80,并將cr4寄存器中PSE對應(yīng)比特設(shè)置為1。
792  #ifndef DISABLE_PG_G
793          testl   $CPUID_PGE, R(cpu_feature)
794          jz      2f
795          movl    $PG_G, R(pgeflag)
796          movl    %cr4, %eax
797          orl     $CR4_PGE, %eax
798          movl    %eax, %cr4
799  2:
800  #endif
CPUID_PGE在/sys/i386/include/specialreg.h中定義為0x00002000,這是PGE標(biāo)志在
cpuid返回值中的位置。PG_G在/sys/i386/include/pmap.h中定義為0x100,此處將其賦給
全局變量pgeflag,表示開啟了全局頁面支持。CR4_PGE在/sys/i386/include/specialreg.h
中定義為0x00000080,這是PGE在cr4寄存器中的比特位置。上面這幾行的意思就是如果
cpuid指令的結(jié)果顯示cpu支持PGE,則將全局變量pgeflag設(shè)置為0x100,并將cr4寄存器中
PGE對應(yīng)比特設(shè)置為1。
814          xorl    %eax, %eax
815          movl    R(KERNend),%ecx
816          shrl    $PAGE_SHIFT,%ecx
817          fillkptphys($PG_RW)
清空eax。將KRENend的值0x1000000(16M)寫入ecx,并右移12比特,得到頁面數(shù)目
0x1000(4096)。我們先來看看fillkpt宏的代碼:
170  /*
171   * fillkpt
172   *      eax = page frame address
173   *      ebx = index into page table
174   *      ecx = how many pages to map
175   *      base = base address of page dir/table
176   *      prot = protection bits
177   */
178  #define fillkpt(base, prot)               \
179          shll    $PTESHIFT,%ebx          ; \
180          addl    base,%ebx               ; \
181          orl     $PG_V,%eax              ; \
182          orl     prot,%eax               ; \
183  1:      movl    %eax,(%ebx)             ; \
184          addl    $PAGE_SIZE,%eax         ; /* increment physical address */ \
185          addl    $PTESIZE,%ebx           ; /* next pte */ \
186          loop    1b
187
入?yún)bx是頁表內(nèi)的索引,PTESHIFT在/sys/i386/include/pmap.h中定義為2(非PAE),
179行將ebx左移2位得到的就是頁表內(nèi)的偏移地址。加上base中存放的頁表基址得到的
就是頁表項(xiàng)的地址。PG_V在/sys/i386/include/pmap.h中定義為0x001,這是頁表目錄項(xiàng)
或頁表項(xiàng)中表示對應(yīng)的頁面當(dāng)前是否在物理內(nèi)存中的標(biāo)志比特。入?yún)ax存放的頁面的
基地址,因此低12比特均為0。181和182行將eax的第0比特和第1比特置1,表示對應(yīng)頁面
存在于內(nèi)存中,屬性為讀寫。183行將在eax中構(gòu)建好的頁表項(xiàng)寫入ebx指向的頁表項(xiàng)地址。
184行在eax中構(gòu)造用于描述下一個頁面的頁表項(xiàng),185行將ebx指向下一條頁表項(xiàng)的地址,
186行循環(huán)寫入新構(gòu)建的頁表項(xiàng)。
因此,fillkpt的功能就是,給定某個頁表頁面的基地址(base)、頁面保護(hù)模式(prot)、
需要填充的第一頁表項(xiàng)在頁表頁面內(nèi)的索引(ebx)、頁面的基地址(eax)、需要填充的
頁表項(xiàng)的數(shù)目(ecx),填充從ebx開始的ecx個頁表項(xiàng),讓其指向從eax開始的ecx個連續(xù)
頁面,每個頁表項(xiàng)的第0比特置1,表示頁面存在于物理內(nèi)存中,第1比特置1,表示屬性為讀寫。
下面來看fillkptphys的代碼:
188  /*
189   * fillkptphys(prot)
190   *      eax = physical address
191   *      ecx = how many pages to map
192   *      prot = protection bits
193   */
194  #define fillkptphys(prot)                 \
195          movl    %eax, %ebx              ; \
196          shrl    $PAGE_SHIFT, %ebx       ; \
197          fillkpt(R(KPTphys), prot)
eax為頁面物理地址,將其右移12比特之后得到頁面在頁表內(nèi)的索引。fillkpt的第一
入?yún)⑹琼摫眄撁娴幕刂,這里指定的是KPTphys,這是緊鄰在KERNend之后的30個
頁面空間的起始地址(0x1000000)。 回到814到817行,這幾行的意思就是填充
KPTphys(0x1000000)之后的4096個4字節(jié)條目,每個條目指向一個頁面,這4096個條目
指向的就是從0地址到0x1000000之間的16M空間,這是之前存放內(nèi)核的地方。
這些頁面顯然已經(jīng)存在于物理內(nèi)存中,因此對應(yīng)條目的第0比特為1,第1比特為1表示
這些條目的屬性為讀寫。完成設(shè)置之后的這4096個頁表項(xiàng)的內(nèi)容如下:
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
826          movl    R(IdlePTD), %eax
827          movl    $NPGPTD, %ecx
828          fillkptphys($PG_RW)
這幾行是建立頁表目錄所在頁面的映射,NPGPTD定義為1,表示頁表目錄所占頁面為1,
IdlePTD是頁表目錄頁面的基地址0x101e000,緊鄰在KPTphys指向的30個頁面空間的
后面。此處即在前面描述內(nèi)核16M空間的4096個頁表項(xiàng)的后面再用一個頁表項(xiàng)來描述
頁表目錄頁面,屬性為讀寫。
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
0x1004000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004020 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004030 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004040 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004050 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004060 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004070 :    0x00000000      0x00000000      0x0101e003
中間空的30個條目就對應(yīng)于KPTphys指向的30個頁面。
830  /* Map proc0's KSTACK in the physical way ... */
831          movl    R(p0kpa), %eax
832          movl    $(KSTACK_PAGES), %ecx
833          fillkptphys($PG_RW)
p0kpa(0x101f000)是緊鄰在IdelPTD之后的2個頁面的空間,KSTACK_PAGES定義為2,
此處即再分配兩個頁表項(xiàng)來描述這兩個頁面,屬性為讀寫。
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
0x1004000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004020 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004030 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004040 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004050 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004060 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004070 :    0x00000000      0x00000000      0x0101e003      0x0101f003
0x1004080 :    0x01020003
835  /* Map ISA hole */
836          movl    $ISA_HOLE_START, %eax
837          movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
838          fillkptphys($PG_RW)
ISA_HOLE_START在/sys/i386/include/pmap.h中定義為0xa0000,ISA_HOLE_LENGTH
定義為0x100000-0xa0000,即393216字節(jié),96個頁面。此處即用96個頁表?xiàng)l目來映射從
0xa0000開始的96個頁面的空間。但這個空間是屬于0-KERNend的,之前已經(jīng)映射過了。
840  /* Map space for the vm86 region */
841          movl    R(vm86phystk), %eax
842          movl    $4, %ecx
843          fillkptphys($PG_RW)
再分配4個條目來映射vm86phystk(0x1021000)之后的4個頁面的空間,屬性為讀寫。
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
0x1004000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004020 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004030 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004040 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004050 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004060 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004070 :    0x00000000      0x00000000      0x0101e003      0x0101f003
0x1004080 :    0x01020003      0x01021003      0x01022003      0x01023003
0x1004090 :    0x01024003
845  /* Map page 0 into the vm86 page table */
846          movl    $0, %eax
847          movl    $0, %ebx
848          movl    $1, %ecx
849          fillkpt(R(vm86pa), $PG_RW|PG_U)
這幾行將第0頁映射到vm86pa指向的區(qū)域中,vm86pa指向的是0x1022000區(qū)域:
0x1022000 :    0x00000007      0x00000000      0x00000000      0x00000000
只映射了1頁,屬性為PG_V|PG_RS|PG_U,即0x7,表示當(dāng)前存在于物理內(nèi)存中、
可讀寫、特權(quán)級別為用戶級。
851  /* ...likewise for the ISA hole */
852          movl    $ISA_HOLE_START, %eax
853          movl    $ISA_HOLE_START>>PAGE_SHIFT, %ebx
854          movl    $ISA_HOLE_LENGTH>>PAGE_SHIFT, %ecx
855          fillkpt(R(vm86pa), $PG_RW|PG_U)
在vm86pa區(qū)域中建立ISA hole的映射,共計(jì)96個頁表?xiàng)l目:
0x1022000 :    0x00000007      0x00000000      0x00000000      0x00000000
0x1022010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1022270 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x1022280 :    0x000a0007      0x000a1007      0x000a2007      0x000a3007
0x1022290 :    0x000a4007      0x000a5007      0x000a6007      0x000a7007
0x10222a0 :    0x000a8007      0x000a9007      0x000aa007      0x000ab007
0x10222b0 :    0x000ac007      0x000ad007      0x000ae007      0x000af007
0x10222c0 :    0x000b0007      0x000b1007      0x000b2007      0x000b3007
0x10222d0 :    0x000b4007      0x000b5007      0x000b6007      0x000b7007
0x10222e0 :    0x000b8007      0x000b9007      0x000ba007      0x000bb007
0x10222f0 :    0x000bc007      0x000bd007      0x000be007      0x000bf007
0x1022300 :    0x000c0007      0x000c1007      0x000c2007      0x000c3007
0x1022310 :    0x000c4007      0x000c5007      0x000c6007      0x000c7007
0x1022320 :    0x000c8007      0x000c9007      0x000ca007      0x000cb007
0x1022330 :    0x000cc007      0x000cd007      0x000ce007      0x000cf007
0x1022340 :    0x000d0007      0x000d1007      0x000d2007      0x000d3007
0x1022350 :    0x000d4007      0x000d5007      0x000d6007      0x000d7007
0x1022360 :    0x000d8007      0x000d9007      0x000da007      0x000db007
0x1022370 :    0x000dc007      0x000dd007      0x000de007      0x000df007
0x1022380 :    0x000e0007      0x000e1007      0x000e2007      0x000e3007
0x1022390 :    0x000e4007      0x000e5007      0x000e6007      0x000e7007
0x10223a0 :    0x000e8007      0x000e9007      0x000ea007      0x000eb007
0x10223b0 :    0x000ec007      0x000ed007      0x000ee007      0x000ef007
0x10223c0 :    0x000f0007      0x000f1007      0x000f2007      0x000f3007
0x10223d0 :    0x000f4007      0x000f5007      0x000f6007      0x000f7007
0x10223e0 :    0x000f8007      0x000f9007      0x000fa007      0x000fb007
0x10223f0 :    0x000fc007      0x000fd007      0x000fe007      0x000ff007
......
0x1025fe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1025ff0 :    0x00000000      0x00000000      0x00000000      0x00000000
858  /* Map cpu0's private page into global kmem (4K @ cpu0prvpage) */
859          movl    R(cpu0pp), %eax
860          movl    $1, %ecx
861          fillkptphys($PG_RW)
繼續(xù)回到KPTphys(0x1000000)之后的頁表區(qū)域。再分配一個頁表?xiàng)l目給cpu0pp指向的
1個頁面的區(qū)域(0x1025000),屬性為讀寫。
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
0x1004000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004020 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004030 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004040 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004050 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004060 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004070 :    0x00000000      0x00000000      0x0101e003      0x0101f003
0x1004080 :    0x01020003      0x01021003      0x01022003      0x01023003
0x1004090 :    0x01024003      0x01025003
863  /* Map SMP page table page into global kmem FWIW */
864          movl    R(SMPptpa), %eax
865          movl    $1, %ecx
866          fillkptphys($PG_RW)
再分配一個頁表?xiàng)l目給SMPptpa指向的1個頁面的區(qū)域(0x1026000),屬性為讀寫。
0x1000000 :    0x00000003      0x00001003      0x00002003      0x00003003
0x1000010 :    0x00004003      0x00005003      0x00006003      0x00007003
......
0x1003fe0 :    0x00ff8003      0x00ff9003      0x00ffa003      0x00ffb003
0x1003ff0 :    0x00ffc003      0x00ffd003      0x00ffe003      0x00fff003
0x1004000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004010 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004020 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004030 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004040 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004050 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004060 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1004070 :    0x00000000      0x00000000      0x0101e003      0x0101f003
0x1004080 :    0x01020003      0x01021003      0x01022003      0x01023003
0x1004090 :    0x01024003      0x01025003      0x01026003
868  /* Map the private page into the SMP page table */
869          movl    R(cpu0pp), %eax
870          movl    $0, %ebx                /* pte offset = 0 */
871          movl    $1, %ecx                /* one private page coming right up */
872          fillkpt(R(SMPptpa), $PG_RW)
在SMPptpa(0x1026000)頁面中分配一個頁表?xiàng)l目來映射cpu0pp(0x1025000)指向的頁面,
屬性為讀寫。
0x1026000 :    0x01025003      0x00000000      0x00000000      0x00000000
874  /* ... and put the page table table in the pde. */
875          movl    R(SMPptpa), %eax
876          movl    $MPPTDI, %ebx
877          movl    $1, %ecx
878          fillkpt(R(IdlePTD), $PG_RW)
在IdlePTD指向的頁表頁面目錄中創(chuàng)建一條頁表目錄項(xiàng)來指向SMPptpa指向的SMP頁表頁面。
MPPTDI定義為1023,表示最后一個頁表目錄項(xiàng)。屬性為讀寫。我們可以看到,頁表目錄頁面
的其它頁表目錄項(xiàng)的內(nèi)容到此時仍然為空。
0x101e000 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101e010 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101efe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101eff0 :    0x00000000      0x00000000      0x00000000      0x01026003
880  /* Fakeup VA for the local apic to allow early traps. */
881          ALLOCPAGES(1)
882          movl    %esi, %eax
883          movl    $(NPTEPG-1), %ebx       /* pte offset = NTEPG-1 */
884          movl    $1, %ecx                /* one private pt coming right up */
885          fillkpt(R(SMPptpa), $PG_RW)
再分配一個頁面,此時physfree指向0x1028000。將SMPptpa(0x1026000)頁面中的最后
一個條目用來映射這個新分配的頁面,屬性為讀寫。
0x1026000 :    0x01025003      0x00000000      0x00000000      0x00000000
0x1026010 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x1026fe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x1026ff0 :    0x00000000      0x00000000      0x00000000      0x01027003
888  /*
889   * Create an identity mapping for low physical memory, including the kernel.
890   * The part of this mapping that covers the first 1 MB of physical memory
891   * becomes a permanent part of the kernel's address space.  The rest of this
892   * mapping is destroyed in pmap_bootstrap().  Ordinarily, the same page table
893   * pages are shared by the identity mapping and the kernel's native mapping.
894   * However, the permanent identity mapping cannot contain PG_G mappings.
895   * Thus, if the kernel is loaded within the permanent identity mapping, that
896   * page table page must be duplicated and not shared.
897   *
898   * N.B. Due to errata concerning large pages and physical address zero,
899   * a PG_PS mapping is not used.
900   */
901          movl    R(KPTphys), %eax
902          xorl    %ebx, %ebx
903          movl    $NKPT, %ecx
904          fillkpt(R(IdlePTD), $PG_RW)
將IdlePTD(0x101e000)頁面中的前NKPT(30)個條目用來映射KPTphys(0x1000000)
指向的30個頁面的空間,屬性為讀寫。
0x101e000 :    0x01000003      0x01001003      0x01002003      0x01003003
0x101e010 :    0x01004003      0x01005003      0x01006003      0x01007003
0x101e020 :    0x01008003      0x01009003      0x0100a003      0x0100b003
0x101e030 :    0x0100c003      0x0100d003      0x0100e003      0x0100f003
0x101e040 :    0x01010003      0x01011003      0x01012003      0x01013003
0x101e050 :    0x01014003      0x01015003      0x01016003      0x01017003
0x101e060 :    0x01018003      0x01019003      0x0101a003      0x0101b003
0x101e070 :    0x0101c003      0x0101d003      0x00000000      0x00000000
0x101e080 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101efe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101eff0 :    0x00000000      0x00000000      0x00000000      0x01026003
920  /*
921   * For the non-PSE case, install PDEs for PTs covering the KVA.
922   * For the PSE case, do the same, but clobber the ones corresponding
923   * to the kernel (from btext to KERNend) with 4M (2M for PAE) ('PS')
924   * PDEs immediately after.
925   */
926          movl    R(KPTphys), %eax
927          movl    $KPTDI, %ebx
928          movl    $NKPT, %ecx
929          fillkpt(R(IdlePTD), $PG_RW)
930          cmpl    $0,R(pseflag)
931          je      done_pde
KPTDI定義為第一個內(nèi)核頁表目錄的索引,即768。926到929行將IdlePTD(0x101e000)
頁面中的第768項(xiàng)之后的30個頁表目錄項(xiàng)用來指向KPTphys(0x1000000)指向的30個
頁面空間,屬性為讀寫。
0x101e000 :    0x01000003      0x01001003      0x01002003      0x01003003
0x101e010 :    0x01004003      0x01005003      0x01006003      0x01007003
0x101e020 :    0x01008003      0x01009003      0x0100a003      0x0100b003
0x101e030 :    0x0100c003      0x0100d003      0x0100e003      0x0100f003
0x101e040 :    0x01010003      0x01011003      0x01012003      0x01013003
0x101e050 :    0x01014003      0x01015003      0x01016003      0x01017003
0x101e060 :    0x01018003      0x01019003      0x0101a003      0x0101b003
0x101e070 :    0x0101c003      0x0101d003      0x00000000      0x00000000
0x101e080 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101ebf0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101ec00 :    0x01000003      0x01001003      0x01002003      0x01003003
0x101ec10 :    0x01004003      0x01005003      0x01006003      0x01007003
0x101ec20 :    0x01008003      0x01009003      0x0100a003      0x0100b003
0x101ec30 :    0x0100c003      0x0100d003      0x0100e003      0x0100f003
0x101ec40 :    0x01010003      0x01011003      0x01012003      0x01013003
0x101ec50 :    0x01014003      0x01015003      0x01016003      0x01017003
0x101ec60 :    0x01018003      0x01019003      0x0101a003      0x0101b003
0x101ec70 :    0x0101c003      0x0101d003      0x00000000      0x00000000
0x101ec80 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101efe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101eff0 :    0x00000000      0x00000000      0x00000000      0x01026003
930          cmpl    $0,R(pseflag)
931          je      done_pde
若全局變量pseflag為0,則跳轉(zhuǎn)至done_pde,示例中此變量為1。
933          movl    R(KERNend), %ecx
934          movl    $KERNLOAD, %eax
935          subl    %eax, %ecx
936          shrl    $PDRSHIFT, %ecx
937          movl    $(KPTDI+(KERNLOAD/(1
933行將KERNend(0x1000000)寫入ecx。934行將KERNLOAD(0x400000)寫入eax。
935行從ecx中減去eax,得到0xc00000。936行將ecx右移22比特,得到3。
937行,(KERNLOAD/(1
946  done_pde:
947  /* install a pde recursively mapping page directory as a page table */
948          movl    R(IdlePTD), %eax
949          movl    $PTDPTDI, %ebx
950          movl    $NPGPTD,%ecx
951          fillkpt(R(IdlePTD), $PG_RW)
將IdlePTD(0x101e000)頁面中的第PTDPTDI(767)個頁表目錄項(xiàng)指向IdelPTD頁面,
屬性為讀寫。
0x101e000 :    0x01000003      0x01001003      0x01002003      0x01003003
0x101e010 :    0x01004003      0x01005003      0x01006003      0x01007003
0x101e020 :    0x01008003      0x01009003      0x0100a003      0x0100b003
0x101e030 :    0x0100c003      0x0100d003      0x0100e003      0x0100f003
0x101e040 :    0x01010003      0x01011003      0x01012003      0x01013003
0x101e050 :    0x01014003      0x01015003      0x01016003      0x01017003
0x101e060 :    0x01018003      0x01019003      0x0101a003      0x0101b003
0x101e070 :    0x0101c003      0x0101d003      0x00000000      0x00000000
0x101e080 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101ebe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101ebf0 :    0x00000000      0x00000000      0x00000000      0x0101e003
0x101ec00 :    0x01000003      0x00400083      0x00800083      0x00c00083
0x101ec10 :    0x01004003      0x01005003      0x01006003      0x01007003
0x101ec20 :    0x01008003      0x01009003      0x0100a003      0x0100b003
0x101ec30 :    0x0100c003      0x0100d003      0x0100e003      0x0100f003
0x101ec40 :    0x01010003      0x01011003      0x01012003      0x01013003
0x101ec50 :    0x01014003      0x01015003      0x01016003      0x01017003
0x101ec60 :    0x01018003      0x01019003      0x0101a003      0x0101b003
0x101ec70 :    0x0101c003      0x0101d003      0x00000000      0x00000000
0x101ec80 :    0x00000000      0x00000000      0x00000000      0x00000000
......
0x101efe0 :    0x00000000      0x00000000      0x00000000      0x00000000
0x101eff0 :    0x00000000      0x00000000      0x00000000      0x01026003
960          ret
返回到btex主流程中。
294  /*
295   * If the CPU has support for VME, turn it on.
296   */
297          testl   $CPUID_VME, R(cpu_feature)
298          jz      1f
299          movl    %cr4, %eax
300          orl     $CR4_VME, %eax
301          movl    %eax, %cr4
302  1:
如果cpu支持VME,則將cr4寄存器的CR4_VME(0)比特設(shè)置為1。
312          movl    R(IdlePTD), %eax
313          movl    %eax,%cr3               /* load ptd addr into mmu */
將IdlePTD(0x101e000)寫入cr3寄存器。
315          movl    %cr0,%eax               /* get control word */
316          orl     $CR0_PE|CR0_PG,%eax     /* enable paging */
317          movl    %eax,%cr0               /* and let's page NOW! */
318
319          pushl   $begin                  /* jump to high virtualized address */
320          ret
設(shè)置cr0寄存器中的CR0_PE(打開保護(hù)模式)和CR0_PG(打開調(diào)頁機(jī)制)標(biāo)志,啟動
調(diào)頁機(jī)制。此后程序中使用的就是虛擬地址了。此處通過將begin符號所代表的虛擬
地址壓棧再立即返回的形式跳轉(zhuǎn)到虛擬地址begin處(0xc0458a99)。
322  /* now running relocated at KERNBASE where the system is linked to run */
323  begin:
324          /* set up bootstrap stack */
325          movl    proc0kstack,%eax        /* location of in-kernel stack */
326                          /* bootstrap stack end location */
327          leal    (KSTACK_PAGES*PAGE_SIZE-PCB_SIZE)(%eax),%esp
328
329          xorl    %ebp,%ebp               /* mark end of frames */
330
331  #ifdef PAE
332          movl    IdlePDPT,%esi
333  #else
334          movl    IdlePTD,%esi
335  #endif
336          movl    %esi,(KSTACK_PAGES*PAGE_SIZE-PCB_SIZE+PCB_CR3)(%eax)
337
338          pushl   physfree                /* value of first for init386(first) */
339          call    init386                 /* wire 386 chip for unix operation */
325行將內(nèi)核棧起始地址proc0kstack(0xc101f000)寫入eax,內(nèi)核棧共有兩個頁面,
8192字節(jié),pcb結(jié)構(gòu)體的尺寸是624字節(jié),從這兩個頁面的頂端去掉624字節(jié)之后,
將esp指向向下增長的起始位置(proc0kstack+(8192-624)),即0xc1020d90。
329行將ebp清0。334行將IdlePTD(0x101e000)寫入esi。將esi的內(nèi)容(IdlePTD所表示的
頁表目錄頁面的物理地址)寫入內(nèi)核棧中的pcb結(jié)構(gòu)體中的pcb_cr3字段。
physfree目前指向的是0x01028000,這是之前分配完SMPptpa之后的位置。此處將其壓棧,
作為入?yún)irst調(diào)用init386函數(shù)。


本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u/9831/showart_1149550.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP