2015년 6월 27일 토요일

[Linux Kernel] 107주차(2015.06.27)

ARM10C : 107 주차
일시 : 2015.06.27 (107 주차 스터디 진행)
모임명 : NAVER개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명

107 주차 진도

  • start_kernel 1 init/main.c
    • console_init 783 init/main.c
      • tty_ldisc_begin 3493 ~/kernel/iamroot/linux-stable/drivers/tty/tty_io.c
        • tty_register_ldisc 831 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
          • tty_ldisc_ops 66 int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)

main.c::main.c()

  • called: start_kernel()
asmlinkage void __init start_kernel(void)
{
...
    time_init();
    // timer 를 사용하기 위한 clk source, clk_table 메모리 할당 및 초기화,
    // timer event를 위한 timer irq (MCT) 초기화 수행

    sched_clock_postinit();
    // sched_clock_timer을 초기화 수행

    perf_event_init(); // null function
    profile_init(); // null function
    call_function_init();
    // 각 cpu core에서 사용할 call_single_queue를 맴버값 초기화
    // cfd_data 맴버값을 초기화하고 pcp에서 사용할 메모리 공간 할당
    // cpu_chain에 hotplug_cfd_notifier 를 등록함

    // irqs_disabled(): 1
    WARN(!irqs_disabled(), "Interrupts were enabled early\n");

    // early_boot_irqs_disabled: true
    early_boot_irqs_disabled = false;
    // early_boot_irqs_disabled: false

    local_irq_enable();
    // IRQ를 enable 함

    kmem_cache_init_late(); // null function

    /*
     * 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();
  • call: start_kernel()->console_init()

tty_io.c::console_init()

  • called: start_kernel()->console_init()
// ARM10C 20150627
void __init console_init(void)
{
    initcall_t *call;

    /* Setup the default TTY line discipline. */
    tty_ldisc_begin();
  • call: start_kernel()->console_init()->tty_ldisc_begin()
    • tty_ldisc_begin();

tty_ldisc.c::tty_ldisc_begin()

  • called: start_kernel()->console_init()->tty_ldisc_begin()
    • tty_ldisc_begin();
// ARM10C 20150627
void tty_ldisc_begin(void)
{
    /* Setup the default TTY line discipline. */
    // N_TTY 0
    (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

}
// tty_register_ldisc에서 한일: // tty_ldiscs[0]: &tty_ldisc_N_TTY // (&tty_ldisc_N_TTY)->num: 0 // (&tty_ldisc_N_TTY)->refcount: 0
  • call: start_kernel()->console_init()->tty_ldisc_begin()->tty_register_ldisc()

tty_ldisc.c::tty_register_ldisc()

  • called: start_kernel()->console_init()->tty_ldisc_begin()->tty_register_ldisc()
// ARM10C 20150627
// N_TTY: 0, &tty_ldisc_N_TTY
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
{
    unsigned long flags;
    int ret = 0;
    // ret: 0

    // disc: 0, N_TTY: 0, NR_LDISCS: 30
    if (disc < N_TTY || disc >= NR_LDISCS)
        return -EINVAL;

    raw_spin_lock_irqsave(&tty_ldiscs_lock, flags);

    // raw_spin_lock_irqsave에서 한일:
    // &tty_ldiscs_lock 을 사용하여 spin lock을 수행하고 cpsr을 flags에 저장함

    // disc: 0, new_ldisc: &tty_ldisc_N_TTY
    tty_ldiscs[disc] = new_ldisc;
    // tty_ldiscs[0]: &tty_ldisc_N_TTY

    // new_ldisc->num: (&tty_ldisc_N_TTY)->num, disc: 0
    new_ldisc->num = disc;
    // new_ldisc->num: (&tty_ldisc_N_TTY)->num: 0

    // new_ldisc->refcount: (&tty_ldisc_N_TTY)->refcount
    new_ldisc->refcount = 0;
    // new_ldisc->refcount: (&tty_ldisc_N_TTY)->refcount: 0

    raw_spin_unlock_irqrestore(&tty_ldiscs_lock, flags);

    // raw_spin_unlock_irqrestore에서 한일:
    // &tty_ldiscs_lock 을 사용하여 spin unlock을 수행하고 flags에 저장된 cpsr을 복원함

    // ret: 0
    return ret;
    // return 0
}
EXPORT_SYMBOL(tty_register_ldisc);
  • return: start_kernel()->console_init()->tty_ldisc_begin()->tty_register_ldisc()

tty_ldisc.c::tty_ldisc_begin()

  • return: start_kernel()->console_init()->tty_ldisc_begin()->tty_register_ldisc()
// ARM10C 20150627
void tty_ldisc_begin(void)
{
    /* Setup the default TTY line discipline. */
    // N_TTY 0
    (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);

}
  • tty_register_ldisc에서 한일: >tty_ldiscs[0]: &tty_ldisc_N_TTY >(&tty_ldisc_N_TTY)->num: 0 >(&tty_ldisc_N_TTY)->refcount: 0

tty_io.c::console_init()

  • return: start_kernel()->console_init()->tty_ldisc_begin()->tty_register_ldisc()
// ARM10C 20150627
void __init console_init(void)
{
    initcall_t *call;

    /* Setup the default TTY line discipline. */
    tty_ldisc_begin();
  • tty_ldisc_begin에서 한일: > tty_ldiscs[0]: &tty_ldisc_N_TTY > (&tty_ldisc_N_TTY)->num: 0 > (&tty_ldisc_N_TTY)->refcount: 0
// ARM10C 20150627
void __init console_init(void)
{
    initcall_t *call;

    /* Setup the default TTY line discipline. */
    tty_ldisc_begin();

    /*
     * set up the console device so that later boot sequences can
     * inform about problems etc..
     */
    call = __con_initcall_start;
    // call: &__con_initcall_start

    // call: &__con_initcall_start
    while (call < __con_initcall_end) {
        // call:__initcall_s3c24xx_serial_console_init:
        // s3c24xx_serial_console_init
        (*call)();
        call++;
    }
}
  • __con_initcall_start
    • s3c24xx_serial_console_init() 를 호출한다.
      • init.h 에 외부함수로 선언해 놓았다.
    • 이것은 vmlinux.lds.h 에서 섹션이 할당된 부분을 링크해서 사용한다. 
#define CON_INITCALL                            \
        VMLINUX_SYMBOL(__con_initcall_start) = .;       \
        *(.con_initcall.init)                   \
        VMLINUX_SYMBOL(__con_initcall_end) = .;
extern initcall_t __con_initcall_start[], __con_initcall_end[];
  • 따라서 s3c24xx_serial_console_init()을 호출하게 된다.
struct console {
    char    name[16];
    void    (*write)(struct console *, const char *, unsigned);
    int (*read)(struct console *, char *, unsigned);
    struct tty_driver *(*device)(struct console *, int *);
    void    (*unblank)(void);
    int (*setup)(struct console *, char *);
    int (*early_setup)(void);
    short   flags;
    short   index;
    int cflag;
    void    *data;
    struct   console *next;
};
static struct console s3c24xx_serial_console;

static int __init s3c24xx_serial_console_init(void)
{
    register_console(&s3c24xx_serial_console);
    return 0;
}
  • call: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console); ## printk.c::register_console()
  • called: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console);
// ARM10C 20150627
// &s3c24xx_serial_console
void register_console(struct console *newcon)
{
    int i;
    unsigned long flags;
    struct console *bcon = NULL;
    struct console_cmdline *c;

    if (console_drivers)
        for_each_console(bcon)
            if (WARN(bcon == newcon,
                    "console '%s%d' already registered\n",
                    bcon->name, bcon->index))
                return;

  • call: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()

    - register_console(&s3c24xx_serial_console);

static struct console s3c24xx_serial_console = {
    .name       = S3C24XX_SERIAL_NAME,
    .device     = uart_console_device,
    .flags      = CON_PRINTBUFFER,
    .index      = -1,
    .write      = s3c24xx_serial_console_write,
    .setup      = s3c24xx_serial_console_setup,
    .data       = &s3c24xx_uart_drv,
};
#endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
  • call: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console);

samsung.c::s3c24xx_serial_console_setup()

  • called: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console);
