最近在提交cpufreq patch,稍微有点逻辑改动的Rafael都要你test, test。有个改动涉及setpolicy driver,要验证,第一印象就是用qemu。

让我们来看下如何搭环境(initrd=ramdisk):

my linux server(xeon) for building can not access internet,also vb under win is not. install qemu deb offline has too many dependens, forget it, let admin apt-get qemu(qemu-system-x86_64), it's done.

I have already download the linux-pm git repo, below operations r based on this code.

kernel编译

1.generate .config

make O=out_x86_64/ x86_64_defconfig

btw: gcc is default for x86_64 in xeon.

tj@bsvr:/sys/devices/system/cpu/cpu0/cpufreq$ file /usr/bin/gcc
/usr/bin/gcc: symbolic link to `gcc-4.8' 
tj@bsvr:/sys/devices/system/cpu/cpu0/cpufreq$ file /usr/bin/gcc-4.8 
/usr/bin/gcc-4.8: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=fd10e59c8b3fd9ff72ecb1586fa83be45e339f7b, stripped

2.make

make O=out_x86_64/ bzImage -j8

遇到了错误:

You are building kernel with non-retpoline compiler.
Please update your compiler.
make[1]: *** [checkbin] Error 1

直接disable RETPOLINE:

arch/x86/Kconfig:
 config RETPOLINE
        bool "Avoid speculative indirect branches in kernel"
-   default y
+ default n

继续又错:

error: Cannot generate ORC metadata for CONFIG_UNWINDER_ORC=y, please install libelf-dev, libelf-devel or elfutils-libelf-devel

我们用menuconfig

make O=out_x86_64/ menuconfig 

改选Frame pointer...

Kernel hacking > Choose kernel unwinder  -> select Frame pointer unwinder

设置ramdisk size为65536 (64MB)

Device Drivers > Block dev > <*> RAM block device support > ()Default RAM disk size

then building is ok.

Kernel: arch/x86/boot/bzImage is ready  (#1)

tj@bsvr:~/work/kernel/linux-pm$ file out_x86_64/arch/x86/boot/bzImage 
out_x86_64/arch/x86/boot/bzImage: x86 boot sector

building busybox

1.generate config

make defconfig

2.静态编译

make menuconfig
Busybox setting > --- Build Options > [*] Build Busybox as a static

3.building

make -j4

没有幺蛾子,it's ok

  LINK    busybox_unstripped
Static linking against glibc, can't use --gc-sections
Trying libraries: crypt m
 Library crypt is not needed, excluding it
 Library m is needed, can't exclude it (yet)
Final link with: m

btw: my bb version: busybox-1.27.1

4.install

安装到指定目录for later usage:

make CONFIG_PREFIX=~/work/kernel/qemu/x86_64/busybox_install/ install

进去看下:

tj@bsvr:~/work/kernel/qemu/x86_64/busybox_install$ ls -l
total 12
drwxrwxr-x 2 tj tj 4096 Apr 30 12:30 bin
lrwxrwxrwx 1 tj tj   11 Apr 30 12:30 linuxrc -> bin/busybox
drwxrwxr-x 2 tj tj 4096 Apr 30 12:30 sbin
drwxrwxr-x 4 tj tj 4096 Apr 30 12:30 usr

有个linuxrc文件,link到了2.5M的bin/busybox,其他都是link。。。

tj@bsvr:/work/tj/kernel/qemu/x86_64/busybox_install/bin$ ls -lh
total 2.5M
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 ash -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 base64 -> busybox
-rwxr-xr-x 1 tj tj 2.5M Apr 30 12:30 busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 cat -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 chattr -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 chgrp -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 chmod -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 chown -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 conspy -> busybox
lrwxrwxrwx 1 tj tj    7 Apr 30 12:30 cp -> busybox
...

制作ramdisk

这里参考别人了,hurry up,不过需要有root权限,只能cp到vb ubuntu下,得压缩后再cp,不然link全部变了real file了,几百M。

另外不要在vb下share的挂载点操作,cp到外面,比如Downloads:

tj@tj-u1404:~/Downloads/mk_ramdisk$ ls
busybox_install  etc  mk_ramdisk.sh

ok,run mk_ramdisk.h, then show below if successful:

Allocating group tables: done                            
Writing inode tables: done                            
Creating journal (4096 blocks): done
Writing superblocks and filesystem accounting information: done

tj@tj-u1404:~/Downloads/mk_ramdisk$ ls
tj@tj-u1404:~/Downloads/mk_ramdisk$ ls
busybox_install  etc  mk_ramdisk.sh  ramdisk  ramdisk.gz  rootfs  tmpfs
tj@tj-u1404:~/Downloads/mk_ramdisk$ 
tj@tj-u1404:~/Downloads/mk_ramdisk$ ls -lh ramdisk.gz 
-rw-rw-r-- 1 tj tj 1.5M Apr 30 03:17 ramdisk.gz

运行qemu x86_64

cp到一个目录:

tj@bsvr:~/work/kernel/qemu/x86_64$ ls
busybox_install  busybox_install.tar  bzImage  ramdisk.gz  run.sh

run.sh:

tj@bsvr:~/work/kernel/qemu/x86_64$ cat run.sh 
qemu-system-x86_64 \
  -smp 2 \
  -m 512M \
  -kernel ./bzImage \
  -nographic \
  -append "root=/dev/ram0 rw rootfstype=ext4 console=ttyS0 init=/linuxrc" \
  -initrd ./ramdisk.gz
tj@bsvr:~/work/kernel/qemu/x86_64$ 

see below, haha:)

[    4.472432] ifconfig (1082) used greatest stack depth: 13824 bytes left

Please press Enter to activate this console. 

but no cpufreq:

[root@x86 cpu1]# ls
cache             driver            node0             subsystem
crash_notes       firmware_node     online            topology
crash_notes_size  hotplug           power             uevent
[root@x86 cpu1]# 

退出ctl-A + x

check for intel_pstate

intel_pstate用的就是setpolicy driver。

[root@x86 cpu1]# dmesg | grep "intel"
[    2.214309] intel_pstate: CPU ID not supported

nd, 不支持,看下代码需要硬件feature支持:

static int __init intel_pstate_init(void)
{
    const struct x86_cpu_id *id;
    int rc;

    if (no_load)
        return -ENODEV;

    id = x86_match_cpu(hwp_support_ids);
    if (id) {
        copy_cpu_funcs(&core_funcs);
        if (!no_hwp) {
            hwp_active++;
            hwp_mode_bdw = id->driver_data;
            intel_pstate.attr = hwp_cpufreq_attrs;
            goto hwp_cpu_matched;
        }
    } else {
        id = x86_match_cpu(intel_pstate_cpu_ids);
        if (!id) {
            pr_info("CPU ID not supported\n");
            return -ENODEV;
        }

        copy_cpu_funcs((struct pstate_funcs *)id->driver_data);
    }
#define ICPU(model, policy) \
    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_APERFMPERF,\
            (unsigned long)&policy }

static const struct x86_cpu_id intel_pstate_cpu_ids[] = {
    ICPU(INTEL_FAM6_SANDYBRIDGE,         core_funcs),
    ICPU(INTEL_FAM6_SANDYBRIDGE_X,        core_funcs),
    ICPU(INTEL_FAM6_ATOM_SILVERMONT,    silvermont_funcs),
    ICPU(INTEL_FAM6_IVYBRIDGE,        core_funcs),
    ICPU(INTEL_FAM6_HASWELL_CORE,        core_funcs),
    ICPU(INTEL_FAM6_BROADWELL_CORE,        core_funcs),
    ICPU(INTEL_FAM6_IVYBRIDGE_X,        core_funcs),
    ICPU(INTEL_FAM6_HASWELL_X,        core_funcs),
    ICPU(INTEL_FAM6_HASWELL_ULT,        core_funcs),
    ICPU(INTEL_FAM6_HASWELL_GT3E,        core_funcs),
    ICPU(INTEL_FAM6_BROADWELL_GT3E,        core_funcs),
    ICPU(INTEL_FAM6_ATOM_AIRMONT,        airmont_funcs),
    ICPU(INTEL_FAM6_SKYLAKE_MOBILE,        core_funcs),
    ICPU(INTEL_FAM6_BROADWELL_X,        core_funcs),
    ICPU(INTEL_FAM6_SKYLAKE_DESKTOP,    core_funcs),
    ICPU(INTEL_FAM6_BROADWELL_XEON_D,    core_funcs),
    ICPU(INTEL_FAM6_XEON_PHI_KNL,        knl_funcs),
    ICPU(INTEL_FAM6_XEON_PHI_KNM,        knl_funcs),
    ICPU(INTEL_FAM6_ATOM_GOLDMONT,        core_funcs),
    ICPU(INTEL_FAM6_ATOM_GOLDMONT_PLUS,     core_funcs),
    ICPU(INTEL_FAM6_SKYLAKE_X,        core_funcs),
    {}
};

...

#define ICPU_HWP(model, hwp_mode) \
    { X86_VENDOR_INTEL, 6, model, X86_FEATURE_HWP, hwp_mode }

static const struct x86_cpu_id hwp_support_ids[] __initconst = {
    ICPU_HWP(INTEL_FAM6_BROADWELL_X, INTEL_PSTATE_HWP_BROADWELL),
    ICPU_HWP(INTEL_FAM6_BROADWELL_XEON_D, INTEL_PSTATE_HWP_BROADWELL),
    ICPU_HWP(X86_MODEL_ANY, 0),
    {}
};

X86_FEATURE_HWP or X86_FEATURE_APERFMPERF,QEMU(x86_64)本身就不支持,即使host支持也不行,歇菜,还有个x86模拟器叫Bochs以后看了,先用real pc...

refer doc