Skip to content

Commit 46b5800

Browse files
committed
libsel4vm, vgic: read gic registers from fdt
This commit adds an "fdt_ori" and "gic_node" parameter to the vm struct, which allows the library to find the gic register addresses required for emulating the vgic. Signed-off-by: Chris Guikema <[email protected]>
1 parent e4a4cc4 commit 46b5800

File tree

5 files changed

+96
-41
lines changed

5 files changed

+96
-41
lines changed

libsel4vm/include/sel4vm/guest_vm.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ struct vm {
203203
char *vm_name;
204204
unsigned int vm_id;
205205
bool vm_initialised;
206+
207+
char *gic_path;
208+
void *fdt_ori;
206209
};
207210

208211
/***

libsel4vm/src/arch/arm/guest_irq_controller.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,16 @@ int vm_create_default_irq_controller(vm_t *vm)
1212
ZF_LOGE("Failed to initialise default irq controller: Invalid vm");
1313
return -1;
1414
}
15+
16+
if (!vm->gic_path) {
17+
ZF_LOGE("Failed to find GIC path in VM structure");
18+
return -1;
19+
}
20+
21+
if (!vm->fdt_ori) {
22+
ZF_LOGE("Failed to find reference FDT");
23+
return -1;
24+
}
25+
1526
return vm_install_vgic(vm);
1627
}

libsel4vm/src/arch/arm/vgic/gicv2.h

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -10,41 +10,6 @@
1010
#include <assert.h>
1111
#include <stdint.h>
1212

13-
14-
/* FIXME these should be defined in a way that is friendlier to extension. */
15-
#if defined(CONFIG_PLAT_EXYNOS5)
16-
#define GIC_PADDR 0x10480000
17-
#elif defined(CONFIG_PLAT_TK1) || defined(CONFIG_PLAT_TX1)
18-
#define GIC_PADDR 0x50040000
19-
#elif defined(CONFIG_PLAT_TX2)
20-
#define GIC_PADDR 0x03880000
21-
#elif defined(CONFIG_PLAT_QEMU_ARM_VIRT)
22-
#define GIC_PADDR 0x8000000
23-
#elif defined(CONFIG_PLAT_ODROIDC2)
24-
#define GIC_PADDR 0xc4300000
25-
#elif defined(CONFIG_PLAT_ZYNQMP)
26-
#define GIC_PADDR 0xf9000000
27-
#else
28-
#error "Unsupported platform for GIC"
29-
#endif
30-
31-
#ifdef CONFIG_PLAT_QEMU_ARM_VIRT
32-
#define GIC_DIST_PADDR (GIC_PADDR)
33-
#define GIC_CPU_PADDR (GIC_PADDR + 0x00010000)
34-
#define GIC_VCPU_CNTR_PADDR (GIC_PADDR + 0x00030000)
35-
#define GIC_VCPU_PADDR (GIC_PADDR + 0x00040000)
36-
#elif defined(CONFIG_PLAT_ZYNQMP)
37-
#define GIC_DIST_PADDR (GIC_PADDR + 0x10000)
38-
#define GIC_CPU_PADDR (GIC_PADDR + 0x20000)
39-
#define GIC_VCPU_CNTR_PADDR (GIC_PADDR + 0x40000)
40-
#define GIC_VCPU_PADDR (GIC_PADDR + 0x60000)
41-
#else
42-
#define GIC_DIST_PADDR (GIC_PADDR + 0x1000)
43-
#define GIC_CPU_PADDR (GIC_PADDR + 0x2000)
44-
#define GIC_VCPU_CNTR_PADDR (GIC_PADDR + 0x4000)
45-
#define GIC_VCPU_PADDR (GIC_PADDR + 0x6000)
46-
#endif
47-
4813
/* Memory map for GIC distributor */
4914
struct gic_dist_map {
5015
uint32_t enable; /* 0x000 */

libsel4vm/src/arch/arm/vgic/vgic_v2.c

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,70 @@
5858
#include "gicv2.h"
5959
#include "vdist.h"
6060

61+
#include <libfdt.h>
6162

63+
static uintptr_t vcpu_addr;
64+
static uintptr_t cpu_addr;
65+
static uintptr_t dist_addr;
6266
static struct vgic_dist_device *vgic_dist;
6367

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+
64125
static inline struct gic_dist_map *vgic_priv_get_dist(struct vgic_dist_device *d)
65126
{
66127
assert(d);
@@ -215,17 +276,17 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie)
215276
return frame_result;
216277
}
217278
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);
219280
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);
221282
if (err) {
222283
ZF_LOGE("Failed to find device cap for vgic vcpu");
223284
return frame_result;
224285
}
225286
}
226287
frame_result.cptr = frame.capPtr;
227288
frame_result.rights = seL4_AllRights;
228-
frame_result.vaddr = GIC_CPU_PADDR;
289+
frame_result.vaddr = cpu_addr;
229290
frame_result.size_bits = seL4_PageBits;
230291
return frame_result;
231292
}
@@ -236,6 +297,9 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie)
236297
*/
237298
int vm_install_vgic(vm_t *vm)
238299
{
300+
/* Read device tree to find memory regions */
301+
gic_get_registers_from_fdt(vm, &dist_addr, &cpu_addr, &vcpu_addr);
302+
239303
struct vgic *vgic = calloc(1, sizeof(*vgic));
240304
if (!vgic) {
241305
assert(!"Unable to calloc memory for VGIC");
@@ -251,19 +315,21 @@ int vm_install_vgic(vm_t *vm)
251315
return -1;
252316
}
253317
memcpy(vgic_dist, &dev_vgic_dist, sizeof(struct vgic_dist_device));
318+
vgic_dist->pstart = dist_addr;
254319

255320
vgic->dist = calloc(1, sizeof(struct gic_dist_map));
256321
assert(vgic->dist);
257322
if (vgic->dist == NULL) {
258323
return -1;
259324
}
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,
261327
handle_vgic_dist_fault, (void *)vgic_dist);
262328
vgic_dist->vgic = vgic;
263329
vgic_dist_reset(vgic_dist);
264330

265331
/* 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,
267333
handle_vgic_vcpu_fault, NULL);
268334
int err = vm_map_reservation(vm, vgic_vcpu_reservation, vgic_vcpu_iterator, (void *)vm);
269335
if (err) {
@@ -292,7 +358,7 @@ int vm_vgic_maintenance_handler(vm_vcpu_t *vcpu)
292358
}
293359

294360
const struct vgic_dist_device dev_vgic_dist = {
295-
.pstart = GIC_DIST_PADDR,
361+
.pstart = 0,
296362
.size = 0x1000,
297363
.vgic = NULL,
298364
};

libsel4vm/src/arch/arm/vgic/vgicv2_defs.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,13 @@
6868
#define GIC_DIST_SGI_CPU_TARGET_LIST_MASK 0xFF << GIC_DIST_SGI_CPU_TARGET_LIST_SHIFT
6969

7070
#define GIC_DIST_SGI_INTID_MASK 0xF
71+
72+
/*
73+
* https://elixir.bootlin.com/linux/v3.8/source/Documentation/devicetree/bindings/arm/gic.txt
74+
*
75+
* Contants for getting registers from FDT */
76+
#define NUM_GIC_REGS 4
77+
#define GIC_DIST_ENTRY 0
78+
#define GIC_CPU_ENTRY 1
79+
#define GIC_VCPU_CNTR_ENTRY 2
80+
#define GIC_VCPU_ENTRY 3

0 commit comments

Comments
 (0)