blob: 1e00310f03462063e7e57c14d8486edd0994809f [file] [log] [blame]
Wedson Almeida Filhofed69022018-07-11 15:39:12 +01001#ifndef _MM_H
2#define _MM_H
3
4#include <stdbool.h>
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +01005#include <stdint.h>
Wedson Almeida Filhofed69022018-07-11 15:39:12 +01006
7#include "arch_mm.h"
8
9struct mm_ptable {
Andrew Scull265ada92018-07-30 15:19:01 +010010 paddr_t table;
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +010011 uint32_t id;
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010012};
13
Andrew Scull265ada92018-07-30 15:19:01 +010014/* An opaque type for an intermediate physical address from a VM. */
15typedef struct {
16 uintpaddr_t ipa;
17} ipaddr_t;
18
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010019#define PAGE_SIZE (1 << PAGE_BITS)
20
21/* The following are arch-independent page mapping modes. */
22#define MM_MODE_R 0x01 /* read */
23#define MM_MODE_W 0x02 /* write */
24#define MM_MODE_X 0x04 /* execute */
25#define MM_MODE_D 0x08 /* device */
26
27/*
28 * This flag indicates that memory allocation must not use locks. This is
29 * relevant in systems where interlocked operations are only available after
30 * virtual memory is enabled.
31 */
32#define MM_MODE_NOSYNC 0x10
33
34/*
35 * This flag indicates that the mapping is intended to be used in a first
36 * stage translation table, which might have different encodings for the
37 * attribute bits than the second stage table.
38 */
39#define MM_MODE_STAGE1 0x20
40
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +010041/*
42 * This flag indicates that no TLB invalidations should be issued for the
43 * changes in the page table.
44 */
45#define MM_MODE_NOINVALIDATE 0x40
46
47bool mm_ptable_init(struct mm_ptable *t, uint32_t id, int mode);
48void mm_ptable_dump(struct mm_ptable *t, int mode);
Andrew Scullfe636b12018-07-30 14:15:54 +010049bool mm_ptable_identity_map(struct mm_ptable *t, vaddr_t begin, vaddr_t end,
50 int mode);
51bool mm_ptable_identity_map_page(struct mm_ptable *t, vaddr_t va, int mode);
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010052bool mm_ptable_unmap(struct mm_ptable *t, vaddr_t begin, vaddr_t end, int mode);
Wedson Almeida Filho2f94ec12018-07-26 16:00:48 +010053bool mm_ptable_is_mapped(struct mm_ptable *t, vaddr_t addr, int mode);
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010054void mm_ptable_defrag(struct mm_ptable *t, int mode);
Wedson Almeida Filho84a30a02018-07-23 20:05:05 +010055bool mm_ptable_unmap_hypervisor(struct mm_ptable *t, int mode);
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010056
57bool mm_init(void);
Wedson Almeida Filho03e767a2018-07-30 15:32:03 +010058bool mm_cpu_init(void);
Andrew Scullfe636b12018-07-30 14:15:54 +010059bool mm_identity_map(vaddr_t begin, vaddr_t end, int mode);
Wedson Almeida Filhofdf4afc2018-07-19 15:45:21 +010060bool mm_unmap(vaddr_t begin, vaddr_t end, int mode);
61void mm_defrag(void);
Wedson Almeida Filhofed69022018-07-11 15:39:12 +010062
Andrew Scull265ada92018-07-30 15:19:01 +010063/**
64 * Initializes an intermeditate physical address.
65 */
66static inline ipaddr_t ipa_init(uintvaddr_t v)
67{
68 return (ipaddr_t){.ipa = v};
69}
70
71/**
72 * Extracts the absolute intermediate physical address.
73 */
74static inline uintpaddr_t ipa_addr(ipaddr_t ipa)
75{
76 return ipa.ipa;
77}
78
79/**
80 * Converts a physical address to a virtual address. Addresses are currently
81 * identity mapped so this is a simple type convertion.
82 */
83static inline vaddr_t mm_va_from_pa(paddr_t pa)
84{
85 return va_init(pa_addr(pa));
86}
87
88/**
89 * Converts a virtual address to a physical address. Addresses are currently
90 * identity mapped so this is a simple type convertion.
91 */
92static inline paddr_t mm_pa_from_va(vaddr_t va)
93{
94 return pa_init(va_addr(va));
95}
96
97/**
98 * Converts an intermediate physical address to a physical address. Addresses
99 * are currently identity mapped so this is a simple type convertion. Returns
100 * true if the address was mapped in the table and the address was converted.
101 */
102static inline bool mm_pa_from_ipa(struct mm_ptable *t, ipaddr_t ipa,
103 paddr_t *pa)
104{
105 /* TODO: the ptable functions map physical to virtual addresses but they
106 * should really be mapping to intermediate physical addresses.
107 * It might be better to have different interfaces to the mm functions?
108 * This might also mean ipaddr_t should be used when building the VM
109 * tables too?
110 * */
111 if (mm_ptable_is_mapped(t, va_init(ipa_addr(ipa)), 0)) {
112 *pa = pa_init(ipa_addr(ipa));
113 return true;
114 }
115 return false;
116}
117
118/**
119 * Converts a virtual address to a pointer. Only use when the virtual address
120 * is mapped for the calling context.
121 */
122static inline void *mm_ptr_from_va(vaddr_t va)
123{
124 return (void *)va_addr(va);
125}
126
Andrew Scull4f170f52018-07-19 12:58:20 +0100127#endif /* _MM_H */