Page MenuHomeFreeBSD

D55955.diff
No OneTemporary

D55955.diff

diff --git a/sys/arm64/arm64/mte.c b/sys/arm64/arm64/mte.c
--- a/sys/arm64/arm64/mte.c
+++ b/sys/arm64/arm64/mte.c
@@ -49,6 +49,22 @@
struct thread *mte_switch(struct thread *);
+#define load_tags(addr) ({ \
+ uint64_t __val; \
+ asm volatile( \
+ ".arch_extension memtag \n" \
+ "ldgm %0, [%1] \n" \
+ ".arch_extension nomemtag" : "=r" (__val) : "r" (addr)); \
+ __val; \
+})
+
+#define set_tags(tags, addr) do { \
+ asm volatile( \
+ ".arch_extension memtag \n" \
+ "stgm %0, [%1] \n" \
+ ".arch_extension nomemtag" : "=r" (tags) : "r" (addr)); \
+} while (0)
+
/* Fetch the block size used by tag load and store instructions */
static inline size_t
mte_block_size(void)
@@ -95,6 +111,31 @@
page->md.pv_flags |= PV_MTE_TAGGED;
}
+/**
+ * Copy the allocation tags from given target to destination page. This is called
+ * on a copy-on-write and anything that causes a pmap_copy_page call.
+ */
+void
+mte_copy_tags(vm_page_t srcpage, vm_page_t dstpage, char *src, char *dst)
+{
+ size_t block_size;
+ uint64_t tags;
+
+ MPASS((srcpage->md.pv_flags & PV_MTE_TAGGED) != 0);
+
+ /*
+ * Copy the tags from the source page to the destination page,
+ * incrementing by the block count read from GMID_EL1
+ */
+ block_size = mte_block_size();
+ for (size_t count = 0; count < PAGE_SIZE;
+ count += block_size, src += block_size, dst += block_size) {
+ tags = load_tags(src);
+ set_tags(tags, dst);
+ }
+ dstpage->md.pv_flags |= PV_MTE_TAGGED;
+}
+
void
mte_fork(struct thread *new_td, struct thread *orig_td)
{
diff --git a/sys/arm64/arm64/pmap.c b/sys/arm64/arm64/pmap.c
--- a/sys/arm64/arm64/pmap.c
+++ b/sys/arm64/arm64/pmap.c
@@ -146,6 +146,7 @@
#include <vm/uma.h>
#include <machine/asan.h>
+#include <machine/cpu.h>
#include <machine/cpu_feat.h>
#include <machine/elf.h>
#include <machine/ifunc.h>
@@ -6954,6 +6955,15 @@
void *src = VM_PAGE_TO_DMAP(msrc);
void *dst = VM_PAGE_TO_DMAP(mdst);
+ /*
+ * On a page copy, check whether the src page is tagged. If it is,
+ * we must copy the tags before copying the contents of the page.
+ */
+ if ((msrc->md.pv_flags & PV_MTE_TAGGED) != 0)
+ mte_copy_tags(msrc, mdst, src, dst);
+ else
+ mdst->md.pv_flags &= ~PV_MTE_TAGGED;
+
pagecopy(src, dst);
}
@@ -6970,6 +6980,9 @@
int cnt;
while (xfersize > 0) {
+ KASSERT(ADDR_IS_CANONICAL(a_offset),
+ ("%s: Address not in canonical form: %lx", __func__, a_offset));
+
a_pg_offset = a_offset & PAGE_MASK;
m_a = ma[a_offset >> PAGE_SHIFT];
p_a = m_a->phys_addr;
diff --git a/sys/arm64/include/cpu.h b/sys/arm64/include/cpu.h
--- a/sys/arm64/include/cpu.h
+++ b/sys/arm64/include/cpu.h
@@ -285,6 +285,7 @@
void mte_thread0(struct thread *);
void mte_sync_tags(vm_page_t page);
+void mte_copy_tags(vm_page_t, vm_page_t, char *, char *);
/* Functions to read the sanitised view of the special registers */
void update_special_regs(u_int);

File Metadata

Mime Type
text/plain
Expires
Mon, Sep 28, 5:14 AM (1 h, 6 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
39786978
Default Alt Text
D55955.diff (2 KB)

Event Timeline