RE: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
> -Original Message- > From: Vitaly Kuznetsov [mailto:vkuzn...@redhat.com] > Sent: Friday, April 7, 2017 04:27 > To: de...@linuxdriverproject.org; x...@kernel.org > Cc: linux-ker...@vger.kernel.org; KY Srinivasan ; > Haiyang Zhang ; Stephen Hemminger > ; Thomas Gleixner ; Ingo > Molnar ; H. Peter Anvin ; Steven > Rostedt ; Jork Loeser > Subject: [PATCH 2/7] x86/hyper-v: fast hypercall implementation > diff --git a/arch/x86/include/asm/mshyperv.h > b/arch/x86/include/asm/mshyperv.h index 331e834..9a5f58b 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -216,6 +216,43 @@ static inline u64 hv_do_hypercall(u64 control, void > *input, void *output) #endif /* !x86_64 */ } > > +/* Fast hypercall with 8 bytes of input and no output */ static inline > +u64 hv_do_fast_hypercall8(u16 code, u64 input1) { > + union hv_hypercall_input control = {0}; > + > + control.code = code; > + control.fast = 1; > +#ifdef CONFIG_X86_64 > + { > + u64 hv_status; > + > + __asm__ __volatile__("call *%3" > + : "=a" (hv_status) > + : "c" (control.as_uint64), "d" (input1), > +"m" (hv_hypercall_pg) > + : "cc", "r8", "%r9", "%r10", "%r11"); > + return hv_status; Clobber memory (are there such fast hypercalls)? > + } > +#else > + { > + u32 hv_status_hi, hv_status_lo; > + > + __asm__ __volatile__ ("call *%6" > + : "=d"(hv_status_hi), > + "=a"(hv_status_lo) : > + "d" (control.as_uint32_hi), > + "a" (control.as_uint32_lo), > + "c" ((u32)input1), > + "b" ((u32)(input1 >> 32)), > + "m" (hv_hypercall_pg) > + : "cc"); > + > + return hv_status_lo | ((u64)hv_status_hi << 32); > + } > +#endif Please clobber ECX, EDI and ESI for x86. Clobber memory as well? ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
RE: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
> -Original Message- > From: Vitaly Kuznetsov [mailto:vkuzn...@redhat.com] > Sent: Friday, April 7, 2017 4:27 AM > To: de...@linuxdriverproject.org; x...@kernel.org > Cc: linux-ker...@vger.kernel.org; KY Srinivasan ; > Haiyang Zhang ; Stephen Hemminger > ; Thomas Gleixner ; Ingo > Molnar ; H. Peter Anvin ; Steven > Rostedt ; Jork Loeser > Subject: [PATCH 2/7] x86/hyper-v: fast hypercall implementation > > Hyper-V supports 'fast' hypercalls when all parameters are passed through > registers. Implement an inline version of a simpliest of these calls: > hypercall with one 8-byte input and no output. > > Proper hypercall input interface (struct hv_hypercall_input) definition is > added as well. > > Signed-off-by: Vitaly Kuznetsov > --- > arch/x86/include/asm/mshyperv.h| 37 > + > arch/x86/include/uapi/asm/hyperv.h | 19 +++ > 2 files changed, 56 insertions(+) > > diff --git a/arch/x86/include/asm/mshyperv.h > b/arch/x86/include/asm/mshyperv.h > index 331e834..9a5f58b 100644 > --- a/arch/x86/include/asm/mshyperv.h > +++ b/arch/x86/include/asm/mshyperv.h > @@ -216,6 +216,43 @@ static inline u64 hv_do_hypercall(u64 control, void > *input, void *output) > #endif /* !x86_64 */ > } > > +/* Fast hypercall with 8 bytes of input and no output */ > +static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) > +{ > + union hv_hypercall_input control = {0}; Defining the hyper-call arguments on the stack can be problematic if CONFIG_VMAP_STACK is defined - since we are passing the guest physical address to the hypervisor, we cannot have the arguments straddle a page boundary. We have dealt with this issue currently by making sure the arguments are never on the stack via different means. Perhaps, we can allocate memory on a per-cpu basis that can be used for this purpose. In fact, this is what I have done for the hv_post_message hypercall. We can just rename that page and use it in all hypercalls - we can just allocate two pages on a per-CPU basis for this purpose (for input and output parameters). > + > + control.code = code; > + control.fast = 1; > +#ifdef CONFIG_X86_64 > + { > + u64 hv_status; > + > + __asm__ __volatile__("call *%3" > + : "=a" (hv_status) > + : "c" (control.as_uint64), "d" (input1), > +"m" (hv_hypercall_pg) > + : "cc", "r8", "%r9", "%r10", "%r11"); > + return hv_status; > + } > +#else > + { > + u32 hv_status_hi, hv_status_lo; > + > + __asm__ __volatile__ ("call *%6" > + : "=d"(hv_status_hi), > + "=a"(hv_status_lo) : > + "d" (control.as_uint32_hi), > + "a" (control.as_uint32_lo), > + "c" ((u32)input1), > + "b" ((u32)(input1 >> 32)), > + "m" (hv_hypercall_pg) > + : "cc"); > + > + return hv_status_lo | ((u64)hv_status_hi << 32); > + } > +#endif > +} > + > void hyperv_init(void); > void hyperv_report_panic(struct pt_regs *regs); > bool hv_is_hypercall_page_setup(void); > diff --git a/arch/x86/include/uapi/asm/hyperv.h > b/arch/x86/include/uapi/asm/hyperv.h > index 432df4b..c87e900 100644 > --- a/arch/x86/include/uapi/asm/hyperv.h > +++ b/arch/x86/include/uapi/asm/hyperv.h > @@ -256,6 +256,25 @@ > #define HV_PROCESSOR_POWER_STATE_C2 2 > #define HV_PROCESSOR_POWER_STATE_C3 3 > > +/* Hypercall interface */ > +union hv_hypercall_input { > + u64 as_uint64; > + struct { > + __u32 as_uint32_lo; > + __u32 as_uint32_hi; > + }; > + struct { > + __u64 code:16; > + __u64 fast:1; > + __u64 varhead_size:10; > + __u64 reserved1:5; > + __u64 rep_count:12; > + __u64 reserved2:4; > + __u64 rep_start:12; > + __u64 reserved3:4; > + }; > +}; > + > /* hypercall status code */ > #define HV_STATUS_SUCCESS0 > #define HV_STATUS_INVALID_HYPERCALL_CODE 2 > -- > 2.9.3 ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
KY Srinivasan writes: >> -Original Message- >> From: Vitaly Kuznetsov [mailto:vkuzn...@redhat.com] >> Sent: Friday, April 7, 2017 4:27 AM >> To: de...@linuxdriverproject.org; x...@kernel.org >> Cc: linux-ker...@vger.kernel.org; KY Srinivasan ; >> Haiyang Zhang ; Stephen Hemminger >> ; Thomas Gleixner ; Ingo >> Molnar ; H. Peter Anvin ; Steven >> Rostedt ; Jork Loeser >> Subject: [PATCH 2/7] x86/hyper-v: fast hypercall implementation >> >> Hyper-V supports 'fast' hypercalls when all parameters are passed through >> registers. Implement an inline version of a simpliest of these calls: >> hypercall with one 8-byte input and no output. >> >> Proper hypercall input interface (struct hv_hypercall_input) definition is >> added as well. >> >> Signed-off-by: Vitaly Kuznetsov >> --- >> arch/x86/include/asm/mshyperv.h| 37 >> + >> arch/x86/include/uapi/asm/hyperv.h | 19 +++ >> 2 files changed, 56 insertions(+) >> >> diff --git a/arch/x86/include/asm/mshyperv.h >> b/arch/x86/include/asm/mshyperv.h >> index 331e834..9a5f58b 100644 >> --- a/arch/x86/include/asm/mshyperv.h >> +++ b/arch/x86/include/asm/mshyperv.h >> @@ -216,6 +216,43 @@ static inline u64 hv_do_hypercall(u64 control, void >> *input, void *output) >> #endif /* !x86_64 */ >> } >> >> +/* Fast hypercall with 8 bytes of input and no output */ >> +static inline u64 hv_do_fast_hypercall8(u16 code, u64 input1) >> +{ >> +union hv_hypercall_input control = {0}; > > Defining the hyper-call arguments on the stack can be problematic > if CONFIG_VMAP_STACK is defined - since we are passing the guest > physical address to the hypervisor, we cannot have the arguments > straddle a page boundary. > We have dealt with this issue currently by making sure the arguments are > never on the stack via different means. Perhaps, we can allocate memory > on a per-cpu basis that can be used for this purpose. In fact, this is what I > have done > for the hv_post_message hypercall. We can just rename that page and use it > in all > hypercalls - we can just allocate two pages on a per-CPU basis for this > purpose > (for input and output parameters). This is fast hypercall and not the normal one - we pass control to register so we're fine here (and I'd actually expect the compiler to put it to the propper register in the first place. >> + >> +control.code = code; >> +control.fast = 1; >> +#ifdef CONFIG_X86_64 >> +{ >> +u64 hv_status; >> + >> +__asm__ __volatile__("call *%3" >> + : "=a" (hv_status) >> + : "c" (control.as_uint64), "d" (input1), >> + "m" (hv_hypercall_pg) >> + : "cc", "r8", "%r9", "%r10", "%r11"); >> +return hv_status; >> +} >> +#else >> +{ >> +u32 hv_status_hi, hv_status_lo; >> + >> +__asm__ __volatile__ ("call *%6" >> + : "=d"(hv_status_hi), >> +"=a"(hv_status_lo) : >> +"d" (control.as_uint32_hi), >> +"a" (control.as_uint32_lo), >> +"c" ((u32)input1), >> +"b" ((u32)(input1 >> 32)), >> +"m" (hv_hypercall_pg) >> + : "cc"); >> + >> +return hv_status_lo | ((u64)hv_status_hi << 32); >> +} >> +#endif >> +} >> + >> void hyperv_init(void); >> void hyperv_report_panic(struct pt_regs *regs); >> bool hv_is_hypercall_page_setup(void); >> diff --git a/arch/x86/include/uapi/asm/hyperv.h >> b/arch/x86/include/uapi/asm/hyperv.h >> index 432df4b..c87e900 100644 >> --- a/arch/x86/include/uapi/asm/hyperv.h >> +++ b/arch/x86/include/uapi/asm/hyperv.h >> @@ -256,6 +256,25 @@ >> #define HV_PROCESSOR_POWER_STATE_C2 2 >> #define HV_PROCESSOR_POWER_STATE_C3 3 >> >> +/* Hypercall interface */ >> +union hv_hypercall_input { >> +u64 as_uint64; >> +struct { >> +__u32 as_uint32_lo; >> +__u32 as_uint32_hi; >> +}; >> +struct { >> +__u64 code:16; >> +__u64 fast:1; >> +__u64 varhead_size:10; >> +__u64 reserved1:5; >> +__u64 rep_count:12; >> +__u64 reserved2:4; >> +__u64 rep_start:12; >> +__u64 reserved3:4; >> +}; >> +}; >> + >> /* hypercall status code */ >> #define HV_STATUS_SUCCESS 0 >> #define HV_STATUS_INVALID_HYPERCALL_CODE2 >> -- >> 2.9.3 -- Vitaly ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
Jork Loeser writes: >> -Original Message- >> From: Vitaly Kuznetsov [mailto:vkuzn...@redhat.com] >> Sent: Friday, April 7, 2017 04:27 >> To: de...@linuxdriverproject.org; x...@kernel.org >> Cc: linux-ker...@vger.kernel.org; KY Srinivasan ; >> Haiyang Zhang ; Stephen Hemminger >> ; Thomas Gleixner ; Ingo >> Molnar ; H. Peter Anvin ; Steven >> Rostedt ; Jork Loeser >> Subject: [PATCH 2/7] x86/hyper-v: fast hypercall implementation > >> diff --git a/arch/x86/include/asm/mshyperv.h >> b/arch/x86/include/asm/mshyperv.h index 331e834..9a5f58b 100644 >> --- a/arch/x86/include/asm/mshyperv.h >> +++ b/arch/x86/include/asm/mshyperv.h >> @@ -216,6 +216,43 @@ static inline u64 hv_do_hypercall(u64 control, void >> *input, void *output) #endif /* !x86_64 */ } >> >> +/* Fast hypercall with 8 bytes of input and no output */ static inline >> +u64 hv_do_fast_hypercall8(u16 code, u64 input1) { >> +union hv_hypercall_input control = {0}; >> + >> +control.code = code; >> +control.fast = 1; >> +#ifdef CONFIG_X86_64 >> +{ >> +u64 hv_status; >> + >> +__asm__ __volatile__("call *%3" >> + : "=a" (hv_status) >> + : "c" (control.as_uint64), "d" (input1), >> + "m" (hv_hypercall_pg) >> + : "cc", "r8", "%r9", "%r10", "%r11"); >> +return hv_status; > Clobber memory (are there such fast hypercalls)? > Hm, I was under an impression fast hypercalls have no output or put the output in XMM* registers and we don't use them for now. Why clobbering memory? >> +} >> +#else >> +{ >> +u32 hv_status_hi, hv_status_lo; >> + >> +__asm__ __volatile__ ("call *%6" >> + : "=d"(hv_status_hi), >> +"=a"(hv_status_lo) : >> +"d" (control.as_uint32_hi), >> +"a" (control.as_uint32_lo), >> +"c" ((u32)input1), >> +"b" ((u32)(input1 >> 32)), >> +"m" (hv_hypercall_pg) >> + : "cc"); >> + >> +return hv_status_lo | ((u64)hv_status_hi << 32); >> +} >> +#endif > Please clobber ECX, EDI and ESI for x86. Clobber memory as well? ECX is already in listed in inputs (lower part of input1) so it's automatically clobbered. I'll add EDI and ESI to clobbers here, thanks! -- Vitaly ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
Re: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
Vitaly Kuznetsov writes: > Jork Loeser writes: > [snip] > >>> + } >>> +#else >>> + { >>> + u32 hv_status_hi, hv_status_lo; >>> + >>> + __asm__ __volatile__ ("call *%6" >>> + : "=d"(hv_status_hi), >>> + "=a"(hv_status_lo) : >>> + "d" (control.as_uint32_hi), >>> + "a" (control.as_uint32_lo), >>> + "c" ((u32)input1), >>> + "b" ((u32)(input1 >> 32)), >>> + "m" (hv_hypercall_pg) >>> + : "cc"); >>> + >>> + return hv_status_lo | ((u64)hv_status_hi << 32); >>> + } >>> +#endif >> Please clobber ECX, EDI and ESI for x86. Clobber memory as well? > > ECX is already in listed in inputs (lower part of input1) so it's > automatically clobbered. I'll add EDI and ESI to clobbers here, thanks! Oh, I see what you mean - hypervisor is allowed to write to ecx too, we need to pass it with '+'. Will do, thanks! -- Vitaly ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel
RE: [PATCH 2/7] x86/hyper-v: fast hypercall implementation
> -Original Message- > From: Vitaly Kuznetsov [mailto:vkuzn...@redhat.com] > Vitaly Kuznetsov writes: > > > Jork Loeser writes: > > > > [snip] > > > > >>> + } > >>> +#else > >>> + { > >>> + u32 hv_status_hi, hv_status_lo; > >>> + > >>> + __asm__ __volatile__ ("call *%6" > >>> + : "=d"(hv_status_hi), > >>> + "=a"(hv_status_lo) : > >>> + "d" (control.as_uint32_hi), > >>> + "a" (control.as_uint32_lo), > >>> + "c" ((u32)input1), > >>> + "b" ((u32)(input1 >> 32)), > >>> + "m" (hv_hypercall_pg) > >>> + : "cc"); > >>> + > >>> + return hv_status_lo | ((u64)hv_status_hi << 32); > >>> + } > >>> +#endif > >> Please clobber ECX, EDI and ESI for x86. Clobber memory as well? > > > > ECX is already in listed in inputs (lower part of input1) so it's > > automatically clobbered. I'll add EDI and ESI to clobbers here, thanks! > > Oh, I see what you mean - hypervisor is allowed to write to ecx too, we need > to pass it with '+'. Will do, thanks! Yes, thank you Vitaly! As for memory clobber, we would want that if there were hypercalls that modify memory and can issued via the "fast" ABI. If there are not, we are fine. Regards, Jork ___ devel mailing list de...@linuxdriverproject.org http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel