mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
Merge branch 'fixes' of https://git.kernel.org/pub/scm/linux/kernel/git/liveupdate/linux.git
This commit is contained in:
@@ -173,7 +173,9 @@ struct liveupdate_flb_ops {
|
||||
* @lock: A mutex that protects all fields within this structure, providing
|
||||
* the synchronization service for the FLB's ops.
|
||||
* @finished: True once the FLB's finish() callback has run.
|
||||
* @retrieved: True once the FLB's retrieve() callback has run.
|
||||
* @retrieve_status: Status code indicating whether retrieve() has been
|
||||
* attempted. 0 means not attempted, 1 means successful,
|
||||
* and negative value means it failed with that error code.
|
||||
*/
|
||||
struct luo_flb_private_state {
|
||||
refcount_t count;
|
||||
@@ -181,7 +183,7 @@ struct luo_flb_private_state {
|
||||
void *obj;
|
||||
struct mutex lock;
|
||||
bool finished;
|
||||
bool retrieved;
|
||||
int retrieve_status;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -243,6 +245,7 @@ int liveupdate_flb_get_incoming(struct liveupdate_flb *flb, void **objp);
|
||||
void liveupdate_flb_put_incoming(struct liveupdate_flb *flb);
|
||||
|
||||
int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp);
|
||||
void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb);
|
||||
|
||||
#else /* CONFIG_LIVEUPDATE */
|
||||
|
||||
@@ -292,5 +295,9 @@ static inline int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
static inline void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb)
|
||||
{
|
||||
}
|
||||
|
||||
#endif /* CONFIG_LIVEUPDATE */
|
||||
#endif /* _LINUX_LIVEUPDATE_H */
|
||||
|
||||
@@ -38,6 +38,16 @@
|
||||
#include "../kexec_internal.h"
|
||||
#include "kexec_handover_internal.h"
|
||||
|
||||
/*
|
||||
* This is the minimal alignment required by deferred struct page init.
|
||||
* deferred_init_memmap_chunk frees memory to the buddy allocator, which looks
|
||||
* at the neighboring pages (up to MAX_PAGE_ORDER) to merge them.
|
||||
* If KHO scratch is not aligned to that value, buddy can access uninitialized
|
||||
* struct pages, which can cause a crash.
|
||||
*/
|
||||
#define SCRATCH_ALIGNMENT_BYTES (PAGE_SIZE * MAX_ORDER_NR_PAGES)
|
||||
static_assert(SCRATCH_ALIGNMENT_BYTES >= CMA_MIN_ALIGNMENT_BYTES);
|
||||
|
||||
/* The magic token for preserved pages */
|
||||
#define KHO_PAGE_MAGIC 0x4b484f50U /* ASCII for 'KHOP' */
|
||||
|
||||
@@ -491,7 +501,7 @@ static int __init kho_preserved_memory_reserve(phys_addr_t phys,
|
||||
struct page *page;
|
||||
u64 sz;
|
||||
|
||||
sz = 1 << (order + PAGE_SHIFT);
|
||||
sz = 1UL << (order + PAGE_SHIFT);
|
||||
page = kho_get_preserved_page(phys, order);
|
||||
|
||||
/* Reserve the memory preserved in KHO in memblock */
|
||||
@@ -640,8 +650,8 @@ static void __init scratch_size_update(void)
|
||||
* Scratch areas are released as MIGRATE_CMA. Round them up to the right
|
||||
* size.
|
||||
*/
|
||||
scratch_size_lowmem = round_up(scratch_size_lowmem, CMA_MIN_ALIGNMENT_BYTES);
|
||||
scratch_size_global = round_up(scratch_size_global, CMA_MIN_ALIGNMENT_BYTES);
|
||||
scratch_size_lowmem = round_up(scratch_size_lowmem, SCRATCH_ALIGNMENT_BYTES);
|
||||
scratch_size_global = round_up(scratch_size_global, SCRATCH_ALIGNMENT_BYTES);
|
||||
}
|
||||
|
||||
static phys_addr_t __init scratch_size_node(int nid)
|
||||
@@ -656,7 +666,7 @@ static phys_addr_t __init scratch_size_node(int nid)
|
||||
size = scratch_size_pernode;
|
||||
}
|
||||
|
||||
return round_up(size, CMA_MIN_ALIGNMENT_BYTES);
|
||||
return round_up(size, SCRATCH_ALIGNMENT_BYTES);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -692,7 +702,7 @@ static void __init kho_reserve_scratch(void)
|
||||
* next kernel
|
||||
*/
|
||||
size = scratch_size_lowmem;
|
||||
addr = memblock_phys_alloc_range(size, CMA_MIN_ALIGNMENT_BYTES, 0,
|
||||
addr = memblock_phys_alloc_range(size, SCRATCH_ALIGNMENT_BYTES, 0,
|
||||
ARCH_LOW_ADDRESS_LIMIT);
|
||||
if (!addr) {
|
||||
pr_err("Failed to reserve lowmem scratch buffer\n");
|
||||
@@ -705,7 +715,7 @@ static void __init kho_reserve_scratch(void)
|
||||
|
||||
/* reserve large contiguous area for allocations without nid */
|
||||
size = scratch_size_global;
|
||||
addr = memblock_phys_alloc(size, CMA_MIN_ALIGNMENT_BYTES);
|
||||
addr = memblock_phys_alloc(size, SCRATCH_ALIGNMENT_BYTES);
|
||||
if (!addr) {
|
||||
pr_err("Failed to reserve global scratch buffer\n");
|
||||
goto err_free_scratch_areas;
|
||||
@@ -721,7 +731,7 @@ static void __init kho_reserve_scratch(void)
|
||||
*/
|
||||
for_each_node_state(nid, N_MEMORY) {
|
||||
size = scratch_size_node(nid);
|
||||
addr = memblock_alloc_range_nid(size, CMA_MIN_ALIGNMENT_BYTES,
|
||||
addr = memblock_alloc_range_nid(size, SCRATCH_ALIGNMENT_BYTES,
|
||||
0, MEMBLOCK_ALLOC_ACCESSIBLE,
|
||||
nid, true);
|
||||
if (!addr) {
|
||||
|
||||
@@ -133,7 +133,7 @@ static int luo_flb_file_preserve_one(struct liveupdate_flb *flb)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void luo_flb_file_unpreserve_one(struct liveupdate_flb *flb)
|
||||
void liveupdate_flb_put_outgoing(struct liveupdate_flb *flb)
|
||||
{
|
||||
struct luo_flb_private *private = luo_flb_get_private(flb);
|
||||
|
||||
@@ -168,7 +168,10 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
|
||||
if (private->incoming.finished)
|
||||
return -ENODATA;
|
||||
|
||||
if (private->incoming.retrieved)
|
||||
if (private->incoming.retrieve_status < 0)
|
||||
return private->incoming.retrieve_status;
|
||||
|
||||
if (private->incoming.retrieve_status > 0)
|
||||
return 0;
|
||||
|
||||
if (!fh->active)
|
||||
@@ -194,12 +197,13 @@ static int luo_flb_retrieve_one(struct liveupdate_flb *flb)
|
||||
|
||||
err = flb->ops->retrieve(&args);
|
||||
if (err) {
|
||||
private->incoming.retrieve_status = err;
|
||||
module_put(flb->ops->owner);
|
||||
return err;
|
||||
}
|
||||
|
||||
private->incoming.obj = args.obj;
|
||||
private->incoming.retrieved = true;
|
||||
private->incoming.retrieve_status = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -213,7 +217,7 @@ void liveupdate_flb_put_incoming(struct liveupdate_flb *flb)
|
||||
if (!refcount_dec_and_test(&private->incoming.count))
|
||||
return;
|
||||
|
||||
if (!private->incoming.retrieved) {
|
||||
if (private->incoming.retrieve_status <= 0) {
|
||||
int err = luo_flb_retrieve_one(flb);
|
||||
|
||||
if (WARN_ON(err))
|
||||
@@ -264,7 +268,7 @@ int luo_flb_file_preserve(struct liveupdate_file_handler *fh)
|
||||
|
||||
exit_err:
|
||||
list_for_each_entry_continue_reverse(iter, flb_list, list)
|
||||
luo_flb_file_unpreserve_one(iter->flb);
|
||||
liveupdate_flb_put_outgoing(iter->flb);
|
||||
up_read(&luo_register_rwlock);
|
||||
|
||||
return err;
|
||||
@@ -289,7 +293,7 @@ void luo_flb_file_unpreserve(struct liveupdate_file_handler *fh)
|
||||
|
||||
guard(rwsem_read)(&luo_register_rwlock);
|
||||
list_for_each_entry_reverse(iter, flb_list, list)
|
||||
luo_flb_file_unpreserve_one(iter->flb);
|
||||
liveupdate_flb_put_outgoing(iter->flb);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -544,6 +548,10 @@ int liveupdate_flb_get_outgoing(struct liveupdate_flb *flb, void **objp)
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
guard(mutex)(&private->outgoing.lock);
|
||||
if (!private->outgoing.obj)
|
||||
return -ENOENT;
|
||||
|
||||
refcount_inc(&private->outgoing.count);
|
||||
*objp = private->outgoing.obj;
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -316,8 +316,12 @@ static int luo_session_finish(struct luo_session *session,
|
||||
struct luo_ucmd *ucmd)
|
||||
{
|
||||
struct liveupdate_session_finish *argp = ucmd->cmd;
|
||||
int err = luo_session_finish_one(session);
|
||||
int err;
|
||||
|
||||
if (argp->reserved)
|
||||
return -EINVAL;
|
||||
|
||||
err = luo_session_finish_one(session);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user