Re: [PATCH v2] spapr: Add "memop" hypercall

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




On 25.05.2012, at 05:53, Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx> wrote:

> This adds a qemu-specific hypervisor call to the pseries machine
> which allows to do what amounts to memmove, memcpy and xor over
> regions of physical memory such as the framebuffer.
> 
> This is the simplest way to get usable framebuffer speed from
> SLOF since the framebuffer isn't mapped in the VRMA and so would
> otherwise require an hcall per 8 bytes access.
> 
> The performance is still not great but usable, and can be improved
> with a more complex implementation of the hcall itself if needed.
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx>
> ---
> 
> v2: - Added documentation for our private hcalls

Very cool :). This really does belong to QEMU's documentation, as these hypercall are basically private SLOF <-> QEMU backdoor interface.

>    - Fixed coding style issues
> 
> docs/specs/ppc-spapr-hcalls.txt |   78 +++++++++++++++++++++++++++++++++++++++
> hw/spapr.h                      |    3 +-
> hw/spapr_hcall.c                |   52 ++++++++++++++++++++++++++
> 3 files changed, 132 insertions(+), 1 deletions(-)
> create mode 100644 docs/specs/ppc-spapr-hcalls.txt
> 
> diff --git a/docs/specs/ppc-spapr-hcalls.txt b/docs/specs/ppc-spapr-hcalls.txt
> new file mode 100644
> index 0000000..4b3fa9a
> --- /dev/null
> +++ b/docs/specs/ppc-spapr-hcalls.txt
> @@ -0,0 +1,78 @@
> +When used with the "pseries" machine type, qemu-system-ppc64 implement

s

> +a set of hypervisor calls using a subset of the server "PAPR" specification
> +(IBM internal at this point), which is also what IBM

's

> proprietary hypervisor
> +adheres too.
> +
> +The subset is selected based on the requirements of Linux as a guest.
> +
> +In addition to those calls, we have added our own private hypervisor
> +calls which are mostly used as a private interface between the firmware
> +running in the guest and qemu.

QEMU

> +
> +All those hypercalls start at hcall number 0xf000 which correspond
> +to a implementation specific range in PAPR.
> +
> +- H_RTAS (0xf000)
> +
> +RTAS is a set of runtime services generally provided by the firmware
> +inside the guest to the operating system. It predates the existence
> +of hypervisors (it was originally an extension to Open Firmware) and
> +is still used by PAPR to provide various services that aren't performance
> +sensitive.
> +
> +We currently implement the RTAS services in qemu

QEMU (won't comment on it below, please just search&replace it ;))

> itself. The actual RTAS
> +"firmware" blob in the guest is a small stub of a few instructions which
> +calls our private H_RTAS hypervisor call to pass the RTAS calls to qemu.
> +
> +Arguments:
> +
> +  r3 : H_RTAS (0xf000)
> +  r4 : Guest physical address of RTAS parameter block
> +
> +Returns:
> +
> +  H_SUCCESS   : Successully called the RTAS function (RTAS result
> +                will have been stored in the parameter block)
> +  H_PARAMETER : Unknown token
> +
> +- H_LOGICAL_MEMOP (0xf001)
> +
> +When the guest runs in "real mode" (in powerpc lingua this means
> +with MMU disabled, ie guest effective == guest physical), it only
> +has access to a subset of memory and no IOs.
> +
> +PAPR provides a set of hypervisor calls to perform cachable or
> +non-cachable accesses to any guest physical addresses that the
> +guest can use in order to access IO devices while in real mode.
> +
> +This is typically used by the firmware running in the guest.
> +
> +However, doing a hypercall for each access is extremely inefficient
> +(even more so when running KVM) when accessing the frame buffer. In
> +that case, things like scrolling become unusably slow.
> +
> +This hypercall allows the guest to request a "memory op" to be applied
> +to memory. The supported memory ops at this point are to copy a range
> +of memory (supports overlap of source and destination) and XOR which
> +is used by our SLOF firmware to invert the screen.
> +
> +Arguments:
> +
> +  r3: H_LOGICAL_MEMOP (0xf001)
> +  r4: Guest physical address of destination
> +  r5: Guest physical address of source
> +  r6: Individual element size
> +        0 = 1 byte
> +        1 = 2 bytes
> +        2 = 4 bytes
> +        3 = 8 bytes
> +  r7: Number of elements
> +  r8: Operation
> +        0 = copy
> +        1 = xor
> +
> +Returns:
> +
> +  H_SUCCESS   : Success
> +  H_PARAMETER : Invalid argument
> +
> diff --git a/hw/spapr.h b/hw/spapr.h
> index 7c497aa..0343f33 100644
> --- a/hw/spapr.h
> +++ b/hw/spapr.h
> @@ -264,7 +264,8 @@ typedef struct sPAPREnvironment {
>  */
> #define KVMPPC_HCALL_BASE       0xf000
> #define KVMPPC_H_RTAS           (KVMPPC_HCALL_BASE + 0x0)
> -#define KVMPPC_HCALL_MAX        KVMPPC_H_RTAS
> +#define KVMPPC_H_LOGICAL_MEMOP  (KVMPPC_HCALL_BASE + 0x1)
> +#define KVMPPC_HCALL_MAX        KVMPPC_H_LOGICAL_MEMOP
> 
> extern sPAPREnvironment *spapr;
> 
> diff --git a/hw/spapr_hcall.c b/hw/spapr_hcall.c
> index 94bb504..5211364 100644
> --- a/hw/spapr_hcall.c
> +++ b/hw/spapr_hcall.c
> @@ -608,6 +608,57 @@ static target_ulong h_logical_store(CPUPPCState *env, sPAPREnvironment *spapr,
>     return H_PARAMETER;
> }
> 
> +static target_ulong h_logical_memop(CPUPPCState *env, sPAPREnvironment *spapr,
> +                                    target_ulong opcode, target_ulong *args)
> +{
> +    target_ulong dst   = args[0]; /* Destination address */
> +    target_ulong src   = args[1]; /* Source address */
> +    target_ulong esize = args[2]; /* Element size (0=1,1=2,2=4,3=8) */
> +    target_ulong count = args[3]; /* Element count */
> +    target_ulong op    = args[4]; /* 0 = copy, 1 = invert */
> +    uint64_t tmp;
> +    unsigned int mask = (1 << esize) - 1;
> +    int step = 1 << esize;
> +
> +    if (count > 0x80000000) {
> +    return H_PARAMETER;

Indentation?

> +    }
> +
> +    if ((dst & mask) || (src & mask)) {
> +        return H_PARAMETER;
> +    }

If (op > 1) return H_PARAMETER;

> +
> +    if (dst >= src && dst < (src + (count << esize))) {
> +            dst = dst + ((count - 1) << esize);
> +            src = src + ((count - 1) << esize);
> +            step = -step;
> +    }
> +
> +    while (count--) {
> +        switch (esize) {
> +        case 0: tmp = ldub_phys(src);

I'm surprised checkpatch didn't complain here. Please do

case x:
    foo();
    break();

> break;
> +        case 1: tmp = lduw_phys(src); break;
> +        case 2: tmp = ldl_phys(src);  break;
> +        case 3: tmp = ldq_phys(src);  break;
> +        default:
> +        return H_PARAMETER;

Indentation?

> +        }
> +        if (op) {

op == 1

> +            tmp = ~tmp;
> +        }
> +        switch (esize) {
> +        case 0: stb_phys(dst, tmp); break;
> +        case 1: stw_phys(dst, tmp); break;
> +        case 2: stl_phys(dst, tmp); break;
> +        case 3: stq_phys(dst, tmp);

Same as above

Otherwise a good idea :).


Alex

> break;
> +        }
> +        dst = dst + step;
> +        src = src + step;
> +    }
> +
> +    return H_SUCCESS;
> +}
> +
> static target_ulong h_logical_icbi(CPUPPCState *env, sPAPREnvironment *spapr,
>                                    target_ulong opcode, target_ulong *args)
> {
> @@ -700,6 +751,7 @@ static void hypercall_register_types(void)
>     spapr_register_hypercall(H_LOGICAL_CACHE_STORE, h_logical_store);
>     spapr_register_hypercall(H_LOGICAL_ICBI, h_logical_icbi);
>     spapr_register_hypercall(H_LOGICAL_DCBF, h_logical_dcbf);
> +    spapr_register_hypercall(KVMPPC_H_LOGICAL_MEMOP, h_logical_memop);
> 
>     /* qemu/KVM-PPC specific hcalls */
>     spapr_register_hypercall(KVMPPC_H_RTAS, h_rtas);
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe kvm-ppc" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux