diff options
author | 2018-03-29 08:12:58 +0000 | |
---|---|---|
committer | 2018-03-29 08:12:58 +0000 | |
commit | a45f661f0879b5536e714169a456796bee5a03d7 (patch) | |
tree | 19f914b55da4a8ec5723bae3d7765b29b36f84c4 | |
parent | Do not crash on empty window, reported by Jamie Macdonald in GitHub (diff) | |
download | wireguard-openbsd-a45f661f0879b5536e714169a456796bee5a03d7.tar.xz wireguard-openbsd-a45f661f0879b5536e714169a456796bee5a03d7.zip |
Make sparc64 ofwboot open the softraid boot chunk early on and keep the
handle open until a kernel has been loaded from the softraid volume.
This works around an apparent memory leak in the firmware on T5220
which fails to load an ldom guest kernel from softraid with a "Fast
Data Access MMU Miss" trap after many OF_open()/OF_close() calls.
This problem goes away when we call OF_open()/OF_close() just once
instead of for every block we want to read.
Crank ofwboot version to 1.10.
Make sure to keep working boot media around before upgrading!
Softraid boot of an T5220 ldom guest (CRYPTO), and a v240 (RAID 1),
have been tested and are known to work. Please report issues to bugs@.
ok kettenis@
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/boot.c | 24 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/disk.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/ofdev.c | 6 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c | 76 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h | 5 | ||||
-rw-r--r-- | sys/arch/sparc64/stand/ofwboot/vers.c | 2 |
6 files changed, 62 insertions, 56 deletions
diff --git a/sys/arch/sparc64/stand/ofwboot/boot.c b/sys/arch/sparc64/stand/ofwboot/boot.c index 5a22dc658e0..09a2a4714d2 100644 --- a/sys/arch/sparc64/stand/ofwboot/boot.c +++ b/sys/arch/sparc64/stand/ofwboot/boot.c @@ -1,4 +1,4 @@ -/* $OpenBSD: boot.c,v 1.27 2016/09/11 17:53:26 jsing Exp $ */ +/* $OpenBSD: boot.c,v 1.28 2018/03/29 08:12:58 stsp Exp $ */ /* $NetBSD: boot.c,v 1.3 2001/05/31 08:55:19 mrg Exp $ */ /* * Copyright (c) 1997, 1999 Eduardo E. Horvath. All rights reserved. @@ -248,6 +248,8 @@ loadfile(int fd, char *args) close(fd); #ifdef SOFTRAID + if (bootdev_dip) + OF_close(bootdev_dip->sr_handle); sr_clear_keys(); #endif chain(entry, args, ssym, esym); @@ -283,12 +285,11 @@ fail: } #ifdef SOFTRAID -/* Set bootdev_dip to the software boot volume, if specified. */ +/* Set bootdev_dip to the softraid boot volume, if specified. */ static int srbootdev(const char *bootline) { struct sr_boot_volume *bv; - struct diskinfo *dip; int unit; bootdev_dip = NULL; @@ -320,9 +321,23 @@ srbootdev(const char *bootline) return EPERM; if (bv->sbv_diskinfo == NULL) { + struct sr_boot_chunk *bc; + struct diskinfo *dip, *bc_dip; + int sr_handle; + + /* All reads will come from the boot chunk. */ + bc = sr_vol_boot_chunk(bv); + if (bc == NULL) + return ENXIO; + bc_dip = (struct diskinfo *)bc->sbc_diskinfo; + sr_handle = OF_open(bc_dip->path); + if (sr_handle == -1) + return EIO; + dip = alloc(sizeof(struct diskinfo)); bzero(dip, sizeof(*dip)); dip->sr_vol = bv; + dip->sr_handle = sr_handle; bv->sbv_diskinfo = dip; } @@ -331,7 +346,8 @@ srbootdev(const char *bootline) /* Attempt to read disklabel. */ bv->sbv_part = 'c'; - if (sr_getdisklabel(bv, &dip->disklabel)) { + if (sr_getdisklabel(bv, &bootdev_dip->disklabel)) { + OF_close(bootdev_dip->sr_handle); free(bv->sbv_diskinfo, sizeof(struct diskinfo)); bv->sbv_diskinfo = NULL; bootdev_dip = NULL; diff --git a/sys/arch/sparc64/stand/ofwboot/disk.h b/sys/arch/sparc64/stand/ofwboot/disk.h index 043cc09a64c..929ed93758d 100644 --- a/sys/arch/sparc64/stand/ofwboot/disk.h +++ b/sys/arch/sparc64/stand/ofwboot/disk.h @@ -1,4 +1,4 @@ -/* $OpenBSD: disk.h,v 1.1 2014/11/26 20:30:41 stsp Exp $ */ +/* $OpenBSD: disk.h,v 1.2 2018/03/29 08:12:58 stsp Exp $ */ /* * Copyright (c) 1997 Tobias Weingartner @@ -36,7 +36,10 @@ struct diskinfo { char path[256]; struct disklabel disklabel; + + /* Used during softraid boot. */ struct sr_boot_volume *sr_vol; + int sr_handle; /* open handle for reading from boot chunk */ TAILQ_ENTRY(diskinfo) list; }; diff --git a/sys/arch/sparc64/stand/ofwboot/ofdev.c b/sys/arch/sparc64/stand/ofwboot/ofdev.c index 9a69605859f..8e2d22d0616 100644 --- a/sys/arch/sparc64/stand/ofwboot/ofdev.c +++ b/sys/arch/sparc64/stand/ofwboot/ofdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ofdev.c,v 1.25 2015/10/01 16:08:20 krw Exp $ */ +/* $OpenBSD: ofdev.c,v 1.26 2018/03/29 08:12:58 stsp Exp $ */ /* $NetBSD: ofdev.c,v 1.1 2000/08/20 14:58:41 mrg Exp $ */ /* @@ -125,8 +125,8 @@ strategy(void *devdata, int rw, daddr32_t blk, size_t size, void *buf, #ifdef SOFTRAID /* Intercept strategy for softraid volumes. */ if (dev->type == OFDEV_SOFTRAID) - return sr_strategy(bootdev_dip->sr_vol, rw, - blk, size, buf, rsize); + return sr_strategy(bootdev_dip->sr_vol, bootdev_dip->sr_handle, + rw, blk, size, buf, rsize); #endif if (dev->type != OFDEV_DISK) panic("strategy"); diff --git a/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c b/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c index 49c6eee737e..534b4ebbf15 100644 --- a/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c +++ b/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_sparc64.c,v 1.2 2016/09/11 17:53:26 jsing Exp $ */ +/* $OpenBSD: softraid_sparc64.c,v 1.3 2018/03/29 08:12:58 stsp Exp $ */ /* * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> @@ -306,9 +306,25 @@ srprobe(void) free(md, SR_META_SIZE * DEV_BSIZE); } +struct sr_boot_chunk * +sr_vol_boot_chunk(struct sr_boot_volume *bv) +{ + struct sr_boot_chunk *bc = NULL; + + if (bv->sbv_level == 1 || bv->sbv_level == 'C' ) { /* RAID1 or CRYPTO */ + /* Select first online chunk. */ + SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) + if (bc->sbc_state == BIOC_SDONLINE) + break; + } + + return bc; +} + + int -sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, - void *buf, size_t *rsize) +sr_strategy(struct sr_boot_volume *bv, int sr_handle, int rw, daddr32_t blk, + size_t size, void *buf, size_t *rsize) { struct diskinfo *sr_dip, *dip; struct partition *pp; @@ -320,7 +336,6 @@ sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, u_char iv[8]; u_char *bp; int err; - int ihandle; /* We only support read-only softraid. */ if (rw != F_READ) @@ -331,55 +346,28 @@ sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, blk += DL_GETPOFFSET(&sr_dip->disklabel.d_partitions[bv->sbv_part - 'a']); + bc = sr_vol_boot_chunk(bv); + if (bc == NULL) + return ENXIO; + + dip = (struct diskinfo *)bc->sbc_diskinfo; + pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a']; + bzero(&ofdev, sizeof(ofdev)); + ofdev.handle = sr_handle; + ofdev.type = OFDEV_DISK; + ofdev.bsize = DEV_BSIZE; + ofdev.partoff = DL_GETPOFFSET(pp); + if (bv->sbv_level == 0) { return ENOTSUP; } else if (bv->sbv_level == 1) { - - /* Select first online chunk. */ - SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) - if (bc->sbc_state == BIOC_SDONLINE) - break; - if (bc == NULL) - return EIO; - - dip = (struct diskinfo *)bc->sbc_diskinfo; - pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a']; blk += bv->sbv_data_blkno; /* XXX - If I/O failed we should try another chunk... */ - ihandle = OF_open(dip->path); - if (ihandle == -1) - return EIO; - bzero(&ofdev, sizeof(ofdev)); - ofdev.handle = ihandle; - ofdev.type = OFDEV_DISK; - ofdev.bsize = DEV_BSIZE; - ofdev.partoff = DL_GETPOFFSET(pp); err = strategy(&ofdev, rw, blk, size, buf, rsize); - OF_close(ihandle); return err; } else if (bv->sbv_level == 'C') { - - /* Select first online chunk. */ - SLIST_FOREACH(bc, &bv->sbv_chunks, sbc_link) - if (bc->sbc_state == BIOC_SDONLINE) - break; - if (bc == NULL) - return EIO; - - dip = (struct diskinfo *)bc->sbc_diskinfo; - pp = &dip->disklabel.d_partitions[bc->sbc_part - 'a']; - - ihandle = OF_open(dip->path); - if (ihandle == -1) - return EIO; - bzero(&ofdev, sizeof(ofdev)); - ofdev.handle = ihandle; - ofdev.type = OFDEV_DISK; - ofdev.bsize = DEV_BSIZE; - ofdev.partoff = DL_GETPOFFSET(pp); - /* XXX - select correct key. */ aes_xts_setkey(&ctx, (u_char *)bv->sbv_keys, 64); @@ -395,7 +383,6 @@ sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, printf("Read from crypto volume failed " "(read %d bytes): %s\n", *rsize, strerror(err)); - OF_close(ihandle); return err; } bcopy(&blkno, iv, sizeof(blkno)); @@ -404,7 +391,6 @@ sr_strategy(struct sr_boot_volume *bv, int rw, daddr32_t blk, size_t size, aes_xts_decrypt(&ctx, bp + j); } *rsize = nsect * DEV_BSIZE; - OF_close(ihandle); return err; } else diff --git a/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h b/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h index 9189917047a..ce297d66614 100644 --- a/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h +++ b/sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h @@ -1,4 +1,4 @@ -/* $OpenBSD: softraid_sparc64.h,v 1.3 2016/09/11 17:53:26 jsing Exp $ */ +/* $OpenBSD: softraid_sparc64.h,v 1.4 2018/03/29 08:12:58 stsp Exp $ */ /* * Copyright (c) 2012 Joel Sing <jsing@openbsd.org> @@ -21,8 +21,9 @@ void srprobe(void); +struct sr_boot_chunk *sr_vol_boot_chunk(struct sr_boot_volume *); const char *sr_getdisklabel(struct sr_boot_volume *, struct disklabel *); -int sr_strategy(struct sr_boot_volume *, int, daddr32_t, size_t, +int sr_strategy(struct sr_boot_volume *, int, int, daddr32_t, size_t, void *, size_t *); #endif /* _SOFTRAID_SPARC64_H */ diff --git a/sys/arch/sparc64/stand/ofwboot/vers.c b/sys/arch/sparc64/stand/ofwboot/vers.c index 7905595ead1..2c747fd35da 100644 --- a/sys/arch/sparc64/stand/ofwboot/vers.c +++ b/sys/arch/sparc64/stand/ofwboot/vers.c @@ -1 +1 @@ -const char version[] = "1.9"; +const char version[] = "1.10"; |