static int __init
s3c24xx_serial_console_setup(struct console *co, char *options)
{
    struct uart_port *port;
    int baud = 9600;
    int bits = 8;
    int parity = 'n';
    int flow = 'n';

    dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n",
        co, co->index, options);

    /* is this a valid port */

    if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS)
        co->index = 0;

    port = &s3c24xx_serial_ports[co->index].port;

    /* is the port configured? */

    if (port->mapbase == 0x0)
        return -ENODEV;

    cons_uart = port;

    dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);

    /*
     * Check whether an invalid uart number has been specified, and
     * if so, search for the first available port that does have
     * console support.
     */
    if (options)
        uart_parse_options(options, &baud, &parity, &bits, &flow);
    else
        s3c24xx_serial_get_options(port, &baud, &parity, &bits);

    dbg("s3c24xx_serial_console_setup: baud %d\n", baud);

    return uart_set_options(port, co, baud, parity, bits, flow);
}
  • return: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console);

printk.c::register_console()

  • return: start_kernel()->console_init()->s3c24xx_serial_console_init()->register_console()
    • register_console(&s3c24xx_serial_console);
// ARM10C 20150627
// &s3c24xx_serial_console
void register_console(struct console *newcon)
{
    int i;
    unsigned long flags;
    struct console *bcon = NULL;
    struct console_cmdline *c;

    if (console_drivers)
        for_each_console(bcon)
            if (WARN(bcon == newcon,
                    "console '%s%d' already registered\n",
                    bcon->name, bcon->index))
                return;
    /*
     * before we register a new CON_BOOT console, make sure we don't
     * already have a valid console
     */
    if (console_drivers && newcon->flags & CON_BOOT) {
        /* find the last or real console */
        for_each_console(bcon) {
            if (!(bcon->flags & CON_BOOT)) {
                pr_info("Too late to register bootconsole %s%d\n",
                    newcon->name, newcon->index);
                return;
            }
        }
    }

    if (console_drivers && console_drivers->flags & CON_BOOT)
        bcon = console_drivers;

    if (preferred_console < 0 || bcon || !console_drivers)
        preferred_console = selected_console;

    if (newcon->early_setup)
        newcon->early_setup();

    /*
     *  See if we want to use this console driver. If we
     *  didn't select a console we take the first one
     *  that registers here.
     */
    if (preferred_console < 0) {
        if (newcon->index < 0)
            newcon->index = 0;
        if (newcon->setup == NULL ||
            newcon->setup(newcon, NULL) == 0) {
            newcon->flags |= CON_ENABLED;
            if (newcon->device) {
                newcon->flags |= CON_CONSDEV;
                preferred_console = 0;
            }
        }
    }

    /*
     *  See if this console matches one we selected on
     *  the command line.
     */
    for (i = 0, c = console_cmdline;
         i < MAX_CMDLINECONSOLES && c->name[0];
         i++, c++) {
        if (strcmp(c->name, newcon->name) != 0)
            continue;
        if (newcon->index >= 0 &&
            newcon->index != c->index)
            continue;
        if (newcon->index < 0)
            newcon->index = c->index;

        if (_braille_register_console(newcon, c))
            return;

        if (newcon->setup &&
            newcon->setup(newcon, console_cmdline[i].options) != 0)
            break;
        newcon->flags |= CON_ENABLED;
        newcon->index = c->index;
        if (i == selected_console) {
            newcon->flags |= CON_CONSDEV;
            preferred_console = selected_console;
        }
        break;
    }

log

  • 1st log
4f4095e..99bc637  master     -> origin/master
Merge made by the 'recursive' strategy.
arch/arm/kernel/vmlinux.lds.S    |  3 +++
drivers/clocksource/exynos_mct.c |  9 +++++++++
drivers/tty/n_tty.c              |  1 +
drivers/tty/serial/samsung.c     |  4 +++-
drivers/tty/tty_io.c             | 11 +++++++++++
drivers/tty/tty_ldisc.c          | 32 ++++++++++++++++++++++++++++++++
include/linux/console.h          |  1 +
include/linux/hrtimer.h          |  2 +-
include/linux/init.h             |  3 +++
include/linux/ktime.h            |  6 ++----
include/linux/tty.h              |  2 +-
include/linux/tty_ldisc.h        |  1 +
include/uapi/linux/tty.h         |  4 ++++
init/main.c                      |  1 +
kernel/printk/printk.c           |  2 ++
kernel/time/clockevents.c        | 22 +++++++++++++++++-----
16 files changed, 92 insertions(+), 12 deletions(-)
  • 2nd log
87b829c..b4970f1  master     -> origin/master
Merge made by the 'recursive' strategy.
arch/arm/include/asm/io.h             |   2 ++
drivers/clocksource/exynos_mct.c      | 102 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
drivers/tty/serial/samsung.c          |  25 +++++++++++++++++++++++--
drivers/tty/serial/samsung.h          |   2 ++
drivers/tty/tty_io.c                  |   2 ++
include/linux/console.h               |   6 ++++++
include/linux/serial_core.h           |   3 ++-
include/uapi/asm-generic/errno-base.h |   2 ++
kernel/hrtimer.c                      |  90 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
kernel/printk/console_cmdline.h       |   3 ++-
kernel/printk/printk.c                |  27 +++++++++++++++++++++++++++
kernel/time/clockevents.c             |  21 ++++++++++++++++++++-
kernel/time/sched_clock.c             |  19 +++++++++++++++++++
kernel/time/tick-oneshot.c            |  22 ++++++++++++++++++++--
14 files changed, 314 insertions(+), 12 deletions(-)
  • 3th log
c4b416b..9b98f31  master     -> origin/master
Updating c4b416b..9b98f31
Fast-forward
drivers/tty/tty_io.c    |   1 +
init/main.c             |  47 ++++++++++++++
kernel/params.c         | 158 ++++++++++++++++++++++++++++++++++++++++++++++--
kernel/printk/braille.h |   6 +-
kernel/printk/printk.c  |  65 +++++++++++++++++++-
lib/vsprintf.c          |   3 +
6 files changed, 274 insertions(+), 6 deletions(-)

댓글 없음:

댓글 쓰기