Since some applications are hitting the current 16 TB RAM limit (and
the 128 TB virtual address space), extend the physical RAM limit to
8 PB and the virtual address space to 64 PB using la57 addressing.

TODO: compile- and run- time switch to support pre-la57 processors.
---

Note: requires qemu patch to emulate la57.

 arch/x64/arch-cpu.hh       |  1 +
 arch/x64/arch-mmu.hh       |  5 +++++
 arch/x64/arch-setup.cc     |  2 +-
 arch/x64/boot.S            |  8 +++++++-
 arch/x64/mmu.cc            |  4 ++--
 arch/x64/processor-flags.h |  1 +
 arch/x64/processor.hh      |  1 +
 core/mmu.cc                |  6 +++---
 include/osv/mmu-defs.hh    | 10 +++++-----
 9 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/arch/x64/arch-cpu.hh b/arch/x64/arch-cpu.hh
index b1cb0bf..72e3e1a 100644
--- a/arch/x64/arch-cpu.hh
+++ b/arch/x64/arch-cpu.hh
@@ -161,6 +161,7 @@ inline void arch_cpu::init_on_cpu()
     if (features().xsave) {
         cr4 |= cr4_osxsave;
     }
+    cr4 |= cr4_la57;
     write_cr4(cr4);
 
     if (features().xsave) {
diff --git a/arch/x64/arch-mmu.hh b/arch/x64/arch-mmu.hh
index 2e6ea13..8dfbfcf 100644
--- a/arch/x64/arch-mmu.hh
+++ b/arch/x64/arch-mmu.hh
@@ -13,6 +13,11 @@ extern uint8_t phys_bits, virt_bits;
 constexpr uint8_t rsvd_bits_used = 1;
 constexpr uint8_t max_phys_bits = 52 - rsvd_bits_used;
 
+constexpr int page_table_levels() { return 5; }
+constexpr unsigned virt_addr_bits() { return 12 + 9 * page_table_levels(); }
+constexpr uintptr_t virt_addr_valid_mask() { return (uintptr_t(1) << 
virt_addr_bits()) - 1; }
+constexpr uintptr_t virt_addr_invalid_mask() { return ~virt_addr_valid_mask(); 
}
+
 enum class mattr {
     normal
 };
diff --git a/arch/x64/arch-setup.cc b/arch/x64/arch-setup.cc
index 0fabfec..7ee6c9b 100644
--- a/arch/x64/arch-setup.cc
+++ b/arch/x64/arch-setup.cc
@@ -75,7 +75,7 @@ void setup_temporary_phys_map()
     auto pt = reinterpret_cast<u64*>(cr3);
     for (auto&& area : mmu::identity_mapped_areas) {
         auto base = reinterpret_cast<void*>(get_mem_area_base(area));
-        pt[mmu::pt_index(base, 3)] = pt[0];
+        pt[mmu::pt_index(base, 4)] = pt[0];
     }
 }
 
diff --git a/arch/x64/boot.S b/arch/x64/boot.S
index bfca8c7..8de4366 100644
--- a/arch/x64/boot.S
+++ b/arch/x64/boot.S
@@ -10,6 +10,11 @@
 
 .data
 .align 4096
+ident_pt_l5:
+    .quad ident_pt_l4 + 0x67
+    .rept 511
+    .quad 0
+    .endr
 ident_pt_l4:
     .quad ident_pt_l3 + 0x67
     .rept 511
@@ -62,6 +67,7 @@ interrupt_stack_top = .
                  | X86_CR4_PAE        \
                  | X86_CR4_PGE        \
                  | X86_CR4_PCE        \
+                 | X86_CR4_LA57       \
                  | X86_CR4_OSFXSR     \
                  | X86_CR4_OSXMMEXCPT )
 
@@ -81,7 +87,7 @@ start32:
     and $~7, %esp
     mov $BOOT_CR4, %eax
     mov %eax, %cr4
-    lea ident_pt_l4, %eax
+    lea ident_pt_l5, %eax
     mov %eax, %cr3
     mov $0xc0000080, %ecx
     mov $0x00000900, %eax
diff --git a/arch/x64/mmu.cc b/arch/x64/mmu.cc
index 2f1ba5e..2ee01d3 100644
--- a/arch/x64/mmu.cc
+++ b/arch/x64/mmu.cc
@@ -113,9 +113,9 @@ void flush_tlb_all()
     tlb_flush_waiter.clear();
 }
 
-static pt_element<4> page_table_root 
__attribute__((init_priority((int)init_prio::pt_root)));
+static pt_element<page_table_levels()> page_table_root 
__attribute__((init_priority((int)init_prio::pt_root)));
 
