WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] [xen-unstable] x86-64: EFI runtime code

To: xen-changelog@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] [xen-unstable] x86-64: EFI runtime code
From: Xen patchbot-unstable <patchbot@xxxxxxx>
Date: Fri, 08 Jul 2011 06:22:12 +0100
Delivery-date: Thu, 07 Jul 2011 22:23:23 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-help: <mailto:xen-changelog-request@lists.xensource.com?subject=help>
List-id: BK change log <xen-changelog.lists.xensource.com>
List-post: <mailto:xen-changelog@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.xensource.com?subject=unsubscribe>
Reply-to: xen-devel@xxxxxxxxxxxxxxxxxxx
Sender: xen-changelog-bounces@xxxxxxxxxxxxxxxxxxx
# HG changeset patch
# User Jan Beulich <jbeulich@xxxxxxxxxx>
# Date 1309249249 -3600
# Node ID d19e778442673050bba8ea8cf61585902ff81162
# Parent  8b7d00f2abb21b504f6f8e1a6cc235cee8eb0858
x86-64: EFI runtime code

This allows Dom0 access to all suitable EFI runtime services. The
actual calls into EFI are done in "physical" mode, as entering virtual
mode has been determined to be incompatible with kexec (EFI's
SetVirtualAddressMap() can be called only once, and hence the
secondary kernel can't establish its mappings). ("Physical" mode here
being quoted because this is a mode with paging enabled [otherwise
64-bit mode wouldn't work] but all mappings being 1:1.)

Open issue (not preventing this from being committed imo):

Page (and perhaps other) faults occuring while calling runtime
functions in the context of a hypercall don't get handled correctly
(they don't even seem to reach do_page_fault()). I'm intending to
investigate this further.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxxxx>
---


diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/efi/boot.c
--- a/xen/arch/x86/efi/boot.c   Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/efi/boot.c   Tue Jun 28 09:20:49 2011 +0100
@@ -16,6 +16,7 @@
 #include <xen/stringify.h>
 #include <xen/vga.h>
 #include <asm/e820.h>
+#include <asm/mm.h>
 #include <asm/msr.h>
 #include <asm/processor.h>
 
@@ -1149,6 +1150,53 @@
     for( ; ; ); /* not reached */
 }
 
+static __init void copy_mapping(unsigned long mfn, unsigned long end,
+                                bool_t (*is_valid)(unsigned long smfn,
+                                                   unsigned long emfn))
+{
+    unsigned long next;
+
+    for ( ; mfn < end; mfn = next )
+    {
+        l4_pgentry_t l4e = efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)];
+        l3_pgentry_t *l3src, *l3dst;
+        unsigned long va = (unsigned long)mfn_to_virt(mfn);
+
+        next = mfn + (1UL << (L3_PAGETABLE_SHIFT - PAGE_SHIFT));
+        if ( !is_valid(mfn, min(next, end)) )
+            continue;
+        if ( !(l4e_get_flags(l4e) & _PAGE_PRESENT) )
+        {
+            l3dst = alloc_xen_pagetable();
+            BUG_ON(!l3dst);
+            clear_page(l3dst);
+            efi_l4_pgtable[l4_table_offset(mfn << PAGE_SHIFT)] =
+                l4e_from_paddr(virt_to_maddr(l3dst), __PAGE_HYPERVISOR);
+        }
+        else
+            l3dst = l4e_to_l3e(l4e);
+        l3src = l4e_to_l3e(idle_pg_table[l4_table_offset(va)]);
+        l3dst[l3_table_offset(mfn << PAGE_SHIFT)] = l3src[l3_table_offset(va)];
+    }
+}
+
+static bool_t __init ram_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    unsigned long sz = pfn_to_pdx(emfn - 1) / PDX_GROUP_COUNT + 1;
+
+    return !(smfn & pfn_hole_mask) &&
+           find_next_bit(pdx_group_valid, sz,
+                         pfn_to_pdx(smfn) / PDX_GROUP_COUNT) < sz;
+}
+
+static bool_t __init rt_range_valid(unsigned long smfn, unsigned long emfn)
+{
+    return 1;
+}
+
+#define INVALID_VIRTUAL_ADDRESS (0xBAAADUL << \
+                                 (EFI_PAGE_SHIFT + BITS_PER_LONG - 32))
+
 void __init efi_init_memory(void)
 {
     unsigned int i;
@@ -1169,11 +1217,11 @@
         if ( !(desc->Attribute & EFI_MEMORY_RUNTIME) )
             continue;
 
+        desc->VirtualStart = INVALID_VIRTUAL_ADDRESS;
+
         smfn = PFN_DOWN(desc->PhysicalStart);
         emfn = PFN_UP(desc->PhysicalStart + len);
 
-        desc->VirtualStart = 0xBAAADUL << (EFI_PAGE_SHIFT + BITS_PER_LONG - 
32);
-
         if ( desc->Attribute & EFI_MEMORY_WB )
             /* nothing */;
         else if ( desc->Attribute & EFI_MEMORY_WT )
@@ -1217,5 +1265,34 @@
 #if 0 /* Incompatible with kexec. */
     efi_rs->SetVirtualAddressMap(efi_memmap_size, efi_mdesc_size,
                                  mdesc_ver, efi_memmap);
+#else
+    /* Set up 1:1 page tables to do runtime calls in "physical" mode. */
+    efi_l4_pgtable = alloc_xen_pagetable();
+    BUG_ON(!efi_l4_pgtable);
+    clear_page(efi_l4_pgtable);
+
+    copy_mapping(0, max_page, ram_range_valid);
+
+    /* Insert non-RAM runtime mappings. */
+    for ( i = 0; i < efi_memmap_size; i += efi_mdesc_size )
+    {
+        const EFI_MEMORY_DESCRIPTOR *desc = efi_memmap + i;
+
+        if ( desc->Attribute & EFI_MEMORY_RUNTIME )
+        {
+            if ( desc->VirtualStart != INVALID_VIRTUAL_ADDRESS )
+                copy_mapping(PFN_DOWN(desc->PhysicalStart),
+                             PFN_UP(desc->PhysicalStart +
+                                    (desc->NumberOfPages << EFI_PAGE_SHIFT)),
+                             rt_range_valid);
+            else
+                /* XXX */;
+        }
+    }
+
+    /* Insert Xen mappings. */
+    for ( i = l4_table_offset(HYPERVISOR_VIRT_START);
+          i < l4_table_offset(HYPERVISOR_VIRT_END); ++i )
+        efi_l4_pgtable[i] = idle_pg_table[i];
 #endif
 }
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/efi/compat.c
--- a/xen/arch/x86/efi/compat.c Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/efi/compat.c Tue Jun 28 09:20:49 2011 +0100
@@ -4,13 +4,27 @@
 #define efi_get_info efi_compat_get_info
 #define xenpf_efi_info compat_pf_efi_info
 
