Blog

KVM After 2.6.20

Linux 2.6.20 was released this week with KVM included, so I tried booting a small guest rather than merely reading patches. The first attempt failed immediately because the processor’s virtualisation support was disabled in the firmware. Progress began with entering setup, which keeps systems programming humble.

KVM uses the processor’s hardware virtualisation extensions and exposes a kernel interface through /dev/kvm. A user-space program supplies the virtual machine’s device model and asks the kernel to run virtual CPUs. This is not a complete machine monitor appearing from one kernel option; kernel and user space divide the work.

The basic checks on this Intel test box were:

grep vmx /proc/cpuinfo
modprobe kvm
modprobe kvm-intel
ls -l /dev/kvm

On an AMD processor I would look for svm and use the corresponding module. Seeing the flag is necessary but not always sufficient, because firmware can still disable the facility.

After loading the modules, I launched a guest image with the available QEMU KVM support and watched the kernel log in another terminal. The guest booted, though virtual disk and network performance are not conclusions I can draw from ten minutes and one ageing drive.

I prefer this architecture because putting CPU execution support behind a kernel interface lets normal Linux scheduling and memory management participate, while device emulation remains in user space where a failure is less likely to take the host with it. The caveat is that the boundary can impose overhead, hardware support varies, and young interfaces may change as use exposes mistakes.

Security deserves restraint too. Hardware isolation is not a promise that a hostile guest can never escape. Device emulation processes parse guest-controlled input, and kernel code now manages another complicated processor mode. I am treating guests as isolated test systems, not as magical bags into which all risk disappears.

The useful result today is narrow: with 2.6.20, suitable hardware, enabled firmware support, kernel modules, and matching user space, a Linux host can run a hardware-assisted guest. Whether KVM becomes the preferred general solution will depend on performance, management tools, and how gracefully it handles less cooperative machines.

For now it boots. In infrastructure experiments, reaching a login prompt is the traditional point at which confidence rises faster than evidence.

CMake Build Trees Are Disposable

My KDE 4 build kept compiling code for a library I had just disabled. I checked the option twice, added a loud message to CMakeLists.txt, and still got the old generated header. The compiler was not being stubborn. I was looking at leftovers.

The first clue was CMakeCache.txt: the build directory had been configured against another source checkout. The second was a generated config.h whose timestamp did not move when I reran CMake. An earlier configure had put a copy in the source tree, and that directory appeared first in the include path.

make clean did not help. It removed compiled output known to the generated makefiles; it did not remove the cache, old makefiles, or a header generated by an obsolete rule. That distinction cost me most of the afternoon.

The useful diagnosis was simple. I configured a brand-new build directory from the same checkout and compared the generated command line and config.h. The fresh tree had the option I expected. At that point there was no reason to repair the old tree one cache entry at a time, so I discarded it and configured again.

I also removed the generated header from the source tree and made its destination unambiguous:

configure_file(
    ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
    ${CMAKE_CURRENT_BINARY_DIR}/config.h
)

Now the binary include directory supplies config.h, and a fresh checkout cannot accidentally inherit one. If the clean build disagrees with the old build, I check the old cache’s source path, generated-file timestamps, and include order before blaming CMake detection.

Build trees are cheap. An hour spent negotiating with stale generated CMake files is not.

Network State Is Not a Boolean

My test applet announced “offline” while NetworkManager was still associating with an access point. A second later it announced “online.” Technically energetic, socially useless.

I had reduced state to a boolean. The mechanism has transitions: unavailable, disconnected, preparing, configuring, connected, and failure are meaningfully different to a user and to an application deciding whether to retry.

The applet now maps backend states into three presentation states:

enum Connectivity {
    Offline,
    Connecting,
    Online
};

It preserves the detailed state in the adapter for diagnostics, but the paint code does not understand every NetworkManager value. Solid provides the abstraction boundary; the widget receives only what it can honestly display.

I prefer reacting to state-change notifications rather than polling every second. Polling wastes work and can still miss a short transition. The caveat is startup: the client must query initial state before relying on later notifications, or it may wait forever for a change that already happened.

