Linux ACPI
 help / color / mirror / Atom feed
From: Jonathan Cameron <Jonathan.Cameron@huawei.com>
To: Catalin Marinas <catalin.marinas@arm.com>, <james.morse@arm.com>,
	<linux-cxl@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>,
	<linux-acpi@vger.kernel.org>, <linux-arch@vger.kernel.org>,
	<linux-mm@kvack.org>, <gregkh@linuxfoundation.org>,
	Will Deacon <will@kernel.org>,
	Dan Williams <dan.j.williams@intel.com>,
	Davidlohr Bueso <dave@stgolabs.net>
Cc: Yicong Yang <yangyicong@huawei.com>, <linuxarm@huawei.com>,
	Yushan Wang <wangyushan12@huawei.com>,
	Lorenzo Pieralisi <lpieralisi@kernel.org>,
	Mark Rutland <mark.rutland@arm.com>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	<x86@kernel.org>, H Peter Anvin <hpa@zytor.com>,
	Andy Lutomirski <luto@kernel.org>,
	Peter Zijlstra <peterz@infradead.org>
Subject: [RFC v2 7/8] acpi: PoC of Cache control via ACPI0019 and _DSM
Date: Tue, 24 Jun 2025 16:48:03 +0100	[thread overview]
Message-ID: <20250624154805.66985-8-Jonathan.Cameron@huawei.com> (raw)
In-Reply-To: <20250624154805.66985-1-Jonathan.Cameron@huawei.com>

Do not merge. This is the bare outline of what may become an ACPI
code first specification proposal. For that reason it remains an RFC
and is mainly here to show that the framework is flexible enough to
be useful by providing a second driver.

From various discussions, it has become clear that there is some desire not
to end up needing a cache flushing driver for every host that supports the
flush by PA range functionality that is needed for CXL and similar
disagregated memory pools where the host PA mapping to actual memory may
change over time and where various races can occur with prefetchers making
it hard to use CPU instructions to flush all stale data out.

There was once an ARM PSCI specification [1] that defined a firmware
interface to solve this problem.  However that meant dropping into
a more privileged mode, or chatting to an external firmware. That was
overkill for those systems that provide a simple MMIO register interface
for these operations. That specification never made it beyond alpha level.

For the typical class of machine that actually uses these disaggregated
pools, ACPI can potentially provide the same benefits with a great deal more
flexibility.  A _DSM in DSDT via operation regions, may be used to do any of:
1) Make firmware calls
2) Operate a register based state machine.
3) Most other things you might dream of.

This was prototyped against an implementation of the ARM specification
in [1] wrapped up in _DSM magic. That was chosen to give a second
(be it abandoned) example of how this cache control class can be used.

Link: https://developer.arm.com/documentation/den0022/falp1/?lang=en [1]
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
---
 drivers/cache/Kconfig              |   7 ++
 drivers/cache/Makefile             |   1 +
 drivers/cache/acpi_cache_control.c | 152 +++++++++++++++++++++++++++++
 3 files changed, 160 insertions(+)

diff --git a/drivers/cache/Kconfig b/drivers/cache/Kconfig
index 0ed87f25bd69..e4c4ebb01135 100644
--- a/drivers/cache/Kconfig
+++ b/drivers/cache/Kconfig
@@ -12,6 +12,13 @@ config CACHE_COHERENCY_SUBSYSTEM
 
 if CACHE_COHERENCY_SUBSYSTEM
 
+config ACPI_CACHE_CONTROL
+       tristate "ACPI cache maintenance"
+       depends on ARM64 && ACPI
+       help
+         ACPI0019 device ID in DSDT identifies an interface that may be used
+	 to carry out certain forms of cache flush operation.
+
 config HISI_SOC_HHA
 	tristate "HiSilicon Hydra Home Agent (HHA) device driver"
 	depends on (ARM64 && ACPI) || COMPILE_TEST
diff --git a/drivers/cache/Makefile b/drivers/cache/Makefile
index dfc98273ff09..f770bb1f314f 100644
--- a/drivers/cache/Makefile
+++ b/drivers/cache/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_SIFIVE_CCACHE)		+= sifive_ccache.o
 obj-$(CONFIG_STARFIVE_STARLINK_CACHE)	+= starfive_starlink_cache.o
 
 obj-$(CONFIG_CACHE_COHERENCY_SUBSYSTEM)	+= coherency_core.o
+obj-$(CONFIG_ACPI_CACHE_CONTROL)   	+= acpi_cache_control.o
 obj-$(CONFIG_HISI_SOC_HHA)		+= hisi_soc_hha.o
