Skip to content

Commit

Permalink
drm/rockchip: logo: fix rockchip_free_loader_memory
Browse files Browse the repository at this point in the history
Add "mem=0x40000000" to COMMAND LINE, kernel will crash:

[   18.379633][   T35] Unable to handle kernel paging request at virtual address ffffffff01d7c000
[   18.380412][   T35] Mem abort info:
[   18.380726][   T35]   ESR = 0x96000006
[   18.381060][   T35]   EC = 0x25: DABT (current EL), IL = 32 bits
[   18.381587][   T35]   SET = 0, FnV = 0
[   18.381920][   T35]   EA = 0, S1PTW = 0
[   18.382264][   T35] Data abort info:
[   18.382585][   T35]   ISV = 0, ISS = 0x00000006
[   18.383029][   T35]   CM = 0, WnR = 0
[   18.383360][   T35] swapper pgtable: 4k pages, 39-bit VAs, pgdp=0000000001c47000
[   18.384014][   T35] [ffffffff01d7c000] pgd=0000000040f2f003, p4d=0000000040f2f003, pud=0000000040f2f003, pmd=0000000000000000
[   18.385299][   T35] Internal error: Oops: 96000006 [#1] PREEMPT SMP
[   18.385862][   T35] Modules linked in:
[   18.386205][   T35] CPU: 2 PID: 35 Comm: kworker/2:1 Not tainted 5.10.110 rockchip-linux#324
[   18.386843][   T35] Hardware name: Rockchip RK3568 EVB1 DDR4 V10 Board (DT)
[   18.387470][   T35] Workqueue: events rockchip_drm_fb_destroy_work
[   18.388026][   T35] pstate: 80c00009 (Nzcv daif +PAN +UAO -TCO BTYPE=--)
[   18.388626][   T35] pc : rockchip_free_loader_memory+0x100/0x1a0
[   18.389156][   T35] lr : rockchip_free_loader_memory+0xc8/0x1a0
[   18.389683][   T35] sp : ffffffc0125abd00
[   18.390039][   T35] x29: ffffffc0125abd00 x28: 0000000000001000
[   18.390570][   T35] x27: ffffff807df00000 x26: 0000008000000000
[   18.391099][   T35] x25: fffffffeffe00000 x24: 0000000000000001
[   18.391628][   T35] x23: ffffff80043d6300 x22: ffffff807df00000
[   18.392157][   T35] x21: ffffff807dfb7000 x20: ffffff80043a8480
[   18.392686][   T35] x19: ffffffff01d7c000 x18: 0000000000000000
[   18.393215][   T35] x17: 0000000000000000 x16: 0000000000000000
[   18.393744][   T35] x15: 00000072e03fbb78 x14: 0000000000000000
[   18.394273][   T35] x13: 000000000000003d x12: 0000000000000000
[   18.394802][   T35] x11: 00000000fffffff6 x10: ffffffc0122f8000
[   18.395330][   T35] x9 : 0000000000010000 x8 : 0000000000000008
[   18.395859][   T35] x7 : 0000000000818000 x6 : ffffff801ad909f0
[   18.396387][   T35] x5 : 0000000000000039 x4 : ffffffc0122d01b8
[   18.396917][   T35] x3 : 0000000000000000 x2 : 0000000000000000
[   18.397445][   T35] x1 : ffffff80032622d8 x0 : 0000000000001000
[   18.397975][   T35] Call trace:
[   18.398255][   T35]  rockchip_free_loader_memory+0x100/0x1a0
[   18.398762][   T35]  __rockchip_drm_fb_destroy+0xa4/0xc8
[   18.399233][   T35]  rockchip_drm_fb_destroy_work+0x14/0x20
[   18.399728][   T35]  process_one_work+0x1b0/0x490
[   18.400142][   T35]  worker_thread+0x4c/0x3f8
[   18.400534][   T35]  kthread+0x140/0x160
[   18.400882][   T35]  ret_from_fork+0x10/0x30

Logo buffer allocated from Uboot which may removed in kernel for any
purpose such as "debug". So, before freeing to the buddy system, we
must check if the buffer are valid.

Change-Id: I9a27c4552a3c7f450b034d2a6c6c3a321bb2fc54
Signed-off-by: Simon Xue <xxm@rock-chips.com>
  • Loading branch information
Simon Xue authored and stvhay committed Feb 24, 2023
1 parent f9da21e commit 9130494
Showing 1 changed file with 11 additions and 10 deletions.
21 changes: 11 additions & 10 deletions drivers/gpu/drm/rockchip/rockchip_drm_logo.c
Expand Up @@ -148,17 +148,19 @@ static int rockchip_drm_reserve_vm(struct drm_device *drm, struct drm_mm *mm,
}

static unsigned long
rockchip_drm_free_reserved_area(void *start, void *end, int poison, const char *s)
rockchip_drm_free_reserved_area(phys_addr_t start, phys_addr_t end, int poison, const char *s)
{
void *pos;
unsigned long pages = 0;

start = (void *)PAGE_ALIGN((unsigned long)start);
end = (void *)((unsigned long)end & PAGE_MASK);
for (pos = start; pos < end; pos += PAGE_SIZE, pages++) {
struct page *page = virt_to_page(pos);
start = ALIGN_DOWN(start, PAGE_SIZE);
end = PAGE_ALIGN(end);
for (; start < end; start += PAGE_SIZE) {
struct page *page = phys_to_page(start);
void *direct_map_addr;

if (!pfn_valid(__phys_to_pfn(start)))
continue;

/*
* 'direct_map_addr' might be different from 'pos'
* because some architectures' virt_to_page()
Expand All @@ -176,6 +178,7 @@ rockchip_drm_free_reserved_area(void *start, void *end, int poison, const char *
memset(direct_map_addr, poison, PAGE_SIZE);

free_reserved_page(page);
pages++;
}

if (pages && s)
Expand All @@ -188,14 +191,11 @@ void rockchip_free_loader_memory(struct drm_device *drm)
{
struct rockchip_drm_private *private = drm->dev_private;
struct rockchip_logo *logo;
void *start, *end;

if (!private || !private->logo || --private->logo->count)
return;

logo = private->logo;
start = phys_to_virt(logo->dma_addr);
end = phys_to_virt(logo->dma_addr + logo->size);

if (private->domain) {
u32 pg_size = 1UL << __ffs(private->domain->pgsize_bitmap);
Expand All @@ -205,7 +205,8 @@ void rockchip_free_loader_memory(struct drm_device *drm)
}

memblock_free(logo->start, logo->size);
rockchip_drm_free_reserved_area(start, end, -1, "drm_logo");
rockchip_drm_free_reserved_area(logo->dma_addr, logo->dma_addr + logo->size,
-1, "drm_logo");
kfree(logo);
private->logo = NULL;
private->loader_protect = false;
Expand Down

0 comments on commit 9130494

Please sign in to comment.