summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2018-11-05 13:53:06 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2018-11-05 13:53:06 +0000
commit40fc639cb57bbbbb360437ad5d4934c7635d14a8 (patch)
treec36a29785f0aff7e4e39c517a9354575649fdfb1
parent9b539c3a538225ff8d6ffa0132e51db9a678401f (diff)
parentc540c5554db983fb615df293797142edc10b4c62 (diff)
downloadillumos-joyent-40fc639cb57bbbbb360437ad5d4934c7635d14a8.tar.gz
[illumos-gate merge]
commit c540c5554db983fb615df293797142edc10b4c62 9927 refetch_read_once() would like a p please bob commit b6c711cc370ad66a5c9391c71936f34bb8616e93 9939 Need to stop GCC reordering functions commit b75eb7e6b5e51c1d1a8023c478487c4f4542768f 9840 loader: do not repeat int13 calls when we have no media 9841 loader: issue edd probe before legacy ah=08 commit 3602e97d70b31e6f0ae7e1d6fdcd52f4c0e0fbaf 9949 loader: do not probe floppy devices for zfs
-rw-r--r--usr/src/Makefile.master22
-rw-r--r--usr/src/boot/sys/boot/i386/libi386/biosdisk.c278
-rw-r--r--usr/src/boot/sys/boot/i386/loader/main.c2
-rw-r--r--usr/src/uts/Makefile.uts1
-rw-r--r--usr/src/uts/intel/asm/cpu.h2
5 files changed, 222 insertions, 83 deletions
diff --git a/usr/src/Makefile.master b/usr/src/Makefile.master
index b0283d1b5a..9bcbc553aa 100644
--- a/usr/src/Makefile.master
+++ b/usr/src/Makefile.master
@@ -354,13 +354,21 @@ CCNOAUTOINLINE= \
-_gcc=-fno-inline-small-functions \
-_gcc=-fno-inline-functions-called-once \
-_gcc=-fno-ipa-cp \
- -_gcc6=-fno-ipa-icf \
-_gcc7=-fno-ipa-icf \
-_gcc8=-fno-ipa-icf \
- -_gcc6=-fno-clone-functions \
-_gcc7=-fno-clone-functions \
-_gcc8=-fno-clone-functions
+# GCC may put functions in different named sub-sections of .text based on
+# their presumed calling frequency. At least in the kernel, where we actually
+# deliver relocatable objects, we don't want this to happen.
+#
+# Since at present we don't benefit from this even in userland, we disable it globally,
+# but the application of this may move into usr/src/uts/ in future.
+CCNOREORDER= \
+ -_gcc7=-fno-reorder-functions \
+ -_gcc8=-fno-reorder-functions
+
# One optimization the compiler might perform is to turn this:
# #pragma weak foo
# extern int foo;
@@ -587,12 +595,12 @@ $(SRCDBGBLD)CCSOURCEDEBUGFLAGS = -g -xs
CFLAGS= $(COPTFLAG) $($(MACH)_CFLAGS) $(SPACEFLAG) $(CCMODE) \
$(ILDOFF) $(CERRWARN) $(CSTD) $(CCUNBOUND) $(IROPTFLAG) \
- $(CGLOBALSTATIC) $(CCNOAUTOINLINE) $(CSOURCEDEBUGFLAGS) \
- $(CUSERFLAGS)
+ $(CGLOBALSTATIC) $(CCNOAUTOINLINE) $(CCNOREORDER) \
+ $(CSOURCEDEBUGFLAGS) $(CUSERFLAGS)
CFLAGS64= $(COPTFLAG64) $($(MACH64)_CFLAGS) $(SPACEFLAG64) $(CCMODE64) \
$(ILDOFF) $(CERRWARN) $(CSTD) $(CCUNBOUND) $(IROPTFLAG64) \
- $(CGLOBALSTATIC) $(CCNOAUTOINLINE) $(CSOURCEDEBUGFLAGS) \
- $(CUSERFLAGS64)
+ $(CGLOBALSTATIC) $(CCNOAUTOINLINE) $(CCNOREORDER) \
+ $(CSOURCEDEBUGFLAGS) $(CUSERFLAGS64)
#
# Flags that are used to build parts of the code that are subsequently
# run on the build machine (also known as the NATIVE_BUILD).
@@ -600,7 +608,7 @@ CFLAGS64= $(COPTFLAG64) $($(MACH64)_CFLAGS) $(SPACEFLAG64) $(CCMODE64) \
NATIVE_CFLAGS= $(COPTFLAG) $($(NATIVE_MACH)_CFLAGS) $(CCMODE) \
$(ILDOFF) $(CERRWARN) $(CSTD) $($(NATIVE_MACH)_CCUNBOUND) \
$(IROPTFLAG) $(CGLOBALSTATIC) $(CCNOAUTOINLINE) \
- $(CSOURCEDEBUGFLAGS) $(CUSERFLAGS)
+ $(CCNOREORDER) $(CSOURCEDEBUGFLAGS) $(CUSERFLAGS)
DTEXTDOM=-DTEXT_DOMAIN=\"$(TEXT_DOMAIN)\" # For messaging.
DTS_ERRNO=-D_TS_ERRNO
diff --git a/usr/src/boot/sys/boot/i386/libi386/biosdisk.c b/usr/src/boot/sys/boot/i386/libi386/biosdisk.c
index e286a7e29f..3db2144763 100644
--- a/usr/src/boot/sys/boot/i386/libi386/biosdisk.c
+++ b/usr/src/boot/sys/boot/i386/libi386/biosdisk.c
@@ -79,8 +79,10 @@ static struct bdinfo
#define BD_MODEINT13 0x0000
#define BD_MODEEDD1 0x0001
#define BD_MODEEDD3 0x0002
+#define BD_MODEEDD (BD_MODEEDD1 | BD_MODEEDD3)
#define BD_MODEMASK 0x0003
#define BD_FLOPPY 0x0004
+#define BD_NO_MEDIA 0x0008
int bd_type; /* BIOS 'drive type' (floppy only) */
uint16_t bd_sectorsize; /* Sector size */
uint64_t bd_sectors; /* Disk size */
@@ -188,60 +190,83 @@ bd_init(void)
}
/*
- * Try to detect a device supported by the legacy int13 BIOS
+ * Return EDD version or 0 if EDD is not supported on this drive.
*/
static int
-bd_int13probe(struct bdinfo *bd)
+bd_check_extensions(int unit)
{
- struct edd_params params;
- int ret = 1; /* assume success */
+ /* Determine if we can use EDD with this device. */
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0x4100;
+ v86.edx = unit;
+ v86.ebx = 0x55aa;
+ v86int();
+
+ if (V86_CY(v86.efl) || /* carry set */
+ (v86.ebx & 0xffff) != 0xaa55) /* signature */
+ return (0);
+
+ /* extended disk access functions (AH=42h-44h,47h,48h) supported */
+ if ((v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
+ return (0);
+ return ((v86.eax >> 8) & 0xff);
+}
+
+static void
+bd_reset_disk(int unit)
+{
+ /* reset disk */
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0;
+ v86.edx = unit;
+ v86int();
+}
+
+/*
+ * Read CHS info. Return 0 on success, error otherwise.
+ */
+static int
+bd_get_diskinfo_std(struct bdinfo *bd)
+{
+ bzero(&v86, sizeof (v86));
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
v86.eax = 0x800;
v86.edx = bd->bd_unit;
v86int();
- /* Don't error out if we get bad sector number, try EDD as well */
- if (V86_CY(v86.efl) || /* carry set */
- (v86.edx & 0xff) <= (unsigned)(bd->bd_unit & 0x7f)) /* unit # bad */
- return (0); /* skip device */
+ if (V86_CY(v86.efl) && ((v86.eax & 0xff00) != 0))
+ return ((v86.eax & 0xff00) >> 8);
- if ((v86.ecx & 0x3f) == 0) /* absurd sector number */
- ret = 0; /* set error */
+ /* return custom error on absurd sector number */
+ if ((v86.ecx & 0x3f) == 0)
+ return (0x60);
- /* Convert max cyl # -> # of cylinders */
bd->bd_cyl = ((v86.ecx & 0xc0) << 2) + ((v86.ecx & 0xff00) >> 8) + 1;
/* Convert max head # -> # of heads */
bd->bd_hds = ((v86.edx & 0xff00) >> 8) + 1;
bd->bd_sec = v86.ecx & 0x3f;
- bd->bd_type = v86.ebx & 0xff;
- bd->bd_flags |= BD_MODEINT13;
+ bd->bd_type = v86.ebx;
+ bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
- /* Calculate sectors count from the geometry */
- bd->bd_sectors = bd->bd_cyl * bd->bd_hds * bd->bd_sec;
- bd->bd_sectorsize = BIOSDISK_SECSIZE;
- DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
- bd->bd_hds, bd->bd_sec);
+ return (0);
+}
+
+/*
+ * Read EDD info. Return 0 on success, error otherwise.
+ */
+static int
+bd_get_diskinfo_ext(struct bdinfo *bd)
+{
+ struct edd_params params;
+ uint64_t total;
- /* Determine if we can use EDD with this device. */
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0x4100;
- v86.edx = bd->bd_unit;
- v86.ebx = 0x55aa;
- v86int();
- if (V86_CY(v86.efl) || /* carry set */
- (v86.ebx & 0xffff) != 0xaa55 || /* signature */
- (v86.ecx & EDD_INTERFACE_FIXED_DISK) == 0)
- return (ret); /* return code from int13 AH=08 */
-
- /* EDD supported */
- bd->bd_flags |= BD_MODEEDD1;
- if ((v86.eax & 0xff00) >= 0x3000)
- bd->bd_flags |= BD_MODEEDD3;
/* Get disk params */
- params.len = sizeof (struct edd_params);
+ bzero(&params, sizeof (params));
+ params.len = sizeof (params);
v86.ctl = V86_FLAGS;
v86.addr = 0x13;
v86.eax = 0x4800;
@@ -249,36 +274,120 @@ bd_int13probe(struct bdinfo *bd)
v86.ds = VTOPSEG(&params);
v86.esi = VTOPOFF(&params);
v86int();
- if (!V86_CY(v86.efl)) {
- uint64_t total;
- /*
- * Sector size must be a multiple of 512 bytes.
- * An alternate test would be to check power of 2,
- * powerof2(params.sector_size).
- */
- if (params.sector_size % BIOSDISK_SECSIZE)
- bd->bd_sectorsize = BIOSDISK_SECSIZE;
- else
- bd->bd_sectorsize = params.sector_size;
+ if (V86_CY(v86.efl) && ((v86.eax & 0xff00) != 0))
+ return ((v86.eax & 0xff00) >> 8);
- total = bd->bd_sectorsize * params.sectors;
- if (params.sectors != 0) {
- /* Only update if we did not overflow. */
- if (total > params.sectors)
- bd->bd_sectors = params.sectors;
- }
+ /*
+ * Sector size must be a multiple of 512 bytes.
+ * An alternate test would be to check power of 2,
+ * powerof2(params.sector_size).
+ * 4K is largest read buffer we can use at this time.
+ */
+ if (params.sector_size >= 512 &&
+ params.sector_size <= 4096 &&
+ (params.sector_size % BIOSDISK_SECSIZE) == 0)
+ bd->bd_sectorsize = params.sector_size;
+ bd->bd_cyl = params.cylinders;
+ bd->bd_hds = params.heads;
+ bd->bd_sec = params.sectors_per_track;
+
+ if (params.sectors != 0) {
+ total = params.sectors;
+ } else {
total = (uint64_t)params.cylinders *
params.heads * params.sectors_per_track;
- if (total > 0 && bd->bd_sectors > total)
- bd->bd_sectors = total;
+ }
+ bd->bd_sectors = total;
+
+ return (0);
+}
+
+/*
+ * Try to detect a device supported by the legacy int13 BIOS
+ */
+static int
+bd_int13probe(struct bdinfo *bd)
+{
+ int edd;
+ int ret;
- ret = 1;
+ bd->bd_flags &= ~BD_NO_MEDIA;
+
+ edd = bd_check_extensions(bd->bd_unit);
+ if (edd == 0)
+ bd->bd_flags |= BD_MODEINT13;
+ else if (edd < 0x30)
+ bd->bd_flags |= BD_MODEEDD1;
+ else
+ bd->bd_flags |= BD_MODEEDD3;
+
+ /* Default sector size */
+ bd->bd_sectorsize = BIOSDISK_SECSIZE;
+
+ /*
+ * Test if the floppy device is present, so we can avoid receiving
+ * bogus information from bd_get_diskinfo_std().
+ */
+ if (bd->bd_unit < 0x80) {
+ /* reset disk */
+ bd_reset_disk(bd->bd_unit);
+
+ /* Get disk type */
+ v86.ctl = V86_FLAGS;
+ v86.addr = 0x13;
+ v86.eax = 0x1500;
+ v86.edx = bd->bd_unit;
+ v86int();
+ if (V86_CY(v86.efl) || (v86.eax & 0x300) == 0)
+ return (0);
}
- DEBUG("unit 0x%x flags %x, sectors %llu, sectorsize %u",
- bd->bd_unit, bd->bd_flags, bd->bd_sectors, bd->bd_sectorsize);
- return (ret);
+
+ ret = 1;
+ if (edd != 0)
+ ret = bd_get_diskinfo_ext(bd);
+ if (ret != 0 || bd->bd_sectors == 0)
+ ret = bd_get_diskinfo_std(bd);
+
+ if (ret != 0 && bd->bd_unit < 0x80) {
+ /* Set defaults for 1.44 floppy */
+ bd->bd_cyl = 80;
+ bd->bd_hds = 2;
+ bd->bd_sec = 18;
+ bd->bd_type = 4;
+ bd->bd_sectors = 2880;
+ /* Since we are there, there most likely is no media */
+ bd->bd_flags |= BD_NO_MEDIA;
+ ret = 0;
+ }
+
+ if (ret != 0) {
+ if (bd->bd_sectors != 0 && edd != 0) {
+ bd->bd_sec = 63;
+ bd->bd_hds = 255;
+ bd->bd_cyl =
+ (bd->bd_sectors + bd->bd_sec * bd->bd_hds - 1) /
+ bd->bd_sec * bd->bd_hds;
+ } else {
+ printf("Can not get information about %s unit %#x\n",
+ biosdisk.dv_name, bd->bd_unit);
+ return (0);
+ }
+ }
+
+ if (bd->bd_sec == 0)
+ bd->bd_sec = 63;
+ if (bd->bd_hds == 0)
+ bd->bd_hds = 255;
+
+ if (bd->bd_sectors == 0)
+ bd->bd_sectors = (uint64_t)bd->bd_cyl * bd->bd_hds * bd->bd_sec;
+
+ DEBUG("unit 0x%x geometry %d/%d/%d", bd->bd_unit, bd->bd_cyl,
+ bd->bd_hds, bd->bd_sec);
+
+ return (1);
}
/*
@@ -300,14 +409,19 @@ bd_print(int verbose)
for (i = 0; i < nbdinfo; i++) {
snprintf(line, sizeof (line),
- " disk%d: BIOS drive %c (%ju X %u):\n", i,
+ " disk%d: BIOS drive %c (%s%ju X %u):\n", i,
(bdinfo[i].bd_unit < 0x80) ? ('A' + bdinfo[i].bd_unit):
('C' + bdinfo[i].bd_unit - 0x80),
+ (bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA ?
+ "no media, " : "",
(uintmax_t)bdinfo[i].bd_sectors,
bdinfo[i].bd_sectorsize);
if ((ret = pager_output(line)) != 0)
break;
+ if ((bdinfo[i].bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ continue;
+
dev.dd.d_dev = &biosdisk;
dev.dd.d_unit = i;
dev.d_slice = -1;
@@ -350,6 +464,13 @@ bd_open(struct open_file *f, ...)
if (dev->dd.d_unit < 0 || dev->dd.d_unit >= nbdinfo)
return (EIO);
+
+ if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA) {
+ if (!bd_int13probe(&BD(dev)))
+ return (EIO);
+ if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ return (EIO);
+ }
BD(dev).bd_open++;
if (BD(dev).bd_bcache == NULL)
BD(dev).bd_bcache = bcache_allocate();
@@ -454,6 +575,9 @@ bd_realstrategy(void *devdata, int rw, daddr_t dblk, size_t size,
caddr_t bbuf;
int rc;
+ if ((BD(dev).bd_flags & BD_NO_MEDIA) == BD_NO_MEDIA)
+ return (EIO);
+
/*
* First make sure the IO size is a multiple of 512 bytes. While we do
* process partial reads below, the strategy mechanism is built
@@ -684,29 +808,33 @@ bd_io(struct disk_devdesc *dev, daddr_t dblk, int blks, caddr_t dest,
if (dowrite == BD_RD && dblk >= 0x100000000)
bd_io_workaround(dev);
for (retry = 0; retry < 3; retry++) {
- /* if retrying, reset the drive */
- if (retry > 0) {
- v86.ctl = V86_FLAGS;
- v86.addr = 0x13;
- v86.eax = 0;
- v86.edx = BD(dev).bd_unit;
- v86int();
- }
-
- if (BD(dev).bd_flags & BD_MODEEDD1)
+ if (BD(dev).bd_flags & BD_MODEEDD)
result = bd_edd_io(dev, dblk, blks, dest, dowrite);
else
result = bd_chs_io(dev, dblk, blks, dest, dowrite);
- if (result == 0)
+ if (result == 0) {
+ if (BD(dev).bd_flags & BD_NO_MEDIA)
+ BD(dev).bd_flags &= ~BD_NO_MEDIA;
+ break;
+ }
+
+ bd_reset_disk(BD(dev).bd_unit);
+
+ /*
+ * Error codes:
+ * 20h controller failure
+ * 31h no media in drive (IBM/MS INT 13 extensions)
+ * 80h no media in drive, VMWare (Fusion)
+ * There is no reason to repeat the IO with errors above.
+ */
+ if (result == 0x20 || result == 0x31 || result == 0x80) {
+ BD(dev).bd_flags |= BD_NO_MEDIA;
break;
+ }
}
- /*
- * 0x20 - Controller failure. This is common error when the
- * media is not present.
- */
- if (result != 0 && result != 0x20) {
+ if (result != 0 && (BD(dev).bd_flags & BD_NO_MEDIA) == 0) {
if (dowrite == BD_WR) {
printf("%s%d: Write %d sector(s) from %p (0x%x) "
"to %lld: 0x%x\n", dev->dd.d_dev->dv_name,
diff --git a/usr/src/boot/sys/boot/i386/loader/main.c b/usr/src/boot/sys/boot/i386/loader/main.c
index b398505a5b..443a523cfd 100644
--- a/usr/src/boot/sys/boot/i386/loader/main.c
+++ b/usr/src/boot/sys/boot/i386/loader/main.c
@@ -424,6 +424,8 @@ i386_zfs_probe(void)
for (unit = 0; unit < MAXBDDEV; unit++) {
if (bd_unit2bios(unit) == -1)
break;
+ if (bd_unit2bios(unit) < 0x80)
+ continue;
sprintf(devname, "disk%d:", unit);
zfs_probe_dev(devname, NULL);
}
diff --git a/usr/src/uts/Makefile.uts b/usr/src/uts/Makefile.uts
index 65bcf5b18b..704992618b 100644
--- a/usr/src/uts/Makefile.uts
+++ b/usr/src/uts/Makefile.uts
@@ -237,6 +237,7 @@ CFLAGS_uts += $(XAOPT)
CFLAGS_uts += $(CTF_FLAGS_$(CLASS))
CFLAGS_uts += $(CERRWARN)
CFLAGS_uts += $(CCNOAUTOINLINE)
+CFLAGS_uts += $(CCNOREORDER)
CFLAGS_uts += $(CGLOBALSTATIC)
CFLAGS_uts += $(EXTRA_CFLAGS)
CFLAGS_uts += $(CSOURCEDEBUGFLAGS)
diff --git a/usr/src/uts/intel/asm/cpu.h b/usr/src/uts/intel/asm/cpu.h
index b8b6d9f5bf..a96d8ab6b6 100644
--- a/usr/src/uts/intel/asm/cpu.h
+++ b/usr/src/uts/intel/asm/cpu.h
@@ -63,7 +63,7 @@ prefetch_read_many(void *addr)
}
extern __GNU_INLINE void
-refetch_read_once(void *addr)
+prefetch_read_once(void *addr)
{
#if defined(__amd64)
__asm__(