Re: [Qemu-devel] [RFC v2 2/3] Add units-per-idebus property

2014-09-22 Thread Markus Armbruster
Marcel Apfelbaum  writes:

> On Fri, 2014-09-19 at 11:39 +0200, Markus Armbruster wrote:
>> John Snow  writes:
>> 
>> > Signed-off-by: John Snow 
[...]
>> > @@ -1583,6 +1584,7 @@ static void machine_class_init(ObjectClass *oc, void 
>> > *data)
>> >  mc->hot_add_cpu = qm->hot_add_cpu;
>> >  mc->kvm_type = qm->kvm_type;
>> >  mc->block_default_type = qm->block_default_type;
>> > +mc->units_per_idebus = qm->units_per_idebus;
>> >  mc->max_cpus = qm->max_cpus;
>> >  mc->no_serial = qm->no_serial;
>> >  mc->no_parallel = qm->no_parallel;
>> 
>> Not sufficient!  You missed the duplicated code in
>> pc_generic_machine_class_init().  That something was missing was quite
>> obvious in my testing, although what was missing was not.  This is the
>> fix I mentioned above.
>> 
>> Marcel, you touched both copies recently.  Do you know why we need two
>> of them?  And why do we copy from QEMUMachine to MachineClass member by
>> member?  Why can't we just point from MachineClass to QEMUMachine?  Or
>> at least embed the struct so we can copy it wholesale?
> Hi Markus,
>
> I'll try to explain the design:
> 1. MachineClass should not be aware of QEMUMachine. The objective here is to
>eliminate QEMUMachine and it should not be part of MachineClass at any 
> cost.
> 2. The plan is like this:
>- The machine types that are not yet QOMified will be QOMified on the fly
>  by qemu_register_machine (vl.c) that calls machine_class_init and matches
>  QEMUMachine fields with MachineClass fields.
>  - This mechanism will be removed when all machines are QOMified. (never? 
> :) )

Okay %-)

>- Machines that are QOMified will not reach this code at all, but follow
>  the normal QOM path.
> As you can see, by design there is no duplication.
>
> Now let's get to PC machines case:
> - This is a "weird" use case of hybrid QOMifying.
> - All that the author wanted was to have all the PC machines
>   derive from type TYPE_PC_MACHINE, but didn't have the time/resources/will
>   to go over every PC machine and QOMify it. But he did need the common class.
> - His implementation:
>   - He couldn't use the generic qemu_register_machine because the PC machines
> would not have derived from MACHINE_PC_TYPE.
>   - So he used the following logic:
> - from the vl.c point of view, the PC machines are QOMified, so the
>   PC machines registration *does not reach vl.c".
> - from the PC machines point of view, they remained not QOMified.
> - qemu_register_pc_machine mimics vl.c registration *only for pc machines*
>   and has to copy the fields by itself. Plus, it gives the PC machines a 
> common
>   base class, the thing he was interested in in the first place.

Artifact of this hackery: two identical static functions: vl.c's
machine_class_init() and pc.c's pc_generic_machine_class_init().  Trap
for the unwary, and it caught John.

Unless there are plans to get rid of pc_generic_machine_class_init()
fairly soon, I'd recommend to give machine_class_init() external linkage
with a suitable comment, and drop pc_generic_machine_class_init().

> I hope it helped,

Sure did!

I checked the CodeTransitions Wiki page.  It covers this work, and
points to http://wiki.qemu.org/Features/QOM/Machine for more
information.  Good.



Re: [Qemu-devel] [RFC v2 2/3] Add units-per-idebus property

