config(2)

大掃除

大掃除と掛けて、何と解く? DRAMのリフレッシュ方式の一つと解く。 その心は? まとめて、ドーンとやる、バースト・リフレッシュ。

この他にも、チョロチョロやる、分散リフレッシュとか、 隠れてやるヒディン・リフレッシュがある。これは、外出時に ルンバに掃除させるとか、かな。

大掃除って、日本だけの風習? フェルミ推定してみる。ニュースでは、神社とかお寺の大仏さんの 煤払いってやるから、宗教行事が転じて、一般に広まった? ならば、世界的に行われても不思議ではない。

次は答え合わせ。ググるが楽だけど、それじゃバカになる。 図書館へ行って、知のコンシェルジュである司書に相談かな。 年中行事の本でも調べれば、出てくるかも。

tofu

wslの端末を開くと、豆腐文字に見回れる事が度々発生。ロケールをちゃんと設定してないから だろうと思って、emacsに貼り付けたら、浮かびあがってきた。

Linux 用 Windows サブシステムが Microsoft Store で入手可能になりました。
'wsl.exe --update' を実行するか、https://aka.ms/wslstorepage にアクセスしてアップグレードできます
Microsoft Store から WSL をインストールすると、最新の WSL 更新がより速く提供されます。
詳細については、https://aka.ms/wslstoreinfo
をご覧ください。

M$自身がリナに擦り寄って、こういう宣伝をするなんて、世の中変ったものだ。

ややこしや、最新WSL2のバージョンは「1.0.0.0」――WSL2をインストールする最新手順も紹介

この方ってWindows屋さんでしょ。注目の的ですよ。

VMware Workstation 16.2.5 Player Release Notes

とか言っていたら、新しい案内が届いた。そろそろ来年の準備をしておけって事だな。

dmassage の例

dmassage -t

dmassage -f /bsd | config -e -o /nbsd /bsd

dmassage -s GENERIC >SMALLKERNEL

興味が有るのは2番目の例。どうやらdmesgに表れないデバイス情報を取出してるっぽい。そして、その情報を元に新しいカーネル nbsd を作る。configの2番目の用例だな。

どんな情報が出てくるか、ログしてみる。

vbox$ doas dmassage -f /bsd >LOG
config: eof

そして、確認。530ヶも不要なデバイスが有るとな。GENERICってのは、そんなに色々なデバイスがサポートされてるのか。さすがi386の世界だな。

disable 0    video* at uvideo*|utvfu*
disable 2    midi* at umidi*|sb0|sb*|mpu*|mpu*|autri*|eap*|env
disable 3    drm0 at inteldrm*|radeondrm*
 :
disable 529  ipmi0 at mainbus0
disable 530  esm0 at mainbus0
quit

実際に書き換えたカーネルを作ってみる。

vbox# dmassage -f /bsd | config -e -o /tmp/nbsd /bsd
OpenBSD 7.2 (GENERIC.MP) #2: Thu Nov 24 23:53:30 MST 2022
    root@syspatch-72-i386.openbsd.org:/usr/src/sys/arch/i386/compile/GENERIC.MP
Enter 'help' for information
ukc> disable 0    video* at uvideo*|utvfu*
  0 video* disabled
ukc> disable 2    midi* at umidi*|sb0|sb*|mpu*|mpu*|autri*|eap*|env
  2 midi* disabled
 :
ukc> disable 530  esm0 at mainbus0
530 esm0 disabled
ukc> quit
Saving modified kernel.

そして、差分を確認。カーネルのサイズには変更は無い。だからデバイス探索のスイッチがOFFになってるんだね。これで、余分な手間が省けるから、起動が速くなるって寸法だな。

vbox# cmp -l /bsd /tmp/nbsd
13220543   2   4
13220607   2   4
 :
13237407   2   4
13237503   0   3

real kernel conf

dmassageの用例に、-f /bsdなんてのがある。バイナリーファイルであるカーネルをperlが扱えるのか? そんな疑問が芽生えたぞ。しゃーない、perl言語と対面するか。

# Globals.
my $GETCONF = "/bin/echo 'lines 1000\nlist' | /usr/sbin/config -e";
my $DMESG = "/var/run/dmesg.boot";

