| // Copyright 2016 The Fuchsia Authors |
| // Copyright (c) 2016 Travis Geiselbrecht |
| // |
| // Use of this source code is governed by a MIT-style |
| // license that can be found in the LICENSE file or at |
| // https://opensource.org/licenses/MIT |
| |
| #pragma once |
| |
| #include <arch/x86/ioport.h> |
| #include <arch/x86/mmu.h> |
| #include <kernel/atomic.h> |
| #include <vm/arch_vm_aspace.h> |
| #include <zircon/compiler.h> |
| #include <fbl/canary.h> |
| #include <fbl/mutex.h> |
| |
| struct MappingCursor; |
| |
| class X86ArchVmAspace final : public ArchVmAspaceInterface { |
| public: |
| template <typename PageTable> |
| static void UnmapEntry(X86ArchVmAspace* aspace, vaddr_t vaddr, volatile pt_entry_t* pte); |
| |
| X86ArchVmAspace(); |
| virtual ~X86ArchVmAspace(); |
| |
| status_t Init(vaddr_t base, size_t size, uint mmu_flags) override; |
| |
| status_t Destroy() override; |
| |
| // main methods |
| status_t Map(vaddr_t vaddr, paddr_t paddr, size_t count, |
| uint mmu_flags, size_t* mapped) override; |
| |
| status_t Unmap(vaddr_t vaddr, size_t count, size_t* unmapped) override; |
| |
| status_t Protect(vaddr_t vaddr, size_t count, uint mmu_flags) override; |
| |
| status_t Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) override; |
| |
| vaddr_t PickSpot(vaddr_t base, uint prev_region_mmu_flags, |
| vaddr_t end, uint next_region_mmu_flags, |
| vaddr_t align, size_t size, uint mmu_flags) override; |
| |
| paddr_t arch_table_phys() const override { return pt_phys_; } |
| |
| paddr_t pt_phys() const { return pt_phys_; } |
| |
| size_t pt_pages() const { return pt_pages_; } |
| |
| int active_cpus() { return atomic_load(&active_cpus_); } |
| |
| IoBitmap& io_bitmap() { return io_bitmap_; } |
| |
| static void ContextSwitch(X86ArchVmAspace* from, X86ArchVmAspace* to); |
| |
| private: |
| // Test the vaddr against the address space's range. |
| bool IsValidVaddr(vaddr_t vaddr) { |
| return (vaddr >= base_ && vaddr <= base_ + size_ - 1); |
| } |
| |
| template <template <int> class PageTable> |
| status_t DestroyAspace() TA_REQ(lock_); |
| |
| template <template <int> class PageTable> |
| status_t MapPages(vaddr_t vaddr, paddr_t paddr, const size_t count, |
| uint mmu_flags, size_t* mapped) TA_REQ(lock_); |
| |
| template <template <int> class PageTable> |
| status_t UnmapPages(vaddr_t vaddr, const size_t count, size_t* unmapped) TA_REQ(lock_); |
| |
| template <template <int> class PageTable> |
| status_t ProtectPages(vaddr_t vaddr, size_t count, uint mmu_flags) TA_REQ(lock_); |
| |
| template <template <int> class PageTable, typename F> |
| status_t QueryVaddr(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags, |
| F arch_to_mmu) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t AddMapping(volatile pt_entry_t* table, uint mmu_flags, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t AddMappingL0(volatile pt_entry_t* table, uint mmu_flags, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| bool RemoveMapping(volatile pt_entry_t* table, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| template <typename PageTable> |
| bool RemoveMappingL0(volatile pt_entry_t* table, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t UpdateMapping(volatile pt_entry_t* table, uint mmu_flags, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t UpdateMappingL0(volatile pt_entry_t* table, uint mmu_flags, |
| const MappingCursor& start_cursor, |
| MappingCursor* new_cursor) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t GetMapping(volatile pt_entry_t* table, vaddr_t vaddr, |
| page_table_levels* ret_level, |
| volatile pt_entry_t** mapping) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t GetMappingL0(volatile pt_entry_t* table, vaddr_t vaddr, |
| enum page_table_levels* ret_level, |
| volatile pt_entry_t** mapping) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| void UpdateEntry(vaddr_t vaddr, volatile pt_entry_t* pte, paddr_t paddr, |
| arch_flags_t flags) TA_REQ(lock_); |
| |
| template <typename PageTable> |
| status_t SplitLargePage(vaddr_t vaddr, volatile pt_entry_t* pte) TA_REQ(lock_); |
| |
| fbl::Canary<fbl::magic("VAAS")> canary_; |
| IoBitmap io_bitmap_; |
| |
| // low lock to protect the mmu code |
| fbl::Mutex lock_; |
| |
| // Pointer to the translation table. |
| paddr_t pt_phys_ = 0; |
| pt_entry_t* pt_virt_ = nullptr; |
| |
| // Counter of pages allocated to back the translation table. |
| size_t pt_pages_ = 0; |
| |
| uint flags_ = 0; |
| |
| // Range of address space. |
| vaddr_t base_ = 0; |
| size_t size_ = 0; |
| |
| // CPUs that are currently executing in this aspace. |
| // Actually an mp_cpu_mask_t, but header dependencies. |
| volatile int active_cpus_ = 0; |
| }; |
| |
| using ArchVmAspace = X86ArchVmAspace; |