linux运行中的一个错误解决

7 篇文章 0 订阅
2 篇文章 0 订阅

错误日志:

ACPI Error: Table [PPTT] is not invalidated during early boot stage (20180810/tbxface-165)

linux版本:4.19(注意:以下所有代码虽然是linux-4.19,但是与主线版本不同,只能作为参考)

首先查询到此日志在linux代码中的位置,位于“drivers/acpi/acpica/tbxface.c”文件的164行,相关代码块如下:

	/*
	 * Ensure OS early boot logic, which is required by some hosts. If the
	 * table state is reported to be wrong, developers should fix the
	 * issue by invoking acpi_put_table() for the reported table during the
	 * early stage.
	 */
	for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
		table_desc = &acpi_gbl_root_table_list.tables[i];
		if (table_desc->pointer) {
			ACPI_ERROR((AE_INFO,
				    "Table [%4.4s] is not invalidated during early boot stage",
				    table_desc->signature.ascii));
		}
	}

在此处有一段注释,大意是如果ACPI表状态出错,要检查“acpi_put_table()”函数。那么这个函数是什么呢?
此函数也位于“drivers/acpi/acpica/tbxface.c”文件,在359行。函数的注释如下:

/*******************************************************************************
 *
 * FUNCTION:    acpi_put_table
 *
 * PARAMETERS:  table               - The pointer to the table
 *
 * RETURN:      None
 *
 * DESCRIPTION: Release a table returned by acpi_get_table() and its clones.
 *              Note that it is not safe if this function was invoked after an
 *              uninstallation happened to the original table descriptor.
 *              Currently there is no OSPMs' requirement to handle such
 *              situations.
 *
 ******************************************************************************/
void acpi_put_table(struct acpi_table_header *table)

"acpi_put_table()"用来释放由“acpi_get_table()”获取的表。那就看看"acpi_get_table()"函数,位于“drivers/acpi/acpica/tbxface.c”文件297行:

/*******************************************************************************
 *
 * FUNCTION:    acpi_get_table
 *
 * PARAMETERS:  signature           - ACPI signature of needed table
 *              instance            - Which instance (for SSDTs)
 *              out_table           - Where the pointer to the table is returned
 *
 * RETURN:      Status and pointer to the requested table
 *
 * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
 *              RSDT/XSDT.
 *              Note that an early stage acpi_get_table() call must be paired
 *              with an early stage acpi_put_table() call. otherwise the table
 *              pointer mapped by the early stage mapping implementation may be
 *              erroneously unmapped by the late stage unmapping implementation
 *              in an acpi_put_table() invoked during the late stage.
 *
 ******************************************************************************/
acpi_status
acpi_get_table(char *signature,
	       u32 instance, struct acpi_table_header ** out_table)

很明显,这里的注释告诉我们,“acpi_get_table()”和“acpi_put_table()”要配对使用。再来看一个“acpi_put_table()”调用的函数“acpi_tb_put_table()”:

void acpi_tb_put_table(struct acpi_table_desc *table_desc)
{

	ACPI_FUNCTION_TRACE(acpi_tb_put_table);

	if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
		table_desc->validation_count--;

		/*
		 * Detect validation_count underflows to ensure that the warning
		 * message will only be printed once.
		 */
		if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
			ACPI_WARNING((AE_INFO,
				      "Table %p, Validation count underflows\n",
				      table_desc));
			return_VOID;
		}
	}

	if (table_desc->validation_count == 0) {

		/* Table need to be "INVALIDATED" */

		acpi_tb_invalidate_table(table_desc);
	}

	return_VOID;
}

最后面的注释说“Table need to be “INVALIDATED””,和错误“ACPI Error: Table [PPTT] is not invalidated during early boot stage (20180810/tbxface-165)”中的信息对上了,因此大概率就可以猜测是很有可能是某处代码没有将“Table”释放,造成这个错误。接下来就查找调用了“acpi_get_table()”的函数,看看存不存在直接返回没有释放“Table”或者干脆就没调用“acpi_put_table()”的情况。
很幸运,很快就找到了,位于“drivers/acpi/pptt.c”的"find_acpi_cpu_id()"函数,以下为此函数的代码:

/*
 * find_acpi_cpu_id() - Determine a unique cpu signature
 * Return 0 if found a matched cpu.
 */
int find_acpi_cpu_id(bool (*match_f)(struct acpi_pptt_id *))
{
	struct acpi_table_header *table_hdr;
	struct acpi_subtable_header *entry;
	struct acpi_pptt_id *cpu_id;
	u32 id_sz;
	unsigned long table_end;
	acpi_status status;

	status = acpi_get_table(ACPI_SIG_PPTT, 0, &table_hdr);
	if (ACPI_FAILURE(status)) {
		pr_warn_once("No PPTT table found, can't find cpu id through acpi\n");
		return -ENOENT;
	}

	table_end = (unsigned long)table_hdr + table_hdr->length;
	entry = ACPI_ADD_PTR(struct acpi_subtable_header, table_hdr,
			     sizeof(struct acpi_table_pptt));
	id_sz = sizeof(struct acpi_pptt_id *);

	/* iterate the tables until find an expected cpu signature */
	while ((unsigned long)entry + id_sz < table_end) {
		cpu_id = (struct acpi_pptt_id *)entry;

		if (entry->length == 0) {
			pr_warn("Invalid zero length subtable\n");
			return -EINVAL;
		}

		if (entry->type == ACPI_PPTT_TYPE_ID && match_f(cpu_id))
			return 0;

		entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
				     entry->length);
	}

	return -1;
}

可以看到没有使用“acpi_put_table()”,修改结果如下,这是使用"git diff"生成的文件,可以看到修改前后对比:

diff --git a/drivers/acpi/pptt.c b/drivers/acpi/pptt.c
index f6d640acff5f..036bf8ed13e9 100644
--- a/drivers/acpi/pptt.c
+++ b/drivers/acpi/pptt.c
@@ -909,6 +909,7 @@ int find_acpi_cpu_id(bool (*match_f)(struct acpi_pptt_id *))
        u32 id_sz;
        unsigned long table_end;
        acpi_status status;
+       int ret = -1;
 
        status = acpi_get_table(ACPI_SIG_PPTT, 0, &table_hdr);
        if (ACPI_FAILURE(status)) {
@@ -927,15 +928,19 @@ int find_acpi_cpu_id(bool (*match_f)(struct acpi_pptt_id *))
 
                if (entry->length == 0) {
                        pr_warn("Invalid zero length subtable\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       break;
                }
 
-               if (entry->type == ACPI_PPTT_TYPE_ID && match_f(cpu_id))
-                       return 0;
+               if (entry->type == ACPI_PPTT_TYPE_ID && match_f(cpu_id)){
+                       ret = 0;
+                       break;
+               }
 
                entry = ACPI_ADD_PTR(struct acpi_subtable_header, entry,
                                     entry->length);
        }
 
-       return -1;
+       acpi_put_table(table_hdr);
+       return ret;
 }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值