diff --git a/drivers/cache/acpi_cache_control.c b/drivers/cache/acpi_cache_control.c
new file mode 100644
index 000000000000..563afff37df0
--- /dev/null
+++ b/drivers/cache/acpi_cache_control.c
@@ -0,0 +1,152 @@
+
+#include <linux/acpi.h>
+#include <linux/cache_coherency.h>
+#include <asm/cacheflush.h>
+
+struct acpi_cache_control {
+	struct cache_coherency_device ccd;
+	/* Stuff */
+};
+
+static const guid_t testguid =
+	GUID_INIT(0x61FDC7D5, 0x1468, 0x4807,
+		0xB5, 0x65, 0x51, 0x5B, 0xF6, 0xB7, 0x53, 0x19);
+
+static int acpi_cache_control_query(struct acpi_device *device)
+{
+	union acpi_object *out_obj;
+
+	out_obj = acpi_evaluate_dsm(device->handle, &testguid, 1, 1, NULL);//&in_obj);
+	if (out_obj->package.count < 4) {
+		printk("Only partial capabilities received\n");
+		return -EINVAL;
+	}
+	for (int i = 0; i < out_obj->package.count; i++)
+		if (out_obj->package.elements[i].type != 1) {
+			printk("Element %d not integer\n", i);
+			return -EINVAL;
+		}
+	switch (out_obj->package.elements[0].integer.value) {
+	case 0:
+		printk("Supports range\n");
+		break;
+	case 1:
+		printk("Full flush only\n");
+		break;
+	default:
+		printk("unknown op type %llx\n",
+			out_obj->package.elements[0].integer.value);
+		break;
+	}
+
+	printk("Latency is %lld msecs\n",
+		out_obj->package.elements[1].integer.value);
+	printk("Min delay between calls is %lld msecs\n",
+		out_obj->package.elements[2].integer.value);
+
+	if (out_obj->package.elements[3].integer.value & BIT(0))
+		printk("CLEAN_INVALIDATE\n");
+	if (out_obj->package.elements[3].integer.value & BIT(1))
+		printk("CLEAN\n");
+	if (out_obj->package.elements[3].integer.value & BIT(2))
+		printk("INVALIDATE\n");
+	ACPI_FREE(out_obj);
+	return 0;
+}
+
+static int acpi_cache_control_inval(struct acpi_device *device, u64 base, u64 size)
+{
+	union acpi_object *out_obj;
+	union acpi_object in_array[] = {
+		[0].integer = { ACPI_TYPE_INTEGER, base },
+		[1].integer = { ACPI_TYPE_INTEGER, size },
+		[2].integer = { ACPI_TYPE_INTEGER, 0 }, // Clean invalidate
+	};
+	union acpi_object in_obj = {
+		.package = {
+			.type = ACPI_TYPE_PACKAGE,
+			.count = ARRAY_SIZE(in_array),
+			.elements = in_array,
+		},
+	};
+
+	out_obj = acpi_evaluate_dsm(device->handle, &testguid, 1, 2, &in_obj);
+	ACPI_FREE(out_obj);
+	return 0;
+}
+
+static int acpi_cc_wbinv(struct cache_coherency_device *ccd,
+			 struct cc_inval_params *invp)
+{
+	struct acpi_device *acpi_dev =
+		container_of(ccd->parent, struct acpi_device, dev);
+
+	return acpi_cache_control_inval(acpi_dev, invp->addr, invp->size);
+}
+
+static int acpi_cc_done(struct cache_coherency_device *ccd)
+{
+	/* Todo */
+	return 0;
+}
+
+static const struct coherency_ops acpi_cc_ops = {
+	.wbinv = acpi_cc_wbinv,
+	.done = acpi_cc_done,
+};
+
+static int acpi_cache_control_add(struct acpi_device *device)
+{
+	struct acpi_cache_control *acpi_cc;
+	int ret;
+
+	ret = acpi_cache_control_query(device);
+	if (ret)
+		return ret;
+
+	acpi_cc = (struct acpi_cache_control *)
+		cache_coherency_alloc_device(&device->dev, &acpi_cc_ops,
+					     sizeof(*acpi_cc));
+	if (!acpi_cc)
+		return -ENOMEM;
+
+	ret = cache_coherency_device_register(&acpi_cc->ccd);
+	if (ret) {
+		cache_coherency_device_free(&acpi_cc->ccd);
+		return ret;
+	}
+
+	dev_set_drvdata(&device->dev, acpi_cc);
+	return 0;
+}
+
+static void acpi_cache_control_del(struct acpi_device *device)
+{
+	struct acpi_cache_control *acpi_cc = dev_get_drvdata(&device->dev);
+
+	cache_coherency_device_unregister(&acpi_cc->ccd);
+	cache_coherency_device_free(&acpi_cc->ccd);
+}
+
+static const struct acpi_device_id acpi_cache_control_ids[] = {
+	{ "ACPI0019" },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(acpi, acpi_cache_control_ids);
+
+static struct acpi_driver acpi_cache_control_driver = {
+	.name = "acpi_cache_control",
+	.ids = acpi_cache_control_ids,
+	.ops = {
+		.add = acpi_cache_control_add,
+		.remove = acpi_cache_control_del,
+	},
+};
+
+module_acpi_driver(acpi_cache_control_driver);
+
+MODULE_IMPORT_NS("CACHE_COHERENCY");
+MODULE_AUTHOR("Jonathan Cameron <Jonathan.Cameron@huawei.com>");
+MODULE_DESCRIPTION("HACKS HACKS HACKS");
+MODULE_LICENSE("GPL");
-- 
2.48.1


  parent reply	other threads:[~2025-06-24 15:51 UTC|newest]

Thread overview: 38+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-06-24 15:47 [PATCH v2 0/8] Cache coherency management subsystem Jonathan Cameron
2025-06-24 15:47 ` [PATCH v2 1/8] memregion: Support fine grained invalidate by cpu_cache_invalidate_memregion() Jonathan Cameron
2025-07-09 19:46   ` Davidlohr Bueso
2025-07-09 22:31   ` dan.j.williams
2025-07-11 11:54     ` Jonathan Cameron
2025-06-24 15:47 ` [PATCH v2 2/8] generic: Support ARCH_HAS_CPU_CACHE_INVALIDATE_MEMREGION Jonathan Cameron
2025-06-24 16:16   ` Greg KH
2025-06-25 16:46   ` Jonathan Cameron
2025-07-10  5:57   ` dan.j.williams
2025-07-10  6:01     ` H. Peter Anvin
2025-07-11 11:53       ` Jonathan Cameron
2025-07-11 11:52     ` Jonathan Cameron
2025-08-07 16:07       ` Jonathan Cameron
2025-06-24 15:47 ` [PATCH v2 3/8] cache: coherency core registration and instance handling Jonathan Cameron
2025-06-24 15:48 ` [PATCH v2 4/8] MAINTAINERS: Add Jonathan Cameron to drivers/cache Jonathan Cameron
2025-06-24 15:48 ` [PATCH v2 5/8] arm64: Select GENERIC_CPU_CACHE_INVALIDATE_MEMREGION Jonathan Cameron
2025-06-25 16:21   ` kernel test robot
2025-06-28  7:10   ` kernel test robot
2025-06-24 15:48 ` [PATCH v2 6/8] cache: Support cache maintenance for HiSilicon SoC Hydra Home Agent Jonathan Cameron
2025-06-24 17:18   ` Randy Dunlap
2025-06-24 15:48 ` Jonathan Cameron [this message]
2025-06-24 15:48 ` [PATCH v2 8/8] Hack: Pretend we have PSCI 1.2 Jonathan Cameron
2025-06-25  8:52 ` [PATCH v2 0/8] Cache coherency management subsystem Peter Zijlstra
2025-06-25  9:12   ` H. Peter Anvin
2025-06-25  9:31     ` Peter Zijlstra
2025-06-25 17:03       ` Jonathan Cameron
2025-06-26  9:55         ` Jonathan Cameron
2025-07-10  5:32           ` dan.j.williams
2025-07-10 10:59             ` Peter Zijlstra
2025-07-10 18:36               ` dan.j.williams
2025-07-10  5:22       ` dan.j.williams
2025-07-10  5:31         ` H. Peter Anvin
2025-07-10 10:56         ` Peter Zijlstra
2025-07-10 18:45           ` dan.j.williams
2025-07-10 18:55             ` H. Peter Anvin
2025-07-10 19:11               ` dan.j.williams
2025-07-10 19:16                 ` H. Peter Anvin
2025-07-09 19:53     ` Davidlohr Bueso

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250624154805.66985-8-Jonathan.Cameron@huawei.com \
    --to=jonathan.cameron@huawei.com \
    --cc=bp@alien8.de \
    --cc=catalin.marinas@arm.com \
    --cc=dan.j.williams@intel.com \
    --cc=dave.hansen@linux.intel.com \
    --cc=dave@stgolabs.net \
    --cc=gregkh@linuxfoundation.org \
    --cc=hpa@zytor.com \
    --cc=james.morse@arm.com \
    --cc=linux-acpi@vger.kernel.org \
    --cc=linux-arch@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-cxl@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linuxarm@huawei.com \
    --cc=lpieralisi@kernel.org \
    --cc=luto@kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=mingo@redhat.com \
    --cc=peterz@infradead.org \
    --cc=tglx@linutronix.de \
    --cc=wangyushan12@huawei.com \
    --cc=will@kernel.org \
    --cc=x86@kernel.org \
    --cc=yangyicong@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox