[Linux] sudo 사용을 위한 sudoers 설정

sudo 에 관한 설정을 바꿀 때는 /etc/sudoers 파일을 직접 고치는 것 보다는 /etc/sudoers.d/ 안에 설정 파일을 추가하는 것이 좋다.

새로운 사용자를 추가하려면 다음과 같이 파일을 추가한다.

vi /etc/sudoers.d/011_dasomoli-sudoer

dasomoli ALL=(ALL)   ALL

추가한 파일은 0440으로 권한을 바꿔준다.

chmod 0440 /etc/sudoers.d/011_dasomoli-sudoer

 

sudo를 할 때 아예 패스워드를 묻지 않게 할 수도 있는데, 라즈베리 파이3의 경우, 이를 이용해서 기본 계정의 경우 sudo 시 패스워드를 묻지 않도록 하고 있다.

vi /etc/sudoers.d/010_pi-nopasswd

pi ALL=(ALL) NOPASSWD: ALL

 

그러나 sudo 그룹이 있는 경우가 많으므로, 사실 위 보다는 그냥 아래 명령을 root권한으로 주는 것이 더 낫다.

# usermod -aG sudo username

[Linux:Kernel] string 처리 개선

String copying

ssize_t strscpy(char *dest, const char *src, size_t count);

ssize_t strscpy_truncate(char *dest, const char *src, size_t count);

strscpy()는 src에서 dest로 최대 count bytes를 copy한다. source string이 count bytes보다 긴 경우를 제외하고는 copy된 bytes 수를 리턴한다. 긴 경우는 -E2BIG을 리턴한다. 다른 차이는 overflow 나는 경우는 src를 truncate하는게 아니라 dest가 empty string이 된다. 에러 체크를 항상 하면 괜찮은데, 안하는 경우, truncate된 string이 문제를 일으키는 일이 많기 때문에 이렇게 동작한다고 한다.

truncate된 string이 필요한 경우는 아래 버전을 사용하면 된다. 리턴 값은 같지만, null-terminate된 truncate된 string이 dest에 들어간다.

Integer parsing

simple_strto*() 함수가 많이 사용되지만, checkpatch가 불평하듯, kstrto*()가 더 낫다. 그런데, simple_strto*()는 “123abc”와 같은 string을 123으로 변환하는데, 이게 편리한 경우도 있다. 그래서 새로운 함수가 제안되었다.

int parse_integer(const char *s, unsigned int base, <type> *val);

사실, parse_integer()는 함수가 아니라 val의 타입에 맞는 여러가지 매크로이다. val이 unsigned short라면, 디코딩은 unsigned를 기초로 하고, 결과값이 short의 범위를 벗어나지 않는지 확인된다.

최종 결과는 val안에 담기고, 디코딩된 char 수가 리턴된다. 전체 string이 decode됐는지는 s[return_value] 가 null byte인지를 체크하면 된다. null-terminate string이면 원래 s[strlen(s)]는 ‘\0’일 테니까. 아니라면, 그 곳에 parsing하는 string이 계속 있을 거다. base가 문서화되지 않은 값 PARSE_INTEGER_NEWLINE과 or되면, 맨 마지막의 newline character는 무시-sysfs file로의 input을 parsing할 때 유용하다-된다. 아무 character도 convert되지 않으면, -EINVAL을 리턴한다. overflow인 경우 -ERANGE를 리턴한다.

출처: Improving kernel string handling(http://lwn.net/Articles/643376/)

[Linux:Kernel] Documentation/io-mapping.txt

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under GPL license).
Documentation/io-mapping.txt
번역: 양정석 <dasomoli@gmailREMOVETHIS.com>
linux/io-mapping.h 안의 io_mapping 함수들은 CPU에 I/O 디바이스들의 작은 영역을
효율적으로 맵핑하는 추상화를 제공합니다. 애초의 용도는 ioremap_wc가 커널 주소
영역을 너무 많이 소비할 때 처럼 CPU에 전체 영역을 정적으로 맵핑할 수 없을 때,
32비트 프로세서들에서 큰 그래픽 영역을 제공하기 위함입니다.
맵핑 객체는 드라이버 초기화 중에 다음을 사용하여 생성합니다
        struct io_mapping *io_mapping_create_wc(unsigned long base,
                                                unsigned long size)
                ‘base’는 맵핑 가능하게 만들어 질 영역의 버스 주소인 반면,
                ‘size’는 얼마나 크게 영역을 맵핑할 것인지를 나타냅니다.
                둘다 바이트 수 입니다.
                이 _wc 변형은 io_mapping_map_atomic_wc나 io_mapping_map_wc로만
                사용할 수 있는 맵핑을 제공합니다.
이 맵핑 객체로, 개별 페이지들이 자동적으로, 혹은 아니게 필요한 스케줄링 환경에
따라 맵핑될 수 있습니다. 물론, 어토믹 맵핑은 더 효율적입니다:
        void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
                                       unsigned long offset)
                ‘offset’은 정의된 맵핑 영역 안에서의 오프셋입니다. 생성 함수
                에서 지정된 영역을 넘어서서 주소를 접근하는 것은 정의되지
                않은 결과를 불러옵니다. 페이지 정렬되지 않은 오프셋을
                사용하는 것도 정의되지 않은 결과를 불러옵니다. 반환 값은
                CPU 주소 공간 안의 한 페이지를 가리킵니다.
                이 _wc 변형은 페이지로의 write-combining 맵핑을 반환하고,
                io_mapping_create_wc에 의해 생성된 맵핑에만 사용가능합니다.
                태스크가 이 맵핑된 페이지를 잡고 있는 동안 슬립하지 않음을
                알아두세요.
        void io_mapping_unmap_atomic(void *vaddr)
                ‘vaddr’은 반드시 마지막 io_mapping_map_atomic_wc 호출에
                의해 반환된 값이어야 합니다. 이것은 지정된 페이지를 맵핑
                해제하고 그 태스크가 다시 한번 잠들 수 있게 합니다.
여러분이 그 락을 잡은 동안 슬립해야할 필요가 있다면, 극히 더 느리긴 하지만,
어토믹이 아닌 변형을 사용할 수 있습니다.
        void *io_mapping_map_wc(struct io_mapping *mapping,
                                unsigned long offset)
                이것은 태스크가 맵핑된 페이지를 잡고 있는 동안 슬립할 수 있다는
                것을 제외하면 io_mapping_map_atomic_wc와 같이 동작합니다.
        void io_mapping_unmap(void *vaddr)
                이것은 io_mapping_map_wc로 매핑된 페이지들이 사용되는 것을
                제외하면 io_mapping_unmap_atomic과 같이 동작합니다.
