On Mon, 2012-05-21 at 10:38 +0200, Alexander Graf wrote: > On 21.05.2012, at 09:24, Benjamin Herrenschmidt wrote: > > > This adds a kvm-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. > > Shouldn't we try and implement the same thing in QEMU as well to make > things compatible? Also, what would the downside be of always going > through QEMU for this hypercall? > > The reason I'm asking is that we might want to do memmove,memcpy,xor > on MMIO memory, which then user space could easily do, but which > incurs quite some headaches to do it from inside KVM. I don't understand your question ... this is implemented in qemu... The problem with SLOF is specific to -M pseries, because it runs in "guest" real mode, it doesn't have access to device memory unless it does it via hcalls. Cheers, Ben. > > Alex > > > > > Signed-off-by: Benjamin Herrenschmidt <benh@xxxxxxxxxxxxxxxxxxx> > > --- > > hw/spapr.h | 3 ++- > > hw/spapr_hcall.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ > > 2 files changed, 51 insertions(+), 1 deletion(-) > > > > 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..c5c26dc 100644 > > --- a/hw/spapr_hcall.c > > +++ b/hw/spapr_hcall.c > > @@ -608,6 +608,54 @@ 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; > > + > > + if ((dst & mask) || (src & mask)) > > + 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); 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; > > + } > > + if (op) > > + 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); 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 +748,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