]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/kern/subr_log.c
xnu-4570.51.1.tar.gz
[apple/xnu.git] / bsd / kern / subr_log.c
index c301e27976c9d5055450e984932acd659067dbdc..cde2de0bedd85a73761a37b378d289721e431907 100644 (file)
@@ -71,6 +71,7 @@
 #include <sys/vnode.h>
 #include <stdbool.h>
 #include <firehose/tracepoint_private.h>
+#include <firehose/chunk_private.h>
 #include <firehose/ioctl_private.h>
 #include <os/firehose_buffer_private.h>
 
 #include <kern/locks.h>
 
 /* XXX should be in a common header somewhere */
-extern void logwakeup(void);
+extern void logwakeup(struct msgbuf *);
 extern void oslogwakeup(void);
 extern void oslog_streamwakeup(void);
 static void oslog_streamwakeup_locked(void);
@@ -116,31 +117,35 @@ extern uint32_t oslog_s_error_count;
 #define LOG_ASYNC      0x04
 #define LOG_RDWAIT     0x08
 
-#define MAX_UNREAD_CHARS (CONFIG_MSG_BSIZE/2)
 /* All globals should be accessed under LOG_LOCK() */
 
+static char amsg_bufc[1024];
+static struct msgbuf aslbuf = {MSG_MAGIC, sizeof (amsg_bufc), 0, 0, amsg_bufc};
+struct msgbuf *aslbufp __attribute__((used)) = &aslbuf;
+
 /* logsoftc only valid while log_open=1 */
 struct logsoftc {
        int     sc_state;               /* see above for possibilities */
        struct  selinfo sc_selp;        /* thread waiting for select */
        int     sc_pgid;                /* process/group for async I/O */
+       struct msgbuf *sc_mbp;
 } logsoftc;
 
-int    log_open;                       /* also used in log() */
+static int log_open;
 char smsg_bufc[CONFIG_MSG_BSIZE]; /* static buffer */
-char oslog_stream_bufc[FIREHOSE_BUFFER_CHUNK_SIZE]; /* static buffer */
-struct firehose_buffer_chunk_s __attribute__((aligned(8))) oslog_boot_buf = {
-       .fbc_pos = {
-               .fbc_next_entry_offs = offsetof(struct firehose_buffer_chunk_s, fbc_data),
-               .fbc_private_offs = FIREHOSE_BUFFER_CHUNK_SIZE,
-               .fbc_refcnt = 1, // indicate that there is a writer to this chunk
-               .fbc_stream = firehose_stream_persist,
-               .fbc_flag_io = 1, // for now, lets assume this is coming from the io bank
+char oslog_stream_bufc[FIREHOSE_CHUNK_SIZE]; /* static buffer */
+struct firehose_chunk_s oslog_boot_buf = {
+       .fc_pos = {
+               .fcp_next_entry_offs = offsetof(struct firehose_chunk_s, fc_data),
+               .fcp_private_offs = FIREHOSE_CHUNK_SIZE,
+               .fcp_refcnt = 1, // indicate that there is a writer to this chunk
+               .fcp_stream = firehose_stream_persist,
+               .fcp_flag_io = 1, // for now, lets assume this is coming from the io bank
        },
 }; /* static buffer */
-firehose_buffer_chunk_t firehose_boot_chunk = &oslog_boot_buf;
-struct msgbuf msgbuf = {MSG_MAGIC,sizeof(smsg_bufc),0,0,smsg_bufc};
-struct msgbuf oslog_stream_buf = {MSG_MAGIC,0,0,0,NULL};
+firehose_chunk_t firehose_boot_chunk = &oslog_boot_buf;
+struct msgbuf msgbuf = {MSG_MAGIC, sizeof(smsg_bufc), 0, 0, smsg_bufc};
+struct msgbuf oslog_stream_buf = {MSG_MAGIC, 0, 0, 0, NULL};
 struct msgbuf *msgbufp __attribute__((used)) = &msgbuf;
 struct msgbuf *oslog_streambufp __attribute__((used)) = &oslog_stream_buf;
 
@@ -167,7 +172,7 @@ struct oslog_streamsoftc {
        int     sc_state;               /* see above for possibilities */
        struct  selinfo sc_selp;        /* thread waiting for select */
        int     sc_pgid;                /* process/group for async I/O */
-}oslog_streamsoftc;
+} oslog_streamsoftc;
 
 STAILQ_HEAD(, oslog_stream_buf_entry_s) oslog_stream_free_head =
                STAILQ_HEAD_INITIALIZER(oslog_stream_free_head);
@@ -232,9 +237,7 @@ static void oslog_streamwrite_append_bytes(const char *buffer, int buflen);
 #endif
 
 static int sysctl_kern_msgbuf(struct sysctl_oid *oidp,
-                               void *arg1,
-                               int arg2,
-                               struct sysctl_req *req);
+       void *arg1, int arg2, struct sysctl_req *req);
 
 /*ARGSUSED*/
 int
@@ -245,6 +248,16 @@ logopen(__unused dev_t dev, __unused int flags, __unused int mode, struct proc *
                LOG_UNLOCK();
                return (EBUSY);
        }
+       if (atm_get_diagnostic_config() & ATM_ENABLE_LEGACY_LOGGING) {
+               logsoftc.sc_mbp = msgbufp;
+       } else {
+               /*
+                * Support for messagetracer (kern_asl_msg())
+                * In this mode, /dev/klog exports only ASL-formatted messages
+                * written into aslbufp via vaddlog().
+                */
+               logsoftc.sc_mbp = aslbufp;
+       }
        logsoftc.sc_pgid = p->p_pid;            /* signal process only */
        log_open = 1;
 
@@ -407,9 +420,10 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
 {
        int l;
        int error = 0;
+       struct msgbuf *mbp = logsoftc.sc_mbp;
 
        LOG_LOCK();
-       while (msgbufp->msg_bufr == msgbufp->msg_bufx) {
+       while (mbp->msg_bufr == mbp->msg_bufx) {
                if (flag & IO_NDELAY) {
                        error = EWOULDBLOCK;
                        goto out;
@@ -424,7 +438,7 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
                 * If the wakeup is missed 
                 * then wait for 5 sec and reevaluate 
                 */
-               if ((error = tsleep((caddr_t)msgbufp, LOG_RDPRI | PCATCH,
+               if ((error = tsleep((caddr_t)mbp, LOG_RDPRI | PCATCH,
                                "klog", 5 * hz)) != 0) {
                        /* if it times out; ignore */
                        if (error != EWOULDBLOCK)
@@ -437,23 +451,22 @@ logread(__unused dev_t dev, struct uio *uio, int flag)
        while (uio_resid(uio) > 0) {
                int readpos;
 
-               l = msgbufp->msg_bufx - msgbufp->msg_bufr;
+               l = mbp->msg_bufx - mbp->msg_bufr;
                if (l < 0)
-                       l = msgbufp->msg_size - msgbufp->msg_bufr;
+                       l = mbp->msg_size - mbp->msg_bufr;
                l = min(l, uio_resid(uio));
                if (l == 0)
                        break;
 
-               readpos = msgbufp->msg_bufr;
+               readpos = mbp->msg_bufr;
                LOG_UNLOCK();
-               error = uiomove((caddr_t)&msgbufp->msg_bufc[readpos],
-                       l, uio);
+               error = uiomove((caddr_t)&mbp->msg_bufc[readpos], l, uio);
                LOG_LOCK();
                if (error)
                        break;
-               msgbufp->msg_bufr = readpos + l;
-               if (msgbufp->msg_bufr >= msgbufp->msg_size)
-                       msgbufp->msg_bufr = 0;
+               mbp->msg_bufr = readpos + l;
+               if (mbp->msg_bufr >= mbp->msg_size)
+                       mbp->msg_bufr = 0;
        }
 out:
        LOG_UNLOCK();
@@ -466,7 +479,7 @@ oslog_streamread(__unused dev_t dev, struct uio *uio, int flag)
 {
        int error = 0;
        int copy_size = 0;
-       static char logline[FIREHOSE_BUFFER_CHUNK_SIZE];
+       static char logline[FIREHOSE_CHUNK_SIZE];
 
        lck_spin_lock(&oslog_stream_lock);
 
@@ -587,11 +600,13 @@ oslog_streamread(__unused dev_t dev, struct uio *uio, int flag)
 int
 logselect(__unused dev_t dev, int rw, void * wql, struct proc *p)
 {
+       const struct msgbuf *mbp = logsoftc.sc_mbp;
+
        switch (rw) {
 
        case FREAD:
                LOG_LOCK();     
-               if (msgbufp->msg_bufr != msgbufp->msg_bufx) {
+               if (mbp->msg_bufr != mbp->msg_bufx) {
                        LOG_UNLOCK();
                        return (1);
                }
@@ -642,10 +657,8 @@ oslog_streamselect(__unused dev_t dev, int rw, void * wql, struct proc *p)
 }
 
 void
-logwakeup(void)
+logwakeup(struct msgbuf *mbp)
 {
-       int pgid;
-
        /* cf. r24974766 & r25201228*/
        if (oslog_is_safe() == FALSE) {
                return;
@@ -656,9 +669,13 @@ logwakeup(void)
                LOG_UNLOCK();
                return;
        }
+       if (NULL == mbp)
+               mbp = logsoftc.sc_mbp;
+       if (mbp != logsoftc.sc_mbp)
+               goto out;
        selwakeup(&logsoftc.sc_selp);
        if (logsoftc.sc_state & LOG_ASYNC) {
-               pgid = logsoftc.sc_pgid;
+               int pgid = logsoftc.sc_pgid;
                LOG_UNLOCK();
                if (pgid < 0)
                        gsignal(-pgid, SIGIO); 
@@ -667,9 +684,10 @@ logwakeup(void)
                LOG_LOCK();
        }
        if (logsoftc.sc_state & LOG_RDWAIT) {
-               wakeup((caddr_t)msgbufp);
+               wakeup((caddr_t)mbp);
                logsoftc.sc_state &= ~LOG_RDWAIT;
        }
+out:
        LOG_UNLOCK();
 }
 
@@ -689,7 +707,7 @@ oslogwakeup(void)
 static void
 oslog_streamwakeup_locked(void)
 {
-       lck_spin_assert(&oslog_stream_lock, LCK_ASSERT_OWNED);
+       LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED);
        if (!oslog_stream_open) {
                return;
        }
@@ -718,15 +736,16 @@ int
 logioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __unused struct proc *p)
 {
        int l;
+       const struct msgbuf *mbp = logsoftc.sc_mbp;
 
        LOG_LOCK();
        switch (com) {
 
        /* return number of characters immediately available */
        case FIONREAD:
-               l = msgbufp->msg_bufx - msgbufp->msg_bufr;
+               l = mbp->msg_bufx - mbp->msg_bufr;
                if (l < 0)
-                       l += msgbufp->msg_size;
+                       l += mbp->msg_size;
                *(off_t *)data = l;
                break;
 
@@ -765,7 +784,7 @@ int
 oslogioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __unused struct proc *p)
 {
        int ret = 0;
-       mach_vm_size_t buffer_size = (FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT * FIREHOSE_BUFFER_CHUNK_SIZE);
+       mach_vm_size_t buffer_size = (FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT * FIREHOSE_CHUNK_SIZE);
        firehose_buffer_map_info_t map_info = {0, 0};
        firehose_buffer_t kernel_firehose_buffer = NULL;
        mach_vm_address_t user_addr = 0;
@@ -776,7 +795,7 @@ oslogioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __un
        /* return number of characters immediately available */
 
        case LOGBUFFERMAP:
-               kernel_firehose_buffer = kernel_firehose_addr;
+               kernel_firehose_buffer = (firehose_buffer_t)kernel_firehose_addr;
 
                ret = mach_make_memory_entry_64(kernel_map,
                                                &buffer_size,
@@ -785,11 +804,12 @@ oslogioctl(__unused dev_t dev, u_long com, caddr_t data, __unused int flag, __un
                                                &mem_entry_ptr,
                                                MACH_PORT_NULL);
                if (ret == KERN_SUCCESS) {
-                       ret = mach_vm_map(get_task_map(current_task()),
+                       ret = mach_vm_map_kernel(get_task_map(current_task()),
                                          &user_addr,
                                          buffer_size,
                                          0, /*  mask */
                                          VM_FLAGS_ANYWHERE,
+                                         VM_KERN_MEMORY_NONE,
                                          mem_entry_ptr,
                                          0, /* offset */
                                          FALSE, /* copy */
@@ -856,7 +876,7 @@ void
 oslog_init(void)
 {
        kern_return_t kr;
-       vm_size_t size = FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT * FIREHOSE_BUFFER_CHUNK_SIZE;
+       vm_size_t size = FIREHOSE_BUFFER_KERNEL_CHUNK_COUNT * FIREHOSE_CHUNK_SIZE;
 
        oslog_lock_init();
 
@@ -867,9 +887,9 @@ oslog_init(void)
                panic("Failed to allocate memory for firehose logging buffer");
        }
        kernel_firehose_addr += PAGE_SIZE;
-       bzero(kernel_firehose_addr, size);
+       bzero((void *)kernel_firehose_addr, size);
        /* register buffer with firehose */
-       kernel_firehose_addr = __firehose_buffer_create((size_t *) &size);
+       kernel_firehose_addr = (vm_offset_t)__firehose_buffer_create((size_t *) &size);
 
        kprintf("oslog_init completed\n");
 }
@@ -890,13 +910,10 @@ oslog_init(void)
  *             SMP reentrancy.
  */
 void
-log_putc_locked(char c)
+log_putc_locked(struct msgbuf *mbp, char c)
 {
-       struct msgbuf *mbp;
-
-       mbp = msgbufp; 
        mbp->msg_bufc[mbp->msg_bufx++] = c;
-       if (mbp->msg_bufx >= msgbufp->msg_size)
+       if (mbp->msg_bufx >= mbp->msg_size)
                mbp->msg_bufx = 0;
 }
 
@@ -906,7 +923,7 @@ oslog_stream_find_free_buf_entry_locked(void)
        struct msgbuf *mbp;
        oslog_stream_buf_entry_t buf_entry = NULL;
 
-       lck_spin_assert(&oslog_stream_lock, LCK_ASSERT_OWNED);
+       LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED);
 
        mbp = oslog_streambufp;
 
@@ -945,17 +962,18 @@ oslog_stream_find_free_buf_entry_locked(void)
 void
 oslog_streamwrite_metadata_locked(oslog_stream_buf_entry_t m_entry)
 {
-       lck_spin_assert(&oslog_stream_lock, LCK_ASSERT_OWNED);
+       LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED);
        STAILQ_INSERT_TAIL(&oslog_stream_buf_head, m_entry, buf_entries);
 
        return;
 }
 
-static void oslog_streamwrite_append_bytes(const char *buffer, int buflen)
+static void
+oslog_streamwrite_append_bytes(const char *buffer, int buflen)
 {
        struct msgbuf *mbp;
 
-       lck_spin_assert(&oslog_stream_lock, LCK_ASSERT_OWNED);
+       LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED);
 
        mbp = oslog_streambufp;
        // Check if we have enough space in the stream buffer to write the data
@@ -994,7 +1012,7 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid,
        uint16_t ft_size = offsetof(struct firehose_tracepoint_s, ft_data);
        int ft_length = ft_size + publen;
 
-       lck_spin_assert(&oslog_stream_lock, LCK_ASSERT_OWNED);
+       LCK_SPIN_ASSERT(&oslog_stream_lock, LCK_ASSERT_OWNED);
 
        mbp = oslog_streambufp;
        if (ft_length > mbp->msg_size) {
@@ -1078,7 +1096,7 @@ oslog_streamwrite_locked(firehose_tracepoint_id_u ftid,
  *
  * Returns:    (void)
  *
- * Notes:      This function is used for syingle byte output to the log.  It
+ * Notes:      This function is used for single byte output to the log.  It
  *             primarily exists to maintain binary backward compatibility.
  */
 void
@@ -1086,14 +1104,14 @@ log_putc(char c)
 {
        int unread_count = 0;
        LOG_LOCK();
-       log_putc_locked(c);
+       log_putc_locked(msgbufp, c);
        unread_count = msgbufp->msg_bufx - msgbufp->msg_bufr;
        LOG_UNLOCK();
 
        if (unread_count < 0)
                unread_count = 0 - unread_count;
-       if (c == '\n' || unread_count >= MAX_UNREAD_CHARS)
-               logwakeup();
+       if (c == '\n' || unread_count >= (msgbufp->msg_size / 2))
+               logwakeup(msgbufp);
 }
 
 
@@ -1107,7 +1125,8 @@ log_putc(char c)
  * memory is dynamically allocated. Memory management must already be up.
  */
 int
-log_setsize(int size) {
+log_setsize(int size)
+{
        char *new_logdata;
        int new_logsize, new_bufr, new_bufx;
        char *old_logdata;
@@ -1208,12 +1227,13 @@ void oslog_setsize(int size)
        printf("oslog_setsize: new buffer size = %d, new num entries= %d\n", oslog_stream_buf_size, oslog_stream_num_entries);
 }
 
-SYSCTL_PROC(_kern, OID_AUTO, msgbuf, CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0, sysctl_kern_msgbuf, "I", "");
+SYSCTL_PROC(_kern, OID_AUTO, msgbuf,
+       CTLTYPE_INT | CTLFLAG_RW | CTLFLAG_LOCKED, 0, 0,
+       sysctl_kern_msgbuf, "I", "");
 
-static int sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
-                                                         void *arg1 __unused,
-                                                         int arg2 __unused,
-                                                         struct sysctl_req *req)
+static int
+sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
+       void *arg1 __unused, int arg2 __unused, struct sysctl_req *req)
 {
        int old_bufsize, bufsize;
        int error;
@@ -1239,7 +1259,8 @@ static int sysctl_kern_msgbuf(struct sysctl_oid *oidp __unused,
  * It returns as much data still in the buffer as possible.
  */
 int
-log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval) {
+log_dmesg(user_addr_t buffer, uint32_t buffersize, int32_t * retval)
+{
        uint32_t i;
        uint32_t localbuff_size;
        int error = 0, newl, skip;