-
Notifications
You must be signed in to change notification settings - Fork 62
/
iomem.h
148 lines (129 loc) · 5.35 KB
/
iomem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
/*
* IO memory handling
*
* Copyright (c) 2016-2017 Fabrice Bellard
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
#ifndef IOMEM_H
#define IOMEM_H
typedef void DeviceWriteFunc(void *opaque, uint32_t offset,
uint32_t val, int size_log2);
typedef uint32_t DeviceReadFunc(void *opaque, uint32_t offset, int size_log2);
#define DEVIO_SIZE8 (1 << 0)
#define DEVIO_SIZE16 (1 << 1)
#define DEVIO_SIZE32 (1 << 2)
/* not supported, could add specific 64 bit callbacks when needed */
//#define DEVIO_SIZE64 (1 << 3)
#define DEVIO_DISABLED (1 << 4)
#define DEVRAM_FLAG_ROM (1 << 0) /* not writable */
#define DEVRAM_FLAG_DIRTY_BITS (1 << 1) /* maintain dirty bits */
#define DEVRAM_FLAG_DISABLED (1 << 2) /* allocated but not mapped */
#define DEVRAM_PAGE_SIZE_LOG2 12
#define DEVRAM_PAGE_SIZE (1 << DEVRAM_PAGE_SIZE_LOG2)
typedef struct PhysMemoryMap PhysMemoryMap;
typedef struct {
PhysMemoryMap *map;
uint64_t addr;
uint64_t org_size; /* original size */
uint64_t size; /* =org_size or 0 if the mapping is disabled */
BOOL is_ram;
/* the following is used for RAM access */
int devram_flags;
uint8_t *phys_mem;
int dirty_bits_size; /* in bytes */
uint32_t *dirty_bits; /* NULL if not used */
uint32_t *dirty_bits_tab[2];
int dirty_bits_index; /* 0-1 */
/* the following is used for I/O access */
void *opaque;
DeviceReadFunc *read_func;
DeviceWriteFunc *write_func;
int devio_flags;
} PhysMemoryRange;
#define PHYS_MEM_RANGE_MAX 32
struct PhysMemoryMap {
int n_phys_mem_range;
PhysMemoryRange phys_mem_range[PHYS_MEM_RANGE_MAX];
PhysMemoryRange *(*register_ram)(PhysMemoryMap *s, uint64_t addr,
uint64_t size, int devram_flags);
void (*free_ram)(PhysMemoryMap *s, PhysMemoryRange *pr);
const uint32_t *(*get_dirty_bits)(PhysMemoryMap *s, PhysMemoryRange *pr);
void (*set_ram_addr)(PhysMemoryMap *s, PhysMemoryRange *pr, uint64_t addr,
BOOL enabled);
void *opaque;
void (*flush_tlb_write_range)(void *opaque, uint8_t *ram_addr,
size_t ram_size);
};
PhysMemoryMap *phys_mem_map_init(void);
void phys_mem_map_end(PhysMemoryMap *s);
PhysMemoryRange *register_ram_entry(PhysMemoryMap *s, uint64_t addr,
uint64_t size, int devram_flags);
static inline PhysMemoryRange *cpu_register_ram(PhysMemoryMap *s, uint64_t addr,
uint64_t size, int devram_flags)
{
return s->register_ram(s, addr, size, devram_flags);
}
PhysMemoryRange *cpu_register_device(PhysMemoryMap *s, uint64_t addr,
uint64_t size, void *opaque,
DeviceReadFunc *read_func, DeviceWriteFunc *write_func,
int devio_flags);
PhysMemoryRange *get_phys_mem_range(PhysMemoryMap *s, uint64_t paddr);
void phys_mem_set_addr(PhysMemoryRange *pr, uint64_t addr, BOOL enabled);
static inline const uint32_t *phys_mem_get_dirty_bits(PhysMemoryRange *pr)
{
PhysMemoryMap *map = pr->map;
return map->get_dirty_bits(map, pr);
}
static inline void phys_mem_set_dirty_bit(PhysMemoryRange *pr, size_t offset)
{
size_t page_index;
uint32_t mask, *dirty_bits_ptr;
if (pr->dirty_bits) {
page_index = offset >> DEVRAM_PAGE_SIZE_LOG2;
mask = 1 << (page_index & 0x1f);
dirty_bits_ptr = pr->dirty_bits + (page_index >> 5);
*dirty_bits_ptr |= mask;
}
}
static inline BOOL phys_mem_is_dirty_bit(PhysMemoryRange *pr, size_t offset)
{
size_t page_index;
uint32_t *dirty_bits_ptr;
if (!pr->dirty_bits)
return TRUE;
page_index = offset >> DEVRAM_PAGE_SIZE_LOG2;
dirty_bits_ptr = pr->dirty_bits + (page_index >> 5);
return (*dirty_bits_ptr >> (page_index & 0x1f)) & 1;
}
void phys_mem_reset_dirty_bit(PhysMemoryRange *pr, size_t offset);
uint8_t *phys_mem_get_ram_ptr(PhysMemoryMap *map, uint64_t paddr, BOOL is_rw);
/* IRQ support */
typedef void SetIRQFunc(void *opaque, int irq_num, int level);
typedef struct {
SetIRQFunc *set_irq;
void *opaque;
int irq_num;
} IRQSignal;
void irq_init(IRQSignal *irq, SetIRQFunc *set_irq, void *opaque, int irq_num);
static inline void set_irq(IRQSignal *irq, int level)
{
irq->set_irq(irq->opaque, irq->irq_num, level);
}
#endif /* IOMEM_H */