1// Copyright 2016 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6#pragma once
7
8#include <fbl/intrusive_double_list.h>
9#include <fbl/macros.h>
10
11#include <trace.h>
12#include <vm/pmm.h>
13#include <zircon/types.h>
14
15class PmmNode;
16
17class PmmArena : public fbl::DoublyLinkedListable<PmmArena*> {
18public:
19    constexpr PmmArena() = default;
20    ~PmmArena() = default;
21
22    DISALLOW_COPY_ASSIGN_AND_MOVE(PmmArena);
23
24    // initialize the arena and allocate memory for internal data structures
25    zx_status_t Init(const pmm_arena_info_t* info, PmmNode* node);
26
27    // accessors
28    const pmm_arena_info_t& info() const { return info_; }
29    const char* name() const { return info_.name; }
30    paddr_t base() const { return info_.base; }
31    size_t size() const { return info_.size; }
32    unsigned int flags() const { return info_.flags; }
33    unsigned int priority() const { return info_.priority; }
34
35    // Counts the number of pages in every state. For each page in the arena,
36    // increments the corresponding VM_PAGE_STATE_*-indexed entry of
37    // |state_count|. Does not zero out the entries first.
38    void CountStates(size_t state_count[VM_PAGE_STATE_COUNT_]) const;
39
40    vm_page_t* get_page(size_t index) { return &page_array_[index]; }
41
42    // find a free run of contiguous pages
43    vm_page_t* FindFreeContiguous(size_t count, uint8_t alignment_log2);
44
45    // return a pointer to a specific page
46    vm_page_t* FindSpecific(paddr_t pa);
47
48    // helpers
49    bool page_belongs_to_arena(const vm_page* page) const {
50        return (page->paddr() >= base() && page->paddr() < (base() + size()));
51    }
52
53    bool address_in_arena(paddr_t address) const {
54        return (address >= info_.base && address <= info_.base + info_.size - 1);
55    }
56
57    void Dump(bool dump_pages, bool dump_free_ranges) const;
58
59private:
60    pmm_arena_info_t info_ = {};
61    vm_page_t* page_array_ = nullptr;
62};
63