58
58
#include "gicv2.h"
59
59
#include "vdist.h"
60
60
61
+ #include <libfdt.h>
61
62
63
+ static uintptr_t vcpu_addr ;
64
+ static uintptr_t cpu_addr ;
65
+ static uintptr_t dist_addr ;
62
66
static struct vgic_dist_device * vgic_dist ;
63
67
68
+ static int gic_get_registers_from_fdt (vm_t * vm , uintptr_t * dist , uintptr_t * cpu , uintptr_t * vcpu )
69
+ {
70
+ const struct fdt_property * c ;
71
+ int len ;
72
+
73
+ int gic_offset = fdt_path_offset (vm -> fdt_ori , vm -> gic_path );
74
+ if (0 > gic_offset ) {
75
+ ZF_LOGE ("Failed to find gic offset from path: %s" , vm -> gic_path );
76
+ return -1 ;
77
+ }
78
+
79
+ int parent_offset = fdt_parent_offset (vm -> fdt_ori , gic_offset );
80
+ if (0 > parent_offset ) {
81
+ ZF_LOGE ("Failed to find gic parent offset" );
82
+ return -1 ;
83
+ }
84
+
85
+ int address_cells = fdt_address_cells (vm -> fdt_ori , parent_offset );
86
+ int size_cells = fdt_address_cells (vm -> fdt_ori , parent_offset );
87
+
88
+ if ((address_cells == 0 ) || (size_cells == 0 )) {
89
+ ZF_LOGE ("#address-cells or #size-cells are 0" );
90
+ return -1 ;
91
+ }
92
+
93
+ c = fdt_get_property (vm -> fdt_ori , gic_offset , "reg" , & len );
94
+ if (!c ) {
95
+ ZF_LOGE ("Failed to find reg in gic node" );
96
+ return -1 ;
97
+ }
98
+
99
+ /*
100
+ * 1st reg entry: Distributor
101
+ * 2nd reg entry: CPU Interface
102
+ * 3rd reg entry: GIC Virtual Interface Control Register
103
+ * 4th reg entry: GIC Virtual CPU Interface Register
104
+ */
105
+ uint64_t gic_regs [NUM_GIC_REGS ];
106
+ int calculated_size = size_cells * address_cells * NUM_GIC_REGS * sizeof (uint32_t );
107
+ int reg_offset = calculated_size / NUM_GIC_REGS ;
108
+
109
+ if (len != calculated_size ) {
110
+ ZF_LOGE ("Register size is unexpected. %d != %d" , len , calculated_size );
111
+ return -1 ;
112
+ }
113
+
114
+ for (int i = 0 ; i < NUM_GIC_REGS ; i ++ ) {
115
+ memcpy (& gic_regs [i ], (void * )(c -> data + (i * reg_offset )), sizeof (uint32_t ) * address_cells );
116
+ }
117
+
118
+ * dist = fdt64_to_cpu (gic_regs [GIC_DIST_ENTRY ]);
119
+ * cpu = fdt64_to_cpu (gic_regs [GIC_CPU_ENTRY ]);
120
+ * vcpu = fdt64_to_cpu (gic_regs [GIC_VCPU_ENTRY ]);
121
+
122
+ return 0 ;
123
+ }
124
+
64
125
static inline struct gic_dist_map * vgic_priv_get_dist (struct vgic_dist_device * d )
65
126
{
66
127
assert (d );
@@ -215,17 +276,17 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie)
215
276
return frame_result ;
216
277
}
217
278
seL4_Word vka_cookie ;
218
- err = vka_utspace_alloc_at (vm -> vka , & frame , kobject_get_type (KOBJECT_FRAME , 12 ), 12 , GIC_VCPU_PADDR , & vka_cookie );
279
+ err = vka_utspace_alloc_at (vm -> vka , & frame , kobject_get_type (KOBJECT_FRAME , 12 ), 12 , vcpu_addr , & vka_cookie );
219
280
if (err ) {
220
- err = simple_get_frame_cap (vm -> simple , (void * )GIC_VCPU_PADDR , 12 , & frame );
281
+ err = simple_get_frame_cap (vm -> simple , (void * )vcpu_addr , 12 , & frame );
221
282
if (err ) {
222
283
ZF_LOGE ("Failed to find device cap for vgic vcpu" );
223
284
return frame_result ;
224
285
}
225
286
}
226
287
frame_result .cptr = frame .capPtr ;
227
288
frame_result .rights = seL4_AllRights ;
228
- frame_result .vaddr = GIC_CPU_PADDR ;
289
+ frame_result .vaddr = cpu_addr ;
229
290
frame_result .size_bits = seL4_PageBits ;
230
291
return frame_result ;
231
292
}
@@ -236,6 +297,9 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie)
236
297
*/
237
298
int vm_install_vgic (vm_t * vm )
238
299
{
300
+ /* Read device tree to find memory regions */
301
+ gic_get_registers_from_fdt (vm , & dist_addr , & cpu_addr , & vcpu_addr );
302
+
239
303
struct vgic * vgic = calloc (1 , sizeof (* vgic ));
240
304
if (!vgic ) {
241
305
assert (!"Unable to calloc memory for VGIC" );
@@ -251,19 +315,21 @@ int vm_install_vgic(vm_t *vm)
251
315
return -1 ;
252
316
}
253
317
memcpy (vgic_dist , & dev_vgic_dist , sizeof (struct vgic_dist_device ));
318
+ vgic_dist -> pstart = dist_addr ;
254
319
255
320
vgic -> dist = calloc (1 , sizeof (struct gic_dist_map ));
256
321
assert (vgic -> dist );
257
322
if (vgic -> dist == NULL ) {
258
323
return -1 ;
259
324
}
260
- vm_memory_reservation_t * vgic_dist_res = vm_reserve_memory_at (vm , GIC_DIST_PADDR , PAGE_SIZE_4K ,
325
+
326
+ vm_memory_reservation_t * vgic_dist_res = vm_reserve_memory_at (vm , dist_addr , PAGE_SIZE_4K ,
261
327
handle_vgic_dist_fault , (void * )vgic_dist );
262
328
vgic_dist -> vgic = vgic ;
263
329
vgic_dist_reset (vgic_dist );
264
330
265
331
/* Remap VCPU to CPU */
266
- vm_memory_reservation_t * vgic_vcpu_reservation = vm_reserve_memory_at (vm , GIC_CPU_PADDR , PAGE_SIZE_4K ,
332
+ vm_memory_reservation_t * vgic_vcpu_reservation = vm_reserve_memory_at (vm , cpu_addr , PAGE_SIZE_4K ,
267
333
handle_vgic_vcpu_fault , NULL );
268
334
int err = vm_map_reservation (vm , vgic_vcpu_reservation , vgic_vcpu_iterator , (void * )vm );
269
335
if (err ) {
@@ -292,7 +358,7 @@ int vm_vgic_maintenance_handler(vm_vcpu_t *vcpu)
292
358
}
293
359
294
360
const struct vgic_dist_device dev_vgic_dist = {
295
- .pstart = GIC_DIST_PADDR ,
361
+ .pstart = 0 ,
296
362
.size = 0x1000 ,
297
363
.vgic = NULL ,
298
364
};
0 commit comments