+#define efi_runtime_call efi_compat_runtime_call
+#define xenpf_efi_runtime_call compat_pf_efi_runtime_call
+
+#define xenpf_efi_guid compat_pf_efi_guid
+#define xenpf_efi_time compat_pf_efi_time
+
 #define COMPAT
 #undef DEFINE_XEN_GUEST_HANDLE
 #define DEFINE_XEN_GUEST_HANDLE DEFINE_COMPAT_HANDLE
+#undef XEN_GUEST_HANDLE
+#define XEN_GUEST_HANDLE COMPAT_HANDLE
 #undef guest_handle_okay
 #define guest_handle_okay compat_handle_okay
 #undef guest_handle_cast
 #define guest_handle_cast compat_handle_cast
+#undef __copy_from_guest
+#define __copy_from_guest __copy_from_compat
+#undef copy_from_guest_offset
+#define copy_from_guest_offset copy_from_compat_offset
+#undef copy_to_guest
+#define copy_to_guest copy_to_compat
 #undef __copy_to_guest_offset
 #define __copy_to_guest_offset __copy_to_compat_offset
 #include "runtime.c"
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/efi/efi.h
--- a/xen/arch/x86/efi/efi.h    Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/efi/efi.h    Tue Jun 28 09:20:49 2011 +0100
@@ -5,6 +5,8 @@
 #include <efi/efidevp.h>
 #include <efi/efiapi.h>
 #include <xen/efi.h>
+#include <xen/spinlock.h>
+#include <asm/page.h>
 
 extern unsigned int efi_num_ct;
 extern EFI_CONFIGURATION_TABLE *efi_ct;
@@ -16,3 +18,8 @@
 
 extern UINTN efi_memmap_size, efi_mdesc_size;
 extern void *efi_memmap;
