|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: Xen 4.4 development update
On Thu, Aug 15, 2013 at 04:50:47PM -0400, Konrad Rzeszutek Wilk wrote:
> On Thu, Aug 15, 2013 at 04:24:20PM -0400, Eric Shelton wrote:
> > On Thu, Aug 15, 2013 at 10:12 AM, Konrad Rzeszutek Wilk
> > <konrad.wilk@xxxxxxxxxx> wrote:
> > > On Thu, Aug 15, 2013 at 01:32:12AM -0400, Eric Shelton wrote:
> > >
> > > First of, thank you for taking a stab at it and redoing it.
> >
> > Sure. The first releases of the patch were posted during a hectic
> > time in the release cycle. Three months later, I wanted to make sure
> > this had not gotten lost in the noise, and instead got wrapped up
> > while it was still fairly fresh for me.
> >
> > > Some general comments:
> > > - the #ifdef CONFIG_XEN is generaly frowend upon. If you need them they
> > > should
> > > be in header files. The exception is the CONFIG_X86 and
> > > CONFIG_X86_64. Now said that there are other instances of code where
> > > it is sprinkled with #ifdef CONFIG_ACPI .. #ifdef CONFIG_PCI, and so
> > > on. It would have been nice if all of that got moved to a header file
> > > but in reality that could make it just more confusing. Enough about
> > > that - what I want to say is that doing #idef CONFIG_XEN is something
> > > we have been trying the utmost to not put in generic code. The
> > > reasoning is that instead of using the API (so for example if we have
> > > an generic layer and then there are platform related drivers - we
> > > want to implement the stuff in the platform drivers - not add
> > > side-channels for a specific platform).
> >
> > OK. Hopefully the reorganization I suggest below will clear out most
> > or all of this.
> >
> > > - Is there any way to move the bulk of the hypercalls in the
> > > efi_runtime services. Meaning alter the efi_runtime services
> > > to do hypercalls instead of EFI calls? That way I would think most
> > > of the EFI general logic would be untouched? This is going back to
> > > the first comment - you would want to leave as much generic code
> > > untouched as possible. And implement the bulk of the code in the
> > > platform specific code.
> >
> > This sounds similar to Matthew Garrett's suggestion "to do this by
> > replacing efi_call_* I'm not quite sure how I would "alter the
> > efi_runtime services" to accomplish this - or at least not in some way
> > that is not worse than what is being done for things like
> > *_set_variable(). If you can more concretely show me how this might
> > be coded for one of the runtime service functions, I would be happy to
> > replicate that across the patch.
>
> Ha! I am just hand-waving right now :-)
>
> What I had in mind was that this:
>
> efi_phys.systab = (efi_system_table_t
> *)boot_params.efi_info.efi_systab;
>
> Is done, and we could implement some stub functions in the efi_systab
> that would convert the Microsoft stack passing to normal Linux
> and then do the hypercalls.
>
> It would be a bit of this:
>
> virt_efi_get_time -> calls efi_call_virt2 (efi_stub_32|64.S) ->
> assembler code Linux to EFI stacks, and calls in
> efi.systab->runtime->get_time
>
> The get_time would be our own little blob of code that alters the
> parameters from EFI stack to Linux and makes the hypercall (so probably
> in C). Then when the hypercall is done, it changes the stack back to EFI
> and returns.
>
> In other words we would implement an EFI runtime code that actually
> would do hypercalls.
>
> But from your analysis that does not solve the whole problem. Those
> efi_init* variants in some cases are unneccessary. Which brings another
> question - if we do barell throught them, what is the worst that will
> happen? Can the values returned be the same?
Right after I sent the email I thought about another option. Which is
the one I think Matthew was referring to. That is make efi_call*
function be more of a function pointer and the default one (compiled) is
the baremetal version. When Xen boots it over-writes it with its
specific. There is also some lookup to figure out which of the set_time,
get_time, etc calls are being called. This is all hand-waving and the
patch below has not even been compile tested.
From 197339fe9e4c95abe5b8948cf2bc3119c0ec87b5 Mon Sep 17 00:00:00 2001
From: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
Date: Fri, 16 Aug 2013 10:06:52 -0400
Subject: [PATCH] efi/xen: Use a function pointer for baremetal and Xen
specific
efi calls.
Signed-off-by: Konrad Rzeszutek Wilk <konrad.wilk@xxxxxxxxxx>
---
arch/x86/include/asm/efi.h | 43 +++++++++++++++++++++++++++++++------
arch/x86/platform/efi/efi_64.c | 11 ++++++++++
arch/x86/platform/efi/efi_stub_64.S | 28 ++++++++++++------------
arch/x86/xen/efi.c | 40 ++++++++++++++++++++++++++++++++++
arch/x86/xen/setup.c | 9 ++++++++
arch/x86/xen/xen-ops.h | 13 +++++++++++
6 files changed, 123 insertions(+), 21 deletions(-)
create mode 100644 arch/x86/xen/efi.c
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 0062a01..f234570 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -41,16 +41,45 @@ extern unsigned long asmlinkage efi_call_phys(void *, ...);
#define EFI_LOADER_SIGNATURE "EL64"
-extern u64 efi_call0(void *fp);
-extern u64 efi_call1(void *fp, u64 arg1);
-extern u64 efi_call2(void *fp, u64 arg1, u64 arg2);
-extern u64 efi_call3(void *fp, u64 arg1, u64 arg2, u64 arg3);
-extern u64 efi_call4(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
-extern u64 efi_call5(void *fp, u64 arg1, u64 arg2, u64 arg3,
+extern u64 native_efi_call0(void *fp);
+extern u64 native_efi_call1(void *fp, u64 arg1);
+extern u64 native_efi_call2(void *fp, u64 arg1, u64 arg2);
+extern u64 native_efi_call3(void *fp, u64 arg1, u64 arg2, u64 arg3);
+extern u64 native_efi_call4(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+extern u64 native_efi_call5(void *fp, u64 arg1, u64 arg2, u64 arg3,
u64 arg4, u64 arg5);
-extern u64 efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
+extern u64 native_efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
u64 arg4, u64 arg5, u64 arg6);
+#ifdef CONFIG_PARAVIRT
+extern u64 (*platform_efi_call0)(void *fp);
+extern u64 (*platform_efi_call1)(void *fp, u64 arg1);
+extern u64 (*platform_efi_call2)(void *fp, u64 arg1, u64 arg2);
+extern u64 (*platform_efi_call3)(void *fp, u64 arg1, u64 arg2, u64 arg3);
+extern u64 (*platform_efi_call4)(void *fp, u64 arg1, u64 arg2, u64 arg3, u64
arg4);
+extern u64 (*platform_efi_call5)(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5);
+extern u64 (*platform_efi_call6)(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5, u64 arg6);
+
+#define efi_call0(f) platform_efi_call0(f)
+#define efi_call1(f, a1) platform_efi_call1(f, a1)
+#define efi_call2(f, a1, a2) platform_efi_call2(f, a1, a2)
+#define efi_call3(f, a1, a2, a3) platform_efi_call3(f, a1, a2, a3)
+#define efi_call4(f, a1, a2, a3, a4) platform_efi_call4(f, a1, a2, a3, a4)
+#define efi_call5(f, a1, a2, a3, a4, a5) platform_efi_call5(f, a1, a2,
a3, a4, a5)
+#define efi_call6(f, a1, a2, a3, a4, a5, a6) platform_efi_call6(f, a1, a2,
a3, a4, a5, a6)
+#else
+#define efi_call0(f) native_efi_call0(f)
+#define efi_call1(f, a1) native_efi_call1(f, a1)
+#define efi_call2(f, a1, a2) native_efi_call2(f, a1, a2)
+#define efi_call3(f, a1, a2, a3) native_efi_call3(f, a1, a2, a3)
+#define efi_call4(f, a1, a2, a3, a4) native_efi_call4(f, a1, a2, a3, a4)
+#define efi_call5(f, a1, a2, a3, a4, a5) native_efi_call5(f, a1, a2, a3,
a4, a5)
+#define efi_call6(f, a1, a2, a3, a4, a5, a6) native_efi_call6(f, a1, a2, a3,
a4, a5, a6)
+
+#endif
+
#define efi_call_phys0(f) \
efi_call0((f))
#define efi_call_phys1(f, a1) \
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 39a0e7f..afa4354 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -113,3 +113,14 @@ void __iomem *__init efi_ioremap(unsigned long phys_addr,
unsigned long size,
return (void __iomem *)__va(phys_addr);
}
+#ifdef CONFIG_PARAVIRT
+u64 (*platform_efi_call0)(void *fp) = native_efi_call0;
+u64 (*platform_efi_call1)(void *fp, u64 arg1) = native_efi_call1;
+u64 (*platform_efi_call2)(void *fp, u64 arg1, u64 arg2) = native_efi_call2;
+u64 (*platform_efi_call3)(void *fp, u64 arg1, u64 arg2, u64 arg3) =
native_efi_call3;
+u64 (*platform_efi_call4)(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4) =
native_efi_call4;
+u64 (*platform_efi_call5)(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5) = native_efi_call5;
+u64 (*platform_efi_call6)(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5, u64 arg6) = native_efi_call6;
+#endif
diff --git a/arch/x86/platform/efi/efi_stub_64.S
b/arch/x86/platform/efi/efi_stub_64.S
index 4c07cca..60e993c 100644
--- a/arch/x86/platform/efi/efi_stub_64.S
+++ b/arch/x86/platform/efi/efi_stub_64.S
@@ -34,16 +34,16 @@
mov %rsi, %cr0; \
mov (%rsp), %rsp
-ENTRY(efi_call0)
+ENTRY(native_efi_call0)
SAVE_XMM
subq $32, %rsp
call *%rdi
addq $32, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call0)
+ENDPROC(native_efi_call0)
-ENTRY(efi_call1)
+ENTRY(native_efi_call1)
SAVE_XMM
subq $32, %rsp
mov %rsi, %rcx
@@ -51,9 +51,9 @@ ENTRY(efi_call1)
addq $32, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call1)
+ENDPROC(native_efi_call1)
-ENTRY(efi_call2)
+ENTRY(native_efi_call2)
SAVE_XMM
subq $32, %rsp
mov %rsi, %rcx
@@ -61,9 +61,9 @@ ENTRY(efi_call2)
addq $32, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call2)
+ENDPROC(native_efi_call2)
-ENTRY(efi_call3)
+ENTRY(native_efi_call3)
SAVE_XMM
subq $32, %rsp
mov %rcx, %r8
@@ -72,9 +72,9 @@ ENTRY(efi_call3)
addq $32, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call3)
+ENDPROC(native_efi_call3)
-ENTRY(efi_call4)
+ENTRY(native_efi_call4)
SAVE_XMM
subq $32, %rsp
mov %r8, %r9
@@ -84,9 +84,9 @@ ENTRY(efi_call4)
addq $32, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call4)
+ENDPROC(native_efi_call4)
-ENTRY(efi_call5)
+ENTRY(native_efi_call5)
SAVE_XMM
subq $48, %rsp
mov %r9, 32(%rsp)
@@ -97,9 +97,9 @@ ENTRY(efi_call5)
addq $48, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call5)
+ENDPROC(native_efi_call5)
-ENTRY(efi_call6)
+ENTRY(native_efi_call6)
SAVE_XMM
mov (%rsp), %rax
mov 8(%rax), %rax
@@ -113,4 +113,4 @@ ENTRY(efi_call6)
addq $48, %rsp
RESTORE_XMM
ret
-ENDPROC(efi_call6)
+ENDPROC(native_efi_call6)
diff --git a/arch/x86/xen/efi.c b/arch/x86/xen/efi.c
new file mode 100644
index 0000000..f09f829
--- /dev/null
+++ b/arch/x86/xen/efi.c
@@ -0,0 +1,40 @@
+
+#include <asm/xen/hypercall.h>
+
+#include <xen/xen.h>
+#include <linux/efi.h>
+#include <asm/efi.h>
+#include <xen/interface/physdev.h>
+#include "xen-ops.h"
+
+efi_runtime_services_t xen_efi_fnc = {
+ .get_time = xen_get_time;
+ .set_time = xen_set_time;
+ /* and so on */
+};
+u64 xen_efi_call0(void *fp)
+{
+ char *func_idx;
+ u64 (*fnc)(void);
+
+ /*
+ * Look up which of the functions it is in the platform
+ * code, and find the same function in the Xen platform.
+ */
+ func_idx = &efi.systab->runtime - fp;
+ BUG_ON(func_idx == 0); /* Can't be the header! */
+ fnc = (char *)xen_efi_fnc + func_idx; /* This probably won't compile. */
+
+ BUG_ON(!fnc);
+ fnc();
+}
+/* and so on.
+u64 xen_efi_call1(void *fp, u64 arg1);
+u64 xen_efi_call2(void *fp, u64 arg1, u64 arg2);
+u64 xen_efi_call3(void *fp, u64 arg1, u64 arg2, u64 arg3);
+u64 xen_efi_call4(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+u64 xen_efi_call5(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5);
+u64 xen_efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5, u64 arg6);
+*/
diff --git a/arch/x86/xen/setup.c b/arch/x86/xen/setup.c
index 056d11f..cc820d2 100644
--- a/arch/x86/xen/setup.c
+++ b/arch/x86/xen/setup.c
@@ -563,4 +563,13 @@ void __init xen_arch_setup(void)
#ifdef CONFIG_NUMA
numa_off = 1;
#endif
+#ifdef CONFIG_EFI
+ platform_efi_call0 = xen_efi_call0;
+ platform_efi_call1 = xen_efi_call1;
+ platform_efi_call2 = xen_efi_call2;
+ platform_efi_call3 = xen_efi_call3;
+ platform_efi_call4 = xen_efi_call4;
+ platform_efi_call5 = xen_efi_call5;
+ platform_efi_call6 = xen_efi_call6;
+#endif
}
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index 86782c5..d680558 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -123,4 +123,17 @@ void xen_adjust_exception_frame(void);
extern int xen_panic_handler_init(void);
+#ifdef CONFIG_EFI
+extern u64 xen_efi_call0(void *fp);
+extern u64 xen_efi_call1(void *fp, u64 arg1);
+extern u64 xen_efi_call2(void *fp, u64 arg1, u64 arg2);
+extern u64 xen_efi_call3(void *fp, u64 arg1, u64 arg2, u64 arg3);
+extern u64 xen_efi_call4(void *fp, u64 arg1, u64 arg2, u64 arg3, u64 arg4);
+extern u64 xen_efi_call5(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5);
+extern u64 xen_efi_call6(void *fp, u64 arg1, u64 arg2, u64 arg3,
+ u64 arg4, u64 arg5, u64 arg6);
+
+
+#endif
#endif /* XEN_OPS_H */
--
1.7.11.7
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |