From db6096698656d32db7df630594bd9617ee54f828 Mon Sep 17 00:00:00 2001 From: Apple Date: Tue, 9 Apr 2013 23:11:37 +0000 Subject: [PATCH] xnu-2050.22.13.tar.gz --- bsd/conf/MASTER | 1 - bsd/conf/MASTER.x86_64 | 4 +- bsd/conf/files | 2 - bsd/dev/i386/sysctl.c | 2 +- bsd/hfs/hfs_catalog.c | 10 +- bsd/hfs/hfs_catalog.h | 3 +- bsd/hfs/hfs_cnode.c | 11 +- bsd/hfs/hfs_link.c | 4 +- bsd/hfs/hfs_vfsops.c | 12 +- bsd/hfs/hfs_vfsutils.c | 6 +- bsd/hfs/hfs_vnops.c | 108 +- bsd/kern/kern_descrip.c | 5 +- bsd/kern/kern_panicinfo.c | 209 -- bsd/kern/kern_symfile.c | 33 +- bsd/kern/trace.codes | 5 + bsd/miscfs/specfs/spec_vnops.c | 24 +- bsd/net/dlil.c | 4 +- bsd/netinet6/nd6.c | 8 +- bsd/netinet6/nd6_nbr.c | 20 +- bsd/sys/kdebug.h | 5 +- bsd/sys/sysctl.h | 6 +- bsd/vfs/vfs_fsevents.c | 146 +- bsd/vfs/vfs_subr.c | 5 + bsd/vfs/vfs_syscalls.c | 9 + config/MasterVersion | 2 +- iokit/IOKit/IOHibernatePrivate.h | 30 +- iokit/IOKit/IOService.h | 4 +- iokit/IOKit/pwr_mgt/IOPM.h | 3 + iokit/IOKit/pwr_mgt/IOPMLibDefs.h | 4 +- iokit/IOKit/pwr_mgt/IOPMPrivate.h | 24 +- iokit/IOKit/pwr_mgt/RootDomain.h | 9 +- iokit/Kernel/IOHibernateIO.cpp | 120 +- iokit/Kernel/IOHibernateInternal.h | 3 + iokit/Kernel/IOPMrootDomain.cpp | 186 +- iokit/Kernel/IOServicePM.cpp | 336 ++- iokit/Kernel/IOServicePMPrivate.h | 18 +- iokit/Kernel/RootDomainUserClient.cpp | 38 +- iokit/Kernel/RootDomainUserClient.h | 2 + libkern/c++/OSKext.cpp | 25 +- osfmk/conf/files.x86_64 | 1 - osfmk/console/panic_dialog.c | 970 ------- osfmk/console/panic_image.c | 2702 ------------------ osfmk/console/rendered_numbers.c | 376 --- osfmk/console/video_console.c | 6 - osfmk/default_pager/default_pager_internal.h | 2 + osfmk/i386/AT386/model_dep.c | 6 - osfmk/i386/Diagnostics.c | 16 +- osfmk/i386/Diagnostics.h | 1 - osfmk/i386/cpuid.c | 2 +- osfmk/i386/hibernate_i386.c | 43 +- osfmk/i386/misc_protos.h | 1 - osfmk/i386/task.h | 6 +- osfmk/i386/trap.c | 13 +- osfmk/kern/hibernate.c | 25 +- osfmk/kern/task.c | 2 + osfmk/mach/task_info.h | 2 +- osfmk/vm/vm_page.h | 4 +- osfmk/vm/vm_resident.c | 182 +- pexpert/conf/MASTER | 2 - pexpert/conf/MASTER.x86_64 | 4 +- pexpert/conf/files | 1 - pexpert/i386/pe_init.c | 5 - pexpert/pexpert/i386/protos.h | 4 - 63 files changed, 1094 insertions(+), 4728 deletions(-) delete mode 100644 bsd/kern/kern_panicinfo.c delete mode 100644 osfmk/console/panic_dialog.c delete mode 100644 osfmk/console/panic_image.c delete mode 100644 osfmk/console/rendered_numbers.c diff --git a/bsd/conf/MASTER b/bsd/conf/MASTER index 2cbd0b9e8..17c0acc52 100644 --- a/bsd/conf/MASTER +++ b/bsd/conf/MASTER @@ -155,7 +155,6 @@ options SYSV_SEM # SVID semaphores # options SYSV_MSG # SVID messages # options SYSV_SHM # SVID shared mem # options PSYNCH # pthread synch # -options PANIC_INFO # want kernel panic info # options DEVELOPMENT # dev kernel # # secure_kernel - secure kernel from user programs diff --git a/bsd/conf/MASTER.x86_64 b/bsd/conf/MASTER.x86_64 index a1be0eb1f..64b17727c 100644 --- a/bsd/conf/MASTER.x86_64 +++ b/bsd/conf/MASTER.x86_64 @@ -44,7 +44,7 @@ # # Standard Apple Research Configurations: # -------- ----- -------- --------------- -# BASE = [ intel mach medium config_dtrace vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit panic_info config_imageboot config_workqueue psynch zleaks memorystatus vm_pressure_events ] +# BASE = [ intel mach medium config_dtrace vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit config_imageboot config_workqueue psynch zleaks memorystatus vm_pressure_events ] # FILESYS = [ devfs revfs hfs journaling fdesc config_fse quota namedstreams fifo config_volfs hfs_compression config_hfs_std config_hfs_alloc_rbtree config_hfs_trim config_imgsrc_access config_triggers config_ext_resolver config_searchfs ] # NETWORKING = [ inet inet6 compat_oldsock tcpdrop_synfin bpfilter ipdivert ipfirewall ipv6firewall ipfw2 dummynet traffic_mgt sendfile bond vlan gif stf zlib randomipid ifnet_input_chk config_mbuf_jumbo if_bridge PF ] # NFS = [ nfsclient nfsserver ] @@ -56,7 +56,7 @@ # PROFILE = [ RELEASE profile ] # DEBUG = [ BASE NETWORKING NFS VPN FILESYS libdriver_g debug xpr_debug mach_assert ] # -# EMBEDDED_BASE = [ intel mach bsmall vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit panic_info config_imageboot config_workqueue psynch ] +# EMBEDDED_BASE = [ intel mach bsmall vol pst gdb kernobjc fixpri simple_clock mdebug kernserv driverkit uxpr kernstack ipc_compat ipc_debug sysv_sem sysv_msg sysv_shm audit config_imageboot config_workqueue psynch ] # EMBEDDED_FILESYS = [ devfs hfs journaling fdesc fifo ] # EMBEDDED_NET = [ inet compat_oldsock tcpdrop_synfin bpfilter ] # EMBEDDED = [ EMBEDDED_BASE EMBEDDED_NET VPN EMBEDDED_FILESYS libdriver no_printf_str no_kprintf_str no_kdebug ] diff --git a/bsd/conf/files b/bsd/conf/files index dd8075219..118244ccc 100644 --- a/bsd/conf/files +++ b/bsd/conf/files @@ -69,7 +69,6 @@ OPTIONS/development optional development OPTIONS/sysv_sem optional sysv_sem OPTIONS/sysv_msg optional sysv_msg OPTIONS/sysv_shm optional sysv_shm -OPTIONS/panic_info optional panic_info OPTIONS/no_bsd_inlines optional no_bsd_inlines # @@ -529,7 +528,6 @@ bsd/kern/kern_lockf.c standard bsd/kern/kern_fork.c standard bsd/kern/kern_malloc.c standard bsd/kern/kern_mman.c standard -bsd/kern/kern_panicinfo.c optional panic_info bsd/kern/kern_physio.c standard bsd/kern/kern_priv.c standard bsd/kern/kern_proc.c standard diff --git a/bsd/dev/i386/sysctl.c b/bsd/dev/i386/sysctl.c index c2d7de7ff..ddc9503e3 100644 --- a/bsd/dev/i386/sysctl.c +++ b/bsd/dev/i386/sysctl.c @@ -477,7 +477,7 @@ SYSCTL_PROC(_machdep_cpu_thermal, OID_AUTO, package_thermal_intr, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, (void *)offsetof(cpuid_thermal_leaf_t, package_thermal_intr), sizeof(boolean_t), - cpu_thermal, "I", "Packge Thermal interrupt and Status"); + cpu_thermal, "I", "Package Thermal interrupt and Status"); SYSCTL_PROC(_machdep_cpu_thermal, OID_AUTO, hardware_feedback, CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_LOCKED, diff --git a/bsd/hfs/hfs_catalog.c b/bsd/hfs/hfs_catalog.c index bc2e5959e..0d310bc82 100644 --- a/bsd/hfs/hfs_catalog.c +++ b/bsd/hfs/hfs_catalog.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2011 Apple Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -481,7 +481,7 @@ exit: * catalog descriptor (when supplied outdescp is non-null). */ int -cat_idlookup(struct hfsmount *hfsmp, cnid_t cnid, int allow_system_files, +cat_idlookup(struct hfsmount *hfsmp, cnid_t cnid, int allow_system_files, int wantrsrc, struct cat_desc *outdescp, struct cat_attr *attrp, struct cat_fork *forkp) { struct BTreeIterator * iterator; @@ -542,7 +542,7 @@ cat_idlookup(struct hfsmount *hfsmp, cnid_t cnid, int allow_system_files, result = cat_lookupbykey(hfsmp, keyp, ((allow_system_files != 0) ? HFS_LOOKUP_SYSFILE : 0), - 0, 0, outdescp, attrp, forkp, NULL); + 0, wantrsrc, outdescp, attrp, forkp, NULL); /* No corresponding file/folder record found for a thread record, * mark the volume inconsistent. */ @@ -594,7 +594,7 @@ cat_lookupmangled(struct hfsmount *hfsmp, struct cat_desc *descp, int wantrsrc, return (ENOENT); } - result = cat_idlookup(hfsmp, fileID, 0, outdescp, attrp, forkp); + result = cat_idlookup(hfsmp, fileID, 0,0, outdescp, attrp, forkp); if (result) return (ENOENT); /* It must be in the correct directory */ @@ -1850,7 +1850,7 @@ cat_set_childlinkbit(struct hfsmount *hfsmp, cnid_t cnid) lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_EXCLUSIVE_LOCK); /* Look up our catalog folder record */ - retval = cat_idlookup(hfsmp, cnid, 0, &desc, &attr, NULL); + retval = cat_idlookup(hfsmp, cnid, 0, 0, &desc, &attr, NULL); if (retval) { hfs_systemfile_unlock(hfsmp, lockflags); hfs_end_transaction(hfsmp); diff --git a/bsd/hfs/hfs_catalog.h b/bsd/hfs/hfs_catalog.h index 13aa86513..022fddabb 100644 --- a/bsd/hfs/hfs_catalog.h +++ b/bsd/hfs/hfs_catalog.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2007 Apple Inc. All rights reserved. + * Copyright (c) 2002-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -296,6 +296,7 @@ extern int cat_lookup ( struct hfsmount *hfsmp, extern int cat_idlookup (struct hfsmount *hfsmp, cnid_t cnid, int allow_system_files, + int wantrsrc, struct cat_desc *outdescp, struct cat_attr *attrp, struct cat_fork *forkp); diff --git a/bsd/hfs/hfs_cnode.c b/bsd/hfs/hfs_cnode.c index 970f2648e..d50734286 100644 --- a/bsd/hfs/hfs_cnode.c +++ b/bsd/hfs/hfs_cnode.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2012 Apple Inc. All rights reserved. + * Copyright (c) 2002-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -999,6 +999,13 @@ hfs_getnewvnode( issystemfile = (descp->cd_flags & CD_ISMETA) && (vtype == VREG); wantrsrc = flags & GNV_WANTRSRC; + /* Sanity check the vtype and mode */ + if (vtype == VBAD) { + /* Mark the FS as corrupt and bail out */ + hfs_mark_volume_inconsistent(hfsmp); + return (EINVAL); + } + /* Zero out the out_flags */ *out_flags = 0; @@ -1543,7 +1550,7 @@ hfs_valid_cnode(struct hfsmount *hfsmp, struct vnode *dvp, struct componentname } } } else { - if (cat_idlookup(hfsmp, cnid, 0, NULL, NULL, NULL) == 0) { + if (cat_idlookup(hfsmp, cnid, 0, 0, NULL, NULL, NULL) == 0) { stillvalid = 1; *error = 0; } diff --git a/bsd/hfs/hfs_link.c b/bsd/hfs/hfs_link.c index b1b9359af..43b4a26e4 100644 --- a/bsd/hfs/hfs_link.c +++ b/bsd/hfs/hfs_link.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2010 Apple Inc. All rights reserved. + * Copyright (c) 1999-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -539,7 +539,7 @@ hfs_vnop_link(struct vnop_link_args *ap) struct cat_attr cattr; /* If inode is missing then we lost a race with unlink. */ - if ((cat_idlookup(hfsmp, cp->c_fileid, 0, NULL, &cattr, NULL) != 0) || + if ((cat_idlookup(hfsmp, cp->c_fileid, 0, 0, NULL, &cattr, NULL) != 0) || (cattr.ca_fileid != cp->c_fileid)) { error = ENOENT; goto out; diff --git a/bsd/hfs/hfs_vfsops.c b/bsd/hfs/hfs_vfsops.c index d08359180..a07a4c38b 100644 --- a/bsd/hfs/hfs_vfsops.c +++ b/bsd/hfs/hfs_vfsops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2012 Apple Inc. All rights reserved. + * Copyright (c) 1999-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -824,7 +824,7 @@ hfs_reload_callback(struct vnode *vp, void *cargs) /* lookup by fileID since name could have changed */ lockflags = hfs_systemfile_lock(args->hfsmp, SFL_CATALOG, HFS_SHARED_LOCK); - args->error = cat_idlookup(args->hfsmp, cp->c_fileid, 0, &desc, &cp->c_attr, datafork); + args->error = cat_idlookup(args->hfsmp, cp->c_fileid, 0, 0, &desc, &cp->c_attr, datafork); hfs_systemfile_unlock(args->hfsmp, lockflags); if (args->error) { return (VNODE_RETURNED_DONE); @@ -1005,7 +1005,7 @@ hfs_reload(struct mount *mountp) } /* Reload the volume name */ - if ((error = cat_idlookup(hfsmp, kHFSRootFolderID, 0, &cndesc, NULL, NULL))) + if ((error = cat_idlookup(hfsmp, kHFSRootFolderID, 0, 0, &cndesc, NULL, NULL))) return (error); vcb->volumeNameEncodingHint = cndesc.cd_encoding; bcopy(cndesc.cd_nameptr, vcb->vcbVN, min(255, cndesc.cd_namelen)); @@ -3279,7 +3279,7 @@ hfs_vget(struct hfsmount *hfsmp, cnid_t cnid, struct vnode **vpp, int skiplock, const char *nameptr; lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK); - error = cat_idlookup(hfsmp, cnid, 0, &cndesc, &cnattr, &cnfork); + error = cat_idlookup(hfsmp, cnid, 0, 0, &cndesc, &cnattr, &cnfork); hfs_systemfile_unlock(hfsmp, lockflags); if (error) { @@ -6272,7 +6272,7 @@ hfs_relocate_journal_file(struct hfsmount *hfsmp, u_int32_t jnl_size, int resize goto free_fail; } - error = cat_idlookup(hfsmp, hfsmp->hfs_jnlfileid, 1, &journal_desc, &journal_attr, &journal_fork); + error = cat_idlookup(hfsmp, hfsmp->hfs_jnlfileid, 1, 0, &journal_desc, &journal_attr, &journal_fork); if (error) { printf("hfs_relocate_journal_file: cat_idlookup returned %d\n", error); goto free_fail; @@ -6489,7 +6489,7 @@ hfs_reclaim_journal_info_block(struct hfsmount *hfsmp, u_int32_t allocLimit, vfs } /* Update the catalog record for .journal_info_block */ - error = cat_idlookup(hfsmp, hfsmp->hfs_jnlinfoblkid, 1, &jib_desc, &jib_attr, &jib_fork); + error = cat_idlookup(hfsmp, hfsmp->hfs_jnlinfoblkid, 1, 0, &jib_desc, &jib_attr, &jib_fork); if (error) { printf("hfs_reclaim_journal_info_block: cat_idlookup returned %d\n", error); goto fail; diff --git a/bsd/hfs/hfs_vfsutils.c b/bsd/hfs/hfs_vfsutils.c index 84a81a948..626c1e64c 100644 --- a/bsd/hfs/hfs_vfsutils.c +++ b/bsd/hfs/hfs_vfsutils.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2010 Apple Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -270,7 +270,7 @@ OSErr hfs_MountHFSVolume(struct hfsmount *hfsmp, HFSMasterDirectoryBlock *mdb, vcb->vcbAtrb &= ~kHFSVolumeUnmountedMask; if (error == noErr) { - error = cat_idlookup(hfsmp, kHFSRootFolderID, 0, NULL, NULL, NULL); + error = cat_idlookup(hfsmp, kHFSRootFolderID, 0, 0, NULL, NULL, NULL); if (HFS_MOUNT_DEBUG) { printf("hfs_mounthfs (std): error looking up root folder (%d) \n", error); } @@ -663,7 +663,7 @@ OSErr hfs_MountHFSPlusVolume(struct hfsmount *hfsmp, HFSPlusVolumeHeader *vhp, } /* Pick up volume name and create date */ - retval = cat_idlookup(hfsmp, kHFSRootFolderID, 0, &cndesc, &cnattr, NULL); + retval = cat_idlookup(hfsmp, kHFSRootFolderID, 0, 0, &cndesc, &cnattr, NULL); if (retval) { if (HFS_MOUNT_DEBUG) { printf("hfs_mounthfsplus: cat_idlookup returned (%d) getting rootfolder \n", retval); diff --git a/bsd/hfs/hfs_vnops.c b/bsd/hfs/hfs_vnops.c index f7725b383..1d0497a0f 100644 --- a/bsd/hfs/hfs_vnops.c +++ b/bsd/hfs/hfs_vnops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2012 Apple Inc. All rights reserved. + * Copyright (c) 2000-2013 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * @@ -1618,7 +1618,8 @@ hfs_vnop_exchange(ap) const unsigned char *to_nameptr; char from_iname[32]; char to_iname[32]; - u_int32_t tempflag; + uint32_t to_flag_special; + uint32_t from_flag_special; cnid_t from_parid; cnid_t to_parid; int lockflags; @@ -1711,9 +1712,8 @@ hfs_vnop_exchange(ap) to_cp = VTOC(to_vp); hfsmp = VTOHFS(from_vp); - /* Only normal files can be exchanged. */ - if (!vnode_isreg(from_vp) || !vnode_isreg(to_vp) || - VNODE_IS_RSRC(from_vp) || VNODE_IS_RSRC(to_vp)) { + /* Resource forks cannot be exchanged. */ + if (VNODE_IS_RSRC(from_vp) || VNODE_IS_RSRC(to_vp)) { error = EINVAL; goto exit; } @@ -1800,7 +1800,14 @@ hfs_vnop_exchange(ap) /* Save a copy of from attributes before swapping. */ bcopy(&from_cp->c_desc, &tempdesc, sizeof(struct cat_desc)); bcopy(&from_cp->c_attr, &tempattr, sizeof(struct cat_attr)); - tempflag = from_cp->c_flag & (C_HARDLINK | C_HASXATTRS); + + /* Save whether or not each cnode is a hardlink or has EAs */ + from_flag_special = from_cp->c_flag & (C_HARDLINK | C_HASXATTRS); + to_flag_special = to_cp->c_flag & (C_HARDLINK | C_HASXATTRS); + + /* Drop the special bits from each cnode */ + from_cp->c_flag &= ~(C_HARDLINK | C_HASXATTRS); + to_cp->c_flag &= ~(C_HARDLINK | C_HASXATTRS); /* * Swap the descriptors and all non-fork related attributes. @@ -1809,7 +1816,16 @@ hfs_vnop_exchange(ap) bcopy(&to_cp->c_desc, &from_cp->c_desc, sizeof(struct cat_desc)); from_cp->c_hint = 0; - from_cp->c_fileid = from_cp->c_cnid; + /* + * If 'to' was a hardlink, then we copied over its link ID/CNID/(namespace ID) + * when we bcopy'd the descriptor above. However, we need to be careful + * when setting up the fileID below, because we cannot assume that the + * file ID is the same as the CNID if either one was a hardlink. + * The file ID is stored in the c_attr as the ca_fileid. So it needs + * to be pulled explicitly; we cannot just use the CNID. + */ + from_cp->c_fileid = to_cp->c_attr.ca_fileid; + from_cp->c_itime = to_cp->c_itime; from_cp->c_btime = to_cp->c_btime; from_cp->c_atime = to_cp->c_atime; @@ -1819,13 +1835,42 @@ hfs_vnop_exchange(ap) from_cp->c_bsdflags = to_cp->c_bsdflags; from_cp->c_mode = to_cp->c_mode; from_cp->c_linkcount = to_cp->c_linkcount; - from_cp->c_flag = to_cp->c_flag & (C_HARDLINK | C_HASXATTRS); + from_cp->c_attr.ca_linkref = to_cp->c_attr.ca_linkref; + from_cp->c_attr.ca_firstlink = to_cp->c_attr.ca_firstlink; + + /* + * The cnode flags need to stay with the cnode and not get transferred + * over along with everything else because they describe the content; they are + * not attributes that reflect changes specific to the file ID. In general, + * fields that are tied to the file ID are the ones that will move. + * + * This reflects the fact that the file may have borrowed blocks, dirty metadata, + * or other extents, which may not yet have been written to the catalog. If + * they were, they would have been transferred above in the ExchangeFileIDs call above... + * + * The flags that are special are: + * C_HARDLINK, C_HASXATTRS + * + * These flags move with the item and file ID in the namespace since their + * state is tied to that of the file ID. + * + * So to transfer the flags, we have to take the following steps + * 1) Store in a localvar whether or not the special bits are set. + * 2) Drop the special bits from the current flags + * 3) swap the special flag bits to their destination + */ + from_cp->c_flag |= to_flag_special; + from_cp->c_attr.ca_recflags = to_cp->c_attr.ca_recflags; bcopy(to_cp->c_finderinfo, from_cp->c_finderinfo, 32); bcopy(&tempdesc, &to_cp->c_desc, sizeof(struct cat_desc)); to_cp->c_hint = 0; - to_cp->c_fileid = to_cp->c_cnid; + /* + * Pull the file ID from the tempattr we copied above. We can't assume + * it is the same as the CNID. + */ + to_cp->c_fileid = tempattr.ca_fileid; to_cp->c_itime = tempattr.ca_itime; to_cp->c_btime = tempattr.ca_btime; to_cp->c_atime = tempattr.ca_atime; @@ -1835,7 +1880,15 @@ hfs_vnop_exchange(ap) to_cp->c_bsdflags = tempattr.ca_flags; to_cp->c_mode = tempattr.ca_mode; to_cp->c_linkcount = tempattr.ca_linkcount; - to_cp->c_flag = tempflag; + to_cp->c_attr.ca_linkref = tempattr.ca_linkref; + to_cp->c_attr.ca_firstlink = tempattr.ca_firstlink; + + /* + * Only OR in the "from" flags into our cnode flags below. + * Leave the rest of the flags alone. + */ + to_cp->c_flag |= from_flag_special; + to_cp->c_attr.ca_recflags = tempattr.ca_recflags; bcopy(tempattr.ca_finderinfo, to_cp->c_finderinfo, 32); @@ -5551,14 +5604,43 @@ restart: lockflags = hfs_systemfile_lock(hfsmp, SFL_CATALOG, HFS_SHARED_LOCK); - /* Get resource fork data */ - error = cat_lookup(hfsmp, descptr, 1, (struct cat_desc *)0, - (struct cat_attr *)0, &rsrcfork, NULL); + /* + * Get resource fork data + * + * We call cat_idlookup (instead of cat_lookup) below because we can't + * trust the descriptor in the provided cnode for lookups at this point. + * Between the time of the original lookup of this vnode and now, the + * descriptor could have gotten swapped or replaced. If this occurred, + * the parent/name combo originally desired may not necessarily be provided + * if we use the descriptor. Even worse, if the vnode represents + * a hardlink, we could have removed one of the links from the namespace + * but left the descriptor alone, since hfs_unlink does not invalidate + * the descriptor in the cnode if other links still point to the inode. + * + * Consider the following (slightly contrived) scenario: + * /tmp/a <--> /tmp/b (hardlinks). + * 1. Thread A: open rsrc fork on /tmp/b. + * 1a. Thread A: does lookup, goes out to lunch right before calling getnamedstream. + * 2. Thread B does 'mv /foo/b /tmp/b' + * 2. Thread B succeeds. + * 3. Thread A comes back and wants rsrc fork info for /tmp/b. + * + * Even though the hardlink backing /tmp/b is now eliminated, the descriptor + * is not removed/updated during the unlink process. So, if you were to + * do a lookup on /tmp/b, you'd acquire an entirely different record's resource + * fork. + * + * As a result, we use the fileid, which should be invariant for the lifetime + * of the cnode (possibly barring calls to exchangedata). + */ + + error = cat_idlookup (hfsmp, cp->c_attr.ca_fileid, 0, 1, NULL, NULL, &rsrcfork); hfs_systemfile_unlock(hfsmp, lockflags); if (error) { return (error); } + /* * Supply hfs_getnewvnode with a component name. */ diff --git a/bsd/kern/kern_descrip.c b/bsd/kern/kern_descrip.c index 5913c5456..04af17fe7 100644 --- a/bsd/kern/kern_descrip.c +++ b/bsd/kern/kern_descrip.c @@ -2353,8 +2353,11 @@ close_internal_locked(proc_t p, int fd, struct fileproc *fp, int flags) if ((fp->f_flags & FP_INCHRREAD) == 0) fileproc_drain(p, fp); - if (resvfd == 0) + if (resvfd == 0) { _fdrelse(p, fd); + } else { + procfdtbl_reservefd(p, fd); + } error = closef_locked(fp, fp->f_fglob, p); if ((fp->f_flags & FP_WAITCLOSE) == FP_WAITCLOSE) diff --git a/bsd/kern/kern_panicinfo.c b/bsd/kern/kern_panicinfo.c deleted file mode 100644 index eb5c5bfbd..000000000 --- a/bsd/kern/kern_panicinfo.c +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - - -/* prototypes not exported by osfmk/console. */ -extern void panic_dialog_test( void ); -extern void noroot_icon_test(void); -extern int panic_dialog_set_image( const unsigned char * ptr, unsigned int size ); -extern void panic_dialog_get_image( unsigned char ** ptr, unsigned int * size ); - -/* make the compiler happy */ -static int sysctl_dopanicinfo SYSCTL_HANDLER_ARGS; - - -#define PANIC_IMAGE_SIZE_LIMIT (32 * 4096) /* 128K - Maximum amount of memory consumed for the panic UI */ - -/* Local data */ -static int image_size_limit = PANIC_IMAGE_SIZE_LIMIT; - -/* XXX Should be STATIC for dtrace debugging.. */ -static int -sysctl_dopanicinfo SYSCTL_HANDLER_ARGS -{ - __unused int cmd = oidp->oid_arg2; /* subcommand*/ - int *name = arg1; /* oid element argument vector */ - int namelen = arg2; /* number of oid element arguments */ - user_addr_t oldp = req->oldptr; /* user buffer copy out address */ - size_t *oldlenp = &req->oldlen; /* user buffer copy out size */ - user_addr_t newp = req->newptr; /* user buffer copy in address */ - size_t newlen = req->newlen; /* user buffer copy in size */ - int error = 0; - proc_t p = current_proc(); - - vm_offset_t newimage = (vm_offset_t )NULL; - kern_return_t kret; - unsigned char * prev_image_ptr; - unsigned int prev_image_size; - - /* all sysctl names at this level are terminal */ - if (namelen != 1) - return (ENOTDIR); /* overloaded */ - - /* must be super user to muck with image */ - if ( (error = proc_suser(p)) ) - return (error); - - switch (name[0]) { - default: - return (ENOTSUP); - - case KERN_PANICINFO_TEST: - - panic_dialog_test(); - break; - - case KERN_PANICINFO_NOROOT_TEST: - printf("Testing noroot icon \n"); - - noroot_icon_test(); - break; - - case KERN_PANICINFO_MAXSIZE: - - /* return the image size limits */ - - newlen = 0; - newp = USER_ADDR_NULL; - - error = sysctl_int(oldp, oldlenp, newp, newlen, &image_size_limit); - - break; - - case KERN_PANICINFO_IMAGE: - - /* If we have a new image, allocate wired kernel memory and copy it in from user space */ - if ( newp != USER_ADDR_NULL ) { - - /* check the length of the incoming image before allocating space for it. */ - if ( newlen > (size_t)image_size_limit ) { - error = ENOMEM; - break; - } - - /* allocate some kernel wired memory for the new image */ - kret = kmem_alloc(kernel_map, &newimage, (vm_size_t)round_page(newlen)); - - if (kret != KERN_SUCCESS) { - switch (kret) { - default: - error = EINVAL; - break; - case KERN_NO_SPACE: - case KERN_RESOURCE_SHORTAGE: - error = ENOMEM; - break; - case KERN_PROTECTION_FAILURE: - error = EPERM; - break; - } - break; - } - - /* copy the image in from user space */ - if ( (error = copyin(newp, (char *) newimage, newlen)) ) - goto errout; - - } else { /* setup to make the default image active */ - - newimage = (vm_offset_t )NULL; - newlen = 0; - } - - /* get the current image location and size */ - panic_dialog_get_image( &prev_image_ptr, &prev_image_size ); - - /* did the caller request a copy of the previous image ? */ - if ( oldp != USER_ADDR_NULL ) { - if ( *oldlenp < prev_image_size ) { - error = ERANGE; - goto errout; - } - - /* copy the image to user space or zero the size if the default image is active */ - if ( prev_image_ptr != NULL ) { - if ( (error = copyout( prev_image_ptr, oldp, prev_image_size )) ) - goto errout; - - *oldlenp = prev_image_size; - } - else /* tell the user that the default image is active */ - *oldlenp = 0; - } - - /* Make the new image active, or reactivate the default image. - But, handle the special case of asking for the current image - without changing the current image. - */ - - if ( !(oldp && newp == USER_ADDR_NULL) ) { - if ( (error = panic_dialog_set_image( (unsigned char *) newimage, newlen )) ) - goto errout; - - /* free the wired memory used by the previous image */ - if ( prev_image_ptr != NULL ) { - (void)kmem_free(kernel_map, (vm_offset_t) prev_image_ptr, (vm_size_t)round_page(prev_image_size)); - printf("Panic UI memory freed (%p)\n", (void *)round_page(prev_image_size)); - } - } - - break; - -errout: - if ( newimage != (vm_offset_t )NULL ) - (void)kmem_free(kernel_map, newimage, (vm_size_t)round_page(newlen)); - - break; - } - - /* adjust index so we return the right required/consumed amount */ - if (!error) - req->oldidx += req->oldlen; - - return (error); -} -SYSCTL_PROC(_kern, KERN_PANICINFO, panicinfo, CTLTYPE_NODE|CTLFLAG_RW | CTLFLAG_LOCKED | CTLFLAG_ANYBODY, - 0, /* Pointer argument (arg1) */ - 0, /* Integer argument (arg2) */ - sysctl_dopanicinfo, /* Handler function */ - NULL, /* Data pointer */ - ""); diff --git a/bsd/kern/kern_symfile.c b/bsd/kern/kern_symfile.c index d0d467494..1636b4ab5 100644 --- a/bsd/kern/kern_symfile.c +++ b/bsd/kern/kern_symfile.c @@ -179,14 +179,15 @@ struct kern_direct_file_io_ref_t * kern_open_file_for_direct_io(const char * name, kern_get_file_extents_callback_t callback, void * callback_ref, + off_t set_file_size, + off_t write_file_offset, + caddr_t write_file_addr, + vm_size_t write_file_len, dev_t * partition_device_result, dev_t * image_device_result, uint64_t * partitionbase_result, uint64_t * maxiocount_result, - uint32_t * oflags, - off_t offset, - caddr_t addr, - vm_size_t len) + uint32_t * oflags) { struct kern_direct_file_io_ref_t * ref; @@ -225,9 +226,9 @@ kern_open_file_for_direct_io(const char * name, if ((error = vnode_open(name, (O_CREAT | FWRITE), (0), 0, &ref->vp, ref->ctx))) goto out; - if (addr && len) + if (write_file_addr && write_file_len) { - if ((error = kern_write_file(ref, offset, addr, len))) + if ((error = kern_write_file(ref, write_file_offset, write_file_addr, write_file_len))) goto out; } @@ -251,9 +252,24 @@ kern_open_file_for_direct_io(const char * name, goto out; device = va.va_fsid; + ref->filelength = va.va_data_size; + p1 = &device; p2 = p; do_ioctl = &file_ioctl; + + if (set_file_size) + { + off_t bytesallocated = 0; + u_int32_t alloc_flags = PREALLOCATE | ALLOCATEFROMPEOF | ALLOCATEALL; + error = VNOP_ALLOCATE(ref->vp, set_file_size, alloc_flags, + &bytesallocated, 0 /*fst_offset*/, + ref->ctx); + // F_SETSIZE: + if (!error) error = vnode_setsize(ref->vp, set_file_size, IO_NOZEROFILL, ref->ctx); + kprintf("vnode_setsize(%d) %qd\n", error, set_file_size); + ref->filelength = bytesallocated; + } } else if ((ref->vp->v_type == VBLK) || (ref->vp->v_type == VCHR)) { @@ -278,9 +294,7 @@ kern_open_file_for_direct_io(const char * name, if (error) goto out; - if (ref->vp->v_type == VREG) - ref->filelength = va.va_data_size; - else + if (ref->vp->v_type != VREG) { error = do_ioctl(p1, p2, DKIOCGETBLOCKCOUNT, (caddr_t) &fileblk); if (error) @@ -438,6 +452,7 @@ out: kfree(ref, sizeof(struct kern_direct_file_io_ref_t)); ref = NULL; } + return(ref); } diff --git a/bsd/kern/trace.codes b/bsd/kern/trace.codes index fd215a76a..5ccd2bbff 100644 --- a/bsd/kern/trace.codes +++ b/bsd/kern/trace.codes @@ -1570,6 +1570,11 @@ 0x21030504 LOGINWINDOW_LOGOUT_START 0x21030508 LOGINWINDOW_DESKTOP_UP 0x2103050c LOGINWINDOW_DESKTOP_UP_NOTIFICATION +0x21030510 LOGINWINDOW_DISPLAYWAKE +0x21030514 LOGINWINDOW_SYSTEMWAKE +0x21030518 LOGINWINDOW_UNLOCKUI_TRIGGERED +0x2103051c LOGINWINDOW_UNLOCKUI_SHOWN +0x21030520 LOGINWINDOW_NO_LOCKUI_SHOWN 0x21040000 APP_DIDActivateWindow 0x21050000 TOOL_PRIVATE_1 0x21050004 TOOL_PRIVATE_2 diff --git a/bsd/miscfs/specfs/spec_vnops.c b/bsd/miscfs/specfs/spec_vnops.c index 11a0369a3..f3956c8b1 100644 --- a/bsd/miscfs/specfs/spec_vnops.c +++ b/bsd/miscfs/specfs/spec_vnops.c @@ -867,7 +867,7 @@ static uint32_t throttle_timer_start(struct _throttle_io_info_t *info, boolean_t update_io_count) { struct timeval elapsed; - int elapsed_msecs; + uint64_t elapsed_msecs; int throttle_level; uint64_t deadline; @@ -881,9 +881,9 @@ throttle_timer_start(struct _throttle_io_info_t *info, boolean_t update_io_count microuptime(&elapsed); timevalsub(&elapsed, &info->throttle_last_IO_timestamp[throttle_level]); - elapsed_msecs = elapsed.tv_sec * 1000 + elapsed.tv_usec / 1000; + elapsed_msecs = (uint64_t)elapsed.tv_sec * (uint64_t)1000 + (elapsed.tv_usec / 1000); - if (elapsed_msecs < THROTTLE_WINDOW) { + if (elapsed_msecs < (uint64_t)THROTTLE_WINDOW) { /* * we had an I/O occur in this level within * our throttle window, so we need to @@ -922,7 +922,7 @@ throttle_timer(struct _throttle_io_info_t *info) { uthread_t ut, utlist; struct timeval elapsed; - int elapsed_msecs; + uint64_t elapsed_msecs; int throttle_level; boolean_t update_io_count = FALSE; boolean_t need_wakeup = FALSE; @@ -932,9 +932,9 @@ throttle_timer(struct _throttle_io_info_t *info) microuptime(&elapsed); timevalsub(&elapsed, &info->throttle_start_IO_period_timestamp); - elapsed_msecs = elapsed.tv_sec * 1000 + elapsed.tv_usec / 1000; + elapsed_msecs = (uint64_t)elapsed.tv_sec * (uint64_t)1000 + (elapsed.tv_usec / 1000); - if (elapsed_msecs >= info->throttle_io_period) { + if (elapsed_msecs >= (uint64_t)info->throttle_io_period) { /* * we're closing out the current IO period... * if we have a waiting thread, wake it up @@ -1246,7 +1246,7 @@ throttle_io_will_be_throttled_internal(void * throttle_info) { struct _throttle_io_info_t *info = throttle_info; struct timeval elapsed; - int elapsed_msecs; + uint64_t elapsed_msecs; int thread_throttle_level; int throttle_level; @@ -1257,9 +1257,9 @@ throttle_io_will_be_throttled_internal(void * throttle_info) microuptime(&elapsed); timevalsub(&elapsed, &info->throttle_last_IO_timestamp[throttle_level]); - elapsed_msecs = elapsed.tv_sec * 1000 + elapsed.tv_usec / 1000; + elapsed_msecs = (uint64_t)elapsed.tv_sec * (uint64_t)1000 + (elapsed.tv_usec / 1000); - if (elapsed_msecs < THROTTLE_WINDOW) + if (elapsed_msecs < (uint64_t)THROTTLE_WINDOW) break; } if (throttle_level >= thread_throttle_level) { @@ -1566,7 +1566,7 @@ int throttle_info_io_will_be_throttled(void * throttle_info, int policy) { struct _throttle_io_info_t *info = throttle_info; struct timeval elapsed; - int elapsed_msecs; + uint64_t elapsed_msecs; int throttle_level; int thread_throttle_level; @@ -1586,9 +1586,9 @@ int throttle_info_io_will_be_throttled(void * throttle_info, int policy) microuptime(&elapsed); timevalsub(&elapsed, &info->throttle_last_IO_timestamp[throttle_level]); - elapsed_msecs = elapsed.tv_sec * 1000 + elapsed.tv_usec / 1000; + elapsed_msecs = (uint64_t)elapsed.tv_sec * (uint64_t)1000 + (elapsed.tv_usec / 1000); - if (elapsed_msecs < THROTTLE_WINDOW) + if (elapsed_msecs < (uint64_t)THROTTLE_WINDOW) break; } if (throttle_level >= thread_throttle_level) { diff --git a/bsd/net/dlil.c b/bsd/net/dlil.c index 5da68ac68..888926318 100644 --- a/bsd/net/dlil.c +++ b/bsd/net/dlil.c @@ -2289,8 +2289,10 @@ ifnet_poll_thread_fn(void *v, wait_result_t w) * else hold an IO refcnt to prevent the interface * from being detached (will be released below.) */ - if (!ifnet_is_attached(ifp, 1)) + if (!ifnet_is_attached(ifp, 1)) { + lck_mtx_lock_spin(&ifp->if_poll_lock); break; + } m_lim = (if_rxpoll_max != 0) ? if_rxpoll_max : MAX((qlimit(&inp->rcvq_pkts)), diff --git a/bsd/netinet6/nd6.c b/bsd/netinet6/nd6.c index 7cae1d7e7..2495e5650 100644 --- a/bsd/netinet6/nd6.c +++ b/bsd/netinet6/nd6.c @@ -1870,7 +1870,9 @@ nd6_rtrequest( * has elapsed. */ if (ln != NULL) - ln->ln_expire = MAX(timenow.tv_sec, 1); + ln->ln_expire = + (ifp->if_eflags & IFEF_IPV6_ND6ALT) + ? 0 : MAX(timenow.tv_sec, 1); } if ((rt->rt_flags & RTF_CLONING)) break; @@ -1948,8 +1950,10 @@ nd6_rtrequest( * initialized in rtrequest(), so rt_expire is 0. */ ln->ln_state = ND6_LLINFO_NOSTATE; + /* In case we're called before 1.0 sec. has elapsed */ - ln->ln_expire = MAX(timenow.tv_sec, 1); + ln->ln_expire = (ifp->if_eflags & IFEF_IPV6_ND6ALT) + ? 0 : MAX(timenow.tv_sec, 1); } rt->rt_flags |= RTF_LLINFO; LN_INSERTHEAD(ln); diff --git a/bsd/netinet6/nd6_nbr.c b/bsd/netinet6/nd6_nbr.c index be58f8dac..53d5367cf 100644 --- a/bsd/netinet6/nd6_nbr.c +++ b/bsd/netinet6/nd6_nbr.c @@ -177,7 +177,8 @@ nd6_llreach_alloc(struct rtentry *rt, struct ifnet *ifp, void *addr, struct llinfo_nd6 *ln = rt->rt_llinfo; if (nd6_llreach_base != 0 && - ln->ln_expire != 0 && rt->rt_ifp != lo_ifp && + (ln->ln_expire != 0 || (ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) && + rt->rt_ifp != lo_ifp && ifp->if_addrlen == IF_LLREACH_MAXLEN && /* Ethernet */ alen == ifp->if_addrlen) { struct if_llreach *lr; @@ -267,6 +268,11 @@ nd6_ns_input( struct sockaddr_dl proxydl; boolean_t advrouter; + if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) { + nd6log((LOG_INFO, "nd6_ns_input: on ND6ALT interface!\n")); + return; + } + /* Expect 32-bit aligned data pointer on strict-align platforms */ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); @@ -853,6 +859,11 @@ nd6_na_input( union nd_opts ndopts; struct timeval timenow; + if ((ifp->if_eflags & IFEF_IPV6_ND6ALT) != 0) { + nd6log((LOG_INFO, "nd6_na_input: on ND6ALT interface!\n")); + return; + } + /* Expect 32-bit aligned data pointer on strict-align platforms */ MBUF_STRICT_DATA_ALIGNMENT_CHECK_32(m); @@ -2283,6 +2294,10 @@ nd6_alt_node_present(struct ifnet *ifp, struct sockaddr_in6 *sin6, log(LOG_ERR, "%s: failed to add/update host route to %s.\n", __func__, ip6_sprintf(&sin6->sin6_addr)); } + else { + nd6log((LOG_DEBUG, "%s: host route to %s [lr=%p]\n", __func__, + ip6_sprintf(&sin6->sin6_addr), lr)); + } } void @@ -2290,6 +2305,9 @@ nd6_alt_node_absent(struct ifnet *ifp, struct sockaddr_in6 *sin6) { struct rtentry *rt; + nd6log((LOG_DEBUG, "%s: host route to %s\n", __func__, + ip6_sprintf(&sin6->sin6_addr))); + lck_mtx_assert(rnh_lock, LCK_MTX_ASSERT_NOTOWNED); lck_mtx_lock(rnh_lock); diff --git a/bsd/sys/kdebug.h b/bsd/sys/kdebug.h index fbaddae7b..ae8970aa4 100644 --- a/bsd/sys/kdebug.h +++ b/bsd/sys/kdebug.h @@ -313,8 +313,9 @@ __BEGIN_DECLS #define DKIO_PASSIVE 0x40 #define DKIO_NOCACHE 0x80 -/* Codes for Application Sub Classes */ -#define DBG_APP_SAMBA 128 +/* Kernel Debug Sub Classes for Applications (DBG_APPS) */ +#define DBG_APP_LOGINWINDOW 0x03 +#define DBG_APP_SAMBA 0x80 /**********************************************************************/ diff --git a/bsd/sys/sysctl.h b/bsd/sys/sysctl.h index 29cec4776..601ace8b8 100644 --- a/bsd/sys/sysctl.h +++ b/bsd/sys/sysctl.h @@ -455,7 +455,7 @@ SYSCTL_DECL(_user); #define KERN_PROCARGS 38 /* 39 was KERN_PCSAMPLES... now deprecated */ #define KERN_NETBOOT 40 /* int: are we netbooted? 1=yes,0=no */ -#define KERN_PANICINFO 41 /* node: panic UI information */ +#define KERN_PANICINFO 41 /* node: panic UI information (deprecated) */ #define KERN_SYSV 42 /* node: System V IPC information */ #define KERN_AFFINITY 43 /* xxx */ #define KERN_TRANSLATE 44 /* xxx */ @@ -548,7 +548,7 @@ SYSCTL_DECL(_user); #define KERN_KDDISABLE_BG_TRACE 20 #define KERN_KDSET_TYPEFILTER 22 -/* KERN_PANICINFO types */ +/* KERN_PANICINFO types (deprecated) */ #define KERN_PANICINFO_MAXSIZE 1 /* quad: panic UI image size limit */ #define KERN_PANICINFO_IMAGE 2 /* panic UI in 8-bit kraw format */ #define KERN_PANICINFO_TEST 4 /* Allow the panic UI to be tested by root without causing a panic */ @@ -596,7 +596,7 @@ SYSCTL_DECL(_user); { "procargs",CTLTYPE_STRUCT },\ { "dummy", CTLTYPE_INT }, /* deprecated pcsamples */ \ { "netboot", CTLTYPE_INT }, \ - { "panicinfo", CTLTYPE_NODE }, \ + { "panicinfo", CTLTYPE_NODE }, /* deprecated: panicinfo */ \ { "sysv", CTLTYPE_NODE }, \ { "dummy", CTLTYPE_INT }, \ { "dummy", CTLTYPE_INT }, \ diff --git a/bsd/vfs/vfs_fsevents.c b/bsd/vfs/vfs_fsevents.c index 52cdb65af..887ee2888 100644 --- a/bsd/vfs/vfs_fsevents.c +++ b/bsd/vfs/vfs_fsevents.c @@ -382,7 +382,7 @@ add_fsevent(int type, vfs_context_t ctx, ...) kfs_event *kfse, *kfse_dest=NULL, *cur; fs_event_watcher *watcher; va_list ap; - int error = 0, did_alloc=0, need_event_unlock = 0; + int error = 0, did_alloc=0; dev_t dev = 0; uint64_t now, elapsed; char *pathbuff=NULL; @@ -559,11 +559,9 @@ add_fsevent(int type, vfs_context_t ctx, ...) kfse->abstime = now; kfse->pid = p->p_pid; if (type == FSE_RENAME || type == FSE_EXCHANGE) { - if (need_event_unlock == 0) { - memset(kfse_dest, 0, sizeof(kfs_event)); - kfse_dest->refcount = 1; - OSBitOrAtomic16(KFSE_BEING_CREATED, &kfse_dest->flags); - } + memset(kfse_dest, 0, sizeof(kfs_event)); + kfse_dest->refcount = 1; + OSBitOrAtomic16(KFSE_BEING_CREATED, &kfse_dest->flags); kfse_dest->type = type; kfse_dest->pid = p->p_pid; kfse_dest->abstime = now; @@ -587,9 +585,6 @@ add_fsevent(int type, vfs_context_t ctx, ...) // now process the arguments passed in and copy them into // the kfse // - if (need_event_unlock == 0) { - lck_rw_lock_shared(&event_handling_lock); - } cur = kfse; for(arg_type=va_arg(ap, int32_t); arg_type != FSE_ARG_DONE; arg_type=va_arg(ap, int32_t)) @@ -620,10 +615,6 @@ add_fsevent(int type, vfs_context_t ctx, ...) // printf("add_fsevent: failed to getattr on vp %p (%d)\n", cur->fref.vp, ret); cur->str = NULL; error = EINVAL; - if (need_event_unlock == 0) { - // then we only grabbed it shared - lck_rw_unlock_shared(&event_handling_lock); - } goto clean_up; } @@ -663,10 +654,6 @@ add_fsevent(int type, vfs_context_t ctx, ...) if (ret != 0 || vp == NULL) { error = ENOENT; - if (need_event_unlock == 0) { - // then we only grabbed it shared - lck_rw_unlock_shared(&event_handling_lock); - } goto clean_up; } } @@ -737,18 +724,6 @@ add_fsevent(int type, vfs_context_t ctx, ...) OSBitAndAtomic16(~KFSE_BEING_CREATED, &kfse_dest->flags); } - if (need_event_unlock == 0) { - // then we only grabbed it shared - lck_rw_unlock_shared(&event_handling_lock); - } - - // unlock this here so we don't hold it across the - // event delivery loop. - if (need_event_unlock) { - lck_rw_unlock_exclusive(&event_handling_lock); - need_event_unlock = 0; - } - // // now we have to go and let everyone know that // is interested in this type of event @@ -766,23 +741,18 @@ add_fsevent(int type, vfs_context_t ctx, ...) if (watcher_add_event(watcher, kfse) != 0) { watcher->num_dropped++; + continue; } } - if (kfse->refcount < 1) { - panic("add_fsevent: line %d: kfse recount %d but should be at least 1\n", __LINE__, kfse->refcount); - } + // if (kfse->refcount < 1) { + // panic("add_fsevent: line %d: kfse recount %d but should be at least 1\n", __LINE__, kfse->refcount); + // } } unlock_watch_table(); clean_up: - // have to check if this needs to be unlocked (in - // case we came here from an error handling path) - if (need_event_unlock) { - lck_rw_unlock_exclusive(&event_handling_lock); - need_event_unlock = 0; - } if (pathbuff) { release_pathbuff(pathbuff); @@ -950,6 +920,9 @@ add_watcher(int8_t *event_list, int32_t num_events, int32_t eventq_size, fs_even !strncmp(watcher->proc_name, "coreservicesd", sizeof(watcher->proc_name)) || !strncmp(watcher->proc_name, "mds", sizeof(watcher->proc_name))) { watcher->flags |= WATCHER_APPLE_SYSTEM_SERVICE; + } else { + printf("fsevents: watcher %s (pid: %d) - Using /dev/fsevents directly is unsupported. Migrate to FSEventsFramework\n", + watcher->proc_name, watcher->pid); } lock_watch_table(); @@ -1033,22 +1006,17 @@ remove_watcher(fs_event_watcher *target) // drain the event_queue + lck_rw_lock_exclusive(&event_handling_lock); while(watcher->rd != watcher->wr) { - lck_rw_lock_exclusive(&event_handling_lock); kfse = watcher->event_queue[watcher->rd]; - if (!kfse || kfse->type == FSE_INVALID || kfse->refcount < 1) { - lck_rw_unlock_exclusive(&event_handling_lock); - break; - } watcher->event_queue[watcher->rd] = NULL; watcher->rd = (watcher->rd+1) % watcher->eventq_size; OSSynchronizeIO(); - if (kfse != NULL) { + if (kfse != NULL && kfse->type != FSE_INVALID && kfse->refcount >= 1) { release_event_ref(kfse); } - lck_rw_unlock_exclusive(&event_handling_lock); } - + lck_rw_unlock_exclusive(&event_handling_lock); if (watcher->event_list) { FREE(watcher->event_list, M_TEMP); @@ -1134,54 +1102,49 @@ watcher_add_event(fs_event_watcher *watcher, kfs_event *kfse) watcher->event_queue[watcher->wr] = kfse; OSSynchronizeIO(); watcher->wr = (watcher->wr + 1) % watcher->eventq_size; - + // // wake up the watcher if there are more than MAX_NUM_PENDING events. // otherwise schedule a timer (if one isn't already set) which will // send any pending events if no more are received in the next // EVENT_DELAY_IN_MS milli-seconds. // - int32_t num_pending = 0; - if (watcher->rd < watcher->wr) { - num_pending = watcher->wr - watcher->rd; - } - - if (watcher->rd > watcher->wr) { - num_pending = watcher->wr + watcher->eventq_size - watcher->rd; - } - - if (num_pending > (watcher->eventq_size*3/4) && !(watcher->flags & WATCHER_APPLE_SYSTEM_SERVICE)) { - /* Non-Apple Service is falling behind, start dropping events for this process */ + int32_t num_pending = 0; + if (watcher->rd < watcher->wr) { + num_pending = watcher->wr - watcher->rd; + } + + if (watcher->rd > watcher->wr) { + num_pending = watcher->wr + watcher->eventq_size - watcher->rd; + } + + if (num_pending > (watcher->eventq_size*3/4) && !(watcher->flags & WATCHER_APPLE_SYSTEM_SERVICE)) { + /* Non-Apple Service is falling behind, start dropping events for this process */ + lck_rw_lock_exclusive(&event_handling_lock); + while (watcher->rd != watcher->wr) { + kfse = watcher->event_queue[watcher->rd]; + watcher->event_queue[watcher->rd] = NULL; + watcher->rd = (watcher->rd+1) % watcher->eventq_size; + OSSynchronizeIO(); + if (kfse != NULL && kfse->type != FSE_INVALID && kfse->refcount >= 1) { + release_event_ref(kfse); + } + } + watcher->flags |= WATCHER_DROPPED_EVENTS; + lck_rw_unlock_exclusive(&event_handling_lock); + + printf("fsevents: watcher falling behind: %s (pid: %d) rd: %4d wr: %4d q_size: %4d flags: 0x%x\n", + watcher->proc_name, watcher->pid, watcher->rd, watcher->wr, + watcher->eventq_size, watcher->flags); + + fsevents_wakeup(watcher); + } else if (num_pending > MAX_NUM_PENDING) { + fsevents_wakeup(watcher); + } else if (timer_set == 0) { + schedule_event_wakeup(); + } - lck_rw_lock_exclusive(&event_handling_lock); - while (watcher->rd != watcher->wr) { - kfse = watcher->event_queue[watcher->rd]; - if (!kfse || kfse->type == FSE_INVALID || kfse->refcount < 1) { - lck_rw_unlock_exclusive(&event_handling_lock); - break; - } - watcher->event_queue[watcher->rd] = NULL; - watcher->rd = (watcher->rd+1) % watcher->eventq_size; - OSSynchronizeIO(); - if (kfse != NULL) { - release_event_ref(kfse); - } - } - lck_rw_unlock_exclusive(&event_handling_lock); - - printf("fsevents: watcher failing behind: %s (pid: %d) rd: %4d wr: %4d q_size: %4d flags: 0x%x\n", - watcher->proc_name, watcher->pid, watcher->rd, watcher->wr, - watcher->eventq_size, watcher->flags); - - watcher->flags |= WATCHER_DROPPED_EVENTS; - fsevents_wakeup(watcher); - } else if (num_pending > MAX_NUM_PENDING) { - fsevents_wakeup(watcher); - } else if (timer_set == 0) { - schedule_event_wakeup(); - } - - return 0; + return 0; } static int @@ -1480,6 +1443,8 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio) } skipped = 0; + + lck_rw_lock_shared(&event_handling_lock); while (uio_resid(uio) > 0 && watcher->rd != watcher->wr) { if (watcher->flags & WATCHER_CLOSING) { break; @@ -1490,11 +1455,8 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio) // (since it may have been recycled/reused and changed // its type or which device it is for) // - lck_rw_lock_shared(&event_handling_lock); - kfse = watcher->event_queue[watcher->rd]; if (!kfse || kfse->type == FSE_INVALID || kfse->refcount < 1) { - lck_rw_unlock_shared(&event_handling_lock); break; } @@ -1532,12 +1494,12 @@ fmod_watch(fs_event_watcher *watcher, struct uio *uio) } } + watcher->event_queue[watcher->rd] = NULL; watcher->rd = (watcher->rd + 1) % watcher->eventq_size; OSSynchronizeIO(); release_event_ref(kfse); - - lck_rw_unlock_shared(&event_handling_lock); } + lck_rw_unlock_shared(&event_handling_lock); if (skipped && error == 0) { goto restart_watch; diff --git a/bsd/vfs/vfs_subr.c b/bsd/vfs/vfs_subr.c index d287837a3..1c8bfc50e 100644 --- a/bsd/vfs/vfs_subr.c +++ b/bsd/vfs/vfs_subr.c @@ -4486,6 +4486,11 @@ vnode_create(uint32_t flavor, uint32_t size, void *data, vnode_t *vpp) if (param == NULL) return (EINVAL); + /* Do quick sanity check on the parameters */ + if (param->vnfs_vtype == VBAD) { + return (EINVAL); + } + #if CONFIG_TRIGGERS if ((flavor == VNCREATE_TRIGGER) && (size == VNCREATE_TRIGGER_SIZE)) { tinfo = (struct vnode_trigger_param *)data; diff --git a/bsd/vfs/vfs_syscalls.c b/bsd/vfs/vfs_syscalls.c index 652a8e34a..36c3c5e3f 100644 --- a/bsd/vfs/vfs_syscalls.c +++ b/bsd/vfs/vfs_syscalls.c @@ -7347,6 +7347,15 @@ exchangedata (__unused proc_t p, struct exchangedata_args *uap, __unused int32_t goto out; } + /* + * if the two vnodes are not files, return an error. + */ + if ( (vnode_isreg(svp) == 0) || (vnode_isreg(fvp) == 0) ) { + error = EINVAL; + goto out; + } + + #if CONFIG_MACF error = mac_vnode_check_exchangedata(ctx, fvp, svp); diff --git a/config/MasterVersion b/config/MasterVersion index 02b81f57c..84a48a017 100644 --- a/config/MasterVersion +++ b/config/MasterVersion @@ -1,4 +1,4 @@ -12.2.0 +12.3.0 # The first line of this file contains the master version number for the kernel. # All other instances of the kernel version in xnu are derived from this file. diff --git a/iokit/IOKit/IOHibernatePrivate.h b/iokit/IOKit/IOHibernatePrivate.h index 2fdcb9dbb..da180376c 100644 --- a/iokit/IOKit/IOHibernatePrivate.h +++ b/iokit/IOKit/IOHibernatePrivate.h @@ -100,8 +100,9 @@ struct IOHibernateImageHeader uint32_t debugFlags; uint32_t options; uint32_t sleepTime; + uint32_t compression; - uint32_t reserved[69]; // make sizeof == 512 + uint32_t reserved[68]; // make sizeof == 512 uint64_t encryptEnd __attribute__ ((packed)); uint64_t deviceBase __attribute__ ((packed)); @@ -275,14 +276,18 @@ struct kern_direct_file_io_ref_t * kern_open_file_for_direct_io(const char * name, kern_get_file_extents_callback_t callback, void * callback_ref, + + off_t set_file_size, + + off_t write_file_offset, + caddr_t write_file_addr, + vm_size_t write_file_len, + dev_t * partition_device_result, dev_t * image_device_result, uint64_t * partitionbase_result, uint64_t * maxiocount_result, - uint32_t * oflags, - off_t offset, - caddr_t addr, - vm_size_t len); + uint32_t * oflags); void kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref, off_t write_offset, caddr_t addr, vm_size_t write_length, @@ -290,7 +295,7 @@ kern_close_file_for_direct_io(struct kern_direct_file_io_ref_t * ref, #endif /* _SYS_CONF_H_ */ hibernate_page_list_t * -hibernate_page_list_allocate(void); +hibernate_page_list_allocate(boolean_t log); kern_return_t hibernate_setup(IOHibernateImageHeader * header, @@ -299,8 +304,7 @@ hibernate_setup(IOHibernateImageHeader * header, boolean_t vmflush, hibernate_page_list_t ** page_list_ret, hibernate_page_list_t ** page_list_wired_ret, - hibernate_page_list_t ** page_list_pal_ret, - boolean_t * encryptedswap); + hibernate_page_list_t ** page_list_pal_ret); kern_return_t hibernate_teardown(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, @@ -314,6 +318,11 @@ hibernate_gobble_pages(uint32_t gobble_count, uint32_t free_page_time); void hibernate_free_gobble_pages(void); +void +hibernate_vm_lock_queues(void); +void +hibernate_vm_unlock_queues(void); + void hibernate_vm_lock(void); void @@ -324,6 +333,7 @@ void hibernate_page_list_setall(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, hibernate_page_list_t * page_list_pal, + boolean_t preflight, uint32_t * pagesOut); // mark pages to be saved, or pages not to be saved but available @@ -331,6 +341,7 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, void hibernate_page_list_setall_machine(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, + boolean_t preflight, uint32_t * pagesOut); // mark pages not to be saved and not for scratch usage during restore @@ -414,6 +425,7 @@ enum kIOHibernateModeSwitch = 0x00000020, kIOHibernateModeRestart = 0x00000040, kIOHibernateModeSSDInvert = 0x00000080, + kIOHibernateModeFileResize = 0x00000100, }; // IOHibernateImageHeader.signature @@ -433,6 +445,8 @@ enum #define kIOHibernateModeKey "Hibernate Mode" #define kIOHibernateFileKey "Hibernate File" +#define kIOHibernateFileMinSizeKey "Hibernate File Min" +#define kIOHibernateFileMaxSizeKey "Hibernate File Max" #define kIOHibernateFreeRatioKey "Hibernate Free Ratio" #define kIOHibernateFreeTimeKey "Hibernate Free Time" diff --git a/iokit/IOKit/IOService.h b/iokit/IOKit/IOService.h index db7f5d20b..9c68d22a5 100644 --- a/iokit/IOKit/IOService.h +++ b/iokit/IOKit/IOService.h @@ -1735,6 +1735,7 @@ public: IOReturn changePowerStateWithOverrideTo( unsigned long ordinal ); static const char * getIOMessageString( uint32_t msg ); IOReturn setIgnoreIdleTimer( bool ignore ); + static void setAdvisoryTickleEnable( bool enable ); #ifdef __LP64__ static IOWorkLoop * getPMworkloop( void ); @@ -1783,7 +1784,8 @@ private: void ParentChangeNotifyInterestedDriversDidChange ( void ); void ParentChangeTellCapabilityDidChange ( void ); void ParentChangeAcknowledgePowerChange ( void ); - + void ParentChangeCancelIdleTimer( IOPMPowerStateIndex ); + void all_done ( void ); void start_ack_timer ( void ); void stop_ack_timer ( void ); diff --git a/iokit/IOKit/pwr_mgt/IOPM.h b/iokit/IOKit/pwr_mgt/IOPM.h index 3401744c4..c2003ef47 100644 --- a/iokit/IOKit/pwr_mgt/IOPM.h +++ b/iokit/IOKit/pwr_mgt/IOPM.h @@ -769,6 +769,9 @@ enum { enum { kIOPMSubclassPolicy, kIOPMSuperclassPolicy1 +#ifdef KERNEL_PRIVATE + , kIOPMActivityTickleTypeAdvisory = 128 +#endif }; struct stateChangeNote { diff --git a/iokit/IOKit/pwr_mgt/IOPMLibDefs.h b/iokit/IOKit/pwr_mgt/IOPMLibDefs.h index 117732a71..3acac824e 100644 --- a/iokit/IOKit/pwr_mgt/IOPMLibDefs.h +++ b/iokit/IOKit/pwr_mgt/IOPMLibDefs.h @@ -38,5 +38,7 @@ #define kPMSetMaintenanceWakeCalendar 8 #define kPMSetUserAssertionLevels 9 #define kPMActivityTickle 10 +#define kPMGetSystemSleepType 11 +#define kPMSetClamshellSleepState 12 -#define kNumPMMethods 11 +#define kNumPMMethods 13 diff --git a/iokit/IOKit/pwr_mgt/IOPMPrivate.h b/iokit/IOKit/pwr_mgt/IOPMPrivate.h index 651544913..6ff802dde 100644 --- a/iokit/IOKit/pwr_mgt/IOPMPrivate.h +++ b/iokit/IOKit/pwr_mgt/IOPMPrivate.h @@ -626,6 +626,11 @@ enum { * *****************************************************************************/ +/* kIOPMFeatureAutoPowerOffKey + * Feature published if Auto Power Off is supported + */ +#define kIOPMFeatureAutoPowerOffKey "AutoPowerOff" + /* kIOPMAutoPowerOffEnabledKey * Indicates if Auto Power Off is enabled. * It has a boolean value. @@ -642,6 +647,19 @@ enum { */ #define kIOPMAutoPowerOffDelayKey "AutoPowerOff Delay" +/* kIOPMAutoPowerOffTimerKey + * Key refers to a CFNumberRef that indicates the time in seconds until the + * expiration of the Auto Power Off delay period. This value should be used + * to program a wake alarm before system sleep. + */ +#define kIOPMAutoPowerOffTimerKey "AutoPowerOff Timer" + +/* kIOPMUserWakeAlarmScheduledKey + * Key refers to a boolean value that indicates if an user alarm was scheduled + * or pending. + */ +#define kIOPMUserWakeAlarmScheduledKey "UserWakeAlarmScheduled" + /***************************************************************************** * * System Sleep Policy @@ -677,8 +695,9 @@ struct IOPMSystemSleepPolicyVariables uint32_t standbyDelay; // standby delay in seconds uint32_t poweroffDelay; // auto-poweroff delay in seconds uint32_t scheduledAlarms; // bitmask of scheduled alarm types + uint32_t poweroffTimer; // auto-poweroff timer in seconds - uint32_t reserved[50]; // pad sizeof 256 bytes + uint32_t reserved[49]; // pad sizeof 256 bytes }; enum { @@ -689,7 +708,8 @@ enum { }; enum { - kIOPMSleepPhase1 = 1, + kIOPMSleepPhase0 = 0, + kIOPMSleepPhase1, kIOPMSleepPhase2 }; diff --git a/iokit/IOKit/pwr_mgt/RootDomain.h b/iokit/IOKit/pwr_mgt/RootDomain.h index 95dbc96a5..c817bf40d 100644 --- a/iokit/IOKit/pwr_mgt/RootDomain.h +++ b/iokit/IOKit/pwr_mgt/RootDomain.h @@ -387,6 +387,8 @@ public: IOReturn setMaintenanceWakeCalendar( const IOPMCalendarStruct * calendar ); + IOReturn getSystemSleepType( uint32_t * sleepType ); + // Handle callbacks from IOService::systemWillShutdown() void acknowledgeSystemWillShutdown( IOService * from ); @@ -455,7 +457,6 @@ public: */ bool pmNotificationIsSuspended( uint32_t pid ); - #if HIBERNATION bool getHibernateSettings( uint32_t * hibernateMode, @@ -575,6 +576,7 @@ private: unsigned int clamshellDisabled :1; unsigned int desktopMode :1; unsigned int acAdaptorConnected :1; + unsigned int clamshellSleepDisabled :1; unsigned int idleSleepTimerPending :1; unsigned int userDisabledAllSleep :1; @@ -645,6 +647,7 @@ private: OSSet * preventSystemSleepList; UInt32 _scheduledAlarms; + UInt32 _userScheduledAlarm; #if HIBERNATION clock_sec_t _standbyTimerResetSeconds; @@ -655,6 +658,7 @@ private: // IOPMrootDomain internal sleep call IOReturn privateSleepSystem( uint32_t sleepReason ); void reportUserInput( void ); + void setDisableClamShellSleep( bool ); bool checkSystemCanSleep( IOOptionBits options = 0 ); bool checkSystemCanSustainFullWake( void ); @@ -706,7 +710,8 @@ private: #if HIBERNATION bool getSleepOption( const char * key, uint32_t * option ); - bool evaluateSystemSleepPolicy( IOPMSystemSleepParameters * p, int phase ); + bool evaluateSystemSleepPolicy( IOPMSystemSleepParameters * p, + int phase, uint32_t * hibMode ); void evaluateSystemSleepPolicyEarly( void ); void evaluateSystemSleepPolicyFinal( void ); #endif /* HIBERNATION */ diff --git a/iokit/Kernel/IOHibernateIO.cpp b/iokit/Kernel/IOHibernateIO.cpp index 5f19ecd15..74b18022e 100644 --- a/iokit/Kernel/IOHibernateIO.cpp +++ b/iokit/Kernel/IOHibernateIO.cpp @@ -182,8 +182,9 @@ extern uint32_t gIOHibernateState; uint32_t gIOHibernateMode; static char gIOHibernateBootSignature[256+1]; static char gIOHibernateFilename[MAXPATHLEN+1]; -static uint32_t gIOHibernateFreeRatio = 0; // free page target (percent) -uint32_t gIOHibernateFreeTime = 0*1000; // max time to spend freeing pages (ms) +static uint32_t gIOHibernateFreeRatio = 0; // free page target (percent) +uint32_t gIOHibernateFreeTime = 0*1000; // max time to spend freeing pages (ms) +static uint64_t gIOHibernateCompression = 0x80; // default compression 50% static IODTNVRAM * gIOOptionsEntry; static IORegistryEntry * gIOChosenEntry; @@ -603,9 +604,10 @@ IOCopyMediaForDev(dev_t device) } IOReturn -IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, - IOPolledFileIOVars ** fileVars, OSData ** fileExtents, - OSData ** imagePath, uint8_t * volumeCryptKey) +IOPolledFileOpen( const char * filename, uint64_t setFileSize, + IOBufferMemoryDescriptor * ioBuffer, + IOPolledFileIOVars ** fileVars, OSData ** fileExtents, + OSData ** imagePath, uint8_t * volumeCryptKey) { IOReturn err = kIOReturnSuccess; IOPolledFileIOVars * vars; @@ -643,13 +645,16 @@ IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, clock_get_uptime(&startTime); vars->fileRef = kern_open_file_for_direct_io(filename, &file_extent_callback, &ctx, + setFileSize, + // write file: + 0, (caddr_t) gIOHibernateCurrentHeader, + sizeof(IOHibernateImageHeader), + // results &block_dev, &hibernate_image_dev, &vars->block0, &maxiobytes, - &vars->flags, - 0, (caddr_t) gIOHibernateCurrentHeader, - sizeof(IOHibernateImageHeader)); + &vars->flags); #if 0 uint32_t msDelay = (131071 & random()); HIBLOG("sleep %d\n", msDelay); @@ -679,6 +684,7 @@ IOPolledFileOpen( const char * filename, IOBufferMemoryDescriptor * ioBuffer, break; } + vars->fileSize = ctx.size; if (maxiobytes < vars->bufferSize) vars->bufferSize = maxiobytes; @@ -1118,6 +1124,7 @@ IOHibernateSystemSleep(void) OSData * data; OSObject * obj; OSString * str; + OSNumber * num; bool dsSSD; IOHibernateVars * vars; @@ -1183,9 +1190,70 @@ IOHibernateSystemSleep(void) break; } - // open & invalidate the image file + if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFileMinSizeKey))) + { + if ((num = OSDynamicCast(OSNumber, obj))) vars->fileMinSize = num->unsigned64BitValue(); + obj->release(); + } + if ((obj = IOService::getPMRootDomain()->copyProperty(kIOHibernateFileMaxSizeKey))) + { + if ((num = OSDynamicCast(OSNumber, obj))) vars->fileMaxSize = num->unsigned64BitValue(); + obj->release(); + } + + boolean_t encryptedswap = true; + uint32_t pageCount; + AbsoluteTime startTime, endTime; + uint64_t nsec; + + bzero(gIOHibernateCurrentHeader, sizeof(IOHibernateImageHeader)); + gIOHibernateCurrentHeader->debugFlags = gIOHibernateDebugFlags; gIOHibernateCurrentHeader->signature = kIOHibernateHeaderInvalidSignature; - err = IOPolledFileOpen(gIOHibernateFilename, vars->ioBuffer, + + dsSSD = (kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey)); + clock_get_uptime(&startTime); + err = hibernate_setup(gIOHibernateCurrentHeader, + gIOHibernateFreeRatio, gIOHibernateFreeTime, + dsSSD, + &vars->page_list, &vars->page_list_wired, &vars->page_list_pal); + clock_get_uptime(&endTime); + SUB_ABSOLUTETIME(&endTime, &startTime); + absolutetime_to_nanoseconds(endTime, &nsec); + HIBLOG("hibernate_setup(%d) took %qd ms\n", err, nsec / 1000000ULL); + + uint64_t setFileSize = 0; + + if (vars->fileMinSize || (kIOHibernateModeFileResize & gIOHibernateMode)) + { + hibernate_page_list_setall(vars->page_list, + vars->page_list_wired, + vars->page_list_pal, + true /* preflight */, + &pageCount); + PE_Video consoleInfo; + bzero(&consoleInfo, sizeof(consoleInfo)); + IOService::getPlatform()->getConsoleInfo(&consoleInfo); + + // estimate: 5% increase in pages compressed + // screen preview 2 images compressed 50% + setFileSize = ((ptoa_64((105 * pageCount) / 100) * gIOHibernateCompression) >> 8) + + vars->page_list->list_size + + (consoleInfo.v_width * consoleInfo.v_height * 4); + + HIBLOG("hibernate_page_list_setall preflight pageCount %d est comp %qd setfile %qd min %qd\n", + pageCount, (100ULL * gIOHibernateCompression) >> 8, + setFileSize, vars->fileMinSize); + + if (!(kIOHibernateModeFileResize & gIOHibernateMode) + && (setFileSize < vars->fileMinSize)) + { + setFileSize = vars->fileMinSize; + } + } + + // open & invalidate the image file + + err = IOPolledFileOpen(gIOHibernateFilename, setFileSize, vars->ioBuffer, &vars->fileVars, &vars->fileExtents, &data, &vars->volumeCryptKey[0]); if (KERN_SUCCESS != err) @@ -1194,8 +1262,6 @@ IOHibernateSystemSleep(void) break; } - bzero(gIOHibernateCurrentHeader, sizeof(IOHibernateImageHeader)); - gIOHibernateCurrentHeader->debugFlags = gIOHibernateDebugFlags; dsSSD = ((0 != (kIOHibernateOptionSSD & vars->fileVars->flags)) && (kOSBooleanTrue == IOService::getPMRootDomain()->getProperty(kIOPMDeepSleepEnabledKey))); if (dsSSD) @@ -1222,19 +1288,6 @@ IOHibernateSystemSleep(void) gIOHibernateCurrentHeader->options |= kIOHibernateOptionProgress; } - boolean_t encryptedswap; - AbsoluteTime startTime, endTime; - uint64_t nsec; - - clock_get_uptime(&startTime); - err = hibernate_setup(gIOHibernateCurrentHeader, - gIOHibernateFreeRatio, gIOHibernateFreeTime, - dsSSD, - &vars->page_list, &vars->page_list_wired, &vars->page_list_pal, &encryptedswap); - clock_get_uptime(&endTime); - SUB_ABSOLUTETIME(&endTime, &startTime); - absolutetime_to_nanoseconds(endTime, &nsec); - HIBLOG("hibernate_setup(%d) took %qd ms\n", err, nsec / 1000000ULL); if (KERN_SUCCESS != err) break; @@ -2092,7 +2145,8 @@ hibernate_write_image(void) hibernate_page_list_setall(vars->page_list, vars->page_list_wired, - vars->page_list_pal, + vars->page_list_pal, + false /* !preflight */, &pageCount); HIBLOG("hibernate_page_list_setall found pageCount %d\n", pageCount); @@ -2324,7 +2378,9 @@ hibernate_write_image(void) pagesDone = 0; lastBlob = 0; - HIBLOG("writing %d pages\n", pageCount); + HIBLOG("bitmap_size 0x%x, previewSize 0x%x, writing %d pages @ 0x%llx\n", + bitmap_size, header->previewSize, + pageCount, vars->fileVars->position); enum // pageType @@ -2424,7 +2480,7 @@ hibernate_write_image(void) // HIBLOG("------------lose: %d\n", pageCompressedSize); pageCompressedSize = page_size; } - + if (pageCompressedSize != page_size) data = (src + page_size); else @@ -2514,6 +2570,9 @@ hibernate_write_image(void) header->image1Sum = sum1; header->image2Sum = sum2; header->sleepTime = gIOLastSleepTime.tv_sec; + + header->compression = (compressedSize << 8) / uncompressedSize; + gIOHibernateCompression = header->compression; count = vars->fileExtents->getLength(); if (count > sizeof(header->fileExtentMap)) @@ -2564,8 +2623,8 @@ hibernate_write_image(void) nsec / 1000000ULL, nsec ? (((vars->fileVars->cryptBytes * 1000000000ULL) / 1024 / 1024) / nsec) : 0); - HIBLOG("\nimage %qd, uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n", - header->imageSize, + HIBLOG("\nimage %qd (%lld%%), uncompressed %qd (%d), compressed %qd (%d%%), sum1 %x, sum2 %x\n", + header->imageSize, (header->imageSize * 100) / vars->fileVars->fileSize, uncompressedSize, atop_32(uncompressedSize), compressedSize, uncompressedSize ? ((int) ((compressedSize * 100ULL) / uncompressedSize)) : 0, sum1, sum2); @@ -2858,6 +2917,7 @@ hibernate_machine_init(void) panic("Hibernate restore error %x", err); gIOHibernateCurrentHeader->actualImage2Sum = sum; + gIOHibernateCompression = gIOHibernateCurrentHeader->compression; if (vars->fileVars->io) (void) IOHibernatePollerIODone(vars->fileVars, false); diff --git a/iokit/Kernel/IOHibernateInternal.h b/iokit/Kernel/IOHibernateInternal.h index 2c1378e5f..6e044eb57 100644 --- a/iokit/Kernel/IOHibernateInternal.h +++ b/iokit/Kernel/IOHibernateInternal.h @@ -46,6 +46,8 @@ struct IOHibernateVars OSObject * saveBootDevice; struct IOPolledFileIOVars * fileVars; + uint64_t fileMinSize; + uint64_t fileMaxSize; vm_offset_t videoMapping; vm_size_t videoAllocSize; vm_size_t videoMapSize; @@ -73,6 +75,7 @@ struct IOPolledFileIOVars IOByteCount lastRead; IOByteCount readEnd; uint32_t flags; + uint64_t fileSize; uint64_t block0; uint64_t position; uint64_t extentPosition; diff --git a/iokit/Kernel/IOPMrootDomain.cpp b/iokit/Kernel/IOPMrootDomain.cpp index 9e4573420..dd6d10f2a 100644 --- a/iokit/Kernel/IOPMrootDomain.cpp +++ b/iokit/Kernel/IOPMrootDomain.cpp @@ -268,7 +268,9 @@ enum { kDarkWakeFlagIgnoreDiskIOInDark = 0x04, // ignore disk idle in DW kDarkWakeFlagIgnoreDiskIOAlways = 0x08, // always ignore disk idle kDarkWakeFlagIgnoreDiskIOMask = 0x0C, - kDarkWakeFlagAlarmIsDark = 0x0100 + kDarkWakeFlagAlarmIsDark = 0x0100, + kDarkWakeFlagGraphicsPowerState1 = 0x0200, + kDarkWakeFlagAudioNotSuppressed = 0x0400 }; static IOPMrootDomain * gRootDomain; @@ -906,6 +908,7 @@ bool IOPMrootDomain::start( IOService * nub ) clamshellExists = false; clamshellDisabled = true; acAdaptorConnected = true; + clamshellSleepDisabled = false; // Set the default system capabilities at boot. _currentCapability = kIOPMSystemCapabilityCPU | @@ -1194,6 +1197,8 @@ IOReturn IOPMrootDomain::setProperties( OSObject * props_obj ) #if HIBERNATION const OSSymbol *hibernatemode_string = OSSymbol::withCString(kIOHibernateModeKey); const OSSymbol *hibernatefile_string = OSSymbol::withCString(kIOHibernateFileKey); + const OSSymbol *hibernatefilemin_string = OSSymbol::withCString(kIOHibernateFileMinSizeKey); + const OSSymbol *hibernatefilemax_string = OSSymbol::withCString(kIOHibernateFileMaxSizeKey); const OSSymbol *hibernatefreeratio_string = OSSymbol::withCString(kIOHibernateFreeRatioKey); const OSSymbol *hibernatefreetime_string = OSSymbol::withCString(kIOHibernateFreeTimeKey); #endif @@ -1257,6 +1262,8 @@ IOReturn IOPMrootDomain::setProperties( OSObject * props_obj ) } #if HIBERNATION else if (key->isEqualTo(hibernatemode_string) || + key->isEqualTo(hibernatefilemin_string) || + key->isEqualTo(hibernatefilemax_string) || key->isEqualTo(hibernatefreeratio_string) || key->isEqualTo(hibernatefreetime_string)) { @@ -1296,11 +1303,20 @@ IOReturn IOPMrootDomain::setProperties( OSObject * props_obj ) setProperty(key, b); } else if (key->isEqualTo(kIOPMDeepSleepDelayKey) || - key->isEqualTo(kIOPMAutoPowerOffDelayKey)) + key->isEqualTo(kIOPMAutoPowerOffDelayKey) || + key->isEqualTo(kIOPMAutoPowerOffTimerKey)) { if ((n = OSDynamicCast(OSNumber, obj))) setProperty(key, n); } + else if (key->isEqualTo(kIOPMUserWakeAlarmScheduledKey)) + { + if (kOSBooleanTrue == obj) + OSBitOrAtomic(kIOPMAlarmBitCalendarWake, &_userScheduledAlarm); + else + OSBitAndAtomic(~kIOPMAlarmBitCalendarWake, &_userScheduledAlarm); + DLOG("_userScheduledAlarm = 0x%x\n", (uint32_t) _userScheduledAlarm); + } #if SUSPEND_PM_NOTIFICATIONS_DEBUG else if (key->isEqualTo(suspendPMClient_string)) { @@ -2196,6 +2212,7 @@ void IOPMrootDomain::powerChangeDone( unsigned long previousPowerState ) // Code will resume execution here upon wake. clock_get_uptime(&systemWakeTime); + _highestCapability = 0; #if HIBERNATION IOHibernateSystemWake(); @@ -2620,6 +2637,7 @@ void IOPMrootDomain::tellNoChangeDown( unsigned long stateNum ) startIdleSleepTimer( kIdleSleepRetryInterval ); } + IOService::setAdvisoryTickleEnable( true ); return tellClients( kIOMessageSystemWillNotSleep ); } @@ -2660,6 +2678,7 @@ void IOPMrootDomain::tellChangeUp( unsigned long stateNum ) // stay awake for at least idleSeconds startIdleSleepTimer(idleSeconds); } + IOService::setAdvisoryTickleEnable( true ); tellClients( kIOMessageSystemWillPowerOn ); } @@ -2947,10 +2966,10 @@ bool IOPMrootDomain::shouldSleepOnClamshellClosed( void ) if (!clamshellExists) return false; - DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d\n", - clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected); + DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n", + clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled); - return ( !clamshellDisabled && !(desktopMode && acAdaptorConnected) ); + return ( !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled ); } void IOPMrootDomain::sendClientClamshellNotification( void ) @@ -2996,6 +3015,35 @@ void IOPMrootDomain::setSleepSupported( IOOptionBits flags ) OSBitOrAtomic(flags, &platformSleepSupport); } +//****************************************************************************** +// setDisableClamShellSleep +// +//****************************************************************************** + +void IOPMrootDomain::setDisableClamShellSleep( bool val ) +{ + if (gIOPMWorkLoop->inGate() == false) { + + gIOPMWorkLoop->runAction( + OSMemberFunctionCast(IOWorkLoop::Action, this, &IOPMrootDomain::setDisableClamShellSleep), + (OSObject *)this, + (void *)val); + + return; + } + else { + DLOG("setDisableClamShellSleep(%x)\n", (uint32_t) val); + if ( clamshellSleepDisabled != val ) + { + clamshellSleepDisabled = val; + // If clamshellSleepDisabled is reset to 0, reevaluate if + // system need to go to sleep due to clamshell state + if ( !clamshellSleepDisabled && clamshellClosed) + handlePowerNotification(kLocalEvalClamshellCommand); + } + } +} + //****************************************************************************** // wakeFromDoze // @@ -3636,7 +3684,7 @@ struct IOPMSystemSleepPolicyTable } __attribute__((packed)); bool IOPMrootDomain::evaluateSystemSleepPolicy( - IOPMSystemSleepParameters * params, int sleepPhase ) + IOPMSystemSleepParameters * params, int sleepPhase, uint32_t * hibMode ) { const IOPMSystemSleepPolicyTable * pt; OSObject * prop = 0; @@ -3644,6 +3692,7 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( uint64_t currentFactors = 0; uint32_t standbyDelay = 0; uint32_t powerOffDelay = 0; + uint32_t powerOffTimer = 0; uint32_t mismatch; bool standbyEnabled; bool powerOffEnabled; @@ -3661,12 +3710,15 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( && (getProperty(kIOPMDeepSleepEnabledKey) == kOSBooleanTrue)); powerOffEnabled = (getSleepOption(kIOPMAutoPowerOffDelayKey, &powerOffDelay) && (getProperty(kIOPMAutoPowerOffEnabledKey) == kOSBooleanTrue)); - DLOG("standby %d delay %u, powerOff %d delay %u, hibernate %u\n", - standbyEnabled, standbyDelay, powerOffEnabled, powerOffDelay, - hibernateMode); + if (!getSleepOption(kIOPMAutoPowerOffTimerKey, &powerOffTimer)) + powerOffTimer = powerOffDelay; + + DLOG("phase %d, standby %d delay %u, poweroff %d delay %u timer %u, hibernate 0x%x\n", + sleepPhase, standbyEnabled, standbyDelay, + powerOffEnabled, powerOffDelay, powerOffTimer, *hibMode); // pmset level overrides - if ((hibernateMode & kIOHibernateModeOn) == 0) + if ((*hibMode & kIOHibernateModeOn) == 0) { if (!gSleepPolicyHandler) { @@ -3674,7 +3726,7 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( powerOffEnabled = false; } } - else if (!(hibernateMode & kIOHibernateModeSleep)) + else if (!(*hibMode & kIOHibernateModeSleep)) { // Force hibernate (i.e. mode 25) // If standby is enabled, force standy. @@ -3724,11 +3776,11 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( DLOG("sleep factors 0x%llx\n", currentFactors); - // Clear the output params - bzero(params, sizeof(*params)); - if (gSleepPolicyHandler) { + uint32_t savedHibernateMode; + IOReturn result; + if (!gSleepPolicyVars) { gSleepPolicyVars = IONew(IOPMSystemSleepPolicyVariables, 1); @@ -3738,21 +3790,38 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( } gSleepPolicyVars->signature = kIOPMSystemSleepPolicySignature; gSleepPolicyVars->version = kIOPMSystemSleepPolicyVersion; - if (kIOPMSleepPhase1 == sleepPhase) - { - gSleepPolicyVars->currentCapability = _currentCapability; - gSleepPolicyVars->highestCapability = _highestCapability; - gSleepPolicyVars->sleepReason = lastSleepReason; - gSleepPolicyVars->hibernateMode = hibernateMode; - gSleepPolicyVars->standbyDelay = standbyDelay; - gSleepPolicyVars->poweroffDelay = powerOffDelay; - } - gSleepPolicyVars->sleepFactors = currentFactors; - gSleepPolicyVars->sleepPhase = sleepPhase; - gSleepPolicyVars->scheduledAlarms = _scheduledAlarms; + gSleepPolicyVars->currentCapability = _currentCapability; + gSleepPolicyVars->highestCapability = _highestCapability; + gSleepPolicyVars->sleepFactors = currentFactors; + gSleepPolicyVars->sleepReason = lastSleepReason; + gSleepPolicyVars->sleepPhase = sleepPhase; + gSleepPolicyVars->standbyDelay = standbyDelay; + gSleepPolicyVars->poweroffDelay = powerOffDelay; + gSleepPolicyVars->scheduledAlarms = _scheduledAlarms | _userScheduledAlarm; + gSleepPolicyVars->poweroffTimer = powerOffTimer; + + if (kIOPMSleepPhase0 == sleepPhase) + { + // preserve hibernateMode + savedHibernateMode = gSleepPolicyVars->hibernateMode; + gSleepPolicyVars->hibernateMode = *hibMode; + } + else if (kIOPMSleepPhase1 == sleepPhase) + { + // use original hibernateMode for phase2 + gSleepPolicyVars->hibernateMode = *hibMode; + } + + result = gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params); - if ((gSleepPolicyHandler(gSleepPolicyTarget, gSleepPolicyVars, params) != - kIOReturnSuccess) || (kIOPMSleepTypeInvalid == params->sleepType) || + if (kIOPMSleepPhase0 == sleepPhase) + { + // restore hibernateMode + gSleepPolicyVars->hibernateMode = savedHibernateMode; + } + + if ((result != kIOReturnSuccess) || + (kIOPMSleepTypeInvalid == params->sleepType) || (params->sleepType >= kIOPMSleepTypeLast) || (kIOPMSystemSleepParametersVersion != params->version)) { @@ -3761,9 +3830,9 @@ bool IOPMrootDomain::evaluateSystemSleepPolicy( } if ((params->sleepType >= kIOPMSleepTypeSafeSleep) && - ((hibernateMode & kIOHibernateModeOn) == 0)) + ((*hibMode & kIOHibernateModeOn) == 0)) { - hibernateMode |= (kIOHibernateModeOn | kIOHibernateModeSleep); + *hibMode |= (kIOHibernateModeOn | kIOHibernateModeSleep); } DLOG("sleep params v%u, type %u, flags 0x%x, wake 0x%x, timer %u, poweroff %u\n", @@ -3878,7 +3947,8 @@ void IOPMrootDomain::evaluateSystemSleepPolicyEarly( void ) // Save for late evaluation if sleep is aborted bzero(&gEarlySystemSleepParams, sizeof(gEarlySystemSleepParams)); - if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1)) + if (evaluateSystemSleepPolicy(&gEarlySystemSleepParams, kIOPMSleepPhase1, + &hibernateMode)) { if (!hibernateNoDefeat && (gEarlySystemSleepParams.sleepType == kIOPMSleepTypeNormalSleep)) @@ -3917,7 +3987,8 @@ void IOPMrootDomain::evaluateSystemSleepPolicyFinal( void ) DLOG("%s\n", __FUNCTION__); - if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2)) + bzero(¶ms, sizeof(params)); + if (evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase2, &hibernateMode)) { if ((hibernateDisabled || hibernateAborted) && (params.sleepType != kIOPMSleepTypeNormalSleep)) @@ -4007,6 +4078,37 @@ bool IOPMrootDomain::getSleepOption( const char * key, uint32_t * option ) } #endif /* HIBERNATION */ +IOReturn IOPMrootDomain::getSystemSleepType( uint32_t * sleepType ) +{ +#if HIBERNATION + IOPMSystemSleepParameters params; + uint32_t hibMode = 0; + bool ok; + + if (gIOPMWorkLoop->inGate() == false) + { + IOReturn ret = gIOPMWorkLoop->runAction( + OSMemberFunctionCast(IOWorkLoop::Action, this, + &IOPMrootDomain::getSystemSleepType), + (OSObject *) this, + (void *) sleepType); + return ret; + } + + getSleepOption(kIOHibernateModeKey, &hibMode); + bzero(¶ms, sizeof(params)); + + ok = evaluateSystemSleepPolicy(¶ms, kIOPMSleepPhase0, &hibMode); + if (ok) + { + *sleepType = params.sleepType; + return kIOReturnSuccess; + } +#endif + + return kIOReturnUnsupported; +} + // MARK: - // MARK: Shutdown and Restart @@ -4091,7 +4193,9 @@ void IOPMrootDomain::handlePlatformHaltRestart( UInt32 pe_type ) ctx.PowerState = ON_STATE; ctx.MessageType = kIOMessageSystemPagingOff; IOService::updateConsoleUsers(NULL, kIOMessageSystemPagingOff); +#if HIBERNATION IOHibernateSystemRestart(); +#endif break; default: @@ -4449,6 +4553,7 @@ void IOPMrootDomain::handleOurPowerChangeStart( if ((_highestCapability & kIOPMSystemCapabilityGraphics) == 0) _systemMessageClientMask |= kSystemMessageClientKernel; + IOService::setAdvisoryTickleEnable( true ); tellClients(kIOMessageSystemWillPowerOn); } @@ -4458,6 +4563,7 @@ void IOPMrootDomain::handleOurPowerChangeStart( tracePoint( kIOPMTracePointDarkWakeEntry ); *inOutChangeFlags |= kIOPMSyncTellPowerDown; _systemMessageClientMask = kSystemMessageClientUser; + IOService::setAdvisoryTickleEnable( false ); } } @@ -4495,6 +4601,7 @@ void IOPMrootDomain::handleOurPowerChangeStart( if (_pendingCapability & kIOPMSystemCapabilityGraphics) { _systemMessageClientMask = kSystemMessageClientAll; + IOService::setAdvisoryTickleEnable( true ); } else { @@ -4644,10 +4751,7 @@ void IOPMrootDomain::handleOurPowerChangeDone( // Update highest system capability. - if (!CAP_CURRENT(kIOPMSystemCapabilityCPU)) - _highestCapability = 0; // reset at sleep state - else - _highestCapability |= _currentCapability; + _highestCapability |= _currentCapability; if (darkWakePostTickle && (kSystemTransitionWake == _systemTransitionType) && @@ -4720,6 +4824,7 @@ void IOPMrootDomain::overridePowerChangeForUIService( actions->parameter |= kPMActionsFlagLimitPower; } else if ((actions->parameter & kPMActionsFlagIsAudioDevice) && + ((gDarkWakeFlags & kDarkWakeFlagAudioNotSuppressed) == 0) && ((_pendingCapability & kIOPMSystemCapabilityAudio) == 0) && (changeFlags & kIOPMSynchronize)) { @@ -5407,7 +5512,8 @@ bool IOPMrootDomain::checkSystemCanSustainFullWake( void ) return false; } - if (clamshellExists && clamshellClosed && !acAdaptorConnected) + if (clamshellExists && clamshellClosed && !acAdaptorConnected && + !clamshellSleepDisabled) { // Lid closed on battery power return false; @@ -6054,6 +6160,7 @@ void IOPMrootDomain::evaluatePolicy( int stimulus, uint32_t arg ) // Notify clients about full wake. _systemMessageClientMask = kSystemMessageClientAll; + IOService::setAdvisoryTickleEnable( true ); tellClients(kIOMessageSystemWillPowerOn); } @@ -6323,8 +6430,8 @@ void IOPMrootDomain::evaluateAssertions(IOPMDriverAssertionType newAssertions, I if (changedBits & kIOPMDriverAssertionPreventDisplaySleepBit) { if (wrangler) { - bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false; + bool value = (newAssertions & kIOPMDriverAssertionPreventDisplaySleepBit) ? true : false; DLOG("wrangler->setIgnoreIdleTimer\(%d)\n", value); wrangler->setIgnoreIdleTimer( value ); } @@ -7745,7 +7852,8 @@ void IOPMTimeline::setEventsTrackedCount(uint32_t newTracked) } pmTraceMemoryDescriptor = IOBufferMemoryDescriptor::withOptions( - kIOMemoryKernelUserShared | kIODirectionIn, make_buf_size); + kIOMemoryKernelUserShared | kIODirectionIn | kIOMemoryMapperNone, + make_buf_size); if (!pmTraceMemoryDescriptor) { diff --git a/iokit/Kernel/IOServicePM.cpp b/iokit/Kernel/IOServicePM.cpp index 3c76e4d09..e46b02482 100644 --- a/iokit/Kernel/IOServicePM.cpp +++ b/iokit/Kernel/IOServicePM.cpp @@ -99,6 +99,9 @@ static const OSSymbol * gIOPMPowerClientDriver = 0; static const OSSymbol * gIOPMPowerClientChildProxy = 0; static const OSSymbol * gIOPMPowerClientChildren = 0; +static const OSSymbol * gIOPMPowerClientAdvisoryTickle = 0; +static bool gIOPMAdvisoryTickleEnabled = true; + static uint32_t getPMRequestType( void ) { uint32_t type = kIOPMRequestTypeInvalid; @@ -161,6 +164,9 @@ do { \ #endif #define kIOPMPowerStateMax 0xFFFFFFFF +#define kInvalidTicklePowerState (-1) + +#define kNoTickleCancelWindow (60ULL * 1000ULL * 1000ULL * 1000ULL) #define IS_PM_ROOT (this == gIOPMRootNode) #define IS_ROOT_DOMAIN (getPMRootDomain() == this) @@ -206,7 +212,6 @@ static void logClientIDForNotification( OSObject *object, IOPMInterestContext *context, const char *logString); - //********************************************************************************* // PM machine states @@ -490,6 +495,9 @@ void IOService::PMinit ( void ) gIOPMPowerClientChildren = OSSymbol::withCStringNoCopy( "ChildrenPowerState" ); + + gIOPMPowerClientAdvisoryTickle = + OSSymbol::withCStringNoCopy( "AdvisoryTicklePowerState" ); } if (gIOPMRequestQueue && gIOPMReplyQueue && gIOPMFreeQueue) @@ -521,7 +529,8 @@ void IOService::PMinit ( void ) fIdleTimerMinPowerState = 0; fActivityLock = IOLockAlloc(); fStrictTreeOrder = false; - fActivityTicklePowerState = -1; + fActivityTicklePowerState = kInvalidTicklePowerState; + fAdvisoryTicklePowerState = kInvalidTicklePowerState; fControllingDriver = NULL; fPowerStates = NULL; fNumberOfPowerStates = 0; @@ -1253,6 +1262,12 @@ void IOService::handleRegisterPowerDriver ( IOPMRequest * request ) fOutputPowerCharacterFlags = 0; for ( i = 0; i < numberOfStates; i++ ) { fOutputPowerCharacterFlags |= fPowerStates[i].outputPowerFlags; + if (!fDeviceUsablePowerState && + (fPowerStates[i].capabilityFlags & IOPMDeviceUsable)) + { + // The minimum power state that the device is usable + fDeviceUsablePowerState = i; + } } // Register powerDriver as interested, unless already done. @@ -1913,6 +1928,12 @@ void IOService::handlePowerDomainDidChangeTo ( IOPMRequest * request ) fParentsCurrentPowerFlags); computeDesiredState(initialDesire); } + else if (fAdvisoryTickleUsed && (newPowerState > 0) && + ((parentChangeFlags & kIOPMSynchronize) == 0)) + { + // re-compute desired state in case advisory tickle was enabled + computeDesiredState(); + } // Absorb parent's kIOPMSynchronize flag. myChangeFlags = kIOPMParentInitiated | kIOPMDomainDidChange | @@ -2572,6 +2593,10 @@ void IOService::computeDesiredState ( unsigned long localClamp ) if (hasChildren && (client == gIOPMPowerClientChildProxy)) continue; + if (client == gIOPMPowerClientAdvisoryTickle && + !gIOPMAdvisoryTickleEnabled) + continue; + desiredState = getPowerStateForClient(client); assert(desiredState < fNumberOfPowerStates); PM_LOG1(" %u %s\n", @@ -2605,29 +2630,38 @@ void IOService::computeDesiredState ( unsigned long localClamp ) (uint32_t) localClamp, (uint32_t) fTempClampPowerState, (uint32_t) fCurrentPowerState, newPowerState); - // Restart idle timer if stopped and device desire has increased. - - if (fDeviceDesire && fIdleTimerStopped) - { - fIdleTimerStopped = false; - fActivityTickleCount = 0; - clock_get_uptime(&fIdleTimerStartTime); - start_PM_idle_timer(); - } + // Restart idle timer if stopped and device desire has increased. + // Or if advisory desire exists. + + if (fIdleTimerStopped) + { + if (fDeviceDesire > 0) + { + fIdleTimerStopped = false; + fActivityTickleCount = 0; + clock_get_uptime(&fIdleTimerStartTime); + start_PM_idle_timer(); + } + else if (fHasAdvisoryDesire) + { + fIdleTimerStopped = false; + start_PM_idle_timer(); + } + } - // Invalidate cached tickle power state when desires change, and not - // due to a tickle request. This invalidation must occur before the - // power state change to minimize races. We want to err on the side - // of servicing more activity tickles rather than dropping one when - // the device is in a low power state. + // Invalidate cached tickle power state when desires change, and not + // due to a tickle request. This invalidation must occur before the + // power state change to minimize races. We want to err on the side + // of servicing more activity tickles rather than dropping one when + // the device is in a low power state. - if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) && - (fActivityTicklePowerState != -1)) - { - IOLockLock(fActivityLock); - fActivityTicklePowerState = -1; - IOLockUnlock(fActivityLock); - } + if ((getPMRequestType() != kIOPMRequestTypeActivityTickle) && + (fActivityTicklePowerState != kInvalidTicklePowerState)) + { + IOLockLock(fActivityLock); + fActivityTicklePowerState = kInvalidTicklePowerState; + IOLockUnlock(fActivityLock); + } } //********************************************************************************* @@ -2732,6 +2766,11 @@ applyToPowerParent( // MARK: - // MARK: Activity Tickle & Idle Timer +void IOService::setAdvisoryTickleEnable( bool enable ) +{ + gIOPMAdvisoryTickleEnabled = enable; +} + //********************************************************************************* // [public] activityTickle // @@ -2747,7 +2786,10 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) IOPMRequest * request; bool noPowerChange = true; - if ( initialized && stateNumber && (type == kIOPMSuperclassPolicy1) ) + if (!initialized) + return true; // no power change + + if ((type == kIOPMSuperclassPolicy1) && stateNumber) { IOLockLock(fActivityLock); @@ -2763,7 +2805,7 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) // This helps to filter out redundant tickles as // this function may be called from the data path. - if (fActivityTicklePowerState < (long)stateNumber) + if (fActivityTicklePowerState < (int)stateNumber) { fActivityTicklePowerState = stateNumber; noPowerChange = false; @@ -2771,8 +2813,9 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); if (request) { - request->fArg0 = (void *) stateNumber; // power state - request->fArg1 = (void *) (uintptr_t) true; // power rise + request->fArg0 = (void *) stateNumber; // power state + request->fArg1 = (void *) true; // power rise + request->fArg2 = (void *) false; // regular tickle submitPMRequest(request); } } @@ -2780,6 +2823,31 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) IOLockUnlock(fActivityLock); } + else if ((type == kIOPMActivityTickleTypeAdvisory) && + ((stateNumber = fDeviceUsablePowerState))) + { + IOLockLock(fActivityLock); + + fAdvisoryTickled = true; + + if (fAdvisoryTicklePowerState != (int)stateNumber) + { + fAdvisoryTicklePowerState = stateNumber; + noPowerChange = false; + + request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); + if (request) + { + request->fArg0 = (void *) stateNumber; // power state + request->fArg1 = (void *) true; // power rise + request->fArg2 = (void *) true; // advisory tickle + submitPMRequest(request); + } + } + + IOLockUnlock(fActivityLock); + } + // Returns false if the activityTickle might cause a transition to a // higher powered state, true otherwise. @@ -2792,31 +2860,67 @@ bool IOService::activityTickle ( unsigned long type, unsigned long stateNumber ) void IOService::handleActivityTickle ( IOPMRequest * request ) { - uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0; - bool adjustPower = false; - + uint32_t ticklePowerState = (uint32_t)(uintptr_t) request->fArg0; + bool deviceWasActive = (request->fArg1 == (void *) true); + bool isRegularTickle = (request->fArg2 == (void *) false); + bool adjustPower = false; + PM_ASSERT_IN_GATE(); - if (request->fArg1) - { - // Power rise from activity tickle. - if ((ticklePowerState > fDeviceDesire) && - (ticklePowerState < fNumberOfPowerStates)) - { - fIdleTimerMinPowerState = ticklePowerState; - adjustPower = true; - } - } - else if (fDeviceDesire > fIdleTimerMinPowerState) - { - // Power drop due to idle timer expiration. - // Do not allow idle timer to reduce power below tickle power. - ticklePowerState = fDeviceDesire - 1; - adjustPower = true; - } + if (isRegularTickle) + { + if (deviceWasActive) + { + if ((ticklePowerState > fDeviceDesire) && + (ticklePowerState < fNumberOfPowerStates)) + { + fIdleTimerMinPowerState = ticklePowerState; + updatePowerClient(gIOPMPowerClientDevice, ticklePowerState); + adjustPower = true; + } + } + else if (fDeviceDesire > fIdleTimerMinPowerState) + { + // Power drop due to idle timer expiration. + // Do not allow idle timer to reduce power below tickle power. + // This prevents the idle timer from decreasing the device desire + // to zero and cancelling the effect of a pre-sleep tickle when + // system wakes up to doze state, while the device is unable to + // raise its power state to satisfy the tickle. + + ticklePowerState = fDeviceDesire - 1; + updatePowerClient(gIOPMPowerClientDevice, ticklePowerState); + adjustPower = true; + } + } + else // advisory tickle + { + if (deviceWasActive) + { + if ((ticklePowerState == fDeviceUsablePowerState) && + (ticklePowerState < fNumberOfPowerStates)) + { + updatePowerClient(gIOPMPowerClientAdvisoryTickle, ticklePowerState); + fHasAdvisoryDesire = true; + fAdvisoryTickleUsed = true; + adjustPower = true; + } + else + { + IOLockLock(fActivityLock); + fAdvisoryTicklePowerState = kInvalidTicklePowerState; + IOLockUnlock(fActivityLock); + } + } + else if (fHasAdvisoryDesire) + { + removePowerClient(gIOPMPowerClientAdvisoryTickle); + fHasAdvisoryDesire = false; + adjustPower = true; + } + } if (adjustPower) { - updatePowerClient(gIOPMPowerClientDevice, ticklePowerState); adjustPowerState(); } } @@ -2992,15 +3096,14 @@ void IOService::idleTimerExpired( void ) // but the power drop request must be issued regardless. if (fActivityTicklePowerState > 0) - { fActivityTicklePowerState--; - } request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); if (request) { request->fArg0 = (void *) 0; // power state (irrelevant) - request->fArg1 = (void *) (uintptr_t) false; // power drop + request->fArg1 = (void *) false; // timer expiration (not tickle) + request->fArg2 = (void *) false; // regular tickle submitPMRequest( request ); // Do not restart timer until after the tickle request has been @@ -3010,6 +3113,30 @@ void IOService::idleTimerExpired( void ) } } + if (fAdvisoryTickled) + { + fAdvisoryTickled = false; + } + else if (fHasAdvisoryDesire) + { + // Want new tickles to turn into pm request after we drop the lock + fAdvisoryTicklePowerState = kInvalidTicklePowerState; + + request = acquirePMRequest( this, kIOPMRequestTypeActivityTickle ); + if (request) + { + request->fArg0 = (void *) 0; // power state (irrelevant) + request->fArg1 = (void *) false; // timer expiration (not tickle) + request->fArg2 = (void *) true; // advisory tickle + submitPMRequest( request ); + + // Do not restart timer until after the tickle request has been + // processed. + + restartTimer = false; + } + } + IOLockUnlock(fActivityLock); if (restartTimer) @@ -3959,6 +4086,22 @@ void IOService::all_done ( void ) { powerChangeDone(fCurrentPowerState); } + else if (fAdvisoryTickleUsed) + { + // Not root domain and advisory tickle target + // Re-adjust power after power tree sync at the 'did' pass + if (!fAdjustPowerScheduled && + (fHeadNoteChangeFlags & kIOPMDomainDidChange)) + { + IOPMRequest * request; + request = acquirePMRequest( this, kIOPMRequestTypeAdjustPowerState ); + if (request) + { + submitPMRequest( request ); + fAdjustPowerScheduled = true; + } + } + } return; } @@ -4450,6 +4593,10 @@ IOReturn IOService::ParentChangeStart ( void ) // Power domain is lowering power if ( fHeadNotePowerState < fCurrentPowerState ) { + // Piggy-back idle timer cancellation on a parent down + if (0 == fHeadNotePowerState) + ParentChangeCancelIdleTimer(fHeadNotePowerState); + // TODO: redundant? See handlePowerDomainWillChangeTo() setParentInfo( fHeadNoteParentFlags, fHeadNoteParentConnection, true ); @@ -4628,6 +4775,72 @@ void IOService::ParentChangeAcknowledgePowerChange ( void ) nub->release(); } +void IOService::ParentChangeCancelIdleTimer( IOPMPowerStateIndex newPowerState ) +{ + AbsoluteTime now; + uint64_t nsec; + bool cancel = false; + + // No ready or idle timer not in use + if (!initialized || !fIdleTimerPeriod || fLockedFlags.PMStop || + !fAdvisoryTickleUsed) + return; + + // Not allowed to induce artifical idle timeout + if (fIdleTimerIgnored || fIdleTimerMinPowerState) + goto done; + + // Idle timer already has no influence + if (!fDesiredPowerState || fIdleTimerStopped) + goto done; + + IOLockLock(fActivityLock); + + if (!fDeviceWasActive) + { + // No tickles since the last idle timer expiration. + // Safe to drop the device desire to zero. + cancel = true; + } + else + { + // Was tickled since the last idle timer expiration, + // but not in the last minute. + clock_get_uptime(&now); + SUB_ABSOLUTETIME(&now, &fDeviceActiveTimestamp); + absolutetime_to_nanoseconds(now, &nsec); + if (nsec >= kNoTickleCancelWindow) + { + cancel = true; + } + } + + if (cancel) + { + // Force the next tickle to raise power state + fActivityTicklePowerState = kInvalidTicklePowerState; + fDeviceWasActive = false; + } + + IOLockUnlock(fActivityLock); + + if (cancel) + { + // cancel idle timer + if (fIdleTimer && thread_call_cancel(fIdleTimer)) + release(); + + updatePowerClient(gIOPMPowerClientDevice, 0); + computeDesiredState(); + + fIdleTimerStopped = true; + } + +done: + OUR_PMLog( kPMLogStartParentChange, fHeadNotePowerState, fCurrentPowerState ); + PM_LOG("%s::%s cancel=%d\n", fName, __FUNCTION__, cancel); +} + // MARK: - // MARK: Ack and Settle timers @@ -6383,11 +6596,11 @@ bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue ) // Catch requests created by idleTimerExpired(). if ((request->getType() == kIOPMRequestTypeActivityTickle) && - (request->fArg1 == (void *) (uintptr_t) false)) + (request->fArg1 == (void *) false)) { - // Idle timer power drop request completed. + // Idle timer expiration - power drop request completed. // Restart the idle timer if deviceDesire can go lower, otherwise set - // a flag so we know to restart idle timer when deviceDesire goes up. + // a flag so we know to restart idle timer when fDeviceDesire > 0. if (fDeviceDesire > 0) { @@ -6395,9 +6608,15 @@ bool IOService::retirePMRequest( IOPMRequest * request, IOPMWorkQueue * queue ) clock_get_uptime(&fIdleTimerStartTime); start_PM_idle_timer(); } + else if (fHasAdvisoryDesire) + { + start_PM_idle_timer(); + } else + { fIdleTimerStopped = true; - } + } + } // If the request is linked, then Work queue has already incremented its // producer count. @@ -6815,7 +7034,6 @@ void IOService::executePMRequest( IOPMRequest * request ) break; case kIOPMRequestTypePowerDomainDidChange: - handlePowerDomainDidChangeTo( request ); break; @@ -7742,6 +7960,12 @@ IOReturn IOServicePM::gatedSerialize( OSSerialize * s ) } #endif + if (HasAdvisoryDesire && !gIOPMAdvisoryTickleEnabled) + { + // Don't report advisory tickle when it has no influence + dict->removeObject(gIOPMPowerClientAdvisoryTickle); + } + ok = dict->serialize(s); dict->release(); } diff --git a/iokit/Kernel/IOServicePMPrivate.h b/iokit/Kernel/IOServicePMPrivate.h index 61e88e4eb..bdb74358b 100644 --- a/iokit/Kernel/IOServicePMPrivate.h +++ b/iokit/Kernel/IOServicePMPrivate.h @@ -241,6 +241,8 @@ private: unsigned int DriverCallBusy:1; unsigned int PCDFunctionOverride:1; unsigned int IdleTimerIgnored:1; + unsigned int HasAdvisoryDesire:1; + unsigned int AdvisoryTickleUsed:1; // Time of last device activity. AbsoluteTime DeviceActiveTimestamp; @@ -299,7 +301,6 @@ private: AbsoluteTime DriverCallStartTime; IOPMPowerFlags CurrentCapabilityFlags; - long ActivityTicklePowerState; unsigned long CurrentPowerConsumption; IOPMPowerStateIndex TempClampPowerState; OSArray * NotifyChildArray; @@ -312,10 +313,14 @@ private: uint32_t OutOfBandMessage; uint32_t TempClampCount; uint32_t OverrideMaxPowerState; + uint32_t DeviceUsablePowerState; // Protected by ActivityLock - BEGIN + int ActivityTicklePowerState; + int AdvisoryTicklePowerState; uint32_t ActivityTickleCount; - uint32_t DeviceWasActive; + uint32_t DeviceWasActive : 1; + uint32_t AdvisoryTickled : 1; // Protected by ActivityLock - END uint32_t WaitReason; @@ -364,7 +369,6 @@ private: #define fInitialPowerChange pwrMgt->InitialPowerChange #define fInitialSetPowerState pwrMgt->InitialSetPowerState #define fDeviceOverrideEnabled pwrMgt->DeviceOverrideEnabled -#define fDeviceWasActive pwrMgt->DeviceWasActive #define fDoNotPowerDown pwrMgt->DoNotPowerDown #define fParentsKnowState pwrMgt->ParentsKnowState #define fStrictTreeOrder pwrMgt->StrictTreeOrder @@ -374,6 +378,8 @@ private: #define fDriverCallBusy pwrMgt->DriverCallBusy #define fPCDFunctionOverride pwrMgt->PCDFunctionOverride #define fIdleTimerIgnored pwrMgt->IdleTimerIgnored +#define fHasAdvisoryDesire pwrMgt->HasAdvisoryDesire +#define fAdvisoryTickleUsed pwrMgt->AdvisoryTickleUsed #define fDeviceActiveTimestamp pwrMgt->DeviceActiveTimestamp #define fActivityLock pwrMgt->ActivityLock #define fIdleTimerPeriod pwrMgt->IdleTimerPeriod @@ -396,7 +402,6 @@ private: #define fOutOfBandParameter pwrMgt->OutOfBandParameter #define fDriverCallStartTime pwrMgt->DriverCallStartTime #define fCurrentCapabilityFlags pwrMgt->CurrentCapabilityFlags -#define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState #define fCurrentPowerConsumption pwrMgt->CurrentPowerConsumption #define fTempClampPowerState pwrMgt->TempClampPowerState #define fNotifyChildArray pwrMgt->NotifyChildArray @@ -409,7 +414,12 @@ private: #define fOutOfBandMessage pwrMgt->OutOfBandMessage #define fTempClampCount pwrMgt->TempClampCount #define fOverrideMaxPowerState pwrMgt->OverrideMaxPowerState +#define fDeviceUsablePowerState pwrMgt->DeviceUsablePowerState +#define fActivityTicklePowerState pwrMgt->ActivityTicklePowerState +#define fAdvisoryTicklePowerState pwrMgt->AdvisoryTicklePowerState #define fActivityTickleCount pwrMgt->ActivityTickleCount +#define fDeviceWasActive pwrMgt->DeviceWasActive +#define fAdvisoryTickled pwrMgt->AdvisoryTickled #define fWaitReason pwrMgt->WaitReason #define fSavedMachineState pwrMgt->SavedMachineState #define fRootDomainState pwrMgt->RootDomainState diff --git a/iokit/Kernel/RootDomainUserClient.cpp b/iokit/Kernel/RootDomainUserClient.cpp index 75a26e7cc..c3835903a 100644 --- a/iokit/Kernel/RootDomainUserClient.cpp +++ b/iokit/Kernel/RootDomainUserClient.cpp @@ -191,6 +191,23 @@ IOReturn RootDomainUserClient::secureSetUserAssertionLevels( return kIOReturnSuccess; } +IOReturn RootDomainUserClient::secureGetSystemSleepType( + uint32_t *outSleepType) +{ + int admin_priv = 0; + IOReturn ret; + + ret = clientHasPrivilege(fOwningTask, kIOClientPrivilegeAdministrator); + admin_priv = (kIOReturnSuccess == ret); + + if (admin_priv && fOwner) { + ret = fOwner->getSystemSleepType(outSleepType); + } else { + ret = kIOReturnNotPrivileged; + } + return ret; +} + IOReturn RootDomainUserClient::clientClose( void ) { detach(fOwner); @@ -311,11 +328,26 @@ IOReturn RootDomainUserClient::externalMethod( break; case kPMActivityTickle: - fOwner->reportUserInput( ); - fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); + if ( fOwner->checkSystemCanSustainFullWake() ) + { + fOwner->reportUserInput( ); + fOwner->setProperty(kIOPMRootDomainWakeTypeKey, "UserActivity Assertion"); + } ret = kIOReturnSuccess; break; - + + case kPMSetClamshellSleepState: + fOwner->setDisableClamShellSleep(arguments->scalarInput[0] ? true : false); + ret = kIOReturnSuccess; + break; + + case kPMGetSystemSleepType: + if (1 == arguments->scalarOutputCount) + { + ret = this->secureGetSystemSleepType( + (uint32_t *) &arguments->scalarOutput[0]); + } + break; /* case kPMMethodCopySystemTimeline: // intentional fallthrough diff --git a/iokit/Kernel/RootDomainUserClient.h b/iokit/Kernel/RootDomainUserClient.h index 9e6be4003..3dece8c25 100644 --- a/iokit/Kernel/RootDomainUserClient.h +++ b/iokit/Kernel/RootDomainUserClient.h @@ -67,6 +67,8 @@ private: IOReturn secureSetUserAssertionLevels(uint32_t assertionBitfield); + IOReturn secureGetSystemSleepType( uint32_t *sleepType ); + public: virtual IOReturn clientClose( void ); diff --git a/libkern/c++/OSKext.cpp b/libkern/c++/OSKext.cpp index 1e4395043..73d92b9f9 100644 --- a/libkern/c++/OSKext.cpp +++ b/libkern/c++/OSKext.cpp @@ -7822,15 +7822,16 @@ OSKext::copyInfo(OSArray * infoKeys) lcp = (struct load_command *) (temp_kext_mach_hdr + 1); for (i = 0; i < temp_kext_mach_hdr->ncmds; i++) { if (lcp->cmd == LC_SEGMENT_KERNEL) { - kernel_segment_command_t * scp; + kernel_segment_command_t * segp; + kernel_section_t * secp; - scp = (kernel_segment_command_t *) lcp; + segp = (kernel_segment_command_t *) lcp; // 10543468 - if we jettisoned __LINKEDIT clear size info if (flags.jettisonLinkeditSeg) { - if (strncmp(scp->segname, SEG_LINKEDIT, sizeof(scp->segname)) == 0) { - scp->vmsize = 0; - scp->fileoff = 0; - scp->filesize = 0; + if (strncmp(segp->segname, SEG_LINKEDIT, sizeof(segp->segname)) == 0) { + segp->vmsize = 0; + segp->fileoff = 0; + segp->filesize = 0; } } #if 0 @@ -7838,11 +7839,15 @@ OSKext::copyInfo(OSArray * infoKeys) kOSKextLogErrorLevel | kOSKextLogGeneralFlag, "%s: LC_SEGMENT_KERNEL segname '%s' vmaddr 0x%llX 0x%lX vmsize %llu nsects %u", - __FUNCTION__, scp->segname, scp->vmaddr, - VM_KERNEL_UNSLIDE(scp->vmaddr), - scp->vmsize, scp->nsects); + __FUNCTION__, segp->segname, segp->vmaddr, + VM_KERNEL_UNSLIDE(segp->vmaddr), + segp->vmsize, segp->nsects); #endif - scp->vmaddr = VM_KERNEL_UNSLIDE(scp->vmaddr); + segp->vmaddr = VM_KERNEL_UNSLIDE(segp->vmaddr); + + for (secp = firstsect(segp); secp != NULL; secp = nextsect(segp, secp)) { + secp->addr = VM_KERNEL_UNSLIDE(secp->addr); + } } lcp = (struct load_command *)((caddr_t)lcp + lcp->cmdsize); } diff --git a/osfmk/conf/files.x86_64 b/osfmk/conf/files.x86_64 index 88d449c78..02f3cadf8 100644 --- a/osfmk/conf/files.x86_64 +++ b/osfmk/conf/files.x86_64 @@ -96,7 +96,6 @@ osfmk/i386/mtrr.c optional config_mtrr osfmk/console/i386/serial_console.c optional com device-driver -osfmk/console/panic_dialog.c optional vc device-driver osfmk/console/video_console.c optional vc device-driver osfmk/console/i386/video_scroll.c optional vc device-driver diff --git a/osfmk/console/panic_dialog.c b/osfmk/console/panic_dialog.c deleted file mode 100644 index ca0acb6d1..000000000 --- a/osfmk/console/panic_dialog.c +++ /dev/null @@ -1,970 +0,0 @@ -/* - * Copyright (c) 2002-2006 Apple Computer, Inc. All rights reserved. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. The rights granted to you under the License - * may not be used to create, or enable the creation or redistribution of, - * unlawful or unlicensed copies of an Apple operating system, or to - * circumvent, violate, or enable the circumvention or violation of, any - * terms of an Apple operating system software license agreement. - * - * Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -extern struct vc_info vinfo; -extern boolean_t panicDialogDesired; - -#include "panic_image.c" - -void panic_ui_initialize(const unsigned char * system_clut); -int panic_dialog_set_image( const unsigned char * ptr, unsigned int size ); -void panic_dialog_get_image(const unsigned char **ptr, unsigned int *size); -void draw_panic_dialog( void ); -void panic_dialog_test( void ); - -static int panic_dialog_verify( const struct panicimage * data, unsigned int size ); -static int pixels_needed_to_blit_digit( int digit ); -static void blit_digit( int digit ); -static const char * strnstr(const char * s, const char * find, size_t slen); -static void panic_blit_rect(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, int transparent, - const unsigned char * dataPtr); - -static int panic_info_x; -static int panic_info_y; - -static const unsigned char * active_clut = NULL; /* This is a copy of the active clut */ - -static boolean_t panicDialogDrawn = FALSE; - -static const struct panicimage * panic_dialog = NULL; /* the active panic dialog */ -static const unsigned char * panic_dialog_data = NULL; /* where the image data starts */ -static const unsigned char * panic_dialog_clut = NULL; /* where the clut used for the image starts */ - -static const unsigned char *curr_image_ptr; /* If NULL, the default panic - dialog is active */ -static unsigned int curr_image_size = 0; - -#define FONT_WIDTH 8 -#define FONT_HEIGHT 16 -static unsigned short rendered_font[FONT_HEIGHT][FONT_WIDTH]; - -#define VERSIONBUF_LEN 20 -static char versionbuf[VERSIONBUF_LEN]; /* ####.###~###\0 */ - -#define isdigit(d) ((d) >= '0' && (d) <= '9') - -#define CLUT_ENTRIES 256 -#define CLUT_SIZE (CLUT_ENTRIES * 3) - - -/* - * This routine sets up the default panic dialog - */ - -extern unsigned char iso_font[]; -extern const char version[]; - -void -panic_ui_initialize(const unsigned char * system_clut) -{ - char vstr[VERSIONBUF_LEN]; - - panic_dialog_set_image( NULL, 0 ); - - active_clut = system_clut; - - strlcpy(vstr, "custom", VERSIONBUF_LEN); - - /* Convert xnu-####.###.obj~### into ####.###~### */ - - if (version[0]) { - const char *versionpos = strnstr(version, "xnu-", VERSIONBUF_LEN); - - if (versionpos) { - int len, i; - - vstr[0] = '\0'; - - for (i = 0, len = 4; len < VERSIONBUF_LEN; len++) { - if (isdigit(versionpos[len]) || versionpos[len] == '.') { /* extract ####.###. */ - vstr[i++] = versionpos[len]; - continue; - } - break; - } - - if ( versionpos[len-1] == '.' ) /* remove trailing period if present */ - i--; - - for (; len < VERSIONBUF_LEN; len++) { /* skip to next digit if present */ - if ( !isdigit(versionpos[len]) ) - continue; - break; - } - - if ( versionpos[len-1] == '~' ) { /* extract ~### if present */ - vstr[i++] = versionpos[len-1]; - for (; len < VERSIONBUF_LEN; len++) { /* extract ### */ - if ( isdigit(versionpos[len]) ) { - vstr[i++] = versionpos[len]; - continue; - } - break; - } - } - - vstr[i] = '\0'; - } - } - - strlcpy(versionbuf, vstr, VERSIONBUF_LEN); -} - - - -void -panic_dialog_test( void ) -{ - boolean_t o_panicDialogDrawn = panicDialogDrawn; - boolean_t o_panicDialogDesired = panicDialogDesired; - unsigned int o_logPanicDataToScreen = logPanicDataToScreen; - unsigned long o_panic_caller = panic_caller; - unsigned int o_panicDebugging = panicDebugging; - - panicDebugging = TRUE; - panic_caller = (unsigned long)(char *)__builtin_return_address(0); - logPanicDataToScreen = FALSE; - panicDialogDesired = TRUE; - panicDialogDrawn = FALSE; - - draw_panic_dialog(); - - panicDebugging = o_panicDebugging; - panic_caller = o_panic_caller; - logPanicDataToScreen = o_logPanicDataToScreen; - panicDialogDesired = o_panicDialogDesired; - panicDialogDrawn = o_panicDialogDrawn; -} - - -void -draw_panic_dialog( void ) -{ - if (!panicDialogDrawn && panicDialogDesired) { - if ( !logPanicDataToScreen ) { - int pd_x, pd_y; - int count, nibble, indx; - struct ether_addr kdp_mac_addr; - unsigned int panic_dialog_count, ip_addr; - char panic_num_chars[13+8+1], mac_addr_chars[17+1], ip_addr_chars[15+1]; - struct { - int pixels; - char * chars; - } panic_dialog_info[3]; - - - /* dim the screen 50% before putting up panic dialog */ - dim_screen(); - - /* set up to draw background box */ - /* by locating where the upper left corner is placed */ - - pd_x = (int)((vinfo.v_width/2) - panic_dialog->pd_width/2); - pd_y = (int)((vinfo.v_height/2) - panic_dialog->pd_height/2); - - /* draw panic dialog at pd_x/pd_y */ - panic_blit_rect(pd_x, pd_y, panic_dialog->pd_width, - panic_dialog->pd_height, 0, - panic_dialog_data); - - panic_dialog_count = 0; /* number of info items to display at the bottom of dialog */ - - if (panicDebugging) { - int x1, x2; - - /* - * PANIC CALLER - * - * don't display the panic caller if it is 0 - * - */ - - if ( panic_caller != 0 ) { - /* Calculate the pixels need to generate the panic number */ - panic_dialog_info[panic_dialog_count].pixels = 0; - - for ( indx=1, count=0; count < 13; count++ ) { - if ( versionbuf[count] == '\0' ) - break; - - panic_num_chars[indx++] = versionbuf[count]; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( versionbuf[count] ); - } - - panic_num_chars[indx++] = ':'; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( ':' ); - - for ( count=8; count != 0; count-- ) { - nibble = (int)((panic_caller >> ((count-1)<<2)) &0xF); - panic_num_chars[indx++] = nibble; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble ); - } - - panic_num_chars[0] = indx; - panic_dialog_info[panic_dialog_count].chars = panic_num_chars; - panic_dialog_count++; - } - - /* - * MAC ADDRESS - * - * if the mac address is not available, then use ff:ff:ff:ff:ff:ff - * - */ - - kdp_mac_addr = kdp_get_mac_addr(); - - /* If no mac_addr has been set, then force to -1 */ - if( ! (kdp_mac_addr.ether_addr_octet[0] || kdp_mac_addr.ether_addr_octet[1] || kdp_mac_addr.ether_addr_octet[2] - || kdp_mac_addr.ether_addr_octet[3] || kdp_mac_addr.ether_addr_octet[4] || kdp_mac_addr.ether_addr_octet[5])) { - for (count = 0; count < 6; count++ ) - kdp_mac_addr.ether_addr_octet[count] = -1; - } - - panic_dialog_info[panic_dialog_count].pixels = 0; - - for (indx=1, count=0; count < 6; count++ ) { - nibble = (kdp_mac_addr.ether_addr_octet[count] & 0xf0) >> 4; - mac_addr_chars[indx++] = nibble; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble ); - - nibble = kdp_mac_addr.ether_addr_octet[count] & 0xf; - mac_addr_chars[indx++] = nibble; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( nibble ); - - if( count < 5 ) { - mac_addr_chars[indx++] = ':'; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( ':' ); - } - } - - mac_addr_chars[0] = indx; - panic_dialog_info[panic_dialog_count].chars = mac_addr_chars; - panic_dialog_count++; - - /* - * IP ADDRESS - * - * do not display the ip addresses if the machine isn't attachable. - * there's no sense in possibly confusing people. - */ - - if ( (ip_addr = (unsigned int) ntohl(kdp_get_ip_address())) != 0 ) { - int d1, d2, d3; - - panic_dialog_info[panic_dialog_count].pixels = 0; - - for ( indx=1, count=0; count < 4; count++ ) { - nibble = (ip_addr & 0xff000000 ) >> 24; - - d3 = (nibble % 10) ; nibble = nibble / 10; - d2 = (nibble % 10) ; nibble = nibble / 10; - d1 = (nibble % 10) ; - - if( d1 != 0 ) { - ip_addr_chars[indx++] = d1; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d1 ); - } - - ip_addr_chars[indx++] = d2; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d2 ); - - ip_addr_chars[indx++] = d3; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( d3 ); - - if ( count < 3 ) { - ip_addr_chars[indx++] = '.'; - panic_dialog_info[panic_dialog_count].pixels += pixels_needed_to_blit_digit( '.' ); - } - - d1= d2 = d3 = 0; - ip_addr = ip_addr << 8; - } - - ip_addr_chars[0] = indx; - panic_dialog_info[panic_dialog_count].chars = ip_addr_chars; - panic_dialog_count++; - } - - - /* vertical alignment for information to be displayed */ - panic_info_y = (int)((vinfo.v_height/2) + panic_dialog->pd_height/2 - (panic_dialog->pd_info_height)); - - /* blit out all the information we gathered */ - - switch ( panic_dialog_count ) { - case 1 : /* one item is centered */ - panic_info_x = (int)((vinfo.v_width/2) - (panic_dialog_info[0].pixels/2)); - for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++) - blit_digit(panic_dialog_info[0].chars[indx]); - - break; - - case 2 : /* left centered and right centered */ - x1 = ((panic_dialog->pd_width/2) - panic_dialog_info[0].pixels)/2; - panic_info_x = (int)(((vinfo.v_width/2) - (panic_dialog->pd_width/2)) + x1); - - for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++) - blit_digit(panic_dialog_info[0].chars[indx]); - - x2 = ((panic_dialog->pd_width/2) - panic_dialog_info[1].pixels)/2; - panic_info_x = (int)((vinfo.v_width/2) + x2); - - for (indx=1; indx < panic_dialog_info[1].chars[0]; indx++) - blit_digit(panic_dialog_info[1].chars[indx]); - - break; - - case 3 : /* left centered, middle and right centered */ - x1 = ((panic_dialog->pd_width/2) - panic_dialog_info[0].pixels - (panic_dialog_info[1].pixels/2))/2; - panic_info_x = (int)(((vinfo.v_width/2) - (panic_dialog->pd_width/2)) + x1); - - for (indx=1; indx < panic_dialog_info[0].chars[0]; indx++) - blit_digit(panic_dialog_info[0].chars[indx]); - - panic_info_x = (int)((vinfo.v_width/2) - (panic_dialog_info[1].pixels/2)); - - for (indx=1; indx < panic_dialog_info[1].chars[0]; indx++) - blit_digit(panic_dialog_info[1].chars[indx]); - - x2 = ((panic_dialog->pd_width/2) - panic_dialog_info[2].pixels - (panic_dialog_info[1].pixels/2))/2; - panic_info_x = (int)((vinfo.v_width/2) + x2 + (panic_dialog_info[1].pixels/2)); - - for (indx=1; indx < panic_dialog_info[2].chars[0]; indx++) - blit_digit(panic_dialog_info[2].chars[indx]); - - break; - - default : /* nothing */ - break; - - } /* switch */ - } /* if panic_deugging */ - } /* if ! logPanicDataToScreen */ - } /* if ! panicDialogDrawn && ! panicDialogDesired */ - - panicDialogDrawn = TRUE; - panicDialogDesired = FALSE; -} - - -/* - * This routine installs a new panic dialog - * If ptr is NULL, then the default "built-in" panic dialog will be installed. - * note: It is the caller that must take care of deallocating memory used for the previous panic dialog - */ - -int -panic_dialog_set_image( const unsigned char * ptr, unsigned int size ) -{ - int error; - unsigned int newsize; - const struct panicimage * newimage; - - /* if ptr is NULL, restore panic image to built-in default */ - if ( ptr == NULL ) { - newimage = &panic_dialog_default; - newsize = (unsigned int)(sizeof(struct panicimage) + newimage->pd_dataSize); - } - else { - newimage = (const struct panicimage *)ptr; - newsize = size; - } - - if ( (error = panic_dialog_verify( newimage, newsize )) ) - return (error); - - panic_dialog = newimage; - panic_dialog_data = &panic_dialog->data[0]; - panic_dialog_clut = &panic_dialog->data[panic_dialog->pd_dataSize-CLUT_SIZE]; - - curr_image_ptr = ptr; - curr_image_size = size; - - return (0); -} - - -/* - * This routines returns the current address of the panic dialog - * If the default panic dialog is active, then *ptr will be NULL - */ - -void -panic_dialog_get_image(const unsigned char ** ptr, unsigned int * size ) -{ - *ptr = curr_image_ptr; - *size = curr_image_size; -} - - -/* - * This routine verifies the panic dialog image is valid. - */ - -static int -panic_dialog_verify( const struct panicimage * newimage, unsigned int size ) -{ - unsigned int sum, i; - - if ( size < (sizeof(struct panicimage) + newimage->pd_dataSize) ) - return EINVAL; - - if ( newimage->pd_tag != 0x524E4D70 /* 'RNMp' */ ) - return EINVAL; - - size = newimage->pd_dataSize-CLUT_SIZE; - for (sum=0,i=0; idata[i]; - sum <<= sum&1; - } - - if ( sum != newimage->pd_sum ) - return EINVAL; - - return 0; -} - - -/* - * Service Routines for managing the panic dialog - */ - - -static const struct rendered_num * find_rendered_digit( int digit ); -static void panic_blit_rect_8(unsigned int x, unsigned int y, - unsigned int width, unsigned int height, - int transparent, const unsigned char *dataPtr); -static void panic_blit_rect_16(unsigned int x, unsigned int y, - unsigned int width, unsigned int height, - int transparent, const unsigned char *dataPtr); -static void panic_blit_rect_32(unsigned int x, unsigned int y, - unsigned int width, unsigned int height, - int transparent, const unsigned char *dataPtr); -static void panic_blit_rect_30(unsigned int x, unsigned int y, - unsigned int width, unsigned int height, - int transparent, const unsigned char *dataPtr); -static int decode_rle(const unsigned char *dataPtr, - unsigned int *quantity, unsigned int *depth, - const unsigned char **value); - - -/* Utilities to convert 8 bit/gray */ -static unsigned int make24bitcolor( unsigned int index, const unsigned char * clut ); -static unsigned char findIndexMatch( unsigned char index ); -static unsigned char color24togray8( unsigned int color24 ); -static unsigned char findbestgray( unsigned int color24 ); -static int isActiveClutOK( void ); - -static int -pixels_needed_to_blit_digit(__unused int digit ) -{ - return FONT_WIDTH; -} - - -static const struct rendered_num * -find_rendered_digit( int digit ) -{ - //extern unsigned char iso_font[]; - const struct rendered_num *digitPtr; - - if ( digit < 16 ) { - if ( digit < 10 ) - digit += 0x30; - else - digit += 0x37; - } - - digitPtr = (const struct rendered_num *) &iso_font[digit * 16]; - return digitPtr; -} - - -static void -blit_digit( int digit ) -{ - const unsigned char *raw_data = - (const unsigned char *)find_rendered_digit(digit); - unsigned width = FONT_WIDTH, height = FONT_HEIGHT; - int row; - - for (row=0; row=0; j--) { - - if ( bits & 0x80 ) - rendered_font[row][j] = OSSwapBigToHostInt16(0x0100 | panic_dialog->pd_info_color[0]); - else - rendered_font[row][j] = OSSwapBigToHostInt16(0x0100 | panic_dialog->pd_info_color[1]); - bits <<= 1; - } - } - - panic_blit_rect( panic_info_x, panic_info_y , width, height, 255, (unsigned char *) rendered_font); - panic_info_x += width; -} - - -static void -panic_blit_rect(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, int transparent, - const unsigned char *dataPtr) -{ - if(!vinfo.v_depth) - return; - - switch( vinfo.v_depth) { - case 8: - panic_blit_rect_8( x, y, width, height, transparent, dataPtr); - break; - case 16: - panic_blit_rect_16( x, y, width, height, transparent, dataPtr); - break; - case 32: - panic_blit_rect_32( x, y, width, height, transparent, dataPtr); - break; - case 30: - panic_blit_rect_30( x, y, width, height, transparent, dataPtr); - break; - } -} - -/* - * panic_blit_rect_8 decodes the RLE encoded image data on the fly, looks up the - * color by indexing into the clut, or attempts to find the best index. - */ - -static void -panic_blit_rect_8(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, __unused int transparent, - const unsigned char * dataPtr) -{ - volatile unsigned char * dst; - unsigned int line, col, i; - static int clutOK = -1; - unsigned int data, quantity, depth; - const unsigned char *value; - - - if ( clutOK == -1 ) - clutOK = isActiveClutOK(); - - dst = (volatile unsigned char *) (vinfo.v_baseaddr + - (y * vinfo.v_rowbytes) + - x); - - quantity = 0; - i = 0; - - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - - if (quantity == 0) { - dataPtr += decode_rle(dataPtr, &quantity, &depth, &value); - i = 0; - } - - if ( clutOK ) - data = value[i++]; - else - data = findIndexMatch( value[i++] ); - - *(dst + col) = data; - - if ( i == depth ) { - i = 0; - quantity--; - } - } - - dst = (volatile unsigned char *) (((uintptr_t)dst) + vinfo.v_rowbytes); - } -} - -/* - * panic_blit_rect_16 decodes the RLE encoded image data on the fly, looks up the - * color by indexing into the clut, uses the top 5 bits to fill in each of the three - * pixel values (RGB) and writes each pixel to the screen. - */ - -static void -panic_blit_rect_16(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, __unused int transparent, - const unsigned char *dataPtr) -{ - - volatile unsigned short * dst; - unsigned int line, col, i; - unsigned int quantity, index, data, depth; - const unsigned char *value; - - dst = (volatile unsigned short *) (vinfo.v_baseaddr + - (y * vinfo.v_rowbytes) + - (x * 2)); - - quantity = 0; - i = 0; - - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - - if (quantity == 0) { - dataPtr += decode_rle(dataPtr, &quantity, &depth, &value); - i = 0; - } - - index = value[i++] * 3; - - data = ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 0])) << 7) - | ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 1])) << 2) - | ( (unsigned short) (0xf8 & (panic_dialog_clut[index + 2])) >> 3); - - *(dst + col) = data; - - if ( i == depth ) { - i = 0; - quantity--; - } - } - - dst = (volatile unsigned short *) (((uintptr_t)dst) + vinfo.v_rowbytes); - } - } - -/* - * panic_blit_rect_32 decodes the RLE encoded image data on the fly, and fills - * in each of the three pixel values from the clut (RGB) for each pixel and - * writes it to the screen. - */ - -static void -panic_blit_rect_32(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, __unused int transparent, - const unsigned char *dataPtr) -{ - volatile unsigned int * dst; - unsigned int line, col, i; - unsigned int quantity, index, data, depth; - const unsigned char *value; - - - dst = (volatile unsigned int *) (vinfo.v_baseaddr + - (y * vinfo.v_rowbytes) + - (x * 4)); - - quantity = 0; - i = 0; - - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - - if (quantity == 0) { - dataPtr += decode_rle(dataPtr, &quantity, &depth, &value); - i = 0; - } - - index = value[i++] * 3; - - data = ( (unsigned int) panic_dialog_clut[index + 0] << 16) - | ( (unsigned int) panic_dialog_clut[index + 1] << 8) - | ( (unsigned int) panic_dialog_clut[index + 2]); - - *(dst + col) = data; - - if ( i == depth ) { - i = 0; - quantity--; - } - } - - dst = (volatile unsigned int *) (((uintptr_t)dst) + vinfo.v_rowbytes); - } -} - -/* - * panic_blit_rect_30 decodes the RLE encoded image data on the fly, and fills - * in each of the three pixel values from the clut (RGB) for each pixel and - * writes it to the screen. - */ - -static void -panic_blit_rect_30(unsigned int x, unsigned int y, unsigned int width, - unsigned int height, __unused int transparent, - const unsigned char *dataPtr) -{ - volatile unsigned int * dst; - unsigned int line, col, i; - unsigned int quantity, index, data, depth; - const unsigned char *value; - unsigned int in; - - dst = (volatile unsigned int *) (vinfo.v_baseaddr + - (y * vinfo.v_rowbytes) + - (x * 4)); - - quantity = 0; - i = 0; - - for( line = 0; line < height; line++) { - for( col = 0; col < width; col++) { - - if (quantity == 0) { - dataPtr += decode_rle(dataPtr, &quantity, &depth, &value); - i = 0; - } - - index = value[i++] * 3; - in = panic_dialog_clut[index + 0]; - data = (in << 2) | (in >> 6); - - in = panic_dialog_clut[index + 1]; - data |= (in << (2 + 10)) | ((3 << 10) & (in << 4)); - - in = panic_dialog_clut[index + 2]; - data |= (in << (2 + 20)) | ((3 << 20) & (in << 14)); - - *(dst + col) = data; - - if ( i == depth ) { - i = 0; - quantity--; - } - } - - dst = (volatile unsigned int *) (((uintptr_t)dst) + vinfo.v_rowbytes); - } -} - - -/* - decode_rle decodes a single quantity/value run of a "modified-RLE" encoded - image. The encoding works as follows: - - The run is described in the first byte. If the MSB is zero, then the next seven bits - are the quantity of bytes that follow that make up the run of value bytes. (see case 0) - - If the MSB is set, bits 0-3 are the quantity's least significant 4 bits. If bit 5 is set, - then the quantity is further described in the next byte, where an additional 7 bits (4-10) - worth of quantity will be found. If the MSB of this byte is set, then an additional - 7 bits (11-17) worth of quantity will be found in the next byte. This repeats until the MSB of - a quantity byte is zero, thus ending the run of quantity bytes. - - Bits 5/6 of the first byte, describe the number of bytes in the value run following the quantity run. - These bits describe value runs of 1 to 4 bytes. And the quantity describe the number of value runs. - (see cases 1-4) - - encodings are: (q = quantity, v = value, c = quantity continues) - - case 0: [ 0 q6-q0 ] [ v7-v0 ] ... [ v7-v0 ] - case 1: [ 1 0 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] - case 2: [ 1 0 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] - case 3: [ 1 1 0 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] - case 4: [ 1 1 1 c q3-q0 ] [ c q10-q4 ] [ c q17-q11 ] [ q24-q18 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] [ v7-v0 ] -*/ - -static int -decode_rle(const unsigned char *dataPtr, unsigned int *quantity, - unsigned int *depth, const unsigned char **value ) -{ - unsigned int mask; - int i, runlen, runsize; - - i = 0; - mask = dataPtr[i] & 0xF0; - - if ( mask & 0x80 ) { - runsize = ((mask & 0x60) >> 5) + 1; - runlen = dataPtr[i++] & 0x0F; - - if ( mask & 0x10 ) { - int shift = 4; - - do { - mask = dataPtr[i] & 0x80; - runlen |= ((dataPtr[i++] & 0x7F) << shift); - shift+=7; - } while (mask); - } - } else { - runlen = 1; - runsize = dataPtr[i++]; - } - - *depth = runsize; - *quantity = runlen; - *value = &dataPtr[i]; - - return i+runsize; -} - - -/* From user mode Libc - this ought to be in a library */ -static const char * -strnstr(const char * s, const char * find, size_t slen) -{ - char c, sc; - size_t len; - - if ((c = *find++) != '\0') { - len = strlen(find); - do { - do { - if ((sc = *s++) == '\0' || slen-- < 1) - return (NULL); - } while (sc != c); - if (len > slen) - return (NULL); - } while (strncmp(s, find, len) != 0); - s--; - } - return s; -} - -/* - * these routines are for converting a color into grayscale - * in 8-bit mode, if the active clut is different than the - * clut used to create the panic dialog, then we must convert to gray - */ - -static unsigned int -make24bitcolor( unsigned int index, const unsigned char * clut ) -{ - unsigned int color24 = 0; - int i = index * 3; - - color24 |= clut[i+0] << 16; - color24 |= clut[i+1] << 8; - color24 |= clut[i+2]; - - return color24; -} - - -static unsigned char -findbestgray( unsigned int color24 ) -{ - unsigned int c24, rel, bestindex=-1, bestgray = -1; - unsigned char gray8, c8; - int i; -#define abs(v) ((v) > 0)?(v):-(v) - - gray8 = color24togray8( color24 ); /* convert the original color into grayscale */ - - for (i=0; i>16)&0xff) != ((c24>>8)&0xff)) || ((c24>>8)&0xff) != (c24 & 0xff) ) - continue; /* only match against grays */ - - c8 = c24 & 0xFF; /* isolate the gray */ - - /* find the gray with the smallest difference */ - rel = abs( gray8 - c8 ); - if ( rel < bestgray ) { - bestgray = rel; - bestindex = i; - } - } - - /* Did we fail to find any grays ? */ - if (ULONG_MAX == bestindex) { - /* someday we should look for the best color match */ - /* but for now just return the gray as the index */ - /* at least there might be something readble on the display */ - - bestindex = gray8; - } - - return bestindex; -#undef abs -} - - -static unsigned char -color24togray8( unsigned int color24 ) -{ - int R, G, B; - int Gray; - unsigned char gray8; - - R = (color24 & 0xFF0000) >> 16 ; - G = (color24 & 0xFF00) >> 8 ; - B = (color24 & 0xFF); - - Gray = (R*30) + (G*59) + (B*11); - gray8 = (unsigned char) ((Gray + 50) / 100); - return gray8; -} - - -static unsigned char -findIndexMatch( unsigned char index ) -{ - static unsigned int last_in_index = -1; - static unsigned char last_index; - unsigned int sc; - - if ( index == last_in_index ) - return last_index; - - last_in_index = index; - sc = make24bitcolor( index, panic_dialog_clut ); - last_index = findbestgray( sc ); /* find the nearest matching gray in the active clut */ - - return last_index; -} - -static int -isActiveClutOK( void ) -{ - int i; - int r = 1; /* assume OK */ - - for (i=0; i #include #include +#include diagWork dgWork; uint64_t lastRuptClear = 0ULL; + int diagCall64(x86_saved_state_t * state) { @@ -81,18 +83,18 @@ diagCall64(x86_saved_state_t * state) uint64_t selector, data; uint64_t currNap, durNap; x86_saved_state64_t *regs; + boolean_t diagflag; assert(is_saved_state64(state)); regs = saved_state64(state); - - if (!(dgWork.dgFlags & enaDiagSCs)) - return 0; /* If not enabled, cause an exception */ - + diagflag = ((dgWork.dgFlags & enaDiagSCs) != 0); selector = regs->rdi; switch (selector) { /* Select the routine */ case dgRuptStat: /* Suck Interruption statistics */ (void) ml_set_interrupts_enabled(TRUE); + if (diagflag == 0) + break; data = regs->rsi; /* Get the number of processors */ if (data == 0) { /* If no location is specified for data, clear all @@ -136,6 +138,9 @@ diagCall64(x86_saved_state_t * state) case dgGzallocTest: { (void) ml_set_interrupts_enabled(TRUE); + if (diagflag == 0) + break; + unsigned *ptr = (unsigned *)kalloc(1024); kfree(ptr, 1024); *ptr = 0x42; @@ -147,6 +152,9 @@ diagCall64(x86_saved_state_t * state) case dgPermCheck: { (void) ml_set_interrupts_enabled(TRUE); + if (diagflag == 0) + break; + return pmap_permissions_verify(kernel_pmap, kernel_map, 0, ~0ULL); } break; diff --git a/osfmk/i386/Diagnostics.h b/osfmk/i386/Diagnostics.h index 3a2ffc17a..e2c264a8b 100644 --- a/osfmk/i386/Diagnostics.h +++ b/osfmk/i386/Diagnostics.h @@ -68,7 +68,6 @@ int diagCall64(x86_saved_state_t *regs); #define dgMapPage 16 #define dgGzallocTest 17 #define dgBind 18 -#define dgPproc 19 #define dgAcntg 20 #define dgKlra 21 #define dgKfree 22 diff --git a/osfmk/i386/cpuid.c b/osfmk/i386/cpuid.c index abb0b94ed..46061d43a 100644 --- a/osfmk/i386/cpuid.c +++ b/osfmk/i386/cpuid.c @@ -587,7 +587,7 @@ cpuid_set_generic_info(i386_cpu_info_t *info_p) info_p->cpuid_features = quad(reg[ecx], reg[edx]); /* Get "processor flag"; necessary for microcode update matching */ - info_p->cpuid_processor_flag = (rdmsr64(MSR_IA32_PLATFORM_ID)>> 50) & 3; + info_p->cpuid_processor_flag = (rdmsr64(MSR_IA32_PLATFORM_ID)>> 50) & 0x7; /* Fold extensions into family/model */ if (info_p->cpuid_family == 0x0f) diff --git a/osfmk/i386/hibernate_i386.c b/osfmk/i386/hibernate_i386.c index 6cdc1cec9..83c33dba5 100644 --- a/osfmk/i386/hibernate_i386.c +++ b/osfmk/i386/hibernate_i386.c @@ -51,7 +51,7 @@ extern ppnum_t max_ppnum; /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ hibernate_page_list_t * -hibernate_page_list_allocate(void) +hibernate_page_list_allocate(boolean_t log) { ppnum_t base, num; vm_size_t size; @@ -167,9 +167,8 @@ hibernate_page_list_allocate(void) bitmap->last_page = dram_ranges[bank].last_page; bitmap->bitmapwords = (bitmap->last_page + 1 - bitmap->first_page + 31) >> 5; - kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n", bank, - bitmap->first_page, - bitmap->last_page); + if (log) kprintf("hib bank[%d]: 0x%x000 end 0x%xfff\n", + bank, bitmap->first_page, bitmap->last_page); bitmap = (hibernate_bitmap_t *) &bitmap->bitmap[bitmap->bitmapwords]; } @@ -181,6 +180,7 @@ hibernate_page_list_allocate(void) void hibernate_page_list_setall_machine( __unused hibernate_page_list_t * page_list, __unused hibernate_page_list_t * page_list_wired, + __unused boolean_t preflight, __unused uint32_t * pagesOut) { } @@ -229,42 +229,11 @@ hibernate_processor_setup(IOHibernateImageHeader * header) void hibernate_vm_lock(void) { - if (current_cpu_datap()->cpu_hibernate) - { - vm_page_lock_queues(); - lck_mtx_lock(&vm_page_queue_free_lock); - - if (vm_page_local_q) { - uint32_t i; - - for (i = 0; i < vm_page_local_q_count; i++) { - struct vpl *lq; - - lq = &vm_page_local_q[i].vpl_un.vpl; - - VPL_LOCK(&lq->vpl_lock); - } - } - } + if (current_cpu_datap()->cpu_hibernate) hibernate_vm_lock_queues(); } void hibernate_vm_unlock(void) { - if (current_cpu_datap()->cpu_hibernate) - { - if (vm_page_local_q) { - uint32_t i; - - for (i = 0; i < vm_page_local_q_count; i++) { - struct vpl *lq; - - lq = &vm_page_local_q[i].vpl_un.vpl; - - VPL_UNLOCK(&lq->vpl_lock); - } - } - lck_mtx_unlock(&vm_page_queue_free_lock); - vm_page_unlock_queues(); - } + if (current_cpu_datap()->cpu_hibernate) hibernate_vm_unlock_queues(); } diff --git a/osfmk/i386/misc_protos.h b/osfmk/i386/misc_protos.h index 4186c623b..0007b3321 100644 --- a/osfmk/i386/misc_protos.h +++ b/osfmk/i386/misc_protos.h @@ -69,7 +69,6 @@ extern void panic_io_port_read(void); extern void remote_kdb(void); extern void clear_kdb_intr(void); -extern void draw_panic_dialog(void); extern void cpu_init(void); #ifdef __i386__ extern void cpu_shutdown(void); diff --git a/osfmk/i386/task.h b/osfmk/i386/task.h index b2bedd46a..b4035d57f 100644 --- a/osfmk/i386/task.h +++ b/osfmk/i386/task.h @@ -62,5 +62,9 @@ #define MACHINE_TASK \ struct user_ldt * i386_ldt; \ - void* task_debug; + void* task_debug; \ + uint64_t uexc_range_start; \ + uint64_t uexc_range_size; \ + uint64_t uexc_handler; + diff --git a/osfmk/i386/trap.c b/osfmk/i386/trap.c index a2a805a03..d7b460878 100644 --- a/osfmk/i386/trap.c +++ b/osfmk/i386/trap.c @@ -221,10 +221,6 @@ user_page_fault_continue( vaddr = uregs->cr2; } - if (__probable((kr == KERN_SUCCESS) || (kr == KERN_ABORTED))) { - thread_exception_return(); - /*NOTREACHED*/ - } /* PAL debug hook */ pal_dbg_page_fault( thread, vaddr, kr ); @@ -1110,6 +1106,7 @@ user_trap( break; case T_PAGE_FAULT: + { prot = VM_PROT_READ; if (err & T_PF_WRITE) @@ -1122,9 +1119,13 @@ user_trap( prot, FALSE, THREAD_ABORTSAFE, NULL, 0); - user_page_fault_continue(kret); - + if (__probable((kret == KERN_SUCCESS) || (kret == KERN_ABORTED))) { + thread_exception_return(); /* NOTREACHED */ + } + + user_page_fault_continue(kret); + } /* NOTREACHED */ break; case T_SSE_FLOAT_ERROR: diff --git a/osfmk/kern/hibernate.c b/osfmk/kern/hibernate.c index c88c0fd1e..431c4795c 100644 --- a/osfmk/kern/hibernate.c +++ b/osfmk/kern/hibernate.c @@ -51,8 +51,7 @@ hibernate_setup(IOHibernateImageHeader * header, boolean_t vmflush, hibernate_page_list_t ** page_list_ret, hibernate_page_list_t ** page_list_wired_ret, - hibernate_page_list_t ** page_list_pal_ret, - boolean_t * encryptedswap) + hibernate_page_list_t ** page_list_pal_ret) { hibernate_page_list_t * page_list = NULL; hibernate_page_list_t * page_list_wired = NULL; @@ -63,19 +62,19 @@ hibernate_setup(IOHibernateImageHeader * header, *page_list_wired_ret = NULL; *page_list_pal_ret = NULL; - if (vmflush) + if (vmflush && dp_isssd) hibernate_flush_memory(); - page_list = hibernate_page_list_allocate(); + page_list = hibernate_page_list_allocate(TRUE); if (!page_list) return (KERN_RESOURCE_SHORTAGE); - page_list_wired = hibernate_page_list_allocate(); + page_list_wired = hibernate_page_list_allocate(FALSE); if (!page_list_wired) { kfree(page_list, page_list->list_size); return (KERN_RESOURCE_SHORTAGE); } - page_list_pal = hibernate_page_list_allocate(); + page_list_pal = hibernate_page_list_allocate(FALSE); if (!page_list_pal) { kfree(page_list, page_list->list_size); @@ -83,8 +82,6 @@ hibernate_setup(IOHibernateImageHeader * header, return (KERN_RESOURCE_SHORTAGE); } - *encryptedswap = dp_encryption; - // pages we could force out to reduce hibernate image size gobble_count = (uint32_t)((((uint64_t) page_list->page_count) * ((uint64_t) free_page_ratio)) / 100); @@ -92,14 +89,16 @@ hibernate_setup(IOHibernateImageHeader * header, hibernate_processor_setup(header); - HIBLOG("hibernate_alloc_pages flags %08x, gobbling %d pages\n", - header->processorFlags, gobble_count); - if (gobble_count) hibernate_gobble_pages(gobble_count, free_page_time); - *page_list_ret = page_list; - *page_list_wired_ret = page_list_wired; + HIBLOG("hibernate_alloc_pages act %d, inact %d, anon %d, throt %d, spec %d, wire %d, wireinit %d\n", + vm_page_active_count, vm_page_inactive_count, + vm_page_anonymous_count, vm_page_throttled_count, vm_page_speculative_count, + vm_page_wire_count, vm_page_wire_count_initial); + + *page_list_ret = page_list; + *page_list_wired_ret = page_list_wired; *page_list_pal_ret = page_list_pal; return (KERN_SUCCESS); diff --git a/osfmk/kern/task.c b/osfmk/kern/task.c index 96a00ff5a..1378bf415 100644 --- a/osfmk/kern/task.c +++ b/osfmk/kern/task.c @@ -495,6 +495,8 @@ task_create_internal( new_task->watchapplying = 0; #endif /* CONFIG_EMBEDDED */ + new_task->uexc_range_start = new_task->uexc_range_size = new_task->uexc_handler = 0; + if (parent_task != TASK_NULL) { new_task->sec_token = parent_task->sec_token; new_task->audit_token = parent_task->audit_token; diff --git a/osfmk/mach/task_info.h b/osfmk/mach/task_info.h index d62982d0c..d115f3826 100644 --- a/osfmk/mach/task_info.h +++ b/osfmk/mach/task_info.h @@ -188,7 +188,7 @@ typedef struct task_thread_times_info *task_thread_times_info_t; #define TASK_ABSOLUTETIME_INFO 1 struct task_absolutetime_info { - uint64_t total_user; /* total time */ + uint64_t total_user; uint64_t total_system; uint64_t threads_user; /* existing threads only */ uint64_t threads_system; diff --git a/osfmk/vm/vm_page.h b/osfmk/vm/vm_page.h index b9888628d..70050ffa3 100644 --- a/osfmk/vm/vm_page.h +++ b/osfmk/vm/vm_page.h @@ -424,7 +424,9 @@ unsigned int vm_page_throttled_count;/* How many inactives are throttled */ extern unsigned int vm_page_speculative_count; /* How many speculative pages are unclaimed? */ extern -unsigned int vm_page_wire_count; /* How many pages are wired? */ +unsigned int vm_page_wire_count; /* How many pages are wired? */ +extern +unsigned int vm_page_wire_count_initial; /* How many pages wired at startup */ extern unsigned int vm_page_free_target; /* How many do we want free? */ extern diff --git a/osfmk/vm/vm_resident.c b/osfmk/vm/vm_resident.c index a548c0600..c660d662c 100644 --- a/osfmk/vm/vm_resident.c +++ b/osfmk/vm/vm_resident.c @@ -4940,7 +4940,7 @@ hibernate_free_gobble_pages(void) } static boolean_t -hibernate_consider_discard(vm_page_t m) +hibernate_consider_discard(vm_page_t m, boolean_t preflight) { vm_object_t object = NULL; int refmod_state; @@ -4952,39 +4952,39 @@ hibernate_consider_discard(vm_page_t m) panic("hibernate_consider_discard: private"); if (!vm_object_lock_try(m->object)) { - hibernate_stats.cd_lock_failed++; + if (!preflight) hibernate_stats.cd_lock_failed++; break; } object = m->object; if (VM_PAGE_WIRED(m)) { - hibernate_stats.cd_found_wired++; + if (!preflight) hibernate_stats.cd_found_wired++; break; } if (m->precious) { - hibernate_stats.cd_found_precious++; + if (!preflight) hibernate_stats.cd_found_precious++; break; } if (m->busy || !object->alive) { /* * Somebody is playing with this page. */ - hibernate_stats.cd_found_busy++; + if (!preflight) hibernate_stats.cd_found_busy++; break; } if (m->absent || m->unusual || m->error) { /* * If it's unusual in anyway, ignore it */ - hibernate_stats.cd_found_unusual++; + if (!preflight) hibernate_stats.cd_found_unusual++; break; } if (m->cleaning) { - hibernate_stats.cd_found_cleaning++; + if (!preflight) hibernate_stats.cd_found_cleaning++; break; } if (m->laundry) { - hibernate_stats.cd_found_laundry++; + if (!preflight) hibernate_stats.cd_found_laundry++; break; } if (!m->dirty) @@ -5005,8 +5005,9 @@ hibernate_consider_discard(vm_page_t m) || (VM_PURGABLE_VOLATILE == object->purgable) || (VM_PURGABLE_EMPTY == object->purgable); - if (discard == FALSE) - hibernate_stats.cd_found_dirty++; + if (discard == FALSE) { + if (!preflight) hibernate_stats.cd_found_dirty++; + } } while (FALSE); @@ -5064,6 +5065,40 @@ hibernate_discard_page(vm_page_t m) #endif /* DEBUG */ } +/* + Grab locks for hibernate_page_list_setall() +*/ +void +hibernate_vm_lock_queues(void) +{ + vm_page_lock_queues(); + lck_mtx_lock(&vm_page_queue_free_lock); + + if (vm_page_local_q) { + uint32_t i; + for (i = 0; i < vm_page_local_q_count; i++) { + struct vpl *lq; + lq = &vm_page_local_q[i].vpl_un.vpl; + VPL_LOCK(&lq->vpl_lock); + } + } +} + +void +hibernate_vm_unlock_queues(void) +{ + if (vm_page_local_q) { + uint32_t i; + for (i = 0; i < vm_page_local_q_count; i++) { + struct vpl *lq; + lq = &vm_page_local_q[i].vpl_un.vpl; + VPL_UNLOCK(&lq->vpl_lock); + } + } + lck_mtx_unlock(&vm_page_queue_free_lock); + vm_page_unlock_queues(); +} + /* Bits zero in the bitmaps => page needs to be saved. All pages default to be saved, pages known to VM to not need saving are subtracted. @@ -5074,6 +5109,7 @@ void hibernate_page_list_setall(hibernate_page_list_t * page_list, hibernate_page_list_t * page_list_wired, hibernate_page_list_t * page_list_pal, + boolean_t preflight, uint32_t * pagesOut) { uint64_t start, end, nsec; @@ -5092,8 +5128,13 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, hibernate_bitmap_t * bitmap; hibernate_bitmap_t * bitmap_wired; + HIBLOG("hibernate_page_list_setall(preflight %d) start %p, %p\n", preflight, page_list, page_list_wired); - HIBLOG("hibernate_page_list_setall start %p, %p\n", page_list, page_list_wired); + if (preflight) { + page_list = NULL; + page_list_wired = NULL; + page_list_pal = NULL; + } #if DEBUG vm_page_lock_queues(); @@ -5111,16 +5152,23 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, clock_get_uptime(&start); - hibernate_page_list_zero(page_list); - hibernate_page_list_zero(page_list_wired); - hibernate_page_list_zero(page_list_pal); - - hibernate_stats.cd_vm_page_wire_count = vm_page_wire_count; - hibernate_stats.cd_pages = pages; + if (!preflight) { + hibernate_page_list_zero(page_list); + hibernate_page_list_zero(page_list_wired); + hibernate_page_list_zero(page_list_pal); + + hibernate_stats.cd_vm_page_wire_count = vm_page_wire_count; + hibernate_stats.cd_pages = pages; + } if (vm_page_local_q) { for (i = 0; i < vm_page_local_q_count; i++) - vm_page_reactivate_local(i, TRUE, TRUE); + vm_page_reactivate_local(i, TRUE, !preflight); + } + + if (preflight) { + vm_page_lock_queues(); + lck_mtx_lock(&vm_page_queue_free_lock); } m = (vm_page_t) hibernate_gobble_queue; @@ -5128,12 +5176,14 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, { pages--; count_wire--; - hibernate_page_bitset(page_list, TRUE, m->phys_page); - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) { + hibernate_page_bitset(page_list, TRUE, m->phys_page); + hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + } m = (vm_page_t) m->pageq.next; } - for( i = 0; i < real_ncpus; i++ ) + if (!preflight) for( i = 0; i < real_ncpus; i++ ) { if (cpu_data_ptr[i] && cpu_data_ptr[i]->cpu_processor) { @@ -5159,10 +5209,12 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, { pages--; count_wire--; - hibernate_page_bitset(page_list, TRUE, m->phys_page); - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); - - hibernate_stats.cd_total_free++; + if (!preflight) { + hibernate_page_bitset(page_list, TRUE, m->phys_page); + hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + + hibernate_stats.cd_total_free++; + } } } @@ -5173,10 +5225,12 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, { pages--; count_wire--; - hibernate_page_bitset(page_list, TRUE, m->phys_page); - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); - - hibernate_stats.cd_total_free++; + if (!preflight) { + hibernate_page_bitset(page_list, TRUE, m->phys_page); + hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + + hibernate_stats.cd_total_free++; + } } queue_iterate( &vm_page_queue_throttled, @@ -5185,15 +5239,15 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq ) { if ((kIOHibernateModeDiscardCleanInactive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); count_discard_inactive++; } else count_throttled++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } queue_iterate( &vm_page_queue_anonymous, @@ -5202,9 +5256,9 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq ) { if ((kIOHibernateModeDiscardCleanInactive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); if (m->dirty) count_discard_purgeable++; else @@ -5213,7 +5267,7 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, else count_zf++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } queue_iterate( &vm_page_queue_inactive, @@ -5222,9 +5276,9 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq ) { if ((kIOHibernateModeDiscardCleanInactive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); if (m->dirty) count_discard_purgeable++; else @@ -5233,7 +5287,7 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, else count_inactive++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } queue_iterate( &vm_page_queue_cleaned, @@ -5242,9 +5296,9 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq ) { if ((kIOHibernateModeDiscardCleanInactive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); if (m->dirty) count_discard_purgeable++; else @@ -5253,7 +5307,7 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, else count_cleaned++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } for( i = 0; i <= VM_PAGE_MAX_SPECULATIVE_AGE_Q; i++ ) @@ -5264,15 +5318,15 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq) { if ((kIOHibernateModeDiscardCleanInactive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); count_discard_speculative++; } else count_speculative++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } } @@ -5282,9 +5336,9 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, pageq ) { if ((kIOHibernateModeDiscardCleanActive & gIOHibernateMode) - && hibernate_consider_discard(m)) + && hibernate_consider_discard(m, preflight)) { - hibernate_page_bitset(page_list, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list, TRUE, m->phys_page); if (m->dirty) count_discard_purgeable++; else @@ -5293,26 +5347,29 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, else count_active++; count_wire--; - hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); + if (!preflight) hibernate_page_bitset(page_list_wired, TRUE, m->phys_page); } - // pull wired from hibernate_bitmap - - bitmap = &page_list->bank_bitmap[0]; - bitmap_wired = &page_list_wired->bank_bitmap[0]; - for (bank = 0; bank < page_list->bank_count; bank++) - { - for (i = 0; i < bitmap->bitmapwords; i++) - bitmap->bitmap[i] = bitmap->bitmap[i] | ~bitmap_wired->bitmap[i]; - bitmap = (hibernate_bitmap_t *) &bitmap->bitmap [bitmap->bitmapwords]; - bitmap_wired = (hibernate_bitmap_t *) &bitmap_wired->bitmap[bitmap_wired->bitmapwords]; + if (!preflight) { + // pull wired from hibernate_bitmap + bitmap = &page_list->bank_bitmap[0]; + bitmap_wired = &page_list_wired->bank_bitmap[0]; + for (bank = 0; bank < page_list->bank_count; bank++) + { + for (i = 0; i < bitmap->bitmapwords; i++) + bitmap->bitmap[i] = bitmap->bitmap[i] | ~bitmap_wired->bitmap[i]; + bitmap = (hibernate_bitmap_t *) &bitmap->bitmap [bitmap->bitmapwords]; + bitmap_wired = (hibernate_bitmap_t *) &bitmap_wired->bitmap[bitmap_wired->bitmapwords]; + } } // machine dependent adjustments - hibernate_page_list_setall_machine(page_list, page_list_wired, &pages); + hibernate_page_list_setall_machine(page_list, page_list_wired, preflight, &pages); - hibernate_stats.cd_count_wire = count_wire; - hibernate_stats.cd_discarded = count_discard_active + count_discard_inactive + count_discard_purgeable + count_discard_speculative + count_discard_cleaned; + if (!preflight) { + hibernate_stats.cd_count_wire = count_wire; + hibernate_stats.cd_discarded = count_discard_active + count_discard_inactive + count_discard_purgeable + count_discard_speculative + count_discard_cleaned; + } clock_get_uptime(&end); absolutetime_to_nanoseconds(end - start, &nsec); @@ -5335,6 +5392,11 @@ hibernate_page_list_setall(hibernate_page_list_t * page_list, vm_page_unlock_queues(); #endif /* DEBUG */ + if (preflight) { + lck_mtx_unlock(&vm_page_queue_free_lock); + vm_page_unlock_queues(); + } + KERNEL_DEBUG_CONSTANT(IOKDBG_CODE(DBG_HIBERNATE, 8) | DBG_FUNC_END, count_wire, *pagesOut, 0, 0, 0); } diff --git a/pexpert/conf/MASTER b/pexpert/conf/MASTER index 833878544..0c3099fec 100644 --- a/pexpert/conf/MASTER +++ b/pexpert/conf/MASTER @@ -88,8 +88,6 @@ options DEBUG # general debugging code # options MACH_ASSERT # # options CONFIG_DTRACE # dtrace support # -options PANIC_INFO # want kernel panic info # - options CONFIG_NO_PANIC_STRINGS # options CONFIG_NO_PRINTF_STRINGS # options CONFIG_NO_KPRINTF_STRINGS # diff --git a/pexpert/conf/MASTER.x86_64 b/pexpert/conf/MASTER.x86_64 index 9f0004250..a73bb602e 100644 --- a/pexpert/conf/MASTER.x86_64 +++ b/pexpert/conf/MASTER.x86_64 @@ -3,11 +3,11 @@ # Standard Apple Mac OS Configurations: # -------- ----- ------ --------------- # -# RELEASE = [ intel mach mach_pe panic_info config_dtrace ] +# RELEASE = [ intel mach mach_pe config_dtrace ] # PROFILE = [ RELEASE profile ] # DEBUG = [ RELEASE debug mach_assert ] # -# EMBEDDED = [ intel mach mach_pe panic_info ] +# EMBEDDED = [ intel mach mach_pe ] # DEVELOPMENT = [ EMBEDDED ] # ###################################################################### diff --git a/pexpert/conf/files b/pexpert/conf/files index 8c11d3933..1ec12c871 100644 --- a/pexpert/conf/files +++ b/pexpert/conf/files @@ -1,5 +1,4 @@ # -OPTIONS/panic_info optional panic_info OPTIONS/config_dtrace optional config_dtrace # diff --git a/pexpert/i386/pe_init.c b/pexpert/i386/pe_init.c index 1ef6c7c7b..29efd7c67 100644 --- a/pexpert/i386/pe_init.c +++ b/pexpert/i386/pe_init.c @@ -168,11 +168,6 @@ void PE_init_iokit(void) default_noroot_data = failedBootPict; } - /* - * Initialize the panic UI - */ - panic_ui_initialize( (unsigned char *) appleClut8 ); - /* * Initialize the spinning wheel (progress indicator). */ diff --git a/pexpert/pexpert/i386/protos.h b/pexpert/pexpert/i386/protos.h index 854f8c42c..86ba54d31 100644 --- a/pexpert/pexpert/i386/protos.h +++ b/pexpert/pexpert/i386/protos.h @@ -72,10 +72,6 @@ __OUT(l, long) extern void cninit(void); extern int sprintf(char * str, const char * format, ...); -//------------------------------------------------------------------------ -// from osfmk/console/panic_dialog.c -extern void panic_ui_initialize(const unsigned char * clut); - /* ------------------------------------------------------------------------ * from osfmk/i386/serial_io.h */ -- 2.45.2