EFI support backports
cover EFI support backports
From: Darren Hart <[email protected]>
The following patches have been merged back from upstream to address various issues with the EFI boot process. These are intended to be merged with yocto/standard/base.
Please watch for a subsequent patch adding a series of efi config fragments.
The following changes since commit ab1de8c21d2b1d084b8488496d75cc54fcd94f02:
Merge commit 'v3.0.10' into yocto/standard/base (2011-11-23 00:31:29 -0500)
are available in the git repository at:
git://git.infradead.org/users/dvhart/linux-yocto-3.0.git dvhart/standard/efi
http://git.infradead.org/users/dvhart/linux-yocto-3.0.git/shortlog/refs/heads/dvhart/standard/efi
Matt Fleming (2):
x86/rtc: Don't recursively acquire rtc_lock
x86, efi: Make efi_call_phys_prelog() CONFIG_RELOCATABLE-aware
Maurice Ma (1):
x86, efi: Convert efi_phys_get_time() args to physical addresses
arch/x86/kernel/rtc.c | 23 ++++++++++++----------- arch/x86/platform/efi/efi.c | 3 ++- arch/x86/platform/efi/efi_32.c | 22 +++++++++++++--------- arch/x86/platform/mrst/vrtc.c | 9 +++++++++ 4 files changed, 36 insertions(+), 21 deletions(-)
Signature · 1 line
1.7.6.4
PATCH 1/3 x86/rtc: Don't recursively acquire rtc_lock
From: Matt Fleming <[email protected]>
A deadlock was introduced on x86 in commit ef68c8f87ed1 ("x86:
Serialize EFI time accesses on rtc_lock") because efi_get_time() and friends can be called with rtc_lock already held by read_persistent_time(), e.g.:
timekeeping_init()
read_persistent_clock() <-- acquire rtc_lock
efi_get_time()
phys_efi_get_time() <-- acquire rtc_lock <DEADLOCK>
To fix this let's push the locking down into the get_wallclock() and set_wallclock() implementations. Only the clock implementations that access the x86 RTC directly need to acquire rtc_lock, so it makes sense to push the locking down into the rtc, vrtc and efi code.
The virtualization implementations don't require rtc_lock to be held because they provide their own serialization.
--- arch/x86/kernel/rtc.c | 23 ++++++++++++----------- arch/x86/platform/mrst/vrtc.c | 9 +++++++++ 2 files changed, 21 insertions(+), 11 deletions(-)
arch/x86/kernel/rtc.c +12 -11
@@ -42,8 +42,11 @@ int mach_set_rtc_mmss(unsigned long nowtime) {int real_seconds, real_minutes, cmos_minutes;unsigned char save_control, save_freq_select; +unsigned long flags;int retval =0 ; +spin_lock_irqsave (&rtc_lock, flags); +/* tell the clock it's being set */ save_control =CMOS_READ (RTC_CONTROL );CMOS_WRITE ((save_control|RTC_SET ),RTC_CONTROL );
@@ -93,12 +96,17 @@ int mach_set_rtc_mmss(unsigned long nowtime)CMOS_WRITE (save_control,RTC_CONTROL );CMOS_WRITE (save_freq_select,RTC_FREQ_SELECT ); +spin_unlock_irqrestore (&rtc_lock, flags); +return retval; }unsigned long mach_get_cmos_time (void ) {unsigned int status, year, mon, day, hour, min, sec, century =0 ; +unsigned long flags; + +spin_lock_irqsave (&rtc_lock, flags);/* * If UIP is clear, then we have >= 244 microseconds before
@@ -125,6 +133,8 @@ unsigned long mach_get_cmos_time(void) status =CMOS_READ (RTC_CONTROL );WARN_ON_ONCE (RTC_ALWAYS_BCD && (status &RTC_DM_BINARY )); +spin_unlock_irqrestore (&rtc_lock, flags); +if (RTC_ALWAYS_BCD || !(status &RTC_DM_BINARY )) { sec =bcd2bin (sec); min =bcd2bin (min);
@@ -169,24 +179,15 @@ EXPORT_SYMBOL(rtc_cmos_write);int update_persistent_clock (struct timespec now) { -unsigned long flags; -int retval; - -spin_lock_irqsave (&rtc_lock, flags); - retval = x86_platform.set_wallclock (now.tv_sec); -spin_unlock_irqrestore (&rtc_lock, flags); - -return retval; +return x86_platform.set_wallclock (now.tv_sec); }/* not static: needed by APM */ void read_persistent_clock (struct timespec *ts) { -unsigned long retval, flags; +unsigned long retval; -spin_lock_irqsave (&rtc_lock, flags); retval = x86_platform.get_wallclock (); -spin_unlock_irqrestore (&rtc_lock, flags); ts->tv_sec = retval; ts->tv_nsec =0 ;
arch/x86/platform/mrst/vrtc.c +9 -0
@@ -58,8 +58,11 @@ EXPORT_SYMBOL_GPL(vrtc_cmos_write);unsigned long vrtc_get_time (void ) {u8 sec, min, hour, mday, mon; +unsigned long flags;u32 year; +spin_lock_irqsave (&rtc_lock, flags); +while ((vrtc_cmos_read (RTC_FREQ_SELECT ) &RTC_UIP ))cpu_relax ();
@@ -70,6 +73,8 @@ unsigned long vrtc_get_time(void) mon =vrtc_cmos_read (RTC_MONTH ); year =vrtc_cmos_read (RTC_YEAR ); +spin_unlock_irqrestore (&rtc_lock, flags); +/* vRTC YEAR reg contains the offset to 1960 */ year +=1960 ;
@@ -83,8 +88,10 @@ unsigned long vrtc_get_time(void)int vrtc_set_mmss (unsigned long nowtime) {int real_sec, real_min; +unsigned long flags;int vrtc_min; +spin_lock_irqsave (&rtc_lock, flags); vrtc_min =vrtc_cmos_read (RTC_MINUTES ); real_sec = nowtime %60 ;
@@ -95,6 +102,8 @@ int vrtc_set_mmss(unsigned long nowtime)vrtc_cmos_write (real_sec,RTC_SECONDS );vrtc_cmos_write (real_min,RTC_MINUTES ); +spin_unlock_irqrestore (&rtc_lock, flags); +return 0 ; }
Signature · 1 line
1.7.6.4
PATCH 2/3 x86, efi: Make efi_call_phys_prelog() CONFIG_RELOCATABLE-aware
In reply to Darren HartFrom: Matt Fleming <[email protected]>
efi_call_phys_prelog() assumes that the kernel was loaded at a physical address within the first 8MB of ram, usually 0x1000000. However, this isn't the case with a CONFIG_RELOCATABLE=y kernel which could have been loaded anywhere in the physical address space.
Replace the hardcoded pgd_index(0) and pgd_index(PAGE_OFFSET) with the runtime addresses of the kernel in the physical and virtual space, respectively.
--- arch/x86/platform/efi/efi_32.c | 22 +++++++++++++--------- 1 files changed, 13 insertions(+), 9 deletions(-)
arch/x86/platform/efi/efi_32.c +13 -9
@@ -44,8 +44,12 @@ void efi_call_phys_prelog(void) {unsigned long cr4;unsigned long temp; +unsigned long phys_addr, virt_addr;struct desc_ptr gdt_descr; + virt_addr = (unsigned long )_text; + phys_addr = virt_addr -PAGE_OFFSET ; +local_irq_save (efi_rt_eflags);/*
@@ -57,18 +61,18 @@ void efi_call_phys_prelog(void)if (cr4 &X86_CR4_PAE ) { efi_bak_pg_dir_pointer[0 ].pgd = - swapper_pg_dir[pgd_index (0 )].pgd; - swapper_pg_dir[0 ].pgd = - swapper_pg_dir[pgd_index (PAGE_OFFSET )].pgd; + swapper_pg_dir[pgd_index (phys_addr)].pgd; + swapper_pg_dir[pgd_index (phys_addr)].pgd = + swapper_pg_dir[pgd_index (virt_addr)].pgd; }else { efi_bak_pg_dir_pointer[0 ].pgd = - swapper_pg_dir[pgd_index (0 )].pgd; + swapper_pg_dir[pgd_index (phys_addr)].pgd; efi_bak_pg_dir_pointer[1 ].pgd = - swapper_pg_dir[pgd_index (0x400000 )].pgd; - swapper_pg_dir[pgd_index (0 )].pgd = - swapper_pg_dir[pgd_index (PAGE_OFFSET )].pgd; - temp =PAGE_OFFSET +0x400000 ; - swapper_pg_dir[pgd_index (0x400000 )].pgd = + swapper_pg_dir[pgd_index (phys_addr +0x400000 )].pgd; + swapper_pg_dir[pgd_index (phys_addr)].pgd = + swapper_pg_dir[pgd_index (virt_addr)].pgd; + temp = virt_addr +0x400000 ; + swapper_pg_dir[pgd_index (phys_addr +0x400000 )].pgd = swapper_pg_dir[pgd_index (temp)].pgd; }
Signature · 1 line
1.7.6.4
PATCH 3/3 x86, efi: Convert efi_phys_get_time() args to physical addresses
In reply to Darren HartFrom: Maurice Ma <[email protected]>
Because callers of efi_phys_get_time() pass virtual stack addresses as arguments, we need to find their corresponding physical addresses and when calling GetTime() in physical mode.
Without this patch the following line is printed on boot,
"Oops: efitime: can't read time!"
--- arch/x86/platform/efi/efi.c | 3 ++- 1 files changed, 2 insertions(+), 1 deletions(-)
arch/x86/platform/efi/efi.c +2 -1
@@ -167,7 +167,8 @@ static efi_status_t __init phys_efi_get_time(efi_time_t *tm,efi_status_t status;efi_call_phys_prelog (); - status =efi_call_phys2 (efi_phys.get_time, tm, tc); + status =efi_call_phys2 (efi_phys.get_time,virt_to_phys (tm), +virt_to_phys (tc));efi_call_phys_epilog ();return status; }
Signature · 1 line
1.7.6.4
Bruce Ashfield
AppliedQuoted 7 lines · Darren Hart
From: Darren Hart<[email protected]>
The following patches have been merged back from upstream to address various issues with the EFI boot process. These are intended to be merged with yocto/standard/base.
Please watch for a subsequent patch adding a series of efi config fragments.
Merged to base and all the BSP branches. I've put it in with my pending 3.0.12 pull request, which should be out ASAP.
Bruce
Quoted 23 lines
The following changes since commit
ab1de8c21d2b1d084b8488496d75cc54fcd94f02:Merge commit 'v3.0.10' into yocto/standard/base (2011-11-23 00:31:29 -0500)are available in the git repository at:
git://git.infradead.org/users/dvhart/linux-yocto-3.0.gitdvhart/standard/efi
http://git.infradead.org/users/dvhart/linux-yocto-3.0.git/shortlog/refs/heads/dvhart/standard/efiMatt Fleming (2):
x86/rtc: Don't recursively acquirertc_lock
x86, efi: Makeefi_call_phys_prelog()CONFIG_RELOCATABLE-awareMaurice Ma (1):
x86, efi: Convertefi_phys_get_time()args to physical addressesarch/x86/kernel/rtc.c | 23 ++++++++++++----------- arch/x86/platform/efi/efi.c | 3 ++- arch/x86/platform/efi/efi_32.c | 22 +++++++++++++--------- arch/x86/platform/mrst/vrtc.c | 9 +++++++++ 4 files changed, 36 insertions(+), 21 deletions(-)