aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/efi
diff options
context:
space:
mode:
authorJan Beulich <jbeulich@novell.com>2011-07-19 14:10:53 +0100
committerJan Beulich <jbeulich@novell.com>2011-07-19 14:10:53 +0100
commit876895c30294a8caead2386dcb7d17af88ed7cfd (patch)
tree4b6d42f576de3c67bdecb94276f718387badb0de /xen/arch/x86/efi
parente4c3755d4dd746511a87b9f7da7199fcd3ee0333 (diff)
downloadxen-876895c30294a8caead2386dcb7d17af88ed7cfd.tar.gz
xen-876895c30294a8caead2386dcb7d17af88ed7cfd.tar.bz2
xen-876895c30294a8caead2386dcb7d17af88ed7cfd.zip
x86: consistently serialize CMOS/RTC accesses on rtc_lock
Since RTC/CMOS accesses aren't atomic, there are possible races between code paths setting the index register and subsequently reading/writing the data register. This is supposed to be dealt with by acquiring rtc_lock, but two places up to now lacked respective synchronization: Accesses to the EFI time functions and smpboot_{setup,restore}_warm_reset_vector(). This in turn requires no longer directly passing through guest writes to the index register, but instead using a machanism similar to that for PCI config space method 1 accesses. Signed-off-by: Jan Beulich <jbeulich@novell.com>
Diffstat (limited to 'xen/arch/x86/efi')
-rw-r--r--xen/arch/x86/efi/runtime.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/xen/arch/x86/efi/runtime.c b/xen/arch/x86/efi/runtime.c
index a79e8c6745..b95aa798ca 100644
--- a/xen/arch/x86/efi/runtime.c
+++ b/xen/arch/x86/efi/runtime.c
@@ -2,8 +2,9 @@
#include <xen/cache.h>
#include <xen/errno.h>
#include <xen/guest_access.h>
-#include <xen/time.h>
#include <xen/irq.h>
+#include <xen/time.h>
+#include <asm/mc146818rtc.h>
DEFINE_XEN_GUEST_HANDLE(CHAR16);
@@ -81,9 +82,11 @@ unsigned long efi_get_time(void)
{
EFI_TIME time;
EFI_STATUS status;
- unsigned long cr3 = efi_rs_enter();
+ unsigned long cr3 = efi_rs_enter(), flags;
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetTime(&time, NULL);
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( EFI_ERROR(status) )
@@ -224,7 +227,7 @@ static inline EFI_GUID *cast_guid(struct xenpf_efi_guid *guid)
int efi_runtime_call(struct xenpf_efi_runtime_call *op)
{
- unsigned long cr3;
+ unsigned long cr3, flags;
EFI_STATUS status = EFI_NOT_STARTED;
int rc = 0;
@@ -238,7 +241,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetTime(cast_time(&op->u.get_time.time), &caps);
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( !EFI_ERROR(status) )
@@ -256,7 +261,9 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->SetTime(cast_time(&op->u.set_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
break;
@@ -268,8 +275,10 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
status = efi_rs->GetWakeupTime(&enabled, &pending,
cast_time(&op->u.get_wakeup_time));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
if ( !EFI_ERROR(status) )
@@ -288,12 +297,14 @@ int efi_runtime_call(struct xenpf_efi_runtime_call *op)
return -EINVAL;
cr3 = efi_rs_enter();
+ spin_lock_irqsave(&rtc_lock, flags);
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));
+ spin_unlock_irqrestore(&rtc_lock, flags);
efi_rs_leave(cr3);
op->misc = 0;