Thanks a lot for all the replies. The pointer to __switch_to revealed
the problem.
The lock-up happens indepently of whether the message is printed on
the console or just logged to the buffer. Also, the printk was not
placed in __switch_to() but rather in schedule() itself. The problem
is that printk may call try_to_wake_up() which in turn will try to
acquire a runqueue lock ( of the CPU where klogd ran the last time).
That could be the excact same lock that schedule() already holds.
This, of course, deadlocks the CPU as recursive locking of spin locks
is not supported in the kernel.