I hate software

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Monday, 25 November 2013

KVM on ARM Cortex A15 (OMAP5432 UEVM)

Posted on 13:04 by Unknown
Hi! In this post I'll summarize the steps I needed to do in order to get KVM working on the OMAP5 ARM board using the virtualization extensions.

ARM A15 HYP mode.

In Cortex-A15, ARM have introduced a new operating mode called HYP (hypervisor). It has lower permissions than TruztZone. In fact, HYP splits the "insecure" world into two parts, one for hypervisor and the other one for the guests. By default on most boards the system boots into the insecure non-HYP mode. To enter the HYP mode, one needs to use platform-specific ways. For OMAP5 this involves making a call to the TrustZone which will restart the insecure mode cores.

A good overview of how virtualization support for ARM was added to Linux is available at LWN.
http://lwn.net/Articles/557132/

Ingo Molnar HYP patch

There was a patch for u-boot to enable entering HYP mode on OMAP5 by Ingo Molnar. Too bad, it was either written for an early revision of omap5 or poorly tested. It did not work for my board, so I had to learn about OMAP5 TrustZone SCM commands from various sources and put up a patch (which is integrated to my u-boot branch).
If you're interested, you can take a look at the corresponding mailing list entry.

http://u-boot.10912.n7.nabble.com/RFD-OMAP5-Working-HYP-mode-td163302.html

Preparing u-boot SD card

Get the android images from TI or build them yourself. You can use the usbboot tool to boot images from the PC. Or even better, you can build u-boot (this is the preferred way) and then you won't need android images. But you may need the TI GLSDK for the x-loader (MLO). Creating an SD card with u-boot is the same as for omap3 and omap4, so I'll leave this out. There is some magic with creating a proper partition table, so I advise that you get some prebuilt image (like ubuntu for pandaboard) and then replace the files in the FAT partition.

http://software-dl.ti.com/omap/omap5/omap5_public_sw/OMAP5432-EVM/5AJ_1_5_Release/index_FDS.html
http://www.omappedia.com/wiki/6AJ.1.1_Release_Notes

Please consult the OMAP5432 manual on how to set up the DIP switches to boot from SD card.

Source code

For u-boot:
https://github.com/astarasikov/uboot-tegra/tree/omap5_hyp_test

For linux kernel:
https://github.com/astarasikov/linux/tree/omap5_kvm_hacks

Linux kernel is based on the TI omapzoom 3.8-y branch. I fixed a null pointer in the DWC USB3 driver and some issues with the 64-bit DMA bitmasks (I hacked the drivers to work with ARM LPAE, but this probably broke them for anything else. The upstream has not yet decided on how this should be handled).

Compiling stuff

First, let's build the u-boot
#!/bin/bash
export PATH=/home/alexander/handhelds/armv6/codesourcery/bin:$PATH
export ARCH=arm
export CROSS_COMPILE=arm-none-eabi-
U_BOARD=omap5_uevm
make clean
make distclean
make ${U_BOARD}_config
make -j8

you'll get the u-boot.bin and the u-boot.img (which can be put to the SD card). Besides, that will build the mkimage tool that we'll need later.

Now, we need to create the boot script for u-boot that will load the kernel and the device tree file to RAM.

i2c mw 0x48 0xd9 0x15
i2c mw 0x48 0xd4 0x05
setenv fdt_high 0xffffffff
fdt addr 0x80F80000
mmc rescan
mmc part
fatload mmc 0:1 0x80300000 uImage
fatload mmc 0:1 ${fdtaddr} omap5-uevm.dtb
setenv mmcargs setenv bootargs console=ttyO2,115200n8 root=/dev/sda1 rw rootdelay=5 earlyprintk nosmp
printenv
run mmcargs
bootm 0x80300000 - ${fdtaddr} 

Now, compile it to the u-boot binary format:
./tools/mkimage -A arm -T script -C none -n "omap5 boot.scr" -d boot.txt boot.scr


Building linux:

export PATH=/home/alexander/handhelds/armv6/linaro-2012q2/bin:$PATH
export ARCH=arm
export CROSS_COMPILE=/home/alexander/handhelds/armv6/linaro-2012q2/bin/arm-none-eabi-
export OMAP_ROOT=/home/alexander/handhelds/omap
export MAKE_OPTS="-j4 ARCH=$ARCH CROSS_COMPILE=$CROSS_COMPILE"

pushd .
cd ${OMAP_ROOT}/kernel_omapzoom
make $MAKE_OPTS omap5uevm_defconfig
make $MAKE_OPTS zImage
popd

Now, we need to compile the DTS (device tree source code) using the dtc tool. If you choose to use the usbboot instead of u-boot, you can enable the config option in kernel and simply append the DTB blob to the end of zImage.
(Boot Options -> Use appended device tree blob to zImage)

./scripts/dtc/dtc arch/arm/boot/dts/omap5-uevm.dts -o omap5-uevm.dtb -O dtb
cat kernel_omapzoom/arch/arm/boot/zImage omap5-uevm.dtb > kernel
./usbboot -f; fastboot -c "console=ttyO2 console=tty0 rootwait root=/dev/sda1" -b 0x83000000 boot kernel

