Mondo IT

recensioni, articoli e approfondimenti sul mondo IT

[EN] dig a hole in QEMU: how to execute code on the host from VMs (Part 1)

leave a comment »

In the next posts I’ll show you my recent works on QEMU. The purpose of my work is execute code on the Host machine every time that a virtual machine write or read to certain memory address. As you may know, QEMU is not largely documented, so in these posts I try to simplify works for people who are interested in these kind of operation.

The design of the solution that I’ve implemented starts from a QEMU emulated device, called LittleP. In addiction, we need of a Guest drivers that is programmed to write/read data to a fixed memory address. In my case I have used a GNU/Linux virtual machine, but probably it is possible to do the same thing with others operating systems.

So let’s start with the addiction of a new QEMU emulated device. To do this we have to add a new file (in this example littlep.c) in qemu/hw directory. This file should be something like this:

#include “sysbus.h”
#include “qemu-char.h”

//A DEVICE CAN HAVE DATA/CONTROL REGISTERS, COUNTER ETC. ALL THESE DESCRIBES THE DEVICE’S STATE

typedef struct {
SysBusDevice busdev;
MemoryRegion iomem;
int read_pos;
int read_count;
int read_trigger;
CharDriverState *chr;
qemu_irq irq;
const unsigned char *id;
} littlep_state;

static const unsigned char littlep_id[2] =
{ 0x05, 0x06};

static uint64_t littlep_read(void *opaque, target_phys_addr_t offset,
unsigned size)
{

//HERE IS THE CODE EXECUTE WHEN VIRTUAL MACHINE READ SOMETHING IN THE PLACE WHERE THIS DEVICE IS ADDRESSED
printf(“read DONE”);
return 0;
}

static void littlep_write(void *opaque, target_phys_addr_t offset,
uint64_t value, unsigned size)
{

//HERE IS THE CODE EXECUTE WHEN VIRTUAL MACHINE WRITE SOMETHING IN THE PLACE WHERE THIS DEVICE IS ADDRESSED
printf(“WRITE DONE”);
return;
}

//HERE WE DEFINE FUNCTIONS TO EXECUTE ON HOST

static const MemoryRegionOps littlep_ops = {
.read = littlep_read,
.write = littlep_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};

static const VMStateDescription vmstate_littlep = {
.name = “littlep”,
.version_id = 1,
.minimum_version_id = 1,
.minimum_version_id_old = 1,
.fields      = (VMStateField[]) {
VMSTATE_END_OF_LIST()}
};

static int littlep_init(SysBusDevice *dev, const unsigned char *id)
{
littlep_state *s = FROM_SYSBUS(littlep_state, dev);

memory_region_init_io(&s->iomem, &littlep_ops, s, “littlep”, 0x10000);
sysbus_init_mmio(dev, &s->iomem);
sysbus_init_irq(dev, &s->irq);
s->id = id;
s->chr = qemu_char_get_next_serial();
if (s->chr) {
qemu_chr_add_handlers(s->chr, pl011_can_receive, pl011_receive,
pl011_event, s);
}
vmstate_register(&dev->qdev, -1, &vmstate_littlep, s);
return 0;
}

static int littlep_pre_init(SysBusDevice *dev)
{
return littlep_init(dev, littlep_id);
}

static void littlep_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
SysBusDeviceClass *sdc = SYS_BUS_DEVICE_CLASS(klass);
sdc->init = littlep_pre_init;
dc->vmsd = &vmstate_littlep;
}

static TypeInfo littlep_info = {
.name          = “littlep”,
.parent        = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(littlep_state),
.class_init    = littlep_class_init,
};

static void littlep_register_types(void)
{
type_register_static(&littlep_info);
}

type_init(littlep_register_types)

This is a standard QEMU device file (I’ve simplified a few things to easily understand) in which there is a TypeInfo structure that hook the init function (littlep_class_init) into the QOM (QEMU Object Model). This function hooks the SYS_BUS_DEVICE init (littlep_pre_init) required by QDEV.

The littlep_init function is the most important because initialize (line 1-5 of the function) an object of type MemoryRegionOps called littlep_ops. 0x10000 is the hex (64K)size of this memory. This kind of object let us define (see comments in the file) the functions that QEMU have to execute on the host when a read/write operation succeed at the address in which is addressed the device on the VM.

To specify the address where the device have to be mapped we must modify the machine file. We’ll see this details in my next post.

Advertisements

Written by Michele Paolino

13/11/2012 a 12:37

Rispondi

Effettua il login con uno di questi metodi per inviare il tuo commento:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...

%d blogger hanno fatto clic su Mi Piace per questo: