From 5efbb4442a0e8c653539e263bf87c48849280e23 Mon Sep 17 00:00:00 2001 From: Alexandru Date: Thu, 28 Aug 2014 10:11:44 -0500 Subject: [PATCH] mem: adding architectural page table support for SE mode This patch enables the use of page tables that are stored in system memory and respect x86 specification, in SE mode. It defines an architectural page table for x86 as a MultiLevelPageTable class and puts a placeholder class for other ISAs page tables, giving the possibility for future implementation. --- src/arch/alpha/process.hh | 3 ++ src/arch/arm/process.hh | 3 ++ src/arch/mips/process.hh | 3 ++ src/arch/power/process.hh | 3 ++ src/arch/sparc/process.hh | 3 ++ src/arch/x86/pagetable.hh | 85 ++++++++++++++++++++++++++++++++ src/arch/x86/pagetable_walker.cc | 17 ------- src/arch/x86/process.hh | 9 ++++ src/arch/x86/system.hh | 14 ++++++ src/mem/SConscript | 2 + src/sim/Process.py | 2 + src/sim/process.cc | 5 +- src/sim/process.hh | 2 + 13 files changed, 133 insertions(+), 18 deletions(-) diff --git a/src/arch/alpha/process.hh b/src/arch/alpha/process.hh index 8c8288341..d3f9fdfc3 100644 --- a/src/arch/alpha/process.hh +++ b/src/arch/alpha/process.hh @@ -55,4 +55,7 @@ class AlphaLiveProcess : public LiveProcess void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; +/* No architectural page table defined for this ISA */ +typedef NoArchPageTable ArchPageTable; + #endif // __ARCH_ALPHA_PROCESS_HH__ diff --git a/src/arch/arm/process.hh b/src/arch/arm/process.hh index 34ce1dd02..1b77f9e4a 100644 --- a/src/arch/arm/process.hh +++ b/src/arch/arm/process.hh @@ -98,5 +98,8 @@ class ArmLiveProcess64 : public ArmLiveProcess void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; +/* No architectural page table defined for this ISA */ +typedef NoArchPageTable ArchPageTable; + #endif // __ARM_PROCESS_HH__ diff --git a/src/arch/mips/process.hh b/src/arch/mips/process.hh index a126344ca..33c02d08b 100644 --- a/src/arch/mips/process.hh +++ b/src/arch/mips/process.hh @@ -59,5 +59,8 @@ class MipsLiveProcess : public LiveProcess void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; +/* No architectural page table defined for this ISA */ +typedef NoArchPageTable ArchPageTable; + #endif // __MIPS_PROCESS_HH__ diff --git a/src/arch/power/process.hh b/src/arch/power/process.hh index 977b75ae8..b96c77c70 100644 --- a/src/arch/power/process.hh +++ b/src/arch/power/process.hh @@ -58,5 +58,8 @@ class PowerLiveProcess : public LiveProcess void setSyscallReturn(ThreadContext *tc, SyscallReturn return_value); }; +/* No architectural page table defined for this ISA */ +typedef NoArchPageTable ArchPageTable; + #endif // __POWER_PROCESS_HH__ diff --git a/src/arch/sparc/process.hh b/src/arch/sparc/process.hh index 119f608ba..2eda40aac 100644 --- a/src/arch/sparc/process.hh +++ b/src/arch/sparc/process.hh @@ -131,4 +131,7 @@ class Sparc64LiveProcess : public SparcLiveProcess void setSyscallArg(ThreadContext *tc, int i, SparcISA::IntReg val); }; +/* No architectural page table defined for this ISA */ +typedef NoArchPageTable ArchPageTable; + #endif // __SPARC_PROCESS_HH__ diff --git a/src/arch/x86/pagetable.hh b/src/arch/x86/pagetable.hh index 2a7ade853..86e488bdc 100644 --- a/src/arch/x86/pagetable.hh +++ b/src/arch/x86/pagetable.hh @@ -1,4 +1,5 @@ /* + * Copyright (c) 2014 Advanced Micro Devices, Inc. * Copyright (c) 2007 The Hewlett-Packard Development Company * All rights reserved. * @@ -42,11 +43,15 @@ #include #include +#include #include "base/bitunion.hh" #include "base/misc.hh" #include "base/types.hh" #include "base/trie.hh" +#include "cpu/thread_context.hh" +#include "arch/x86/system.hh" +#include "debug/MMU.hh" class Checkpoint; @@ -73,6 +78,25 @@ namespace X86ISA Bitfield<31, 22> norml2; EndBitUnion(VAddr) + // Unfortunately, the placement of the base field in a page table entry is + // very erratic and would make a mess here. It might be moved here at some + // point in the future. + BitUnion64(PageTableEntry) + Bitfield<63> nx; + Bitfield<51, 12> base; + Bitfield<11, 9> avl; + Bitfield<8> g; + Bitfield<7> ps; + Bitfield<6> d; + Bitfield<5> a; + Bitfield<4> pcd; + Bitfield<3> pwt; + Bitfield<2> u; + Bitfield<1> w; + Bitfield<0> p; + EndBitUnion(PageTableEntry) + + struct TlbEntry { // The base of the physical page. @@ -127,6 +151,67 @@ namespace X86ISA void serialize(std::ostream &os); void unserialize(Checkpoint *cp, const std::string §ion); }; + + /** The size of each level of the page table expressed in base 2 + * logarithmic values + */ + const std::vector PageTableLayout = {9, 9, 9, 9}; + + enum PTEField{ + PTE_NotPresent = 0, + PTE_Present, + PTE_ReadOnly = 0, + PTE_ReadWrite, + PTE_Supervisor = 0, + PTE_UserSupervisor, + }; + + /** Page table operations specific to x86 ISA. + * Indended to be used as parameter of MultiLevelPageTable. + */ + class PageTableOps + { + public: + void setPTEFields(PageTableEntry& PTE, + uint64_t present = PTE_Present, + uint64_t read_write = PTE_ReadWrite, + uint64_t user_supervisor = PTE_UserSupervisor) + { + PTE.p = present; + PTE.w = read_write; + PTE.u = user_supervisor;// both user and supervisor access allowed + } + + /** returns the physical memory address of the page table */ + Addr getBasePtr(ThreadContext* tc) + { + CR3 cr3 = pageTablePhysAddr; + DPRINTF(MMU, "CR3: %d\n", cr3); + return cr3.longPdtb; + } + + /** returns the page number out of a page table entry */ + Addr getPnum(PageTableEntry PTE) + { + return PTE.base; + } + + /** sets the page number in a page table entry */ + void setPnum(PageTableEntry& PTE, Addr paddr) + { + PTE.base = paddr; + } + + /** returns the offsets to index in every level of a page + * table, contained in a virtual address + */ + std::vector getOffsets(Addr vaddr) + { + X86ISA::VAddr addr(vaddr); + return {addr.longl1, addr.longl2, addr.longl3, addr.longl4}; + } + }; + } #endif diff --git a/src/arch/x86/pagetable_walker.cc b/src/arch/x86/pagetable_walker.cc index e75f2edc4..3d8cc9292 100644 --- a/src/arch/x86/pagetable_walker.cc +++ b/src/arch/x86/pagetable_walker.cc @@ -63,23 +63,6 @@ namespace X86ISA { -// Unfortunately, the placement of the base field in a page table entry is -// very erratic and would make a mess here. It might be moved here at some -// point in the future. -BitUnion64(PageTableEntry) - Bitfield<63> nx; - Bitfield<11, 9> avl; - Bitfield<8> g; - Bitfield<7> ps; - Bitfield<6> d; - Bitfield<5> a; - Bitfield<4> pcd; - Bitfield<3> pwt; - Bitfield<2> u; - Bitfield<1> w; - Bitfield<0> p; -EndBitUnion(PageTableEntry) - Fault Walker::start(ThreadContext * _tc, BaseTLB::Translation *_translation, RequestPtr _req, BaseTLB::Mode _mode) diff --git a/src/arch/x86/process.hh b/src/arch/x86/process.hh index 6a221e792..2fb051953 100644 --- a/src/arch/x86/process.hh +++ b/src/arch/x86/process.hh @@ -44,6 +44,7 @@ #include #include "sim/process.hh" +#include "mem/multi_level_page_table.hh" class SyscallDesc; @@ -133,6 +134,14 @@ namespace X86ISA X86ISA::IntReg getSyscallArg(ThreadContext *tc, int &i, int width); void setSyscallArg(ThreadContext *tc, int i, X86ISA::IntReg val); }; + + /** + * Declaration of architectural page table for x86. + * + * These page tables are stored in system memory and respect x86 specification. + */ + typedef MultiLevelPageTable ArchPageTable; + } #endif // __ARCH_X86_PROCESS_HH__ diff --git a/src/arch/x86/system.hh b/src/arch/x86/system.hh index 998a69cd7..e8dd2f8b3 100644 --- a/src/arch/x86/system.hh +++ b/src/arch/x86/system.hh @@ -61,6 +61,20 @@ namespace X86ISA class FloatingPointer; class ConfigTable; } + + /* memory mappings for KVMCpu in SE mode */ + const uint64_t syscallCodeVirtAddr = 0xffff800000000000; + const uint64_t syscallCodePhysAddr = 0x60000; + const uint64_t GDTVirtAddr = 0xffff800000001000; + const uint64_t GDTPhysAddr = 0x61000; + const uint64_t IDTVirtAddr = 0xffff800000002000; + const uint64_t IDTPhysAddr = 0x62000; + const uint64_t TSSVirtAddr = 0xffff800000003000; + const uint64_t TSSPhysAddr = 0x63000; + const uint64_t ISTVirtAddr = 0xffff800000004000; + const uint64_t ISTPhysAddr = 0x64000; + + const uint64_t pageTablePhysAddr = 0x70000; } class X86System : public System diff --git a/src/mem/SConscript b/src/mem/SConscript index 50b00e8db..dd96879e6 100644 --- a/src/mem/SConscript +++ b/src/mem/SConscript @@ -65,6 +65,8 @@ if env['TARGET_ISA'] != 'null': Source('fs_translating_port_proxy.cc') Source('se_translating_port_proxy.cc') Source('page_table.cc') +if env['TARGET_ISA'] == 'x86': + Source('multi_level_page_table.cc') if env['HAVE_DRAMSIM']: SimObject('DRAMSim2.py') diff --git a/src/sim/Process.py b/src/sim/Process.py index 55ccc50d0..6f2322805 100644 --- a/src/sim/Process.py +++ b/src/sim/Process.py @@ -38,6 +38,8 @@ class Process(SimObject): output = Param.String('cout', 'filename for stdout') errout = Param.String('cerr', 'filename for stderr') system = Param.System(Parent.any, "system process will run on") + useArchPT = Param.Bool('false', 'maintain an in-memory version of the page\ + table in an architecture-specific format') max_stack_size = Param.MemorySize('64MB', 'maximum size of the stack') @classmethod diff --git a/src/sim/process.cc b/src/sim/process.cc index d9f9a0fe6..a738908e1 100644 --- a/src/sim/process.cc +++ b/src/sim/process.cc @@ -106,7 +106,10 @@ Process::Process(ProcessParams * params) : SimObject(params), system(params->system), max_stack_size(params->max_stack_size), M5_pid(system->allocatePID()), - pTable(new FuncPageTable(name(), M5_pid)), + useArchPT(params->useArchPT), + pTable(useArchPT ? + static_cast(new ArchPageTable(name(), M5_pid, system)) : + static_cast(new FuncPageTable(name(), M5_pid)) ), initVirtMem(system->getSystemPort(), this, SETranslatingPortProxy::Always) { diff --git a/src/sim/process.hh b/src/sim/process.hh index 361e07bca..03380acf7 100644 --- a/src/sim/process.hh +++ b/src/sim/process.hh @@ -125,6 +125,8 @@ class Process : public SimObject //separated. uint64_t M5_pid; + // flag for using architecture specific page table + bool useArchPT; PageTableBase* pTable; class FdMap