git: f4c6843ec2b9 - main - xen: use correct cache attributes for Xen specific memory regions
Roger Pau Monné
royger at FreeBSD.org
Thu Aug 12 17:01:46 UTC 2021
On Thu, Aug 12, 2021 at 09:43:57AM -0700, John Baldwin wrote:
> On 8/12/21 8:53 AM, Roger Pau Monné wrote:
> > On Thu, Aug 12, 2021 at 08:20:51AM -0700, John Baldwin wrote:
> > > On 8/12/21 12:24 AM, Roger Pau Monné wrote:
> > > > The branch main has been updated by royger:
> > > >
> > > > URL: https://cgit.FreeBSD.org/src/commit/?id=f4c6843ec2b9aa5eff475778fb000ed6278c5b77
> > > >
> > > > commit f4c6843ec2b9aa5eff475778fb000ed6278c5b77
> > > > Author: Roger Pau Monné <royger at FreeBSD.org>
> > > > AuthorDate: 2021-04-09 09:31:44 +0000
> > > > Commit: Roger Pau Monné <royger at FreeBSD.org>
> > > > CommitDate: 2021-08-12 07:18:32 +0000
> > > >
> > > > xen: use correct cache attributes for Xen specific memory regions
> > > > bus_activate_resource maps memory regions as uncacheable on x86, which
> > > > is more strict than required for regions allocated using xenmem_alloc,
> > > > so don't rely on bus_activate_resource and instead map the region
> > > > using pmap_mapdev_attr and VM_MEMATTR_XEN as the cache attribute.
> > > > Sponsored by: Citrix Systems R&D
> > >
> > > It would probably be cleaner to use bus_map_resource() for this instead. It
> > > would mean you would have to use a structure that writes to as the argument
> > > to bus_read/write_* instead of using the resource directly.
> >
> > Those regions are usually handled to other subsystems of the kernel.
> > They are mostly used to map memory from other domains and then perform
> > IO on their behalf (like blkback and netback do), so it's not really
> > possible to assert that all users of the regions would use
> > bus_read/write_* to access them.
> >
> > I could however switch to using bus_map_resource if I can pass the
> > desired memory cache attribute and get a linear address back. It looks
> > like resource_map_request parameter allows to select the cache
> > attribute.
>
> Yes, one of the use case for bus_map_resource is to permit passing a
> non-default memory attribute. (It also permits mapping sub-ranges, but
> that isn't applicable in this case.) The 'r_vaddr' in the resource_map
> is the equivalent of rman_get_addr. It'd be a little cleaner (and
> perhaps friendly to future changes in this area) if your clients used
> the 'r_vaddr' from the resource_map directly instead of using
> rman_set_virtual() on the original resource. (At some point I would like
> to have each 'struct resource' keep a list of all the mappings created
> from it and to forcefully invalidate/free any existing mappings that
> still remain when a 'struct resource' is freed. I imagine as part of
> that I might end up with some assertions about the embedded resource
> fields in the 'struct resource' being self-consistent).
Does the following diff seem better:
diff --git a/sys/dev/xen/bus/xenpv.c b/sys/dev/xen/bus/xenpv.c
index 91004039a85e..748ead7f2f41 100644
--- a/sys/dev/xen/bus/xenpv.c
+++ b/sys/dev/xen/bus/xenpv.c
@@ -120,7 +120,8 @@ xenpv_alloc_physmem(device_t dev, device_t child, int *res_id, size_t size)
{
struct resource *res;
vm_paddr_t phys_addr;
- void *virt_addr;
+ struct resource_map_request margs;
+ struct resource_map map;
int error;
res = bus_alloc_resource(child, SYS_RES_MEMORY, res_id, LOW_MEM_LIMIT,
@@ -135,9 +136,16 @@ xenpv_alloc_physmem(device_t dev, device_t child, int *res_id, size_t size)
bus_release_resource(child, SYS_RES_MEMORY, *res_id, res);
return (NULL);
}
- virt_addr = pmap_mapdev_attr(phys_addr, size, VM_MEMATTR_XEN);
- KASSERT(virt_addr != NULL, ("Failed to create linear mappings"));
- rman_set_virtual(res, virt_addr);
+
+ resource_init_map_request(&margs);
+ margs.memattr = VM_MEMATTR_XEN;
+ error = bus_map_resource(child, SYS_RES_MEMORY, res, &margs, &map);
+ if (error != 0) {
+ vm_phys_fictitious_unreg_range(phys_addr, phys_addr + size);
+ bus_release_resource(child, SYS_RES_MEMORY, *res_id, res);
+ return (NULL);
+ }
+ rman_set_mapping(res, &map);
return (res);
}
@@ -146,14 +154,14 @@ static int
xenpv_free_physmem(device_t dev, device_t child, int res_id, struct resource *res)
{
vm_paddr_t phys_addr;
- vm_offset_t virt_addr;
+ struct resource_map map;
size_t size;
phys_addr = rman_get_start(res);
size = rman_get_size(res);
- virt_addr = (vm_offset_t)rman_get_virtual(res);
+ rman_get_mapping(res, &map);
- pmap_unmapdev(virt_addr, size);
+ bus_unmap_resource(child, SYS_RES_MEMORY, res, &map);
vm_phys_fictitious_unreg_range(phys_addr, phys_addr + size);
return (bus_release_resource(child, SYS_RES_MEMORY, res_id, res));
}
I also wonder if rman_set_mapping should clear the RF_UNMAPPED flag
from the resource? Or the content of the flags field is opaque from
rman PoV and it should be the caller of rman_set_mapping the one to
clear the flag? (xenpv_alloc_physmem in the code above)
It's kind of pointless to copy the bus_unmap_resource logic in
xenpv_free_physmem when it could be done by bus_release_resource if
the RF_UNMAPPED flag was cleared.
Thanks, Roger.
More information about the dev-commits-src-main
mailing list