-pt_element<4> *get_root_pt(uintptr_t virt __attribute__((unused))) {
+pt_element<page_table_levels()> *get_root_pt(uintptr_t virt 
__attribute__((unused))) {
     return &page_table_root;
 }
 
diff --git a/arch/x64/processor-flags.h b/arch/x64/processor-flags.h
index 6531152..ef87c35 100644
--- a/arch/x64/processor-flags.h
+++ b/arch/x64/processor-flags.h
@@ -24,6 +24,7 @@
 #define X86_CR4_PCE            (1 << 8)
 #define X86_CR4_OSFXSR         (1 << 9)
 #define X86_CR4_OSXMMEXCPT     (1 << 10)
+#define X86_CR4_LA57        (1 << 12)
 #define X86_CR4_VMXE           (1 << 13)
 #define X86_CR4_SMXE           (1 << 14)
 #define X86_CR4_FSGSBASE       (1 << 16)
diff --git a/arch/x64/processor.hh b/arch/x64/processor.hh
index 250153b..5cd239a 100644
--- a/arch/x64/processor.hh
+++ b/arch/x64/processor.hh
@@ -36,6 +36,7 @@ constexpr ulong cr4_pge = 1u << 7;
 constexpr ulong cr4_pce = 1u << 8;
 constexpr ulong cr4_osfxsr = 1u << 9;
 constexpr ulong cr4_osxmmexcpt = 1u << 10;
+constexpr ulong cr4_la57 = 1u << 12;
 constexpr ulong cr4_vmxe = 1u << 13;
 constexpr ulong cr4_smxe = 1u << 14;
 constexpr ulong cr4_fsgsbase = 1u << 16;
diff --git a/core/mmu.cc b/core/mmu.cc
index f929412..f1b29cc 100644
--- a/core/mmu.cc
+++ b/core/mmu.cc
@@ -351,8 +351,8 @@ template<typename PageOp, int ParentLevel> class map_level;
 template<typename PageOp>
         void map_range(uintptr_t vma_start, uintptr_t vstart, size_t size, 
PageOp& page_mapper, size_t slop = page_size)
 {
-    map_level<PageOp, 4> pt_mapper(vma_start, vstart, size, page_mapper, slop);
-    pt_mapper(hw_ptep<4>::force(mmu::get_root_pt(vstart)));
+    map_level<PageOp, page_table_levels()> pt_mapper(vma_start, vstart, size, 
page_mapper, slop);
+    pt_mapper(hw_ptep<page_table_levels()>::force(mmu::get_root_pt(vstart)));
 }
 
 template<typename PageOp, int ParentLevel> class map_level {
@@ -425,7 +425,7 @@ private:
         auto idx = pt_index(vcur, level);
         auto eidx = pt_index(vend, level);
         base_virt += idx * step;
-        base_virt = (int64_t(base_virt) << 16) >> 16; // extend 47th bit
+        base_virt = (int64_t(base_virt) << 7) >> 7; // extend 56th bit
 
         do {
             auto ptep = pt.at(idx);
diff --git a/include/osv/mmu-defs.hh b/include/osv/mmu-defs.hh
index 18edf44..9e75335 100644
--- a/include/osv/mmu-defs.hh
+++ b/include/osv/mmu-defs.hh
@@ -42,16 +42,16 @@ constexpr mem_area identity_mapped_areas[] = {
     mem_area::mempool,
 };
 
-constexpr uintptr_t mem_area_size = uintptr_t(1) << 44;
+constexpr uintptr_t mem_area_size = uintptr_t(1) << 53;
 
 constexpr uintptr_t get_mem_area_base(mem_area area)
 {
-    return 0xffff800000000000 | uintptr_t(area) << 44;
+    return 0xff00000000000000 | uintptr_t(area) << 53;
 }
 
 static inline mem_area get_mem_area(void* addr)
 {
-    return mem_area(reinterpret_cast<uintptr_t>(addr) >> 44 & 7);
+    return mem_area(reinterpret_cast<uintptr_t>(addr) >> 53 & 7);
 }
 
 constexpr void* translate_mem_area(mem_area from, mem_area to, void* addr)
@@ -175,7 +175,7 @@ template<int N>
 pt_element<N> make_empty_pte() { return pt_element<N>(); }
 
 /* get the root of the page table responsible for virtual address virt */
-pt_element<4> *get_root_pt(uintptr_t virt);
+pt_element<page_table_levels()> *get_root_pt(uintptr_t virt);
 
 /* take an error code coming from the exception frame, and return
    whether the error reports a page fault (insn/write) */
@@ -230,7 +230,7 @@ using hw_ptep_base = typename std::conditional<
    The arch must implement change_perm for this class. */
 template <int N>
 class hw_ptep : public hw_ptep_base<N> {
-    static_assert(N >= 0 && N <= 4, "Wrong hw_pte level");
+    static_assert(N >= 0 && N <= page_table_levels(), "Wrong hw_pte level");
 public:
     hw_ptep(const hw_ptep& a) : hw_ptep_base<N>(a.p) {}
     hw_ptep& operator=(const hw_ptep& a) = default;
-- 
2.9.3

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to