-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libsel4vm, vgic: generate dist and cpu values #83
base: master
Are you sure you want to change the base?
Conversation
This isn't perfect, and requires a change in |
10783be
to
40a0325
Compare
Test with: seL4/camkes-vm#52 |
@@ -58,7 +58,8 @@ | |||
#include "gicv2.h" | |||
#include "vdist.h" | |||
|
|||
|
|||
static uintptr_t vcpu_addr; | |||
static uintptr_t cpu_addr; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we avoid these global variables and change the code flow to pass this pas parameter? We could also wrap al this in a struct for a context and then pass a pointer around. I think I have tried something in #69
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this point, yes, it feels like this could be reworked to avoid the globals. Since you've already done some work with that in the PR you referenced, do you want to handle that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd try to rebase my PR on this then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My preference would be to avoid adding the globals in this PR. The vgic_dist_device struct is intended for storing these exact mapping addresses and so they should be added there. As they aren't the same for the gic_v3, it's fine to create a different vgic_dist_device that's specialized to the gicv2 as it's private to this compilation unit.
40a0325
to
390bef1
Compare
|
||
/* Contants for getting registers from Device Tree */ | ||
#define NUM_GIC_REGS 4 | ||
#define GIC_DIST_ENTRY 0 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should get a more verbose comment. How much of a device tree standard is this actually or is it just what everybody seems to use. I think it might be better to inline these values and not expose any constants. Then a comment there can explain the the magic values come from. We can factor this out when these constants are to be somewhere. If we provide defines here, we names must be much more specific to avoid conflicts or get confusing.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I found a link with the standard. Its not just what everyone seems to use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you rename this to e.g. NUM_FDT_GIC_REGS
and FDT_GIC_REG_IDX_<DIST|CPU|VCPU_CNTR|VCPU>
? So we have names that are a bit less ambiguous and clearly state this is device tree related
390bef1
to
239562e
Compare
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]>
239562e
to
46b5800
Compare
@@ -236,6 +297,9 @@ static vm_frame_t vgic_vcpu_iterator(uintptr_t addr, void *cookie) | |||
*/ | |||
int vm_install_vgic(vm_t *vm) | |||
{ | |||
/* Read device tree to find memory regions */ | |||
gic_get_registers_from_fdt(vm, &dist_addr, &cpu_addr, &vcpu_addr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably check and return the error here if the GIC can't be found in the FDT.
char *gic_path; | ||
void *fdt_ori; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As these are both Arm specific, they should be added to the vm_arch struct.
This isn't an insignificant design change to the vm_t struct. If this is something that we should add, then it probably needs to be properly integrated into the rest of the library with proper initialization functions. If it's just an initial way to prototype associating a device tree with a guest for virtual devices to more easily find configuration information it should probably still have a proper way of installing it. (This would also allow the camkes-vm layer to more explicitly generate the fdt and then install it into the guest for the rest of the guest devices to use). Also, how is this expected to work with guests that don't use an FDT but want to use virtual devices that do use an fdt? |
One more comment, if this isn't something that we want to tackle now, then maybe a smaller-impact change would be choosing to have device specific interfaces for vm_install_vgic() that could take the configuration arguments needed, allowing the caller (camkes-vm) to do the device tree parsing and pass in the address ranges via the newer vm_install_vgic() interface. |
Thanks for the comments, Kent. This was something that I just put together based on the comments on using the GIC path to find the phandle. Basically, its more of a proof of concept. If you want to separate this commit out into a draft, so we can figure out the best way to do this properly while merging in the gic phandle, I'm okay with that approach. |
Doesn't the kernel pass an FDT to each VMM regardless of whether the guest needs to use the FDT? So I guess there's a disconnect between the guest's device tree, and the FDT used to describe the hardware resources of the system. Would it be possible to just use the ps_io_ops interface to get the FDT? Then search for the node with the |
In CAmkES, the DTB is given to the component if it has the I think one question that needs to be decided is whether device trees are a concept that libsel4vm should know about and have a mechanism for managing a device tree and installing it into the guest. It seems to me that this is better suited for libsel4vmmplatsupport? |
Yea, I'm not trying to say you shouldn't have proposed the changes, just pointing out that adding a way for vm devices to query a device tree associated with the guest is something that would be quite useful to many more devices than just the vgic, so we should consider the wider implications. EG, should this device tree be the system device tree, or the one that the guest sees? Are devices allowed to mutate it? If it's using a libfdt compatible object, then we could allow devices to install nodes in during their own initialization and have an explicit finalization step which is what Qemu does. |
} | ||
|
||
int address_cells = fdt_address_cells(vm->fdt_ori, parent_offset); | ||
int size_cells = fdt_address_cells(vm->fdt_ori, parent_offset); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int size_cells = fdt_address_cells(vm->fdt_ori, parent_offset); | |
int size_cells = fdt_size_cells(vm->fdt_ori, parent_offset); |
*/ | ||
uint64_t gic_regs[NUM_GIC_REGS]; | ||
int calculated_size = size_cells * address_cells * NUM_GIC_REGS * sizeof(uint32_t); | ||
int reg_offset = calculated_size / NUM_GIC_REGS; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int reg_offset = calculated_size / NUM_GIC_REGS; | |
int reg_size = calculated_size / NUM_GIC_REGS; |
This is the size of one value, not the offset
} | ||
|
||
for (int i = 0; i < NUM_GIC_REGS; i++) { | ||
memcpy(&gic_regs[i], (void *)(c->data + (i * reg_offset)), sizeof(uint32_t) * address_cells); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this has an implicit assumption that address_cells
is 2 and address_cells is 1. That may hold practically, so we could simply reject anything else for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should work with any case of address/size being 1 or 2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, extracting the value works for 1 or 2. But we need uint64_t gic_regs[NUM_GIC_REGS] = {0};
then to ensure the array is filled with zeros. Otherwise we might just copy 32 bits and the other 32-bit are random data,
* 4th reg entry: GIC Virtual CPU Interface Register | ||
*/ | ||
uint64_t gic_regs[NUM_GIC_REGS]; | ||
int calculated_size = size_cells * address_cells * NUM_GIC_REGS * sizeof(uint32_t); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
int calculated_size = size_cells * address_cells * NUM_GIC_REGS * sizeof(uint32_t); | |
int calculated_size = (address_cells + size_cells) * NUM_GIC_REGS * sizeof(uint32_t); |
We have one address cell followed by a size cell for each element. This just work because 2 * 2
happens to equal 2 + 2
I'm going to mark this as a draft, since like Kent mentioned, in order to do this, you need access to the FDT in the libraries, which is a bigger design choice than just this PR. I think this would still be useful as a reference for getting the GIC information out of the device tree once the FDT is available. |
This commit adds an "fdt_ori" and "gic_node" parameter to the vm struct, which allows the library to find the GIC_DIST and GIC_CPU register addresses required for emulating the vgic.