こんなのが宣言されてた。ならば、それを撫ぞってやろう。

riscv# config -e -o /tmp/xx /bsd
OpenBSD 7.2 (SEEING) #3: Fri Nov 18 16:30:39 JST 2022
    sakae@riscv.my.domain:/sys/arch/riscv64/compile/SEEING
Enter 'help' for information
ukc> help
        help                                Command help list
        add             dev                 Add a device
        base            8|10|16             Base on large numbers
        change          devno|dev           Change device
        disable         attr val|devno|dev  Disable device
        enable          attr val|devno|dev  Enable device
        find            devno|dev           Find device
        list                                List configuration
        lines           count               # of lines per page
        show            [attr [val]]        Show attribute
        exit                                Exit, without saving changes
        quit                                Quit, saving current changes
        nkmempg         [number]            Show/change NKMEMPAGES

ふむ、途中で止らないようにページサイズを1000行にしておいてからlistするんだな。こういうインターフェースが用意されているとは、今迄configを扱っていて重大な見落としだな。

ukc> lines 1000
ukc> list
  0 vscsi0 at root flags 0x0
  1 softraid0 at root flags 0x0
  2 mainbus0 at root flags 0x0
  3 cpu0 at mainbus0 early -1 flags 0x0
  :
109 hotplug count 1 (pseudo device)
110 wsmux count 2 (pseudo device)

ハードなデバイスとソフトな仮想デバイスの現在の状況を教えてくれるんだな。じゃ、ちょっと実験で、ホットプラグってデバイスを無効にしてみる。

ukc> disable 109
109 hotplug disabled
ukc> list
 :
109 hotplug count 1 disable (pseudo device)
110 wsmux count 2 (pseudo device)

ちゃんとdisableになった。これだけ分れば、あえてperl語を解析する必要は無いだろう。

実際に最小デバイスのカーネルを作って起動してみたけど、圧倒的に時間を食ているのは、/etc/rcの実行部分だったよ。体感スピードで効いてくるのは、カーネルのコンパイル時だけそうだ。

mkheaders()

前回の積み残しであったconfigの追求。何が対象になるかと調べたら、ずっと前の方でファイルリストを作っていた。

(gdb) b addfile if flags != 0
Breakpoint 1 at 0x9be2: file files.c, line 94.
(gdb) r -b /tmp/K -s /sys SEEING
Starting program: /tmp/config -b /tmp/K -s /sys SEEING

(gdb) bt
#0  addfile (nvpath=0x797afd20, optx=0x797b5020, flags=4, rule=0x0) at files.c:94
#1  0x19c5a1a6 in yyparse () at gram.y:177
#2  0x19c5c710 in main (argc=1, argv=0xcf7efc98) at main.c:267

(gdb) up
#1  0x19c5a1a6 in yyparse () at gram.y:177
177             XFILE pathnames fopts fflgs rule { addfile($2, $3, $4, $5); };

難解なやつが出てきた。少しmanを当って、書き方のルールを調べてみる。

file.conf(5)

needs-flag   Create an attribute header file, defining whether or not
             this attribute is compiled in.
needs-count  Create an attribute header file, defining how many instances
             of this attribute are to be compiled in.  This rule is
             mostly used for pseudo-devices.

対象を探してみる。

vbox$ cd /sys/dev
vbox$ find . -name 'files.*' | xargs grep needs
./acpi/files.acpi:file  dev/acpi/acpi.c                 acpi needs-flag
./acpi/files.acpi:file  dev/acpi/acpicpu.c              acpicpu needs-flag
  :

こういうやつを選び出しているんだな。最初にがfileで始まる、それが$1。続いてファイル名($2)、次がfopt($3)、そしてfflgs($4)、次がルールとな。こういう風にaddfileの引数を組み立てているんか。

下記は、一例

