mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-19 15:33:56 +00:00
Interrupts must be disabled while handling a partial cache line flush,
as otherwise the interrupt handling code may modify data in the non-DMA part of the cache line while we have it stashed away in the temporary stack buffer, then we end up restoring a stale value. PR: 160431 Submitted by: Ian Lepore MFC after: 1 week
This commit is contained in:
parent
f7f6865e6d
commit
15eddb68ee
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=234561
@ -1091,14 +1091,16 @@ static void
|
||||
bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op)
|
||||
{
|
||||
char _tmp_cl[arm_dcache_align], _tmp_clend[arm_dcache_align];
|
||||
register_t s;
|
||||
int partial;
|
||||
|
||||
if ((op & BUS_DMASYNC_PREWRITE) && !(op & BUS_DMASYNC_PREREAD)) {
|
||||
cpu_dcache_wb_range((vm_offset_t)buf, len);
|
||||
cpu_l2cache_wb_range((vm_offset_t)buf, len);
|
||||
}
|
||||
partial = (((vm_offset_t)buf) | len) & arm_dcache_align_mask;
|
||||
if (op & BUS_DMASYNC_PREREAD) {
|
||||
if (!(op & BUS_DMASYNC_PREWRITE) &&
|
||||
((((vm_offset_t)(buf) | len) & arm_dcache_align_mask) == 0)) {
|
||||
if (!(op & BUS_DMASYNC_PREWRITE) && !partial) {
|
||||
cpu_dcache_inv_range((vm_offset_t)buf, len);
|
||||
cpu_l2cache_inv_range((vm_offset_t)buf, len);
|
||||
} else {
|
||||
@ -1107,27 +1109,32 @@ bus_dmamap_sync_buf(void *buf, int len, bus_dmasync_op_t op)
|
||||
}
|
||||
}
|
||||
if (op & BUS_DMASYNC_POSTREAD) {
|
||||
if ((vm_offset_t)buf & arm_dcache_align_mask) {
|
||||
memcpy(_tmp_cl, (void *)((vm_offset_t)buf & ~
|
||||
arm_dcache_align_mask),
|
||||
(vm_offset_t)buf & arm_dcache_align_mask);
|
||||
}
|
||||
if (((vm_offset_t)buf + len) & arm_dcache_align_mask) {
|
||||
memcpy(_tmp_clend, (void *)((vm_offset_t)buf + len),
|
||||
arm_dcache_align - (((vm_offset_t)(buf) + len) &
|
||||
arm_dcache_align_mask));
|
||||
if (partial) {
|
||||
s = intr_disable();
|
||||
if ((vm_offset_t)buf & arm_dcache_align_mask)
|
||||
memcpy(_tmp_cl, (void *)((vm_offset_t)buf &
|
||||
~arm_dcache_align_mask),
|
||||
(vm_offset_t)buf & arm_dcache_align_mask);
|
||||
if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
|
||||
memcpy(_tmp_clend,
|
||||
(void *)((vm_offset_t)buf + len),
|
||||
arm_dcache_align - (((vm_offset_t)(buf) +
|
||||
len) & arm_dcache_align_mask));
|
||||
}
|
||||
cpu_dcache_inv_range((vm_offset_t)buf, len);
|
||||
cpu_l2cache_inv_range((vm_offset_t)buf, len);
|
||||
|
||||
if ((vm_offset_t)buf & arm_dcache_align_mask)
|
||||
memcpy((void *)((vm_offset_t)buf &
|
||||
~arm_dcache_align_mask), _tmp_cl,
|
||||
(vm_offset_t)buf & arm_dcache_align_mask);
|
||||
if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
|
||||
memcpy((void *)((vm_offset_t)buf + len), _tmp_clend,
|
||||
arm_dcache_align - (((vm_offset_t)(buf) + len) &
|
||||
arm_dcache_align_mask));
|
||||
if (partial) {
|
||||
if ((vm_offset_t)buf & arm_dcache_align_mask)
|
||||
memcpy((void *)((vm_offset_t)buf &
|
||||
~arm_dcache_align_mask), _tmp_cl,
|
||||
(vm_offset_t)buf & arm_dcache_align_mask);
|
||||
if (((vm_offset_t)buf + len) & arm_dcache_align_mask)
|
||||
memcpy((void *)((vm_offset_t)buf + len),
|
||||
_tmp_clend, arm_dcache_align -
|
||||
(((vm_offset_t)(buf) + len) &
|
||||
arm_dcache_align_mask));
|
||||
intr_restore(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user