diff options
Diffstat (limited to 'arch/sandbox/cpu/cpu.c')
-rw-r--r-- | arch/sandbox/cpu/cpu.c | 155 |
1 files changed, 133 insertions, 22 deletions
diff --git a/arch/sandbox/cpu/cpu.c b/arch/sandbox/cpu/cpu.c index cde0b055a6..fdfb209f77 100644 --- a/arch/sandbox/cpu/cpu.c +++ b/arch/sandbox/cpu/cpu.c | |||
@@ -2,7 +2,7 @@ | |||
2 | /* | 2 | /* |
3 | * Copyright (c) 2011 The Chromium OS Authors. | 3 | * Copyright (c) 2011 The Chromium OS Authors. |
4 | */ | 4 | */ |
5 | #define DEBUG | 5 | |
6 | #include <common.h> | 6 | #include <common.h> |
7 | #include <dm.h> | 7 | #include <dm.h> |
8 | #include <errno.h> | 8 | #include <errno.h> |
@@ -57,14 +57,104 @@ int cleanup_before_linux_select(int flags) | |||
57 | return 0; | 57 | return 0; |
58 | } | 58 | } |
59 | 59 | ||
60 | /** | ||
61 | * is_in_sandbox_mem() - Checks if a pointer is within sandbox's emulated DRAM | ||
62 | * | ||
63 | * This provides a way to check if a pointer is owned by sandbox (and is within | ||
64 | * its RAM) or not. Sometimes pointers come from a test which conceptually runs | ||
65 | * output sandbox, potentially with direct access to the C-library malloc() | ||
66 | * function, or the sandbox stack (which is not actually within the emulated | ||
67 | * DRAM. | ||
68 | * | ||
69 | * Such pointers obviously cannot be mapped into sandbox's DRAM, so we must | ||
70 | * detect them an process them separately, by recording a mapping to a tag, | ||
71 | * which we can use to map back to the pointer later. | ||
72 | * | ||
73 | * @ptr: Pointer to check | ||
74 | * @return true if this is within sandbox emulated DRAM, false if not | ||
75 | */ | ||
76 | static bool is_in_sandbox_mem(const void *ptr) | ||
77 | { | ||
78 | return (const uint8_t *)ptr >= gd->arch.ram_buf && | ||
79 | (const uint8_t *)ptr < gd->arch.ram_buf + gd->ram_size; | ||
80 | } | ||
81 | |||
82 | /** | ||
83 | * phys_to_virt() - Converts a sandbox RAM address to a pointer | ||
84 | * | ||
85 | * Sandbox uses U-Boot addresses from 0 to the size of DRAM. These index into | ||
86 | * the emulated DRAM buffer used by sandbox. This function converts such an | ||
87 | * address to a pointer into this buffer, which can be used to access the | ||
88 | * memory. | ||
89 | * | ||
90 | * If the address is outside this range, it is assumed to be a tag | ||
91 | */ | ||
60 | void *phys_to_virt(phys_addr_t paddr) | 92 | void *phys_to_virt(phys_addr_t paddr) |
61 | { | 93 | { |
62 | return (void *)(gd->arch.ram_buf + paddr); | 94 | struct sandbox_mapmem_entry *mentry; |
95 | struct sandbox_state *state; | ||
96 | |||
97 | /* If the address is within emulated DRAM, calculate the value */ | ||
98 | if (paddr < gd->ram_size) | ||
99 | return (void *)(gd->arch.ram_buf + paddr); | ||
100 | |||
101 | /* | ||
102 | * Otherwise search out list of tags for the correct pointer previously | ||
103 | * created by map_to_sysmem() | ||
104 | */ | ||
105 | state = state_get_current(); | ||
106 | list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { | ||
107 | if (mentry->tag == paddr) { | ||
108 | debug("%s: Used map from %lx to %p\n", __func__, | ||
109 | (ulong)paddr, mentry->ptr); | ||
110 | return mentry->ptr; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | printf("%s: Cannot map sandbox address %lx (SDRAM from 0 to %lx)\n", | ||
115 | __func__, (ulong)paddr, (ulong)gd->ram_size); | ||
116 | os_abort(); | ||
117 | |||
118 | /* Not reached */ | ||
119 | return NULL; | ||
63 | } | 120 | } |
64 | 121 | ||
65 | phys_addr_t virt_to_phys(void *vaddr) | 122 | struct sandbox_mapmem_entry *find_tag(const void *ptr) |
66 | { | 123 | { |
67 | return (phys_addr_t)((uint8_t *)vaddr - gd->arch.ram_buf); | 124 | struct sandbox_mapmem_entry *mentry; |
125 | struct sandbox_state *state = state_get_current(); | ||
126 | |||
127 | list_for_each_entry(mentry, &state->mapmem_head, sibling_node) { | ||
128 | if (mentry->ptr == ptr) { | ||
129 | debug("%s: Used map from %p to %lx\n", __func__, ptr, | ||
130 | mentry->tag); | ||
131 | return mentry; | ||
132 | } | ||
133 | } | ||
134 | return NULL; | ||
135 | } | ||
136 | |||
137 | phys_addr_t virt_to_phys(void *ptr) | ||
138 | { | ||
139 | struct sandbox_mapmem_entry *mentry; | ||
140 | |||
141 | /* | ||
142 | * If it is in emulated RAM, don't bother looking for a tag. Just | ||
143 | * calculate the pointer using the provides offset into the RAM buffer. | ||
144 | */ | ||
145 | if (is_in_sandbox_mem(ptr)) | ||
146 | return (phys_addr_t)((uint8_t *)ptr - gd->arch.ram_buf); | ||
147 | |||
148 | mentry = find_tag(ptr); | ||
149 | if (!mentry) { | ||
150 | /* Abort so that gdb can be used here */ | ||
151 | printf("%s: Cannot map sandbox address %p (SDRAM from 0 to %lx)\n", | ||
152 | __func__, ptr, (ulong)gd->ram_size); | ||
153 | os_abort(); | ||
154 | } | ||
155 | debug("%s: Used map from %p to %lx\n", __func__, ptr, mentry->tag); | ||
156 | |||
157 | return mentry->tag; | ||
68 | } | 158 | } |
69 | 159 | ||
70 | void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) | 160 | void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) |
@@ -87,24 +177,57 @@ void *map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags) | |||
87 | return phys_to_virt(paddr); | 177 | return phys_to_virt(paddr); |
88 | } | 178 | } |
89 | 179 | ||
90 | void unmap_physmem(const void *vaddr, unsigned long flags) | 180 | void unmap_physmem(const void *ptr, unsigned long flags) |
91 | { | 181 | { |
92 | #ifdef CONFIG_PCI | 182 | #ifdef CONFIG_PCI |
93 | if (map_dev) { | 183 | if (map_dev) { |
94 | pci_unmap_physmem(vaddr, map_len, map_dev); | 184 | pci_unmap_physmem(ptr, map_len, map_dev); |
95 | map_dev = NULL; | 185 | map_dev = NULL; |
96 | } | 186 | } |
97 | #endif | 187 | #endif |
98 | } | 188 | } |
99 | 189 | ||
100 | void sandbox_set_enable_pci_map(int enable) | 190 | phys_addr_t map_to_sysmem(const void *ptr) |
101 | { | 191 | { |
102 | enable_pci_map = enable; | 192 | struct sandbox_mapmem_entry *mentry; |
193 | |||
194 | /* | ||
195 | * If it is in emulated RAM, don't bother creating a tag. Just return | ||
196 | * the offset into the RAM buffer. | ||
197 | */ | ||
198 | if (is_in_sandbox_mem(ptr)) | ||
199 | return (u8 *)ptr - gd->arch.ram_buf; | ||
200 | |||
201 | /* | ||
202 | * See if there is an existing tag with this pointer. If not, set up a | ||
203 | * new one. | ||
204 | */ | ||
205 | mentry = find_tag(ptr); | ||
206 | if (!mentry) { | ||
207 | struct sandbox_state *state = state_get_current(); | ||
208 | |||
209 | mentry = malloc(sizeof(*mentry)); | ||
210 | if (!mentry) { | ||
211 | printf("%s: Error: Out of memory\n", __func__); | ||
212 | os_exit(ENOMEM); | ||
213 | } | ||
214 | mentry->tag = state->next_tag++; | ||
215 | mentry->ptr = (void *)ptr; | ||
216 | list_add_tail(&mentry->sibling_node, &state->mapmem_head); | ||
217 | debug("%s: Added map from %p to %lx\n", __func__, ptr, | ||
218 | (ulong)mentry->tag); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Return the tag as the address to use. A later call to map_sysmem() | ||
223 | * will return ptr | ||
224 | */ | ||
225 | return mentry->tag; | ||
103 | } | 226 | } |
104 | 227 | ||
105 | phys_addr_t map_to_sysmem(const void *ptr) | 228 | void sandbox_set_enable_pci_map(int enable) |
106 | { | 229 | { |
107 | return (u8 *)ptr - gd->arch.ram_buf; | 230 | enable_pci_map = enable; |
108 | } | 231 | } |
109 | 232 | ||
110 | void flush_dcache_range(unsigned long start, unsigned long stop) | 233 | void flush_dcache_range(unsigned long start, unsigned long stop) |
@@ -165,15 +288,3 @@ ulong timer_get_boot_us(void) | |||
165 | 288 | ||
166 | return (count - base_count) / 1000; | 289 | return (count - base_count) / 1000; |
167 | } | 290 | } |
168 | |||
169 | int setjmp(jmp_buf jmp) | ||
170 | { | ||
171 | return os_setjmp((ulong *)jmp, sizeof(*jmp)); | ||
172 | } | ||
173 | |||
174 | void longjmp(jmp_buf jmp, int ret) | ||
175 | { | ||
176 | os_longjmp((ulong *)jmp, ret); | ||
177 | while (1) | ||
178 | ; | ||
179 | } | ||