diff options
author | John Sonnenschein <johns@joyent.com> | 2012-05-17 18:26:57 +0000 |
---|---|---|
committer | John Sonnenschein <johns@joyent.com> | 2012-05-17 18:26:57 +0000 |
commit | 04b244dd661c24b510ac22936decfc0972d202d3 (patch) | |
tree | 3ebfef98afc303fddf3415d6fba64e8682f495e8 /usr/src/uts | |
parent | eac250589e41f1b705e1b7427b02b3379aac9f9e (diff) | |
parent | a69187741b83640a90dd8586195456dd50c016a8 (diff) | |
download | illumos-joyent-20120517.tar.gz |
Merge git.joyent.com:illumos-joyent20120517
Diffstat (limited to 'usr/src/uts')
46 files changed, 954 insertions, 795 deletions
diff --git a/usr/src/uts/common/dtrace/dtrace.c b/usr/src/uts/common/dtrace/dtrace.c index 290494147f..a5dd75f944 100644 --- a/usr/src/uts/common/dtrace/dtrace.c +++ b/usr/src/uts/common/dtrace/dtrace.c @@ -6120,6 +6120,23 @@ dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1, continue; } + /* + * Clear the string space, since there's no + * helper to do it for us. + */ + if (DTRACE_USTACK_STRSIZE(rec->dtrd_arg) != 0) { + int depth = DTRACE_USTACK_NFRAMES( + rec->dtrd_arg); + size_t strsize = DTRACE_USTACK_STRSIZE( + rec->dtrd_arg); + uint64_t *buf = (uint64_t *)(tomax + + valoffs); + void *strspace = &buf[depth + 1]; + + dtrace_bzero(strspace, + MIN(depth, strsize)); + } + DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT); dtrace_getupcstack((uint64_t *) (tomax + valoffs), diff --git a/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c b/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c index 45b7d4db87..5cff040236 100644 --- a/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c +++ b/usr/src/uts/common/fs/hyprlofs/hyprlofs_vnops.c @@ -1275,7 +1275,9 @@ static int hyprlofs_seek(vnode_t *vp, offset_t ooff, offset_t *noffp, caller_context_t *ct) { - ASSERT(VTOHLN(vp)->hln_looped == 1); + if (VTOHLN(vp)->hln_looped == 0) + return ((*noffp < 0 || *noffp > MAXOFFSET_T) ? EINVAL : 0); + return (VOP_SEEK(REALVP(vp), ooff, noffp, ct)); } diff --git a/usr/src/uts/common/fs/nfs/nfs4_subr.c b/usr/src/uts/common/fs/nfs/nfs4_subr.c index edc1602e13..c14117c009 100644 --- a/usr/src/uts/common/fs/nfs/nfs4_subr.c +++ b/usr/src/uts/common/fs/nfs/nfs4_subr.c @@ -2110,8 +2110,10 @@ recov_retry: goto out; } } - va.va_type = VNON; - pva.va_type = VNON; + + pgar.n4g_va.va_type = VNON; + gar.n4g_va.va_type = VNON; + remap_lookup(np, rootvp, RML_ORDINARY, cr, &newfh, &gar, &newpfh, &pgar, &e); if (nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp)) { @@ -2137,10 +2139,8 @@ recov_retry: goto out; } - if (!e.error) { - va = gar.n4g_va; - pva = pgar.n4g_va; - } + va = gar.n4g_va; + pva = pgar.n4g_va; if ((e.error != 0) || (va.va_type != VDIR)) { @@ -2173,6 +2173,13 @@ recov_retry: if (pnp != NULL) { remap_lookup(pnp, rootvp, RML_ORDINARY, cr, &newpfh, &pgar, NULL, NULL, &e); + /* + * This remap_lookup call modifies pgar. The following + * line prevents trouble when checking the va_type of + * pva later in this code. + */ + pva = pgar.n4g_va; + if (nfs4_needs_recovery(&e, FALSE, mi->mi_vfsp)) { if (need_start_op) { diff --git a/usr/src/uts/common/fs/ufs/lufs.c b/usr/src/uts/common/fs/ufs/lufs.c index 301bb09c01..43cc78219c 100644 --- a/usr/src/uts/common/fs/ufs/lufs.c +++ b/usr/src/uts/common/fs/ufs/lufs.c @@ -1492,7 +1492,7 @@ lufs_init(void) _init_top(); - if (&bio_lufs_strategy != NULL) + if (bio_lufs_strategy == NULL) bio_lufs_strategy = (void (*) (void *, buf_t *)) lufs_strategy; /* diff --git a/usr/src/uts/common/fs/zfs/spa.c b/usr/src/uts/common/fs/zfs/spa.c index ed0d0cb36f..a4c61fc947 100644 --- a/usr/src/uts/common/fs/zfs/spa.c +++ b/usr/src/uts/common/fs/zfs/spa.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ /* @@ -167,15 +167,17 @@ spa_prop_add_list(nvlist_t *nvl, zpool_prop_t prop, char *strval, static void spa_prop_get_config(spa_t *spa, nvlist_t **nvp) { + vdev_t *rvd = spa->spa_root_vdev; uint64_t size; uint64_t alloc; + uint64_t space; uint64_t cap, version; zprop_source_t src = ZPROP_SRC_NONE; spa_config_dirent_t *dp; ASSERT(MUTEX_HELD(&spa->spa_props_lock)); - if (spa->spa_root_vdev != NULL) { + if (rvd != NULL) { alloc = metaslab_class_get_alloc(spa_normal_class(spa)); size = metaslab_class_get_space(spa_normal_class(spa)); spa_prop_add_list(*nvp, ZPOOL_PROP_NAME, spa_name(spa), 0, src); @@ -183,6 +185,15 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) spa_prop_add_list(*nvp, ZPOOL_PROP_ALLOCATED, NULL, alloc, src); spa_prop_add_list(*nvp, ZPOOL_PROP_FREE, NULL, size - alloc, src); + + space = 0; + for (int c = 0; c < rvd->vdev_children; c++) { + vdev_t *tvd = rvd->vdev_child[c]; + space += tvd->vdev_max_asize - tvd->vdev_asize; + } + spa_prop_add_list(*nvp, ZPOOL_PROP_EXPANDSZ, NULL, space, + src); + spa_prop_add_list(*nvp, ZPOOL_PROP_READONLY, NULL, (spa_mode(spa) == FREAD), src); @@ -193,7 +204,7 @@ spa_prop_get_config(spa_t *spa, nvlist_t **nvp) ddt_get_pool_dedup_ratio(spa), src); spa_prop_add_list(*nvp, ZPOOL_PROP_HEALTH, NULL, - spa->spa_root_vdev->vdev_state, src); + rvd->vdev_state, src); version = spa_version(spa); if (version == zpool_prop_default_numeric(ZPOOL_PROP_VERSION)) diff --git a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h index c297ae165c..3a2d7a04d8 100644 --- a/usr/src/uts/common/fs/zfs/sys/vdev_impl.h +++ b/usr/src/uts/common/fs/zfs/sys/vdev_impl.h @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #ifndef _SYS_VDEV_IMPL_H @@ -55,7 +56,8 @@ typedef struct vdev_cache_entry vdev_cache_entry_t; /* * Virtual device operations */ -typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *ashift); +typedef int vdev_open_func_t(vdev_t *vd, uint64_t *size, uint64_t *max_size, + uint64_t *ashift); typedef void vdev_close_func_t(vdev_t *vd); typedef uint64_t vdev_asize_func_t(vdev_t *vd, uint64_t psize); typedef int vdev_io_start_func_t(zio_t *zio); @@ -119,6 +121,7 @@ struct vdev { uint64_t vdev_orig_guid; /* orig. guid prior to remove */ uint64_t vdev_asize; /* allocatable device capacity */ uint64_t vdev_min_asize; /* min acceptable asize */ + uint64_t vdev_max_asize; /* max acceptable asize */ uint64_t vdev_ashift; /* block alignment shift */ uint64_t vdev_state; /* see VDEV_STATE_* #defines */ uint64_t vdev_prevstate; /* used when reopening a vdev */ diff --git a/usr/src/uts/common/fs/zfs/vdev.c b/usr/src/uts/common/fs/zfs/vdev.c index 1af113e2e0..6606b1f486 100644 --- a/usr/src/uts/common/fs/zfs/vdev.c +++ b/usr/src/uts/common/fs/zfs/vdev.c @@ -22,7 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -108,7 +108,7 @@ vdev_get_min_asize(vdev_t *vd) vdev_t *pvd = vd->vdev_parent; /* - * The our parent is NULL (inactive spare or cache) or is the root, + * If our parent is NULL (inactive spare or cache) or is the root, * just return our own asize. */ if (pvd == NULL) @@ -737,6 +737,7 @@ vdev_add_parent(vdev_t *cvd, vdev_ops_t *ops) mvd->vdev_asize = cvd->vdev_asize; mvd->vdev_min_asize = cvd->vdev_min_asize; + mvd->vdev_max_asize = cvd->vdev_max_asize; mvd->vdev_ashift = cvd->vdev_ashift; mvd->vdev_state = cvd->vdev_state; mvd->vdev_crtxg = cvd->vdev_crtxg; @@ -1108,7 +1109,8 @@ vdev_open(vdev_t *vd) spa_t *spa = vd->vdev_spa; int error; uint64_t osize = 0; - uint64_t asize, psize; + uint64_t max_osize = 0; + uint64_t asize, max_asize, psize; uint64_t ashift = 0; ASSERT(vd->vdev_open_thread == curthread || @@ -1139,7 +1141,7 @@ vdev_open(vdev_t *vd) return (ENXIO); } - error = vd->vdev_ops->vdev_op_open(vd, &osize, &ashift); + error = vd->vdev_ops->vdev_op_open(vd, &osize, &max_osize, &ashift); /* * Reset the vdev_reopening flag so that we actually close @@ -1197,6 +1199,7 @@ vdev_open(vdev_t *vd) } osize = P2ALIGN(osize, (uint64_t)sizeof (vdev_label_t)); + max_osize = P2ALIGN(max_osize, (uint64_t)sizeof (vdev_label_t)); if (vd->vdev_children == 0) { if (osize < SPA_MINDEVSIZE) { @@ -1206,6 +1209,8 @@ vdev_open(vdev_t *vd) } psize = osize; asize = osize - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE); + max_asize = max_osize - (VDEV_LABEL_START_SIZE + + VDEV_LABEL_END_SIZE); } else { if (vd->vdev_parent != NULL && osize < SPA_MINDEVSIZE - (VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE)) { @@ -1215,6 +1220,7 @@ vdev_open(vdev_t *vd) } psize = 0; asize = osize; + max_asize = max_osize; } vd->vdev_psize = psize; @@ -1234,16 +1240,22 @@ vdev_open(vdev_t *vd) * For testing purposes, a higher ashift can be requested. */ vd->vdev_asize = asize; + vd->vdev_max_asize = max_asize; vd->vdev_ashift = MAX(ashift, vd->vdev_ashift); } else { /* - * Make sure the alignment requirement hasn't increased. + * Detect if the alignment requirement has increased. + * We don't want to make the pool unavailable, just + * issue a warning instead. */ - if (ashift > vd->vdev_top->vdev_ashift) { - vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN, - VDEV_AUX_BAD_LABEL); - return (EINVAL); + if (ashift > vd->vdev_top->vdev_ashift && + vd->vdev_ops->vdev_op_leaf) { + cmn_err(CE_WARN, + "Disk, '%s', has a block alignment that is " + "larger than the pool's alignment\n", + vd->vdev_path); } + vd->vdev_max_asize = max_asize; } /* @@ -2467,6 +2479,7 @@ vdev_get_stats(vdev_t *vd, vdev_stat_t *vs) vs->vs_rsize = vdev_get_min_asize(vd); if (vd->vdev_ops->vdev_op_leaf) vs->vs_rsize += VDEV_LABEL_START_SIZE + VDEV_LABEL_END_SIZE; + vs->vs_esize = vd->vdev_max_asize - vd->vdev_asize; mutex_exit(&vd->vdev_stat_lock); /* diff --git a/usr/src/uts/common/fs/zfs/vdev_disk.c b/usr/src/uts/common/fs/zfs/vdev_disk.c index f78580d0f1..49e425929f 100644 --- a/usr/src/uts/common/fs/zfs/vdev_disk.c +++ b/usr/src/uts/common/fs/zfs/vdev_disk.c @@ -21,6 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -32,6 +33,7 @@ #include <sys/fs/zfs.h> #include <sys/zio.h> #include <sys/sunldi.h> +#include <sys/efi_partition.h> #include <sys/fm/fs/zfs.h> /* @@ -104,8 +106,39 @@ vdev_disk_rele(vdev_t *vd) } } +static uint64_t +vdev_disk_get_space(vdev_t *vd, uint64_t capacity, uint_t blksz) +{ + ASSERT(vd->vdev_wholedisk); + + vdev_disk_t *dvd = vd->vdev_tsd; + dk_efi_t dk_ioc; + efi_gpt_t *efi; + uint64_t avail_space = 0; + int efisize = EFI_LABEL_SIZE * 2; + + dk_ioc.dki_data = kmem_alloc(efisize, KM_SLEEP); + dk_ioc.dki_lba = 1; + dk_ioc.dki_length = efisize; + dk_ioc.dki_data_64 = (uint64_t)(uintptr_t)dk_ioc.dki_data; + efi = dk_ioc.dki_data; + + if (ldi_ioctl(dvd->vd_lh, DKIOCGETEFI, (intptr_t)&dk_ioc, + FKIOCTL, kcred, NULL) == 0) { + uint64_t efi_altern_lba = LE_64(efi->efi_gpt_AlternateLBA); + + zfs_dbgmsg("vdev %s, capacity %llu, altern lba %llu", + vd->vdev_path, capacity, efi_altern_lba); + if (capacity > efi_altern_lba) + avail_space = (capacity - efi_altern_lba) * blksz; + } + kmem_free(dk_ioc.dki_data, efisize); + return (avail_space); +} + static int -vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_disk_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { spa_t *spa = vd->vdev_spa; vdev_disk_t *dvd; @@ -276,16 +309,6 @@ skip_open: } /* - * If we own the whole disk, try to enable disk write caching. - * We ignore errors because it's OK if we can't do it. - */ - if (vd->vdev_wholedisk == 1) { - int wce = 1; - (void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce, - FKIOCTL, kcred, NULL); - } - - /* * Determine the device's minimum transfer size. * If the ioctl isn't supported, assume DEV_BSIZE. */ @@ -295,6 +318,25 @@ skip_open: *ashift = highbit(MAX(dkmext.dki_pbsize, SPA_MINBLOCKSIZE)) - 1; + if (vd->vdev_wholedisk == 1) { + uint64_t capacity = dkmext.dki_capacity - 1; + uint64_t blksz = dkmext.dki_lbsize; + int wce = 1; + + /* + * If we own the whole disk, try to enable disk write caching. + * We ignore errors because it's OK if we can't do it. + */ + (void) ldi_ioctl(dvd->vd_lh, DKIOCSETWCE, (intptr_t)&wce, + FKIOCTL, kcred, NULL); + + *max_psize = *psize + vdev_disk_get_space(vd, capacity, blksz); + zfs_dbgmsg("capacity change: vdev %s, psize %llu, " + "max_psize %llu", vd->vdev_path, *psize, *max_psize); + } else { + *max_psize = *psize; + } + /* * Clear the nowritecache bit, so that on a vdev_reopen() we will * try again. diff --git a/usr/src/uts/common/fs/zfs/vdev_file.c b/usr/src/uts/common/fs/zfs/vdev_file.c index 8c22aa5316..043fa51294 100644 --- a/usr/src/uts/common/fs/zfs/vdev_file.c +++ b/usr/src/uts/common/fs/zfs/vdev_file.c @@ -20,6 +20,7 @@ */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -47,7 +48,8 @@ vdev_file_rele(vdev_t *vd) } static int -vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { vdev_file_t *vf; vnode_t *vp; @@ -112,7 +114,7 @@ skip_open: return (error); } - *psize = vattr.va_size; + *max_psize = *psize = vattr.va_size; *ashift = SPA_MINBLOCKSHIFT; return (0); diff --git a/usr/src/uts/common/fs/zfs/vdev_mirror.c b/usr/src/uts/common/fs/zfs/vdev_mirror.c index 698c0275d3..a28ca3e396 100644 --- a/usr/src/uts/common/fs/zfs/vdev_mirror.c +++ b/usr/src/uts/common/fs/zfs/vdev_mirror.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + #include <sys/zfs_context.h> #include <sys/spa.h> #include <sys/vdev_impl.h> @@ -127,7 +131,8 @@ vdev_mirror_map_alloc(zio_t *zio) } static int -vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { int numerrors = 0; int lasterror = 0; @@ -149,6 +154,7 @@ vdev_mirror_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1; + *max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1; *ashift = MAX(*ashift, cvd->vdev_ashift); } diff --git a/usr/src/uts/common/fs/zfs/vdev_missing.c b/usr/src/uts/common/fs/zfs/vdev_missing.c index 6a5588d592..3bd8c90e04 100644 --- a/usr/src/uts/common/fs/zfs/vdev_missing.c +++ b/usr/src/uts/common/fs/zfs/vdev_missing.c @@ -24,6 +24,10 @@ */ /* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + +/* * The 'missing' vdev is a special vdev type used only during import. It * signifies a placeholder in the root vdev for some vdev that we know is * missing. We pass it down to the kernel to allow the rest of the @@ -40,7 +44,8 @@ /* ARGSUSED */ static int -vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) +vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize, + uint64_t *ashift) { /* * Really this should just fail. But then the root vdev will be in the @@ -49,6 +54,7 @@ vdev_missing_open(vdev_t *vd, uint64_t *psize, uint64_t *ashift) * will fail the GUID sum check before ever trying to open the pool. */ *psize = 0; + *max_psize = 0; *ashift = 0; return (0); } diff --git a/usr/src/uts/common/fs/zfs/vdev_raidz.c b/usr/src/uts/common/fs/zfs/vdev_raidz.c index 6094e01876..3ac3d3b167 100644 --- a/usr/src/uts/common/fs/zfs/vdev_raidz.c +++ b/usr/src/uts/common/fs/zfs/vdev_raidz.c @@ -22,6 +22,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2011 Joyent, Inc. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. */ #include <sys/zfs_context.h> @@ -1445,7 +1446,8 @@ vdev_raidz_reconstruct(raidz_map_t *rm, int *t, int nt) } static int -vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { vdev_t *cvd; uint64_t nparity = vd->vdev_nparity; @@ -1473,10 +1475,12 @@ vdev_raidz_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = MIN(*asize - 1, cvd->vdev_asize - 1) + 1; + *max_asize = MIN(*max_asize - 1, cvd->vdev_max_asize - 1) + 1; *ashift = MAX(*ashift, cvd->vdev_ashift); } *asize *= vd->vdev_children; + *max_asize *= vd->vdev_children; if (numerrors > nparity) { vd->vdev_stat.vs_aux = VDEV_AUX_NO_REPLICAS; diff --git a/usr/src/uts/common/fs/zfs/vdev_root.c b/usr/src/uts/common/fs/zfs/vdev_root.c index 879f78f3a5..1abc79d330 100644 --- a/usr/src/uts/common/fs/zfs/vdev_root.c +++ b/usr/src/uts/common/fs/zfs/vdev_root.c @@ -23,6 +23,10 @@ * Use is subject to license terms. */ +/* + * Copyright (c) 2012 by Delphix. All rights reserved. + */ + #include <sys/zfs_context.h> #include <sys/spa.h> #include <sys/vdev_impl.h> @@ -50,7 +54,8 @@ too_many_errors(vdev_t *vd, int numerrors) } static int -vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) +vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *max_asize, + uint64_t *ashift) { int lasterror = 0; int numerrors = 0; @@ -77,6 +82,7 @@ vdev_root_open(vdev_t *vd, uint64_t *asize, uint64_t *ashift) } *asize = 0; + *max_asize = 0; *ashift = 0; return (0); diff --git a/usr/src/uts/common/fs/zfs/zfs_ioctl.c b/usr/src/uts/common/fs/zfs/zfs_ioctl.c index baffc223a3..f2bf4fc98f 100644 --- a/usr/src/uts/common/fs/zfs/zfs_ioctl.c +++ b/usr/src/uts/common/fs/zfs/zfs_ioctl.c @@ -22,7 +22,7 @@ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. * Portions Copyright 2011 Martin Matuska * Copyright 2011 Nexenta Systems, Inc. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ @@ -4066,6 +4066,22 @@ zfs_ioc_clear(zfs_cmd_t *zc) return (error); } +static int +zfs_ioc_pool_reopen(zfs_cmd_t *zc) +{ + spa_t *spa; + int error; + + error = spa_open(zc->zc_name, &spa, FTAG); + if (error) + return (error); + + spa_vdev_state_enter(spa, SCL_NONE); + vdev_reopen(spa->spa_root_vdev); + (void) spa_vdev_state_exit(spa, NULL, 0); + spa_close(spa, FTAG); + return (0); +} /* * inputs: * zc_name name of filesystem @@ -4910,7 +4926,9 @@ static zfs_ioc_vec_t zfs_ioc_vec[] = { { zfs_ioc_destroy_snaps_nvl, zfs_secpolicy_destroy_recursive, DATASET_NAME, B_TRUE, POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, { zfs_ioc_pool_reguid, zfs_secpolicy_config, POOL_NAME, B_TRUE, - POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY } + POOL_CHECK_SUSPENDED | POOL_CHECK_READONLY }, + { zfs_ioc_pool_reopen, zfs_secpolicy_config, POOL_NAME, B_TRUE, + POOL_CHECK_SUSPENDED }, }; int diff --git a/usr/src/uts/common/gssapi/Makefile b/usr/src/uts/common/gssapi/Makefile index 1b691b92cb..0f02a03623 100644 --- a/usr/src/uts/common/gssapi/Makefile +++ b/usr/src/uts/common/gssapi/Makefile @@ -23,7 +23,7 @@ # Copyright (c) 1989,1997,1999 by Sun Microsystems, Inc. # All rights reserved. # -#pragma ident "%Z%%M% %I% %E% SMI" +# Copyright 2012 Milan Jurik. All rights reserved. # # uts/common/gssd/Makefile # @@ -64,7 +64,7 @@ $(GSSDDIRS): gssd_prot.h: gssd.x $(RM) $@ - $(RPCGEN) -M -h gssd.x > $@ + $(RPCGEN) -CM -h gssd.x > $@ gssd_prot.c: gssd.x $(RM) $@ diff --git a/usr/src/uts/common/io/scsi/targets/sd.c b/usr/src/uts/common/io/scsi/targets/sd.c index 4ab44d9eb3..8ec8672eb9 100644 --- a/usr/src/uts/common/io/scsi/targets/sd.c +++ b/usr/src/uts/common/io/scsi/targets/sd.c @@ -4224,6 +4224,18 @@ sd_set_properties(struct sd_lun *un, char *name, char *value) "RMW type set to %d\n", un->un_f_rmw_type); } + if (strcasecmp(name, "physical-block-size") == 0) { + if (ddi_strtol(value, &endptr, 0, &val) == 0 && + ISP2(val) && val >= un->un_tgt_blocksize && + val >= un->un_sys_blocksize) { + un->un_phy_blocksize = val; + } else { + goto value_invalid; + } + SD_INFO(SD_LOG_ATTACH_DETACH, un, "sd_set_properties: " + "physical block size set to %d\n", un->un_phy_blocksize); + } + /* * Validate the throttle values. * If any of the numbers are invalid, set everything to defaults. @@ -7624,6 +7636,13 @@ sd_unit_attach(dev_info_t *devi) un->un_f_mmc_gesn_polling = TRUE; /* + * physical sector size defaults to DEV_BSIZE currently. We can + * override this value via the driver configuration file so we must + * set it before calling sd_read_unit_properties(). + */ + un->un_phy_blocksize = DEV_BSIZE; + + /* * Retrieve the properties from the static driver table or the driver * configuration file (.conf) for this unit and update the soft state * for the device as needed for the indicated properties. @@ -7668,11 +7687,6 @@ sd_unit_attach(dev_info_t *devi) un->un_blockcount = 0; /* - * physical sector size default to DEV_BSIZE currently. - */ - un->un_phy_blocksize = DEV_BSIZE; - - /* * Set up the per-instance info needed to determine the correct * CDBs and other info for issuing commands to the target. */ @@ -23482,10 +23496,17 @@ sd_get_media_info_com(dev_t dev, uint_t *dki_media_type, uint_t *dki_lbsize, * Now read the capacity so we can provide the lbasize, * pbsize and capacity. */ - if (dki_pbsize && un->un_f_descr_format_supported) + if (dki_pbsize && un->un_f_descr_format_supported) { rval = sd_send_scsi_READ_CAPACITY_16(ssc, &capacity, &lbasize, &pbsize, SD_PATH_DIRECT); + /* + * Override the physical blocksize if the instance already + * has a larger value. + */ + pbsize = MAX(pbsize, un->un_phy_blocksize); + } + if (dki_pbsize == NULL || rval != 0 || !un->un_f_descr_format_supported) { rval = sd_send_scsi_READ_CAPACITY(ssc, &capacity, &lbasize, @@ -31747,7 +31768,11 @@ sd_check_emulation_mode(sd_ssc_t *ssc) } else { if (!ISP2(pbsize % DEV_BSIZE) || pbsize == 0) { un->un_phy_blocksize = DEV_BSIZE; - } else { + } else if (pbsize > un->un_phy_blocksize) { + /* + * Don't reset the physical blocksize + * unless we've detected a larger value. + */ un->un_phy_blocksize = pbsize; } } diff --git a/usr/src/uts/common/sys/fs/zfs.h b/usr/src/uts/common/sys/fs/zfs.h index baa201d7a5..a523201954 100644 --- a/usr/src/uts/common/sys/fs/zfs.h +++ b/usr/src/uts/common/sys/fs/zfs.h @@ -21,7 +21,7 @@ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2011 by Delphix. All rights reserved. + * Copyright (c) 2012 by Delphix. All rights reserved. * Copyright 2011 Nexenta Systems, Inc. All rights reserved. */ @@ -167,6 +167,7 @@ typedef enum { ZPOOL_PROP_ALLOCATED, ZPOOL_PROP_READONLY, ZPOOL_PROP_COMMENT, + ZPOOL_PROP_EXPANDSZ, ZPOOL_NUM_PROPS } zpool_prop_t; @@ -672,6 +673,7 @@ typedef struct vdev_stat { uint64_t vs_space; /* total capacity */ uint64_t vs_dspace; /* deflated capacity */ uint64_t vs_rsize; /* replaceable dev size */ + uint64_t vs_esize; /* expandable dev size */ uint64_t vs_ops[ZIO_TYPES]; /* operation count */ uint64_t vs_bytes[ZIO_TYPES]; /* bytes read/written */ uint64_t vs_read_errors; /* read errors */ @@ -788,7 +790,8 @@ typedef enum zfs_ioc { ZFS_IOC_SPACE_WRITTEN, ZFS_IOC_SPACE_SNAPS, ZFS_IOC_DESTROY_SNAPS_NVL, - ZFS_IOC_POOL_REGUID + ZFS_IOC_POOL_REGUID, + ZFS_IOC_POOL_REOPEN } zfs_ioc_t; /* diff --git a/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_impl.h b/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_impl.h index 2fb6454396..e7751760bd 100644 --- a/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_impl.h +++ b/usr/src/uts/common/sys/ib/mgt/ibcm/ibcm_impl.h @@ -2170,15 +2170,15 @@ void ibcm_dump_noderec(sa_node_record_t *); void ibcm_query_classport_info(ibt_channel_hdl_t channel); -#define IBCM_DUMP_RAW_MSG ibcm_dump_raw_message -#define IBCM_DUMP_SERVICE_REC ibcm_dump_srvrec -#define IBCM_DUMP_PATH_REC ibcm_dump_pathrec -#define IBCM_DUMP_NODE_REC ibcm_dump_noderec +#define IBCM_DUMP_RAW_MSG(x) ibcm_dump_raw_message(x) +#define IBCM_DUMP_SERVICE_REC(x) ibcm_dump_srvrec(x) +#define IBCM_DUMP_PATH_REC(x) ibcm_dump_pathrec(x) +#define IBCM_DUMP_NODE_REC(x) ibcm_dump_noderec(x) #else -#define IBCM_DUMP_RAW_MSG 0 && -#define IBCM_DUMP_SERVICE_REC 0 && -#define IBCM_DUMP_PATH_REC 0 && -#define IBCM_DUMP_NODE_REC 0 && +#define IBCM_DUMP_RAW_MSG(x) +#define IBCM_DUMP_SERVICE_REC(x) +#define IBCM_DUMP_PATH_REC(x) +#define IBCM_DUMP_NODE_REC(x) #endif ibt_status_t ibcm_ibmf_analyze_error(int ibmf_status); diff --git a/usr/src/uts/common/sys/ucode.h b/usr/src/uts/common/sys/ucode.h index e4f01bfeb0..d96c354c45 100644 --- a/usr/src/uts/common/sys/ucode.h +++ b/usr/src/uts/common/sys/ucode.h @@ -116,6 +116,7 @@ typedef struct ucode_file_amd { uint8_t uf_resv[896]; uint8_t uf_code_present; uint8_t uf_code[191]; + uint8_t uf_encr[2048]; #else uint8_t *ucodep; uint32_t usize; diff --git a/usr/src/uts/i86pc/Makefile.files b/usr/src/uts/i86pc/Makefile.files index a287bfd209..dfe6ef4d8d 100644 --- a/usr/src/uts/i86pc/Makefile.files +++ b/usr/src/uts/i86pc/Makefile.files @@ -114,6 +114,7 @@ CORE_OBJS += \ timestamp.o \ todpc_subr.o \ trap.o \ + turbo.o \ vm_machdep.o \ xpv_platform.o \ x_call.o diff --git a/usr/src/uts/i86pc/Makefile.workarounds b/usr/src/uts/i86pc/Makefile.workarounds index aed875925c..2300e74393 100644 --- a/usr/src/uts/i86pc/Makefile.workarounds +++ b/usr/src/uts/i86pc/Makefile.workarounds @@ -21,8 +21,6 @@ # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -# ident "%Z%%M% %I% %E% SMI" -# # This makefile contains workaround defines to be shared # by Makefile.i86pc and the genunix Makefile. # @@ -117,3 +115,8 @@ WORKAROUND_DEFS += -DOPTERON_ERRATUM_172 # Accessed or Dirty Bit. # WORKAROUND_DEFS += -DOPTERON_ERRATUM_298 + +# +# Processor May Incorrectly Update Stack Pointer +# +WORKAROUND_DEFS += -DOPTERON_ERRATUM_721 diff --git a/usr/src/uts/i86pc/boot/boot_console.c b/usr/src/uts/i86pc/boot/boot_console.c index f07735bb5e..cadc735588 100644 --- a/usr/src/uts/i86pc/boot/boot_console.c +++ b/usr/src/uts/i86pc/boot/boot_console.c @@ -19,6 +19,8 @@ * CDDL HEADER END */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -56,10 +58,22 @@ extern int bcons_ischar_xen(void); #endif /* __xpv */ static int cons_color = CONS_COLOR; -int console = CONS_SCREEN_TEXT; +static int console = CONS_SCREEN_TEXT; +static int tty_num = 0; +static int tty_addr[] = {0x3f8, 0x2f8, 0x3e8, 0x2e8}; #if defined(__xpv) static int console_hypervisor_redirect = B_FALSE; -int console_hypervisor_device = CONS_INVALID; +static int console_hypervisor_device = CONS_INVALID; +static int console_hypervisor_tty_num = 0; + +/* Obtain the hypervisor console type */ +int +console_hypervisor_dev_type(int *tnum) +{ + if (tnum != NULL) + *tnum = console_hypervisor_tty_num; + return (console_hypervisor_device); +} #endif /* __xpv */ static int serial_ischar(void); @@ -140,14 +154,7 @@ static int port; static void serial_init(void) { - switch (console) { - case CONS_TTYA: - port = 0x3f8; - break; - case CONS_TTYB: - port = 0x2f8; - break; - } + port = tty_addr[tty_num]; outb(port + ISR, 0x20); if (inb(port + ISR) & 0x20) { @@ -377,7 +384,7 @@ serial_adjust_prop(void) uchar_t mcr = DTR | RTS; (void) strcpy(propname, "ttyX-mode"); - propname[3] = 'a' + console - CONS_TTYA; + propname[3] = 'a' + tty_num; propval = get_mode_value(propname); if (propval == NULL) propval = "9600,8,n,1,-"; @@ -472,7 +479,7 @@ serial_adjust_prop(void) outb(port + LCR, lcr); (void) strcpy(propname, "ttyX-rts-dtr-off"); - propname[3] = 'a' + console - CONS_TTYA; + propname[3] = 'a' + tty_num; propval = get_mode_value(propname); if (propval == NULL) propval = "false"; @@ -482,6 +489,15 @@ serial_adjust_prop(void) outb(port + MCR, mcr | OUT2); } +/* Obtain the console type */ +int +boot_console_type(int *tnum) +{ + if (tnum != NULL) + *tnum = tty_num; + return (console); +} + /* * A structure to map console names to values. */ @@ -491,8 +507,10 @@ typedef struct { } console_value_t; console_value_t console_devices[] = { - { "ttya", CONS_TTYA }, - { "ttyb", CONS_TTYB }, + { "ttya", CONS_TTY }, /* 0 */ + { "ttyb", CONS_TTY }, /* 1 */ + { "ttyc", CONS_TTY }, /* 2 */ + { "ttyd", CONS_TTY }, /* 3 */ { "text", CONS_SCREEN_TEXT }, { "graphics", CONS_SCREEN_GRAPHICS }, #if defined(__xpv) @@ -501,7 +519,7 @@ console_value_t console_devices[] = { #if !defined(_BOOT) { "usb-serial", CONS_USBSER }, #endif - { "", CONS_INVALID } + { NULL, CONS_INVALID } }; void @@ -537,15 +555,19 @@ bcons_init(char *bootstr) * a comma or white space. */ if (cons_str != NULL) { + int n; + cons_len = strlen(cons_str); - consolep = console_devices; - for (; consolep->name[0] != '\0'; consolep++) { + for (n = 0; console_devices[n].name != NULL; n++) { + consolep = &console_devices[n]; len = strlen(consolep->name); if ((len <= cons_len) && ((cons_str[len] == '\0') || (cons_str[len] == ',') || (cons_str[len] == '\'') || (cons_str[len] == '"') || ISSPACE(cons_str[len])) && (strncmp(cons_str, consolep->name, len) == 0)) { console = consolep->value; + if (console == CONS_TTY) + tty_num = n; break; } } @@ -577,10 +599,9 @@ bcons_init(char *bootstr) if (DOMAIN_IS_INITDOMAIN(xen_info)) { switch (HYPERVISOR_console_io(CONSOLEIO_get_device, 0, NULL)) { case XEN_CONSOLE_COM1: - console_hypervisor_device = CONS_TTYA; - break; case XEN_CONSOLE_COM2: - console_hypervisor_device = CONS_TTYB; + console_hypervisor_device = CONS_TTY; + console_hypervisor_tty_num = tty_num; break; case XEN_CONSOLE_VGA: /* @@ -610,8 +631,7 @@ bcons_init(char *bootstr) #endif /* __xpv */ switch (console) { - case CONS_TTYA: - case CONS_TTYB: + case CONS_TTY: serial_init(); break; @@ -652,6 +672,7 @@ void bcons_init2(char *inputdev, char *outputdev, char *consoledev) { int cons = CONS_INVALID; + int ttyn; char *devnames[] = { consoledev, outputdev, inputdev, NULL }; console_value_t *consolep; int i; @@ -667,17 +688,20 @@ bcons_init2(char *inputdev, char *outputdev, char *consoledev) * but the ttyX-mode was not, we only need to * check bootenv.rc for that setting. */ - if ((!console_mode_set) && - (console == CONS_TTYA || console == CONS_TTYB)) + if ((!console_mode_set) && (console == CONS_TTY)) serial_init(); return; } for (i = 0; devnames[i] != NULL; i++) { - consolep = console_devices; - for (; consolep->name[0] != '\0'; consolep++) { + int n; + + for (n = 0; console_devices[n].name != NULL; n++) { + consolep = &console_devices[n]; if (strcmp(devnames[i], consolep->name) == 0) { cons = consolep->value; + if (cons == CONS_TTY) + ttyn = n; } } if (cons != CONS_INVALID) @@ -704,7 +728,8 @@ bcons_init2(char *inputdev, char *outputdev, char *consoledev) } console = cons; - if (cons == CONS_TTYA || cons == CONS_TTYB) { + if (cons == CONS_TTY) { + tty_num = ttyn; serial_init(); return; } @@ -741,8 +766,10 @@ bcons_device_change(int new_console) console = new_console; - if (new_console == CONS_TTYA || new_console == CONS_TTYB) + if (new_console == CONS_TTY) { + tty_num = console_hypervisor_tty_num; serial_init(); + } } #endif /* __xpv */ @@ -799,8 +826,7 @@ static void _doputchar(int c) { switch (console) { - case CONS_TTYA: - case CONS_TTYB: + case CONS_TTY: serial_putchar(c); return; case CONS_SCREEN_TEXT: @@ -862,8 +888,7 @@ bcons_getchar(void) #endif /* __xpv */ switch (console) { - case CONS_TTYA: - case CONS_TTYB: + case CONS_TTY: return (serial_getchar()); default: return (kb_getchar()); @@ -883,8 +908,7 @@ bcons_ischar(void) #endif /* __xpv */ switch (console) { - case CONS_TTYA: - case CONS_TTYB: + case CONS_TTY: return (serial_ischar()); default: return (kb_ischar()); diff --git a/usr/src/uts/i86pc/dboot/dboot_printf.c b/usr/src/uts/i86pc/dboot/dboot_printf.c index ceb46659dd..d834364839 100644 --- a/usr/src/uts/i86pc/dboot/dboot_printf.c +++ b/usr/src/uts/i86pc/dboot/dboot_printf.c @@ -20,12 +20,12 @@ */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright 2007 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ -#pragma ident "%Z%%M% %I% %E% SMI" - #include <sys/types.h> #include <sys/param.h> #include <sys/machparam.h> @@ -59,7 +59,7 @@ dboot_panic(char *fmt, ...) va_start(args, fmt); do_dboot_printf(fmt, args); - if (console == CONS_SCREEN_TEXT) { + if (boot_console_type(NULL) == CONS_SCREEN_TEXT) { dboot_printf("Press any key to reboot\n"); (void) bcons_getchar(); } diff --git a/usr/src/uts/i86pc/io/consplat.c b/usr/src/uts/i86pc/io/consplat.c index 6fb1df8a67..82e53086a7 100644 --- a/usr/src/uts/i86pc/io/consplat.c +++ b/usr/src/uts/i86pc/io/consplat.c @@ -20,6 +20,8 @@ */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -62,29 +64,39 @@ plat_support_serial_kbd_and_ms() { #define A_CNT(arr) (sizeof (arr) / sizeof (arr[0])) -#define CONS_INVALID -1 -#define CONS_SCREEN 0 -#define CONS_TTYA 1 -#define CONS_TTYB 2 -#define CONS_USBSER 3 -#define CONS_HYPERVISOR 4 +#ifndef CONS_INVALID +#define CONS_INVALID -1 +#define CONS_SCREEN_TEXT 0 +#define CONS_TTY 1 +#define CONS_XXX 2 /* Unused */ +#define CONS_USBSER 3 +#define CONS_HYPERVISOR 4 +#define CONS_SCREEN_GRAPHICS 5 +#endif /* CONS_INVALID */ char *plat_fbpath(void); static int -console_type() +console_type(int *tnum) { static int boot_console = CONS_INVALID; + static int tty_num = 0; char *cons; dev_info_t *root; - if (boot_console != CONS_INVALID) + /* If we already have determined the console, just return it. */ + if (boot_console != CONS_INVALID) { + if (tnum != NULL) + *tnum = tty_num; return (boot_console); + } #if defined(__xpv) if (!DOMAIN_IS_INITDOMAIN(xen_info) || bcons_hypervisor_redirect()) { boot_console = CONS_HYPERVISOR; + if (tnum != NULL) + *tnum = tty_num; return (boot_console); } #endif /* __xpv */ @@ -94,7 +106,7 @@ console_type() * fallback on the old "input-device" property. * If "input-device" is not defined either, also check "output-device". */ - boot_console = CONS_SCREEN; /* default is screen/kb */ + boot_console = CONS_SCREEN_TEXT; /* default is screen/kb */ root = ddi_root_node(); if ((ddi_prop_lookup_string(DDI_DEV_T_ANY, root, DDI_PROP_DONTPASS, "console", &cons) == DDI_SUCCESS) || @@ -102,10 +114,10 @@ console_type() DDI_PROP_DONTPASS, "input-device", &cons) == DDI_SUCCESS) || (ddi_prop_lookup_string(DDI_DEV_T_ANY, root, DDI_PROP_DONTPASS, "output-device", &cons) == DDI_SUCCESS)) { - if (strcmp(cons, "ttya") == 0) { - boot_console = CONS_TTYA; - } else if (strcmp(cons, "ttyb") == 0) { - boot_console = CONS_TTYB; + if (strlen(cons) == 4 && strncmp(cons, "tty", 3) == 0 && + cons[3] >= 'a' && cons[3] <= 'd') { + boot_console = CONS_TTY; + tty_num = cons[3] - 'a'; } else if (strcmp(cons, "usb-serial") == 0) { (void) i_ddi_attach_hw_nodes("ehci"); (void) i_ddi_attach_hw_nodes("uhci"); @@ -129,22 +141,26 @@ console_type() * could be found, fallback to "ttya" since it's likely to exist * and it matches longstanding behavior on SPARC. */ - if (boot_console == CONS_SCREEN && plat_fbpath() == NULL) - boot_console = CONS_TTYA; + if (boot_console == CONS_SCREEN_TEXT && plat_fbpath() == NULL) { + boot_console = CONS_TTY; + tty_num = 0; + } + if (tnum != NULL) + *tnum = tty_num; return (boot_console); } int plat_stdin_is_keyboard(void) { - return (console_type() == CONS_SCREEN); + return (console_type(NULL) == CONS_SCREEN_TEXT); } int plat_stdout_is_framebuffer(void) { - return (console_type() == CONS_SCREEN); + return (console_type(NULL) == CONS_SCREEN_TEXT); } static char * @@ -432,7 +448,9 @@ plat_ttypath(int inum) { static char *defaultpath[] = { "/isa/asy@1,3f8:a", - "/isa/asy@1,2f8:b" + "/isa/asy@1,2f8:b", + "/isa/asy@1,3e8:c", + "/isa/asy@1,2e8:d" }; static char path[MAXPATHLEN]; char *bp; @@ -466,25 +484,24 @@ plat_ttypath(int inum) } /* - * Lacking support for com2 and com3, if that matters. * Another possible enhancement could be to use properties * for the port mapping rather than simply hard-code them. */ char * plat_stdinpath(void) { - switch (console_type()) { + int tty_num = 0; + + switch (console_type(&tty_num)) { #if defined(__xpv) case CONS_HYPERVISOR: return ("/xpvd/xencons@0"); #endif /* __xpv */ - case CONS_TTYA: - return (plat_ttypath(0)); - case CONS_TTYB: - return (plat_ttypath(1)); + case CONS_TTY: + return (plat_ttypath(tty_num)); case CONS_USBSER: return (plat_usbser_path()); - case CONS_SCREEN: + case CONS_SCREEN_TEXT: default: break; }; @@ -494,18 +511,18 @@ plat_stdinpath(void) char * plat_stdoutpath(void) { - switch (console_type()) { + int tty_num = 0; + + switch (console_type(&tty_num)) { #if defined(__xpv) case CONS_HYPERVISOR: return ("/xpvd/xencons@0"); #endif /* __xpv */ - case CONS_TTYA: - return (plat_ttypath(0)); - case CONS_TTYB: - return (plat_ttypath(1)); + case CONS_TTY: + return (plat_ttypath(tty_num)); case CONS_USBSER: return (plat_usbser_path()); - case CONS_SCREEN: + case CONS_SCREEN_TEXT: default: break; }; diff --git a/usr/src/uts/i86pc/io/isa.c b/usr/src/uts/i86pc/io/isa.c index b94cc6fbb4..6179e54aa2 100644 --- a/usr/src/uts/i86pc/io/isa.c +++ b/usr/src/uts/i86pc/io/isa.c @@ -19,6 +19,7 @@ * CDDL HEADER END */ /* + * Copyright (c) 2012 Gary Mills * Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright 2012 Garrett D'Amore <garrett@damore.org>. All rights reserved. */ @@ -53,7 +54,7 @@ #include <sys/hypervisor.h> #include <sys/evtchn_impl.h> -extern int console_hypervisor_device; +extern int console_hypervisor_dev_type(int *); #endif @@ -62,12 +63,13 @@ extern int isa_resource_setup(void); extern int (*psm_intr_ops)(dev_info_t *, ddi_intr_handle_impl_t *, psm_intr_op_t, int *); extern void pci_register_isa_resources(int, uint32_t, uint32_t); -static char USED_RESOURCES[] = "used-resources"; static void isa_enumerate(int); static void enumerate_BIOS_serial(dev_info_t *); static void adjust_prtsz(dev_info_t *isa_dip); static void isa_create_ranges_prop(dev_info_t *); +#define USED_RESOURCES "used-resources" + /* * The following typedef is used to represent an entry in the "ranges" * property of a pci-isa bridge device node. @@ -89,11 +91,16 @@ typedef struct { #define USED_CELL_SIZE 2 /* 1 byte addr, 1 byte size */ #define ISA_ADDR_IO 1 /* IO address space */ #define ISA_ADDR_MEM 0 /* memory adress space */ -#define BIOS_DATA_AREA 0x400 + /* * #define ISA_DEBUG 1 */ +#define num_BIOS_serial 4 /* number of BIOS serial ports to look at */ +#define min_BIOS_serial 2 /* minimum number of BIOS serial ports */ +#define COM_ISR 2 /* 16550 intr status register */ +#define COM_SCR 7 /* 16550 scratch register */ + /* * For serial ports not enumerated by ACPI, and parallel ports with * illegal size. Typically, a system can have as many as 4 serial @@ -103,6 +110,17 @@ typedef struct { static struct regspec isa_extra_resource[MAX_EXTRA_RESOURCE]; static int isa_extra_count = 0; +/* Register definitions for COM1 to COM4. */ +static struct regspec asy_regs[] = { + {1, 0x3f8, 0x8}, + {1, 0x2f8, 0x8}, + {1, 0x3e8, 0x8}, + {1, 0x2e8, 0x8} +}; + +/* Serial port interrupt vectors for COM1 to COM4. */ +static int asy_intrs[] = {0x4, 0x3, 0x4, 0x3}; + /* * Local data */ @@ -346,7 +364,7 @@ isa_create_ranges_prop(dev_info_t *dip) uint_t nio = 0, nmem = 0, nrng = 0, n; pib_ranges_t *ranges; - used = ddi_find_devinfo("used-resources", -1, 0); + used = ddi_find_devinfo(USED_RESOURCES, -1, 0); if (used == NULL) { cmn_err(CE_WARN, "Failed to find used-resources <%s>\n", ddi_get_name(dip)); @@ -439,8 +457,10 @@ isa_apply_range(dev_info_t *dip, struct regspec *isa_reg_p, * BIOS data area. Parallel port on some machines comes with * illegal size. */ - if (isa_reg_p->regspec_bustype != ISA_ADDR_IO) - goto out_of_range; + if (isa_reg_p->regspec_bustype != ISA_ADDR_IO) { + cmn_err(CE_WARN, "Bus type not ISA I/O\n"); + return (DDI_ME_REGSPEC_RANGE); + } for (i = 0; i < isa_extra_count; i++) { struct regspec *reg_p = &isa_extra_resource[i]; @@ -461,7 +481,6 @@ isa_apply_range(dev_info_t *dip, struct regspec *isa_reg_p, if (i < isa_extra_count) return (DDI_SUCCESS); -out_of_range: cmn_err(CE_WARN, "isa_apply_range: Out of range base <0x%x>, size <%d>", isa_reg_p->regspec_addr, isa_reg_p->regspec_size); return (DDI_ME_REGSPEC_RANGE); @@ -753,7 +772,11 @@ isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, ddi_intr_handle_impl_t *hdlp, void *result) { struct intrspec *ispec; +#if defined(__xpv) + int cons, ttyn; + cons = console_hypervisor_dev_type(&ttyn); +#endif if (pseudo_isa) return (i_ddi_intr_ops(pdip, rdip, intr_op, hdlp, result)); @@ -827,12 +850,8 @@ isa_intr_ops(dev_info_t *pdip, dev_info_t *rdip, ddi_intr_op_t intr_op, * console, make sure we don't try to use that interrupt as * it will cause us to panic when xen_bind_pirq() fails. */ - if (((ispec->intrspec_vec == 4) && - (console_hypervisor_device == CONS_TTYA)) || - ((ispec->intrspec_vec == 3) && - (console_hypervisor_device == CONS_TTYB))) { + if (cons == CONS_TTY && ispec->intrspec_vec == asy_intrs[ttyn]) return (DDI_FAILURE); - } #endif ((ihdl_plat_t *)hdlp->ih_private)->ip_ispecp = ispec; if ((*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_XLATE_VECTOR, @@ -1148,6 +1167,17 @@ add_known_used_resources(void) } +/* + * Return non-zero if UART device exists. + */ +static int +uart_exists(ushort_t port) +{ + outb(port + COM_SCR, (char)0x5a); + outb(port + COM_ISR, (char)0x00); + return (inb(port + COM_SCR) == (char)0x5a); +} + static void isa_enumerate(int reprogram) { @@ -1155,13 +1185,6 @@ isa_enumerate(int reprogram) dev_info_t *xdip; dev_info_t *isa_dip = ddi_find_devinfo("isa", -1, 0); - /* hard coded isa stuff */ - struct regspec asy_regs[] = { - {1, 0x3f8, 0x8}, - {1, 0x2f8, 0x8} - }; - int asy_intrs[] = {0x4, 0x3}; - struct regspec i8042_regs[] = { {1, 0x60, 0x1}, {1, 0x64, 0x1} @@ -1169,7 +1192,11 @@ isa_enumerate(int reprogram) int i8042_intrs[] = {0x1, 0xc}; char *acpi_prop; int acpi_enum = 1; /* ACPI is default to be on */ +#if defined(__xpv) + int cons, ttyn; + cons = console_hypervisor_dev_type(&ttyn); +#endif if (reprogram || !isa_dip) return; @@ -1205,20 +1232,27 @@ isa_enumerate(int reprogram) cmn_err(CE_NOTE, "!ACPI is off"); /* serial ports */ - for (i = 0; i < 2; i++) { + for (i = 0; i < min_BIOS_serial; i++) { + ushort_t addr = asy_regs[i].regspec_addr; + if (!uart_exists(addr)) + continue; #if defined(__xpv) - if ((i == 0 && console_hypervisor_device == CONS_TTYA) || - (i == 1 && console_hypervisor_device == CONS_TTYB)) { + if (cons == CONS_TTY && ttyn == i) continue; - } #endif ndi_devi_alloc_sleep(isa_dip, "asy", (pnode_t)DEVI_SID_NODEID, &xdip); + (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip, + "compatible", "PNP0500"); + /* This should be gotten from master file: */ + (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip, + "model", "Standard PC COM port"); (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, xdip, "reg", (int *)&asy_regs[i], 3); (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip, "interrupts", asy_intrs[i]); (void) ndi_devi_bind_driver(xdip, 0); + /* Adjusting isa_extra here causes a kernel dump later. */ } /* i8042 node */ @@ -1241,40 +1275,31 @@ isa_enumerate(int reprogram) /* * On some machines, serial port 2 isn't listed in the ACPI table. - * This function goes through the BIOS data area and makes sure all + * This function goes through the base I/O addresses and makes sure all * the serial ports there are in the dev_info tree. If any are missing, * this function will add them. */ -static int num_BIOS_serial = 2; /* number of BIOS serial ports to look at */ - static void enumerate_BIOS_serial(dev_info_t *isa_dip) { - ushort_t *bios_data; int i; dev_info_t *xdip; int found; int ret; struct regspec *tmpregs; int tmpregs_len; - static struct regspec tmp_asy_regs[] = { - {1, 0x3f8, 0x8}, - }; - static int default_asy_intrs[] = { 4, 3, 4, 3 }; - static size_t size = 4; +#if defined(__xpv) + int cons, ttyn; + + cons = console_hypervisor_dev_type(&ttyn); +#endif /* - * The first four 2-byte quantities of the BIOS data area contain - * the base I/O addresses of the first four serial ports. + * Scan the base I/O addresses of the first four serial ports. */ - bios_data = (ushort_t *)psm_map_new((paddr_t)BIOS_DATA_AREA, size, - PSM_PROT_READ); for (i = 0; i < num_BIOS_serial; i++) { - if (bios_data[i] == 0) { - /* no COM[i]: port */ - continue; - } + ushort_t addr = asy_regs[i].regspec_addr; /* Look for it in the dev_info tree */ found = 0; @@ -1294,18 +1319,21 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) continue; } - if (tmpregs->regspec_addr == bios_data[i]) + if (tmpregs->regspec_addr == addr) found = 1; + /* * Free the memory allocated by * ddi_prop_lookup_int_array(). */ ddi_prop_free(tmpregs); + if (found) + break; } /* If not found, then add it */ - if (!found) { + if (!found && uart_exists(addr)) { ndi_devi_alloc_sleep(isa_dip, "asy", (pnode_t)DEVI_SID_NODEID, &xdip); (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip, @@ -1313,15 +1341,14 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) /* This should be gotten from master file: */ (void) ndi_prop_update_string(DDI_DEV_T_NONE, xdip, "model", "Standard PC COM port"); - tmp_asy_regs[0].regspec_addr = bios_data[i]; (void) ndi_prop_update_int_array(DDI_DEV_T_NONE, xdip, - "reg", (int *)&tmp_asy_regs[0], 3); + "reg", (int *)&asy_regs[i], 3); (void) ndi_prop_update_int(DDI_DEV_T_NONE, xdip, - "interrupts", default_asy_intrs[i]); + "interrupts", asy_intrs[i]); (void) ndi_devi_bind_driver(xdip, 0); ASSERT(isa_extra_count < MAX_EXTRA_RESOURCE); - bcopy(tmp_asy_regs, + bcopy(&asy_regs[i], isa_extra_resource + isa_extra_count, sizeof (struct regspec)); isa_extra_count++; @@ -1346,8 +1373,7 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) if (strncmp(ddi_node_name(curdip), "asy", 3) != 0) continue; - if ((i == 0 && console_hypervisor_device == CONS_TTYA) || - (i == 1 && console_hypervisor_device == CONS_TTYB)) { + if (cons == CONS_TTY && ttyn == i) { ret = ndi_devi_free(curdip); if (ret != DDI_SUCCESS) { cmn_err(CE_WARN, @@ -1362,7 +1388,6 @@ enumerate_BIOS_serial(dev_info_t *isa_dip) } #endif - psm_unmap((caddr_t)bios_data, size); } /* diff --git a/usr/src/uts/i86pc/ml/cpr_wakecode.s b/usr/src/uts/i86pc/ml/cpr_wakecode.s index fc58cd5d2a..6955d5893e 100644 --- a/usr/src/uts/i86pc/ml/cpr_wakecode.s +++ b/usr/src/uts/i86pc/ml/cpr_wakecode.s @@ -84,12 +84,6 @@ wc_save_context(wc_cpu_t *pcpu) #else /* lint */ -#if defined(__GNU_AS__) - - NOTHING AT ALL YET! - -#else /* !defined(__GNU_AS__) */ - #if defined(__amd64) ENTRY_NP(wc_save_context) @@ -230,8 +224,6 @@ wc_save_context(wc_cpu_t *pcpu) #endif /* __amd64 */ -#endif /* __GNU_AS__ */ - #endif /* lint */ @@ -263,20 +255,18 @@ wc_rm_end(void) #else /* lint */ -#if defined(__GNU_AS__) - - NOTHING AT ALL YET! - -#else /* __GNU_AS__ */ - #if defined(__amd64) ENTRY_NP(wc_rm_start) /* - * For vulcan as we need to do a .code32 and mentally invert the - * meaning of the addr16 and data16 prefixes to get 32-bit access when - * generating code to be executed in 16-bit mode (sigh...) + * For the Sun Studio 10 assembler we needed to do a .code32 and + * mentally invert the meaning of the addr16 and data16 prefixes to + * get 32-bit access when generating code to be executed in 16-bit + * mode (sigh...) + * + * This code, despite always being built with GNU as, has inherited + * the conceptual damage. */ .code32 @@ -309,7 +299,7 @@ wc_rm_end(void) * %cr0 has already been initialsed to zero */ movl %cr0, %eax - D16 orl $[CR0_PE|CR0_WP|CR0_AM], %eax + D16 orl $_CONST(CR0_PE|CR0_WP|CR0_AM), %eax movl %eax, %cr0 /* @@ -494,45 +484,45 @@ cominit: */ / select COM1 - D16 movl $[COM1+LCR], %edx + D16 movl $_CONST(COM1+LCR), %edx D16 movb $DLAB, %al / divisor latch outb (%dx) - D16 movl $[COM1+DLL], %edx / divisor latch lsb + D16 movl $_CONST(COM1+DLL), %edx / divisor latch lsb D16 movb $B9600L, %al / divisor latch outb (%dx) - D16 movl $[COM1+DLH], %edx / divisor latch hsb + D16 movl $_CONST(COM1+DLH), %edx / divisor latch hsb D16 movb $B9600H, %al / divisor latch outb (%dx) - D16 movl $[COM1+LCR], %edx / select COM1 - D16 movb $[STOP1|BITS8], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM1+LCR), %edx / select COM1 + D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len outb (%dx) - D16 movl $[COM1+MCR], %edx / select COM1 - D16 movb $[RTS|DTR], %al / data term ready & req to send + D16 movl $_CONST(COM1+MCR), %edx / select COM1 + D16 movb $_CONST(RTS|DTR), %al / data term ready & req to send outb (%dx) / select COM2 - D16 movl $[COM2+LCR], %edx + D16 movl $_CONST(COM2+LCR), %edx D16 movb $DLAB, %al / divisor latch outb (%dx) - D16 movl $[COM2+DLL], %edx / divisor latch lsb + D16 movl $_CONST(COM2+DLL), %edx / divisor latch lsb D16 movb $B9600L, %al / divisor latch outb (%dx) - D16 movl $[COM2+DLH], %edx / divisor latch hsb + D16 movl $_CONST(COM2+DLH), %edx / divisor latch hsb D16 movb $B9600H, %al / divisor latch outb (%dx) - D16 movl $[COM2+LCR], %edx / select COM1 - D16 movb $[STOP1|BITS8], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM2+LCR), %edx / select COM1 + D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len outb (%dx) - D16 movl $[COM2+MCR], %edx / select COM1 - D16 movb $[RTS|DTR], %al / data term ready & req to send + D16 movl $_CONST(COM2+MCR), %edx / select COM1 + D16 movb $_CONST(RTS|DTR), %al / data term ready & req to send outb (%dx) #endif /* DEBUG */ @@ -949,7 +939,7 @@ wc_rm_end: #endif D16 A16 movl %cs:WC_CR4(%ebx), %eax / restore cr4 - D16 andl $-1!CR4_PGE, %eax / don't set Global Enable yet + D16 andl $_BITNOT(CR4_PGE), %eax / don't set Global Enable yet movl %eax, %cr4 #if LED @@ -1015,45 +1005,45 @@ cominit: */ / select COM1 - D16 movl $[COM1+LCR], %edx + D16 movl $_CONST(COM1+LCR), %edx D16 movb $DLAB, %al / divisor latch outb (%dx) - D16 movl $[COM1+DLL], %edx / divisor latch lsb + D16 movl $_CONST(COM1+DLL), %edx / divisor latch lsb D16 movb $B9600L, %al / divisor latch outb (%dx) - D16 movl $[COM1+DLH], %edx / divisor latch hsb + D16 movl $_CONST(COM1+DLH), %edx / divisor latch hsb D16 movb $B9600H, %al / divisor latch outb (%dx) - D16 movl $[COM1+LCR], %edx / select COM1 - D16 movb $[STOP1|BITS8], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM1+LCR), %edx / select COM1 + D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len outb (%dx) - D16 movl $[COM1+MCR], %edx / select COM1 - D16 movb $[RTS|DTR], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM1+MCR), %edx / select COM1 + D16 movb $_CONST(RTS|DTR), %al / 1 stop bit, 8bit word len outb (%dx) / select COM2 - D16 movl $[COM2+LCR], %edx + D16 movl $_CONST(COM2+LCR), %edx D16 movb $DLAB, %al / divisor latch outb (%dx) - D16 movl $[COM2+DLL], %edx / divisor latch lsb + D16 movl $_CONST(COM2+DLL), %edx / divisor latch lsb D16 movb $B9600L, %al / divisor latch outb (%dx) - D16 movl $[COM2+DLH], %edx / divisor latch hsb + D16 movl $_CONST(COM2+DLH), %edx / divisor latch hsb D16 movb $B9600H, %al / divisor latch outb (%dx) - D16 movl $[COM2+LCR], %edx / select COM1 - D16 movb $[STOP1|BITS8], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM2+LCR), %edx / select COM1 + D16 movb $_CONST(STOP1|BITS8), %al / 1 stop bit, 8bit word len outb (%dx) - D16 movl $[COM2+MCR], %edx / select COM1 - D16 movb $[RTS|DTR], %al / 1 stop bit, 8bit word len + D16 movl $_CONST(COM2+MCR), %edx / select COM1 + D16 movb $_CONST(RTS|DTR), %al / 1 stop bit, 8bit word len outb (%dx) #endif /* DEBUG */ @@ -1106,7 +1096,7 @@ kernel_wc_code: movzwl WC_TR(%ebx), %eax / clear TSS busy bit addl WC_GDT+2(%ebx), %eax - andl $-1!0x200, 4(%eax) + andl $_BITNOT(0x200), 4(%eax) ltr WC_TR(%ebx) / $UTSS_SEL movw WC_SS(%ebx), %ss / restore segment registers @@ -1172,7 +1162,5 @@ kernel_wc_code: #endif /* defined(__amd64) */ -#endif /* !defined(__GNU_AS__) */ - #endif /* lint */ diff --git a/usr/src/uts/i86pc/ml/mpcore.s b/usr/src/uts/i86pc/ml/mpcore.s index 3ff8aa9d6d..eaf70b72df 100644 --- a/usr/src/uts/i86pc/ml/mpcore.s +++ b/usr/src/uts/i86pc/ml/mpcore.s @@ -78,260 +78,6 @@ real_mode_stop_cpu_stage2(void) ENTRY_NP(real_mode_start_cpu) -#if !defined(__GNUC_AS__) - - /* - * For vulcan as we need to do a .code32 and mentally invert the - * meaning of the addr16 and data16 prefixes to get 32-bit access when - * generating code to be executed in 16-bit mode (sigh...) - */ - .code32 - cli - movw %cs, %ax - movw %ax, %ds /* load cs into ds */ - movw %ax, %ss /* and into ss */ - - /* - * Helps in debugging by giving us the fault address. - * - * Remember to patch a hlt (0xf4) at cmntrap to get a good stack. - */ - D16 movl $0xffc, %esp - movl %cr0, %eax - - /* - * Enable protected-mode, write protect, and alignment mask - */ - D16 orl $[CR0_PE|CR0_WP|CR0_AM], %eax - movl %eax, %cr0 - - /* - * Do a jmp immediately after writing to cr0 when enabling protected - * mode to clear the real mode prefetch queue (per Intel's docs) - */ - jmp pestart - -pestart: - /* - * 16-bit protected mode is now active, so prepare to turn on long - * mode. - * - * Note that we currently assume that if we're attempting to run a - * kernel compiled with (__amd64) #defined, the target CPU has long - * mode support. - */ - -#if 0 - /* - * If there's a chance this might not be true, the following test should - * be done, with the no_long_mode branch then doing something - * appropriate: - */ - - D16 movl $0x80000000, %eax /* get largest extended CPUID */ - cpuid - D16 cmpl $0x80000000, %eax /* check if > 0x80000000 */ - jbe no_long_mode /* nope, no long mode */ - D16 movl $0x80000001, %eax - cpuid /* get extended feature flags */ - btl $29, %edx /* check for long mode */ - jnc no_long_mode /* long mode not supported */ -#endif - - /* - * Add any initial cr4 bits - */ - movl %cr4, %eax - A16 D16 orl CR4OFF, %eax - - /* - * Enable PAE mode (CR4.PAE) - */ - D16 orl $CR4_PAE, %eax - movl %eax, %cr4 - - /* - * Point cr3 to the 64-bit long mode page tables. - * - * Note that these MUST exist in 32-bit space, as we don't have - * a way to load %cr3 with a 64-bit base address for the page tables - * until the CPU is actually executing in 64-bit long mode. - */ - A16 D16 movl CR3OFF, %eax - movl %eax, %cr3 - - /* - * Set long mode enable in EFER (EFER.LME = 1) - */ - D16 movl $MSR_AMD_EFER, %ecx - rdmsr - D16 orl $AMD_EFER_LME, %eax - wrmsr - - /* - * Finally, turn on paging (CR0.PG = 1) to activate long mode. - */ - movl %cr0, %eax - D16 orl $CR0_PG, %eax - movl %eax, %cr0 - - /* - * The instruction after enabling paging in CR0 MUST be a branch. - */ - jmp long_mode_active - -long_mode_active: - /* - * Long mode is now active but since we're still running with the - * original 16-bit CS we're actually in 16-bit compatability mode. - * - * We have to load an intermediate GDT and IDT here that we know are - * in 32-bit space before we can use the kernel's GDT and IDT, which - * may be in the 64-bit address space, and since we're in compatability - * mode, we only have access to 16 and 32-bit instructions at the - * moment. - */ - A16 D16 lgdt TEMPGDTOFF /* load temporary GDT */ - A16 D16 lidt TEMPIDTOFF /* load temporary IDT */ - - /* - * Do a far transfer to 64-bit mode. Set the CS selector to a 64-bit - * long mode selector (CS.L=1) in the temporary 32-bit GDT and jump - * to the real mode platter address of long_mode 64 as until the 64-bit - * CS is in place we don't have access to 64-bit instructions and thus - * can't reference a 64-bit %rip. - */ - D16 pushl $TEMP_CS64_SEL - A16 D16 pushl LM64OFF - D16 lret - - .globl long_mode_64 -long_mode_64: - .code64 - /* - * We are now running in long mode with a 64-bit CS (EFER.LMA=1, - * CS.L=1) so we now have access to 64-bit instructions. - * - * First, set the 64-bit GDT base. - */ - .globl rm_platter_pa - movl rm_platter_pa, %eax - - lgdtq GDTROFF(%rax) /* load 64-bit GDT */ - - /* - * Save the CPU number in %r11; get the value here since it's saved in - * the real mode platter. - */ - movl CPUNOFF(%rax), %r11d - - /* - * Add rm_platter_pa to %rsp to point it to the same location as seen - * from 64-bit mode. - */ - addq %rax, %rsp - - /* - * Now do an lretq to load CS with the appropriate selector for the - * kernel's 64-bit GDT and to start executing 64-bit setup code at the - * virtual address where boot originally loaded this code rather than - * the copy in the real mode platter's rm_code array as we've been - * doing so far. - */ - pushq $KCS_SEL - pushq $kernel_cs_code - lretq - .globl real_mode_start_cpu_end -real_mode_start_cpu_end: - nop - -kernel_cs_code: - /* - * Complete the balance of the setup we need to before executing - * 64-bit kernel code (namely init rsp, TSS, LGDT, FS and GS). - */ - .globl rm_platter_va - movq rm_platter_va, %rax - - lidtq IDTROFF(%rax) - - movw $KDS_SEL, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - - movw $KTSS_SEL, %ax /* setup kernel TSS */ - ltr %ax - - xorw %ax, %ax /* clear LDTR */ - lldt %ax - - /* - * Set GS to the address of the per-cpu structure as contained in - * cpu[cpu_number]. - * - * Unfortunately there's no way to set the 64-bit gsbase with a mov, - * so we have to stuff the low 32 bits in %eax and the high 32 bits in - * %edx, then call wrmsr. - */ - leaq cpu(%rip), %rdi - movl (%rdi, %r11, 8), %eax - movl 4(%rdi, %r11, 8), %edx - movl $MSR_AMD_GSBASE, %ecx - wrmsr - - /* - * Init FS and KernelGSBase. - * - * Based on code in mlsetup(), set them both to 8G (which shouldn't be - * valid until some 64-bit processes run); this will then cause an - * exception in any code that tries to index off them before they are - * properly setup. - */ - xorl %eax, %eax /* low 32 bits = 0 */ - movl $2, %edx /* high 32 bits = 2 */ - movl $MSR_AMD_FSBASE, %ecx - wrmsr - - movl $MSR_AMD_KGSBASE, %ecx - wrmsr - - /* - * Init %rsp to the exception stack set in tss_ist1 and create a legal - * AMD64 ABI stack frame - */ - movq %gs:CPU_TSS, %rax - movq TSS_IST1(%rax), %rsp - pushq $0 /* null return address */ - pushq $0 /* null frame pointer terminates stack trace */ - movq %rsp, %rbp /* stack aligned on 16-byte boundary */ - - movq %cr0, %rax - andq $-1![CR0_TS|CR0_EM], %rax /* clr emulate math chip bit */ - orq $[CR0_MP|CR0_NE], %rax - movq %rax, %cr0 /* set machine status word */ - - /* - * Before going any further, enable usage of page table NX bit if - * that's how our page tables are set up. - */ - bt $X86FSET_NX, x86_featureset(%rip) - jnc 1f - movl $MSR_AMD_EFER, %ecx - rdmsr - orl $AMD_EFER_NXE, %eax - wrmsr -1: - - /* - * Complete the rest of the setup and call mp_startup(). - */ - movq %gs:CPU_THREAD, %rax /* get thread ptr */ - call *T_PC(%rax) /* call mp_startup */ - /* not reached */ - int $20 /* whoops, returned somehow! */ -#else /* __GNUC_AS__ */ - /* * NOTE: The GNU assembler automatically does the right thing to * generate data size operand prefixes based on the code size @@ -583,7 +329,6 @@ kernel_cs_code: call *T_PC(%rax) /* call mp_startup */ /* not reached */ int $20 /* whoops, returned somehow! */ -#endif /* !__GNUC_AS__ */ SET_SIZE(real_mode_start_cpu) diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c index 0a389e0063..10946474dd 100644 --- a/usr/src/uts/i86pc/os/cpuid.c +++ b/usr/src/uts/i86pc/os/cpuid.c @@ -30,7 +30,7 @@ * Portions Copyright 2009 Advanced Micro Devices, Inc. */ /* - * Copyright (c) 2011, Joyent, Inc. All rights reserved. + * Copyright (c) 2012, Joyent, Inc. All rights reserved. */ /* * Various routines to handle identification @@ -160,7 +160,8 @@ static char *x86_feature_names[NUM_X86_FEATURES] = { "xsave", "avx", "vmx", - "svm" + "svm", + "topoext" }; boolean_t @@ -269,7 +270,7 @@ struct xsave_info { */ #define NMAX_CPI_STD 6 /* eax = 0 .. 5 */ -#define NMAX_CPI_EXTD 0x1c /* eax = 0x80000000 .. 0x8000001b */ +#define NMAX_CPI_EXTD 0x1f /* eax = 0x80000000 .. 0x8000001e */ /* * Some terminology needs to be explained: @@ -283,6 +284,8 @@ struct xsave_info { * memory controllers, PCI configuration spaces. They are connected * inside the package with Hypertransport links. On single-node * processors, processor node is equivalent to chip/socket/package. + * - Compute Unit: Some AMD processors pair cores in "compute units" that + * share the FPU and the I$ and L2 caches. */ struct cpuid_info { @@ -343,6 +346,8 @@ struct cpuid_info { uint_t cpi_procnodeid; /* AMD: nodeID on HT, Intel: chipid */ uint_t cpi_procnodes_per_pkg; /* AMD: # of nodes in the package */ /* Intel: 1 */ + uint_t cpi_compunitid; /* AMD: ComputeUnit ID, Intel: coreid */ + uint_t cpi_cores_per_compunit; /* AMD: # of cores in the ComputeUnit */ struct xsave_info cpi_xsave; /* fn D: xsave/xrestor info */ }; @@ -727,6 +732,7 @@ cpuid_intel_getids(cpu_t *cpu, void *feature) cpi->cpi_pkgcoreid = 0; } cpi->cpi_procnodeid = cpi->cpi_chipid; + cpi->cpi_compunitid = cpi->cpi_coreid; } static void @@ -736,6 +742,7 @@ cpuid_amd_getids(cpu_t *cpu) uint32_t nb_caps_reg; uint_t node2_1; struct cpuid_info *cpi = cpu->cpu_m.mcpu_cpi; + struct cpuid_regs *cp; /* * AMD CMP chips currently have a single thread per core. @@ -753,9 +760,15 @@ cpuid_amd_getids(cpu_t *cpu) * from 0 regardless of how many or which are disabled, and there * is no way for operating system to discover the real core id when some * are disabled. + * + * In family 0x15, the cores come in pairs called compute units. They + * share I$ and L2 caches and the FPU. Enumeration of this feature is + * simplified by the new topology extensions CPUID leaf, indicated by + * the X86 feature X86FSET_TOPOEXT. */ cpi->cpi_coreid = cpu->cpu_id; + cpi->cpi_compunitid = cpu->cpu_id; if (cpi->cpi_xmaxeax >= 0x80000008) { @@ -784,10 +797,21 @@ cpuid_amd_getids(cpu_t *cpu) cpi->cpi_apicid & ((1<<coreidsz) - 1); cpi->cpi_ncpu_per_chip = cpi->cpi_ncore_per_chip; - /* Get nodeID */ - if (cpi->cpi_family == 0xf) { + /* Get node ID, compute unit ID */ + if (is_x86_feature(x86_featureset, X86FSET_TOPOEXT) && + cpi->cpi_xmaxeax >= 0x8000001e) { + cp = &cpi->cpi_extd[0x1e]; + cp->cp_eax = 0x8000001e; + (void) __cpuid_insn(cp); + + cpi->cpi_procnodes_per_pkg = BITX(cp->cp_ecx, 10, 8) + 1; + cpi->cpi_procnodeid = BITX(cp->cp_ecx, 7, 0); + cpi->cpi_cores_per_compunit = BITX(cp->cp_ebx, 15, 8) + 1; + cpi->cpi_compunitid = BITX(cp->cp_ebx, 7, 0) + + (cpi->cpi_ncore_per_chip / cpi->cpi_cores_per_compunit) + * (cpi->cpi_procnodeid / cpi->cpi_procnodes_per_pkg); + } else if (cpi->cpi_family == 0xf || cpi->cpi_family >= 0x11) { cpi->cpi_procnodeid = (cpi->cpi_apicid >> coreidsz) & 7; - cpi->cpi_chipid = cpi->cpi_procnodeid; } else if (cpi->cpi_family == 0x10) { /* * See if we are a multi-node processor. @@ -798,7 +822,6 @@ cpuid_amd_getids(cpu_t *cpu) /* Single-node */ cpi->cpi_procnodeid = BITX(cpi->cpi_apicid, 5, coreidsz); - cpi->cpi_chipid = cpi->cpi_procnodeid; } else { /* @@ -813,7 +836,6 @@ cpuid_amd_getids(cpu_t *cpu) if (cpi->cpi_apicid == cpi->cpi_pkgcoreid) { /* We are BSP */ cpi->cpi_procnodeid = (first_half ? 0 : 1); - cpi->cpi_chipid = cpi->cpi_procnodeid >> 1; } else { /* We are AP */ @@ -833,17 +855,14 @@ cpuid_amd_getids(cpu_t *cpu) else cpi->cpi_procnodeid = node2_1 + first_half; - - cpi->cpi_chipid = cpi->cpi_procnodeid >> 1; } } - } else if (cpi->cpi_family >= 0x11) { - cpi->cpi_procnodeid = (cpi->cpi_apicid >> coreidsz) & 7; - cpi->cpi_chipid = cpi->cpi_procnodeid; } else { cpi->cpi_procnodeid = 0; - cpi->cpi_chipid = cpi->cpi_procnodeid; } + + cpi->cpi_chipid = + cpi->cpi_procnodeid / cpi->cpi_procnodes_per_pkg; } /* @@ -1218,30 +1237,28 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset) if (cp->cp_ecx & CPUID_INTC_ECX_SSE3) { add_x86_feature(featureset, X86FSET_SSE3); } - if (cpi->cpi_vendor == X86_VENDOR_Intel) { - if (cp->cp_ecx & CPUID_INTC_ECX_SSSE3) { - add_x86_feature(featureset, X86FSET_SSSE3); - } - if (cp->cp_ecx & CPUID_INTC_ECX_SSE4_1) { - add_x86_feature(featureset, X86FSET_SSE4_1); - } - if (cp->cp_ecx & CPUID_INTC_ECX_SSE4_2) { - add_x86_feature(featureset, X86FSET_SSE4_2); - } - if (cp->cp_ecx & CPUID_INTC_ECX_AES) { - add_x86_feature(featureset, X86FSET_AES); - } - if (cp->cp_ecx & CPUID_INTC_ECX_PCLMULQDQ) { - add_x86_feature(featureset, X86FSET_PCLMULQDQ); - } + if (cp->cp_ecx & CPUID_INTC_ECX_SSSE3) { + add_x86_feature(featureset, X86FSET_SSSE3); + } + if (cp->cp_ecx & CPUID_INTC_ECX_SSE4_1) { + add_x86_feature(featureset, X86FSET_SSE4_1); + } + if (cp->cp_ecx & CPUID_INTC_ECX_SSE4_2) { + add_x86_feature(featureset, X86FSET_SSE4_2); + } + if (cp->cp_ecx & CPUID_INTC_ECX_AES) { + add_x86_feature(featureset, X86FSET_AES); + } + if (cp->cp_ecx & CPUID_INTC_ECX_PCLMULQDQ) { + add_x86_feature(featureset, X86FSET_PCLMULQDQ); + } - if (cp->cp_ecx & CPUID_INTC_ECX_XSAVE) { - add_x86_feature(featureset, X86FSET_XSAVE); - /* We only test AVX when there is XSAVE */ - if (cp->cp_ecx & CPUID_INTC_ECX_AVX) { - add_x86_feature(featureset, - X86FSET_AVX); - } + if (cp->cp_ecx & CPUID_INTC_ECX_XSAVE) { + add_x86_feature(featureset, X86FSET_XSAVE); + /* We only test AVX when there is XSAVE */ + if (cp->cp_ecx & CPUID_INTC_ECX_AVX) { + add_x86_feature(featureset, + X86FSET_AVX); } } } @@ -1439,6 +1456,10 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset) if (cp->cp_ecx & CPUID_AMD_ECX_SVM) { add_x86_feature(featureset, X86FSET_SVM); } + + if (cp->cp_ecx & CPUID_AMD_ECX_TOPOEXT) { + add_x86_feature(featureset, X86FSET_TOPOEXT); + } break; default: break; @@ -1547,6 +1568,7 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset) cpi->cpi_apicid = CPI_APIC_ID(cpi); cpi->cpi_procnodes_per_pkg = 1; + cpi->cpi_cores_per_compunit = 1; if (is_x86_feature(featureset, X86FSET_HTT) == B_FALSE && is_x86_feature(featureset, X86FSET_CMP) == B_FALSE) { /* @@ -1573,6 +1595,7 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset) cpi->cpi_coreid = cpi->cpi_chipid; cpi->cpi_pkgcoreid = 0; cpi->cpi_procnodeid = cpi->cpi_chipid; + cpi->cpi_compunitid = cpi->cpi_chipid; } } @@ -1797,7 +1820,7 @@ cpuid_pass2(cpu_t *cpu) /* * XSAVE enumeration */ - if (cpi->cpi_maxeax >= 0xD && cpi->cpi_vendor == X86_VENDOR_Intel) { + if (cpi->cpi_maxeax >= 0xD) { struct cpuid_regs regs; boolean_t cpuid_d_valid = B_TRUE; @@ -2531,23 +2554,21 @@ cpuid_pass4(cpu_t *cpu) if (!is_x86_feature(x86_featureset, X86FSET_SSE3)) *ecx &= ~CPUID_INTC_ECX_SSE3; - if (cpi->cpi_vendor == X86_VENDOR_Intel) { - if (!is_x86_feature(x86_featureset, X86FSET_SSSE3)) - *ecx &= ~CPUID_INTC_ECX_SSSE3; - if (!is_x86_feature(x86_featureset, X86FSET_SSE4_1)) - *ecx &= ~CPUID_INTC_ECX_SSE4_1; - if (!is_x86_feature(x86_featureset, X86FSET_SSE4_2)) - *ecx &= ~CPUID_INTC_ECX_SSE4_2; - if (!is_x86_feature(x86_featureset, X86FSET_AES)) - *ecx &= ~CPUID_INTC_ECX_AES; - if (!is_x86_feature(x86_featureset, X86FSET_PCLMULQDQ)) - *ecx &= ~CPUID_INTC_ECX_PCLMULQDQ; - if (!is_x86_feature(x86_featureset, X86FSET_XSAVE)) - *ecx &= ~(CPUID_INTC_ECX_XSAVE | - CPUID_INTC_ECX_OSXSAVE); - if (!is_x86_feature(x86_featureset, X86FSET_AVX)) - *ecx &= ~CPUID_INTC_ECX_AVX; - } + if (!is_x86_feature(x86_featureset, X86FSET_SSSE3)) + *ecx &= ~CPUID_INTC_ECX_SSSE3; + if (!is_x86_feature(x86_featureset, X86FSET_SSE4_1)) + *ecx &= ~CPUID_INTC_ECX_SSE4_1; + if (!is_x86_feature(x86_featureset, X86FSET_SSE4_2)) + *ecx &= ~CPUID_INTC_ECX_SSE4_2; + if (!is_x86_feature(x86_featureset, X86FSET_AES)) + *ecx &= ~CPUID_INTC_ECX_AES; + if (!is_x86_feature(x86_featureset, X86FSET_PCLMULQDQ)) + *ecx &= ~CPUID_INTC_ECX_PCLMULQDQ; + if (!is_x86_feature(x86_featureset, X86FSET_XSAVE)) + *ecx &= ~(CPUID_INTC_ECX_XSAVE | + CPUID_INTC_ECX_OSXSAVE); + if (!is_x86_feature(x86_featureset, X86FSET_AVX)) + *ecx &= ~CPUID_INTC_ECX_AVX; /* * [no explicit support required beyond x87 fp context] @@ -2567,22 +2588,24 @@ cpuid_pass4(cpu_t *cpu) hwcap_flags |= AV_386_SSE2; if (*ecx & CPUID_INTC_ECX_SSE3) hwcap_flags |= AV_386_SSE3; - if (cpi->cpi_vendor == X86_VENDOR_Intel) { - if (*ecx & CPUID_INTC_ECX_SSSE3) - hwcap_flags |= AV_386_SSSE3; - if (*ecx & CPUID_INTC_ECX_SSE4_1) - hwcap_flags |= AV_386_SSE4_1; - if (*ecx & CPUID_INTC_ECX_SSE4_2) - hwcap_flags |= AV_386_SSE4_2; - if (*ecx & CPUID_INTC_ECX_MOVBE) - hwcap_flags |= AV_386_MOVBE; - if (*ecx & CPUID_INTC_ECX_AES) - hwcap_flags |= AV_386_AES; - if (*ecx & CPUID_INTC_ECX_PCLMULQDQ) - hwcap_flags |= AV_386_PCLMULQDQ; - if ((*ecx & CPUID_INTC_ECX_XSAVE) && - (*ecx & CPUID_INTC_ECX_OSXSAVE)) - hwcap_flags |= AV_386_XSAVE; + if (*ecx & CPUID_INTC_ECX_SSSE3) + hwcap_flags |= AV_386_SSSE3; + if (*ecx & CPUID_INTC_ECX_SSE4_1) + hwcap_flags |= AV_386_SSE4_1; + if (*ecx & CPUID_INTC_ECX_SSE4_2) + hwcap_flags |= AV_386_SSE4_2; + if (*ecx & CPUID_INTC_ECX_MOVBE) + hwcap_flags |= AV_386_MOVBE; + if (*ecx & CPUID_INTC_ECX_AES) + hwcap_flags |= AV_386_AES; + if (*ecx & CPUID_INTC_ECX_PCLMULQDQ) + hwcap_flags |= AV_386_PCLMULQDQ; + if ((*ecx & CPUID_INTC_ECX_XSAVE) && + (*ecx & CPUID_INTC_ECX_OSXSAVE)) { + hwcap_flags |= AV_386_XSAVE; + + if (*ecx & CPUID_INTC_ECX_AVX) + hwcap_flags |= AV_386_AVX; } if (*ecx & CPUID_INTC_ECX_VMX) hwcap_flags |= AV_386_VMX; @@ -3006,6 +3029,20 @@ cpuid_get_procnodes_per_pkg(cpu_t *cpu) return (cpu->cpu_m.mcpu_cpi->cpi_procnodes_per_pkg); } +uint_t +cpuid_get_compunitid(cpu_t *cpu) +{ + ASSERT(cpuid_checkpass(cpu, 1)); + return (cpu->cpu_m.mcpu_cpi->cpi_compunitid); +} + +uint_t +cpuid_get_cores_per_compunit(cpu_t *cpu) +{ + ASSERT(cpuid_checkpass(cpu, 1)); + return (cpu->cpu_m.mcpu_cpi->cpi_cores_per_compunit); +} + /*ARGSUSED*/ int cpuid_have_cr8access(cpu_t *cpu) @@ -3336,6 +3373,13 @@ cpuid_opteron_erratum(cpu_t *cpu, uint_t erratum) return (DR_AX(eax) || DR_B0(eax) || DR_B1(eax) || DR_BA(eax) || DR_B2(eax) || RB_C0(eax)); + case 721: +#if defined(__amd64) + return (cpi->cpi_family == 0x10 || cpi->cpi_family == 0x12); +#else + return (0); +#endif + default: return (-1); @@ -4135,6 +4179,9 @@ cpuid_set_cpu_properties(void *dip, processorid_t cpu_id, case X86_VENDOR_Intel: create = IS_NEW_F6(cpi) || cpi->cpi_family >= 0xf; break; + case X86_VENDOR_AMD: + create = cpi->cpi_family >= 0xf; + break; default: create = 0; break; diff --git a/usr/src/uts/i86pc/os/cpupm/pwrnow.c b/usr/src/uts/i86pc/os/cpupm/pwrnow.c index d403c69e34..0116fe9157 100644 --- a/usr/src/uts/i86pc/os/cpupm/pwrnow.c +++ b/usr/src/uts/i86pc/os/cpupm/pwrnow.c @@ -38,6 +38,8 @@ static void pwrnow_fini(cpu_t *); static void pwrnow_power(cpuset_t, uint32_t); static void pwrnow_stop(cpu_t *); +static boolean_t pwrnow_cpb_supported(void); + /* * Interfaces for modules implementing AMD's PowerNow!. */ @@ -67,6 +69,7 @@ cpupm_state_ops_t pwrnow_ops = { #define AMD_CPUID_PSTATE_HARDWARE (1<<7) #define AMD_CPUID_TSC_CONSTANT (1<<8) +#define AMD_CPUID_CPB (1<<9) /* * Debugging support @@ -128,6 +131,10 @@ pwrnow_pstate_transition(uint32_t req_state) ctrl = CPU_ACPI_PSTATE_CTRL(req_pstate); write_ctrl(handle, ctrl); + if (mach_state->ms_turbo != NULL) + cpupm_record_turbo_info(mach_state->ms_turbo, + mach_state->ms_pstate.cma_state.pstate, req_state); + mach_state->ms_pstate.cma_state.pstate = req_state; cpu_set_curr_clock((uint64_t)CPU_ACPI_FREQ(req_pstate) * 1000000); } @@ -192,6 +199,12 @@ pwrnow_init(cpu_t *cp) cpupm_alloc_domains(cp, CPUPM_P_STATES); + /* + * Check for Core Performance Boost support + */ + if (pwrnow_cpb_supported()) + mach_state->ms_turbo = cpupm_turbo_init(cp); + PWRNOW_DEBUG(("Processor %d succeeded.\n", cp->cpu_id)) return (PWRNOW_RET_SUCCESS); } @@ -208,6 +221,10 @@ pwrnow_fini(cpu_t *cp) cpupm_free_domains(&cpupm_pstate_domains); cpu_acpi_free_pstate_data(handle); + + if (mach_state->ms_turbo != NULL) + cpupm_turbo_fini(mach_state->ms_turbo); + mach_state->ms_turbo = NULL; } boolean_t @@ -249,6 +266,30 @@ pwrnow_supported() return (B_TRUE); } +static boolean_t +pwrnow_cpb_supported(void) +{ + struct cpuid_regs cpu_regs; + + /* Required features */ + if (!is_x86_feature(x86_featureset, X86FSET_CPUID) || + !is_x86_feature(x86_featureset, X86FSET_MSR)) { + PWRNOW_DEBUG(("No CPUID or MSR support.")); + return (B_FALSE); + } + + /* + * Get the Advanced Power Management Information. + */ + cpu_regs.cp_eax = 0x80000007; + (void) __cpuid_insn(&cpu_regs); + + if (!(cpu_regs.cp_edx & AMD_CPUID_CPB)) + return (B_FALSE); + + return (B_TRUE); +} + static void pwrnow_stop(cpu_t *cp) { @@ -258,4 +299,8 @@ pwrnow_stop(cpu_t *cp) cpupm_remove_domains(cp, CPUPM_P_STATES, &cpupm_pstate_domains); cpu_acpi_free_pstate_data(handle); + + if (mach_state->ms_turbo != NULL) + cpupm_turbo_fini(mach_state->ms_turbo); + mach_state->ms_turbo = NULL; } diff --git a/usr/src/uts/i86pc/os/cpupm/speedstep.c b/usr/src/uts/i86pc/os/cpupm/speedstep.c index 2be4529a83..27df5c022d 100644 --- a/usr/src/uts/i86pc/os/cpupm/speedstep.c +++ b/usr/src/uts/i86pc/os/cpupm/speedstep.c @@ -38,33 +38,11 @@ #include <sys/dtrace.h> #include <sys/sdt.h> -/* - * turbo related structure definitions - */ -typedef struct cpupm_turbo_info { - kstat_t *turbo_ksp; /* turbo kstat */ - int in_turbo; /* in turbo? */ - int turbo_supported; /* turbo flag */ - uint64_t t_mcnt; /* turbo mcnt */ - uint64_t t_acnt; /* turbo acnt */ -} cpupm_turbo_info_t; - -typedef struct turbo_kstat_s { - struct kstat_named turbo_supported; /* turbo flag */ - struct kstat_named t_mcnt; /* IA32_MPERF_MSR */ - struct kstat_named t_acnt; /* IA32_APERF_MSR */ -} turbo_kstat_t; - static int speedstep_init(cpu_t *); static void speedstep_fini(cpu_t *); static void speedstep_power(cpuset_t, uint32_t); static void speedstep_stop(cpu_t *); -static boolean_t turbo_supported(void); -static int turbo_kstat_update(kstat_t *, int); -static void get_turbo_info(cpupm_turbo_info_t *); -static void reset_turbo_info(void); -static void record_turbo_info(cpupm_turbo_info_t *, uint32_t, uint32_t); -static void update_turbo_info(cpupm_turbo_info_t *); +static boolean_t speedstep_turbo_supported(void); /* * Interfaces for modules implementing Intel's Enhanced SpeedStep. @@ -96,16 +74,6 @@ cpupm_state_ops_t speedstep_ops = { #define IA32_MISC_ENABLE_CXE (1<<25) #define CPUID_TURBO_SUPPORT (1 << 1) -#define CPU_ACPI_P0 0 -#define CPU_IN_TURBO 1 - -/* - * MSR for hardware coordination feedback mechanism - * - IA32_MPERF: increments in proportion to a fixed frequency - * - IA32_APERF: increments in proportion to actual performance - */ -#define IA32_MPERF_MSR 0xE7 -#define IA32_APERF_MSR 0xE8 /* * Debugging support @@ -117,116 +85,6 @@ volatile int ess_debug = 0; #define ESSDEBUG(arglist) #endif -static kmutex_t turbo_mutex; - -turbo_kstat_t turbo_kstat = { - { "turbo_supported", KSTAT_DATA_UINT32 }, - { "turbo_mcnt", KSTAT_DATA_UINT64 }, - { "turbo_acnt", KSTAT_DATA_UINT64 }, -}; - -/* - * kstat update function of the turbo mode info - */ -static int -turbo_kstat_update(kstat_t *ksp, int flag) -{ - cpupm_turbo_info_t *turbo_info = ksp->ks_private; - - if (flag == KSTAT_WRITE) { - return (EACCES); - } - - /* - * update the count in case CPU is in the turbo - * mode for a long time - */ - if (turbo_info->in_turbo == CPU_IN_TURBO) - update_turbo_info(turbo_info); - - turbo_kstat.turbo_supported.value.ui32 = - turbo_info->turbo_supported; - turbo_kstat.t_mcnt.value.ui64 = turbo_info->t_mcnt; - turbo_kstat.t_acnt.value.ui64 = turbo_info->t_acnt; - - return (0); -} - -/* - * Get count of MPERF/APERF MSR - */ -static void -get_turbo_info(cpupm_turbo_info_t *turbo_info) -{ - ulong_t iflag; - uint64_t mcnt, acnt; - - iflag = intr_clear(); - mcnt = rdmsr(IA32_MPERF_MSR); - acnt = rdmsr(IA32_APERF_MSR); - turbo_info->t_mcnt += mcnt; - turbo_info->t_acnt += acnt; - intr_restore(iflag); -} - -/* - * Clear MPERF/APERF MSR - */ -static void -reset_turbo_info(void) -{ - ulong_t iflag; - - iflag = intr_clear(); - wrmsr(IA32_MPERF_MSR, 0); - wrmsr(IA32_APERF_MSR, 0); - intr_restore(iflag); -} - -/* - * sum up the count of one CPU_ACPI_P0 transition - */ -static void -record_turbo_info(cpupm_turbo_info_t *turbo_info, - uint32_t cur_state, uint32_t req_state) -{ - if (!turbo_info->turbo_supported) - return; - /* - * enter P0 state - */ - if (req_state == CPU_ACPI_P0) { - reset_turbo_info(); - turbo_info->in_turbo = CPU_IN_TURBO; - } - /* - * Leave P0 state - */ - else if (cur_state == CPU_ACPI_P0) { - turbo_info->in_turbo = 0; - get_turbo_info(turbo_info); - } -} - -/* - * update the sum of counts and clear MSRs - */ -static void -update_turbo_info(cpupm_turbo_info_t *turbo_info) -{ - ulong_t iflag; - uint64_t mcnt, acnt; - - iflag = intr_clear(); - mcnt = rdmsr(IA32_MPERF_MSR); - acnt = rdmsr(IA32_APERF_MSR); - wrmsr(IA32_MPERF_MSR, 0); - wrmsr(IA32_APERF_MSR, 0); - turbo_info->t_mcnt += mcnt; - turbo_info->t_acnt += acnt; - intr_restore(iflag); -} - /* * Write the ctrl register. How it is written, depends upon the _PCT * APCI object value. @@ -276,8 +134,6 @@ speedstep_pstate_transition(uint32_t req_state) cpu_acpi_handle_t handle = mach_state->ms_acpi_handle; cpu_acpi_pstate_t *req_pstate; uint32_t ctrl; - cpupm_turbo_info_t *turbo_info = - (cpupm_turbo_info_t *)(mach_state->ms_vendor); req_pstate = (cpu_acpi_pstate_t *)CPU_ACPI_PSTATES(handle); req_pstate += req_state; @@ -290,11 +146,10 @@ speedstep_pstate_transition(uint32_t req_state) ctrl = CPU_ACPI_PSTATE_CTRL(req_pstate); write_ctrl(handle, ctrl); - if (turbo_info) - record_turbo_info(turbo_info, + if (mach_state->ms_turbo != NULL) + cpupm_record_turbo_info(mach_state->ms_turbo, mach_state->ms_pstate.cma_state.pstate, req_state); - mach_state->ms_pstate.cma_state.pstate = req_state; cpu_set_curr_clock(((uint64_t)CPU_ACPI_FREQ(req_pstate) * 1000000)); } @@ -330,7 +185,6 @@ speedstep_init(cpu_t *cp) (cpupm_mach_state_t *)cp->cpu_m.mcpu_pm_mach_state; cpu_acpi_handle_t handle = mach_state->ms_acpi_handle; cpu_acpi_pct_t *pct_stat; - cpupm_turbo_info_t *turbo_info; ESSDEBUG(("speedstep_init: processor %d\n", cp->cpu_id)); @@ -363,34 +217,8 @@ speedstep_init(cpu_t *cp) cpupm_alloc_domains(cp, CPUPM_P_STATES); - if (!turbo_supported()) { - mach_state->ms_vendor = NULL; - goto ess_ret_success; - } - /* - * turbo mode supported - */ - turbo_info = mach_state->ms_vendor = - kmem_zalloc(sizeof (cpupm_turbo_info_t), KM_SLEEP); - turbo_info->turbo_supported = 1; - turbo_info->turbo_ksp = kstat_create("turbo", cp->cpu_id, - "turbo", "misc", KSTAT_TYPE_NAMED, - sizeof (turbo_kstat) / sizeof (kstat_named_t), - KSTAT_FLAG_VIRTUAL); - - if (turbo_info->turbo_ksp == NULL) { - cmn_err(CE_NOTE, "kstat_create(turbo) fail"); - } else { - turbo_info->turbo_ksp->ks_data = &turbo_kstat; - turbo_info->turbo_ksp->ks_lock = &turbo_mutex; - turbo_info->turbo_ksp->ks_update = turbo_kstat_update; - turbo_info->turbo_ksp->ks_data_size += MAXNAMELEN; - turbo_info->turbo_ksp->ks_private = turbo_info; - - kstat_install(turbo_info->turbo_ksp); - } - -ess_ret_success: + if (speedstep_turbo_supported()) + mach_state->ms_turbo = cpupm_turbo_init(cp); ESSDEBUG(("Processor %d succeeded.\n", cp->cpu_id)) return (ESS_RET_SUCCESS); @@ -405,17 +233,13 @@ speedstep_fini(cpu_t *cp) cpupm_mach_state_t *mach_state = (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state); cpu_acpi_handle_t handle = mach_state->ms_acpi_handle; - cpupm_turbo_info_t *turbo_info = - (cpupm_turbo_info_t *)(mach_state->ms_vendor); cpupm_free_domains(&cpupm_pstate_domains); cpu_acpi_free_pstate_data(handle); - if (turbo_info) { - if (turbo_info->turbo_ksp != NULL) - kstat_delete(turbo_info->turbo_ksp); - kmem_free(turbo_info, sizeof (cpupm_turbo_info_t)); - } + if (mach_state->ms_turbo != NULL) + cpupm_turbo_fini(mach_state->ms_turbo); + mach_state->ms_turbo = NULL; } static void @@ -424,17 +248,13 @@ speedstep_stop(cpu_t *cp) cpupm_mach_state_t *mach_state = (cpupm_mach_state_t *)(cp->cpu_m.mcpu_pm_mach_state); cpu_acpi_handle_t handle = mach_state->ms_acpi_handle; - cpupm_turbo_info_t *turbo_info = - (cpupm_turbo_info_t *)(mach_state->ms_vendor); cpupm_remove_domains(cp, CPUPM_P_STATES, &cpupm_pstate_domains); cpu_acpi_free_pstate_data(handle); - if (turbo_info) { - if (turbo_info->turbo_ksp != NULL) - kstat_delete(turbo_info->turbo_ksp); - kmem_free(turbo_info, sizeof (cpupm_turbo_info_t)); - } + if (mach_state->ms_turbo != NULL) + cpupm_turbo_fini(mach_state->ms_turbo); + mach_state->ms_turbo = NULL; } boolean_t @@ -470,7 +290,7 @@ speedstep_supported(uint_t family, uint_t model) } boolean_t -turbo_supported(void) +speedstep_turbo_supported(void) { struct cpuid_regs cpu_regs; diff --git a/usr/src/uts/i86pc/os/cpupm/turbo.c b/usr/src/uts/i86pc/os/cpupm/turbo.c new file mode 100644 index 0000000000..7844ce2247 --- /dev/null +++ b/usr/src/uts/i86pc/os/cpupm/turbo.c @@ -0,0 +1,208 @@ +/* + * CDDL HEADER START + * + * The contents of this file are subject to the terms of the + * Common Development and Distribution License (the "License"). + * You may not use this file except in compliance with the License. + * + * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE + * or http://www.opensolaris.org/os/licensing. + * See the License for the specific language governing permissions + * and limitations under the License. + * + * When distributing Covered Code, include this CDDL HEADER in each + * file and include the License file at usr/src/OPENSOLARIS.LICENSE. + * If applicable, add the following below this CDDL HEADER, with the + * fields enclosed by brackets "[]" replaced with your own identifying + * information: Portions Copyright [yyyy] [name of copyright owner] + * + * CDDL HEADER END + */ +/* + * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + */ +/* + * Copyright (c) 2009, Intel Corporation. + * All Rights Reserved. + */ + +#include <sys/x86_archext.h> +#include <sys/machsystm.h> +#include <sys/archsystm.h> +#include <sys/x_call.h> +#include <sys/acpi/acpi.h> +#include <sys/acpica.h> +#include <sys/speedstep.h> +#include <sys/cpu_acpi.h> +#include <sys/cpupm.h> +#include <sys/dtrace.h> +#include <sys/sdt.h> + +typedef struct turbo_kstat_s { + struct kstat_named turbo_supported; /* turbo flag */ + struct kstat_named t_mcnt; /* IA32_MPERF_MSR */ + struct kstat_named t_acnt; /* IA32_APERF_MSR */ +} turbo_kstat_t; + +static int turbo_kstat_update(kstat_t *, int); +static void get_turbo_info(cpupm_mach_turbo_info_t *); +static void reset_turbo_info(void); +static void record_turbo_info(cpupm_mach_turbo_info_t *, uint32_t, uint32_t); +static void update_turbo_info(cpupm_mach_turbo_info_t *); + +static kmutex_t turbo_mutex; + +turbo_kstat_t turbo_kstat = { + { "turbo_supported", KSTAT_DATA_UINT32 }, + { "turbo_mcnt", KSTAT_DATA_UINT64 }, + { "turbo_acnt", KSTAT_DATA_UINT64 }, +}; + +#define CPU_ACPI_P0 0 +#define CPU_IN_TURBO 1 + +/* + * MSR for hardware coordination feedback mechanism + * - IA32_MPERF: increments in proportion to a fixed frequency + * - IA32_APERF: increments in proportion to actual performance + */ +#define IA32_MPERF_MSR 0xE7 +#define IA32_APERF_MSR 0xE8 + +/* + * kstat update function of the turbo mode info + */ +static int +turbo_kstat_update(kstat_t *ksp, int flag) +{ + cpupm_mach_turbo_info_t *turbo_info = ksp->ks_private; + + if (flag == KSTAT_WRITE) { + return (EACCES); + } + + /* + * update the count in case CPU is in the turbo + * mode for a long time + */ + if (turbo_info->in_turbo == CPU_IN_TURBO) + update_turbo_info(turbo_info); + + turbo_kstat.turbo_supported.value.ui32 = + turbo_info->turbo_supported; + turbo_kstat.t_mcnt.value.ui64 = turbo_info->t_mcnt; + turbo_kstat.t_acnt.value.ui64 = turbo_info->t_acnt; + + return (0); +} + +/* + * update the sum of counts and clear MSRs + */ +static void +update_turbo_info(cpupm_mach_turbo_info_t *turbo_info) +{ + ulong_t iflag; + uint64_t mcnt, acnt; + + iflag = intr_clear(); + mcnt = rdmsr(IA32_MPERF_MSR); + acnt = rdmsr(IA32_APERF_MSR); + wrmsr(IA32_MPERF_MSR, 0); + wrmsr(IA32_APERF_MSR, 0); + turbo_info->t_mcnt += mcnt; + turbo_info->t_acnt += acnt; + intr_restore(iflag); +} + +/* + * Get count of MPERF/APERF MSR + */ +static void +get_turbo_info(cpupm_mach_turbo_info_t *turbo_info) +{ + ulong_t iflag; + uint64_t mcnt, acnt; + + iflag = intr_clear(); + mcnt = rdmsr(IA32_MPERF_MSR); + acnt = rdmsr(IA32_APERF_MSR); + turbo_info->t_mcnt += mcnt; + turbo_info->t_acnt += acnt; + intr_restore(iflag); +} + +/* + * Clear MPERF/APERF MSR + */ +static void +reset_turbo_info(void) +{ + ulong_t iflag; + + iflag = intr_clear(); + wrmsr(IA32_MPERF_MSR, 0); + wrmsr(IA32_APERF_MSR, 0); + intr_restore(iflag); +} + +/* + * sum up the count of one CPU_ACPI_P0 transition + */ +void +cpupm_record_turbo_info(cpupm_mach_turbo_info_t *turbo_info, + uint32_t cur_state, uint32_t req_state) +{ + if (!turbo_info->turbo_supported) + return; + /* + * enter P0 state + */ + if (req_state == CPU_ACPI_P0) { + reset_turbo_info(); + turbo_info->in_turbo = CPU_IN_TURBO; + } + /* + * Leave P0 state + */ + else if (cur_state == CPU_ACPI_P0) { + turbo_info->in_turbo = 0; + get_turbo_info(turbo_info); + } +} + +cpupm_mach_turbo_info_t * +cpupm_turbo_init(cpu_t *cp) +{ + cpupm_mach_turbo_info_t *turbo_info; + + turbo_info = kmem_zalloc(sizeof (cpupm_mach_turbo_info_t), KM_SLEEP); + + turbo_info->turbo_supported = 1; + turbo_info->turbo_ksp = kstat_create("turbo", cp->cpu_id, + "turbo", "misc", KSTAT_TYPE_NAMED, + sizeof (turbo_kstat) / sizeof (kstat_named_t), + KSTAT_FLAG_VIRTUAL); + + if (turbo_info->turbo_ksp == NULL) { + cmn_err(CE_NOTE, "kstat_create(turbo) fail"); + } else { + turbo_info->turbo_ksp->ks_data = &turbo_kstat; + turbo_info->turbo_ksp->ks_lock = &turbo_mutex; + turbo_info->turbo_ksp->ks_update = turbo_kstat_update; + turbo_info->turbo_ksp->ks_data_size += MAXNAMELEN; + turbo_info->turbo_ksp->ks_private = turbo_info; + + kstat_install(turbo_info->turbo_ksp); + } + + return (turbo_info); +} + +void +cpupm_turbo_fini(cpupm_mach_turbo_info_t *turbo_info) +{ + if (turbo_info->turbo_ksp != NULL) + kstat_delete(turbo_info->turbo_ksp); + kmem_free(turbo_info, sizeof (cpupm_mach_turbo_info_t)); +} diff --git a/usr/src/uts/i86pc/os/microcode.c b/usr/src/uts/i86pc/os/microcode.c index 90d9585640..c5c6a16790 100644 --- a/usr/src/uts/i86pc/os/microcode.c +++ b/usr/src/uts/i86pc/os/microcode.c @@ -33,6 +33,7 @@ #include <sys/kobj.h> #include <sys/kobj_impl.h> #include <sys/machsystm.h> +#include <sys/ontrap.h> #include <sys/param.h> #include <sys/machparam.h> #include <sys/promif.h> @@ -646,16 +647,17 @@ ucode_match_amd(uint16_t eq_sig, cpu_ucode_info_t *uinfop, if (ucodefp == NULL || size < sizeof (ucode_header_amd_t)) return (EM_NOMATCH); + uh = &ucodefp->uf_header; + /* * Don't even think about loading patches that would require code - * execution. + * execution. Does not apply to patches for family 0x14 and beyond. */ - if (size > offsetof(ucode_file_amd_t, uf_code_present) && + if (uh->uh_cpu_rev < 0x5000 && + size > offsetof(ucode_file_amd_t, uf_code_present) && ucodefp->uf_code_present) return (EM_NOMATCH); - uh = &ucodefp->uf_header; - if (eq_sig != uh->uh_cpu_rev) return (EM_NOMATCH); @@ -671,7 +673,7 @@ ucode_match_amd(uint16_t eq_sig, cpu_ucode_info_t *uinfop, return (EM_NOMATCH); } - if (uh->uh_patch_id <= uinfop->cui_rev) + if (uh->uh_patch_id <= uinfop->cui_rev && !ucode_force_update) return (EM_HIGHERREV); return (EM_OK); @@ -726,6 +728,9 @@ ucode_write(xc_arg_t arg1, xc_arg_t unused2, xc_arg_t unused3) { ucode_update_t *uusp = (ucode_update_t *)arg1; cpu_ucode_info_t *uinfop = CPU->cpu_m.mcpu_ucode_info; +#ifndef __xpv + on_trap_data_t otd; +#endif ASSERT(ucode); ASSERT(uusp->ucodep); @@ -743,7 +748,10 @@ ucode_write(xc_arg_t arg1, xc_arg_t unused2, xc_arg_t unused3) return (0); } - wrmsr(ucode->write_msr, (uintptr_t)uusp->ucodep); + if (!on_trap(&otd, OT_DATA_ACCESS)) + wrmsr(ucode->write_msr, (uintptr_t)uusp->ucodep); + + no_trap(); #endif ucode->read_rev(uinfop); uusp->new_rev = uinfop->cui_rev; @@ -758,6 +766,8 @@ ucode_load_amd(ucode_file_t *ufp, cpu_ucode_info_t *uinfop, cpu_t *cp) ucode_file_amd_t *ucodefp = ufp->amd; #ifdef __xpv ucode_update_t uus; +#else + on_trap_data_t otd; #endif ASSERT(ucode); @@ -765,7 +775,13 @@ ucode_load_amd(ucode_file_t *ufp, cpu_ucode_info_t *uinfop, cpu_t *cp) #ifndef __xpv kpreempt_disable(); + if (on_trap(&otd, OT_DATA_ACCESS)) { + no_trap(); + kpreempt_enable(); + return (0); + } wrmsr(ucode->write_msr, (uintptr_t)ucodefp); + no_trap(); ucode->read_rev(uinfop); kpreempt_enable(); @@ -1093,7 +1109,8 @@ ucode_update(uint8_t *ucodep, int size) kpreempt_enable(); CPUSET_DEL(cpuset, id); - if (uusp->new_rev != 0 && uusp->info.cui_rev == uusp->new_rev) { + if (uusp->new_rev != 0 && uusp->info.cui_rev == uusp->new_rev && + !ucode_force_update) { rc = EM_HIGHERREV; } else if ((uusp->new_rev == 0) || (uusp->expected_rev != 0 && uusp->expected_rev != uusp->new_rev)) { diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c index 63b858f978..dc79a04af2 100644 --- a/usr/src/uts/i86pc/os/mlsetup.c +++ b/usr/src/uts/i86pc/os/mlsetup.c @@ -19,6 +19,8 @@ * CDDL HEADER END */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright (c) 1993, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011 by Delphix. All rights reserved. */ @@ -110,7 +112,6 @@ mlsetup(struct regs *rp) extern disp_t cpu0_disp; extern char t0stack[]; extern int post_fastreboot; - extern int console; extern uint64_t plat_dr_options; ASSERT_STACK_ALIGNED(); @@ -348,7 +349,7 @@ mlsetup(struct regs *rp) * Explicitly set console to text mode (0x3) if this is a boot * post Fast Reboot, and the console is set to CONS_SCREEN_TEXT. */ - if (post_fastreboot && console == CONS_SCREEN_TEXT) + if (post_fastreboot && boot_console_type(NULL) == CONS_SCREEN_TEXT) set_console_mode(0x3); /* diff --git a/usr/src/uts/i86pc/os/mp_machdep.c b/usr/src/uts/i86pc/os/mp_machdep.c index d7aab080a6..7062df90ff 100644 --- a/usr/src/uts/i86pc/os/mp_machdep.c +++ b/usr/src/uts/i86pc/os/mp_machdep.c @@ -245,6 +245,11 @@ pg_plat_hw_shared(cpu_t *cp, pghw_type_t hw) } else { return (0); } + case PGHW_FPU: + if (cpuid_get_cores_per_compunit(cp) > 1) + return (1); + else + return (0); case PGHW_PROCNODE: if (cpuid_get_procnodes_per_pkg(cp) > 1) return (1); @@ -306,6 +311,8 @@ pg_plat_hw_instance_id(cpu_t *cpu, pghw_type_t hw) return (cpuid_get_coreid(cpu)); case PGHW_CACHE: return (cpuid_get_last_lvl_cacheid(cpu)); + case PGHW_FPU: + return (cpuid_get_compunitid(cpu)); case PGHW_PROCNODE: return (cpuid_get_procnodeid(cpu)); case PGHW_CHIP: @@ -331,6 +338,7 @@ pg_plat_hw_rank(pghw_type_t hw1, pghw_type_t hw2) static pghw_type_t hw_hier[] = { PGHW_IPIPE, PGHW_CACHE, + PGHW_FPU, PGHW_PROCNODE, PGHW_CHIP, PGHW_POW_IDLE, @@ -361,8 +369,13 @@ pg_plat_cmt_policy(pghw_type_t hw) /* * For shared caches, also load balance across them to * maximize aggregate cache capacity + * + * On AMD family 0x15 CPUs, cores come in pairs called + * compute units, sharing the FPU and the I$ and L2 + * caches. Use balancing and cache affinity. */ switch (hw) { + case PGHW_FPU: case PGHW_CACHE: return (CMT_BALANCE|CMT_AFFINITY); default: diff --git a/usr/src/uts/i86pc/os/mp_startup.c b/usr/src/uts/i86pc/os/mp_startup.c index 843c5ae73a..588d38bb7a 100644 --- a/usr/src/uts/i86pc/os/mp_startup.c +++ b/usr/src/uts/i86pc/os/mp_startup.c @@ -649,6 +649,10 @@ int opteron_workaround_6323525; /* if non-zero -> at least one cpu has it */ int opteron_erratum_298; #endif +#if defined(OPTERON_ERRATUM_721) +int opteron_erratum_721; +#endif + static void workaround_warning(cpu_t *cp, uint_t erratum) { @@ -1177,6 +1181,16 @@ workaround_errata(struct cpu *cpu) missing += do_erratum_298(cpu); + if (cpuid_opteron_erratum(cpu, 721) > 0) { +#if defined(OPTERON_ERRATUM_721) + wrmsr(MSR_AMD_DE_CFG, rdmsr(MSR_AMD_DE_CFG) | AMD_DE_CFG_E721); + opteron_erratum_721++; +#else + workaround_warning(cpu, 721); + missing++; +#endif + } + #ifdef __xpv return (0); #else @@ -1267,6 +1281,10 @@ workaround_errata_end() " system\noperation may occur.\n"); } #endif +#if defined(OPTERON_ERRATUM_721) + if (opteron_erratum_721) + workaround_applied(721); +#endif } /* diff --git a/usr/src/uts/i86pc/sys/boot_console.h b/usr/src/uts/i86pc/sys/boot_console.h index 912e2010d9..b2fcf98f97 100644 --- a/usr/src/uts/i86pc/sys/boot_console.h +++ b/usr/src/uts/i86pc/sys/boot_console.h @@ -19,6 +19,8 @@ * CDDL HEADER END */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ @@ -36,8 +38,8 @@ extern "C" { #define CONS_INVALID -1 #define CONS_SCREEN_TEXT 0 -#define CONS_TTYA 1 -#define CONS_TTYB 2 +#define CONS_TTY 1 +#define CONS_XXX 2 /* Unused */ #define CONS_USBSER 3 #define CONS_HYPERVISOR 4 #define CONS_SCREEN_GRAPHICS 5 @@ -51,6 +53,8 @@ extern void kb_init(void); extern int kb_getchar(void); extern int kb_ischar(void); +extern int boot_console_type(int *); + extern void bcons_init(char *); extern void bcons_putchar(int); extern int bcons_getchar(void); @@ -63,8 +67,6 @@ extern boolean_t bcons_hypervisor_redirect(void); extern void bcons_device_change(int); #endif /* !_BOOT */ -extern int console; - #ifdef __cplusplus } #endif diff --git a/usr/src/uts/i86pc/sys/cpupm_mach.h b/usr/src/uts/i86pc/sys/cpupm_mach.h index 0d1304b112..279c00e0c9 100644 --- a/usr/src/uts/i86pc/sys/cpupm_mach.h +++ b/usr/src/uts/i86pc/sys/cpupm_mach.h @@ -107,6 +107,14 @@ typedef struct cpupm_mach_acpi_state { cma_state_t cma_state; } cpupm_mach_acpi_state_t; +typedef struct cpupm_mach_turbo_info { + kstat_t *turbo_ksp; /* turbo kstat */ + int in_turbo; /* in turbo? */ + int turbo_supported; /* turbo flag */ + uint64_t t_mcnt; /* turbo mcnt */ + uint64_t t_acnt; /* turbo acnt */ +} cpupm_mach_turbo_info_t; + typedef struct cpupm_mach_state { void *ms_acpi_handle; cpupm_mach_acpi_state_t ms_pstate; @@ -115,7 +123,7 @@ typedef struct cpupm_mach_state { uint32_t ms_caps; dev_info_t *ms_dip; kmutex_t ms_lock; - void *ms_vendor; + cpupm_mach_turbo_info_t *ms_turbo; struct cpupm_notification *ms_handlers; } cpupm_mach_state_t; @@ -191,6 +199,10 @@ extern void cpupm_add_notify_handler(cpu_t *, CPUPM_NOTIFY_HANDLER, void *); extern int cpupm_get_top_speed(cpu_t *); extern void cpupm_idle_cstate_data(cma_c_state_t *, int); extern void cpupm_wakeup_cstate_data(cma_c_state_t *, hrtime_t); +extern void cpupm_record_turbo_info(cpupm_mach_turbo_info_t *, uint32_t, + uint32_t); +extern cpupm_mach_turbo_info_t *cpupm_turbo_init(cpu_t *); +extern void cpupm_turbo_fini(cpupm_mach_turbo_info_t *); #ifdef __cplusplus } diff --git a/usr/src/uts/i86xpv/os/xpv_panic.c b/usr/src/uts/i86xpv/os/xpv_panic.c index 132b9fb724..336fa406c3 100644 --- a/usr/src/uts/i86xpv/os/xpv_panic.c +++ b/usr/src/uts/i86xpv/os/xpv_panic.c @@ -19,6 +19,8 @@ * CDDL HEADER END */ /* + * Copyright (c) 2012 Gary Mills + * * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. */ @@ -121,7 +123,7 @@ xpv_panic_putc(int m) struct cons_polledio *c = cons_polledio; /* This really shouldn't happen */ - if (console == CONS_HYPERVISOR) + if (boot_console_type(NULL) == CONS_HYPERVISOR) return; if (use_polledio == B_TRUE) @@ -700,7 +702,7 @@ xpv_do_panic(void *arg) * to stop. */ use_polledio = B_FALSE; - if (console == CONS_HYPERVISOR) { + if (boot_console_type(NULL) == CONS_HYPERVISOR) { bcons_device_change(CONS_HYPERVISOR); } else if (cons_polledio != NULL && cons_polledio->cons_polledio_putchar != NULL) { diff --git a/usr/src/uts/intel/os/bootenv.rc b/usr/src/uts/intel/os/bootenv.rc index 752e13b15a..8ad92c694d 100644 --- a/usr/src/uts/intel/os/bootenv.rc +++ b/usr/src/uts/intel/os/bootenv.rc @@ -21,17 +21,21 @@ # # CDDL HEADER END # -#pragma ident "%Z%%M% %I% %E% SMI" -# # bootenv.rc -- boot "environment variables" # setprop keyboard-layout Unknown setprop ata-dma-enabled 1 setprop atapi-cd-dma-enabled 1 +setprop ttyd-rts-dtr-off false +setprop ttyd-ignore-cd true +setprop ttyc-rts-dtr-off false +setprop ttyc-ignore-cd true setprop ttyb-rts-dtr-off false setprop ttyb-ignore-cd true setprop ttya-rts-dtr-off false setprop ttya-ignore-cd true +setprop ttyd-mode 9600,8,n,1,- +setprop ttyc-mode 9600,8,n,1,- setprop ttyb-mode 9600,8,n,1,- setprop ttya-mode 9600,8,n,1,- setprop lba-access-ok 1 diff --git a/usr/src/uts/intel/sys/controlregs.h b/usr/src/uts/intel/sys/controlregs.h index aa9ab14a89..d84bba7d3a 100644 --- a/usr/src/uts/intel/sys/controlregs.h +++ b/usr/src/uts/intel/sys/controlregs.h @@ -209,6 +209,10 @@ extern "C" { #define AMD_BU_CFG_E298 (UINT64_C(1) << 1) +#define MSR_AMD_DE_CFG 0xc0011029 + +#define AMD_DE_CFG_E721 (UINT64_C(1)) + /* AMD's osvw MSRs */ #define MSR_AMD_OSVW_ID_LEN 0xc0010140 #define MSR_AMD_OSVW_STATUS 0xc0010141 diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h index 1a278c2a0f..29aa445a33 100644 --- a/usr/src/uts/intel/sys/x86_archext.h +++ b/usr/src/uts/intel/sys/x86_archext.h @@ -381,6 +381,7 @@ extern "C" { #define X86FSET_AVX 34 #define X86FSET_VMX 35 #define X86FSET_SVM 36 +#define X86FSET_TOPOEXT 37 /* * flags to patch tsc_read routine. @@ -604,7 +605,7 @@ extern "C" { #if defined(_KERNEL) || defined(_KMEMUSER) -#define NUM_X86_FEATURES 37 +#define NUM_X86_FEATURES 38 extern uchar_t x86_featureset[]; extern void free_x86_featureset(void *featureset); @@ -689,6 +690,8 @@ extern int cpuid_get_cacheid(struct cpu *); extern uint32_t cpuid_get_apicid(struct cpu *); extern uint_t cpuid_get_procnodeid(struct cpu *cpu); extern uint_t cpuid_get_procnodes_per_pkg(struct cpu *cpu); +extern uint_t cpuid_get_compunitid(struct cpu *cpu); +extern uint_t cpuid_get_cores_per_compunit(struct cpu *cpu); extern int cpuid_is_cmt(struct cpu *); extern int cpuid_syscall32_insn(struct cpu *); extern int getl2cacheinfo(struct cpu *, int *, int *, int *); diff --git a/usr/src/uts/sfmmu/vm/hat_sfmmu.c b/usr/src/uts/sfmmu/vm/hat_sfmmu.c index ded9e793e3..a50a2db579 100644 --- a/usr/src/uts/sfmmu/vm/hat_sfmmu.c +++ b/usr/src/uts/sfmmu/vm/hat_sfmmu.c @@ -5032,7 +5032,7 @@ sfmmu_hblk_chgattr(struct hat *sfmmup, struct hme_blk *hmeblkp, caddr_t addr, use_demap_range = (TTEBYTES(ttesz) == DEMAP_RANGE_PGSZ(dmrp)); if (use_demap_range) { DEMAP_RANGE_CONTINUE(dmrp, addr, endaddr); - } else { + } else if (dmrp != NULL) { DEMAP_RANGE_FLUSH(dmrp); } @@ -5389,7 +5389,7 @@ sfmmu_hblk_chgprot(sfmmu_t *sfmmup, struct hme_blk *hmeblkp, caddr_t addr, use_demap_range = (TTEBYTES(ttesz) == MMU_PAGESIZE); if (use_demap_range) { DEMAP_RANGE_CONTINUE(dmrp, addr, endaddr); - } else { + } else if (dmrp != NULL) { DEMAP_RANGE_FLUSH(dmrp); } @@ -5741,12 +5741,13 @@ hat_unload_callback( * If the process is exiting, we can save a lot of fuss since * we'll flush the TLB when we free the ctx anyway. */ - if (sfmmup->sfmmu_free) + if (sfmmup->sfmmu_free) { dmrp = NULL; - else + } else { dmrp = &dmr; + DEMAP_RANGE_INIT(sfmmup, dmrp); + } - DEMAP_RANGE_INIT(sfmmup, dmrp); endaddr = addr + len; hblktag.htag_id = sfmmup; hblktag.htag_rid = SFMMU_INVALID_SHMERID; @@ -5919,8 +5920,8 @@ hat_unload_callback( * to minimize the number of xt_sync()s that need to occur. */ if (callback != NULL && addr_count == MAX_CB_ADDR) { - DEMAP_RANGE_FLUSH(dmrp); if (dmrp != NULL) { + DEMAP_RANGE_FLUSH(dmrp); cpuset = sfmmup->sfmmu_cpusran; xt_sync(cpuset); } @@ -5960,8 +5961,8 @@ hat_unload_callback( } sfmmu_hblks_list_purge(&list, 0); - DEMAP_RANGE_FLUSH(dmrp); if (dmrp != NULL) { + DEMAP_RANGE_FLUSH(dmrp); cpuset = sfmmup->sfmmu_cpusran; xt_sync(cpuset); } @@ -6054,7 +6055,7 @@ sfmmu_hblk_unload(struct hat *sfmmup, struct hme_blk *hmeblkp, caddr_t addr, if (use_demap_range) { DEMAP_RANGE_CONTINUE(dmrp, addr, endaddr); - } else { + } else if (dmrp != NULL) { DEMAP_RANGE_FLUSH(dmrp); } ttecnt = 0; diff --git a/usr/src/uts/sfmmu/vm/hat_sfmmu.h b/usr/src/uts/sfmmu/vm/hat_sfmmu.h index 337a93704d..8bdc3e39b2 100644 --- a/usr/src/uts/sfmmu/vm/hat_sfmmu.h +++ b/usr/src/uts/sfmmu/vm/hat_sfmmu.h @@ -1673,12 +1673,10 @@ typedef struct { #define DMR_MAXBIT ((ulong_t)1<<63) /* dmr_bit high bit */ #define DEMAP_RANGE_INIT(sfmmup, dmrp) \ - if ((dmrp) != NULL) { \ (dmrp)->dmr_sfmmup = (sfmmup); \ (dmrp)->dmr_bitvec = 0; \ (dmrp)->dmr_maxbit = sfmmu_dmr_maxbit; \ - (dmrp)->dmr_pgsz = MMU_PAGESIZE; \ - } + (dmrp)->dmr_pgsz = MMU_PAGESIZE; #define DEMAP_RANGE_PGSZ(dmrp) ((dmrp)? (dmrp)->dmr_pgsz : MMU_PAGESIZE) @@ -1690,10 +1688,9 @@ typedef struct { } #define DEMAP_RANGE_FLUSH(dmrp) \ - if ((dmrp) != NULL) { \ - if ((dmrp)->dmr_bitvec != 0) \ - sfmmu_tlb_range_demap(dmrp); \ - } + if ((dmrp)->dmr_bitvec != 0) \ + sfmmu_tlb_range_demap(dmrp); + #define DEMAP_RANGE_MARKPG(dmrp, addr) \ if ((dmrp) != NULL) { \ diff --git a/usr/src/uts/sun4u/lw8/io/sgenv.c b/usr/src/uts/sun4u/lw8/io/sgenv.c index b44d118def..7b5971bf57 100644 --- a/usr/src/uts/sun4u/lw8/io/sgenv.c +++ b/usr/src/uts/sun4u/lw8/io/sgenv.c @@ -1708,8 +1708,6 @@ sgenv_get_board_info_data(void) DCMN_ERR_EVENT(CE_NOTE, "%s: entered.", f); - ASSERT(board_cache != NULL); - if (first_time) { sgenv_set_valid_node_positions(node_present); first_time = FALSE; diff --git a/usr/src/uts/sun4u/starfire/sys/idn.h b/usr/src/uts/sun4u/starfire/sys/idn.h index a117529afb..14034c0fe4 100644 --- a/usr/src/uts/sun4u/starfire/sys/idn.h +++ b/usr/src/uts/sun4u/starfire/sys/idn.h @@ -3429,10 +3429,10 @@ struct idn_gkstat_named { (x)[2] = (uint_t)(a2), (x)[3] = (uint_t)(a3)) #define GET_XARGS(x, a0, a1, a2, a3) \ - (((a0) ? *(uint_t *)(a0) = (x)[0] : 1), \ - ((a1) ? *(uint_t *)(a1) = (x)[1] : 1), \ - ((a2) ? *(uint_t *)(a2) = (x)[2] : 1), \ - ((a3) ? *(uint_t *)(a3) = (x)[3] : 1)) + ((*(uint_t *)(a0) = (x)[0]), \ + (*(uint_t *)(a1) = (x)[1]), \ + (*(uint_t *)(a2) = (x)[2]), \ + (*(uint_t *)(a3) = (x)[3])) #define CLR_XARGS(x) \ ((x)[0] = (x)[1] = (x)[2] = (x)[3] = 0) diff --git a/usr/src/uts/sun4u/sys/pci/pcisch.h b/usr/src/uts/sun4u/sys/pci/pcisch.h index 2bb9b7db0c..061d770ad9 100644 --- a/usr/src/uts/sun4u/sys/pci/pcisch.h +++ b/usr/src/uts/sun4u/sys/pci/pcisch.h @@ -26,8 +26,6 @@ #ifndef _SYS_PCISCH_H #define _SYS_PCISCH_H -#pragma ident "%Z%%M% %I% %E% SMI" - #ifdef __cplusplus extern "C" { #endif @@ -504,13 +502,13 @@ typedef struct pcix_err_tbl { */ #define TLBTAG_CONTEXT_SHIFT 25 #define TLBTAG_ERRSTAT_SHIFT 23 -#define TLBTAG_CONTEXT_BITS (0xfffull << TLBTAG_CONTEXT_SHIFT) -#define TLBTAG_ERRSTAT_BITS (0x3ull << TLBTAG_ERRSTAT_SHIFT) -#define TLBTAG_ERR_BIT (0x1ull << 22) -#define TLBTAG_WRITABLE_BIT (0x1ull << 21) -#define TLBTAG_STREAM_BIT (0x1ull << 20) -#define TLBTAG_PGSIZE_BIT (0x1ull << 19) -#define TLBTAG_PCIVPN_BITS 0x7ffffull +#define TLBTAG_CONTEXT_BITS (0xffful << TLBTAG_CONTEXT_SHIFT) +#define TLBTAG_ERRSTAT_BITS (0x3ul << TLBTAG_ERRSTAT_SHIFT) +#define TLBTAG_ERR_BIT (0x1ul << 22) +#define TLBTAG_WRITABLE_BIT (0x1ul << 21) +#define TLBTAG_STREAM_BIT (0x1ul << 20) +#define TLBTAG_PGSIZE_BIT (0x1ul << 19) +#define TLBTAG_PCIVPN_BITS 0x7fffful #define TLBTAG_ERRSTAT_PROT 0 #define TLBTAG_ERRSTAT_INVALID 1 |