kernel: Decide whether to use simple or affine scheduler

Simple scheduler is used when we do not have to worry about cache affinity
(i.e. single core with or without SMT, multicore with all cache levels
shared).

When we replace gSchedulerLock with more fine grained locking affine
scheduler should also be chosen when logical CPU count is high (regardless
of cache).
kernel: Fully detect CPU topology before initializing scheduler
scheduler_affine: Add logic shared with simple scheduler

The scheduler is in very early stage. There is no thread migration and
the algorithms choosing CPU for thread are very simple.

Since affine scheduler is going to use one run queue per core simple on
single core machines it will work exactly the same as simple scheduler.
That would allow us to have only one scheduler implementation usable
on all kinds of machines.