diff --git a/sys/dev/md/md.c b/sys/dev/md/md.c --- a/sys/dev/md/md.c +++ b/sys/dev/md/md.c @@ -278,7 +278,9 @@ /* MD_PRELOAD related fields */ struct { u_char *pl_ptr; + vm_paddr_t pl_phys; size_t pl_len; + bool mapped; char name[PATH_MAX]; } s_preload; @@ -820,7 +822,8 @@ } static void -mdcopyto_vlist(void *src, bus_dma_segment_t *vlist, off_t offset, off_t len) +mdcopyto_vlist(struct md_s *sc, void *src, vm_paddr_t psrc, + bus_dma_segment_t *vlist, off_t offset, off_t len) { off_t seg_len; @@ -831,8 +834,14 @@ while (len != 0) { seg_len = omin(len, vlist->ds_len - offset); - bcopy(src, (void *)(uintptr_t)(vlist->ds_addr + offset), - seg_len); + if (sc->s_preload.mapped) { + bcopy(src, (void *)(uintptr_t)(vlist->ds_addr + offset), + seg_len); + } else { + physcopyout(psrc, + (void *)(uintptr_t)(vlist->ds_addr + offset), + seg_len); + } offset = 0; src = (uint8_t *)src + seg_len; len -= seg_len; @@ -841,7 +850,8 @@ } static void -mdcopyfrom_vlist(bus_dma_segment_t *vlist, off_t offset, void *dst, off_t len) +mdcopyfrom_vlist(struct md_s *sc, bus_dma_segment_t *vlist, off_t offset, + void *dst, vm_paddr_t pdst, off_t len) { off_t seg_len; @@ -852,8 +862,13 @@ while (len != 0) { seg_len = omin(len, vlist->ds_len - offset); - bcopy((void *)(uintptr_t)(vlist->ds_addr + offset), dst, - seg_len); + if (sc->s_preload.mapped) { + bcopy((void *)(uintptr_t)(vlist->ds_addr + offset), + dst, seg_len); + } else { + physcopyin((void *)(uintptr_t)(vlist->ds_addr + offset), + pdst, seg_len); + } offset = 0; dst = (uint8_t *)dst + seg_len; len -= seg_len; @@ -864,25 +879,36 @@ static int mdstart_preload(struct md_s *sc, struct bio *bp) { - uint8_t *p; + uint8_t *p = 0; + vm_paddr_t phys = 0; - p = sc->s.s_preload.pl_ptr + bp->bio_offset; + if (sc->s_preload.mapped) + p = sc->s_preload.pl_ptr + bp->bio_offset; + else + phys = sc->s_preload.pl_phys + bp->bio_offset; switch (bp->bio_cmd) { case BIO_READ: if ((bp->bio_flags & BIO_VLIST) != 0) { - mdcopyto_vlist(p, (bus_dma_segment_t *)bp->bio_data, + mdcopyto_vlist(sc, p, phys, + (bus_dma_segment_t *)bp->bio_data, bp->bio_ma_offset, bp->bio_length); } else { - bcopy(p, bp->bio_data, bp->bio_length); + if (sc->s_preload.mapped) + bcopy(p, bp->bio_data, bp->bio_length); + else + physcopyout(phys, bp->bio_data, bp->bio_length); } cpu_flush_dcache(bp->bio_data, bp->bio_length); break; case BIO_WRITE: if ((bp->bio_flags & BIO_VLIST) != 0) { - mdcopyfrom_vlist((bus_dma_segment_t *)bp->bio_data, - bp->bio_ma_offset, p, bp->bio_length); + mdcopyfrom_vlist(sc, (bus_dma_segment_t *)bp->bio_data, + bp->bio_ma_offset, p, phys, bp->bio_length); } else { - bcopy(bp->bio_data, p, bp->bio_length); + if (sc->s_preload.mapped) + bcopy(bp->bio_data, p, bp->bio_length); + else + physcopyin(bp->bio_data, phys, bp->bio_length); } break; } @@ -2034,7 +2060,8 @@ } static void -md_preloaded(u_char *image, size_t length, const char *name) +md_preloaded(u_char *image, vm_paddr_t pimage, size_t length, + const char *name, bool mapped) { struct md_s *sc; int error; @@ -2044,8 +2071,10 @@ return; sc->mediasize = length; sc->sectorsize = DEV_BSIZE; - sc->s.s_preload.pl_ptr = image; - sc->s.s_preload.pl_len = length; + sc->s_preload.pl_ptr = image; + sc->s_preload.pl_phys = pimage; + sc->s_preload.pl_len = length; + sc->s_preload.mapped = mapped; sc->start = mdstart_preload; if (name != NULL) strlcpy(sc->s_preload.name, name, @@ -2112,7 +2141,7 @@ len = preload_fetch_size(mod); if (ptr != NULL && len != 0) { sx_xlock(&md_sx); - md_preloaded(ptr, len, name); + md_preloaded(ptr, 0, len, name, true); sx_xunlock(&md_sx); } }