“Online” also means only that the connection mechanism considers a network active. It does not guarantee a working name server, reachable destination, or paid hotel login. The applet should report connection state, not certify the Internet.

Three states are less satisfyingly binary. They are also less wrong, an increasingly fashionable property in software.

D-Bus 1.0 and Boring Interfaces

D-Bus 1.0 arrived last week, so I replaced a small experimental IPC call today and discovered that my “simple” interface exposed an internal class name, an internal enum, and optimism about call order.

The wire has four names worth keeping straight: a bus name identifies the service, an object path identifies an object, an interface groups methods and signals, and a member names the operation. Treating all four as one application string works until the service grows a second object.

For a thumbnail service I settled on deliberately plain values:

service:   org.kde.Thumbnailer
path:      /Thumbnailer
interface: org.kde.Thumbnailer
method:    Queue(string url, int width, int height)
signal:    Ready(string url, string file)

The exact names may change; the useful constraint is that callers do not need my C++ headers or object layout. Strings and integers cross the process boundary predictably. Errors should cross as named errors, not magic negative dimensions.

A method call can be synchronous, but that does not make blocking the GUI wise. Thumbnail generation may involve disk access or a broken file. The caller should queue work and react to completion, while also handling service disappearance. Processes are allowed to crash independently; that is among their principal features.

I prefer small, boring bus interfaces with operations phrased in domain terms. They are easier to inspect and less likely to preserve an accidental implementation forever. The caveat is round-trip cost and versioning. Turning every getter into a remote call creates slow, chatty code, and changing a published signature later can break clients I do not control.

Introspection is useful during development, but readable metadata does not replace a written contract. Callers still need to know whether requests are idempotent, which errors are expected, and how long returned object paths remain valid.

For KDE 4 porting, D-Bus 1.0 gives us a stable point to build against, not permission to export every object. I am writing the interface first, testing it from a separate process, and only then attaching the current implementation. If the test needs a private header, the boundary has failed.

Today’s service returns one error instead of hanging when the source file vanishes. This is less exciting than transparent desktop integration, but substantially more useful when transparent desktop integration loses a file.

Plasma Data Before Decoration

I changed the weather prototype’s frame today and accidentally made it fetch the forecast again. The border and the network request had become neighbours in one class, then naturally began borrowing each other’s tools.

The experiment now separates a data source from the visualisation. The source produces named values and announces updates. The applet chooses how to present them. Fake data is enough to exercise the boundary:

QVariantMap WeatherSource::snapshot() const
{
    QVariantMap data;
    data.insert("condition", "cloudy");
    data.insert("temperature", 12);
    data.insert("location", "Porto Alegre");
    return data;
}

The applet receives a complete snapshot instead of reading half-updated fields one by one. This matters if the source later performs work asynchronously: a temperature from the new report paired with yesterday’s condition is internally consistent only in avant-garde meteorology.

The visual item invalidates its content when data changes. Theme or frame changes invalidate geometry and decoration, but do not restart the source. Keeping those paths separate avoids needless work and gives the containment freedom to alter presentation.

For this little applet, pullable snapshots plus one update notification beat a long series of property-specific signals. A new field can appear without adding another connection, and a newly created applet can request current state immediately. Copying a large map for frequent updates would be wasteful, though, and weakly typed keys invite spelling mistakes. This fits small desktop data, not every stream.

Error data travels in the same snapshot rather than through a modal dialog. The applet can then show stale values with a warning, hide them, or offer a retry according to the space and purpose of that visualisation.

There are unresolved questions. Sources need lifetimes, update intervals, error states, and perhaps sharing between several applets. A clock should not require sixty private timer objects merely because sixty visualisations exist. On the other hand, premature sharing can couple applets through one source’s policy.

This remains a Plasma prototype, not evidence of a completed KDE 4 shell. The useful result is that I can replace the rectangle with text, or the text with a graph, without changing how forecast data arrives.

The forecast itself still says cloudy. At least this time it did not download new clouds when I changed the border colour.