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)
- tty_register_ldisc 831 (void) tty_register_ldisc(N_TTY, &tty_ldisc_N_TTY);
- tty_ldisc_begin 3493 ~/kernel/iamroot/linux-stable/drivers/tty/tty_io.c
- console_init 783 init/main.c
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 에서 섹션이 할당된 부분을 링크해서 사용한다.
- s3c24xx_serial_console_init() 를 호출한다.
#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()
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(-)