+
+extern l4_pgentry_t *efi_l4_pgtable;
+
+unsigned long efi_rs_enter(void);
+void efi_rs_leave(unsigned long);
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/efi/runtime.c
--- a/xen/arch/x86/efi/runtime.c        Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/efi/runtime.c        Tue Jun 28 09:20:49 2011 +0100
@@ -2,6 +2,7 @@
 #include <xen/cache.h>
 #include <xen/errno.h>
 #include <xen/guest_access.h>
+#include <xen/time.h>
 
 DEFINE_XEN_GUEST_HANDLE(CHAR16);
 
@@ -19,6 +20,7 @@
 const CHAR16 *__read_mostly efi_fw_vendor;
 
 EFI_RUNTIME_SERVICES *__read_mostly efi_rs;
+static DEFINE_SPINLOCK(efi_rs_lock);
 
 UINTN __read_mostly efi_memmap_size;
 UINTN __read_mostly efi_mdesc_size;
@@ -30,6 +32,68 @@
        .smbios = EFI_INVALID_TABLE_ADDR,
 };
 
+l4_pgentry_t *__read_mostly efi_l4_pgtable;
+
+unsigned long efi_rs_enter(void)
+{
+    unsigned long cr3 = read_cr3();
+
+    spin_lock(&efi_rs_lock);
+
+    /* prevent fixup_page_fault() from doing anything */
+    irq_enter();
+
+    write_cr3(virt_to_maddr(efi_l4_pgtable));
+
+    return cr3;
+}
+
+void efi_rs_leave(unsigned long cr3)
+{
+    write_cr3(cr3);
+    irq_exit();
+    spin_unlock(&efi_rs_lock);
+}
+
+unsigned long efi_get_time(void)
+{
+    EFI_TIME time;
+    EFI_STATUS status;
+    unsigned long cr3 = efi_rs_enter();
+
+    status = efi_rs->GetTime(&time, NULL);
+    efi_rs_leave(cr3);
+
+    if ( EFI_ERROR(status) )
+        return 0;
+
+    return mktime(time.Year, time.Month, time.Day,
+                  time.Hour, time.Minute, time.Second);
+}
+
+void efi_halt_system(void)
+{
+    EFI_STATUS status;
+    unsigned long cr3 = efi_rs_enter();
+
+    status = efi_rs->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+    efi_rs_leave(cr3);
+
+    printk(XENLOG_WARNING "EFI: could not halt system (%#lx)\n", status);
+}
+
+void efi_reset_system(bool_t warm)
+{
+    EFI_STATUS status;
+    unsigned long cr3 = efi_rs_enter();
+
+    status = efi_rs->ResetSystem(warm ? EfiResetWarm : EfiResetCold,
+                                 EFI_SUCCESS, 0, NULL);
+    efi_rs_leave(cr3);
+
+    printk(XENLOG_WARNING "EFI: could not reset system (%#lx)\n", status);
+}
+
 #endif
 
 int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
@@ -86,3 +150,267 @@
 
     return 0;
 }
+
+static long gwstrlen(XEN_GUEST_HANDLE(CHAR16) str)
+{
+    unsigned long len;
+
+    for ( len = 0; ; ++len )
+    {
+        CHAR16 c;
+
+        if ( copy_from_guest_offset(&c, str, len, 1) )
+            return -EFAULT;
+        if ( !c )
+            break;
+    }
+
+    return len;
+}
+
+static inline EFI_TIME *cast_time(struct xenpf_efi_time *time)
+{
+#define chk_fld(F, f) \
+    BUILD_BUG_ON(sizeof(cast_time(NULL)->F) != sizeof(time->f) || \
+                 offsetof(EFI_TIME, F) != offsetof(struct xenpf_efi_time, f))
+    chk_fld(Year, year);
+    chk_fld(Month, month);
+    chk_fld(Day, day);
+    chk_fld(Hour, hour);
+    chk_fld(Minute, min);
+    chk_fld(Second, sec);
+    chk_fld(Nanosecond, ns);
+    chk_fld(TimeZone, tz);
+    chk_fld(Daylight, daylight);
+#undef chk_fld
+    return (void *)time;
+}
+
+static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
+{
+#define chk_fld(n) \
+    BUILD_BUG_ON(sizeof(cast_guid(NULL)->Data##n) != sizeof(guid->data##n) || \
+                 offsetof(EFI_GUID, Data##n) != \
+                 offsetof(struct xenpf_efi_guid, data##n))
+    chk_fld(1);
+    chk_fld(2);
+    chk_fld(3);
+    chk_fld(4);
+#undef chk_fld
+    return (void *)guid;
+}
+
+int efi_runtime_call(struct xenpf_efi_runtime_call *op)
+{
+    unsigned long cr3;
+    EFI_STATUS status = EFI_NOT_STARTED;
+    int rc = 0;
+
+    switch ( op->function )
+    {
+    case XEN_EFI_get_time:
+    {
+        EFI_TIME_CAPABILITIES caps;
+
+        if ( op->misc )
+            return -EINVAL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
+        efi_rs_leave(cr3);
+
+        if ( !EFI_ERROR(status) )
+        {
+            op->u.get_time.resolution = caps.Resolution;
+            op->u.get_time.accuracy = caps.Accuracy;
+            if ( caps.SetsToZero )
+                op->misc = XEN_EFI_GET_TIME_SET_CLEARS_NS;
+        }
+    }
+    break;
+
+    case XEN_EFI_set_time:
+        if ( op->misc )
+            return -EINVAL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->SetTime(cast_time(&op->u.set_time));
+        efi_rs_leave(cr3);
+        break;
+
+    case XEN_EFI_get_wakeup_time:
+    {
+        BOOLEAN enabled, pending;
+
+        if ( op->misc )
+            return -EINVAL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->GetWakeupTime(&enabled, &pending,
+                                       cast_time(&op->u.get_wakeup_time));
+        efi_rs_leave(cr3);
+
+        if ( !EFI_ERROR(status) )
+        {
+            if ( enabled )
+                op->misc |= XEN_EFI_GET_WAKEUP_TIME_ENABLED;
+            if ( pending )
+                op->misc |= XEN_EFI_GET_WAKEUP_TIME_PENDING;
+        }
+    }
+    break;
+
+    case XEN_EFI_set_wakeup_time:
+        if ( op->misc & ~(XEN_EFI_SET_WAKEUP_TIME_ENABLE |
+                          XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) )
+            return -EINVAL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->SetWakeupTime(!!(op->misc &
+                                          XEN_EFI_SET_WAKEUP_TIME_ENABLE),
+                                       (op->misc &
+                                        XEN_EFI_SET_WAKEUP_TIME_ENABLE_ONLY) ?
+                                       NULL :
+                                       cast_time(&op->u.set_wakeup_time));
+        efi_rs_leave(cr3);
+
+        op->misc = 0;
+        break;
+
+    case XEN_EFI_get_next_high_monotonic_count:
+        if ( op->misc )
+            return -EINVAL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->GetNextHighMonotonicCount(&op->misc);
+        efi_rs_leave(cr3);
+        break;
+
+    case XEN_EFI_get_variable:
+    {
+        CHAR16 *name;
+        long len;
+        unsigned char *data;
+        UINTN size;
+
+        if ( op->misc )
+            return -EINVAL;
+
+        len = gwstrlen(guest_handle_cast(op->u.get_variable.name, CHAR16));
+        if ( len < 0 )
+            return len;
+        name = xmalloc_array(CHAR16, ++len);
+        if ( !name )
+           return -ENOMEM;
+        __copy_from_guest(name, op->u.get_variable.name, len);
+
+        size = op->u.get_variable.size;
+        if ( size )
+        {
+            data = xmalloc_bytes(size);
+            if ( !data )
+            {
+                xfree(name);
+                return -ENOMEM;
+            }
+        }
+        else
+            data = NULL;
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->GetVariable(
+            name, cast_guid(&op->u.get_variable.vendor_guid),
+            &op->misc, &size, data);
+        efi_rs_leave(cr3);
+
+        if ( !EFI_ERROR(status) &&
+             copy_to_guest(op->u.get_variable.data, data, size) )
+            rc = -EFAULT;
+        op->u.get_variable.size = size;
+
+        xfree(data);
+        xfree(name);
+    }
+    break;
+
+    case XEN_EFI_set_variable:
+    {
+        CHAR16 *name;
+        long len;
+        unsigned char *data;
+
+        if ( op->misc )
+            return -EINVAL;
+
+        len = gwstrlen(guest_handle_cast(op->u.set_variable.name, CHAR16));
+        if ( len < 0 )
+            return len;
+        name = xmalloc_array(CHAR16, ++len);
+        if ( !name )
+           return -ENOMEM;
+        __copy_from_guest(name, op->u.set_variable.name, len);
+
+        data = xmalloc_bytes(op->u.set_variable.size);
+        if ( !data )
+            rc = -ENOMEM;
+        else if ( copy_from_guest(data, op->u.set_variable.data,
+                                  op->u.set_variable.size) )
+            rc = -EFAULT;
+        else
+        {
+            cr3 = efi_rs_enter();
+            status = efi_rs->SetVariable(
+                name, cast_guid(&op->u.set_variable.vendor_guid),
+                op->misc, op->u.set_variable.size, data);
+            efi_rs_leave(cr3);
+        }
+
+        xfree(data);
+        xfree(name);
+    }
+    break;
+
+    case XEN_EFI_get_next_variable_name:
+    {
+        union {
+            CHAR16 *str;
+            unsigned char *raw;
+        } name;
+        UINTN size;
+
+        if ( op->misc )
+            return -EINVAL;
+
+        size = op->u.get_next_variable_name.size;
+        name.raw = xmalloc_bytes(size);
+        if ( !name.raw )
+            return -ENOMEM;
+        copy_from_guest(name.raw, op->u.get_next_variable_name.name, size);
+
+        cr3 = efi_rs_enter();
+        status = efi_rs->GetNextVariableName(
+            &size, name.str,
+            cast_guid(&op->u.get_next_variable_name.vendor_guid));
+        efi_rs_leave(cr3);
+
+        if ( !EFI_ERROR(status) &&
+             copy_to_guest(op->u.get_next_variable_name.name, name.raw, size) )
+            rc = -EFAULT;
+        op->u.get_next_variable_name.size = size;
+
+        xfree(name.raw);
+    }
+    break;
+
+    default:
+        return -ENOSYS;
+    }
+
+#ifndef COMPAT
+    op->status = status;
+#else
+    op->status = (status & 0x3fffffff) | (status >> 62);
+#endif
+
+    return rc;
+}
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/efi/stub.c
--- a/xen/arch/x86/efi/stub.c   Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/efi/stub.c   Tue Jun 28 09:20:49 2011 +0100
@@ -1,6 +1,7 @@
 #include <xen/efi.h>
 #include <xen/errno.h>
 #include <xen/init.h>
+#include <asm/bug.h>
 
 #ifndef efi_enabled
 const bool_t efi_enabled = 0;
@@ -8,6 +9,15 @@
 
 void __init efi_init_memory(void) { }
 
+unsigned long efi_get_time(void)
+{
+    BUG();
+    return 0;
+}
+
+void efi_halt_system(void) { }
+void efi_reset_system(bool_t warm) { }
+
 int efi_get_info(uint32_t idx, union xenpf_efi_info *info)
 {
     return -ENOSYS;
@@ -15,3 +25,11 @@
 
 int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *)
     __attribute__((__alias__("efi_get_info")));
+
+int efi_runtime_call(struct xenpf_efi_runtime_call *op)
+{
+    return -ENOSYS;
+}
+
+int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *)
+    __attribute__((__alias__("efi_runtime_call")));
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/platform_hypercall.c
--- a/xen/arch/x86/platform_hypercall.c Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/platform_hypercall.c Tue Jun 28 09:20:49 2011 +0100
@@ -305,6 +305,17 @@
         }
         break;
 
+    case XENPF_efi_runtime_call:
+        ret = xsm_efi_runtime_call();
+        if ( ret )
+            break;
+
+        ret = efi_runtime_call(&op->u.efi_runtime_call);
+        if ( ret == 0 &&
+             copy_field_to_guest(u_xenpf_op, op, u.efi_runtime_call) )
+            ret = -EFAULT;
+        break;
+
     case XENPF_enter_acpi_sleep:
         ret = xsm_acpi_sleep();
         if ( ret )
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/shutdown.c
--- a/xen/arch/x86/shutdown.c   Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/shutdown.c   Tue Jun 28 09:20:49 2011 +0100
@@ -15,6 +15,7 @@
 #include <xen/console.h>
 #include <xen/shutdown.h>
 #include <xen/acpi.h>
+#include <xen/efi.h>
 #include <asm/msr.h>
 #include <asm/regs.h>
 #include <asm/mc146818rtc.h>
@@ -95,6 +96,7 @@
     watchdog_disable();
     console_start_sync();
     local_irq_enable();
+    efi_halt_system();
     smp_call_function(__machine_halt, NULL, 0);
     __machine_halt(NULL);
 }
@@ -337,6 +339,8 @@
     if ( tboot_in_measured_env() )
         tboot_shutdown(TB_SHUTDOWN_REBOOT);
 
+    efi_reset_system(reboot_mode != 0);
+
     /* Rebooting needs to touch the page at absolute address 0. */
     *((unsigned short *)__va(0x472)) = reboot_mode;
 
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/time.c
--- a/xen/arch/x86/time.c       Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/time.c       Tue Jun 28 09:20:49 2011 +0100
@@ -21,6 +21,7 @@
 #include <xen/smp.h>
 #include <xen/irq.h>
 #include <xen/softirq.h>
+#include <xen/efi.h>
 #include <xen/cpuidle.h>
 #include <xen/symbols.h>
 #include <xen/keyhandler.h>
@@ -759,6 +760,13 @@
     unsigned long res, flags;
     int i;
 
+    if ( efi_enabled )
+    {
+        res = efi_get_time();
+        if ( res )
+            return res;
+    }
+
     spin_lock_irqsave(&rtc_lock, flags);
 
     /* read RTC exactly on falling edge of update flag */
diff -r 8b7d00f2abb2 -r d19e77844267 xen/arch/x86/x86_64/platform_hypercall.c
--- a/xen/arch/x86/x86_64/platform_hypercall.c  Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/arch/x86/x86_64/platform_hypercall.c  Tue Jun 28 09:20:49 2011 +0100
@@ -12,6 +12,7 @@
 #define do_platform_op(x)   compat_platform_op(_##x)
 
 #define efi_get_info        efi_compat_get_info
+#define efi_runtime_call(x) efi_compat_runtime_call(x)
 
 #define xen_processor_px    compat_processor_px
 #define xen_processor_px_t  compat_processor_px_t
diff -r 8b7d00f2abb2 -r d19e77844267 xen/include/public/platform.h
--- a/xen/include/public/platform.h     Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/include/public/platform.h     Tue Jun 28 09:20:49 2011 +0100
@@ -114,6 +114,77 @@
 typedef struct xenpf_platform_quirk xenpf_platform_quirk_t;
 DEFINE_XEN_GUEST_HANDLE(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
+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 {
+            XEN_GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+            unsigned long size;
+            XEN_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;
+            XEN_GUEST_HANDLE(void) name;  /* UCS-2/UTF-16 string */
+            struct xenpf_efi_guid vendor_guid;
+        } get_next_variable_name;
+    } u;
+};
+typedef struct xenpf_efi_runtime_call xenpf_efi_runtime_call_t;
+DEFINE_XEN_GUEST_HANDLE(xenpf_efi_runtime_call_t);
+
 #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 */
