diff mbox

[v1,3/4] hw: Deduce the default machine from the specified CPU model

Message ID 1346099868-7774-4-git-send-email-meadori@codesourcery.com
State New
Headers show

Commit Message

Meador Inge Aug. 27, 2012, 8:37 p.m. UTC
This changes the driver behavior to choose the default machine
model based on the CPU being used.  Defaulting the machine this
way makes it easier to use QEMU as an ISS by just specifying
the -cpu option since a default machine that is suitable for
emulating the full ISA can be chosen.

For example, currently on ARM the ARM Integrator/CP board is
chosen as the default machine when specifying just a CPU.
However, this doesn't work well when passing -cpu cortex-m3
since on ARMv7-M processors the NVIC is a part of the architecture
and is needed to support instructions like SVC.

Signed-off-by: Meador Inge <meadori@codesourcery.com>
---
 hw/alpha_dp264.c              |    2 +-
 hw/axis_dev88.c               |    2 +-
 hw/boards.h                   |    4 ++--
 hw/integratorcp.c             |    2 +-
 hw/lm32_boards.c              |    3 +--
 hw/mcf5208.c                  |    2 +-
 hw/milkymist.c                |    1 -
 hw/mips_malta.c               |    2 +-
 hw/openrisc_sim.c             |    2 +-
 hw/pc_piix.c                  |    2 +-
 hw/pc_sysfw.c                 |    2 +-
 hw/petalogix_ml605_mmu.c      |    1 -
 hw/petalogix_s3adsp1800_mmu.c |    2 +-
 hw/ppc_newworld.c             |    2 +-
 hw/ppc_oldworld.c             |    2 +-
 hw/puv3.c                     |    2 +-
 hw/s390-virtio.c              |    2 +-
 hw/shix.c                     |    2 +-
 hw/sun4m.c                    |    2 +-
 hw/sun4u.c                    |    2 +-
 hw/xtensa_sim.c               |    2 +-
 qapi-schema.json              |    4 ++--
 vl.c                          |   38 +++++++++++++++++++++++++-------------
 23 files changed, 47 insertions(+), 38 deletions(-)

Comments

Peter Maydell Aug. 27, 2012, 8:47 p.m. UTC | #1
On 27 August 2012 21:37, Meador Inge <meadori@codesourcery.com> wrote:
> This changes the driver behavior to choose the default machine
> model based on the CPU being used.  Defaulting the machine this
> way makes it easier to use QEMU as an ISS by just specifying
> the -cpu option since a default machine that is suitable for
> emulating the full ISA can be chosen.
>
> For example, currently on ARM the ARM Integrator/CP board is
> chosen as the default machine when specifying just a CPU.
> However, this doesn't work well when passing -cpu cortex-m3
> since on ARMv7-M processors the NVIC is a part of the architecture
> and is needed to support instructions like SVC.

Personally I'd rather we didn't support a "default machine" at
all, at least for ARM. It does matter what board you run on,
so you need to specify.

Just to pick an obvious example, you can't stick a core
which supports VFPv4 (the A15 is the only one we have) into
the integratorcp, so you would still have to specify both
a CPU and a machine name there.

We could reasonably add patches which made boards error
out if you tried to use them with unsupported CPUs, I guess.

-- PMM
Paul Brook Aug. 28, 2012, 12:58 p.m. UTC | #2
> > This changes the driver behavior to choose the default machine
> > model based on the CPU being used.  Defaulting the machine this
> > way makes it easier to use QEMU as an ISS by just specifying
> > the -cpu option since a default machine that is suitable for
> > emulating the full ISA can be chosen.
> > 
> > For example, currently on ARM the ARM Integrator/CP board is
> > chosen as the default machine when specifying just a CPU.
> > However, this doesn't work well when passing -cpu cortex-m3
> > since on ARMv7-M processors the NVIC is a part of the architecture
> > and is needed to support instructions like SVC.
> 
> Personally I'd rather we didn't support a "default machine" at
> all, at least for ARM. It does matter what board you run on,
> so you need to specify.

A possible compromise is to only accept -cpu if -M is also specified.
 
> Just to pick an obvious example, you can't stick a core
> which supports VFPv4 (the A15 is the only one we have) into
> the integratorcp

Yes you can.

Your OS probably doesn't support it, and you might have trouble persuading the 
OS vendor to support something that doesn't physically exist, but those are a 
competely separate problems.

> We could reasonably add patches which made boards error
> out if you tried to use them with unsupported CPUs, I guess.

That suffers from a large fuzzy region containing interesting combinations 
that could/do work, but will probably never be created in silicon.

If done properly this the QOM conversion should give you this for free.

Paul
Peter Maydell Aug. 28, 2012, 1:10 p.m. UTC | #3
On 28 August 2012 13:58, Paul Brook <paul@codesourcery.com> wrote:
> Peter Maydell wrote:
>> Just to pick an obvious example, you can't stick a core
>> which supports VFPv4 (the A15 is the only one we have) into
>> the integratorcp
>
> Yes you can.

No you can't. integratorcp.c doesn't create the parts of the CPU
which live in QEMU's 'a15mpcore_priv' device, so the resulting
mess is liable to just fall over. If anybody reports bugs in
QEMU in such a configuration I will tell them to go away and
use a supported configuration instead.

At some point when we complete the QOM conversion the board
will be instantiating a single object which has both the A15
cores and the builtin peripherals. However when that happens
I would expect the QOM-objects for 926 and A15 not to be
interchangeable, for the same reason that a physical h/w
926 and A15 aren't interchangeable -- they have different
sets of connections to the outside world, and you can't
just stuff one chip into a socket intended for the other.

-- PMM
Paul Brook Aug. 28, 2012, 1:32 p.m. UTC | #4
> >> Just to pick an obvious example, you can't stick a core
> >> which supports VFPv4 (the A15 is the only one we have) into
> >> the integratorcp
> > 
> > Yes you can.
> 
> No you can't. integratorcp.c doesn't create the parts of the CPU
> which live in QEMU's 'a15mpcore_priv' device, so the resulting
> mess is liable to just fall over. If anybody reports bugs in
> QEMU in such a configuration I will tell them to go away and
> use a supported configuration instead.

The A15 core itself will work just fine.  The core is completely independent 
of the interrupt controller.  Unlike the M profile cores where the NVIC is 
inherently part of the CPU exception handling mechanism.  

Paul
Peter Maydell Aug. 28, 2012, 1:54 p.m. UTC | #5
On 28 August 2012 14:32, Paul Brook <paul@codesourcery.com> wrote:
>> No you can't. integratorcp.c doesn't create the parts of the CPU
>> which live in QEMU's 'a15mpcore_priv' device, so the resulting
>> mess is liable to just fall over. If anybody reports bugs in
>> QEMU in such a configuration I will tell them to go away and
>> use a supported configuration instead.
>
> The A15 core itself will work just fine.  The core is completely independent
> of the interrupt controller.

This is a view of the world which is becoming steadily less
true. It is not possible to configure a hardware A9MP without
the GIC and internal peripherals, for example. And the A15's
timer peripherals are accessed as cp15 registers, not memory
mapped I/O, making them even more obviously a coherent part
of the CPU.

-- PMM
diff mbox

Patch

diff --git a/hw/alpha_dp264.c b/hw/alpha_dp264.c
index 9eb939f..d6717aa 100644
--- a/hw/alpha_dp264.c
+++ b/hw/alpha_dp264.c
@@ -169,7 +169,7 @@  static QEMUMachine clipper_machine = {
     .desc = "Alpha DP264/CLIPPER",
     .init = clipper_init,
     .max_cpus = 4,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void clipper_machine_init(void)
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index eab6327..41078e6 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -353,7 +353,7 @@  static QEMUMachine axisdev88_machine = {
     .name = "axis-dev88",
     .desc = "AXIS devboard 88",
     .init = axisdev88_init,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void axisdev88_machine_init(void)
diff --git a/hw/boards.h b/hw/boards.h
index a2e0a54..6f52561 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -28,7 +28,7 @@  typedef struct QEMUMachine {
         no_floppy:1,
         no_cdrom:1,
         no_sdcard:1;
-    int is_default;
+    const char* default_for_cpu_model;
     const char *default_machine_opts;
     GlobalProperty *compat_props;
     struct QEMUMachine *next;
@@ -36,7 +36,7 @@  typedef struct QEMUMachine {
 } QEMUMachine;
 
 int qemu_register_machine(QEMUMachine *m);
-QEMUMachine *find_default_machine(void);
+QEMUMachine *find_default_machine(const char *cpu_model);
 
 extern QEMUMachine *current_machine;
 
diff --git a/hw/integratorcp.c b/hw/integratorcp.c
index d0e2e90..4df0774 100644
--- a/hw/integratorcp.c
+++ b/hw/integratorcp.c
@@ -509,7 +509,7 @@  static QEMUMachine integratorcp_machine = {
     .name = "integratorcp",
     .desc = "ARM Integrator/CP (ARM926EJ-S)",
     .init = integratorcp_init,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void integratorcp_machine_init(void)
diff --git a/hw/lm32_boards.c b/hw/lm32_boards.c
index b76d800..2e5348b 100644
--- a/hw/lm32_boards.c
+++ b/hw/lm32_boards.c
@@ -290,14 +290,13 @@  static QEMUMachine lm32_evr_machine = {
     .name = "lm32-evr",
     .desc = "LatticeMico32 EVR32 eval system",
     .init = lm32_evr_init,
-    .is_default = 1
+    .default_for_cpu_model = "any",
 };
 
 static QEMUMachine lm32_uclinux_machine = {
     .name = "lm32-uclinux",
     .desc = "lm32 platform for uClinux and u-boot by Theobroma Systems",
     .init = lm32_uclinux_init,
-    .is_default = 0
 };
 
 static void lm32_machine_init(void)
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index ee25b1b..0e28ffd9 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -291,7 +291,7 @@  static QEMUMachine mcf5208evb_machine = {
     .name = "mcf5208evb",
     .desc = "MCF5206EVB",
     .init = mcf5208evb_init,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void mcf5208evb_machine_init(void)
diff --git a/hw/milkymist.c b/hw/milkymist.c
index 2e7235b..a8606ea 100644
--- a/hw/milkymist.c
+++ b/hw/milkymist.c
@@ -207,7 +207,6 @@  static QEMUMachine milkymist_machine = {
     .name = "milkymist",
     .desc = "Milkymist One",
     .init = milkymist_init,
-    .is_default = 0
 };
 
 static void milkymist_machine_init(void)
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index ad23f26..ac955e9 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -1020,7 +1020,7 @@  static QEMUMachine mips_malta_machine = {
     .desc = "MIPS Malta Core LV",
     .init = mips_malta_init,
     .max_cpus = 16,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void mips_malta_register_types(void)
diff --git a/hw/openrisc_sim.c b/hw/openrisc_sim.c
index 55e97f0..a037fc8 100644
--- a/hw/openrisc_sim.c
+++ b/hw/openrisc_sim.c
@@ -139,7 +139,7 @@  static QEMUMachine openrisc_sim_machine = {
     .desc = "or32 simulation",
     .init = openrisc_sim_init,
     .max_cpus = 1,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void openrisc_sim_machine_init(void)
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index 88ff041..6226e8e 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -355,7 +355,7 @@  static QEMUMachine pc_machine_v1_2 = {
     .desc = "Standard PC",
     .init = pc_init_pci,
     .max_cpus = 255,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 #define PC_COMPAT_1_1 \
diff --git a/hw/pc_sysfw.c b/hw/pc_sysfw.c
index b45f0ac..9e034d2 100644
--- a/hw/pc_sysfw.c
+++ b/hw/pc_sysfw.c
@@ -93,7 +93,7 @@  static void pc_fw_add_pflash_drv(void)
       return;
     }
 
-    machine = find_default_machine();
+    machine = find_default_machine(NULL);
     if (machine == NULL) {
       return;
     }
diff --git a/hw/petalogix_ml605_mmu.c b/hw/petalogix_ml605_mmu.c
index dced648..48d20df 100644
--- a/hw/petalogix_ml605_mmu.c
+++ b/hw/petalogix_ml605_mmu.c
@@ -148,7 +148,6 @@  static QEMUMachine petalogix_ml605_machine = {
     .name = "petalogix-ml605",
     .desc = "PetaLogix linux refdesign for xilinx ml605 little endian",
     .init = petalogix_ml605_init,
-    .is_default = 0
 };
 
 static void petalogix_ml605_machine_init(void)
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 2cf6882..48a17c7 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -117,7 +117,7 @@  static QEMUMachine petalogix_s3adsp1800_machine = {
     .name = "petalogix-s3adsp1800",
     .desc = "PetaLogix linux refdesign for xilinx Spartan 3ADSP1800",
     .init = petalogix_s3adsp1800_init,
-    .is_default = 1
+    .default_for_cpu_model = "any",
 };
 
 static void petalogix_s3adsp1800_machine_init(void)
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index e95cfe8..50f2ed3 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -424,7 +424,7 @@  static QEMUMachine core99_machine = {
     .init = ppc_core99_init,
     .max_cpus = MAX_CPUS,
 #ifdef TARGET_PPC64
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 #endif
 };
 
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 1dcd8a6..868ab82 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -339,7 +339,7 @@  static QEMUMachine heathrow_machine = {
     .init = ppc_heathrow_init,
     .max_cpus = MAX_CPUS,
 #ifndef TARGET_PPC64
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 #endif
 };
 
diff --git a/hw/puv3.c b/hw/puv3.c
index 43f7216..b8ba049 100644
--- a/hw/puv3.c
+++ b/hw/puv3.c
@@ -119,7 +119,7 @@  static QEMUMachine puv3_machine = {
     .name = "puv3",
     .desc = "PKUnity Version-3 based on UniCore32",
     .init = puv3_init,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
     .use_scsi = 0,
 };
 
diff --git a/hw/s390-virtio.c b/hw/s390-virtio.c
index 47eed35..9fcd608 100644
--- a/hw/s390-virtio.c
+++ b/hw/s390-virtio.c
@@ -341,7 +341,7 @@  static QEMUMachine s390_machine = {
     .no_sdcard = 1,
     .use_virtcon = 1,
     .max_cpus = 255,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void s390_machine_init(void)
diff --git a/hw/shix.c b/hw/shix.c
index dd9ce17..09bcce4 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -93,7 +93,7 @@  static QEMUMachine shix_machine = {
     .name = "shix",
     .desc = "shix card",
     .init = shix_init,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static void shix_machine_init(void)
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 0f909b5..2c45f03 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -1386,7 +1386,7 @@  static QEMUMachine ss5_machine = {
     .desc = "Sun4m platform, SPARCstation 5",
     .init = ss5_init,
     .use_scsi = 1,
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static QEMUMachine ss10_machine = {
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 07cd042..9858e79 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -964,7 +964,7 @@  static QEMUMachine sun4u_machine = {
     .desc = "Sun4u platform",
     .init = sun4u_init,
     .max_cpus = 1, // XXX for now
-    .is_default = 1,
+    .default_for_cpu_model = "any",
 };
 
 static QEMUMachine sun4v_machine = {
diff --git a/hw/xtensa_sim.c b/hw/xtensa_sim.c
index 831460b..78f5eea 100644
--- a/hw/xtensa_sim.c
+++ b/hw/xtensa_sim.c
@@ -111,7 +111,7 @@  static void xtensa_sim_init(ram_addr_t ram_size,
 static QEMUMachine xtensa_sim_machine = {
     .name = "sim",
     .desc = "sim machine (" XTENSA_DEFAULT_CPU_MODEL ")",
-    .is_default = true,
+    .default_for_cpu_model = "any",
     .init = xtensa_sim_init,
     .max_cpus = 4,
 };
diff --git a/qapi-schema.json b/qapi-schema.json
index bd8ad74..e210ec6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2315,13 +2315,13 @@ 
 #
 # @alias: #optional an alias for the machine name
 #
-# @default: #optional whether the machine is default
+# @default-for-cpu-model: #optional the machine is default for the given cpu
 #
 # Since: 1.2.0
 ##
 { 'type': 'MachineInfo',
   'data': { 'name': 'str', '*alias': 'str',
-            '*is-default': 'bool' } }
+            '*default-for-cpu-model': 'str' } }
 
 ##
 # @query-machines:
diff --git a/vl.c b/vl.c
index 7c577fa..1f945a2 100644
--- a/vl.c
+++ b/vl.c
@@ -1226,16 +1226,25 @@  static QEMUMachine *find_machine(const char *name)
     return NULL;
 }
 
-QEMUMachine *find_default_machine(void)
+/* Find the default machine implementation for the given cpu_model.
+ * If cpu_model is NULL, then pick the one that matches "any".
+ */
+QEMUMachine *find_default_machine(const char *cpu_model)
 {
     QEMUMachine *m;
+    QEMUMachine *best_match = NULL;
+    QEMUMachine *any_match = NULL;
 
     for(m = first_machine; m != NULL; m = m->next) {
-        if (m->is_default) {
-            return m;
+        if (m->default_for_cpu_model) {
+            if (cpu_model && strcmp(m->default_for_cpu_model, cpu_model) == 0) {
+                best_match = m;
+            } else if (strcmp(m->default_for_cpu_model, "any") == 0) {
+                any_match = m;
+            }
         }
     }
-    return NULL;
+    return best_match ? best_match : any_match;
 }
 
 MachineInfoList *qmp_query_machines(Error **errp)
@@ -1248,9 +1257,9 @@  MachineInfoList *qmp_query_machines(Error **errp)
         MachineInfo *info;
 
         info = g_malloc0(sizeof(*info));
-        if (m->is_default) {
-            info->has_is_default = true;
-            info->is_default = true;
+        if (m->default_for_cpu_model) {
+            info->has_default_for_cpu_model = true;
+            info->default_for_cpu_model = g_strdup(m->default_for_cpu_model);
         }
 
         if (m->alias) {
@@ -2166,8 +2175,12 @@  static QEMUMachine *machine_parse(const char *name)
         if (m->alias) {
             printf("%-20s %s (alias of %s)\n", m->alias, m->desc, m->name);
         }
-        printf("%-20s %s%s\n", m->name, m->desc,
-               m->is_default ? " (default)" : "");
+        if (m->default_for_cpu_model) {
+            printf("%-20s %s (default for cpu \"%s\")\n", m->name, m->desc,
+                   m->default_for_cpu_model);
+        } else {
+            printf("%-20s %s\n", m->name, m->desc);
+        }
     }
     exit(!name || !is_help_option(name));
 }
@@ -2404,7 +2417,7 @@  int main(int argc, char **argv, char **envp)
     os_setup_early_signal_handling();
 
     module_call_init(MODULE_INIT_MACHINE);
-    machine = find_default_machine();
+    machine = NULL;
     cpu_model = NULL;
     ram_size = 0;
     snapshot = 0;
@@ -3299,9 +3312,8 @@  int main(int argc, char **argv, char **envp)
         exit(1);
     }
 
-    if (machine == NULL) {
-        fprintf(stderr, "No machine found.\n");
-        exit(1);
+    if (!machine) {
+        machine = find_default_machine(cpu_model);
     }
 
     if (machine->hw_version) {