__arm920_setup과 __enable_mmu에서 설정한 제어 레지스터의 값(R0)을 실제로 CP15 Register 1, control register 에 저장한다. 이제부터 MMU가 작동하고 가상 메모리 공간을 사용하게 된다. 모든 메모리 주소 참조는 주소 변환 과정을 거친다. IP 레지스터에 저장되어 있던 __mmap_switched 로 분기한다.
 
[__mmap_switched ] /arch/arm/kernel/head-common.S
 
__data_loc과 __data_start의 위치가 다를 경우 __data_start 부터 __bss_start 까지 __data_loc에 위치한 데이터를 복사한다. XIP 커널은 ROM에 있는 data 섹션(__data_loc)의 내용을 RAM(__data_start)으로 복사해야 한다.
BSS 영역을 0으로 초기화한다. CP15 Register 0 에서 읽어온 ID code (R9)와 부트로더 에서 넘긴 ARCH 넘버(R1)를 arch/arm/kernel/setup.c의 processor_id와 __machine_arch_type 변수에 저장한다.

__enable_mmu에서 처리했던 CP15 Register 1, control register 의 값(R0)을
arch/arm/kernel/entry-armv.S의 cr_alignment에 저장하고, A bit(Alignment Fault Checking)을 클리어 한 값을 cr_no_alignment에 저장하고,
스택포인터(sp)를 init_thread_union + THREAD_START_SP 로 설정한다. 

start_kernel 로 분기한다.

'리눅스커널' 카테고리의 다른 글

[ volatile , barrier ]  (0) 2009.10.02
Memory Barrier  (0) 2009.10.02
[ __enable_mmu ] arch/arm/kernel/head.S  (0) 2009.10.02
[ __arm920_setup ] arch/arm/mm/proc-arm920.S  (0) 2009.10.02
[ __create_page_tables ] /arch/arm/kernel/head.S  (0) 2009.10.02
Posted by blee
,
kernel 설정에 따라 CP15 Register 1 에 적용될 값을 설정한다.
CP15 Register 3, domain access control register 에 접근 권한을 설정한다.
CP15 Register 2, translation table base(TTB) register 에 페이지 테이블을 주소를 정한다.

 kernel 설정  비트   의미
  CONFIG_ALIGNMENT_TRAP
CR_A
 데이터 주소 정렬 여부 검사
  CONFIG_CPU_DCACHE_DISABLE
CR_C
 D-Cache disable
  ONFIG_CPU_BPREDICT_DISABLE
CR_Z
 예약됨
  CONFIG_CPU_ICACHE_DISABLE
CR_I
 I-Cache disable

 No  Domain   Type
 0
 DOMAIN_KERNEL
  DOMAIN_MANAGER
 0
 DOMAIN_TABLE
  DOMAIN_MANAGER
 1
 DOMAIN_USER
  DOMAIN_MANAGER
 2
 DOMAIN_IO
  DOMAIN_CLIENT

Posted by blee
,
proc_info_list의 __cpu_flush에 저장되어 있던 분기 명령이 실행되면서 ARM920 일경우 __arm920_setup으로 이동한다. I-Cache와 D-Cache를 무효화(invalidate)하고 쓰기 버퍼의 내용도 비운다. 더불어 I/D-TLB도 무효화한다.
CP15 제어 레지스터를 읽어서 MMU, Cache 관련 비트를 설정한다. (R0 레지스터)
 

[ __v6_setup ] arch/arm/mm/proc-v6.S


proc_info_list의 __cpu_flush에 저장되어 있던 분기 명령이 실행되면서 ARMv6 일경우
__v6_setup으로 이동한다.
I-Cache와 D-Cache를 무효화(invalidate)하고 쓰기 버퍼의 내용도 비운다. 더불어 I/D-TLB도 무효화한다.
CP15 제어 레지스터를 읽어서 MMU, Cache 관련 비트를 설정한다. (R0 레지스터)
 
Posted by blee
,
페이지 테이블을 KERNEL_RAM_PADDR - 0x4000(16K)에 만든다. 이 영역을 모두 0 으로 초기화 하고, struct proc_info_list 의 PROCINFO_MM_MMUFLAGS 값에 해당하는 __cpu_mm_mmu_flags  값을 읽어 와서 적용한다. 현재 PC가 있는 1Mbyte 영역과 MMU가 enable 되었을 때를 대비한 커널영역에 대한 1차 페이지 테이블을 생성하게 된다. 부트로더로 부터 전달되는 부트 파라미터에 대한 영역도 만들어 준다.
SMDK2410 일 경우, 물리메모리는 0x30000000 에서 시작, 커널은 0x30008000 에 있다. 이때 PC값은 0x30008000 보다 큰 어디를 가르키고 있을 것이다.

swapper_pg_dir ( 0xC0004000 )
 0ffset  Level 1 descriptor 
 0x000 * 4  
  :  
 0x300 * 4  0x300 << 20 |  __cpu_mm_mmu_flags
  :  
 0xC00 * 4  0xC00 << 20 |  __cpu_mm_mmu_flags
 0xC01 * 4  0xC01 << 20 |  __cpu_mm_mmu_flags
 0xC02 * 4  0xC02 << 20 |  __cpu_mm_mmu_flags
  :  
 0xFFF * 4  

Posted by blee
,
__arch_info_begin 부터 __arch_info_end 까지 ( 섹션 .arch.info.init 영역 )  저장된 machine_desc 구조체에서 MACHINFO_TYPE 값에 해당하는, 변수 nr 을 읽어 온다.

 이 값이 부
터로드에서 넘긴 arch 넘버(R1)와 같은지 비교하고, 같으면 리턴하고, 다르면 machine_desc 구조체 만큼 증가하여 __arch_info_end 까지 반복하게 된다. 성공 하면, R5 은 일치하는 machine_desc 구조체의 시작 주소를 가지게 되고, 실패하면 R5에 0값을 대입한다.

섹션 .arch.info.init 영역은 컴파일 시에 MACHINE_START define 에 의해서 저장되게 된다.
include/asm-arm/mach/arch.h 에 정의 되어 있다.

#define MACHINE_START(_type,_name)
          \
static const struct machine_desc __mach_desc_##_type    \
 __attribute_used__                 \
 __attribute__((__section__(".arch.info.init"))) = {    \
    .nr     = MACH_TYPE_##_type,        \
    .name       = _name,
MACH_TYPE_##_type 은 arch/arm/tools/mach-types 에 그 값들이 정의 되어 있다.

각 arch 별로 아래와 같은 정의가 존재한다.

// arch/arm/mach-s3c2410/mach-smdk2410.c
MACHINE_START(SMDK2410, "SMDK2410")
// arch/arm/mach-realview/realview_eb.c
MACHINE_START(REALVIEW_EB, "ARM-RealView EB“)
Posted by blee
,
 __proc_info_begin 부터 __proc_info_end 까지 ( 섹션 .proc.info.init 영역 )  저장된 proc_info_list 구조체에서 cpu_val, cpu_mask 값을 읽어 온다.

호출 되기전 R9에 Process ID가 저장되어 있고,
이 값을 읽어온 cpu_mask 과 mask 하고, cpu_val 과 같은 지 비교한다.

같으면, 리턴하고, 다르면 proc_info_list 구조체 만큼 이동하며 __proc_info_end 까지 반복한다.
성공 하면, R5 은 일치하는 proc_info_list 구조체의 시작 주소를 가지게 되고, 실패하면 R5에 0값을 대입한다.
Posted by blee
,
FIQ, IRQ 를 Disable 하고, SVC 모드로 한다.
CP15 Register 0 에서 Process ID 를 읽어 온다.
__lookup_processor_type 를 호출하고, 결과를 R10 에 저장한다. 결과가 0 이라면, __error_p 로 분기한다.
__loopup_machine_type 를 호출하고, 결과를 R8 에 저장한다. 결과가 0 이라면, __error_a 로 분기한다.
__create_page_table 를 호출하여, 페이지 테이블을 생성한다.
R13 에 __switch_data  주소를 저장하고, LR 에 __enalbe_mmu  주소를 저장하고, proc_info_list 구조체의 PROCINFO_INITFUNC 으로 PC 값을 바꾼다.
arch 별로 proc-***.S 파일 형태로 구분되어 있는 setup 코드를 수행한다.

ARM920T (arch/arm/mm/proc-arm920.S)
__arm920_setup
 
V6  (arch/arm/mm/proc-v6.S )
__v6_setup
Posted by blee
,

ARM Instruction

리눅스커널 2009. 10. 2. 08:40

볼때 마다 헤깔리는 명령어다.

STMIA,STMIB,STMDA,STMDB R13,{R0,R1,R2}
STMEA,STMFA,STMED,STMFD R13,{R0,R1,R2}


 수행전

   N+C
   N+8
   N+4
 R13 ->  N
   N-4
   N-8
   N-C

STMIA, STMEA

 R13 ->
   R2
   R1
   R0
   
   
   

STMIB, STMFA

 R13 ->  R2
   R1
   R0
   
   
   
   

STMDA, STMED

 
   
   
   R2
   R1
   R0
 R13 ->   

STMDB, STMFD

 
   
   
   
   R2
   R1
 R13 ->  R0


 

Posted by blee
,
- 다운로드

Kernel.2.6.21
Kernel 2.6.21 Patch
Toolchain
 
- 압축해제 및 패치

$ tar jxvf linux-2.6.21.tar.bz2
$ gzip -d patch-2.6.21-arm1.gz
$ gzip -d patch-2.6.21-arm1-t2_1.gz
$ cd linux-2.6.21
$ cat ../patch-2.6.21-arm1 | patch -p1
[x] $ cat ../patch-2.6.21-arm1-t2_1 | patch -p1

- s3c2410 설정
$ cp arch/arm/configs/s3c2410_defconfig .config

- ARM11(V6), SMP 설정
$ cp arch/arm/configs/realview-smp_defconfig .config

- 컴파일 및 ctags, cscope 생성
$ make V=1 ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi-
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- tags
$ make ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- cscope
$ arm-none-linux-gnueabi-objdump -d vmlinux > vmlinux.objdump
Posted by blee
,