드라이버에 가까운 시간에, io_mapping 객체는 반드시 해제되어야만 합니다:
        void io_mapping_free(struct io_mapping *mapping)
현재 구현:
이들 함수의 초기 구현은 이미 구현된 맵핑 메카니즘을 사용해서 오직 추상 계층만
제공하고 새로운 기능은 없습니다.
64비트 프로세서에서 io_mapping_create_wc는 자원으로의 영구적으로 커널이 볼 수
있는 맵핑을 생성하는 전체 영역을 위해서 ioremap_wc를 호출합니다. 그 map_atomic과
map 함수들은 ioremap_wc에 의해 반환되는 가상 주소의 기준점으로부터의 요청된
오프셋을 더합니다.
HIGHMEM이 정의된 32비트 프로세서에서는 io_mappinc_map_atomic_wc가
kmap_atomic_pfn을 지정된 페이지를 어토믹하게 맵핑하는데 사용됩니다;
kmap_atimic_pfn은 디바이스 페이지와 사용될 것이라고 정말 여겨지지 않았습니다만,
이 용도를 위한 효율적인 맵핑을 제공합니다.
HIGHMEM 정의가 없는 32비트 프로세서에서는 io_mapping_map_atomic_wc와
io_mapping_map_wc 모두 새로운 맵핑을 모든 프로세서에 알리기 위해서 IPI를 수행하는
극악하게 비효율적인 함수인 ioremap_wc를 사용합니다. 이것은 극적인 성능 저하를
가져옵니다.

[Linux:Kernel] Documentation/printk-formats.txt

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under GPL license).

변수가 아래 타입이라면,           printk형식 지시자를 사용하세요:
———————————————————
                int                     %d 나 %x
                unsigned int            %u 나 %x
                long                    %ld 나 %lx
                unsigned long           %lu 나 %lx
                long long               %lld 나 %llx
                unsigned long long      %llu 나 %llx
                size_t                  %zu 나 %zx
                ssize_t                 %zd 나 %zx

가공되지 않은 포인터 값은 %p로 출력되는 것이 ‘좋습니다’. 커널은 포인터
형식을 위해 다음의 확장된 형식 지시자를 지원합니다:

심볼/함수 포인터:

        %pF     versatile_init+0x0/0x110
        %pf     versatile_init
        %pS     versatile_init+0x0/0x110
        %pSR    versatile_init+0x9/0x110
                (__builtin_extract_return_addr() 변환으로)
        %ps     versatile_init
        %pB     prev_fn_of_versatile_init+0x88/0x88

        심볼과 함수 포인터를 출력하기 위해서, (‘S’)로 오프셋과 함께, 혹은 (‘s’)로
        오프셋 없이, ‘S’와 ‘s’ 지시자들로 심볼 이름을 나타냅니다. KALLSYMS 없는
        커널 상에서 사용되면, 심볼 주소가 대신 출력됩니다.

        ‘B’ 지시자는 오프셋과 함께 심볼 이름을 나타내고, 스택 트레이스를 출력할
        때 사용되어야 합니다. 이 지시자는 Tail-Call이 사용되고, noreturn GCC 속성으로
        표시되었을 때 일어날 컴파일러 최적화의 효과를 고려하게 합니다.

        ia64, ppc64, 그리고 parisc64 아키텍처에서 함수 포인터들은 실제로는
        가장 먼저 풀어야 할 함수 기술자들입니다. ‘F’와 ‘f’ 지시자는 이 해결을
        수행하여 ‘S’와 ‘s’ 지시자와 같은 기능을 제공합니다.

커널 포인터:

        %pK     0x01234567 나 0x0123456789abcdef

        권한이 없는 사용자에게 가려져야 할 커널 포인터를 출력하기 위해서 사용.
        %pK의 동작은 kptr_restrict sysctl에 의존적입니다.
        – 더 자세한 사항은 Documentation/sysctl/kernel.txt를 보세요.

구조체 자원:

        %pr     [mem 0x60000000-0x6fffffff flags 0x2200] or
                [mem 0x0000000060000000-0x000000006fffffff flags 0x2200]
        %pR     [mem 0x60000000-0x6fffffff pref] or
                [mem 0x0000000060000000-0x000000006fffffff pref]

        구조체 자원을 출력하기 위해 사용. ‘R’과 ‘r’ 지시자는 디코딩된 플래그
        멤버들이 있게(‘R’) 혹은 없게(‘r’) 자원을 출력합니다.

phys_addr_t 타입의 물리 주소:

        %pa[p]  0x01234567 나 0x0123456789abcdef

        CPU 데이터 경로의 너비와 상관없이, 빌드 옵션에 의해서 다양하게 될 수 있는
        phys_addr_t 타입(그리고 resource_size_t 같은 그 변형)의 출력을 위해서 사용.
        참조로 넘김.
        

dma_addr_t 타입의 DMA 주소:

        %pad    0x01234567 나 0x0123456789abcdef

        CPU 데이터 경로의 너비와 상관없이, 빌드 옵션에 의해서 다양하게 될 수 있는
        dma_addr_t 타입의 출력을 위해서 사용. 참조로 넘김.

16진수 문자열의 비가공 버퍼:
        %*ph    00 01 02  …  3f
        %*phC   00:01:02: … :3f
        %*phD   00-01-02- … -3f
        %*phN   000102 … 3f

        명확한 구분자로 된 16진수 문자열로 작은 버퍼(64 바이트 길이까지의)를
        출력할 때 사용. 더 큰 버퍼는 print_hex_dump()의 사용을 고려하세요.

MAC/FDDI 주소:

        %pM     00:01:02:03:04:05
        %pMR    05:04:03:02:01:00
        %pMF    00-01-02-03-04-05
        %pm     000102030405
        %pmR    050403020100

        16진수 표기로 된 6바이트 MAC/FDDI 주소를 출력할 때 사용. ‘M’과
        ‘m’ 지시자는 바이트 구분자가 있게(‘M’) 혹은 없게(‘m’) 주소를 출력합니다.
        기본 바이트 구분자는 콜론(‘:’)입니다.

        FDDI 주소들이 쓰이는 곳에서 ‘F’ 지시자는 기본 구분자 대신에 대시(‘-‘)
        구분자를 사용하기 위해서 ‘M’ 지시자 이후에 사용될 수 있습니다.

        블루투스 주소를 위해서 리틀 엔디언으로 된 블루투스 주소의 보이는 형태의
        거꾸로 된 바이트 순서 맞춤을 사용하기 위해서 ‘R’ 지시자가 쓰이면 좋습니다.

