Skip to contentSkip to conversation

system emulator modularization

RFC PATCH In review Magnus Damm 3 participants 4 messages Jan 16, 2005 Kbuild

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 system emulator modularization

Heya,

I have recently been scratching one of my favourite itches:
modularization. QEMU has some well defined interfaces, but one of the bottlenecks when it comes to add and test new code is IMHO the command line options. The current way to do it is pretty straight forward - just add your new command line options to vl.c and off you go. However, this leads to some kind of option space pollution. With other words, I do not think the current solution scales wery well and it would be a shame to make it harder to add code to QEMU than it has to be.

So, what I would like to add to QEMU is some kind of module support. My idea consists of two basic building blocks: modules and labels.

A module is some kind of well defined function of the emulator, maybe code that emulates one chip, or perhaps some core emulator code. You could call it a class.

A label is a named instance of a module. Each label is associated with a private data area that contains all state about the label. Pretty much an object.

So, to be able to use any module you have to create an instance of it by creating a label. When a label is created it is possible to pass parameters to the instance. Each module has a set of operations, I suggest the following:

check():
Called when the label is created. Used to validate module parameters. Should not allocate any data, private data belonging to label is already allocated by global module code. Must make sure that the module parameters are saved in a standardized endian-independent format - I suggest network byte order.

start():
Called when the label is enabled. The private data is still in network byte order, now it is time for the module to convert the data to native byte order, allocate data and register itself or whatever. This start operation is used both for restore from a saved state and for a clean start.

stop():
Called when the label is disabled, ie when the emulator is shut down or when state is saved. The module should unregister itself and convert the private data into network byte order. After stop() it should be possible to use the same private data and perform start().

Quoted 1 line

From the command line it should be possible to create/change labels

and to list availible modules. The attached patch lists modules after the help text, and the temporary option -x is currently used to create a label. From the help text:

-x label=module[:args] create one instance of module called label

The grand plan (not finished yet if ever) is that labels should depend on each other and something like this could be used to start the emulator with 2 vga cards and one nic on the pci bus:

-x vga0=cirrus-vga
-x vga1=std-vga
-x nic0=ne2000:mac=0x0080deadbe
-x pcibus0=pcibus:vga0,vga1,nic0
-x cpu0=x86:nommx
-x mypc=pc:cpu0,pcibus0

This idea together with predefined profiles (collection of predefined labels) and that it should be possible to override predefined labels with user-defined ones would make QEMU pretty flexible IMHO.

The attached patch does not do anything useful, it just contains some module code and a module skeleton. The code is pretty much a big hack, but I included it just to let you see. The module code is "inspired" from the Linux kernel, but improved to support instances. Module information is stored in a special section, just link in the code between module.o and module_last.o and everything should work by itself.

/ magnus

Makefile.target +1 -0
diff -urN qemu/Makefile.target qemu-modules/Makefile.target
@@ -290,6 +290,7 @@
 # must use static linking to avoid leaving stuff in virtual address space
 VL_OBJS=vl.o osdep.o block.o readline.o monitor.o pci.o console.o 
 VL_OBJS+=block-cow.o block-qcow.o aes.o block-vmdk.o block-cloop.o block-dmg.o
+VL_OBJS+=module.o module_skeleton.o module_last.o
 
 SOUND_HW = sb16.o
 AUDIODRV = audio.o noaudio.o wavaudio.o
module.c +178 -0

178 lines not on this page · raw message

module.h +78 -0

78 lines not on this page · raw message

module_last.c +7 -0
diff -urN qemu/module_last.c qemu-modules/module_last.c
@@ -0,0 +1,7 @@
+#include <stdio.h>
+
+#include "module.h"
+
+/* the object file generated from this file must be placed at the end */
+
+static void *__param_last __param_section = NULL;
module_skeleton.c +33 -0
diff -urN qemu/module_skeleton.c qemu-modules/module_skeleton.c
@@ -0,0 +1,33 @@
+#include "module.h"
+
+struct private {
+  unsigned int foo;
+  char buf[100];
+  int my_bool;
+};
+
+static int check(struct private *p)
+{
+  module_printf(p, " check! my_bool = %d, args are \"%s\"\n", 
+				p->my_bool, module_args(p));
+
+  return 0;
+}
+
+static int start(struct private *p)
+{
+  return 0;
+}
+
+static void stop(struct private *p)
+{
+}
+
+static struct module_ops ops = MODULE_OPS(check, start, stop, struct private);
+
+static struct module_param params[] = {
+  MODULE_PARAM(my_bool, "bool", "a bool parameter called my_bool", 
+	       xx, struct private),
+};
+
+MODULE(skel, "", "a simple module skeleton", ops, params, struct private);
vl.c +16 -0
diff -urN qemu/vl.c qemu-modules/vl.c
@@ -76,6 +76,8 @@
 
 #include "exec-all.h"
 
+#include "module.h"
+
 //#define DO_TB_FLUSH
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
@@ -2769,6 +2771,7 @@
            "                (default is CL-GD5446 PCI VGA)\n"
 #endif
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
+           "-x label=module[:args]  create one instance of module called label\n"
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -2792,6 +2795,11 @@
            "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
            "PC emulation.\n");
 #endif
+
+	printf("\nAvailable modules:\n");
+	module_list_all();
+
+
     exit(1);
 }
 
@@ -2848,6 +2856,7 @@
     QEMU_OPTION_loadvm,
     QEMU_OPTION_full_screen,
     QEMU_OPTION_pidfile,
+	QEMU_OPTION_set_module,
 };
 
 typedef struct QEMUOption {
@@ -2915,6 +2924,7 @@
     /* temporary options */
     { "pci", 0, QEMU_OPTION_pci },
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+    { "x", HAS_ARG, QEMU_OPTION_set_module },
     { NULL },
 };
 
@@ -3328,6 +3338,12 @@
                     graphic_depth = depth;
                 }
                 break;
+            case QEMU_OPTION_set_module:
+			  if (module_label_create(optarg) < 0) {
+                    fprintf(stderr, "qemu: unable to create label \"%s\"\n", optarg);
+                    exit(1);
+			  }
+                break;
             case QEMU_OPTION_monitor:
                 pstrcpy(monitor_device, sizeof(monitor_device), optarg);
                 break;
#1 lore raw

I would welcome this concept for configuring QEmu. Also, if this directives could be stored in a INI file, it would be very cool.

Andreas

Quoted 9 lines

-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Magnus Damm
Sent: Sunday, January 16, 2005 12:52 AM
To: [email protected]
Subject: [Qemu-devel] [PATCH][RFC] system emulator modularization

Quoted 4 lines

Heya,

I have recently been scratching one of my favourite itches:
modularization. QEMU has some well defined interfaces, but one of

the

Quoted 1 line

bottlenecks when it comes to add and test new code is IMHO the

command

Quoted 3 lines

line options. The current way to do it is pretty straight forward - just add your new command line options to vl.c and off you go. However, this leads to some kind of option space pollution. With

other

Quoted 2 lines

words, I do not think the current solution scales wery well and it would be a shame to make it harder to add code to QEMU than it has

to

Quoted 6 lines

be.

So, what I would like to add to QEMU is some kind of module support. My idea consists of two basic building blocks: modules and labels.

A module is some kind of well defined function of the emulator,

maybe

Quoted 4 lines

code that emulates one chip, or perhaps some core emulator code. You could call it a class.

A label is a named instance of a module. Each label is associated

with

Quoted 4 lines

a private data area that contains all state about the label. Pretty much an object.

So, to be able to use any module you have to create an instance of

it

Quoted 6 lines

by creating a label. When a label is created it is possible to pass parameters to the instance. Each module has a set of operations, I suggest the following:

check():
Called when the label is created. Used to validate module

parameters.

Quoted 7 lines

Should not allocate any data, private data belonging to label is already allocated by global module code. Must make sure that the module parameters are saved in a standardized endian-independent format - I suggest network byte order.

start():
Called when the label is enabled. The private data is still in

network

Quoted 2 lines

byte order, now it is time for the module to convert the data to native byte order, allocate data and register itself or whatever.

This

Quoted 1 line

start operation is used both for restore from a saved state and for

a

Quoted 10 lines

clean start.

stop():
Called when the label is disabled, ie when the emulator is shut down or when state is saved. The module should unregister itself and convert the private data into network byte order. After stop() it should be possible to use the same private data and perform start().

Quoted 1 line

From the command line it should be possible to create/change labels

and to list availible modules. The attached patch lists modules

after

Quoted 1 line

the help text, and the temporary option -x is currently used to

create

Quoted 5 lines

a label. From the help text:

-x label=module[:args] create one instance of module called label

The grand plan (not finished yet if ever) is that labels should

depend

Quoted 11 lines

on each other and something like this could be used to start the emulator with 2 vga cards and one nic on the pci bus:

(quoted diff) +0 -6
-x vga0=cirrus-vga
-x vga1=std-vga
-x nic0=ne2000:mac=0x0080deadbe
-x pcibus0=pcibus:vga0,vga1,nic0
-x cpu0=x86:nommx
-x mypc=pc:cpu0,pcibus0

This idea together with predefined profiles (collection of

predefined

Quoted 4 lines

labels) and that it should be possible to override predefined labels with user-defined ones would make QEMU pretty flexible IMHO.

The attached patch does not do anything useful, it just contains

some

Quoted 1 line

module code and a module skeleton. The code is pretty much a big

hack,

Quoted 8 lines

but I included it just to let you see. The module code is "inspired" from the Linux kernel, but improved to support instances. Module information is stored in a special section, just link in the code between module.o and module_last.o and everything should work by itself.

/ magnus

#2 lore raw

Hey, why not do as simple as you can ?

myscript
#!/bin/bash
qemu -options -hda /somewhere/myimage

Quoted 5 lines · --- Andreas Bollhalder

I would welcome this concept for configuring QEmu. Also, if this directives could be stored in a INI file, it would be very cool.

Andreas

=====
Sylvain Petreolle (spetreolle_at_users.sourceforge.net) humans are like computers,
yesterday the BIOS was all
- today its just a word

#3 lore raw
Quoted 5 lines · Sylvain Petreolle

Hey, why not do as simple as you can ?

myscript
#!/bin/bash
qemu -options -hda /somewhere/myimage

I agree that "keep it simple" is the best way of doing things, but I think a host-os independent way to load/save configuration would be very useful. It allows people to swap configurations with each other regardless of host operating system which is one step in the right direction IMHO...

/ magnus