Monday 22 February 2010

Atom Z530 identity crisis

Last week I peeked at /proc/cpuinfo on a Atom Z530 netbook and got the following model name information:

model name : Intel(R) Core (TM) CPU Z530 @ 1.60GHz

Is the kernel mistaken? It's not a Core CPU, it's an Atom! In fact the Z530 is mistaken. If one examines page 29 of http://download.intel.com/design/processor/specupdt/319536.pdf you will see errata AAE29:

"AAE29 CPUID Instruction Returns Incorrect Brand String

When a CPUID instruction is executed with EAX = 80000002H, 80000003H and 80000004H on an Intel® Atom(TM) processor, the return value contains the brand string Intel(R) Core(TM)2 CPU when it should have Intel(R) Atom(TM) CPU."

Doh! That's a rather poor mistake in the silicon.

Apparently this affects Intel® Atom(TM) processors Z550, Z540, Z530, Z520, Z515, Z510, and Z500 on 45-nm process technology. It is fixable with a microcode fix, which normally involves getting a BIOS upgrade.

The errata makes interesting reading - especially errata AAE44 and AAE46 - for older kernels I suggest booting with kernel boot option mem=nopentium to work around any bizarre kernel oopses caused by these particular processor bugs. In fact, I recommend this for any Atom processor as these bugs seem to also apply to the Atom Nxxx series to.

Friday 19 February 2010

Examining Wifi Signal Quality

If one looks at the Wifi signal quality reported by a variety of Linux laptops one will see a range of different results even though the machines are the same distance from an access point.

So why is this? Well, some of it has to do with the physical hardware - antennae, diversity, and the wifi silicon too. The other factor to consider is the Wifi driver, which may or may not calculate the signal quality as one would expect.

Bill Moss has written an excellent article describing the method used to calculate the ipw2200 wireless signal quality. It's based on a least squares fit on four data points from calibrations on the Windows XP driver. His article compares the traditional linear model based on the raw hardware provided Received Signal Strength Indicator (RSSI) values to the quadratic model used by the ipw2200 driver. It's an interesting read.

The problem is that the RSSI scale is vendor specific and maximum values vary (e.g. Ciscso uses 101, Atheros 60). RSSI is not associated with any power scale such as mW - it is an arbitrary scale which the hardware provides to a device driver. One should not assume that the values are precise or even very accurate either. There is more detail about this in this posting by Afsaneh Sattari. Hopefully you see the problem.

Looking at drivers in more detail, one finds the calculation varies from driver to driver:

For example Ath9K, Ath5K, Hostap, iwmc3200, rtl8187 and wl12xx drivers (to name but a few) use a linear mapping from the RSSI to calculate the signal quality. iwlwifi uses a least squares fit, rt2x00 uses a scaled down RSSI with a larger mix of TX/RX success and failure weightings. And libertas uses RSSI with a mix of TX success and failure weightings.

So next time you compare your Wifi signal quality on your laptop with somebody else bear in mind there are many factors to make up this meaningless indicator of quality metric!

Tuesday 16 February 2010

GCC inline assembler explained

There are times when the Linux Kernel uses inline assembler to either use specific instruction sequences for optimal code efficiency or to use processor features that are not accessible in C (e.g. memory barriers, I/O instructions, manipulating processor state, etc..).

GCC provides a mechanism to enable one to place inlined assembler into C source but to the beginner the syntax can be a little impenetrable. A useful little primer and guide to GCC inline assembler can be found at http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html

The primer is a little old, but nevertheless it is still valid and very useful.

Monday 15 February 2010

Kernel Oops page fault error codes

The x86 Linux kernel Oops messages provide normally just enough information to help a kernel developer corner and fix critical bugs. The start of a typical Oops message may look like the following:

