2010年9月12日 星期日

DKMS和KERNELRELEASE變數

當 Makefile 是從 kernel build system 被呼叫執行時,KERNELRELEASE 變數會被 kbuild 定義。

這是一個常見的 Makefile 小技巧,判斷 KERNELRELEASE 是否定義來執行不同的設定。

如下列是compat-wireless的Makefile,就用到這樣的技巧:

  1. (SKIP)

  2. ifneq ($(KERNELRELEASE),)

  3. NOSTDINC_FLAGS := -I$(M)/include/ \
  4. -include $(M)/include/linux/compat-2.6.h \
  5. $(CFLAGS)

  6. obj-y := compat/

  7. obj-$(CONFIG_COMPAT_RFKILL) += net/rfkill/

  8. ifeq ($(BT),)
  9. obj-$(CONFIG_COMPAT_WIRELESS) += net/wireless/ net/mac80211/
  10. obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/


  11. endif


  12. else

  13. export PWD := $(shell pwd)
  14. CFLAGS += \
  15. -DCOMPAT_BASE_TREE="\"$(shell cat compat_base_tree)\"" \
  16. -DCOMPAT_BASE_TREE_VERSION="\"$(shell cat compat_base_tree_version)\"" \
  17. -DCOMPAT_PROJECT="\"Compat-wireless\"" \
  18. -DCOMPAT_VERSION="\"$(shell cat compat_version)\""

  19. # These exported as they are used by the scripts
  20. # to check config and compat autoconf
  21. export COMPAT_CONFIG=config.mk
  22. export CONFIG_CHECK=.$(COMPAT_CONFIG)_md5sum.txt
  23. export COMPAT_AUTOCONF=include/linux/compat_autoconf.h
  24. export CREL=$(shell cat $(PWD)/compat_version)
  25. export CREL_PRE:=.compat_autoconf_
  26. export CREL_CHECK:=$(CREL_PRE)$(CREL)

  27. include $(PWD)/$(COMPAT_CONFIG)

  28. all: modules

  29. modules: $(CREL_CHECK)
  30. @./scripts/check_config.sh
  31. $(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules
  32. @touch $@

  33. (SKIP)

  34. endif


當從 shell 執行 make 時,因為 KERNELRELEASE 沒有定義,所以第23行到第39行之間的一些變數和 CFLAGS 會被設定,然後第45行會呼叫 kbuild 的 Makefile:
$(MAKE) -C $(KLIB_BUILD) M=$(PWD) modules

之後 compat-wireless 的 Makefile 又會被呼叫一次,此時 KERNELRELEASE 已經被 kbuild 所定義,所以第5行到第18行會被執行。而做的事情就如同一般的 module Makefile 將 driver 的路徑加入 obj-$CONFIG_* 中,如第15行:
obj-$(CONFIG_COMPAT_WIRELESS_MODULES) += drivers/net/wireless/




不過,DKMS 在 build module 時會自己傳入 KERNELRELEASE 這個參數,如在 /usr/sbin/dkms:function do_build():
local the_make_command=`echo $make_command | sed "s/^make/make KERNELRELEASE=${kernelver_array[0]}/"`


我們可以看到,在 compat-wireless 的 Makefile 中,當 KERNELRELEASE 變數已被設值時,並沒有 target 可以 build,必須是經由 kbuild 的 Makefile 來 make 才可以。

所以一個 workaround 是在 dkms.conf 中將 MAKE[0] 寫成 make -C /lib/modules/`uname -r`/build M=`pwd` modules。但是在這個例子中我們還必須先在 CLFAGS 中加入一些 define。直接呼叫kbuild的話,這些 CFLAGS 都沒設定,這樣並無法正確的 build 出 module。

所以,一個可行的辦法是將 Makefile 拆開,然後在 dkms.conf:MAKE[0] 中自行指定 Makefile,如:
make -f dkms.mk


雖然必須更改原始的 Makefile,但是卻可讓 DKMS 正確運作。

CONFIG_LOCALVERSION_AUTO和git describe

最近在編譯某家大廠的BSP時,發現kernel version在正常的tag之後被加了一大串東西:
include/config/kernel.release:1:2.6.32.11+drm33.2-16040-g98cebdd

2.6.32.11+drm33.2是Ubuntu Lucid kernel的version沒錯,但是後面的-16040-g98cebdd並不是Ubuntu kernel版號的一部份,看起來是像`git describe`的結果。

執行一下,果然沒錯:

$ git describe
v2.6.31-rc4-16040-g98cebdd

v2.6.31-rc4是某個tag,16040表示目前的HEAD是從tag v2.6.31-rc4之後第16040個commit,g98cebdd表示目前commit的git sha1前幾個值是98cebdd...。

而這個版號是因為 CONFIG_LOCALVERSION_AUTO=y 產生出來的。從LOCALVERSION_AUTO的文義有點難聯想到它的行為。

以下是完整的文件說明:


config LOCALVERSION_AUTO
bool "Automatically append version information to the version string"
default y
help
This will try to automatically determine if the current tree is a
release tree by looking for git tags that belong to the current
top of tree revision.

A string of the format -gxxxxxxxx will be added to the localversion
if a git-based tree is found. The string generated by this will be
appended after any matching localversion* files, and after the value
set in CONFIG_LOCALVERSION.

(The actual string used here is the first eight characters produced
by running the command:

$ git rev-parse --verify HEAD

which is done within the script "scripts/setlocalversion".)

Ubuntu kernel module使用的優先順序

在Ubuntu中,主要的kernel module來源大略有三種:

(1) 來自DKMS package:
會被安裝到 /lib/modules/`uname -r`/updates/

(2) Ubuntu kernel加入的driver
會被安裝到 /lib/modules/`uname -r`/kernel/ubuntu/

(3) Linux kernel tree中原本就有的driver。

正常情況下,我們希望DKMS所安裝的kernel module在modprobe時有較高的優先順序,因為通常使用者是因為系統內建的driver無法正確工作而自行安裝DKMS的package。

而Linux Ubuntu Module是Ubuntu kernel自行加入所需的新或較新版本的driver,應該還是要比kernel tree內附的driver有較高的使用順序。

觀察 /etc/depmod.d/ubuntu.conf 便可發現這些目錄的使用順序都在這個設定檔案中被指定:

search updates ubuntu built-in

2010年6月13日 星期日

UDS-M落幕

Ubuntu 10.04 (Lucid Lynx)才剛發表,Canonical和Ubuntu社群又開始忙著準備下一個版本的開發。首先就是5月10日到14日在比利時布魯塞爾召開的UDS-M (Ubuntu Developer Summit for Maverick)

在這一星期中,會有滿滿的議程用來討論下一版Ubuntu的藍圖(bluesprints),而討論完成的bluesprints會成為下一版Ubuntu的工作項目,會被持續的追踪進度。 :-)

對於kernel team而言,Jeremy Kerr關於device tree的session十分有趣:Device Tree OverviewALSA System on Chip (SoC) Flattened Device Tree BindingsUsing Device Tree on ARM

顯示Canonical是很重視ARM的這塊市場的(如新成立的LinaroCanonical也有參與)。

Canonical Kernel Team / 攝影者 Acelan


同時UDS也是Ubuntu開發者和社群間彼此討論、交換心得的一個機會,不只是可以和大廳走廊遇到的開發者閒聊,而是有一大堆的community team的session可以參加。只是可惜從沒遇到來自台灣的與會者。希望在下一次UDS-N可以遇到來自台灣社群的人參加。

如果你仔細看UDS的議程的話,會發現這是一個十分忙碌的一週,從早到晚的session、再加上時差、還有語言的隔閡、還要思考,更別提近20小時的飛行時間,每次回來都像是全身精力被抽光的狀態。

不過UDS的確是十分有生產力的一週,下一版Ubuntu的骨架都在這一週內被討論和決定。

2010年3月19日 星期五

處理無release event熱鍵的新方法

Notebook的熱鍵(hotkey)常是由客製化過的EC(embedded controller) code來控制,而且沒有一個統一的標準,所以常常帶來了一些混亂。

熱鍵缺少了key release event就是很常見的情形。像是在Fujitsu Amilo和Samsung NC系列,很多型號都有這樣的問題。

因為沒有release event,所以會發生「只有第一次按有用」「只按一下降低音量的鍵,卻變成靜音」等奇怪的情況。

2.6.31之前的kernel會在AT keyboard驅動程式(atkbd.c)中加了許多DMI quirk和熱鍵的scan code,只要型號和scan code符合,atkbd會自動加入release event。

不過,在這麼一般的驅動程式中加入一堆DMI quirk,並不是一個好主意。所以在2.6.32 kernel,便在/sys下加入了一個可以由userspace控制的介面:
/sys/devices/platform/i8042/serio0/force_release


要讓某些scan code自動的產生出release event,只要把hotkey的scan code用逗號隔開,再寫入(echo + pipeline)這個檔案,之後kernel便會自動的幫這些scan code產生出release event。

對於一個distro來說,最好能夠收集這些有問題的型號和熱鍵的scan code,並且自動的偵測和設定。以Ubuntu而言,從Ubuntu Karmic之後,熱鍵便從HAL改為由udev來管理。所以在Ubuntu Lucid中,udev也加入了這個新功能:

將DMI quirk紀錄在此:
/lib/udev/rules.d/95-keyboard-force-release.rules


將熱鍵的scan code紀錄在此:
/lib/udev/keymaps/force-release/


在Ubuntu Lucid中,處理這類問題,就不須再更動、重編kernel,只要簡單的修改一些udev script即可。

2010年3月16日 星期二

top中數值的意義

us: user cpu time
sy: system cpu time
ni: user nice cpu time
id: idle cpu time
wa: io wait cpu time
hi: hardware irq (servicing hardware interrupts)
si: software irq (servicing software interrupts)
st: steal time (time in involuntary wait by virtual cpu while hypervisor is servicing another processor)

man vmstat
man mpstat

2010年3月15日 星期一

為什麼用startx啟動X-window時 suspend會失敗

When login from the console, libpam-ck-connector will create XDG_SESSION_COOKIE. While you run `startx`, In /etc/X11/Xsession.d/90consolekit, it checks the environment variable XDG_SESSION_COOKIE is already set and will not create a proper CK session.

Try to `unset XDG_SESSION_COOKIE` before `startx` to see if suspend/hibernate works.