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,8 +836,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; @@ -843,7 +852,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; @@ -854,8 +864,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; @@ -866,25 +881,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_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 +2069,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 +2081,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 +2130,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 +2152,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); } } @@ -2136,14 +2165,11 @@ (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) { - sprintf(scratch, "preload%d 0x%016jx", i, - (uintmax_t)paddr); - sx_xlock(&md_sx); - md_preloaded(ptr, len, scratch); - sx_xunlock(&md_sx); - } + sprintf(scratch, "preload%d 0x%016jx", i, + (uintmax_t)paddr); + sx_xlock(&md_sx); + md_preloaded(0, paddr, len, scratch, false); + sx_xunlock(&md_sx); } status_dev = make_dev(&mdctl_cdevsw, INT_MAX, UID_ROOT, GID_WHEEL,