mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
Merge 58e401790a on remote branch
Change-Id: I9790077c57d1e497dcf92c7224360105baf23e30
This commit is contained in:
commit
fad511703f
2 changed files with 77 additions and 36 deletions
|
|
@ -494,8 +494,12 @@ static void handle_alloc_generic_req(struct qmi_handle *handle,
|
|||
}
|
||||
}
|
||||
|
||||
if (!memblock[index].allotted) {
|
||||
if (memblock[index].guard_band && alloc_req->num_bytes > 0)
|
||||
if (!memblock[index].allotted && alloc_req->num_bytes > 0) {
|
||||
|
||||
if (alloc_req->num_bytes > memblock[index].init_size)
|
||||
alloc_req->num_bytes = memblock[index].init_size;
|
||||
|
||||
if (memblock[index].guard_band)
|
||||
size = alloc_req->num_bytes + MEMSHARE_GUARD_BYTES;
|
||||
else
|
||||
size = alloc_req->num_bytes;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Sony Mobile Communications AB.
|
||||
* Copyright (c) 2012-2013, 2019-2020 The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/hwspinlock.h>
|
||||
|
|
@ -86,6 +87,17 @@
|
|||
/* Max number of processors/hosts in a system */
|
||||
#define SMEM_HOST_COUNT 14
|
||||
|
||||
/* Entry range check
|
||||
* ptr >= start : Checks if ptr is greater than the start of access region
|
||||
* ptr + size >= ptr: Check for integer overflow (On 32bit system where ptr
|
||||
* and size are 32bits, ptr + size can wrap around to be a small integer)
|
||||
* ptr + size <= end: Checks if ptr+size is less than the end of access region
|
||||
*/
|
||||
#define IN_PARTITION_RANGE(ptr, size, start, end) \
|
||||
(((void *)(ptr) >= (void *)(start)) && \
|
||||
(((void *)(ptr) + (size)) >= (void *)(ptr)) && \
|
||||
(((void *)(ptr) + (size)) <= (void *)(end)))
|
||||
|
||||
/**
|
||||
* struct smem_proc_comm - proc_comm communication struct (legacy)
|
||||
* @command: current command to be executed
|
||||
|
|
@ -353,6 +365,7 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
|
|||
size_t size)
|
||||
{
|
||||
struct smem_private_entry *hdr, *end;
|
||||
struct smem_private_entry *next_hdr;
|
||||
struct smem_partition_header *phdr;
|
||||
size_t alloc_size;
|
||||
void *cached;
|
||||
|
|
@ -365,18 +378,25 @@ static int qcom_smem_alloc_private(struct qcom_smem *smem,
|
|||
end = phdr_to_last_uncached_entry(phdr);
|
||||
cached = phdr_to_last_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)end > p_end || (void *)cached > p_end))
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(end, 0, phdr, cached) ||
|
||||
cached > p_end))
|
||||
return -EINVAL;
|
||||
|
||||
while (hdr < end) {
|
||||
while ((hdr < end) && ((hdr + 1) < end)) {
|
||||
if (hdr->canary != SMEM_PRIVATE_CANARY)
|
||||
goto bad_canary;
|
||||
if (le16_to_cpu(hdr->item) == item)
|
||||
return -EEXIST;
|
||||
|
||||
hdr = uncached_entry_next(hdr);
|
||||
next_hdr = uncached_entry_next(hdr);
|
||||
|
||||
if (WARN_ON(next_hdr <= hdr))
|
||||
return -EINVAL;
|
||||
|
||||
hdr = next_hdr;
|
||||
}
|
||||
if (WARN_ON((void *)hdr > p_end))
|
||||
|
||||
if (WARN_ON((void *)hdr > (void *)end))
|
||||
return -EINVAL;
|
||||
|
||||
/* Check that we don't grow into the cached region */
|
||||
|
|
@ -534,9 +554,11 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
unsigned item,
|
||||
size_t *size)
|
||||
{
|
||||
struct smem_private_entry *e, *end;
|
||||
struct smem_private_entry *e, *uncached_end, *cached_end;
|
||||
struct smem_private_entry *next_e;
|
||||
struct smem_partition_header *phdr;
|
||||
void *item_ptr, *p_end;
|
||||
size_t entry_size = 0;
|
||||
u32 partition_size;
|
||||
size_t cacheline;
|
||||
u32 padding_data;
|
||||
|
|
@ -548,72 +570,87 @@ static void *qcom_smem_get_private(struct qcom_smem *smem,
|
|||
cacheline = le32_to_cpu(entry->cacheline);
|
||||
|
||||
e = phdr_to_first_uncached_entry(phdr);
|
||||
end = phdr_to_last_uncached_entry(phdr);
|
||||
uncached_end = phdr_to_last_uncached_entry(phdr);
|
||||
cached_end = phdr_to_last_cached_entry(phdr);
|
||||
|
||||
if (WARN_ON((void *)end > p_end))
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(uncached_end, 0, phdr, cached_end)
|
||||
|| (void *)cached_end > p_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
while (e < end) {
|
||||
while ((e < uncached_end) && ((e + 1) < uncached_end)) {
|
||||
if (e->canary != SMEM_PRIVATE_CANARY)
|
||||
goto invalid_canary;
|
||||
|
||||
if (le16_to_cpu(e->item) == item) {
|
||||
if (size != NULL) {
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
|
||||
if (e_size < partition_size
|
||||
&& padding_data < e_size)
|
||||
*size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
if (e_size < partition_size && padding_data < e_size)
|
||||
entry_size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
item_ptr = uncached_entry_to_item(e);
|
||||
if (WARN_ON(item_ptr > p_end))
|
||||
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, e, uncached_end)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (size != NULL)
|
||||
*size = entry_size;
|
||||
|
||||
return item_ptr;
|
||||
}
|
||||
|
||||
e = uncached_entry_next(e);
|
||||
next_e = uncached_entry_next(e);
|
||||
if (WARN_ON(next_e <= e))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
e = next_e;
|
||||
}
|
||||
if (WARN_ON((void *)e > p_end))
|
||||
if (WARN_ON((void *)e > (void *)uncached_end))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* Item was not found in the uncached list, search the cached list */
|
||||
|
||||
e = phdr_to_first_cached_entry(phdr, cacheline);
|
||||
end = phdr_to_last_cached_entry(phdr);
|
||||
if (cached_end == p_end)
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
if (WARN_ON((void *)e < (void *)phdr || (void *)end > p_end))
|
||||
e = phdr_to_first_cached_entry(phdr, cacheline);
|
||||
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(cached_end, 0, uncached_end, p_end) ||
|
||||
!IN_PARTITION_RANGE(e, sizeof(*e), cached_end, p_end)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
while (e > end) {
|
||||
while (e > cached_end) {
|
||||
if (e->canary != SMEM_PRIVATE_CANARY)
|
||||
goto invalid_canary;
|
||||
|
||||
if (le16_to_cpu(e->item) == item) {
|
||||
if (size != NULL) {
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
e_size = le32_to_cpu(e->size);
|
||||
padding_data = le16_to_cpu(e->padding_data);
|
||||
|
||||
if (e_size < partition_size
|
||||
&& padding_data < e_size)
|
||||
*size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
}
|
||||
if (e_size < partition_size && padding_data < e_size)
|
||||
entry_size = e_size - padding_data;
|
||||
else
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
item_ptr = cached_entry_to_item(e);
|
||||
if (WARN_ON(item_ptr < (void *)phdr))
|
||||
if (WARN_ON(!IN_PARTITION_RANGE(item_ptr, entry_size, cached_end, e)))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
if (size != NULL)
|
||||
*size = entry_size;
|
||||
|
||||
return item_ptr;
|
||||
}
|
||||
|
||||
e = cached_entry_next(e, cacheline);
|
||||
next_e = cached_entry_next(e, cacheline);
|
||||
if (WARN_ON(next_e >= e))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
e = next_e;
|
||||
}
|
||||
|
||||
if (WARN_ON((void *)e < (void *)phdr))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue