14c68d6c0SKeir Fraser // SPDX-License-Identifier: GPL-2.0-only 24c68d6c0SKeir Fraser /* 34c68d6c0SKeir Fraser * Copyright (C) 2022 - Google LLC 44c68d6c0SKeir Fraser * Author: Keir Fraser <keirf@google.com> 54c68d6c0SKeir Fraser */ 64c68d6c0SKeir Fraser 74c68d6c0SKeir Fraser #include <linux/list.h> 84c68d6c0SKeir Fraser #include <linux/bug.h> 94c68d6c0SKeir Fraser nvhe_check_data_corruption(bool v)104c68d6c0SKeir Fraserstatic inline __must_check bool nvhe_check_data_corruption(bool v) 114c68d6c0SKeir Fraser { 124c68d6c0SKeir Fraser return v; 134c68d6c0SKeir Fraser } 144c68d6c0SKeir Fraser 154c68d6c0SKeir Fraser #define NVHE_CHECK_DATA_CORRUPTION(condition) \ 164c68d6c0SKeir Fraser nvhe_check_data_corruption(({ \ 174c68d6c0SKeir Fraser bool corruption = unlikely(condition); \ 184c68d6c0SKeir Fraser if (corruption) { \ 194c68d6c0SKeir Fraser if (IS_ENABLED(CONFIG_BUG_ON_DATA_CORRUPTION)) { \ 204c68d6c0SKeir Fraser BUG_ON(1); \ 214c68d6c0SKeir Fraser } else \ 224c68d6c0SKeir Fraser WARN_ON(1); \ 234c68d6c0SKeir Fraser } \ 244c68d6c0SKeir Fraser corruption; \ 254c68d6c0SKeir Fraser })) 264c68d6c0SKeir Fraser 274c68d6c0SKeir Fraser /* The predicates checked here are taken from lib/list_debug.c. */ 284c68d6c0SKeir Fraser 29*aebc7b0dSMarco Elver __list_valid_slowpath __list_add_valid_or_report(struct list_head * new,struct list_head * prev,struct list_head * next)30b16c42c8SMarco Elverbool __list_add_valid_or_report(struct list_head *new, struct list_head *prev, 314c68d6c0SKeir Fraser struct list_head *next) 324c68d6c0SKeir Fraser { 334c68d6c0SKeir Fraser if (NVHE_CHECK_DATA_CORRUPTION(next->prev != prev) || 344c68d6c0SKeir Fraser NVHE_CHECK_DATA_CORRUPTION(prev->next != next) || 354c68d6c0SKeir Fraser NVHE_CHECK_DATA_CORRUPTION(new == prev || new == next)) 364c68d6c0SKeir Fraser return false; 374c68d6c0SKeir Fraser 384c68d6c0SKeir Fraser return true; 394c68d6c0SKeir Fraser } 404c68d6c0SKeir Fraser 41*aebc7b0dSMarco Elver __list_valid_slowpath __list_del_entry_valid_or_report(struct list_head * entry)42b16c42c8SMarco Elverbool __list_del_entry_valid_or_report(struct list_head *entry) 434c68d6c0SKeir Fraser { 444c68d6c0SKeir Fraser struct list_head *prev, *next; 454c68d6c0SKeir Fraser 464c68d6c0SKeir Fraser prev = entry->prev; 474c68d6c0SKeir Fraser next = entry->next; 484c68d6c0SKeir Fraser 494c68d6c0SKeir Fraser if (NVHE_CHECK_DATA_CORRUPTION(next == LIST_POISON1) || 504c68d6c0SKeir Fraser NVHE_CHECK_DATA_CORRUPTION(prev == LIST_POISON2) || 514c68d6c0SKeir Fraser NVHE_CHECK_DATA_CORRUPTION(prev->next != entry) || 524c68d6c0SKeir Fraser NVHE_CHECK_DATA_CORRUPTION(next->prev != entry)) 534c68d6c0SKeir Fraser return false; 544c68d6c0SKeir Fraser 554c68d6c0SKeir Fraser return true; 564c68d6c0SKeir Fraser } 57