IPv4 주소:

        %pI4    1.2.3.4
        %pi4    001.002.003.004
        %p[Ii]4[hnbl]

        IPv4의 점으로 구분된 10진수 주소를 출력할 때 사용. ‘I4’와 ‘i4’ 지시자는
        앞 쪽 0들이 있게(‘i4’) 혹은 없게(‘I4’) 주소를 출력합니다.

        덧붙는 ‘h’, ‘n’, ‘b’, 그리고 ‘l’ 지사자들은 각각 호스트, 네트워크,
        빅 또는    리틀 엔디언 주소를 나타내는데 사용됩니다. 아무 지시자가 없다면,
        기본 네트워크/빅 엔디언 오더가 사용됩니다.

IPv6 주소:

        %pI6    0001:0002:0003:0004:0005:0006:0007:0008
        %pi6    00010002000300040005000600070008
        %pI6c   1:2:3:4:5:6:7:8

        IPv6 네트워크-오더 16비트 16진수 주소를 출력할 때 사용. ‘I6’와 ‘i6’
        지시자는 콜론 구분자가 있게(‘I6’) 혹은 없게(‘i6’) 주소를 출력합니다.
        앞 쪽의 0들은 항상 사용됩니다.
        
        덧붙는 ‘c’ 지시자는 ‘I’ 지시자와 함께 http://tools.ietf.org/html/rfc5952에
        쓰여 있는 압축된 IPv6 주소를 출력하는데 사용할 수 있습니다.

IPv4/IPv6 주소 (일반적인, 포트와 함께, flowinfo, 범위):

        %pIS    1.2.3.4         나 0001:0002:0003:0004:0005:0006:0007:0008
        %piS    001.002.003.004 나 00010002000300040005000600070008
        %pISc   1.2.3.4         나 1:2:3:4:5:6:7:8
        %pISpc  1.2.3.4:12345   나 [1:2:3:4:5:6:7:8]:12345
        %p[Ii]S[pfschnbl]

        그 타입이 AF_INET인지 AF_INET6인지 구분할 필요 없이 IP 주소를 줄력할 때
        사용. ‘IS’ 또는 ‘iS’를 통해 지정된 유효한 ‘struct socketaddr’로의
        포인터는 이 형식 지시자에게 넘겨질 수 있습니다.

        덧붙는 ‘p’, ‘f’, 그리고 ‘s’ 지시자는 포트(IPv4, IPv6), flowinfo(IPv6),
        범위(IPv6)를 지정하는데 사용됩니다. 포트는 “:” 접두어를 갖고, flowinfo는
        ‘/’, 그리고 스코프는 ‘%’를 갖고, 각각 실제 값이 뒤 따릅니다.

        IPv6 주소의 경우에 http://tools.ietf.org/html/rfc5952에서 기술된
        압축된 IPv6 주소는 지시자 ‘c’를 사용하면 사용됩니다. IPv6 주소는
        추가적인 지시자        ‘p’, ‘f’, ‘s’의 경우에
        https://tools.ietf.org/html/draft-ietf-6man-text-addr-representation-07 에
        제안된 것처럼 ‘[‘, ‘]’로 둘러싸입니다.

        IPv4 주소의 경우, 덧붙는 ‘h’, ‘n’, ‘b’, 그리고 ‘l’ 지시자가 잘 사용될 수
        있고, IPv6 주소의 경우에는 무시됩니다.

        더 많은 예제:

        %pISfc          1.2.3.4         나 [1:2:3:4:5:6:7:8]/123456789
        %pISsc          1.2.3.4         나 [1:2:3:4:5:6:7:8]%1234567890
        %pISpfc         1.2.3.4:12345   나 [1:2:3:4:5:6:7:8]:12345/123456789

UUID/GUID 주소:

        %pUb    00010203-0405-0607-0809-0a0b0c0d0e0f
        %pUB    00010203-0405-0607-0809-0A0B0C0D0E0F
        %pUl    03020100-0504-0706-0809-0a0b0c0e0e0f
        %pUL    03020100-0504-0706-0809-0A0B0C0E0E0F

        16바이트 UUID/GUID 주소를 출력하기 위해 사용. 덧붙는 ‘l’, ‘L’, ‘b’,
        그리고, ‘B’ 지시자는 리틀 엔디언 오더를 소문자(‘l’) 또는 대문자(‘L’)
        16진수 문자로 – 그리고 빅 엔디언 오더를 소문자(‘b’) 또는 대문자(‘B’)
        16진수 문자로 표시하는데 사용됩니다.

        아무 추가 지시자도 붙지 않으면 기본으로 리틀 엔디언 오더에 소문자로
        출력될 것입니다.

dentry 이름:
        %pd{,2,3,4}
        %pD{,2,3,4}

        dentry 이름을 출력하는데 사용; 만약 우리가 d_move()로 경쟁 상태를 만들면,
        그 이름은 오래된 것과 새 것이 섞일 것입니다. 웁스를 일으키지 않습니다.
        %pd dentry는 우리가 사용하곤 했던 %s dentry->d_name.name와 같지만 더
        안전합니다. %pd<n>은 마지막 n 컴포넌트를 출력합니다. %pD는 struct file에
        같은 동작을 합니다.

struct va_format:

        %pV

        struct va_fotmat 구조체를 출력하는데 사용. 이들은 다음과 같은 va_list와
        형식 문자열을 포함합니다:

        struct va_format {
                const char *fmt;
                va_list *va;
        };

        형식 문자열이나 va_list 인자들의 정확성을 확인하기 위한 어떤 메카니즘 없이
        이 기능을 사용하지 마세요.

u64는 %llu/&llx로 ‘출력해야’ 합니다:

        printk(“%llu”, u64_var);

s64는 %lld/%llx로 ‘출력해야’ 합니다:

        printk(“%lld”, s64_var);

Example:
<type>이 그 크기의 설정 옵션(예를 들면, sector_t, blkcnt_t)이나 그 크기의 아키텍처
(예를 들면, tcflag_t)에 의존적이라면, 가능한 가장 큰 타입의 형식 지시자를 쓰고
명시적으로 형을 변환하세요.
예제:

        printk(“test: sector number/total blocks: %llu/%llu\n”,
                (unsigned long long)sector, (unsigned long long)blockcount);

다시 알림: sizeof() 결과는 size_t 타입입니다.

여러분의 협력과 주의에 감사합니다.
By Randy Dunlap <rdunlap@infradead.org> and
Andrew Murray <amurray@mpc-data.co.uk>
그리고 우리말 번역에 양정석 <dasomoli@gmail.com>

[Linux:Kernel] AArch64 리눅스의 메모리 배치

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

Documentation/arm64/memory.txt

     AArch64 리눅스의 메모리 배치
     ============================

Author: Catalin Marinas <catalin.marinas@arm.com>
번역  : 양정석 <dasomoli@gmailREMOVETHIS.com>
Date  : 20 February 2012

