A decorated page-table (dpt) encapsulates a native page-table (e.g.
a PGD) and maintain additional attributes related to this page-table.
It aims to be the base structure for providing useful functions to
manage a page-table, such as tracking VA range mapped in a page-table
or safely handling references to another page-table.

Signed-off-by: Alexandre Chartre <alexandre.char...@oracle.com>
---
 arch/x86/include/asm/dpt.h | 23 +++++++++++++
 arch/x86/mm/Makefile       |  2 +-
 arch/x86/mm/dpt.c          | 67 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 91 insertions(+), 1 deletion(-)
 create mode 100644 arch/x86/include/asm/dpt.h
 create mode 100644 arch/x86/mm/dpt.c

diff --git a/arch/x86/include/asm/dpt.h b/arch/x86/include/asm/dpt.h
new file mode 100644
index 000000000000..1da4d43d5e94
--- /dev/null
+++ b/arch/x86/include/asm/dpt.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef ARCH_X86_MM_DPT_H
+#define ARCH_X86_MM_DPT_H
+
+#include <linux/spinlock.h>
+
+#include <asm/pgtable.h>
+
+/*
+ * A decorated page-table (dpt) encapsulates a native page-table (e.g.
+ * a PGD) and maintain additional attributes related to this page-table.
+ */
+struct dpt {
+       spinlock_t              lock;           /* protect all attributes */
+       pgd_t                   *pagetable;     /* the actual page-table */
+       unsigned int            alignment;      /* page-table alignment */
+
+};
+
+extern struct dpt *dpt_create(unsigned int pgt_alignment);
+extern void dpt_destroy(struct dpt *dpt);
+
+#endif
diff --git a/arch/x86/mm/Makefile b/arch/x86/mm/Makefile
index e57af263e870..5b52d854a030 100644
--- a/arch/x86/mm/Makefile
+++ b/arch/x86/mm/Makefile
@@ -48,7 +48,7 @@ obj-$(CONFIG_NUMA_EMU)                += numa_emulation.o
 obj-$(CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS) += pkeys.o
 obj-$(CONFIG_RANDOMIZE_MEMORY)                 += kaslr.o
 obj-$(CONFIG_PAGE_TABLE_ISOLATION)             += pti.o
-obj-$(CONFIG_ADDRESS_SPACE_ISOLATION)          += asi.o
+obj-$(CONFIG_ADDRESS_SPACE_ISOLATION)          += asi.o dpt.o
 
 obj-$(CONFIG_AMD_MEM_ENCRYPT)  += mem_encrypt.o
 obj-$(CONFIG_AMD_MEM_ENCRYPT)  += mem_encrypt_identity.o
diff --git a/arch/x86/mm/dpt.c b/arch/x86/mm/dpt.c
new file mode 100644
index 000000000000..333e259c5b7f
--- /dev/null
+++ b/arch/x86/mm/dpt.c
@@ -0,0 +1,67 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019, 2020, Oracle and/or its affiliates.
+ *
+ */
+
+#include <linux/slab.h>
+
+#include <asm/dpt.h>
+
+/*
+ * dpt_create - allocate a page-table and create a corresponding
+ * decorated page-table. The page-table is allocated and aligned
+ * at the specified alignment (pgt_alignment) which should be a
+ * multiple of PAGE_SIZE.
+ */
+struct dpt *dpt_create(unsigned int pgt_alignment)
+{
+       unsigned int alloc_order;
+       unsigned long pagetable;
+       struct dpt *dpt;
+
+       if (!IS_ALIGNED(pgt_alignment, PAGE_SIZE))
+               return NULL;
+
+       alloc_order = round_up(PAGE_SIZE + pgt_alignment,
+                              PAGE_SIZE) >> PAGE_SHIFT;
+
+       dpt = kzalloc(sizeof(*dpt), GFP_KERNEL);
+       if (!dpt)
+               return NULL;
+
+       pagetable = (unsigned long)__get_free_pages(GFP_KERNEL_ACCOUNT |
+                                                   __GFP_ZERO,
+                                                   alloc_order);
+       if (!pagetable) {
+               kfree(dpt);
+               return NULL;
+       }
+       dpt->pagetable = (pgd_t *)(pagetable + pgt_alignment);
+       dpt->alignment = pgt_alignment;
+
+       spin_lock_init(&dpt->lock);
+
+       return dpt;
+}
+EXPORT_SYMBOL(dpt_create);
+
+void dpt_destroy(struct dpt *dpt)
+{
+       unsigned int pgt_alignment;
+       unsigned int alloc_order;
+
+       if (!dpt)
+               return;
+
+       if (dpt->pagetable) {
+               pgt_alignment = dpt->alignment;
+               alloc_order = round_up(PAGE_SIZE + pgt_alignment,
+                                      PAGE_SIZE) >> PAGE_SHIFT;
+               free_pages((unsigned long)(dpt->pagetable) - pgt_alignment,
+                          alloc_order);
+       }
+
+       kfree(dpt);
+}
+EXPORT_SYMBOL(dpt_destroy);
-- 
2.18.2

Reply via email to