(gdb) p *fi
$9 = {
  fi_next = 0x0,
  fi_srcfile = 0x797b5760 "/sys/conf/files",
  fi_srcline = 100,
  fi_flags = 4 '\004',
  fi_lastc = 0 '\000',
  fi_nvpath = 0x797afd20,
  fi_base = 0x797bcf40 "drm_drv",
  fi_optx = 0x797b5020,
  fi_optf = 0x0,
  fi_mkrule = 0x0
}
(gdb) p *fi.fi_nvpath
$10 = {
  nv_next = 0x0,
  nv_name = 0x797b3ee0 "dev/pci/drm/drm_drv.c",
  :
}

mkioconf()

次は、見落とししてたけど、大事そうなやつ。

唯一ダイナミックに作成されるCのソースファイル。動き出したカーネルがこのソースで定義された情報を参照して、ドライバーの設定を変更するのに使われる。ざっと見てみたけど、FreeBSDには無い機能だ。

何故って、そんな機能は、モジュールシシテムが実現しちゃっているから(Linuxも同様だ)。でも、これって、モジュールはカーネルの外側に有るんで、セキュリティー的な弱点になる。それを嫌ってOpenBSDは、モジュール方式を止めた。その変わりにカーネルが許す範囲で、機能をON/OFF出来るようにした。4.1BSDで登場して、4.4BSDで更新されたって事だ。

mkioconf(void)
{
        qsort(packed, npacked, sizeof *packed, cforder);
        if ((fp = fopen("ioconf.c", "w")) == NULL) {
             :
           v = emithdr(fp);
        if (v != 0 || emitexterns(fp) || emitloc(fp) ||
            emitlocnames(fp) || emitpv(fp) || emitcfdata(fp) ||
            emitroots(fp) || emitpseudo(fp)) {

例の失敗しない限り、実行してくって方式で、長くなるコードを適当に分解してる。

ここに到達する前に作られ整理された情報はpackedに入っている。例えばあるドライバーは複数の親で使えるって言うような情報を上手く表現するとかだ。packed.cに詳しい説明が有るけど、日曜プログラマーには、ちと荷が重いので省略する。

config -e

カーネルのconfigを変更してみる。主対象はドライバー類のON/OFFとかだ。取り上げるのはお馴染の金魚時計。金魚は中国原産ってチコちゃんでやってたね。農林水産省は、錦鯉の輸出を頑張るそうだからね。

riscv$ gdb config
(gdb) r -e -o /tmp/X bsd
ukc> find gfrtc
 48 gfrtc* at syscon*|simplebus*|mainbus0 early 0 flags 0x0
ukc> disable 48

Breakpoint 1, disable (devno=48) at ukcutil.c:609
609             int done = 0;
(gdb) bt
#0  disable (devno=48) at ukcutil.c:609
#1  0x0000000b100c3ba8 in Xdisable (cmd=0x3ffffc5210) at cmd.c:137
#2  0x0000000b100c3214 in config () at ukcutil.c:1348
#3  0x0000000b100bed30 in ukc (file=0x3ffffc6998 "bsd", outfile=0x0, uflag=0,
    force=0) at ukc.c:161
#4  0x0000000b100b1cf2 in main (argc=1, argv=0x3ffffc6858) at main.c:220
613                     cd = get_cfdata(devno);
(gdb) p *cd
$1 = {
  cf_attach = 0xffffffc000677190,
  cf_driver = 0xffffffc00080d038,
  cf_unit = 0,
  cf_fstate = 2,
  cf_loc = 0xffffffc00080b510,
  cf_flags = 0,
  cf_parents = 0xffffffc00080b4be,
  cf_locnames = 1,
  cf_starunit1 = 0
}
(gdb)
615                     switch (cd->cf_fstate) {
(gdb)
620                             cd->cf_fstate = FSTATE_DSTAR;
(gdb)
621                             break;
(gdb) p cd.cf_fstate
$2 = 4
 :

ほー、 cf_fstate が、スイッチになるのか。

autoconf

何気に autoconf(9) なんてやってみたら、下記のような集合が出てきた。/usr/share/man/man9には、確かにautoconfと言う原稿が置いてあるんで、親切心の発露かな。

NAME
     config_search, config_rootsearch, config_found_sm, config_found,
     config_rootfound - autoconfiguration framework

config_search で、どこから呼び出されるか確認しる。

(gdb) bt
#0  config_search (fn=<optimized out>, parent=0xffffffc002da4000, aux=<optimized out>) at /usr/src/sys/kern/subr_autoconf.c:1\
88
#1  0xffffffc0002e6a80 in config_found_sm (parent=0xffffffc002da4000, aux=0xffffffc000805c80, print=0x0, submatch=0xffffffc00\
03646b0 <mainbus_match_primary>) at /usr/src/sys/kern/subr_autoconf.c:321
#2  0xffffffc000364964 in mainbus_attach_node (self=0xffffffc002da4000, node=1004, submatch=0xffffffc0003646b0 <mainbus_match\
_primary>) at /usr/src/sys/arch/riscv64/dev/mainbus.c:254
#3  0xffffffc000364602 in mainbus_attach_cpus (self=0xffffffc002da4000, match=0xffffffc0003646b0 <mainbus_match_primary>) at \
/usr/src/sys/arch/riscv64/dev/mainbus.c:314
#4  0xffffffc0003643fc in mainbus_attach (parent=<optimized out>, self=<optimized out>, aux=<optimized out>) at /usr/src/sys/\
arch/riscv64/dev/mainbus.c:126
#5  0xffffffc0002e6c9a in config_attach (parent=0x0, match=<optimized out>, aux=0x0, print=0x0) at /usr/src/sys/kern/subr_aut\
oconf.c:412
#6  0xffffffc0002e6e48 in config_rootfound (rootname=0xffffffc000623abc "mainbus", aux=0x0) at /usr/src/sys/kern/subr_autocon\
f.c:337
#7  0xffffffc00038e096 in cpu_configure () at /usr/src/sys/arch/riscv64/riscv64/autoconf.c:53
#8  0xffffffc00030adb4 in main (framep=<optimized out>) at /usr/src/sys/kern/init_main.c:336

次は、 gfrtc_match で、金魚時計を発見して、それを取り入れる部分。

(gdb) bt 4
#0  gfrtc_match (parent=<optimized out>, match=<optimized out>, aux=0xffffffc000805c80) at /usr/src/sys/dev/fdt/gfrtc.c:96
#1  0xffffffc0002e661a in mapply (m=0xffffffc000805bb8, cf=0xffffffc00080bfa0 <cfdata+2688>) at /usr/src/sys/kern/subr_autoco\
nf.c:147
#2  0xffffffc0002e64ee in config_search (fn=<optimized out>, parent=0xffffffc002da4000, aux=<optimized out>) at /usr/src/sys/\
kern/subr_autoconf.c:216
#3  0xffffffc0002e6a80 in config_found_sm (parent=0xffffffc002da4000, aux=0xffffffc000805c80, print=0x0, submatch=0xffffffc00\
2da4000) at /usr/src/sys/kern/subr_autoconf.c:321
(More stack frames follow...)