이 문서는 AArch64 리눅스 커널이 사용하는 가상 메모리 배치를 설명합니다.
이 아키텍처는 4KB 페이지 크기의 4단계 변환 테이블과 64KB 페이지 크기의
3단계 변환 테이블을 허용합니다.

AArch64 리눅스는 유저와 커널 양 쪽 모두 39비트 (512GB) 가상 주소를 허용하는
4KB 페이지 설정의 3단계 변환 테이블을 사용합니다. 64KB 페이지는 오직
2단계 변환 테이블이 사용되지만 메모리 배치는 같습니다.

유저 주소는 63:39 비트가 0으로 셋팅되는 반면, 커널 주소는 같은 곳의 비트에
1로 셋팅됩니다. TTBRx 선택은 가상 주소의 비트 63에 의해 결정됩니다.
swapper_pg_dir은 오직 커널 (전역) 맵핑만 포합하는 반면,
유저 pgd는 오직 유저 (비전역) 맵핑만 포함합니다. swapper_pgd_dir 주소는
TTBR1으로 쓰여지고, TTBR0로 절대 쓰여지지 않습니다.


4KB 페이지의 AArch64 리눅스 메모리 배치:

시작 크기 용도
———————————————————————–
0000000000000000 0000007fffffffff 512GB 유저

ffffff8000000000 ffffffbbfffeffff ~240GB vmalloc

ffffffbbffff0000 ffffffbbffffffff  64KB [guard page]

ffffffbc00000000 ffffffbdffffffff   8GB vmemmap

ffffffbe00000000 ffffffbffbbfffff  ~8GB [guard, 추후 vmmemap]

ffffffbffa000000 ffffffbffaffffff  16MB PCI I/O 공간

ffffffbffb000000 ffffffbffbbfffff  12MB [guard]

ffffffbffbc00000 ffffffbffbdfffff   2MB 고정 맵핑

ffffffbffbe00000 ffffffbffbffffff   2MB [guard]

ffffffbffc000000 ffffffbfffffffff  64MB 모듈들

ffffffc000000000 ffffffffffffffff 256GB 커널 논리 메모리 맵


64KB 페이지의 AArch64 리눅스 메모리 배치:

시작 크기 용도
———————————————————————–
0000000000000000 000003ffffffffff   4TB 유저

fffffc0000000000 fffffdfbfffeffff  ~2TB vmalloc

fffffdfbffff0000 fffffdfbffffffff  64KB [guard page]

fffffdfc00000000 fffffdfdffffffff   8GB vmemmap

fffffdfe00000000 fffffdfffbbfffff  ~8GB [guard, 추후 vmmemap]

fffffdfffa000000 fffffdfffaffffff  16MB PCI I/O 공간

fffffdfffb000000 fffffdfffbbfffff  12MB [guard]

fffffdfffbc00000 fffffdfffbdfffff   2MB 고정 맵핑

fffffdfffbe00000 fffffdfffbffffff   2MB [guard]

fffffdfffc000000 fffffdffffffffff  64MB 모듈들

fffffe0000000000 ffffffffffffffff   2TB 커널 논리 메모리 맵


4KB 페이지의 변환 테이블 탐색:

+——–+——–+——–+——–+——–+——–+——–+——–+
|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
+——–+——–+——–+——–+——–+——–+——–+——–+
 |                 |         |         |         |         |
 |                 |         |         |         |         v
 |                 |         |         |         |   [11:0]  페이지 내의 오프셋
 |                 |         |         |         +-> [20:12] L3 인덱스
 |                 |         |         +———–> [29:21] L2 인덱스
 |                 |         +———————> [38:30] L1 인덱스
 |                 +——————————-> [47:39] L0 인덱스 (미사용)
 +————————————————-> [63] TTBR0/1


64KB 페이지의 변환 테이블 탐색:

+——–+——–+——–+——–+——–+——–+——–+——–+
|63    56|55    48|47    40|39    32|31    24|23    16|15     8|7      0|
+——–+——–+——–+——–+——–+——–+——–+——–+
 |                 |    |               |              |
 |                 |    |               |              v
 |                 |    |               |            [15:0]  페이지 내의 오프셋
 |                 |    |               +———-> [28:16] L3 인덱스
 |                 |    +————————–> [41:29] L2 인덱스 (38:29 만 사용)
 |                 +——————————-> [47:42] L1 인덱스 (미사용)
 +————————————————-> [63] TTBR0/1

KVM을 사용할 때, 하이퍼바이저는 커널 페이지를 EL2에서 커널 VA로부터 고정된
오프셋(커널 VA의 상위 24비트를 0으로 셋팅한)에 맵핑합니다:

시작 크기 용도
———————————————————————–
0000004000000000 0000007fffffffff 256GB HYP 내에서 맵핑된 커널 객체

[Linux:Kernel] AArch64 리눅스 부팅(AArch64 Linux Booting)

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

Documentation/arm64/booting.txt

AArch64 리눅스 부팅

===================

Author: Will Deacon <will.deacon@arm.com>
번역  : 양정석 <dasomoli@gmailREMOVETHIS.com>
Date  : 07 September 2012

이 문서는 Russell King의 ARM 부팅 문서에 기초하고 AArch64 리눅스 커널의
모든 공개 릴리즈와 연관됩니다.

AArch64 예외 모델은 몇 개의 예외 단계(EL0 – EL3)으로, 그 중 EL0와 EL1은
시큐어와 논-시큐어 구성을 가지는 것으로 구성되어 있습니다. EL2는
하이퍼바이저 단계이고 논-시큐어 모드에서만 존재합니다. EL3는 가장 높은
단계이고, 시큐어 모드에서만 존재합니다.

이 문서의 목적에 따라, 우리는 ‘부트 로더’ 용어를 간단히 리눅스 커널로
제어를 넘기기 전에 CPU(들) 상에서 실행되는 모든 소프트웨어로 정의하여
사용할 것입니다. 이것은 시큐어 모니터와 하이퍼바이저 코드를 포함할 것이고,
또는 최소 부팅 환경을 준비하기 위한 한 줌의 명령들이 될 수도 있습니다.

기본적으로, 부트 로더는 다음을 (최소한) 제공해야 합니다:

1. RAM을 셋업하고 초기화
2. 디바이스 트리를 셋업
3. 커널 이미지를 압축 해제
4. 커널 이미지를 호출
1. RAM을 셋업하고 초기화
————————

요구 사항: 필수

