2019-02-07 04:26:10

by Hedi Berriche

[permalink] [raw]
Subject: [Patch v2 0/4] Protect against concurrent calls into UV BIOS

Changes since v1:

Addressed comments from Bhupesh Sharma, Thomas Gleixner, and Ard Biesheuvel:

* made __uv_bios_call() static
* moved the efi_enabled() cleanup to its own patchlet
* explained the reason for renaming the efi_runtime_lock semaphore
* dropped the reviewed-bys as they should be given on the mailing list
* Cc'ng [email protected] given the nature of the problem addressed by the patches


---

Calls into UV BIOS were not being serialised which is wrong as it violates EFI
runtime rules, and bad as it does result in all sorts of potentially hard to
track down hangs and panics when efi_scratch.prev_mm gets clobbered whenever
efi_switch_mm() gets called concurrently from two different CPUs.

Patch #1 makes the efi_runtime_lock semaphore visible to EFI runtime callers
defined outside drivers/firmware/efi/runtime-wrappers.c in preparation for
using it to serialise calls into UV BIOS; the lock is also renamed to
efi_runtime_sem so that it can coexist with the efi_runtime_lock spinlock
defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is enabled.

Patch #2 removes uv_bios_call_reentrant() because it's dead code.

Patch #3 is a cleanup that drops test_bit() in favour of the ad hoc efi_enabled().

Patch #4 makes uv_bios_call() variants use efi_runtime_sem to protect against
concurrency.

Cc: Russ Anderson <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Dimitri Sivanich <[email protected]>
Cc: Steve Wahl <[email protected]>
Cc: [email protected]

Hedi Berriche (4):
efi/x86: turn EFI runtime semaphore into a global lock
x86/platform/UV: kill uv_bios_call_reentrant() as it has no callers
x86/platform/UV: use efi_enabled() instead of test_bit()
x86/platform/UV: use efi_runtime_sem to serialise BIOS calls

arch/x86/include/asm/uv/bios.h | 4 +-
arch/x86/platform/uv/bios_uv.c | 33 ++++++++------
drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
include/linux/efi.h | 3 ++
4 files changed, 55 insertions(+), 45 deletions(-)

--
2.20.1



2019-02-07 04:23:42

by Hedi Berriche

[permalink] [raw]
Subject: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

Make efi_runtime_lock semaphore global so that it can be used by EFI
runtime callers that may be defined outside efi/runtime-wrappers.c.

Also now that efi_runtime_lock semaphore is no longer static, rename it
to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
enabled.

The immediate motivation of this change is to serialise UV platform BIOS
calls using the efi_runtime_sem semaphore.

No functional changes.

Cc: Russ Anderson <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Dimitri Sivanich <[email protected]>
Cc: Steve Wahl <[email protected]>
Cc: [email protected]
Signed-off-by: Hedi Berriche <[email protected]>
---
drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
include/linux/efi.h | 3 ++
2 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
index 8903b9ccfc2b..ec60d6227925 100644
--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
* @rts_arg<1-5>: efi_runtime_service() function arguments
*
* Accesses to efi_runtime_services() are serialized by a binary
- * semaphore (efi_runtime_lock) and caller waits until the work is
+ * semaphore (efi_runtime_sem) and caller waits until the work is
* finished, hence _only_ one work is queued at a time and the caller
* thread waits for completion.
*/
@@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
* none of the remaining functions are actually ever called at runtime.
* So let's just use a single lock to serialize all Runtime Services calls.
*/
-static DEFINE_SEMAPHORE(efi_runtime_lock);
+DEFINE_SEMAPHORE(efi_runtime_sem);

/*
* Calls the appropriate efi_runtime_service() with the appropriate
@@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
data);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
NULL, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
data);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
{
efi_status_t status;

- if (down_trylock(&efi_runtime_lock))
+ if (down_trylock(&efi_runtime_sem))
return EFI_NOT_READY;

status = efi_call_virt(set_variable, name, vendor, attr, data_size,
data);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
remaining_space, max_variable_size, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

- if (down_trylock(&efi_runtime_lock))
+ if (down_trylock(&efi_runtime_sem))
return EFI_NOT_READY;

status = efi_call_virt(query_variable_info, attr, storage_space,
remaining_space, max_variable_size);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
{
efi_status_t status;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
NULL, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
unsigned long data_size,
efi_char16_t *data)
{
- if (down_interruptible(&efi_runtime_lock)) {
+ if (down_interruptible(&efi_runtime_sem)) {
pr_warn("failed to invoke the reset_system() runtime service:\n"
"could not get exclusive access to the firmware\n");
return;
}
efi_rts_work.efi_rts_id = RESET_SYSTEM;
__efi_call_virt(reset_system, reset_type, status, data_size, data);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
}

static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
@@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
NULL, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

@@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
return EFI_UNSUPPORTED;

- if (down_interruptible(&efi_runtime_lock))
+ if (down_interruptible(&efi_runtime_sem))
return EFI_ABORTED;
status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
max_size, reset_type, NULL);
- up(&efi_runtime_lock);
+ up(&efi_runtime_sem);
return status;
}

diff --git a/include/linux/efi.h b/include/linux/efi.h
index 45ff763fba76..930cd20842b8 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
/* Workqueue to queue EFI Runtime Services */
extern struct workqueue_struct *efi_rts_wq;

