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 @@ -280,7 +280,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; @@ -822,7 +824,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; @@ -833,17 +836,25 @@ 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); + src = (uint8_t *)src + seg_len; + } else { + physcopyout(psrc, + (void *)(uintptr_t)(vlist->ds_addr + offset), + seg_len); + psrc += seg_len; + } offset = 0; - src = (uint8_t *)src + seg_len; len -= seg_len; vlist++; } } 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; @@ -854,10 +865,16 @@ 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); + dst = (uint8_t *)dst + seg_len; + } else { + physcopyin((void *)(uintptr_t)(vlist->ds_addr + offset), + pdst, seg_len); + pdst += seg_len; + } offset = 0; - dst = (uint8_t *)dst + seg_len; len -= seg_len; vlist++; } @@ -866,25 +883,36 @@ static int mdstart_preload(struct md_s *sc, struct bio *bp) { - uint8_t *p; + uint8_t *p = NULL; + vm_paddr_t phys = 0; - p = sc->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; } @@ -2043,7 +2071,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; @@ -2054,7 +2083,9 @@ sc->mediasize = length; sc->sectorsize = DEV_BSIZE; 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, @@ -2101,10 +2132,10 @@ if (mfs_root_size != 0) { sx_xlock(&md_sx); #ifdef MD_ROOT_MEM - md_preloaded(mfs_root, mfs_root_size, NULL); + md_preloaded(mfs_root, 0, mfs_root_size, NULL, true); #else - md_preloaded(__DEVOLATILE(u_char *, &mfs_root), mfs_root_size, - NULL); + md_preloaded(__DEVOLATILE(u_char *, &mfs_root), 0, mfs_root_size, + NULL, true); #endif sx_xunlock(&md_sx); } @@ -2123,7 +2154,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); } } @@ -2133,15 +2164,14 @@ */ for (int i = 0; i < 32; i++) { if (resource_long_value("md", i, "physaddr", - (long *) &paddr) != 0 || + (long *)&paddr) != 0 || resource_int_value("md", i, "len", &len) != 0) break; - ptr = (char *)pmap_map(NULL, paddr, paddr + len, VM_PROT_READ); - if (ptr != NULL && len != 0) { + if (len != 0) { sprintf(scratch, "preload%d 0x%016jx", i, (uintmax_t)paddr); sx_xlock(&md_sx); - md_preloaded(ptr, len, scratch); + md_preloaded(NULL, paddr, len, scratch, false); sx_xunlock(&md_sx); } }