* Re: Xen 4.4 development update
@ 2013-08-08 19:38 Eric Shelton
2013-08-08 19:55 ` Konrad Rzeszutek Wilk
0 siblings, 1 reply; 10+ messages in thread
From: Eric Shelton @ 2013-08-08 19:38 UTC (permalink / raw)
To: George Dunlap; +Cc: Daniel Kiper, xen-devel@lists.xen.org
> * Xen EFI feature: pvops dom0 able to make use of EFI run-time
> services (external)
> owner: Daniel Kiper
> status: Just begun
I think this is addressed, maybe in full, by this patchset, presented
in the midst of getting 4.3 in order:
http://lists.xen.org/archives/html/xen-devel/2013-05/msg02492.html
I have used this for the last 3 months. The noted i915 issue was
resolved by later updates to the kernel or X driver, as 3.10.1 is
running smoothly. The only issue I have observed is that although Xen
correctly powers off the system in response to a dom0-initiated
shutdown, Xen is not currently rebooting - I have to let the system
wind down and then do a power cycle.
The patchset is an update to a set originally submitted by Tang Liang,
which I gather was based on work done by Suse. Given that the patches
are 100% kernel-side (the Xen code was put in place some time ago),
what needs to be done for acceptance by the LKML folks?
- Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Xen 4.4 development update
2013-08-08 19:38 Xen 4.4 development update Eric Shelton
@ 2013-08-08 19:55 ` Konrad Rzeszutek Wilk
2013-08-08 20:51 ` Eric Shelton
0 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-08-08 19:55 UTC (permalink / raw)
To: Eric Shelton; +Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
On Thu, Aug 08, 2013 at 03:38:58PM -0400, Eric Shelton wrote:
> > * Xen EFI feature: pvops dom0 able to make use of EFI run-time
> > services (external)
> > owner: Daniel Kiper
> > status: Just begun
>
> I think this is addressed, maybe in full, by this patchset, presented
> in the midst of getting 4.3 in order:
>
> http://lists.xen.org/archives/html/xen-devel/2013-05/msg02492.html
>
> I have used this for the last 3 months. The noted i915 issue was
> resolved by later updates to the kernel or X driver, as 3.10.1 is
> running smoothly. The only issue I have observed is that although Xen
> correctly powers off the system in response to a dom0-initiated
> shutdown, Xen is not currently rebooting - I have to let the system
> wind down and then do a power cycle.
>
> The patchset is an update to a set originally submitted by Tang Liang,
> which I gather was based on work done by Suse. Given that the patches
> are 100% kernel-side (the Xen code was put in place some time ago),
> what needs to be done for acceptance by the LKML folks?
Rework them. The maintainer would like it done differently - that was my
recollection last year when I chatted with him (Matthew Garret).
Daniel will know more - but he is right now making multiboot2 work with
Xen and then attacking this.
>
> - Eric
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@lists.xen.org
> http://lists.xen.org/xen-devel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Xen 4.4 development update
2013-08-08 19:55 ` Konrad Rzeszutek Wilk
@ 2013-08-08 20:51 ` Eric Shelton
2013-08-09 18:56 ` Daniel Kiper
2013-08-20 16:13 ` Stefano Stabellini
0 siblings, 2 replies; 10+ messages in thread
From: Eric Shelton @ 2013-08-08 20:51 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
On Thu, Aug 8, 2013 at 3:55 PM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> wrote:
. . .
> Rework them. The maintainer would like it done differently - that was my
> recollection last year when I chatted with him (Matthew Garret).
>
> Daniel will know more - but he is right now making multiboot2 work with
> Xen and then attacking this.
Back then (https://lkml.org/lkml/2012/2/9/299), Matthew said:
> Hm. Is there absolutely no way to do this by replacing efi_call_*? It'd
> really be nice to avoid yet another set of duplicate functions here -
> the ia64/x86 situation is already bad enough. Ideally this would be
> sufficiently generic that arm can also plug into it.
It looks like the arm patches are just now nearing commit worthiness,
with V2 just posted a couple of days ago:
https://lkml.org/lkml/2013/8/6/584
It looks like Garrett's goal of merging arm and x86 EFI code is being
realized, and that I will need to refactor my patchset to keep up with
these changes. Roy Franz seems to be doing the heavy lifting on arm
EFI, with Matt Fleming serving as the maintainer.
Related to this, is the Xen hypervisor booting under EFI for arm
already? I assume not, if Linux currently lacks the needed
hypercalls. Does anything arm-specific need to happen in an
EFI-friendly dom0 kernel, given that it is hypercall driven? Is there
a platform for test?
- Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Xen 4.4 development update
2013-08-08 20:51 ` Eric Shelton
@ 2013-08-09 18:56 ` Daniel Kiper
2013-08-15 5:32 ` Eric Shelton
2013-08-20 16:13 ` Stefano Stabellini
1 sibling, 1 reply; 10+ messages in thread
From: Daniel Kiper @ 2013-08-09 18:56 UTC (permalink / raw)
To: Eric Shelton; +Cc: George Dunlap, xen-devel@lists.xen.org
On Thu, Aug 08, 2013 at 04:51:51PM -0400, Eric Shelton wrote:
> On Thu, Aug 8, 2013 at 3:55 PM, Konrad Rzeszutek Wilk
> <konrad.wilk@oracle.com> wrote:
> . . .
> > Rework them. The maintainer would like it done differently - that was my
> > recollection last year when I chatted with him (Matthew Garret).
> >
> > Daniel will know more - but he is right now making multiboot2 work with
> > Xen and then attacking this.
>
> Back then (https://lkml.org/lkml/2012/2/9/299), Matthew said:
>
> > Hm. Is there absolutely no way to do this by replacing efi_call_*? It'd
> > really be nice to avoid yet another set of duplicate functions here -
> > the ia64/x86 situation is already bad enough. Ideally this would be
> > sufficiently generic that arm can also plug into it.
>
> It looks like the arm patches are just now nearing commit worthiness,
> with V2 just posted a couple of days ago:
>
> https://lkml.org/lkml/2013/8/6/584
>
> It looks like Garrett's goal of merging arm and x86 EFI code is being
> realized, and that I will need to refactor my patchset to keep up with
> these changes. Roy Franz seems to be doing the heavy lifting on arm
> EFI, with Matt Fleming serving as the maintainer.
I have not dug very deep but it looks that it is only EFI loader
patch series (called stub in Linux Kernel). It is not related to
Xen EFI stuff in Linux Kernel.
> Related to this, is the Xen hypervisor booting under EFI for arm
> already? I assume not, if Linux currently lacks the needed
> hypercalls. Does anything arm-specific need to happen in an
> EFI-friendly dom0 kernel, given that it is hypercall driven? Is there
> a platform for test?
IIRC there is no EFI support in Xen on ARM. However, you should ask
Stefano and/or Ian Campbell for more details. They are ARM maintainers
for Xen.
As Konrad said I am working on multiboot2 protocol support for Xen.
It is needed to load Xen from e.g. GRUB2 loader on EFI platforms.
I would like to finish this first because there are some interests
in that project. Then I will be working on EFI support for Xen
in Linux Kernel. However, if you like to work on this stuff go
ahead. I do no have any objections. Just drop me line then I would
not duplicate your efforts.
Daniel
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Xen 4.4 development update
2013-08-09 18:56 ` Daniel Kiper
@ 2013-08-15 5:32 ` Eric Shelton
2013-08-15 14:12 ` Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: " Konrad Rzeszutek Wilk
0 siblings, 1 reply; 10+ messages in thread
From: Eric Shelton @ 2013-08-15 5:32 UTC (permalink / raw)
To: Daniel Kiper; +Cc: George Dunlap, xen-devel@lists.xen.org
On 08/09/2013 02:56 PM, Daniel Kiper wrote:
> On Thu, Aug 08, 2013 at 04:51:51PM -0400, Eric Shelton wrote:
>> On Thu, Aug 8, 2013 at 3:55 PM, Konrad Rzeszutek Wilk
>> <konrad.wilk@oracle.com> wrote:
>> . . .
>>> Rework them. The maintainer would like it done differently - that was my
>>> recollection last year when I chatted with him (Matthew Garret).
>>>
>>> Daniel will know more - but he is right now making multiboot2 work with
>>> Xen and then attacking this.
>>
>> Back then (https://lkml.org/lkml/2012/2/9/299), Matthew said:
>>
>>> Hm. Is there absolutely no way to do this by replacing efi_call_*? It'd
>>> really be nice to avoid yet another set of duplicate functions here -
>>> the ia64/x86 situation is already bad enough. Ideally this would be
>>> sufficiently generic that arm can also plug into it.
>>
>> It looks like the arm patches are just now nearing commit worthiness,
>> with V2 just posted a couple of days ago:
>>
>> https://lkml.org/lkml/2013/8/6/584
>>
>> It looks like Garrett's goal of merging arm and x86 EFI code is being
>> realized, and that I will need to refactor my patchset to keep up with
>> these changes. Roy Franz seems to be doing the heavy lifting on arm
>> EFI, with Matt Fleming serving as the maintainer.
>
> I have not dug very deep but it looks that it is only EFI loader
> patch series (called stub in Linux Kernel). It is not related to
> Xen EFI stuff in Linux Kernel.
That looks correct. The only file in common between the two sets of
patches is include/linux/efi.h, and those changes do not affect each other.
>> Related to this, is the Xen hypervisor booting under EFI for arm
>> already? I assume not, if Linux currently lacks the needed
>> hypercalls. Does anything arm-specific need to happen in an
>> EFI-friendly dom0 kernel, given that it is hypercall driven? Is there
>> a platform for test?
>
> IIRC there is no EFI support in Xen on ARM. However, you should ask
> Stefano and/or Ian Campbell for more details. They are ARM maintainers
> for Xen.
>
> As Konrad said I am working on multiboot2 protocol support for Xen.
> It is needed to load Xen from e.g. GRUB2 loader on EFI platforms.
> I would like to finish this first because there are some interests
> in that project. Then I will be working on EFI support for Xen
> in Linux Kernel. However, if you like to work on this stuff go
> ahead. I do no have any objections. Just drop me line then I would
> not duplicate your efforts.
In the interest of getting a more finalized patch out while I still
recall some of the details of this, please find below a revised patch.
There continues to be an issue with reboot working on my laptop, but I
think it is in the hypervisor, as the kernel is making the hypercall
requesting the reboot. Unfortunately, I do not have the tools to debug
Xen on my laptop, as it lacks a serial port and I do not have a few of
the things needed for EHCI port debugging. The kernel reboots just fine
when running directly under EFI, although I do not know right now if it
is via the EFI runtime or the more traditional reboot mechanisms.
If there are no comments, I will try running this by the Linux EFI
maintainer.
=============
From: Eric Shelton <eshelton@pobox.com>
Date: Thu, 15 Aug 2013 00:31:08 -0400
Subject: [PATCH 1/1] EFI stub: add support for boot under EFI-booted Xen
Allows dom0 kernel to detect when it is running under a Xen hypervisor
booted under EFI, and then make hyper calls to Xen to identify and
obtain resources such as ACPI tables, E820 information, and the EFI
console in order to complete booting.
Applies cleanly against 3.11rc5 and recent arm efi patches.
Signed-off-by: Eric Shelton <eshelton@pobox.com>
---
arch/x86/platform/efi/Makefile | 3 +
arch/x86/platform/efi/efi.c | 82 ++++++--
arch/x86/platform/efi/xen.c | 427
+++++++++++++++++++++++++++++++++++++++
arch/x86/xen/enlighten.c | 22 +-
include/linux/efi.h | 8 +
include/xen/interface/platform.h | 132 ++++++++++++
6 files changed, 649 insertions(+), 25 deletions(-)
create mode 100644 arch/x86/platform/efi/xen.c
diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
index 6db1cc4..f485766 100644
--- a/arch/x86/platform/efi/Makefile
+++ b/arch/x86/platform/efi/Makefile
@@ -1,2 +1,5 @@
obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
+#ifdef CONFIG_XEN
+obj-$(CONFIG_EFI) += xen.o
+#endif
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index 90f6ed1..ca043bda 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -12,6 +12,7 @@
* Bibo Mao <bibo.mao@intel.com>
* Chandramouli Narayanan <mouli@linux.intel.com>
* Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2013 Eric Shelton <eshelton@pobox.com>
*
* Copied from efi_32.c to eliminate the duplicated code between EFI
* 32/64 support code. --ying 2007-10-26
@@ -51,6 +52,12 @@
#include <asm/x86_init.h>
#include <asm/rtc.h>
+#ifdef CONFIG_XEN
+extern void efi_init_xen(void);
+extern u32 efi_mem_type_xen(unsigned long phys_addr);
+extern u64 efi_mem_attributes_xen(unsigned long phys_addr);
+#endif
+
#define EFI_DEBUG 1
#define EFI_MIN_RESERVE 5120
@@ -381,6 +388,11 @@ int __init efi_memblock_x86_reserve_range(void)
struct efi_info *e = &boot_params.efi_info;
unsigned long pmap;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return 0;
+#endif
+
#ifdef CONFIG_X86_32
/* Can't handle data above 4GB at this time */
if (e->efi_memmap_hi) {
@@ -409,6 +421,8 @@ static void __init print_efi_memmap(void)
void *p;
int i;
+ if (memmap.map == NULL) return;
+
for (p = memmap.map, i = 0;
p < memmap.map_end;
p += memmap.desc_size, i++) {
@@ -426,6 +440,11 @@ void __init efi_reserve_boot_services(void)
{
void *p;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return;
+#endif
+
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
efi_memory_desc_t *md = p;
u64 start = md->phys_addr;
@@ -467,6 +486,11 @@ void __init efi_free_boot_services(void)
{
void *p;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return;
+#endif
+
if (!efi_is_native())
return;
@@ -578,20 +602,15 @@ static int __init efi_systab_init(void *phys)
return 0;
}
-static int __init efi_config_init(u64 tables, int nr_tables)
+int __init efi_config_init(u64 tables, int nr_tables, int entrySz)
{
void *config_tables, *tablep;
- int i, sz;
-
- if (efi_enabled(EFI_64BIT))
- sz = sizeof(efi_config_table_64_t);
- else
- sz = sizeof(efi_config_table_32_t);
+ int i;
/*
* Let's see what config tables the firmware passed to us.
*/
- config_tables = early_ioremap(tables, nr_tables * sz);
+ config_tables = early_ioremap(tables, nr_tables * entrySz);
if (config_tables == NULL) {
pr_err("Could not map Configuration table!\n");
return -ENOMEM;
@@ -599,7 +618,7 @@ static int __init efi_config_init(u64 tables, int
nr_tables)
tablep = config_tables;
pr_info("");
- for (i = 0; i < efi.systab->nr_tables; i++) {
+ for (i = 0; i < nr_tables; i++) {
efi_guid_t guid;
unsigned long table;
@@ -612,8 +631,7 @@ static int __init efi_config_init(u64 tables, int
nr_tables)
if (table64 >> 32) {
pr_cont("\n");
pr_err("Table located above 4GB, disabling EFI.\n");
- early_iounmap(config_tables,
- efi.systab->nr_tables * sz);
+ early_iounmap(config_tables, nr_tables * entrySz);
return -EINVAL;
}
#endif
@@ -645,10 +663,10 @@ static int __init efi_config_init(u64 tables, int
nr_tables)
efi.uga = table;
pr_cont(" UGA=0x%lx ", table);
}
- tablep += sz;
+ tablep += entrySz;
}
pr_cont("\n");
- early_iounmap(config_tables, efi.systab->nr_tables * sz);
+ early_iounmap(config_tables, nr_tables * entrySz);
return 0;
}
@@ -708,9 +726,16 @@ void __init efi_init(void)
{
efi_char16_t *c16;
char vendor[100] = "unknown";
- int i = 0;
+ int entrySz, i = 0;
void *tmp;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN)) {
+ efi_init_xen();
+ return;
+ }
+#endif
+
#ifdef CONFIG_X86_32
if (boot_params.efi_info.efi_systab_hi ||
boot_params.efi_info.efi_memmap_hi) {
@@ -745,7 +770,12 @@ void __init efi_init(void)
efi.systab->hdr.revision >> 16,
efi.systab->hdr.revision & 0xffff, vendor);
- if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
+ if (efi_enabled(EFI_64BIT))
+ entrySz = sizeof(efi_config_table_64_t);
+ else
+ entrySz = sizeof(efi_config_table_32_t);
+
+ if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, entrySz))
return;
set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
@@ -782,7 +812,14 @@ void __init efi_init(void)
void __init efi_late_init(void)
{
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return;
+#endif
+
+#ifdef CONFIG_ACPI_BGRT
efi_bgrt_init();
+#endif
}
void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
@@ -871,6 +908,11 @@ void __init efi_enter_virtual_mode(void)
void *p, *va, *new_memmap = NULL;
int count = 0;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return;
+#endif
+
efi.systab = NULL;
/*
@@ -1007,6 +1049,11 @@ u32 efi_mem_type(unsigned long phys_addr)
efi_memory_desc_t *md;
void *p;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return efi_mem_type_xen(phys_addr);
+#endif
+
if (!efi_enabled(EFI_MEMMAP))
return 0;
@@ -1025,6 +1072,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
efi_memory_desc_t *md;
void *p;
+#ifdef CONFIG_XEN
+ if (efi_enabled(EFI_XEN))
+ return efi_mem_attributes_xen(phys_addr);
+#endif
+
for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
md = p;
if ((md->phys_addr <= phys_addr) &&
diff --git a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
new file mode 100644
index 0000000..ec0943a
--- /dev/null
+++ b/arch/x86/platform/efi/xen.c
@@ -0,0 +1,427 @@
+/*
+ * Xen EFI (Extensible Firmware Interface) support functions
+ * Based on related efforts in SLE and SUSE trees
+ *
+ * Copyright (C) 1999 VA Linux Systems
+ * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
+ * Copyright (C) 1999-2002 Hewlett-Packard Co.
+ * David Mosberger-Tang <davidm@hpl.hp.com>
+ * Stephane Eranian <eranian@hpl.hp.com>
+ * Copyright (C) 2005-2008 Intel Co.
+ * Fenghua Yu <fenghua.yu@intel.com>
+ * Bibo Mao <bibo.mao@intel.com>
+ * Chandramouli Narayanan <mouli@linux.intel.com>
+ * Huang Ying <ying.huang@intel.com>
+ * Copyright (C) 2011 Novell Co.
+ * Jan Beulic <JBeulich@suse.com>
+ * Copyright (C) 2011-2012 Oracle Co.
+ * Liang Tang <liang.tang@oracle.com>
+ * Copyright (C) 2013 Eric Shelton <eshelton@pobox.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/efi.h>
+#include <linux/export.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <linux/time.h>
+
+#include <asm/setup.h>
+#include <asm/efi.h>
+#include <asm/time.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/x86_init.h>
+
+#include <xen/interface/platform.h>
+#include <xen/interface/sched.h>
+#include <asm/xen/hypercall.h>
+
+#define PFX "EFI: "
+
+#define call (op.u.efi_runtime_call)
+#define DECLARE_CALL(what) \
+ struct xen_platform_op op; \
+ op.cmd = XENPF_efi_runtime_call; \
+ call.function = XEN_EFI_##what; \
+ call.misc = 0
+
+static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
+{
+ int err;
+ DECLARE_CALL(get_time);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ if (tm) {
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
+ memcpy(tm, &call.u.get_time.time, sizeof(*tm));
+ }
+
+ if (tc) {
+ tc->resolution = call.u.get_time.resolution;
+ tc->accuracy = call.u.get_time.accuracy;
+ tc->sets_to_zero = !!(call.misc &
+ XEN_EFI_GET_TIME_SET_CLEARS_NS);
+ }
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_time(efi_time_t *tm)
+{
+ DECLARE_CALL(set_time);
+
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
+ memcpy(&call.u.set_time, tm, sizeof(*tm));
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
+ efi_bool_t *pending,
+ efi_time_t *tm)
+{
+ int err;
+ DECLARE_CALL(get_wakeup_time);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ if (tm) {
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
+ memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
+ }
+
+ if (enabled)
+ *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
+
+ if (pending)
+ *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled,
efi_time_t *tm)
+{
+ DECLARE_CALL(set_wakeup_time);
+
+ BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
+ if (enabled)
+ call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
+ if (tm)
+ memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
+ else
+ call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_get_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 *attr,
+ unsigned long *data_size,
+ void *data)
+{
+ int err;
+ DECLARE_CALL(get_variable);
+
+ set_xen_guest_handle(call.u.get_variable.name, name);
+ BUILD_BUG_ON(sizeof(*vendor) !=
+ sizeof(call.u.get_variable.vendor_guid));
+ memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
+ call.u.get_variable.size = *data_size;
+ set_xen_guest_handle(call.u.get_variable.data, data);
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *data_size = call.u.get_variable.size;
+ *attr = call.misc; /* misc in struction is U32 variable*/
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
+ efi_char16_t *name,
+ efi_guid_t *vendor)
+{
+ int err;
+ DECLARE_CALL(get_next_variable_name);
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+ call.u.get_next_variable_name.size = *name_size;
+ set_xen_guest_handle(call.u.get_next_variable_name.name, name);
+ BUILD_BUG_ON(sizeof(*vendor) !=
+ sizeof(call.u.get_next_variable_name.vendor_guid));
+ memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
+ sizeof(*vendor));
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *name_size = call.u.get_next_variable_name.size;
+ memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
+ sizeof(*vendor));
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_set_variable(efi_char16_t *name,
+ efi_guid_t *vendor,
+ u32 attr,
+ unsigned long data_size,
+ void *data)
+{
+ DECLARE_CALL(set_variable);
+
+ set_xen_guest_handle(call.u.set_variable.name, name);
+ call.misc = attr;
+ BUILD_BUG_ON(sizeof(*vendor) !=
+ sizeof(call.u.set_variable.vendor_guid));
+ memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
+ call.u.set_variable.size = data_size;
+ set_xen_guest_handle(call.u.set_variable.data, data);
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_variable_info(u32 attr,
+ u64 *storage_space,
+ u64 *remaining_space,
+ u64 *max_variable_size)
+{
+ int err;
+ DECLARE_CALL(query_variable_info);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *storage_space = call.u.query_variable_info.max_store_size;
+ *remaining_space = call.u.query_variable_info.remain_store_size;
+ *max_variable_size = call.u.query_variable_info.max_size;
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
+{
+ int err;
+ DECLARE_CALL(get_next_high_monotonic_count);
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *count = call.misc;
+
+ return call.status;
+}
+
+static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
+ unsigned long count,
+ unsigned long sg_list)
+{
+ DECLARE_CALL(update_capsule);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
+ capsules);
+ call.u.update_capsule.capsule_count = count;
+ call.u.update_capsule.sg_list = sg_list;
+
+ return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
+}
+
+static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t
**capsules,
+ unsigned long count,
+ u64 *max_size,
+ int *reset_type)
+{
+ int err;
+ DECLARE_CALL(query_capsule_capabilities);
+
+ if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
+ return EFI_UNSUPPORTED;
+
+ set_xen_guest_handle(call.u.query_capsule_capabilities.
+ capsule_header_array, capsules);
+ call.u.query_capsule_capabilities.capsule_count = count;
+
+ err = HYPERVISOR_dom0_op(&op);
+ if (err)
+ return EFI_UNSUPPORTED;
+
+ *max_size = call.u.query_capsule_capabilities.max_capsule_size;
+ *reset_type = call.u.query_capsule_capabilities.reset_type;
+
+ return call.status;
+}
+
+#undef DECLARE_CALL
+#undef call
+
+static void xen_efi_reset_system(int reset_type,
+ efi_status_t status,
+ unsigned long data_size,
+ efi_char16_t *data)
+{
+ struct sched_shutdown r = { .reason = SHUTDOWN_reboot };
+
+ if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
+ BUG();
+}
+
+void __init xen_efi_probe(void)
+{
+ static struct xen_platform_op __initdata op = {
+ .cmd = XENPF_firmware_info,
+ .u.firmware_info = {
+ .type = XEN_FW_EFI_INFO,
+ .index = XEN_FW_EFI_CONFIG_TABLE
+ }
+ };
+
+ if (HYPERVISOR_dom0_op(&op) == 0) {
+ /* TODO: check return info */
+ set_bit(EFI_XEN, &x86_efi_facility);
+ set_bit(EFI_BOOT, &x86_efi_facility);
+ /* since hypervisor calls the runtime, 32/64 bit
+ * EFI/kernel mismatch is not an issue. Set to
+ * match kernel so runtime calls will be made */
+#ifdef CONFIG_64BIT
+ set_bit(EFI_64BIT, &x86_efi_facility);
+#endif
+ }
+}
+
+
+void __init efi_init_xen(void)
+{
+ efi_char16_t c16[100];
+ char vendor[ARRAY_SIZE(c16)] = "unknown";
+ int ret, i;
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ /* redirect system to Xen hypercall implementation */
+ efi.systab = NULL,
+ efi.mps = EFI_INVALID_TABLE_ADDR;
+ efi.acpi = EFI_INVALID_TABLE_ADDR;
+ efi.acpi20 = EFI_INVALID_TABLE_ADDR;
+ efi.smbios = EFI_INVALID_TABLE_ADDR;
+ efi.sal_systab = EFI_INVALID_TABLE_ADDR;
+ efi.boot_info = EFI_INVALID_TABLE_ADDR;
+ efi.hcdp = EFI_INVALID_TABLE_ADDR;
+ efi.uga = EFI_INVALID_TABLE_ADDR;
+ efi.uv_systab = EFI_INVALID_TABLE_ADDR;
+ efi.get_time = xen_efi_get_time;
+ efi.set_time = xen_efi_set_time;
+ efi.get_wakeup_time = xen_efi_get_wakeup_time;
+ efi.set_wakeup_time = xen_efi_set_wakeup_time;
+ efi.get_variable = xen_efi_get_variable;
+ efi.get_next_variable = xen_efi_get_next_variable;
+ efi.set_variable = xen_efi_set_variable;
+ efi.query_variable_info = xen_efi_query_variable_info;
+ efi.update_capsule = xen_efi_update_capsule;
+ efi.query_capsule_caps = xen_efi_query_capsule_caps;
+ efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
+ efi.set_virtual_address_map = NULL;
+ efi.reset_system = xen_efi_reset_system;
+
+ /*
+ * Show what we know for posterity
+ */
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+
+ op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
+ info->vendor.bufsz = sizeof(c16);
+ set_xen_guest_handle(info->vendor.name, c16);
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret) {
+ for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
+ vendor[i] = c16[i];
+ vendor[i] = '\0';
+ } else
+ pr_err("Could not get the firmware vendor!\n");
+
+ op.u.firmware_info.index = XEN_FW_EFI_VERSION;
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret)
+ pr_info("EFI-xen v%u.%.02u by %s\n",
+ info->version >> 16,
+ info->version & 0xffff, vendor);
+ else
+ pr_err("Could not get EFI revision!\n");
+
+ op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
+ ret = HYPERVISOR_dom0_op(&op);
+ if (!ret)
+ efi.runtime_version = info->version;
+ else
+ pr_warn(PFX "Could not get runtime services revision.\n");
+ set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
+
+ /*
+ * Let's see what config tables the firmware passed to us.
+ */
+ op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
+ if (HYPERVISOR_dom0_op(&op))
+ BUG();
+
+ if (efi_config_init(info->cfg.addr, info->cfg.nent,
+ sizeof(efi_config_table_64_t)))
+ panic("Could not init EFI Configuration Tables!\n");
+ set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
+
+ /* the EFI memory info is digested by the hypervisor and
+ * supplied to dom0 via E820 entries */
+ set_bit(EFI_MEMMAP, &x86_efi_facility);
+
+ set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
+
+ /* NOTE: efi.c only does this for CONFIG_X86_32 */
+ x86_platform.get_wallclock = efi_get_time;
+ x86_platform.set_wallclock = efi_set_rtc_mmss;
+}
+
+/*
+ * Convenience functions to obtain memory types and attributes
+ */
+u32 efi_mem_type_xen(unsigned long phys_addr)
+{
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+ op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+ info->mem.addr = phys_addr;
+ info->mem.size = 0;
+ return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
+}
+
+u64 efi_mem_attributes_xen(unsigned long phys_addr)
+{
+ struct xen_platform_op op;
+ union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
+
+ op.cmd = XENPF_firmware_info;
+ op.u.firmware_info.type = XEN_FW_EFI_INFO;
+ op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
+ info->mem.addr = phys_addr;
+ info->mem.size = 0;
+ return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
+}
+
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 193097e..51edc64 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -32,6 +32,7 @@
#include <linux/gfp.h>
#include <linux/memblock.h>
#include <linux/edd.h>
+#include <linux/efi.h>
#include <xen/xen.h>
#include <xen/events.h>
@@ -1342,15 +1343,6 @@ int xen_panic_handler_init(void)
return 0;
}
-static const struct machine_ops xen_machine_ops __initconst = {
- .restart = xen_restart,
- .halt = xen_machine_halt,
- .power_off = xen_machine_power_off,
- .shutdown = xen_machine_halt,
- .crash_shutdown = xen_crash_shutdown,
- .emergency_restart = xen_emergency_restart,
-};
-
static void __init xen_boot_params_init_edd(void)
{
#if IS_ENABLED(CONFIG_EDD)
@@ -1493,7 +1485,12 @@ asmlinkage void __init xen_start_kernel(void)
pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
}
- machine_ops = xen_machine_ops;
+ machine_ops.restart = xen_restart;
+ machine_ops.halt = xen_machine_halt;
+ machine_ops.power_off = xen_machine_power_off;
+ machine_ops.shutdown = xen_machine_halt;
+ machine_ops.crash_shutdown = xen_crash_shutdown;
+ machine_ops.emergency_restart = xen_emergency_restart;
/*
* The only reliable way to retain the initial address of the
@@ -1613,6 +1610,11 @@ asmlinkage void __init xen_start_kernel(void)
xen_setup_runstate_info(0);
+#ifdef CONFIG_EFI
+ if (xen_initial_domain())
+ xen_efi_probe();
+#endif
+
/* Start the world */
#ifdef CONFIG_X86_32
i386_start_kernel();
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 5f8f176..2781dea 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -84,7 +84,10 @@ typedef struct {
#define EFI_PAL_CODE 13
#define EFI_MAX_MEMORY_TYPE 14
+#define EFI_INVALID_TYPE 0xffffffff
+
/* Attribute values: */
+#define EFI_INVALID_ATTRIBUTE ((u64)0x0000000000000000ULL) /* invalid
attribute */
#define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
#define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
#define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
@@ -597,6 +600,10 @@ extern void efi_initialize_iomem_resources(struct
resource *code_resource,
extern void efi_get_time(struct timespec *now);
extern int efi_set_rtc_mmss(const struct timespec *now);
extern void efi_reserve_boot_services(void);
+#ifdef CONFIG_XEN
+extern int __init efi_config_init(u64 tables, int nr_tables, int entrySz);
+extern void xen_efi_probe(void);
+#endif
extern struct efi_memory_map memmap;
/**
@@ -634,6 +641,7 @@ extern int __init efi_setup_pcdp_console(char *);
#define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */
#define EFI_MEMMAP 4 /* Can we use EFI memory map? */
#define EFI_64BIT 5 /* Is the firmware 64-bit? */
+#define EFI_XEN 6 /* Must we access EFI via Xen? */
#ifdef CONFIG_EFI
# ifdef CONFIG_X86
diff --git a/include/xen/interface/platform.h
b/include/xen/interface/platform.h
index c57d5f6..d005f0b 100644
--- a/include/xen/interface/platform.h
+++ b/include/xen/interface/platform.h
@@ -108,10 +108,111 @@ struct xenpf_platform_quirk {
};
DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);
+#define XENPF_efi_runtime_call 49
+#define XEN_EFI_get_time 1
+#define XEN_EFI_set_time 2
+#define XEN_EFI_get_wakeup_time 3
+#define XEN_EFI_set_wakeup_time 4
+#define XEN_EFI_get_next_high_monotonic_count 5
+#define XEN_EFI_get_variable 6
+#define XEN_EFI_set_variable 7
+#define XEN_EFI_get_next_variable_name 8
+#define XEN_EFI_query_variable_info 9
+#define XEN_EFI_query_capsule_capabilities 10
+#define XEN_EFI_update_capsule 11
+
+struct xenpf_efi_runtime_call {
+ uint32_t function;
+ /*
+ * This field is generally used for per sub-function flags (defined
+ * below), except for the XEN_EFI_get_next_high_monotonic_count case,
+ * where it holds the single returned value.
+ */
+ uint32_t misc;
+ unsigned long status;
+ union {
+#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
+ struct {
+ struct xenpf_efi_time {
+ uint16_t year;
+ uint8_t month;
+ uint8_t day;
+ uint8_t hour;
+ uint8_t min;
+ uint8_t sec;
+ uint32_t ns;
+ int16_t tz;
+ uint8_t daylight;
+ } time;
+ uint32_t resolution;
+ uint32_t accuracy;
+ } get_time;
+
+ struct xenpf_efi_time set_time;
+
+#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
+#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
+ struct xenpf_efi_time get_wakeup_time;
+
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001
+#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
+ struct xenpf_efi_time set_wakeup_time;
+
+#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001
+#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
+#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
+ struct {
+ GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
+ unsigned long size;
+ GUEST_HANDLE(void) data;
+ struct xenpf_efi_guid {
+ uint32_t data1;
+ uint16_t data2;
+ uint16_t data3;
+ uint8_t data4[8];
+ } vendor_guid;
+ } get_variable, set_variable;
+
+ struct {
+ unsigned long size;
+ GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
+ struct xenpf_efi_guid vendor_guid;
+ } get_next_variable_name;
+
+ struct {
+ uint32_t attr;
+ uint64_t max_store_size;
+ uint64_t remain_store_size;
+ uint64_t max_size;
+ } query_variable_info;
+
+ struct {
+ GUEST_HANDLE(void) capsule_header_array;
+ unsigned long capsule_count;
+ uint64_t max_capsule_size;
+ unsigned int reset_type;
+ } query_capsule_capabilities;
+
+ struct {
+ GUEST_HANDLE(void) capsule_header_array;
+ unsigned long capsule_count;
+ uint64_t sg_list; /* machine address */
+ } update_capsule;
+ } u;
+};
+DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
+
#define XENPF_firmware_info 50
#define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
#define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
#define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
+#define XEN_FW_EFI_INFO 4 /* from EFI */
+#define XEN_FW_EFI_VERSION 0
+#define XEN_FW_EFI_CONFIG_TABLE 1
+#define XEN_FW_EFI_VENDOR 2
+#define XEN_FW_EFI_MEM_INFO 3
+#define XEN_FW_EFI_RT_VERSION 4
+#define XEN_FW_EFI_PCI_ROM 5
#define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard shift
flags. */
struct xenpf_firmware_info {
/* IN variables. */
@@ -143,6 +244,36 @@ struct xenpf_firmware_info {
/* must refer to 128-byte buffer */
GUEST_HANDLE(uchar) edid;
} vbeddc_info; /* XEN_FW_VBEDDC_INFO */
+ union xenpf_efi_info {
+ uint32_t version;
+ struct {
+ uint64_t addr; /* EFI_CONFIGURATION_TABLE */
+ uint32_t nent;
+ } cfg;
+ struct {
+ uint32_t revision;
+ uint32_t bufsz; /* input, in bytes */
+ GUEST_HANDLE(void) name;
+ /* UCS-2/UTF-16 string */
+ } vendor;
+ struct {
+ uint64_t addr;
+ uint64_t size;
+ uint64_t attr;
+ uint32_t type;
+ } mem;
+ struct {
+ /* IN variables */
+ uint16_t segment;
+ uint8_t bus;
+ uint8_t devfn;
+ uint16_t vendor;
+ uint16_t devid;
+ /* OUT variables */
+ uint64_t address;
+ xen_ulong_t size;
+ } pci_rom;
+ } efi_info; /* XEN_FW_EFI_INFO */
uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
} u;
@@ -361,6 +492,7 @@ struct xen_platform_op {
struct xenpf_read_memtype read_memtype;
struct xenpf_microcode_update microcode;
struct xenpf_platform_quirk platform_quirk;
+ struct xenpf_efi_runtime_call efi_runtime_call;
struct xenpf_firmware_info firmware_info;
struct xenpf_enter_acpi_sleep enter_acpi_sleep;
struct xenpf_change_freq change_freq;
--
1.8.3.4
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: Xen 4.4 development update
2013-08-15 5:32 ` Eric Shelton
@ 2013-08-15 14:12 ` Konrad Rzeszutek Wilk
2013-08-15 20:24 ` Eric Shelton
0 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-08-15 14:12 UTC (permalink / raw)
To: Eric Shelton; +Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
On Thu, Aug 15, 2013 at 01:32:12AM -0400, Eric Shelton wrote:
> On 08/09/2013 02:56 PM, Daniel Kiper wrote:
> >On Thu, Aug 08, 2013 at 04:51:51PM -0400, Eric Shelton wrote:
> >>On Thu, Aug 8, 2013 at 3:55 PM, Konrad Rzeszutek Wilk
> >><konrad.wilk@oracle.com> wrote:
> >>. . .
> >>>Rework them. The maintainer would like it done differently - that was my
> >>>recollection last year when I chatted with him (Matthew Garret).
> >>>
> >>>Daniel will know more - but he is right now making multiboot2 work with
> >>>Xen and then attacking this.
> >>
> >>Back then (https://lkml.org/lkml/2012/2/9/299), Matthew said:
> >>
> >>>Hm. Is there absolutely no way to do this by replacing efi_call_*? It'd
> >>>really be nice to avoid yet another set of duplicate functions here -
> >>>the ia64/x86 situation is already bad enough. Ideally this would be
> >>>sufficiently generic that arm can also plug into it.
> >>
> >>It looks like the arm patches are just now nearing commit worthiness,
> >>with V2 just posted a couple of days ago:
> >>
> >>https://lkml.org/lkml/2013/8/6/584
> >>
> >>It looks like Garrett's goal of merging arm and x86 EFI code is being
> >>realized, and that I will need to refactor my patchset to keep up with
> >>these changes. Roy Franz seems to be doing the heavy lifting on arm
> >>EFI, with Matt Fleming serving as the maintainer.
> >
> >I have not dug very deep but it looks that it is only EFI loader
> >patch series (called stub in Linux Kernel). It is not related to
> >Xen EFI stuff in Linux Kernel.
>
> That looks correct. The only file in common between the two sets of
> patches is include/linux/efi.h, and those changes do not affect each
> other.
>
> >>Related to this, is the Xen hypervisor booting under EFI for arm
> >>already? I assume not, if Linux currently lacks the needed
> >>hypercalls. Does anything arm-specific need to happen in an
> >>EFI-friendly dom0 kernel, given that it is hypercall driven? Is there
> >>a platform for test?
> >
> >IIRC there is no EFI support in Xen on ARM. However, you should ask
> >Stefano and/or Ian Campbell for more details. They are ARM maintainers
> >for Xen.
> >
> >As Konrad said I am working on multiboot2 protocol support for Xen.
> >It is needed to load Xen from e.g. GRUB2 loader on EFI platforms.
> >I would like to finish this first because there are some interests
> >in that project. Then I will be working on EFI support for Xen
> >in Linux Kernel. However, if you like to work on this stuff go
> >ahead. I do no have any objections. Just drop me line then I would
> >not duplicate your efforts.
>
> In the interest of getting a more finalized patch out while I still
> recall some of the details of this, please find below a revised
> patch. There continues to be an issue with reboot working on my
> laptop, but I think it is in the hypervisor, as the kernel is making
> the hypercall requesting the reboot. Unfortunately, I do not have
> the tools to debug Xen on my laptop, as it lacks a serial port and I
> do not have a few of the things needed for EHCI port debugging. The
> kernel reboots just fine when running directly under EFI, although I
> do not know right now if it is via the EFI runtime or the more
> traditional reboot mechanisms.
>
> If there are no comments, I will try running this by the Linux EFI
> maintainer.
First of, thank you for taking a stab at it and redoing it.
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).
- 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.
- When approaching Matthew I would suggest you label it as RFC - to get
an idea of how he would like it done - as I don't think he will
take the patch as is. He might suggest the thing I just mentioned
above. Or perhaps make most of the 'efi_*' calls go through some form
of function table that by default is set to baremetal_efi_calls
(see x86_init.c)
- There are some code paths that just do:
if (xen)
return;
But it is not clear why that is so (missing comments). This is needed
b/c if somebody wants to redo the code in the future they would need to
know where to place that 'if (xen) do something different'
- You want to credit Jan Beulich in the commit description saying
that the patch was derieved from the work that he did for SuSE Linux.
Liang Tang took some of that - but he forgot to mention that in the
initial post.
- It is unclear to me why the machine_ops assigment has been changed?
Thank you again for taking a stab at it! I know that getting push back
on patches is not a thing that anybody likes - but the end goal is make
it be fantastic and sometimes that takes a couple of rounds (or about a
dozen as my first patches for Linux took that many revisions)
>
> =============
>
> From: Eric Shelton <eshelton@pobox.com>
> Date: Thu, 15 Aug 2013 00:31:08 -0400
> Subject: [PATCH 1/1] EFI stub: add support for boot under EFI-booted Xen
>
> Allows dom0 kernel to detect when it is running under a Xen
> hypervisor booted under EFI, and then make hyper calls to Xen to
> identify and obtain resources such as ACPI tables, E820 information,
> and the EFI console in order to complete booting.
>
> Applies cleanly against 3.11rc5 and recent arm efi patches.
>
> Signed-off-by: Eric Shelton <eshelton@pobox.com>
> ---
> arch/x86/platform/efi/Makefile | 3 +
> arch/x86/platform/efi/efi.c | 82 ++++++--
> arch/x86/platform/efi/xen.c | 427
> +++++++++++++++++++++++++++++++++++++++
> arch/x86/xen/enlighten.c | 22 +-
> include/linux/efi.h | 8 +
> include/xen/interface/platform.h | 132 ++++++++++++
> 6 files changed, 649 insertions(+), 25 deletions(-)
> create mode 100644 arch/x86/platform/efi/xen.c
>
> diff --git a/arch/x86/platform/efi/Makefile b/arch/x86/platform/efi/Makefile
> index 6db1cc4..f485766 100644
> --- a/arch/x86/platform/efi/Makefile
> +++ b/arch/x86/platform/efi/Makefile
> @@ -1,2 +1,5 @@
> obj-$(CONFIG_EFI) += efi.o efi_$(BITS).o efi_stub_$(BITS).o
> +#ifdef CONFIG_XEN
> +obj-$(CONFIG_EFI) += xen.o
> +#endif
> obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
> diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
> index 90f6ed1..ca043bda 100644
> --- a/arch/x86/platform/efi/efi.c
> +++ b/arch/x86/platform/efi/efi.c
> @@ -12,6 +12,7 @@
> * Bibo Mao <bibo.mao@intel.com>
> * Chandramouli Narayanan <mouli@linux.intel.com>
> * Huang Ying <ying.huang@intel.com>
> + * Copyright (C) 2013 Eric Shelton <eshelton@pobox.com>
> *
> * Copied from efi_32.c to eliminate the duplicated code between EFI
> * 32/64 support code. --ying 2007-10-26
> @@ -51,6 +52,12 @@
> #include <asm/x86_init.h>
> #include <asm/rtc.h>
>
> +#ifdef CONFIG_XEN
> +extern void efi_init_xen(void);
> +extern u32 efi_mem_type_xen(unsigned long phys_addr);
> +extern u64 efi_mem_attributes_xen(unsigned long phys_addr);
> +#endif
> +
> #define EFI_DEBUG 1
>
> #define EFI_MIN_RESERVE 5120
> @@ -381,6 +388,11 @@ int __init efi_memblock_x86_reserve_range(void)
> struct efi_info *e = &boot_params.efi_info;
> unsigned long pmap;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return 0;
> +#endif
> +
> #ifdef CONFIG_X86_32
> /* Can't handle data above 4GB at this time */
> if (e->efi_memmap_hi) {
> @@ -409,6 +421,8 @@ static void __init print_efi_memmap(void)
> void *p;
> int i;
>
> + if (memmap.map == NULL) return;
> +
> for (p = memmap.map, i = 0;
> p < memmap.map_end;
> p += memmap.desc_size, i++) {
> @@ -426,6 +440,11 @@ void __init efi_reserve_boot_services(void)
> {
> void *p;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return;
> +#endif
> +
> for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
> efi_memory_desc_t *md = p;
> u64 start = md->phys_addr;
> @@ -467,6 +486,11 @@ void __init efi_free_boot_services(void)
> {
> void *p;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return;
> +#endif
> +
> if (!efi_is_native())
> return;
>
> @@ -578,20 +602,15 @@ static int __init efi_systab_init(void *phys)
> return 0;
> }
>
> -static int __init efi_config_init(u64 tables, int nr_tables)
> +int __init efi_config_init(u64 tables, int nr_tables, int entrySz)
> {
> void *config_tables, *tablep;
> - int i, sz;
> -
> - if (efi_enabled(EFI_64BIT))
> - sz = sizeof(efi_config_table_64_t);
> - else
> - sz = sizeof(efi_config_table_32_t);
> + int i;
>
> /*
> * Let's see what config tables the firmware passed to us.
> */
> - config_tables = early_ioremap(tables, nr_tables * sz);
> + config_tables = early_ioremap(tables, nr_tables * entrySz);
> if (config_tables == NULL) {
> pr_err("Could not map Configuration table!\n");
> return -ENOMEM;
> @@ -599,7 +618,7 @@ static int __init efi_config_init(u64 tables,
> int nr_tables)
>
> tablep = config_tables;
> pr_info("");
> - for (i = 0; i < efi.systab->nr_tables; i++) {
> + for (i = 0; i < nr_tables; i++) {
> efi_guid_t guid;
> unsigned long table;
>
> @@ -612,8 +631,7 @@ static int __init efi_config_init(u64 tables,
> int nr_tables)
> if (table64 >> 32) {
> pr_cont("\n");
> pr_err("Table located above 4GB, disabling EFI.\n");
> - early_iounmap(config_tables,
> - efi.systab->nr_tables * sz);
> + early_iounmap(config_tables, nr_tables * entrySz);
> return -EINVAL;
> }
> #endif
> @@ -645,10 +663,10 @@ static int __init efi_config_init(u64 tables,
> int nr_tables)
> efi.uga = table;
> pr_cont(" UGA=0x%lx ", table);
> }
> - tablep += sz;
> + tablep += entrySz;
> }
> pr_cont("\n");
> - early_iounmap(config_tables, efi.systab->nr_tables * sz);
> + early_iounmap(config_tables, nr_tables * entrySz);
> return 0;
> }
>
> @@ -708,9 +726,16 @@ void __init efi_init(void)
> {
> efi_char16_t *c16;
> char vendor[100] = "unknown";
> - int i = 0;
> + int entrySz, i = 0;
> void *tmp;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN)) {
> + efi_init_xen();
> + return;
> + }
> +#endif
> +
> #ifdef CONFIG_X86_32
> if (boot_params.efi_info.efi_systab_hi ||
> boot_params.efi_info.efi_memmap_hi) {
> @@ -745,7 +770,12 @@ void __init efi_init(void)
> efi.systab->hdr.revision >> 16,
> efi.systab->hdr.revision & 0xffff, vendor);
>
> - if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
> + if (efi_enabled(EFI_64BIT))
> + entrySz = sizeof(efi_config_table_64_t);
> + else
> + entrySz = sizeof(efi_config_table_32_t);
> +
> + if (efi_config_init(efi.systab->tables, efi.systab->nr_tables, entrySz))
> return;
>
> set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> @@ -782,7 +812,14 @@ void __init efi_init(void)
>
> void __init efi_late_init(void)
> {
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return;
> +#endif
> +
> +#ifdef CONFIG_ACPI_BGRT
> efi_bgrt_init();
> +#endif
> }
>
> void __init efi_set_executable(efi_memory_desc_t *md, bool executable)
> @@ -871,6 +908,11 @@ void __init efi_enter_virtual_mode(void)
> void *p, *va, *new_memmap = NULL;
> int count = 0;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return;
> +#endif
> +
> efi.systab = NULL;
>
> /*
> @@ -1007,6 +1049,11 @@ u32 efi_mem_type(unsigned long phys_addr)
> efi_memory_desc_t *md;
> void *p;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return efi_mem_type_xen(phys_addr);
> +#endif
> +
> if (!efi_enabled(EFI_MEMMAP))
> return 0;
>
> @@ -1025,6 +1072,11 @@ u64 efi_mem_attributes(unsigned long phys_addr)
> efi_memory_desc_t *md;
> void *p;
>
> +#ifdef CONFIG_XEN
> + if (efi_enabled(EFI_XEN))
> + return efi_mem_attributes_xen(phys_addr);
> +#endif
> +
> for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
> md = p;
> if ((md->phys_addr <= phys_addr) &&
> diff --git a/arch/x86/platform/efi/xen.c b/arch/x86/platform/efi/xen.c
> new file mode 100644
> index 0000000..ec0943a
> --- /dev/null
> +++ b/arch/x86/platform/efi/xen.c
> @@ -0,0 +1,427 @@
> +/*
> + * Xen EFI (Extensible Firmware Interface) support functions
> + * Based on related efforts in SLE and SUSE trees
> + *
> + * Copyright (C) 1999 VA Linux Systems
> + * Copyright (C) 1999 Walt Drummond <drummond@valinux.com>
> + * Copyright (C) 1999-2002 Hewlett-Packard Co.
> + * David Mosberger-Tang <davidm@hpl.hp.com>
> + * Stephane Eranian <eranian@hpl.hp.com>
> + * Copyright (C) 2005-2008 Intel Co.
> + * Fenghua Yu <fenghua.yu@intel.com>
> + * Bibo Mao <bibo.mao@intel.com>
> + * Chandramouli Narayanan <mouli@linux.intel.com>
> + * Huang Ying <ying.huang@intel.com>
> + * Copyright (C) 2011 Novell Co.
> + * Jan Beulic <JBeulich@suse.com>
> + * Copyright (C) 2011-2012 Oracle Co.
> + * Liang Tang <liang.tang@oracle.com>
> + * Copyright (C) 2013 Eric Shelton <eshelton@pobox.com>
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/init.h>
> +#include <linux/efi.h>
> +#include <linux/export.h>
> +#include <linux/platform_device.h>
> +#include <linux/spinlock.h>
> +#include <linux/time.h>
> +
> +#include <asm/setup.h>
> +#include <asm/efi.h>
> +#include <asm/time.h>
> +#include <asm/cacheflush.h>
> +#include <asm/tlbflush.h>
> +#include <asm/x86_init.h>
> +
> +#include <xen/interface/platform.h>
> +#include <xen/interface/sched.h>
> +#include <asm/xen/hypercall.h>
> +
> +#define PFX "EFI: "
> +
> +#define call (op.u.efi_runtime_call)
> +#define DECLARE_CALL(what) \
> + struct xen_platform_op op; \
> + op.cmd = XENPF_efi_runtime_call; \
> + call.function = XEN_EFI_##what; \
> + call.misc = 0
> +
> +static efi_status_t xen_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> +{
> + int err;
> + DECLARE_CALL(get_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_time.time));
> + memcpy(tm, &call.u.get_time.time, sizeof(*tm));
> + }
> +
> + if (tc) {
> + tc->resolution = call.u.get_time.resolution;
> + tc->accuracy = call.u.get_time.accuracy;
> + tc->sets_to_zero = !!(call.misc &
> + XEN_EFI_GET_TIME_SET_CLEARS_NS);
> + }
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_time(efi_time_t *tm)
> +{
> + DECLARE_CALL(set_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_time));
> + memcpy(&call.u.set_time, tm, sizeof(*tm));
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_wakeup_time(efi_bool_t *enabled,
> + efi_bool_t *pending,
> + efi_time_t *tm)
> +{
> + int err;
> + DECLARE_CALL(get_wakeup_time);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + if (tm) {
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.get_wakeup_time));
> + memcpy(tm, &call.u.get_wakeup_time, sizeof(*tm));
> + }
> +
> + if (enabled)
> + *enabled = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_ENABLED);
> +
> + if (pending)
> + *pending = !!(call.misc & XEN_EFI_GET_WAKEUP_TIME_PENDING);
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_wakeup_time(efi_bool_t enabled,
> efi_time_t *tm)
> +{
> + DECLARE_CALL(set_wakeup_time);
> +
> + BUILD_BUG_ON(sizeof(*tm) != sizeof(call.u.set_wakeup_time));
> + if (enabled)
> + call.misc = XEN_EFI_SET_WAKEUP_TIME_ENABLE;
> + if (tm)
> + memcpy(&call.u.set_wakeup_time, tm, sizeof(*tm));
> + else
> + call.misc |= XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_get_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 *attr,
> + unsigned long *data_size,
> + void *data)
> +{
> + int err;
> + DECLARE_CALL(get_variable);
> +
> + set_xen_guest_handle(call.u.get_variable.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.get_variable.vendor_guid));
> + memcpy(&call.u.get_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.get_variable.size = *data_size;
> + set_xen_guest_handle(call.u.get_variable.data, data);
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *data_size = call.u.get_variable.size;
> + *attr = call.misc; /* misc in struction is U32 variable*/
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_variable(unsigned long *name_size,
> + efi_char16_t *name,
> + efi_guid_t *vendor)
> +{
> + int err;
> + DECLARE_CALL(get_next_variable_name);
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> + call.u.get_next_variable_name.size = *name_size;
> + set_xen_guest_handle(call.u.get_next_variable_name.name, name);
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.get_next_variable_name.vendor_guid));
> + memcpy(&call.u.get_next_variable_name.vendor_guid, vendor,
> + sizeof(*vendor));
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *name_size = call.u.get_next_variable_name.size;
> + memcpy(vendor, &call.u.get_next_variable_name.vendor_guid,
> + sizeof(*vendor));
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_set_variable(efi_char16_t *name,
> + efi_guid_t *vendor,
> + u32 attr,
> + unsigned long data_size,
> + void *data)
> +{
> + DECLARE_CALL(set_variable);
> +
> + set_xen_guest_handle(call.u.set_variable.name, name);
> + call.misc = attr;
> + BUILD_BUG_ON(sizeof(*vendor) !=
> + sizeof(call.u.set_variable.vendor_guid));
> + memcpy(&call.u.set_variable.vendor_guid, vendor, sizeof(*vendor));
> + call.u.set_variable.size = data_size;
> + set_xen_guest_handle(call.u.set_variable.data, data);
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_variable_info(u32 attr,
> + u64 *storage_space,
> + u64 *remaining_space,
> + u64 *max_variable_size)
> +{
> + int err;
> + DECLARE_CALL(query_variable_info);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *storage_space = call.u.query_variable_info.max_store_size;
> + *remaining_space = call.u.query_variable_info.remain_store_size;
> + *max_variable_size = call.u.query_variable_info.max_size;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_get_next_high_mono_count(u32 *count)
> +{
> + int err;
> + DECLARE_CALL(get_next_high_monotonic_count);
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *count = call.misc;
> +
> + return call.status;
> +}
> +
> +static efi_status_t xen_efi_update_capsule(efi_capsule_header_t **capsules,
> + unsigned long count,
> + unsigned long sg_list)
> +{
> + DECLARE_CALL(update_capsule);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.update_capsule.capsule_header_array,
> + capsules);
> + call.u.update_capsule.capsule_count = count;
> + call.u.update_capsule.sg_list = sg_list;
> +
> + return HYPERVISOR_dom0_op(&op) ? EFI_UNSUPPORTED : call.status;
> +}
> +
> +static efi_status_t xen_efi_query_capsule_caps(efi_capsule_header_t
> **capsules,
> + unsigned long count,
> + u64 *max_size,
> + int *reset_type)
> +{
> + int err;
> + DECLARE_CALL(query_capsule_capabilities);
> +
> + if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> + return EFI_UNSUPPORTED;
> +
> + set_xen_guest_handle(call.u.query_capsule_capabilities.
> + capsule_header_array, capsules);
> + call.u.query_capsule_capabilities.capsule_count = count;
> +
> + err = HYPERVISOR_dom0_op(&op);
> + if (err)
> + return EFI_UNSUPPORTED;
> +
> + *max_size = call.u.query_capsule_capabilities.max_capsule_size;
> + *reset_type = call.u.query_capsule_capabilities.reset_type;
> +
> + return call.status;
> +}
> +
> +#undef DECLARE_CALL
> +#undef call
> +
> +static void xen_efi_reset_system(int reset_type,
> + efi_status_t status,
> + unsigned long data_size,
> + efi_char16_t *data)
> +{
> + struct sched_shutdown r = { .reason = SHUTDOWN_reboot };
> +
> + if (HYPERVISOR_sched_op(SCHEDOP_shutdown, &r))
> + BUG();
> +}
> +
> +void __init xen_efi_probe(void)
> +{
> + static struct xen_platform_op __initdata op = {
> + .cmd = XENPF_firmware_info,
> + .u.firmware_info = {
> + .type = XEN_FW_EFI_INFO,
> + .index = XEN_FW_EFI_CONFIG_TABLE
> + }
> + };
> +
> + if (HYPERVISOR_dom0_op(&op) == 0) {
> + /* TODO: check return info */
> + set_bit(EFI_XEN, &x86_efi_facility);
> + set_bit(EFI_BOOT, &x86_efi_facility);
> + /* since hypervisor calls the runtime, 32/64 bit
> + * EFI/kernel mismatch is not an issue. Set to
> + * match kernel so runtime calls will be made */
> +#ifdef CONFIG_64BIT
> + set_bit(EFI_64BIT, &x86_efi_facility);
> +#endif
> + }
> +}
> +
> +
> +void __init efi_init_xen(void)
> +{
> + efi_char16_t c16[100];
> + char vendor[ARRAY_SIZE(c16)] = "unknown";
> + int ret, i;
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + /* redirect system to Xen hypercall implementation */
> + efi.systab = NULL,
> + efi.mps = EFI_INVALID_TABLE_ADDR;
> + efi.acpi = EFI_INVALID_TABLE_ADDR;
> + efi.acpi20 = EFI_INVALID_TABLE_ADDR;
> + efi.smbios = EFI_INVALID_TABLE_ADDR;
> + efi.sal_systab = EFI_INVALID_TABLE_ADDR;
> + efi.boot_info = EFI_INVALID_TABLE_ADDR;
> + efi.hcdp = EFI_INVALID_TABLE_ADDR;
> + efi.uga = EFI_INVALID_TABLE_ADDR;
> + efi.uv_systab = EFI_INVALID_TABLE_ADDR;
> + efi.get_time = xen_efi_get_time;
> + efi.set_time = xen_efi_set_time;
> + efi.get_wakeup_time = xen_efi_get_wakeup_time;
> + efi.set_wakeup_time = xen_efi_set_wakeup_time;
> + efi.get_variable = xen_efi_get_variable;
> + efi.get_next_variable = xen_efi_get_next_variable;
> + efi.set_variable = xen_efi_set_variable;
> + efi.query_variable_info = xen_efi_query_variable_info;
> + efi.update_capsule = xen_efi_update_capsule;
> + efi.query_capsule_caps = xen_efi_query_capsule_caps;
> + efi.get_next_high_mono_count = xen_efi_get_next_high_mono_count;
> + efi.set_virtual_address_map = NULL;
> + efi.reset_system = xen_efi_reset_system;
> +
> + /*
> + * Show what we know for posterity
> + */
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> +
> + op.u.firmware_info.index = XEN_FW_EFI_VENDOR;
> + info->vendor.bufsz = sizeof(c16);
> + set_xen_guest_handle(info->vendor.name, c16);
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret) {
> + for (i = 0; i < sizeof(vendor) - 1 && c16[i]; ++i)
> + vendor[i] = c16[i];
> + vendor[i] = '\0';
> + } else
> + pr_err("Could not get the firmware vendor!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + pr_info("EFI-xen v%u.%.02u by %s\n",
> + info->version >> 16,
> + info->version & 0xffff, vendor);
> + else
> + pr_err("Could not get EFI revision!\n");
> +
> + op.u.firmware_info.index = XEN_FW_EFI_RT_VERSION;
> + ret = HYPERVISOR_dom0_op(&op);
> + if (!ret)
> + efi.runtime_version = info->version;
> + else
> + pr_warn(PFX "Could not get runtime services revision.\n");
> + set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
> +
> + /*
> + * Let's see what config tables the firmware passed to us.
> + */
> + op.u.firmware_info.index = XEN_FW_EFI_CONFIG_TABLE;
> + if (HYPERVISOR_dom0_op(&op))
> + BUG();
> +
> + if (efi_config_init(info->cfg.addr, info->cfg.nent,
> + sizeof(efi_config_table_64_t)))
> + panic("Could not init EFI Configuration Tables!\n");
> + set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
> +
> + /* the EFI memory info is digested by the hypervisor and
> + * supplied to dom0 via E820 entries */
> + set_bit(EFI_MEMMAP, &x86_efi_facility);
> +
> + set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility); /* not checked */
> +
> + /* NOTE: efi.c only does this for CONFIG_X86_32 */
> + x86_platform.get_wallclock = efi_get_time;
> + x86_platform.set_wallclock = efi_set_rtc_mmss;
> +}
> +
> +/*
> + * Convenience functions to obtain memory types and attributes
> + */
> +u32 efi_mem_type_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.type;
> +}
> +
> +u64 efi_mem_attributes_xen(unsigned long phys_addr)
> +{
> + struct xen_platform_op op;
> + union xenpf_efi_info *info = &op.u.firmware_info.u.efi_info;
> +
> + op.cmd = XENPF_firmware_info;
> + op.u.firmware_info.type = XEN_FW_EFI_INFO;
> + op.u.firmware_info.index = XEN_FW_EFI_MEM_INFO;
> + info->mem.addr = phys_addr;
> + info->mem.size = 0;
> + return HYPERVISOR_dom0_op(&op) ? 0 : info->mem.attr;
> +}
> +
> diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
> index 193097e..51edc64 100644
> --- a/arch/x86/xen/enlighten.c
> +++ b/arch/x86/xen/enlighten.c
> @@ -32,6 +32,7 @@
> #include <linux/gfp.h>
> #include <linux/memblock.h>
> #include <linux/edd.h>
> +#include <linux/efi.h>
>
> #include <xen/xen.h>
> #include <xen/events.h>
> @@ -1342,15 +1343,6 @@ int xen_panic_handler_init(void)
> return 0;
> }
>
> -static const struct machine_ops xen_machine_ops __initconst = {
> - .restart = xen_restart,
> - .halt = xen_machine_halt,
> - .power_off = xen_machine_power_off,
> - .shutdown = xen_machine_halt,
> - .crash_shutdown = xen_crash_shutdown,
> - .emergency_restart = xen_emergency_restart,
> -};
> -
> static void __init xen_boot_params_init_edd(void)
> {
> #if IS_ENABLED(CONFIG_EDD)
> @@ -1493,7 +1485,12 @@ asmlinkage void __init xen_start_kernel(void)
> pv_mmu_ops.ptep_modify_prot_commit = xen_ptep_modify_prot_commit;
> }
>
> - machine_ops = xen_machine_ops;
> + machine_ops.restart = xen_restart;
> + machine_ops.halt = xen_machine_halt;
> + machine_ops.power_off = xen_machine_power_off;
> + machine_ops.shutdown = xen_machine_halt;
> + machine_ops.crash_shutdown = xen_crash_shutdown;
> + machine_ops.emergency_restart = xen_emergency_restart;
>
> /*
> * The only reliable way to retain the initial address of the
> @@ -1613,6 +1610,11 @@ asmlinkage void __init xen_start_kernel(void)
>
> xen_setup_runstate_info(0);
>
> +#ifdef CONFIG_EFI
> + if (xen_initial_domain())
> + xen_efi_probe();
> +#endif
> +
> /* Start the world */
> #ifdef CONFIG_X86_32
> i386_start_kernel();
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 5f8f176..2781dea 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -84,7 +84,10 @@ typedef struct {
> #define EFI_PAL_CODE 13
> #define EFI_MAX_MEMORY_TYPE 14
>
> +#define EFI_INVALID_TYPE 0xffffffff
> +
> /* Attribute values: */
> +#define EFI_INVALID_ATTRIBUTE ((u64)0x0000000000000000ULL) /*
> invalid attribute */
> #define EFI_MEMORY_UC ((u64)0x0000000000000001ULL) /* uncached */
> #define EFI_MEMORY_WC ((u64)0x0000000000000002ULL) /* write-coalescing */
> #define EFI_MEMORY_WT ((u64)0x0000000000000004ULL) /* write-through */
> @@ -597,6 +600,10 @@ extern void
> efi_initialize_iomem_resources(struct resource *code_resource,
> extern void efi_get_time(struct timespec *now);
> extern int efi_set_rtc_mmss(const struct timespec *now);
> extern void efi_reserve_boot_services(void);
> +#ifdef CONFIG_XEN
> +extern int __init efi_config_init(u64 tables, int nr_tables, int entrySz);
> +extern void xen_efi_probe(void);
> +#endif
> extern struct efi_memory_map memmap;
>
> /**
> @@ -634,6 +641,7 @@ extern int __init efi_setup_pcdp_console(char *);
> #define EFI_RUNTIME_SERVICES 3 /* Can we use runtime services? */
> #define EFI_MEMMAP 4 /* Can we use EFI memory map? */
> #define EFI_64BIT 5 /* Is the firmware 64-bit? */
> +#define EFI_XEN 6 /* Must we access EFI via Xen? */
>
> #ifdef CONFIG_EFI
> # ifdef CONFIG_X86
> diff --git a/include/xen/interface/platform.h
> b/include/xen/interface/platform.h
> index c57d5f6..d005f0b 100644
> --- a/include/xen/interface/platform.h
> +++ b/include/xen/interface/platform.h
> @@ -108,10 +108,111 @@ struct xenpf_platform_quirk {
> };
> DEFINE_GUEST_HANDLE_STRUCT(xenpf_platform_quirk_t);
>
> +#define XENPF_efi_runtime_call 49
> +#define XEN_EFI_get_time 1
> +#define XEN_EFI_set_time 2
> +#define XEN_EFI_get_wakeup_time 3
> +#define XEN_EFI_set_wakeup_time 4
> +#define XEN_EFI_get_next_high_monotonic_count 5
> +#define XEN_EFI_get_variable 6
> +#define XEN_EFI_set_variable 7
> +#define XEN_EFI_get_next_variable_name 8
> +#define XEN_EFI_query_variable_info 9
> +#define XEN_EFI_query_capsule_capabilities 10
> +#define XEN_EFI_update_capsule 11
> +
> +struct xenpf_efi_runtime_call {
> + uint32_t function;
> + /*
> + * This field is generally used for per sub-function flags (defined
> + * below), except for the XEN_EFI_get_next_high_monotonic_count case,
> + * where it holds the single returned value.
> + */
> + uint32_t misc;
> + unsigned long status;
> + union {
> +#define XEN_EFI_GET_TIME_SET_CLEARS_NS 0x00000001
> + struct {
> + struct xenpf_efi_time {
> + uint16_t year;
> + uint8_t month;
> + uint8_t day;
> + uint8_t hour;
> + uint8_t min;
> + uint8_t sec;
> + uint32_t ns;
> + int16_t tz;
> + uint8_t daylight;
> + } time;
> + uint32_t resolution;
> + uint32_t accuracy;
> + } get_time;
> +
> + struct xenpf_efi_time set_time;
> +
> +#define XEN_EFI_GET_WAKEUP_TIME_ENABLED 0x00000001
> +#define XEN_EFI_GET_WAKEUP_TIME_PENDING 0x00000002
> + struct xenpf_efi_time get_wakeup_time;
> +
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE 0x00000001
> +#define XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY 0x00000002
> + struct xenpf_efi_time set_wakeup_time;
> +
> +#define XEN_EFI_VARIABLE_NON_VOLATILE 0x00000001
> +#define XEN_EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002
> +#define XEN_EFI_VARIABLE_RUNTIME_ACCESS 0x00000004
> + struct {
> + GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
> + unsigned long size;
> + GUEST_HANDLE(void) data;
> + struct xenpf_efi_guid {
> + uint32_t data1;
> + uint16_t data2;
> + uint16_t data3;
> + uint8_t data4[8];
> + } vendor_guid;
> + } get_variable, set_variable;
> +
> + struct {
> + unsigned long size;
> + GUEST_HANDLE(void) name; /* UCS-2/UTF-16 string */
> + struct xenpf_efi_guid vendor_guid;
> + } get_next_variable_name;
> +
> + struct {
> + uint32_t attr;
> + uint64_t max_store_size;
> + uint64_t remain_store_size;
> + uint64_t max_size;
> + } query_variable_info;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t max_capsule_size;
> + unsigned int reset_type;
> + } query_capsule_capabilities;
> +
> + struct {
> + GUEST_HANDLE(void) capsule_header_array;
> + unsigned long capsule_count;
> + uint64_t sg_list; /* machine address */
> + } update_capsule;
> + } u;
> +};
> +DEFINE_GUEST_HANDLE_STRUCT(xenpf_efi_runtime_call);
> +
> #define XENPF_firmware_info 50
> #define XEN_FW_DISK_INFO 1 /* from int 13 AH=08/41/48 */
> #define XEN_FW_DISK_MBR_SIGNATURE 2 /* from MBR offset 0x1b8 */
> #define XEN_FW_VBEDDC_INFO 3 /* from int 10 AX=4f15 */
> +#define XEN_FW_EFI_INFO 4 /* from EFI */
> +#define XEN_FW_EFI_VERSION 0
> +#define XEN_FW_EFI_CONFIG_TABLE 1
> +#define XEN_FW_EFI_VENDOR 2
> +#define XEN_FW_EFI_MEM_INFO 3
> +#define XEN_FW_EFI_RT_VERSION 4
> +#define XEN_FW_EFI_PCI_ROM 5
> #define XEN_FW_KBD_SHIFT_FLAGS 5 /* Int16, Fn02: Get keyboard
> shift flags. */
> struct xenpf_firmware_info {
> /* IN variables. */
> @@ -143,6 +244,36 @@ struct xenpf_firmware_info {
> /* must refer to 128-byte buffer */
> GUEST_HANDLE(uchar) edid;
> } vbeddc_info; /* XEN_FW_VBEDDC_INFO */
> + union xenpf_efi_info {
> + uint32_t version;
> + struct {
> + uint64_t addr; /* EFI_CONFIGURATION_TABLE */
> + uint32_t nent;
> + } cfg;
> + struct {
> + uint32_t revision;
> + uint32_t bufsz; /* input, in bytes */
> + GUEST_HANDLE(void) name;
> + /* UCS-2/UTF-16 string */
> + } vendor;
> + struct {
> + uint64_t addr;
> + uint64_t size;
> + uint64_t attr;
> + uint32_t type;
> + } mem;
> + struct {
> + /* IN variables */
> + uint16_t segment;
> + uint8_t bus;
> + uint8_t devfn;
> + uint16_t vendor;
> + uint16_t devid;
> + /* OUT variables */
> + uint64_t address;
> + xen_ulong_t size;
> + } pci_rom;
> + } efi_info; /* XEN_FW_EFI_INFO */
>
> uint8_t kbd_shift_flags; /* XEN_FW_KBD_SHIFT_FLAGS */
> } u;
> @@ -361,6 +492,7 @@ struct xen_platform_op {
> struct xenpf_read_memtype read_memtype;
> struct xenpf_microcode_update microcode;
> struct xenpf_platform_quirk platform_quirk;
> + struct xenpf_efi_runtime_call efi_runtime_call;
> struct xenpf_firmware_info firmware_info;
> struct xenpf_enter_acpi_sleep enter_acpi_sleep;
> struct xenpf_change_freq change_freq;
> --
> 1.8.3.4
>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: Xen 4.4 development update
2013-08-15 14:12 ` Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: " Konrad Rzeszutek Wilk
@ 2013-08-15 20:24 ` Eric Shelton
2013-08-15 20:50 ` Konrad Rzeszutek Wilk
0 siblings, 1 reply; 10+ messages in thread
From: Eric Shelton @ 2013-08-15 20:24 UTC (permalink / raw)
To: Konrad Rzeszutek Wilk
Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
On Thu, Aug 15, 2013 at 10:12 AM, Konrad Rzeszutek Wilk
<konrad.wilk@oracle.com> 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.
Rather than doing that,I would suggest, as least as far as the runtime
services are concerned, that the architecture/implementation specific
code has been narrowly encapsulated - in the virt_efi_* functions in
efi.c, and in the corresponding xen_efi_* functions in xen.c. These
are registered in the function table included in the 'efi' struct and
called through there, and are essentially setter/getter functions
without any general logic. There are higher level functions, such as
efi_set_rtc_mmss(), and they use the function table to get/set EFI
info as needed, and have not been duplicated. The runtime services
look pretty cleanly implemented in this way, and introduce essentially
no changes since this general mechanism was already in place. The
only improvement I might suggest is to break out the runtime services
function pointers into a separate struct, perhaps named efi_runtime,
as it would make it a bit clearer they are runtime services accessor
methods.
The remaining functions are for initialization, and these are where
the "if efi_enabled(EFI_XEN)" and "#ifdef CONFIG_XEN" stuff crept in.
Many of the differences arise from the fact that much of what the
kernel originally did for EFI init has been moved into the hypervisor,
and the information is accessed via hypercalls. As a result, xen.c
has much less to do than efi.c, which has to concern itself with
memory mapping of the system and runtime services tables. Where dom0
is booting under Xen, various init functions were changed to return
immediately, as this extra work does not need to be done.
It sounds like I should return to what the original patches were
doing, and make use of a function table for the init functions, much
as done for the runtime services. However, as function pointers were
not in the original code, this looked a bit uglier in the first
patches, because each original efi_*_init function ended up with a
counterpart efi_*_init_generic function, which did "if (func_ptr ==
NULL) { return; } else { func_ptr(args); }", with most values being
NULL in xen.c (probably because many table entries were only called
internally in efi.c). I can make this a little less ugly by (1)
minimizing the functions in the table, and (2) making table.func_ptr()
calls instead of *_generic() calls.
Additionally it might be sensible to split up efi.c into efi_runtime.c
and efi_init.c to separately bundle the functions used during these
two phases of operation. The maintainer for the linux kernel would
have to rule on that idea...
> - When approaching Matthew I would suggest you label it as RFC - to get
> an idea of how he would like it done - as I don't think he will
> take the patch as is. He might suggest the thing I just mentioned
> above. Or perhaps make most of the 'efi_*' calls go through some form
> of function table that by default is set to baremetal_efi_calls
> (see x86_init.c)
See above. This appears to already be happening for the runtime
services calls. The problems appear to be with init code, which I
will try to resolve with a similar function table-based approach.
> - There are some code paths that just do:
> if (xen)
> return;
> But it is not clear why that is so (missing comments). This is needed
> b/c if somebody wants to redo the code in the future they would need to
> know where to place that 'if (xen) do something different'
The course laid out above will remove this code, in favor of the
additional function table.
> - You want to credit Jan Beulich in the commit description saying
> that the patch was derieved from the work that he did for SuSE Linux.
> Liang Tang took some of that - but he forgot to mention that in the
> initial post.
Definitely. If the hypercalls and original patches had not been
around, I likely would not have gone very far with this, and instead
stuck with the weird legacy BIOS boot mechanisms provided by Apple
(mainly for Bootcamp).
> - It is unclear to me why the machine_ops assigment has been changed?
Sorry, that was a result of work with a C++ codebase that generally
disfavored object-to-object assignments. The original
struct-to-struct assignment was legitimate, and will be restored.
> Thank you again for taking a stab at it! I know that getting push back
> on patches is not a thing that anybody likes - but the end goal is make
> it be fantastic and sometimes that takes a couple of rounds (or about a
> dozen as my first patches for Linux took that many revisions)
No problem on the comments. This is mainly about a cleaner and
clearer presentation on the code. I appreciate having an express
indication of the coding philosophies and design patterns for both Xen
and the Linux kernel, especially if it smooths the path through LKML.
- Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: Xen 4.4 development update
2013-08-15 20:24 ` Eric Shelton
@ 2013-08-15 20:50 ` Konrad Rzeszutek Wilk
2013-08-16 14:10 ` Konrad Rzeszutek Wilk
0 siblings, 1 reply; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-08-15 20:50 UTC (permalink / raw)
To: Eric Shelton; +Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
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@oracle.com> 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?
>
> Rather than doing that,I would suggest, as least as far as the runtime
> services are concerned, that the architecture/implementation specific
> code has been narrowly encapsulated - in the virt_efi_* functions in
> efi.c, and in the corresponding xen_efi_* functions in xen.c. These
> are registered in the function table included in the 'efi' struct and
> called through there, and are essentially setter/getter functions
> without any general logic. There are higher level functions, such as
> efi_set_rtc_mmss(), and they use the function table to get/set EFI
> info as needed, and have not been duplicated. The runtime services
> look pretty cleanly implemented in this way, and introduce essentially
> no changes since this general mechanism was already in place. The
> only improvement I might suggest is to break out the runtime services
> function pointers into a separate struct, perhaps named efi_runtime,
> as it would make it a bit clearer they are runtime services accessor
> methods.
Ok, so you are hoisting this a bit higher. That would work too - and
it would be less messier. I think getting Matthew's thoughts on this
is neccessary - as at the end of this it is his call.
>
> The remaining functions are for initialization, and these are where
> the "if efi_enabled(EFI_XEN)" and "#ifdef CONFIG_XEN" stuff crept in.
> Many of the differences arise from the fact that much of what the
> kernel originally did for EFI init has been moved into the hypervisor,
> and the information is accessed via hypercalls. As a result, xen.c
> has much less to do than efi.c, which has to concern itself with
> memory mapping of the system and runtime services tables. Where dom0
> is booting under Xen, various init functions were changed to return
> immediately, as this extra work does not need to be done.
If we prepapred the efi structures (hand-waving here) with the data that
the hypervisor has already setup and give that to this code - would that
work? Basically it would (I hope) just walk throught the same steps
that the hypervisor did, but all of this efi calls would be stubbed out.
For example the E820 - we already do some of that in setup.c so I would
think this could just prepare an memmap that has no entries.
Or get the entries from the XENMEM_machine_memory_map like in
arch/x86/xen/setup.c and just prepare the memmap.. Thought there is a
bunch of goodness happening in xen_memory_setup() that should still
be invoked.
>
> It sounds like I should return to what the original patches were
> doing, and make use of a function table for the init functions, much
> as done for the runtime services. However, as function pointers were
The original ones were much larger and the maintainer (Matthew) was
not too thrilled about them.
> not in the original code, this looked a bit uglier in the first
> patches, because each original efi_*_init function ended up with a
> counterpart efi_*_init_generic function, which did "if (func_ptr ==
> NULL) { return; } else { func_ptr(args); }", with most values being
> NULL in xen.c (probably because many table entries were only called
> internally in efi.c). I can make this a little less ugly by (1)
> minimizing the functions in the table, and (2) making table.func_ptr()
> calls instead of *_generic() calls.
>
> Additionally it might be sensible to split up efi.c into efi_runtime.c
> and efi_init.c to separately bundle the functions used during these
> two phases of operation. The maintainer for the linux kernel would
> have to rule on that idea...
Yeah, it comes back to how Matthew would like it. And I need to do some
more homework and look more dilligiently at the efi.c code. Next week
should be able to do that.
>
> > - When approaching Matthew I would suggest you label it as RFC - to get
> > an idea of how he would like it done - as I don't think he will
> > take the patch as is. He might suggest the thing I just mentioned
> > above. Or perhaps make most of the 'efi_*' calls go through some form
> > of function table that by default is set to baremetal_efi_calls
> > (see x86_init.c)
>
> See above. This appears to already be happening for the runtime
> services calls. The problems appear to be with init code, which I
> will try to resolve with a similar function table-based approach.
>
> > - There are some code paths that just do:
> > if (xen)
> > return;
> > But it is not clear why that is so (missing comments). This is needed
> > b/c if somebody wants to redo the code in the future they would need to
> > know where to place that 'if (xen) do something different'
>
> The course laid out above will remove this code, in favor of the
> additional function table.
>
> > - You want to credit Jan Beulich in the commit description saying
> > that the patch was derieved from the work that he did for SuSE Linux.
> > Liang Tang took some of that - but he forgot to mention that in the
> > initial post.
>
> Definitely. If the hypercalls and original patches had not been
> around, I likely would not have gone very far with this, and instead
> stuck with the weird legacy BIOS boot mechanisms provided by Apple
> (mainly for Bootcamp).
>
> > - It is unclear to me why the machine_ops assigment has been changed?
>
> Sorry, that was a result of work with a C++ codebase that generally
> disfavored object-to-object assignments. The original
> struct-to-struct assignment was legitimate, and will be restored.
>
> > Thank you again for taking a stab at it! I know that getting push back
> > on patches is not a thing that anybody likes - but the end goal is make
> > it be fantastic and sometimes that takes a couple of rounds (or about a
> > dozen as my first patches for Linux took that many revisions)
>
> No problem on the comments. This is mainly about a cleaner and
> clearer presentation on the code. I appreciate having an express
> indication of the coding philosophies and design patterns for both Xen
> and the Linux kernel, especially if it smooths the path through LKML.
Yeeey!
>
> - Eric
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: Xen 4.4 development update
2013-08-15 20:50 ` Konrad Rzeszutek Wilk
@ 2013-08-16 14:10 ` Konrad Rzeszutek Wilk
0 siblings, 0 replies; 10+ messages in thread
From: Konrad Rzeszutek Wilk @ 2013-08-16 14:10 UTC (permalink / raw)
To: Eric Shelton; +Cc: George Dunlap, Daniel Kiper, xen-devel@lists.xen.org
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@oracle.com> 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@oracle.com>
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@oracle.com>
---
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
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: Xen 4.4 development update
2013-08-08 20:51 ` Eric Shelton
2013-08-09 18:56 ` Daniel Kiper
@ 2013-08-20 16:13 ` Stefano Stabellini
1 sibling, 0 replies; 10+ messages in thread
From: Stefano Stabellini @ 2013-08-20 16:13 UTC (permalink / raw)
To: Eric Shelton
Cc: Ian Campbell, George Dunlap, Daniel Kiper,
xen-devel@lists.xen.org, Julien Grall
On Thu, 8 Aug 2013, Eric Shelton wrote:
> Related to this, is the Xen hypervisor booting under EFI for arm
> already?
Not yet, but it's on our todo list.
> I assume not, if Linux currently lacks the needed
> hypercalls. Does anything arm-specific need to happen in an
> EFI-friendly dom0 kernel, given that it is hypercall driven? Is there
> a platform for test?
It would be great if you could generalize your work enough so that it
would at least compile on arm.
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2013-08-20 16:13 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-08 19:38 Xen 4.4 development update Eric Shelton
2013-08-08 19:55 ` Konrad Rzeszutek Wilk
2013-08-08 20:51 ` Eric Shelton
2013-08-09 18:56 ` Daniel Kiper
2013-08-15 5:32 ` Eric Shelton
2013-08-15 14:12 ` Is: Linux-EFI code to call Xen's EFI hypercalls [RFC PATCH comments] Was:Re: " Konrad Rzeszutek Wilk
2013-08-15 20:24 ` Eric Shelton
2013-08-15 20:50 ` Konrad Rzeszutek Wilk
2013-08-16 14:10 ` Konrad Rzeszutek Wilk
2013-08-20 16:13 ` Stefano Stabellini
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.