diff options
author | Jan Beulich <jbeulich@novell.com> | 2011-07-19 14:10:53 +0100 |
---|---|---|
committer | Jan Beulich <jbeulich@novell.com> | 2011-07-19 14:10:53 +0100 |
commit | 876895c30294a8caead2386dcb7d17af88ed7cfd (patch) | |
tree | 4b6d42f576de3c67bdecb94276f718387badb0de /xen/arch/x86/efi | |
parent | e4c3755d4dd746511a87b9f7da7199fcd3ee0333 (diff) | |
download | xen-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.c | 17 |
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; |