부트 로더는 커널이 시스템 상의 임시 데이터 저장 공간으로 사용할 모든
RAM을 찾아서 초기화할 것으로 여겨집니다. 이는 머신 의존적인 방법으로
수행됩니다. (자동으로 모든 RAM의 크기를 재고 위치시키는데 내부
알고리즘을 사용하거나, 머신 안의 RAM에 대한 지식을 사용하거나, 또는
부트 로더 설계자가 맞춰 보는 다른 방법을 사용할 수도 있습니다.)
2. 디바이스 트리를 셋업
———————–

요구 사항: 필수

디바이스 트리 조각 (dtb)는 8 바이트 경계로 커널 이미지의 시작으로부터
512 메가 바이트 내에, 그리고 2 바이트 경계에 걸치지 않도록 위치해야만
합니다. 이것은 커널이 초기 페이지 내이블 내의 하나의 섹션 맵핑을 사용해서
조각을 맵핑할 수 있도록 해줍니다.
3. 커널 이미지를 압축 해제
————————–

요구 사항: 선택

AArch64 커널은 현재 압축 해제기를 제공하지 않고, 그래서 압축된 Image 타겟
(예를 들면, Image.gz)이 사용된다면 부트 로더에 의한 압축 해제
(gzip, 기타 등)를 요구합니다. 이 요구 사항을 구현하지 않은 부트로더들을
위해서 압축되지 않은 Image 타겟이 현재 대신 이용 가능합니다.
4. 커널 이미지를 호출
———————

요구 사항: 필수

압축 해제된 커널 이미지는 다음과 같은 64바이트 헤더를 포함합니다:

  u32 code0;
/* 실행 가능 코드 */
  u32 code1; /* 실행 가능 코드 */
  u64 text_offset; /* 이미지 로딩 오프셋 */
  u64 res0 = 0; /* 여분으로 예약 */
  u64 res1 = 0; /* 여분으로 예약 */
  u64 res2 = 0; /* 여분으로 예약 */
  u64 res3 = 0; /* 여분으로 예약 */
  u64 res4 = 0; /* 여분으로 예약 */
  u32 magic = 0x644d5241; /* 매직 넘버, 리틀 엔디언, “ARM\x64” */
  u32 res5 = 0;       /* 여분으로 예약 */
헤더 설명:

– code0/code1 은 stext로의 뜀을 책임집니다.
– EFI를 통해 부팅할 때, code0/code1은 초기에 건너 뜁니다. res5는
  PE 헤더로의 offset이고, PE 헤더는 EFI 진입 포인트(efi_stub_entry)를
  가집니다. 그 코드 조각이 작업을 끝내면, 보통의 부팅 프로세스를 재개하기
  위해서 code0 로 점프합니다.
  
이미지는 시스템 RAM의 시작으로부터 지정된 오프셋(현재는 0x80000)에
위치하고, 거기서 호출되어야만 합니다. 시스템 RAM의 시작은 2MB로 정렬되어져
있어야 합니다.

커널로 점프하기 전에, 다음 조건을 만족해야만 합니다:

– 모든 DMA 가능 장치들을 중지시켜 메모리가 가짜 네트워크 패킷이나
  디스크 데이터로 인해 깨지지 않도록 하세요. 이것은 많은 디버깅 시간을
  절약시켜 줄 것입니다.
  
– 주요 CPU 일반-목적(general-purpose) 레지스터 셋팅
  x0 = 시스템 RAM 내의 디바이스 트리 조각(dtb)의 물리 주소
  x1 = 0 (차후 용도를 위해 예약)
  x2 = 0 (차후 용도를 위해 예약)
  x3 = 0 (차후 용도를 위해 예약)  
  
– CPU 모드
  모든 형태의 인터럽트는 PSTATE.DAIF(Debug, Serror, IRQ 그리고 FIQ)로
  마스킹되어져야 합니다.
  CPU는 EL2(가상화 확장에 접근하기 위해서 추천함) 또는 논-시큐어 EL1 에
  있어야 합니다.

– 캐시, MMU
  MMU는 반드시 꺼져야 합니다.
  명령 캐시는 켜지거나 꺼져 있을 수 있습니다.
  로딩된 커널 이미지에 해당하는 주소 범위는 PoC로 깨끗해야 합니다.
  시스템 캐시나 켜진 캐시와 연관된 다른 마스터들의 존재 안에서,
  이것은 보통, 셋/웨이 연산보다는 VA에 의한 캐시 관리를 필요로 합니다.
  VA 연산에 의한 구조화된 캐시 관리를 준수하는 시스템 캐시는 설정되어져야
  하고, 켜지게 될 것 입니다.
  VA 연산에 의한 구조화된 캐시 관리를 따르지 않는(권장하지 않음) 시스템
  캐시는 설정되고 꺼져야만 합니다.

– 구조화된 타이머
  CNTFRQ는 반드시 타이머 주기로 프로그램되어야 하고, CNTVOFF는 모든
  CPU들의 일관된 값으로 프로그램되어야 합니다. 만약 EL1에서 커널로
  진입한다면, CNTHCTL_EL2는 반드시 셋팅된 EL1PCTEN(비트 0)을 가져야 합니다.

– 연관성
  커널에 의해 부팅될 모든 CPU들은 커널로의 진입 상의 같은 연관 도메인의
  일부가 되어야 합니다. 이것은 각 CPU 상의 관리 연산의 수신을 켜는
  ‘구현에 따라 정의된’ 초기화를 요구할 것입니다.
  
– 시스템 레지스터
  커널이미지가 진입하는 그 예외 레벨에서 모든 쓰기 가능한 구조화된 시스템
  레지스터들은 ‘알려지지 않은’ 상태 내의 실행을 막기 위해서 더 높은 예외
  레벨에서 소프트웨어에 의해 초기화되어야만 합니다.

위에 쓰여진 CPU 모드, 캐시, MMU, 구조화된 타이머, 연관성과 시스템 레지스터들에
대한 요구사항은 모든 CPU에 적용됩니다. 모든 CPU는 같은 예외 레벨 안에서
커널로 진입해야 합니다.

부트로더는 각 CPU가 다음과 같은 관례로 커널로 진입할 것으로 생각합니다:

– 주 CPU는 커널 이미지의 첫 명령으로 직접 점프해야만 합니다. 이 CPU에 의해
  넘겨진 디바이스 트리 조각은 각 CPU 노드의 ‘enable-method’ 프로퍼티를
  포함해야만 합니다. 지원되는 enable-method 들은 아래에서 설명합니다.

  부트로더는 이들 디바이스 트리 프로퍼티를 생생하고 커널 진입보다 먼저
  조각 안에 그들을 끼워 넣을 것입니다.

– “spin-table” enable-method 의 CPU들은 그들의 cpu 노드 내에
  하나의 ‘cpu-release-addr’ 프로퍼티를 가져야 합니다. 이 프로퍼티는
  자연스럽게 정렬된 64비트의 0으로 초기화된 메모리 위치를 나타냅니다.

  이 CPU들은 예약된 영역 안에 포함되어야만 하는, 그들의 cpu-release-addr
  위치를 폴링하는 (디바이스 트리 안의 /memreserve/ 영역에 의해 커널로
  전달되는) 메모리의 예약된 영역 안의 커널 밖에서 돌아야 합니다.
  wfe 명령은 비지-루프(busy-loop)의 부하를 줄이기 위해서 추가될 것이고,
  sev는 주 CPU에 의해 일어날 것입니다. cpu-release-addr에 의해
  가리켜지는 위치를 읽는 것이 0이 아닌 값을 반환할 때, 그 CPU는 이 값으로
  점프해야 합니다. 그 값은 하나의 64비트 리틀 엔디언 값으로 쓰여질
  것이므로 CPU들은 읽은 값을 그리로 점프하기 전에 그들 원래의 엔디언으로
  변환해야 합니다.

– “psci” enable method의 CPU들은 커널의 밖(즉, memory 노드 안에 커널로
  기술된 메모리의 그 영역 밖, 또는 디바이스 트리 안의 /memreserve/ 영역에
  의해 커널로 기술된 메모리의 예약된 영역 안)에 남아 있어야 합니다.
  커널은 커널 내로 CPU들을 가져오기 위해서 ARM DEN 0022A
  (“Power State Coordination Interface System Software on ARM processors”)
  문서 안에 설명된 것처럼 CPU_ON 호출들을 일으킬 것입니다.
  
  디바이스 트리는 하나의 ‘psci’ 노드를
  Documentation/devicetree/bindings/arm/psci.txt 안에 설명된대로
  포함해야만 합니다.

– 두번째 CPU 일반-목적 레지스터 셋팅
  x0 = 0 (차후 용도를 위해 예약)
  x1 = 0 (차후 용도를 위해 예약)
  x2 = 0 (차후 용도를 위해 예약)
  x3 = 0 (차후 용도를 위해 예약)

[Linux:Kernel] 동적 디버그 사용법(dynamic debug howto.txt)

이 문서의 저작권은 GPL 라이센스를 따릅니다(This document is released under the GPL license).

Documentation/dynamic-debug-howto.txt

번역: 양정석<dasomoli@gmailREMOVETHIS.com>

소개

====

이 문서는 어떻게 동적 디버그 (Dynamic Debug:dyndbg) 기능을 사용하는지 설명합니다.

동적 디버그는 여러분이 추가적인 커널 정보를 얻을 수 있도록 동적으로 커널 코드를 켜고/끌

수 있도록 설계되었습니다. 현재는 CONFIG_DYNAMIC_DEBUG가 설정되어 있다면, 모든

pr_debug()/dev_dbg() 그리고 print_hex_dump_debug()/

print_hex_dump_bytes() 호출은 호출하는 지점마다(per-callsite) 동적으로 켜질

수 있습니다.

CONFIG_DYNAMIC_DEBUG가 설정되어 있지 않으면, print_hex_dump_debug()는

그저 print_hex_dump(KERN_DEBUG)의 축약입니다.

print_hex_dump_debug()/print_hex_dump_bytes()에서 만약 그것이 변하지 않는

문자열이라면 형식 문자열(format string)은 그 ‘prrefix_str’ 인자입니다;

또는 ‘prefix_str’ 이 빌드 시 동적인 경우라면 “hexdump”.

동적 디버그는 더 유용한 기능들도 가집니다:

 * 0이나 1의 조합으로 매칭해서 디버깅 문장을 끄고 켤 수 있도록 하는 간단한 쿼리 언어:

   – 소스 파일 이름

   – 함수 이름

   – (행 번호의 범위를 포함하는) 행 번호

   – 모듈 이름

   – 형식 문자열

 * debugfs 제어 파일 제공: 여러분을 안내하는데 도움이 되도록, 알려진 디버그 문장들의

   완전한 목록을 보이도록 읽혀질 수 있는 <debugfs>/dynamic_debug/control.

동적 디버그 동작 제어하기

=========================

pr_debug()/dev_dbg()의 동작은 이 기능의 용도에 따라 ‘debugfs’ 파일 시스템 내의

제어 파일에 쓰는 것을 통해 제어됩니다. 이어서, 우리는 제어 파일을 알아봅니다:

<debugfs>/dynamic_debug/contorl. 예를 들어, 여러분이 소스 파일 ‘svcsock.c’의

1603번째 행에서 출력을 켜기를 원한다면, 간단히 이렇게 하세요:

nullarbor:~ # echo ‘file svcsock.c line 1603 +p’ >
<debugfs>/dynamic_debug/control

여러분이 문법을 틀린다면, 쓰기가 실패할 것입니다:

nullarbor:~ # echo ‘file svcsock.c wtf 1 +p’ >
<debugfs>/dynamic_debug/control

-bash: echo: write error: Invalid argument

동적 디버그 동작 보기

=====================

여러분은 다음을 통해 현재 설정된 모든 디버그 문장의 동작을 볼 수 있습니다:

nullarbor:~ # cat <debugfs>/dynamic_debug/control

# filename:lineno [module]function flags format

/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:323 [svcxprt_rdma]svc_rdma_cleanup =_ “SVCRDMA Module Removed, deregister RPC RDMA transport\012”

/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:341 [svcxprt_rdma]svc_rdma_init =_ “\011max_inline       : %d\012”

/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:340 [svcxprt_rdma]svc_rdma_init =_ “\011sq_depth         : %d\012”

/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svc_rdma.c:338 [svcxprt_rdma]svc_rdma_init =_ “\011max_requests     : %d\012”


여러분은 또한 이 데이터에 표준 유닉스 텍스트 조작 필터를 적용할 수 있습니다. 예를 들면,

nullarbor:~ # grep -i rdma <debugfs>/dynamic_debug/control  | wc -l

62

nullarbor:~ # grep -i tcp <debugfs>/dynamic_debug/control | wc -l

42

세번째 열은 현재 각 디버그 문장을 호출하는 곳마다의 켜짐 플래그(이 플래그의 정의는

아래를 보세요)를 보여줍니다. 아무 플래그도 설정되지 않은, 기본 값은 “=_” 입니다.

그래서 여러분은 모든 디버그 문장 호출처를 기본값이 아닌 플래그로 볼 수 있습니다:

nullarbor:~ # awk ‘$3 != “=_”‘ <debugfs>/dynamic_debug/control

# filename:lineno [module]function flags format

/usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c:1603 [sunrpc]svc_send p “svc_process: st_sendto returned %d\012”

명령 언어 레퍼런스

==================