VirtualOpen

For userspace part, I've followed the manual from VirtualOpenSystems for versatile express. The only tricky part was building qemu for the ArchLinux ARM host, and the guest binaries are available for download.
http://www.virtualopensystems.com/media/kvm-resources/kvm-arm-guide.pdf


P.S. please share your stories on how you're using or plan to use virtualization on ARM
Read More
Posted in | No comments

Sunday, 24 November 2013

An update on OSX Touchscreen driver

Posted on 14:43 by Unknown
After playing with the HID interface in OS X, I have found out there exists an API for simulating input events from user space, so I've implemented the touchscreen driver using it.

One unexpected caveat was that you need to set up an increasing event number to be able to click the menu bar. Even worse, when launched from XCode, the app would hang if you clicked the XCode menu bar. If you click any other app or launch it outside XCode, everything's fine. Caused some pain while debugging.

Now I still want to implement the driver as a kernel module. On the other hand, the userspace version is also fine. I want to add the support for multitouch gestures, though I'm not sure it is possible to provide multiple pointers to applications.

<iframe width="560" height="315" src="//www.youtube.com/embed/ccMOPNel-2k" frameborder="0" allowfullscreen></iframe>

The code is at github https://github.com/astarasikov/osxhidtouch

You can get the binary OSX touchscreen driver for the Dell S2340T screen from the link below. Basically, you can replace the HidTouch binary with your own, and if you put it to "HidTouch.app/Contents/MacOS/HidTouch", you will get an app bundle that can be installed to Applications and added to the auto-start.
https://drive.google.com/file/d/0B7wcN-tOkdeRRmdYQmhJSWsta1U/edit?usp=sharing
Read More
Posted in | No comments

Thursday, 21 November 2013

Multitouch touchscreen support in OS X

Posted on 15:55 by Unknown
Hi there!

I happen to have a Dell S2340T multitouch monitor (quite an expensive toy btw) which has a touch controller from 3M. It works fine in Windows (which I don't have any plans to use), sort of works in linux (which is my primary work environment) and does not work at all in OS X (not a big deal but it would be cool to have it).

So I set out on the search for a driver and have figured out the following:

  • There is some old driver from TouchBase that sucks. I mean, it's using some stinky installer that pollutes the OS X root file system, it has the UI from 90s. More than that, it's not signed and does not support my touchscreen. Even adding the USB Vendor ID to its Info.plist did not fix a thing
  • There is some new trial driver from TouchBase that should work for most devices but is limited to 100 touches (a demo version). Well, I didn't want to grovel before them and sign up at their stupid site. And still, even if I patched the driver to remove the trial limitations, I would have to sign it with my certificate and there would be no legal way for me to distribute it on the internetz
  • There is a full version of the TouchBase driver that costs $100. Are they fucking crazy? On the other hand, I would do the same. See, home users don't care, multitouch displays are very rare, and people are used to pirating sofrware. But one could raise quite some money selling the driver to the workshops that build customized Apple computers (like ModBook) or car PCs.
  • There are some drivers for other touchscreens, but they're for the old single-touch devices

Doesn't look promising. Now, one may wonder "WTF ain't it working out of the box? It's a HID device, should work everywhere". Well, there are two problems:

  • Multitouch devices have the new HID event type (called HID usages) for the Digitizer class which the OS X does not support in IOKit.  Actually, since it uses a new HID class (different to single-touch monitors), it is not even classified as a touchscreen by the OS (rather as a multitouch trackpad)
  • The touchscreen gets recognized by the generic HID driver as a mouse. And here comes the problem - when a finger is released, the device reports the pointer to be at the origin (point <0, 0>) which causes the cursor to be stuck at the top left corner
I decided to learn about the HID system in OS X and write a driver. I started with the sample code from the HID documentation and added some event debugging. I found out that the device reports the events both as a digitizer and as a pointing device. So for now I prepared a demo app in Qt5 that can recognize multiple touches and draw points in different colors when the screen is touched. Have a look at it in action:


The source code is at https://github.com/astarasikov/osx-multitouch-demo .


Well, looks like I should figure out how to turn this into a device driver. I will probably need to figure out how to enumerate HID devices based on their class and make a kext file (Kernel EXTension) for XNU (the kernel used in OS X) and then.. sell my driver for some $20, right?
Read More
Posted in | No comments

Tuesday, 12 November 2013

Using a hybrid graphics laptop on linux

Posted on 11:33 by Unknown

Introduction.

I have a laptop with so-called hybrid graphics. That is, it has two GPUs - one of them is part of the SoC (Intel HD3000 GPU), the other one is the "discrete" PCIe Radeon HD 6630M from AMD. Typicaly, older models of dual-GPU laptops (and new Apple Macbook Pro machines) have a multiplexer that switches the output from the GPU to display. As the majority of modern laptops, my features a "muxless" combination of the GPUs - that is, the more powerful GPU does not have any physical connection to the display panel. Instead, it can write to the framebuffer memory of the less powerful GPU (or it can perform only the computational part of OpenGL/DirectX and let the primary GPU handle 2D drawing and blitting).

Linux support for the hybrid graphics if far from perfect. To be honest, it just sucks even now that such kind of laptop have been dominating the market for some 4-5 years already. With the recent advent of the "DRI-PRIME" interface the linux kernel and userspace now supports using the secondary GPU for offloading intensive graphic workloads. Right now to utilize the separate GPU, an application has to be launched with a special environment variable (namely, "DRI_PRIME=1") and the system is supposed to dynamically power-up the GPU when it is needed and turn it off to reduce power consumption and heating at other times. Unfortunately, the support for power management is still deeply broken. In this post I summarize my findings and scripts which allow to turn off the external GPU permanently to save power and increase the battery life of the laptop. I am not using the secondary GPU because OpenGL and X11 drivers for the Intel GPU are more stable, and the open-source Radeon driver/mesa does not yet support OpenCL (the computational API for GPUs).

vga_switcheroo

The kernel interface for controlling the power for the external GPU is called "vga_switcheroo" and it allows to power-down the GPU. Unfortunately, I have found out that my laptop (and most others) enable the GPU after a suspend-resume cycle. I think this behaviour is intentional, because ACPI calls should be used to control the power of the GPU. However, it confuses the vga_switcheroo which thinks the card is still powered down. Meanwhile, the card drains some 10-30 watts of power, effectively reducing the laptop battery life from 7 hours to 2 hours or so.

My first stab at this problem was a patch that forced the vga_switcheroo to disable all the cards that were not held by the userspace at resume. That did solve the problem for a while, but was hackish and never made it into the mainline kernel. However, it is still useful for linux kernels up to 3.9.
http://lkml.indiana.edu/hypermail/linux/kernel/1204.3/02530.html

kernel 3.10+

As of linux version 3.10, several changes were made in regards to the hybrid graphics power management. First is the introduction of the dynamic power management (in the form of clock control code and parsing the predefined power states provided by the OEM BIOS) for the Radeon chips. Second one is the change to the vga_switcheroo which allowed it to power down the card when unused without the user interaction. It does work to some extent, but the problem with the card being powered on after a sleep-resume cycle remains.

The problem is that now, when I manually disable the card via the vga_switcheroo, the PCI device is gone - it is removed and never appears again. The same behaviour could be exhibited on pre-3.10 kernels if one did issue the "remove" command to the DRM node (/sys/class/drm/card1/). Besides, my hack to the vga_switcheroo stopped working since these upgrades. Now, this did not make me happy and I set out to figure out the solution.

acpi_call

Linux powers off the radeon GPU using the PCIe bridge and GPU PCIe registers. A "portable" and "official" way to control the power of a GPU is using an ACPI call. ACPI is an interface for the Intel-X86 based computers (although now also implemented for the ARM CPUs in an attempt to provide the support for UEFI, Windows RT and an unified linux kernel binary capable of running on any ARM SoC) intended to provide abstraction of hardware enumeration and power management. It contains tables with lists of PCI and other PNP (plug-and-play) peripherals which can be used by the OS kernel instead of the unsafe "probing" mechanism. Moreover, it contains a specification for the interpreted bytecode language. Some methods are implemented by the OEM inside the BIOS ACPI tables to perform certain functions - query battery status, power up- and down the devices etc.

Folks have since long figured out to use ACPI calls in linux to control the power of the discrete GPU. Although it could interfere with the vga_switcheroo interface, in case we either completely disable the external GPU or power it off via vga_switcheroo first, we're safe to use it. Moreover, I have found out that I can use an ACPI call to power on the device and make it visible to the system after it is removed as described in the previous paragraph!

There exist a module for the linux kernel that allows to perform arbitrary ACPI calls from the userspace. Turns out that a direct ACPI call can even work around the new vga_switcheroo. There's a good guide on installing the acpi_call module into the DKMS subsystem so that it is automatically packaged and built any time you upgrade the linux kernel on your machine.
http://garyservin.wordpress.com/2012/01/06/disabling-discrete-gpu-in-debian-gnulinux-wheezy/

The module contains the turn_off_gpu.sh script in the examples folder which can be used to power down the GPU. I ran it and took a notice of the method used for my laptop - it was the "\_SB.PCI0.PEG0.PEGP._OFF" (which means South Bridge -> PCI controller 0 -> Pci Express Graphics -> Pci Express Graphics Port).

Now, I did the following magical trick:
echo "\_SB.PCI0.PEG0.PEGP._ON" > /proc/acpi/call
And BANG! after being gone when turned off via the vga_switcheroo, the GPU was identified by linux and enabled again. Neato.

Putting it all together.
Now the real showstopper is that the card still drains power after resume. I figured I had to write a script which would power down the card. It turned out that sometimes if the laptop was woken up and then it immediately went to sleep due to some race condition, systemd did not execute the resume hook.

Instead, I used the udev. Udev is a daemon that listens for the events that the kernel sends when hardware state changes. Each time the laptop wakes up, the power supply and battery drivers are reinitialized. Besides, the primary GPU also sends wakeup events. Another two observations are that I'm not using the discrete GPU and it is safe to call the ACPI "OFF" method multiple times. So, it is not a problem if we call the script too many times. I decided to just call it on any event from the two aforementioned subsystems. Here is how it can be done (note that you need to have root permissions to edit the files in /etc. If you are a newcomer to linux, you can become root by issuing a "sudo su" command):

Create the file "/etc/udev/rules.d/10-battery-hook.rules" with the following contents:
ACTION=="change", SUBSYSTEM=="power_supply", RUN+="/etc/gpu_poweroff.sh"
ACTION=="change", SUBSYSTEM=="drm", RUN+="/etc/gpu_poweroff.sh"

Now, create the /etc/gpu_poweroff.sh script with the contents mentioned below. You can uncomment the "echo" calls to debug the script and verify it is getting called. By the way, the power_profile part is not necessary but is an example of how to put a radeon GPU into a low-power state without disabling it.

gpu_poweroff.sh

#!/bin/bash

#this is a script for lowering the power consumption
#of a radeon GPUs in laptops. comment out whatever portion
#of it you don't need

#echo "gpu script @`date`" >> /tmp/foo

if [ -e /sys/class/drm/card0 ] ;then
for i in /sys/class/drm/card*; do
if [ -e $i/device/power_method ]; then
echo profile > $i/device/power_method
fi
if [ -e $i/device/power_profile ]; then
echo low > $i/device/power_profile
fi
done
fi

if [ -d /sys/kernel/debug/vgaswitcheroo ]; then
echo OFF > /sys/kernel/debug/vgaswitcheroo/switch 
fi

acpi_methods="
\_SB.PCI0.P0P1.VGA._OFF
\_SB.PCI0.P0P2.VGA._OFF
\_SB_.PCI0.OVGA.ATPX
\_SB_.PCI0.OVGA.XTPX
\_SB.PCI0.P0P3.PEGP._OFF
\_SB.PCI0.P0P2.PEGP._OFF
\_SB.PCI0.P0P1.PEGP._OFF
\_SB.PCI0.MXR0.MXM0._OFF
\_SB.PCI0.PEG1.GFX0._OFF
\_SB.PCI0.PEG0.GFX0.DOFF
\_SB.PCI0.PEG1.GFX0.DOFF
\_SB.PCI0.PEG0.PEGP._OFF
\_SB.PCI0.XVR0.Z01I.DGOF
\_SB.PCI0.PEGR.GFX0._OFF
\_SB.PCI0.PEG.VID._OFF
\_SB.PCI0.PEG0.VID._OFF
\_SB.PCI0.P0P2.DGPU._OFF
\_SB.PCI0.P0P4.DGPU.DOFF
\_SB.PCI0.IXVE.IGPU.DGOF
\_SB.PCI0.RP00.VGA._PS3
\_SB.PCI0.RP00.VGA.P3MO
\_SB.PCI0.GFX0.DSM._T_0
\_SB.PCI0.LPC.EC.PUBS._OFF
\_SB.PCI0.P0P2.NVID._OFF
\_SB.PCI0.P0P2.VGA.PX02
\_SB_.PCI0.PEGP.DGFX._OFF
\_SB_.PCI0.VGA.PX02
\_SB.PCI0.PEG0.PEGP.SGOF
\_SB.PCI0.AGP.VGA.PX02
"

# turn off the dGPU via an ACPI call
if [ -e /proc/acpi/call ]; then
for i in $acpi_methods; do
echo $i > /proc/acpi/call
done
#echo "turned gpu off @`date`" >> /tmp/foo
fi

exit 0

Make it executable by issuing a "chmod +x /etc/gpu_poweroff.sh" command.
Also, take a look at the "/etc/rc.local" script. If it does not exist, simply create it with the following contents and make it executable:

#!/bin/sh -e
bash /etc/gpu_poweroff.sh
exit 0

If it does exist, insert the call to the "/etc/gpu_poweroff.sh" before the "exit" line.

Bonus

To silence the fans on the Sony Vaio laptop, you can add the following to your rc.local script (I advise against putting it to the gpu_poweroff script because this command has a noticeable delay):

if [ -e /sys/devices/platform/sony-laptop/thermal_control ]; then
echo silent > /sys/devices/platform/sony-laptop/thermal_control
fi
Read More
Posted in | No comments

Friday, 4 October 2013

Sleeping considered harmful

Posted on 13:18 by Unknown

Intrabduction

Synchronization is a very controversial topic in computer science and software engineering. We're caught up in a vicious circle where everyone is told syncronization is difficult and therefore tries to stay away from the topic, and when one has to deal with threading, they prefer to stay away from reading about synchronization because reading is even more difficult.

One thing I have noticed while developing linux software for various devices is that drivers written by hardware vendors inevitably suck. Today I will tell you about one thing that freaks me out (sure there's a whole universe of things that freak me out but that's beyond the scope of this post).

Now, sometimes, when dealing with hardware, one has to wait (sleep) some time after writing to registers to let the device change its state. One prominent example are the drivers for the LED controllers. Yeah, your fancy new Android paperweight probably has a color LED to notify when your friends sign on to FaceBoob. LEDs can have various triggers, for example, one can set a LED to blink when memory is accessed, just like on old desktop boxes with HDDs. Somehow every time you try to set a trigger to a LED in Android kernel (as opposed to using the Android's proprietary ioctls), the device just freezes dead. What actually happens?

If we take a look at the LED class definition in the linux kernel, we'll see that the functions controlling the LED state (which are to be implemented by the hardware vendor) must not use sleeping primitives like msleep or usleep. Why is such a requirement posed? There are two reasons. One is that LEDs can be used in a context that does not allow sleeping - for example, inside the scheduler code to indicate the CPU load. Sleeping while scheduling could be handled by kernel developers, of course, but such an operation will cause time drifting and increase the complexity of the scheduler. Another reason is that LED control code may be called thousands of times per second, and any delay will cause the huge CPU load.

Anyway, even the performance critical code needs to be correct, therefore the need for the synchronization. The lightweight synchronization primitive used throughout the whole kernel is the spinlock. As you may guess from its name, it does not block the calling thread (like a semaphore or a mutex would do), but busy-waits till it can get into critical section. Polling (or busy-waiting) has always been discouraged because it consumes CPU time. However, it allows the algorithm to progress instead of blocking (therefore, most lock-free algorithms use memory barriers and busy waiting which is equivalent to using a spin lock in kernel). Either way, what you should need about spinlocks is that in most cases they are used to guard writing to an IO register which is a very fast operation, and while a spinlock is held, interrupts are disabled, therefore if you called sleep(), your thread would have no way to resume.

And yeah, most newbie driver developers don't know that some external busses (like I2C) require sleeping due to the nature of hardware. So, when one issues an I2C transfer inside the spinlock, they just want to see the kernel freeze.

Now that we've figured out what causes freezing, let's think of what we can do about it. On the one hand, if we have enough money, we can just assume customers will accept any crap we sell since they have no alternative. And that does work for Samsung, Qualcomm, Sony and many other vendors. On the other hand, we may want to fix it. We know we can't sleep in a lock, but we need a lock to keep data consistent. Linux has several solutions to the rescue and I'll give an overview of the two of them that are easy and suitable for a typical embedded/desktop system
(i.e., an SMP processor with a small number of cores).

Workqueues

First solution is using a workqueue. A workqueue is an abstraction (on top of kernel threads) which allows to schedule jobs (work) to be executed at some moment later. You can think of a workqueue as of a "future" or "async" concept used in userland.

I will use the example of a LED driver I have written for one smartphone (HTC Kovsky also known as Sony Ericsson Xperia X1) to illustrate the workqueue.

First, we need to include the relevant header. Don't trust me here, stuff changes all the time in linux, so you'd rather use grep to find the actual header.
  1. #include <linux/workqueue.h>

We need to declare a "work" that we want to schedule. A work is essentially a routine which would be called, that accepts the instance of a "struct work_struct" class. We can use the "DECLARE_WORK" macro to define a work.

  1. static DECLARE_WORK(colorled_wq, htckovsky_update_color_leds);

Now, let's look at how to implement the work function.

  1. static void htckovsky_update_button_light(struct work_struct* work) {
  2. char buffer[3] = {MICROP_KEYPAD_BRIGHTNESS_KOVS, 0, 0};
  3. char brightness = kovsky_leds[BUTTONS].brightness;
  4. if (brightness) {
  5. buffer[1] = 0x94;
  6. buffer[2] = brightness >> 2;
  7. }
  8. microp_ng_write(client, buffer, 3);
  9. }

As one may notice, we're using the microp_ng_write function which is actually initiating an I2C transfer. We could also add an msleep() call or even add a mutex and that would still work.

Now, how do we call the code? Simple, in your non-sleeping routine (which may be an interrupt handler or an implementation of a function from the LED class), call the "schedule_work" routine.

  1. static void htckovsky_set_brightness_color(struct led_classdev *led_cdev,
  2. enum led_brightness brightness)
  3. {
  4. schedule_work(&colorled_wq);
  5. }

Now, what if you wanted to pass some data to the work routine without using the global variables? The macro "container_of" comes to rescue! Container_of is essentially an implementation of the OOP-like classes in C based on routines and composition instead of inheritance. It works like the following: assume you have a routine which only accepts the "struct work_struct" pointer, and you want to pass arbitrary data. Modifying linux code and creating a copy of the workqueue implementation each time would be silly and boring (although that's what windows developers would do anyway). Instead, we create a structure to hold our data, and add the pointer to the workqueue as a member to it. The container_of macro calculates the offset of a workqueue in our structure, and substracts it from the workqueue pointer. Woops, we have a pointer to our structure and can unmarshal our data from it. This works like the following:

struct work_struct *our_work = kmalloc(sizeof(struct work_struct), GFP_KERNEL);
/* Init the work structure */
INIT_WORK(our_work, handler_routine);
struct my_work_data {
struct work_struct *cool_work;
} work = {
cool_work = our_work;
};

The full source code of the driver is available at the corresponding linux tree at gitorious. It does not synchronize the LED state, though. One should be careful when writing code without synchronization: even though for a LED which updates thousands of times per second, displaying a mixed state is not an issue (a human eye will not notice glitches), if you go this way, only keep your "virtual", driver state global and concurrently accessible, but make sure that the data written to the hardware registers can not be modified concurrently!
https://gitorious.org/linux-on-qualcomm-s-msm/alex-linux-xperia/source/844e6f8bed194d6947d966233f411e8997484091:drivers/leds/leds-microp-htckovsky.c

Kernel Threads
Another alternative is using the kernel threads. In fact, kernel threads are almost like a userspace process running in kernel mode. It can receive signals and do many other things, but programming kernel threads is more difficult and almost all the time you can get away with using workqueues. Here's some sample code showing how to spawn a thread and do your dirty business inside:

static int my_thread(void *v) {
struct completion exit;
siginfo_t info;

daemonize("mydriver_baddaemond");
allow_signal(SIGKILL);
init_completion(&exit);

while (1) {
if (signal_pending(current)) {
if (dequeue_signal_lock(current, &current->blocked, &info) == SIGKILL) {
goto cleanup;
}
}
else {
//Do your very bad stuff here
}
}

cleanup:
complete_and_exit(&exit, 0);
return 0;
}

//should be somewhere in the driver data
struct task_struct *my_task = NULL;

static void start_thread(void) {
void *arg = NULL; //Can be used to pass data to the handler
my_task = kthread_create(my_thread, arg, "mydriver_baddaemond");
}

static void stop_thread(void) {
send_sig(SIGKILL, my_task, 0);
my_thread_task = NULL;
}

Conclusions
Now you know how to make your drivers more stable and less power-hungry. Almost every time you are thinking of an ad-hoc implementation of a common concept, be sure linux has a clean and working solution already.
Read More
Posted in | No comments

[russian] Уязвимость загрузки APK в Android

Posted on 12:25 by Unknown
Это - перевод статьи-анализа уязвимости. Оригинал - http://blog.sina.com.cn/s/blog_be6dacae0101bksm.html

Не успели интернет-массы отбурлить после недавно обнаруженной группой Bluebox Security уязвимости в ОС Android, позволяющей заменить код установленного приложения без нарушения цифровой подписи, как в системе загрузки Apk была обнаружена еще одна дырка.

Немного теории.

Многие думают, что сам факт написания программы в управляемой среде типа Java автоматически делает их код неуязвимым и безопасным. Но забывают о том, что у JVM есть довольно строгая спецификация на низкоуровневые взаимодействия с памятью и арифметику. Давайте рассмотрим простой пример. Скорее всего, внимательные программисты сразу поймут детали уязвимости, а для тех, кто не поймет - будет пояснение.

public class JavaTest {
public static void main (String [] args) {
short a = (short) 0xFFFF;
int b;
b = a;
System.out.println (b);
b = a & 0xFFFF;
System.out.println (b);
}
}
Просто, да? Если нет, то давайте посмотрим, во что это реально исполняется. Я тут быстренько написал в REPL Clojure - он на JVM, да и результаты будут одинаковы в большинстве не-JVM языков.
Clojure 1.1.0
user=> (def a (short 0xffff))
#'user/a
user=> (def b (int a))
#'user/b
user=> (def c (int (and a 0xffff)))
#'user/c
user=> a
-1
user=> b
-1
user=> c
65535
user=>
В чем дело? В расширении знаковых типов (sign extension). Казалось бы, основа основ, которую вбивают со школьной скамьи, ан нет - эта бяка ответственна за половину известных уязвимостей (за остальную половину - неинициализированная память). 0xffff, когда мы кладем его в 16-битный short, превращается в -1 (дополнительный код). Согласно правилам расширения знака, если мы присваиваем более широкому типу (в данном случае - 32-битному int) отрицательное значение, оно преобразуется так, чтобы представление в новом формате хранило то же значение, что исходная переменная. То есть, мы получаем int b = 0xFFFFFFFF. Старший (знаковый) бит стоит => лополнительный код => -1. Когда мы отсекаем старшие биты (b & 0xffff), старший бит обнуляется, и мы получаем 0xffff. Но у нас же int, 32 бита - это всего лишь 65535 в прямом коде.

Формат ZIP

Давайте рассмотрим формат архивов ZIP, которым на самом деле являются Jar и Apk архивы (примечание переводчика - на платформе Android Apk обычно часть данных типа картинок не сжимается, и выравнивается на 4 байта утилитой ZipAlign, чтобы можно было отображать ресурсы в память через системный вызов mmap, но это не влияет на совместимость с другими реализациями ZIP). Каждая запись в Zip архиве (абстракцией для которой является Java класс ZipEntry) имеет заголовок следующего вида:

        local file header signature     4 bytes  (0x04034b50)
version needed to extract 2 bytes
general purpose bit flag 2 bytes
compression method 2 bytes
last mod file time 2 bytes
last mod file date 2 bytes
crc-32 4 bytes
compressed size 4 bytes
uncompressed size 4 bytes
filename length 2 bytes
extra field length 2 bytes

filename (variable size)
extra field (variable size)
Обратите внимание на то, что два последних поля (имя файла и дополнительное поле, которое хранится после данных файла), имеют переменную длину.

Проверка Apk в системе Android

При загрузке apk файла происходит проверка контрольной суммы. Функция getInputStream, которая позволяет получить поток для чтения данных из ZipEntry, выглядит примерно следующим образом:

RAFStream rafstrm = new RAFStream(raf, entry.mLocalHeaderRelOffset + 28);
DataInputStream is = new DataInputStream(rafstrm);
int localExtraLenOrWhatever = Short.reverseBytes(is.readShort());
is.close();
//skip the name and this "extra" data or whatever it is: 
rafstrm.skip(entry.nameLength + localExtraLenOrWhatever);
rafstrm.mLength = rafstrm.mOffset + entry.compressedSize;
if (entry.compressionMethod == ZipEntry.DEFLATED) {
int bufSize = Math.max(1024, (int) Math.min(entry.getSize(), 65535L));
return new ZipInflaterInputStream(rafstrm, new Inflater(true), bufSize, entry);
}
else {
return rafstrm;
}
Обратите внимание на выделенные фрагменты кода. Как мы видим, максимальная длина "экстра" данных - 65535 байт (для хранения используется двухбайтовое беззнаковое число). Проблема в том, что в Java нет беззнаковых типов данных, и максимальная длина - 32768 (2 ^ 15). А что, если записать в заголовок Zip большее значение? Правильно, старший бит будет интерпретирован как знаковый, и в соответствии с расширением знаковых типов, переменная localExtraLenOrWhatever получит отрицательное значение.

Таким образом, вектор атаки очевиден - записать отрицательное значение в длину поля "extra", тем самым получив возможность перезаписать имя DEX файла. Небольшое ограничение - для проведения такой атаки необходимо, чтобы размер DEX кода в исходном APK был меньше 64кб.

На сегодняшний день уязвимость исправлена, но ошибки, связанные с переполнением целочисленных типов, по-прежнему являются причиной многих уязвимостей. С учётом того, что больше и больше программистов не знают не только о различиях big/little endian, а даже о знаковых типах данных - ситуация будет только ухудшаться :)
Read More
Posted in | No comments

Monday, 13 May 2013

Mobile phones suck!

Posted on 02:05 by Unknown
Here we go again, another rant about mobile operating systems.

I'm fed up with Android. But there's no alternative for me right now. So I have to moan. To make this moaning more constuctive, let's go over what I hate about Android, what I like about other OSs, and what I want to see.

Android sucks

  • Multimedia [audio] is not realtime. Seriously, this is stupid. A dual-core 1.5GHz CPU, and I still hear clicks and pops every now and then when I launch the browser
  • Multimedia scanner notifications are broken. So, I download a piece of music, and what happens next? Right, the media scanner kicks in and kills the music player. Why? Oh, because the cool kids are going mad about OOP  and design patterns nowadays, but implementing a proper live configuration updating is beyond the scope of the abilities of those Senior Developers. Sure, burning everything to the ground and creating the new instance of the class is the only way to go   
  • No, I ain't going to replace my phone with an mp3 player because I'm lazy. I don't want to bother copying music over to it, I just want to download it over Wi-Fi from warez sites (d'oh)
  • UI lags. Even on a quad-core CPU with 2Gb ram
  • Apps crash every now and then. Oh well. I don't even know why. In java you have structured exception handling and stuff like that. Even on Windows Mobile where everything was written in plain C with manual memory management, there were not that many crashes. Does your destkop crash every 30 seconds? No? Ok, I'll blame Java. Android's Dalvik JVM, to be more precise. The application life cycle is implemented in Java, the launcher is implemented in Java, but for some multimedia apps the performance of Java is not enough, and IntBuffer's create a considerable overhead. Besides, parsing C structures without JNA is just painful. So, developers have to integrate their C and C++ code into the Java environment. Every Java-to-C call and C-to-Java involves lots of manual memory manipulations, and I suppose most developers don't do that correctly. Still,  it puzzles me why pure Java apps crash so often
  • No proper fsck and dead file removal. Seriously, if your data file system is corrupted, and the settings database for an app becomes unwritable, guess what happens? Right, the app launches, crashes with the IOException, and the cycle repeats indefinitely
  • Android's using a crippled custom libc and is binary incompatible with GNU/Linux. Okay, libhybris allows us to steal Android's OpenGL drivers, I'm not moaning anymore

Android unsucks

There are positive points, of course
  • The system is open-source, it can be easily adapted for any custom piece of hardware [I'm more interested in the HW engineer's point of view rather than the end user's one]
  • It is based on linux kernel, allowing to reuse many software via chroot or doable porting [like Qt4]
  • That's about all
  • Oh, no. There are a lot of commercial devices available, the user has a lot of choices

What next

I've used many mobile platforms and here's what I've liked and disliked about them

Windows Mobile

  • Damn slow UI. No compositing or 3D support whatsoever
  • Low memory footprint
  • Very stable
  • Lots of apps
  • Native C SDK
  • Ability to load kernel-mode drivers
  • Good driver model, with stable ABI and configuration via registry 


Windows Phone

  • Locked down tightly. No fun for hacking
  • Too expensive to build a custom device
  • But on the positive side, capability-based resource management and app isolation via containers (security!)

iOS

  • It just works
  • But no source code
  • And SDKs are tied to OSX


Maemo/Meego

  • Based on Qt and X11 (Wayland soon), lots of reusable code
  • Using traditional GNU/Linux stack and buildsystem
  • Open-source
  • Native code (except for some parts of UI written in QML).
  • Lower resource requirements than Android


I'm looking forward to Jolla's Sailfish OS and trying to port the Nemo Mobile (the unbranded open-source stack behind Sailfish) to my omap4 devices.

Some ideas

Here's what I think a new kind of mobile OS must be
  • Realtime scheduling [at least, proper priority handling for multimedia and UI, but policy is a complex question]
  • Using capability security model
  • Ability to proxify services and override methods
  • Built with power optimization in mind
  • Microkernel architecture with fixed IPC buffer size [to prevent buffer overflow exploits, to ease debugging]
  • Support para- and hw- virtualization
  • Dynamic resource paths. I want to query irqs like XPath. For example, |irq = Irq_session "/soc/gic/12"| or "/bus/i2c/omap4-1/0x30/irq_expander/10". Maybe a solution is some kind of a platform driver that will just map strings to irq at runtime.
  • Reuse existing linux API and code
So far some of these features are implemented by Fiasco.OC and Genode, but there are some areas in which I want a completely different approach
  • Replace XML and LUA configs with... an XML with schema or, better, a DSL with static checking
  • Avoid runtime memory allocation. I want that as much data structures as possible (at least in drivers) are allocated at compile-time. This will reduce memory trashing, bootup time and simplify the out-of-memory handling
Use a decent language. I mean, something like Scala or Haskell.
  • First one is no uninitialized data. During my C coding experience, 80% of "WTF" problems are uninitialized variables.
  • Next, immutability. Functions without side effects can be verified. Of course, verifying 100% code is very expensive (and well, absolute verification is impossible because we cannot verify the universe), but at least splitting the code to the "dangerous" and "debuggable" is a good start".
  • Strict type checking and lack of implicit type casts. Will save a lot of problems with the C "everything is an int" paradigm
  • Option types. Like haskell's Maybe/Just and OCaml's Some. They eliminate the "NULL" pointers, the source of all crashes and undefined behaviour in C++ and Java, by forcing the programmer to pattern-match the value
As for reusing linux code, I think a starting point could be microkernelizing linux. We could make every module a separate process and replace all global non-static variables and exported symbols with IPC calls for a start. 

Open questions

I am still unsure on some points, and would be happy to see comments on them
  • Whether implementing heterogenous CPU support is a feasible task
  • Can we make a better bytecode than JVM? why does JVM suck? why is it slow? or is it not?
  • What systems of such kind exists already? Phantom OS? Inferno OS?
Read More
Posted in | No comments
Older Posts Home
Subscribe to: Comments (Atom)

Popular Posts

  • thoughts on modern operating systems
    For a long time I've been messing with low-level code on various embedded hardware. While I generally find linux kernel code an outstand...
  • An update on OSX Touchscreen driver
    After playing with the HID interface in OS X, I have found out there exists an API for simulating input events from user space, so I've ...
  • Why I adore Java NOT.
    Ok, here are some of my thoughts about Java as both a language and a development platform. TL;DR: when all you have is a hammer, everything ...
  • Doing it wrong: application preferences
    One thing that's been always bothering me is the lack of a unified way to keep persistent settings. When you're installing a shiny n...
  • KVM on ARM Cortex A15 (OMAP5432 UEVM)
    Hi! In this post I'll summarize the steps I needed to do in order to get KVM working on the OMAP5 ARM board using the virtualization ext...
  • Multitouch touchscreen support in OS X
    Hi there! I happen to have a Dell S2340T multitouch monitor (quite an expensive toy btw) which has a touch controller from 3M. It works fine...
  • Results of 2012 as seen from 2013
    This post is a couple hours late but my excuse is that I was having amazing holidays with my nearest and dearest and without the huge distra...
  • Mobile phones suck!
    Here we go again, another rant about mobile operating systems. I'm fed up with Android. But there's no alternative for me right now....
  • linux gone wrong
    I've been hacking on linux kernel for embedded hardware (mainly PDAs) for quite a while already and I'm sick to death of the bullshi...
  • Visions on Genode OS development
    Introduction This documents summarizes my visions of what and how could and should be improved about the Genode Operating System Framework i...

Blog Archive

  • ▼  2013 (14)
    • ▼  November (4)
      • KVM on ARM Cortex A15 (OMAP5432 UEVM)
      • An update on OSX Touchscreen driver
      • Multitouch touchscreen support in OS X
      • Using a hybrid graphics laptop on linux
    • ►  October (2)
    • ►  May (2)
    • ►  April (2)
    • ►  February (2)
    • ►  January (2)
  • ►  2012 (6)
    • ►  December (1)
    • ►  October (1)
    • ►  September (3)
    • ►  June (1)
Powered by Blogger.

About Me

Unknown
View my complete profile