kern/subr_autoconf.c に面白い関数が有って、ON/OFF を参照してた。

(gdb) bt
#0  mapply (m=0xffffffc000805ec8, cf=0xffffffc00080b590 <cfdata+112>) at /usr/src/sys/kern/subr_autoconf.c:132
#1  0xffffffc0002e6e32 in config_rootsearch (fn=<error reading variable: Cannot access memory at address 0x0>, aux=0x0, rootn\
ame=<optimized out>) at /usr/src/sys/kern/subr_autoconf.c:300
#2  config_rootfound (rootname=0xffffffc000623abc "mainbus", aux=0x0) at /usr/src/sys/kern/subr_autoconf.c:336
#3  0xffffffc00038e096 in cpu_configure () at /usr/src/sys/arch/riscv64/riscv64/autoconf.c:53
#4  0xffffffc00030adb4 in main (framep=<optimized out>) at /usr/src/sys/kern/init_main.c:336

呼ばれた時の状況例。

132             if (m->indirect)
1: *m = {
  fn = 0xffffffc00029ccba <simplebus_submatch>,
  parent = 0xffffffc002da5000,
  match = 0x0,
  aux = 0xffffffc000805b98,
  indirect = 0,
  pri = 0
}

etc

Porting OpenBSD to RISC-V ISA

今年の更新は、これで終りです。来年も 4649。


This year's Index

Home