+/* EFI runtime semaphore */
+extern struct semaphore efi_runtime_sem;
+
struct linux_efi_memreserve {
int size; // allocated size of the array
atomic_t count; // number of entries used
--
2.20.1


2019-02-07 04:23:52

by Hedi Berriche

[permalink] [raw]
Subject: [Patch v2 4/4] x86/platform/UV: use efi_runtime_sem to serialise BIOS calls

Calls into UV firmware must be protected against concurrency, use the
now visible efi_runtime_sem lock to serialise them.

Cc: Russ Anderson <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Dimitri Sivanich <[email protected]>
Cc: Steve Wahl <[email protected]>
Cc: [email protected]
Signed-off-by: Hedi Berriche <[email protected]>
---
arch/x86/include/asm/uv/bios.h | 3 ++-
arch/x86/platform/uv/bios_uv.c | 23 +++++++++++++++++++++--
2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index 4eee646544b2..581e2978a16c 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -48,7 +48,8 @@ enum {
BIOS_STATUS_SUCCESS = 0,
BIOS_STATUS_UNIMPLEMENTED = -ENOSYS,
BIOS_STATUS_EINVAL = -EINVAL,
- BIOS_STATUS_UNAVAIL = -EBUSY
+ BIOS_STATUS_UNAVAIL = -EBUSY,
+ BIOS_STATUS_ABORT = -EINTR,
};

/* Address map parameters */
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 8bace0ca9e57..e779b2a128ea 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -29,7 +29,8 @@

struct uv_systab *uv_systab;

-s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
+ u64 a4, u64 a5)
{
struct uv_systab *tab = uv_systab;
s64 ret;
@@ -51,6 +52,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)

return ret;
}
+
+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+{
+ s64 ret;
+
+ if (down_interruptible(&efi_runtime_sem))
+ return BIOS_STATUS_ABORT;
+
+ ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
+ up(&efi_runtime_sem);
+
+ return ret;
+}
EXPORT_SYMBOL_GPL(uv_bios_call);

s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -59,10 +73,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
unsigned long bios_flags;
s64 ret;

+ if (down_interruptible(&efi_runtime_sem))
+ return BIOS_STATUS_ABORT;
+
local_irq_save(bios_flags);
- ret = uv_bios_call(which, a1, a2, a3, a4, a5);
+ ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
local_irq_restore(bios_flags);

+ up(&efi_runtime_sem);
+
return ret;
}

--
2.20.1


2019-02-07 07:45:14

by Hedi Berriche

[permalink] [raw]
Subject: [Patch v2 2/4] x86/platform/UV: kill uv_bios_call_reentrant() as it has no callers

uv_bios_call_reentrant() has no callers nor is it exported, kill it.

Cc: Russ Anderson <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Dimitri Sivanich <[email protected]>
Cc: Steve Wahl <[email protected]>
Cc: [email protected]
Signed-off-by: Hedi Berriche <[email protected]>
---
arch/x86/include/asm/uv/bios.h | 1 -
arch/x86/platform/uv/bios_uv.c | 12 ------------
2 files changed, 13 deletions(-)

diff --git a/arch/x86/include/asm/uv/bios.h b/arch/x86/include/asm/uv/bios.h
index e652a7cc6186..4eee646544b2 100644
--- a/arch/x86/include/asm/uv/bios.h
+++ b/arch/x86/include/asm/uv/bios.h
@@ -140,7 +140,6 @@ enum uv_memprotect {
*/
extern s64 uv_bios_call(enum uv_bios_cmd, u64, u64, u64, u64, u64);
extern s64 uv_bios_call_irqsave(enum uv_bios_cmd, u64, u64, u64, u64, u64);
-extern s64 uv_bios_call_reentrant(enum uv_bios_cmd, u64, u64, u64, u64, u64);

extern s64 uv_bios_get_sn_info(int, int *, long *, long *, long *, long *);
extern s64 uv_bios_freq_base(u64, u64 *);
diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index 4a6a5a26c582..cd05af157763 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -66,18 +66,6 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
return ret;
}

-s64 uv_bios_call_reentrant(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
- u64 a4, u64 a5)
-{
- s64 ret;
-
- preempt_disable();
- ret = uv_bios_call(which, a1, a2, a3, a4, a5);
- preempt_enable();
-
- return ret;
-}
-

long sn_partition_id;
EXPORT_SYMBOL_GPL(sn_partition_id);
--
2.20.1


2019-02-07 12:08:35

by Hedi Berriche

[permalink] [raw]
Subject: [Patch v2 3/4] x86/platform/UV: use efi_enabled() instead of test_bit()

Use ad hoc efi_enabled() instead of fiddling with test_bit().

Cleanup, no functional changes.

Cc: Russ Anderson <[email protected]>
Cc: Mike Travis <[email protected]>
Cc: Dimitri Sivanich <[email protected]>
Cc: Steve Wahl <[email protected]>
Cc: [email protected]
Signed-off-by: Hedi Berriche <[email protected]>
---
arch/x86/platform/uv/bios_uv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/platform/uv/bios_uv.c b/arch/x86/platform/uv/bios_uv.c
index cd05af157763..8bace0ca9e57 100644
--- a/arch/x86/platform/uv/bios_uv.c
+++ b/arch/x86/platform/uv/bios_uv.c
@@ -44,7 +44,7 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
* If EFI_OLD_MEMMAP is set, we need to fall back to using our old EFI
* callback method, which uses efi_call() directly, with the kernel page tables:
*/
- if (unlikely(test_bit(EFI_OLD_MEMMAP, &efi.flags)))
+ if (unlikely(efi_enabled(EFI_OLD_MEMMAP)))
ret = efi_call((void *)__va(tab->function), (u64)which, a1, a2, a3, a4, a5);
else
ret = efi_call_virt_pointer(tab, function, (u64)which, a1, a2, a3, a4, a5);
--
2.20.1


2019-02-07 16:06:13

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
>
> Make efi_runtime_lock semaphore global so that it can be used by EFI
> runtime callers that may be defined outside efi/runtime-wrappers.c.
>
> Also now that efi_runtime_lock semaphore is no longer static, rename it
> to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
> defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
> enabled.
>
> The immediate motivation of this change is to serialise UV platform BIOS
> calls using the efi_runtime_sem semaphore.
>
> No functional changes.
>
> Cc: Russ Anderson <[email protected]>
> Cc: Mike Travis <[email protected]>
> Cc: Dimitri Sivanich <[email protected]>
> Cc: Steve Wahl <[email protected]>
> Cc: [email protected]
> Signed-off-by: Hedi Berriche <[email protected]>

Hello Hedi,

Same feedback as on v1: please don't rename the lock.


> ---
> drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
> include/linux/efi.h | 3 ++
> 2 files changed, 33 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
> index 8903b9ccfc2b..ec60d6227925 100644
> --- a/drivers/firmware/efi/runtime-wrappers.c
> +++ b/drivers/firmware/efi/runtime-wrappers.c
> @@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
> * @rts_arg<1-5>: efi_runtime_service() function arguments
> *
> * Accesses to efi_runtime_services() are serialized by a binary
> - * semaphore (efi_runtime_lock) and caller waits until the work is
> + * semaphore (efi_runtime_sem) and caller waits until the work is
> * finished, hence _only_ one work is queued at a time and the caller
> * thread waits for completion.
> */
> @@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
> * none of the remaining functions are actually ever called at runtime.
> * So let's just use a single lock to serialize all Runtime Services calls.
> */
> -static DEFINE_SEMAPHORE(efi_runtime_lock);
> +DEFINE_SEMAPHORE(efi_runtime_sem);
>
> /*
> * Calls the appropriate efi_runtime_service() with the appropriate
> @@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
> NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
> NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
> data);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
> NULL, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
> data);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
> {
> efi_status_t status;
>
> - if (down_trylock(&efi_runtime_lock))
> + if (down_trylock(&efi_runtime_sem))
> return EFI_NOT_READY;
>
> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
> data);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> return EFI_UNSUPPORTED;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
> remaining_space, max_variable_size, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> return EFI_UNSUPPORTED;
>
> - if (down_trylock(&efi_runtime_lock))
> + if (down_trylock(&efi_runtime_sem))
> return EFI_NOT_READY;
>
> status = efi_call_virt(query_variable_info, attr, storage_space,
> remaining_space, max_variable_size);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
> {
> efi_status_t status;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
> NULL, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
> unsigned long data_size,
> efi_char16_t *data)
> {
> - if (down_interruptible(&efi_runtime_lock)) {
> + if (down_interruptible(&efi_runtime_sem)) {
> pr_warn("failed to invoke the reset_system() runtime service:\n"
> "could not get exclusive access to the firmware\n");
> return;
> }
> efi_rts_work.efi_rts_id = RESET_SYSTEM;
> __efi_call_virt(reset_system, reset_type, status, data_size, data);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> }
>
> static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> @@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> return EFI_UNSUPPORTED;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
> NULL, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> @@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> return EFI_UNSUPPORTED;
>
> - if (down_interruptible(&efi_runtime_lock))
> + if (down_interruptible(&efi_runtime_sem))
> return EFI_ABORTED;
> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
> max_size, reset_type, NULL);
> - up(&efi_runtime_lock);
> + up(&efi_runtime_sem);
> return status;
> }
>
> diff --git a/include/linux/efi.h b/include/linux/efi.h
> index 45ff763fba76..930cd20842b8 100644
> --- a/include/linux/efi.h
> +++ b/include/linux/efi.h
> @@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
> /* Workqueue to queue EFI Runtime Services */
> extern struct workqueue_struct *efi_rts_wq;
>
> +/* EFI runtime semaphore */
> +extern struct semaphore efi_runtime_sem;
> +
> struct linux_efi_memreserve {
> int size; // allocated size of the array
> atomic_t count; // number of entries used
> --
> 2.20.1
>

2019-02-07 17:39:40

by Hedi Berriche

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Thu, Feb 07, 2019 at 16:05 Ard Biesheuvel wrote:
>On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
>>
>> Make efi_runtime_lock semaphore global so that it can be used by EFI
>> runtime callers that may be defined outside efi/runtime-wrappers.c.
>>
>> Also now that efi_runtime_lock semaphore is no longer static, rename it
>> to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
>> defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
>> enabled.
>>
>> The immediate motivation of this change is to serialise UV platform BIOS
>> calls using the efi_runtime_sem semaphore.
>>
>> No functional changes.
>>
>> Cc: Russ Anderson <[email protected]>
>> Cc: Mike Travis <[email protected]>
>> Cc: Dimitri Sivanich <[email protected]>
>> Cc: Steve Wahl <[email protected]>
>> Cc: [email protected]
>> Signed-off-by: Hedi Berriche <[email protected]>
>
>Hello Hedi,

Hi Ard,

>Same feedback as on v1: please don't rename the lock.

With the efi_runtime_lock semaphore being no longer static, not renaming it
will cause a compile failure as it will clash with the declaration of the
efi_runtime_lock *spinlock* in arch/x86/platform/efi/efi_64.c in the
CONFIG_EFI_MIXED case.

>> ---
>> drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
>> include/linux/efi.h | 3 ++
>> 2 files changed, 33 insertions(+), 30 deletions(-)
>>
>> diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
>> index 8903b9ccfc2b..ec60d6227925 100644
>> --- a/drivers/firmware/efi/runtime-wrappers.c
>> +++ b/drivers/firmware/efi/runtime-wrappers.c
>> @@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
>> * @rts_arg<1-5>: efi_runtime_service() function arguments
>> *
>> * Accesses to efi_runtime_services() are serialized by a binary
>> - * semaphore (efi_runtime_lock) and caller waits until the work is
>> + * semaphore (efi_runtime_sem) and caller waits until the work is
>> * finished, hence _only_ one work is queued at a time and the caller
>> * thread waits for completion.
>> */
>> @@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
>> * none of the remaining functions are actually ever called at runtime.
>> * So let's just use a single lock to serialize all Runtime Services calls.
>> */
>> -static DEFINE_SEMAPHORE(efi_runtime_lock);
>> +DEFINE_SEMAPHORE(efi_runtime_sem);
>>
>> /*
>> * Calls the appropriate efi_runtime_service() with the appropriate
>> @@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
>> NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
>> NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
>> data);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
>> NULL, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
>> data);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
>> {
>> efi_status_t status;
>>
>> - if (down_trylock(&efi_runtime_lock))
>> + if (down_trylock(&efi_runtime_sem))
>> return EFI_NOT_READY;
>>
>> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
>> data);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>> return EFI_UNSUPPORTED;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
>> remaining_space, max_variable_size, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>> return EFI_UNSUPPORTED;
>>
>> - if (down_trylock(&efi_runtime_lock))
>> + if (down_trylock(&efi_runtime_sem))
>> return EFI_NOT_READY;
>>
>> status = efi_call_virt(query_variable_info, attr, storage_space,
>> remaining_space, max_variable_size);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
>> {
>> efi_status_t status;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
>> NULL, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
>> unsigned long data_size,
>> efi_char16_t *data)
>> {
>> - if (down_interruptible(&efi_runtime_lock)) {
>> + if (down_interruptible(&efi_runtime_sem)) {
>> pr_warn("failed to invoke the reset_system() runtime service:\n"
>> "could not get exclusive access to the firmware\n");
>> return;
>> }
>> efi_rts_work.efi_rts_id = RESET_SYSTEM;
>> __efi_call_virt(reset_system, reset_type, status, data_size, data);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> }
>>
>> static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>> @@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>> return EFI_UNSUPPORTED;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
>> NULL, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> @@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>> return EFI_UNSUPPORTED;
>>
>> - if (down_interruptible(&efi_runtime_lock))
>> + if (down_interruptible(&efi_runtime_sem))
>> return EFI_ABORTED;
>> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
>> max_size, reset_type, NULL);
>> - up(&efi_runtime_lock);
>> + up(&efi_runtime_sem);
>> return status;
>> }
>>
>> diff --git a/include/linux/efi.h b/include/linux/efi.h
>> index 45ff763fba76..930cd20842b8 100644
>> --- a/include/linux/efi.h
>> +++ b/include/linux/efi.h
>> @@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
>> /* Workqueue to queue EFI Runtime Services */
>> extern struct workqueue_struct *efi_rts_wq;
>>
>> +/* EFI runtime semaphore */
>> +extern struct semaphore efi_runtime_sem;
>> +
>> struct linux_efi_memreserve {
>> int size; // allocated size of the array
>> atomic_t count; // number of entries used
>> --
>> 2.20.1
>>

--
Be careful of reading health books, you might die of a misprint.
-- Mark Twain

2019-02-07 19:39:42

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Thu, 7 Feb 2019 at 18:38, Hedi Berriche <[email protected]> wrote:
>
> On Thu, Feb 07, 2019 at 16:05 Ard Biesheuvel wrote:
> >On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
> >>
> >> Make efi_runtime_lock semaphore global so that it can be used by EFI
> >> runtime callers that may be defined outside efi/runtime-wrappers.c.
> >>
> >> Also now that efi_runtime_lock semaphore is no longer static, rename it
> >> to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
> >> defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
> >> enabled.
> >>
> >> The immediate motivation of this change is to serialise UV platform BIOS
> >> calls using the efi_runtime_sem semaphore.
> >>
> >> No functional changes.
> >>
> >> Cc: Russ Anderson <[email protected]>
> >> Cc: Mike Travis <[email protected]>
> >> Cc: Dimitri Sivanich <[email protected]>
> >> Cc: Steve Wahl <[email protected]>
> >> Cc: [email protected]
> >> Signed-off-by: Hedi Berriche <[email protected]>
> >
> >Hello Hedi,
>
> Hi Ard,
>
> >Same feedback as on v1: please don't rename the lock.
>
> With the efi_runtime_lock semaphore being no longer static, not renaming it
> will cause a compile failure as it will clash with the declaration of the
> efi_runtime_lock *spinlock* in arch/x86/platform/efi/efi_64.c in the
> CONFIG_EFI_MIXED case.
>

Ah right, it's in the commit log, as requested. Apologies for not spotting that.

Given how UV is a bit of an outlier, I'd prefer it if we could make
this functionality a bit more light weight, by only exposing the lock
if needed, and not create a global symbol for an internal lock if we
can avoid it.

Could you please try something along the lines of

--- a/drivers/firmware/efi/runtime-wrappers.c
+++ b/drivers/firmware/efi/runtime-wrappers.c
@@ -146,6 +146,10 @@
*/
static DEFINE_SEMAPHORE(efi_runtime_lock);

+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
/*
* Calls the appropriate efi_runtime_service() with the appropriate
* arguments.

and add a declaration

extern struct semaphore __efi_uv_runtime_lock;

to bios_uv.c itself rather than to a header file? You can combine this
with your changes in patch #4 (and drop the first patch entirely)

Also, I noticed that there is some CONFIG_EFI guarded code in
bios_uv.c while the whole file already depends on CONFIG_EFI via the
Kconfig symbol. Perhaps you could include a patch to clean that up as
well? Thanks.





> >> ---
> >> drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
> >> include/linux/efi.h | 3 ++
> >> 2 files changed, 33 insertions(+), 30 deletions(-)
> >>
> >> diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
> >> index 8903b9ccfc2b..ec60d6227925 100644
> >> --- a/drivers/firmware/efi/runtime-wrappers.c
> >> +++ b/drivers/firmware/efi/runtime-wrappers.c
> >> @@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
> >> * @rts_arg<1-5>: efi_runtime_service() function arguments
> >> *
> >> * Accesses to efi_runtime_services() are serialized by a binary
> >> - * semaphore (efi_runtime_lock) and caller waits until the work is
> >> + * semaphore (efi_runtime_sem) and caller waits until the work is
> >> * finished, hence _only_ one work is queued at a time and the caller
> >> * thread waits for completion.
> >> */
> >> @@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
> >> * none of the remaining functions are actually ever called at runtime.
> >> * So let's just use a single lock to serialize all Runtime Services calls.
> >> */
> >> -static DEFINE_SEMAPHORE(efi_runtime_lock);
> >> +DEFINE_SEMAPHORE(efi_runtime_sem);
> >>
> >> /*
> >> * Calls the appropriate efi_runtime_service() with the appropriate
> >> @@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
> >> NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
> >> NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
> >> data);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
> >> NULL, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
> >> data);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_trylock(&efi_runtime_lock))
> >> + if (down_trylock(&efi_runtime_sem))
> >> return EFI_NOT_READY;
> >>
> >> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
> >> data);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
> >> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >> return EFI_UNSUPPORTED;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
> >> remaining_space, max_variable_size, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
> >> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >> return EFI_UNSUPPORTED;
> >>
> >> - if (down_trylock(&efi_runtime_lock))
> >> + if (down_trylock(&efi_runtime_sem))
> >> return EFI_NOT_READY;
> >>
> >> status = efi_call_virt(query_variable_info, attr, storage_space,
> >> remaining_space, max_variable_size);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
> >> {
> >> efi_status_t status;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
> >> NULL, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
> >> unsigned long data_size,
> >> efi_char16_t *data)
> >> {
> >> - if (down_interruptible(&efi_runtime_lock)) {
> >> + if (down_interruptible(&efi_runtime_sem)) {
> >> pr_warn("failed to invoke the reset_system() runtime service:\n"
> >> "could not get exclusive access to the firmware\n");
> >> return;
> >> }
> >> efi_rts_work.efi_rts_id = RESET_SYSTEM;
> >> __efi_call_virt(reset_system, reset_type, status, data_size, data);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> }
> >>
> >> static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> >> @@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> >> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >> return EFI_UNSUPPORTED;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
> >> NULL, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> @@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
> >> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >> return EFI_UNSUPPORTED;
> >>
> >> - if (down_interruptible(&efi_runtime_lock))
> >> + if (down_interruptible(&efi_runtime_sem))
> >> return EFI_ABORTED;
> >> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
> >> max_size, reset_type, NULL);
> >> - up(&efi_runtime_lock);
> >> + up(&efi_runtime_sem);
> >> return status;
> >> }
> >>
> >> diff --git a/include/linux/efi.h b/include/linux/efi.h
> >> index 45ff763fba76..930cd20842b8 100644
> >> --- a/include/linux/efi.h
> >> +++ b/include/linux/efi.h
> >> @@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
> >> /* Workqueue to queue EFI Runtime Services */
> >> extern struct workqueue_struct *efi_rts_wq;
> >>
> >> +/* EFI runtime semaphore */
> >> +extern struct semaphore efi_runtime_sem;
> >> +
> >> struct linux_efi_memreserve {
> >> int size; // allocated size of the array
> >> atomic_t count; // number of entries used
> >> --
> >> 2.20.1
> >>
>
> --
> Be careful of reading health books, you might die of a misprint.
> -- Mark Twain

2019-02-12 17:47:01

by Hedi Berriche

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Thu, Feb 07, 2019 at 17:38 Hedi Berriche wrote:
>On Thu, Feb 07, 2019 at 16:05 Ard Biesheuvel wrote:
>>On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
>>>
>>>Make efi_runtime_lock semaphore global so that it can be used by EFI
>>>runtime callers that may be defined outside efi/runtime-wrappers.c.
>>>
>>>Also now that efi_runtime_lock semaphore is no longer static, rename it
>>>to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
>>>defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
>>>enabled.
>>>
>>>The immediate motivation of this change is to serialise UV platform BIOS
>>>calls using the efi_runtime_sem semaphore.
>>>
>>>No functional changes.
>>>
>>>Cc: Russ Anderson <[email protected]>
>>>Cc: Mike Travis <[email protected]>
>>>Cc: Dimitri Sivanich <[email protected]>
>>>Cc: Steve Wahl <[email protected]>
>>>Cc: [email protected]
>>>Signed-off-by: Hedi Berriche <[email protected]>
>>
>>Hello Hedi,
>
>Hi Ard,
>
>>Same feedback as on v1: please don't rename the lock.
>
>With the efi_runtime_lock semaphore being no longer static, not renaming it
>will cause a compile failure as it will clash with the declaration of the
>efi_runtime_lock *spinlock* in arch/x86/platform/efi/efi_64.c in the
>CONFIG_EFI_MIXED case.

Ard,

Any comments on whether resolving the conflict between

{efi_runtime_lock, drivers/firmware/efi/runtime-wrappers.c}

and
{efi_runtime_lock, arch/x86/platform/efi/efi_64.c}

provides the required justification for renaming the efi_runtime_lock semaphore?

Cheers,
Hedi.

>>>---
>>> drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
>>> include/linux/efi.h | 3 ++
>>> 2 files changed, 33 insertions(+), 30 deletions(-)
>>>
>>>diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
>>>index 8903b9ccfc2b..ec60d6227925 100644
>>>--- a/drivers/firmware/efi/runtime-wrappers.c
>>>+++ b/drivers/firmware/efi/runtime-wrappers.c
>>>@@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
>>> * @rts_arg<1-5>: efi_runtime_service() function arguments
>>> *
>>> * Accesses to efi_runtime_services() are serialized by a binary
>>>- * semaphore (efi_runtime_lock) and caller waits until the work is
>>>+ * semaphore (efi_runtime_sem) and caller waits until the work is
>>> * finished, hence _only_ one work is queued at a time and the caller
>>> * thread waits for completion.
>>> */
>>>@@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
>>> * none of the remaining functions are actually ever called at runtime.
>>> * So let's just use a single lock to serialize all Runtime Services calls.
>>> */
>>>-static DEFINE_SEMAPHORE(efi_runtime_lock);
>>>+DEFINE_SEMAPHORE(efi_runtime_sem);
>>>
>>> /*
>>> * Calls the appropriate efi_runtime_service() with the appropriate
>>>@@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
>>> NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
>>> NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
>>> data);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
>>> NULL, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
>>> data);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_trylock(&efi_runtime_lock))
>>>+ if (down_trylock(&efi_runtime_sem))
>>> return EFI_NOT_READY;
>>>
>>> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
>>> data);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>> return EFI_UNSUPPORTED;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
>>> remaining_space, max_variable_size, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>> return EFI_UNSUPPORTED;
>>>
>>>- if (down_trylock(&efi_runtime_lock))
>>>+ if (down_trylock(&efi_runtime_sem))
>>> return EFI_NOT_READY;
>>>
>>> status = efi_call_virt(query_variable_info, attr, storage_space,
>>> remaining_space, max_variable_size);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
>>> {
>>> efi_status_t status;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
>>> NULL, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
>>> unsigned long data_size,
>>> efi_char16_t *data)
>>> {
>>>- if (down_interruptible(&efi_runtime_lock)) {
>>>+ if (down_interruptible(&efi_runtime_sem)) {
>>> pr_warn("failed to invoke the reset_system() runtime service:\n"
>>> "could not get exclusive access to the firmware\n");
>>> return;
>>> }
>>> efi_rts_work.efi_rts_id = RESET_SYSTEM;
>>> __efi_call_virt(reset_system, reset_type, status, data_size, data);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> }
>>>
>>> static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>>>@@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>> return EFI_UNSUPPORTED;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
>>> NULL, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>@@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>> return EFI_UNSUPPORTED;
>>>
>>>- if (down_interruptible(&efi_runtime_lock))
>>>+ if (down_interruptible(&efi_runtime_sem))
>>> return EFI_ABORTED;
>>> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
>>> max_size, reset_type, NULL);
>>>- up(&efi_runtime_lock);
>>>+ up(&efi_runtime_sem);
>>> return status;
>>> }
>>>
>>>diff --git a/include/linux/efi.h b/include/linux/efi.h
>>>index 45ff763fba76..930cd20842b8 100644
>>>--- a/include/linux/efi.h
>>>+++ b/include/linux/efi.h
>>>@@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
>>> /* Workqueue to queue EFI Runtime Services */
>>> extern struct workqueue_struct *efi_rts_wq;
>>>
>>>+/* EFI runtime semaphore */
>>>+extern struct semaphore efi_runtime_sem;
>>>+
>>> struct linux_efi_memreserve {
>>> int size; // allocated size of the array
>>> atomic_t count; // number of entries used
>>>--
>>>2.20.1
>>>
>
>--
>Be careful of reading health books, you might die of a misprint.
> -- Mark Twain

--
Be careful of reading health books, you might die of a misprint.
-- Mark Twain

2019-02-12 17:48:25

by Ard Biesheuvel

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Tue, 12 Feb 2019 at 18:25, Hedi Berriche <[email protected]> wrote:
>
> On Thu, Feb 07, 2019 at 17:38 Hedi Berriche wrote:
> >On Thu, Feb 07, 2019 at 16:05 Ard Biesheuvel wrote:
> >>On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
> >>>
> >>>Make efi_runtime_lock semaphore global so that it can be used by EFI
> >>>runtime callers that may be defined outside efi/runtime-wrappers.c.
> >>>
> >>>Also now that efi_runtime_lock semaphore is no longer static, rename it
> >>>to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
> >>>defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
> >>>enabled.
> >>>
> >>>The immediate motivation of this change is to serialise UV platform BIOS
> >>>calls using the efi_runtime_sem semaphore.
> >>>
> >>>No functional changes.
> >>>
> >>>Cc: Russ Anderson <[email protected]>
> >>>Cc: Mike Travis <[email protected]>
> >>>Cc: Dimitri Sivanich <[email protected]>
> >>>Cc: Steve Wahl <[email protected]>
> >>>Cc: [email protected]
> >>>Signed-off-by: Hedi Berriche <[email protected]>
> >>
> >>Hello Hedi,
> >
> >Hi Ard,
> >
> >>Same feedback as on v1: please don't rename the lock.
> >
> >With the efi_runtime_lock semaphore being no longer static, not renaming it
> >will cause a compile failure as it will clash with the declaration of the
> >efi_runtime_lock *spinlock* in arch/x86/platform/efi/efi_64.c in the
> >CONFIG_EFI_MIXED case.
>
> Ard,
>
> Any comments on whether resolving the conflict between
>
> {efi_runtime_lock, drivers/firmware/efi/runtime-wrappers.c}
>
> and
> {efi_runtime_lock, arch/x86/platform/efi/efi_64.c}
>
> provides the required justification for renaming the efi_runtime_lock semaphore?
>

Hello Hedi,

No it doesn't. I responded 5 days ago with a suggestion on how to
address this instead.

> Cheers,
> Hedi.
>
> >>>---
> >>> drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
> >>> include/linux/efi.h | 3 ++
> >>> 2 files changed, 33 insertions(+), 30 deletions(-)
> >>>
> >>>diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
> >>>index 8903b9ccfc2b..ec60d6227925 100644
> >>>--- a/drivers/firmware/efi/runtime-wrappers.c
> >>>+++ b/drivers/firmware/efi/runtime-wrappers.c
> >>>@@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
> >>> * @rts_arg<1-5>: efi_runtime_service() function arguments
> >>> *
> >>> * Accesses to efi_runtime_services() are serialized by a binary
> >>>- * semaphore (efi_runtime_lock) and caller waits until the work is
> >>>+ * semaphore (efi_runtime_sem) and caller waits until the work is
> >>> * finished, hence _only_ one work is queued at a time and the caller
> >>> * thread waits for completion.
> >>> */
> >>>@@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
> >>> * none of the remaining functions are actually ever called at runtime.
> >>> * So let's just use a single lock to serialize all Runtime Services calls.
> >>> */
> >>>-static DEFINE_SEMAPHORE(efi_runtime_lock);
> >>>+DEFINE_SEMAPHORE(efi_runtime_sem);
> >>>
> >>> /*
> >>> * Calls the appropriate efi_runtime_service() with the appropriate
> >>>@@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
> >>> NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
> >>> NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
> >>> data);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
> >>> NULL, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
> >>> data);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_trylock(&efi_runtime_lock))
> >>>+ if (down_trylock(&efi_runtime_sem))
> >>> return EFI_NOT_READY;
> >>>
> >>> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
> >>> data);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
> >>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >>> return EFI_UNSUPPORTED;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
> >>> remaining_space, max_variable_size, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
> >>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >>> return EFI_UNSUPPORTED;
> >>>
> >>>- if (down_trylock(&efi_runtime_lock))
> >>>+ if (down_trylock(&efi_runtime_sem))
> >>> return EFI_NOT_READY;
> >>>
> >>> status = efi_call_virt(query_variable_info, attr, storage_space,
> >>> remaining_space, max_variable_size);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
> >>> {
> >>> efi_status_t status;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
> >>> NULL, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
> >>> unsigned long data_size,
> >>> efi_char16_t *data)
> >>> {
> >>>- if (down_interruptible(&efi_runtime_lock)) {
> >>>+ if (down_interruptible(&efi_runtime_sem)) {
> >>> pr_warn("failed to invoke the reset_system() runtime service:\n"
> >>> "could not get exclusive access to the firmware\n");
> >>> return;
> >>> }
> >>> efi_rts_work.efi_rts_id = RESET_SYSTEM;
> >>> __efi_call_virt(reset_system, reset_type, status, data_size, data);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> }
> >>>
> >>> static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> >>>@@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
> >>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >>> return EFI_UNSUPPORTED;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
> >>> NULL, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>@@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
> >>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
> >>> return EFI_UNSUPPORTED;
> >>>
> >>>- if (down_interruptible(&efi_runtime_lock))
> >>>+ if (down_interruptible(&efi_runtime_sem))
> >>> return EFI_ABORTED;
> >>> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
> >>> max_size, reset_type, NULL);
> >>>- up(&efi_runtime_lock);
> >>>+ up(&efi_runtime_sem);
> >>> return status;
> >>> }
> >>>
> >>>diff --git a/include/linux/efi.h b/include/linux/efi.h
> >>>index 45ff763fba76..930cd20842b8 100644
> >>>--- a/include/linux/efi.h
> >>>+++ b/include/linux/efi.h
> >>>@@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
> >>> /* Workqueue to queue EFI Runtime Services */
> >>> extern struct workqueue_struct *efi_rts_wq;
> >>>
> >>>+/* EFI runtime semaphore */
> >>>+extern struct semaphore efi_runtime_sem;
> >>>+
> >>> struct linux_efi_memreserve {
> >>> int size; // allocated size of the array
> >>> atomic_t count; // number of entries used
> >>>--
> >>>2.20.1
> >>>
> >
> >--
> >Be careful of reading health books, you might die of a misprint.
> > -- Mark Twain
>
> --
> Be careful of reading health books, you might die of a misprint.
> -- Mark Twain

2019-02-13 02:35:37

by Hedi Berriche

[permalink] [raw]
Subject: Re: [Patch v2 1/4] efi/x86: turn EFI runtime semaphore into a global lock

On Tue, Feb 12, 2019 at 17:25 Hedi Berriche wrote:
>On Thu, Feb 07, 2019 at 17:38 Hedi Berriche wrote:
>>On Thu, Feb 07, 2019 at 16:05 Ard Biesheuvel wrote:
>>>On Thu, 7 Feb 2019 at 05:23, Hedi Berriche <[email protected]> wrote:
>>>>
>>>>Make efi_runtime_lock semaphore global so that it can be used by EFI
>>>>runtime callers that may be defined outside efi/runtime-wrappers.c.
>>>>
>>>>Also now that efi_runtime_lock semaphore is no longer static, rename it
>>>>to efi_runtime_sem so it doesn't clash with the efi_runtime_lock spinlock
>>>>defined in arch/x86/platform/efi/efi_64.c when CONFIG_EFI_MIXED is
>>>>enabled.
>>>>
>>>>The immediate motivation of this change is to serialise UV platform BIOS
>>>>calls using the efi_runtime_sem semaphore.
>>>>
>>>>No functional changes.
>>>>
>>>>Cc: Russ Anderson <[email protected]>
>>>>Cc: Mike Travis <[email protected]>
>>>>Cc: Dimitri Sivanich <[email protected]>
>>>>Cc: Steve Wahl <[email protected]>
>>>>Cc: [email protected]
>>>>Signed-off-by: Hedi Berriche <[email protected]>
>>>
>>>Hello Hedi,
>>
>>Hi Ard,
>>
>>>Same feedback as on v1: please don't rename the lock.
>>
>>With the efi_runtime_lock semaphore being no longer static, not renaming it
>>will cause a compile failure as it will clash with the declaration of the
>>efi_runtime_lock *spinlock* in arch/x86/platform/efi/efi_64.c in the
>>CONFIG_EFI_MIXED case.
>
>Ard,
>
>Any comments on whether resolving the conflict between
>
> {efi_runtime_lock, drivers/firmware/efi/runtime-wrappers.c}
>
>and
> {efi_runtime_lock, arch/x86/platform/efi/efi_64.c}
>
>provides the required justification for renaming the efi_runtime_lock semaphore?

Ard,

Apologies for sending this email which must have come across as absurd given
the *second* email you sent on 2019-02-07 19:38:42.

The trouble is that I *never* received that email (nor the one you sent today
2019-02-12 17:26:06 as reply to this one) because for some reason my email
address was dropped from the distribution list.

It's only about 30 minutes ago that a colleague brought it up to my attention
and forwarded both emails:

Thu, 7 Feb 2019 20:38:42 +0100
Tue, 12 Feb 2019 18:26:06 +0100

No idea how my email address got dropped but I wanted to make sure to explain
the seemingly absurd email I sent today as well as the lack of comment on your
earlier email.

Cheers,
Hedi.
>>>>---
>>>>drivers/firmware/efi/runtime-wrappers.c | 60 ++++++++++++-------------
>>>>include/linux/efi.h | 3 ++
>>>>2 files changed, 33 insertions(+), 30 deletions(-)
>>>>
>>>>diff --git a/drivers/firmware/efi/runtime-wrappers.c b/drivers/firmware/efi/runtime-wrappers.c
>>>>index 8903b9ccfc2b..ec60d6227925 100644
>>>>--- a/drivers/firmware/efi/runtime-wrappers.c
>>>>+++ b/drivers/firmware/efi/runtime-wrappers.c
>>>>@@ -53,7 +53,7 @@ struct efi_runtime_work efi_rts_work;
>>>> * @rts_arg<1-5>: efi_runtime_service() function arguments
>>>> *
>>>> * Accesses to efi_runtime_services() are serialized by a binary
>>>>- * semaphore (efi_runtime_lock) and caller waits until the work is
>>>>+ * semaphore (efi_runtime_sem) and caller waits until the work is
>>>> * finished, hence _only_ one work is queued at a time and the caller
>>>> * thread waits for completion.
>>>> */
>>>>@@ -144,7 +144,7 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
>>>> * none of the remaining functions are actually ever called at runtime.
>>>> * So let's just use a single lock to serialize all Runtime Services calls.
>>>> */
>>>>-static DEFINE_SEMAPHORE(efi_runtime_lock);
>>>>+DEFINE_SEMAPHORE(efi_runtime_sem);
>>>>
>>>>/*
>>>> * Calls the appropriate efi_runtime_service() with the appropriate
>>>>@@ -233,10 +233,10 @@ static efi_status_t virt_efi_get_time(efi_time_t *tm, efi_time_cap_t *tc)
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(GET_TIME, tm, tc, NULL, NULL, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -244,10 +244,10 @@ static efi_status_t virt_efi_set_time(efi_time_t *tm)
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(SET_TIME, tm, NULL, NULL, NULL, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -257,11 +257,11 @@ static efi_status_t virt_efi_get_wakeup_time(efi_bool_t *enabled,
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(GET_WAKEUP_TIME, enabled, pending, tm, NULL,
>>>> NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -269,11 +269,11 @@ static efi_status_t virt_efi_set_wakeup_time(efi_bool_t enabled, efi_time_t *tm)
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(SET_WAKEUP_TIME, &enabled, tm, NULL, NULL,
>>>> NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -285,11 +285,11 @@ static efi_status_t virt_efi_get_variable(efi_char16_t *name,
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(GET_VARIABLE, name, vendor, attr, data_size,
>>>> data);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -299,11 +299,11 @@ static efi_status_t virt_efi_get_next_variable(unsigned long *name_size,
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(GET_NEXT_VARIABLE, name_size, name, vendor,
>>>> NULL, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -315,11 +315,11 @@ static efi_status_t virt_efi_set_variable(efi_char16_t *name,
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(SET_VARIABLE, name, vendor, &attr, &data_size,
>>>> data);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -330,12 +330,12 @@ virt_efi_set_variable_nonblocking(efi_char16_t *name, efi_guid_t *vendor,
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_trylock(&efi_runtime_lock))
>>>>+ if (down_trylock(&efi_runtime_sem))
>>>> return EFI_NOT_READY;
>>>>
>>>> status = efi_call_virt(set_variable, name, vendor, attr, data_size,
>>>> data);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -350,11 +350,11 @@ static efi_status_t virt_efi_query_variable_info(u32 attr,
>>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>>> return EFI_UNSUPPORTED;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(QUERY_VARIABLE_INFO, &attr, storage_space,
>>>> remaining_space, max_variable_size, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -369,12 +369,12 @@ virt_efi_query_variable_info_nonblocking(u32 attr,
>>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>>> return EFI_UNSUPPORTED;
>>>>
>>>>- if (down_trylock(&efi_runtime_lock))
>>>>+ if (down_trylock(&efi_runtime_sem))
>>>> return EFI_NOT_READY;
>>>>
>>>> status = efi_call_virt(query_variable_info, attr, storage_space,
>>>> remaining_space, max_variable_size);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -382,11 +382,11 @@ static efi_status_t virt_efi_get_next_high_mono_count(u32 *count)
>>>>{
>>>> efi_status_t status;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(GET_NEXT_HIGH_MONO_COUNT, count, NULL, NULL,
>>>> NULL, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -395,14 +395,14 @@ static void virt_efi_reset_system(int reset_type,
>>>> unsigned long data_size,
>>>> efi_char16_t *data)
>>>>{
>>>>- if (down_interruptible(&efi_runtime_lock)) {
>>>>+ if (down_interruptible(&efi_runtime_sem)) {
>>>> pr_warn("failed to invoke the reset_system() runtime service:\n"
>>>> "could not get exclusive access to the firmware\n");
>>>> return;
>>>> }
>>>> efi_rts_work.efi_rts_id = RESET_SYSTEM;
>>>> __efi_call_virt(reset_system, reset_type, status, data_size, data);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>>}
>>>>
>>>>static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>>>>@@ -414,11 +414,11 @@ static efi_status_t virt_efi_update_capsule(efi_capsule_header_t **capsules,
>>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>>> return EFI_UNSUPPORTED;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(UPDATE_CAPSULE, capsules, &count, &sg_list,
>>>> NULL, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>@@ -432,11 +432,11 @@ static efi_status_t virt_efi_query_capsule_caps(efi_capsule_header_t **capsules,
>>>> if (efi.runtime_version < EFI_2_00_SYSTEM_TABLE_REVISION)
>>>> return EFI_UNSUPPORTED;
>>>>
>>>>- if (down_interruptible(&efi_runtime_lock))
>>>>+ if (down_interruptible(&efi_runtime_sem))
>>>> return EFI_ABORTED;
>>>> status = efi_queue_work(QUERY_CAPSULE_CAPS, capsules, &count,
>>>> max_size, reset_type, NULL);
>>>>- up(&efi_runtime_lock);
>>>>+ up(&efi_runtime_sem);
>>>> return status;
>>>>}
>>>>
>>>>diff --git a/include/linux/efi.h b/include/linux/efi.h
>>>>index 45ff763fba76..930cd20842b8 100644
>>>>--- a/include/linux/efi.h
>>>>+++ b/include/linux/efi.h
>>>>@@ -1745,6 +1745,9 @@ extern struct efi_runtime_work efi_rts_work;
>>>>/* Workqueue to queue EFI Runtime Services */
>>>>extern struct workqueue_struct *efi_rts_wq;
>>>>
>>>>+/* EFI runtime semaphore */
>>>>+extern struct semaphore efi_runtime_sem;
>>>>+
>>>>struct linux_efi_memreserve {
>>>> int size; // allocated size of the array
>>>> atomic_t count; // number of entries used
>>>>--
>>>>2.20.1
>>>>
>>
>>--
>>Be careful of reading health books, you might die of a misprint.
>> -- Mark Twain
>
>--
>Be careful of reading health books, you might die of a misprint.
> -- Mark Twain

--
Be careful of reading health books, you might die of a misprint.
-- Mark Twain