summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorstsp <stsp@openbsd.org>2018-03-29 08:12:58 +0000
committerstsp <stsp@openbsd.org>2018-03-29 08:12:58 +0000
commita45f661f0879b5536e714169a456796bee5a03d7 (patch)
tree19f914b55da4a8ec5723bae3d7765b29b36f84c4 /sys
parentDo not crash on empty window, reported by Jamie Macdonald in GitHub (diff)
downloadwireguard-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@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/sparc64/stand/ofwboot/boot.c24
-rw-r--r--sys/arch/sparc64/stand/ofwboot/disk.h5
-rw-r--r--sys/arch/sparc64/stand/ofwboot/ofdev.c6
-rw-r--r--sys/arch/sparc64/stand/ofwboot/softraid_sparc64.c76
-rw-r--r--sys/arch/sparc64/stand/ofwboot/softraid_sparc64.h5
-rw-r--r--sys/arch/sparc64/stand/ofwboot/vers.c2
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";