Comparar commits

...

3 Commits

Autor SHA1 Mensagem Data
Travis Geiselbrecht 619f6c0b12 WIP
Change-Id: I5ccab174562f05c9996365f34cb5542907bc98fe
2017-06-08 20:56:30 -07:00
Travis Geiselbrecht 4f9da73631 WIP move the per arch mmu object into the arch code
Change-Id: I65452eb4cb62b6e62b8987065022e691df0cbb97
2017-06-08 17:08:04 -07:00
Travis Geiselbrecht 6f899c90a9 [kernel][vm] objectify the mmu layer by adding a simple wrapper object
This just adds a wrapper object around the arch_mmu routines and
switches the high level api to an object oriented model. Subsequent
changes will remove the wrapper and have the two arches implement the
objects directly.

Change-Id: I5ce0d28db5612f4fbc9e0c87d2f6b22dcd09a3f1
2017-06-08 16:40:07 -07:00
37 arquivos alterados com 353 adições e 149 exclusões
+1
Ver Arquivo
@@ -15,6 +15,7 @@
#include <arch/arm64/exceptions.h>
#include <kernel/thread.h>
#include <kernel/stats.h>
#include <kernel/vm.h>
#include <kernel/vm/fault.h>
#include <platform.h>
+25 -5
Ver Arquivo
@@ -7,11 +7,8 @@
#pragma once
#include <magenta/compiler.h>
#include <list.h>
#include <arch/arm64/mmu.h>
__BEGIN_CDECLS
#include <kernel/vm/arch_vm_aspace.h>
#define ARCH_ASPACE_MAGIC 0x41524153 // ARAS
@@ -32,5 +29,28 @@ struct arch_aspace {
size_t size;
};
__END_CDECLS
class ARM64ArchVmAspace final : public ArchVmAspaceBase {
public:
ARM64ArchVmAspace();
virtual ~ARM64ArchVmAspace();
DISALLOW_COPY_ASSIGN_AND_MOVE(ARM64ArchVmAspace);
virtual status_t Init(vaddr_t base, size_t size, uint mmu_flags);
virtual status_t Destroy();
// main methods
virtual status_t Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped);
virtual status_t Unmap(vaddr_t vaddr, size_t count, size_t* unmapped);
virtual status_t Protect(vaddr_t vaddr, size_t count, uint mmu_flags);
virtual status_t Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags);
static void ContextSwitch(ARM64ArchVmAspace *from, ARM64ArchVmAspace *to);
arch_aspace& GetInnerAspace() { return aspace_; }
private:
arch_aspace aspace_ = {};
};
using ArchVmAspace = ARM64ArchVmAspace;
+44 -7
Ver Arquivo
@@ -5,6 +5,7 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <arch/mmu.h>
#include <arch/arm64/mmu.h>
#include <assert.h>
#include <debug.h>
@@ -12,6 +13,7 @@
#include <inttypes.h>
#include <kernel/mutex.h>
#include <kernel/vm.h>
#include <kernel/vm/arch_vm_aspace.h>
#include <kernel/vm/pmm.h>
#include <lib/heap.h>
#include <rand.h>
@@ -123,7 +125,7 @@ static pte_t mmu_flags_to_pte_attr(uint flags) {
return attr;
}
status_t arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* flags) {
status_t arch_internal::arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* flags) {
ulong index;
uint index_shift;
uint page_size_shift;
@@ -655,7 +657,7 @@ static status_t arm64_mmu_protect(vaddr_t vaddr, size_t size, pte_t attrs,
return ret;
}
status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, const size_t count, uint flags, size_t* mapped) {
status_t arch_internal::arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, const size_t count, uint flags, size_t* mapped) {
LTRACEF("vaddr %#" PRIxPTR " paddr %#" PRIxPTR " count %zu flags %#x\n",
vaddr, paddr, count, flags);
@@ -702,7 +704,7 @@ status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, const
return (ret < 0) ? (status_t)ret : NO_ERROR;
}
status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t count, size_t* unmapped) {
status_t arch_internal::arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t count, size_t* unmapped) {
LTRACEF("vaddr %#" PRIxPTR " count %zu\n", vaddr, count);
DEBUG_ASSERT(aspace);
@@ -741,7 +743,7 @@ status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t count
return (ret < 0) ? (status_t)ret : 0;
}
status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint flags) {
status_t arch_internal::arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint flags) {
DEBUG_ASSERT(aspace);
DEBUG_ASSERT(aspace->magic == ARCH_ASPACE_MAGIC);
@@ -774,7 +776,7 @@ status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, ui
return ret;
}
status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint flags) {
status_t arch_internal::arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint flags) {
LTRACEF("aspace %p, base %#" PRIxPTR ", size 0x%zx, flags 0x%x\n",
aspace, base, size, flags);
@@ -826,7 +828,7 @@ status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size,
return NO_ERROR;
}
status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace) {
status_t arch_internal::arch_mmu_destroy_aspace(arch_aspace_t* aspace) {
LTRACEF("aspace %p\n", aspace);
DEBUG_ASSERT(aspace);
@@ -849,7 +851,7 @@ status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace) {
return NO_ERROR;
}
void arch_mmu_context_switch(arch_aspace_t* old_aspace, arch_aspace_t* aspace) {
void arch_internal::arch_mmu_context_switch(arch_aspace_t* old_aspace, arch_aspace_t* aspace) {
if (TRACE_CONTEXT_SWITCH)
TRACEF("aspace %p\n", aspace);
@@ -887,3 +889,38 @@ void arch_zero_page(void* _ptr) {
ptr += zva_size;
} while (ptr != end_ptr);
}
ARM64ArchVmAspace::ARM64ArchVmAspace() { }
ARM64ArchVmAspace::~ARM64ArchVmAspace() {
// TODO: check that we've destroyed the aspace
}
status_t ARM64ArchVmAspace::Init(vaddr_t base, size_t size, uint mmu_flags) {
return arch_internal::arch_mmu_init_aspace(&aspace_, base, size, mmu_flags);
}
status_t ARM64ArchVmAspace::Destroy() {
return arch_internal::arch_mmu_destroy_aspace(&aspace_);
}
status_t ARM64ArchVmAspace::Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped) {
return arch_internal::arch_mmu_map(&aspace_, vaddr, paddr, count, mmu_flags, mapped);
}
status_t ARM64ArchVmAspace::Unmap(vaddr_t vaddr, size_t count, size_t* unmapped) {
return arch_internal::arch_mmu_unmap(&aspace_, vaddr, count, unmapped);
}
status_t ARM64ArchVmAspace::Protect(vaddr_t vaddr, size_t count, uint mmu_flags) {
return arch_internal::arch_mmu_protect(&aspace_, vaddr, count, mmu_flags);
}
status_t ARM64ArchVmAspace::Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) {
return arch_internal::arch_mmu_query(&aspace_, vaddr, paddr, mmu_flags);
}
void ARM64ArchVmAspace::ContextSwitch(ARM64ArchVmAspace *from, ARM64ArchVmAspace *to) {
arch_internal::arch_mmu_context_switch(from ? &from->aspace_ : nullptr, to ? &to->aspace_ : nullptr);
}
+1 -1
Ver Arquivo
@@ -121,7 +121,7 @@ status_t x86_bootstrap16_prep(
(entry64 - (uintptr_t)x86_bootstrap16_start);
ASSERT(long_mode_entry <= UINT32_MAX);
uint64_t phys_bootstrap_pml4 = bootstrap_aspace->arch_aspace().pt_phys;
uint64_t phys_bootstrap_pml4 = bootstrap_aspace->arch_aspace().GetInnerAspace().pt_phys;
uint64_t phys_kernel_pml4 = x86_get_cr3();
if (phys_bootstrap_pml4 > UINT32_MAX) {
// TODO(teisenbe): Once the pmm supports it, we should request that this
+1
Ver Arquivo
@@ -15,6 +15,7 @@
#include <arch/x86/descriptor.h>
#include <kernel/thread.h>
#include <kernel/stats.h>
#include <kernel/vm.h>
#include <kernel/vm/fault.h>
#include <platform.h>
+48 -4
Ver Arquivo
@@ -7,11 +7,9 @@
#pragma once
#include <magenta/compiler.h>
#include <arch/x86/mmu.h>
#include <kernel/spinlock.h>
__BEGIN_CDECLS
#include <kernel/vm/arch_vm_aspace.h>
#define ARCH_ASPACE_MAGIC 0x41524153 // ARAS
@@ -39,5 +37,51 @@ struct arch_aspace {
spin_lock_t io_bitmap_lock;
};
__END_CDECLS
class X86ArchVmAspace final : public ArchVmAspaceBase {
public:
X86ArchVmAspace();
virtual ~X86ArchVmAspace();
DISALLOW_COPY_ASSIGN_AND_MOVE(X86ArchVmAspace);
virtual status_t Init(vaddr_t base, size_t size, uint mmu_flags);
virtual status_t Destroy();
// main methods
virtual status_t Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped);
virtual status_t Unmap(vaddr_t vaddr, size_t count, size_t* unmapped);
virtual status_t Protect(vaddr_t vaddr, size_t count, uint mmu_flags);
virtual status_t Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags);
static void ContextSwitch(X86ArchVmAspace *from, X86ArchVmAspace *to);
arch_aspace& GetInnerAspace() { return aspace_; }
private:
arch_aspace aspace_ = {};
};
class X86ArchVmGuestAspace final : public ArchVmAspaceBase {
public:
X86ArchVmGuestAspace();
virtual ~X86ArchVmGuestAspace();
DISALLOW_COPY_ASSIGN_AND_MOVE(X86ArchVmGuestAspace);
virtual status_t Init(vaddr_t base, size_t size, uint mmu_flags);
virtual status_t Destroy();
// main methods
virtual status_t Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped);
virtual status_t Unmap(vaddr_t vaddr, size_t count, size_t* unmapped);
virtual status_t Protect(vaddr_t vaddr, size_t count, uint mmu_flags);
virtual status_t Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags);
paddr_t Pml4Address() const { return aspace_.pt_phys; }
private:
arch_aspace aspace_ = {};
};
using ArchVmAspace = X86ArchVmAspace;
using ArchVmGuestAspace = X86ArchVmGuestAspace;
-1
Ver Arquivo
@@ -8,7 +8,6 @@
#include <magenta/compiler.h>
#include <dev/interrupt.h>
#include <kernel/vm.h>
__BEGIN_CDECLS
+12 -11
Ver Arquivo
@@ -14,6 +14,7 @@
#include <kernel/auto_lock.h>
#include <kernel/mp.h>
#include <kernel/thread.h>
#include <kernel/vm.h>
#include <kernel/vm/vm_aspace.h>
#include <malloc.h>
#include <string.h>
@@ -25,7 +26,7 @@
/* Task used for updating IO permissions on each CPU */
struct ioport_update_context {
// aspace that we're trying to update
arch_aspace_t* aspace;
ArchVmAspace* aspace;
};
static void ioport_update_task(void* raw_context) {
DEBUG_ASSERT(arch_ints_disabled());
@@ -33,18 +34,18 @@ static void ioport_update_task(void* raw_context) {
(struct ioport_update_context*)raw_context;
VmAspace *aspace = vmm_aspace_to_obj(get_current_thread()->aspace);
struct arch_aspace* as = &aspace->arch_aspace();
ArchVmAspace *as = &aspace->arch_aspace();
if (as != context->aspace) {
return;
}
spin_lock(&as->io_bitmap_lock);
spin_lock(&as->GetInnerAspace().io_bitmap_lock);
// This is overkill, but it's much simpler to reason about
x86_reset_tss_io_bitmap();
x86_set_tss_io_bitmap(*static_cast<bitmap::RleBitmap*>(as->io_bitmap));
x86_set_tss_io_bitmap(*static_cast<bitmap::RleBitmap*>(as->GetInnerAspace().io_bitmap));
spin_unlock(&as->io_bitmap_lock);
spin_unlock(&as->GetInnerAspace().io_bitmap_lock);
}
int x86_set_io_bitmap(uint32_t port, uint32_t len, bool enable) {
@@ -54,10 +55,10 @@ int x86_set_io_bitmap(uint32_t port, uint32_t len, bool enable) {
return ERR_INVALID_ARGS;
VmAspace *aspace = vmm_aspace_to_obj(get_current_thread()->aspace);
struct arch_aspace* as = &aspace->arch_aspace();
ArchVmAspace *as = &aspace->arch_aspace();
mxtl::unique_ptr<bitmap::RleBitmap> optimistic_bitmap;
if (!as->io_bitmap) {
if (!as->GetInnerAspace().io_bitmap) {
// Optimistically allocate a bitmap structure if we don't have one, and
// we'll see if we actually need this allocation later. In the common
// case, when we make the allocation we will use it.
@@ -86,12 +87,12 @@ int x86_set_io_bitmap(uint32_t port, uint32_t len, bool enable) {
status_t status = NO_ERROR;
do {
AutoSpinLock guard(as->io_bitmap_lock);
AutoSpinLock guard(as->GetInnerAspace().io_bitmap_lock);
if (!as->io_bitmap) {
as->io_bitmap = optimistic_bitmap.release();
if (!as->GetInnerAspace().io_bitmap) {
as->GetInnerAspace().io_bitmap = optimistic_bitmap.release();
}
auto bitmap = static_cast<bitmap::RleBitmap*>(as->io_bitmap);
auto bitmap = static_cast<bitmap::RleBitmap*>(as->GetInnerAspace().io_bitmap);
DEBUG_ASSERT(bitmap);
status = enable ?
+44 -7
Ver Arquivo
@@ -19,6 +19,7 @@
#include <arch/x86/mmu_mem_types.h>
#include <kernel/mp.h>
#include <kernel/vm.h>
#include <kernel/vm/arch_vm_aspace.h>
#include <kernel/vm/pmm.h>
#include <bitmap/rle-bitmap.h>
@@ -1144,7 +1145,7 @@ static status_t mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t cou
return NO_ERROR;
}
status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t count,
static status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, const size_t count,
size_t* unmapped) {
return mmu_unmap<PageTable>(aspace, vaddr, count, unmapped);
}
@@ -1195,7 +1196,7 @@ static status_t mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, con
return NO_ERROR;
}
status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, const size_t count,
static status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, const size_t count,
uint mmu_flags, size_t* mapped) {
return mmu_map<PageTable>(aspace, vaddr, paddr, count, mmu_flags, mapped);
}
@@ -1238,7 +1239,7 @@ static status_t mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count,
return NO_ERROR;
}
status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint mmu_flags) {
static status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint mmu_flags) {
return mmu_protect<PageTable>(aspace, vaddr, count, mmu_flags);
}
@@ -1277,7 +1278,7 @@ void x86_mmu_init(void) {}
/*
* Fill in the high level x86 arch aspace structure and allocating a top level page table.
*/
status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint mmu_flags) {
static status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint mmu_flags) {
DEBUG_ASSERT(aspace);
DEBUG_ASSERT(aspace->magic != ARCH_ASPACE_MAGIC);
@@ -1384,7 +1385,7 @@ status_t mmu_destroy_aspace(arch_aspace_t* aspace) {
return NO_ERROR;
}
status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace) {
static status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace) {
return mmu_destroy_aspace<PageTable>(aspace);
}
@@ -1392,7 +1393,7 @@ status_t guest_mmu_destroy_paspace(guest_paspace_t* paspace) {
return mmu_destroy_aspace<ExtendedPageTable>(paspace);
}
void arch_mmu_context_switch(arch_aspace_t* old_aspace, arch_aspace_t* aspace) {
static void arch_mmu_context_switch(arch_aspace_t* old_aspace, arch_aspace_t* aspace) {
mp_cpu_mask_t cpu_bit = 1U << arch_curr_cpu_num();
if (aspace != nullptr) {
DEBUG_ASSERT(aspace->magic == ARCH_ASPACE_MAGIC);
@@ -1481,7 +1482,7 @@ static status_t mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr,
return NO_ERROR;
}
status_t arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) {
static status_t arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) {
return mmu_query<PageTable>(aspace, vaddr, paddr, mmu_flags, x86_mmu_flags);
}
@@ -1510,3 +1511,39 @@ void x86_mmu_percpu_init(void) {
efer_msr |= X86_EFER_NXE;
write_msr(X86_MSR_IA32_EFER, efer_msr);
}
// OO STUFF
X86ArchVmAspace::X86ArchVmAspace() {
}
X86ArchVmAspace::~X86ArchVmAspace() {
// TODO: check that we've destroyed the aspace
}
status_t X86ArchVmAspace::Init(vaddr_t base, size_t size, uint mmu_flags) {
return arch_mmu_init_aspace(&aspace_, base, size, mmu_flags);
}
status_t X86ArchVmAspace::Destroy() {
return arch_mmu_destroy_aspace(&aspace_);
}
status_t X86ArchVmAspace::Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped) {
return arch_mmu_map(&aspace_, vaddr, paddr, count, mmu_flags, mapped);
}
status_t X86ArchVmAspace::Unmap(vaddr_t vaddr, size_t count, size_t* unmapped) {
return arch_mmu_unmap(&aspace_, vaddr, count, unmapped);
}
status_t X86ArchVmAspace::Protect(vaddr_t vaddr, size_t count, uint mmu_flags) {
return arch_mmu_protect(&aspace_, vaddr, count, mmu_flags);
}
status_t X86ArchVmAspace::Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) {
return arch_mmu_query(&aspace_, vaddr, paddr, mmu_flags);
}
void X86ArchVmAspace::ContextSwitch(X86ArchVmAspace *from, X86ArchVmAspace *to) {
arch_mmu_context_switch(from ? &from->aspace_ : nullptr, to ? &to->aspace_ : nullptr);
}
+16 -15
Ver Arquivo
@@ -8,15 +8,16 @@
#include <err.h>
#include <arch/x86/mmu.h>
#include <arch/mmu.h>
#include <kernel/vm/arch_vm_aspace.h>
static bool mmu_tests(void* context) {
BEGIN_TEST;
unittest_printf("creating large un-aligned vm region, and unmap it without mapping, make sure no leak (MG-315)\n");
{
arch_aspace_t aspace;
ArchVmAspace aspace;
vaddr_t base = 1UL << 20;
size_t size = (1UL << 47) - base - (1UL << 20);
status_t err = arch_mmu_init_aspace(&aspace, 1UL << 20, size, 0);
status_t err = aspace.Init(1UL << 20, size, 0);
EXPECT_EQ(err, NO_ERROR, "init aspace");
const uint arch_rw_flags = ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE;
@@ -31,45 +32,45 @@ static bool mmu_tests(void* context) {
// Map a single page to force the lower PDP of the target region
// to be created
size_t mapped;
err = arch_mmu_map(&aspace, va - 3 * PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
err = aspace.Map(va - 3 * PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
EXPECT_EQ(err, NO_ERROR, "map single page");
EXPECT_EQ(mapped, 1u, "map single page");
// Map the last page of the region
err = arch_mmu_map(&aspace, va + alloc_size - PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
err = aspace.Map(va + alloc_size - PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
EXPECT_EQ(err, NO_ERROR, "map last page");
EXPECT_EQ(mapped, 1u, "map single page");
paddr_t pa;
uint flags;
err = arch_mmu_query(&aspace, va + alloc_size - PAGE_SIZE, &pa, &flags);
err = aspace.Query(va + alloc_size - PAGE_SIZE, &pa, &flags);
EXPECT_EQ(err, NO_ERROR, "last entry is mapped");
// Attempt to unmap the target region (analogous to unmapping a demand
// paged region that has only had its last page touched)
size_t unmapped;
err = arch_mmu_unmap(&aspace, va, alloc_size / PAGE_SIZE, &unmapped);
err = aspace.Unmap(va, alloc_size / PAGE_SIZE, &unmapped);
EXPECT_EQ(err, NO_ERROR, "unmap unallocated region");
EXPECT_EQ(unmapped, alloc_size / PAGE_SIZE, "unmap unallocated region");
err = arch_mmu_query(&aspace, va + alloc_size - PAGE_SIZE, &pa, &flags);
err = aspace.Query(va + alloc_size - PAGE_SIZE, &pa, &flags);
EXPECT_EQ(err, ERR_NOT_FOUND, "last entry is not mapped anymore");
// Unmap the single page from earlier
err = arch_mmu_unmap(&aspace, va - 3 * PAGE_SIZE, 1, &unmapped);
err = aspace.Unmap(va - 3 * PAGE_SIZE, 1, &unmapped);
EXPECT_EQ(err, NO_ERROR, "unmap single page");
EXPECT_EQ(unmapped, 1u, "unmap unallocated region");
err = arch_mmu_destroy_aspace(&aspace);
err = aspace.Destroy();
EXPECT_EQ(err, NO_ERROR, "destroy aspace");
}
unittest_printf("creating large un-aligned vm region, and unmap it without mapping (MG-315)\n");
{
arch_aspace_t aspace;
ArchVmAspace aspace;
vaddr_t base = 1UL << 20;
size_t size = (1UL << 47) - base - (1UL << 20);
status_t err = arch_mmu_init_aspace(&aspace, 1UL << 20, size, 0);
status_t err = aspace.Init(1UL << 20, size, 0);
EXPECT_EQ(err, NO_ERROR, "init aspace");
const uint arch_rw_flags = ARCH_MMU_FLAG_PERM_READ | ARCH_MMU_FLAG_PERM_WRITE;
@@ -84,23 +85,23 @@ static bool mmu_tests(void* context) {
// Map a single page to force the lower PDP of the target region
// to be created
size_t mapped;
err = arch_mmu_map(&aspace, va - 2 * PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
err = aspace.Map(va - 2 * PAGE_SIZE, 0, 1, arch_rw_flags, &mapped);
EXPECT_EQ(err, NO_ERROR, "map single page");
EXPECT_EQ(mapped, 1u, "map single page");
// Attempt to unmap the target region (analogous to unmapping a demand
// paged region that has not been touched)
size_t unmapped;
err = arch_mmu_unmap(&aspace, va, alloc_size / PAGE_SIZE, &unmapped);
err = aspace.Unmap(va, alloc_size / PAGE_SIZE, &unmapped);
EXPECT_EQ(err, NO_ERROR, "unmap unallocated region");
EXPECT_EQ(unmapped, alloc_size / PAGE_SIZE, "unmap unallocated region");
// Unmap the single page from earlier
err = arch_mmu_unmap(&aspace, va - 2 * PAGE_SIZE, 1, &unmapped);
err = aspace.Unmap(va - 2 * PAGE_SIZE, 1, &unmapped);
EXPECT_EQ(err, NO_ERROR, "unmap single page");
EXPECT_EQ(unmapped, 1u, "unmap single page");
err = arch_mmu_destroy_aspace(&aspace);
err = aspace.Destroy();
EXPECT_EQ(err, NO_ERROR, "destroy aspace");
}
+1
Ver Arquivo
@@ -25,6 +25,7 @@
#include <arch/x86/feature.h>
#include <arch/x86/proc_trace.h>
#include <arch/x86/registers.h>
#include <inttypes.h>
#include <magenta/compiler.h>
#include <kernel/spinlock.h>
#include <kernel/thread.h>
+2
Ver Arquivo
@@ -5,6 +5,7 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <arch/mmu.h>
#include <assert.h>
#include <magenta/compiler.h>
#include <debug.h>
@@ -16,6 +17,7 @@
#include <kernel/mutex.h>
#include <kernel/spinlock.h>
#include <kernel/vm.h>
#include <kernel/vm/arch_vm_aspace.h>
#include <kernel/vm/vm_object.h>
#include <kernel/vm/vm_object_physical.h>
#include <list.h>
+2
Ver Arquivo
@@ -11,6 +11,7 @@
#define ARCH_MMU_FLAG_GUEST_PASPACE (1u << 8) /* guest physical address space */
/* initialize per address space */
namespace dontuse {
status_t guest_mmu_init_paspace(guest_paspace_t* paspace, size_t size) __NONNULL((1));
status_t guest_mmu_destroy_paspace(guest_paspace_t* paspace) __NONNULL((1));
@@ -19,3 +20,4 @@ status_t guest_mmu_map(guest_paspace_t* paspace, vaddr_t vaddr, paddr_t paddr, s
status_t guest_mmu_unmap(guest_paspace_t* paspace, vaddr_t vaddr, size_t count, size_t* unmapped) __NONNULL((1));
status_t guest_mmu_protect(guest_paspace_t* paspace, vaddr_t vaddr, size_t count, uint mmu_flags) __NONNULL((1));
status_t guest_mmu_query(guest_paspace_t* paspace, vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) __NONNULL((1));
};
+16 -29
Ver Arquivo
@@ -11,45 +11,32 @@
#include <magenta/compiler.h>
#include <sys/types.h>
/* to bring in definition of arch_aspace */
#include <arch/aspace.h>
#define ARCH_MMU_FLAG_CACHED (0 << 0)
#define ARCH_MMU_FLAG_UNCACHED (1 << 0)
#define ARCH_MMU_FLAG_UNCACHED_DEVICE (2 << 0) /* only exists on some arches, otherwise UNCACHED */
#define ARCH_MMU_FLAG_WRITE_COMBINING (3 << 0) /* only exists on some arches, otherwise UNCACHED */
#define ARCH_MMU_FLAG_CACHE_MASK (3 << 0)
#define ARCH_MMU_FLAG_PERM_USER (1 << 2)
#define ARCH_MMU_FLAG_PERM_READ (1 << 3)
#define ARCH_MMU_FLAG_PERM_WRITE (1 << 4)
#define ARCH_MMU_FLAG_PERM_EXECUTE (1 << 5)
#define ARCH_MMU_FLAG_NS (1 << 6) /* NON-SECURE */
#define ARCH_MMU_FLAG_INVALID (1 << 7) /* indicates that flags are not specified */
/* forward declare the per-address space arch-specific context object */
// forward declare the per-address space arch-specific context object
typedef struct arch_aspace arch_aspace_t;
#define ARCH_ASPACE_FLAG_KERNEL (1 << 0)
#if 0
// put all of these inside an internal namespace to discourage older code from calling directly
namespace arch_internal {
/* initialize per address space */
status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint mmu_flags) __NONNULL((1));
status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace) __NONNULL((1));
// initialize per address space
status_t arch_mmu_init_aspace(arch_aspace_t* aspace, vaddr_t base, size_t size, uint mmu_flags);
status_t arch_mmu_destroy_aspace(arch_aspace_t* aspace);
/* routines to map/unmap/update permissions/query mappings per address space */
status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped) __NONNULL((1));
status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, size_t* unmapped) __NONNULL((1));
status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint mmu_flags) __NONNULL((1));
status_t arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) __NONNULL((1));
// routines to map/unmap/update permissions/query mappings per address space
status_t arch_mmu_map(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped);
status_t arch_mmu_unmap(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, size_t* unmapped);
status_t arch_mmu_protect(arch_aspace_t* aspace, vaddr_t vaddr, size_t count, uint mmu_flags);
status_t arch_mmu_query(arch_aspace_t* aspace, vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags);
vaddr_t arch_mmu_pick_spot(const arch_aspace_t* aspace,
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) __NONNULL((1));
vaddr_t align, size_t size, uint mmu_flags);
/* load a new user address space context.
* aspace argument NULL should unload user space.
*/
void arch_mmu_context_switch(arch_aspace_t* old_aspace, arch_aspace_t* aspace);
void arch_disable_mmu(void);
} // namespace arch_internal
#endif
+3 -2
Ver Arquivo
@@ -16,7 +16,6 @@
#include <arch/thread.h>
#include <kernel/wait.h>
#include <kernel/spinlock.h>
#include <kernel/vm.h>
#include <debug.h>
__BEGIN_CDECLS
@@ -68,6 +67,8 @@ typedef void (*thread_user_callback_t)(enum thread_user_state_change new_state,
#define THREAD_LINEBUFFER_LENGTH 128
struct vmm_aspace;
typedef struct thread {
int magic;
struct list_node thread_list_node;
@@ -87,7 +88,7 @@ typedef struct thread {
int pinned_cpu; /* only run on pinned_cpu if >= 0 */
/* pointer to the kernel address space this thread is associated with */
vmm_aspace_t *aspace;
struct vmm_aspace *aspace;
/* pointer to user thread if one exists for this thread */
void *user_thread;
-2
Ver Arquivo
@@ -8,9 +8,7 @@
#pragma once
#include <arch.h>
#include <arch/mmu.h>
#include <assert.h>
#include <kernel/vm/page.h>
#include <list.h>
#include <magenta/compiler.h>
#include <stdint.h>
+59
Ver Arquivo
@@ -0,0 +1,59 @@
// Copyright 2017 The Fuchsia Authors
//
// 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 <mxtl/canary.h>
#include <mxtl/macros.h>
#include <sys/types.h>
#include <kernel/vm.h>
// flags
const uint ARCH_MMU_FLAG_CACHED = (0u << 0);
const uint ARCH_MMU_FLAG_UNCACHED = (1u << 0);
const uint ARCH_MMU_FLAG_UNCACHED_DEVICE = (2u << 0); // only exists on some arches, otherwise UNCACHED
const uint ARCH_MMU_FLAG_WRITE_COMBINING = (3u << 0); // only exists on some arches, otherwise UNCACHED
const uint ARCH_MMU_FLAG_CACHE_MASK = (3u << 0);
const uint ARCH_MMU_FLAG_PERM_USER = (1u << 2);
const uint ARCH_MMU_FLAG_PERM_READ = (1u << 3);
const uint ARCH_MMU_FLAG_PERM_WRITE = (1u << 4);
const uint ARCH_MMU_FLAG_PERM_EXECUTE = (1u << 5);
const uint ARCH_MMU_FLAG_NS = (1u << 6); // NON-SECURE
const uint ARCH_MMU_FLAG_INVALID = (1u << 7); // indicates that flags are not specified
const uint ARCH_ASPACE_FLAG_KERNEL = (1u << 0);
// per arch base class api to encapsulate the mmu routines on an aspace
class ArchVmAspaceBase {
public:
ArchVmAspaceBase() {}
virtual ~ArchVmAspaceBase() {}
DISALLOW_COPY_ASSIGN_AND_MOVE(ArchVmAspaceBase);
virtual status_t Init(vaddr_t base, size_t size, uint mmu_flags) = 0;
virtual status_t Destroy() = 0;
// main methods
virtual status_t Map(vaddr_t vaddr, paddr_t paddr, size_t count, uint mmu_flags, size_t* mapped) = 0;
virtual status_t Unmap(vaddr_t vaddr, size_t count, size_t* unmapped) = 0;
virtual status_t Protect(vaddr_t vaddr, size_t count, uint mmu_flags) = 0;
virtual status_t Query(vaddr_t vaddr, paddr_t* paddr, uint* mmu_flags) = 0;
virtual 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) {
return PAGE_ALIGN(base);
}
static void ContextSwitch(ArchVmAspaceBase *from, ArchVmAspaceBase *to);
private:
mxtl::Canary<mxtl::magic("VAAS")> canary_;
};
#include <arch/aspace.h>
+1 -8
Ver Arquivo
@@ -11,11 +11,8 @@
#include <magenta/compiler.h>
#include <stdint.h>
#if __cplusplus
// forward declare
class VmObject;
#endif
__BEGIN_CDECLS
// core per page structure
typedef struct vm_page {
@@ -30,13 +27,11 @@ typedef struct vm_page {
// in allocated/just freed state, use a linked list to hold the page in a queue
struct list_node node;
} free;
#if __cplusplus
struct {
// attached to a vm object
uint64_t offset;
VmObject* obj;
} object;
#endif
uint8_t pad[24]; // pad out to 32 bytes
};
@@ -64,5 +59,3 @@ static inline bool page_is_free(const vm_page_t* page) {
const char* page_state_to_string(unsigned int state);
void dump_page(const vm_page_t* page);
__END_CDECLS
-4
Ver Arquivo
@@ -11,8 +11,6 @@
#include <magenta/compiler.h>
#include <sys/types.h>
__BEGIN_CDECLS
// physical allocator
typedef struct pmm_arena_info {
char name[16];
@@ -90,5 +88,3 @@ paddr_t vm_page_to_paddr(const vm_page_t* page);
// paddr to vm_page_t
vm_page_t* paddr_to_vm_page(paddr_t addr);
__END_CDECLS
+3 -2
Ver Arquivo
@@ -11,6 +11,7 @@
#include <kernel/mutex.h>
#include <kernel/vm.h>
#include <kernel/vm/vm_address_region.h>
#include <kernel/vm/arch_vm_aspace.h>
#include <lib/crypto/prng.h>
#include <mxtl/canary.h>
#include <mxtl/intrusive_double_list.h>
@@ -45,7 +46,7 @@ public:
vaddr_t base() const { return base_; }
size_t size() const { return size_; }
const char* name() const { return name_; }
arch_aspace_t& arch_aspace() { return arch_aspace_; }
ArchVmAspace& arch_aspace() { return arch_aspace_; }
bool is_user() const { return (flags_ & TYPE_MASK) == TYPE_USER; }
bool is_aslr_enabled() const { return aslr_enabled_; }
@@ -194,7 +195,7 @@ private:
uint8_t aslr_seed_[crypto::PRNG::kMinEntropy];
// architecturally specific part of the aspace
arch_aspace_t arch_aspace_ = {};
ArchVmAspace arch_aspace_;
#if WITH_LIB_VDSO
mxtl::RefPtr<VmMapping> vdso_code_mapping_;
+1
Ver Arquivo
@@ -9,6 +9,7 @@
#include <assert.h>
#include <kernel/mutex.h>
#include <kernel/vm.h>
#include <kernel/vm/page.h>
#include <kernel/vm/vm_page_list.h>
#include <lib/user_copy/user_ptr.h>
#include <list.h>
+11
Ver Arquivo
@@ -0,0 +1,11 @@
// Copyright 2017 The Fuchsia Authors
//
// 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
#include <kernel/vm/arch_vm_aspace.h>
#include <kernel/vm.h>
#include <magenta/errors.h>
+1
Ver Arquivo
@@ -16,6 +16,7 @@ MODULE_DEPS += \
third_party/lib/cryptolib
MODULE_SRCS += \
$(LOCAL_DIR)/arch_vm_aspace.cpp \
$(LOCAL_DIR)/bootalloc.cpp \
$(LOCAL_DIR)/page.cpp \
$(LOCAL_DIR)/pmm.cpp \
+5 -6
Ver Arquivo
@@ -60,8 +60,7 @@ void MarkPagesInUse(vaddr_t va, size_t len) {
uint flags;
paddr_t pa;
status_t err = arch_mmu_query(&VmAspace::kernel_aspace()->arch_aspace(), va + offset,
&pa, &flags);
status_t err = VmAspace::kernel_aspace()->arch_aspace().Query(va + offset, &pa, &flags);
if (err >= 0) {
LTRACEF("va %#" PRIxPTR ", pa %#" PRIxPTR ", flags %#x, err %d, start_pa %#" PRIxPTR
" runlen %#" PRIxPTR "\n",
@@ -261,7 +260,7 @@ paddr_t vaddr_to_paddr(const void* ptr) {
return (paddr_t) nullptr;
paddr_t pa;
status_t rc = arch_mmu_query(&aspace->arch_aspace(), (vaddr_t)ptr, &pa, nullptr);
status_t rc = aspace->arch_aspace().Query((vaddr_t)ptr, &pa, nullptr);
if (rc)
return (paddr_t) nullptr;
@@ -299,7 +298,7 @@ static int cmd_vm(int argc, const cmd_args* argv, uint32_t flags) {
paddr_t pa;
uint flags;
status_t err = arch_mmu_query(&aspace->arch_aspace(), argv[2].u, &pa, &flags);
status_t err = aspace->arch_aspace().Query(argv[2].u, &pa, &flags);
printf("arch_mmu_query returns %d\n", err);
if (err >= 0) {
printf("\tpa %#" PRIxPTR ", flags %#x\n", pa, flags);
@@ -316,7 +315,7 @@ static int cmd_vm(int argc, const cmd_args* argv, uint32_t flags) {
size_t mapped;
auto err =
arch_mmu_map(&aspace->arch_aspace(), argv[3].u, argv[2].u, (uint)argv[4].u, (uint)argv[5].u, &mapped);
aspace->arch_aspace().Map(argv[3].u, argv[2].u, (uint)argv[4].u, (uint)argv[5].u, &mapped);
printf("arch_mmu_map returns %d, mapped %zu\n", err, mapped);
} else if (!strcmp(argv[1].str, "unmap")) {
if (argc < 4)
@@ -329,7 +328,7 @@ static int cmd_vm(int argc, const cmd_args* argv, uint32_t flags) {
}
size_t unmapped;
auto err = arch_mmu_unmap(&aspace->arch_aspace(), argv[2].u, (uint)argv[3].u, &unmapped);
auto err = aspace->arch_aspace().Unmap(argv[2].u, (uint)argv[3].u, &unmapped);
printf("arch_mmu_unmap returns %d, unmapped %zu\n", err, unmapped);
} else {
printf("unknown command\n");
+1 -2
Ver Arquivo
@@ -486,8 +486,7 @@ bool VmAddressRegion::CheckGapLocked(const ChildList::iterator& prev,
? next->as_vm_mapping()->arch_mmu_flags()
: ARCH_MMU_FLAG_INVALID;
*pva =
arch_mmu_pick_spot(&aspace_->arch_aspace(), real_gap_beg, prev_arch_mmu_flags, real_gap_end,
*pva = aspace_->arch_aspace().PickSpot(real_gap_beg, prev_arch_mmu_flags, real_gap_end,
next_arch_mmu_flags, align, region_size, arch_mmu_flags);
if (*pva < real_gap_beg)
goto not_found; // address wrapped around
+4 -3
Ver Arquivo
@@ -139,7 +139,8 @@ status_t VmAspace::Init() {
// intialize the architectually specific part
bool is_high_kernel = (flags_ & TYPE_MASK) == TYPE_KERNEL;
uint arch_aspace_flags = is_high_kernel ? ARCH_ASPACE_FLAG_KERNEL : 0;
status_t status = arch_mmu_init_aspace(&arch_aspace_, base_, size_, arch_aspace_flags);
status_t status = arch_aspace_.Init(base_, size_, arch_aspace_flags);
if (status != NO_ERROR) {
return status;
}
@@ -217,7 +218,7 @@ VmAspace::~VmAspace() {
// TODO(teisenbe): Move this to Destroy(). Currently can't move since
// ProcessDispatcher calls Destroy() from the context of a thread in the
// aspace.
arch_mmu_destroy_aspace(&arch_aspace_);
arch_aspace_.Destroy();
}
mxtl::RefPtr<VmAddressRegion> VmAspace::RootVmar() {
@@ -363,7 +364,7 @@ status_t VmAspace::ReserveSpace(const char* name, size_t size, vaddr_t vaddr) {
// lookup how it's already mapped
uint arch_mmu_flags = 0;
auto err = arch_mmu_query(&arch_aspace_, vaddr, nullptr, &arch_mmu_flags);
auto err = arch_aspace_.Query(vaddr, nullptr, &arch_mmu_flags);
if (err) {
// if it wasn't already mapped, use some sort of strict default
arch_mmu_flags = ARCH_MMU_FLAG_CACHED | ARCH_MMU_FLAG_PERM_READ;
+13 -14
Ver Arquivo
@@ -120,8 +120,7 @@ status_t VmMapping::ProtectLocked(vaddr_t base, size_t size, uint new_arch_mmu_f
// If we're changing the whole mapping, just make the change.
if (base_ == base && size_ == size) {
status_t status = arch_mmu_protect(&aspace_->arch_aspace(), base, size / PAGE_SIZE,
new_arch_mmu_flags);
status_t status = aspace_->arch_aspace().Protect(base, size / PAGE_SIZE, new_arch_mmu_flags);
LTRACEF("arch_mmu_protect returns %d\n", status);
arch_mmu_flags_ = new_arch_mmu_flags;
return NO_ERROR;
@@ -138,7 +137,7 @@ status_t VmMapping::ProtectLocked(vaddr_t base, size_t size, uint new_arch_mmu_f
return ERR_NO_MEMORY;
}
status_t status = arch_mmu_protect(&aspace_->arch_aspace(), base, size / PAGE_SIZE,
status_t status = aspace_->arch_aspace().Protect(base, size / PAGE_SIZE,
new_arch_mmu_flags);
LTRACEF("arch_mmu_protect returns %d\n", status);
arch_mmu_flags_ = new_arch_mmu_flags;
@@ -161,7 +160,7 @@ status_t VmMapping::ProtectLocked(vaddr_t base, size_t size, uint new_arch_mmu_f
return ERR_NO_MEMORY;
}
status_t status = arch_mmu_protect(&aspace_->arch_aspace(), base, size / PAGE_SIZE,
status_t status = aspace_->arch_aspace().Protect(base, size / PAGE_SIZE,
new_arch_mmu_flags);
LTRACEF("arch_mmu_protect returns %d\n", status);
@@ -190,7 +189,7 @@ status_t VmMapping::ProtectLocked(vaddr_t base, size_t size, uint new_arch_mmu_f
return ERR_NO_MEMORY;
}
status_t status = arch_mmu_protect(&aspace_->arch_aspace(), base, size / PAGE_SIZE,
status_t status = aspace_->arch_aspace().Protect(base, size / PAGE_SIZE,
new_arch_mmu_flags);
LTRACEF("arch_mmu_protect returns %d\n", status);
@@ -257,7 +256,7 @@ status_t VmMapping::UnmapLocked(vaddr_t base, size_t size) {
// Check if unmapping from one of the ends
if (base_ == base || base + size == base_ + size_) {
LTRACEF("unmapping base %#lx size %#zx\n", base, size);
status_t status = arch_mmu_unmap(&aspace_->arch_aspace(), base, size / PAGE_SIZE, nullptr);
status_t status = aspace_->arch_aspace().Unmap(base, size / PAGE_SIZE, nullptr);
if (status < 0) {
return status;
}
@@ -292,7 +291,7 @@ status_t VmMapping::UnmapLocked(vaddr_t base, size_t size) {
// Unmap the middle segment
LTRACEF("unmapping base %#lx size %#zx\n", base, size);
status_t status = arch_mmu_unmap(&aspace_->arch_aspace(), base, size / PAGE_SIZE, nullptr);
status_t status = aspace_->arch_aspace().Unmap(base, size / PAGE_SIZE, nullptr);
if (status < 0) {
return status;
}
@@ -362,7 +361,7 @@ status_t VmMapping::UnmapVmoRangeLocked(uint64_t offset, uint64_t len) const {
LTRACEF("going to unmap %#" PRIxPTR ", len %#" PRIx64 " aspace %p\n",
unmap_base.ValueOrDie(), len_new, aspace_.get());
status_t status = arch_mmu_unmap(&aspace_->arch_aspace(), unmap_base.ValueOrDie(),
status_t status = aspace_->arch_aspace().Unmap(unmap_base.ValueOrDie(),
static_cast<size_t>(len_new) / PAGE_SIZE, nullptr);
if (status < 0)
return status;
@@ -422,7 +421,7 @@ status_t VmMapping::MapRange(size_t offset, size_t len, bool commit) {
LTRACEF_LEVEL(2, "mapping pa %#" PRIxPTR " to va %#" PRIxPTR "\n", pa, va);
size_t mapped;
auto ret = arch_mmu_map(&aspace_->arch_aspace(), va, pa, 1, arch_mmu_flags_, &mapped);
auto ret = aspace_->arch_aspace().Map(va, pa, 1, arch_mmu_flags_, &mapped);
if (ret < 0) {
TRACEF("error %d mapping page at va %#" PRIxPTR " pa %#" PRIxPTR "\n", ret, va, pa);
}
@@ -566,7 +565,7 @@ status_t VmMapping::PageFault(vaddr_t va, const uint pf_flags) {
// this may happen if we are one of multiple threads racing on a single address
uint page_flags;
paddr_t pa;
status_t err = arch_mmu_query(&aspace_->arch_aspace(), va, &pa, &page_flags);
status_t err = aspace_->arch_aspace().Query(va, &pa, &page_flags);
if (err >= 0) {
LTRACEF("queried va, page at pa %#" PRIxPTR ", flags %#x is already there\n", pa,
page_flags);
@@ -581,7 +580,7 @@ status_t VmMapping::PageFault(vaddr_t va, const uint pf_flags) {
DEBUG_ASSERT((pa != vm_get_zero_page_paddr()) || !(mmu_flags & ARCH_MMU_FLAG_PERM_WRITE));
// same page, different permission
status = arch_mmu_protect(&aspace_->arch_aspace(), va, 1, mmu_flags);
status = aspace_->arch_aspace().Protect(va, 1, mmu_flags);
if (status < 0) {
TRACEF("failed to modify permissions on existing mapping\n");
return ERR_NO_MEMORY;
@@ -596,14 +595,14 @@ status_t VmMapping::PageFault(vaddr_t va, const uint pf_flags) {
DEBUG_ASSERT((new_pa != vm_get_zero_page_paddr()) || !(mmu_flags & ARCH_MMU_FLAG_PERM_WRITE));
// unmap the old one and put the new one in place
status = arch_mmu_unmap(&aspace_->arch_aspace(), va, 1, nullptr);
status = aspace_->arch_aspace().Unmap(va, 1, nullptr);
if (status < 0) {
TRACEF("failed to remove old mapping before replacing\n");
return ERR_NO_MEMORY;
}
size_t mapped;
status = arch_mmu_map(&aspace_->arch_aspace(), va, new_pa, 1, mmu_flags, &mapped);
status = aspace_->arch_aspace().Map(va, new_pa, 1, mmu_flags, &mapped);
if (status < 0) {
TRACEF("failed to map replacement page\n");
return ERR_NO_MEMORY;
@@ -621,7 +620,7 @@ status_t VmMapping::PageFault(vaddr_t va, const uint pf_flags) {
DEBUG_ASSERT((new_pa != vm_get_zero_page_paddr()) || !(mmu_flags & ARCH_MMU_FLAG_PERM_WRITE));
size_t mapped;
status = arch_mmu_map(&aspace_->arch_aspace(), va, new_pa, 1, mmu_flags, &mapped);
status = aspace_->arch_aspace().Map(va, new_pa, 1, mmu_flags, &mapped);
if (status < 0) {
TRACEF("failed to map page\n");
return ERR_NO_MEMORY;
+2 -9
Ver Arquivo
@@ -27,13 +27,11 @@
// This file mostly contains C wrappers around the underlying C++ objects, conforming to
// the older api.
static void vmm_context_switch(VmAspace* oldspace, VmAspace* newaspace);
static inline void vmm_context_switch(VmAspace* oldspace, VmAspace* newaspace) {
DEBUG_ASSERT(thread_lock_held());
arch_mmu_context_switch(oldspace ? &oldspace->arch_aspace() : nullptr,
newaspace ? &newaspace->arch_aspace() : nullptr);
ArchVmAspace::ContextSwitch(oldspace ? &oldspace->arch_aspace() : nullptr,
newaspace ? &newaspace->arch_aspace() : nullptr);
}
void vmm_context_switch(vmm_aspace_t* oldspace, vmm_aspace_t* newaspace) {
@@ -95,11 +93,6 @@ vmm_aspace_t* vmm_get_kernel_aspace(void) {
return reinterpret_cast<vmm_aspace_t*>(VmAspace::kernel_aspace());
}
arch_aspace_t* vmm_get_arch_aspace(vmm_aspace_t* aspace) {
auto real_aspace = reinterpret_cast<VmAspace*>(aspace);
return &real_aspace->arch_aspace();
}
static int cmd_vmm(int argc, const cmd_args* argv, uint32_t flags) {
if (argc < 2) {
notenoughargs:
+1
Ver Arquivo
@@ -16,6 +16,7 @@
#include <kernel/thread.h>
#include <kernel/mutex.h>
#include <kernel/spinlock.h>
#include <kernel/vm.h>
#include <lib/cmpctmalloc.h>
#include <lib/heap.h>
#include <platform.h>
@@ -6,6 +6,8 @@
#include <hypervisor/guest_physical_address_space.h>
#include <arch/mmu.h>
#include <kernel/vm/arch_vm_aspace.h>
#include <kernel/vm/fault.h>
#include <mxalloc/new.h>
@@ -23,7 +25,7 @@ status_t GuestPhysicalAddressSpace::Create(mxtl::RefPtr<VmObject> guest_phys_mem
if (!ac.check())
return ERR_NO_MEMORY;
status_t status = guest_mmu_init_paspace(&gpas->paspace_, kAddressSpaceSize);
status_t status = gpas->Init(kAddressSpaceSize);
if (status != NO_ERROR)
return status;
@@ -40,41 +42,44 @@ GuestPhysicalAddressSpace::GuestPhysicalAddressSpace(mxtl::RefPtr<VmObject> gues
: guest_phys_mem_(guest_phys_mem) {}
GuestPhysicalAddressSpace::~GuestPhysicalAddressSpace() {
__UNUSED status_t status = guest_mmu_destroy_paspace(&paspace_);
status_t status = aspace_.Destroy();
DEBUG_ASSERT(status == NO_ERROR);
}
static status_t map_page(guest_paspace_t* paspace, vaddr_t guest_paddr, paddr_t host_paddr,
status_t GuestPhysicalAddressSpace::Init(size_t size) {
return aspace_.Init(0, size, 0);
}
static status_t map_page(ArchVmGuestAspace *aspace, vaddr_t guest_paddr, paddr_t host_paddr,
uint mmu_flags) {
size_t mapped;
status_t status = guest_mmu_map(paspace, guest_paddr, host_paddr, 1, mmu_flags, &mapped);
status_t status = aspace->Map(guest_paddr, host_paddr, 1, mmu_flags, &mapped);
if (status != NO_ERROR)
return status;
return mapped != 1 ? ERR_NO_MEMORY : NO_ERROR;
}
status_t GuestPhysicalAddressSpace::MapApicPage(vaddr_t guest_paddr, paddr_t host_paddr) {
return map_page(&paspace_, guest_paddr, host_paddr, kApicMmuFlags);
return map_page(&aspace_, guest_paddr, host_paddr, kApicMmuFlags);
}
status_t GuestPhysicalAddressSpace::MapRange(vaddr_t guest_paddr, size_t size) {
auto mmu_map = [](void* context, size_t offset, size_t index, paddr_t pa) -> status_t {
guest_paspace_t* paspace = static_cast<guest_paspace_t*>(context);
return map_page(paspace, offset, pa, kMmuFlags);
ArchVmGuestAspace* aspace = static_cast<ArchVmGuestAspace*>(context);
return map_page(aspace, offset, pa, kMmuFlags);
};
return guest_phys_mem_->Lookup(guest_paddr, size, kPfFlags, mmu_map, &paspace_);
return guest_phys_mem_->Lookup(guest_paddr, size, kPfFlags, mmu_map, &aspace_);
}
status_t GuestPhysicalAddressSpace::UnmapRange(vaddr_t guest_paddr, size_t size) {
size_t num_pages = size / PAGE_SIZE;
size_t unmapped;
status_t status = guest_mmu_unmap(&paspace_, guest_paddr, num_pages, &unmapped);
status_t status = aspace_.Unmap(guest_paddr, num_pages, &unmapped);
if (status != NO_ERROR)
return status;
return unmapped != num_pages ? ERR_BAD_STATE : NO_ERROR;
}
status_t GuestPhysicalAddressSpace::GetPage(vaddr_t guest_paddr, paddr_t* host_paddr) {
uint mmu_flags;
return guest_mmu_query(&paspace_, guest_paddr, host_paddr, &mmu_flags);
return aspace_.Query(guest_paddr, host_paddr, nullptr);
}
@@ -7,7 +7,9 @@
#pragma once
#include <arch/guest_mmu.h>
#include <arch/aspace.h>
#include <kernel/vm/vm_object.h>
#include <mxtl/macros.h>
#include <mxtl/unique_ptr.h>
class GuestPhysicalAddressSpace {
@@ -17,19 +19,24 @@ public:
~GuestPhysicalAddressSpace();
status_t Init(size_t size);
size_t size() const { return guest_phys_mem_->size(); }
#if ARCH_X86_64
paddr_t Pml4Address() { return paspace_.pt_phys; }
status_t MapApicPage(vaddr_t guest_paddr, paddr_t host_paddr);
#endif
status_t UnmapRange(vaddr_t guest_paddr, size_t size);
status_t GetPage(vaddr_t guest_paddr, paddr_t* host_paddr);
#if ARCH_X86_64
paddr_t Pml4Address() { return aspace_.Pml4Address(); }
status_t MapApicPage(vaddr_t guest_paddr, paddr_t host_paddr);
#endif
private:
guest_paspace_t paspace_;
ArchVmGuestAspace aspace_;
mxtl::RefPtr<VmObject> guest_phys_mem_;
explicit GuestPhysicalAddressSpace(mxtl::RefPtr<VmObject> guest_phys_mem);
DISALLOW_COPY_ASSIGN_AND_MOVE(GuestPhysicalAddressSpace);
status_t MapRange(vaddr_t guest_paddr, size_t size);
};
+1
Ver Arquivo
@@ -17,6 +17,7 @@
#include <platform.h>
#include <platform/debug.h>
#include <kernel/thread.h>
#include <kernel/vm.h>
#if WITH_LIB_DEBUGLOG
#include <lib/debuglog.h>
+1 -1
Ver Arquivo
@@ -258,7 +258,7 @@ mx_status_t sys_process_create(mx_handle_t job_handle,
ktrace_name(TAG_PROC_NAME, koid, 0, buf);
// Give arch-specific tracing a chance to record process creation.
arch_trace_process_create(koid, &vmar_dispatcher->vmar()->aspace()->arch_aspace());
arch_trace_process_create(koid, &vmar_dispatcher->vmar()->aspace()->arch_aspace().GetInnerAspace());
// Create a handle and attach the dispatcher to it
HandleOwner proc_h(MakeHandle(mxtl::move(proc_dispatcher), proc_rights));
+2
Ver Arquivo
@@ -4,9 +4,11 @@
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <arch/x86/mmu.h>
#include <assert.h>
#include <efi/boot-services.h>
#include <err.h>
#include <inttypes.h>
#include <kernel/vm.h>
#include <lib/memory_limit.h>
#include <magenta/boot/multiboot.h>
+1
Ver Arquivo
@@ -10,6 +10,7 @@
#if WITH_DEV_PCIE
#include <arch/x86/feature.h>
#include <inttypes.h>
#include <dev/pcie_bus_driver.h>
#include <dev/pcie_device.h>
#include <mxtl/ref_ptr.h>
+1
Ver Arquivo
@@ -11,6 +11,7 @@
#include <dev/pcie_bus_driver.h>
#include <dev/pcie_platform.h>
#include <inttypes.h>
#include <kernel/mutex.h>
#include <lk/init.h>
#include <magenta/syscalls/pci.h>
+1
Ver Arquivo
@@ -10,6 +10,7 @@
#include <assert.h>
#include <debug.h>
#include <err.h>
#include <inttypes.h>
#include <reg.h>
#include <trace.h>