summaryrefslogtreecommitdiffstats
path: root/arch/m68k/amiga/chipram.c
diff options
context:
space:
mode:
authorKumar Kartikeya Dwivedi <memxor@gmail.com>2026-09-04 10:43:19 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-04 07:58:36 -0700
commit6668ed271eaefaa63e686bdfbedaeb7b8e492722 (patch)
tree58e8288fead484f6755ad0815fc74c3742663761 /arch/m68k/amiga/chipram.c
downloadlinux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.tar.gz
linux-stable-6668ed271eaefaa63e686bdfbedaeb7b8e492722.zip
selftests/bpf: Reject graph kptr use after RCU unlockgrafted
Add a sleepable verifier test that loads a graph-node local kptr in an explicit RCU read-side critical section, then passes its node to bpf_rbtree_remove() after the section ends. Before the verifier fix, the stale NON_OWN_REF flag makes the node look like a live borrowed reference and the program is accepted. After the fix, the pointer is demoted without NON_OWN_REF and the graph kfunc argument is rejected. Also exercise a graph kptr loaded while a spin lock provides implicit RCU protection. The pointer must be invalidated when the lock is released, which guards the required ordering between non-owning-reference invalidation and RCU demotion. Update the existing fault-protected load test state description. The post-unlock pointer no longer carries NON_OWN_REF, but remains readable because the load is rewritten to use BPF_PROBE_MEM. Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20260904084325.52250-7-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Diffstat (limited to 'arch/m68k/amiga/chipram.c')
-rw-r--r--arch/m68k/amiga/chipram.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/arch/m68k/amiga/chipram.c b/arch/m68k/amiga/chipram.c
new file mode 100644
index 000000000..19a7bfefb
--- /dev/null
+++ b/arch/m68k/amiga/chipram.c
@@ -0,0 +1,124 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+** linux/amiga/chipram.c
+**
+** Modified 03-May-94 by Geert Uytterhoeven <geert@linux-m68k.org>
+** - 64-bit aligned allocations for full AGA compatibility
+**
+** Rewritten 15/9/2000 by Geert to use resource management
+*/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/init.h>
+#include <linux/ioport.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/module.h>
+
+#include <asm/atomic.h>
+#include <asm/page.h>
+#include <asm/amigahw.h>
+
+unsigned long amiga_chip_size;
+EXPORT_SYMBOL(amiga_chip_size);
+
+static struct resource chipram_res = {
+ .name = "Chip RAM", .start = CHIP_PHYSADDR
+};
+static atomic_t chipavail;
+
+
+void __init amiga_chip_init(void)
+{
+ if (!AMIGAHW_PRESENT(CHIP_RAM))
+ return;
+
+ chipram_res.end = CHIP_PHYSADDR + amiga_chip_size - 1;
+ request_resource(&iomem_resource, &chipram_res);
+
+ atomic_set(&chipavail, amiga_chip_size);
+}
+
+
+void *amiga_chip_alloc(unsigned long size, const char *name)
+{
+ struct resource *res;
+ void *p;
+
+ res = kzalloc_obj(struct resource);
+ if (!res)
+ return NULL;
+
+ res->name = name;
+ p = amiga_chip_alloc_res(size, res);
+ if (!p) {
+ kfree(res);
+ return NULL;
+ }
+
+ return p;
+}
+EXPORT_SYMBOL(amiga_chip_alloc);
+
+
+ /*
+ * Warning:
+ * amiga_chip_alloc_res is meant only for drivers that need to
+ * allocate Chip RAM before kmalloc() is functional. As a consequence,
+ * those drivers must not free that Chip RAM afterwards.
+ */
+
+void *amiga_chip_alloc_res(unsigned long size, struct resource *res)
+{
+ int error;
+
+ /* round up */
+ size = PAGE_ALIGN(size);
+
+ pr_debug("amiga_chip_alloc_res: allocate %lu bytes\n", size);
+ error = allocate_resource(&chipram_res, res, size, 0, UINT_MAX,
+ PAGE_SIZE, NULL, NULL);
+ if (error < 0) {
+ pr_err("amiga_chip_alloc_res: allocate_resource() failed %d!\n",
+ error);
+ return NULL;
+ }
+
+ atomic_sub(size, &chipavail);
+ pr_debug("amiga_chip_alloc_res: returning %pR\n", res);
+ return ZTWO_VADDR(res->start);
+}
+
+void amiga_chip_free(void *ptr)
+{
+ unsigned long start = ZTWO_PADDR(ptr);
+ struct resource *res;
+ unsigned long size;
+
+ res = lookup_resource(&chipram_res, start);
+ if (!res) {
+ pr_err("amiga_chip_free: trying to free nonexistent region at "
+ "%p\n", ptr);
+ return;
+ }
+
+ size = resource_size(res);
+ pr_debug("amiga_chip_free: free %lu bytes at %p\n", size, ptr);
+ atomic_add(size, &chipavail);
+ release_resource(res);
+ kfree(res);
+}
+EXPORT_SYMBOL(amiga_chip_free);
+
+
+unsigned long amiga_chip_avail(void)
+{
+ unsigned long n = atomic_read(&chipavail);
+
+ pr_debug("amiga_chip_avail : %lu bytes\n", n);
+ return n;
+}
+EXPORT_SYMBOL(amiga_chip_avail);
+