Merge tag 'printk-for-4.18' of git://git.kernel.org/pub/scm/linux/kernel/git/pmladek...
[platform/kernel/linux-rpi.git] / lib / vsprintf.c
index 8999202..a48aaa7 100644 (file)
@@ -336,7 +336,7 @@ char *put_dec(char *buf, unsigned long long n)
  *
  * If speed is not important, use snprintf(). It's easy to read the code.
  */
-int num_to_str(char *buf, int size, unsigned long long num)
+int num_to_str(char *buf, int size, unsigned long long num, unsigned int width)
 {
        /* put_dec requires 2-byte alignment of the buffer. */
        char tmp[sizeof(num) * 3] __aligned(2);
@@ -350,11 +350,21 @@ int num_to_str(char *buf, int size, unsigned long long num)
                len = put_dec(tmp, num) - tmp;
        }
 
-       if (len > size)
+       if (len > size || width > size)
                return 0;
+
+       if (width > len) {
+               width = width - len;
+               for (idx = 0; idx < width; idx++)
+                       buf[idx] = ' ';
+       } else {
+               width = 0;
+       }
+
        for (idx = 0; idx < len; ++idx)
-               buf[idx] = tmp[len - idx - 1];
-       return len;
+               buf[idx + width] = tmp[len - idx - 1];
+
+       return len + width;
 }
 
 #define SIGN   1               /* unsigned/signed, must be 1 */
@@ -1641,19 +1651,22 @@ char *device_node_string(char *buf, char *end, struct device_node *dn,
        return widen_string(buf, buf - buf_start, end, spec);
 }
 
-static bool have_filled_random_ptr_key __read_mostly;
+static DEFINE_STATIC_KEY_TRUE(not_filled_random_ptr_key);
 static siphash_key_t ptr_key __read_mostly;
 
-static void fill_random_ptr_key(struct random_ready_callback *unused)
+static void enable_ptr_key_workfn(struct work_struct *work)
 {
        get_random_bytes(&ptr_key, sizeof(ptr_key));
-       /*
-        * have_filled_random_ptr_key==true is dependent on get_random_bytes().
-        * ptr_to_id() needs to see have_filled_random_ptr_key==true
-        * after get_random_bytes() returns.
-        */
-       smp_mb();
-       WRITE_ONCE(have_filled_random_ptr_key, true);
+       /* Needs to run from preemptible context */
+       static_branch_disable(&not_filled_random_ptr_key);
+}
+
+static DECLARE_WORK(enable_ptr_key_work, enable_ptr_key_workfn);
+
+static void fill_random_ptr_key(struct random_ready_callback *unused)
+{
+       /* This may be in an interrupt handler. */
+       queue_work(system_unbound_wq, &enable_ptr_key_work);
 }
 
 static struct random_ready_callback random_ready = {
@@ -1667,7 +1680,8 @@ static int __init initialize_ptr_random(void)
        if (!ret) {
                return 0;
        } else if (ret == -EALREADY) {
-               fill_random_ptr_key(&random_ready);
+               /* This is in preemptible context */
+               enable_ptr_key_workfn(&enable_ptr_key_work);
                return 0;
        }
 
@@ -1681,7 +1695,7 @@ static char *ptr_to_id(char *buf, char *end, void *ptr, struct printf_spec spec)
        const char *str = sizeof(ptr) == 8 ? "(____ptrval____)" : "(ptrval)";
        unsigned long hashval;
 
-       if (unlikely(!have_filled_random_ptr_key)) {
+       if (static_branch_unlikely(&not_filled_random_ptr_key)) {
                spec.field_width = 2 * sizeof(ptr);
                /* string length must be less than default_width */
                return string(buf, end, str, spec);
@@ -2562,6 +2576,8 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args)
                        case 's':
                        case 'F':
                        case 'f':
+                       case 'x':
+                       case 'K':
                                save_arg(void *);
                                break;
                        default:
@@ -2736,6 +2752,8 @@ int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf)
                        case 's':
                        case 'F':
                        case 'f':
+                       case 'x':
+                       case 'K':
                                process = true;
                                break;
                        default: