On 24/08/2020 10.11, Huacai Chen wrote:
> MIPS has two types of KVM: TE & VZ, and TE is the default type. Now,
> libvirt uses a null-machine to detect the kvm capability. In the MIPS
> case, it will return "KVM not supported" on a VZ platform by default.
> So, add the kvm_type() hook to the null-machine.
> 
> This seems not a very good solution, but I cannot do it better now.

This is still ugly. Why do the other architectures do not have the
same problem? Let's see... in kvm-all.c, we have:

    int type = 0;
    [...]
    kvm_type = qemu_opt_get(qemu_get_machine_opts(), "kvm-type");
    if (mc->kvm_type) {
        type = mc->kvm_type(ms, kvm_type);
    } else if (kvm_type) {
        ret = -EINVAL;
        fprintf(stderr, "Invalid argument kvm-type=%s\n", kvm_type);
        goto err;
    }

    do {
        ret = kvm_ioctl(s, KVM_CREATE_VM, type);
    } while (ret == -EINTR);

Thus the KVM_CREATE_VM ioctl is likely called with type = 0 in this
case (i.e. when libvirt probes with the "null"-machine).

Now let's have a look at the kernel. The "type" parameter is passed
there to the architecture specific function kvm_arch_init_vm().
For powerpc, this looks like:

        if (type == 0) {
                if (kvmppc_hv_ops)
                        kvm_ops = kvmppc_hv_ops;
                else
                        kvm_ops = kvmppc_pr_ops;
                if (!kvm_ops)
                        goto err_out;
        } else  if (type == KVM_VM_PPC_HV) {
                if (!kvmppc_hv_ops)
                        goto err_out;
                kvm_ops = kvmppc_hv_ops;
        } else if (type == KVM_VM_PPC_PR) {
                if (!kvmppc_pr_ops)
                        goto err_out;
                kvm_ops = kvmppc_pr_ops;
        } else
                goto err_out;

That means for type == 0, it automatically detects the best
kvm-type.

For mips, this function looks like this:

        switch (type) {
#ifdef CONFIG_KVM_MIPS_VZ
        case KVM_VM_MIPS_VZ:
#else
        case KVM_VM_MIPS_TE:
#endif
                break;
        default:
                /* Unsupported KVM type */
                return -EINVAL;
        };

That means, for type == 0, it returns -EINVAL here!

Looking at the API docu in Documentation/virt/kvm/api.rst
the description of the type parameter is quite sparse, but it
says:

 "You probably want to use 0 as machine type."

So I think this is a bug in the implementation of KVM in the
mips kernel code. The kvm_arch_init_vm() in the mips code should
do the same as on powerpc, and use the best available KVM type
there instead of returning EINVAL. Once that is fixed there,
you don't need this patch here for QEMU anymore.

 HTH,
  Thomas


> Reviewed-by: Aleksandar Markovic <aleksandar.qemu.de...@gmail.com>
> Signed-off-by: Huacai Chen <che...@lemote.com>
> Co-developed-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
> ---
>  hw/core/meson.build    | 2 +-
>  hw/core/null-machine.c | 6 ++++++
>  2 files changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/core/meson.build b/hw/core/meson.build
> index fc91f98..b6591b9 100644
> --- a/hw/core/meson.build
> +++ b/hw/core/meson.build
> @@ -35,7 +35,6 @@ softmmu_ss.add(files(
>    'machine-hmp-cmds.c',
>    'machine.c',
>    'nmi.c',
> -  'null-machine.c',
>    'qdev-fw.c',
>    'qdev-properties-system.c',
>    'sysbus.c',
> @@ -45,5 +44,6 @@ softmmu_ss.add(files(
>  
>  specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
>    'machine-qmp-cmds.c',
> +  'null-machine.c',
>    'numa.c',
>  ))
> diff --git a/hw/core/null-machine.c b/hw/core/null-machine.c
> index 7e69352..4b4ab76 100644
> --- a/hw/core/null-machine.c
> +++ b/hw/core/null-machine.c
> @@ -17,6 +17,9 @@
>  #include "sysemu/sysemu.h"
>  #include "exec/address-spaces.h"
>  #include "hw/core/cpu.h"
> +#ifdef TARGET_MIPS
> +#include "kvm_mips.h"
> +#endif
>  
>  static void machine_none_init(MachineState *mch)
>  {
> @@ -55,6 +58,9 @@ static void machine_none_machine_init(MachineClass *mc)
>      mc->no_floppy = 1;
>      mc->no_cdrom = 1;
>      mc->no_sdcard = 1;
> +#ifdef TARGET_MIPS
> +    mc->kvm_type = mips_kvm_type;
> +#endif
>  }
>  
>  DEFINE_MACHINE("none", machine_none_machine_init)
> 


Reply via email to