어휘적인 수준에서, 하나의 명령은 스페이스나 탭으로 나뉘어진 단어 순서로 구성됩니다.

그래서 이들은 모두 동등합니다:

nullarbor:~ # echo -c ‘file svcsock.c line 1603 +p’ >
<debugfs>/dynamic_debug/control

nullarbor:~ # echo -c ‘  file   svcsock.c     line  1603 +p  ‘ >
<debugfs>/dynamic_debug/control

nullarbor:~ # echo -n ‘file svcsock.c line 1603 +p’ >
<debugfs>/dynamic_debug/control

명령 제출은 write() 시스템 호출로 경계지어집니다. 여러 명령은 ‘;’ 나 ‘\n’ 으로

나뉘어져서 함께 쓰여질 수 있습니다.

  ~# echo “func pnpacpi_get_resources +p; func pnp_assign_mem +p” \

     > <debugfs>/dynamic_debug/control

여러분의 쿼리 집합이 크다면, 역시 이를 일괄적으로 수행할 수 있습니다:

  ~# cat query-batch-file > <debugfs>/dynamic_debug/control

다른 방법은 와일드카드를 사용하는 것입니다. 매치 규칙은 ‘*’ (0개나 그 이상의 문자들과

매치)과 ‘?’ (정확히 하나의 문자와 매치)를 지원합니다. 예를 들면, 여러분은 모든 usb

드라이버들을 매치시킬 수 있습니다:

  ~# echo “file drivers/usb/* +p” > <debugfs>/dynamic_debug/control

문법적인 수준에서, 매치 명세(match-spec)들, 그 뒤에 플래그 변경 명세(flags-spec)

의 순서로 구성됩니다.

command ::= match-spec* flags-spec

매치 명세들은 플래그 변경 명세를 어디에 적용해야 하는지를 위해 알려진 pr_debug()

호출처의 부분 집합을 고르는데 사용됩니다. 각 짝들 사이에 암묵적인 AND로 하나의 쿼리처럼

그들을 생각하세요. 매치 명세의 빈 목록은 모든 디버그 문장 호출처를 선택함을 알아두세요.

매치 명세는 비교되는 호출처의 속성을 제어하는 하나의 키워드, 그리고 비교될 하나의 값으로

구성됩니다. 가능한 키워드들은:

match-spec ::= ‘func’ string |
      ‘file’ string |
      ‘module’ string |
      ‘format’ string |
      ‘line’ line-range

line-range ::= lineno |
      ‘-‘lineno |
      lineno’-‘ |
      lineno’-‘lineno

// 알림: line-range 스페이스를 포함할 수 없습니다. 예를 들면,

// “1-30″은 유효한 범위이지만, “1 – 30″은 아닙니다.

lineno ::= unsigned-int

각 키워드의 뜻은:

func

    주어진 문자열은 각 호출처의 함수 이름과 비교됩니다 예를 들면:

    func svc_tcp_accept

file

    주어진 문자열은 전체 경로 이름이나 소스 루트의(src-root) 상대 경로 이름, 또는 각

    호출처의 소스 파일의 경로를 제외한 이름(basename)과 비교됩니다. 예를 들면:

    file svcsock.c

    file kernel/freezer.c

    file /usr/src/packages/BUILD/sgi-enhancednfs-1.4/default/net/sunrpc/svcsock.c

module

    주어진 문자열은 각 호출처의 모듈 이름과 비교됩니다. 모듈 이름은 “lsmod” 에서 보여지는

    문자열입니다. 즉, 디렉토리나 .ko 접미사가 없고, ‘-‘는 ‘_’로 변경됩니다. 예를 들면:

    module sunrpc

    module nfsd

format

    주어진 문자열은 동적 디버그 형식 문자열 내에서 검색됩니다. 그 문자열은 전체 형식과

    매치될 필요는 없고 오직 일부만 매치되면 된다는 것을 알아두세요. 공백 문자들과 다른

    특수 문자들은 C의 8진수 문자 이스케이프 \ooo 표현을 사용해서 쓰여질 수 있습니다.

    예를 들면, 스페이스 문자는 \040 입니다. 다른 방식으로, 문자열을 쌍따옴표 문자(“) 나

    따옴표(‘)로 둘러쌀 수 있습니다.

    예제:

    format svcrdma:
   // NFS/RDMA 서버 pr_debug 들에서 많음

    format readahead
   // readahead 캐시 안의 pr_debug 들

    format nfsd:\040SETATTR // 공백 문자로 형식을 매치하는 한가지 방법

    format “nfsd: SETATTR”  // 공백 문자로 형식을 매치하는 더 깔끔한 방법

    format ‘nfsd: SETATTR’  // 공백 문자로 형식을 매치하는 또 다른 방법

line

    주어진 행 번호 또는 행 번호의 범위는 각 pr_debug() 호출처의 행 번호와 비교됩니다.

    하나의 행 번호는 호출처 행 번호와 정확히 매치됩니다. 행 번호의 범위는 처음과 마지막의

    행 번호 안의 호출처와 매치됩니다. 첫번째 수가 없는 것은 파일의 첫번째 줄을 의미하고,

    행 번호가 없는 것은 파일의 마지막 줄을 의미합니다. 예를 들면: 

    line 1603
   // 정확히 1603번 줄

    line 1600-1605  // 1600번에서 1605번 줄까지의 여섯 줄

    line -1605
   // 1번 줄에서 1605번 줄까지의 1605 줄

    line 1600-
   // 1600번 줄에서 파일의 끝까지의 모든 줄

플래그 명세는 하나 또는 그 이상의 플래그 성질이 따르는 하나의 변경 동작으로 구성됩니다.

변경 동작은 하나의 성질입니다:

  –    주어진 플래그 제거

  +    주어진 플래그 추가

  =    주어진 플래그로 플래그를 설정

플래그들은 다음과 같습니다:

  p    pr_debug() 호출처 켜기

  f    출력된 메시지 안에 함수 이름을 포함

  l    출력된 메시지 안에 행 번호를 포함

  m    출력된 메시지 안에 모듈 이름을 포함

  t    인터럽트 컨텍스트에서 생성되지 않은 메시지 안에 스레드 ID 포함.

  _    플래그가 설정되지 않음. (또는 입력 상의 다른 것들로 설정)

print_hex_dump_debug()와 print_hex_dump_bytes()에서는, 오직 ‘p’ 플래그가

다른 플래그들이 무시되는 것을 의미합니다.

보여줄 때, 플래그들은 ‘=’이 앞에 옵니다(연상 기호: 무슨 플래그가 현재 동일한지).

Note the regexp ^[-+=][flmpt_]+$ matches a flags specification.

To clear all flags at once, use “=_” or “-flmpt”.

정규표현 ^[-+=][flmpt_]+$ 는 플래그 명세와 매치함을 알아두세요.

모든 플래그를 없애기 위해서, “=_” 나 “-flmpt”를 사용하세요.

부트 프로세스 동안의 디버그 메시지

==================================

부트 프로세스 동안의 코어 코드와 빌트인 모듈 디버그 메시지를 활성화 하기 위해서, 유저 공간과

debugfs 가 존재하기 전에도, dyndbg=”QUERY”, module.dyndbg=”QUERY”, 또는

ddebug_query=”QUERY”(ddebug_query는 dyndbg에 의해 구식이 되었고, 더 이상 사용하지

않습니다)를 사용할 수 있습니다. QUERY는 위에 설명된 문법을 따르지만, 1023 문자를 넘을 수

없습니다. 여러분의 부트로더는 제한으로 더 적은 수를 쓰고 있을 수 있습니다.

이들 dyndbg 파라미터들은 ddebug 테이블이 처리된 후에, arch_initcall 의 일부로

바로 처리됩니다. 그래서 여러분은 이 부트 파라미터를 통해 이 arch_initcall 이후에

모든 코드 안의 디버그 메시지를 켤 수 있습니다.

예를 들면, x86 시스템 상에서 ACPI 활성화는 subsys_initcall 이고,

   dyndbg=”file ec.c +p”

는 여러분의 머신(일반적으로 랩탑)이 임베디드 컨트롤러를 가진다면, ACPI 셋업동안 초기 임베디드

컨트롤러 트랜잭션을 보여줄 것입니다.

PCI (또는 다른 장치들의) 초기화는 또한 디버깅 목적의 이 부트 파라미터 사용의 유력한

후보들입니다.

foo 모듈이 빌트-인이 아니라면, foo.dyndbg 는 여전히 부트 타임에 아무 효과 없이 처리될

것입니다만, 모듈이 이후에 로딩될 때 처리될 것입니다. dyndbg_query= 과 순수한 dyndbg= 은

부트 시에만 처리됩니다.

모듈 초기화 시점의 디버그 메시지

================================

“modprobe foo”가 호출될 때, modprobe는 foo.params를 위해 /proc/cmdline을 스캔하고,

“foo.”을 벗겨서 제거하고, 이를 modprobe args 나 /etc/modprob.d/*.conf 파일 안에

주어진 파라미터들과 함께 다음 순서로 커널에게 넘긴다:

1. # /etc/modprobe.d/*.conf를 통해 주어진 파라미터들

   options foo dyndbg=+pt

   options foo dyndbg # +p로 기본

2. # boot args에서 주어진 foo.dyndbg, “foo.” 는 벗겨져서 제거되어 전달됨

   foo.dyndbg=” func bar +p; func buz +mp”

3. # modprobe로의 args

   modprobe foo dyndbg==pmf # 이전 설정을 덮어 씀

이들 dyndbg 쿼리들은 가장 마지막에 말한 것이 마지막에 적용되도록, 순서대로 적용됩니다.

이것은 boot args가 /etc/modprobe.d(정확하게는 1이 시스템 전체, 2는 커널이나 부트에

의존적임)로부터 이들을 수정하거나 덮어 쓰도록, 그리고 modeprbe args 가 둘 다를 덮어쓰도록

합니다.

foo.dyndbg=”QUERY” 형식 안에서, 쿼리는 반드시 “foo 모듈”을 제외해야 합니다.

“foo”는 param-name 으로부터 추출되고, “QUERY” 내의 각 쿼리에 적용되고, 오직

각 타입의 1 match-spec만 적용됩니다.

dyndbg 옵션은 “가짜” 모듈 파라미터입니다. 이는 다음을 의미합니다:

– 모듈들은 그를 명시적으로 정의할 필요가 없습니다.

– 모든 모듈은 그들이 pr_debug를 사용하든 말든, 아무 말 없이 이를 얻을 수 있습니다.

– 그것은 /sys/module/$module/parameters 안에 나타나지 않습니다. 이를 보기 위해서,

  제어 파일을 grep 하거나, /proc/cmdline 을 검사하세요.
CONFIG_DYNAMIC_DEBUG 커널에서는 디버그 메시지가 더이상 필요하지 않다면, 부트-타임에
주어진 (또는 컴파일 동안 -DDEBUG 플래그에 의해 켜진) 어떠한 셋팅도 이후에 sysfs
인터페이스를 통해 끌 수 있습니다.

   echo “module module_name -p” > <debugfs>/dynamic_debug/control

예제

====

// svcsock.c 파일의 1603번째 줄의 메시지를 켜기

nullarbor:~ # echo -n ‘file svcsock.c line 1603 +p’ >
<debugfs>/dynamic_debug/control

// svcsock.c 파일 안의 모든 메시지 켜기

nullarbor:~ # echo -n ‘file svcsock.c +p’ >
<debugfs>/dynamic_debug/control

// NFS 서버 모듈의 모든 메시지 켜기

nullarbor:~ # echo -n ‘module nfsd +p’ >
<debugfs>/dynamic_debug/control

// svc_process() 함수 안의 모든 12 메시지를 켜기

nullarbor:~ # echo -n ‘func svc_process +p’ >
<debugfs>/dynamic_debug/control

// svc_process() 함수 안의 모든 12 메시지를 끄기

nullarbor:~ # echo -n ‘func svc_process -p’ >
<debugfs>/dynamic_debug/control

// NFS가 호출하는 READ, READLINK, READDIR 그리고, READDIR+를 위한 메시지 켜기

nullarbor:~ # echo -n ‘format “nfsd: READ” +p’ >
<debugfs>/dynamic_debug/control

// “usb” 문자열을 포함하는 경로의 메시지 켜기

nullarbor:~ # echo -n ‘*usb* +p’ > <debugfs>/dynamic_debug/control

// 모든 메시지 켜기

nullarbor:~ # echo -n ‘+p’ > <debugfs>/dynamic_debug/control

// 모든 켜진 메시지에 모듈과 함수 추가

nullarbor:~ # echo -n ‘+mf’ > <debugfs>/dynamic_debug/control

// boot-args 예제, 가독성을 위해 줄바꿈과 주석을 넣음

Kernel command line: …

  // dyndbg=값 처리 안에서 어떻게 되어가고 있는지 보기

  dynamic_debug.verbose=1

  // 2 빌트인 안의 pr_debug 켜기, #cmt 는 제거됨

  dyndbg=”module params +p #cmt ; module sys +p”

  // 나중에 로딩되는 모듈 안의 2 함수 안의 pr_debug를 켜기

  pc87360.dyndbg=”func pc87360_init_device +p; func pc87360_find +p”