From e096202b1fa47165a726e73f53278080af6a06bc Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 29 Jan 2020 10:56:35 +0100 Subject: [PATCH] hw/x86: use PAT for write combining support Fixes #3623 --- .../src/bootstrap/spec/x86_64/platform.cc | 10 ++++++++++ repos/base-hw/src/include/hw/spec/x86_64/cpu.h | 10 ++++++++++ .../src/include/hw/spec/x86_64/page_table.h | 16 ++++++++++------ 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc index 35316db82..ab349306e 100644 --- a/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc +++ b/repos/base-hw/src/bootstrap/spec/x86_64/platform.cc @@ -279,6 +279,16 @@ unsigned Bootstrap::Platform::enable_mmu() { using ::Board::Cpu; + /* enable PAT if available */ + Cpu::Cpuid_1_edx::access_t cpuid1 = Cpu::Cpuid_1_edx::read(); + if (Cpu::Cpuid_1_edx::Pat::get(cpuid1)) { + Cpu::IA32_pat::access_t pat = Cpu::IA32_pat::read(); + if (Cpu::IA32_pat::Pa1::get(pat) != Cpu::IA32_pat::Pa1::WRITE_COMBINING) { + Cpu::IA32_pat::Pa1::set(pat, Cpu::IA32_pat::Pa1::WRITE_COMBINING); + Cpu::IA32_pat::write(pat); + } + } + Cpu::Cr3::write(Cpu::Cr3::Pdb::masked((addr_t)core_pd->table_base)); addr_t const stack_base = reinterpret_cast(&__bootstrap_stack); diff --git a/repos/base-hw/src/include/hw/spec/x86_64/cpu.h b/repos/base-hw/src/include/hw/spec/x86_64/cpu.h index 7dfeba75e..100c4dc5e 100644 --- a/repos/base-hw/src/include/hw/spec/x86_64/cpu.h +++ b/repos/base-hw/src/include/hw/spec/x86_64/cpu.h @@ -84,6 +84,16 @@ struct Hw::X86_64_cpu struct Lapic : Bitfield< 11, 1> { }; /* Enable/disable local APIC */ struct Base : Bitfield< 12, 24> { }; /* Base address of APIC registers */ ); + + X86_64_MSR_REGISTER(IA32_pat, 0x277, + struct Pa1 : Bitfield <8, 3> { + enum { WRITE_COMBINING = 0b001 }; + }; + ); + + X86_64_CPUID_REGISTER(Cpuid_1_edx, 1, edx, + struct Pat : Bitfield<16, 1> { }; + ); }; #endif /* _SRC__LIB__HW__SPEC__X86_64__CPU_H_ */ diff --git a/repos/base-hw/src/include/hw/spec/x86_64/page_table.h b/repos/base-hw/src/include/hw/spec/x86_64/page_table.h index 0cfcf510d..ee7fc455d 100644 --- a/repos/base-hw/src/include/hw/spec/x86_64/page_table.h +++ b/repos/base-hw/src/include/hw/spec/x86_64/page_table.h @@ -67,8 +67,8 @@ namespace Hw struct P : Bitfield<0, 1> { }; /* present */ struct Rw : Bitfield<1, 1> { }; /* read/write */ struct Us : Bitfield<2, 1> { }; /* user/supervisor */ - struct Pwt : Bitfield<3, 1> { }; /* write-through */ - struct Pcd : Bitfield<4, 1> { }; /* cache disable */ + struct Pwt : Bitfield<3, 1> { }; /* write-through or PAT defined */ + struct Pcd : Bitfield<4, 1> { }; /* cache disable or PAT defined */ struct A : Bitfield<5, 1> { }; /* accessed */ struct D : Bitfield<6, 1> { }; /* dirty */ struct Xd : Bitfield<63, 1> { }; /* execute-disable */ @@ -121,10 +121,12 @@ class Hw::Level_4_translation_table static access_t create(Page_flags const &flags, addr_t const pa) { - /* XXX: Set memory type depending on active PAT */ + bool const wc = flags.cacheable == Genode::Cache_attribute::WRITE_COMBINED; + return Common::create(flags) | G::bits(flags.global) - | Pa::masked(pa); + | Pa::masked(pa) + | Pwt::bits(wc ? 1 : 0); } }; @@ -299,11 +301,13 @@ class Hw::Page_directory static typename Base::access_t create(Page_flags const &flags, addr_t const pa) { - /* XXX: Set memory type depending on active PAT */ + bool const wc = flags.cacheable == Genode::Cache_attribute::WRITE_COMBINED; + return Base::create(flags) | Base::Ps::bits(1) | G::bits(flags.global) - | Pa::masked(pa); + | Pa::masked(pa) + | Base::Pwt::bits(wc ? 1 : 0); } };