@@ -388,6 +459,7 @@
         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;
diff -r 8b7d00f2abb2 -r d19e77844267 xen/include/xen/efi.h
--- a/xen/include/xen/efi.h     Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/include/xen/efi.h     Tue Jun 28 09:20:49 2011 +0100
@@ -29,10 +29,18 @@
 union xenpf_efi_info;
 union compat_pf_efi_info;
 
+struct xenpf_efi_runtime_call;
+struct compat_pf_efi_runtime_call;
+
 void efi_init_memory(void);
+unsigned long efi_get_time(void);
+void efi_halt_system(void);
+void efi_reset_system(bool_t warm);
 #ifndef COMPAT
 int efi_get_info(uint32_t idx, union xenpf_efi_info *);
+int efi_runtime_call(struct xenpf_efi_runtime_call *);
 #endif
 int efi_compat_get_info(uint32_t idx, union compat_pf_efi_info *);
+int efi_compat_runtime_call(struct compat_pf_efi_runtime_call *);
 
 #endif /* __XEN_EFI_H__ */
diff -r 8b7d00f2abb2 -r d19e77844267 xen/include/xsm/xsm.h
--- a/xen/include/xsm/xsm.h     Tue Jun 28 09:19:35 2011 +0100
+++ b/xen/include/xsm/xsm.h     Tue Jun 28 09:20:49 2011 +0100
@@ -132,6 +132,7 @@
     int (*physinfo) (void);
     int (*platform_quirk) (uint32_t);
     int (*firmware_info) (void);
+    int (*efi_runtime_call) (void);
     int (*acpi_sleep) (void);
     int (*change_freq) (void);
     int (*getidletime) (void);
@@ -553,6 +554,11 @@
     return xsm_call(firmware_info());
 }
 
+static inline int xsm_efi_runtime_call (void)
+{
+    return xsm_call(efi_runtime_call());
+}
+
 static inline int xsm_acpi_sleep (void)
 {
     return xsm_call(acpi_sleep());

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] [xen-unstable] x86-64: EFI runtime code, Xen patchbot-unstable <=