2014-09-21 Thread Marcel Apfelbaum
On Fri, 2014-09-19 at 11:39 +0200, Markus Armbruster wrote:
> John Snow  writes:
> 
> > Signed-off-by: John Snow 
> > ---
> >  blockdev.c| 10 --
> >  device-hotplug.c  |  2 +-
> >  hw/i386/pc_q35.c  |  3 ++-
> >  include/hw/boards.h   |  3 ++-
> >  include/sysemu/blockdev.h |  2 +-
> >  vl.c  | 19 +++
> >  6 files changed, 25 insertions(+), 14 deletions(-)
> >
> > diff --git a/blockdev.c b/blockdev.c
> > index 5e7c93a..6c524b7 100644
> > --- a/blockdev.c
> > +++ b/blockdev.c
> > @@ -45,6 +45,7 @@
> >  #include "qmp-commands.h"
> >  #include "trace.h"
> >  #include "sysemu/arch_init.h"
> > +#include "hw/boards.h"
> >  
> >  static QTAILQ_HEAD(drivelist, DriveInfo) drives = 
> > QTAILQ_HEAD_INITIALIZER(drives);
> >  
> > @@ -643,7 +644,7 @@ QemuOptsList qemu_legacy_drive_opts = {
> >  },
> >  };
> >  
> > -DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType 
> > block_default_type)
> > +DriveInfo *drive_new(QemuOpts *all_opts, MachineClass *mc)
> >  {
> >  const char *value;
> >  DriveInfo *dinfo = NULL;
> > @@ -651,6 +652,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, 
> > BlockInterfaceType block_default_type)
> >  QemuOpts *legacy_opts;
> >  DriveMediaType media = MEDIA_DISK;
> >  BlockInterfaceType type;
> > +BlockInterfaceType block_default_type = mc->block_default_type;
> >  int cyls, heads, secs, translation;
> >  int max_devs, bus_id, unit_id, index;
> >  const char *devaddr;
> > @@ -828,7 +830,11 @@ DriveInfo *drive_new(QemuOpts *all_opts, 
> > BlockInterfaceType block_default_type)
> >  unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
> >  index   = qemu_opt_get_number(legacy_opts, "index", -1);
> >  
> > -max_devs = if_max_devs[type];
> > +if (type == IF_IDE && mc->units_per_idebus) {
> > +max_devs = mc->units_per_idebus;
> > +} else {
> > +max_devs = if_max_devs[type];
> > +}
> 
> This overrides if_max_devs[IF_IDE] in one out of three places.
> 
> if_max_devs[type] governs the mapping between index and (bus, unit).
> 
> If it's zero, then (bus, unit) = (0, index).
> 
> Else, (bus, unit) = (index / max_devs, index % max_devs).
> 
> Overriding it just here affects these things:
> 
> * Picking a default when the user specifies neither index nor unit
> 
> * Range checking unit
> 
> * Default ID, but let's ignore that for now
> 
> It does *not* affect drive_index_to_bus_id(), drive_index_to_unit_id(),
> i.e. the actual mapping between index and (bus, unit)!  index=1 is still
> mapped to (bus, unit) = (0, 1).  No good.
> 
> Testing (needs an incremental fix, see below) confirms:
> 
> qemu: -drive if=ide,media=cdrom,index=1: unit 1 too big (max is 0)
> 
> You have to override if_max_devs[] consistently.
> 
> You provide for overriding if_max_devs[IF_IDE] only.  It'll do for now.
> 
> >  
> >  if (index != -1) {
> >  if (bus_id != 0 || unit_id != -1) {
> > diff --git a/device-hotplug.c b/device-hotplug.c
> > index e6a1ffb..857ac53 100644
> > --- a/device-hotplug.c
> > +++ b/device-hotplug.c
> > @@ -40,7 +40,7 @@ DriveInfo *add_init_drive(const char *optstr)
> >  return NULL;
> >  
> >  mc = MACHINE_GET_CLASS(current_machine);
> > -dinfo = drive_new(opts, mc->block_default_type);
> > +dinfo = drive_new(opts, mc);
> >  if (!dinfo) {
> >  qemu_opts_del(opts);
> >  return NULL;
> > diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> > index d4a907c..fd26fe1 100644
> > --- a/hw/i386/pc_q35.c
> > +++ b/hw/i386/pc_q35.c
> > @@ -348,7 +348,8 @@ static void pc_q35_init_1_4(MachineState *machine)
> >  
> >  #define PC_Q35_2_2_MACHINE_OPTIONS  \
> >  PC_Q35_MACHINE_OPTIONS, \
> > -.default_machine_opts = "firmware=bios-256k.bin"
> > +.default_machine_opts = "firmware=bios-256k.bin",   \
> > +.units_per_idebus = 1
> >  
> 
> I figrue this keeps -drive if=ide for older Q35 machines compatibly
> broken.  If that's what we want to do...
> 
> >  static QEMUMachine pc_q35_machine_v2_2 = {
> >  PC_Q35_2_2_MACHINE_OPTIONS,
> > diff --git a/include/hw/boards.h b/include/hw/boards.h
> > index dfb6718..73e656f 100644
> > --- a/include/hw/boards.h
> > +++ b/include/hw/boards.h
> > @@ -37,6 +37,7 @@ struct QEMUMachine {
> >  no_cdrom:1,
> >  no_sdcard:1;
> >  int is_default;
> > +unsigned short units_per_idebus;
> >  const char *default_machine_opts;
> >  const char *default_boot_order;
> >  GlobalProperty *compat_props;
> 
> if_max_devs[] and the max_devs variables are all int.  I'd rather not
> mix signed and unsigned without need
> 
> > @@ -95,11 +96,11 @@ struct MachineClass {
> >  no_cdrom:1,
> >  no_sdcard:1;
> >  int is_default;
> > +unsigned short units_per_idebus;
> >  const char *default_machine_opts;
> >  const char *default_boot_order;
> >  GlobalPropert

Re: [Qemu-devel] [RFC v2 2/3] Add units-per-idebus property

2014-09-19 Thread Markus Armbruster
John Snow  writes:

> Signed-off-by: John Snow 
> ---
>  blockdev.c| 10 --
>  device-hotplug.c  |  2 +-
>  hw/i386/pc_q35.c  |  3 ++-
>  include/hw/boards.h   |  3 ++-
>  include/sysemu/blockdev.h |  2 +-
>  vl.c  | 19 +++
>  6 files changed, 25 insertions(+), 14 deletions(-)
>
> diff --git a/blockdev.c b/blockdev.c
> index 5e7c93a..6c524b7 100644
> --- a/blockdev.c
> +++ b/blockdev.c
> @@ -45,6 +45,7 @@
>  #include "qmp-commands.h"
>  #include "trace.h"
>  #include "sysemu/arch_init.h"
> +#include "hw/boards.h"
>  
>  static QTAILQ_HEAD(drivelist, DriveInfo) drives = 
> QTAILQ_HEAD_INITIALIZER(drives);
>  
> @@ -643,7 +644,7 @@ QemuOptsList qemu_legacy_drive_opts = {
>  },
>  };
>  
> -DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType 
> block_default_type)
> +DriveInfo *drive_new(QemuOpts *all_opts, MachineClass *mc)
>  {
>  const char *value;
>  DriveInfo *dinfo = NULL;
> @@ -651,6 +652,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, 
> BlockInterfaceType block_default_type)
>  QemuOpts *legacy_opts;
>  DriveMediaType media = MEDIA_DISK;
>  BlockInterfaceType type;
> +BlockInterfaceType block_default_type = mc->block_default_type;
>  int cyls, heads, secs, translation;
>  int max_devs, bus_id, unit_id, index;
>  const char *devaddr;
> @@ -828,7 +830,11 @@ DriveInfo *drive_new(QemuOpts *all_opts, 
> BlockInterfaceType block_default_type)
>  unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
>  index   = qemu_opt_get_number(legacy_opts, "index", -1);
>  
> -max_devs = if_max_devs[type];
> +if (type == IF_IDE && mc->units_per_idebus) {
> +max_devs = mc->units_per_idebus;
> +} else {
> +max_devs = if_max_devs[type];
> +}

This overrides if_max_devs[IF_IDE] in one out of three places.

if_max_devs[type] governs the mapping between index and (bus, unit).

If it's zero, then (bus, unit) = (0, index).

Else, (bus, unit) = (index / max_devs, index % max_devs).

Overriding it just here affects these things:

* Picking a default when the user specifies neither index nor unit

* Range checking unit

* Default ID, but let's ignore that for now

It does *not* affect drive_index_to_bus_id(), drive_index_to_unit_id(),
i.e. the actual mapping between index and (bus, unit)!  index=1 is still
mapped to (bus, unit) = (0, 1).  No good.

Testing (needs an incremental fix, see below) confirms:

qemu: -drive if=ide,media=cdrom,index=1: unit 1 too big (max is 0)

You have to override if_max_devs[] consistently.

You provide for overriding if_max_devs[IF_IDE] only.  It'll do for now.

>  
>  if (index != -1) {
>  if (bus_id != 0 || unit_id != -1) {
> diff --git a/device-hotplug.c b/device-hotplug.c
> index e6a1ffb..857ac53 100644
> --- a/device-hotplug.c
> +++ b/device-hotplug.c
> @@ -40,7 +40,7 @@ DriveInfo *add_init_drive(const char *optstr)
>  return NULL;
>  
>  mc = MACHINE_GET_CLASS(current_machine);
> -dinfo = drive_new(opts, mc->block_default_type);
> +dinfo = drive_new(opts, mc);
>  if (!dinfo) {
>  qemu_opts_del(opts);
>  return NULL;
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index d4a907c..fd26fe1 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -348,7 +348,8 @@ static void pc_q35_init_1_4(MachineState *machine)
>  
>  #define PC_Q35_2_2_MACHINE_OPTIONS  \
>  PC_Q35_MACHINE_OPTIONS, \
> -.default_machine_opts = "firmware=bios-256k.bin"
> +.default_machine_opts = "firmware=bios-256k.bin",   \
> +.units_per_idebus = 1
>  

I figrue this keeps -drive if=ide for older Q35 machines compatibly
broken.  If that's what we want to do...

>  static QEMUMachine pc_q35_machine_v2_2 = {
>  PC_Q35_2_2_MACHINE_OPTIONS,
> diff --git a/include/hw/boards.h b/include/hw/boards.h
> index dfb6718..73e656f 100644
> --- a/include/hw/boards.h
> +++ b/include/hw/boards.h
> @@ -37,6 +37,7 @@ struct QEMUMachine {
>  no_cdrom:1,
>  no_sdcard:1;
>  int is_default;
> +unsigned short units_per_idebus;
>  const char *default_machine_opts;
>  const char *default_boot_order;
>  GlobalProperty *compat_props;

if_max_devs[] and the max_devs variables are all int.  I'd rather not
mix signed and unsigned without need

> @@ -95,11 +96,11 @@ struct MachineClass {
>  no_cdrom:1,
>  no_sdcard:1;
>  int is_default;
> +unsigned short units_per_idebus;
>  const char *default_machine_opts;
>  const char *default_boot_order;
>  GlobalProperty *compat_props;
>  const char *hw_version;
> -
>  HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
> DeviceState *dev);
>  };

Let's keep the blank line separating the instance variables from the
method.

> diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
> in

[Qemu-devel] [RFC v2 2/3] Add units-per-idebus property

2014-09-18 Thread John Snow
Signed-off-by: John Snow 
---
 blockdev.c| 10 --
 device-hotplug.c  |  2 +-
 hw/i386/pc_q35.c  |  3 ++-
 include/hw/boards.h   |  3 ++-
 include/sysemu/blockdev.h |  2 +-
 vl.c  | 19 +++
 6 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 5e7c93a..6c524b7 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -45,6 +45,7 @@
 #include "qmp-commands.h"
 #include "trace.h"
 #include "sysemu/arch_init.h"
+#include "hw/boards.h"
 
 static QTAILQ_HEAD(drivelist, DriveInfo) drives = 
QTAILQ_HEAD_INITIALIZER(drives);
 
@@ -643,7 +644,7 @@ QemuOptsList qemu_legacy_drive_opts = {
 },
 };
 
-DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType block_default_type)
+DriveInfo *drive_new(QemuOpts *all_opts, MachineClass *mc)
 {
 const char *value;
 DriveInfo *dinfo = NULL;
@@ -651,6 +652,7 @@ DriveInfo *drive_new(QemuOpts *all_opts, BlockInterfaceType 
block_default_type)
 QemuOpts *legacy_opts;
 DriveMediaType media = MEDIA_DISK;
 BlockInterfaceType type;
+BlockInterfaceType block_default_type = mc->block_default_type;
 int cyls, heads, secs, translation;
 int max_devs, bus_id, unit_id, index;
 const char *devaddr;
@@ -828,7 +830,11 @@ DriveInfo *drive_new(QemuOpts *all_opts, 
BlockInterfaceType block_default_type)
 unit_id = qemu_opt_get_number(legacy_opts, "unit", -1);
 index   = qemu_opt_get_number(legacy_opts, "index", -1);
 
-max_devs = if_max_devs[type];
+if (type == IF_IDE && mc->units_per_idebus) {
+max_devs = mc->units_per_idebus;
+} else {
+max_devs = if_max_devs[type];
+}
 
 if (index != -1) {
 if (bus_id != 0 || unit_id != -1) {
diff --git a/device-hotplug.c b/device-hotplug.c
index e6a1ffb..857ac53 100644
--- a/device-hotplug.c
+++ b/device-hotplug.c
@@ -40,7 +40,7 @@ DriveInfo *add_init_drive(const char *optstr)
 return NULL;
 
 mc = MACHINE_GET_CLASS(current_machine);
-dinfo = drive_new(opts, mc->block_default_type);
+dinfo = drive_new(opts, mc);
 if (!dinfo) {
 qemu_opts_del(opts);
 return NULL;
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index d4a907c..fd26fe1 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -348,7 +348,8 @@ static void pc_q35_init_1_4(MachineState *machine)
 
 #define PC_Q35_2_2_MACHINE_OPTIONS  \
 PC_Q35_MACHINE_OPTIONS, \
-.default_machine_opts = "firmware=bios-256k.bin"
+.default_machine_opts = "firmware=bios-256k.bin",   \
+.units_per_idebus = 1
 
 static QEMUMachine pc_q35_machine_v2_2 = {
 PC_Q35_2_2_MACHINE_OPTIONS,
diff --git a/include/hw/boards.h b/include/hw/boards.h
index dfb6718..73e656f 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -37,6 +37,7 @@ struct QEMUMachine {
 no_cdrom:1,
 no_sdcard:1;
 int is_default;
+unsigned short units_per_idebus;
 const char *default_machine_opts;
 const char *default_boot_order;
 GlobalProperty *compat_props;
@@ -95,11 +96,11 @@ struct MachineClass {
 no_cdrom:1,
 no_sdcard:1;
 int is_default;
+unsigned short units_per_idebus;
 const char *default_machine_opts;
 const char *default_boot_order;
 GlobalProperty *compat_props;
 const char *hw_version;
-
 HotplugHandler *(*get_hotplug_handler)(MachineState *machine,
DeviceState *dev);
 };
diff --git a/include/sysemu/blockdev.h b/include/sysemu/blockdev.h
index 25d52d2..f7de0a0 100644
--- a/include/sysemu/blockdev.h
+++ b/include/sysemu/blockdev.h
@@ -55,7 +55,7 @@ DriveInfo *drive_get_by_blockdev(BlockDriverState *bs);
 QemuOpts *drive_def(const char *optstr);
 QemuOpts *drive_add(BlockInterfaceType type, int index, const char *file,
 const char *optstr);
-DriveInfo *drive_new(QemuOpts *arg, BlockInterfaceType block_default_type);
+DriveInfo *drive_new(QemuOpts *arg, MachineClass *mc);
 void drive_del(DriveInfo *dinfo);
 
 /* device-hotplug */
diff --git a/vl.c b/vl.c
index e095bcd..8359469 100644
--- a/vl.c
+++ b/vl.c
@@ -1151,9 +1151,9 @@ static int cleanup_add_fd(QemuOpts *opts, void *opaque)
 
 static int drive_init_func(QemuOpts *opts, void *opaque)
 {
-BlockInterfaceType *block_default_type = opaque;
+MachineClass *mc = opaque;
 
-return drive_new(opts, *block_default_type) == NULL;
+return drive_new(opts, mc) == NULL;
 }
 
 static int drive_enable_snapshot(QemuOpts *opts, void *opaque)
@@ -1165,7 +1165,7 @@ static int drive_enable_snapshot(QemuOpts *opts, void 
*opaque)
 }
 
 static void default_drive(int enable, int snapshot, BlockInterfaceType type,
-  int index, const char *optstr)
+  int index, const char *optstr, MachineClass *mc)
 {
 QemuOpts *opts;
 
@@ -1177,7 +1177,8 @@ static void default_drive(int enable, int snapshot, 
BlockIn