kernel BUG at kernel/signal.c:1599!
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pc = 84427f6a
*pde = 00000000
Oops: 0001 [#1]

The 4 digit value after the "Oops:" message dumps out the page fault error code in hexadecimal which in turn can help one deduce what caused the oops. The page fault error code is encoded as follows:

bit 0 - 0 = no page found, 1 = protection fault
bit 1 - 0 = read access, 1 = write access
bit 2 - 0 = kernel-mode access, 1 = user mode access
bit 3 - 0 = n/a, 1 = use of reserved bit detected
bit 4 - 0 = n/a, 1 = fault was an instruction fetch

So, in the above example, the Oops error code was 0x0001 which means it was a page protection fault, read access in kernel mode.

A lot of Oops error codes are 0x0000, which means a page was not found by a read access in kernel mode.

For more information, consult arch/x86/mm/fault.c

Sunday 14 February 2010

200 Mbps Powerline Ethernet Plugs

This week I bought a pair of 200 Mbps powerline ethernet plugs from Faculty-X to add some extra home network connectivity. Up until now I've been happy with the speed of my 80211g Wifi network, but I really wanted to get a faster connection between two parts of my house and I didn't want to run any Ethernet cabling through my walls.

I purchased some budget powerline plugs which did state on the box they worked for Windows, Mac and Linux, but on receiving them found that one needed to run a Windows based configuration tool to configure a password protected private LAN connection between the two plugs. However, by default, one can just plug these devices into the electrical wall sockets and they work, but the network is public.

So I gritted my teeth and tried to run the configuration software from Wine, but I could not connect to the plugs. Then I tried from a virtual Windows Vista inside KVM and also failed to connect and configure the devices. Finally, I installed Vista on a sacrificial laptop, ran the configuration software and configured the two plugs to run as a private network. Amusingly I was able to scan and find some other powerline plugs with very week signals, so somebody else down my street is using similar kit.

The private network is protected using 128 bit AES encryption on the link, plus I only connect to machines using ssh, so hopefully it reduces the snooping risk.

My gripe is that a box should not be labelled "compatible with Windows, Mac and Linux" when in fact the configuration software in Windows based. This is totally misleading and disingenuous. To have to run a OS-centric app to get the full functionality of networking kit is very lame.

The pragmatic side of my personality chose to go the path of least resistance and configure the powerline plugs using Windows (with much gnashing of teeth). The hacker side of my personality wanted to capture the packet activity between the the configuration application and the powerline plug to help me write a open source configuration tool. When I get a spare 10 minutes I will write to the manufacturer and see if they will open up the configuration protocol...

As for speed - well, I'm fairly pleased. With the two devices plugged into a 4 way power socket I was able to get about 150Mbs+ and between two floors in my house across two ring mains (with fairly old wiring) I was able to get about 100Mbs which isn't bad considering all the noisy kit such as fridges that cause interference.

My upstairs network has been mainly wifi based - even my server runs off a Ralink wifi card. I mainly ssh into my server, so network performance has not really been an issue. However, as of this weekend, my server is now connected to the network via one of these powerline plugs I can now send a Wake-on-LAN (WoL) packet to the server to switch it on remotely. I just installed the wakeonlan package and then run the wakeonlan command specifying the MAC address of the server's Ethernet card - easy!

The next few months will see how reliable these devices are. The technical blurb with the plugs states that they only use 6W - when I get a spare half hour I will measure the power consumption of an idle and busy network to get an idea of the true yearly running cost.

Wednesday 10 February 2010

x86 BIOS calls used by grub and Linux

The other day I was checking up to see which BIOS calls are used by grub and Linux.  I naively believed grub used just a few to get some disk geometry information and to do some reads as well as a little bit of console/keyboard I/O.  In fact Grub uses quite a few BIOS calls, namely:

BIOS "int 0x13 Function 0x41, bx=0x55aa" to check if LBA mode is
supported
BIOS "int 0x13 Function 0x42" read sectors from disk into memory (LBA
mode)
BIOS "int 0x13 Function 0x08" determine HDD geometry
BIOS "int 0x13 Function 0x02" read sectors from disk into memory
(non-LBA mode)
BIOS "int 0x13 Function 0x00" reset floppy drive (if not booted from
HDD)
BIOS "int 0x13 Function 0x4B01" check bootable CD-ROM emulation
status
BIOS "int 0x13 Function 0x4800" get driver paramaters

BIOS "int 0x15 Function 0xe801" get memory size (Phoenix BIOS v4.0)
BIOS "int 0x15 Function 0xe820" get memory map
BIOS "int 0x15 Function 0xc0" get ROM configuration
BIOS "int 0x15 Function 0x2400" disable A20 gate

BIOS "int 0x10 Function 0x4f00" get SVGA information (VBE)
BIOS "int 0x10 Function 0x4f01" get SVGA mode
BIOS "int 0x10 Function 0x4f02" set SVGA mode

BIOS "int 0x10 Function 0x01" set cursor shape
BIOS "int 0x10 Function 0x02" set cursor position
BIOS "int 0x10 Function 0x03" get cursor position and size
BIOS "int 0x10 Function 0x09" write character and attribute at cursor
BIOS "int 0x10 Function 0x0e" write character in teletype mode

BIOS "int 0x16 Function 0x00" keyboard - get keystroke
BIOS "int 0x16 Function 0x01" keyboard - check for keystroke

BIOS "int 0x1a Function 0x02" get real-time clock

BIOS Advanced Power Management (APM) calls: Grub will ignore APM if it does not detect it - it's not manditory to have APM for grub to work. So these are non required.

APM "int 0x15 Function 0x5300" check for APM
APM "int 0x15 Function 0x5301" connection real-mode interface
APM "int 0x15 Function 0x5304" disconnect interface
APM "int 0x15 Function 0x5307" set power state
APM "int 0x15 Function 0x530E" driver version


As for the Linux kernel, it also uses quite a range of BIOS calls, for example figuring out specific system settings and doing console work.

Below is a list of calls that I could find in the x86 arch specific code, I'm not sure if it's the fully definitive list, but I believe I found the majority of the BIOS calls.

BIOS "int 0x10 Function 0x00" set video mode
BIOS "int 0x10 Function 0x02" set cursor position
BIOS "int 0x10 Function 0x03" get cursor position and size
BIOS "int 0x10 Function 0x0e" write character in teletype mode
BIOS "int 0x10 Function 0x0f" get current video mode
BIOS "int 0x10 Function 0x0100" set cursor scan lines
BIOS "int 0x10 Function 0x1111" set 9x14 font
BIOS "int 0x10 Function 0x1112" set 8x8 font
BIOS "int 0x10 Function 0x1200" bl=0x10, check EGA/VGA
BIOS "int 0x10 Function 0x1200" bl=0x20, video, alternative function
select
BIOS "int 0x10 Function 0x1201" bl=0x34, turn of cursor emulation
BIOS "int 0x10 Function 0x1a00" get display combination code
BIOS "int 0x10 Function 0x4f00" get SVGA information (VBE)
BIOS "int 0x10 Function 0x4f01" get SVGA mode
BIOS "int 0x10 Function 0x4f02" set SVGA mode
BIOS "int 0x10 Function 0x4f08" get/sec DAC palette control
BIOS "int 0x10 Function 0x4f0a" get protected mode interface
BIOS "int 0x10 Function 0x4f15" check DDC capabilities

BIOS "int 0x15 Function 0x2401" enable A20 gate
APM "int 0x15 Function 0x5300" check for APM
APM "int 0x15 Function 0x5303" connect interface
APM "int 0x15 Function 0x5304" disconnect interface
BIOS "int 0x15 Function 0xe980" get Intel speedset information
BIOS "int 0x15 Function 0xec00" set BIOS CPU mode
BIOS "int 0x15 Function 0xc0" query MCA
BIOS "int 0x15 Function 0xe801" get memory size (Phoenix BIOS v4.0)
BIOS "int 0x15 Function 0xe820" get memory map
BIOS "int 0x15 Function 0x88" get extended memory size

BIOS "int 0x16 Function 0x00" keyboard - get keystroke
BIOS "int 0x16 Function 0x01" keyboard - check for keystroke
BIOS "int 0x16 Function 0x0305" set keyboard rate

BIOS "int 0x1a Function 0x02" get real time clock
BIOS "int 0x1a Function 0x02" get real time clock

Needless to say, some of these are not used for example, the use of some depend on how the console is configured.

Anyhow, it's quite surprising how much we still rely on core BIOS functionality to get a system up and running.  Kudos to Ralph Brown's interrupt list to help me figure out the BIOS int and function code mappings.

Sunday 7 February 2010

GCC hacks in the Linux Kernel

M. Tim Jones has written a concise and useful article on some useful special optimisation hints and capabilities found in version 4.3.2 of the GNU C Compiler.

The article describes how to use these methods and includes working examples found in Linux kernel. It will take just 5-10 minutes to read and is time worth spent to get up to speed with these useful GCC hacks

Monday 1 February 2010

inteltool - dumps Intel CPU/chipset configuration settings

A little used tool from the coreboot project is inteltool. This tool is useful for dumping the configuration space of Intel CPUs and for examining the Northbridge and Southbridge settings.

The debian package can be found in universe, and can be installed using:

sudo apt-get install inteltool

..and has to be run using sudo.

At the simplest level, it can be run to get CPU and Northbridge/Southbridge version information:

$ sudo inteltool
Intel CPU: Family 6, Model f
Intel Northbridge: 8086:2a00 (PM965)
Intel Southbridge: 8086:2815 (ICH8-M)

However, one can drill down a bit, for example to get a dump of the GPIO settings, use the -g flag, e.g.:

$ sudo inteltool -g
Intel CPU: Family 6, Model f
Intel Northbridge: 8086:2a00 (PM965)
Intel Southbridge: 8086:2815 (ICH8-M)

============= GPIOS =============

GPIOBASE = 0x1180 (IO)

gpiobase+0x0000: 0x99541d02 (GPIO_USE_SEL)
gpiobase+0x0004: 0xe0fa7fc2 (GP_IO_SEL)
gpiobase+0x0008: 0x00000000 (RESERVED)
gpiobase+0x000c: 0xe1aa5fc7 (GP_LVL)
gpiobase+0x0010: 0x00000000 (GPIO_USE_SEL Override (LOW))
gpiobase+0x0014: 0x00000000 (RESERVED)
gpiobase+0x0018: 0x00000000 (GPO_BLINK)
gpiobase+0x001c: 0x00000000 (GP_SER_BLINK)
gpiobase+0x0020: 0x00080000 (GP_SB_CMDSTS)
gpiobase+0x0024: 0x00000000 (GP_SB_DATA)
gpiobase+0x0028: 0x00000000 (RESERVED)
gpiobase+0x002c: 0x00001900 (GPI_INV)
gpiobase+0x0030: 0x00000146 (GPIO_USE_SEL2)
gpiobase+0x0034: 0x00540f70 (GP_IO_SEL2)
gpiobase+0x0038: 0x00540f74 (GP_LVL2)
gpiobase+0x003c: 0x00000000 (GPIO_USE_SEL Override (HIGH))

There are other options to dump out the RCBA, Power Management, Memory Controller, EPBAR, DMIBAR and PCIEXBAR registers as well as the CPU MSRs.

It's an excellent utility for digging into the configuration of any Intel PC.