diff mbox

[02/24] xen/arm: hypercalls

Message ID 1343316846-25860-2-git-send-email-stefano.stabellini@eu.citrix.com (mailing list archive)
State New, archived
Headers show

Commit Message

Stefano Stabellini July 26, 2012, 3:33 p.m. UTC
Use r12 to pass the hypercall number to the hypervisor.

We need a register to pass the hypercall number because we might not
know it at compile time and HVC only takes an immediate argument.

Among the available registers r12 seems to be the best choice because it
is defined as "intra-procedure call scratch register".

Use the ISS to pass an hypervisor specific tag.

Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
---
 arch/arm/include/asm/xen/hypercall.h |   50 ++++++++++++++++++++++++++
 arch/arm/xen/Makefile                |    2 +-
 arch/arm/xen/hypercall.S             |   65 ++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 1 deletions(-)
 create mode 100644 arch/arm/include/asm/xen/hypercall.h
 create mode 100644 arch/arm/xen/hypercall.S

Comments

Konrad Rzeszutek Wilk July 26, 2012, 4:33 p.m. UTC | #1
On Thu, Jul 26, 2012 at 04:33:44PM +0100, Stefano Stabellini wrote:
> Use r12 to pass the hypercall number to the hypervisor.
> 
> We need a register to pass the hypercall number because we might not
> know it at compile time and HVC only takes an immediate argument.
> 
> Among the available registers r12 seems to be the best choice because it
> is defined as "intra-procedure call scratch register".
> 
> Use the ISS to pass an hypervisor specific tag.
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> ---
>  arch/arm/include/asm/xen/hypercall.h |   50 ++++++++++++++++++++++++++
>  arch/arm/xen/Makefile                |    2 +-
>  arch/arm/xen/hypercall.S             |   65 ++++++++++++++++++++++++++++++++++
>  3 files changed, 116 insertions(+), 1 deletions(-)
>  create mode 100644 arch/arm/include/asm/xen/hypercall.h
>  create mode 100644 arch/arm/xen/hypercall.S
> 
> diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
> new file mode 100644
> index 0000000..4ac0624
> --- /dev/null
> +++ b/arch/arm/include/asm/xen/hypercall.h
> @@ -0,0 +1,50 @@
> +/******************************************************************************
> + * hypercall.h
> + *
> + * Linux-specific hypervisor handling.
> + *
> + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License version 2
> + * as published by the Free Software Foundation; or, when distributed
> + * separately from the Linux kernel or incorporated into other
> + * software packages, subject to the following license:
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this source file (the "Software"), to deal in the Software without
> + * restriction, including without limitation the rights to use, copy, modify,
> + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> + * and to permit persons to whom the Software is furnished to do so, subject to
> + * the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#ifndef _ASM_ARM_XEN_HYPERCALL_H
> +#define _ASM_ARM_XEN_HYPERCALL_H
> +
> +#include <xen/interface/xen.h>
> +
> +long privcmd_call(unsigned call, unsigned long a1,
> +		unsigned long a2, unsigned long a3,
> +		unsigned long a4, unsigned long a5);
> +int HYPERVISOR_xen_version(int cmd, void *arg);
> +int HYPERVISOR_console_io(int cmd, int count, char *str);
> +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
> +int HYPERVISOR_sched_op(int cmd, void *arg);
> +int HYPERVISOR_event_channel_op(int cmd, void *arg);
> +unsigned long HYPERVISOR_hvm_op(int op, void *arg);
> +int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
> +int HYPERVISOR_physdev_op(int cmd, void *arg);
> +
> +#endif /* _ASM_ARM_XEN_HYPERCALL_H */
> diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
> index 0bad594..b9d6acc 100644
> --- a/arch/arm/xen/Makefile
> +++ b/arch/arm/xen/Makefile
> @@ -1 +1 @@
> -obj-y		:= enlighten.o
> +obj-y		:= enlighten.o hypercall.o
> diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
> new file mode 100644
> index 0000000..038cc5b
> --- /dev/null
> +++ b/arch/arm/xen/hypercall.S
> @@ -0,0 +1,65 @@
> +/******************************************************************************
> + * hypercall.S
> + *
> + * Xen hypercall wrappers
> + *
> + * The Xen hypercall calling convention is very similar to the ARM
> + * procedure calling convention: the first paramter is passed in r0, the
> + * second in r1, the third in r2 and the third in r3. Considering that

I think you meant 'and the fourth in r3'.

So where does the similarity end?  Just in that we use r12?

> + * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
> + * in r4, differently from the procedure calling convention of using the

> + * stack for that case.
> + *
> + * The hypercall number is passed in r12.
> + *
> + * The return value is in r0.
> + *
> + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> + * hypercall tag.
> + *
> + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> + */
> +
> +#include <linux/linkage.h>
> +#include <asm/assembler.h>
> +#include <xen/interface/xen.h>
> +
> +
> +/* HVC 0xEA1 */
> +#ifdef CONFIG_THUMB2_KERNEL
> +#define xen_hvc .word 0xf7e08ea1
> +#else
> +#define xen_hvc .word 0xe140ea71
> +#endif
> +
> +/* We need to save and restore r4, because Xen clobbers it. */

Hmm, the comment says r4, but right below I see r12?
Should this comment be by 'privcmd_call'?

> +#define HYPERCALL(hypercall)			\
> +ENTRY(HYPERVISOR_##hypercall)			\
> +	mov r12, #__HYPERVISOR_##hypercall;	\
> +	xen_hvc;							\
> +	mov pc, lr;							\
> +ENDPROC(HYPERVISOR_##hypercall)
> +
> +                .text
> +
> +HYPERCALL(xen_version);
> +HYPERCALL(console_io);
> +HYPERCALL(grant_table_op);
> +HYPERCALL(sched_op);
> +HYPERCALL(event_channel_op);
> +HYPERCALL(hvm_op);
> +HYPERCALL(memory_op);
> +HYPERCALL(physdev_op);
> +
> +ENTRY(privcmd_call)
> +	stmdb	sp!, {r4}
> +	mov r12, r0
> +	mov r0, r1
> +	mov r1, r2
> +	mov r2, r3
> +	ldr r3, [sp, #8]
> +	ldr r4, [sp, #4]
> +	xen_hvc
> +	pop {r4}
> +	mov pc, lr
> +ENDPROC(privcmd_call);
> -- 
> 1.7.2.5
> 
> 
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
David Vrabel July 26, 2012, 4:56 p.m. UTC | #2
On 26/07/12 16:33, Stefano Stabellini wrote:
> 
> + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> + * hypercall tag.

Is this number, 0xea1, assigned to Xen by some external body?

David
Stefano Stabellini July 26, 2012, 5:19 p.m. UTC | #3
On Thu, 26 Jul 2012, David Vrabel wrote:
> On 26/07/12 16:33, Stefano Stabellini wrote:
> > 
> > + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> > + * hypercall tag.
> 
> Is this number, 0xea1, assigned to Xen by some external body?

I am not aware of any "external body" that could assign us such a number
but it is specified in the Xen hypercall calling convention, documented
here:

http://xenbits.xensource.com/hg/xen-unstable.hg/file/663eb766cdde/xen/include/public/arch-arm.h
Christopher Covington July 26, 2012, 7:19 p.m. UTC | #4
Hi Stefano,

On 07/26/2012 11:33 AM, Stefano Stabellini wrote:
> Use r12 to pass the hypercall number to the hypervisor.
> 
> We need a register to pass the hypercall number because we might not
> know it at compile time and HVC only takes an immediate argument.

You're not going to JIT assemble the appropriate HVC instruction? Darn.

How many call numbers are there, though? 8? It seems like it'd be
reasonable to take the approach that seems to be favored for MRC/MCR
instructions, using a function containing switch statement that chooses
between several inline assembly instructions based off an enum passed to
the function. See for example arch_timer_reg_read in
arch/arm/kernel/arch_timer.c.

Regards,
Christopher
Ian Campbell July 27, 2012, 9 a.m. UTC | #5
On Thu, 2012-07-26 at 17:56 +0100, David Vrabel wrote:
> On 26/07/12 16:33, Stefano Stabellini wrote:
> > 
> > + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> > + * hypercall tag.
> 
> Is this number, 0xea1, assigned to Xen by some external body?

The value and semantics of the hvc instructions immediate operand is
entirely up to the hypervisor authors. We could have chosen 0 or some
random number, we went for the latter because it increases the chances,
by some tiny amount, that we won't clash with some other hypervisors ABI
which makes supporting "foreign" guests that bit easier should it even
come to it.

IOW it's arbitrary in the same way that a Linux system calls used to use
int 0x80.

Ian.
Ian Campbell July 27, 2012, 9:17 a.m. UTC | #6
On Thu, 2012-07-26 at 17:33 +0100, Konrad Rzeszutek Wilk wrote:
> On Thu, Jul 26, 2012 at 04:33:44PM +0100, Stefano Stabellini wrote:
> > Use r12 to pass the hypercall number to the hypervisor.
> > 
> > We need a register to pass the hypercall number because we might not
> > know it at compile time and HVC only takes an immediate argument.
> > 
> > Among the available registers r12 seems to be the best choice because it
> > is defined as "intra-procedure call scratch register".
> > 
> > Use the ISS to pass an hypervisor specific tag.
> > 
> > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > ---
> >  arch/arm/include/asm/xen/hypercall.h |   50 ++++++++++++++++++++++++++
> >  arch/arm/xen/Makefile                |    2 +-
> >  arch/arm/xen/hypercall.S             |   65 ++++++++++++++++++++++++++++++++++
> >  3 files changed, 116 insertions(+), 1 deletions(-)
> >  create mode 100644 arch/arm/include/asm/xen/hypercall.h
> >  create mode 100644 arch/arm/xen/hypercall.S
> > 
> > diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
> > new file mode 100644
> > index 0000000..4ac0624
> > --- /dev/null
> > +++ b/arch/arm/include/asm/xen/hypercall.h
> > @@ -0,0 +1,50 @@
> > +/******************************************************************************
> > + * hypercall.h
> > + *
> > + * Linux-specific hypervisor handling.
> > + *
> > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > + *
> > + * This program is free software; you can redistribute it and/or
> > + * modify it under the terms of the GNU General Public License version 2
> > + * as published by the Free Software Foundation; or, when distributed
> > + * separately from the Linux kernel or incorporated into other
> > + * software packages, subject to the following license:
> > + *
> > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > + * of this source file (the "Software"), to deal in the Software without
> > + * restriction, including without limitation the rights to use, copy, modify,
> > + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> > + * and to permit persons to whom the Software is furnished to do so, subject to
> > + * the following conditions:
> > + *
> > + * The above copyright notice and this permission notice shall be included in
> > + * all copies or substantial portions of the Software.
> > + *
> > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> > + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > + * IN THE SOFTWARE.
> > + */
> > +
> > +#ifndef _ASM_ARM_XEN_HYPERCALL_H
> > +#define _ASM_ARM_XEN_HYPERCALL_H
> > +
> > +#include <xen/interface/xen.h>
> > +
> > +long privcmd_call(unsigned call, unsigned long a1,
> > +		unsigned long a2, unsigned long a3,
> > +		unsigned long a4, unsigned long a5);
> > +int HYPERVISOR_xen_version(int cmd, void *arg);
> > +int HYPERVISOR_console_io(int cmd, int count, char *str);
> > +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
> > +int HYPERVISOR_sched_op(int cmd, void *arg);
> > +int HYPERVISOR_event_channel_op(int cmd, void *arg);
> > +unsigned long HYPERVISOR_hvm_op(int op, void *arg);
> > +int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
> > +int HYPERVISOR_physdev_op(int cmd, void *arg);
> > +
> > +#endif /* _ASM_ARM_XEN_HYPERCALL_H */
> > diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
> > index 0bad594..b9d6acc 100644
> > --- a/arch/arm/xen/Makefile
> > +++ b/arch/arm/xen/Makefile
> > @@ -1 +1 @@
> > -obj-y		:= enlighten.o
> > +obj-y		:= enlighten.o hypercall.o
> > diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
> > new file mode 100644
> > index 0000000..038cc5b
> > --- /dev/null
> > +++ b/arch/arm/xen/hypercall.S
> > @@ -0,0 +1,65 @@
> > +/******************************************************************************
> > + * hypercall.S
> > + *
> > + * Xen hypercall wrappers
> > + *
> > + * The Xen hypercall calling convention is very similar to the ARM
> > + * procedure calling convention: the first paramter is passed in r0, the
> > + * second in r1, the third in r2 and the third in r3. Considering that
> 
> I think you meant 'and the fourth in r3'.
> 
> So where does the similarity end?  Just in that we use r12?

The standard ARM function calling convention is arguments 1-4 on r0-r3
and arguments 5+ on the stack. r12 is a scratch register which can be
clobbered by the *linker* on subroutine call (r12 is also called "ip"
the intra-procedure call scratch register).

The hypervisor doesn't want to be accessing hypercall arguments off the
guest stack, for obvious reasons, so we use r4 for the fifth argument
(and if we even implemented 6 argument hypercalls we'd use r5, etc).
There is no equivalent to the hypercall number in the procedure calling
convention so we picked r12 because it is up and out of the way and is
otherwise a scratch register. Obviously that you must not make a
procedure call between setting the hypercall number in r12 and calling
the hvc instruction.

> 
> > + * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
> > + * in r4, differently from the procedure calling convention of using the
> 
> > + * stack for that case.
> > + *
> > + * The hypercall number is passed in r12.
> > + *
> > + * The return value is in r0.
> > + *
> > + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> > + * hypercall tag.
> > + *
> > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > + */
> > +
> > +#include <linux/linkage.h>
> > +#include <asm/assembler.h>
> > +#include <xen/interface/xen.h>
> > +
> > +
> > +/* HVC 0xEA1 */
> > +#ifdef CONFIG_THUMB2_KERNEL
> > +#define xen_hvc .word 0xf7e08ea1
> > +#else
> > +#define xen_hvc .word 0xe140ea71
> > +#endif
> > +
> > +/* We need to save and restore r4, because Xen clobbers it. */
> 
> Hmm, the comment says r4, but right below I see r12?

The ARM procedure calling convention allows a subroutine to clobber
r1..r3 (r0 is the return value) but not r4 which must be preserved. But
the hypervisor ABI clobbers all argument registers so the caller has to
specially preserve r4 in this context whenever there is a 5 argument
hypercall.

I presume that none of the hypercalls defined below have 5 arguments and
therefore we don't need to preserve r4 except in the generic
privcmd_call function. 

To be honest I prefer the style which we use on x86 which is to define
hypercall{0,1,2,3,4,5} macros and to wrap those with the specific names
using inline functions.

I find the x86 way more self documenting, and being in C prevents errors
around the number of arguments. It also allows for better in-lining and
exposes to gcc the actual clobbers, which might allow it to avoid saving
r4 on the stack at all etc.

> Should this comment be by 'privcmd_call'?

When we add a 5 argument hypercall I suppose we'll see the required
push/pop of r4 added to this macro too.

> > +#define HYPERCALL(hypercall)			\
> > +ENTRY(HYPERVISOR_##hypercall)			\
> > +	mov r12, #__HYPERVISOR_##hypercall;	\
> > +	xen_hvc;							\
> > +	mov pc, lr;							\
> > +ENDPROC(HYPERVISOR_##hypercall)
> > +
> > +                .text
> > +
> > +HYPERCALL(xen_version);
> > +HYPERCALL(console_io);
> > +HYPERCALL(grant_table_op);
> > +HYPERCALL(sched_op);
> > +HYPERCALL(event_channel_op);
> > +HYPERCALL(hvm_op);
> > +HYPERCALL(memory_op);
> > +HYPERCALL(physdev_op);
> > +
> > +ENTRY(privcmd_call)
> > +	stmdb	sp!, {r4}
> > +	mov r12, r0
> > +	mov r0, r1
> > +	mov r1, r2
> > +	mov r2, r3
> > +	ldr r3, [sp, #8]
> > +	ldr r4, [sp, #4]
> > +	xen_hvc
> > +	pop {r4}

Why not ldmdb for symmetry?

> > +	mov pc, lr
> > +ENDPROC(privcmd_call);
> > -- 
> > 1.7.2.5
> > 
> > 
> > _______________________________________________
> > Xen-devel mailing list
> > Xen-devel@lists.xen.org
> > http://lists.xen.org/xen-devel
Ian Campbell July 27, 2012, 9:19 a.m. UTC | #7
On Thu, 2012-07-26 at 20:19 +0100, Christopher Covington wrote:
> Hi Stefano,
> 
> On 07/26/2012 11:33 AM, Stefano Stabellini wrote:
> > Use r12 to pass the hypercall number to the hypervisor.
> > 
> > We need a register to pass the hypercall number because we might not
> > know it at compile time and HVC only takes an immediate argument.
> 
> You're not going to JIT assemble the appropriate HVC instruction? Darn.

;-)

> How many call numbers are there, though? 8?

The maximum currently defined hypercall number is 55, although there are
some small gaps so there's actually more like 45 in total.

>  It seems like it'd be
> reasonable to take the approach that seems to be favored for MRC/MCR
> instructions, using a function containing switch statement that chooses
> between several inline assembly instructions based off an enum passed to
> the function. See for example arch_timer_reg_read in
> arch/arm/kernel/arch_timer.c.

I don't think it is feasible with this number of hypercalls, even
accepting that in many cases the number will be a constant so gcc can
likely optimise almost all of it away.

Is there something wrong with the r12 based approach?

Ian.
Christopher Covington July 27, 2012, 12:56 p.m. UTC | #8
On 07/27/2012 05:19 AM, Ian Campbell wrote:
> On Thu, 2012-07-26 at 20:19 +0100, Christopher Covington wrote:
>> Hi Stefano,
>>
>> On 07/26/2012 11:33 AM, Stefano Stabellini wrote:
>>> Use r12 to pass the hypercall number to the hypervisor.
>>>
>>> We need a register to pass the hypercall number because we might not
>>> know it at compile time and HVC only takes an immediate argument.
>>
>> You're not going to JIT assemble the appropriate HVC instruction? Darn.
> 
> ;-)
> 
>> How many call numbers are there, though? 8?
> 
> The maximum currently defined hypercall number is 55, although there are
> some small gaps so there's actually more like 45 in total.
> 
>>  It seems like it'd be
>> reasonable to take the approach that seems to be favored for MRC/MCR
>> instructions, using a function containing switch statement that chooses
>> between several inline assembly instructions based off an enum passed to
>> the function. See for example arch_timer_reg_read in
>> arch/arm/kernel/arch_timer.c.
> 
> I don't think it is feasible with this number of hypercalls, even
> accepting that in many cases the number will be a constant so gcc can
> likely optimise almost all of it away.
> 
> Is there something wrong with the r12 based approach?

Only that you're defining a custom interface for something that there is
a potentially more standard interface for. I just wanted to double check
that all the ways of using the potentially more standard interface had
been explored and found to be unreasonable.

Christopher
Stefano Stabellini July 27, 2012, 1:02 p.m. UTC | #9
On Fri, 27 Jul 2012, Ian Campbell wrote:
> On Thu, 2012-07-26 at 17:33 +0100, Konrad Rzeszutek Wilk wrote:
> > On Thu, Jul 26, 2012 at 04:33:44PM +0100, Stefano Stabellini wrote:
> > > Use r12 to pass the hypercall number to the hypervisor.
> > > 
> > > We need a register to pass the hypercall number because we might not
> > > know it at compile time and HVC only takes an immediate argument.
> > > 
> > > Among the available registers r12 seems to be the best choice because it
> > > is defined as "intra-procedure call scratch register".
> > > 
> > > Use the ISS to pass an hypervisor specific tag.
> > > 
> > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > > ---
> > >  arch/arm/include/asm/xen/hypercall.h |   50 ++++++++++++++++++++++++++
> > >  arch/arm/xen/Makefile                |    2 +-
> > >  arch/arm/xen/hypercall.S             |   65 ++++++++++++++++++++++++++++++++++
> > >  3 files changed, 116 insertions(+), 1 deletions(-)
> > >  create mode 100644 arch/arm/include/asm/xen/hypercall.h
> > >  create mode 100644 arch/arm/xen/hypercall.S
> > > 
> > > diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
> > > new file mode 100644
> > > index 0000000..4ac0624
> > > --- /dev/null
> > > +++ b/arch/arm/include/asm/xen/hypercall.h
> > > @@ -0,0 +1,50 @@
> > > +/******************************************************************************
> > > + * hypercall.h
> > > + *
> > > + * Linux-specific hypervisor handling.
> > > + *
> > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > + *
> > > + * This program is free software; you can redistribute it and/or
> > > + * modify it under the terms of the GNU General Public License version 2
> > > + * as published by the Free Software Foundation; or, when distributed
> > > + * separately from the Linux kernel or incorporated into other
> > > + * software packages, subject to the following license:
> > > + *
> > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > + * of this source file (the "Software"), to deal in the Software without
> > > + * restriction, including without limitation the rights to use, copy, modify,
> > > + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> > > + * and to permit persons to whom the Software is furnished to do so, subject to
> > > + * the following conditions:
> > > + *
> > > + * The above copyright notice and this permission notice shall be included in
> > > + * all copies or substantial portions of the Software.
> > > + *
> > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> > > + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > > + * IN THE SOFTWARE.
> > > + */
> > > +
> > > +#ifndef _ASM_ARM_XEN_HYPERCALL_H
> > > +#define _ASM_ARM_XEN_HYPERCALL_H
> > > +
> > > +#include <xen/interface/xen.h>
> > > +
> > > +long privcmd_call(unsigned call, unsigned long a1,
> > > +		unsigned long a2, unsigned long a3,
> > > +		unsigned long a4, unsigned long a5);
> > > +int HYPERVISOR_xen_version(int cmd, void *arg);
> > > +int HYPERVISOR_console_io(int cmd, int count, char *str);
> > > +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
> > > +int HYPERVISOR_sched_op(int cmd, void *arg);
> > > +int HYPERVISOR_event_channel_op(int cmd, void *arg);
> > > +unsigned long HYPERVISOR_hvm_op(int op, void *arg);
> > > +int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
> > > +int HYPERVISOR_physdev_op(int cmd, void *arg);
> > > +
> > > +#endif /* _ASM_ARM_XEN_HYPERCALL_H */
> > > diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
> > > index 0bad594..b9d6acc 100644
> > > --- a/arch/arm/xen/Makefile
> > > +++ b/arch/arm/xen/Makefile
> > > @@ -1 +1 @@
> > > -obj-y		:= enlighten.o
> > > +obj-y		:= enlighten.o hypercall.o
> > > diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
> > > new file mode 100644
> > > index 0000000..038cc5b
> > > --- /dev/null
> > > +++ b/arch/arm/xen/hypercall.S
> > > @@ -0,0 +1,65 @@
> > > +/******************************************************************************
> > > + * hypercall.S
> > > + *
> > > + * Xen hypercall wrappers
> > > + *
> > > + * The Xen hypercall calling convention is very similar to the ARM
> > > + * procedure calling convention: the first paramter is passed in r0, the
> > > + * second in r1, the third in r2 and the third in r3. Considering that
> > 
> > I think you meant 'and the fourth in r3'.
> > 
> > So where does the similarity end?  Just in that we use r12?
> 
> The standard ARM function calling convention is arguments 1-4 on r0-r3
> and arguments 5+ on the stack. r12 is a scratch register which can be
> clobbered by the *linker* on subroutine call (r12 is also called "ip"
> the intra-procedure call scratch register).
> 
> The hypervisor doesn't want to be accessing hypercall arguments off the
> guest stack, for obvious reasons, so we use r4 for the fifth argument
> (and if we even implemented 6 argument hypercalls we'd use r5, etc).
> There is no equivalent to the hypercall number in the procedure calling
> convention so we picked r12 because it is up and out of the way and is
> otherwise a scratch register. Obviously that you must not make a
> procedure call between setting the hypercall number in r12 and calling
> the hvc instruction.
> 
> > 
> > > + * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
> > > + * in r4, differently from the procedure calling convention of using the
> > 
> > > + * stack for that case.
> > > + *
> > > + * The hypercall number is passed in r12.
> > > + *
> > > + * The return value is in r0.
> > > + *
> > > + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> > > + * hypercall tag.
> > > + *
> > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > + */
> > > +
> > > +#include <linux/linkage.h>
> > > +#include <asm/assembler.h>
> > > +#include <xen/interface/xen.h>
> > > +
> > > +
> > > +/* HVC 0xEA1 */
> > > +#ifdef CONFIG_THUMB2_KERNEL
> > > +#define xen_hvc .word 0xf7e08ea1
> > > +#else
> > > +#define xen_hvc .word 0xe140ea71
> > > +#endif
> > > +
> > > +/* We need to save and restore r4, because Xen clobbers it. */
> > 
> > Hmm, the comment says r4, but right below I see r12?
> 
> The ARM procedure calling convention allows a subroutine to clobber
> r1..r3 (r0 is the return value) but not r4 which must be preserved. But
> the hypervisor ABI clobbers all argument registers so the caller has to
> specially preserve r4 in this context whenever there is a 5 argument
> hypercall.
> 
> I presume that none of the hypercalls defined below have 5 arguments and
> therefore we don't need to preserve r4 except in the generic
> privcmd_call function. 
> 
> To be honest I prefer the style which we use on x86 which is to define
> hypercall{0,1,2,3,4,5} macros and to wrap those with the specific names
> using inline functions.
> 
> I find the x86 way more self documenting, and being in C prevents errors
> around the number of arguments. It also allows for better in-lining and
> exposes to gcc the actual clobbers, which might allow it to avoid saving
> r4 on the stack at all etc.

Considering that we cannot do the same thing that we do on x86 (see this
thread http://marc.info/?l=linux-kernel&m=133052035426427&w=2), I
decided to go for the assembly implementation because it is much shorter
and easier to understand (for me at least, being just 3 lines of code in
the generic case and just one macro) and this way we can exploit the
code generated by gcc to put the arguments in the right registers.

Also I like the fact that it is the same strategy used by libc to issue
syscalls.

As you can see it results in 3 lines of code for all the hypercalls
except the ones that might take more than 4 arguments, that right now is
just privcmd.



> > Should this comment be by 'privcmd_call'?
> 
> When we add a 5 argument hypercall I suppose we'll see the required
> push/pop of r4 added to this macro too.

For performance and simplicity I would add a second macro that push/pop
r4, only required for hypercalls with more than 4 arguments.


> > > +#define HYPERCALL(hypercall)			\
> > > +ENTRY(HYPERVISOR_##hypercall)			\
> > > +	mov r12, #__HYPERVISOR_##hypercall;	\
> > > +	xen_hvc;							\
> > > +	mov pc, lr;							\
> > > +ENDPROC(HYPERVISOR_##hypercall)
> > > +
> > > +                .text
> > > +
> > > +HYPERCALL(xen_version);
> > > +HYPERCALL(console_io);
> > > +HYPERCALL(grant_table_op);
> > > +HYPERCALL(sched_op);
> > > +HYPERCALL(event_channel_op);
> > > +HYPERCALL(hvm_op);
> > > +HYPERCALL(memory_op);
> > > +HYPERCALL(physdev_op);
> > > +
> > > +ENTRY(privcmd_call)
> > > +	stmdb	sp!, {r4}
> > > +	mov r12, r0
> > > +	mov r0, r1
> > > +	mov r1, r2
> > > +	mov r2, r3
> > > +	ldr r3, [sp, #8]
> > > +	ldr r4, [sp, #4]
> > > +	xen_hvc
> > > +	pop {r4}
> 
> Why not ldmdb for symmetry?

Yep, I can do that.
Ian Campbell July 27, 2012, 1:18 p.m. UTC | #10
On Fri, 2012-07-27 at 14:02 +0100, Stefano Stabellini wrote:
> On Fri, 27 Jul 2012, Ian Campbell wrote:
> > On Thu, 2012-07-26 at 17:33 +0100, Konrad Rzeszutek Wilk wrote:
> > > On Thu, Jul 26, 2012 at 04:33:44PM +0100, Stefano Stabellini wrote:
> > > > Use r12 to pass the hypercall number to the hypervisor.
> > > > 
> > > > We need a register to pass the hypercall number because we might not
> > > > know it at compile time and HVC only takes an immediate argument.
> > > > 
> > > > Among the available registers r12 seems to be the best choice because it
> > > > is defined as "intra-procedure call scratch register".
> > > > 
> > > > Use the ISS to pass an hypervisor specific tag.
> > > > 
> > > > Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
> > > > ---
> > > >  arch/arm/include/asm/xen/hypercall.h |   50 ++++++++++++++++++++++++++
> > > >  arch/arm/xen/Makefile                |    2 +-
> > > >  arch/arm/xen/hypercall.S             |   65 ++++++++++++++++++++++++++++++++++
> > > >  3 files changed, 116 insertions(+), 1 deletions(-)
> > > >  create mode 100644 arch/arm/include/asm/xen/hypercall.h
> > > >  create mode 100644 arch/arm/xen/hypercall.S
> > > > 
> > > > diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
> > > > new file mode 100644
> > > > index 0000000..4ac0624
> > > > --- /dev/null
> > > > +++ b/arch/arm/include/asm/xen/hypercall.h
> > > > @@ -0,0 +1,50 @@
> > > > +/******************************************************************************
> > > > + * hypercall.h
> > > > + *
> > > > + * Linux-specific hypervisor handling.
> > > > + *
> > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > > + * modify it under the terms of the GNU General Public License version 2
> > > > + * as published by the Free Software Foundation; or, when distributed
> > > > + * separately from the Linux kernel or incorporated into other
> > > > + * software packages, subject to the following license:
> > > > + *
> > > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > > + * of this source file (the "Software"), to deal in the Software without
> > > > + * restriction, including without limitation the rights to use, copy, modify,
> > > > + * merge, publish, distribute, sublicense, and/or sell copies of the Software,
> > > > + * and to permit persons to whom the Software is furnished to do so, subject to
> > > > + * the following conditions:
> > > > + *
> > > > + * The above copyright notice and this permission notice shall be included in
> > > > + * all copies or substantial portions of the Software.
> > > > + *
> > > > + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> > > > + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> > > > + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
> > > > + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> > > > + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> > > > + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
> > > > + * IN THE SOFTWARE.
> > > > + */
> > > > +
> > > > +#ifndef _ASM_ARM_XEN_HYPERCALL_H
> > > > +#define _ASM_ARM_XEN_HYPERCALL_H
> > > > +
> > > > +#include <xen/interface/xen.h>
> > > > +
> > > > +long privcmd_call(unsigned call, unsigned long a1,
> > > > +		unsigned long a2, unsigned long a3,
> > > > +		unsigned long a4, unsigned long a5);
> > > > +int HYPERVISOR_xen_version(int cmd, void *arg);
> > > > +int HYPERVISOR_console_io(int cmd, int count, char *str);
> > > > +int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
> > > > +int HYPERVISOR_sched_op(int cmd, void *arg);
> > > > +int HYPERVISOR_event_channel_op(int cmd, void *arg);
> > > > +unsigned long HYPERVISOR_hvm_op(int op, void *arg);
> > > > +int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
> > > > +int HYPERVISOR_physdev_op(int cmd, void *arg);
> > > > +
> > > > +#endif /* _ASM_ARM_XEN_HYPERCALL_H */
> > > > diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
> > > > index 0bad594..b9d6acc 100644
> > > > --- a/arch/arm/xen/Makefile
> > > > +++ b/arch/arm/xen/Makefile
> > > > @@ -1 +1 @@
> > > > -obj-y		:= enlighten.o
> > > > +obj-y		:= enlighten.o hypercall.o
> > > > diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
> > > > new file mode 100644
> > > > index 0000000..038cc5b
> > > > --- /dev/null
> > > > +++ b/arch/arm/xen/hypercall.S
> > > > @@ -0,0 +1,65 @@
> > > > +/******************************************************************************
> > > > + * hypercall.S
> > > > + *
> > > > + * Xen hypercall wrappers
> > > > + *
> > > > + * The Xen hypercall calling convention is very similar to the ARM
> > > > + * procedure calling convention: the first paramter is passed in r0, the
> > > > + * second in r1, the third in r2 and the third in r3. Considering that
> > > 
> > > I think you meant 'and the fourth in r3'.
> > > 
> > > So where does the similarity end?  Just in that we use r12?
> > 
> > The standard ARM function calling convention is arguments 1-4 on r0-r3
> > and arguments 5+ on the stack. r12 is a scratch register which can be
> > clobbered by the *linker* on subroutine call (r12 is also called "ip"
> > the intra-procedure call scratch register).
> > 
> > The hypervisor doesn't want to be accessing hypercall arguments off the
> > guest stack, for obvious reasons, so we use r4 for the fifth argument
> > (and if we even implemented 6 argument hypercalls we'd use r5, etc).
> > There is no equivalent to the hypercall number in the procedure calling
> > convention so we picked r12 because it is up and out of the way and is
> > otherwise a scratch register. Obviously that you must not make a
> > procedure call between setting the hypercall number in r12 and calling
> > the hvc instruction.
> > 
> > > 
> > > > + * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
> > > > + * in r4, differently from the procedure calling convention of using the
> > > 
> > > > + * stack for that case.
> > > > + *
> > > > + * The hypercall number is passed in r12.
> > > > + *
> > > > + * The return value is in r0.
> > > > + *
> > > > + * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
> > > > + * hypercall tag.
> > > > + *
> > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > + */
> > > > +
> > > > +#include <linux/linkage.h>
> > > > +#include <asm/assembler.h>
> > > > +#include <xen/interface/xen.h>
> > > > +
> > > > +
> > > > +/* HVC 0xEA1 */
> > > > +#ifdef CONFIG_THUMB2_KERNEL
> > > > +#define xen_hvc .word 0xf7e08ea1
> > > > +#else
> > > > +#define xen_hvc .word 0xe140ea71
> > > > +#endif
> > > > +
> > > > +/* We need to save and restore r4, because Xen clobbers it. */
> > > 
> > > Hmm, the comment says r4, but right below I see r12?
> > 
> > The ARM procedure calling convention allows a subroutine to clobber
> > r1..r3 (r0 is the return value) but not r4 which must be preserved. But
> > the hypervisor ABI clobbers all argument registers so the caller has to
> > specially preserve r4 in this context whenever there is a 5 argument
> > hypercall.
> > 
> > I presume that none of the hypercalls defined below have 5 arguments and
> > therefore we don't need to preserve r4 except in the generic
> > privcmd_call function. 
> > 
> > To be honest I prefer the style which we use on x86 which is to define
> > hypercall{0,1,2,3,4,5} macros and to wrap those with the specific names
> > using inline functions.
> > 
> > I find the x86 way more self documenting, and being in C prevents errors
> > around the number of arguments. It also allows for better in-lining and
> > exposes to gcc the actual clobbers, which might allow it to avoid saving
> > r4 on the stack at all etc.
> 
> Considering that we cannot do the same thing that we do on x86 (see this
> thread http://marc.info/?l=linux-kernel&m=133052035426427&w=2),

I'd forgotten all about this arm-gcc braindamage.

>  I
> decided to go for the assembly implementation because it is much shorter
> and easier to understand (for me at least, being just 3 lines of code in
> the generic case and just one macro) and this way we can exploit the
> code generated by gcc to put the arguments in the right registers.
> 
> Also I like the fact that it is the same strategy used by libc to issue
> syscalls.

Fair enough.

> As you can see it results in 3 lines of code for all the hypercalls
> except the ones that might take more than 4 arguments, that right now is
> just privcmd.
> 
> 
> 
> > > Should this comment be by 'privcmd_call'?
> > 
> > When we add a 5 argument hypercall I suppose we'll see the required
> > push/pop of r4 added to this macro too.
> 
> For performance and simplicity I would add a second macro that push/pop
> r4, only required for hypercalls with more than 4 arguments.

For clarity / documentation purposes it might actually be worthwhile to
define all of HYPERCALL{0,1,2,3,4} even if the {0,1,2,3} cases are all
just:
        #define HYPERCALL0(x) HYPERCALL_SIMPLE(x)

> > > > +#define HYPERCALL(hypercall)			\
> > > > +ENTRY(HYPERVISOR_##hypercall)			\
> > > > +	mov r12, #__HYPERVISOR_##hypercall;	\
> > > > +	xen_hvc;							\
> > > > +	mov pc, lr;							\
> > > > +ENDPROC(HYPERVISOR_##hypercall)
> > > > +
> > > > +                .text
> > > > +
> > > > +HYPERCALL(xen_version);
> > > > +HYPERCALL(console_io);
> > > > +HYPERCALL(grant_table_op);
> > > > +HYPERCALL(sched_op);
> > > > +HYPERCALL(event_channel_op);
> > > > +HYPERCALL(hvm_op);
> > > > +HYPERCALL(memory_op);
> > > > +HYPERCALL(physdev_op);
> > > > +
> > > > +ENTRY(privcmd_call)
> > > > +	stmdb	sp!, {r4}
> > > > +	mov r12, r0
> > > > +	mov r0, r1
> > > > +	mov r1, r2
> > > > +	mov r2, r3
> > > > +	ldr r3, [sp, #8]
> > > > +	ldr r4, [sp, #4]
> > > > +	xen_hvc
> > > > +	pop {r4}
> > 
> > Why not ldmdb for symmetry?
> 
> Yep, I can do that.
Stefano Stabellini July 27, 2012, 1:41 p.m. UTC | #11
On Fri, 27 Jul 2012, Ian Campbell wrote:
> > > > Should this comment be by 'privcmd_call'?
> > > 
> > > When we add a 5 argument hypercall I suppose we'll see the required
> > > push/pop of r4 added to this macro too.
> > 
> > For performance and simplicity I would add a second macro that push/pop
> > r4, only required for hypercalls with more than 4 arguments.
> 
> For clarity / documentation purposes it might actually be worthwhile to
> define all of HYPERCALL{0,1,2,3,4} even if the {0,1,2,3} cases are all
> just:
>         #define HYPERCALL0(x) HYPERCALL_SIMPLE(x)

I agree

> > > > > +#define HYPERCALL(hypercall)			\
> > > > > +ENTRY(HYPERVISOR_##hypercall)			\
> > > > > +	mov r12, #__HYPERVISOR_##hypercall;	\
> > > > > +	xen_hvc;							\
> > > > > +	mov pc, lr;							\
> > > > > +ENDPROC(HYPERVISOR_##hypercall)
> > > > > +
> > > > > +                .text
> > > > > +
> > > > > +HYPERCALL(xen_version);
> > > > > +HYPERCALL(console_io);
> > > > > +HYPERCALL(grant_table_op);
> > > > > +HYPERCALL(sched_op);
> > > > > +HYPERCALL(event_channel_op);
> > > > > +HYPERCALL(hvm_op);
> > > > > +HYPERCALL(memory_op);
> > > > > +HYPERCALL(physdev_op);
> > > > > +
> > > > > +ENTRY(privcmd_call)
> > > > > +	stmdb	sp!, {r4}
> > > > > +	mov r12, r0
> > > > > +	mov r0, r1
> > > > > +	mov r1, r2
> > > > > +	mov r2, r3
> > > > > +	ldr r3, [sp, #8]
> > > > > +	ldr r4, [sp, #4]
> > > > > +	xen_hvc
> > > > > +	pop {r4}
> > > 
> > > Why not ldmdb for symmetry?
> > 
> > Yep, I can do that.

Actually it is just ldm or ldmia
Stefano Stabellini July 27, 2012, 1:57 p.m. UTC | #12
On Fri, 27 Jul 2012, Christopher Covington wrote:
> On 07/27/2012 05:19 AM, Ian Campbell wrote:
> > On Thu, 2012-07-26 at 20:19 +0100, Christopher Covington wrote:
> >> Hi Stefano,
> >>
> >> On 07/26/2012 11:33 AM, Stefano Stabellini wrote:
> >>> Use r12 to pass the hypercall number to the hypervisor.
> >>>
> >>> We need a register to pass the hypercall number because we might not
> >>> know it at compile time and HVC only takes an immediate argument.
> >>
> >> You're not going to JIT assemble the appropriate HVC instruction? Darn.
> > 
> > ;-)
> > 

I admit having spent few hours thinking about how to implement a
self-modifying function able to change the ISS at run time. Fortunately
few hours later I was struck by common sense and I decided to follow a
different direction ;-)


> > The maximum currently defined hypercall number is 55, although there are
> > some small gaps so there's actually more like 45 in total.
> > 
> >>  It seems like it'd be
> >> reasonable to take the approach that seems to be favored for MRC/MCR
> >> instructions, using a function containing switch statement that chooses
> >> between several inline assembly instructions based off an enum passed to
> >> the function. See for example arch_timer_reg_read in
> >> arch/arm/kernel/arch_timer.c.
> > 
> > I don't think it is feasible with this number of hypercalls, even
> > accepting that in many cases the number will be a constant so gcc can
> > likely optimise almost all of it away.
> > 
> > Is there something wrong with the r12 based approach?
> 
> Only that you're defining a custom interface for something that there is
> a potentially more standard interface for. I just wanted to double check
> that all the ways of using the potentially more standard interface had
> been explored and found to be unreasonable.

Yep, thanks for helping us reviewing the code.
Russell King - ARM Linux July 27, 2012, 2:21 p.m. UTC | #13
On Fri, Jul 27, 2012 at 02:02:18PM +0100, Stefano Stabellini wrote:
> > > > +/******************************************************************************
> > > > + * hypercall.h
> > > > + *
> > > > + * Linux-specific hypervisor handling.
> > > > + *
> > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > + *
> > > > + * This program is free software; you can redistribute it and/or
> > > > + * modify it under the terms of the GNU General Public License version 2
> > > > + * as published by the Free Software Foundation; or, when distributed
> > > > + * separately from the Linux kernel or incorporated into other
> > > > + * software packages, subject to the following license:
> > > > + *
> > > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > > + * of this source file (the "Software"), to deal in the Software without

Erm, is that an additional restriction on the GPL which prevents me from
shipping this code on a CD and charging for the act of creating the CD
and shipping it?  That would technically make the above statement
incompatible with the GPL.
Stefano Stabellini July 27, 2012, 2:36 p.m. UTC | #14
On Fri, 27 Jul 2012, Russell King - ARM Linux wrote:
> On Fri, Jul 27, 2012 at 02:02:18PM +0100, Stefano Stabellini wrote:
> > > > > +/******************************************************************************
> > > > > + * hypercall.h
> > > > > + *
> > > > > + * Linux-specific hypervisor handling.
> > > > > + *
> > > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > > + *
> > > > > + * This program is free software; you can redistribute it and/or
> > > > > + * modify it under the terms of the GNU General Public License version 2
> > > > > + * as published by the Free Software Foundation; or, when distributed
> > > > > + * separately from the Linux kernel or incorporated into other
> > > > > + * software packages, subject to the following license:
> > > > > + *
> > > > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > > > + * of this source file (the "Software"), to deal in the Software without
> 
> Erm, is that an additional restriction on the GPL which prevents me from
> shipping this code on a CD and charging for the act of creating the CD
> and shipping it?  That would technically make the above statement
> incompatible with the GPL.

IMNAL but this is just an alternative, less strict, MIT license for this
file, same as the x86 counterpart
(arch/x86/include/asm/xen/hypercall.h). The intent is to allow other
operating systems, the BSDs for example, to be able to use it if they
want to.
Actually, given that the ARM implementation is not inline, I should
remember to add this copyright header to the assembly source file too.
Ian Campbell July 27, 2012, 2:39 p.m. UTC | #15
On Fri, 2012-07-27 at 15:21 +0100, Russell King - ARM Linux wrote:
> On Fri, Jul 27, 2012 at 02:02:18PM +0100, Stefano Stabellini wrote:
> > > > > +/******************************************************************************
> > > > > + * hypercall.h
> > > > > + *
> > > > > + * Linux-specific hypervisor handling.
> > > > > + *
> > > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > > + *
> > > > > + * This program is free software; you can redistribute it and/or
> > > > > + * modify it under the terms of the GNU General Public License version 2
> > > > > + * as published by the Free Software Foundation; or, when distributed
> > > > > + * separately from the Linux kernel or incorporated into other
> > > > > + * software packages, subject to the following license:
> > > > > + *
> > > > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > > > + * of this source file (the "Software"), to deal in the Software without
> 
> Erm, is that an additional restriction on the GPL which prevents me from
> shipping this code on a CD and charging for the act of creating the CD
> and shipping it?  That would technically make the above statement
> incompatible with the GPL.

There's an "or" in there.

The non-GPL alternative license is the standard one applied by upstream
Xen to the interface headers:
        http://xenbits.xen.org/hg/xen-unstable.hg/file/tip/xen/include/public/COPYING

It's the X11/MIT license IIRC, which the FSF say is GPL compatible.
http://www.gnu.org/licenses/license-list.html#X11License

The same license is used a few other places in the kernel, e.g. the DRM
code.

Ian.
Russell King - ARM Linux July 27, 2012, 2:59 p.m. UTC | #16
On Fri, Jul 27, 2012 at 03:39:31PM +0100, Ian Campbell wrote:
> On Fri, 2012-07-27 at 15:21 +0100, Russell King - ARM Linux wrote:
> > On Fri, Jul 27, 2012 at 02:02:18PM +0100, Stefano Stabellini wrote:
> > > > > > +/******************************************************************************
> > > > > > + * hypercall.h
> > > > > > + *
> > > > > > + * Linux-specific hypervisor handling.
> > > > > > + *
> > > > > > + * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
> > > > > > + *
> > > > > > + * This program is free software; you can redistribute it and/or
> > > > > > + * modify it under the terms of the GNU General Public License version 2
> > > > > > + * as published by the Free Software Foundation; or, when distributed
> > > > > > + * separately from the Linux kernel or incorporated into other
> > > > > > + * software packages, subject to the following license:
> > > > > > + *
> > > > > > + * Permission is hereby granted, free of charge, to any person obtaining a copy
> > > > > > + * of this source file (the "Software"), to deal in the Software without
> > 
> > Erm, is that an additional restriction on the GPL which prevents me from
> > shipping this code on a CD and charging for the act of creating the CD
> > and shipping it?  That would technically make the above statement
> > incompatible with the GPL.
> 
> There's an "or" in there.
> 
> The non-GPL alternative license is the standard one applied by upstream
> Xen to the interface headers:
>         http://xenbits.xen.org/hg/xen-unstable.hg/file/tip/xen/include/public/COPYING
> 
> It's the X11/MIT license IIRC, which the FSF say is GPL compatible.
> http://www.gnu.org/licenses/license-list.html#X11License
> 
> The same license is used a few other places in the kernel, e.g. the DRM
> code.

Ok, but be aware that you won't be able to take code from the Linux
kernel and place it in a file marked with that license header (because
the code authors haven't given permission for it to be placed under any
other license other than GPLv2.)
diff mbox

Patch

diff --git a/arch/arm/include/asm/xen/hypercall.h b/arch/arm/include/asm/xen/hypercall.h
new file mode 100644
index 0000000..4ac0624
--- /dev/null
+++ b/arch/arm/include/asm/xen/hypercall.h
@@ -0,0 +1,50 @@ 
+/******************************************************************************
+ * hypercall.h
+ *
+ * Linux-specific hypervisor handling.
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy, modify,
+ * merge, publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef _ASM_ARM_XEN_HYPERCALL_H
+#define _ASM_ARM_XEN_HYPERCALL_H
+
+#include <xen/interface/xen.h>
+
+long privcmd_call(unsigned call, unsigned long a1,
+		unsigned long a2, unsigned long a3,
+		unsigned long a4, unsigned long a5);
+int HYPERVISOR_xen_version(int cmd, void *arg);
+int HYPERVISOR_console_io(int cmd, int count, char *str);
+int HYPERVISOR_grant_table_op(unsigned int cmd, void *uop, unsigned int count);
+int HYPERVISOR_sched_op(int cmd, void *arg);
+int HYPERVISOR_event_channel_op(int cmd, void *arg);
+unsigned long HYPERVISOR_hvm_op(int op, void *arg);
+int HYPERVISOR_memory_op(unsigned int cmd, void *arg);
+int HYPERVISOR_physdev_op(int cmd, void *arg);
+
+#endif /* _ASM_ARM_XEN_HYPERCALL_H */
diff --git a/arch/arm/xen/Makefile b/arch/arm/xen/Makefile
index 0bad594..b9d6acc 100644
--- a/arch/arm/xen/Makefile
+++ b/arch/arm/xen/Makefile
@@ -1 +1 @@ 
-obj-y		:= enlighten.o
+obj-y		:= enlighten.o hypercall.o
diff --git a/arch/arm/xen/hypercall.S b/arch/arm/xen/hypercall.S
new file mode 100644
index 0000000..038cc5b
--- /dev/null
+++ b/arch/arm/xen/hypercall.S
@@ -0,0 +1,65 @@ 
+/******************************************************************************
+ * hypercall.S
+ *
+ * Xen hypercall wrappers
+ *
+ * The Xen hypercall calling convention is very similar to the ARM
+ * procedure calling convention: the first paramter is passed in r0, the
+ * second in r1, the third in r2 and the third in r3. Considering that
+ * Xen hypercalls have 5 arguments at most, the fifth paramter is passed
+ * in r4, differently from the procedure calling convention of using the
+ * stack for that case.
+ *
+ * The hypercall number is passed in r12.
+ *
+ * The return value is in r0.
+ *
+ * The hvc ISS is required to be 0xEA1, that is the Xen specific ARM
+ * hypercall tag.
+ *
+ * Stefano Stabellini <stefano.stabellini@eu.citrix.com>, Citrix, 2012
+ */
+
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <xen/interface/xen.h>
+
+
+/* HVC 0xEA1 */
+#ifdef CONFIG_THUMB2_KERNEL
+#define xen_hvc .word 0xf7e08ea1
+#else
+#define xen_hvc .word 0xe140ea71
+#endif
+
+/* We need to save and restore r4, because Xen clobbers it. */
+#define HYPERCALL(hypercall)			\
+ENTRY(HYPERVISOR_##hypercall)			\
+	mov r12, #__HYPERVISOR_##hypercall;	\
+	xen_hvc;							\
+	mov pc, lr;							\
+ENDPROC(HYPERVISOR_##hypercall)
+
+                .text
+
+HYPERCALL(xen_version);
+HYPERCALL(console_io);
+HYPERCALL(grant_table_op);
+HYPERCALL(sched_op);
+HYPERCALL(event_channel_op);
+HYPERCALL(hvm_op);
+HYPERCALL(memory_op);
+HYPERCALL(physdev_op);
+
+ENTRY(privcmd_call)
+	stmdb	sp!, {r4}
+	mov r12, r0
+	mov r0, r1
+	mov r1, r2
+	mov r2, r3
+	ldr r3, [sp, #8]
+	ldr r4, [sp, #4]
+	xen_hvc
+	pop {r4}
+	mov pc, lr
+ENDPROC(privcmd_call);